@apollo/federation-internals 2.0.0-preview.7 → 2.0.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 (109) hide show
  1. package/CHANGELOG.md +32 -3
  2. package/dist/buildSchema.d.ts.map +1 -1
  3. package/dist/buildSchema.js +51 -41
  4. package/dist/buildSchema.js.map +1 -1
  5. package/dist/coreSpec.d.ts +16 -8
  6. package/dist/coreSpec.d.ts.map +1 -1
  7. package/dist/coreSpec.js +205 -53
  8. package/dist/coreSpec.js.map +1 -1
  9. package/dist/definitions.d.ts +28 -11
  10. package/dist/definitions.d.ts.map +1 -1
  11. package/dist/definitions.js +185 -67
  12. package/dist/definitions.js.map +1 -1
  13. package/dist/directiveAndTypeSpecification.d.ts +11 -1
  14. package/dist/directiveAndTypeSpecification.d.ts.map +1 -1
  15. package/dist/directiveAndTypeSpecification.js +77 -20
  16. package/dist/directiveAndTypeSpecification.js.map +1 -1
  17. package/dist/error.d.ts +17 -0
  18. package/dist/error.d.ts.map +1 -1
  19. package/dist/error.js +54 -2
  20. package/dist/error.js.map +1 -1
  21. package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
  22. package/dist/extractSubgraphsFromSupergraph.js +7 -1
  23. package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
  24. package/dist/federation.d.ts +22 -5
  25. package/dist/federation.d.ts.map +1 -1
  26. package/dist/federation.js +143 -86
  27. package/dist/federation.js.map +1 -1
  28. package/dist/federationSpec.d.ts +6 -2
  29. package/dist/federationSpec.d.ts.map +1 -1
  30. package/dist/federationSpec.js +47 -22
  31. package/dist/federationSpec.js.map +1 -1
  32. package/dist/inaccessibleSpec.d.ts +10 -2
  33. package/dist/inaccessibleSpec.d.ts.map +1 -1
  34. package/dist/inaccessibleSpec.js +634 -16
  35. package/dist/inaccessibleSpec.js.map +1 -1
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/introspection.d.ts.map +1 -1
  41. package/dist/introspection.js +8 -3
  42. package/dist/introspection.js.map +1 -1
  43. package/dist/joinSpec.d.ts +5 -1
  44. package/dist/joinSpec.d.ts.map +1 -1
  45. package/dist/joinSpec.js +21 -0
  46. package/dist/joinSpec.js.map +1 -1
  47. package/dist/knownCoreFeatures.d.ts +4 -0
  48. package/dist/knownCoreFeatures.d.ts.map +1 -0
  49. package/dist/knownCoreFeatures.js +16 -0
  50. package/dist/knownCoreFeatures.js.map +1 -0
  51. package/dist/operations.d.ts +1 -0
  52. package/dist/operations.d.ts.map +1 -1
  53. package/dist/operations.js +16 -1
  54. package/dist/operations.js.map +1 -1
  55. package/dist/{sharing.d.ts → precompute.d.ts} +1 -1
  56. package/dist/precompute.d.ts.map +1 -0
  57. package/dist/{sharing.js → precompute.js} +3 -3
  58. package/dist/precompute.js.map +1 -0
  59. package/dist/schemaUpgrader.d.ts.map +1 -1
  60. package/dist/schemaUpgrader.js +17 -7
  61. package/dist/schemaUpgrader.js.map +1 -1
  62. package/dist/suggestions.d.ts +1 -1
  63. package/dist/suggestions.d.ts.map +1 -1
  64. package/dist/suggestions.js.map +1 -1
  65. package/dist/supergraphs.d.ts.map +1 -1
  66. package/dist/supergraphs.js +2 -0
  67. package/dist/supergraphs.js.map +1 -1
  68. package/dist/tagSpec.d.ts +7 -2
  69. package/dist/tagSpec.d.ts.map +1 -1
  70. package/dist/tagSpec.js +35 -14
  71. package/dist/tagSpec.js.map +1 -1
  72. package/dist/validate.js +13 -7
  73. package/dist/validate.js.map +1 -1
  74. package/dist/values.d.ts +2 -2
  75. package/dist/values.d.ts.map +1 -1
  76. package/dist/values.js +13 -11
  77. package/dist/values.js.map +1 -1
  78. package/package.json +4 -4
  79. package/src/__tests__/coreSpec.test.ts +212 -0
  80. package/src/__tests__/definitions.test.ts +75 -0
  81. package/src/__tests__/removeInaccessibleElements.test.ts +2229 -137
  82. package/src/__tests__/schemaUpgrader.test.ts +3 -2
  83. package/src/__tests__/subgraphValidation.test.ts +419 -4
  84. package/src/__tests__/values.test.ts +315 -3
  85. package/src/buildSchema.ts +98 -51
  86. package/src/coreSpec.ts +277 -65
  87. package/src/definitions.ts +317 -92
  88. package/src/directiveAndTypeSpecification.ts +98 -21
  89. package/src/error.ts +119 -1
  90. package/src/extractSubgraphsFromSupergraph.ts +7 -1
  91. package/src/federation.ts +184 -102
  92. package/src/federationSpec.ts +56 -24
  93. package/src/inaccessibleSpec.ts +985 -39
  94. package/src/index.ts +2 -0
  95. package/src/introspection.ts +8 -3
  96. package/src/joinSpec.ts +33 -3
  97. package/src/knownCoreFeatures.ts +13 -0
  98. package/src/operations.ts +15 -0
  99. package/src/{sharing.ts → precompute.ts} +3 -6
  100. package/src/schemaUpgrader.ts +29 -13
  101. package/src/suggestions.ts +1 -1
  102. package/src/supergraphs.ts +2 -0
  103. package/src/tagSpec.ts +49 -16
  104. package/src/validate.ts +20 -9
  105. package/src/values.ts +39 -12
  106. package/tsconfig.test.tsbuildinfo +1 -1
  107. package/tsconfig.tsbuildinfo +1 -1
  108. package/dist/sharing.d.ts.map +0 -1
  109. package/dist/sharing.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.removeInactiveProvidesAndRequires = exports.addSubgraphToError = exports.addSubgraphToASTNode = exports.Subgraph = exports.FEDERATION_OPERATION_FIELDS = exports.entitiesFieldName = exports.serviceFieldName = exports.FEDERATION_OPERATION_TYPES = exports.entityTypeSpec = exports.serviceTypeSpec = exports.anyTypeSpec = exports.Subgraphs = exports.subgraphsFromServiceList = exports.collectTargetFields = exports.parseFieldSetArgument = exports.newEmptyFederation2Schema = exports.buildSubgraph = exports.isEntityType = exports.isFederationField = exports.isFederationSubgraphSchema = exports.federationMetadata = exports.printSubgraphNames = exports.asFed2SubgraphDocument = exports.setSchemaAsFed2Subgraph = exports.FederationBlueprint = exports.FederationMetadata = exports.collectUsedExternalFieldsCoordinates = exports.FEDERATION_RESERVED_SUBGRAPH_NAME = void 0;
