@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@coderich/autograph",
3
3
  "main": "index.js",
4
- "version": "0.13.49",
4
+ "version": "0.13.51",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -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 next(listener(event, next));
92
+ return listener(event, next);
93
93
  }
94
94
  return next();
95
95
  };
@@ -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
 
@@ -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.isMutation) await Promise.all([...query.input.$thunks, Emitter.emit('validate', event)]);
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.merged = event.input;
330
- event.input = event.args?.input;
329
+ event.doc ??= {};
330
+ event.input ??= {};
331
+ event.merged = AppService.mergeDeep(event.doc, event.input);
331
332
 
332
333
  return event;
333
334
  }
@@ -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.input.transform(Util.unflatten(this.#query.input, { safe: true }), args),
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
- // const $input = this.#model.walk(doc, (node) => {
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 values = get(this.#model.transformers.input.transform(input), key);
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 values = get(this.#model.transformers.input.transform(input), key, []);
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 [find, replace] = get(this.#model.transformers.input.transform(input), key);
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
  });
@@ -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 inputPipelines = ['validate', 'construct', 'instruct', 'normalize', 'serialize'];
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
- input: new Transformer({ args: { schema: this.#schema, path: [] } }),
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.input.config({
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
- (a) => {
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.input.transform(value, { ...args, thunks: a.thunks, query: a.query, resolver: a.resolver, context: a.context, path });
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 (inputPipelines.some(el => curr.pipelines[el].length)) return Object.assign(prev, { [curr.name]: undefined });
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
  });