@coderich/autograph 0.9.10 → 0.9.13

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.
@@ -0,0 +1,47 @@
1
+ const { get } = require('lodash');
2
+ const DataService = require('./DataService');
3
+ const { map, ensureArray } = require('../service/app.service');
4
+
5
+ module.exports = class ResultSet {
6
+ constructor(query, data, adjustForPagination = true) {
7
+ if (data == null) return data;
8
+
9
+ const { model, first, after, last, before } = query.toObject();
10
+ const rs = map(data, doc => model.getResultSetItem().create(query, doc));
11
+
12
+ let hasNextPage = false;
13
+ let hasPreviousPage = false;
14
+ if (adjustForPagination && rs.length) (({ hasPreviousPage, hasNextPage } = DataService.paginateResultSet(rs, first, after, last, before)));
15
+
16
+ return Object.defineProperties(rs, {
17
+ $$pageInfo: {
18
+ get() {
19
+ const edges = ensureArray(rs);
20
+
21
+ return {
22
+ startCursor: get(edges, '0.$$cursor', ''),
23
+ endCursor: get(edges, `${edges.length - 1}.$$cursor`, ''),
24
+ hasPreviousPage,
25
+ hasNextPage,
26
+ };
27
+ },
28
+ enumerable: false,
29
+ },
30
+ $$isResultSet: {
31
+ value: true,
32
+ enumerable: false,
33
+ },
34
+ toObject: {
35
+ get() {
36
+ return () => map(this, doc => Object.entries(doc).reduce((prev, [key, value]) => {
37
+ if (value === undefined) return prev;
38
+ prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
39
+ return prev;
40
+ }, {}));
41
+ },
42
+ enumerable: false,
43
+ configurable: true,
44
+ },
45
+ });
46
+ }
47
+ };
@@ -0,0 +1,299 @@
1
+ const { get } = require('lodash');
2
+ const DataService = require('./DataService');
3
+ const { map, ensureArray, keyPaths, mapPromise, toGUID, hashObject } = require('../service/app.service');
4
+
5
+ module.exports = class ResultSet {
6
+ constructor(query, data, adjustForPagination = true) {
7
+ if (data == null) return data;
8
+ const { resolver, model, sort, first, after, last, before } = query.toObject();
9
+ const fields = model.getFields().filter(f => f.getName() !== 'id');
10
+
11
+ const rs = map(data, (doc) => {
12
+ if (doc == null || typeof doc !== 'object') return doc;
13
+
14
+ //
15
+ const cache = new Map();
16
+
17
+ const definition = {
18
+ // $$model: model,
19
+ $$isResultSetItem: true,
20
+
21
+ get id() { return doc.id || doc[model.idKey()]; },
22
+ set id(id) { doc.id = id; }, // Embedded array of documents need to set id
23
+ get $id() { return toGUID(model.getName(), this.id); },
24
+
25
+ get $$cursor() {
26
+ const sortPaths = keyPaths(sort);
27
+ const sortValues = sortPaths.reduce((prv, path) => Object.assign(prv, { [path]: get(this, path) }), {});
28
+ const sortJSON = JSON.stringify(sortValues);
29
+ return Buffer.from(sortJSON).toString('base64');
30
+ },
31
+
32
+ $$save: input => resolver.match(model).id(this.id).save({ ...this, ...input }),
33
+ $$remove: () => resolver.match(model).id(this.id).remove(),
34
+ $$delete: () => resolver.match(model).id(this.id).delete(),
35
+
36
+ get toObject() {
37
+ return () => map(this, obj => Object.entries(obj).reduce((prev, [key, value]) => {
38
+ if (value === undefined) return prev;
39
+ prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
40
+ return prev;
41
+ }, {}));
42
+ },
43
+
44
+ ...fields.reduce((prev, field) => {
45
+ const key = field.getKey();
46
+ const name = field.getName();
47
+ const $name = `$${name}`;
48
+ const value = doc[key];
49
+
50
+ return {
51
+ ...prev,
52
+
53
+ // Deserialized field attributes
54
+ get [name]() {
55
+ if (cache.has(name)) return cache.get(name);
56
+ let $value = field.deserialize(query, value);
57
+ $value = $value != null && field.isEmbedded() ? new ResultSet(query.model(field.getModelRef()), $value, false) : $value;
58
+ cache.set(name, $value);
59
+ return $value;
60
+ },
61
+ set [name]($value) {
62
+ cache.set(name, $value);
63
+ },
64
+
65
+ // Fully deserialized, hydrated, and resolved field attributes
66
+ get [$name]() {
67
+ return (args = {}) => {
68
+ // Ensure where clause
69
+ args.where = args.where || {};
70
+
71
+ // Cache
72
+ const cacheKey = `${$name}-${hashObject(args)}`;
73
+ if (cache.has(cacheKey)) return cache.get(cacheKey);
74
+
75
+ const promise = new Promise((resolve, reject) => {
76
+ (() => {
77
+ const $value = this[name];
78
+
79
+ if (field.isScalar() || field.isEmbedded()) return Promise.resolve($value);
80
+
81
+ const modelRef = field.getModelRef();
82
+
83
+ if (field.isArray()) {
84
+ if (field.isVirtual()) {
85
+ args.where[[field.getVirtualField()]] = this.id; // Is where[[field.getVirtualField()]] correct?
86
+ return resolver.match(modelRef).merge(args).many();
87
+ }
88
+
89
+ // Not a "required" query + strip out nulls
90
+ args.where.id = $value;
91
+ return resolver.match(modelRef).merge(args).many();
92
+ }
93
+
94
+ if (field.isVirtual()) {
95
+ args.where[[field.getVirtualField()]] = this.id;
96
+ return resolver.match(modelRef).merge(args).one();
97
+ }
98
+
99
+ return resolver.match(modelRef).id($value).one({ required: field.isRequired() });
100
+ })().then((results) => {
101
+ if (results == null) return field.resolve(query, results); // Allow field to determine
102
+ return mapPromise(results, result => field.resolve(query, result)).then(() => results); // Resolve the inside fields but still return "results"!!!!
103
+ }).then((resolved) => {
104
+ resolve(resolved);
105
+ }).catch((e) => {
106
+ reject(e);
107
+ });
108
+ });
109
+
110
+ cache.set(cacheKey, promise);
111
+ return promise;
112
+ };
113
+ },
114
+
115
+ // Field count (let's assume it's a Connection Type - meaning dont try with anything else)
116
+ get [`${$name}:count`]() {
117
+ return (q = {}) => {
118
+ q.where = q.where || {};
119
+ if (field.isVirtual()) q.where[field.getVirtualField()] = this.id;
120
+ else q.where.id = this[name];
121
+ return resolver.match(field.getModelRef()).merge(q).count();
122
+ };
123
+ },
124
+ };
125
+ }, {}),
126
+ };
127
+
128
+ // const definition = fields.reduce((prev, field) => {
129
+ // const key = field.getKey();
130
+ // const name = field.getName();
131
+ // const $name = `$${name}`;
132
+ // const value = doc[key];
133
+
134
+ // return {
135
+ // ...prev,
136
+
137
+ // // Deserialized field attributes
138
+ // get [name]() {
139
+ // if (cache.has(name)) return cache.get(name);
140
+ // let $value = field.deserialize(query, value);
141
+ // $value = $value != null && field.isEmbedded() ? new ResultSet(query.model(field.getModelRef()), $value, false) : $value;
142
+ // cache.set(name, $value);
143
+ // return $value;
144
+ // },
145
+ // set [name]($value) {
146
+ // cache.set(name, $value);
147
+ // },
148
+
149
+ // // Fully deserialized, hydrated, and resolved field attributes
150
+ // get [$name]() {
151
+ // return (args = {}) => {
152
+ // // Ensure where clause
153
+ // args.where = args.where || {};
154
+
155
+ // // Cache
156
+ // const cacheKey = `${$name}-${hashObject(args)}`;
157
+ // if (cache.has(cacheKey)) return cache.get(cacheKey);
158
+
159
+ // const promise = new Promise((resolve, reject) => {
160
+ // (() => {
161
+ // const $value = this[name];
162
+
163
+ // if (field.isScalar() || field.isEmbedded()) return Promise.resolve($value);
164
+
165
+ // const modelRef = field.getModelRef();
166
+
167
+ // if (field.isArray()) {
168
+ // if (field.isVirtual()) {
169
+ // args.where[[field.getVirtualField()]] = this.id; // Is where[[field.getVirtualField()]] correct?
170
+ // return resolver.match(modelRef).merge(args).many();
171
+ // }
172
+
173
+ // // Not a "required" query + strip out nulls
174
+ // args.where.id = $value;
175
+ // return resolver.match(modelRef).merge(args).many();
176
+ // }
177
+
178
+ // if (field.isVirtual()) {
179
+ // args.where[[field.getVirtualField()]] = this.id;
180
+ // return resolver.match(modelRef).merge(args).one();
181
+ // }
182
+
183
+ // return resolver.match(modelRef).id($value).one({ required: field.isRequired() });
184
+ // })().then((results) => {
185
+ // if (results == null) return field.resolve(query, results); // Allow field to determine
186
+ // return mapPromise(results, result => field.resolve(query, result)).then(() => results); // Resolve the inside fields but still return "results"!!!!
187
+ // }).then((resolved) => {
188
+ // resolve(resolved);
189
+ // }).catch((e) => {
190
+ // reject(e);
191
+ // });
192
+ // });
193
+
194
+ // cache.set(cacheKey, promise);
195
+ // return promise;
196
+ // };
197
+ // },
198
+
199
+ // // Field count (let's assume it's a Connection Type - meaning dont try with anything else)
200
+ // get [`${$name}:count`]() {
201
+ // return (q = {}) => {
202
+ // q.where = q.where || {};
203
+ // if (field.isVirtual()) q.where[field.getVirtualField()] = this.id;
204
+ // else q.where.id = this[name];
205
+ // return resolver.match(field.getModelRef()).merge(q).count();
206
+ // };
207
+ // },
208
+ // };
209
+ // }, {
210
+ // get id() { return doc.id || doc[model.idKey()]; },
211
+ // set id(id) { doc.id = id; }, // Embedded array of documents need to set id
212
+
213
+ // get $id() { return toGUID(model.getName(), this.id); },
214
+
215
+ // get $$cursor() {
216
+ // const sortPaths = keyPaths(sort);
217
+ // const sortValues = sortPaths.reduce((prv, path) => Object.assign(prv, { [path]: get(this, path) }), {});
218
+ // const sortJSON = JSON.stringify(sortValues);
219
+ // return Buffer.from(sortJSON).toString('base64');
220
+ // },
221
+
222
+ // $$model: model,
223
+ // $$isResultSetItem: true,
224
+ // $$save: input => resolver.match(model).id(this.id).save({ ...this, ...input }),
225
+ // $$remove: () => resolver.match(model).id(this.id).remove(),
226
+ // $$delete: () => resolver.match(model).id(this.id).delete(),
227
+
228
+ // get toObject() {
229
+ // return () => map(this, obj => Object.entries(obj).reduce((prev, [key, value]) => {
230
+ // if (value === undefined) return prev;
231
+ // prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
232
+ // return prev;
233
+ // }, {}));
234
+ // },
235
+ // });
236
+
237
+ return definition;
238
+ });
239
+
240
+ let hasNextPage = false;
241
+ let hasPreviousPage = false;
242
+ if (adjustForPagination && rs.length) (({ hasPreviousPage, hasNextPage } = DataService.paginateResultSet(rs, first, after, last, before)));
243
+
244
+ return Object.defineProperties(rs, {
245
+ $$pageInfo: {
246
+ get() {
247
+ const edges = ensureArray(rs);
248
+
249
+ return {
250
+ startCursor: get(edges, '0.$$cursor', ''),
251
+ endCursor: get(edges, `${edges.length - 1}.$$cursor`, ''),
252
+ hasPreviousPage,
253
+ hasNextPage,
254
+ };
255
+ },
256
+ enumerable: false,
257
+ },
258
+ $$isResultSet: {
259
+ value: true,
260
+ enumerable: false,
261
+ },
262
+ toObject: {
263
+ get() {
264
+ return () => map(this, doc => Object.entries(doc).reduce((prev, [key, value]) => {
265
+ if (value === undefined) return prev;
266
+ prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
267
+ return prev;
268
+ }, {}));
269
+ },
270
+ enumerable: false,
271
+ configurable: true,
272
+ },
273
+ });
274
+
275
+ // const idk = {
276
+ // ...rs,
277
+ // $$isResultSet: true,
278
+ // get $$pageInfo() {
279
+ // const edges = ensureArray(rs);
280
+
281
+ // return {
282
+ // startCursor: get(edges, '0.$$cursor', ''),
283
+ // endCursor: get(edges, `${edges.length - 1}.$$cursor`, ''),
284
+ // hasPreviousPage,
285
+ // hasNextPage,
286
+ // };
287
+ // },
288
+ // get toObject() {
289
+ // return () => map(this, doc => Object.entries(doc).reduce((prev, [key, value]) => {
290
+ // if (value === undefined) return prev;
291
+ // prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
292
+ // return prev;
293
+ // }, {}));
294
+ // },
295
+ // };
296
+
297
+ // return idk;
298
+ }
299
+ };
@@ -4,6 +4,8 @@ const { map, ensureArray, keyPaths, mapPromise, toGUID, hashObject } = require('
4
4
 
5
5
  module.exports = class ResultSet {
6
6
  constructor(query, data, adjustForPagination = true) {
7
+ if (data == null) return data;
8
+
7
9
  const { resolver, model, sort, first, after, last, before } = query.toObject();
8
10
  const fields = model.getFields().filter(f => f.getName() !== 'id');
9
11
 
@@ -13,80 +15,15 @@ module.exports = class ResultSet {
13
15
  //
14
16
  const cache = new Map();
15
17
 
16
- // Base definition all results have
17
- const definition = {
18
- id: {
19
- get() { return doc.id || doc[model.idKey()]; },
20
- set(id) { doc.id = id; }, // Embedded array of documents need to set id
21
- enumerable: true,
22
- },
23
-
24
- $id: {
25
- get() { return toGUID(model.getName(), this.id); },
26
- enumerable: false,
27
- },
28
-
29
- $$cursor: {
30
- get() {
31
- const sortPaths = keyPaths(sort);
32
- const sortValues = sortPaths.reduce((prv, path) => Object.assign(prv, { [path]: get(this, path) }), {});
33
- const sortJSON = JSON.stringify(sortValues);
34
- return Buffer.from(sortJSON).toString('base64');
35
- },
36
- enumerable: false,
37
- },
38
-
39
- $$model: {
40
- value: model,
41
- enumerable: false,
42
- },
43
-
44
- $$data: {
45
- value: data,
46
- enumerable: false,
47
- },
48
-
49
- $$isResultSetItem: {
50
- value: true,
51
- enumerable: false,
52
- },
53
-
54
- $$save: {
55
- get() { return input => resolver.match(model).id(this.id).save({ ...this, ...input }); },
56
- enumerable: false,
57
- },
58
-
59
- $$remove: {
60
- get() { return () => resolver.match(model).id(this.id).remove(); },
61
- enumerable: false,
62
- },
63
-
64
- $$delete: {
65
- get() { return () => resolver.match(model).id(this.id).delete(); },
66
- enumerable: false,
67
- },
68
-
69
- toObject: {
70
- get() {
71
- return () => map(this, obj => Object.entries(obj).reduce((prev, [key, value]) => {
72
- if (value === undefined) return prev;
73
- prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
74
- return prev;
75
- }, {}));
76
- },
77
- enumerable: false,
78
- configurable: true,
79
- },
80
- };
81
-
82
- fields.forEach((field) => {
18
+ const definition = fields.reduce((prev, field) => {
83
19
  const key = field.getKey();
84
20
  const name = field.getName();
85
21
  const $name = `$${name}`;
86
22
  const value = doc[key];
87
23
 
88
- // Field attributes
89
- definition[name] = {
24
+ // Deserialized field attributes
25
+ prev[name] = {
26
+ // value,
90
27
  get() {
91
28
  if (cache.has(name)) return cache.get(name);
92
29
  let $value = field.deserialize(query, value);
@@ -101,8 +38,9 @@ module.exports = class ResultSet {
101
38
  configurable: true, // Allows things like delete
102
39
  };
103
40
 
104
- // Hydrated field attributes
105
- definition[`$${name}`] = {
41
+ // Fully deserialized, hydrated, and resolved field attributes
42
+ prev[$name] = {
43
+ // value: () => value,
106
44
  get() {
107
45
  return (args = {}) => {
108
46
  // Ensure where clause
@@ -155,7 +93,7 @@ module.exports = class ResultSet {
155
93
  };
156
94
 
157
95
  // Field count (let's assume it's a Connection Type - meaning dont try with anything else)
158
- definition[`$${name}:count`] = {
96
+ prev[`${$name}:count`] = {
159
97
  get() {
160
98
  return (q = {}) => {
161
99
  q.where = q.where || {};
@@ -166,6 +104,66 @@ module.exports = class ResultSet {
166
104
  },
167
105
  enumerable: false,
168
106
  };
107
+
108
+ return prev;
109
+ }, {
110
+ id: {
111
+ get() { return doc.id || doc[model.idKey()]; },
112
+ set(id) { doc.id = id; }, // Embedded array of documents need to set id
113
+ enumerable: true,
114
+ },
115
+
116
+ $id: {
117
+ get() { return toGUID(model.getName(), this.id); },
118
+ enumerable: false,
119
+ },
120
+
121
+ $$cursor: {
122
+ get() {
123
+ const sortPaths = keyPaths(sort);
124
+ const sortValues = sortPaths.reduce((prv, path) => Object.assign(prv, { [path]: get(this, path) }), {});
125
+ const sortJSON = JSON.stringify(sortValues);
126
+ return Buffer.from(sortJSON).toString('base64');
127
+ },
128
+ enumerable: false,
129
+ },
130
+
131
+ $$model: {
132
+ value: model,
133
+ enumerable: false,
134
+ },
135
+
136
+ $$isResultSetItem: {
137
+ value: true,
138
+ enumerable: false,
139
+ },
140
+
141
+ $$save: {
142
+ get() { return input => resolver.match(model).id(this.id).save({ ...this, ...input }); },
143
+ enumerable: false,
144
+ },
145
+
146
+ $$remove: {
147
+ get() { return () => resolver.match(model).id(this.id).remove(); },
148
+ enumerable: false,
149
+ },
150
+
151
+ $$delete: {
152
+ get() { return () => resolver.match(model).id(this.id).delete(); },
153
+ enumerable: false,
154
+ },
155
+
156
+ toObject: {
157
+ get() {
158
+ return () => map(this, obj => Object.entries(obj).reduce((prev, [key, value]) => {
159
+ if (value === undefined) return prev;
160
+ prev[key] = get(value, '$$isResultSet') ? value.toObject() : value;
161
+ return prev;
162
+ }, {}));
163
+ },
164
+ enumerable: false,
165
+ configurable: true,
166
+ },
169
167
  });
170
168
 
171
169
  // Create and return ResultSetItem
@@ -16,6 +16,10 @@ module.exports = class MongoDriver {
16
16
  return MongoClient.connect(uri, options);
17
17
  }
18
18
 
19
+ disconnect() {
20
+ return this.connection.then(client => client.close());
21
+ }
22
+
19
23
  raw(collection) {
20
24
  return proxyPromise(this.connection.then(client => client.db().collection(collection)));
21
25
  }
@@ -144,15 +148,15 @@ module.exports = class MongoDriver {
144
148
  }
145
149
 
146
150
  static getAddFields(query) {
147
- const { schema, where } = query;
151
+ const { shape, where } = query;
148
152
 
149
- return Object.entries(schema).reduce((prev, [key, { type }]) => {
150
- const value = where[key];
153
+ return shape.reduce((prev, { from, type }) => {
154
+ const value = where[from];
151
155
  if (value === undefined) return prev;
152
156
  if (!isScalarDataType(type)) return prev;
153
157
  const stype = String((type === 'Float' || type === 'Int' ? 'Number' : type)).toLowerCase();
154
158
  if (String(typeof value) === `${stype}`) return prev;
155
- return Object.assign(prev, { [key]: { $toString: `$${key}` } });
159
+ return Object.assign(prev, { [from]: { $toString: `$${from}` } });
156
160
  }, {});
157
161
  }
158
162
 
Binary file
@@ -12,6 +12,10 @@ module.exports = class Model extends Node {
12
12
  this.key = uvl(this.getDirectiveArg('model', 'key'), this.getName());
13
13
  }
14
14
 
15
+ idKey() {
16
+ return this.getDirectiveArg('model', 'id', '_id');
17
+ }
18
+
15
19
  getSchema() {
16
20
  return this.schema;
17
21
  }
@@ -1,14 +1,13 @@
1
1
  const FS = require('fs');
2
2
  const Glob = require('glob');
3
- const Path = require('path');
4
3
  const Merge = require('deepmerge');
5
4
  const { nvl, uvl } = require('../../service/app.service');
6
5
  const { validateSchema, makeExecutableSchema, mergeASTSchema, mergeASTArray } = require('../../service/graphql.service');
7
6
  const Node = require('./Node');
8
7
  const Model = require('./Model');
9
8
 
10
- const loadFile = file => FS.readFileSync(Path.resolve(file), 'utf8');
11
- const reqFile = file => require(Path.resolve(file)); // eslint-disable-line global-require,import/no-dynamic-require
9
+ const loadFile = file => FS.readFileSync(file, 'utf8');
10
+ const reqFile = file => require(file); // eslint-disable-line global-require,import/no-dynamic-require
12
11
 
13
12
  module.exports = class Schema extends Node {
14
13
  constructor(schema) {