Skip to content

Commit 3267f57

Browse files
authored
Merge pull request feathersjs-ecosystem#459 from feathers-plus/fgraphql-2
Added support for dePopulate to fgraphql hook.
2 parents cf941eb + 8c7b9dc commit 3267f57

File tree

3 files changed

+91
-27
lines changed

3 files changed

+91
-27
lines changed

lib/services/de-populate.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = function (func) {
99

1010
(Array.isArray(items) ? items : [items]).forEach(item => {
1111
if (typeof func === 'function') {
12-
func(item)
12+
func(item);
1313
}
1414

1515
removeProps('_computed', item);

lib/services/fgraphql.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = function fgraphql (options1 = {}) {
1818
inclAllFieldsServer: true,
1919
inclAllFieldsClient: true,
2020
inclAllFields: null, // Will be initialized each hook call.
21+
inclJoinedNames: true,
2122
extraAuthProps: []
2223
}, options1.options || {});
2324

@@ -134,38 +135,46 @@ async function processRecord (store, query, depth, rec, type, j) {
134135
debug(`processRecord rec# ${j} typeof ${typeof rec} Type ${type}`);
135136
if (!rec) return; // Catch any null values from resolvers.
136137

137-
const allNamesInQuery = [];
138138
const recFieldNamesInQuery = [];
139+
const joinedNamesInQuery = [];
139140

140141
// Process every query item.
141142
const queryPropNames = Object.keys(query);
142143
for (let i = 0, ilen = queryPropNames.length; i < ilen; i++) {
143144
const fieldName = queryPropNames[i];
144-
await processRecordQuery(store, query, depth, rec, fieldName, type, allNamesInQuery, recFieldNamesInQuery, j, i);
145+
await processRecordQuery(store, query, depth, rec, fieldName, type,
146+
recFieldNamesInQuery, joinedNamesInQuery, j, i);
145147
}
146148

147149
// Retain only record fields selected
148-
debug(`field names found ${allNamesInQuery}`);
150+
debug(`field names found ${recFieldNamesInQuery} joined names ${joinedNamesInQuery}`);
149151
if (recFieldNamesInQuery.length || !store.options.inclAllFields || queryPropNames.includes('_none')) {
150152
// recs[0] may have been created by [rec] so can't replace array elem
151153
Object.keys(rec).forEach(key => {
152-
if (!allNamesInQuery.includes(key)) {
154+
if (!recFieldNamesInQuery.includes(key) && !joinedNamesInQuery.includes(key)) {
153155
delete rec[key];
154156
}
155157
});
156158
}
159+
160+
// Include joined names in record.
161+
if (store.options.inclJoinedNames && joinedNamesInQuery.length) {
162+
rec._include = joinedNamesInQuery;
163+
}
157164
}
158165

159166
// Process one query field for a record.
160-
async function processRecordQuery (store, query, depth, rec, fieldName, type, allNamesInQuery, recFieldNamesInQuery, j, i) {
167+
async function processRecordQuery (
168+
store, query, depth, rec, fieldName, type,
169+
recFieldNamesInQuery, joinedNamesInQuery, j, i
170+
) {
161171
debug(`\nprocessRecordQuery rec# ${j} Type ${type} field# ${i} name ${fieldName}`);
162172

163173
// One way to include/exclude rec fields is to give their names a falsey value.
164174
// _args and _none are not record field names but special purpose
165175
if (query[fieldName] && fieldName !== '_args' && fieldName !== '_none') {
166-
allNamesInQuery.push(fieldName);
167-
168176
if (store.ourResolvers[type][fieldName]) {
177+
joinedNamesInQuery.push(fieldName);
169178
await processRecordFieldResolver(store, query, depth, rec, fieldName, type);
170179
} else {
171180
debug('is not resolver call');
@@ -232,7 +241,6 @@ function convertResolverResult (result, ourQuery, fieldName, type) {
232241

233242
function convertSdlToFeathersSchemaObject (schemaDefinitionLanguage, parse) {
234243
const graphQLSchemaObj = parse(schemaDefinitionLanguage);
235-
// inspector('graphQLSchemaObj', graphQLSchemaObj)
236244
return convertDocument(graphQLSchemaObj);
237245
}
238246

tests/services/fgraphql.js renamed to tests/services/fgraphql.test.js

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ describe('services fgraphql', () => {
2121
['opt server-', s('str'), r('full'), 'User', q('obj'), o('server-'), afterJane(), false, a('janeFull-') ],
2222
['opt client-', s('str'), r('full'), 'User', q('obj'), o('client-'), afterJane(), true, a('janeFull-') ],
2323
['before hook', s('str'), r('full'), 'User', q('obj'), o('both'), beforeJane(), false, a('janeFull') ],
24+
['func params', s('param'),r('params'), 'User', q('params'),o('both'), afterJane(), false, a('janeParams')],
25+
['join names', s('str'), r('full'), 'User', q('obj'), o('join-'), afterJane(), false, a('janeJoin') ],
2426
// Test conversion of resolver results
2527
// desc, schema, resolvers, recordType, query, options, context, client, result
2628
['undef->null', s('cnv0'), r('undefin'),'User', q('obj'), o('both'), beforeJane(), false, a('janeNull') ],
@@ -177,6 +179,15 @@ type User {
177179
fullName: { nonNullTypeField: true, typeof: 'String' }
178180
}
179181
};
182+
case 'param':
183+
return {
184+
User: {
185+
firstName: { typeof: 'String' },
186+
lastName: { typeof: 'String' },
187+
fullName: { nonNullTypeField: true, typeof: 'String' },
188+
params: { typeof: 'JSON' }
189+
}
190+
};
180191
case 'err1':
181192
return () => null;
182193

@@ -217,6 +228,16 @@ function r (typ) {
217228
}
218229
}
219230
};
231+
case 'params':
232+
return {
233+
User: {
234+
// fullName: String!
235+
fullName:
236+
(parent, args, content, ast) => `${parent.first} ${parent.last}`, // eslint-disable-line no-unused-vars
237+
params:
238+
(parent, args, content, ast) => ({ args, ast })
239+
}
240+
};
220241
case 'err1':
221242
return { User: { fullName: 'foo' } };
222243

@@ -319,6 +340,10 @@ function q (typ) {
319340
return { fullName: '', first: null, last: 1 } ;
320341
case 'fcn':
321342
return () => ({ fullName: {} } );
343+
case 'params':
344+
return { fullName: {}, params: {
345+
_args: { key: 1, query: { foo: 2 }, params: { bar: 3 }, baz: 4 }
346+
} } ;
322347
case 'err1':
323348
return undefined;
324349

@@ -419,6 +444,12 @@ function o (typ) {
419444
inclAllFieldsClient: true,
420445
extraAuthProps: ['foo']
421446
};
447+
case 'join-':
448+
return {
449+
inclAllFieldsServer: true,
450+
inclAllFieldsClient: true,
451+
inclJoinedNames: false
452+
};
422453
default:
423454
throw new Error(`Invalid typ ${typ} for "o" function.`);
424455
}
@@ -429,21 +460,28 @@ function a (typ) {
429460
switch (typ) {
430461
/* eslint-disable */
431462
case 'janeNull' :
432-
return { first: 'Jane', last: 'Doe', fullName: null };
463+
return { first: 'Jane', last: 'Doe', fullName: null, _include: ['fullName'] };
433464
case 'janeFull' :
434-
return { first: 'Jane', last: 'Doe', fullName: 'Jane Doe' };
465+
return { first: 'Jane', last: 'Doe', fullName: 'Jane Doe', _include: ['fullName'] };
435466
case 'janeArray' :
436-
return { first: 'Jane', last: 'Doe', fullName: ['Jane Doe'] };
467+
return { first: 'Jane', last: 'Doe', fullName: ['Jane Doe'], _include: ['fullName'] };
437468
case 'janeArray0' :
438-
return { first: 'Jane', last: 'Doe', fullName: [] };
469+
return { first: 'Jane', last: 'Doe', fullName: [], _include: ['fullName'] };
439470
case 'janeFull-' :
440-
return { fullName: 'Jane Doe' };
471+
return { fullName: 'Jane Doe', _include: ['fullName'] };
441472
case 'janeMess' :
442-
return { first: 'foo', last: 'Doe', fullName: 'Jane Doe' };
473+
return { first: 'foo', last: 'Doe', fullName: 'Jane Doe', _include: ['fullName'] };
443474
case 'jane0' :
444-
return { first: 'Jane' };
475+
return { first: 'Jane' };
445476
case 'janeFalsey' :
446-
return { last: 'Doe' };
477+
return { last: 'Doe' };
478+
case 'janeJoin' :
479+
return { first: 'Jane', last: 'Doe', fullName: 'Jane Doe' };
480+
case 'janeParams' :
481+
return { first: 'Jane', last: 'Doe', fullName: 'Jane Doe', _include: ['fullName', 'params'],
482+
params: {
483+
args: { key: 1, query: { foo: 2 }, params: { bar: 3 }, baz: 4 }, ast: undefined
484+
} };
447485

448486
case 'S2post' :
449487
return {
@@ -452,7 +490,8 @@ function a (typ) {
452490
posts: [
453491
{ _id: '1001', body: 'foo body' },
454492
{ _id: '1002', body: 'bar body' },
455-
]
493+
],
494+
_include: ['posts']
456495
};
457496
case 'S2parm' :
458497
return {
@@ -461,7 +500,8 @@ function a (typ) {
461500
posts: [
462501
{ _id: '1001', body: 'foo body' },
463502
{ _id: '9999', body: 'bar body' },
464-
]
503+
],
504+
_include: ['posts']
465505
};
466506
case 'S2comm' :
467507
return {
@@ -470,7 +510,8 @@ function a (typ) {
470510
comments: [
471511
{ _id: '2001', comment: 'foo comment' },
472512
{ _id: '2002', comment: 'bar comment' },
473-
]
513+
],
514+
_include: ['comments']
474515
};
475516
case 'S2cont' :
476517
return {
@@ -479,7 +520,8 @@ function a (typ) {
479520
posts: [
480521
{ _id: '1001', body: 'foo body' },
481522
{ _id: '9999', body: 'bar body' },
482-
]
523+
],
524+
_include: ['posts']
483525
};
484526
case 'S2both' :
485527
return {
@@ -492,7 +534,8 @@ function a (typ) {
492534
comments: [
493535
{ _id: '2001', comment: 'foo comment' },
494536
{ _id: '2002', comment: 'bar comment' },
495-
]
537+
],
538+
_include: ['posts', 'comments']
496539
};
497540

498541
case 'S3all' :
@@ -502,29 +545,42 @@ function a (typ) {
502545
posts: [
503546
{ _id: '1001',
504547
body: 'foo body',
505-
author: { _id: '3001', first: 'Jane', last: 'Doe' }
548+
author: { _id: '3001', first: 'Jane', last: 'Doe' },
549+
_include: ['author']
506550
},
507551
{
508552
_id: '1002',
509553
body: 'bar body',
510-
author: { _id: '3001', first: 'Jane', last: 'Doe' }
554+
author: { _id: '3001', first: 'Jane', last: 'Doe' },
555+
_include: ['author']
511556
}
512557
],
513558
comments: [
514559
{ _id: '2001',
515560
comment: 'foo comment',
516-
author: { _id: '4001', first: 'Jane', last: 'Doe' }
561+
author: { _id: '4001', first: 'Jane', last: 'Doe' },
562+
_include: ['author']
517563
},
518564
{
519565
_id: '2002',
520566
comment: 'bar comment',
521-
author: { _id: '4001', first: 'Jane', last: 'Doe' }
567+
author: { _id: '4001', first: 'Jane', last: 'Doe' },
568+
_include: ['author']
522569
}
523-
]
570+
],
571+
_include: ['posts', 'comments']
524572
}
525573

526574
default:
527575
throw new Error(`Invalid typ ${typ} for "a" function.`);
528576
}
529577
/* eslint-enable */
530578
}
579+
580+
/*
581+
const { inspect } = require('util');
582+
function inspector(desc, obj) {
583+
console.log(desc);
584+
console.log(inspect(obj, { colors: true, depth: 5 }));
585+
}
586+
*/

0 commit comments

Comments
 (0)