@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
@@ -15,7 +15,7 @@ const scalar_type_js_1 = require("./composition/scalar-type.js");
15
15
  const union_type_js_1 = require("./composition/union-type.js");
16
16
  function createSupergraphStateBuilder() {
17
17
  const state = {
18
- graphs: new Map(),
18
+ subgraphs: new Map(),
19
19
  scalarTypes: new Map(),
20
20
  objectTypes: new Map(),
21
21
  interfaceTypes: new Map(),
@@ -39,22 +39,21 @@ function createSupergraphStateBuilder() {
39
39
  const interfaceType = (0, interface_type_js_1.interfaceTypeBuilder)();
40
40
  const objectType = (0, object_type_js_1.objectTypeBuilder)();
41
41
  const unionType = (0, union_type_js_1.unionTypeBuilder)();
42
+ const subgraphStates = new Map();
43
+ const graphNameToIdMap = {};
42
44
  return {
43
- addGraph(graph) {
44
- if (state.graphs.has(graph.id)) {
45
- throw new Error(`Graph with ID "${graph.id}" already exists`);
45
+ addSubgraph(subgraph) {
46
+ if (state.subgraphs.has(subgraph.graph.id)) {
47
+ throw new Error(`Graph with ID "${subgraph.graph.id}" already exists`);
46
48
  }
47
- state.graphs.set(graph.id, {
48
- id: graph.id,
49
- name: graph.name,
50
- url: graph.url,
51
- version: graph.version,
52
- });
49
+ state.subgraphs.set(subgraph.graph.id, subgraph);
50
+ graphNameToIdMap[subgraph.graph.name] = subgraph.graph.id;
53
51
  },
54
52
  getGraph(id) {
55
- return state.graphs.get(id);
53
+ return state.subgraphs.get(id);
56
54
  },
57
55
  visitSubgraphState(subgraphState) {
56
+ subgraphStates.set(subgraphState.graph.id, subgraphState);
58
57
  for (const link of subgraphState.links) {
59
58
  state.links.push(linkWithGraph(link, subgraphState.graph.id));
60
59
  }
@@ -109,15 +108,14 @@ function createSupergraphStateBuilder() {
109
108
  getSupergraphState() {
110
109
  return state;
111
110
  },
111
+ getSubgraphState(graphId) {
112
+ return subgraphStates.get(graphId);
113
+ },
112
114
  links() {
113
115
  return (0, link_js_1.mergeLinks)(state.links);
114
116
  },
115
117
  build() {
116
118
  const transformFields = createFieldsTransformer(state);
117
- const graphNameToIdMap = {};
118
- for (const [id, graph] of state.graphs) {
119
- graphNameToIdMap[graph.name] = id;
120
- }
121
119
  const helpers = {
122
120
  graphNameToId(graphName) {
123
121
  return graphNameToIdMap[graphName] ?? null;
@@ -134,31 +132,31 @@ function createSupergraphStateBuilder() {
134
132
  1;
135
133
  const nodes = new Array(numberOfExpectedNodes);
136
134
  let i = 0;
137
- nodes[i++] = (0, ast_js_1.createJoinGraphEnumTypeNode)(Array.from(state.graphs.values()).map(graph => ({
138
- name: graph.name,
139
- enumValue: graph.id,
140
- url: graph.url ?? '',
135
+ nodes[i++] = (0, ast_js_1.createJoinGraphEnumTypeNode)(Array.from(state.subgraphs.values()).map(subgraph => ({
136
+ name: subgraph.graph.name,
137
+ enumValue: subgraph.graph.id,
138
+ url: subgraph.graph.url ?? '',
141
139
  })));
142
140
  for (const directiveState of state.directives.values()) {
143
- nodes[i++] = directive.composeSupergraphNode(directiveState, state.graphs, helpers);
141
+ nodes[i++] = directive.composeSupergraphNode(directiveState, state.subgraphs, helpers);
144
142
  }
145
143
  for (const scalarTypeState of state.scalarTypes.values()) {
146
- nodes[i++] = scalarType.composeSupergraphNode(scalarTypeState, state.graphs, helpers);
144
+ nodes[i++] = scalarType.composeSupergraphNode(scalarTypeState, state.subgraphs, helpers);
147
145
  }
148
146
  for (const objectTypeState of state.objectTypes.values()) {
149
- nodes[i++] = objectType.composeSupergraphNode(transformFields(objectTypeState), state.graphs, helpers);
147
+ nodes[i++] = objectType.composeSupergraphNode(transformFields(objectTypeState), state.subgraphs, helpers);
150
148
  }
151
149
  for (const interfaceTypeState of state.interfaceTypes.values()) {
152
- nodes[i++] = interfaceType.composeSupergraphNode(interfaceTypeState, state.graphs, helpers);
150
+ nodes[i++] = interfaceType.composeSupergraphNode(interfaceTypeState, state.subgraphs, helpers);
153
151
  }
154
152
  for (const unionTypeState of state.unionTypes.values()) {
155
- nodes[i++] = unionType.composeSupergraphNode(unionTypeState, state.graphs, helpers);
153
+ nodes[i++] = unionType.composeSupergraphNode(unionTypeState, state.subgraphs, helpers);
156
154
  }
157
155
  for (const enumTypeState of state.enumTypes.values()) {
158
- nodes[i++] = enumType.composeSupergraphNode(enumTypeState, state.graphs, helpers);
156
+ nodes[i++] = enumType.composeSupergraphNode(enumTypeState, state.subgraphs, helpers);
159
157
  }
160
158
  for (const inputObjectTypeState of state.inputObjectTypes.values()) {
161
- nodes[i++] = inputObjectType.composeSupergraphNode(inputObjectTypeState, state.graphs, helpers);
159
+ nodes[i++] = inputObjectType.composeSupergraphNode(inputObjectTypeState, state.subgraphs, helpers);
162
160
  }
163
161
  return nodes;
164
162
  },
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FieldsOfTheSameTypeRule = void 0;
4
4
  const graphql_1 = require("graphql");
5
+ const state_js_1 = require("../../../subgraph/state.js");
5
6
  function stripNonNull(type) {
6
7
  return type.replace(/!$/, '');
7
8
  }
@@ -36,7 +37,28 @@ function FieldsOfTheSameTypeRule(context) {
36
37
  return {
37
38
  ObjectTypeField(objectTypeState, fieldState) {
38
39
  const typeToGraphs = new Map();
40
+ const typeNameToPossibleTypeNames = new Map();
39
41
  fieldState.byGraph.forEach((field, graphName) => {
42
+ const typeName = field.type.replaceAll('!', '').replaceAll('[', '').replaceAll(']', '');
43
+ const typeState = context.subgraphStates.get(graphName)?.types.get(typeName);
44
+ if (typeState?.kind === state_js_1.TypeKind.UNION) {
45
+ if (!typeNameToPossibleTypeNames.has(typeName)) {
46
+ typeNameToPossibleTypeNames.set(typeName, new Set());
47
+ }
48
+ const list = typeNameToPossibleTypeNames.get(typeName);
49
+ typeState.members.forEach(member => {
50
+ list.add(member);
51
+ });
52
+ }
53
+ else if (typeState?.kind === state_js_1.TypeKind.INTERFACE) {
54
+ if (!typeNameToPossibleTypeNames.has(typeName)) {
55
+ typeNameToPossibleTypeNames.set(typeName, new Set());
56
+ }
57
+ const list = typeNameToPossibleTypeNames.get(typeName);
58
+ typeState.implementedBy.forEach(member => {
59
+ list.add(member);
60
+ });
61
+ }
40
62
  const normalizedOutputTypes = normalizeOutputTypeStrings({
41
63
  superType: fieldState.type,
42
64
  localType: field.type,
@@ -53,6 +75,19 @@ function FieldsOfTheSameTypeRule(context) {
53
75
  }
54
76
  });
55
77
  if (typeToGraphs.size > 1) {
78
+ if (typeNameToPossibleTypeNames.size === 1) {
79
+ const possibleTypeNames = [];
80
+ typeNameToPossibleTypeNames.forEach((list, unionOrInterfaceName) => {
81
+ possibleTypeNames.push(unionOrInterfaceName);
82
+ for (const typeName of list) {
83
+ possibleTypeNames.push(typeName);
84
+ }
85
+ });
86
+ const outputTypeNames = Array.from(typeToGraphs.keys()).map(t => t.replaceAll('!', '').replaceAll('[', '').replaceAll(']', ''));
87
+ if (outputTypeNames.every(t => possibleTypeNames.includes(t))) {
88
+ return;
89
+ }
90
+ }
56
91
  const groups = Array.from(typeToGraphs.entries()).map(([outputType, graphs]) => {
57
92
  const plural = graphs.length > 1 ? 's' : '';
58
93
  return `type "${outputType}" in subgraph${plural} "${graphs
@@ -36,7 +36,10 @@ function InvalidFieldSharingRule(context) {
36
36
  continue;
37
37
  }
38
38
  }
39
- if (fieldIsShareable || fieldIsUsedAsKey) {
39
+ const fedV1FieldInExtension = field.version === 'v1.0' && field.extension;
40
+ if (fieldIsShareable ||
41
+ fieldIsUsedAsKey ||
42
+ (objectTypeState.isEntity && fedV1FieldInExtension)) {
40
43
  resolvableIn.push(graphId);
41
44
  continue;
42
45
  }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SUPERGRAPH_ID = void 0;
4
+ exports.SUPERGRAPH_ID = Symbol('__supergraph__');
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Edge = exports.assertFieldEdge = exports.isFieldEdge = exports.assertAbstractEdge = exports.isAbstractEdge = exports.assertEntityEdge = exports.isEntityEdge = void 0;
4
+ const helpers_1 = require("./helpers");
5
+ const moves_1 = require("./moves");
6
+ function isEntityEdge(edge) {
7
+ return edge.move instanceof moves_1.EntityMove;
8
+ }
9
+ exports.isEntityEdge = isEntityEdge;
10
+ function assertEntityEdge(edge) {
11
+ if (!isEntityEdge(edge)) {
12
+ throw new Error(`Expected edge to be Edge<EntityMove>, but got ${edge}`);
13
+ }
14
+ }
15
+ exports.assertEntityEdge = assertEntityEdge;
16
+ function isAbstractEdge(edge) {
17
+ return edge.move instanceof moves_1.AbstractMove;
18
+ }
19
+ exports.isAbstractEdge = isAbstractEdge;
20
+ function assertAbstractEdge(edge) {
21
+ if (!isAbstractEdge(edge)) {
22
+ throw new Error(`Expected edge to be Edge<AbstractMove>, but got ${edge}`);
23
+ }
24
+ }
25
+ exports.assertAbstractEdge = assertAbstractEdge;
26
+ function isFieldEdge(edge) {
27
+ return edge.move instanceof moves_1.FieldMove;
28
+ }
29
+ exports.isFieldEdge = isFieldEdge;
30
+ function assertFieldEdge(edge) {
31
+ if (!isFieldEdge(edge)) {
32
+ throw new Error(`Expected edge to be Edge<FieldMove>, but got ${edge}`);
33
+ }
34
+ }
35
+ exports.assertFieldEdge = assertFieldEdge;
36
+ class Edge {
37
+ head;
38
+ move;
39
+ tail;
40
+ resolvable = [];
41
+ _toString = (0, helpers_1.lazy)(() => `${this.head} -(${this.move})-> ${this.tail}`);
42
+ constructor(head, move, tail) {
43
+ this.head = head;
44
+ this.move = move;
45
+ this.tail = tail;
46
+ }
47
+ isCrossGraphEdge() {
48
+ return this.head.graphId !== this.tail.graphId;
49
+ }
50
+ toString() {
51
+ return this._toString.get();
52
+ }
53
+ getResolvability(graphNames) {
54
+ return this.resolvable.find(([checkedGraphNames]) => {
55
+ return checkedGraphNames.every(name => graphNames.includes(name));
56
+ })?.[1];
57
+ }
58
+ setResolvable(success, graphNames, error) {
59
+ const result = success ? { success, error: undefined } : { success, error: error };
60
+ this.resolvable.push([graphNames, result]);
61
+ return result;
62
+ }
63
+ }
64
+ exports.Edge = Edge;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SatisfiabilityError = void 0;
4
+ class SatisfiabilityError extends Error {
5
+ kind;
6
+ sourceGraphName;
7
+ typeName;
8
+ fieldName;
9
+ static forKey(sourceGraphName, targetGraphName, typeName, keyFields) {
10
+ return new SatisfiabilityError('KEY', sourceGraphName, typeName, null, `cannot move to subgraph "${targetGraphName}" using @key(fields: "${keyFields}") of "${typeName}", the key field(s) cannot be resolved from subgraph "${sourceGraphName}".`);
11
+ }
12
+ static forRequire(sourceGraphName, typeName, fieldName) {
13
+ return new SatisfiabilityError('REQUIRE', sourceGraphName, typeName, fieldName, `cannot satisfy @require conditions on field "${typeName}.${fieldName}".`);
14
+ }
15
+ static forExternal(sourceGraphName, typeName, fieldName) {
16
+ return new SatisfiabilityError('EXTERNAL', sourceGraphName, typeName, fieldName, `field "${typeName}.${fieldName}" is not resolvable because marked @external.`);
17
+ }
18
+ static forMissingField(sourceGraphName, typeName, fieldName) {
19
+ return new SatisfiabilityError('MISSING_FIELD', sourceGraphName, typeName, fieldName, `cannot find field "${typeName}.${fieldName}".`);
20
+ }
21
+ static forNoKey(sourceGraphName, targetGraphName, typeName, fieldName) {
22
+ return new SatisfiabilityError('NO_KEY', sourceGraphName, typeName, fieldName, `cannot move to subgraph "${targetGraphName}", which has field "${typeName}.${fieldName}", because type "${typeName}" has no @key defined in subgraph "${targetGraphName}".`);
23
+ }
24
+ constructor(kind, sourceGraphName, typeName, fieldName, message) {
25
+ super(message);
26
+ this.kind = kind;
27
+ this.sourceGraphName = sourceGraphName;
28
+ this.typeName = typeName;
29
+ this.fieldName = fieldName;
30
+ }
31
+ isMatchingField(typeName, fieldName) {
32
+ if (this.typeName !== typeName) {
33
+ return false;
34
+ }
35
+ if (this.fieldName) {
36
+ return this.fieldName === fieldName;
37
+ }
38
+ return true;
39
+ }
40
+ toString() {
41
+ return this.message;
42
+ }
43
+ }
44
+ exports.SatisfiabilityError = SatisfiabilityError;
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FieldsResolver = exports.Fields = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const helpers_1 = require("../../../../subgraph/helpers");
6
+ const state_1 = require("../../../../utils/state");
7
+ class Fields {
8
+ typeName;
9
+ source;
10
+ fields;
11
+ constructor(typeName, source, fields) {
12
+ this.typeName = typeName;
13
+ this.source = source;
14
+ this.fields = fields;
15
+ }
16
+ contains(typeName, fieldName) {
17
+ return this._contains(typeName, fieldName, this.fields);
18
+ }
19
+ equals(other) {
20
+ if (this.typeName !== other.typeName) {
21
+ return false;
22
+ }
23
+ if (this.source === other.source) {
24
+ return true;
25
+ }
26
+ return this._fieldsEqual(this.fields, other.fields);
27
+ }
28
+ _fieldsEqual(fields, otherFields) {
29
+ if (fields.length !== otherFields.length) {
30
+ return false;
31
+ }
32
+ for (let i = 0; i < fields.length; i++) {
33
+ const field = fields[i];
34
+ const otherField = otherFields[i];
35
+ if (field.typeName !== otherField.typeName || field.fieldName !== otherField.fieldName) {
36
+ return false;
37
+ }
38
+ const areEqual = Array.isArray(field.selectionSet) && Array.isArray(otherField.selectionSet)
39
+ ? this._fieldsEqual(field.selectionSet, otherField.selectionSet)
40
+ : field.selectionSet === otherField.selectionSet;
41
+ if (!areEqual) {
42
+ return false;
43
+ }
44
+ }
45
+ return true;
46
+ }
47
+ _contains(typeName, fieldName, fields) {
48
+ return fields.some(f => (f.typeName === typeName && f.fieldName === fieldName) ||
49
+ (f.selectionSet ? this._contains(typeName, fieldName, f.selectionSet) : false));
50
+ }
51
+ toString() {
52
+ return this.source;
53
+ }
54
+ }
55
+ exports.Fields = Fields;
56
+ class FieldsResolver {
57
+ supergraphState;
58
+ cache = new Map();
59
+ constructor(supergraphState) {
60
+ this.supergraphState = supergraphState;
61
+ }
62
+ resolve(typeName, keyFields) {
63
+ const key = this.keyFactory(typeName, keyFields);
64
+ if (this.cache.has(key)) {
65
+ return this.cache.get(key);
66
+ }
67
+ const typeState = this.supergraphState.objectTypes.get(typeName);
68
+ if (!typeState) {
69
+ throw new Error(`Expected an object type when resolving keyFields of ${typeName}`);
70
+ }
71
+ const selectionSetNode = (0, helpers_1.parseFields)(keyFields);
72
+ if (!selectionSetNode) {
73
+ throw new Error(`Expected a selection set when resolving keyFields of ${typeName}`);
74
+ }
75
+ const fields = new Fields(typeName, keyFields, this.resolveSelectionSetNode(typeName, selectionSetNode));
76
+ this.cache.set(key, fields);
77
+ return fields;
78
+ }
79
+ keyFactory(typeName, keyFields) {
80
+ return `${typeName}/${keyFields}`;
81
+ }
82
+ resolveFieldNode(typeName, fieldNode, fields) {
83
+ const typeState = this.supergraphState.objectTypes.get(typeName) ??
84
+ this.supergraphState.interfaceTypes.get(typeName);
85
+ if (!typeState) {
86
+ throw new Error(`Type "${typeName}" is not defined.`);
87
+ }
88
+ if (fieldNode.name.value === '__typename') {
89
+ return;
90
+ }
91
+ if (!typeState.fields.has(fieldNode.name.value)) {
92
+ throw new Error(`Type "${typeName.toString()}" does not have field "${fieldNode.name.value}".`);
93
+ }
94
+ if (fieldNode.selectionSet) {
95
+ const outputType = (0, state_1.stripTypeModifiers)(typeState.fields.get(fieldNode.name.value).type);
96
+ fields.push({
97
+ fieldName: fieldNode.name.value,
98
+ typeName,
99
+ selectionSet: this.resolveSelectionSetNode(outputType, fieldNode.selectionSet),
100
+ });
101
+ }
102
+ else {
103
+ fields.push({
104
+ typeName,
105
+ fieldName: fieldNode.name.value,
106
+ selectionSet: null,
107
+ });
108
+ }
109
+ }
110
+ resolveInlineFragmentNode(fragmentNode, fields) {
111
+ if (!fragmentNode.typeCondition?.name.value) {
112
+ throw new Error(`Inline fragment without type condition is not supported.`);
113
+ }
114
+ const typeName = fragmentNode.typeCondition.name.value;
115
+ const typeState = this.supergraphState.objectTypes.get(typeName) ??
116
+ this.supergraphState.interfaceTypes.get(typeName);
117
+ if (!typeState) {
118
+ throw new Error(`Type "${typeName}" is not defined.`);
119
+ }
120
+ for (const selection of fragmentNode.selectionSet.selections) {
121
+ if (selection.kind === graphql_1.Kind.FIELD) {
122
+ this.resolveFieldNode(typeName, selection, fields);
123
+ }
124
+ else {
125
+ throw new Error(`Inline fragment within an inline fragment is not supported.`);
126
+ }
127
+ }
128
+ }
129
+ resolveSelectionSetNode(typeName, selectionSetNode, fields = []) {
130
+ for (const selection of selectionSetNode.selections) {
131
+ if (selection.kind === graphql_1.Kind.FIELD) {
132
+ this.resolveFieldNode(typeName, selection, fields);
133
+ }
134
+ else if (selection.kind === graphql_1.Kind.INLINE_FRAGMENT) {
135
+ this.resolveInlineFragmentNode(selection, fields);
136
+ }
137
+ else {
138
+ throw new Error(`Fragment spread is not supported.`);
139
+ }
140
+ }
141
+ return this.sortFields(fields);
142
+ }
143
+ sortFields(fields) {
144
+ return fields.sort((a, b) => `${a.typeName}.${a.fieldName}`.localeCompare(`${b.typeName}.${b.fieldName}`));
145
+ }
146
+ }
147
+ exports.FieldsResolver = FieldsResolver;