@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.
- package/CHANGELOG.md +25 -0
- package/dist/coreSpec.d.ts +1 -1
- package/dist/coreSpec.d.ts.map +1 -1
- package/dist/coreSpec.js +34 -11
- package/dist/coreSpec.js.map +1 -1
- package/dist/definitions.d.ts +20 -8
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +97 -58
- package/dist/definitions.js.map +1 -1
- package/dist/directiveAndTypeSpecification.d.ts.map +1 -1
- package/dist/directiveAndTypeSpecification.js +10 -1
- package/dist/directiveAndTypeSpecification.js.map +1 -1
- package/dist/error.d.ts +10 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +22 -2
- package/dist/error.js.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.js +1 -1
- package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
- package/dist/federation.d.ts +4 -1
- package/dist/federation.d.ts.map +1 -1
- package/dist/federation.js +33 -26
- package/dist/federation.js.map +1 -1
- package/dist/federationSpec.js +1 -1
- package/dist/federationSpec.js.map +1 -1
- package/dist/inaccessibleSpec.d.ts +7 -3
- package/dist/inaccessibleSpec.d.ts.map +1 -1
- package/dist/inaccessibleSpec.js +622 -32
- package/dist/inaccessibleSpec.js.map +1 -1
- package/dist/precompute.d.ts.map +1 -1
- package/dist/precompute.js +2 -2
- package/dist/precompute.js.map +1 -1
- package/dist/schemaUpgrader.d.ts.map +1 -1
- package/dist/schemaUpgrader.js +16 -5
- package/dist/schemaUpgrader.js.map +1 -1
- package/dist/supergraphs.d.ts.map +1 -1
- package/dist/supergraphs.js +1 -0
- package/dist/supergraphs.js.map +1 -1
- package/dist/validate.js +13 -7
- package/dist/validate.js.map +1 -1
- package/dist/values.d.ts +2 -2
- package/dist/values.d.ts.map +1 -1
- package/dist/values.js +13 -11
- package/dist/values.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/coreSpec.test.ts +112 -0
- package/src/__tests__/removeInaccessibleElements.test.ts +2216 -177
- package/src/__tests__/subgraphValidation.test.ts +22 -5
- package/src/__tests__/values.test.ts +315 -3
- package/src/coreSpec.ts +70 -16
- package/src/definitions.ts +201 -83
- package/src/directiveAndTypeSpecification.ts +18 -1
- package/src/error.ts +62 -2
- package/src/extractSubgraphsFromSupergraph.ts +1 -1
- package/src/federation.ts +36 -26
- package/src/federationSpec.ts +2 -2
- package/src/inaccessibleSpec.ts +973 -55
- package/src/precompute.ts +2 -4
- package/src/schemaUpgrader.ts +25 -6
- package/src/supergraphs.ts +1 -0
- package/src/validate.ts +20 -9
- package/src/values.ts +39 -12
- package/tsconfig.test.tsbuildinfo +1 -1
- 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.
|
|
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.
|
|
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(
|
|
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
|
-
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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(
|
|
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.
|
|
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
|
|
package/src/federationSpec.ts
CHANGED
|
@@ -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 {
|
|
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
|
|