@coderich/autograph 0.13.0 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/src/query/Query.js +1 -0
- package/src/query/QueryBuilder.js +9 -3
- package/src/schema/Schema.js +37 -25
- package/src/service/AppService.js +11 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coderich/autograph",
|
|
3
3
|
"main": "index.js",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"dataloader": "2.2.2",
|
|
24
24
|
"deepmerge": "4.3.1",
|
|
25
25
|
"fill-range": "7.0.1",
|
|
26
|
+
"graphql-parse-resolve-info": "4.13.0",
|
|
26
27
|
"lodash.get": "4.4.2",
|
|
27
28
|
"lodash.merge": "4.6.2",
|
|
28
29
|
"lodash.uniqwith": "4.5.0",
|
package/src/query/Query.js
CHANGED
|
@@ -75,6 +75,7 @@ module.exports = class Query {
|
|
|
75
75
|
const { input, where, sort, before, after, isNative, isCursorPaging } = this.#query;
|
|
76
76
|
|
|
77
77
|
const query = this.clone({
|
|
78
|
+
model: this.#model.key,
|
|
78
79
|
select: Object.values(this.#model.fields).map(field => field.key),
|
|
79
80
|
input: this.#model.walk(input, node => node.value !== undefined && Object.assign(node, { key: node.field.key })),
|
|
80
81
|
where: isNative ? where : this.#model.walk(where, node => Object.assign(node, { key: node.field.key })),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const Query = require('./Query');
|
|
2
|
-
const { getGQLReturnType, mergeDeep } = require('../service/AppService');
|
|
2
|
+
const { getGQLReturnType, getGQLSelectFields, mergeDeep } = require('../service/AppService');
|
|
3
3
|
|
|
4
4
|
module.exports = class QueryBuilder {
|
|
5
5
|
#config;
|
|
@@ -41,7 +41,9 @@ module.exports = class QueryBuilder {
|
|
|
41
41
|
* For use in GraphQL resolver methods to return the "correct" response
|
|
42
42
|
*/
|
|
43
43
|
resolve(info) {
|
|
44
|
-
|
|
44
|
+
this.info(info);
|
|
45
|
+
|
|
46
|
+
switch (getGQLReturnType(info)) {
|
|
45
47
|
case 'array': return this.many();
|
|
46
48
|
case 'number': return this.count();
|
|
47
49
|
case 'connection': return { count: () => this.count(), edges: () => this.many(), pageInfo: () => this.many() };
|
|
@@ -65,6 +67,11 @@ module.exports = class QueryBuilder {
|
|
|
65
67
|
return this;
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
info(info) {
|
|
71
|
+
this.select(getGQLSelectFields(this.#query.model, info));
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
|
|
68
75
|
native(clause) {
|
|
69
76
|
this.#propCheck('native', 'id', 'where');
|
|
70
77
|
this.#query.isNative = true;
|
|
@@ -83,7 +90,6 @@ module.exports = class QueryBuilder {
|
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
select(...select) {
|
|
86
|
-
this.#propCheck('select');
|
|
87
93
|
select = select.flat();
|
|
88
94
|
this.#query.select = select;
|
|
89
95
|
this.#query.args.select = select;
|
package/src/schema/Schema.js
CHANGED
|
@@ -61,11 +61,19 @@ module.exports = class Schema {
|
|
|
61
61
|
* Merge typeDefs and resolvers
|
|
62
62
|
*/
|
|
63
63
|
merge(schema = {}) {
|
|
64
|
+
// Normalize schema input
|
|
64
65
|
if (typeof schema === 'string') schema = { typeDefs: schema };
|
|
65
66
|
else if (schema instanceof Schema) schema = schema.toObject();
|
|
66
|
-
|
|
67
|
-
if (typeDefs)
|
|
68
|
-
|
|
67
|
+
|
|
68
|
+
if (schema.typeDefs) {
|
|
69
|
+
const typeDefs = Util.ensureArray(schema.typeDefs).map(td => (typeof td === 'string' ? parse(td) : td));
|
|
70
|
+
this.#typeDefs = mergeTypeDefs([typeDefs, this.#typeDefs], { noLocation: true, reverseDirectives: true, onFieldTypeConflict: a => a });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (schema.resolvers) {
|
|
74
|
+
this.#resolvers = mergeDeep(this.#resolvers, schema.resolvers);
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
return this;
|
|
70
78
|
}
|
|
71
79
|
|
|
@@ -75,7 +83,8 @@ module.exports = class Schema {
|
|
|
75
83
|
parse() {
|
|
76
84
|
if (this.#schema) return this.#schema;
|
|
77
85
|
|
|
78
|
-
|
|
86
|
+
// const schema = buildASTSchema(this.#typeDefs);
|
|
87
|
+
this.#schema = { types: {}, models: {}, indexes: [] };
|
|
79
88
|
let model, field, isField, isList;
|
|
80
89
|
const thunks = [];
|
|
81
90
|
|
|
@@ -86,6 +95,8 @@ module.exports = class Schema {
|
|
|
86
95
|
if (!allowedKinds.includes(node.kind)) return false;
|
|
87
96
|
|
|
88
97
|
if (modelKinds.includes(node.kind) && !operations.includes(name)) {
|
|
98
|
+
// this.#schema.types[name] = schema.getType(name);
|
|
99
|
+
|
|
89
100
|
model = this.#schema.models[name] = {
|
|
90
101
|
name,
|
|
91
102
|
key: name,
|
|
@@ -344,6 +355,7 @@ module.exports = class Schema {
|
|
|
344
355
|
scope: AutoGraphMixed #
|
|
345
356
|
meta: AutoGraphMixed # Custom input "meta" field for mutations
|
|
346
357
|
source: AutoGraphMixed # Data source (default: "default")
|
|
358
|
+
decorate: AutoGraphMixed # Decorator (default: "default")
|
|
347
359
|
embed: Boolean # Mark this an embedded model (default false)
|
|
348
360
|
persist: Boolean # Persist this model (default true)
|
|
349
361
|
) on OBJECT | INTERFACE
|
|
@@ -381,15 +393,15 @@ module.exports = class Schema {
|
|
|
381
393
|
|
|
382
394
|
static #api(schema) {
|
|
383
395
|
// These models are for creating types
|
|
384
|
-
const readModels = Object.values(schema.models).filter(model => model.crud
|
|
385
|
-
const createModels = Object.values(schema.models).filter(model => model.crud
|
|
386
|
-
const updateModels = Object.values(schema.models).filter(model => model.crud
|
|
396
|
+
const readModels = Object.values(schema.models).filter(model => model.crud?.includes('r'));
|
|
397
|
+
const createModels = Object.values(schema.models).filter(model => model.crud?.includes('c'));
|
|
398
|
+
const updateModels = Object.values(schema.models).filter(model => model.crud?.includes('u'));
|
|
387
399
|
|
|
388
400
|
// These are for defining schema queries/mutations
|
|
389
401
|
const entityModels = Object.values(schema.models).filter(model => model.isEntity);
|
|
390
|
-
const queryModels = entityModels.filter(model => model.crud
|
|
391
|
-
const mutationModels = entityModels.filter(model => ['c', 'u', 'd'].some(el => model.crud
|
|
392
|
-
const subscriptionModels = entityModels.filter(model => model.crud
|
|
402
|
+
const queryModels = entityModels.filter(model => model.crud?.includes('r'));
|
|
403
|
+
const mutationModels = entityModels.filter(model => ['c', 'u', 'd'].some(el => model.crud?.includes(el)));
|
|
404
|
+
const subscriptionModels = entityModels.filter(model => model.crud?.includes('s'));
|
|
393
405
|
|
|
394
406
|
return {
|
|
395
407
|
typeDefs: `
|
|
@@ -415,7 +427,7 @@ module.exports = class Schema {
|
|
|
415
427
|
`)}
|
|
416
428
|
|
|
417
429
|
${readModels.map((model) => {
|
|
418
|
-
const fields = Object.values(model.fields).filter(field => field.crud
|
|
430
|
+
const fields = Object.values(model.fields).filter(field => field.crud?.includes('r'));
|
|
419
431
|
const connectionFields = fields.filter(field => field.isConnection);
|
|
420
432
|
|
|
421
433
|
return `
|
|
@@ -443,7 +455,7 @@ module.exports = class Schema {
|
|
|
443
455
|
})}
|
|
444
456
|
|
|
445
457
|
${createModels.map((model) => {
|
|
446
|
-
const fields = Object.values(model.fields).filter(field => field.crud
|
|
458
|
+
const fields = Object.values(model.fields).filter(field => field.crud?.includes('c') && !field.isVirtual);
|
|
447
459
|
|
|
448
460
|
return `
|
|
449
461
|
input ${model}InputCreate {
|
|
@@ -453,7 +465,7 @@ module.exports = class Schema {
|
|
|
453
465
|
})}
|
|
454
466
|
|
|
455
467
|
${updateModels.map((model) => {
|
|
456
|
-
const fields = Object.values(model.fields).filter(field => field.crud
|
|
468
|
+
const fields = Object.values(model.fields).filter(field => field.crud?.includes('u') && !field.isVirtual);
|
|
457
469
|
|
|
458
470
|
return `
|
|
459
471
|
input ${model}InputUpdate {
|
|
@@ -484,9 +496,9 @@ module.exports = class Schema {
|
|
|
484
496
|
${mutationModels.map((model) => {
|
|
485
497
|
const api = [];
|
|
486
498
|
const meta = model.meta ? `meta: ${model.meta}` : '';
|
|
487
|
-
if (model.crud
|
|
488
|
-
if (model.crud
|
|
489
|
-
if (model.crud
|
|
499
|
+
if (model.crud?.includes('c')) api.push(`create${model}(input: ${model}InputCreate! ${meta}): ${model}!`);
|
|
500
|
+
if (model.crud?.includes('u')) api.push(`update${model}(id: ID! input: ${model}InputUpdate ${meta}): ${model}!`);
|
|
501
|
+
if (model.crud?.includes('d')) api.push(`delete${model}(id: ID! ${meta}): ${model}!`);
|
|
490
502
|
return api.join('\n');
|
|
491
503
|
})}
|
|
492
504
|
}
|
|
@@ -518,12 +530,12 @@ module.exports = class Schema {
|
|
|
518
530
|
}, {}),
|
|
519
531
|
Query: queryModels.reduce((prev, model) => {
|
|
520
532
|
return Object.assign(prev, {
|
|
521
|
-
[`get${model}`]: (doc, args, context, info) => context.autograph.resolver.match(model).args(args).one({ required: true }),
|
|
533
|
+
[`get${model}`]: (doc, args, context, info) => context.autograph.resolver.match(model).args(args).info(info).one({ required: true }),
|
|
522
534
|
[`find${model}`]: (doc, args, context, info) => {
|
|
523
535
|
return {
|
|
524
|
-
edges: () => context.autograph.resolver.match(model).args(args).many(),
|
|
525
|
-
count: () => context.autograph.resolver.match(model).args(args).count(),
|
|
526
|
-
pageInfo: () => context.autograph.resolver.match(model).args(args).many(),
|
|
536
|
+
edges: () => context.autograph.resolver.match(model).args(args).info(info).many(),
|
|
537
|
+
count: () => context.autograph.resolver.match(model).args(args).info(info).count(),
|
|
538
|
+
pageInfo: () => context.autograph.resolver.match(model).args(args).info(info).many(),
|
|
527
539
|
};
|
|
528
540
|
},
|
|
529
541
|
});
|
|
@@ -532,7 +544,7 @@ module.exports = class Schema {
|
|
|
532
544
|
const { id } = args;
|
|
533
545
|
const [modelName] = fromGUID(id);
|
|
534
546
|
const model = schema.models[modelName];
|
|
535
|
-
return context.autograph.resolver.match(model).id(id).one().then((result) => {
|
|
547
|
+
return context.autograph.resolver.match(model).id(id).info(info).one().then((result) => {
|
|
536
548
|
if (result == null) return result;
|
|
537
549
|
result.__typename = modelName; // eslint-disable-line no-underscore-dangle
|
|
538
550
|
return result;
|
|
@@ -541,9 +553,9 @@ module.exports = class Schema {
|
|
|
541
553
|
}),
|
|
542
554
|
...(mutationModels.length ? {
|
|
543
555
|
Mutation: mutationModels.reduce((prev, model) => {
|
|
544
|
-
if (model.crud
|
|
545
|
-
if (model.crud
|
|
546
|
-
if (model.crud
|
|
556
|
+
if (model.crud?.includes('c')) prev[`create${model}`] = (doc, args, context, info) => context.autograph.resolver.match(model).args(args).info(info).save(args.input);
|
|
557
|
+
if (model.crud?.includes('u')) prev[`update${model}`] = (doc, args, context, info) => context.autograph.resolver.match(model).args(args).info(info).save(args.input);
|
|
558
|
+
if (model.crud?.includes('d')) prev[`delete${model}`] = (doc, args, context, info) => context.autograph.resolver.match(model).args(args).info(info).delete();
|
|
547
559
|
return prev;
|
|
548
560
|
}, {}),
|
|
549
561
|
} : {}),
|
|
@@ -552,7 +564,7 @@ module.exports = class Schema {
|
|
|
552
564
|
[model]: Object.values(model.fields).filter(field => field.model?.isEntity).reduce((prev2, field) => {
|
|
553
565
|
return Object.assign(prev2, {
|
|
554
566
|
[field]: (doc, args, context, info) => {
|
|
555
|
-
return context.autograph.resolver.match(field.model).where({ [field.linkBy]: doc[field.linkField.name] }).args(args).resolve(info);
|
|
567
|
+
return context.autograph.resolver.match(field.model).where({ [field.linkBy]: doc[field.linkField.name] }).args(args).info(info).resolve(info);
|
|
556
568
|
},
|
|
557
569
|
});
|
|
558
570
|
}, {}),
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
const get = require('lodash.get');
|
|
1
2
|
const Util = require('@coderich/util');
|
|
2
3
|
const PicoMatch = require('picomatch');
|
|
3
4
|
const FillRange = require('fill-range');
|
|
4
5
|
const ObjectHash = require('object-hash');
|
|
5
6
|
const ObjectId = require('bson-objectid');
|
|
6
7
|
const DeepMerge = require('deepmerge');
|
|
8
|
+
const { parseResolveInfo, simplifyParsedResolveInfoFragmentWithType } = require('graphql-parse-resolve-info');
|
|
7
9
|
|
|
8
10
|
exports.isGlob = str => PicoMatch.scan(str).isGlob;
|
|
9
11
|
exports.globToRegex = (glob, options = {}) => PicoMatch.makeRe(glob, { nocase: true, ...options, expandRange: (a, b) => `(${FillRange(a, b, { toRegex: true })})` });
|
|
@@ -26,11 +28,19 @@ exports.finalizeWhereClause = (obj, arrayOp = '$in') => {
|
|
|
26
28
|
}, {});
|
|
27
29
|
};
|
|
28
30
|
|
|
29
|
-
exports.getGQLReturnType = (
|
|
31
|
+
exports.getGQLReturnType = (info) => {
|
|
32
|
+
const returnType = `${info.returnType}`;
|
|
30
33
|
const typeMap = { array: /^\[.+\].?$/, connection: /.+Connection!?$/, number: /^(Int|Float)!?$/, scalar: /.*/ };
|
|
31
34
|
return Object.entries(typeMap).find(([type, pattern]) => returnType.match(pattern))[0];
|
|
32
35
|
};
|
|
33
36
|
|
|
37
|
+
exports.getGQLSelectFields = (model, info) => {
|
|
38
|
+
const parsed = parseResolveInfo(info, { noLocation: true });
|
|
39
|
+
const { fields } = simplifyParsedResolveInfoFragmentWithType(parsed, info.returnType);
|
|
40
|
+
const node = get(fields, `edges.fieldsByTypeName.${model}Edge.node.fieldsByTypeName.${model}`);
|
|
41
|
+
return Object.keys(node || fields);
|
|
42
|
+
};
|
|
43
|
+
|
|
34
44
|
exports.removeUndefinedDeep = (obj) => {
|
|
35
45
|
return Util.unflatten(Object.entries(Util.flatten(obj)).reduce((prev, [key, value]) => {
|
|
36
46
|
return value === undefined ? prev : Object.assign(prev, { [key]: value });
|