@apollo/federation-internals 2.1.0-alpha.0 → 2.1.0-alpha.3

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 (82) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/buildSchema.d.ts.map +1 -1
  3. package/dist/buildSchema.js +24 -13
  4. package/dist/buildSchema.js.map +1 -1
  5. package/dist/coreSpec.d.ts.map +1 -1
  6. package/dist/coreSpec.js +15 -42
  7. package/dist/coreSpec.js.map +1 -1
  8. package/dist/definitions.d.ts +47 -8
  9. package/dist/definitions.d.ts.map +1 -1
  10. package/dist/definitions.js +186 -121
  11. package/dist/definitions.js.map +1 -1
  12. package/dist/directiveAndTypeSpecification.js +14 -48
  13. package/dist/directiveAndTypeSpecification.js.map +1 -1
  14. package/dist/error.d.ts +20 -17
  15. package/dist/error.d.ts.map +1 -1
  16. package/dist/error.js +42 -7
  17. package/dist/error.js.map +1 -1
  18. package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
  19. package/dist/extractSubgraphsFromSupergraph.js +9 -0
  20. package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
  21. package/dist/federation.d.ts +5 -1
  22. package/dist/federation.d.ts.map +1 -1
  23. package/dist/federation.js +83 -128
  24. package/dist/federation.js.map +1 -1
  25. package/dist/federationSpec.d.ts +13 -9
  26. package/dist/federationSpec.d.ts.map +1 -1
  27. package/dist/federationSpec.js +27 -5
  28. package/dist/federationSpec.js.map +1 -1
  29. package/dist/inaccessibleSpec.js +44 -67
  30. package/dist/inaccessibleSpec.js.map +1 -1
  31. package/dist/operations.d.ts +48 -21
  32. package/dist/operations.d.ts.map +1 -1
  33. package/dist/operations.js +334 -52
  34. package/dist/operations.js.map +1 -1
  35. package/dist/print.d.ts +1 -1
  36. package/dist/print.d.ts.map +1 -1
  37. package/dist/print.js +1 -1
  38. package/dist/print.js.map +1 -1
  39. package/dist/schemaUpgrader.js +2 -8
  40. package/dist/schemaUpgrader.js.map +1 -1
  41. package/dist/supergraphs.d.ts.map +1 -1
  42. package/dist/supergraphs.js +4 -4
  43. package/dist/supergraphs.js.map +1 -1
  44. package/dist/tagSpec.d.ts.map +1 -1
  45. package/dist/tagSpec.js +1 -3
  46. package/dist/tagSpec.js.map +1 -1
  47. package/dist/utils.d.ts +9 -0
  48. package/dist/utils.d.ts.map +1 -1
  49. package/dist/utils.js +31 -1
  50. package/dist/utils.js.map +1 -1
  51. package/dist/validate.d.ts.map +1 -1
  52. package/dist/validate.js +26 -22
  53. package/dist/validate.js.map +1 -1
  54. package/dist/validation/KnownTypeNamesInFederationRule.js +1 -1
  55. package/dist/validation/KnownTypeNamesInFederationRule.js.map +1 -1
  56. package/dist/values.d.ts.map +1 -1
  57. package/dist/values.js +19 -18
  58. package/dist/values.js.map +1 -1
  59. package/package.json +2 -2
  60. package/src/__tests__/definitions.test.ts +18 -0
  61. package/src/__tests__/operations.test.ts +217 -99
  62. package/src/__tests__/subgraphValidation.test.ts +77 -0
  63. package/src/buildSchema.ts +30 -23
  64. package/src/coreSpec.ts +47 -43
  65. package/src/definitions.ts +281 -125
  66. package/src/directiveAndTypeSpecification.ts +50 -48
  67. package/src/error.ts +94 -41
  68. package/src/extractSubgraphsFromSupergraph.ts +20 -0
  69. package/src/federation.ts +158 -136
  70. package/src/federationSpec.ts +32 -5
  71. package/src/inaccessibleSpec.ts +209 -196
  72. package/src/operations.ts +525 -76
  73. package/src/print.ts +1 -1
  74. package/src/schemaUpgrader.ts +8 -8
  75. package/src/supergraphs.ts +5 -4
  76. package/src/tagSpec.ts +2 -3
  77. package/src/utils.ts +40 -0
  78. package/src/validate.ts +60 -52
  79. package/src/validation/KnownTypeNamesInFederationRule.ts +1 -1
  80. package/src/values.ts +19 -18
  81. package/tsconfig.test.tsbuildinfo +1 -1
  82. package/tsconfig.tsbuildinfo +1 -1
package/src/coreSpec.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ASTNode, DirectiveLocation, GraphQLError, StringValueNode } from "graphql";
2
2
  import { URL } from "url";