3
+ exports.removeInactiveProvidesAndRequires = exports.addSubgraphToError = exports.addSubgraphToASTNode = exports.Subgraph = exports.FEDERATION_OPERATION_FIELDS = exports.entitiesFieldName = exports.serviceFieldName = exports.FEDERATION_OPERATION_TYPES = exports.entityTypeSpec = exports.serviceTypeSpec = exports.anyTypeSpec = exports.Subgraphs = exports.subgraphsFromServiceList = exports.collectTargetFields = exports.parseFieldSetArgument = exports.newEmptyFederation2Schema = exports.buildSubgraph = exports.isEntityType = exports.isFederationField = exports.isFederationSubgraphSchema = exports.federationMetadata = exports.printSubgraphNames = exports.asFed2SubgraphDocument = exports.FEDERATION2_LINK_WTH_FULL_IMPORTS = exports.setSchemaAsFed2Subgraph = exports.FederationBlueprint = exports.FederationMetadata = exports.collectUsedFields = exports.FEDERATION_UNNAMED_SUBGRAPH_NAME = exports.FEDERATION_RESERVED_SUBGRAPH_NAME = void 0;
4
4
  const definitions_1 = require("./definitions");
5
5
  const utils_1 = require("./utils");
6
6
  const specifiedRules_1 = require("graphql/validation/specifiedRules");
