Skip to content

Commit c682291

Browse files
author
Oliver Rumbelow
authored
Merge pull request #233 from st3xupery/master2.x
Multiple filter w/ include fix + internal routing fix + more
2 parents 8f2072f + ca1623a commit c682291

File tree

11 files changed

+80
-18
lines changed

11 files changed

+80
-18
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
node_modules
2-
coverage.html
2+
coverage
33
complexity
44
npm-debug.log
55
jsonapi-server.cpuprofile

example/resources/photos.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ jsonApi.define({
6464
width: 350,
6565
tags: ['black', 'green'],
6666
photographer: { type: 'people', id: 'ad3aa89e-9c5b-4ac9-a652-6670f9f27587' }
67+
},
68+
{
69+
id: 'ed45eba1-15fe-41c7-93da-1df3dfa5289f',
70+
type: 'photos',
71+
title: 'Sunset Horizon',
72+
url: 'http://www.example.com/sunset',
73+
height: 450,
74+
width: 1050,
75+
raw: true,
76+
tags: ['orange', 'sky', 'sun'],
77+
photographer: { type: 'people', id: 'cc5cca2e-0dd8-4b95-8cfc-a11230e73116' }
6778
}
79+
6880
]
6981
})

lib/filter.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ filter._parseScalarFilterElement = (attributeConfig, scalarElement) => {
6767
filter._parseFilterElementHelper = (attributeConfig, filterElement) => {
6868
if (!filterElement) return { error: 'invalid or empty filter element' }
6969

70-
if (typeof filterElement === 'string') filterElement = filterElement.split(FILTER_SEPERATOR)
71-
7270
const parsedElements = [].concat(filterElement).map(scalarElement => filter._parseScalarFilterElement(attributeConfig, scalarElement))
7371

7472
if (parsedElements.length === 1) return parsedElements[0]
@@ -117,6 +115,8 @@ filter.parseAndValidate = request => {
117115
for (const key in request.params.filter) {
118116
filterElement = request.params.filter[key]
119117

118+
if (typeof filterElement === 'string') request.params.filter[key] = filterElement = filterElement.split(FILTER_SEPERATOR)
119+
120120
if (!Array.isArray(filterElement) && filterElement instanceof Object) continue // skip deep filters
121121

122122
error = filter._resourceDoesNotHaveProperty(resourceConfig, key)

lib/graphQl/index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ const writeTypes = require('./writeTypes.js')
1313
jsonApiGraphQL.with = app => {
1414
const config = jsonApi._apiConfig
1515

16-
app.use(new RegExp(`${config.base}$`), graphqlHTTP({
17-
schema: jsonApiGraphQL.generate(jsonApi._resources),
18-
graphiql: !!config.graphiql
19-
}))
16+
if (config.graphiql !== false) {
17+
app.use(new RegExp(`${config.base}$`), graphqlHTTP({
18+
schema: jsonApiGraphQL.generate(jsonApi._resources),
19+
graphiql: !!config.graphiql
20+
}))
21+
}
2022
}
2123

2224
jsonApiGraphQL.generate = allResourceConfig => {

lib/postProcessing/include.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const debug = require('../debugging.js')
1212

1313
includePP.action = (request, response, callback) => {
1414
let includes = request.params.include
15-
const filters = request.params.filter || { }
15+
const filters = request.params.filter
1616
if (!includes) return callback()
1717
includes = (`${includes}`).split(',')
1818

@@ -47,6 +47,7 @@ includePP._arrayToTree = (request, includes, filters, callback) => {
4747
const parts = text.split('.')
4848
const first = parts.shift()
4949
const rest = parts.join('.')
50+
if (!filter) filter = {}
5051

5152
let resourceAttribute = node._resourceConfig.map(resourceConfig => {
5253
return resourceConfig.attributes[first]
@@ -70,6 +71,7 @@ includePP._arrayToTree = (request, includes, filters, callback) => {
7071
}
7172

7273
filter = filter[first] || { }
74+
7375
if (filter instanceof Array) {
7476
filter = filter.filter(i => i instanceof Object).pop()
7577
}
@@ -159,7 +161,7 @@ includePP._fillIncludeTree = (includeTree, request, callback) => {
159161
ids += `&${includeTree[parts[1]]._filter.join('&')}`
160162
}
161163
resourcesToFetch.push({
162-
url: `${jsonApi._apiConfig.pathPrefix + parts[0]}/?${ids}`,
164+
url: `${jsonApi._apiConfig.base + parts[0]}/?${ids}`,
163165
as: relation
164166
})
165167
})
@@ -173,7 +175,7 @@ includePP._fillIncludeTree = (includeTree, request, callback) => {
173175
ids += `&${includeTree[parts[2]]._filter.join('&')}`
174176
}
175177
resourcesToFetch.push({
176-
url: `${jsonApi._apiConfig.pathPrefix + parts[1]}/?${ids}`,
178+
url: `${jsonApi._apiConfig.base + parts[1]}/?${ids}`,
177179
as: relation
178180
})
179181
})

lib/rerouter.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ rerouter.route = (newRequest, callback) => {
1818

1919
const req = {
2020
url: newRequest.uri,
21+
originalUrl: newRequest.originalRequest.originalUrl,
2122
headers: newRequest.originalRequest.headers,
2223
cookies: newRequest.originalRequest.cookies,
2324
params: rerouter._mergeParams(url.parse(newRequest.uri.split('?')[1] || { }), newRequest.params)

lib/router.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ router._getParams = req => {
184184
headers: req.headers,
185185
safeHeaders: _.omit(req.headers, headersToRemove),
186186
cookies: req.cookies,
187+
originalUrl: req.originalUrl,
187188
route: {
188189
verb: req.method,
189190
host: req.headers.host,

lib/swagger/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ swagger._getSwaggerBase = () => {
1717
let basePath, host, protocol
1818
if (jsonApi._apiConfig.urlPrefixAlias) {
1919
const urlObj = url.parse(jsonApi._apiConfig.urlPrefixAlias)
20-
basePath = urlObj.pathname.replace(/\/$/, '')
20+
basePath = urlObj.pathname.replace(/(?!^\/)\/$/, '')
2121
host = urlObj.host
2222
protocol = urlObj.protocol.replace(/:$/, '')
2323
} else {

test/_preResourceValidationCheck.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ describe('Testing jsonapi-server', () => {
66
[ { name: 'articles', count: 4 },
77
{ name: 'comments', count: 3 },
88
{ name: 'people', count: 4 },
9-
{ name: 'photos', count: 3 },
9+
{ name: 'photos', count: 4 },
1010
{ name: 'tags', count: 5 }
1111
].forEach(resource => {
1212
describe(`Searching for ${resource.name}`, () => {

test/get-resource.js

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ describe('Testing jsonapi-server', () => {
201201

202202
assert.equal(res.statusCode, '200', 'Expecting 200 OK')
203203
const photoTypes = json.data.map(i => i.attributes.raw)
204-
assert.deepEqual(photoTypes, [ true ], 'expected matching resources')
204+
assert.deepEqual(photoTypes, [ true, true ], 'expected matching resources')
205205

206206
done()
207207
})
@@ -530,13 +530,13 @@ describe('Testing jsonapi-server', () => {
530530
json = helpers.validateJson(json)
531531

532532
assert.equal(res.statusCode, '200', 'Expecting 200 OK')
533-
assert.equal(json.included.length, 7, 'Should be 7 included resources')
533+
assert.equal(json.included.length, 8, 'Should be 8 included resources')
534534

535535
const people = json.included.filter(resource => resource.type === 'people')
536536
assert.equal(people.length, 4, 'Should be 4 included people resources')
537537

538538
const photos = json.included.filter(resource => resource.type === 'photos')
539-
assert.equal(photos.length, 3, 'Should be 3 included photos resources')
539+
assert.equal(photos.length, 4, 'Should be 4 included photos resources')
540540

541541
done()
542542
})
@@ -552,13 +552,13 @@ describe('Testing jsonapi-server', () => {
552552
json = helpers.validateJson(json)
553553

554554
assert.equal(res.statusCode, '200', 'Expecting 200 OK')
555-
assert.equal(json.included.length, 7, 'Should be 7 included resources')
555+
assert.equal(json.included.length, 8, 'Should be 8 included resources')
556556

557557
const people = json.included.filter(resource => resource.type === 'people')
558558
assert.equal(people.length, 4, 'Should be 4 included people resources')
559559

560560
const photos = json.included.filter(resource => resource.type === 'photos')
561-
assert.equal(photos.length, 3, 'Should be 3 included photos resources')
561+
assert.equal(photos.length, 4, 'Should be 4 included photos resources')
562562

563563
done()
564564
})
@@ -585,6 +585,50 @@ describe('Testing jsonapi-server', () => {
585585
done()
586586
})
587587
})
588+
589+
it('include author.photos with multiple filters', done => {
590+
const url = 'http://localhost:16006/rest/articles?include=author.photos&filter[author]=ad3aa89e-9c5b-4ac9-a652-6670f9f27587&filter[author]=cc5cca2e-0dd8-4b95-8cfc-a11230e73116'
591+
helpers.request({
592+
method: 'GET',
593+
url
594+
}, (err, res, json) => {
595+
assert.equal(err, null)
596+
json = helpers.validateJson(json)
597+
598+
assert.equal(res.statusCode, '200', 'Expecting 200 OK')
599+
assert.equal(json.included.length, 5, 'Should be 2 included resources')
600+
601+
const people = json.included.filter(resource => resource.type === 'people')
602+
assert.equal(people.length, 2, 'Should be 2 included people resource')
603+
604+
const photos = json.included.filter(resource => resource.type === 'photos')
605+
assert.equal(photos.length, 3, 'Should be 2 included photos resource')
606+
607+
done()
608+
})
609+
})
610+
611+
it('include author.photos with multiple filters comma delineated', done => {
612+
const url = 'http://localhost:16006/rest/articles?include=author.photos&filter[author][firstname]=Mark,Oli'
613+
helpers.request({
614+
method: 'GET',
615+
url
616+
}, (err, res, json) => {
617+
assert.equal(err, null)
618+
json = helpers.validateJson(json)
619+
620+
assert.equal(res.statusCode, '200', 'Expecting 200 OK')
621+
assert.equal(json.included.length, 4, 'Should be 2 included resources')
622+
623+
const people = json.included.filter(resource => resource.type === 'people')
624+
assert.equal(people.length, 2, 'Should be 2 included people resource')
625+
626+
const photos = json.included.filter(resource => resource.type === 'photos')
627+
assert.equal(photos.length, 2, 'Should be 2 included photos resource')
628+
629+
done()
630+
})
631+
})
588632
})
589633

590634
describe('by foreign key', () => {

0 commit comments

Comments
 (0)