@wundergraph/composition 0.0.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.
- package/LICENSE +18 -0
- package/README.md +3 -0
- package/dist/ast/ast.d.ts +84 -0
- package/dist/ast/ast.js +183 -0
- package/dist/ast/ast.js.map +1 -0
- package/dist/ast/utils.d.ts +130 -0
- package/dist/ast/utils.js +298 -0
- package/dist/ast/utils.js.map +1 -0
- package/dist/buildASTSchema/buildASTSchema.d.ts +22 -0
- package/dist/buildASTSchema/buildASTSchema.js +59 -0
- package/dist/buildASTSchema/buildASTSchema.js.map +1 -0
- package/dist/buildASTSchema/extendSchema.d.ts +21 -0
- package/dist/buildASTSchema/extendSchema.js +555 -0
- package/dist/buildASTSchema/extendSchema.js.map +1 -0
- package/dist/errors/errors.d.ts +60 -0
- package/dist/errors/errors.js +302 -0
- package/dist/errors/errors.js.map +1 -0
- package/dist/federation/federation-factory.d.ts +58 -0
- package/dist/federation/federation-factory.js +843 -0
- package/dist/federation/federation-factory.js.map +1 -0
- package/dist/federation/federation-result.d.ts +6 -0
- package/dist/federation/federation-result.js +10 -0
- package/dist/federation/federation-result.js.map +1 -0
- package/dist/federation/subgraph.d.ts +18 -0
- package/dist/federation/subgraph.js +305 -0
- package/dist/federation/subgraph.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/normalization/normalization-factory.d.ts +54 -0
- package/dist/normalization/normalization-factory.js +882 -0
- package/dist/normalization/normalization-factory.js.map +1 -0
- package/dist/normalization/utils.d.ts +121 -0
- package/dist/normalization/utils.js +278 -0
- package/dist/normalization/utils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/type-merging/type-merging.d.ts +9 -0
- package/dist/type-merging/type-merging.js +112 -0
- package/dist/type-merging/type-merging.js.map +1 -0
- package/dist/utils/constants.d.ts +6 -0
- package/dist/utils/constants.js +157 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/string-constants.d.ts +39 -0
- package/dist/utils/string-constants.js +43 -0
- package/dist/utils/string-constants.js.map +1 -0
- package/dist/utils/utils.d.ts +7 -0
- package/dist/utils/utils.js +80 -0
- package/dist/utils/utils.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,882 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NormalizationFactory = exports.normalizeSubgraph = exports.normalizeSubgraphFromString = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
const utils_1 = require("../ast/utils");
|
|
6
|
+
const utils_2 = require("./utils");
|
|
7
|
+
const constants_1 = require("../utils/constants");
|
|
8
|
+
const type_merging_1 = require("../type-merging/type-merging");
|
|
9
|
+
const utils_3 = require("../utils/utils");
|
|
10
|
+
const errors_1 = require("../errors/errors");
|
|
11
|
+
const string_constants_1 = require("../utils/string-constants");
|
|
12
|
+
const buildASTSchema_1 = require("../buildASTSchema/buildASTSchema");
|
|
13
|
+
function normalizeSubgraphFromString(subgraph) {
|
|
14
|
+
let document;
|
|
15
|
+
try {
|
|
16
|
+
document = (0, graphql_1.parse)(subgraph);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
return { errors: [(0, errors_1.subgraphInvalidSyntaxError)(err)] };
|
|
20
|
+
}
|
|
21
|
+
const normalizationFactory = new NormalizationFactory();
|
|
22
|
+
return normalizationFactory.normalize(document);
|
|
23
|
+
}
|
|
24
|
+
exports.normalizeSubgraphFromString = normalizeSubgraphFromString;
|
|
25
|
+
function normalizeSubgraph(document) {
|
|
26
|
+
const normalizationFactory = new NormalizationFactory();
|
|
27
|
+
return normalizationFactory.normalize(document);
|
|
28
|
+
}
|
|
29
|
+
exports.normalizeSubgraph = normalizeSubgraph;
|
|
30
|
+
class NormalizationFactory {
|
|
31
|
+
allDirectiveDefinitions = new Map();
|
|
32
|
+
customDirectiveDefinitions = new Map();
|
|
33
|
+
errors = [];
|
|
34
|
+
entityMap = new Map();
|
|
35
|
+
operationTypeNames = new Map();
|
|
36
|
+
parents = new Map();
|
|
37
|
+
parentTypeName = '';
|
|
38
|
+
extensions = new Map();
|
|
39
|
+
isChild = false;
|
|
40
|
+
isCurrentParentExtension = false;
|
|
41
|
+
isSubgraphVersionTwo = false;
|
|
42
|
+
schemaDefinition;
|
|
43
|
+
referencedDirectives = new Set();
|
|
44
|
+
referencedTypeNames = new Set();
|
|
45
|
+
constructor() {
|
|
46
|
+
for (const baseDirectiveDefinition of constants_1.BASE_DIRECTIVE_DEFINITIONS) {
|
|
47
|
+
this.allDirectiveDefinitions.set(baseDirectiveDefinition.name.value, baseDirectiveDefinition);
|
|
48
|
+
}
|
|
49
|
+
this.schemaDefinition = {
|
|
50
|
+
directives: new Map(),
|
|
51
|
+
kind: graphql_1.Kind.SCHEMA_DEFINITION,
|
|
52
|
+
name: (0, utils_1.stringToNameNode)(string_constants_1.SCHEMA),
|
|
53
|
+
operationTypes: new Map(),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
extractDirectives(node, map) {
|
|
57
|
+
if (!node.directives) {
|
|
58
|
+
return map;
|
|
59
|
+
}
|
|
60
|
+
for (const directive of node.directives) {
|
|
61
|
+
const directiveName = directive.name.value;
|
|
62
|
+
const existingDirectives = map.get(directiveName);
|
|
63
|
+
if (existingDirectives) {
|
|
64
|
+
existingDirectives.push(directive);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
map.set(directiveName, [directive]);
|
|
68
|
+
}
|
|
69
|
+
return map;
|
|
70
|
+
}
|
|
71
|
+
extractUniqueInterfaces(node, interfaces) {
|
|
72
|
+
if (!node.interfaces) {
|
|
73
|
+
return interfaces;
|
|
74
|
+
}
|
|
75
|
+
for (const face of node.interfaces) {
|
|
76
|
+
const name = face.name.value;
|
|
77
|
+
if (interfaces.has(name)) {
|
|
78
|
+
this.errors.push(new Error(`Interface "${name}" can only be defined on type "${this.parentTypeName}" once.`)); // TODO
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
interfaces.add(name);
|
|
82
|
+
}
|
|
83
|
+
return interfaces;
|
|
84
|
+
}
|
|
85
|
+
extractUniqueUnionMembers(members, map) {
|
|
86
|
+
for (const member of members) {
|
|
87
|
+
const name = member.name.value;
|
|
88
|
+
if (map.has(name)) {
|
|
89
|
+
this.errors.push(new Error(`Member "${name} can only be defined on union "${this.parentTypeName}" once.`));
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (!constants_1.BASE_SCALARS.has(name)) {
|
|
93
|
+
this.referencedTypeNames.add(name);
|
|
94
|
+
}
|
|
95
|
+
map.set(name, member);
|
|
96
|
+
}
|
|
97
|
+
return map;
|
|
98
|
+
}
|
|
99
|
+
mergeUniqueInterfaces(extensionInterfaces, interfaces, typeName) {
|
|
100
|
+
for (const interfaceName of extensionInterfaces) {
|
|
101
|
+
if (!interfaces.has(interfaceName)) {
|
|
102
|
+
interfaces.add(interfaceName);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
this.errors.push((0, errors_1.duplicateInterfaceError)(interfaceName, typeName)); // TODO
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
mergeUniqueUnionMembers(baseUnion, extensionUnion) {
|
|
109
|
+
if (!extensionUnion) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const extensionMembers = extensionUnion.types;
|
|
113
|
+
const members = baseUnion.types;
|
|
114
|
+
const typeName = baseUnion.name.value;
|
|
115
|
+
for (const [memberName, namedTypeNode] of extensionMembers) {
|
|
116
|
+
if (!members.has(memberName)) {
|
|
117
|
+
members.set(memberName, namedTypeNode);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
this.errors.push((0, errors_1.duplicateUnionMemberError)(memberName, typeName));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
mergeDirectives(baseTypeDirectives, extension) {
|
|
124
|
+
if (!extension) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
for (const [directiveName, directives] of extension.directives) {
|
|
128
|
+
const existingDirectives = baseTypeDirectives.get(directiveName);
|
|
129
|
+
if (existingDirectives) {
|
|
130
|
+
existingDirectives.push(...directives);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
baseTypeDirectives.set(directiveName, [...directives]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
getValidatedAndNormalizedParentDirectives(parent) {
|
|
137
|
+
const parentTypeName = parent.name.value;
|
|
138
|
+
const normalizedDirectives = [];
|
|
139
|
+
for (const [directiveName, directives] of parent.directives) {
|
|
140
|
+
const definition = this.allDirectiveDefinitions.get(directiveName);
|
|
141
|
+
if (!definition) {
|
|
142
|
+
this.errors.push((0, errors_1.undefinedDirectiveError)(parentTypeName, directiveName));
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const allArguments = new Set();
|
|
146
|
+
const requiredArguments = new Set();
|
|
147
|
+
(0, utils_2.getDirectiveDefinitionArgumentSets)(definition.arguments || [], allArguments, requiredArguments);
|
|
148
|
+
const entityKeys = new Set();
|
|
149
|
+
const errorMessages = [];
|
|
150
|
+
for (const directive of directives) {
|
|
151
|
+
if (!(0, utils_2.areNodeKindAndDirectiveLocationCompatible)(parent.kind, definition)) {
|
|
152
|
+
errorMessages.push((0, errors_1.invalidDirectiveLocationErrorMessage)(parentTypeName, parent.kind, directiveName));
|
|
153
|
+
}
|
|
154
|
+
if (!definition.repeatable && directives.length > 1) {
|
|
155
|
+
errorMessages.push((0, errors_1.invalidRepeatedDirectiveErrorMessage)(directiveName, parentTypeName));
|
|
156
|
+
}
|
|
157
|
+
if (!definition.arguments || definition.arguments.length < 1) {
|
|
158
|
+
if (directive.arguments && directive.arguments.length > 0) {
|
|
159
|
+
errorMessages.push((0, errors_1.unexpectedDirectiveArgumentsErrorMessage)(directive, parentTypeName));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
normalizedDirectives.push(directive);
|
|
163
|
+
}
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (!directive.arguments || directive.arguments.length < 1) {
|
|
167
|
+
if (requiredArguments.size > 0) {
|
|
168
|
+
errorMessages.push((0, errors_1.undefinedRequiredArgumentsErrorMessage)(directiveName, parentTypeName, Array.from(requiredArguments)));
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
normalizedDirectives.push(directive);
|
|
172
|
+
}
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const definedArguments = (0, utils_2.getDefinedArgumentsForDirective)(directive.arguments, allArguments, directiveName, parentTypeName, errorMessages);
|
|
176
|
+
const missingRequiredArguments = (0, utils_3.getEntriesNotInSet)(requiredArguments, definedArguments);
|
|
177
|
+
if (missingRequiredArguments.length > 0) {
|
|
178
|
+
errorMessages.push((0, errors_1.undefinedRequiredArgumentsErrorMessage)(directiveName, parentTypeName, Array.from(requiredArguments), missingRequiredArguments));
|
|
179
|
+
}
|
|
180
|
+
// Only add unique entity keys
|
|
181
|
+
if (directiveName === string_constants_1.KEY) {
|
|
182
|
+
const directiveKind = directive.arguments[0].value.kind;
|
|
183
|
+
if (directiveKind !== graphql_1.Kind.STRING) {
|
|
184
|
+
errorMessages.push((0, errors_1.invalidKeyDirectiveArgumentErrorMessage)(directiveKind));
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const entityKey = directive.arguments[0].value.value;
|
|
188
|
+
if (entityKeys.has(entityKey)) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
entityKeys.add(entityKey);
|
|
192
|
+
}
|
|
193
|
+
normalizedDirectives.push(directive);
|
|
194
|
+
}
|
|
195
|
+
if (errorMessages.length > 0) {
|
|
196
|
+
this.errors.push((0, errors_1.invalidDirectiveError)(directiveName, parentTypeName, errorMessages));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return normalizedDirectives;
|
|
200
|
+
}
|
|
201
|
+
validateChildDirectives(child, hostPath) {
|
|
202
|
+
const childKind = child.node.kind;
|
|
203
|
+
for (const [directiveName, directives] of child.directives) {
|
|
204
|
+
const definition = this.allDirectiveDefinitions.get(directiveName);
|
|
205
|
+
if (!definition) {
|
|
206
|
+
this.errors.push((0, errors_1.undefinedDirectiveError)(hostPath, directiveName));
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const allArguments = new Set();
|
|
210
|
+
const requiredArguments = new Set();
|
|
211
|
+
(0, utils_2.getDirectiveDefinitionArgumentSets)(definition.arguments || [], allArguments, requiredArguments);
|
|
212
|
+
const errorMessages = [];
|
|
213
|
+
for (const directive of directives) {
|
|
214
|
+
if (!(0, utils_2.areNodeKindAndDirectiveLocationCompatible)(childKind, definition)) {
|
|
215
|
+
errorMessages.push((0, errors_1.invalidDirectiveLocationErrorMessage)(hostPath, childKind, directiveName));
|
|
216
|
+
}
|
|
217
|
+
if (!definition.repeatable && directives.length > 1) {
|
|
218
|
+
errorMessages.push((0, errors_1.invalidRepeatedDirectiveErrorMessage)(directiveName, hostPath));
|
|
219
|
+
}
|
|
220
|
+
if (!definition.arguments || definition.arguments.length < 1) {
|
|
221
|
+
if (directive.arguments && directive.arguments.length > 0) {
|
|
222
|
+
errorMessages.push((0, errors_1.unexpectedDirectiveArgumentsErrorMessage)(directive, hostPath));
|
|
223
|
+
}
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (!directive.arguments || directive.arguments.length < 1) {
|
|
227
|
+
if (requiredArguments.size > 0) {
|
|
228
|
+
errorMessages.push((0, errors_1.undefinedRequiredArgumentsErrorMessage)(directiveName, hostPath, Array.from(requiredArguments)));
|
|
229
|
+
}
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const definedArguments = (0, utils_2.getDefinedArgumentsForDirective)(directive.arguments, allArguments, directiveName, hostPath, errorMessages);
|
|
233
|
+
const missingRequiredArguments = (0, utils_3.getEntriesNotInSet)(requiredArguments, definedArguments);
|
|
234
|
+
if (missingRequiredArguments.length > 0) {
|
|
235
|
+
errorMessages.push((0, errors_1.undefinedRequiredArgumentsErrorMessage)(directiveName, hostPath, Array.from(requiredArguments), missingRequiredArguments));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (errorMessages.length > 0) {
|
|
239
|
+
this.errors.push((0, errors_1.invalidDirectiveError)(directiveName, hostPath, errorMessages));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
normalize(document) {
|
|
244
|
+
const factory = this;
|
|
245
|
+
(0, graphql_1.visit)(document, {
|
|
246
|
+
DirectiveDefinition: {
|
|
247
|
+
enter(node) {
|
|
248
|
+
const name = node.name.value;
|
|
249
|
+
// TODO These sets would potentially allow the user to define these directives more than once
|
|
250
|
+
// Add our definitions rather than the existing ones
|
|
251
|
+
if (constants_1.VERSION_TWO_DIRECTIVES.has(name)) {
|
|
252
|
+
factory.isSubgraphVersionTwo = true;
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
if (constants_1.VERSION_ONE_DIRECTIVES.has(name)) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
const directiveDefinition = factory.allDirectiveDefinitions.get(name);
|
|
259
|
+
if (directiveDefinition) {
|
|
260
|
+
factory.errors.push((0, errors_1.duplicateDirectiveDefinitionError)(name));
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
factory.allDirectiveDefinitions.set(name, node);
|
|
264
|
+
factory.customDirectiveDefinitions.set(name, node);
|
|
265
|
+
return false;
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
Directive: {
|
|
269
|
+
enter(node) {
|
|
270
|
+
const name = node.name.value;
|
|
271
|
+
if (constants_1.VERSION_TWO_DIRECTIVES.has(name)) {
|
|
272
|
+
factory.isSubgraphVersionTwo = true;
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
if (constants_1.VERSION_ONE_DIRECTIVES.has(name)) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
factory.referencedDirectives.add(name);
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
EnumTypeDefinition: {
|
|
282
|
+
enter(node) {
|
|
283
|
+
const name = node.name.value;
|
|
284
|
+
if (factory.parents.has(name)) {
|
|
285
|
+
factory.errors.push((0, errors_1.duplicateTypeDefinitionError)('enum', name));
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
factory.parentTypeName = name;
|
|
289
|
+
factory.parents.set(name, {
|
|
290
|
+
description: node.description,
|
|
291
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
292
|
+
kind: node.kind,
|
|
293
|
+
name: node.name,
|
|
294
|
+
values: new Map(),
|
|
295
|
+
});
|
|
296
|
+
},
|
|
297
|
+
leave() {
|
|
298
|
+
factory.parentTypeName = '';
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
EnumTypeExtension: {
|
|
302
|
+
enter(node) {
|
|
303
|
+
const name = node.name.value;
|
|
304
|
+
factory.parentTypeName = name;
|
|
305
|
+
factory.isCurrentParentExtension = true;
|
|
306
|
+
const extension = factory.extensions.get(factory.parentTypeName);
|
|
307
|
+
if (extension) {
|
|
308
|
+
if (extension.kind !== graphql_1.Kind.ENUM_TYPE_EXTENSION) {
|
|
309
|
+
factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
factory.extractDirectives(node, extension.directives);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
factory.extensions.set(name, {
|
|
316
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
317
|
+
kind: node.kind,
|
|
318
|
+
name: node.name,
|
|
319
|
+
values: new Map(),
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
leave() {
|
|
323
|
+
factory.isCurrentParentExtension = false;
|
|
324
|
+
factory.parentTypeName = '';
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
EnumValueDefinition: {
|
|
328
|
+
enter(node) {
|
|
329
|
+
const name = node.name.value;
|
|
330
|
+
const parent = factory.isCurrentParentExtension
|
|
331
|
+
? (0, utils_3.getOrThrowError)(factory.extensions, factory.parentTypeName)
|
|
332
|
+
: (0, utils_3.getOrThrowError)(factory.parents, factory.parentTypeName);
|
|
333
|
+
if (parent.kind !== graphql_1.Kind.ENUM_TYPE_DEFINITION && parent.kind !== graphql_1.Kind.ENUM_TYPE_EXTENSION) {
|
|
334
|
+
throw new Error(''); // TODO
|
|
335
|
+
}
|
|
336
|
+
if (parent.values.has(name)) {
|
|
337
|
+
const error = factory.isCurrentParentExtension
|
|
338
|
+
? (0, errors_1.duplicateValueExtensionError)('enum', factory.parentTypeName, name)
|
|
339
|
+
: (0, errors_1.duplicateEnumValueDefinitionError)(name, factory.parentTypeName);
|
|
340
|
+
factory.errors.push(error);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
parent.values.set(name, {
|
|
344
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
345
|
+
name,
|
|
346
|
+
node,
|
|
347
|
+
});
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
FieldDefinition: {
|
|
351
|
+
enter(node) {
|
|
352
|
+
const name = node.name.value;
|
|
353
|
+
const fieldPath = `${factory.parentTypeName}.${name}`;
|
|
354
|
+
factory.isChild = true;
|
|
355
|
+
const fieldRootType = (0, type_merging_1.getNamedTypeForChild)(fieldPath, node.type);
|
|
356
|
+
if (!constants_1.BASE_SCALARS.has(fieldRootType)) {
|
|
357
|
+
factory.referencedTypeNames.add(fieldRootType);
|
|
358
|
+
}
|
|
359
|
+
const parent = factory.isCurrentParentExtension
|
|
360
|
+
? (0, utils_3.getOrThrowError)(factory.extensions, factory.parentTypeName)
|
|
361
|
+
: (0, utils_3.getOrThrowError)(factory.parents, factory.parentTypeName);
|
|
362
|
+
if (parent.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION &&
|
|
363
|
+
parent.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION &&
|
|
364
|
+
parent.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION &&
|
|
365
|
+
parent.kind !== graphql_1.Kind.INTERFACE_TYPE_EXTENSION) {
|
|
366
|
+
throw new Error(''); // TODO
|
|
367
|
+
}
|
|
368
|
+
if (parent.fields.has(name)) {
|
|
369
|
+
const error = factory.isCurrentParentExtension
|
|
370
|
+
? (0, errors_1.duplicateFieldExtensionError)(factory.parentTypeName, name)
|
|
371
|
+
: (0, errors_1.duplicateFieldDefinitionError)(name, factory.parentTypeName);
|
|
372
|
+
factory.errors.push(error);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
parent.fields.set(name, {
|
|
376
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
377
|
+
name,
|
|
378
|
+
node,
|
|
379
|
+
});
|
|
380
|
+
},
|
|
381
|
+
leave() {
|
|
382
|
+
factory.isChild = false;
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
InputObjectTypeDefinition: {
|
|
386
|
+
enter(node) {
|
|
387
|
+
const name = node.name.value;
|
|
388
|
+
if (factory.parents.has(name)) {
|
|
389
|
+
factory.errors.push((0, errors_1.duplicateTypeDefinitionError)('input object', name));
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
factory.parentTypeName = name;
|
|
393
|
+
factory.parents.set(name, {
|
|
394
|
+
description: node.description,
|
|
395
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
396
|
+
fields: new Map(),
|
|
397
|
+
kind: node.kind,
|
|
398
|
+
name: node.name,
|
|
399
|
+
});
|
|
400
|
+
},
|
|
401
|
+
leave() {
|
|
402
|
+
factory.parentTypeName = '';
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
InputObjectTypeExtension: {
|
|
406
|
+
enter(node) {
|
|
407
|
+
const name = node.name.value;
|
|
408
|
+
factory.parentTypeName = name;
|
|
409
|
+
factory.isCurrentParentExtension = true;
|
|
410
|
+
const extension = factory.extensions.get(factory.parentTypeName);
|
|
411
|
+
if (extension) {
|
|
412
|
+
if (extension.kind !== graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION) {
|
|
413
|
+
factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
factory.extractDirectives(node, extension.directives);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
factory.extensions.set(name, {
|
|
420
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
421
|
+
fields: new Map(),
|
|
422
|
+
kind: node.kind,
|
|
423
|
+
name: node.name,
|
|
424
|
+
});
|
|
425
|
+
},
|
|
426
|
+
leave() {
|
|
427
|
+
factory.isCurrentParentExtension = false;
|
|
428
|
+
factory.parentTypeName = '';
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
InputValueDefinition: {
|
|
432
|
+
enter(node) {
|
|
433
|
+
if (!factory.parentTypeName || factory.isChild) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const name = node.name.value;
|
|
437
|
+
const parent = factory.isCurrentParentExtension
|
|
438
|
+
? (0, utils_3.getOrThrowError)(factory.extensions, factory.parentTypeName)
|
|
439
|
+
: (0, utils_3.getOrThrowError)(factory.parents, factory.parentTypeName);
|
|
440
|
+
if (parent.kind !== graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION && parent.kind !== graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION) {
|
|
441
|
+
throw new Error(''); // TODO
|
|
442
|
+
}
|
|
443
|
+
if (parent.fields.has(name)) {
|
|
444
|
+
factory.errors.push((0, errors_1.duplicateValueExtensionError)('input', factory.parentTypeName, name));
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
parent.fields.set(name, {
|
|
448
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
449
|
+
name,
|
|
450
|
+
node,
|
|
451
|
+
});
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
InterfaceTypeDefinition: {
|
|
455
|
+
enter(node) {
|
|
456
|
+
const name = node.name.value;
|
|
457
|
+
if (factory.parents.has(name)) {
|
|
458
|
+
factory.errors.push((0, errors_1.duplicateTypeDefinitionError)('interface', name));
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
factory.parentTypeName = name;
|
|
462
|
+
factory.parents.set(name, {
|
|
463
|
+
description: node.description,
|
|
464
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
465
|
+
fields: new Map(),
|
|
466
|
+
interfaces: (0, utils_1.extractInterfaces)(node, new Set()),
|
|
467
|
+
kind: node.kind,
|
|
468
|
+
name: node.name,
|
|
469
|
+
});
|
|
470
|
+
},
|
|
471
|
+
leave() {
|
|
472
|
+
factory.parentTypeName = '';
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
InterfaceTypeExtension: {
|
|
476
|
+
enter(node) {
|
|
477
|
+
const name = node.name.value;
|
|
478
|
+
factory.parentTypeName = name;
|
|
479
|
+
factory.isCurrentParentExtension = true;
|
|
480
|
+
const extension = factory.extensions.get(factory.parentTypeName);
|
|
481
|
+
if (extension) {
|
|
482
|
+
if (extension.kind !== graphql_1.Kind.INTERFACE_TYPE_EXTENSION) {
|
|
483
|
+
factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
factory.extractDirectives(node, extension.directives);
|
|
487
|
+
factory.extractUniqueInterfaces(node, extension.interfaces);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const interfaces = new Set();
|
|
491
|
+
factory.extensions.set(name, {
|
|
492
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
493
|
+
fields: new Map(),
|
|
494
|
+
interfaces: (0, utils_1.extractInterfaces)(node, interfaces),
|
|
495
|
+
kind: node.kind,
|
|
496
|
+
name: node.name,
|
|
497
|
+
});
|
|
498
|
+
},
|
|
499
|
+
leave() {
|
|
500
|
+
factory.isCurrentParentExtension = false;
|
|
501
|
+
factory.parentTypeName = '';
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
ObjectTypeDefinition: {
|
|
505
|
+
enter(node) {
|
|
506
|
+
const name = node.name.value;
|
|
507
|
+
if (factory.parents.has(name)) {
|
|
508
|
+
factory.errors.push((0, errors_1.duplicateTypeDefinitionError)('object', name));
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
factory.parentTypeName = name;
|
|
512
|
+
factory.parents.set(name, {
|
|
513
|
+
description: node.description,
|
|
514
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
515
|
+
fields: new Map(),
|
|
516
|
+
interfaces: factory.extractUniqueInterfaces(node, new Set()),
|
|
517
|
+
kind: node.kind,
|
|
518
|
+
name: node.name,
|
|
519
|
+
});
|
|
520
|
+
if (!(0, utils_1.isObjectNodeEntity)(node)) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
const existingEntityKeyMap = factory.entityMap.get(name);
|
|
524
|
+
const { entityKeyMap, errors } = (0, utils_1.getEntityKeyExtractionResults)(node, existingEntityKeyMap || new Map());
|
|
525
|
+
if (errors.length > 0) {
|
|
526
|
+
factory.errors.push(...errors);
|
|
527
|
+
}
|
|
528
|
+
if (!existingEntityKeyMap) {
|
|
529
|
+
factory.entityMap.set(name, entityKeyMap);
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
leave() {
|
|
533
|
+
factory.parentTypeName = '';
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
ObjectTypeExtension: {
|
|
537
|
+
enter(node) {
|
|
538
|
+
const name = node.name.value;
|
|
539
|
+
factory.parentTypeName = name;
|
|
540
|
+
factory.isCurrentParentExtension = true;
|
|
541
|
+
const extension = factory.extensions.get(factory.parentTypeName);
|
|
542
|
+
if (extension) {
|
|
543
|
+
if (extension.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
|
|
544
|
+
factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
|
|
545
|
+
return false;
|
|
546
|
+
}
|
|
547
|
+
factory.extractDirectives(node, extension.directives);
|
|
548
|
+
factory.extractUniqueInterfaces(node, extension.interfaces);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const interfaces = new Set();
|
|
552
|
+
factory.extensions.set(name, {
|
|
553
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
554
|
+
fields: new Map(),
|
|
555
|
+
interfaces: (0, utils_1.extractInterfaces)(node, interfaces),
|
|
556
|
+
kind: node.kind,
|
|
557
|
+
name: node.name,
|
|
558
|
+
});
|
|
559
|
+
if (!(0, utils_1.isObjectNodeEntity)(node)) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
const existingEntityKeyMap = factory.entityMap.get(name);
|
|
563
|
+
const { entityKeyMap, errors } = (0, utils_1.getEntityKeyExtractionResults)(node, existingEntityKeyMap || new Map());
|
|
564
|
+
if (errors.length > 0) {
|
|
565
|
+
factory.errors.push(...errors);
|
|
566
|
+
}
|
|
567
|
+
if (!existingEntityKeyMap) {
|
|
568
|
+
factory.entityMap.set(name, entityKeyMap);
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
leave() {
|
|
572
|
+
factory.isCurrentParentExtension = false;
|
|
573
|
+
factory.parentTypeName = '';
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
OperationTypeDefinition: {
|
|
577
|
+
enter(node) {
|
|
578
|
+
const operationType = node.operation;
|
|
579
|
+
const operationPath = `${factory.parentTypeName}.${operationType}`;
|
|
580
|
+
const definitionNode = factory.schemaDefinition.operationTypes.get(operationType);
|
|
581
|
+
const newTypeName = (0, type_merging_1.getNamedTypeForChild)(operationPath, node.type);
|
|
582
|
+
if (definitionNode) {
|
|
583
|
+
(0, errors_1.duplicateOperationTypeDefinitionError)(operationType, newTypeName, (0, type_merging_1.getNamedTypeForChild)(operationPath, definitionNode.type));
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
const existingOperationType = factory.operationTypeNames.get(newTypeName);
|
|
587
|
+
if (existingOperationType) {
|
|
588
|
+
factory.errors.push((0, errors_1.invalidOperationTypeDefinitionError)(existingOperationType, newTypeName, operationType));
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
factory.operationTypeNames.set(newTypeName, operationType);
|
|
592
|
+
factory.schemaDefinition.operationTypes.set(operationType, node);
|
|
593
|
+
}
|
|
594
|
+
return false;
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
ScalarTypeDefinition: {
|
|
598
|
+
enter(node) {
|
|
599
|
+
const name = node.name.value;
|
|
600
|
+
const parent = factory.parents.get(name);
|
|
601
|
+
if (parent) {
|
|
602
|
+
factory.errors.push((0, errors_1.duplicateTypeDefinitionError)('scalar', name));
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
factory.parents.set(name, {
|
|
606
|
+
description: node.description,
|
|
607
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
608
|
+
kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION,
|
|
609
|
+
name: node.name,
|
|
610
|
+
});
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
ScalarTypeExtension: {
|
|
614
|
+
enter(node) {
|
|
615
|
+
const name = node.name.value;
|
|
616
|
+
const extension = factory.extensions.get(name);
|
|
617
|
+
if (extension) {
|
|
618
|
+
if (extension.kind !== graphql_1.Kind.SCALAR_TYPE_EXTENSION) {
|
|
619
|
+
factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
factory.extractDirectives(node, extension.directives);
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
factory.extensions.set(name, {
|
|
626
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
627
|
+
kind: node.kind,
|
|
628
|
+
name: node.name,
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
return false;
|
|
632
|
+
},
|
|
633
|
+
},
|
|
634
|
+
SchemaDefinition: {
|
|
635
|
+
enter(node) {
|
|
636
|
+
// Apollo allows multiple schema definitions
|
|
637
|
+
factory.extractDirectives(node, factory.schemaDefinition.directives);
|
|
638
|
+
factory.schemaDefinition.description = factory.schemaDefinition.description || node.description;
|
|
639
|
+
},
|
|
640
|
+
},
|
|
641
|
+
SchemaExtension: {
|
|
642
|
+
enter(node) {
|
|
643
|
+
factory.extractDirectives(node, factory.schemaDefinition.directives);
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
UnionTypeDefinition: {
|
|
647
|
+
enter(node) {
|
|
648
|
+
const name = node.name.value;
|
|
649
|
+
factory.parentTypeName = name;
|
|
650
|
+
const parent = factory.parents.get(name);
|
|
651
|
+
if (parent) {
|
|
652
|
+
factory.errors.push((0, errors_1.duplicateTypeDefinitionError)('union', name));
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
if (!node.types) {
|
|
656
|
+
factory.errors.push((0, errors_1.noDefinedUnionMembersError)(name));
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
factory.parents.set(name, {
|
|
660
|
+
description: node.description,
|
|
661
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
662
|
+
kind: node.kind,
|
|
663
|
+
name: node.name,
|
|
664
|
+
types: factory.extractUniqueUnionMembers([...node.types], new Map()),
|
|
665
|
+
});
|
|
666
|
+
},
|
|
667
|
+
leave() {
|
|
668
|
+
factory.parentTypeName = '';
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
UnionTypeExtension: {
|
|
672
|
+
enter(node) {
|
|
673
|
+
const name = node.name.value;
|
|
674
|
+
const extension = factory.extensions.get(name);
|
|
675
|
+
if (!node.types) {
|
|
676
|
+
factory.errors.push();
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
if (extension) {
|
|
680
|
+
if (extension.kind !== graphql_1.Kind.UNION_TYPE_EXTENSION) {
|
|
681
|
+
factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
|
|
682
|
+
return false;
|
|
683
|
+
}
|
|
684
|
+
factory.extractDirectives(node, extension.directives);
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
factory.extensions.set(name, {
|
|
688
|
+
directives: factory.extractDirectives(node, new Map()),
|
|
689
|
+
kind: node.kind,
|
|
690
|
+
name: node.name,
|
|
691
|
+
types: factory.extractUniqueUnionMembers([...node.types], new Map()),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
return false;
|
|
695
|
+
},
|
|
696
|
+
},
|
|
697
|
+
});
|
|
698
|
+
const definitions = [];
|
|
699
|
+
for (const directiveDefinition of constants_1.BASE_DIRECTIVE_DEFINITIONS) {
|
|
700
|
+
definitions.push(directiveDefinition);
|
|
701
|
+
}
|
|
702
|
+
if (factory.isSubgraphVersionTwo) {
|
|
703
|
+
for (const directiveDefinition of constants_1.VERSION_TWO_DIRECTIVE_DEFINITIONS) {
|
|
704
|
+
definitions.push(directiveDefinition);
|
|
705
|
+
this.allDirectiveDefinitions.set(directiveDefinition.name.value, directiveDefinition);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
for (const directiveDefinition of this.customDirectiveDefinitions.values()) {
|
|
709
|
+
definitions.push(directiveDefinition);
|
|
710
|
+
}
|
|
711
|
+
if (this.schemaDefinition.operationTypes.size > 0) {
|
|
712
|
+
definitions.push((0, utils_2.schemaContainerToNode)(this, this.schemaDefinition));
|
|
713
|
+
}
|
|
714
|
+
const validExtensionOrphans = new Set();
|
|
715
|
+
const parentsToIgnore = new Set();
|
|
716
|
+
for (const [typeName, extension] of this.extensions) {
|
|
717
|
+
const baseType = this.parents.get(typeName);
|
|
718
|
+
if (!baseType) {
|
|
719
|
+
if (extension.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
|
|
720
|
+
this.errors.push((0, errors_1.noBaseTypeExtensionError)(typeName));
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
(0, utils_2.validateEntityKeys)(this, typeName, true);
|
|
724
|
+
validExtensionOrphans.add(typeName);
|
|
725
|
+
definitions.push((0, utils_2.objectLikeContainerToNode)(this, extension));
|
|
726
|
+
}
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
if (!(0, utils_1.areBaseAndExtensionKindsCompatible)(baseType.kind, extension.kind)) {
|
|
730
|
+
this.errors.push(new Error(`Extension error:\n Incompatible types: ` +
|
|
731
|
+
`"${typeName}" is type "${baseType.kind}", but an extension of the same name is type "${extension.kind}.`));
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
switch (baseType.kind) {
|
|
735
|
+
case graphql_1.Kind.ENUM_TYPE_DEFINITION:
|
|
736
|
+
const enumExtension = extension;
|
|
737
|
+
for (const [valueName, enumValueDefinitionNode] of enumExtension.values) {
|
|
738
|
+
if (!baseType.values.has(valueName)) {
|
|
739
|
+
baseType.values.set(valueName, enumValueDefinitionNode);
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
this.errors.push((0, errors_1.duplicateEnumValueDefinitionError)(valueName, typeName));
|
|
743
|
+
}
|
|
744
|
+
definitions.push((0, utils_2.enumContainerToNode)(this, baseType, enumExtension));
|
|
745
|
+
break;
|
|
746
|
+
case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
747
|
+
const inputExtension = extension;
|
|
748
|
+
for (const [fieldName, inputValueDefinitionNode] of inputExtension.fields) {
|
|
749
|
+
if (!baseType.fields.has(fieldName)) {
|
|
750
|
+
baseType.fields.set(fieldName, inputValueDefinitionNode);
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
this.errors.push((0, errors_1.duplicateFieldDefinitionError)(fieldName, typeName));
|
|
754
|
+
}
|
|
755
|
+
definitions.push((0, utils_2.inputObjectContainerToNode)(this, baseType, inputExtension));
|
|
756
|
+
break;
|
|
757
|
+
case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
|
|
758
|
+
// intentional fallthrough
|
|
759
|
+
case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
|
|
760
|
+
const objectExtension = extension;
|
|
761
|
+
for (const [fieldName, fieldDefinitionNode] of objectExtension.fields) {
|
|
762
|
+
if (!baseType.fields.has(fieldName)) {
|
|
763
|
+
baseType.fields.set(fieldName, fieldDefinitionNode);
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
this.errors.push((0, errors_1.duplicateFieldDefinitionError)(fieldName, typeName));
|
|
767
|
+
}
|
|
768
|
+
(0, utils_2.validateEntityKeys)(this, typeName);
|
|
769
|
+
this.mergeUniqueInterfaces(objectExtension.interfaces, baseType.interfaces, typeName);
|
|
770
|
+
definitions.push((0, utils_2.objectLikeContainerToNode)(this, baseType, objectExtension));
|
|
771
|
+
break;
|
|
772
|
+
case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
|
|
773
|
+
definitions.push((0, utils_2.scalarContainerToNode)(this, baseType, extension));
|
|
774
|
+
break;
|
|
775
|
+
case graphql_1.Kind.UNION_TYPE_DEFINITION:
|
|
776
|
+
const unionExtension = extension;
|
|
777
|
+
definitions.push((0, utils_2.unionContainerToNode)(this, baseType, unionExtension));
|
|
778
|
+
break;
|
|
779
|
+
default:
|
|
780
|
+
throw new Error('Unexpected kind'); // TODO
|
|
781
|
+
}
|
|
782
|
+
// At this point, the base type has been dealt with, so it doesn't need to be dealt with again
|
|
783
|
+
parentsToIgnore.add(typeName);
|
|
784
|
+
}
|
|
785
|
+
for (const [typeName, parentContainer] of this.parents) {
|
|
786
|
+
if (parentsToIgnore.has(typeName)) {
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
switch (parentContainer.kind) {
|
|
790
|
+
case graphql_1.Kind.ENUM_TYPE_DEFINITION:
|
|
791
|
+
definitions.push((0, utils_2.enumContainerToNode)(this, parentContainer));
|
|
792
|
+
break;
|
|
793
|
+
case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
794
|
+
definitions.push((0, utils_2.inputObjectContainerToNode)(this, parentContainer));
|
|
795
|
+
break;
|
|
796
|
+
case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
|
|
797
|
+
// Intentional fallthrough
|
|
798
|
+
case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
|
|
799
|
+
(0, utils_2.validateEntityKeys)(this, typeName);
|
|
800
|
+
definitions.push((0, utils_2.objectLikeContainerToNode)(this, parentContainer));
|
|
801
|
+
break;
|
|
802
|
+
case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
|
|
803
|
+
definitions.push((0, utils_2.scalarContainerToNode)(this, parentContainer));
|
|
804
|
+
break;
|
|
805
|
+
case graphql_1.Kind.UNION_TYPE_DEFINITION:
|
|
806
|
+
definitions.push((0, utils_2.unionContainerToNode)(this, parentContainer));
|
|
807
|
+
break;
|
|
808
|
+
default:
|
|
809
|
+
throw (0, errors_1.unexpectedKindFatalError)(typeName);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
// Check that explicitly defined operations types are valid objects and that their fields are also valid
|
|
813
|
+
for (const operationType of Object.values(graphql_1.OperationTypeNode)) {
|
|
814
|
+
const node = this.schemaDefinition.operationTypes.get(operationType);
|
|
815
|
+
const defaultTypeName = (0, utils_3.getOrThrowError)(utils_1.operationTypeNodeToDefaultType, operationType);
|
|
816
|
+
// If an operation type name was not declared, use the default
|
|
817
|
+
const operationTypeName = node ? (0, type_merging_1.getNamedTypeForChild)(`schema.${operationType}`, node.type) : defaultTypeName;
|
|
818
|
+
// If a custom type is used, the default type should not be defined
|
|
819
|
+
if (operationTypeName !== defaultTypeName &&
|
|
820
|
+
(this.parents.has(defaultTypeName) || this.extensions.has(defaultTypeName))) {
|
|
821
|
+
this.errors.push((0, errors_1.invalidRootTypeDefinitionError)(operationType, operationTypeName, defaultTypeName));
|
|
822
|
+
continue;
|
|
823
|
+
}
|
|
824
|
+
const object = this.parents.get(operationTypeName);
|
|
825
|
+
const extension = this.extensions.get(operationTypeName);
|
|
826
|
+
// Node is truthy of an operation type was explicitly declared
|
|
827
|
+
if (node) {
|
|
828
|
+
// If the type is not defined in the schema, it's always an error
|
|
829
|
+
if (!object && !extension) {
|
|
830
|
+
this.errors.push((0, errors_1.undefinedTypeError)(operationTypeName));
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
// Add the explicitly defined type to the map for the federation-factory
|
|
834
|
+
this.operationTypeNames.set(operationTypeName, operationType);
|
|
835
|
+
}
|
|
836
|
+
const containers = [object, extension];
|
|
837
|
+
for (const container of containers) {
|
|
838
|
+
if (!container) {
|
|
839
|
+
continue;
|
|
840
|
+
}
|
|
841
|
+
if (container.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION && container.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
|
|
842
|
+
this.errors.push((0, errors_1.operationDefinitionError)(operationTypeName, operationType, container.kind));
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
// Operations whose response type is an extension orphan could be valid through a federated graph
|
|
846
|
+
// However, the field would have to be shareable to ever be valid TODO
|
|
847
|
+
for (const fieldContainer of container.fields.values()) {
|
|
848
|
+
const fieldPath = `${operationTypeName}.${fieldContainer.name}`;
|
|
849
|
+
const fieldTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, fieldContainer.node.type);
|
|
850
|
+
if (!constants_1.BASE_SCALARS.has(fieldTypeName) &&
|
|
851
|
+
!this.parents.has(fieldTypeName) &&
|
|
852
|
+
!validExtensionOrphans.has(fieldTypeName)) {
|
|
853
|
+
this.errors.push((0, errors_1.undefinedTypeError)(fieldTypeName));
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
for (const referencedTypeName of this.referencedTypeNames) {
|
|
859
|
+
if (!this.parents.has(referencedTypeName) && !this.entityMap.has(referencedTypeName)) {
|
|
860
|
+
this.errors.push((0, errors_1.undefinedTypeError)(referencedTypeName));
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
if (this.errors.length > 0) {
|
|
864
|
+
return { errors: this.errors };
|
|
865
|
+
}
|
|
866
|
+
const newAST = {
|
|
867
|
+
kind: graphql_1.Kind.DOCUMENT,
|
|
868
|
+
definitions,
|
|
869
|
+
};
|
|
870
|
+
return {
|
|
871
|
+
normalizationResult: {
|
|
872
|
+
isVersionTwo: this.isSubgraphVersionTwo,
|
|
873
|
+
operationTypes: this.operationTypeNames,
|
|
874
|
+
subgraphAST: newAST,
|
|
875
|
+
subgraphString: (0, graphql_1.print)(newAST),
|
|
876
|
+
schema: (0, buildASTSchema_1.buildASTSchema)(newAST, { assumeValid: true }),
|
|
877
|
+
},
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
exports.NormalizationFactory = NormalizationFactory;
|
|
882
|
+
//# sourceMappingURL=normalization-factory.js.map
|