@coderich/autograph 0.13.49 → 0.13.51
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/Emitter.js +3 -3
- package/src/data/Pipeline.js +1 -1
- package/src/data/Resolver.js +6 -5
- package/src/query/Query.js +1 -1
- package/src/query/QueryResolver.js +7 -10
- package/src/schema/Schema.js +42 -11
package/package.json
CHANGED
package/src/data/Emitter.js
CHANGED
|
@@ -27,8 +27,8 @@ class Emitter extends EventEmitter {
|
|
|
27
27
|
|
|
28
28
|
// Next functions are async and control the timing of the next phase
|
|
29
29
|
Promise.all(nextFuncs.sort(Emitter.sort).map((fn) => {
|
|
30
|
-
return new Promise((next) => {
|
|
31
|
-
Promise.resolve(fn(data, next));
|
|
30
|
+
return new Promise((next, err) => {
|
|
31
|
+
Promise.resolve().then(() => fn(data, next)).catch(err);
|
|
32
32
|
}).then((result) => {
|
|
33
33
|
if (result !== undefined) throw new AbortEarlyError(result);
|
|
34
34
|
}).catch(reject);
|
|
@@ -89,7 +89,7 @@ class Emitter extends EventEmitter {
|
|
|
89
89
|
} : (event, next) => {
|
|
90
90
|
if (arr.includes(`${event.query[prop]}`)) {
|
|
91
91
|
if (once) this.removeListener(eventName, wrapper);
|
|
92
|
-
return
|
|
92
|
+
return listener(event, next);
|
|
93
93
|
}
|
|
94
94
|
return next();
|
|
95
95
|
};
|
package/src/data/Pipeline.js
CHANGED
|
@@ -49,10 +49,10 @@ module.exports = class Pipeline {
|
|
|
49
49
|
// Additional Transformers
|
|
50
50
|
Pipeline.define('toArray', ({ value }) => (Array.isArray(value) ? value : [value]), { itemize: false });
|
|
51
51
|
Pipeline.define('toDate', ({ value }) => new Date(value), { configurable: true });
|
|
52
|
+
Pipeline.define('createdAt', ({ query, model, value }) => value || (query.crud === 'create' || model.isEmbedded ? new Date() : undefined), { ignoreNull: false });
|
|
52
53
|
Pipeline.define('updatedAt', () => new Date(), { ignoreNull: false });
|
|
53
54
|
Pipeline.define('toTitleCase', ({ value }) => value.replace(/\w\S*/g, w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()));
|
|
54
55
|
Pipeline.define('toSentenceCase', ({ value }) => value.charAt(0).toUpperCase() + value.slice(1));
|
|
55
|
-
Pipeline.define('createdAt', ({ value }) => value || new Date(), { ignoreNull: false });
|
|
56
56
|
Pipeline.define('timestamp', () => Date.now(), { ignoreNull: false });
|
|
57
57
|
Pipeline.define('dedupe', ({ value }) => uniqWith(value, (b, c) => hashObject(b) === hashObject(c)), { itemize: false });
|
|
58
58
|
|
package/src/data/Resolver.js
CHANGED
|
@@ -2,6 +2,7 @@ const { graphql } = require('graphql');
|
|
|
2
2
|
const Boom = require('@hapi/boom');
|
|
3
3
|
const Util = require('@coderich/util');
|
|
4
4
|
const QueryResolver = require('../query/QueryResolver');
|
|
5
|
+
const AppService = require('../service/AppService');
|
|
5
6
|
const Emitter = require('./Emitter');
|
|
6
7
|
const Loader = require('./Loader');
|
|
7
8
|
const DataLoader = require('./DataLoader');
|
|
@@ -225,7 +226,7 @@ module.exports = class Resolver {
|
|
|
225
226
|
|
|
226
227
|
return this.#createSystemEvent(query, (tquery) => {
|
|
227
228
|
return thunk(tquery).then((result) => {
|
|
228
|
-
if (flags?.required && (result == null || result?.length === 0)) throw Boom.notFound();
|
|
229
|
+
if (flags?.required && (result == null || result?.length === 0)) throw Boom.notFound(`${model} Not Found`);
|
|
229
230
|
return result;
|
|
230
231
|
});
|
|
231
232
|
});
|
|
@@ -306,10 +307,9 @@ module.exports = class Resolver {
|
|
|
306
307
|
const tquery = await $query.transform(false);
|
|
307
308
|
query = tquery.toObject();
|
|
308
309
|
event = this.#createEvent(query);
|
|
309
|
-
if (query.
|
|
310
|
+
if (['create', 'update'].includes(query.crud)) await Promise.all([...query.input.$thunks, Emitter.emit('validate', event)]);
|
|
310
311
|
return thunk(tquery);
|
|
311
312
|
}).then((result) => {
|
|
312
|
-
event.doc ??= result; // Case of create
|
|
313
313
|
event.result = result; // backwards compat
|
|
314
314
|
query.result = result;
|
|
315
315
|
return Emitter.emit(`post${type}`, event);
|
|
@@ -326,8 +326,9 @@ module.exports = class Resolver {
|
|
|
326
326
|
Object.assign(event, query);
|
|
327
327
|
query.match = query.where;
|
|
328
328
|
query.toObject = () => query;
|
|
329
|
-
event.
|
|
330
|
-
event.input
|
|
329
|
+
event.doc ??= {};
|
|
330
|
+
event.input ??= {};
|
|
331
|
+
event.merged = AppService.mergeDeep(event.doc, event.input);
|
|
331
332
|
|
|
332
333
|
return event;
|
|
333
334
|
}
|
package/src/query/Query.js
CHANGED
|
@@ -51,7 +51,7 @@ module.exports = class Query {
|
|
|
51
51
|
const args = { query: this.#query, resolver: this.#resolver, context: this.#context };
|
|
52
52
|
|
|
53
53
|
const [input, where, sort] = [
|
|
54
|
-
this.#model.transformers.
|
|
54
|
+
this.#model.transformers[this.#query.crud]?.transform(Util.unflatten(this.#query.input, { safe: true }), args),
|
|
55
55
|
this.#query.isNative ? this.#query.where : this.#model.transformers.where.transform(Util.unflatten(this.#query.where ?? {}, { safe: true }), args),
|
|
56
56
|
this.#model.transformers.sort.transform(Util.unflatten(this.#query.sort, { safe: true }), args),
|
|
57
57
|
];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const get = require('lodash.get');
|
|
2
2
|
const Util = require('@coderich/util');
|
|
3
3
|
const QueryBuilder = require('./QueryBuilder');
|
|
4
|
-
const { mergeDeep } = require('../service/AppService');
|
|
5
4
|
|
|
6
5
|
module.exports = class QueryResolver extends QueryBuilder {
|
|
7
6
|
#model;
|
|
@@ -34,12 +33,7 @@ module.exports = class QueryResolver extends QueryBuilder {
|
|
|
34
33
|
}
|
|
35
34
|
case 'updateOne': {
|
|
36
35
|
return this.#get(query).then((doc) => {
|
|
37
|
-
|
|
38
|
-
// if (node.field.defaultValue !== undefined || ['instruct', 'restruct', 'serialize'].some(el => node.field.pipelines[el]?.length)) return node;
|
|
39
|
-
// return false;
|
|
40
|
-
// });
|
|
41
|
-
const merged = mergeDeep({}, doc, Util.unflatten(input, { safe: true }));
|
|
42
|
-
return this.#resolver.resolve(query.clone({ doc, input: merged }));
|
|
36
|
+
return this.#resolver.resolve(query.clone({ doc }));
|
|
43
37
|
});
|
|
44
38
|
}
|
|
45
39
|
case 'updateMany': {
|
|
@@ -50,7 +44,8 @@ module.exports = class QueryResolver extends QueryBuilder {
|
|
|
50
44
|
case 'pushOne': {
|
|
51
45
|
return this.#get(query).then((doc) => {
|
|
52
46
|
const [key] = Object.keys(input);
|
|
53
|
-
const
|
|
47
|
+
const $query = Object.assign(query.toObject(), { doc });
|
|
48
|
+
const values = get(this.#model.transformers.create.transform(input, { query: $query }), key);
|
|
54
49
|
const $input = { [key]: (get(doc, key) || []).concat(...values) };
|
|
55
50
|
return this.#resolver.match(this.#model.name).id(doc.id).save($input);
|
|
56
51
|
});
|
|
@@ -64,7 +59,8 @@ module.exports = class QueryResolver extends QueryBuilder {
|
|
|
64
59
|
case 'pullOne': {
|
|
65
60
|
return this.#get(query).then((doc) => {
|
|
66
61
|
const [key] = Object.keys(input);
|
|
67
|
-
const
|
|
62
|
+
const $query = Object.assign(query.toObject(), { doc });
|
|
63
|
+
const values = get(this.#model.transformers.create.transform(input, { query: $query }), key, []);
|
|
68
64
|
const $doc = Util.pathmap(key, doc, (arr) => {
|
|
69
65
|
return arr.filter(el => values.every(v => `${v}` !== `${el}`));
|
|
70
66
|
});
|
|
@@ -80,7 +76,8 @@ module.exports = class QueryResolver extends QueryBuilder {
|
|
|
80
76
|
case 'spliceOne': {
|
|
81
77
|
return this.#get(query).then((doc) => {
|
|
82
78
|
const [key] = Object.keys(input);
|
|
83
|
-
const
|
|
79
|
+
const $query = Object.assign(query.toObject(), { doc });
|
|
80
|
+
const [find, replace] = get(this.#model.transformers.create.transform(input, { query: $query }), key);
|
|
84
81
|
const $input = { [key]: (get(doc, key) || []).map(el => (`${el}` === `${find}` ? replace : el)) };
|
|
85
82
|
return this.#resolver.match(this.#model.name).id(doc.id).save($input);
|
|
86
83
|
});
|
package/src/schema/Schema.js
CHANGED
|
@@ -17,7 +17,8 @@ const fieldKinds = [Kind.FIELD_DEFINITION];
|
|
|
17
17
|
const modelKinds = [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION].concat(interfaceKinds);
|
|
18
18
|
const allowedKinds = modelKinds.concat(fieldKinds).concat(Kind.DOCUMENT, Kind.NON_NULL_TYPE, Kind.NAMED_TYPE, Kind.LIST_TYPE, Kind.DIRECTIVE).concat(scalarKinds).concat(enumKinds);
|
|
19
19
|
const pipelines = ['validate', 'construct', 'restruct', 'instruct', 'normalize', 'serialize', 'deserialize'];
|
|
20
|
-
const
|
|
20
|
+
const createPipelines = ['validate', 'construct', 'instruct', 'normalize', 'serialize'];
|
|
21
|
+
const updatePipelines = ['validate', 'restruct', 'instruct', 'normalize', 'serialize'];
|
|
21
22
|
const scalars = ['ID', 'String', 'Float', 'Int', 'Boolean'];
|
|
22
23
|
|
|
23
24
|
module.exports = class Schema {
|
|
@@ -146,7 +147,8 @@ module.exports = class Schema {
|
|
|
146
147
|
generator: this.#config.generators?.default,
|
|
147
148
|
pipelines: pipelines.reduce((prev, key) => Object.assign(prev, { [key]: [] }), {}),
|
|
148
149
|
transformers: {
|
|
149
|
-
|
|
150
|
+
create: new Transformer({ args: { schema: this.#schema, path: [] } }),
|
|
151
|
+
update: new Transformer({ args: { schema: this.#schema, path: [] } }),
|
|
150
152
|
where: new Transformer({ args: { schema: this.#schema, path: [] } }),
|
|
151
153
|
doc: new Transformer({ args: { schema: this.#schema, path: [] } }),
|
|
152
154
|
},
|
|
@@ -351,7 +353,7 @@ module.exports = class Schema {
|
|
|
351
353
|
}, {}),
|
|
352
354
|
});
|
|
353
355
|
|
|
354
|
-
$model.transformers.
|
|
356
|
+
$model.transformers.create.config({
|
|
355
357
|
strictSchema: true,
|
|
356
358
|
shape: Object.values($model.fields).reduce((prev, curr) => {
|
|
357
359
|
const args = { model: $model, field: curr };
|
|
@@ -360,11 +362,7 @@ module.exports = class Schema {
|
|
|
360
362
|
a => Pipeline.$cast({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
361
363
|
a => Pipeline.$normalize({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
362
364
|
a => Pipeline.$instruct({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
363
|
-
|
|
364
|
-
if (a.query.crud === 'create') return Pipeline.$construct({ ...a, ...args, path: a.path.concat(curr.name) });
|
|
365
|
-
if (a.query.crud === 'update') return Pipeline.$restruct({ ...a, ...args, path: a.path.concat(curr.name) });
|
|
366
|
-
return undefined;
|
|
367
|
-
},
|
|
365
|
+
a => Pipeline.$construct({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
368
366
|
a => Pipeline.$serialize({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
369
367
|
];
|
|
370
368
|
|
|
@@ -372,18 +370,51 @@ module.exports = class Schema {
|
|
|
372
370
|
rules.push(a => Util.map(a.value, (value, i) => {
|
|
373
371
|
const path = a.path.concat(curr.name);
|
|
374
372
|
if (curr.isArray) path.push(i);
|
|
375
|
-
return curr.model.transformers.
|
|
373
|
+
return curr.model.transformers.create.transform(value, { ...args, thunks: a.thunks, query: a.query, resolver: a.resolver, context: a.context, path });
|
|
376
374
|
}));
|
|
377
375
|
}
|
|
378
376
|
|
|
379
377
|
// Validate
|
|
380
|
-
rules.push(a => Pipeline.$validate({ ...a, ...args, path: a.path.concat(curr.name) }));
|
|
378
|
+
rules.push(a => (a.query.op === 'createOne' ? Pipeline.$validate({ ...a, ...args, path: a.path.concat(curr.name) }) : undefined));
|
|
381
379
|
|
|
382
380
|
return Object.assign(prev, { [curr.name]: rules });
|
|
383
381
|
}, {}),
|
|
384
382
|
defaults: Object.values($model.fields).reduce((prev, curr) => {
|
|
385
383
|
if (curr.defaultValue !== undefined) return Object.assign(prev, { [curr.name]: curr.defaultValue });
|
|
386
|
-
if (
|
|
384
|
+
if (createPipelines.some(el => curr.pipelines[el].length)) return Object.assign(prev, { [curr.name]: undefined });
|
|
385
|
+
return prev;
|
|
386
|
+
}, {}),
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
$model.transformers.update.config({
|
|
390
|
+
strictSchema: true,
|
|
391
|
+
shape: Object.values($model.fields).reduce((prev, curr) => {
|
|
392
|
+
const args = { model: $model, field: curr };
|
|
393
|
+
|
|
394
|
+
const rules = [
|
|
395
|
+
a => Pipeline.$cast({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
396
|
+
a => Pipeline.$normalize({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
397
|
+
a => Pipeline.$instruct({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
398
|
+
a => Pipeline.$restruct({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
399
|
+
a => Pipeline.$serialize({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
400
|
+
];
|
|
401
|
+
|
|
402
|
+
if (curr.isEmbedded) {
|
|
403
|
+
rules.push(a => Util.map(a.value, (value, i) => {
|
|
404
|
+
const path = a.path.concat(curr.name);
|
|
405
|
+
if (curr.isArray) path.push(i);
|
|
406
|
+
return curr.model.transformers.update.transform(value, { ...args, thunks: a.thunks, query: a.query, resolver: a.resolver, context: a.context, path });
|
|
407
|
+
}));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Validate
|
|
411
|
+
rules.push(a => (a.query.op === 'updateOne' ? Pipeline.$validate({ ...a, ...args, path: a.path.concat(curr.name) }) : undefined));
|
|
412
|
+
|
|
413
|
+
return Object.assign(prev, { [curr.name]: rules });
|
|
414
|
+
}, {}),
|
|
415
|
+
defaults: Object.values($model.fields).reduce((prev, curr) => {
|
|
416
|
+
// if (curr.defaultValue !== undefined) return Object.assign(prev, { [curr.name]: curr.defaultValue });
|
|
417
|
+
if (updatePipelines.some(el => curr.pipelines[el].length)) return Object.assign(prev, { [curr.name]: undefined });
|
|
387
418
|
return prev;
|
|
388
419
|
}, {}),
|
|
389
420
|
});
|