@theguild/federation-composition 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +2 -1
  2. package/cjs/specifications/link.js +40 -5
  3. package/cjs/subgraph/helpers.js +2 -2
  4. package/cjs/subgraph/state.js +8 -0
  5. package/cjs/subgraph/validation/rules/elements/provides.js +8 -6
  6. package/cjs/subgraph/validation/rules/elements/requires.js +9 -7
  7. package/cjs/subgraph/validation/validate-state.js +9 -3
  8. package/cjs/subgraph/validation/validate-subgraph.js +4 -2
  9. package/cjs/subgraph/validation/validation-context.js +10 -0
  10. package/cjs/supergraph/composition/directive.js +3 -0
  11. package/cjs/supergraph/composition/enum-type.js +3 -0
  12. package/cjs/supergraph/composition/input-object-type.js +3 -0
  13. package/cjs/supergraph/composition/interface-type.js +4 -0
  14. package/cjs/supergraph/composition/object-type.js +18 -20
  15. package/cjs/supergraph/composition/scalar-type.js +2 -0
  16. package/cjs/supergraph/composition/union-type.js +2 -0
  17. package/cjs/supergraph/state.js +24 -26
  18. package/cjs/supergraph/validation/rules/fields-of-the-same-type-rule.js +35 -0
  19. package/cjs/supergraph/validation/rules/invalid-field-sharing-rule.js +4 -1
  20. package/cjs/supergraph/validation/rules/satisfiablity/constants.js +4 -0
  21. package/cjs/supergraph/validation/rules/satisfiablity/edge.js +64 -0
  22. package/cjs/supergraph/validation/rules/satisfiablity/errors.js +44 -0
  23. package/cjs/supergraph/validation/rules/satisfiablity/fields.js +147 -0
  24. package/cjs/supergraph/validation/rules/satisfiablity/finder.js +267 -0
  25. package/cjs/supergraph/validation/rules/satisfiablity/graph.js +675 -0
  26. package/cjs/supergraph/validation/rules/satisfiablity/helpers.js +41 -0
  27. package/cjs/supergraph/validation/rules/satisfiablity/move-validator.js +337 -0
  28. package/cjs/supergraph/validation/rules/satisfiablity/moves.js +52 -0
  29. package/cjs/supergraph/validation/rules/satisfiablity/node.js +89 -0
  30. package/cjs/supergraph/validation/rules/satisfiablity/operation-path.js +70 -0
  31. package/cjs/supergraph/validation/rules/satisfiablity/supergraph.js +37 -0
  32. package/cjs/supergraph/validation/rules/satisfiablity/walker.js +306 -0
  33. package/cjs/supergraph/validation/rules/satisfiablity-rule.js +45 -1081
  34. package/cjs/supergraph/validation/validate-supergraph.js +1 -1
  35. package/cjs/utils/logger.js +127 -0
  36. package/esm/specifications/link.js +40 -5
  37. package/esm/subgraph/helpers.js +2 -2
  38. package/esm/subgraph/state.js +8 -0
  39. package/esm/subgraph/validation/rules/elements/provides.js +8 -6
  40. package/esm/subgraph/validation/rules/elements/requires.js +9 -7
  41. package/esm/subgraph/validation/validate-state.js +9 -3
  42. package/esm/subgraph/validation/validate-subgraph.js +4 -2
  43. package/esm/subgraph/validation/validation-context.js +11 -1
  44. package/esm/supergraph/composition/directive.js +3 -0
  45. package/esm/supergraph/composition/enum-type.js +3 -0
  46. package/esm/supergraph/composition/input-object-type.js +3 -0
  47. package/esm/supergraph/composition/interface-type.js +4 -0
  48. package/esm/supergraph/composition/object-type.js +18 -20
  49. package/esm/supergraph/composition/scalar-type.js +2 -0
  50. package/esm/supergraph/composition/union-type.js +2 -0
  51. package/esm/supergraph/state.js +24 -26
  52. package/esm/supergraph/validation/rules/fields-of-the-same-type-rule.js +35 -0
  53. package/esm/supergraph/validation/rules/invalid-field-sharing-rule.js +4 -1
  54. package/esm/supergraph/validation/rules/satisfiablity/constants.js +1 -0
  55. package/esm/supergraph/validation/rules/satisfiablity/edge.js +54 -0
  56. package/esm/supergraph/validation/rules/satisfiablity/errors.js +40 -0
  57. package/esm/supergraph/validation/rules/satisfiablity/fields.js +142 -0
  58. package/esm/supergraph/validation/rules/satisfiablity/finder.js +261 -0
  59. package/esm/supergraph/validation/rules/satisfiablity/graph.js +671 -0
  60. package/esm/supergraph/validation/rules/satisfiablity/helpers.js +35 -0
  61. package/esm/supergraph/validation/rules/satisfiablity/move-validator.js +333 -0
  62. package/esm/supergraph/validation/rules/satisfiablity/moves.js +46 -0
  63. package/esm/supergraph/validation/rules/satisfiablity/node.js +85 -0
  64. package/esm/supergraph/validation/rules/satisfiablity/operation-path.js +66 -0
  65. package/esm/supergraph/validation/rules/satisfiablity/supergraph.js +33 -0
  66. package/esm/supergraph/validation/rules/satisfiablity/walker.js +301 -0
  67. package/esm/supergraph/validation/rules/satisfiablity-rule.js +40 -1076
  68. package/esm/supergraph/validation/validate-supergraph.js +1 -1
  69. package/esm/utils/logger.js +119 -0
  70. package/package.json +2 -1
  71. package/typings/subgraph/state.d.cts +2 -0
  72. package/typings/subgraph/state.d.ts +2 -0
  73. package/typings/subgraph/validation/validate-state.d.cts +2 -1
  74. package/typings/subgraph/validation/validate-state.d.ts +2 -1
  75. package/typings/subgraph/validation/validation-context.d.cts +3 -0
  76. package/typings/subgraph/validation/validation-context.d.ts +3 -0
  77. package/typings/supergraph/composition/common.d.cts +2 -1
  78. package/typings/supergraph/composition/common.d.ts +2 -1
  79. package/typings/supergraph/composition/directive.d.cts +4 -0
  80. package/typings/supergraph/composition/directive.d.ts +4 -0
  81. package/typings/supergraph/composition/enum-type.d.cts +4 -0
  82. package/typings/supergraph/composition/enum-type.d.ts +4 -0
  83. package/typings/supergraph/composition/input-object-type.d.cts +4 -0
  84. package/typings/supergraph/composition/input-object-type.d.ts +4 -0
  85. package/typings/supergraph/composition/interface-type.d.cts +5 -0
  86. package/typings/supergraph/composition/interface-type.d.ts +5 -0
  87. package/typings/supergraph/composition/object-type.d.cts +5 -0
  88. package/typings/supergraph/composition/object-type.d.ts +5 -0
  89. package/typings/supergraph/composition/scalar-type.d.cts +3 -0
  90. package/typings/supergraph/composition/scalar-type.d.ts +3 -0
  91. package/typings/supergraph/composition/union-type.d.cts +3 -0
  92. package/typings/supergraph/composition/union-type.d.ts +3 -0
  93. package/typings/supergraph/state.d.cts +4 -4
  94. package/typings/supergraph/state.d.ts +4 -4
  95. package/typings/supergraph/validation/rules/satisfiablity/constants.d.cts +2 -0
  96. package/typings/supergraph/validation/rules/satisfiablity/constants.d.ts +2 -0
  97. package/typings/supergraph/validation/rules/satisfiablity/edge.d.cts +31 -0
  98. package/typings/supergraph/validation/rules/satisfiablity/edge.d.ts +31 -0
  99. package/typings/supergraph/validation/rules/satisfiablity/errors.d.cts +17 -0
  100. package/typings/supergraph/validation/rules/satisfiablity/errors.d.ts +17 -0
  101. package/typings/supergraph/validation/rules/satisfiablity/fields.d.cts +33 -0
  102. package/typings/supergraph/validation/rules/satisfiablity/fields.d.ts +33 -0
  103. package/typings/supergraph/validation/rules/satisfiablity/finder.d.cts +28 -0
  104. package/typings/supergraph/validation/rules/satisfiablity/finder.d.ts +28 -0
  105. package/typings/supergraph/validation/rules/satisfiablity/graph.d.cts +63 -0
  106. package/typings/supergraph/validation/rules/satisfiablity/graph.d.ts +63 -0
  107. package/typings/supergraph/validation/rules/satisfiablity/helpers.d.cts +7 -0
  108. package/typings/supergraph/validation/rules/satisfiablity/helpers.d.ts +7 -0
  109. package/typings/supergraph/validation/rules/satisfiablity/move-validator.d.cts +25 -0
  110. package/typings/supergraph/validation/rules/satisfiablity/move-validator.d.ts +25 -0
  111. package/typings/supergraph/validation/rules/satisfiablity/moves.d.cts +24 -0
  112. package/typings/supergraph/validation/rules/satisfiablity/moves.d.ts +24 -0
  113. package/typings/supergraph/validation/rules/satisfiablity/node.d.cts +31 -0
  114. package/typings/supergraph/validation/rules/satisfiablity/node.d.ts +31 -0
  115. package/typings/supergraph/validation/rules/satisfiablity/operation-path.d.cts +29 -0
  116. package/typings/supergraph/validation/rules/satisfiablity/operation-path.d.ts +29 -0
  117. package/typings/supergraph/validation/rules/satisfiablity/supergraph.d.cts +14 -0
  118. package/typings/supergraph/validation/rules/satisfiablity/supergraph.d.ts +14 -0
  119. package/typings/supergraph/validation/rules/satisfiablity/walker.d.cts +35 -0
  120. package/typings/supergraph/validation/rules/satisfiablity/walker.d.ts +35 -0
  121. package/typings/utils/logger.d.cts +33 -0
  122. package/typings/utils/logger.d.ts +33 -0
  123. package/cjs/utils/dependency-graph.js +0 -227
  124. package/esm/utils/dependency-graph.js +0 -222
  125. package/typings/utils/dependency-graph.d.cts +0 -31
  126. package/typings/utils/dependency-graph.d.ts +0 -31
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lazy = exports.scoreKeyFields = exports.occurrences = void 0;
4
+ function occurrences(str, subString) {
5
+ if (subString.length <= 0) {
6
+ return str.length + 1;
7
+ }
8
+ let n = 0, pos = 0, step = subString.length;
9
+ while (true) {
10
+ pos = str.indexOf(subString, pos);
11
+ if (pos >= 0) {
12
+ ++n;
13
+ pos += step;
14
+ }
15
+ else
16
+ break;
17
+ }
18
+ return n;
19
+ }
20
+ exports.occurrences = occurrences;
21
+ function scoreKeyFields(keyFields) {
22
+ const fields = occurrences(keyFields, ' ') + 1;
23
+ const innerSelectionSets = occurrences(keyFields, '{') * 3;
24
+ return fields + innerSelectionSets;
25
+ }
26
+ exports.scoreKeyFields = scoreKeyFields;
27
+ function lazy(factory) {
28
+ let value;
29
+ return {
30
+ get() {
31
+ if (value === undefined) {
32
+ value = factory();
33
+ }
34
+ return value;
35
+ },
36
+ invalidate() {
37
+ value = undefined;
38
+ },
39
+ };
40
+ }
41
+ exports.lazy = lazy;
@@ -0,0 +1,337 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MoveValidator = void 0;
4
+ const edge_1 = require("./edge");
5
+ const errors_1 = require("./errors");
6
+ const finder_1 = require("./finder");
7
+ class MoveValidator {
8
+ supergraph;
9
+ cache = new Map();
10
+ logger;
11
+ pathFinder;
12
+ constructor(logger, supergraph) {
13
+ this.supergraph = supergraph;
14
+ this.logger = logger.create('MoveValidator');
15
+ this.pathFinder = new finder_1.PathFinder(this.logger, supergraph, this);
16
+ }
17
+ canResolveFields(fields, path, visitedEdges, visitedGraphs, visitedFields) {
18
+ const cacheKey = JSON.stringify(fields) +
19
+ ' | ' +
20
+ visitedGraphs.join(',') +
21
+ visitedFields.join(',') +
22
+ ' | ' +
23
+ visitedEdges
24
+ .map(e => e.toString())
25
+ .sort()
26
+ .join(',');
27
+ const cached = this.cache.get(cacheKey);
28
+ if (cached) {
29
+ return cached;
30
+ }
31
+ const requirements = [];
32
+ for (const field of fields) {
33
+ requirements.unshift({
34
+ field,
35
+ paths: [path.clone()],
36
+ });
37
+ }
38
+ while (requirements.length > 0) {
39
+ const requirement = requirements.pop();
40
+ if (!requirement) {
41
+ break;
42
+ }
43
+ const result = this.validateRequirement(requirement, visitedEdges, visitedGraphs, visitedFields);
44
+ if (result.success === false) {
45
+ this.cache.set(cacheKey, result);
46
+ return result;
47
+ }
48
+ for (const innerRequirement of result.requirements) {
49
+ requirements.unshift(innerRequirement);
50
+ }
51
+ }
52
+ this.cache.set(cacheKey, {
53
+ success: true,
54
+ errors: undefined,
55
+ });
56
+ return {
57
+ success: true,
58
+ errors: undefined,
59
+ };
60
+ }
61
+ validateRequirement(requirement, visitedEdges, visitedGraphs, visitedFields) {
62
+ const nextPaths = [];
63
+ const errors = [];
64
+ if ('type' in requirement) {
65
+ for (const path of requirement.paths) {
66
+ const directPathsResult = this.pathFinder.findDirectPaths(path, requirement.type.childTypeName, null, visitedEdges);
67
+ if (directPathsResult.success) {
68
+ if (this.logger.isEnabled) {
69
+ this.logger.log(() => 'Possible direct paths:');
70
+ for (const path of directPathsResult.paths) {
71
+ this.logger.log(() => ' ' + path.toString());
72
+ }
73
+ }
74
+ nextPaths.push(...directPathsResult.paths);
75
+ }
76
+ else {
77
+ errors.push(...directPathsResult.errors);
78
+ }
79
+ }
80
+ for (const path of requirement.paths) {
81
+ const indirectPathsResult = this.pathFinder.findIndirectPaths(path, requirement.type.childTypeName, null, visitedEdges, visitedGraphs, visitedFields);
82
+ if (indirectPathsResult.success) {
83
+ if (this.logger.isEnabled) {
84
+ this.logger.log(() => 'Possible indirect paths:');
85
+ for (const path of indirectPathsResult.paths) {
86
+ this.logger.log(() => ' ' + path.toString());
87
+ }
88
+ }
89
+ nextPaths.push(...indirectPathsResult.paths);
90
+ }
91
+ else {
92
+ errors.push(...indirectPathsResult.errors);
93
+ }
94
+ }
95
+ if (nextPaths.length === 0) {
96
+ if (this.logger.isEnabled) {
97
+ this.logger.log(() => 'Could not resolve from:');
98
+ for (const path of requirement.paths) {
99
+ this.logger.log(() => ' ' + path.toString());
100
+ }
101
+ }
102
+ return {
103
+ success: false,
104
+ errors,
105
+ };
106
+ }
107
+ if (!requirement.type.field) {
108
+ return {
109
+ success: true,
110
+ requirements: [],
111
+ };
112
+ }
113
+ return {
114
+ success: true,
115
+ requirements: [
116
+ {
117
+ field: requirement.type.field,
118
+ paths: nextPaths.slice(),
119
+ },
120
+ ],
121
+ };
122
+ }
123
+ const possibleTypes = this.supergraph.possibleTypesOf(requirement.field.typeName);
124
+ const needsAbstractMove = !possibleTypes.includes(requirement.field.typeName);
125
+ if (needsAbstractMove) {
126
+ const requirements = [];
127
+ for (const possibleType of possibleTypes) {
128
+ const abstractMoveRequirement = {
129
+ type: {
130
+ parentTypeName: requirement.field.typeName,
131
+ childTypeName: possibleType,
132
+ field: {
133
+ ...requirement.field,
134
+ typeName: possibleType,
135
+ },
136
+ },
137
+ paths: requirement.paths,
138
+ };
139
+ requirements.push(abstractMoveRequirement);
140
+ }
141
+ this.logger.log(() => 'Abstract move');
142
+ return {
143
+ success: true,
144
+ requirements,
145
+ };
146
+ }
147
+ for (const path of requirement.paths) {
148
+ const directPathsResult = this.pathFinder.findDirectPaths(path, requirement.field.typeName, requirement.field.fieldName, visitedEdges);
149
+ if (directPathsResult.success) {
150
+ if (this.logger.isEnabled) {
151
+ this.logger.log(() => 'Possible direct paths:');
152
+ for (const path of directPathsResult.paths) {
153
+ this.logger.log(() => ' ' + path.toString());
154
+ }
155
+ }
156
+ nextPaths.push(...directPathsResult.paths);
157
+ }
158
+ else {
159
+ errors.push(...directPathsResult.errors);
160
+ }
161
+ }
162
+ for (const path of requirement.paths) {
163
+ const indirectPathsResult = this.pathFinder.findIndirectPaths(path, requirement.field.typeName, requirement.field.fieldName, visitedEdges, visitedGraphs, visitedFields);
164
+ if (indirectPathsResult.success) {
165
+ if (this.logger.isEnabled) {
166
+ this.logger.log(() => 'Possible indirect paths:');
167
+ for (const path of indirectPathsResult.paths) {
168
+ this.logger.log(() => ' ' + path.toString());
169
+ }
170
+ }
171
+ nextPaths.push(...indirectPathsResult.paths);
172
+ }
173
+ else {
174
+ errors.push(...indirectPathsResult.errors);
175
+ }
176
+ }
177
+ if (nextPaths.length === 0) {
178
+ this.logger.log(() => `Failed to resolve field ${requirement.field.typeName}.${requirement.field.fieldName} from:`);
179
+ if (this.logger.isEnabled) {
180
+ for (const path of requirement.paths) {
181
+ this.logger.log(() => ` ` + path);
182
+ }
183
+ }
184
+ return {
185
+ success: false,
186
+ errors: errors.filter(e => e.isMatchingField(requirement.field.typeName, requirement.field.fieldName)),
187
+ };
188
+ }
189
+ if (!requirement.field.selectionSet || requirement.field.selectionSet.length === 0) {
190
+ return {
191
+ success: true,
192
+ requirements: [],
193
+ };
194
+ }
195
+ return {
196
+ success: true,
197
+ requirements: requirement.field.selectionSet.map(field => ({
198
+ field,
199
+ paths: nextPaths.slice(),
200
+ })),
201
+ };
202
+ }
203
+ isExternal(edge) {
204
+ if (!(0, edge_1.isFieldEdge)(edge)) {
205
+ return false;
206
+ }
207
+ if (edge.move.provided) {
208
+ return false;
209
+ }
210
+ if (!edge.head.typeState) {
211
+ return false;
212
+ }
213
+ if (edge.head.typeState.kind !== 'object') {
214
+ return false;
215
+ }
216
+ const fieldState = edge.head.typeState.fields.get(edge.move.fieldName);
217
+ if (!fieldState) {
218
+ return false;
219
+ }
220
+ const objectTypeStateInGraph = edge.head.typeState.byGraph.get(edge.head.graphId);
221
+ if (!objectTypeStateInGraph) {
222
+ return false;
223
+ }
224
+ const fieldStateInGraph = fieldState.byGraph.get(edge.head.graphId);
225
+ if (!fieldStateInGraph) {
226
+ return false;
227
+ }
228
+ const external = fieldState.byGraph.get(edge.head.graphId)?.external ?? false;
229
+ if (!external) {
230
+ return false;
231
+ }
232
+ const isFedV1 = fieldStateInGraph.version === 'v1.0';
233
+ if (isFedV1 && objectTypeStateInGraph.extension && fieldState.usedAsKey) {
234
+ return false;
235
+ }
236
+ if (!fieldStateInGraph.usedAsKey) {
237
+ return true;
238
+ }
239
+ let hasNonExternalFields = false;
240
+ if (isFedV1) {
241
+ for (const [fieldName, fieldState] of edge.head.typeState.fields) {
242
+ if (fieldName === edge.move.fieldName) {
243
+ continue;
244
+ }
245
+ const fieldStateInGraph = fieldState.byGraph.get(edge.head.graphId);
246
+ if (!fieldStateInGraph) {
247
+ continue;
248
+ }
249
+ if (!fieldStateInGraph.external) {
250
+ hasNonExternalFields = true;
251
+ break;
252
+ }
253
+ }
254
+ }
255
+ if (hasNonExternalFields) {
256
+ return false;
257
+ }
258
+ if (objectTypeStateInGraph.extension) {
259
+ return false;
260
+ }
261
+ return true;
262
+ }
263
+ isOverridden(edge) {
264
+ if (!(0, edge_1.isFieldEdge)(edge)) {
265
+ return false;
266
+ }
267
+ if (!edge.head.typeState) {
268
+ return false;
269
+ }
270
+ if (!edge.head.typeState || edge.head.typeState.kind !== 'object') {
271
+ return false;
272
+ }
273
+ const fieldState = edge.head.typeState.fields.get(edge.move.fieldName);
274
+ if (!fieldState) {
275
+ return false;
276
+ }
277
+ if (!fieldState.override) {
278
+ return false;
279
+ }
280
+ const overriddenGraphId = this.supergraph.graphNameToId(fieldState.override);
281
+ if (!overriddenGraphId) {
282
+ return false;
283
+ }
284
+ return edge.head.graphId === overriddenGraphId;
285
+ }
286
+ isEdgeResolvable(edge, path, visitedEdges, visitedGraphs, visitedFields) {
287
+ this.logger.group(() => 'Checking resolvability of ' + edge);
288
+ this.logger.log(() => 'Visited graphs: ' + visitedGraphs.join(','));
289
+ const resolvability = edge.getResolvability((0, finder_1.concatIfNotExistsString)(visitedGraphs, edge.tail.graphName));
290
+ if (resolvability) {
291
+ this.logger.groupEnd(() => resolvability.success
292
+ ? `Can move to ${edge}`
293
+ : `Cannot move to ${edge} (already visited: ${resolvability.error.kind})`);
294
+ return resolvability;
295
+ }
296
+ if ((0, edge_1.isFieldEdge)(edge)) {
297
+ if (this.isOverridden(edge)) {
298
+ this.logger.groupEnd(() => 'Cannot move to ' + edge + ' because it is overridden');
299
+ return edge.setResolvable(false, visitedGraphs, errors_1.SatisfiabilityError.forMissingField(edge.tail.graphName, edge.move.typeName, edge.move.fieldName));
300
+ }
301
+ if (edge.move.requires) {
302
+ this.logger.log(() => 'Detected @requires');
303
+ const newVisitedGraphs = (0, finder_1.concatIfNotExistsString)(visitedGraphs, edge.tail.graphName);
304
+ const newVisitedFields = (0, finder_1.concatIfNotExistsFields)(visitedFields, edge.move.requires);
305
+ this.logger.log(() => 'Visited graphs: ' + newVisitedGraphs.join(','));
306
+ if (this.canResolveFields(edge.move.requires.fields, path, visitedEdges.concat(edge), newVisitedGraphs, newVisitedFields).success) {
307
+ this.logger.groupEnd(() => 'Can move to ' + edge);
308
+ return edge.setResolvable(true, newVisitedGraphs);
309
+ }
310
+ this.logger.groupEnd(() => 'Cannot move to ' + edge + ' because @require is not resolvable');
311
+ return {
312
+ success: false,
313
+ error: errors_1.SatisfiabilityError.forRequire(edge.head.graphName, edge.move.typeName, edge.move.fieldName),
314
+ };
315
+ }
316
+ else if (this.isExternal(edge)) {
317
+ this.logger.groupEnd(() => 'Cannot move to ' + edge + ' because it is external and cross-graph');
318
+ return edge.setResolvable(false, visitedGraphs, errors_1.SatisfiabilityError.forExternal(edge.head.graphName, edge.move.typeName, edge.move.fieldName));
319
+ }
320
+ }
321
+ else if ((0, edge_1.isEntityEdge)(edge)) {
322
+ this.logger.log(() => 'Detected @key');
323
+ const newVisitedGraphs = (0, finder_1.concatIfNotExistsString)(visitedGraphs, edge.tail.graphName);
324
+ const newVisitedFields = (0, finder_1.concatIfNotExistsFields)(visitedFields, edge.move.keyFields);
325
+ this.logger.log(() => 'Visited graphs: ' + newVisitedGraphs.join(','));
326
+ if (this.canResolveFields(edge.move.keyFields.fields, path, visitedEdges.concat(edge), newVisitedGraphs, newVisitedFields).success) {
327
+ this.logger.groupEnd(() => 'Can move to ' + edge);
328
+ return edge.setResolvable(true, newVisitedGraphs);
329
+ }
330
+ this.logger.groupEnd(() => 'Cannot move to ' + edge + ' because key fields are not resolvable');
331
+ return edge.setResolvable(false, newVisitedGraphs, errors_1.SatisfiabilityError.forKey(edge.head.graphName, edge.tail.graphName, edge.head.typeName, edge.move.keyFields.toString()));
332
+ }
333
+ this.logger.groupEnd(() => 'Can move to ' + edge);
334
+ return edge.setResolvable(true, visitedGraphs);
335
+ }
336
+ }
337
+ exports.MoveValidator = MoveValidator;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntityMove = exports.AbstractMove = exports.FieldMove = void 0;
4
+ const helpers_1 = require("./helpers");
5
+ class FieldMove {
6
+ typeName;
7
+ fieldName;
8
+ requires;
9
+ provides;
10
+ provided;
11
+ _toString = (0, helpers_1.lazy)(() => {
12
+ let str = this.fieldName;
13
+ if (this.requires) {
14
+ str += ` @require(${this.requires})`;
15
+ }
16
+ if (this.provides) {
17
+ str += ` @provides(${this.provides})`;
18
+ }
19
+ if (this.provided) {
20
+ str += ' @provided';
21
+ }
22
+ return str;
23
+ });
24
+ constructor(typeName, fieldName, requires = null, provides = null, provided = false) {
25
+ this.typeName = typeName;
26
+ this.fieldName = fieldName;
27
+ this.requires = requires;
28
+ this.provides = provides;
29
+ this.provided = provided;
30
+ }
31
+ toString() {
32
+ return this._toString.get();
33
+ }
34
+ }
35
+ exports.FieldMove = FieldMove;
36
+ class AbstractMove {
37
+ toString() {
38
+ return `🔮`;
39
+ }
40
+ }
41
+ exports.AbstractMove = AbstractMove;
42
+ class EntityMove {
43
+ keyFields;
44
+ _toString = (0, helpers_1.lazy)(() => `🔑 ${this.keyFields}`);
45
+ constructor(keyFields) {
46
+ this.keyFields = keyFields;
47
+ }
48
+ toString() {
49
+ return this._toString.get();
50
+ }
51
+ }
52
+ exports.EntityMove = EntityMove;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Node = void 0;
4
+ const helpers_1 = require("./helpers");
5
+ class Node {
6
+ index;
7
+ typeName;
8
+ typeState;
9
+ graphId;
10
+ graphName;
11
+ _toString = (0, helpers_1.lazy)(() => `${this.typeName}/${this.graphName}`);
12
+ isLeaf = false;
13
+ childrenIndex = new Map();
14
+ visitedGraphCombos = [];
15
+ constructor(index, typeName, typeState, graphId, graphName) {
16
+ this.index = index;
17
+ this.typeName = typeName;
18
+ this.typeState = typeState;
19
+ this.graphId = graphId;
20
+ this.graphName = graphName;
21
+ if (this.typeState === undefined) {
22
+ throw new Error(`Expected typeState to be defined for ${typeName} in subgraph ${graphName}`);
23
+ }
24
+ if (this.typeState === null ||
25
+ this.typeState.kind === 'scalar' ||
26
+ this.typeState.kind === 'enum') {
27
+ this.isLeaf = true;
28
+ }
29
+ }
30
+ withoutState() {
31
+ this.childrenIndex = new Map();
32
+ this.visitedGraphCombos = [];
33
+ return this;
34
+ }
35
+ addFieldEdge(fieldName, edgeAt) {
36
+ const id = `field__${fieldName}`;
37
+ const indexes = this.childrenIndex.get(id);
38
+ if (indexes) {
39
+ if (!indexes.includes(edgeAt)) {
40
+ indexes.push(edgeAt);
41
+ }
42
+ }
43
+ else {
44
+ this.childrenIndex.set(id, [edgeAt]);
45
+ }
46
+ }
47
+ getFieldEdgeIndexes(fieldName) {
48
+ return this.childrenIndex.get(`field__${fieldName}`);
49
+ }
50
+ addEntityEdge(typeName, edgeAt) {
51
+ this.pushToChildrenIndex(`entity__${typeName}`, edgeAt);
52
+ }
53
+ getEntityEdgeIndexes(typeName) {
54
+ return this.childrenIndex.get(`entity__${typeName}`);
55
+ }
56
+ addAbstractEdge(typeName, edgeAt) {
57
+ this.pushToChildrenIndex(`abstract__${typeName}`, edgeAt);
58
+ }
59
+ getAbstractEdgeIndexes(typeName) {
60
+ return this.childrenIndex.get(`abstract__${typeName}`);
61
+ }
62
+ addCrossGraphEdge(typeName, edgeAt) {
63
+ this.pushToChildrenIndex(`cross-graph__${typeName}`, edgeAt);
64
+ }
65
+ getCrossGraphEdgeIndexes(typeName) {
66
+ return this.childrenIndex.get(`cross-graph__${typeName}`);
67
+ }
68
+ pushToChildrenIndex(id, edgeAt) {
69
+ const indexes = this.childrenIndex.get(id);
70
+ if (indexes) {
71
+ if (!indexes.includes(edgeAt)) {
72
+ indexes.push(edgeAt);
73
+ }
74
+ }
75
+ else {
76
+ this.childrenIndex.set(id, [edgeAt]);
77
+ }
78
+ }
79
+ isGraphComboVisited(graphNameProvidesCombos) {
80
+ return this.visitedGraphCombos.some(visitedGraphs => visitedGraphs.every(g => graphNameProvidesCombos.includes(g)));
81
+ }
82
+ setGraphComboAsVisited(graphNames) {
83
+ this.visitedGraphCombos.push(graphNames);
84
+ }
85
+ toString() {
86
+ return this._toString.get();
87
+ }
88
+ }
89
+ exports.Node = Node;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OperationPath = void 0;
4
+ const edge_1 = require("./edge");
5
+ const helpers_1 = require("./helpers");
6
+ class OperationPath {
7
+ _rootNode;
8
+ _toString = (0, helpers_1.lazy)(() => {
9
+ let str = this._rootNode.toString();
10
+ for (let i = 0; i < this.previousEdges.length; i++) {
11
+ const edge = this.previousEdges[i];
12
+ if (edge) {
13
+ str += ` -(${edge.move})-> ${edge.tail}`;
14
+ }
15
+ }
16
+ return str;
17
+ });
18
+ previousNodes = [];
19
+ previousEdges = [];
20
+ previousSteps = [];
21
+ constructor(_rootNode) {
22
+ this._rootNode = _rootNode;
23
+ }
24
+ move(edge) {
25
+ this._toString.invalidate();
26
+ this.advance(edge);
27
+ return this;
28
+ }
29
+ clone() {
30
+ const newPath = new OperationPath(this._rootNode);
31
+ newPath.previousNodes = this.previousNodes.slice();
32
+ newPath.previousEdges = this.previousEdges.slice();
33
+ newPath.previousSteps = this.previousSteps.slice();
34
+ return newPath;
35
+ }
36
+ depth() {
37
+ return this.previousEdges.length;
38
+ }
39
+ edge() {
40
+ return this.previousEdges[this.previousEdges.length - 1];
41
+ }
42
+ steps() {
43
+ return this.previousSteps;
44
+ }
45
+ tail() {
46
+ return this.edge()?.tail;
47
+ }
48
+ rootNode() {
49
+ return this._rootNode;
50
+ }
51
+ isVisitedEdge(edge) {
52
+ return this.previousEdges.includes(edge);
53
+ }
54
+ toString() {
55
+ return this._toString.get();
56
+ }
57
+ advance(edge) {
58
+ this.previousEdges.push(edge);
59
+ this.previousNodes.push(edge.head);
60
+ this.previousSteps.push((0, edge_1.isFieldEdge)(edge)
61
+ ? {
62
+ typeName: edge.move.typeName,
63
+ fieldName: edge.move.fieldName,
64
+ }
65
+ : {
66
+ typeName: edge.tail.typeName,
67
+ });
68
+ }
69
+ }
70
+ exports.OperationPath = OperationPath;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Supergraph = void 0;
4
+ const logger_1 = require("../../../../utils/logger");
5
+ const constants_1 = require("./constants");
6
+ const fields_1 = require("./fields");
7
+ const graph_1 = require("./graph");
8
+ const move_validator_1 = require("./move-validator");
9
+ const walker_1 = require("./walker");
10
+ class Supergraph {
11
+ supergraph;
12
+ mergedGraph;
13
+ fieldsResolver;
14
+ moveRequirementChecker;
15
+ logger = new logger_1.Logger('Supergraph', new logger_1.LoggerContext());
16
+ constructor(supergraphState) {
17
+ this.fieldsResolver = new fields_1.FieldsResolver(supergraphState);
18
+ this.supergraph = new graph_1.Graph(this.logger, constants_1.SUPERGRAPH_ID, 'supergraph', supergraphState, this.fieldsResolver, true);
19
+ this.mergedGraph = new graph_1.Graph(this.logger, constants_1.SUPERGRAPH_ID, 'merged', supergraphState, this.fieldsResolver);
20
+ for (const [id, subgraphState] of supergraphState.subgraphs) {
21
+ this.mergedGraph.addSubgraph(new graph_1.Graph(this.logger, id, subgraphState.graph.name, supergraphState, this.fieldsResolver, false)
22
+ .addFromRoots()
23
+ .addFromEntities()
24
+ .addUnreachableTypes());
25
+ }
26
+ this.mergedGraph.joinSubgraphs();
27
+ this.supergraph.addFromRoots();
28
+ this.moveRequirementChecker = new move_validator_1.MoveValidator(this.logger, this.mergedGraph);
29
+ }
30
+ validate() {
31
+ return new walker_1.Walker(this.logger, this.moveRequirementChecker, this.supergraph, this.mergedGraph).walk('dfs');
32
+ }
33
+ validateOperation(operation, steps) {
34
+ return new walker_1.Walker(this.logger, this.moveRequirementChecker, this.supergraph, this.mergedGraph).walkTrail(operation, steps);
35
+ }
36
+ }
37
+ exports.Supergraph = Supergraph;