@apollo/federation-internals 2.0.0-preview.9 → 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 (63) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/coreSpec.d.ts +1 -1
  3. package/dist/coreSpec.d.ts.map +1 -1
  4. package/dist/coreSpec.js +34 -11
  5. package/dist/coreSpec.js.map +1 -1
  6. package/dist/definitions.d.ts +20 -8
  7. package/dist/definitions.d.ts.map +1 -1
  8. package/dist/definitions.js +97 -58
  9. package/dist/definitions.js.map +1 -1
  10. package/dist/directiveAndTypeSpecification.d.ts.map +1 -1
  11. package/dist/directiveAndTypeSpecification.js +10 -1
  12. package/dist/directiveAndTypeSpecification.js.map +1 -1
  13. package/dist/error.d.ts +10 -0
  14. package/dist/error.d.ts.map +1 -1
  15. package/dist/error.js +22 -2
  16. package/dist/error.js.map +1 -1
  17. package/dist/extractSubgraphsFromSupergraph.js +1 -1
  18. package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
  19. package/dist/federation.d.ts +4 -1
  20. package/dist/federation.d.ts.map +1 -1
  21. package/dist/federation.js +33 -26
  22. package/dist/federation.js.map +1 -1
  23. package/dist/federationSpec.js +1 -1
  24. package/dist/federationSpec.js.map +1 -1
  25. package/dist/inaccessibleSpec.d.ts +7 -3
  26. package/dist/inaccessibleSpec.d.ts.map +1 -1
  27. package/dist/inaccessibleSpec.js +622 -32
  28. package/dist/inaccessibleSpec.js.map +1 -1
  29. package/dist/precompute.d.ts.map +1 -1
  30. package/dist/precompute.js +2 -2
  31. package/dist/precompute.js.map +1 -1
  32. package/dist/schemaUpgrader.d.ts.map +1 -1
  33. package/dist/schemaUpgrader.js +16 -5
  34. package/dist/schemaUpgrader.js.map +1 -1
  35. package/dist/supergraphs.d.ts.map +1 -1
  36. package/dist/supergraphs.js +1 -0
  37. package/dist/supergraphs.js.map +1 -1
  38. package/dist/validate.js +13 -7
  39. package/dist/validate.js.map +1 -1
  40. package/dist/values.d.ts +2 -2
  41. package/dist/values.d.ts.map +1 -1
  42. package/dist/values.js +13 -11
  43. package/dist/values.js.map +1 -1
  44. package/package.json +3 -3
  45. package/src/__tests__/coreSpec.test.ts +112 -0
  46. package/src/__tests__/removeInaccessibleElements.test.ts +2216 -177
  47. package/src/__tests__/subgraphValidation.test.ts +22 -5
  48. package/src/__tests__/values.test.ts +315 -3
  49. package/src/coreSpec.ts +70 -16
  50. package/src/definitions.ts +201 -83
  51. package/src/directiveAndTypeSpecification.ts +18 -1
  52. package/src/error.ts +62 -2
  53. package/src/extractSubgraphsFromSupergraph.ts +1 -1
  54. package/src/federation.ts +36 -26
  55. package/src/federationSpec.ts +2 -2
  56. package/src/inaccessibleSpec.ts +973 -55
  57. package/src/precompute.ts +2 -4
  58. package/src/schemaUpgrader.ts +25 -6
  59. package/src/supergraphs.ts +1 -0
  60. package/src/validate.ts +20 -9
  61. package/src/values.ts +39 -12
  62. package/tsconfig.test.tsbuildinfo +1 -1
  63. package/tsconfig.tsbuildinfo +1 -1
package/src/federation.ts CHANGED
@@ -45,6 +45,7 @@ import { KnownTypeNamesInFederationRule } from "./validation/KnownTypeNamesInFed
45
45
  import { buildSchema, buildSchemaFromAST } from "./buildSchema";
46
46
  import { parseSelectionSet, selectionOfElement, SelectionSet } from './operations';
47
47
  import { TAG_VERSIONS } from "./tagSpec";
