@coderich/autograph 0.13.5 → 0.13.7
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 +1 -1
- package/src/data/Resolver.js +1 -1
- package/src/schema/Schema.js +52 -32
package/package.json
CHANGED
package/src/data/Resolver.js
CHANGED
|
@@ -23,7 +23,7 @@ module.exports = class Resolver {
|
|
|
23
23
|
this.#dataLoaders = this.#createDataLoaders();
|
|
24
24
|
this.driver = this.raw; // Alias
|
|
25
25
|
this.model = this.match; // Alias
|
|
26
|
-
Util.set(this.#context,
|
|
26
|
+
Util.set(this.#context, `${this.#schema.namespace}.resolver`, this);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
getContext() {
|
package/src/schema/Schema.js
CHANGED
|
@@ -23,17 +23,25 @@ module.exports = class Schema {
|
|
|
23
23
|
|
|
24
24
|
constructor(config) {
|
|
25
25
|
this.#config = config;
|
|
26
|
-
this.#
|
|
26
|
+
this.#config.namespace ??= 'autograph';
|
|
27
|
+
this.#config.directives ??= {};
|
|
28
|
+
this.#config.directives.model ??= 'model';
|
|
29
|
+
this.#config.directives.field ??= 'field';
|
|
30
|
+
this.#config.directives.link ??= 'link';
|
|
31
|
+
this.#config.directives.index ??= 'index';
|
|
32
|
+
this.#typeDefs = Schema.#framework(this.#config.directives);
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
/**
|
|
30
36
|
* Decorate each marked @model with config-driven field decorators
|
|
31
37
|
*/
|
|
32
38
|
decorate() {
|
|
39
|
+
const { directives } = this.#config;
|
|
40
|
+
|
|
33
41
|
this.#typeDefs = visit(this.#typeDefs, {
|
|
34
42
|
enter: (node) => {
|
|
35
43
|
if (modelKinds.includes(node.kind) && !operations.includes(node.name.value)) {
|
|
36
|
-
const directive = node.directives.find(({ name }) => name.value ===
|
|
44
|
+
const directive = node.directives.find(({ name }) => name.value === directives.model);
|
|
37
45
|
|
|
38
46
|
if (directive) {
|
|
39
47
|
const arg = directive.arguments.find(({ name }) => name.value === 'decorate');
|
|
@@ -66,7 +74,16 @@ module.exports = class Schema {
|
|
|
66
74
|
else if (schema instanceof Schema) schema = schema.toObject();
|
|
67
75
|
|
|
68
76
|
if (schema.typeDefs) {
|
|
69
|
-
const typeDefs = Util.ensureArray(schema.typeDefs).map(
|
|
77
|
+
const typeDefs = Util.ensureArray(schema.typeDefs).map((td) => {
|
|
78
|
+
try {
|
|
79
|
+
const $td = typeof td === 'string' ? parse(td) : td;
|
|
80
|
+
return $td;
|
|
81
|
+
} catch (e) {
|
|
82
|
+
console.log(`Unable to parse typeDef (being ignored):\n${td}`); // eslint-disable-line
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}).filter(Boolean);
|
|
86
|
+
|
|
70
87
|
this.#typeDefs = mergeTypeDefs([typeDefs, this.#typeDefs], { noLocation: true, reverseDirectives: true, onFieldTypeConflict: a => a });
|
|
71
88
|
}
|
|
72
89
|
|
|
@@ -84,7 +101,8 @@ module.exports = class Schema {
|
|
|
84
101
|
if (this.#schema) return this.#schema;
|
|
85
102
|
|
|
86
103
|
// const schema = buildASTSchema(this.#typeDefs);
|
|
87
|
-
|
|
104
|
+
const { directives, namespace } = this.#config;
|
|
105
|
+
this.#schema = { types: {}, models: {}, indexes: [], namespace };
|
|
88
106
|
let model, field, isField, isList;
|
|
89
107
|
const thunks = [];
|
|
90
108
|
|
|
@@ -131,8 +149,8 @@ module.exports = class Schema {
|
|
|
131
149
|
const target = isField ? field : model;
|
|
132
150
|
target.directives[name] = target.directives[name] || {};
|
|
133
151
|
|
|
134
|
-
if (name ===
|
|
135
|
-
else if (name ===
|
|
152
|
+
if (name === directives.model) model.isMarkedModel = true;
|
|
153
|
+
else if (name === directives.index) this.#schema.indexes.push({ model });
|
|
136
154
|
|
|
137
155
|
node.arguments.forEach((arg) => {
|
|
138
156
|
const key = arg.name.value;
|
|
@@ -140,54 +158,54 @@ module.exports = class Schema {
|
|
|
140
158
|
const value = values ? values.map(n => n.value) : val;
|
|
141
159
|
target.directives[name][key] = value;
|
|
142
160
|
|
|
143
|
-
if (name ===
|
|
161
|
+
if (name === directives.index) this.#schema.indexes[this.#schema.indexes.length - 1][key] = value;
|
|
144
162
|
|
|
145
163
|
switch (`${name}-${key}`) {
|
|
146
164
|
// Model specific directives
|
|
147
|
-
case
|
|
165
|
+
case `${directives.model}-id`: {
|
|
148
166
|
model.idField = value;
|
|
149
167
|
break;
|
|
150
168
|
}
|
|
151
|
-
case
|
|
169
|
+
case `${directives.model}-source`: {
|
|
152
170
|
model.source = this.#config.dataSources?.[value];
|
|
153
171
|
break;
|
|
154
172
|
}
|
|
155
|
-
case
|
|
173
|
+
case `${directives.model}-loader`: {
|
|
156
174
|
model.loader = this.#config.dataLoaders?.[value];
|
|
157
175
|
break;
|
|
158
176
|
}
|
|
159
|
-
case
|
|
177
|
+
case `${directives.model}-embed`: {
|
|
160
178
|
model.isEmbedded = value;
|
|
161
179
|
break;
|
|
162
180
|
}
|
|
163
181
|
// Field specific directives
|
|
164
|
-
case
|
|
182
|
+
case `${directives.field}-default`: {
|
|
165
183
|
field.defaultValue = value;
|
|
166
184
|
break;
|
|
167
185
|
}
|
|
168
|
-
case
|
|
186
|
+
case `${directives.field}-connection`: {
|
|
169
187
|
field.isConnection = value;
|
|
170
188
|
break;
|
|
171
189
|
}
|
|
172
|
-
case
|
|
190
|
+
case `${directives.field}-validate`: { // Alias for finalize
|
|
173
191
|
target.pipelines.finalize = target.pipelines.finalize.concat(value).filter(Boolean);
|
|
174
192
|
break;
|
|
175
193
|
}
|
|
176
|
-
case
|
|
194
|
+
case `${directives.link}-by`: {
|
|
177
195
|
field.linkBy = value;
|
|
178
196
|
field.isVirtual = true;
|
|
179
197
|
break;
|
|
180
198
|
}
|
|
181
199
|
// Generic by target directives
|
|
182
|
-
case
|
|
200
|
+
case `${directives.model}-persist`: case `${directives.field}-persist`: {
|
|
183
201
|
target.isPersistable = value;
|
|
184
202
|
break;
|
|
185
203
|
}
|
|
186
|
-
case
|
|
204
|
+
case `${directives.model}-crud`: case `${directives.model}-scope`: case `${directives.field}-crud`: {
|
|
187
205
|
target[key] = Util.nvl(value, '');
|
|
188
206
|
break;
|
|
189
207
|
}
|
|
190
|
-
case
|
|
208
|
+
case `${directives.model}-key`: case `${directives.model}-meta`: case `${directives.field}-key`: case `${directives.field}-onDelete`: {
|
|
191
209
|
target[key] = value;
|
|
192
210
|
break;
|
|
193
211
|
}
|
|
@@ -344,7 +362,9 @@ module.exports = class Schema {
|
|
|
344
362
|
return this.#config.makeExecutableSchema(this.toObject());
|
|
345
363
|
}
|
|
346
364
|
|
|
347
|
-
static #framework() {
|
|
365
|
+
static #framework(directives) {
|
|
366
|
+
const { model, field, link, index } = directives;
|
|
367
|
+
|
|
348
368
|
return parse(`
|
|
349
369
|
scalar AutoGraphMixed
|
|
350
370
|
|
|
@@ -352,7 +372,7 @@ module.exports = class Schema {
|
|
|
352
372
|
enum AutoGraphOnDeleteEnum { cascade nullify restrict defer }
|
|
353
373
|
enum AutoGraphPipelineEnum { ${Object.keys(Pipeline).filter(k => !k.startsWith('$')).join(' ')} }
|
|
354
374
|
|
|
355
|
-
directive
|
|
375
|
+
directive @${model}(
|
|
356
376
|
id: String # Specify the ID/PK field (default "id")
|
|
357
377
|
key: String # Specify db table/collection name
|
|
358
378
|
crud: AutoGraphMixed # CRUD API
|
|
@@ -364,7 +384,7 @@ module.exports = class Schema {
|
|
|
364
384
|
persist: Boolean # Persist this model (default true)
|
|
365
385
|
) on OBJECT | INTERFACE
|
|
366
386
|
|
|
367
|
-
directive
|
|
387
|
+
directive @${field}(
|
|
368
388
|
key: String # Specify db key
|
|
369
389
|
persist: Boolean # Persist this field (default true)
|
|
370
390
|
connection: Boolean # Treat this field as a connection type (default false - rolling this out slowly)
|
|
@@ -382,13 +402,13 @@ module.exports = class Schema {
|
|
|
382
402
|
validate: [AutoGraphPipelineEnum!] # Alias for finalize
|
|
383
403
|
) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | SCALAR
|
|
384
404
|
|
|
385
|
-
directive
|
|
405
|
+
directive @${link}(
|
|
386
406
|
to: AutoGraphMixed # The MODEL to link to (default's to modelRef)
|
|
387
407
|
by: AutoGraphMixed! # The FIELD to match yourself by
|
|
388
408
|
use: AutoGraphMixed # The VALUE to use (default's to @link'd value); useful for many-to-many relationships
|
|
389
409
|
) on FIELD_DEFINITION
|
|
390
410
|
|
|
391
|
-
directive
|
|
411
|
+
directive @${index}(
|
|
392
412
|
name: String
|
|
393
413
|
on: [AutoGraphMixed!]!
|
|
394
414
|
type: AutoGraphIndexEnum!
|
|
@@ -535,12 +555,12 @@ module.exports = class Schema {
|
|
|
535
555
|
}, {}),
|
|
536
556
|
Query: queryModels.reduce((prev, model) => {
|
|
537
557
|
return Object.assign(prev, {
|
|
538
|
-
[`get${model}`]: (doc, args, context, info) => context.
|
|
558
|
+
[`get${model}`]: (doc, args, context, info) => context[schema.namespace].resolver.match(model).args(args).info(info).one({ required: true }),
|
|
539
559
|
[`find${model}`]: (doc, args, context, info) => {
|
|
540
560
|
return {
|
|
541
|
-
edges: () => context.
|
|
542
|
-
count: () => context.
|
|
543
|
-
pageInfo: () => context.
|
|
561
|
+
edges: () => context[schema.namespace].resolver.match(model).args(args).info(info).many(),
|
|
562
|
+
count: () => context[schema.namespace].resolver.match(model).args(args).info(info).count(),
|
|
563
|
+
pageInfo: () => context[schema.namespace].resolver.match(model).args(args).info(info).many(),
|
|
544
564
|
};
|
|
545
565
|
},
|
|
546
566
|
});
|
|
@@ -549,7 +569,7 @@ module.exports = class Schema {
|
|
|
549
569
|
const { id } = args;
|
|
550
570
|
const [modelName] = fromGUID(id);
|
|
551
571
|
const model = schema.models[modelName];
|
|
552
|
-
return context.
|
|
572
|
+
return context[schema.namespace].resolver.match(model).id(id).info(info).one().then((result) => {
|
|
553
573
|
if (result == null) return result;
|
|
554
574
|
result.__typename = modelName; // eslint-disable-line no-underscore-dangle
|
|
555
575
|
return result;
|
|
@@ -558,9 +578,9 @@ module.exports = class Schema {
|
|
|
558
578
|
}),
|
|
559
579
|
...(mutationModels.length ? {
|
|
560
580
|
Mutation: mutationModels.reduce((prev, model) => {
|
|
561
|
-
if (model.crud?.includes('c')) prev[`create${model}`] = (doc, args, context, info) => context.
|
|
562
|
-
if (model.crud?.includes('u')) prev[`update${model}`] = (doc, args, context, info) => context.
|
|
563
|
-
if (model.crud?.includes('d')) prev[`delete${model}`] = (doc, args, context, info) => context.
|
|
581
|
+
if (model.crud?.includes('c')) prev[`create${model}`] = (doc, args, context, info) => context[schema.namespace].resolver.match(model).args(args).info(info).save(args.input);
|
|
582
|
+
if (model.crud?.includes('u')) prev[`update${model}`] = (doc, args, context, info) => context[schema.namespace].resolver.match(model).args(args).info(info).save(args.input);
|
|
583
|
+
if (model.crud?.includes('d')) prev[`delete${model}`] = (doc, args, context, info) => context[schema.namespace].resolver.match(model).args(args).info(info).delete();
|
|
564
584
|
return prev;
|
|
565
585
|
}, {}),
|
|
566
586
|
} : {}),
|
|
@@ -569,7 +589,7 @@ module.exports = class Schema {
|
|
|
569
589
|
[model]: Object.values(model.fields).filter(field => field.model?.isEntity).reduce((prev2, field) => {
|
|
570
590
|
return Object.assign(prev2, {
|
|
571
591
|
[field]: (doc, args, context, info) => {
|
|
572
|
-
return context.
|
|
592
|
+
return context[schema.namespace].resolver.match(field.model).where({ [field.linkBy]: doc[field.linkField.name] }).args(args).info(info).resolve(info);
|
|
573
593
|
},
|
|
574
594
|
});
|
|
575
595
|
}, {}),
|