@apollo/gateway 0.300.0-alpha.2 → 2.0.0-alpha.2

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 (198) hide show
  1. package/LICENSE +95 -0
  2. package/README.md +1 -1
  3. package/dist/__generated__/graphqlTypes.d.ts +130 -0
  4. package/dist/__generated__/graphqlTypes.d.ts.map +1 -0
  5. package/dist/__generated__/graphqlTypes.js +25 -0
  6. package/dist/__generated__/graphqlTypes.js.map +1 -0
  7. package/dist/config.d.ts +104 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +47 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/datasources/LocalGraphQLDataSource.d.ts +3 -3
  12. package/dist/datasources/LocalGraphQLDataSource.d.ts.map +1 -1
  13. package/dist/datasources/LocalGraphQLDataSource.js +5 -5
  14. package/dist/datasources/LocalGraphQLDataSource.js.map +1 -1
  15. package/dist/datasources/RemoteGraphQLDataSource.d.ts +6 -4
  16. package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
  17. package/dist/datasources/RemoteGraphQLDataSource.js +60 -17
  18. package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
  19. package/dist/datasources/index.d.ts +1 -1
  20. package/dist/datasources/index.d.ts.map +1 -1
  21. package/dist/datasources/index.js +1 -0
  22. package/dist/datasources/index.js.map +1 -1
  23. package/dist/datasources/parseCacheControlHeader.d.ts +2 -0
  24. package/dist/datasources/parseCacheControlHeader.d.ts.map +1 -0
  25. package/dist/datasources/parseCacheControlHeader.js +16 -0
  26. package/dist/datasources/parseCacheControlHeader.js.map +1 -0
  27. package/dist/datasources/types.d.ts +16 -1
  28. package/dist/datasources/types.d.ts.map +1 -1
  29. package/dist/datasources/types.js +7 -0
  30. package/dist/datasources/types.js.map +1 -1
  31. package/dist/executeQueryPlan.d.ts +2 -1
  32. package/dist/executeQueryPlan.d.ts.map +1 -1
  33. package/dist/executeQueryPlan.js +199 -112
  34. package/dist/executeQueryPlan.js.map +1 -1
  35. package/dist/index.d.ts +62 -80
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +543 -234
  38. package/dist/index.js.map +1 -1
  39. package/dist/loadServicesFromRemoteEndpoint.d.ts +9 -9
  40. package/dist/loadServicesFromRemoteEndpoint.d.ts.map +1 -1
  41. package/dist/loadServicesFromRemoteEndpoint.js +13 -8
  42. package/dist/loadServicesFromRemoteEndpoint.js.map +1 -1
  43. package/dist/loadSupergraphSdlFromStorage.d.ts +13 -0
  44. package/dist/loadSupergraphSdlFromStorage.d.ts.map +1 -0
  45. package/dist/loadSupergraphSdlFromStorage.js +101 -0
  46. package/dist/loadSupergraphSdlFromStorage.js.map +1 -0
  47. package/dist/operationContext.d.ts +17 -0
  48. package/dist/operationContext.d.ts.map +1 -0
  49. package/dist/operationContext.js +42 -0
  50. package/dist/operationContext.js.map +1 -0
  51. package/dist/outOfBandReporter.d.ts +15 -0
  52. package/dist/outOfBandReporter.d.ts.map +1 -0
  53. package/dist/outOfBandReporter.js +88 -0
  54. package/dist/outOfBandReporter.js.map +1 -0
  55. package/dist/utilities/array.d.ts +1 -2
  56. package/dist/utilities/array.d.ts.map +1 -1
  57. package/dist/utilities/array.js +7 -14
  58. package/dist/utilities/array.js.map +1 -1
  59. package/dist/utilities/assert.d.ts +2 -0
  60. package/dist/utilities/assert.d.ts.map +1 -0
  61. package/dist/utilities/assert.js +10 -0
  62. package/dist/utilities/assert.js.map +1 -0
  63. package/dist/utilities/cleanErrorOfInaccessibleNames.d.ts +3 -0
  64. package/dist/utilities/cleanErrorOfInaccessibleNames.d.ts.map +1 -0
  65. package/dist/utilities/cleanErrorOfInaccessibleNames.js +27 -0
  66. package/dist/utilities/cleanErrorOfInaccessibleNames.js.map +1 -0
  67. package/dist/utilities/deepMerge.js +2 -2
  68. package/dist/utilities/deepMerge.js.map +1 -1
  69. package/dist/utilities/graphql.d.ts +1 -4
  70. package/dist/utilities/graphql.d.ts.map +1 -1
  71. package/dist/utilities/graphql.js +3 -36
  72. package/dist/utilities/graphql.js.map +1 -1
  73. package/dist/utilities/opentelemetry.d.ts +10 -0
  74. package/dist/utilities/opentelemetry.d.ts.map +1 -0
  75. package/dist/utilities/opentelemetry.js +19 -0
  76. package/dist/utilities/opentelemetry.js.map +1 -0
  77. package/package.json +30 -21
  78. package/src/__generated__/graphqlTypes.ts +140 -0
  79. package/src/__mocks__/apollo-server-env.ts +56 -0
  80. package/src/__mocks__/make-fetch-happen-fetcher.ts +55 -0
  81. package/src/__mocks__/tsconfig.json +7 -0
  82. package/src/__tests__/build-query-plan.feature +40 -311
  83. package/src/__tests__/buildQueryPlan.test.ts +246 -426
  84. package/src/__tests__/executeQueryPlan.test.ts +1691 -194
  85. package/src/__tests__/execution-utils.ts +33 -26
  86. package/src/__tests__/gateway/__snapshots__/opentelemetry.test.ts.snap +195 -0
  87. package/src/__tests__/gateway/buildService.test.ts +16 -19
  88. package/src/__tests__/gateway/composedSdl.test.ts +44 -0
  89. package/src/__tests__/gateway/endToEnd.test.ts +166 -0
  90. package/src/__tests__/gateway/executor.test.ts +49 -43
  91. package/src/__tests__/gateway/lifecycle-hooks.test.ts +58 -29
  92. package/src/__tests__/gateway/opentelemetry.test.ts +123 -0
  93. package/src/__tests__/gateway/queryPlanCache.test.ts +19 -20
  94. package/src/__tests__/gateway/reporting.test.ts +76 -55
  95. package/src/__tests__/integration/abstract-types.test.ts +1086 -22
  96. package/src/__tests__/integration/aliases.test.ts +5 -6
  97. package/src/__tests__/integration/boolean.test.ts +40 -38
  98. package/src/__tests__/integration/complex-key.test.ts +41 -56
  99. package/src/__tests__/integration/configuration.test.ts +321 -0
  100. package/src/__tests__/integration/custom-directives.test.ts +61 -46
  101. package/src/__tests__/integration/fragments.test.ts +8 -2
  102. package/src/__tests__/integration/list-key.test.ts +2 -2
  103. package/src/__tests__/integration/logger.test.ts +2 -2
  104. package/src/__tests__/integration/multiple-key.test.ts +11 -12
  105. package/src/__tests__/integration/mutations.test.ts +8 -5
  106. package/src/__tests__/integration/networkRequests.test.ts +447 -289
  107. package/src/__tests__/integration/nockMocks.ts +95 -66
  108. package/src/__tests__/integration/provides.test.ts +9 -6
  109. package/src/__tests__/integration/requires.test.ts +17 -15
  110. package/src/__tests__/integration/scope.test.ts +557 -0
  111. package/src/__tests__/integration/unions.test.ts +1 -1
  112. package/src/__tests__/integration/value-types.test.ts +35 -32
  113. package/src/__tests__/integration/variables.test.ts +8 -2
  114. package/src/__tests__/loadServicesFromRemoteEndpoint.test.ts +6 -2
  115. package/src/__tests__/loadSupergraphSdlFromStorage.test.ts +694 -0
  116. package/src/__tests__/queryPlanCucumber.test.ts +11 -61
  117. package/src/__tests__/testSetup.ts +1 -4
  118. package/src/__tests__/tsconfig.json +2 -1
  119. package/src/config.ts +225 -0
  120. package/src/core/__tests__/core.test.ts +412 -0
  121. package/src/datasources/LocalGraphQLDataSource.ts +9 -10
  122. package/src/datasources/RemoteGraphQLDataSource.ts +117 -43
  123. package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +11 -4
  124. package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +148 -79
  125. package/src/datasources/__tests__/tsconfig.json +4 -2
  126. package/src/datasources/index.ts +1 -1
  127. package/src/datasources/parseCacheControlHeader.ts +43 -0
  128. package/src/datasources/types.ts +47 -2
  129. package/src/executeQueryPlan.ts +264 -153
  130. package/src/index.ts +925 -480
  131. package/src/loadServicesFromRemoteEndpoint.ts +24 -17
  132. package/src/loadSupergraphSdlFromStorage.ts +140 -0
  133. package/src/make-fetch-happen.d.ts +2 -2
  134. package/src/operationContext.ts +70 -0
  135. package/src/outOfBandReporter.ts +128 -0
  136. package/src/utilities/__tests__/cleanErrorOfInaccessibleElements.test.ts +104 -0
  137. package/src/utilities/__tests__/tsconfig.json +8 -0
  138. package/src/utilities/array.ts +6 -28
  139. package/src/utilities/assert.ts +14 -0
  140. package/src/utilities/cleanErrorOfInaccessibleNames.ts +29 -0
  141. package/src/utilities/graphql.ts +0 -64
  142. package/src/utilities/opentelemetry.ts +13 -0
  143. package/CHANGELOG.md +0 -226
  144. package/LICENSE.md +0 -20
  145. package/dist/FieldSet.d.ts +0 -18
  146. package/dist/FieldSet.d.ts.map +0 -1
  147. package/dist/FieldSet.js +0 -96
  148. package/dist/FieldSet.js.map +0 -1
  149. package/dist/QueryPlan.d.ts +0 -41
  150. package/dist/QueryPlan.d.ts.map +0 -1
  151. package/dist/QueryPlan.js +0 -15
  152. package/dist/QueryPlan.js.map +0 -1
  153. package/dist/buildQueryPlan.d.ts +0 -44
  154. package/dist/buildQueryPlan.d.ts.map +0 -1
  155. package/dist/buildQueryPlan.js +0 -670
  156. package/dist/buildQueryPlan.js.map +0 -1
  157. package/dist/loadServicesFromStorage.d.ts +0 -21
  158. package/dist/loadServicesFromStorage.d.ts.map +0 -1
  159. package/dist/loadServicesFromStorage.js +0 -64
  160. package/dist/loadServicesFromStorage.js.map +0 -1
  161. package/dist/snapshotSerializers/astSerializer.d.ts +0 -3
  162. package/dist/snapshotSerializers/astSerializer.d.ts.map +0 -1
  163. package/dist/snapshotSerializers/astSerializer.js +0 -14
  164. package/dist/snapshotSerializers/astSerializer.js.map +0 -1
  165. package/dist/snapshotSerializers/index.d.ts +0 -13
  166. package/dist/snapshotSerializers/index.d.ts.map +0 -1
  167. package/dist/snapshotSerializers/index.js +0 -15
  168. package/dist/snapshotSerializers/index.js.map +0 -1
  169. package/dist/snapshotSerializers/queryPlanSerializer.d.ts +0 -3
  170. package/dist/snapshotSerializers/queryPlanSerializer.d.ts.map +0 -1
  171. package/dist/snapshotSerializers/queryPlanSerializer.js +0 -78
  172. package/dist/snapshotSerializers/queryPlanSerializer.js.map +0 -1
  173. package/dist/snapshotSerializers/selectionSetSerializer.d.ts +0 -3
  174. package/dist/snapshotSerializers/selectionSetSerializer.d.ts.map +0 -1
  175. package/dist/snapshotSerializers/selectionSetSerializer.js +0 -12
  176. package/dist/snapshotSerializers/selectionSetSerializer.js.map +0 -1
  177. package/dist/snapshotSerializers/typeSerializer.d.ts +0 -3
  178. package/dist/snapshotSerializers/typeSerializer.d.ts.map +0 -1
  179. package/dist/snapshotSerializers/typeSerializer.js +0 -12
  180. package/dist/snapshotSerializers/typeSerializer.js.map +0 -1
  181. package/dist/utilities/MultiMap.d.ts +0 -4
  182. package/dist/utilities/MultiMap.d.ts.map +0 -1
  183. package/dist/utilities/MultiMap.js +0 -17
  184. package/dist/utilities/MultiMap.js.map +0 -1
  185. package/src/FieldSet.ts +0 -169
  186. package/src/QueryPlan.ts +0 -57
  187. package/src/__tests__/matchers/toCallService.ts +0 -105
  188. package/src/__tests__/matchers/toHaveBeenCalledBefore.ts +0 -40
  189. package/src/__tests__/matchers/toHaveFetched.ts +0 -81
  190. package/src/__tests__/matchers/toMatchAST.ts +0 -64
  191. package/src/buildQueryPlan.ts +0 -1190
  192. package/src/loadServicesFromStorage.ts +0 -170
  193. package/src/snapshotSerializers/astSerializer.ts +0 -21
  194. package/src/snapshotSerializers/index.ts +0 -21
  195. package/src/snapshotSerializers/queryPlanSerializer.ts +0 -144
  196. package/src/snapshotSerializers/selectionSetSerializer.ts +0 -13
  197. package/src/snapshotSerializers/typeSerializer.ts +0 -11
  198. package/src/utilities/MultiMap.ts +0 -11