48
+ import { INACCESSIBLE_VERSIONS } from "./inaccessibleSpec";
48
49
  import {
49
50
  errorCodeDef,
50
51
  ErrorCodeDefinition,
@@ -79,10 +80,10 @@ import {
79
80
  import { defaultPrintOptions, PrintOptions as PrintOptions, printSchema } from "./print";
80
81
  import { createObjectTypeSpecification, createScalarTypeSpecification, createUnionTypeSpecification } from "./directiveAndTypeSpecification";
81
82
  import { didYouMean, suggestionList } from "./suggestions";
82
- import { inaccessibleDirectiveSpec } from "./inaccessibleSpec";
83
83
 
84
84
  const linkSpec = LINK_VERSIONS.latest();
85
85
  const tagSpec = TAG_VERSIONS.latest();
86
+ const inaccessibleSpec = INACCESSIBLE_VERSIONS.latest();
86
87
  const federationSpec = FEDERATION_VERSIONS.latest();
87
88
 
88
89
  // We don't let user use this as a subgraph name. That allows us to use it in `query graphs` to name the source of roots
@@ -91,6 +92,8 @@ const federationSpec = FEDERATION_VERSIONS.latest();
91
92
  // disallowing it feels like more a good thing than a real restriction).
92
93
  export const FEDERATION_RESERVED_SUBGRAPH_NAME = '_';
93
94
 
95
+ export const FEDERATION_UNNAMED_SUBGRAPH_NAME = '<unnamed>';
96
+
94
97
  const FEDERATION_OMITTED_VALIDATION_RULES = [
95
98
  // We allow subgraphs to declare an extension even if the subgraph itself doesn't have a corresponding definition.
96
99
  // The implication being that the definition is in another subgraph.
@@ -287,7 +290,7 @@ export function collectUsedFields(metadata: FederationMetadata): Set<FieldDefini
287
290
  );
288
291
 
289
292
  // Collects all fields used to satisfy an interface constraint
290
- for (const itfType of metadata.schema.types<InterfaceType>('InterfaceType')) {
293
+ for (const itfType of metadata.schema.interfaceTypes()) {
291
294
  const runtimeTypes = itfType.possibleRuntimeTypes();
292
295
  for (const field of itfType.fields()) {
293
296
  for (const runtimeType of runtimeTypes) {
@@ -351,7 +354,7 @@ function validateAllExternalFieldsUsed(metadata: FederationMetadata, errorCollec
351
354
  }
352
355
 
353
356
  function validateNoExternalOnInterfaceFields(metadata: FederationMetadata, errorCollector: GraphQLError[]) {
354
- for (const itf of metadata.schema.types<InterfaceType>('InterfaceType')) {
357
+ for (const itf of metadata.schema.interfaceTypes()) {
355
358
  for (const field of itf.fields()) {
356
359
  if (metadata.isFieldExternal(field)) {
357
360
  errorCollector.push(ERRORS.EXTERNAL_ON_INTERFACE.err({
@@ -565,7 +568,9 @@ export class FederationMetadata {
565
568
  }
566
569
 
567
570
  inaccessibleDirective(): DirectiveDefinition<{}> {
568
- return this.getFederationDirective(inaccessibleDirectiveSpec.name);
571
+ return this.getFederationDirective(
572
+ inaccessibleSpec.inaccessibleDirectiveSpec.name
573
+ );
569
574
  }
570
575
 
571
576
  allFederationDirectives(): DirectiveDefinition[] {
@@ -614,6 +619,10 @@ export class FederationMetadata {
614
619
  }
615
620
 
616
621
  export class FederationBlueprint extends SchemaBlueprint {
622
+ constructor(private readonly withRootTypeRenaming: boolean) {
623
+ super();
624
+ }
625
+
617
626
  onAddedCoreFeature(schema: Schema, feature: CoreFeature) {
618
627
  super.onAddedCoreFeature(schema, feature);
619
628
  if (feature.url.identity === federationIdentity) {
@@ -672,22 +681,24 @@ export class FederationBlueprint extends SchemaBlueprint {
672
681
 
673
682
  // We rename all root type to their default names (we do here rather than in `prepareValidation` because
674
683
  // that can actually fail).
675
- for (const k of allSchemaRootKinds) {
676
- const type = schema.schemaDefinition.root(k)?.type;
677
- const defaultName = defaultRootName(k);
678
- if (type && type.name !== defaultName) {
679
- // We first ensure there is no other type using the default root name. If there is, this is a
680
- // composition error.
681
- const existing = schema.type(defaultName);
682
- if (existing) {
683
- errors.push(ERROR_CATEGORIES.ROOT_TYPE_USED.get(k).err({
684
- message: `The schema has a type named "${defaultName}" but it is not set as the ${k} root type ("${type.name}" is instead): `
684
+ if (this.withRootTypeRenaming) {
685
+ for (const k of allSchemaRootKinds) {
686
+ const type = schema.schemaDefinition.root(k)?.type;
687
+ const defaultName = defaultRootName(k);
688
+ if (type && type.name !== defaultName) {
689
+ // We first ensure there is no other type using the default root name. If there is, this is a
690
+ // composition error.
691
+ const existing = schema.type(defaultName);
692
+ if (existing) {
693
+ errors.push(ERROR_CATEGORIES.ROOT_TYPE_USED.get(k).err({
694
+ message: `The schema has a type named "${defaultName}" but it is not set as the ${k} root type ("${type.name}" is instead): `
685
695
  + 'this is not supported by federation. '
686
696
  + 'If a root type does not use its default name, there should be no other type with that default name.',
687
- nodes: sourceASTs(type, existing),
688
- }));
697
+ nodes: sourceASTs(type, existing),
698
+ }));
699
+ }
700
+ type.rename(defaultName);
689
701
  }
690
- type.rename(defaultName);
691
702
  }
692
703
  }
693
704
 
@@ -772,7 +783,7 @@ export class FederationBlueprint extends SchemaBlueprint {
772
783
  }
773
784
  }
774
785
 
775
- for (const itf of schema.types<InterfaceType>('InterfaceType')) {
786
+ for (const itf of schema.interfaceTypes()) {
776
787
  validateInterfaceRuntimeImplementationFieldsTypes(itf, metadata, errors);
777
788
  }
778
789
 
@@ -829,8 +840,6 @@ export class FederationBlueprint extends SchemaBlueprint {
829
840
  }
830
841
  }
831
842
 
832
- const federationBlueprint = new FederationBlueprint();
833
-
834
843
  function findUnusedNamedForLinkDirective(schema: Schema): string | undefined {
835
844
  if (!schema.directive(linkSpec.url.name)) {
836
845
  return undefined;
@@ -946,10 +955,11 @@ export function isEntityType(type: NamedType): boolean {
946
955
  export function buildSubgraph(
947
956
  name: string,
948
957
  url: string,
949
- source: DocumentNode | string
958
+ source: DocumentNode | string,
959
+ withRootTypeRenaming: boolean = true,
950
960
  ): Subgraph {
951
961
  const buildOptions = {
952
- blueprint: federationBlueprint,
962
+ blueprint: new FederationBlueprint(withRootTypeRenaming),
953
963
  validate: false,
954
964
  };
955
965
  let subgraph: Subgraph;
@@ -959,7 +969,7 @@ export function buildSubgraph(
959
969
  : buildSchemaFromAST(source, buildOptions)
960
970
  subgraph = new Subgraph(name, url, schema);
961
971
  } catch (e) {
962
- if (e instanceof GraphQLError) {
972
+ if (e instanceof GraphQLError && name !== FEDERATION_UNNAMED_SUBGRAPH_NAME) {
963
973
  throw addSubgraphToError(e, name, ERRORS.INVALID_GRAPHQL);
964
974
  } else {
965
975
  throw e;
@@ -969,7 +979,7 @@ export function buildSubgraph(
969
979
  }
970
980
 
971
981
  export function newEmptyFederation2Schema(): Schema {
972
- const schema = new Schema(federationBlueprint);
982
+ const schema = new Schema(new FederationBlueprint(true));
973
983
  setSchemaAsFed2Subgraph(schema);
974
984
  return schema;
975
985
  }
@@ -1250,7 +1260,7 @@ export const serviceTypeSpec = createObjectTypeSpecification({
1250
1260
  export const entityTypeSpec = createUnionTypeSpecification({
1251
1261
  name: '_Entity',
1252
1262
  membersFct: (schema) => {
1253
- return schema.types<ObjectType>("ObjectType").filter(isEntityType).map((t) => t.name);
1263
+ return schema.objectTypes().filter(isEntityType).map((t) => t.name);
1254
1264
  },
1255
1265
  });
1256
1266
 
@@ -1311,7 +1321,7 @@ export class Subgraph {
1311
1321
  }
1312
1322
 
1313
1323
  if (!queryType.field(serviceFieldName)) {
1314
- queryType.addField(serviceFieldName, metadata.serviceType());
1324
+ queryType.addField(serviceFieldName, new NonNullType(metadata.serviceType()));
1315
1325
  }
1316
1326
  }
1317
1327
 
@@ -14,7 +14,7 @@ import { assert } from "./utils";
14
14
  import { TAG_VERSIONS } from "./tagSpec";
15
15
  import { federationMetadata } from "./federation";
16
16
  import { registerKnownFeature } from "./knownCoreFeatures";
17
- import { inaccessibleDirectiveSpec } from "./inaccessibleSpec";
17
+ import { INACCESSIBLE_VERSIONS } from "./inaccessibleSpec";
18
18
 
19
19
  export const federationIdentity = 'https://specs.apollo.dev/federation';
20
20
 
@@ -91,7 +91,7 @@ function fieldSetType(schema: Schema): InputType {
91
91
 
92
92
  export const FEDERATION2_ONLY_SPEC_DIRECTIVES = [
93
93
  shareableDirectiveSpec,
94
- inaccessibleDirectiveSpec,
94
+ INACCESSIBLE_VERSIONS.latest().inaccessibleDirectiveSpec,
95
95
  overrideDirectiveSpec,
96
96
  ];
97
97