@coderich/autograph 0.13.108 → 0.14.0

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.108",
4
+ "version": "0.14.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -16,7 +16,7 @@
16
16
  "clinic": "clinic flame -- node ./test/server"
17
17
  },
18
18
  "dependencies": {
19
- "@coderich/util": "1.2.1",
19
+ "@coderich/util": "2.2.0",
20
20
  "@graphql-tools/merge": "9.0.0",
21
21
  "@graphql-tools/resolvers-composition": "7.0.0",
22
22
  "@hapi/boom": "10.0.1",
@@ -38,7 +38,6 @@
38
38
  "@graphql-tools/schema": "10.0.0",
39
39
  "clinic": "13.0.0",
40
40
  "graphql": "16.8.1",
41
- "mongodb": "5.9.2",
42
41
  "mongodb-memory-server": "8.13.0"
43
42
  },
44
43
  "peerDependencies": {
@@ -1,7 +1,6 @@
1
1
  const get = require('lodash.get');
2
2
  const Util = require('@coderich/util');
3
3
  const DataLoader = require('dataloader');
4
- const { hashObject } = require('../service/AppService');
5
4
 
6
5
  module.exports = class Loader {
7
6
  #model;
@@ -11,7 +10,7 @@ module.exports = class Loader {
11
10
  constructor(model, resolver) {
12
11
  this.#model = model;
13
12
  this.#resolver = resolver;
14
- this.#model.loader.cacheKeyFn ??= query => hashObject(query.toCacheKey());
13
+ this.#model.loader.cacheKeyFn ??= query => query.toCacheKey();
15
14
  this.#loader = new DataLoader(keys => this.#resolve(keys), this.#model.loader);
16
15
  }
17
16
 
@@ -33,10 +32,9 @@ module.exports = class Loader {
33
32
  const $query = query.toDriver().toObject();
34
33
  const key = $query.batch ?? '__default__';
35
34
  let [values] = key === '__default__' ? [] : Object.values(Util.flatten($query.where, { safe: true }));
36
- values = Array.from(new Set(Util.ensureArray(values)));
37
- const $values = values.map(value => (value instanceof RegExp ? value : new RegExp(`${value}`, 'i')));
35
+ values = Loader.#dedup(Util.ensureArray(values));
38
36
  prev[key] = prev[key] || [];
39
- prev[key].push({ query, $query, values, $values, i });
37
+ prev[key].push({ query, $query, values, i });
40
38
  return prev;
41
39
  }, {});
42
40
 
@@ -47,36 +45,37 @@ module.exports = class Loader {
47
45
  }
48
46
  default: {
49
47
  // Collect all the values for the where clause
50
- const values = Array.from(new Set(batches.map(batch => batch.values).flat()));
48
+ const values = Loader.#dedup(batches.map(batch => batch.values).flat());
51
49
  const $query = { ...batches[0].$query, op: 'findMany', where: { [key]: values } };
52
50
 
53
- //
54
51
  if (values.length < 3) {
55
52
  return batches.map(batch => this.#model.source.client.resolve(batch.$query).then(data => ({ data, ...batch })));
56
53
  }
57
54
 
58
- // Collect all the $values (Regular Expressions) to match doc (result) data by
59
- const $values = Array.from(new Set(batches.map(batch => batch.$values).flat()));
60
- const docsByRegExpKey = $values.reduce((map, re) => map.set(re, []), new Map());
61
-
62
55
  // Now we perform 1 query, instead of many smaller ones
63
56
  return this.#model.source.client.resolve($query).then((docs) => {
64
- // This one-time transformation keys all the docs by $value (regex) match
57
+ const docsByKey = new Map();
58
+
65
59
  docs.forEach((doc) => {
66
60
  Util.pathmap(key, doc, (value) => {
67
- docsByRegExpKey.forEach((set, re) => {
68
- Util.map(value, (v) => {
69
- if (`${v}`.match(re)) {
70
- set.push(doc);
71
- }
72
- });
61
+ Util.ensureArray(value).forEach((v) => {
62
+ const k = `${v}`;
63
+ if (!docsByKey.has(k)) docsByKey.set(k, []);
64
+ docsByKey.get(k).push(doc);
73
65
  });
74
66
  return value;
75
67
  });
76
68
  });
77
69
 
78
70
  return batches.map((batch) => {
79
- const matches = Array.from(new Set(batch.$values.map(re => docsByRegExpKey.get(re)).flat().filter(v => v !== undefined)));
71
+ const matches = Array.from(new Set(batch.values.flatMap((v) => {
72
+ if (v instanceof RegExp) {
73
+ const result = [];
74
+ docsByKey.forEach((d, k) => { if (v.test(k)) result.push(...d); });
75
+ return result;
76
+ }
77
+ return docsByKey.get(`${v}`) || [];
78
+ })));
80
79
  const data = batch.$query.op === 'findOne' ? matches[0] : matches;
81
80
  return { data, ...batch };
82
81
  });
@@ -103,6 +102,16 @@ module.exports = class Loader {
103
102
  // }));
104
103
  }
105
104
 
105
+ // Deduplicate an array of values that may contain RegExp objects.
106
+ // new Set() compares by reference, so two RegExp literals with identical patterns
107
+ // are treated as distinct. Using toString() as the Map key handles this correctly
108
+ // while preserving the actual RegExp instance as the value.
109
+ static #dedup(arr) {
110
+ const seen = new Map();
111
+ arr.forEach(v => seen.set(v instanceof RegExp ? v.toString() : v, v));
112
+ return Array.from(seen.values());
113
+ }
114
+
106
115
  static #paginateResults(rs, query) {
107
116
  let hasNextPage = false;
108
117
  let hasPreviousPage = false;
@@ -1,4 +1,4 @@
1
- const EventEmitter = require('events');
1
+ const EventEmitter = require('node:events');
2
2
  const Util = require('@coderich/util');
3
3
  const { AbortEarlyError } = require('../service/ErrorService');
4
4
 
@@ -9,28 +9,36 @@ const { AbortEarlyError } = require('../service/ErrorService');
9
9
  * If it expects more than 1 we block and wait for it to finish.
10
10
  */
11
11
  class Emitter extends EventEmitter {
12
+ #cache = new Map();
13
+
14
+ #invalidate(event) {
15
+ this.#cache.delete(event);
16
+ }
17
+
18
+ #getListeners(event) {
19
+ if (!this.#cache.has(event)) {
20
+ const [basicFuncs, nextFuncs] = this.rawListeners(event).reduce((prev, wrapper) => {
21
+ const { listener = wrapper } = wrapper;
22
+ wrapper.priority = listener.priority ?? 0;
23
+ return prev[listener.length < 2 ? 0 : 1].push(wrapper) && prev;
24
+ }, [[], []]);
25
+ this.#cache.set(event, { basicFuncs: basicFuncs.sort(Emitter.sort), nextFuncs: nextFuncs.sort(Emitter.sort) });
26
+ }
27
+ return this.#cache.get(event);
28
+ }
29
+
12
30
  emit(event, data) {
13
- // Here we pull out functions with "next" vs those without
14
- const [basicFuncs, nextFuncs] = this.rawListeners(event).reduce((prev, wrapper) => {
15
- const { listener = wrapper } = wrapper;
16
- const isBasic = listener.length < 2;
17
- wrapper.priority = listener.priority ?? 0;
18
- return prev[isBasic ? 0 : 1].push(wrapper) && prev;
19
- }, [[], []]);
20
-
21
- // // Basic functions are not designed to be bound to the query execution so we need an isolated resolver from any transactions
22
- // const resolver = data?.resolver?.clone();
23
- // const basicData = { ...data, resolver };
31
+ const { basicFuncs, nextFuncs } = this.#getListeners(event);
24
32
 
25
33
  return new Promise((resolve, reject) => {
26
34
  // Basic functions run first; if they return a value they abort the flow of execution
27
- basicFuncs.sort(Emitter.sort).forEach((fn) => {
35
+ basicFuncs.forEach((fn) => {
28
36
  const value = fn(data);
29
37
  if (value !== undefined && !(value instanceof Promise)) throw new AbortEarlyError(value);
30
38
  });
31
39
 
32
40
  // Next functions are async and control the timing of the next phase
33
- Promise.all(nextFuncs.sort(Emitter.sort).map((fn) => {
41
+ Promise.all(nextFuncs.map((fn) => {
34
42
  return new Promise((next, err) => {
35
43
  Promise.resolve().then(() => fn(data, next)).catch(err);
36
44
  }).then((result) => {
@@ -45,14 +53,47 @@ class Emitter extends EventEmitter {
45
53
 
46
54
  on(event, listener, priority = 0) {
47
55
  listener.priority = priority;
56
+ this.#invalidate(event);
48
57
  return super.on(event, listener);
49
58
  }
50
59
 
60
+ addListener(event, listener, priority = 0) {
61
+ return this.on(event, listener, priority);
62
+ }
63
+
64
+ once(event, listener, priority = 0) {
65
+ listener.priority = priority;
66
+ this.#invalidate(event);
67
+ return super.once(event, listener);
68
+ }
69
+
51
70
  prependListener(event, listener, priority = 0) {
52
71
  listener.priority = priority;
72
+ this.#invalidate(event);
53
73
  return super.prependListener(event, listener);
54
74
  }
55
75
 
76
+ prependOnceListener(event, listener, priority = 0) {
77
+ listener.priority = priority;
78
+ this.#invalidate(event);
79
+ return super.prependOnceListener(event, listener);
80
+ }
81
+
82
+ removeListener(event, listener) {
83
+ this.#invalidate(event);
84
+ return super.removeListener(event, listener);
85
+ }
86
+
87
+ off(event, listener) {
88
+ return this.removeListener(event, listener);
89
+ }
90
+
91
+ removeAllListeners(event) {
92
+ if (event) this.#invalidate(event);
93
+ else this.#cache.clear();
94
+ return super.removeAllListeners(event);
95
+ }
96
+
56
97
  /**
57
98
  * Syntactic sugar to listen on query keys
58
99
  */
@@ -63,7 +63,6 @@ module.exports = class Pipeline {
63
63
  Pipeline.define('$construct', params => Pipeline.resolve(params, 'construct'), { ignoreNull: false });
64
64
  Pipeline.define('$restruct', params => Pipeline.resolve(params, 'restruct'), { ignoreNull: false });
65
65
  Pipeline.define('$serialize', params => Pipeline.resolve(params, 'serialize'), { ignoreNull: false });
66
- Pipeline.define('$deserialize', params => Pipeline.resolve(params, 'deserialize'), { ignoreNull: false });
67
66
  Pipeline.define('$validate', params => Pipeline.resolve(params, 'validate'), { ignoreNull: false });
68
67
 
69
68
  //
@@ -245,7 +245,7 @@ module.exports = class Resolver {
245
245
  model = this.#schema.models[model];
246
246
 
247
247
  return Object.defineProperties(Util.map(result, (doc) => {
248
- const $doc = model.transformers.doc.transform(doc, { resolver: this, context: this.#context });
248
+ const $doc = model.docTransform(doc);
249
249
 
250
250
  // Assign useful/needed meta data
251
251
  return Object.defineProperties($doc, {
@@ -307,44 +307,26 @@ module.exports = class Resolver {
307
307
  const tquery = $query.transform(false);
308
308
  const query = tquery.toObject();
309
309
  const type = query.isMutation ? 'Mutation' : 'Query';
310
- const event = this.#createEvent(query);
310
+ const event = { schema: this.#schema, context: this.#context, resolver: this, query };
311
311
 
312
312
  return Emitter.emit(`pre${type}`, event).then(async (resultEarly) => {
313
- if (resultEarly !== undefined) return resultEarly; // Nothing to validate/transform
314
- // if (query.crud === 'update' && Util.isEqual({ added: {}, updated: {}, deleted: {} }, Util.changeset(query.doc, query.input))) return query.doc;
313
+ if (resultEarly !== undefined) return resultEarly;
315
314
 
316
315
  if (['create', 'update'].includes(query.crud)) {
317
- tquery.validate(); // Transformation sets $thunks
316
+ tquery.validate(); // sets async $thunks (e.g. ensureFK)
318
317
  await Promise.all([...query.input.$thunks]);
319
318
  await Emitter.emit('validate', event);
320
319
  }
321
320
 
322
321
  return thunk(tquery);
323
322
  }).then((result) => {
324
- event.result = result; // backwards compat
325
323
  query.result = result;
326
324
  return Emitter.emit(`post${type}`, event);
327
325
  }).then((result = query.result) => result).catch((e) => {
328
326
  throw Boom.boomify(e);
329
- // const { data = {} } = e;
330
- // throw Boom.boomify(e, { data: { ...event, ...data } });
331
327
  });
332
328
  }
333
329
 
334
- #createEvent(query) {
335
- const event = { schema: this.#schema, context: this.#context, resolver: this, query };
336
-
337
- // Backwards compat
338
- Object.assign(event, query);
339
- query.match = event.args.where;
340
- query.toObject = () => query;
341
- event.merged = event.input;
342
- event.input = Util.unflatten(event.args?.input, { safe: true });
343
- event.doc ??= {};
344
-
345
- return event;
346
- }
347
-
348
330
  static $loader(name, resolver, config) {
349
331
  if (!name) return loaders;
350
332
  if (!resolver) return loaders[name];
@@ -9,6 +9,8 @@ module.exports = class Transformer {
9
9
  keepUndefined: false, // If true, will preserve undefined values
10
10
  };
11
11
 
12
+ #callArgs = {}; // Ephemeral per-call merge of #config.args + transform() args; never persisted
13
+
12
14
  #operation = {
13
15
  set: (target, prop, startValue, proxy) => {
14
16
  if (this.#config.shape[prop]) {
@@ -16,7 +18,7 @@ module.exports = class Transformer {
16
18
 
17
19
  const result = this.#config.shape[prop].reduce((value, t) => {
18
20
  previousValue = value;
19
- if (typeof t === 'function') return Util.uvl(t({ startValue, value, ...this.#config.args }), value);
21
+ if (typeof t === 'function') return Util.uvl(t({ startValue, value, ...this.#callArgs }), value);
20
22
  prop = t; // rename key
21
23
  return value;
22
24
  }, startValue);
@@ -64,7 +66,7 @@ module.exports = class Transformer {
64
66
 
65
67
  transform(mixed, args = {}) {
66
68
  args.thunks ??= [];
67
- this.args(args);
69
+ this.#callArgs = { ...this.#config.args, ...args };
68
70
 
69
71
  const transformed = Util.map(mixed, (data) => {
70
72
  const thunks = Object.defineProperty({}, '$thunks', { value: args.thunks });
@@ -39,19 +39,18 @@ module.exports = class Query {
39
39
  }
40
40
 
41
41
  toCacheKey() {
42
- return {
42
+ return JSON.stringify({
43
43
  op: this.#query.op,
44
44
  select: this.#query.select,
45
45
  where: this.#query.where,
46
46
  sort: this.#query.sort,
47
- joins: this.#query.joins,
48
47
  skip: this.#query.skip,
49
48
  limit: this.#query.limit,
50
49
  before: this.#query.before,
51
50
  after: this.#query.after,
52
51
  first: this.#query.first,
53
52
  last: this.#query.last,
54
- };
53
+ });
55
54
  }
56
55
 
57
56
  /**
@@ -134,14 +133,25 @@ module.exports = class Query {
134
133
  query.batch = (op === 'findOne' || op === 'findMany') && Object.keys(query.where).length === 1 ? Object.keys(query.where)[0] : '__default__';
135
134
 
136
135
  // Construct joins
136
+ const joinsByPath = {};
137
137
  query.joins = [];
138
138
 
139
+ // Recursively search a join tree for the first join matching a target model key
140
+ const findJoin = (joins, modelKey) => {
141
+ for (const j of joins) {
142
+ if (j.to === modelKey) return j;
143
+ const found = findJoin(j.children, modelKey);
144
+ if (found) return found;
145
+ }
146
+ return null;
147
+ };
148
+
139
149
  this.#model.walk(joinData, (node) => {
140
150
  const { model, field, key, value, isLeaf, path, run } = node;
141
151
 
142
152
  if (field.join) {
143
153
  let isArray;
144
- const join = { ...field.join, where: {} };
154
+ const join = { ...field.join, where: {}, children: [] };
145
155
 
146
156
  if (run.length > 1) {
147
157
  join.from = path.reduce((prev, curr, i) => {
@@ -153,12 +163,21 @@ module.exports = class Query {
153
163
 
154
164
  join.isArray = isArray || model.resolvePath(join.from).isArray;
155
165
 
156
- query.joins.push(join);
166
+ // Find the nearest ancestor FK join by scanning ancestor paths from closest to farthest.
167
+ // Joins reached through embedded fields have no FK ancestor and stay at the root level.
168
+ const parentJoin = path.slice(0, -1).reduceRight((found, _, i) => found || joinsByPath[path.slice(0, i + 1).join('.')], null);
169
+
170
+ if (parentJoin) {
171
+ parentJoin.children.push(join);
172
+ } else {
173
+ query.joins.push(join);
174
+ }
175
+ joinsByPath[path.join('.')] = join;
157
176
  }
158
177
 
159
178
  if (isLeaf) {
160
179
  const $model = field.model || model;
161
- const join = query.joins.find(j => j.to === $model.key);
180
+ const join = findJoin(query.joins, $model.key);
162
181
  const $value = Util.map(value, el => (isGlob(el) ? globToRegex(el) : el));
163
182
  const $$value = Array.isArray($value) ? { $in: $value } : $value;
164
183
  const from = field.model ? join.from : key;
@@ -16,7 +16,7 @@ const scalarKinds = [Kind.SCALAR_TYPE_DEFINITION, Kind.SCALAR_TYPE_EXTENSION];
16
16
  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
- const pipelines = ['validate', 'construct', 'restruct', 'instruct', 'normalize', 'serialize', 'deserialize'];
19
+ const pipelines = ['validate', 'construct', 'restruct', 'instruct', 'normalize', 'serialize'];
20
20
  const createPipelines = ['validate', 'construct', 'instruct', 'normalize', 'serialize'];
21
21
  const updatePipelines = ['validate', 'restruct', 'instruct', 'normalize', 'serialize'];
22
22
  // const validatePipelines = ['validate', 'instruct', 'normalize', 'serialize'];
@@ -97,7 +97,7 @@ module.exports = class Schema {
97
97
  try {
98
98
  const $td = typeof td === 'string' ? parse(td) : td;
99
99
  return $td;
100
- } catch (e) {
100
+ } catch {
101
101
  console.log(`Unable to parse typeDef (being ignored):\n${td}`); // eslint-disable-line
102
102
  return null;
103
103
  }
@@ -153,7 +153,6 @@ module.exports = class Schema {
153
153
  create: new Transformer({ args: { schema: this.#schema, path: [] } }),
154
154
  update: new Transformer({ args: { schema: this.#schema, path: [] } }),
155
155
  where: new Transformer({ args: { schema: this.#schema, path: [] } }),
156
- doc: new Transformer({ args: { schema: this.#schema, path: [] } }),
157
156
  },
158
157
  directives: {},
159
158
  ignorePaths: [],
@@ -205,6 +204,7 @@ module.exports = class Schema {
205
204
  target.directives[name] = target.directives[name] || {};
206
205
 
207
206
  if (name === directives.model) {
207
+ model.isEntity = true;
208
208
  model.isMarkedModel = true;
209
209
  model.isEmbedded = false;
210
210
  } else if (name === directives.index) {
@@ -234,6 +234,7 @@ module.exports = class Schema {
234
234
  }
235
235
  case `${directives.model}-embed`: {
236
236
  model.isEmbedded = value;
237
+ model.isEntity = !value;
237
238
  break;
238
239
  }
239
240
  // Field specific directives
@@ -312,8 +313,6 @@ module.exports = class Schema {
312
313
 
313
314
  // Model resolution after field resolution (push)
314
315
  thunks.push(($schema) => {
315
- $model.isEntity = Boolean($model.isMarkedModel && !$model.isEmbedded);
316
-
317
316
  $model.resolvePath = (path, prop = 'name') => this.#schema.resolvePath(`${$model[prop]}.${path}`, prop);
318
317
 
319
318
  $model.isJoinPath = (path, prop = 'name') => {
@@ -452,33 +451,6 @@ module.exports = class Schema {
452
451
 
453
452
  $model.transformers.sort = $model.transformers.where.clone({ defaults: {} });
454
453
 
455
- $model.transformers.doc.config({
456
- shape: Object.values($model.fields).reduce((prev, curr) => {
457
- const args = { model: $model, field: curr };
458
-
459
- const rules = [
460
- curr.name, // Rename key
461
- a => Pipeline.$deserialize({ ...a, ...args, path: a.path.concat(curr.name) }),
462
- ];
463
-
464
- if (curr.isArray) rules.unshift(({ value }) => (value == null ? value : Util.ensureArray(value)));
465
-
466
- if (curr.isEmbedded) {
467
- rules.unshift(a => Util.map(a.value, (value, i) => {
468
- const path = a.path.concat(curr.name);
469
- if (curr.isArray) path.push(i);
470
- return curr.model.transformers.doc.transform(value, { ...args, query: a.query, context: a.context, path });
471
- }));
472
- }
473
-
474
- return Object.assign(prev, { [curr.key]: rules });
475
- }, {}),
476
- defaults: Object.values($model.fields).reduce((prev, curr) => {
477
- if (curr.defaultValue === undefined) return prev;
478
- return Object.assign(prev, { [curr.key]: curr.defaultValue });
479
- }, {}),
480
- });
481
-
482
454
  $model.transformers.validate.config({
483
455
  strictSchema: true,
484
456
  shape: Object.values($model.fields).reduce((prev, curr) => {
@@ -499,6 +471,21 @@ module.exports = class Schema {
499
471
  }, {}),
500
472
  });
501
473
 
474
+ // Deserialize/docs special case handling for performance
475
+ const docFields = Object.values($model.fields);
476
+ $model.docTransform = (doc) => {
477
+ if (doc == null) return doc;
478
+ const out = {};
479
+ for (const docField of docFields) {
480
+ let value = docField.key in doc ? doc[docField.key] : docField.defaultValue;
481
+ if (value === undefined) continue; // eslint-disable-line
482
+ if (docField.isArray) value = value == null ? value : Util.ensureArray(value);
483
+ if (docField.isEmbedded) value = Util.map(value, v => docField.model.docTransform(v));
484
+ out[docField.name] = value;
485
+ }
486
+ return out;
487
+ };
488
+
502
489
  Util.traverse(Object.values($model.fields), (f, info) => {
503
490
  const path = info.path.concat(f.name);
504
491
  if (f.isEmbedded) return { value: Object.values(f.model.fields), info: { path } };
@@ -611,8 +598,6 @@ module.exports = class Schema {
611
598
  },
612
599
  });
613
600
 
614
- // console.log(this.#schema.models.Person.referentialIntegrity);
615
-
616
601
  // Return schema
617
602
  return this.#schema;
618
603
  }
@@ -646,11 +631,11 @@ module.exports = class Schema {
646
631
 
647
632
  const arr = [];
648
633
 
649
- Object.values(this.#schema.models).forEach((m) => {
634
+ Object.values(this.#schema.models).filter(m => m.isEntity).forEach((m) => {
650
635
  Util.traverse(Object.values(m.fields), (f, info) => {
651
636
  const path = info.path.concat(f.name);
652
- if (f.isEmbedded) return { value: Object.values(f.model.fields), info: { path, isArray: info.isArray || f.isArray } };
653
637
  if (f.type === model.name) arr.push({ model: m, field, path: path.concat(`${field}`), isArray: info.isArray || field.isArray || f.isArray });
638
+ else if (f.isEmbedded) return { value: Object.values(f.model.fields), info: { path, isArray: info.isArray || f.isArray } };
654
639
  return null;
655
640
  }, { path: [], isArray: false });
656
641
  });
@@ -722,7 +707,6 @@ module.exports = class Schema {
722
707
  construct: [AutoGraphPipelineEnum!]
723
708
  restruct: [AutoGraphPipelineEnum!]
724
709
  serialize: [AutoGraphPipelineEnum!]
725
- deserialize: [AutoGraphPipelineEnum!]
726
710
  validate: [AutoGraphPipelineEnum!]
727
711
 
728
712
  # TEMP TO APPEASE TRANSITION
@@ -905,7 +889,7 @@ module.exports = class Schema {
905
889
  `,
906
890
  resolvers: {
907
891
  Node: {
908
- __resolveType: (doc, args, context, info) => doc.__typename, // eslint-disable-line no-underscore-dangle
892
+ __resolveType: (doc, args, context, info) => doc.__typename,
909
893
  },
910
894
  ...queryModels.reduce((prev, model) => {
911
895
  return Object.assign(prev, {
@@ -928,7 +912,7 @@ module.exports = class Schema {
928
912
  const model = schema.models[modelName];
929
913
  return context[schema.namespace].resolver.match(model).id(id).info(info).one().then((result) => {
930
914
  if (result == null) return result;
931
- result.__typename = modelName; // eslint-disable-line no-underscore-dangle
915
+ result.__typename = modelName;
932
916
  return result;
933
917
  });
934
918
  },
@@ -40,7 +40,7 @@ exports.JSONParse = (mixed) => {
40
40
  try {
41
41
  const json = JSON.parse(mixed);
42
42
  return json;
43
- } catch (e) {
43
+ } catch {
44
44
  return undefined;
45
45
  }
46
46
  };
@@ -1,11 +0,0 @@
1
- const API = jest.requireActual('../Emitter');
2
- const { mergeDeep } = require('../../service/AppService');
3
-
4
- const { emit } = API;
5
-
6
- API.emit = (eventName, data) => {
7
- if (API.cloneData) data = { ...data, query: mergeDeep({}, data.query) };
8
- return emit.call(API, eventName, data);
9
- };
10
-
11
- module.exports = API;
@@ -1,32 +0,0 @@
1
- /**
2
- * We need to export Pipeline as a POJO so jest can spy on it
3
- * This is because all the methods are defined using Object.defineProperty
4
- */
5
- const Pipeline = jest.requireActual('../Pipeline');
6
- const Util = require('@coderich/util');
7
-
8
- const API = {};
9
-
10
- Pipeline.resolve = (params, pipeline) => {
11
- const transformers = params.field.pipelines[pipeline] || [];
12
-
13
- return transformers.reduce((value, t) => {
14
- return Util.uvl(API[t]({ ...params, value }), value);
15
- }, params.value);
16
-
17
- // return Util.pipeline(transformers.map(t => (value) => {
18
- // return API[t]({ ...params, value });
19
- // }), params.value);
20
- };
21
-
22
- Object.getOwnPropertyNames(Pipeline).reduce((prev, key) => {
23
- return Object.assign(prev, { [key]: Pipeline[key] });
24
- }, API);
25
-
26
- // For those defined outside of Pipeline.js itself
27
- API.define = (key, ...args) => {
28
- Pipeline.define(key, ...args);
29
- API[key] = Pipeline[key];
30
- };
31
-
32
- module.exports = API;