@@ -1,670 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QueryPlanningContext = exports.buildQueryPlanningContext = exports.buildOperationContext = exports.collectSubfields = exports.buildQueryPlan = void 0;
4
- const apollo_env_1 = require("apollo-env");
5
- const graphql_1 = require("graphql");
6
- const FieldSet_1 = require("./FieldSet");
7
- const graphql_2 = require("./utilities/graphql");
8
- const MultiMap_1 = require("./utilities/MultiMap");
9
- const utils_1 = require("@apollo/federation/dist/composition/utils");
10
- const typenameField = {
11
- kind: graphql_1.Kind.FIELD,
12
- name: {
13
- kind: graphql_1.Kind.NAME,
14
- value: graphql_1.TypeNameMetaFieldDef.name,
15
- },
16
- };
17
- function buildQueryPlan(operationContext, options = { autoFragmentization: false }) {
18
- const context = buildQueryPlanningContext(operationContext, options);
19
- if (context.operation.operation === 'subscription') {
20
- throw new graphql_1.GraphQLError('Query planning does not support subscriptions for now.', [context.operation]);
21
- }
22
- const rootType = graphql_1.getOperationRootType(context.schema, context.operation);
23
- const isMutation = context.operation.operation === 'mutation';
24
- const fields = collectFields(context, context.newScope(rootType), context.operation.selectionSet);
25
- const groups = isMutation
26
- ? splitRootFieldsSerially(context, fields)
27
- : splitRootFields(context, fields);
28
- const nodes = groups.map(group => executionNodeForGroup(context, group, rootType));
29
- return {
30
- kind: 'QueryPlan',
31
- node: nodes.length
32
- ? flatWrap(isMutation ? 'Sequence' : 'Parallel', nodes)
33
- : undefined,
34
- };
35
- }
36
- exports.buildQueryPlan = buildQueryPlan;
37
- function executionNodeForGroup(context, { serviceName, fields, requiredFields, internalFragments, mergeAt, dependentGroups, }, parentType) {
38
- const selectionSet = FieldSet_1.selectionSetFromFieldSet(fields, parentType);
39
- const requires = requiredFields.length > 0
40
- ? FieldSet_1.selectionSetFromFieldSet(requiredFields)
41
- : undefined;
42
- const variableUsages = context.getVariableUsages(selectionSet, internalFragments);
43
- const operation = requires
44
- ? operationForEntitiesFetch({
45
- selectionSet,
46
- variableUsages,
47
- internalFragments,
48
- })
49
- : operationForRootFetch({
50
- selectionSet,
51
- variableUsages,
52
- internalFragments,
53
- operation: context.operation.operation,
54
- });
55
- const fetchNode = {
56
- kind: 'Fetch',
57
- serviceName,
58
- selectionSet,
59
- requires,
60
- variableUsages,
61
- internalFragments,
62
- source: graphql_1.stripIgnoredCharacters(graphql_1.print(operation)),
63
- };
64
- const node = mergeAt && mergeAt.length > 0
65
- ? {
66
- kind: 'Flatten',
67
- path: mergeAt,
68
- node: fetchNode,
69
- }
70
- : fetchNode;
71
- if (dependentGroups.length > 0) {
72
- const dependentNodes = dependentGroups.map(dependentGroup => executionNodeForGroup(context, dependentGroup));
73
- return flatWrap('Sequence', [node, flatWrap('Parallel', dependentNodes)]);
74
- }
75
- else {
76
- return node;
77
- }
78
- }
79
- function mapFetchNodeToVariableDefinitions(variableUsages) {
80
- return variableUsages ? Object.values(variableUsages) : [];
81
- }
82
- function operationForRootFetch({ selectionSet, variableUsages, internalFragments, operation = 'query', }) {
83
- return {
84
- kind: graphql_1.Kind.DOCUMENT,
85
- definitions: [
86
- {
87
- kind: graphql_1.Kind.OPERATION_DEFINITION,
88
- operation,
89
- selectionSet,
90
- variableDefinitions: mapFetchNodeToVariableDefinitions(variableUsages),
91
- },
92
- ...internalFragments,
93
- ],
94
- };
95
- }
96
- function operationForEntitiesFetch({ selectionSet, variableUsages, internalFragments, }) {
97
- const representationsVariable = {
98
- kind: graphql_1.Kind.VARIABLE,
99
- name: { kind: graphql_1.Kind.NAME, value: 'representations' },
100
- };
101
- return {
102
- kind: graphql_1.Kind.DOCUMENT,
103
- definitions: [
104
- {
105
- kind: graphql_1.Kind.OPERATION_DEFINITION,
106
- operation: 'query',
107
- variableDefinitions: [
108
- {
109
- kind: graphql_1.Kind.VARIABLE_DEFINITION,
110
- variable: representationsVariable,
111
- type: {
112
- kind: graphql_1.Kind.NON_NULL_TYPE,
113
- type: {
114
- kind: graphql_1.Kind.LIST_TYPE,
115
- type: {
116
- kind: graphql_1.Kind.NON_NULL_TYPE,
117
- type: {
118
- kind: graphql_1.Kind.NAMED_TYPE,
119
- name: { kind: graphql_1.Kind.NAME, value: '_Any' },
120
- },
121
- },
122
- },
123
- },
124
- },
125
- ].concat(mapFetchNodeToVariableDefinitions(variableUsages)),
126
- selectionSet: {
127
- kind: graphql_1.Kind.SELECTION_SET,
128
- selections: [
129
- {
130
- kind: graphql_1.Kind.FIELD,
131
- name: { kind: graphql_1.Kind.NAME, value: '_entities' },
132
- arguments: [
133
- {
134
- kind: graphql_1.Kind.ARGUMENT,
135
- name: {
136
- kind: graphql_1.Kind.NAME,
137
- value: representationsVariable.name.value,
138
- },
139
- value: representationsVariable,
140
- },
141
- ],
142
- selectionSet,
143
- },
144
- ],
145
- },
146
- },
147
- ...internalFragments,
148
- ],
149
- };
150
- }
151
- function flatWrap(kind, nodes) {
152
- if (nodes.length === 0) {
153
- throw Error('programming error: should always be called with nodes');
154
- }
155
- if (nodes.length === 1) {
156
- return nodes[0];
157
- }
158
- return {
159
- kind,
160
- nodes: nodes.flatMap(n => (n.kind === kind ? n.nodes : [n])),
161
- };
162
- }
163
- function splitRootFields(context, fields) {
164
- const groupsByService = Object.create(null);
165
- function groupForService(serviceName) {
166
- let group = groupsByService[serviceName];
167
- if (!group) {
168
- group = new FetchGroup(serviceName);
169
- groupsByService[serviceName] = group;
170
- }
171
- return group;
172
- }
173
- splitFields(context, [], fields, field => {
174
- const { scope, fieldNode, fieldDef } = field;
175
- const { parentType } = scope;
176
- const owningService = context.getOwningService(parentType, fieldDef);
177
- if (!owningService) {
178
- throw new graphql_1.GraphQLError(`Couldn't find owning service for field "${parentType.name}.${fieldDef.name}"`, fieldNode);
179
- }
180
- return groupForService(owningService);
181
- });
182
- return Object.values(groupsByService);
183
- }
184
- function splitRootFieldsSerially(context, fields) {
185
- const fetchGroups = [];
186
- function groupForField(serviceName) {
187
- let group;
188
- const previousGroup = fetchGroups[fetchGroups.length - 1];
189
- if (previousGroup && previousGroup.serviceName === serviceName) {
190
- return previousGroup;
191
- }
192
- group = new FetchGroup(serviceName);
193
- fetchGroups.push(group);
194
- return group;
195
- }
196
- splitFields(context, [], fields, field => {
197
- const { scope, fieldNode, fieldDef } = field;
198
- const { parentType } = scope;
199
- const owningService = context.getOwningService(parentType, fieldDef);
200
- if (!owningService) {
201
- throw new graphql_1.GraphQLError(`Couldn't find owning service for field "${parentType.name}.${fieldDef.name}"`, fieldNode);
202
- }
203
- return groupForField(owningService);
204
- });
205
- return fetchGroups;
206
- }
207
- function splitSubfields(context, path, fields, parentGroup) {
208
- splitFields(context, path, fields, field => {
209
- const { scope, fieldNode, fieldDef } = field;
210
- const { parentType } = scope;
211
- let baseService, owningService;
212
- const parentTypeFederationMetadata = utils_1.getFederationMetadata(parentType);
213
- if (parentTypeFederationMetadata === null || parentTypeFederationMetadata === void 0 ? void 0 : parentTypeFederationMetadata.isValueType) {
214
- baseService = parentGroup.serviceName;
215
- owningService = parentGroup.serviceName;
216
- }
217
- else {
218
- baseService = context.getBaseService(parentType);
219
- owningService = context.getOwningService(parentType, fieldDef);
220
- }
221
- if (!baseService) {
222
- throw new graphql_1.GraphQLError(`Couldn't find base service for type "${parentType.name}"`, fieldNode);
223
- }
224
- if (!owningService) {
225
- throw new graphql_1.GraphQLError(`Couldn't find owning service for field "${parentType.name}.${fieldDef.name}"`, fieldNode);
226
- }
227
- if (owningService === baseService) {
228
- if (owningService === parentGroup.serviceName ||
229
- parentGroup.providedFields.some(FieldSet_1.matchesField(field))) {
230
- return parentGroup;
231
- }
232
- else {
233
- let keyFields = context.getKeyFields({
234
- parentType,
235
- serviceName: parentGroup.serviceName,
236
- });
237
- if (keyFields.length === 0 ||
238
- (keyFields.length === 1 &&
239
- keyFields[0].fieldDef.name === '__typename')) {
240
- keyFields = context.getKeyFields({
241
- parentType,
242
- serviceName: owningService,
243
- });
244
- }
245
- return parentGroup.dependentGroupForService(owningService, keyFields);
246
- }
247
- }
248
- else {
249
- const requiredFields = context.getRequiredFields(parentType, fieldDef, owningService);
250
- if (requiredFields.every(requiredField => parentGroup.providedFields.some(FieldSet_1.matchesField(requiredField)))) {
251
- if (owningService === parentGroup.serviceName) {
252
- return parentGroup;
253
- }
254
- else {
255
- return parentGroup.dependentGroupForService(owningService, requiredFields);
256
- }
257
- }
258
- else {
259
- const keyFields = context.getKeyFields({
260
- parentType,
261
- serviceName: parentGroup.serviceName,
262
- });
263
- if (!keyFields) {
264
- throw new graphql_1.GraphQLError(`Couldn't find keys for type "${parentType.name}}" in service "${baseService}"`, fieldNode);
265
- }
266
- if (baseService === parentGroup.serviceName) {
267
- return parentGroup.dependentGroupForService(owningService, requiredFields);
268
- }
269
- const baseGroup = parentGroup.dependentGroupForService(baseService, keyFields);
270
- return baseGroup.dependentGroupForService(owningService, requiredFields);
271
- }
272
- }
273
- });
274
- }
275
- function splitFields(context, path, fields, groupForField) {
276
- for (const fieldsForResponseName of FieldSet_1.groupByResponseName(fields).values()) {
277
- for (const [parentType, fieldsForParentType] of FieldSet_1.groupByParentType(fieldsForResponseName)) {
278
- const field = fieldsForParentType[0];
279
- const { scope, fieldDef } = field;
280
- if (fieldDef.name === graphql_1.TypeNameMetaFieldDef.name) {
281
- const { schema } = context;
282
- const roots = [
283
- schema.getQueryType(),
284
- schema.getMutationType(),
285
- schema.getSubscriptionType(),
286
- ]
287
- .filter(apollo_env_1.isNotNullOrUndefined)
288
- .map(type => type.name);
289
- if (roots.indexOf(parentType.name) > -1)
290
- continue;
291
- }
292
- if (graphql_1.isIntrospectionType(graphql_1.getNamedType(fieldDef.type))) {
293
- continue;
294
- }
295
- if (graphql_1.isObjectType(parentType) && scope.possibleTypes.includes(parentType)) {
296
- const group = groupForField(field);
297
- group.fields.push(completeField(context, scope, group, path, fieldsForParentType));
298
- }
299
- else {
300
- const possibleFieldDefs = scope.possibleTypes.map(runtimeType => context.getFieldDef(runtimeType, field.fieldNode));
301
- const hasNoExtendingFieldDefs = !possibleFieldDefs.some(utils_1.getFederationMetadata);
302
- if (hasNoExtendingFieldDefs) {
303
- const group = groupForField(field);
304
- group.fields.push(completeField(context, scope, group, path, fieldsForResponseName));
305
- continue;
306
- }
307
- const groupsByRuntimeParentTypes = new MultiMap_1.MultiMap();
308
- for (const runtimeParentType of scope.possibleTypes) {
309
- const fieldDef = context.getFieldDef(runtimeParentType, field.fieldNode);
310
- groupsByRuntimeParentTypes.add(groupForField({
311
- scope: context.newScope(runtimeParentType, scope),
312
- fieldNode: field.fieldNode,
313
- fieldDef,
314
- }), runtimeParentType);
315
- }
316
- for (const [group, runtimeParentTypes] of groupsByRuntimeParentTypes) {
317
- for (const runtimeParentType of runtimeParentTypes) {
318
- const fieldDef = context.getFieldDef(runtimeParentType, field.fieldNode);
319
- const fieldsWithRuntimeParentType = fieldsForParentType.map(field => ({
320
- ...field,
321
- fieldDef,
322
- }));
323
- group.fields.push(completeField(context, context.newScope(runtimeParentType, scope), group, path, fieldsWithRuntimeParentType));
324
- }
325
- }
326
- }
327
- }
328
- }
329
- }
330
- function completeField(context, scope, parentGroup, path, fields) {
331
- const { fieldNode, fieldDef } = fields[0];
332
- const returnType = graphql_1.getNamedType(fieldDef.type);
333
- if (!graphql_1.isCompositeType(returnType)) {
334
- return { scope, fieldNode, fieldDef };
335
- }
336
- else {
337
- const fieldPath = addPath(path, graphql_2.getResponseName(fieldNode), fieldDef.type);
338
- const subGroup = new FetchGroup(parentGroup.serviceName);
339
- subGroup.mergeAt = fieldPath;
340
- subGroup.providedFields = context.getProvidedFields(fieldDef, parentGroup.serviceName);
341
- if (graphql_1.isAbstractType(returnType)) {
342
- subGroup.fields.push({
343
- scope: context.newScope(returnType, scope),
344
- fieldNode: typenameField,
345
- fieldDef: graphql_1.TypeNameMetaFieldDef,
346
- });
347
- }
348
- const subfields = collectSubfields(context, returnType, fields);
349
- splitSubfields(context, fieldPath, subfields, subGroup);
350
- parentGroup.otherDependentGroups.push(...subGroup.dependentGroups);
351
- let definition;
352
- let selectionSet = FieldSet_1.selectionSetFromFieldSet(subGroup.fields, returnType);
353
- if (context.autoFragmentization && subGroup.fields.length > 2) {
354
- ({ definition, selectionSet } = getInternalFragment(selectionSet, returnType, context));
355
- parentGroup.internalFragments.add(definition);
356
- }
357
- subGroup.internalFragments.forEach(fragment => {
358
- parentGroup.internalFragments.add(fragment);
359
- });
360
- return {
361
- scope,
362
- fieldNode: {
363
- ...fieldNode,
364
- selectionSet,
365
- },
366
- fieldDef,
367
- };
368
- }
369
- }
370
- function getInternalFragment(selectionSet, returnType, context) {
371
- const key = JSON.stringify(selectionSet);
372
- if (!context.internalFragments.has(key)) {
373
- const name = `__QueryPlanFragment_${context.internalFragmentCount++}__`;
374
- const definition = {
375
- kind: graphql_1.Kind.FRAGMENT_DEFINITION,
376
- name: {
377
- kind: graphql_1.Kind.NAME,
378
- value: name,
379
- },
380
- typeCondition: {
381
- kind: graphql_1.Kind.NAMED_TYPE,
382
- name: {
383
- kind: graphql_1.Kind.NAME,
384
- value: returnType.name,
385
- },
386
- },
387
- selectionSet,
388
- };
389
- const fragmentSelection = {
390
- kind: graphql_1.Kind.SELECTION_SET,
391
- selections: [
392
- {
393
- kind: graphql_1.Kind.FRAGMENT_SPREAD,
394
- name: {
395
- kind: graphql_1.Kind.NAME,
396
- value: name,
397
- },
398
- },
399
- ],
400
- };
401
- context.internalFragments.set(key, {
402
- name,
403
- definition,
404
- selectionSet: fragmentSelection,
405
- });
406
- }
407
- return context.internalFragments.get(key);
408
- }
409
- function collectFields(context, scope, selectionSet, fields = [], visitedFragmentNames = Object.create(null)) {
410
- for (const selection of selectionSet.selections) {
411
- switch (selection.kind) {
412
- case graphql_1.Kind.FIELD:
413
- const fieldDef = context.getFieldDef(scope.parentType, selection);
414
- fields.push({ scope, fieldNode: selection, fieldDef });
415
- break;
416
- case graphql_1.Kind.INLINE_FRAGMENT: {
417
- const newScope = context.newScope(getFragmentCondition(selection), scope);
418
- if (newScope.possibleTypes.length === 0) {
419
- break;
420
- }
421
- collectFields(context, context.newScope(getFragmentCondition(selection), scope), selection.selectionSet, fields, visitedFragmentNames);
422
- break;
423
- }
424
- case graphql_1.Kind.FRAGMENT_SPREAD:
425
- const fragmentName = selection.name.value;
426
- const fragment = context.fragments[fragmentName];
427
- if (!fragment) {
428
- continue;
429
- }
430
- const newScope = context.newScope(getFragmentCondition(fragment), scope);
431
- if (newScope.possibleTypes.length === 0) {
432
- continue;
433
- }
434
- if (visitedFragmentNames[fragmentName]) {
435
- continue;
436
- }
437
- visitedFragmentNames[fragmentName] = true;
438
- collectFields(context, newScope, fragment.selectionSet, fields, visitedFragmentNames);
439
- break;
440
- }
441
- }
442
- return fields;
443
- function getFragmentCondition(fragment) {
444
- const typeConditionNode = fragment.typeCondition;
445
- if (!typeConditionNode)
446
- return scope.parentType;
447
- return graphql_1.typeFromAST(context.schema, typeConditionNode);
448
- }
449
- }
450
- function collectSubfields(context, returnType, fields) {
451
- let subfields = [];
452
- const visitedFragmentNames = Object.create(null);
453
- for (const field of fields) {
454
- const selectionSet = field.fieldNode.selectionSet;
455
- if (selectionSet) {
456
- subfields = collectFields(context, context.newScope(returnType), selectionSet, subfields, visitedFragmentNames);
457
- }
458
- }
459
- return subfields;
460
- }
461
- exports.collectSubfields = collectSubfields;
462
- class FetchGroup {
463
- constructor(serviceName, fields = [], internalFragments = new Set()) {
464
- this.serviceName = serviceName;
465
- this.fields = fields;
466
- this.internalFragments = internalFragments;
467
- this.requiredFields = [];
468
- this.providedFields = [];
469
- this.dependentGroupsByService = Object.create(null);
470
- this.otherDependentGroups = [];
471
- }
472
- dependentGroupForService(serviceName, requiredFields) {
473
- let group = this.dependentGroupsByService[serviceName];
474
- if (!group) {
475
- group = new FetchGroup(serviceName);
476
- group.mergeAt = this.mergeAt;
477
- this.dependentGroupsByService[serviceName] = group;
478
- }
479
- if (requiredFields) {
480
- if (group.requiredFields) {
481
- group.requiredFields.push(...requiredFields);
482
- }
483
- else {
484
- group.requiredFields = requiredFields;
485
- }
486
- this.fields.push(...requiredFields);
487
- }
488
- return group;
489
- }
490
- get dependentGroups() {
491
- return [
492
- ...Object.values(this.dependentGroupsByService),
493
- ...this.otherDependentGroups,
494
- ];
495
- }
496
- }
497
- function buildOperationContext(schema, document, operationName) {
498
- let operation;
499
- const fragments = Object.create(null);
500
- document.definitions.forEach(definition => {
501
- switch (definition.kind) {
502
- case graphql_1.Kind.OPERATION_DEFINITION:
503
- if (!operationName && operation) {
504
- throw new graphql_1.GraphQLError('Must provide operation name if query contains ' +
505
- 'multiple operations.');
506
- }
507
- if (!operationName ||
508
- (definition.name && definition.name.value === operationName)) {
509
- operation = definition;
510
- }
511
- break;
512
- case graphql_1.Kind.FRAGMENT_DEFINITION:
513
- fragments[definition.name.value] = definition;
514
- break;
515
- }
516
- });
517
- if (!operation) {
518
- if (operationName) {
519
- throw new graphql_1.GraphQLError(`Unknown operation named "${operationName}".`);
520
- }
521
- else {
522
- throw new graphql_1.GraphQLError('Must provide an operation.');
523
- }
524
- }
525
- return { schema, operation, fragments };
526
- }
527
- exports.buildOperationContext = buildOperationContext;
528
- function buildQueryPlanningContext({ operation, schema, fragments }, options) {
529
- return new QueryPlanningContext(schema, operation, fragments, options.autoFragmentization);
530
- }
531
- exports.buildQueryPlanningContext = buildQueryPlanningContext;
532
- class QueryPlanningContext {
533
- constructor(schema, operation, fragments, autoFragmentization) {
534
- this.schema = schema;
535
- this.operation = operation;
536
- this.fragments = fragments;
537
- this.autoFragmentization = autoFragmentization;
538
- this.internalFragments = new Map();
539
- this.internalFragmentCount = 0;
540
- this.variableDefinitions = Object.create(null);
541
- graphql_1.visit(operation, {
542
- VariableDefinition: definition => {
543
- this.variableDefinitions[definition.variable.name.value] = definition;
544
- },
545
- });
546
- }
547
- getFieldDef(parentType, fieldNode) {
548
- const fieldName = fieldNode.name.value;
549
- const fieldDef = graphql_2.getFieldDef(this.schema, parentType, fieldName);
550
- if (!fieldDef) {
551
- throw new graphql_1.GraphQLError(`Cannot query field "${fieldNode.name.value}" on type "${String(parentType)}"`, fieldNode);
552
- }
553
- return fieldDef;
554
- }
555
- getPossibleTypes(type) {
556
- return graphql_1.isAbstractType(type) ? this.schema.getPossibleTypes(type) : [type];
557
- }
558
- getVariableUsages(selectionSet, fragments) {
559
- const usages = Object.create(null);
560
- const document = {
561
- kind: graphql_1.Kind.DOCUMENT,
562
- definitions: [
563
- { kind: graphql_1.Kind.OPERATION_DEFINITION, selectionSet, operation: 'query' },
564
- ...Array.from(fragments),
565
- ],
566
- };
567
- graphql_1.visit(document, {
568
- Variable: (node) => {
569
- usages[node.name.value] = this.variableDefinitions[node.name.value];
570
- },
571
- });
572
- return usages;
573
- }
574
- newScope(parentType, enclosingScope) {
575
- return {
576
- parentType,
577
- possibleTypes: enclosingScope
578
- ? this.getPossibleTypes(parentType).filter(type => enclosingScope.possibleTypes.includes(type))
579
- : this.getPossibleTypes(parentType),
580
- enclosingScope,
581
- };
582
- }
583
- getBaseService(parentType) {
584
- var _a;
585
- return ((_a = utils_1.getFederationMetadata(parentType)) === null || _a === void 0 ? void 0 : _a.serviceName) || null;
586
- }
587
- getOwningService(parentType, fieldDef) {
588
- const fieldFederationMetadata = utils_1.getFederationMetadata(fieldDef);
589
- if ((fieldFederationMetadata === null || fieldFederationMetadata === void 0 ? void 0 : fieldFederationMetadata.serviceName) &&
590
- !(fieldFederationMetadata === null || fieldFederationMetadata === void 0 ? void 0 : fieldFederationMetadata.belongsToValueType)) {
591
- return fieldFederationMetadata.serviceName;
592
- }
593
- else {
594
- return this.getBaseService(parentType);
595
- }
596
- }
597
- getKeyFields({ parentType, serviceName, fetchAll = false, }) {
598
- var _a, _b;
599
- const keyFields = [];
600
- keyFields.push({
601
- scope: {
602
- parentType,
603
- possibleTypes: this.getPossibleTypes(parentType),
604
- },
605
- fieldNode: typenameField,
606
- fieldDef: graphql_1.TypeNameMetaFieldDef,
607
- });
608
- for (const possibleType of this.getPossibleTypes(parentType)) {
609
- const keys = (_b = (_a = utils_1.getFederationMetadata(possibleType)) === null || _a === void 0 ? void 0 : _a.keys) === null || _b === void 0 ? void 0 : _b[serviceName];
610
- if (!(keys && keys.length > 0))
611
- continue;
612
- if (fetchAll) {
613
- keyFields.push(...keys.flatMap(key => collectFields(this, this.newScope(possibleType), {
614
- kind: graphql_1.Kind.SELECTION_SET,
615
- selections: key,
616
- })));
617
- }
618
- else {
619
- keyFields.push(...collectFields(this, this.newScope(possibleType), {
620
- kind: graphql_1.Kind.SELECTION_SET,
621
- selections: keys[0],
622
- }));
623
- }
624
- }
625
- return keyFields;
626
- }
627
- getRequiredFields(parentType, fieldDef, serviceName) {
628
- const requiredFields = [];
629
- requiredFields.push(...this.getKeyFields({ parentType, serviceName }));
630
- const fieldFederationMetadata = utils_1.getFederationMetadata(fieldDef);
631
- if (fieldFederationMetadata === null || fieldFederationMetadata === void 0 ? void 0 : fieldFederationMetadata.requires) {
632
- requiredFields.push(...collectFields(this, this.newScope(parentType), {
633
- kind: graphql_1.Kind.SELECTION_SET,
634
- selections: fieldFederationMetadata.requires,
635
- }));
636
- }
637
- return requiredFields;
638
- }
639
- getProvidedFields(fieldDef, serviceName) {
640
- const returnType = graphql_1.getNamedType(fieldDef.type);
641
- if (!graphql_1.isCompositeType(returnType))
642
- return [];
643
- const providedFields = [];
644
- providedFields.push(...this.getKeyFields({
645
- parentType: returnType,
646
- serviceName,
647
- fetchAll: true,
648
- }));
649
- const fieldFederationMetadata = utils_1.getFederationMetadata(fieldDef);
650
- if (fieldFederationMetadata === null || fieldFederationMetadata === void 0 ? void 0 : fieldFederationMetadata.provides) {
651
- providedFields.push(...collectFields(this, this.newScope(returnType), {
652
- kind: graphql_1.Kind.SELECTION_SET,
653
- selections: fieldFederationMetadata.provides,
654
- }));
655
- }
656
- return providedFields;
657
- }
658
- }
659
- exports.QueryPlanningContext = QueryPlanningContext;
660
- function addPath(path, responseName, type) {
661
- path = [...path, responseName];
662
- while (!graphql_1.isNamedType(type)) {
663
- if (graphql_1.isListType(type)) {
664
- path.push('@');
665
- }
666
- type = type.ofType;
667
- }
668
- return path;
669
- }
670
- //# sourceMappingURL=buildQueryPlan.js.map