@coderich/autograph 0.11.1 → 0.13.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.
Files changed (56) hide show
  1. package/index.js +4 -6
  2. package/package.json +30 -44
  3. package/src/data/DataLoader.js +77 -70
  4. package/src/data/Emitter.js +89 -0
  5. package/src/data/Loader.js +33 -0
  6. package/src/data/Pipeline.js +88 -96
  7. package/src/data/Resolver.js +304 -0
  8. package/src/data/Transaction.js +49 -0
  9. package/src/query/Query.js +159 -334
  10. package/src/query/QueryBuilder.js +228 -114
  11. package/src/query/QueryResolver.js +110 -216
  12. package/src/query/QueryResolverTransaction.js +16 -0
  13. package/src/schema/Schema.js +593 -0
  14. package/src/service/AppService.js +38 -0
  15. package/src/service/ErrorService.js +7 -0
  16. package/CHANGELOG.md +0 -41
  17. package/LICENSE +0 -21
  18. package/README.md +0 -76
  19. package/src/.DS_Store +0 -0
  20. package/src/core/.DS_Store +0 -0
  21. package/src/core/Boom.js +0 -9
  22. package/src/core/EventEmitter.js +0 -95
  23. package/src/core/Resolver.js +0 -124
  24. package/src/core/Schema.js +0 -55
  25. package/src/core/ServerResolver.js +0 -15
  26. package/src/data/.DS_Store +0 -0
  27. package/src/data/DataService.js +0 -120
  28. package/src/data/DataTransaction.js +0 -96
  29. package/src/data/Field.js +0 -83
  30. package/src/data/Model.js +0 -223
  31. package/src/data/TreeMap.js +0 -78
  32. package/src/data/Type.js +0 -50
  33. package/src/driver/.DS_Store +0 -0
  34. package/src/driver/MongoDriver.js +0 -227
  35. package/src/driver/index.js +0 -11
  36. package/src/graphql/.DS_Store +0 -0
  37. package/src/graphql/ast/.DS_Store +0 -0
  38. package/src/graphql/ast/Field.js +0 -206
  39. package/src/graphql/ast/Model.js +0 -145
  40. package/src/graphql/ast/Node.js +0 -291
  41. package/src/graphql/ast/Schema.js +0 -133
  42. package/src/graphql/ast/Type.js +0 -26
  43. package/src/graphql/ast/TypeDefApi.js +0 -93
  44. package/src/graphql/extension/.DS_Store +0 -0
  45. package/src/graphql/extension/api.js +0 -193
  46. package/src/graphql/extension/framework.js +0 -71
  47. package/src/graphql/extension/type.js +0 -34
  48. package/src/query/.DS_Store +0 -0
  49. package/src/query/QueryBuilderTransaction.js +0 -26
  50. package/src/query/QueryService.js +0 -111
  51. package/src/service/.DS_Store +0 -0
  52. package/src/service/app.service.js +0 -319
  53. package/src/service/decorator.service.js +0 -114
  54. package/src/service/event.service.js +0 -66
  55. package/src/service/graphql.service.js +0 -92
  56. package/src/service/schema.service.js +0 -95
