@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.
- package/CHANGELOG.md +32 -3
- package/dist/buildSchema.d.ts.map +1 -1
- package/dist/buildSchema.js +51 -41
- package/dist/buildSchema.js.map +1 -1
- package/dist/coreSpec.d.ts +16 -8
- package/dist/coreSpec.d.ts.map +1 -1
- package/dist/coreSpec.js +205 -53
- package/dist/coreSpec.js.map +1 -1
- package/dist/definitions.d.ts +28 -11
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +185 -67
- package/dist/definitions.js.map +1 -1
- package/dist/directiveAndTypeSpecification.d.ts +11 -1
- package/dist/directiveAndTypeSpecification.d.ts.map +1 -1
- package/dist/directiveAndTypeSpecification.js +77 -20
- package/dist/directiveAndTypeSpecification.js.map +1 -1
- package/dist/error.d.ts +17 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +54 -2
- package/dist/error.js.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
- package/dist/extractSubgraphsFromSupergraph.js +7 -1
- package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
- package/dist/federation.d.ts +22 -5
- package/dist/federation.d.ts.map +1 -1
- package/dist/federation.js +143 -86
- package/dist/federation.js.map +1 -1
- package/dist/federationSpec.d.ts +6 -2
- package/dist/federationSpec.d.ts.map +1 -1
- package/dist/federationSpec.js +47 -22
- package/dist/federationSpec.js.map +1 -1
- package/dist/inaccessibleSpec.d.ts +10 -2
- package/dist/inaccessibleSpec.d.ts.map +1 -1
- package/dist/inaccessibleSpec.js +634 -16
- package/dist/inaccessibleSpec.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/introspection.d.ts.map +1 -1
- package/dist/introspection.js +8 -3
- package/dist/introspection.js.map +1 -1
- package/dist/joinSpec.d.ts +5 -1
- package/dist/joinSpec.d.ts.map +1 -1
- package/dist/joinSpec.js +21 -0
- package/dist/joinSpec.js.map +1 -1
- package/dist/knownCoreFeatures.d.ts +4 -0
- package/dist/knownCoreFeatures.d.ts.map +1 -0
- package/dist/knownCoreFeatures.js +16 -0
- package/dist/knownCoreFeatures.js.map +1 -0
- package/dist/operations.d.ts +1 -0
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +16 -1
- package/dist/operations.js.map +1 -1
- package/dist/{sharing.d.ts → precompute.d.ts} +1 -1
- package/dist/precompute.d.ts.map +1 -0
- package/dist/{sharing.js → precompute.js} +3 -3
- package/dist/precompute.js.map +1 -0
- package/dist/schemaUpgrader.d.ts.map +1 -1
- package/dist/schemaUpgrader.js +17 -7
- package/dist/schemaUpgrader.js.map +1 -1
- package/dist/suggestions.d.ts +1 -1
- package/dist/suggestions.d.ts.map +1 -1
- package/dist/suggestions.js.map +1 -1
- package/dist/supergraphs.d.ts.map +1 -1
- package/dist/supergraphs.js +2 -0
- package/dist/supergraphs.js.map +1 -1
- package/dist/tagSpec.d.ts +7 -2
- package/dist/tagSpec.d.ts.map +1 -1
- package/dist/tagSpec.js +35 -14
- package/dist/tagSpec.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 +4 -4
- package/src/__tests__/coreSpec.test.ts +212 -0
- package/src/__tests__/definitions.test.ts +75 -0
- package/src/__tests__/removeInaccessibleElements.test.ts +2229 -137
- package/src/__tests__/schemaUpgrader.test.ts +3 -2
- package/src/__tests__/subgraphValidation.test.ts +419 -4
- package/src/__tests__/values.test.ts +315 -3
- package/src/buildSchema.ts +98 -51
- package/src/coreSpec.ts +277 -65
- package/src/definitions.ts +317 -92
- package/src/directiveAndTypeSpecification.ts +98 -21
- package/src/error.ts +119 -1
- package/src/extractSubgraphsFromSupergraph.ts +7 -1
- package/src/federation.ts +184 -102
- package/src/federationSpec.ts +56 -24
- package/src/inaccessibleSpec.ts +985 -39
- package/src/index.ts +2 -0
- package/src/introspection.ts +8 -3
- package/src/joinSpec.ts +33 -3
- package/src/knownCoreFeatures.ts +13 -0
- package/src/operations.ts +15 -0
- package/src/{sharing.ts → precompute.ts} +3 -6
- package/src/schemaUpgrader.ts +29 -13
- package/src/suggestions.ts +1 -1
- package/src/supergraphs.ts +2 -0
- package/src/tagSpec.ts +49 -16
- package/src/validate.ts +20 -9
- package/src/values.ts +39 -12
- package/tsconfig.test.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/sharing.d.ts.map +0 -1
- package/dist/sharing.js.map +0 -1
package/dist/federation.js
CHANGED
|
@@ -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.
|
|
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
|
|
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
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
},
|
|
159
|
-
for (const itfType of metadata.schema.
|
|
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
|
|
165
|
-
|
|
168
|
+
if (implemField) {
|
|
169
|
+
usedFields.add(implemField);
|
|
166
170
|
}
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
173
|
}
|
|
170
|
-
return
|
|
174
|
+
return usedFields;
|
|
171
175
|
}
|
|
172
|
-
exports.
|
|
173
|
-
function
|
|
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
|
-
}).
|
|
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) ||
|
|
197
|
+
if (!metadata.isFieldExternal(field) || metadata.isFieldUsed(field)) {
|
|
196
198
|
continue;
|
|
197
199
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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(
|
|
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
|
-
|
|
416
|
-
|
|
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
|
-
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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.
|
|
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:
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
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
|
-
|
|
674
|
-
|
|
675
|
-
|
|
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.
|
|
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() {
|