@coderich/autograph 0.13.44 → 0.13.46
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/Transformer.js +7 -1
- package/src/query/QueryResolver.js +9 -9
- package/src/schema/Schema.js +36 -17
package/package.json
CHANGED
package/src/data/Transformer.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
const Util = require('@coderich/util');
|
|
2
2
|
|
|
3
3
|
module.exports = class Transformer {
|
|
4
|
-
#config = {
|
|
4
|
+
#config = {
|
|
5
|
+
args: {}, // Arguments passed to each thunk
|
|
6
|
+
shape: {}, // The final shape
|
|
7
|
+
defaults: {}, // Default values applied at beginning of transformation
|
|
8
|
+
strictSchema: false, // If true, will strip away unknown attributes
|
|
9
|
+
keepUndefined: false, // If true, will preserve undefined values
|
|
10
|
+
};
|
|
5
11
|
|
|
6
12
|
#operation = {
|
|
7
13
|
set: (target, prop, startValue, proxy) => {
|
|
@@ -60,7 +60,7 @@ module.exports = class QueryResolver extends QueryBuilder {
|
|
|
60
60
|
case 'pullOne': {
|
|
61
61
|
return this.#get(query).then((doc) => {
|
|
62
62
|
const [key] = Object.keys(input);
|
|
63
|
-
const values = get(this.#model.transformers.input.transform(input), key);
|
|
63
|
+
const values = get(this.#model.transformers.input.transform(input), key, []);
|
|
64
64
|
const $input = { [key]: (get(doc, key) || []).filter(el => values.every(v => `${v}` !== `${el}`)) };
|
|
65
65
|
return this.#resolver.match(this.#model.name).id(doc.id).save($input);
|
|
66
66
|
});
|
|
@@ -109,17 +109,17 @@ module.exports = class QueryResolver extends QueryBuilder {
|
|
|
109
109
|
const { id } = query.toObject();
|
|
110
110
|
const txn = this.#resolver.transaction(false);
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
const $where = { [
|
|
112
|
+
return txn.run(Util.promiseChain(this.#model.referentialIntegrity.map(({ model, field, path }) => () => {
|
|
113
|
+
const { onDelete, isArray } = field;
|
|
114
|
+
const $path = path.join('.');
|
|
115
|
+
const $where = { [$path]: id };
|
|
116
116
|
|
|
117
|
-
switch (
|
|
118
|
-
case 'cascade': return isArray ? txn.match(model).where($where).pull(
|
|
119
|
-
case 'nullify': return txn.match(model).where($where).save({ [
|
|
117
|
+
switch (onDelete) {
|
|
118
|
+
case 'cascade': return isArray ? txn.match(model).where($where).pull($path, id) : txn.match(model).where($where).remove();
|
|
119
|
+
case 'nullify': return txn.match(model).where($where).save({ [$path]: null });
|
|
120
120
|
case 'restrict': return txn.match(model).where($where).count().then(count => (count ? Promise.reject(new Error('Restricted')) : count));
|
|
121
121
|
case 'defer': return Promise.resolve(); // Used for embedded models (could be improved)
|
|
122
|
-
default: throw new Error(`Unknown onDelete operator: '${
|
|
122
|
+
default: throw new Error(`Unknown onDelete operator: '${onDelete}'`);
|
|
123
123
|
}
|
|
124
124
|
})));
|
|
125
125
|
}
|
package/src/schema/Schema.js
CHANGED
|
@@ -129,6 +129,7 @@ module.exports = class Schema {
|
|
|
129
129
|
visit(this.#typeDefs, {
|
|
130
130
|
enter: (node) => {
|
|
131
131
|
const name = node.name?.value;
|
|
132
|
+
|
|
132
133
|
if (!allowedKinds.includes(node.kind) || operations.includes(name)) return false;
|
|
133
134
|
|
|
134
135
|
if (modelKinds.includes(node.kind)) {
|
|
@@ -424,8 +425,17 @@ module.exports = class Schema {
|
|
|
424
425
|
curr.name, // Rename key
|
|
425
426
|
a => Pipeline.$deserialize({ ...a, ...args, path: a.path.concat(curr.name) }),
|
|
426
427
|
];
|
|
428
|
+
|
|
427
429
|
if (curr.isArray) rules.unshift(({ value }) => (value == null ? value : Util.ensureArray(value)));
|
|
428
|
-
|
|
430
|
+
|
|
431
|
+
if (curr.isEmbedded) {
|
|
432
|
+
rules.unshift(a => Util.map(a.value, (value, i) => {
|
|
433
|
+
const path = a.path.concat(curr.name);
|
|
434
|
+
if (curr.isArray) path.push(i);
|
|
435
|
+
return curr.model.transformers.doc.transform(value, { ...args, query: a.query, context: a.context, path });
|
|
436
|
+
}));
|
|
437
|
+
}
|
|
438
|
+
|
|
429
439
|
return Object.assign(prev, { [curr.key]: rules });
|
|
430
440
|
}, {}),
|
|
431
441
|
defaults: Object.values($model.fields).reduce((prev, curr) => {
|
|
@@ -443,6 +453,7 @@ module.exports = class Schema {
|
|
|
443
453
|
|
|
444
454
|
// Field resolution comes first (unshift)
|
|
445
455
|
thunks.unshift(($schema) => {
|
|
456
|
+
$field.parent = $model;
|
|
446
457
|
$field.model = $schema.models[$field.type];
|
|
447
458
|
$field.crud = Util.uvl($field.crud, $field.model?.scope, 'crud');
|
|
448
459
|
$field.linkTo ??= $field.model;
|
|
@@ -507,8 +518,12 @@ module.exports = class Schema {
|
|
|
507
518
|
});
|
|
508
519
|
|
|
509
520
|
// Resolve referential integrity
|
|
521
|
+
const onDeleteFields = Array.from(new Set(Object.values(this.#schema.models).reduce((prev, curr) => {
|
|
522
|
+
return prev.concat(Object.values(curr.fields).filter(el => el.onDelete)).flat();
|
|
523
|
+
}, [])));
|
|
524
|
+
|
|
510
525
|
Object.values(this.#schema.models).forEach(($model) => {
|
|
511
|
-
$model.referentialIntegrity = Schema.#identifyOnDeletes(Object.values(this.#schema.models), $model
|
|
526
|
+
$model.referentialIntegrity = Schema.#identifyOnDeletes(Object.values(this.#schema.models).filter(m => m.isEntity), onDeleteFields.filter(f => `${f.model}` === `${$model}`));
|
|
512
527
|
});
|
|
513
528
|
|
|
514
529
|
// Helper methods
|
|
@@ -887,21 +902,25 @@ module.exports = class Schema {
|
|
|
887
902
|
`;
|
|
888
903
|
}
|
|
889
904
|
|
|
890
|
-
static #
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
});
|
|
905
|
+
static #findPathToField(model, field, path = []) {
|
|
906
|
+
const { target, embeds } = Object.values(model.fields).reduce((prev, curr) => {
|
|
907
|
+
if (curr === field) prev.target = curr;
|
|
908
|
+
else if (curr.isEmbedded) prev.embeds.push(curr);
|
|
909
|
+
return prev;
|
|
910
|
+
}, { embeds: [] });
|
|
911
|
+
|
|
912
|
+
if (target) return path.concat(target.name);
|
|
913
|
+
if (embeds.length) return embeds.map(f => Schema.#findPathToField(f.model, field, path.concat(f.name))).filter(Boolean)[0];
|
|
914
|
+
return undefined;
|
|
915
|
+
}
|
|
902
916
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
917
|
+
static #identifyOnDeletes(models, fields) {
|
|
918
|
+
return models.map((model) => {
|
|
919
|
+
return fields.map((field) => {
|
|
920
|
+
const path = Schema.#findPathToField(model, field);
|
|
921
|
+
if (!path) return null;
|
|
922
|
+
return { model, field, path };
|
|
923
|
+
});
|
|
924
|
+
}).flat().filter(Boolean);
|
|
906
925
|
}
|
|
907
926
|
};
|