3
- import { CoreFeature, Directive, DirectiveDefinition, EnumType, ErrGraphQLAPISchemaValidationFailed, ErrGraphQLValidationFailed, InputType, ListType, NamedType, NonNullType, ScalarType, Schema, SchemaDefinition, SchemaElement } from "./definitions";
3
+ import { CoreFeature, Directive, DirectiveDefinition, EnumType, ErrGraphQLAPISchemaValidationFailed, ErrGraphQLValidationFailed, InputType, ListType, NamedType, NonNullType, ScalarType, Schema, SchemaDefinition, SchemaElement, sourceASTs } from "./definitions";
4
4
  import { sameType } from "./types";
5
5
  import { err } from '@apollo/core-schema';
6
6
  import { assert, firstOf } from './utils';
@@ -185,10 +185,10 @@ export function extractCoreFeatureImports(url: FeatureUrl, directive: Directive<
185
185
  continue;
186
186
  }
187
187
  if (typeof elt !== 'object') {
188
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
189
- message: `Invalid sub-value ${valueToString(elt)} for @link(import:) argument: values should be either strings or input object values of the form { name: "<importedElement>", as: "<alias>" }.`,
190
- nodes: directive.sourceAST
191
- }));
188
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
189
+ `Invalid sub-value ${valueToString(elt)} for @link(import:) argument: values should be either strings or input object values of the form { name: "<importedElement>", as: "<alias>" }.`,
190
+ { nodes: directive.sourceAST },
191
+ ));
192
192
  continue;
193
193
  }
194
194
  let name: string | undefined;
@@ -196,28 +196,28 @@ export function extractCoreFeatureImports(url: FeatureUrl, directive: Directive<
196
196
  switch (key) {
197
197
  case 'name':
198
198
  if (typeof value !== 'string') {
199
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
200
- message: `Invalid value for the "name" field for sub-value ${valueToString(elt)} of @link(import:) argument: must be a string.`,
201
- nodes: directive.sourceAST
202
- }));
199
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
200
+ `Invalid value for the "name" field for sub-value ${valueToString(elt)} of @link(import:) argument: must be a string.`,
201
+ { nodes: directive.sourceAST },
202
+ ));
203
203
  continue importArgLoop;
204
204
  }
205
205
  name = value;
206
206
  break;
207
207
  case 'as':
208
208
  if (typeof value !== 'string') {
209
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
210
- message: `Invalid value for the "as" field for sub-value ${valueToString(elt)} of @link(import:) argument: must be a string.`,
211
- nodes: directive.sourceAST
212
- }));
209
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
210
+ `Invalid value for the "as" field for sub-value ${valueToString(elt)} of @link(import:) argument: must be a string.`,
211
+ { nodes: directive.sourceAST },
212
+ ));
213
213
  continue importArgLoop;
214
214
  }
215
215
  break;
216
216
  default:
217
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
218
- message: `Unknown field "${key}" for sub-value ${valueToString(elt)} of @link(import:) argument.`,
219
- nodes: directive.sourceAST
220
- }));
217
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
218
+ `Unknown field "${key}" for sub-value ${valueToString(elt)} of @link(import:) argument.`,
219
+ { nodes: directive.sourceAST },
220
+ ));
221
221
  continue importArgLoop;
222
222
  }
223
223
  }
@@ -226,24 +226,24 @@ export function extractCoreFeatureImports(url: FeatureUrl, directive: Directive<
226
226
  imports.push(i);
227
227
  if (i.as) {
228
228
  if (i.name.charAt(0) === '@' && i.as.charAt(0) !== '@') {
229
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
230
- message: `Invalid @link import renaming: directive "${i.name}" imported name should start with a '@' character, but got "${i.as}".`,
231
- nodes: directive.sourceAST
232
- }));
229
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
230
+ `Invalid @link import renaming: directive "${i.name}" imported name should start with a '@' character, but got "${i.as}".`,
231
+ { nodes: directive.sourceAST },
232
+ ));
233
233
  }
234
234
  else if (i.name.charAt(0) !== '@' && i.as.charAt(0) === '@') {
235
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
236
- message: `Invalid @link import renaming: type "${i.name}" imported name should not start with a '@' character, but got "${i.as}" (or, if @${i.name} is a directive, then it should be referred to with a '@').`,
237
- nodes: directive.sourceAST
238
- }));
235
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
236
+ `Invalid @link import renaming: type "${i.name}" imported name should not start with a '@' character, but got "${i.as}" (or, if @${i.name} is a directive, then it should be referred to with a '@').`,
237
+ { nodes: directive.sourceAST },
238
+ ));
239
239
  }
240
240
  }
241
241
  validateImportedName(name, knownElements, errors, directive);