@@ -1,111 +0,0 @@
1
- const { get, set, uniq, flattenDeep } = require('lodash');
2
- const { keyPaths, ensureArray, isPlainObject } = require('../service/app.service');
3
-
4
- /**
5
- * The where clause may contain attributes that are NOT in the model
6
- * This can happen because the where clause reaches into the schema via refs/virtual refs
7
- */
8
- exports.resolveWhereClause = (query) => {
9
- const { resolver, model, match: where = {} } = query.toObject();
10
- const shape = model.getShape('create', 'where');
11
-
12
- const $where = Object.entries(where).reduce((prev, [from, value]) => {
13
- const el = shape.find(s => s.from === from);
14
- if (!el) return prev; // There's no knowing what this could be
15
-
16
- const { isVirtual, isEmbedded, modelRef, virtualRef } = el.field.toObject();
17
-
18
- if (isVirtual) {
19
- const ids = Promise.all(ensureArray(value).map(v => resolver.match(modelRef).where(isPlainObject(v) ? v : { id: v }).many().then(docs => docs.map(doc => doc[virtualRef])))).then(results => uniq(flattenDeep(results)));
20
- return Object.assign(prev, { id: ids });
21
- }
22
-
23
- if (modelRef && !isEmbedded) {
24
- const ids = Promise.all(ensureArray(value).map(v => (isPlainObject(v) ? resolver.match(modelRef).where(v).many().then(docs => docs.map(doc => doc.id)) : Promise.resolve(v)))).then(results => uniq(flattenDeep(results)));
25
- return Object.assign(prev, { [from]: ids });
26
- }
27
-
28
- return Object.assign(prev, { [from]: value });
29
- }, {});
30
-
31
- // Resolve
32
- return Promise.all(keyPaths($where).map(async (path) => {
33
- const $value = await get($where, path);
34
- return { path, $value };
35
- })).then((results) => {
36
- return results.reduce((prev, { path, $value }) => {
37
- if (Array.isArray($value) && $value.length === 1) [$value] = $value;
38
- return set(prev, path, $value);
39
- }, {});
40
- });
41
- };
42
-
43
- exports.resolveSortBy = (query) => {
44
- const { model, sort = {} } = query.toObject();
45
- const shape = model.getShape('create', 'sortBy');
46
- const $sort = model.shapeObject(shape, sort, query);
47
-
48
- // Because normalize casts the value (sometimes to an array) need special handling
49
- keyPaths($sort).forEach((path) => {
50
- const v = get($sort, path);
51
- const val = Array.isArray(v) ? v[0] : v;
52
- const [attr] = path.split('.');
53
- const field = model.getField(attr);
54
- const join = field.getJoinInfo();
55
-
56
- // If you need to sort by something that's in another FK document
57
- if (join) {
58
- delete $sort[attr];
59
- query.joins(Object.assign(join, { as: `_.${field}`, left: true }));
60
- path = `_.${path}`;
61
- } else {
62
- set($sort, path, val.toLowerCase() === 'asc' ? 1 : -1);
63
- }
64
- });
65
-
66
- return $sort;
67
- };
68
-
69
- exports.resolveReferentialIntegrity = (query) => {
70
- const { id, model, resolver, transaction } = query.toObject();
71
- const txn = resolver.transaction(transaction);
72
-
73
- return new Promise((resolve, reject) => {
74
- try {
75
- model.referentialIntegrity().forEach(({ model: ref, field, fieldRef, isArray, op }) => {
76
- const fieldStr = fieldRef ? `${field}.${fieldRef}` : `${field}`;
77
- const $where = { [fieldStr]: id };
78
-
79
- switch (op) {
80
- case 'cascade': {
81
- if (isArray) {
82
- txn.match(ref).where($where).pull(fieldStr, id);
83
- } else {
84
- txn.match(ref).where($where).remove();
85
- }
86
- break;
87
- }
88
- case 'nullify': {
89
- txn.match(ref).where($where).save({ [fieldStr]: null });
90
- break;
91
- }
92
- case 'restrict': {
93
- txn.match(ref).where($where).count().then(count => (count ? reject(new Error('Restricted')) : count));
94
- break;
95
- }
96
- case 'defer': {
97
- // Defer to the embedded object
98
- // Marks the field as an onDelete candidate otherwise it (and the embedded object) will get skipped
99
- break;
100
- }
101
- default: throw new Error(`Unknown onDelete operator: '${op}'`);
102
- }
103
- });
104
-
105
- // Execute the transaction
106
- txn.run().then(results => resolve(results)).catch(e => reject(e));
107
- } catch (e) {
108
- txn.rollback().then(() => reject(e)).catch(err => reject(err));
109
- }
110
- });
111
- };
Binary file
@@ -1,319 +0,0 @@
1
- const _ = require('lodash');
2
- const PicoMatch = require('picomatch');
3
- const FillRange = require('fill-range');
4
- const DeepMerge = require('deepmerge');
5
- const { ObjectId } = require('mongodb');
6
- const ObjectHash = require('object-hash');
7
-
8
- // const combineMerge = (target, source, options) => {
9
- // const destination = target.slice();
10
-
11
- // source.forEach((item, index) => {
12
- // if (typeof destination[index] === 'undefined') {
13
- // destination[index] = options.cloneUnlessOtherwiseSpecified(item, options);
14
- // } else if (options.isMergeableObject(item)) {
15
- // destination[index] = DeepMerge(target[index], item, options);
16
- // } else if (target.indexOf(item) === -1) {
17
- // destination.push(item);
18
- // }
19
- // });
20
-
21
- // return destination;
22
- // };
23
-
24
- const smartMerge = (target, source, options) => {
25
- return source;
26
- // const [el] = target;
27
- // if (!el || exports.isScalarValue(el)) return source;
28
- // return combineMerge(target, source, options);
29
- };
30
-
31
- exports.id = '3d896496-02a3-4ee5-8e42-2115eb215f7e';
32
- exports.ucFirst = string => string.charAt(0).toUpperCase() + string.slice(1);
33
- exports.lcFirst = string => string.charAt(0).toLowerCase() + string.slice(1);
34
- exports.isNumber = value => typeof value === 'number' && Number.isFinite(value);
35
- exports.isBasicObject = obj => obj != null && typeof obj === 'object' && !(ObjectId.isValid(obj)) && !(obj instanceof Date) && typeof (obj.then) !== 'function';
36
- exports.isPlainObject = obj => exports.isBasicObject(obj) && !Array.isArray(obj);
37
- exports.isScalarValue = value => typeof value !== 'object' && typeof value !== 'function';
38
- exports.isScalarDataType = value => ['String', 'Float', 'Int', 'Boolean', 'DateTime'].indexOf(value) > -1;
39
- exports.isIdValue = value => exports.isScalarValue(value) || value instanceof ObjectId;
40
- exports.mergeDeep = (...args) => DeepMerge.all(args, { isMergeableObject: obj => (exports.isPlainObject(obj) || Array.isArray(obj)), arrayMerge: smartMerge });
41
- exports.uniq = arr => [...new Set(arr.map(a => `${a}`))];
42
- exports.timeout = ms => new Promise(res => setTimeout(res, ms));
43
- exports.hashObject = obj => ObjectHash(obj, { respectType: false, respectFunctionNames: false, respectFunctionProperties: false, unorderedArrays: true, ignoreUnknown: true, replacer: r => (r instanceof ObjectId ? `${r}` : r) });
44
- exports.globToRegex = (glob, options = {}) => PicoMatch.makeRe(glob, { ...options, expandRange: (a, b) => `(${FillRange(a, b, { toRegex: true })})` });
45
- exports.globToRegexp = (glob, options = {}) => PicoMatch.toRegex(exports.globToRegex(glob, options));
46
- exports.toGUID = (model, id) => Buffer.from(`${model},${`${id}`}`).toString('base64');
47
- exports.fromGUID = guid => Buffer.from(`${guid}`, 'base64').toString('ascii').split(',');
48
- exports.guidToId = (autograph, guid) => (autograph.legacyMode ? guid : exports.uvl(exports.fromGUID(guid)[1], guid));
49
- exports.ensureArray = a => (Array.isArray(a) ? a : [a].filter(el => el !== undefined));
50
- exports.uvl = (...values) => values.reduce((prev, value) => (prev === undefined ? value : prev), undefined);
51
- exports.nvl = (...values) => values.reduce((prev, value) => (prev === null ? value : prev), null);
52
- exports.stripObjectNulls = obj => Object.entries(obj).reduce((prev, [key, value]) => (value == null ? prev : Object.assign(prev, { [key]: value })), {});
53
- exports.stripObjectUndefineds = obj => Object.entries(obj).reduce((prev, [key, value]) => (value === undefined ? prev : Object.assign(prev, { [key]: value })), {});
54
- exports.pushIt = (arr, it) => arr[arr.push(it) - 1];
55
- exports.toKeyObj = obj => exports.keyPaths(obj).reduce((prev, path) => Object.assign(prev, { [path]: _.get(obj, path) }), {});
56
-
57
- exports.getGQLReturnType = (returnType) => {
58
- const typeMap = { array: /^\[.+\].?$/, connection: /.+Connection!?$/, number: /^(Int|Float)!?$/, scalar: /.*/ };
59
- return Object.entries(typeMap).find(([type, pattern]) => returnType.match(pattern))[0];
60
- };
61
-
62
- exports.removeUndefinedDeep = (obj) => {
63
- return exports.unravelObject(exports.keyPaths(obj).reduce((prev, path) => {
64
- const value = _.get(obj, path);
65
- if (value === undefined) return prev;
66
- return Object.assign(prev, { [path]: value });
67
- }, {}));
68
- };
69
-
70
- exports.renameObjectKey = (obj, oldKey, newKey) => {
71
- if (oldKey !== newKey) {
72
- Object.defineProperty(obj, newKey, Object.getOwnPropertyDescriptor(obj, oldKey));
73
- delete obj[oldKey];
74
- }
75
- };
76
-
77
- exports.deleteKeys = (obj, keys) => {
78
- if (Array.isArray(obj)) obj.map(item => exports.deleteKeys(item, keys));
79
- else if (obj === Object(obj)) { keys.forEach(key => delete obj[key]); Object.values(obj).forEach(v => exports.deleteKeys(v, keys)); }
80
- return obj;
81
- };
82
-
83
- exports.getDeep = (obj, path, defaultValue) => {
84
- const [prop, ...rest] = path.split('.');
85
- const normalize = data => (Array.isArray(data) ? _.flatten(data) : data);
86
-
87
- return exports.map(obj, (o) => {
88
- const value = o[prop];
89
- if (rest.length) return normalize(exports.map(value, v => exports.getDeep(v, rest.join('.'), defaultValue)));
90
- return value === undefined ? defaultValue : value;
91
- });
92
- };
93
-
94
- exports.map = (mixed, fn) => {
95
- if (mixed == null) return mixed;
96
- const isArray = Array.isArray(mixed);
97
- const arr = isArray ? mixed : [mixed];
98
- const results = isArray ? arr.map((...args) => fn(...args)) : arr.map(el => fn(el));
99
- return isArray ? results : results[0];
100
- };
101
-
102
- exports.mapPromise = (mixed, fn) => {
103
- const map = exports.map(mixed, fn);
104
- return Array.isArray(map) ? Promise.all(map) : Promise.resolve(map);
105
- };
106
-
107
- exports.castCmp = (type, value) => {
108
- switch (type) {
109
- case 'String': {
110
- return `${value}`;
111
- }
112
- case 'Float': case 'Number': {
113
- const num = Number(value);
114
- if (!Number.isNaN(num)) return num;
115
- return value;
116
- }
117
- case 'Int': {
118
- const num = Number(value);
119
- if (!Number.isNaN(num)) return parseInt(value, 10);
120
- return value;
121
- }
122
- case 'Boolean': {
123
- if (value === 'true') return true;
124
- if (value === 'false') return false;
125
- return value;
126
- }
127
- default: {
128
- return value;
129
- }
130
- }
131
- };
132
-
133
- exports.objectContaining = (a, b) => {
134
- if (a === b) return true;
135
-
136
- if (exports.isPlainObject(b)) {
137
- return exports.keyPathLeafs(b).every((leaf) => {
138
- const $a = _.get(a, leaf, { a: 'a' });
139
- const $b = _.get(b, leaf, { b: 'b' });
140
- if (Array.isArray($b)) return $b.some(bb => exports.ensureArray($a).some(aa => exports.objectContaining(aa, bb)));
141
- if (exports.isScalarValue($a) && exports.isScalarValue($b)) return PicoMatch.isMatch(`${$a}`, `${$b}`, { nocase: true });
142
- return exports.hashObject($a) === exports.hashObject($b);
143
- });
144
- }
145
-
146
- return exports.hashObject(a) === exports.hashObject(b);
147
- };
148
-
149
- /**
150
- * Transform an object with dot.notation keys into an expanded object.
151
- * eg. { 'user.name': 'richard' } => { user: { name: 'richard' } }
152
- */
153
- exports.unravelObject = (obj) => {
154
- if (!exports.isPlainObject(obj)) return obj;
155
-
156
- return exports.keyPaths(obj).reduce((prev, path) => {
157
- const splitPath = path.split('.');
158
-
159
- return _.set(prev, path, _.get(obj, path, splitPath.reduce((val, p, i) => {
160
- if (val !== undefined) return val;
161
- const tuple = [splitPath.slice(0, i + 1).join('.'), splitPath.slice(i + 1).join('.')];
162
- return _.get(obj, tuple);
163
- }, undefined)));
164
- }, {});
165
- };
166
-
167
- exports.unrollGuid = (autograph, model, data) => {
168
- if (autograph.legacyMode) return data;
169
- model = autograph.resolver.toModel(model);
170
- const fields = model.getDataRefFields().map(field => field.getName());
171
-
172
- return exports.map(data, (doc) => {
173
- return Object.entries(doc).reduce((prev, [key, value]) => {
174
- return Object.assign(prev, { [key]: (fields.indexOf(key) > -1 ? exports.map(value, v => exports.guidToId(autograph, v)) : value) });
175
- }, {});
176
- });
177
- };
178
-
179
- exports.keyPaths = (obj = {}, keys = [], path) => {
180
- return Object.entries(obj).reduce((prev, [key, value]) => {
181
- const keyPath = path ? `${path}.${key}` : key;
182
- if (exports.isPlainObject(value) && Object.keys(value).length) return exports.keyPaths(value, prev, keyPath);
183
- return prev.concat(keyPath);
184
- }, keys);
185
- };
186
-
187
- exports.keyPathLeafs = (obj, keys, path) => {
188
- return exports.keyPaths(obj, keys, path).sort().reverse().filter((leaf, i, arr) => arr.findIndex(el => el.indexOf(leaf) === 0) === i);
189
- };
190
-
191
- // exports.keyPaths = (obj, keys = [], path) => {
192
- // return Object.entries(obj).reduce((prev, [key, value]) => {
193
- // const keyPath = path ? `${path}.${key}` : key;
194
- // prev.push(keyPath);
195
- // if (exports.isPlainObject(value)) return exports.keyPaths(value, prev, keyPath);
196
- // return prev;
197
- // }, keys);
198
- // };
199
-
200
- exports.queryPaths = (model, obj) => {
201
- return exports.keyPaths(obj).filter(path => path.indexOf('edges.cursor') === -1).map((path) => {
202
- return path.replace(/edges|node/gi, '').replace(/^\.+|\.+$/g, '');
203
- }).filter(a => a);
204
- };
205
-
206
- exports.promiseChain = (promises) => {
207
- return promises.reduce((chain, promise) => {
208
- return chain.then(chainResults => promise([...chainResults]).then(promiseResult => [...chainResults, promiseResult]));
209
- }, Promise.resolve([]));
210
- };
211
-
212
- exports.promiseRetry = (fn, ms, retries = 5, cond = e => e) => {
213
- return fn().catch((e) => {
214
- if (!retries || !cond(e)) throw e;
215
- return exports.timeout(ms).then(() => exports.promiseRetry(fn, ms, --retries, cond));
216
- });
217
- };
218
-
219
- exports.proxyPromise = (promise) => {
220
- return new Proxy(promise, {
221
- get(target, prop, rec) {
222
- const value = Reflect.get(target, prop, rec);
223
- if (typeof value === 'function') return value.bind(target);
224
- return (...args) => promise.then(result => result[prop](...args));
225
- },
226
- });
227
- };
228
-
229
- exports.proxyDeep = (obj, handler, proxyMap = new WeakMap(), path = '') => {
230
- obj = obj || {};
231
- if (proxyMap.has(obj)) return proxyMap.get(obj);
232
-
233
- const proxy = new Proxy(Object.entries(obj).reduce((prev, [key, value]) => {
234
- if (Array.isArray(value)) return Object.assign(prev, { [key]: value.map(v => (exports.isPlainObject(v) ? exports.proxyDeep(v, handler, proxyMap, path) : v)) });
235
- if (exports.isPlainObject(value)) return Object.assign(prev, { [key]: exports.proxyDeep(value, handler, proxyMap, path) });
236
- return Object.assign(prev, { [key]: value });
237
- }, {}), handler);
238
-
239
- const finalProxy = Object.defineProperty(proxy, 'toObject', {
240
- get() {
241
- return (getMap = new WeakMap()) => {
242
- if (getMap.has(this)) return getMap.get(this);
243
-
244
- const plainObject = Object.entries(this).reduce((prev, [key, value]) => {
245
- if (Array.isArray(value)) return Object.assign(prev, { [key]: value.map(v => (v.toObject ? v.toObject(getMap) : v)) });
246
- return Object.assign(prev, { [key]: _.get(value, 'toObject') ? value.toObject(getMap) : value });
247
- }, {});
248
-
249
- getMap.set(this, plainObject);
250
-
251
- return plainObject;
252
- };
253
- },
254
- });
255
-
256
- proxyMap.set(obj, finalProxy);
257
-
258
- return finalProxy;
259
- };
260
-
261
- exports.resolveDataObject = (obj) => {
262
- return Promise.all(Object.keys(obj).map(async (key) => {
263
- const value = await obj[key];
264
- return { key, value };
265
- })).then((results) => {
266
- return results.reduce((prev, { key, value }) => {
267
- return Object.assign(prev, { [key]: value });
268
- }, {});
269
- });
270
- };
271
-
272
- exports.seek = (obj, paths, hint) => {
273
- // We first do a normal get
274
- const value = _.get(obj, paths);
275
- if (!hint || value !== undefined) return value;
276
-
277
- // Normalize paths & hint for traversal
278
- const $paths = Array.isArray(paths) ? paths : paths.split('.');
279
- const $hint = exports.unravelObject(hint);
280
-
281
- // Traverse paths and get as close to the value as possible
282
- const { currentValue, pathsToGo } = $paths.reduce((prev, path, i, arr) => {
283
- if (prev.currentValue === undefined) return prev;
284
- if (!Object.prototype.hasOwnProperty.call(prev.currentValue, path)) return prev;
285
- prev.currentValue = prev.currentValue[path];
286
- prev.pathsToGo = arr.slice(i + 1);
287
- return prev;
288
- }, { currentValue: obj, pathsToGo: $paths });
289
-
290
- // Only if we hit an array can we continue
291
- if (!Array.isArray(currentValue)) return undefined;
292
-
293
- // If we got to the last segment we need the hint in order to verify
294
- const lastPath = Boolean(pathsToGo.length === 1);
295
- const arr = lastPath ? currentValue.filter(v => exports.objectContaining(v, $hint)) : currentValue;
296
-
297
- // We keep going, recursive, till we find the first value
298
- return arr.reduce((prev, v) => prev || exports.seek(v, pathsToGo, $hint), undefined);
299
- };
300
-
301
- exports.deseek = (shape, obj, paths, hint) => {
302
- // Normalize paths
303
- const $paths = (Array.isArray(paths) ? paths : paths.split('.')).map((path) => {
304
- const item = shape.find(s => s.to === path); // Deserializing from unknown to expected
305
- return item ? item.from : path;
306
- });
307
-
308
- // Normalize hint
309
- const $hint = Object.entries(exports.toKeyObj(hint)).reduce((prev, [key, value]) => {
310
- const segments = key.split('.').map((path) => {
311
- const item = shape.find(s => s.to === path); // Deserializing from unknown to expected
312
- return item ? item.from : path;
313
- });
314
-
315
- return Object.assign(prev, { [segments.join('.')]: value });
316
- }, {});
317
-
318
- return exports.seek(obj, $paths, $hint);
319
- };
@@ -1,114 +0,0 @@
1
- const GraphqlFields = require('graphql-fields');
2
-
3
- const resolveQuery = (method, name, resolver, model) => {
4
- return async (root, args, context, info) => {
5
- const queryInfo = { fields: GraphqlFields(info, {}, { processArguments: true }) };
6
-
7
- switch (method) {
8
- case 'get': return resolver.get(context, model, args, true, queryInfo);
9
- case 'find': {
10
- return {
11
- edges: () => resolver.query(context, model, args, queryInfo),
12
- pageInfo: () => resolver.query(context, model, args, queryInfo),
13
- count: () => resolver.count(context, model, args, queryInfo),
14
- };
15
- }
16
- case 'count': return resolver.count(context, model, args, queryInfo);
17
- case 'create': return resolver.create(context, model, args, queryInfo);
18
- case 'update': return resolver.update(context, model, args, queryInfo);
19
- case 'delete': return resolver.delete(context, model, args, queryInfo);
20
- default: return null;
21
- }
22
- };
23
- };
24
-
25
- // APIs
26
- exports.makeCreateAPI = (name, model, parent) => {
27
- let gql = '';
28
-
29
- if (model.hasGQLScope('c')) {
30
- const meta = model.getMeta() ? `meta: ${model.getMeta()}` : '';
31
- gql += `create${name}(input: ${model.getName()}InputCreate! ${meta}): ${model.getName()}!`;
32
- }
33
-
34
- return gql;
35
- };
36
-
37
- exports.makeReadAPI = (name, model, parent) => {
38
- let gql = '';
39
-
40
- if (model.hasGQLScope('r')) {
41
- gql += `
42
- get${name}(id: ID!): ${model.getName()}
43
- find${name}(
44
- where: ${model.getName()}InputWhere
45
- sortBy: ${model.getName()}InputSort
46
- limit: Int
47
- skip: Int
48
- first: Int
49
- after: String
50
- last: Int
51
- before: String
52
- ): ${model.getName()}Connection!
53
- `;
54
- }
55
-
56
- return gql;
57
- };
58
-
59
- exports.makeUpdateAPI = (name, model, parent) => {
60
- let gql = '';
61
-
62
- if (model.hasGQLScope('u')) {
63
- const meta = model.getMeta() ? `meta: ${model.getMeta()}` : '';
64
- gql += `update${name}(id: ID! input: ${model.getName()}InputUpdate ${meta}): ${model.getName()}!`;
65
- }
66
-
67
- return gql;
68
- };
69
-
70
- exports.makeDeleteAPI = (name, model, parent) => {
71
- let gql = '';
72
-
73
- if (model.hasGQLScope('d')) {
74
- const meta = model.getMeta() ? `meta: ${model.getMeta()}` : '';
75
- gql += `delete${name}(id: ID! ${meta}): ${model.getName()}!`;
76
- }
77
-
78
- return gql;
79
- };
80
-
81
- exports.makeSubscriptionAPI = (name, model, parent) => {
82
- let gql = '';
83
-
84
- if (model.hasGQLScope('s')) {
85
- gql += `${name} (
86
- on: [SubscriptionCrudEnum!]! = [create, update, delete]
87
- filter: ${name}SubscriptionInputFilter
88
- ): ${name}SubscriptionPayload!`;
89
- }
90
-
91
- return gql;
92
- };
93
-
94
- // Resolvers
95
- exports.makeQueryResolver = (name, model, resolver) => {
96
- const obj = {};
97
-
98
- if (model.hasGQLScope('r')) {
99
- obj[`get${name}`] = resolveQuery('get', name, resolver, model);
100
- obj[`find${name}`] = resolveQuery('find', name, resolver, model);
101
- }
102
-
103
- return obj;
104
- };
105
-
106
- exports.makeMutationResolver = (name, model, resolver) => {
107
- const obj = {};
108
-
109
- if (model.hasGQLScope('c')) obj[`create${name}`] = resolveQuery('create', name, resolver, model);
110
- if (model.hasGQLScope('u')) obj[`update${name}`] = resolveQuery('update', name, resolver, model);
111
- if (model.hasGQLScope('d')) obj[`delete${name}`] = resolveQuery('delete', name, resolver, model);
112
-
113
- return obj;
114
- };
@@ -1,66 +0,0 @@
1
- const QueryService = require('../query/QueryService');
2
- const EventEmitter = require('../core/EventEmitter');
3
- const { ucFirst } = require('./app.service');
4
-
5
- // Event emitters
6
- const eventEmitter = new EventEmitter().setMaxListeners(100);
7
- const systemEvent = new EventEmitter().setMaxListeners(100).on('system', async (event, next) => {
8
- const { type, data } = event;
9
- next(await eventEmitter.emit(type, data)); // Return result from user-defined middleware
10
- });
11
-
12
- const makeEvent = (mixed) => {
13
- const { query } = mixed;
14
- const event = query.toObject();
15
- event.query = query;
16
- return event;
17
- };
18
-
19
- const makeMiddleware = () => {
20
- return (mixed) => {
21
- const { query } = mixed;
22
- const { model, native, sort, match, batch } = query.toObject();
23
-
24
- return new Promise(async (resolve) => {
25
- if (!native) {
26
- const whereShape = model.getShape('create', 'where');
27
- const $where = batch ? match : await QueryService.resolveWhereClause(query);
28
- const $$where = model.shapeObject(whereShape, $where, query);
29
- query.match($$where);
30
- }
31
-
32
- if (sort && Object.keys(sort).length) {
33
- query.$sort(QueryService.resolveSortBy(query));
34
- }
35
-
36
- resolve();
37
- });
38
- };
39
- };
40
-
41
- //
42
- exports.createSystemEvent = (name, mixed = {}, thunk = () => {}) => {
43
- let event = mixed;
44
- let middleware = () => Promise.resolve();
45
- const type = ucFirst(name);
46
-
47
- if (name !== 'Response') {
48
- event = makeEvent(mixed);
49
- middleware = makeMiddleware();
50
- }
51
-
52
- return systemEvent.emit('system', { type: `pre${type}`, data: event }).then(async (result) => {
53
- if (result !== undefined) return result; // Allowing middleware to dictate result
54
- return middleware(mixed).then(thunk);
55
- }).then((result) => {
56
- event.result = result;
57
- if (event.crud === 'create') event.doc = event.query.toObject().doc;
58
- return systemEvent.emit('system', { type: `post${type}`, data: event }).then((postResult = result) => postResult);
59
- }).then((result) => {
60
- if (name === 'Response') return result;
61
- event.result = result;
62
- return exports.createSystemEvent('Response', event, (finalResult = result) => finalResult);
63
- });
64
- };
65
-
66
- exports.eventEmitter = eventEmitter;