@coderich/autograph 0.13.23 → 0.13.25
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/Pipeline.js +10 -16
- package/src/data/Resolver.js +11 -2
- package/src/schema/Schema.js +20 -6
package/package.json
CHANGED
package/src/data/Pipeline.js
CHANGED
|
@@ -19,16 +19,8 @@ module.exports = class Pipeline {
|
|
|
19
19
|
const wrapper = Object.defineProperty((args) => {
|
|
20
20
|
try {
|
|
21
21
|
if (ignoreNull && args.value == null) return args.value;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return Util.map(args.value, (value) => {
|
|
25
|
-
const v = factory({ ...args, value });
|
|
26
|
-
return v === undefined ? value : v;
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const value = factory(args);
|
|
31
|
-
return value === undefined ? args.value : value;
|
|
22
|
+
if (ignoreNull && itemize) return Util.map(args.value, value => Util.uvl(factory({ ...args, value }), value));
|
|
23
|
+
return Util.uvl(factory(args), args.value);
|
|
32
24
|
} catch (e) {
|
|
33
25
|
const { data = {} } = e;
|
|
34
26
|
throw Boom.boomify(e, { data: { ...args, ...data } });
|
|
@@ -74,12 +66,14 @@ module.exports = class Pipeline {
|
|
|
74
66
|
|
|
75
67
|
//
|
|
76
68
|
Pipeline.define('$pk', (params) => {
|
|
77
|
-
const
|
|
69
|
+
const { pkField } = params.model;
|
|
70
|
+
const value = get(params.query.doc, params.path) || params.value?.[pkField] || params.value; // I "think" the get() is for embedded documents
|
|
78
71
|
return Pipeline[params.field.id]({ ...params, value });
|
|
79
72
|
}, { ignoreNull: false });
|
|
80
73
|
|
|
81
74
|
Pipeline.define('$fk', (params) => {
|
|
82
|
-
const
|
|
75
|
+
const { fkField } = params.field;
|
|
76
|
+
const value = params.value?.[fkField] || params.value;
|
|
83
77
|
return Pipeline[params.field.id]({ ...params, value });
|
|
84
78
|
});
|
|
85
79
|
|
|
@@ -116,10 +110,10 @@ module.exports = class Pipeline {
|
|
|
116
110
|
});
|
|
117
111
|
|
|
118
112
|
//
|
|
119
|
-
Pipeline.define('
|
|
120
|
-
const { type } = field;
|
|
113
|
+
Pipeline.define('ensureFK', ({ query, resolver, field, value }) => {
|
|
114
|
+
const { type, fkField } = field;
|
|
121
115
|
const ids = Util.filterBy(Util.ensureArray(value), (a, b) => `${a}` === `${b}`);
|
|
122
|
-
return resolver.match(type).flags(query.flags).where({
|
|
116
|
+
return resolver.match(type).flags(query.flags).where({ [fkField]: ids }).count().then((count) => {
|
|
123
117
|
if (count !== ids.length) throw Boom.notFound(`${type} Not Found`);
|
|
124
118
|
});
|
|
125
119
|
}, { itemize: false });
|
|
@@ -166,7 +160,7 @@ module.exports = class Pipeline {
|
|
|
166
160
|
static resolve(params, pipeline) {
|
|
167
161
|
const transformers = params.field.pipelines[pipeline] || [];
|
|
168
162
|
|
|
169
|
-
return Util.pipeline(transformers.map(t =>
|
|
163
|
+
return Util.pipeline(transformers.map(t => (value) => {
|
|
170
164
|
return Pipeline[t]({ ...params, value });
|
|
171
165
|
}), params.value);
|
|
172
166
|
}
|
package/src/data/Resolver.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { graphql } = require('graphql');
|
|
2
2
|
const Boom = require('@hapi/boom');
|
|
3
3
|
const Util = require('@coderich/util');
|
|
4
|
+
const Pipeline = require('./Pipeline');
|
|
4
5
|
const Emitter = require('./Emitter');
|
|
5
6
|
const Loader = require('./Loader');
|
|
6
7
|
const DataLoader = require('./DataLoader');
|
|
@@ -220,7 +221,15 @@ module.exports = class Resolver {
|
|
|
220
221
|
if (result == null) return result;
|
|
221
222
|
if (typeof result !== 'object') return result;
|
|
222
223
|
return Object.defineProperties(Util.map(result, (doc) => {
|
|
223
|
-
|
|
224
|
+
// Transform result to domain model
|
|
225
|
+
const $doc = this.#schema.models[model].walk(doc, (node) => {
|
|
226
|
+
if (node.value === undefined) return undefined;
|
|
227
|
+
node.key = node.field.name;
|
|
228
|
+
node.value = Pipeline.$cast(node);
|
|
229
|
+
return node;
|
|
230
|
+
}, { key: 'key' });
|
|
231
|
+
|
|
232
|
+
// Assign useful/needed meta data
|
|
224
233
|
return Object.defineProperties($doc, {
|
|
225
234
|
$: {
|
|
226
235
|
get: () => {
|
|
@@ -233,7 +242,7 @@ module.exports = class Resolver {
|
|
|
233
242
|
}
|
|
234
243
|
case 'lookup': {
|
|
235
244
|
const field = self.toModel(model).fields[args[0]];
|
|
236
|
-
const where = { [field.linkBy]: $doc[field.linkField.
|
|
245
|
+
const where = field.isVirtual ? { [field.linkBy]: $doc[field.linkField] } : { [field.fkField]: $doc[field] };
|
|
237
246
|
return self.match(field.model).where(where);
|
|
238
247
|
}
|
|
239
248
|
default: {
|
package/src/schema/Schema.js
CHANGED
|
@@ -59,7 +59,7 @@ module.exports = class Schema {
|
|
|
59
59
|
|
|
60
60
|
if (directive) {
|
|
61
61
|
const arg = directive.arguments.find(({ name }) => name.value === 'decorate');
|
|
62
|
-
const value = arg?.value
|
|
62
|
+
const value = Util.uvl(Schema.#resolveNodeValue(arg?.value), 'default');
|
|
63
63
|
const decorator = this.#config.decorators?.[value];
|
|
64
64
|
|
|
65
65
|
if (decorator) {
|
|
@@ -214,6 +214,10 @@ module.exports = class Schema {
|
|
|
214
214
|
break;
|
|
215
215
|
}
|
|
216
216
|
// Field specific directives
|
|
217
|
+
case `${directives.field}-fk`: {
|
|
218
|
+
target.fkField = value;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
217
221
|
case `${directives.field}-default`: {
|
|
218
222
|
target.defaultValue = value;
|
|
219
223
|
break;
|
|
@@ -230,9 +234,14 @@ module.exports = class Schema {
|
|
|
230
234
|
target.pipelines.normalize = target.pipelines.normalize.concat(value).filter(Boolean);
|
|
231
235
|
break;
|
|
232
236
|
}
|
|
237
|
+
case `${directives.link}-to`: {
|
|
238
|
+
target.linkTo = value;
|
|
239
|
+
target.isVirtual ??= true;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
233
242
|
case `${directives.link}-by`: {
|
|
234
243
|
target.linkBy = value;
|
|
235
|
-
target.isVirtual
|
|
244
|
+
target.isVirtual ??= true;
|
|
236
245
|
break;
|
|
237
246
|
}
|
|
238
247
|
// Generic by target directives
|
|
@@ -339,8 +348,10 @@ module.exports = class Schema {
|
|
|
339
348
|
thunks.unshift(($schema) => {
|
|
340
349
|
$field.id ??= $model.id;
|
|
341
350
|
$field.model = $schema.models[$field.type];
|
|
342
|
-
$field.linkBy ??= $field.model?.pkField;
|
|
343
351
|
$field.crud = Util.uvl($field.crud, $field.model?.scope, 'crud');
|
|
352
|
+
$field.linkTo ??= $field.model;
|
|
353
|
+
$field.linkBy ??= $field.linkTo?.pkField; // This defines join logic (below) for both straight+virtual references
|
|
354
|
+
$field.fkField ??= $field.model?.pkField; // This is the fkReference field for straight references
|
|
344
355
|
$field.linkField = $field.isVirtual ? $model.fields[$model.pkField] : $field;
|
|
345
356
|
$field.isFKReference = !$field.isPrimaryKey && $field.model?.isMarkedModel && !$field.model?.isEmbedded;
|
|
346
357
|
$field.isEmbedded = Boolean($field.model && !$field.isFKReference && !$field.isPrimaryKey);
|
|
@@ -354,16 +365,16 @@ module.exports = class Schema {
|
|
|
354
365
|
|
|
355
366
|
if ($field.isArray) $field.pipelines.normalize.unshift('toArray');
|
|
356
367
|
if ($field.isPrimaryKey) $field.pipelines.serialize.unshift('$pk'); // Will create/convert to FK type always
|
|
357
|
-
if ($field.isFKReference) $field.pipelines.serialize.unshift('$fk'); // Will convert to FK type IFF defined in payload
|
|
358
|
-
|
|
359
368
|
if ($field.isRequired && $field.isPersistable && !$field.isVirtual) $field.pipelines.finalize.push('required');
|
|
369
|
+
|
|
360
370
|
if ($field.isFKReference) {
|
|
361
371
|
const to = $field.model.key;
|
|
362
372
|
const on = $field.model.fields[$field.linkBy].key;
|
|
363
373
|
const from = $field.linkField.key;
|
|
364
374
|
const as = `join_${to}`;
|
|
365
375
|
$field.join = { to, on, from, as };
|
|
366
|
-
$field.pipelines.
|
|
376
|
+
$field.pipelines.serialize.unshift('$fk'); // Will convert to FK type IFF defined in payload
|
|
377
|
+
$field.pipelines.finalize.push('ensureFK'); // Absolute Last
|
|
367
378
|
}
|
|
368
379
|
});
|
|
369
380
|
|
|
@@ -446,6 +457,8 @@ module.exports = class Schema {
|
|
|
446
457
|
}
|
|
447
458
|
|
|
448
459
|
static #resolveNodeValue(node) {
|
|
460
|
+
if (node == null) return node;
|
|
461
|
+
|
|
449
462
|
switch (node.kind) {
|
|
450
463
|
case 'NullValue': return null;
|
|
451
464
|
case 'ListValue': return node.values.map(Schema.#resolveNodeValue);
|
|
@@ -493,6 +506,7 @@ module.exports = class Schema {
|
|
|
493
506
|
|
|
494
507
|
directive @${field}(
|
|
495
508
|
id: String # Specify the ID strategy (eg. "toObjectId")
|
|
509
|
+
fk: String # Specify the FK field (default model.pk)
|
|
496
510
|
key: String # Specify db key
|
|
497
511
|
persist: Boolean # Persist this field (default true)
|
|
498
512
|
connection: Boolean # Treat this field as a connection type (default false - rolling this out slowly)
|