@apollo/federation-internals 2.4.11 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/argumentCompositionStrategies.d.ts +12 -7
  2. package/dist/argumentCompositionStrategies.d.ts.map +1 -1
  3. package/dist/argumentCompositionStrategies.js +26 -7
  4. package/dist/argumentCompositionStrategies.js.map +1 -1
  5. package/dist/authenticatedSpec.d.ts +13 -0
  6. package/dist/authenticatedSpec.d.ts.map +1 -0
  7. package/dist/authenticatedSpec.js +36 -0
  8. package/dist/authenticatedSpec.js.map +1 -0
  9. package/dist/coreSpec.d.ts +6 -5
  10. package/dist/coreSpec.d.ts.map +1 -1
  11. package/dist/coreSpec.js +42 -32
  12. package/dist/coreSpec.js.map +1 -1
  13. package/dist/definitions.d.ts +2 -3
  14. package/dist/definitions.d.ts.map +1 -1
  15. package/dist/definitions.js +12 -7
  16. package/dist/definitions.js.map +1 -1
  17. package/dist/directiveAndTypeSpecification.d.ts +8 -8
  18. package/dist/directiveAndTypeSpecification.d.ts.map +1 -1
  19. package/dist/directiveAndTypeSpecification.js +21 -16
  20. package/dist/directiveAndTypeSpecification.js.map +1 -1
  21. package/dist/error.d.ts +1 -1
  22. package/dist/extractSubgraphsFromSupergraph.d.ts +1 -1
  23. package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
  24. package/dist/extractSubgraphsFromSupergraph.js +450 -295
  25. package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
  26. package/dist/federation.d.ts +10 -5
  27. package/dist/federation.d.ts.map +1 -1
  28. package/dist/federation.js +58 -16
  29. package/dist/federation.js.map +1 -1
  30. package/dist/federationSpec.d.ts +3 -1
  31. package/dist/federationSpec.d.ts.map +1 -1
  32. package/dist/federationSpec.js +12 -3
  33. package/dist/federationSpec.js.map +1 -1
  34. package/dist/inaccessibleSpec.d.ts +1 -1
  35. package/dist/inaccessibleSpec.d.ts.map +1 -1
  36. package/dist/inaccessibleSpec.js +4 -4
  37. package/dist/inaccessibleSpec.js.map +1 -1
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +2 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/joinSpec.d.ts +19 -17
  43. package/dist/joinSpec.d.ts.map +1 -1
  44. package/dist/joinSpec.js +3 -3
  45. package/dist/joinSpec.js.map +1 -1
  46. package/dist/requiresScopesSpec.d.ts +16 -0
  47. package/dist/requiresScopesSpec.d.ts.map +1 -0
  48. package/dist/requiresScopesSpec.js +55 -0
  49. package/dist/requiresScopesSpec.js.map +1 -0
  50. package/dist/supergraphs.d.ts +19 -4
  51. package/dist/supergraphs.d.ts.map +1 -1
  52. package/dist/supergraphs.js +40 -14
  53. package/dist/supergraphs.js.map +1 -1
  54. package/dist/tagSpec.d.ts +1 -1
  55. package/dist/tagSpec.d.ts.map +1 -1
  56. package/dist/tagSpec.js +4 -4
  57. package/dist/tagSpec.js.map +1 -1
  58. package/dist/utils.d.ts +1 -0
  59. package/dist/utils.d.ts.map +1 -1
  60. package/dist/utils.js +11 -1
  61. package/dist/utils.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/argumentCompositionStrategies.ts +32 -9
  64. package/src/authenticatedSpec.ts +62 -0
  65. package/src/coreSpec.ts +57 -35
  66. package/src/definitions.ts +22 -9
  67. package/src/directiveAndTypeSpecification.ts +25 -24
  68. package/src/error.ts +2 -2
  69. package/src/extractSubgraphsFromSupergraph.ts +647 -393
  70. package/src/federation.ts +95 -16
  71. package/src/federationSpec.ts +13 -5
  72. package/src/inaccessibleSpec.ts +4 -4
  73. package/src/index.ts +2 -1
  74. package/src/joinSpec.ts +23 -13
  75. package/src/precompute.ts +1 -1
  76. package/src/requiresScopesSpec.ts +76 -0
  77. package/src/supergraphs.ts +64 -16
  78. package/src/tagSpec.ts +4 -4
  79. package/src/utils.ts +10 -0
@@ -130,286 +130,47 @@ function typesUsedInFederationDirective(fieldSet, parentType) {
130
130
  });
131
131
  return usedTypes;
132
132
  }
