@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,133 +0,0 @@
1
- const FS = require('fs');
2
- const Glob = require('glob');
3
- const Merge = require('deepmerge');
4
- const { Kind, print, parse, visit } = require('graphql');
5
- const { mergeASTArray } = require('../../service/graphql.service');
6
- const { deleteKeys } = require('../../service/app.service');
7
- const frameworkExt = require('../extension/framework');
8
- const typeExt = require('../extension/type');
9
- const apiExt = require('../extension/api');
10
- const TypeDefApi = require('./TypeDefApi');
11
- const Node = require('./Node');
12
-
13
- /**
14
- * Schema
15
- *
16
- * This class helps facilitate dynamic modification of a schema before it is passed to makeExecutableSchema(). It allows
17
- * for "intelligent" merging of schemas and exposes an API wrapper for typeDefs.
18
- *
19
- * A "schema" is defined by the following object attributes:
20
- *
21
- * typeDefs <String|Object> - GQL String or AST Object (also supports a mixed array of both)
22
- * resolvers <Object> - GraphQL resolvers
23
- * schemaDirectives <Object> - GraphQL directives
24
- *
25
- */
26
- module.exports = class Schema extends TypeDefApi {
27
- constructor(schema) {
28
- super();
29
- this.schema = { typeDefs: [], resolvers: {}, schemaDirectives: {} };
30
- if (schema) this.mergeSchema(schema);
31
- }
32
-
33
- /**
34
- * Synchronously merge a schema
35
- */
36
- mergeSchema(schema, options = {}) {
37
- // Ensure this is a schema of sorts otherwise skip it
38
- if (typeof schema !== 'string' && ['typeDefs', 'resolvers', 'schemaDirectives'].every(key => !schema[key])) return this;
39
-
40
- // Here we want to normalize the schema into the shape { typeDefs, resolvers, schemaDirectives }
41
- // We do NOT want to modify the schema object because that may cause unwanted side-effects.
42
- const normalizedSchema = { ...schema };
43
- if (typeof schema === 'string') normalizedSchema.typeDefs = [schema];
44
- else if (schema.typeDefs && !Array.isArray(schema.typeDefs)) normalizedSchema.typeDefs = [schema.typeDefs];
45
-
46
- // For typeDefs we want the AST so that it can be intelligently merged. Here we convert
47
- // GQL strings to AST objects and also filter out anything that does not parse to AST.
48
- if (normalizedSchema.typeDefs && normalizedSchema.typeDefs.length) {
49
- normalizedSchema.typeDefs = deleteKeys(normalizedSchema.typeDefs.map((td) => {
50
- try {
51
- const ast = typeof td === 'object' ? td : parse(td);
52
- return ast.definitions;
53
- } catch (e) {
54
- return null;
55
- }
56
- }), ['loc']).filter(Boolean).flat();
57
- }
58
-
59
- // Now we're ready to merge the schema
60
- const [left, right] = options.passive ? [normalizedSchema, this.schema] : [this.schema, normalizedSchema];
61
- if (normalizedSchema.typeDefs && normalizedSchema.typeDefs.length) this.schema.typeDefs = mergeASTArray(left.typeDefs.concat(right.typeDefs));
62
- if (normalizedSchema.resolvers) this.schema.resolvers = Merge(left.resolvers, right.resolvers);
63
- if (normalizedSchema.schemaDirectives) this.schema.schemaDirectives = Merge(left.schemaDirectives, right.schemaDirectives);
64
-
65
- // Chaining
66
- return this;
67
- }
68
-
69
- /**
70
- * Asynchronously load files from a given glob pattern and merge each schema
71
- */
72
- mergeSchemaFromFiles(globPattern, options) {
73
- return new Promise((resolve, reject) => {
74
- Glob(globPattern, options, (err, files) => {
75
- if (err) return reject(err);
76
-
77
- return Promise.all(files.map((file) => {
78
- return new Promise((res) => {
79
- if (file.endsWith('.js')) res(require(file)); // eslint-disable-line global-require,import/no-dynamic-require
80
- else res(FS.readFileSync(file, 'utf8'));
81
- }).then(schema => this.mergeSchema(schema, options));
82
- })).then(() => resolve(this)).catch(e => reject(e));
83
- });
84
- });
85
- }
86
-
87
- /**
88
- * Traverses the current schema's typeDefs in order to keep the TypeDefApi in sync. This operation
89
- * only needs to be called when typeDefs have been changed and you want to keep the data model in sync.
90
- */
91
- initialize() {
92
- super.initialize(this.schema.typeDefs);
93
- return this;
94
- }
95
-
96
- /**
97
- * Decorate the schema with Autograph's default api/definitions
98
- */
99
- decorate() {
100
- this.initialize();
101
- this.mergeSchema(frameworkExt(this), { passive: true });
102
- this.mergeSchema(typeExt(this), { passive: true });
103
- this.initialize();
104
- this.mergeSchema(apiExt(this), { passive: true });
105
- this.finalize();
106
- return this;
107
- }
108
-
109
- /**
110
- * This should be called once before passing to makeExecutableSchema()
111
- */
112
- finalize() {
113
- const definitions = visit(this.schema.typeDefs, {
114
- [Kind.FIELD_DEFINITION]: (node) => {
115
- const scope = new Node(node, 'field').getDirectiveArg('field', 'gqlScope', 'crud');
116
- if (scope === null || scope.indexOf('r') === -1) return null; // Delete node
117
- return false; // Stop traversing this node
118
- },
119
- });
120
-
121
- this.getModels().forEach(model => model.finalize());
122
- this.schema.typeDefs = { kind: Kind.DOCUMENT, definitions };
123
- return this;
124
- }
125
-
126
- toObject() {
127
- return this.schema;
128
- }
129
-
130
- toString() {
131
- return print(this.schema.typeDefs);
132
- }
133
- };
@@ -1,26 +0,0 @@
1
- const Node = require('./Node');
2
- const { getTypeInfo } = require('../../service/graphql.service');
3
-
4
- const scalars = ['ID', 'String', 'Float', 'Int', 'Boolean'];
5
-
6
- module.exports = class Type extends Node {
7
- getName() {
8
- return getTypeInfo(this.ast).name;
9
- }
10
-
11
- isArray() {
12
- return Boolean(getTypeInfo(this.ast).isArray);
13
- }
14
-
15
- isRequired(debug) {
16
- return Boolean(getTypeInfo(this.ast, {}, false).isRequired);
17
- }
18
-
19
- isArrayElementRequired() {
20
- return this.isArray() && Boolean(getTypeInfo(this.ast.type).isRequired);
21
- }
22
-
23
- isScalar() {
24
- return scalars.indexOf(this.getName()) > -1;
25
- }
26
- };
@@ -1,93 +0,0 @@
1
- const { Kind, visit } = require('graphql');
2
- const Model = require('./Model');
3
- const Node = require('./Node');
4
-
5
- const operations = ['Query', 'Mutation', 'Subscription'];
6
- const modelKinds = [Kind.OBJECT_TYPE_DEFINITION, Kind.OBJECT_TYPE_EXTENSION, Kind.INTERFACE_TYPE_DEFINITION, Kind.INTERFACE_TYPE_EXTENSION];
7
- const inputKinds = [Kind.INPUT_OBJECT_TYPE_DEFINITION, Kind.INPUT_OBJECT_TYPE_EXTENSION];
8
- const scalarKinds = [Kind.SCALAR_TYPE_DEFINITION, Kind.SCALAR_TYPE_EXTENSION];
9
- const enumKinds = [Kind.ENUM_TYPE_DEFINITION, Kind.ENUM_TYPE_EXTENSION];
10
-
11
- module.exports = class TypeDefApi {
12
- constructor() {
13
- this.models = [];
14
- this.scalars = [];
15
- this.inputs = [];
16
- this.enums = [];
17
- }
18
-
19
- initialize(typeDefs) {
20
- this.models.length = 0;
21
- this.scalars.length = 0;
22
- this.inputs.length = 0;
23
- this.enums.length = 0;
24
-
25
- visit(typeDefs, {
26
- enter: (node) => {
27
- if (modelKinds.indexOf(node.kind) > -1 && operations.indexOf(node.name.value) === -1) {
28
- this.models.push(new Model(this, node));
29
- } else if (scalarKinds.indexOf(node.kind) > -1) {
30
- this.scalars.push(new Node(node));
31
- } else if (inputKinds.indexOf(node.kind) > -1) {
32
- this.inputs.push(new Node(node));
33
- } else if (enumKinds.indexOf(node.kind) > -1) {
34
- this.enums.push(new Node(node));
35
- }
36
-
37
- return false; // Stop traversing this node
38
- },
39
- });
40
-
41
- return this;
42
- }
43
-
44
- // Models
45
- getModel(name) {
46
- return this.models.find(m => m.getName() === name);
47
- }
48
-
49
- getModels() {
50
- return this.models;
51
- }
52
-
53
- getModelNames() {
54
- return this.getModels().map(model => model.getName());
55
- }
56
-
57
- getModelMap() {
58
- return this.getModels().reduce((prev, model) => Object.assign(prev, { [model.getName()]: model }), {});
59
- }
60
-
61
- getMarkedModels() {
62
- return Object.values(this.models).filter(model => model.isMarkedModel());
63
- }
64
-
65
- getEntityModels() {
66
- return Object.values(this.models).filter(model => model.isEntity());
67
- }
68
-
69
- // Definitions
70
- getInput(name) {
71
- return this.getInputs().find(input => input.getName() === name);
72
- }
73
-
74
- getInputs() {
75
- return this.inputs;
76
- }
77
-
78
- getScalar(name) {
79
- return this.getScalars().find(scalar => scalar.getName() === name);
80
- }
81
-
82
- getScalars() {
83
- return this.scalars;
84
- }
85
-
86
- getEnum(name) {
87
- return this.getEnums().find(el => el.getName() === name);
88
- }
89
-
90
- getEnums() {
91
- return this.enums;
92
- }
93
- };
Binary file
@@ -1,193 +0,0 @@
1
- const { get } = require('lodash');
2
- const { Kind } = require('graphql');
3
- const ServerResolver = require('../../core/ServerResolver');
4
- const { ucFirst, toGUID, fromGUID } = require('../../service/app.service');
5
- const { findGQLModels } = require('../../service/schema.service');
6
- const { makeCreateAPI, makeReadAPI, makeUpdateAPI, makeDeleteAPI, makeSubscriptionAPI, makeQueryResolver, makeMutationResolver } = require('../../service/decorator.service');
7
-
8
- const interfaceKinds = [Kind.INTERFACE_TYPE_DEFINITION, Kind.INTERFACE_TYPE_EXTENSION];
9
-
10
- const getGQLWhereFields = (model) => {
11
- return model.getFields().filter((field) => {
12
- if (!field.hasGQLScope('r')) return false;
13
- const modelRef = field.getModelRef();
14
- if (modelRef && !modelRef.isEmbedded() && !modelRef.isEntity()) return false;
15
- return true;
16
- });
17
- };
18
-
19
- module.exports = (schema) => {
20
- const resolver = new ServerResolver();
21
- const allModels = schema.getModels();
22
- const entityModels = schema.getEntityModels();
23
- const markedModels = schema.getMarkedModels();
24
- const createModels = findGQLModels('c', markedModels, allModels);
25
- const readModels = findGQLModels('r', markedModels, allModels);
26
- const updateModels = findGQLModels('u', markedModels, allModels);
27
-
28
- return ({
29
- typeDefs: [
30
- ...createModels.map(model => `
31
- input ${model.getName()}InputCreate {
32
- ${model.getFields().filter(field => field.hasGQLScope('c') && !field.isVirtual()).map(field => `${field.getName()}: ${field.getGQLType('InputCreate')}`)}
33
- }
34
- `),
35
-
36
- ...updateModels.map(model => `
37
- input ${model.getName()}InputUpdate {
38
- ${model.getFields().filter(field => field.hasGQLScope('u') && !field.isVirtual()).map(field => `${field.getName()}: ${field.getGQLType('InputUpdate')}`)}
39
- }
40
- `),
41
-
42
- ...readModels.map(model => `
43
- input ${model.getName()}InputWhere {
44
- ${getGQLWhereFields(model).map(field => `${field.getName()}: ${field.getModelRef() ? `${ucFirst(field.getDataRef())}InputWhere` : 'AutoGraphMixed'}`)}
45
- }
46
- input ${model.getName()}InputSort {
47
- ${getGQLWhereFields(model).map(field => `${field.getName()}: ${field.getModelRef() ? `${ucFirst(field.getDataRef())}InputSort` : 'SortOrderEnum'}`)}
48
- }
49
- extend ${interfaceKinds.indexOf(model.getKind()) > -1 ? 'interface' : 'type'} ${model.getName()} {
50
- ${model.getFields().filter(field => field.hasGQLScope('r')).map(field => `${field.getName()}${field.getExtendArgs()}: ${field.getPayloadType()}`)}
51
- }
52
- type ${model.getName()}Connection {
53
- count: Int!
54
- pageInfo: PageInfo!
55
- edges: [${model.getName()}Edge]
56
- }
57
- type ${model.getName()}Edge {
58
- node: ${model.getName()}
59
- cursor: String!
60
- }
61
- `),
62
-
63
- ...entityModels.filter(model => model.hasGQLScope('s')).map(model => `
64
- input ${model.getName()}SubscriptionInputFilter {
65
- when: [SubscriptionWhenEnum!]! = [preEvent, postEvent]
66
- where: ${model.getName()}SubscriptionInputWhere! = {}
67
- }
68
-
69
- input ${model.getName()}SubscriptionInputWhere {
70
- ${getGQLWhereFields(model).map(field => `${field.getName()}: ${field.getModelRef() && !field.isFKReference() ? `${ucFirst(field.getDataRef())}InputWhere` : 'AutoGraphMixed'}`)}
71
- }
72
-
73
- type ${model.getName()}SubscriptionPayload {
74
- event: ${model.getName()}SubscriptionPayloadEvent
75
- query: ${model.getName()}SubscriptionQuery
76
- }
77
-
78
- type ${model.getName()}SubscriptionPayloadEvent {
79
- crud: SubscriptionCrudEnum!
80
- data: ${model.getName()}SubscriptionPayloadEventData!
81
- }
82
-
83
- type ${model.getName()}SubscriptionPayloadEventData {
84
- ${getGQLWhereFields(model).map(field => `${field.getName()}: ${field.getSubscriptionType()}`)}
85
- }
86
-
87
- interface ${model.getName()}SubscriptionQuery {
88
- ${model.getFields().filter(field => field.hasGQLScope('r')).map(field => `${field.getName()}: ${field.getPayloadType()}`)}
89
- }
90
-
91
- type ${model.getName()}Create implements ${model.getName()}SubscriptionQuery {
92
- ${model.getFields().filter(field => field.hasGQLScope('r')).map(field => `${field.getName()}: ${field.getPayloadType()}`)}
93
- }
94
-
95
- type ${model.getName()}Update implements ${model.getName()}SubscriptionQuery {
96
- ${model.getFields().filter(field => field.hasGQLScope('r')).map(field => `${field.getName()}: ${field.getPayloadType()}`)}
97
- }
98
- `),
99
- ].concat([
100
- `type PageInfo {
101
- startCursor: String!
102
- endCursor: String!
103
- hasPreviousPage: Boolean!
104
- hasNextPage: Boolean!
105
- }`,
106
-
107
- `type Query {
108
- node(id: ID!): Node
109
- ${entityModels.map(model => makeReadAPI(model.getName(), model))}
110
- }`,
111
-
112
- `type Mutation {
113
- _noop: String
114
- ${entityModels.map(model => makeCreateAPI(model.getName(), model))}
115
- ${entityModels.map(model => makeUpdateAPI(model.getName(), model))}
116
- ${entityModels.map(model => makeDeleteAPI(model.getName(), model))}
117
- }`,
118
-
119
- `type Subscription {
120
- _noop: String
121
- ${entityModels.map(model => makeSubscriptionAPI(model.getName(), model))}
122
- }`,
123
- ]),
124
- resolvers: readModels.reduce((prev, model) => {
125
- const modelName = model.getName();
126
-
127
- // Default field resolvers
128
- const fieldResolvers = model.getFields().filter(field => field.hasGQLScope('r')).reduce((def, field) => {
129
- const fieldName = field.getName();
130
- const isConnection = field.isConnection();
131
-
132
- return Object.assign(def, {
133
- [fieldName]: (doc, args, { autograph }, info) => {
134
- if (fieldName === 'id') return autograph.legacyMode ? doc.id : toGUID(modelName, doc.id);
135
-
136
- // If this field is a connection we return thunks in order to delay query
137
- // until the "Connection" resolver (below) is run
138
- if (isConnection) {
139
- return {
140
- count: () => field.count(autograph.resolver, doc, args),
141
- edges: () => field.resolve(autograph.resolver, doc, args),
142
- pageInfo: () => field.resolve(autograph.resolver, doc, args),
143
- };
144
- }
145
-
146
- return field.resolve(autograph.resolver, doc, args);
147
- },
148
- });
149
- }, {});
150
-
151
- if (model.isEntity() && model.hasGQLScope('s')) {
152
- prev[`${model.getName()}SubscriptionQuery`] = {
153
- __resolveType: root => root.__typename, // eslint-disable-line no-underscore-dangle
154
- ...fieldResolvers,
155
- };
156
- prev[`${model.getName()}Create`] = fieldResolvers;
157
- prev[`${model.getName()}Update`] = fieldResolvers;
158
- }
159
-
160
- return Object.assign(prev, {
161
- [modelName]: fieldResolvers,
162
- [`${modelName}Connection`]: {
163
- count: ({ count }) => count(),
164
- edges: ({ edges }) => edges().then(rs => rs.map(node => ({ cursor: get(node, '$cursor'), node }))),
165
- pageInfo: ({ pageInfo }) => pageInfo().then(rs => get(rs, '$pageInfo')),
166
- },
167
- });
168
- }, {
169
- Node: {
170
- __resolveType: (doc, args, context, info) => doc.__typename, // eslint-disable-line no-underscore-dangle
171
- },
172
-
173
- Query: entityModels.reduce((prev, model) => {
174
- return Object.assign(prev, makeQueryResolver(model.getName(), model, resolver));
175
- }, {
176
- node: (doc, args, context, info) => {
177
- const { id } = args;
178
- const [modelName] = fromGUID(id);
179
- const model = schema.getModel(modelName);
180
- return resolver.get(context, model, args, false, info).then((result) => {
181
- if (result == null) return result;
182
- result.__typename = modelName; // eslint-disable-line no-underscore-dangle
183
- return result;
184
- });
185
- },
186
- }),
187
-
188
- Mutation: entityModels.reduce((prev, model) => {
189
- return Object.assign(prev, makeMutationResolver(model.getName(), model, resolver));
190
- }, {}),
191
- }),
192
- });
193
- };
@@ -1,71 +0,0 @@
1
- const Pipeline = require('../../data/Pipeline');
2
-
3
- Pipeline.createPresets();
4
-
5
- module.exports = (schema) => {
6
- return {
7
- typeDefs: `
8
- scalar AutoGraphMixed
9
- scalar AutoGraphDriver
10
- scalar AutoGraphDateTime @field(transform: toDate)
11
- enum AutoGraphPipelineEnum { ${Object.keys(Pipeline).join(' ')} }
12
- enum AutoGraphAuthzEnum { private protected public }
13
- enum AutoGraphOnDeleteEnum { cascade nullify restrict defer }
14
- enum AutoGraphIndexEnum { unique }
15
-
16
- directive @model(
17
- id: String # Specify db key (default "id")
18
- key: String # Specify db table/collection name
19
- driver: AutoGraphDriver # External data driver
20
- createdAt: String # Specify db key (default "createdAt")
21
- updatedAt: String # Specify db key (default "updatedAt")
22
- meta: AutoGraphMixed # Custom input "meta" field for mutations
23
- embed: Boolean # Mark this an embedded model (default false)
24
- persist: Boolean # Persist this model (default true)
25
- gqlScope: AutoGraphMixed # Dictate how GraphQL API behaves
26
- dalScope: AutoGraphMixed # Dictate how the DAL behaves
27
- fieldScope: AutoGraphMixed # Dictate how a FIELD may use me
28
- authz: AutoGraphAuthzEnum # Access level used for authorization (default: private)
29
- namespace: String # Logical grouping of models that can be globbed (useful for authz)
30
- ) on OBJECT | INTERFACE
31
-
32
- directive @field(
33
- id: String # Specify the ModelRef this field FK References
34
- ref: AutoGraphMixed # Specify the modelRef field's name (overrides isEmbedded)
35
- key: String # Specify db key
36
- persist: Boolean # Persist this field (default true)
37
- connection: Boolean # Treat this field as a connection type (default false - rolling this out slowly)
38
- default: AutoGraphMixed # Define a default value
39
- gqlScope: AutoGraphMixed # Dictate how GraphQL API behaves
40
- dalScope: AutoGraphMixed # Dictate how the DAL behaves
41
- fieldScope: AutoGraphMixed # Dictate how a FIELD may use me
42
- onDelete: AutoGraphOnDeleteEnum # onDelete behavior
43
-
44
- authz: AutoGraphAuthzEnum # Access level used for authorization (default: private)
45
-
46
- # Pipeline Structure
47
- validate: [AutoGraphPipelineEnum!]
48
- construct: [AutoGraphPipelineEnum!]
49
- restruct: [AutoGraphPipelineEnum!]
50
- destruct: [AutoGraphPipelineEnum!]
51
- instruct: [AutoGraphPipelineEnum!]
52
- normalize: [AutoGraphPipelineEnum!]
53
- transform: [AutoGraphPipelineEnum!]
54
- serialize: [AutoGraphPipelineEnum!]
55
- deserialize: [AutoGraphPipelineEnum!]
56
- ) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | SCALAR
57
-
58
- directive @join(
59
- to: AutoGraphMixed # The MODEL to join to (default's to modelRef)
60
- by: AutoGraphMixed! # The FIELD to match yourself by
61
- use: AutoGraphMixed # The VALUE to use (default's to @join'd value); useful for many-to-many relationships
62
- ) on FIELD_DEFINITION
63
-
64
- directive @index(
65
- name: String
66
- on: [AutoGraphMixed!]!
67
- type: AutoGraphIndexEnum!
68
- ) repeatable on OBJECT
69
- `,
70
- };
71
- };
@@ -1,34 +0,0 @@
1
- /**
2
- * Decorate Entity Models
3
- */
4
- module.exports = (schema) => {
5
- return ({
6
- typeDefs: schema.getMarkedModels().map((model) => {
7
- const id = model.idKey();
8
- const modelName = model.getName();
9
- const createdAt = model.getDirectiveArg('model', 'createdAt', 'createdAt');
10
- const updatedAt = model.getDirectiveArg('model', 'updatedAt', 'updatedAt');
11
-
12
- if (model.getKind() === 'ObjectTypeDefinition' && (id || createdAt || updatedAt)) {
13
- const interfaces = [];
14
- if (id) interfaces.push('Node');
15
- const interfacesGQL = interfaces.length ? ' implements'.concat(' ', interfaces.join(' & ')) : '';
16
-
17
- return `
18
- extend type ${modelName}${interfacesGQL} {
19
- ${id ? `id: ID! @field(key: "${id}", gqlScope: r)` : ''}
20
- ${createdAt ? `createdAt: AutoGraphDateTime @field(key: "${createdAt}", construct: createdAt, gqlScope: r)` : ''}
21
- ${updatedAt ? `updatedAt: AutoGraphDateTime @field(key: "${updatedAt}", serialize: timestamp, gqlScope: r)` : ''}
22
- }
23
- `;
24
- }
25
-
26
- return '';
27
- }).concat(`
28
- interface Node { id: ID! }
29
- enum SortOrderEnum { asc desc }
30
- enum SubscriptionCrudEnum { create update delete } # Not going to support "read"
31
- enum SubscriptionWhenEnum { preEvent postEvent }
32
- `),
33
- });
34
- };
Binary file
@@ -1,26 +0,0 @@
1
- const QueryBuilder = require('./QueryBuilder');
2
-
3
- module.exports = class QueryBuilderTransaction extends QueryBuilder {
4
- constructor(resolver, model, transaction) {
5
- super(resolver, model);
6
- this.query.transaction(transaction);
7
- }
8
-
9
- execute(cmd, args) {
10
- return new Promise((resolve, reject) => {
11
- this.theCall = { cmd, args, resolve, reject };
12
- });
13
- }
14
-
15
- exec(options) {
16
- if (!this.theCall) return undefined;
17
-
18
- const { cmd, args, resolve } = this.theCall;
19
- this.query.options(options);
20
-
21
- return super.execute(cmd, args).then((result) => {
22
- resolve(result);
23
- return result;
24
- });
25
- }
26
- };