@@ -9,16 +9,20 @@ const KnownTypeNamesInFederationRule_1 = require("./validation/KnownTypeNamesInF
9
9
  const buildSchema_1 = require("./buildSchema");
10
10
  const operations_1 = require("./operations");
11
11
  const tagSpec_1 = require("./tagSpec");
12
+ const inaccessibleSpec_1 = require("./inaccessibleSpec");
12
13
  const error_1 = require("./error");
13
- const sharing_1 = require("./sharing");
14
+ const precompute_1 = require("./precompute");
14
15
  const coreSpec_1 = require("./coreSpec");
15
16
  const federationSpec_1 = require("./federationSpec");
16
17
  const print_1 = require("./print");
17
18
  const directiveAndTypeSpecification_1 = require("./directiveAndTypeSpecification");
19
+ const suggestions_1 = require("./suggestions");
18
20
  const linkSpec = coreSpec_1.LINK_VERSIONS.latest();
19
21
  const tagSpec = tagSpec_1.TAG_VERSIONS.latest();
22
+ const inaccessibleSpec = inaccessibleSpec_1.INACCESSIBLE_VERSIONS.latest();
20
23
  const federationSpec = federationSpec_1.FEDERATION_VERSIONS.latest();
21
24
  exports.FEDERATION_RESERVED_SUBGRAPH_NAME = '_';
25
+ exports.FEDERATION_UNNAMED_SUBGRAPH_NAME = '<unnamed>';
22
26
  const FEDERATION_OMITTED_VALIDATION_RULES = [
23
27
  graphql_1.PossibleTypeExtensionsRule,
24
28
  graphql_1.KnownTypeNamesRule
@@ -148,29 +152,29 @@ function validateAllFieldSet(definition, targetTypeExtractor, errorCollector, fe
148
152
  }
149
153
  }
150
154
  }
