@coderich/autograph 0.12.0 → 0.13.1

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 +84 -101
  7. package/src/data/Resolver.js +304 -0
  8. package/src/data/Transaction.js +49 -0
  9. package/src/query/Query.js +159 -335
  10. package/src/query/QueryBuilder.js +228 -114
  11. package/src/query/QueryResolver.js +110 -205
  12. package/src/query/QueryResolverTransaction.js +16 -0
  13. package/src/schema/Schema.js +602 -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 -161
  29. package/src/data/Field.js +0 -83
  30. package/src/data/Model.js +0 -214
  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,206 +0,0 @@
1
- const Node = require('./Node');
2
- const Type = require('./Type');
3
- const { uvl } = require('../../service/app.service');
4
-
5
- module.exports = class Field extends Node {
6
- constructor(model, ast) {
7
- super(ast, 'field');
8
- this.model = model;
9
- this.schema = model.getSchema();
10
- this.type = new Type(this.ast);
11
- this.key = uvl(this.getDirectiveArg('field', 'key'), this.getName());
12
- this.isArray = this.type.isArray.bind(this.type);
13
- this.isArrayElementRequired = this.type.isArrayElementRequired.bind(this.type);
14
- }
15
-
16
- // Field Methods
17
- getKey() {
18
- return this.key;
19
- }
20
-
21
- getType() {
22
- return this.type.getName();
23
- }
24
-
25
- getDataType() {
26
- const type = this.getType();
27
- return this.isArray() ? [type] : type;
28
- }
29
-
30
- getDataRef() {
31
- return this.isScalar() ? null : this.getType();
32
- }
33
-
34
- getScalarRef() {
35
- return this.schema.getScalar(this.getType());
36
- }
37
-
38
- getEnumRef() {
39
- return this.schema.getEnum(this.getType());
40
- }
41
-
42
- getDefaultValue() {
43
- return this.getDirectiveArg('field', 'default');
44
- }
45
-
46
- // Model Methods
47
- getSchema() {
48
- return this.model.getSchema();
49
- }
50
-
51
- getModel() {
52
- return this.model;
53
- }
54
-
55
- getModelRef() {
56
- const refType = this.getDirectiveArg('field', 'id', this.getType());
57
- return this.schema.getModel(refType);
58
- }
59
-
60
- getFieldRef() {
61
- const ref = this.getDirectiveArg('field', 'ref');
62
- const modelRef = this.getModelRef();
63
- if (!ref || !modelRef) return null;
64
- return modelRef.getField(ref);
65
- }
66
-
67
- getVirtualField() {
68
- const model = this.getModelRef();
69
- return model ? model.getField(this.getVirtualRef()) : null;
70
- }
71
-
72
- getIdModel() {
73
- return this.getModelRef() || this.getModel();
74
- }
75
-
76
- resolveField() {
77
- const field = this.getVirtualField() || this;
78
- return field === this ? this : field.resolveField();
79
- }
80
-
81
- // Boolean Methods
82
- isScalar() {
83
- return Boolean(this.type.isScalar() || !this.getModelRef());
84
- }
85
-
86
- isDefaulted() {
87
- return Boolean(this.getDefaultValue() != null);
88
- }
89
-
90
- isRequired() {
91
- return this.type.isRequired() && this.getName() !== 'id';
92
- }
93
-
94
- isReference() {
95
- return Boolean(this.getDirectiveArg('field', 'ref'));
96
- }
97
-
98
- isFKReference() {
99
- const modelRef = this.getModelRef();
100
- return Boolean(modelRef && !this.isEmbedded());
101
- }
102
-
103
- isIdField() {
104
- return this.isPrimaryKeyId() || this.isFKReference();
105
- }
106
-
107
- isPrimaryKeyId() {
108
- const key = this.getKey();
109
- const idKey = this.getModel().idKey();
110
- return key === idKey;
111
- }
112
-
113
- getJoinInfo() {
114
- const modelRef = this.getModelRef();
115
- if (!modelRef || this.isEmbedded()) return null;
116
- const vref = this.getVirtualRef();
117
- const to = modelRef.getKey();
118
- const by = vref || modelRef.idKey();
119
- const from = vref ? this.getModel().idKey() : this.getKey();
120
- return { to, by, from };
121
- }
122
-
123
- isConnection() {
124
- // Deliberately need to specify this is a connection
125
- const connection = Boolean(this.getDirectiveArg('field', 'connection'));
126
- if (!connection) return false;
127
-
128
- // Also needs to be proper
129
- const modelRef = this.getModelRef();
130
- return Boolean(modelRef && modelRef.isMarkedModel() && this.isArray() && !this.isEmbedded());
131
- }
132
-
133
- isSpliceable() {
134
- const modelRef = this.getModelRef();
135
- return Boolean(modelRef && modelRef.isMarkedModel() && this.isArray() && this.isEmbedded() && !this.isVirtual());
136
- }
137
-
138
- // GQL Schema Methods
139
- getGQLType(suffix, options = {}) {
140
- let type = this.getType();
141
- const modelType = `${type}${suffix}`;
142
- if (suffix && !this.isScalar()) type = this.isEmbedded() ? modelType : 'ID';
143
- type = this.isArray() ? `[${type}${this.isArrayElementRequired() ? '!' : ''}]` : type;
144
- if (!suffix && this.isRequired()) type += '!';
145
- if (suffix === 'InputCreate' && this.isRequired() && !this.isDefaulted()) type += '!';
146
- return type;
147
- }
148
-
149
- getExtendArgs() {
150
- return this.isConnection() ? `(
151
- where: ${this.getType()}InputWhere
152
- sortBy: ${this.getType()}InputSort
153
- limit: Int
154
- skip: Int
155
- first: Int
156
- after: String
157
- last: Int
158
- before: String
159
- )` : '';
160
- }
161
-
162
- getPayloadType() {
163
- let type = this.getType();
164
- const req = this.isRequired() ? '!' : '';
165
- if (this.getName() === 'id') return 'ID!';
166
- if (this.isConnection()) return `${type}Connection${req}`;
167
- type = this.isArray() ? `[${type}${this.isArrayElementRequired() ? '!' : ''}]` : type;
168
- return `${type}${req}`;
169
- }
170
-
171
- getSubscriptionType() {
172
- if (this.isFKReference()) return this.isArray() ? '[ID]' : 'ID';
173
- return this.getGQLType();
174
- }
175
-
176
- finalize() {
177
- this.props = {
178
- key: this.getKey(),
179
- name: this.getName(),
180
- type: this.getType(),
181
- model: this.model,
182
- datatype: this.getDataType(),
183
- defaultValue: this.getDefaultValue(),
184
- isEnum: this.isEnum(),
185
- isArray: this.isArray(),
186
- isScalar: this.isScalar(),
187
- isVirtual: this.isVirtual(),
188
- isRequired: this.isRequired(),
189
- isEmbedded: this.isEmbedded(),
190
- isBasicType: this.isBasicType(),
191
- isIdField: this.isIdField(),
192
- isPrimaryKeyId: this.isPrimaryKeyId(),
193
- isPersistable: this.isPersistable(),
194
- idModel: this.getIdModel(),
195
- modelRef: this.getModelRef(),
196
- virtualRef: this.getVirtualRef(),
197
- virtualField: this.getVirtualField(),
198
- };
199
-
200
- return this;
201
- }
202
-
203
- toObject() {
204
- return this.props;
205
- }
206
- };
@@ -1,145 +0,0 @@
1
- const Node = require('./Node');
2
- const Field = require('./Field');
3
- const { uvl } = require('../../service/app.service');
4
-
5
- module.exports = class Model extends Node {
6
- constructor(schema, ast) {
7
- super(ast, 'model');
8
- this.schema = schema;
9
- this.fields = this.ast.fields.map(f => new Field(this, f));
10
- this.fieldsByName = {};
11
- this.fieldsByKey = {};
12
- this.key = uvl(this.getDirectiveArg('model', 'key'), this.getName());
13
- }
14
-
15
- idKey() {
16
- return this.getDirectiveArg('model', 'id', '_id');
17
- }
18
-
19
- getSchema() {
20
- return this.schema;
21
- }
22
-
23
- getFields() {
24
- return this.fields;
25
- }
26
-
27
- getKey() {
28
- return this.key;
29
- }
30
-
31
- getField(path = '') {
32
- const [name, ...rest] = path.split('.');
33
- let field = this.getFields().find(f => f.getName() === name);
34
- if (!field) field = this.getFieldByKey(name);
35
- if (field == null) return field;
36
-
37
- if (rest.length) {
38
- const modelRef = field.getModelRef();
39
- return modelRef ? modelRef.getField(rest.join('.')) : null;
40
- }
41
-
42
- return field;
43
- }
44
-
45
- getFieldByName(name) {
46
- let field = this.fieldsByName[name];
47
-
48
- if (!field) {
49
- field = this.getFields().find(f => f.getName() === name);
50
- this.fieldsByName[name] = field;
51
- }
52
-
53
- return field;
54
- }
55
-
56
- getFieldByKey(key) {
57
- let field = this.fieldsByKey[key];
58
-
59
- if (!field) {
60
- field = this.getFields().find(f => f.getKey() === key);
61
- this.fieldsByKey[key] = field;
62
- }
63
-
64
- return field;
65
- }
66
-
67
- getFieldNames() {
68
- return this.getFields().map(field => field.getName());
69
- }
70
-
71
- getFieldMap() {
72
- return this.getFields().reduce((prev, field) => Object.assign(prev, { [field.getName()]: field }), {});
73
- }
74
-
75
- getScalarFields() {
76
- return this.getFields().filter(field => field.isBasicType());
77
- }
78
-
79
- getArrayFields() {
80
- return this.getFields().filter(field => field.isArray());
81
- }
82
-
83
- getRequiredFields() {
84
- return this.getFields().filter(field => field.isRequired());
85
- }
86
-
87
- getDefaultFields() {
88
- return this.getFields().filter(field => field.getDefaultValue() != null);
89
- }
90
-
91
- getDefaultedFields() {
92
- return this.getFields().filter(field => field.isDefaulted());
93
- }
94
-
95
- getDataRefFields() {
96
- return this.getFields().filter(field => Boolean(field.getDataRef()));
97
- }
98
-
99
- getModelRefFields() {
100
- return this.getFields().filter(field => Boolean(field.getModelRef()));
101
- }
102
-
103
- getEmbeddedFields() {
104
- return this.getFields().filter(field => field.isEmbedded());
105
- }
106
-
107
- getOnDeleteFields() {
108
- return this.getFields().filter(field => Boolean(field.getDataRef()) && Boolean(field.getOnDelete()));
109
- }
110
-
111
- getSelectFields() {
112
- return this.getFields().filter(field => field.isReadable());
113
- }
114
-
115
- getCountableFields() {
116
- return this.getSelectFields().filter(field => field.isArray() && field.getDataRef());
117
- }
118
-
119
- getPersistableFields() {
120
- return this.getFields().filter(field => field.isPersistable());
121
- }
122
-
123
- // Misc
124
- getIndexes() {
125
- return this.getDirectives('index').map((d) => {
126
- return Object.entries(d.getArgs()).reduce((prev, [key, value]) => {
127
- if (key === 'on') {
128
- // Convert "on" field to key
129
- value = value.map((el) => {
130
- const field = this.getField(el);
131
- if (!field) throw new Error(`Cannot create index on ${this}; Unknown fieldName '${el}'`);
132
- return field.getKey();
133
- });
134
- }
135
-
136
- return Object.assign(prev, { [key]: value });
137
- }, {});
138
- });
139
- }
140
-
141
- finalize() {
142
- this.fields.forEach(field => field.finalize());
143
- return this;
144
- }
145
- };
@@ -1,291 +0,0 @@
1
- const { get } = require('lodash');
2
- const { Kind } = require('graphql');
3
- const { nvl, uvl } = require('../../service/app.service');
4
- const { mergeAST } = require('../../service/graphql.service');
5
-
6
- const operations = ['Query', 'Mutation', 'Subscription'];
7
- const modelKinds = [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION, Kind.INTERFACE_TYPE_DEFINITION, Kind.INTERFACE_TYPE_EXTENSION];
8
- const inputKinds = [Kind.INPUT_OBJECT_TYPE_DEFINITION, Kind.INPUT_OBJECT_TYPE_EXTENSION];
9
- const scalarKinds = [Kind.SCALAR_TYPE_DEFINITION, Kind.SCALAR_TYPE_EXTENSION];
10
- const enumKinds = [Kind.ENUM_TYPE_DEFINITION, Kind.ENUM_TYPE_EXTENSION];
11
-
12
- module.exports = class Node {
13
- constructor(astLike, nodeType) {
14
- this.ast = mergeAST(astLike);
15
- this.arguments = (this.ast.arguments || []).map(el => new Node(el));
16
- this.directives = (this.ast.directives || []).map(el => new Node(el));
17
- this.toString = () => this.getName();
18
- this.nodeType = nodeType;
19
- this.name = get(this.ast, 'name.value');
20
- }
21
-
22
- // Basic AST Methods
23
- getAST() {
24
- return this.ast;
25
- }
26
-
27
- getKind() {
28
- return this.ast.kind;
29
- }
30
-
31
- getName() {
32
- return this.name;
33
- }
34
-
35
- getValue(ast = this.ast) {
36
- const { value = {} } = ast;
37
-
38
- switch (value.kind) {
39
- case Kind.NULL: return null;
40
- case Kind.LIST: return value.values.map(el => this.getValue({ value: el }));
41
- case Kind.OBJECT: {
42
- return value.fields.reduce((prev, field) => {
43
- const node = new Node(field);
44
- return Object.assign(prev, { [node.getName()]: node.getValue() });
45
- }, {});
46
- }
47
- default: {
48
- if (ast.values) return ast.values.map(v => v.name.value);
49
- return value.value;
50
- }
51
- }
52
- }
53
-
54
- getDescription() {
55
- return get(this.ast, 'description.value');
56
- }
57
-
58
- // Directive Methods
59
- getDirectives(...names) {
60
- return this.directives.filter(directive => names.indexOf(directive.getName()) > -1);
61
- }
62
-
63
- getDirective(name) {
64
- return this.directives.find(directive => directive.getName() === name);
65
- }
66
-
67
- getDirectiveArg(name, arg, defaultValue) {
68
- const directive = this.getDirective(name);
69
- if (!directive) return defaultValue;
70
- return uvl(directive.getArg(arg), defaultValue);
71
- }
72
-
73
- getDirectiveArgs(name, defaultValue) {
74
- const directive = this.getDirective(name);
75
- if (!directive) return defaultValue;
76
- return directive.getArgs();
77
- }
78
-
79
- // Argument Methods
80
- getArgs() {
81
- return this.arguments.reduce((prev, arg) => {
82
- return Object.assign(prev, { [arg.getName()]: arg.getValue() });
83
- }, {});
84
- }
85
-
86
- getArg(arg) {
87
- return this.getArgs()[arg];
88
- }
89
-
90
- getArguments() {
91
- return this.arguments;
92
- }
93
-
94
- getArgument(name) {
95
- return this.getArguments().find(arg => arg.getName() === name);
96
- }
97
-
98
- // // Framework Methods
99
- // getKey() {
100
- // switch (this.nodeType) {
101
- // case 'model': return uvl(this.getDirectiveArg('model', 'key'), this.getName());
102
- // case 'field': return uvl(this.getDirectiveArg('field', 'key'), this.getName());
103
- // default: return null;
104
- // }
105
- // }
106
-
107
- getOnDelete() {
108
- return this.getDirectiveArg('field', 'onDelete');
109
- }
110
-
111
- getDriverName() {
112
- return this.getDirectiveArg('model', 'driver', 'default');
113
- }
114
-
115
- getNamespace() {
116
- return this.getDirectiveArg('model', 'namespace', this.getName());
117
- }
118
-
119
- getVirtualRef() {
120
- return this.getDirectiveArg('join', 'by');
121
- }
122
-
123
- getAuthz() {
124
- return this.getDirectiveArg('field', 'authz', this.getDirectiveArg('model', 'authz', 'private'));
125
- }
126
-
127
- getMeta() {
128
- return this.getDirectiveArg('model', 'meta');
129
- }
130
-
131
- // Booleans
132
- isModel() {
133
- return Boolean(modelKinds.some(k => this.getKind() === k) && operations.every(o => this.getName() !== o));
134
- }
135
-
136
- isInput() {
137
- return Boolean(inputKinds.some(k => this.getKind() === k));
138
- }
139
-
140
- isScalar() {
141
- return Boolean(scalarKinds.some(k => this.getKind() === k));
142
- }
143
-
144
- isEnum() {
145
- return Boolean(enumKinds.some(k => this.getKind() === k));
146
- }
147
-
148
- isBasicType() {
149
- return this.isScalar() || this.isEnum();
150
- }
151
-
152
- /**
153
- * Is the field virtual; does it's value come from another model
154
- */
155
- isVirtual() {
156
- return Boolean(this.getDirectiveArg('join', 'by'));
157
- }
158
-
159
- /**
160
- * Is a model annotated with @model
161
- */
162
- isMarkedModel() {
163
- return Boolean(this.getDirective('model'));
164
- }
165
-
166
- /**
167
- * Is the model ready, willing, and able to communicate with external data
168
- */
169
- isEntity() {
170
- return Boolean(this.getDALScope() !== '' && !this.isEmbedded());
171
- }
172
-
173
- /**
174
- * Can this be persisted to the db
175
- */
176
- isPersistable() {
177
- return uvl(this.getDirectiveArg('field', 'persist'), this.getDirectiveArg('model', 'persist'), true);
178
- }
179
-
180
- /**
181
- * Is this embedded in another document
182
- */
183
- isEmbedded() {
184
- switch (this.nodeType) {
185
- case 'model': return Boolean(this.getDirectiveArg('model', 'embed')); // Must be marked; otherwise no way to contain the API traversal
186
- case 'field': {
187
- const model = this.getModelRef();
188
- return Boolean(!this.isReference() && model && !model.isEntity());
189
- }
190
- default: return false;
191
- }
192
- }
193
-
194
- /**
195
- * Define it's behavior at the Data Access Layer
196
- *
197
- * Model + Field:
198
- * C: Can be created (Resolver should throw. NOT the same meaning as persisted)
199
- * R: Can be read (if not must be stripped out)
200
- * U: Can be updated (if not must be stripped out)
201
- * D: Can be deleted (if not must be stripped out)
202
- */
203
- getDALScope() {
204
- switch (this.nodeType) {
205
- case 'model': {
206
- if (!this.isMarkedModel()) return '';
207
- return nvl(uvl(this.getDirectiveArg('model', 'dalScope'), 'crud'), '');
208
- }
209
- case 'field': return nvl(uvl(this.getDirectiveArg('field', 'dalScope'), 'crud'), '');
210
- default: return '';
211
- }
212
- }
213
-
214
- hasDALScope(...els) {
215
- return els.some(el => Boolean(this.getDALScope().toLowerCase().indexOf(el.toLowerCase()) > -1));
216
- }
217
-
218
- /**
219
- * Define it's behavior in the GraphQL API
220
- *
221
- * Model:
222
- * C: Generate createModel Mutation
223
- * R: Generate get|find|count Queries
224
- * U: Generate updateModel Mutation
225
- * D: Generate deleteModel Mutation
226
- * Field:
227
- * C: Include this field in InputCreate
228
- * R: Include my value in the results (strip it out beforehand)
229
- * U: Include this field in InputUpdate
230
- * D: Allow the API to delete (null out)
231
- */
232
- getGQLScope() {
233
- switch (this.nodeType) {
234
- case 'model': {
235
- if (!this.isMarkedModel()) return '';
236
- return nvl(uvl(this.getDirectiveArg('model', 'gqlScope'), 'cruds'), '');
237
- }
238
- case 'field': return nvl(uvl(this.getDirectiveArg('field', 'gqlScope'), 'cruds'), '');
239
- default: return '';
240
- }
241
- }
242
-
243
- hasGQLScope(...els) {
244
- if (this.nodeType === 'field') {
245
- const model = this.getModelRef();
246
- if (model && !model.hasFieldScope(...els)) return false;
247
- }
248
-
249
- return els.some(el => Boolean(this.getGQLScope().toLowerCase().indexOf(el.toLowerCase()) > -1));
250
- }
251
-
252
- getFieldScope() {
253
- switch (this.nodeType) {
254
- case 'model': return nvl(uvl(this.getDirectiveArg('model', 'fieldScope'), 'crud'), '');
255
- case 'field': return nvl(uvl(this.getDirectiveArg('field', 'fieldScope'), 'crud'), '');
256
- default: return '';
257
- }
258
- }
259
-
260
- hasFieldScope(...els) {
261
- return els.some(el => Boolean(this.getFieldScope().toLowerCase().indexOf(el.toLowerCase()) > -1));
262
- }
263
-
264
- /**
265
- * Does the field have an explicit "resolve" set
266
- */
267
- hasResolver() {
268
- return Boolean(this.getDirectiveArg('field', 'resolve'));
269
- }
270
-
271
-
272
- // Create
273
- isCreatable() {
274
- return Boolean(this.getDALScope().toLowerCase().indexOf('c') > -1);
275
- }
276
-
277
- // Read
278
- isReadable() {
279
- return Boolean(this.getDALScope().toLowerCase().indexOf('r') > -1);
280
- }
281
-
282
- // Update
283
- isUpdatable() {
284
- return Boolean(this.getDALScope().toLowerCase().indexOf('u') > -1);
285
- }
286
-
287
- // Delete
288
- isDeletable() {
289
- return Boolean(this.getDALScope().toLowerCase().indexOf('d') > -1);
290
- }
291
- };