242
242
  } else {
243
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
244
- message: `Invalid sub-value ${valueToString(elt)} for @link(import:) argument: missing mandatory "name" field.`,
245
- nodes: directive.sourceAST
246
- }));
243
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
244
+ `Invalid sub-value ${valueToString(elt)} for @link(import:) argument: missing mandatory "name" field.`,
245
+ { nodes: directive.sourceAST },
246
+ ));
247
247
  }
248
248
  }
249
249
 
@@ -264,10 +264,10 @@ function validateImportedName(name: string, knownElements: string[] | undefined,
264
264
  details = didYouMean(suggestions);
265
265
  }
266
266
  }
267
- errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
268
- message: `Cannot import unknown element "${name}".${details}`,
269
- nodes: directive.sourceAST
270
- }));
267
+ errors.push(ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
268
+ `Cannot import unknown element "${name}".${details}`,
269
+ { nodes: directive.sourceAST },
270
+ ));
271
271
  }
272
272
  }
273
273
 
@@ -419,9 +419,9 @@ export class CoreSpecDefinition extends FeatureDefinition {
419
419
  // Already exists with the same version, let it be.
420
420
  return [];
421
421
  } else {
422
- return [ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err({
423
- message: `Cannot add feature ${this} to the schema, it already uses ${existingCore.coreItself.url}`
424
- })];
422
+ return [ERRORS.INVALID_LINK_DIRECTIVE_USAGE.err(
423
+ `Cannot add feature ${this} to the schema, it already uses ${existingCore.coreItself.url}`
424
+ )];
425
425
  }
426
426
  }
427
427
 
@@ -555,7 +555,7 @@ export class FeatureVersion {
555
555
  public static parse(input: string): FeatureVersion {
556
556
  const match = input.match(this.VERSION_RE)
557
557
  if (!match) {
558
- throw new GraphQLError(`Expected a version string (of the form v1.2), got ${input}`);
558
+ throw ERRORS.INVALID_LINK_IDENTIFIER.err(`Expected a version string (of the form v1.2), got ${input}`);
559
559
  }
560
560
  return new this(+match[1], +match[2])
561
561
  }
@@ -663,17 +663,17 @@ export class FeatureUrl {
663
663
  public static parse(input: string, node?: ASTNode): FeatureUrl {
664
664
  const url = new URL(input)
665
665
  if (!url.pathname || url.pathname === '/') {
666
- throw new GraphQLError(`Missing path in feature url '${url}'`, node)
666
+ throw ERRORS.INVALID_LINK_IDENTIFIER.err(`Missing path in feature url '${url}'`, { nodes: node })
667
667
  }
668
668
  const path = url.pathname.split('/')
669
669
  const verStr = path.pop()
670
670
  if (!verStr) {
671
- throw new GraphQLError(`Missing version component in feature url '${url}'`, node)
671
+ throw ERRORS.INVALID_LINK_IDENTIFIER.err(`Missing version component in feature url '${url}'`, { nodes: node })
672
672
  }
673
673
  const version = FeatureVersion.parse(verStr)
674
674
  const name = path[path.length - 1]
675
675
  if (!name) {
676
- throw new GraphQLError(`Missing feature name component in feature url '${url}'`, node)
676
+ throw ERRORS.INVALID_LINK_IDENTIFIER.err(`Missing feature name component in feature url '${url}'`, { nodes: node })
677
677
  }
678
678
  const element = url.hash ? url.hash.slice(1): undefined
679
679
  url.hash = ''
@@ -804,11 +804,15 @@ export function removeAllCoreFeatures(schema: Schema) {
804
804
  for (const { feature, type, references } of typeReferences) {
805
805
  const referencesInSchema = references.filter(r => r.isAttached());
806
806
  if (referencesInSchema.length > 0) {
807
- errors.push(new GraphQLError(
807
+ // Note: using REFERENCED_INACCESSIBLE is slightly abusive because the reference element is not marked
808
+ // @inacessible exactly. Instead, it is inacessible due to core elements being removed, but that's very
809
+ // very close semantically. Overall, adding a publicly documented error code just to minor difference
810
+ // doesn't feel worth it, especially since that case is super unlikely in the first place (and, as
811
+ // the prior comment says, may one day be removed too).
812
+ errors.push(ERRORS.REFERENCED_INACCESSIBLE.err(
808
813
  `Cannot remove elements of feature ${feature} as feature type ${type}` +
809
814
  ` is referenced by elements: ${referencesInSchema.join(', ')}`,
810
- references.map(r => r.sourceAST)
811
- .filter(n => n !== undefined) as ASTNode[]
815
+ { nodes: sourceASTs(...references) },
812
816
  ));
813
817
  }
814
818
  }