151
- function collectUsedExternalFieldsCoordinates(metadata) {
152
- const usedExternalCoordinates = new Set();
153
- collectUsedExternaFieldsForDirective(metadata, metadata.keyDirective(), type => type, usedExternalCoordinates);
154
- collectUsedExternaFieldsForDirective(metadata, metadata.requiresDirective(), field => field.parent, usedExternalCoordinates);
155
- collectUsedExternaFieldsForDirective(metadata, metadata.providesDirective(), field => {
155
+ function collectUsedFields(metadata) {
156
+ const usedFields = new Set();
157
+ collectUsedFieldsForDirective(metadata.keyDirective(), type => type, usedFields);
158
+ collectUsedFieldsForDirective(metadata.requiresDirective(), field => field.parent, usedFields);
159
+ collectUsedFieldsForDirective(metadata.providesDirective(), field => {
156
160
  const type = (0, definitions_1.baseType)(field.type);
157
161
  return (0, definitions_1.isCompositeType)(type) ? type : undefined;
158
- }, usedExternalCoordinates);
159
- for (const itfType of metadata.schema.types('InterfaceType')) {
162
+ }, usedFields);
163
+ for (const itfType of metadata.schema.interfaceTypes()) {
160
164
  const runtimeTypes = itfType.possibleRuntimeTypes();
161
165
  for (const field of itfType.fields()) {
162
166
  for (const runtimeType of runtimeTypes) {
163
167
  const implemField = runtimeType.field(field.name);
164
- if (implemField && metadata.isFieldExternal(implemField)) {
165
- usedExternalCoordinates.add(implemField.coordinate);
168
+ if (implemField) {
169
+ usedFields.add(implemField);
166
170
  }
167
171
  }
168
172
  }
169
173
  }
170
- return usedExternalCoordinates;
174
+ return usedFields;
171
175
  }
172
- exports.collectUsedExternalFieldsCoordinates = collectUsedExternalFieldsCoordinates;
173
- function collectUsedExternaFieldsForDirective(metadata, definition, targetTypeExtractor, usedExternalCoordinates) {
176
+ exports.collectUsedFields = collectUsedFields;
177
+ function collectUsedFieldsForDirective(definition, targetTypeExtractor, usedFieldDefs) {
174
178
  for (const application of definition.applications()) {
175
179
  const type = targetTypeExtractor(application.parent);
176
180
  if (!type) {
@@ -181,32 +185,28 @@ function collectUsedExternaFieldsForDirective(metadata, definition, targetTypeEx
181
185
  directive: application,
182
186
  includeInterfaceFieldsImplementations: true,
183
187
  validate: false,
184
- }).filter((field) => metadata.isFieldExternal(field))
185
- .forEach((field) => usedExternalCoordinates.add(field.coordinate));
188
+ }).forEach((field) => usedFieldDefs.add(field));
186
189
  }
187
190
  }
188
191
  function validateAllExternalFieldsUsed(metadata, errorCollector) {
189
- const allUsedExternals = collectUsedExternalFieldsCoordinates(metadata);
190
192
  for (const type of metadata.schema.types()) {
191
193
  if (!(0, definitions_1.isObjectType)(type) && !(0, definitions_1.isInterfaceType)(type)) {
192
194
  continue;
193
195
  }
194
196
  for (const field of type.fields()) {
195
- if (!metadata.isFieldExternal(field) || allUsedExternals.has(field.coordinate)) {
197
+ if (!metadata.isFieldExternal(field) || metadata.isFieldUsed(field)) {
196
198
  continue;
197
199
  }
198
- if (!isFieldSatisfyingInterface(field)) {
199
- errorCollector.push(error_1.ERRORS.EXTERNAL_UNUSED.err({
200
- message: `Field "${field.coordinate}" is marked @external but is not used in any federation directive (@key, @provides, @requires) or to satisfy an interface;`
201
- + ' the field declaration has no use and should be removed (or the field should not be @external).',
202
- nodes: field.sourceAST,
203
- }));
204
- }
200
+ errorCollector.push(error_1.ERRORS.EXTERNAL_UNUSED.err({
201
+ message: `Field "${field.coordinate}" is marked @external but is not used in any federation directive (@key, @provides, @requires) or to satisfy an interface;`
202
+ + ' the field declaration has no use and should be removed (or the field should not be @external).',
203
+ nodes: field.sourceAST,
204
+ }));
205
205
  }
206
206
  }
207
207
  }
208
208
  function validateNoExternalOnInterfaceFields(metadata, errorCollector) {
209
- for (const itf of metadata.schema.types('InterfaceType')) {
209
+ for (const itf of metadata.schema.interfaceTypes()) {
210
210
  for (const field of itf.fields()) {
211
211
  if (metadata.isFieldExternal(field)) {
212
212
  errorCollector.push(error_1.ERRORS.EXTERNAL_ON_INTERFACE.err({
@@ -217,9 +217,6 @@ function validateNoExternalOnInterfaceFields(metadata, errorCollector) {
217
217
  }
218
218
  }
219
219
  }
220
- function isFieldSatisfyingInterface(field) {
221
- return field.parent.interfaces().some(itf => itf.field(field.name));
222
- }
223
220
  function validateInterfaceRuntimeImplementationFieldsTypes(itf, metadata, errorCollector) {
224
221
  var _a;
225
222
  const requiresDirective = (_a = federationMetadata(itf.schema())) === null || _a === void 0 ? void 0 : _a.requiresDirective();
@@ -255,14 +252,6 @@ const printFieldCoordinate = (f) => `"${f.coordinate}"`;
255
252
  function formatFieldsToReturnType([type, implems]) {
256
253
  return `${(0, utils_1.joinStrings)(implems.map(printFieldCoordinate))} ${implems.length == 1 ? 'has' : 'have'} type "${type}"`;
257
254
  }
258
- function checkIfFed2Schema(schema) {
259
- const core = schema.coreFeatures;
260
- if (!core) {
261
- return false;
262
- }
263
- const federationFeature = core.getByIdentity(federationSpec.identity);
264
- return !!federationFeature && federationFeature.url.version.satisfies(new coreSpec_1.FeatureVersion(2, 0));
265
- }
266
255
  class FederationMetadata {
267
256
  constructor(schema) {
268
257
  this.schema = schema;
@@ -271,13 +260,19 @@ class FederationMetadata {
271
260
  this._externalTester = undefined;
272
261
  this._sharingPredicate = undefined;
273
262
  this._isFed2Schema = undefined;
263
+ this._fieldUsedPredicate = undefined;
274
264
  }
275
265
  isFed2Schema() {
276
266
  if (!this._isFed2Schema) {
277
- this._isFed2Schema = checkIfFed2Schema(this.schema);
267
+ const feature = this.federationFeature();
268
+ this._isFed2Schema = !!feature && feature.url.version.satisfies(new coreSpec_1.FeatureVersion(2, 0));
278
269
  }
279
270
  return this._isFed2Schema;
280
271
  }
272
+ federationFeature() {
273
+ var _a;
274
+ return (_a = this.schema.coreFeatures) === null || _a === void 0 ? void 0 : _a.getByIdentity(federationSpec.identity);
275
+ }
281
276
  externalTester() {
282
277
  if (!this._externalTester) {
283
278
  this._externalTester = new ExternalTester(this.schema);
@@ -286,10 +281,20 @@ class FederationMetadata {
286
281
  }
287
282
  sharingPredicate() {
288
283
  if (!this._sharingPredicate) {
289
- this._sharingPredicate = (0, sharing_1.computeShareables)(this.schema);
284
+ this._sharingPredicate = (0, precompute_1.computeShareables)(this.schema);
290
285
  }
291
286
  return this._sharingPredicate;
292
287
  }
288
+ fieldUsedPredicate() {
289
+ if (!this._fieldUsedPredicate) {
290
+ const usedFields = collectUsedFields(this);
291
+ this._fieldUsedPredicate = (field) => !!usedFields.has(field);
292
+ }
293
+ return this._fieldUsedPredicate;
294
+ }
295
+ isFieldUsed(field) {
296
+ return this.fieldUsedPredicate()(field);
297
+ }
293
298
  isFieldExternal(field) {
294
299
  return this.externalTester().isExternal(field);
295
300
  }
@@ -343,6 +348,9 @@ class FederationMetadata {
343
348
  keyDirective() {
344
349
  return this.getFederationDirective(federationSpec_1.keyDirectiveSpec.name);
345
350
  }
351
+ overrideDirective() {
352
+ return this.getFederationDirective(federationSpec_1.overrideDirectiveSpec.name);
353
+ }
346
354
  extendsDirective() {
347
355
  return this.getFederationDirective(federationSpec_1.extendsDirectiveSpec.name);
348
356
  }
@@ -359,7 +367,10 @@ class FederationMetadata {
359
367
  return this.getFederationDirective(federationSpec_1.shareableDirectiveSpec.name);
360
368
  }
361
369
  tagDirective() {
362
- return this.getFederationDirective(federationSpec_1.tagDirectiveSpec.name);
370
+ return this.getFederationDirective(tagSpec.tagDirectiveSpec.name);
371
+ }
372
+ inaccessibleDirective() {
373
+ return this.getFederationDirective(inaccessibleSpec.inaccessibleDirectiveSpec.name);
363
374
  }
364
375
  allFederationDirectives() {
365
376
  const baseDirectives = [
@@ -371,7 +382,7 @@ class FederationMetadata {
371
382
  this.extendsDirective(),
372
383
  ];
373
384
  return this.isFed2Schema()
374
- ? baseDirectives.concat(this.shareableDirective())
385
+ ? baseDirectives.concat(this.shareableDirective(), this.inaccessibleDirective(), this.overrideDirective())
375
386
  : baseDirectives;
376
387
  }
377
388
  entityType() {
@@ -401,6 +412,10 @@ class FederationMetadata {
401
412
  }
402
413
  exports.FederationMetadata = FederationMetadata;
403
414
  class FederationBlueprint extends definitions_1.SchemaBlueprint {
415
+ constructor(withRootTypeRenaming) {
416
+ super();
417
+ this.withRootTypeRenaming = withRootTypeRenaming;
418
+ }
404
419
  onAddedCoreFeature(schema, feature) {
405
420
  super.onAddedCoreFeature(schema, feature);
406
421
  if (feature.url.identity === federationSpec_1.federationIdentity) {
@@ -410,12 +425,14 @@ class FederationBlueprint extends definitions_1.SchemaBlueprint {
410
425
  }
411
426
  }
412
427
  }
413
- onMissingDirectiveDefinition(schema, name) {
428
+ onMissingDirectiveDefinition(schema, name, args) {
414
429
  if (name === coreSpec_1.linkDirectiveDefaultName) {
415
- linkSpec.addToSchema(schema);
416
- return schema.directive(name);
430
+ const url = args && args['url'];
431
+ const as = url && url.startsWith(linkSpec.identity) ? args['as'] : undefined;
432
+ const errors = linkSpec.addDefinitionsToSchema(schema, as);
433
+ return errors.length > 0 ? errors : schema.directive(name);
417
434
  }
418
- return super.onMissingDirectiveDefinition(schema, name);
435
+ return super.onMissingDirectiveDefinition(schema, name, args);
419
436
  }
420
437
  ignoreParsedField(type, fieldName) {
421
438
  if (!exports.FEDERATION_OPERATION_FIELDS.includes(fieldName)) {
@@ -431,7 +448,7 @@ class FederationBlueprint extends definitions_1.SchemaBlueprint {
431
448
  }
432
449
  }
433
450
  onDirectiveDefinitionAndSchemaParsed(schema) {
434
- completeSubgraphSchema(schema);
451
+ return completeSubgraphSchema(schema);
435
452
  }
436
453
  onInvalidation(schema) {
437
454
  super.onInvalidation(schema);
@@ -442,20 +459,22 @@ class FederationBlueprint extends definitions_1.SchemaBlueprint {
442
459
  onValidation(schema) {
443
460
  var _a;
444
461
  const errors = super.onValidation(schema);
445
- for (const k of definitions_1.allSchemaRootKinds) {
446
- const type = (_a = schema.schemaDefinition.root(k)) === null || _a === void 0 ? void 0 : _a.type;
447
- const defaultName = (0, definitions_1.defaultRootName)(k);
448
- if (type && type.name !== defaultName) {
449
- const existing = schema.type(defaultName);
450
- if (existing) {
451
- errors.push(error_1.ERROR_CATEGORIES.ROOT_TYPE_USED.get(k).err({
452
- message: `The schema has a type named "${defaultName}" but it is not set as the ${k} root type ("${type.name}" is instead): `
453
- + 'this is not supported by federation. '
454
- + 'If a root type does not use its default name, there should be no other type with that default name.',
455
- nodes: (0, definitions_1.sourceASTs)(type, existing),
456
- }));
462
+ if (this.withRootTypeRenaming) {
463
+ for (const k of definitions_1.allSchemaRootKinds) {
464
+ const type = (_a = schema.schemaDefinition.root(k)) === null || _a === void 0 ? void 0 : _a.type;
465
+ const defaultName = (0, definitions_1.defaultRootName)(k);
466
+ if (type && type.name !== defaultName) {
467
+ const existing = schema.type(defaultName);
468
+ if (existing) {
469
+ errors.push(error_1.ERROR_CATEGORIES.ROOT_TYPE_USED.get(k).err({
470
+ message: `The schema has a type named "${defaultName}" but it is not set as the ${k} root type ("${type.name}" is instead): `
471
+ + 'this is not supported by federation. '
472
+ + 'If a root type does not use its default name, there should be no other type with that default name.',
473
+ nodes: (0, definitions_1.sourceASTs)(type, existing),
474
+ }));
475
+ }
476
+ type.rename(defaultName);
457
477
  }
458
- type.rename(defaultName);
459
478
  }
460
479
  }
461
480
  const metadata = federationMetadata(schema);
@@ -497,7 +516,7 @@ class FederationBlueprint extends definitions_1.SchemaBlueprint {
497
516
  errors.push(error);
498
517
  }
499
518
  }
500
- for (const itf of schema.types('InterfaceType')) {
519
+ for (const itf of schema.interfaceTypes()) {
501
520
  validateInterfaceRuntimeImplementationFieldsTypes(itf, metadata, errors);
502
521
  }
503
522
  return errors;
@@ -505,9 +524,35 @@ class FederationBlueprint extends definitions_1.SchemaBlueprint {
505
524
  validationRules() {
506
525
  return FEDERATION_VALIDATION_RULES;
507
526
  }
527
+ onUnknownDirectiveValidationError(schema, unknownDirectiveName, error) {
528
+ const metadata = federationMetadata(schema);
529
+ (0, utils_1.assert)(metadata, `This method should only have been called on a subgraph schema`);
530
+ if (federationSpec_1.ALL_FEDERATION_DIRECTIVES_DEFAULT_NAMES.includes(unknownDirectiveName)) {
531
+ if (metadata.isFed2Schema()) {
532
+ const federationFeature = metadata.federationFeature();
533
+ (0, utils_1.assert)(federationFeature, 'Fed2 subgraph _must_ link to the federation feature');
534
+ const directiveNameInSchema = federationFeature.directiveNameInSchema(unknownDirectiveName);
535
+ if (directiveNameInSchema.startsWith(federationFeature.nameInSchema + '__')) {
536
+ return (0, error_1.withModifiedErrorMessage)(error, `${error.message} If you meant the "@${unknownDirectiveName}" federation directive, you should use fully-qualified name "@${directiveNameInSchema}" or add "@${unknownDirectiveName}" to the \`import\` argument of the @link to the federation specification.`);
537
+ }
538
+ else {
539
+ return (0, error_1.withModifiedErrorMessage)(error, `${error.message} If you meant the "@${unknownDirectiveName}" federation directive, you should use "@${directiveNameInSchema}" as it is imported under that name in the @link to the federation specification of this schema.`);
540
+ }
541
+ }
542
+ else {
543
+ return (0, error_1.withModifiedErrorMessage)(error, `${error.message} If you meant the "@${unknownDirectiveName}" federation 2 directive, note that this schema is a federation 1 schema. To be a federation 2 schema, it needs to @link to the federation specifcation v2.`);
544
+ }
545
+ }
546
+ else if (!metadata.isFed2Schema()) {
547
+ const suggestions = (0, suggestions_1.suggestionList)(unknownDirectiveName, federationSpec_1.FEDERATION2_ONLY_SPEC_DIRECTIVES.map((spec) => spec.name));
548
+ if (suggestions.length > 0) {
549
+ return (0, error_1.withModifiedErrorMessage)(error, `${error.message}${(0, suggestions_1.didYouMean)(suggestions.map((s) => '@' + s))} If so, note that ${suggestions.length === 1 ? 'it is a federation 2 directive' : 'they are federation 2 directives'} but this schema is a federation 1 one. To be a federation 2 schema, it needs to @link to the federation specifcation v2.`);
550
+ }
551
+ }
552
+ return error;
553
+ }
508
554
  }
509
555
  exports.FederationBlueprint = FederationBlueprint;
510
- const federationBlueprint = new FederationBlueprint();
511
556
  function findUnusedNamedForLinkDirective(schema) {
512
557
  if (!schema.directive(linkSpec.url.name)) {
513
558
  return undefined;
@@ -530,7 +575,10 @@ function setSchemaAsFed2Subgraph(schema) {
530
575
  }
531
576
  else {
532
577
  const alias = findUnusedNamedForLinkDirective(schema);
533
- linkSpec.addToSchema(schema, alias);
578
+ const errors = linkSpec.addToSchema(schema, alias);
579
+ if (errors.length > 0) {
580
+ throw (0, definitions_1.ErrGraphQLValidationFailed)(errors);
581
+ }
534
582
  spec = linkSpec;
535
583
  core = schema.coreFeatures;
536
584
  (0, utils_1.assert)(core, 'Schema should now be a core schema');
@@ -540,9 +588,13 @@ function setSchemaAsFed2Subgraph(schema) {
540
588
  url: federationSpec.url.toString(),
541
589
  import: federationSpec_1.FEDERATION2_SPEC_DIRECTIVES.map((spec) => `@${spec.name}`),
542
590
  });
543
- completeSubgraphSchema(schema);
591
+ const errors = completeSubgraphSchema(schema);
592
+ if (errors.length > 0) {
593
+ throw (0, definitions_1.ErrGraphQLValidationFailed)(errors);
594
+ }
544
595
  }
545
596
  exports.setSchemaAsFed2Subgraph = setSchemaAsFed2Subgraph;
597
+ exports.FEDERATION2_LINK_WTH_FULL_IMPORTS = '@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@requires", "@provides", "@external", "@tag", "@extends", "@shareable", "@inaccessible", "@override"])';
546
598
  function asFed2SubgraphDocument(document) {
547
599
  const fed2LinkExtension = {
548
600
  kind: graphql_1.Kind.SCHEMA_EXTENSION,
@@ -599,9 +651,9 @@ function isEntityType(type) {
599
651
  return !!metadata && type.hasAppliedDirective(metadata.keyDirective());
600
652
  }
601
653
  exports.isEntityType = isEntityType;
602
- function buildSubgraph(name, url, source) {
654
+ function buildSubgraph(name, url, source, withRootTypeRenaming = true) {
603
655
  const buildOptions = {
604
- blueprint: federationBlueprint,
656
+ blueprint: new FederationBlueprint(withRootTypeRenaming),
605
657
  validate: false,
606
658
  };
607
659
  let subgraph;
@@ -612,7 +664,7 @@ function buildSubgraph(name, url, source) {
612
664
  subgraph = new Subgraph(name, url, schema);
613
665
  }
614
666
  catch (e) {
615
- if (e instanceof graphql_1.GraphQLError) {
667
+ if (e instanceof graphql_1.GraphQLError && name !== exports.FEDERATION_UNNAMED_SUBGRAPH_NAME) {
616
668
  throw addSubgraphToError(e, name, error_1.ERRORS.INVALID_GRAPHQL);
617
669
  }
618
670
  else {
@@ -623,7 +675,7 @@ function buildSubgraph(name, url, source) {
623
675
  }
624
676
  exports.buildSubgraph = buildSubgraph;
625
677
  function newEmptyFederation2Schema() {
626
- const schema = new definitions_1.Schema(federationBlueprint);
678
+ const schema = new definitions_1.Schema(new FederationBlueprint(true));
627
679
  setSchemaAsFed2Subgraph(schema);
628
680
  return schema;
629
681
  }
@@ -633,20 +685,23 @@ function completeSubgraphSchema(schema) {
633
685
  if (coreFeatures) {
634
686
  const fedFeature = coreFeatures.getByIdentity(federationSpec_1.federationIdentity);
635
687
  if (fedFeature) {
636
- completeFed2SubgraphSchema(schema);
688
+ return completeFed2SubgraphSchema(schema);
637
689
  }
638
690
  else {
639
- completeFed1SubgraphSchema(schema);
691
+ return completeFed1SubgraphSchema(schema);
640
692
  }
641
693
  }
642
694
  else {
643
695
  const fedLink = schema.schemaDefinition.appliedDirectivesOf(coreSpec_1.linkDirectiveDefaultName).find(isFedSpecLinkDirective);
644
696
  if (fedLink) {
645
- linkSpec.addToSchema(schema);
646
- completeFed2SubgraphSchema(schema);
697
+ const errors = linkSpec.addToSchema(schema);
698
+ if (errors.length > 0) {
699
+ return errors;
700
+ }
701
+ return completeFed2SubgraphSchema(schema);
647
702
  }
648
703
  else {
649
- completeFed1SubgraphSchema(schema);
704
+ return completeFed1SubgraphSchema(schema);
650
705
  }
651
706
  }
652
707
  }
@@ -655,13 +710,15 @@ function isFedSpecLinkDirective(directive) {
655
710
  return directive.name === coreSpec_1.linkDirectiveDefaultName && args['url'] && args['url'].startsWith(federationSpec_1.federationIdentity);
656
711
  }
657
712
  function completeFed1SubgraphSchema(schema) {
658
- federationSpec_1.fieldSetTypeSpec.checkOrAdd(schema, '_' + federationSpec_1.fieldSetTypeSpec.name);
659
- federationSpec_1.keyDirectiveSpec.checkOrAdd(schema);
660
- federationSpec_1.requiresDirectiveSpec.checkOrAdd(schema);
661
- federationSpec_1.providesDirectiveSpec.checkOrAdd(schema);
662
- federationSpec_1.extendsDirectiveSpec.checkOrAdd(schema);
663
- federationSpec_1.externalDirectiveSpec.checkOrAdd(schema);
664
- federationSpec_1.tagDirectiveSpec.checkOrAdd(schema);
713
+ return [
714
+ federationSpec_1.fieldSetTypeSpec.checkOrAdd(schema, '_' + federationSpec_1.fieldSetTypeSpec.name),
715
+ federationSpec_1.keyDirectiveSpec.checkOrAdd(schema),
716
+ federationSpec_1.requiresDirectiveSpec.checkOrAdd(schema),
717
+ federationSpec_1.providesDirectiveSpec.checkOrAdd(schema),
718
+ federationSpec_1.extendsDirectiveSpec.checkOrAdd(schema),
719
+ federationSpec_1.externalDirectiveSpec.checkOrAdd(schema),
720
+ tagSpec.tagDirectiveSpec.checkOrAdd(schema),
721
+ ].flat();
665
722
  }
666
723
  function completeFed2SubgraphSchema(schema) {
667
724
  const coreFeatures = schema.coreFeatures;
@@ -670,12 +727,12 @@ function completeFed2SubgraphSchema(schema) {
670
727
  (0, utils_1.assert)(fedFeature, 'This method should not have been called on a schema with no @link for federation');
671
728
  const spec = federationSpec_1.FEDERATION_VERSIONS.find(fedFeature.url.version);
672
729
  if (!spec) {
673
- throw error_1.ERRORS.UNKNOWN_FEDERATION_LINK_VERSION.err({
674
- message: `Invalid version ${fedFeature.url.version} for the federation feature in @link direction on schema`,
675
- nodes: fedFeature.directive.sourceAST
676
- });
730
+ return [error_1.ERRORS.UNKNOWN_FEDERATION_LINK_VERSION.err({
731
+ message: `Invalid version ${fedFeature.url.version} for the federation feature in @link direction on schema`,
732
+ nodes: fedFeature.directive.sourceAST
733
+ })];
677
734
  }
678
- spec.addElementsToSchema(schema);
735
+ return spec.addElementsToSchema(schema);
679
736
  }
680
737
  function parseFieldSetArgument({ parentType, directive, fieldAccessor, validate, }) {
681
738
  var _a;
@@ -852,7 +909,7 @@ exports.serviceTypeSpec = (0, directiveAndTypeSpecification_1.createObjectTypeSp
852
909
  exports.entityTypeSpec = (0, directiveAndTypeSpecification_1.createUnionTypeSpecification)({
853
910
  name: '_Entity',
854
911
  membersFct: (schema) => {
855
- return schema.types("ObjectType").filter(isEntityType).map((t) => t.name);
912
+ return schema.objectTypes().filter(isEntityType).map((t) => t.name);
856
913
  },
857
914
  });
858
915
  exports.FEDERATION_OPERATION_TYPES = [exports.anyTypeSpec, exports.serviceTypeSpec, exports.entityTypeSpec];
@@ -899,7 +956,7 @@ class Subgraph {
899
956
  entityField.remove();
900
957
  }
901
958
  if (!queryType.field(exports.serviceFieldName)) {
902
- queryType.addField(exports.serviceFieldName, metadata.serviceType());
959
+ queryType.addField(exports.serviceFieldName, new definitions_1.NonNullType(metadata.serviceType()));
903
960
  }
904
961
  }
905
962
  validate() {