133
- function extractSubgraphsFromSupergraph(supergraph) {
133
+ function extractSubgraphsFromSupergraph(supergraph, validateExtractedSubgraphs = true) {
134
134
  const [coreFeatures, joinSpec] = (0, supergraphs_1.validateSupergraph)(supergraph);
135
135
  const isFed1 = joinSpec.version.equals(new coreSpec_1.FeatureVersion(0, 1));
136
136
  try {
137
137
  const [subgraphs, graphEnumNameToSubgraphName] = collectEmptySubgraphs(supergraph, joinSpec);
138
- const typeDirective = joinSpec.typeDirective(supergraph);
139
- const implementsDirective = joinSpec.implementsDirective(supergraph);
140
- const ownerDirective = joinSpec.ownerDirective(supergraph);
141
- const fieldDirective = joinSpec.fieldDirective(supergraph);
142
- const unionMemberDirective = joinSpec.unionMemberDirective(supergraph);
143
- const enumValueDirective = joinSpec.enumValueDirective(supergraph);
144
138
  const getSubgraph = (application) => {
145
139
  const graph = application.arguments().graph;
146
- return graph ? graphEnumNameToSubgraphName.get(graph) : undefined;
140
+ if (!graph) {
141
+ return undefined;
142
+ }
143
+ const subgraphName = graphEnumNameToSubgraphName.get(graph);
144
+ (0, utils_1.assert)(subgraphName, () => `Invalid graph name ${graph} found in ${application} on ${application.parent}: does not match a graph defined in the @join__Graph enum`);
145
+ const subgraph = subgraphs.get(subgraphName);
146
+ (0, utils_1.assert)(subgraph, 'All subgraphs should have been created by `collectEmptySubgraphs`');
147
+ return subgraph;
148
+ };
149
+ const types = filteredTypes(supergraph, joinSpec, coreFeatures.coreDefinition);
150
+ const args = {
151
+ supergraph,
152
+ subgraphs,
153
+ joinSpec,
154
+ filteredTypes: types,
155
+ getSubgraph,
147
156
  };
148
- let includeTypeInSubgraph = () => true;
149
157
  if (isFed1) {
150
- const reachableTypesBySubgraph = collectFieldReachableTypesForAllSubgraphs(supergraph, subgraphs.names(), (f, name) => {
151
- const fieldApplications = f.appliedDirectivesOf(fieldDirective);
152
- if (fieldApplications.length) {
153
- const application = fieldApplications.find((application) => getSubgraph(application) === name);
154
- if (application) {
155
- const args = application.arguments();
156
- const typesInFederationDirectives = typesUsedInFederationDirective(args.provides, (0, definitions_1.baseType)(f.type))
157
- .concat(typesUsedInFederationDirective(args.requires, f.parent));
158
- return { isInSubgraph: true, typesInFederationDirectives };
159
- }
160
- else {
161
- return { isInSubgraph: false, typesInFederationDirectives: [] };
162
- }
163
- }
164
- else {
165
- const ownerApplications = ownerDirective ? f.parent.appliedDirectivesOf(ownerDirective) : [];
166
- return { isInSubgraph: !ownerApplications.length || getSubgraph(ownerApplications[0]) == name, typesInFederationDirectives: [] };
167
- }
168
- }, (t, name) => {
169
- const typeApplications = t.appliedDirectivesOf(typeDirective);
170
- const application = typeApplications.find((application) => (application.arguments().key && (getSubgraph(application) === name)));
171
- if (application) {
172
- const typesInFederationDirectives = typesUsedInFederationDirective(application.arguments().key, t);
173
- return { isEntityWithKeyInSubgraph: true, typesInFederationDirectives };
174
- }
175
- else {
176
- return { isEntityWithKeyInSubgraph: false, typesInFederationDirectives: [] };
177
- }
178
- });
179
- includeTypeInSubgraph = (t, name) => { var _a, _b; return (_b = (_a = reachableTypesBySubgraph.get(name)) === null || _a === void 0 ? void 0 : _a.has(t.name)) !== null && _b !== void 0 ? _b : false; };
180
- }
181
- for (const type of filteredTypes(supergraph, joinSpec, coreFeatures.coreDefinition)) {
182
- const typeApplications = type.appliedDirectivesOf(typeDirective);
183
- if (!typeApplications.length) {
184
- subgraphs
185
- .values()
186
- .filter((sg) => includeTypeInSubgraph(type, sg.name))
187
- .map(sg => sg.schema).forEach(schema => schema.addType((0, definitions_1.newNamedType)(type.kind, type.name)));
188
- }
189
- else {
190
- for (const application of typeApplications) {
191
- const args = application.arguments();
192
- const subgraphName = getSubgraph(application);
193
- const schema = subgraphs.get(subgraphName).schema;
194
- let subgraphType = schema.type(type.name);
195
- if (!subgraphType) {
196
- const kind = args.isInterfaceObject ? 'ObjectType' : type.kind;
197
- subgraphType = schema.addType((0, definitions_1.newNamedType)(kind, type.name));
198
- if (args.isInterfaceObject) {
199
- subgraphType.applyDirective('interfaceObject');
200
- }
201
- }
202
- if (args.key) {
203
- const { resolvable } = args;
204
- const directive = subgraphType.applyDirective('key', { 'fields': args.key, resolvable });
205
- if (args.extension) {
206
- directive.setOfExtension(subgraphType.newExtension());
207
- }
208
- }
209
- }
210
- }
158
+ extractSubgraphsFromFed1Supergraph(args);
211
159
  }
212
- for (const type of filteredTypes(supergraph, joinSpec, coreFeatures.coreDefinition)) {
213
- switch (type.kind) {
214
- case 'ObjectType':
215
- case 'InterfaceType':
216
- const addedInterfaces = [];
217
- const implementsApplications = implementsDirective ? type.appliedDirectivesOf(implementsDirective) : [];
218
- for (const application of implementsApplications) {
219
- const args = application.arguments();
220
- const subgraph = subgraphs.get(graphEnumNameToSubgraphName.get(args.graph));
221
- const schema = subgraph.schema;
222
- schema.type(type.name).addImplementedInterface(args.interface);
223
- addedInterfaces.push(args.interface);
224
- }
225
- for (const implementations of type.interfaceImplementations()) {
226
- const name = implementations.interface.name;
227
- if (!addedInterfaces.includes(name)) {
228
- for (const subgraph of subgraphs) {
229
- const subgraphType = subgraph.schema.type(type.name);
230
- const subgraphItf = subgraph.schema.type(name);
231
- if (subgraphType && subgraphItf) {
232
- subgraphType.addImplementedInterface(name);
233
- }
234
- }
235
- }
236
- }
237
- case 'InputObjectType':
238
- const typeApplications = type.appliedDirectivesOf(typeDirective);
239
- const subgraphsDefiningType = [];
240
- for (const app of typeApplications) {
241
- const subgraph = subgraphs.get(graphEnumNameToSubgraphName.get(app.arguments().graph));
242
- if (!subgraphsDefiningType.includes(subgraph)) {
243
- subgraphsDefiningType.push(subgraph);
244
- }
245
- }
246
- for (const field of type.fields()) {
247
- const fieldApplications = field.appliedDirectivesOf(fieldDirective);
248
- if (!fieldApplications.length) {
249
- const ownerApplications = ownerDirective ? type.appliedDirectivesOf(ownerDirective) : [];
250
- if (ownerApplications.length > 0) {
251
- (0, utils_1.assert)(ownerApplications.length == 1, () => `Found multiple join__owner directives on type ${type}`);
252
- const subgraph = subgraphs.get(graphEnumNameToSubgraphName.get(ownerApplications[0].arguments().graph));
253
- const subgraphField = addSubgraphField(field, subgraph);
254
- (0, utils_1.assert)(subgraphField, () => `Found join__owner directive on ${type} but no corresponding join__type`);
255
- continue;
256
- }
257
- if (subgraphsDefiningType.length > 0) {
258
- const isShareable = (0, definitions_1.isObjectType)(type) && subgraphsDefiningType.length > 1;
259
- for (const subgraph of subgraphsDefiningType) {
260
- const subgraphField = addSubgraphField(field, subgraph);
261
- if (subgraphField && isShareable) {
262
- subgraphField.applyDirective(subgraph.metadata().shareableDirective());
263
- }
264
- }
265
- }
266
- else {
267
- const fieldBaseType = (0, definitions_1.baseType)(field.type);
268
- const isShareable = (0, definitions_1.isObjectType)(type) && subgraphs.values().filter((s) => s.schema.type(type.name)).length > 1;
269
- for (const subgraph of subgraphs) {
270
- if (subgraph.schema.type(fieldBaseType.name)) {
271
- const subgraphField = addSubgraphField(field, subgraph);
272
- if (subgraphField && isShareable) {
273
- subgraphField.applyDirective(subgraph.metadata().shareableDirective());
274
- }
275
- }
276
- }
277
- }
278
- }
279
- else {
280
- const isShareable = (0, definitions_1.isObjectType)(type)
281
- && fieldApplications.filter((application) => {
282
- const args = application.arguments();
283
- return !args.external && !args.usedOverridden;
284
- }).length > 1;
285
- for (const application of fieldApplications) {
286
- const args = application.arguments();
287
- if (!args.graph) {
288
- continue;
289
- }
290
- const subgraph = subgraphs.get(graphEnumNameToSubgraphName.get(args.graph));
291
- const subgraphField = addSubgraphField(field, subgraph, args.type);
292
- if (!subgraphField) {
293
- (0, utils_1.assert)(!includeTypeInSubgraph(type, subgraph.name), () => `Found join__field directive for graph ${subgraph.name} on field ${field.coordinate} but no corresponding join__type on ${type}`);
294
- continue;
295
- }
296
- if (args.requires) {
297
- subgraphField.applyDirective(subgraph.metadata().requiresDirective(), { 'fields': args.requires });
298
- }
299
- if (args.provides) {
300
- subgraphField.applyDirective(subgraph.metadata().providesDirective(), { 'fields': args.provides });
301
- }
302
- if (args.external) {
303
- subgraphField.applyDirective(subgraph.metadata().externalDirective());
304
- }
305
- if (args.usedOverridden) {
306
- subgraphField.applyDirective(subgraph.metadata().externalDirective(), { 'reason': '[overridden]' });
307
- }
308
- if (args.override) {
309
- subgraphField.applyDirective(subgraph.metadata().overrideDirective(), { 'from': args.override });
310
- }
311
- if (isShareable && !args.external && !args.usedOverridden) {
312
- subgraphField.applyDirective(subgraph.metadata().shareableDirective());
313
- }
314
- }
315
- }
316
- }
317
- break;
318
- case 'EnumType':
319
- for (const subgraph of subgraphs) {
320
- const subgraphEnum = subgraph.schema.type(type.name);
321
- if (!subgraphEnum) {
322
- continue;
323
- }
324
- (0, utils_1.assert)((0, definitions_1.isEnumType)(subgraphEnum), () => `${subgraphEnum} should be an enum but found a ${subgraphEnum.kind}`);
325
- for (const value of type.values) {
326
- const addValue = !enumValueDirective
327
- || value.appliedDirectivesOf(enumValueDirective).some((d) => graphEnumNameToSubgraphName.get(d.arguments().graph) === subgraph.name);
328
- if (addValue) {
329
- subgraphEnum.addValue(value.name);
330
- }
331
- }
332
- }
333
- break;
334
- case 'UnionType':
335
- for (const subgraph of subgraphs) {
336
- const subgraphUnion = subgraph.schema.type(type.name);
337
- if (!subgraphUnion) {
338
- continue;
339
- }
340
- (0, utils_1.assert)((0, definitions_1.isUnionType)(subgraphUnion), () => `${subgraphUnion} should be an enum but found a ${subgraphUnion.kind}`);
341
- let membersInSubgraph;
342
- if (unionMemberDirective) {
343
- membersInSubgraph = type
344
- .appliedDirectivesOf(unionMemberDirective)
345
- .filter((d) => graphEnumNameToSubgraphName.get(d.arguments().graph) === subgraph.name)
346
- .map((d) => d.arguments().member);
347
- }
348
- else {
349
- membersInSubgraph = type.types().map((t) => t.name);
350
- }
351
- for (const memberTypeName of membersInSubgraph) {
352
- const subgraphType = subgraph.schema.type(memberTypeName);
353
- if (subgraphType) {
354
- subgraphUnion.addType(subgraphType);
355
- }
356
- }
357
- }
358
- break;
359
- }
160
+ else {
161
+ extractSubgraphsFromFed2Supergraph(args);
360
162
  }
361
- const allExecutableDirectives = supergraph.directives().filter((def) => def.hasExecutableLocations());
362
163
  for (const subgraph of subgraphs) {
363
- if (isFed1) {
364
- addExternalFields(subgraph, supergraph, isFed1);
365
- }
366
- (0, federation_1.removeInactiveProvidesAndRequires)(subgraph.schema);
367
- for (const type of subgraph.schema.types()) {
368
- switch (type.kind) {
369
- case 'ObjectType':
370
- case 'InterfaceType':
371
- case 'InputObjectType':
372
- if (!type.hasFields()) {
373
- type.removeRecursive();
374
- }
375
- break;
376
- case 'UnionType':
377
- if (type.membersCount() === 0) {
378
- type.removeRecursive();
379
- }
380
- break;
164
+ if (validateExtractedSubgraphs) {
165
+ try {
166
+ subgraph.validate();
381
167
  }
382
- }
383
- for (const definition of allExecutableDirectives) {
384
- (0, definitions_1.copyDirectiveDefinitionToSchema)({
385
- definition,
386
- schema: subgraph.schema,
387
- copyDirectiveApplicationsInArguments: false,
388
- locationFilter: (loc) => (0, definitions_1.isExecutableDirectiveLocation)(loc),
389
- });
390
- }
391
- }
392
- if (isFed1) {
393
- for (const subgraph of subgraphs) {
394
- for (const itf of subgraph.schema.interfaceTypes()) {
395
- const implementations = itf.possibleRuntimeTypes();
396
- for (const field of itf.fields()) {
397
- if (!implementations.every(implem => implem.field(field.name))) {
398
- field.remove();
399
- }
400
- }
401
- if (!itf.hasFields()) {
402
- itf.remove();
403
- }
168
+ catch (e) {
169
+ throw new SubgraphExtractionError(e, subgraph);
404
170
  }
405
171
  }
406
- }
407
- for (const subgraph of subgraphs) {
408
- try {
409
- subgraph.validate();
410
- }
411
- catch (e) {
412
- throw new SubgraphExtractionError(e, subgraph);
172
+ else {
173
+ subgraph.assumeValid();
413
174
  }
414
175
  }
415
176
  return subgraphs;
@@ -435,6 +196,193 @@ function extractSubgraphsFromSupergraph(supergraph) {
435
196
  }
436
197
  }
437
198
  exports.extractSubgraphsFromSupergraph = extractSubgraphsFromSupergraph;
199
+ function addAllEmptySubgraphTypes({ supergraph, joinSpec, filteredTypes, getSubgraph, }) {
200
+ const typeDirective = joinSpec.typeDirective(supergraph);
201
+ const objOrItfTypes = [];
202
+ const inputObjTypes = [];
203
+ const enumTypes = [];
204
+ const unionTypes = [];
205
+ for (const type of filteredTypes) {
206
+ const typeApplications = type.appliedDirectivesOf(typeDirective);
207
+ switch (type.kind) {
208
+ case 'InterfaceType':
209
+ case 'ObjectType':
210
+ objOrItfTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), getSubgraph) });
211
+ break;
212
+ case 'InputObjectType':
213
+ inputObjTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), getSubgraph) });
214
+ break;
215
+ case 'EnumType':
216
+ enumTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), getSubgraph) });
217
+ break;
218
+ case 'UnionType':
219
+ unionTypes.push({ type, subgraphsInfo: addEmptyType(type, type.appliedDirectivesOf(typeDirective), getSubgraph) });
220
+ break;
221
+ case 'ScalarType':
222
+ for (const application of typeApplications) {
223
+ const subgraph = getSubgraph(application);
224
+ (0, utils_1.assert)(subgraph, () => `Should have found the subgraph for ${application}`);
225
+ subgraph.schema.addType((0, definitions_1.newNamedType)(type.kind, type.name));
226
+ }
227
+ break;
228
+ }
229
+ }
230
+ return {
231
+ objOrItfTypes,
232
+ inputObjTypes,
233
+ enumTypes,
234
+ unionTypes,
235
+ };
236
+ }
237
+ function addEmptyType(type, typeApplications, getSubgraph) {
238
+ (0, utils_1.assert)(typeApplications.length > 0, `Missing @join__type on ${type}`);
239
+ const subgraphsInfo = new Map();
240
+ for (const application of typeApplications) {
241
+ const { graph, key, extension, resolvable, isInterfaceObject } = application.arguments();
242
+ let subgraphInfo = subgraphsInfo.get(graph);
243
+ if (!subgraphInfo) {
244
+ const subgraph = getSubgraph(application);
245
+ (0, utils_1.assert)(subgraph, () => `Should have found the subgraph for ${application}`);
246
+ const kind = isInterfaceObject ? 'ObjectType' : type.kind;
247
+ const subgraphType = subgraph.schema.addType((0, definitions_1.newNamedType)(kind, type.name));
248
+ if (isInterfaceObject) {
249
+ subgraphType.applyDirective('interfaceObject');
250
+ }
251
+ subgraphInfo = { type: subgraphType, subgraph };
252
+ subgraphsInfo.set(graph, subgraphInfo);
253
+ }
254
+ if (key) {
255
+ const directive = subgraphInfo.type.applyDirective('key', { 'fields': key, resolvable });
256
+ if (extension) {
257
+ directive.setOfExtension(subgraphInfo.type.newExtension());
258
+ }
259
+ }
260
+ }
261
+ return subgraphsInfo;
262
+ }
263
+ function extractObjOrItfContent(args, info) {
264
+ const fieldDirective = args.joinSpec.fieldDirective(args.supergraph);
265
+ const implementsDirective = args.joinSpec.implementsDirective(args.supergraph);
266
+ (0, utils_1.assert)(implementsDirective, '@join__implements should existing for a fed2 supergraph');
267
+ for (const { type, subgraphsInfo } of info) {
268
+ const implementsApplications = type.appliedDirectivesOf(implementsDirective);
269
+ for (const application of implementsApplications) {
270
+ const args = application.arguments();
271
+ const subgraphInfo = subgraphsInfo.get(args.graph);
272
+ subgraphInfo.type.addImplementedInterface(args.interface);
273
+ }
274
+ for (const field of type.fields()) {
275
+ const fieldApplications = field.appliedDirectivesOf(fieldDirective);
276
+ if (fieldApplications.length === 0) {
277
+ const isShareable = (0, definitions_1.isObjectType)(type) && subgraphsInfo.size > 1;
278
+ for (const { type: subgraphType, subgraph } of subgraphsInfo.values()) {
279
+ addSubgraphField({ field, type: subgraphType, subgraph, isShareable });
280
+ }
281
+ }
282
+ else {
283
+ const isShareable = (0, definitions_1.isObjectType)(type)
284
+ && fieldApplications.filter((application) => {
285
+ const args = application.arguments();
286
+ return !args.external && !args.usedOverridden;
287
+ }).length > 1;
288
+ for (const application of fieldApplications) {
289
+ const args = application.arguments();
290
+ if (!args.graph) {
291
+ continue;
292
+ }
293
+ const { type: subgraphType, subgraph } = subgraphsInfo.get(args.graph);
294
+ addSubgraphField({ field, type: subgraphType, subgraph, isShareable, joinFieldArgs: args });
295
+ }
296
+ }
297
+ }
298
+ }
299
+ }
300
+ function extractInputObjContent(args, info) {
301
+ const fieldDirective = args.joinSpec.fieldDirective(args.supergraph);
302
+ for (const { type, subgraphsInfo } of info) {
303
+ for (const field of type.fields()) {
304
+ const fieldApplications = field.appliedDirectivesOf(fieldDirective);
305
+ if (fieldApplications.length === 0) {
306
+ for (const { type: subgraphType, subgraph } of subgraphsInfo.values()) {
307
+ addSubgraphInputField({ field, type: subgraphType, subgraph });
308
+ }
309
+ }
310
+ else {
311
+ for (const application of fieldApplications) {
312
+ const args = application.arguments();
313
+ if (!args.graph) {
314
+ continue;
315
+ }
316
+ const { type: subgraphType, subgraph } = subgraphsInfo.get(args.graph);
317
+ addSubgraphInputField({ field, type: subgraphType, subgraph, joinFieldArgs: args });
318
+ }
319
+ }
320
+ }
321
+ }
322
+ }
323
+ function extractEnumTypeContent(args, info) {
324
+ const enumValueDirective = args.joinSpec.enumValueDirective(args.supergraph);
325
+ for (const { type, subgraphsInfo } of info) {
326
+ for (const value of type.values) {
327
+ const enumValueApplications = enumValueDirective ? value.appliedDirectivesOf(enumValueDirective) : [];
328
+ if (enumValueApplications.length === 0) {
329
+ for (const { type: subgraphType } of subgraphsInfo.values()) {
330
+ subgraphType.addValue(value.name);
331
+ }
332
+ }
333
+ else {
334
+ for (const application of enumValueApplications) {
335
+ const args = application.arguments();
336
+ const { type: subgraphType } = subgraphsInfo.get(args.graph);
337
+ subgraphType.addValue(value.name);
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
343
+ function extractUnionTypeContent(args, info) {
344
+ const unionMemberDirective = args.joinSpec.unionMemberDirective(args.supergraph);
345
+ for (const { type, subgraphsInfo } of info) {
346
+ const unionMemberApplications = unionMemberDirective ? type.appliedDirectivesOf(unionMemberDirective) : [];
347
+ if (unionMemberApplications.length === 0) {
348
+ for (const { type: subgraphType, subgraph } of subgraphsInfo.values()) {
349
+ for (const member of type.types()) {
350
+ const subgraphMember = subgraph.schema.type(member.name);
351
+ if (subgraphMember) {
352
+ subgraphType.addType(subgraphMember);
353
+ }
354
+ }
355
+ }
356
+ }
357
+ else {
358
+ for (const application of unionMemberApplications) {
359
+ const args = application.arguments();
360
+ const { type: subgraphType, subgraph } = subgraphsInfo.get(args.graph);
361
+ subgraphType.addType(subgraph.schema.type(args.member));
362
+ }
363
+ }
364
+ }
365
+ }
366
+ function extractSubgraphsFromFed2Supergraph(args) {
367
+ const { objOrItfTypes, inputObjTypes, enumTypes, unionTypes, } = addAllEmptySubgraphTypes(args);
368
+ extractObjOrItfContent(args, objOrItfTypes);
369
+ extractInputObjContent(args, inputObjTypes);
370
+ extractEnumTypeContent(args, enumTypes);
371
+ extractUnionTypeContent(args, unionTypes);
372
+ const allExecutableDirectives = args.supergraph.directives().filter((def) => def.hasExecutableLocations());
373
+ for (const subgraph of args.subgraphs) {
374
+ (0, federation_1.removeInactiveProvidesAndRequires)(subgraph.schema);
375
+ removeUnusedTypesFromSubgraph(subgraph.schema);
376
+ for (const definition of allExecutableDirectives) {
377
+ (0, definitions_1.copyDirectiveDefinitionToSchema)({
378
+ definition,
379
+ schema: subgraph.schema,
380
+ copyDirectiveApplicationsInArguments: false,
381
+ locationFilter: (loc) => (0, definitions_1.isExecutableDirectiveLocation)(loc),
382
+ });
383
+ }
384
+ }
385
+ }
438
386
  const DEBUG_SUBGRAPHS_ENV_VARIABLE_NAME = 'APOLLO_FEDERATION_DEBUG_SUBGRAPHS';
439
387
  function maybeDumpSubgraphSchema(subgraph) {
440
388
  const shouldDump = !!(0, utils_2.validateStringContainsBoolean)(process.env[DEBUG_SUBGRAPHS_ENV_VARIABLE_NAME]);
@@ -458,42 +406,226 @@ function errorToString(e) {
458
406
  const causes = (0, _1.errorCauses)(e);
459
407
  return causes ? (0, _1.printErrors)(causes) : String(e);
460
408
  }
461
- function addSubgraphField(supergraphField, subgraph, encodedType) {
462
- if (supergraphField instanceof definitions_1.FieldDefinition) {
463
- return addSubgraphObjectOrInterfaceField(supergraphField, subgraph, encodedType);
409
+ function addSubgraphField({ field, type, subgraph, isShareable, joinFieldArgs, }) {
410
+ const copiedFieldType = (joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.type)
411
+ ? decodeType(joinFieldArgs.type, subgraph.schema, subgraph.name)
412
+ : copyType(field.type, subgraph.schema, subgraph.name);
413
+ const subgraphField = type.addField(field.name, copiedFieldType);
414
+ for (const arg of field.arguments()) {
415
+ subgraphField.addArgument(arg.name, copyType(arg.type, subgraph.schema, subgraph.name), arg.defaultValue);
464
416
  }
465
- else {
466
- return addSubgraphInputField(supergraphField, subgraph, encodedType);
417
+ if (joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.requires) {
418
+ subgraphField.applyDirective(subgraph.metadata().requiresDirective(), { 'fields': joinFieldArgs.requires });
419
+ }
420
+ if (joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.provides) {
421
+ subgraphField.applyDirective(subgraph.metadata().providesDirective(), { 'fields': joinFieldArgs.provides });
467
422
  }
423
+ const external = !!(joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.external);
424
+ if (external) {
425
+ subgraphField.applyDirective(subgraph.metadata().externalDirective());
426
+ }
427
+ const usedOverridden = !!(joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.usedOverridden);
428
+ if (usedOverridden) {
429
+ subgraphField.applyDirective(subgraph.metadata().externalDirective(), { 'reason': '[overridden]' });
430
+ }
431
+ if (joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.override) {
432
+ subgraphField.applyDirective(subgraph.metadata().overrideDirective(), { 'from': joinFieldArgs.override });
433
+ }
434
+ if (isShareable && !external && !usedOverridden) {
435
+ subgraphField.applyDirective(subgraph.metadata().shareableDirective());
436
+ }
437
+ return subgraphField;
468
438
  }
469
- function addSubgraphObjectOrInterfaceField(supergraphField, subgraph, encodedType) {
470
- const subgraphType = subgraph.schema.type(supergraphField.parent.name);
471
- if (subgraphType) {
472
- const copiedType = encodedType
473
- ? decodeType(encodedType, subgraph.schema, subgraph.name)
474
- : copyType(supergraphField.type, subgraph.schema, subgraph.name);
475
- const field = subgraphType.addField(supergraphField.name, copiedType);
476
- for (const arg of supergraphField.arguments()) {
477
- field.addArgument(arg.name, copyType(arg.type, subgraph.schema, subgraph.name), arg.defaultValue);
478
- }
479
- return field;
439
+ function addSubgraphInputField({ field, type, subgraph, joinFieldArgs, }) {
440
+ const copiedType = (joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.type)
441
+ ? decodeType(joinFieldArgs === null || joinFieldArgs === void 0 ? void 0 : joinFieldArgs.type, subgraph.schema, subgraph.name)
442
+ : copyType(field.type, subgraph.schema, subgraph.name);
443
+ const inputField = type.addField(field.name, copiedType);
444
+ inputField.defaultValue = field.defaultValue;
445
+ return inputField;
446
+ }
447
+ function extractSubgraphsFromFed1Supergraph({ supergraph, subgraphs, joinSpec, filteredTypes, getSubgraph, }) {
448
+ const typeDirective = joinSpec.typeDirective(supergraph);
449
+ const ownerDirective = joinSpec.ownerDirective(supergraph);
450
+ const fieldDirective = joinSpec.fieldDirective(supergraph);
451
+ const reachableTypesBySubgraph = collectFieldReachableTypesForAllSubgraphs(supergraph, subgraphs.names(), (f, name) => {
452
+ var _a;
453
+ const fieldApplications = f.appliedDirectivesOf(fieldDirective);
454
+ if (fieldApplications.length) {
455
+ const application = fieldApplications.find((application) => { var _a; return ((_a = getSubgraph(application)) === null || _a === void 0 ? void 0 : _a.name) === name; });
456
+ if (application) {
457
+ const args = application.arguments();
458
+ const typesInFederationDirectives = typesUsedInFederationDirective(args.provides, (0, definitions_1.baseType)(f.type))
459
+ .concat(typesUsedInFederationDirective(args.requires, f.parent));
460
+ return { isInSubgraph: true, typesInFederationDirectives };
461
+ }
462
+ else {
463
+ return { isInSubgraph: false, typesInFederationDirectives: [] };
464
+ }
465
+ }
466
+ else {
467
+ const ownerApplications = ownerDirective ? f.parent.appliedDirectivesOf(ownerDirective) : [];
468
+ return { isInSubgraph: !ownerApplications.length || ((_a = getSubgraph(ownerApplications[0])) === null || _a === void 0 ? void 0 : _a.name) == name, typesInFederationDirectives: [] };
469
+ }
470
+ }, (t, name) => {
471
+ const typeApplications = t.appliedDirectivesOf(typeDirective);
472
+ const application = typeApplications.find((application) => { var _a; return (application.arguments().key && (((_a = getSubgraph(application)) === null || _a === void 0 ? void 0 : _a.name) === name)); });
473
+ if (application) {
474
+ const typesInFederationDirectives = typesUsedInFederationDirective(application.arguments().key, t);
475
+ return { isEntityWithKeyInSubgraph: true, typesInFederationDirectives };
476
+ }
477
+ else {
478
+ return { isEntityWithKeyInSubgraph: false, typesInFederationDirectives: [] };
479
+ }
480
+ });
481
+ const includeTypeInSubgraph = (t, name) => { var _a, _b; return (_b = (_a = reachableTypesBySubgraph.get(name)) === null || _a === void 0 ? void 0 : _a.has(t.name)) !== null && _b !== void 0 ? _b : false; };
482
+ for (const type of filteredTypes) {
483
+ const typeApplications = type.appliedDirectivesOf(typeDirective);
484
+ if (!typeApplications.length) {
485
+ for (const subgraph of subgraphs) {
486
+ if (includeTypeInSubgraph(type, subgraph.name)) {
487
+ subgraph.schema.addType((0, definitions_1.newNamedType)(type.kind, type.name));
488
+ }
489
+ }
490
+ }
491
+ else {
492
+ for (const application of typeApplications) {
493
+ const args = application.arguments();
494
+ const subgraph = getSubgraph(application);
495
+ (0, utils_1.assert)(subgraph, () => `Should have found the subgraph for ${application}`);
496
+ const schema = subgraph.schema;
497
+ let subgraphType = schema.type(type.name);
498
+ if (!subgraphType) {
499
+ const kind = args.isInterfaceObject ? 'ObjectType' : type.kind;
500
+ subgraphType = schema.addType((0, definitions_1.newNamedType)(kind, type.name));
501
+ if (args.isInterfaceObject) {
502
+ subgraphType.applyDirective('interfaceObject');
503
+ }
504
+ }
505
+ if (args.key) {
506
+ const { resolvable } = args;
507
+ const directive = subgraphType.applyDirective('key', { 'fields': args.key, resolvable });
508
+ if (args.extension) {
509
+ directive.setOfExtension(subgraphType.newExtension());
510
+ }
511
+ }
512
+ }
513
+ }
480
514
  }
481
- else {
482
- return undefined;
515
+ for (const type of filteredTypes) {
516
+ switch (type.kind) {
517
+ case 'ObjectType':
518
+ case 'InterfaceType':
519
+ for (const implementations of type.interfaceImplementations()) {
520
+ const name = implementations.interface.name;
521
+ for (const subgraph of subgraphs) {
522
+ const subgraphType = subgraph.schema.type(type.name);
523
+ const subgraphItf = subgraph.schema.type(name);
524
+ if (subgraphType && subgraphItf) {
525
+ subgraphType.addImplementedInterface(name);
526
+ }
527
+ }
528
+ }
529
+ case 'InputObjectType':
530
+ for (const field of type.fields()) {
531
+ const fieldApplications = field.appliedDirectivesOf(fieldDirective);
532
+ if (!fieldApplications.length) {
533
+ const ownerApplications = ownerDirective ? type.appliedDirectivesOf(ownerDirective) : [];
534
+ if (ownerApplications.length > 0) {
535
+ (0, utils_1.assert)(ownerApplications.length == 1, () => `Found multiple join__owner directives on type ${type}`);
536
+ const subgraph = getSubgraph(ownerApplications[0]);
537
+ (0, utils_1.assert)(subgraph, () => `Should have found the subgraph for ${ownerApplications[0]}`);
538
+ addSubgraphFieldForFed1(field, subgraph, false);
539
+ }
540
+ else {
541
+ const fieldBaseType = (0, definitions_1.baseType)(field.type);
542
+ const isShareable = (0, definitions_1.isObjectType)(type) && subgraphs.values().filter((s) => s.schema.type(type.name)).length > 1;
543
+ for (const subgraph of subgraphs) {
544
+ if (subgraph.schema.type(fieldBaseType.name)) {
545
+ addSubgraphFieldForFed1(field, subgraph, isShareable);
546
+ }
547
+ }
548
+ }
549
+ }
550
+ else {
551
+ const isShareable = (0, definitions_1.isObjectType)(type) && fieldApplications.length > 1;
552
+ for (const application of fieldApplications) {
553
+ const subgraph = getSubgraph(application);
554
+ if (!subgraph) {
555
+ continue;
556
+ }
557
+ const args = application.arguments();
558
+ addSubgraphFieldForFed1(field, subgraph, isShareable, args);
559
+ }
560
+ }
561
+ }
562
+ break;
563
+ case 'EnumType':
564
+ for (const subgraph of subgraphs) {
565
+ const subgraphEnum = subgraph.schema.type(type.name);
566
+ if (!subgraphEnum) {
567
+ continue;
568
+ }
569
+ (0, utils_1.assert)((0, definitions_1.isEnumType)(subgraphEnum), () => `${subgraphEnum} should be an enum but found a ${subgraphEnum.kind}`);
570
+ for (const value of type.values) {
571
+ subgraphEnum.addValue(value.name);
572
+ }
573
+ }
574
+ break;
575
+ case 'UnionType':
576
+ for (const subgraph of subgraphs) {
577
+ const subgraphUnion = subgraph.schema.type(type.name);
578
+ if (!subgraphUnion) {
579
+ continue;
580
+ }
581
+ (0, utils_1.assert)((0, definitions_1.isUnionType)(subgraphUnion), () => `${subgraphUnion} should be an enum but found a ${subgraphUnion.kind}`);
582
+ for (const memberTypeName of type.types().map((t) => t.name)) {
583
+ const subgraphType = subgraph.schema.type(memberTypeName);
584
+ if (subgraphType) {
585
+ subgraphUnion.addType(subgraphType);
586
+ }
587
+ }
588
+ }
589
+ break;
590
+ }
591
+ }
592
+ const allExecutableDirectives = supergraph.directives().filter((def) => def.hasExecutableLocations());
593
+ for (const subgraph of subgraphs) {
594
+ addExternalFields(subgraph, supergraph, true);
595
+ (0, federation_1.removeInactiveProvidesAndRequires)(subgraph.schema);
596
+ removeUnusedTypesFromSubgraph(subgraph.schema);
597
+ for (const definition of allExecutableDirectives) {
598
+ (0, definitions_1.copyDirectiveDefinitionToSchema)({
599
+ definition,
600
+ schema: subgraph.schema,
601
+ copyDirectiveApplicationsInArguments: false,
602
+ locationFilter: (loc) => (0, definitions_1.isExecutableDirectiveLocation)(loc),
603
+ });
604
+ }
483
605
  }
606
+ return subgraphs;
484
607
  }
485
- function addSubgraphInputField(supergraphField, subgraph, encodedType) {
486
- const subgraphType = subgraph.schema.type(supergraphField.parent.name);
487
- if (subgraphType) {
488
- const copiedType = encodedType
489
- ? decodeType(encodedType, subgraph.schema, subgraph.name)
490
- : copyType(supergraphField.type, subgraph.schema, subgraph.name);
491
- const field = subgraphType.addField(supergraphField.name, copiedType);
492
- field.defaultValue = supergraphField.defaultValue;
493
- return field;
608
+ function addSubgraphFieldForFed1(field, subgraph, isShareable, joinFieldArgs) {
609
+ const subgraphType = subgraph.schema.type(field.parent.name);
610
+ if (!subgraphType) {
611
+ return;
612
+ }
613
+ if (field instanceof definitions_1.FieldDefinition) {
614
+ addSubgraphField({
615
+ field,
616
+ subgraph,
617
+ type: subgraphType,
618
+ isShareable,
619
+ joinFieldArgs,
620
+ });
494
621
  }
495
622
  else {
496
- return undefined;
623
+ addSubgraphInputField({
624
+ field,
625
+ subgraph,
626
+ type: subgraphType,
627
+ joinFieldArgs,
628
+ });
497
629
  }
498
630
  }
499
631
  function decodeType(encodedType, subgraph, subgraphName) {
@@ -553,7 +685,12 @@ function addExternalFieldsFromDirectiveFieldSet(subgraph, parentType, directive,
553
685
  const supergraphType = supergraph.type(type.name);
554
686
  const supergraphField = supergraphType.field(fieldName);
555
687
  (0, utils_1.assert)(supergraphField, () => `No field named ${fieldName} found on type ${type.name} in the supergraph`);
556
- const created = addSubgraphObjectOrInterfaceField(supergraphField, subgraph);
688
+ const created = addSubgraphField({
689
+ field: supergraphField,
690
+ subgraph,
691
+ type,
692
+ isShareable: false,
693
+ });
557
694
  if (!forceNonExternal) {
558
695
  created.applyDirective(external);
559
696
  }
@@ -591,4 +728,22 @@ function maybeUpdateFieldForInterface(toModify, itfField) {
591
728
  toModify.type = itfField.type;
592
729
  }
593
730
  }
731
+ function removeUnusedTypesFromSubgraph(schema) {
732
+ for (const type of schema.types()) {
733
+ switch (type.kind) {
734
+ case 'ObjectType':
735
+ case 'InterfaceType':
736
+ case 'InputObjectType':
737
+ if (!type.hasFields()) {
738
+ type.removeRecursive();
739
+ }
740
+ break;
741
+ case 'UnionType':
742
+ if (type.membersCount() === 0) {
743
+ type.removeRecursive();
744
+ }
745
+ break;
746
+ }
747
+ }
748
+ }
594
749
  //# sourceMappingURL=extractSubgraphsFromSupergraph.js.map