@apollo/federation-internals 2.4.4 → 2.4.5

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 (123) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/Subgraph.d.ts +1 -0
  3. package/dist/Subgraph.d.ts.map +1 -0
  4. package/dist/Subgraph.js +2 -0
  5. package/dist/Subgraph.js.map +1 -0
  6. package/dist/argumentCompositionStrategies.d.ts +34 -0
  7. package/dist/argumentCompositionStrategies.d.ts.map +1 -0
  8. package/dist/argumentCompositionStrategies.js +35 -0
  9. package/dist/argumentCompositionStrategies.js.map +1 -0
  10. package/dist/buildSchema.d.ts +10 -0
  11. package/dist/buildSchema.d.ts.map +1 -0
  12. package/dist/buildSchema.js +362 -0
  13. package/dist/buildSchema.js.map +1 -0
  14. package/dist/coreSpec.d.ts +127 -0
  15. package/dist/coreSpec.d.ts.map +1 -0
  16. package/dist/coreSpec.js +590 -0
  17. package/dist/coreSpec.js.map +1 -0
  18. package/dist/debug.d.ts +15 -0
  19. package/dist/debug.d.ts.map +1 -0
  20. package/dist/debug.js +122 -0
  21. package/dist/debug.js.map +1 -0
  22. package/dist/definitions.d.ts +663 -0
  23. package/dist/definitions.d.ts.map +1 -0
  24. package/dist/definitions.js +2841 -0
  25. package/dist/definitions.js.map +1 -0
  26. package/dist/directiveAndTypeSpecification.d.ts +67 -0
  27. package/dist/directiveAndTypeSpecification.d.ts.map +1 -0
  28. package/dist/directiveAndTypeSpecification.js +271 -0
  29. package/dist/directiveAndTypeSpecification.js.map +1 -0
  30. package/dist/error.d.ts +128 -0
  31. package/dist/error.d.ts.map +1 -0
  32. package/dist/error.js +315 -0
  33. package/dist/error.js.map +1 -0
  34. package/dist/extractSubgraphsFromSupergraph.d.ts +8 -0
  35. package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -0
  36. package/dist/extractSubgraphsFromSupergraph.js +576 -0
  37. package/dist/extractSubgraphsFromSupergraph.js.map +1 -0
  38. package/dist/federation.d.ts +175 -0
  39. package/dist/federation.d.ts.map +1 -0
  40. package/dist/federation.js +1414 -0
  41. package/dist/federation.js.map +1 -0
  42. package/dist/federationSpec.d.ts +25 -0
  43. package/dist/federationSpec.d.ts.map +1 -0
  44. package/dist/federationSpec.js +125 -0
  45. package/dist/federationSpec.js.map +1 -0
  46. package/dist/genErrorCodeDoc.d.ts +2 -0
  47. package/dist/genErrorCodeDoc.d.ts.map +1 -0
  48. package/dist/genErrorCodeDoc.js +61 -0
  49. package/dist/genErrorCodeDoc.js.map +1 -0
  50. package/dist/graphQLJSSchemaToAST.d.ts +8 -0
  51. package/dist/graphQLJSSchemaToAST.d.ts.map +1 -0
  52. package/dist/graphQLJSSchemaToAST.js +96 -0
  53. package/dist/graphQLJSSchemaToAST.js.map +1 -0
  54. package/dist/inaccessibleSpec.d.ts +18 -0
  55. package/dist/inaccessibleSpec.d.ts.map +1 -0
  56. package/dist/inaccessibleSpec.js +655 -0
  57. package/dist/inaccessibleSpec.js.map +1 -0
  58. package/dist/index.d.ts +24 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +42 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/introspection.d.ts +6 -0
  63. package/dist/introspection.d.ts.map +1 -0
  64. package/dist/introspection.js +96 -0
  65. package/dist/introspection.js.map +1 -0
  66. package/dist/joinSpec.d.ts +51 -0
  67. package/dist/joinSpec.d.ts.map +1 -0
  68. package/dist/joinSpec.js +160 -0
  69. package/dist/joinSpec.js.map +1 -0
  70. package/dist/knownCoreFeatures.d.ts +5 -0
  71. package/dist/knownCoreFeatures.d.ts.map +1 -0
  72. package/dist/knownCoreFeatures.js +20 -0
  73. package/dist/knownCoreFeatures.js.map +1 -0
  74. package/dist/operations.d.ts +415 -0
  75. package/dist/operations.d.ts.map +1 -0
  76. package/dist/operations.js +2040 -0
  77. package/dist/operations.js.map +1 -0
  78. package/dist/precompute.d.ts +3 -0
  79. package/dist/precompute.d.ts.map +1 -0
  80. package/dist/precompute.js +54 -0
  81. package/dist/precompute.js.map +1 -0
  82. package/dist/print.d.ts +28 -0
  83. package/dist/print.d.ts.map +1 -0
  84. package/dist/print.js +299 -0
  85. package/dist/print.js.map +1 -0
  86. package/dist/schemaUpgrader.d.ts +121 -0
  87. package/dist/schemaUpgrader.d.ts.map +1 -0
  88. package/dist/schemaUpgrader.js +570 -0
  89. package/dist/schemaUpgrader.js.map +1 -0
  90. package/dist/suggestions.d.ts +3 -0
  91. package/dist/suggestions.d.ts.map +1 -0
  92. package/dist/suggestions.js +44 -0
  93. package/dist/suggestions.js.map +1 -0
  94. package/dist/supergraphs.d.ts +10 -0
  95. package/dist/supergraphs.d.ts.map +1 -0
  96. package/dist/supergraphs.js +76 -0
  97. package/dist/supergraphs.js.map +1 -0
  98. package/dist/tagSpec.d.ts +19 -0
  99. package/dist/tagSpec.d.ts.map +1 -0
  100. package/dist/tagSpec.js +66 -0
  101. package/dist/tagSpec.js.map +1 -0
  102. package/dist/types.d.ts +9 -0
  103. package/dist/types.d.ts.map +1 -0
  104. package/dist/types.js +64 -0
  105. package/dist/types.js.map +1 -0
  106. package/dist/utils.d.ts +64 -0
  107. package/dist/utils.d.ts.map +1 -0
  108. package/dist/utils.js +326 -0
  109. package/dist/utils.js.map +1 -0
  110. package/dist/validate.d.ts +4 -0
  111. package/dist/validate.d.ts.map +1 -0
  112. package/dist/validate.js +239 -0
  113. package/dist/validate.js.map +1 -0
  114. package/dist/validation/KnownTypeNamesInFederationRule.d.ts +4 -0
  115. package/dist/validation/KnownTypeNamesInFederationRule.d.ts.map +1 -0
  116. package/dist/validation/KnownTypeNamesInFederationRule.js +41 -0
  117. package/dist/validation/KnownTypeNamesInFederationRule.js.map +1 -0
  118. package/dist/values.d.ts +23 -0
  119. package/dist/values.d.ts.map +1 -0
  120. package/dist/values.js +580 -0
  121. package/dist/values.js.map +1 -0
  122. package/package.json +1 -1
  123. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,1414 @@
1
+ "use strict";
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.isInterfaceObjectType = exports.isEntityType = exports.isFederationField = exports.isFederationSubgraphSchema = exports.federationMetadata = exports.printSubgraphNames = exports.asFed2SubgraphDocument = exports.FEDERATION2_LINK_WITH_FULL_IMPORTS = exports.setSchemaAsFed2Subgraph = exports.FederationBlueprint = exports.hasAppliedDirective = exports.isFederationDirectiveDefinedInSchema = exports.FederationMetadata = exports.collectUsedFields = exports.FEDERATION_UNNAMED_SUBGRAPH_NAME = exports.FEDERATION_RESERVED_SUBGRAPH_NAME = void 0;
4
+ const definitions_1 = require("./definitions");
5
+ const utils_1 = require("./utils");
6
+ const specifiedRules_1 = require("graphql/validation/specifiedRules");
7
+ const graphql_1 = require("graphql");
8
+ const KnownTypeNamesInFederationRule_1 = require("./validation/KnownTypeNamesInFederationRule");
9
+ const buildSchema_1 = require("./buildSchema");
10
+ const operations_1 = require("./operations");
11
+ const tagSpec_1 = require("./tagSpec");
12
+ const error_1 = require("./error");
13
+ const precompute_1 = require("./precompute");
14
+ const coreSpec_1 = require("./coreSpec");
15
+ const federationSpec_1 = require("./federationSpec");
16
+ const print_1 = require("./print");
17
+ const directiveAndTypeSpecification_1 = require("./directiveAndTypeSpecification");
18
+ const suggestions_1 = require("./suggestions");
19
+ const knownCoreFeatures_1 = require("./knownCoreFeatures");
20
+ const joinSpec_1 = require("./joinSpec");
21
+ const linkSpec = coreSpec_1.LINK_VERSIONS.latest();
22
+ const tagSpec = tagSpec_1.TAG_VERSIONS.latest();
23
+ const federationSpec = federationSpec_1.FEDERATION_VERSIONS.latest();
24
+ exports.FEDERATION_RESERVED_SUBGRAPH_NAME = '_';
25
+ exports.FEDERATION_UNNAMED_SUBGRAPH_NAME = '<unnamed>';
26
+ const FEDERATION_OMITTED_VALIDATION_RULES = [
27
+ graphql_1.PossibleTypeExtensionsRule,
28
+ graphql_1.KnownTypeNamesRule
29
+ ];
30
+ const FEDERATION_SPECIFIC_VALIDATION_RULES = [
31
+ KnownTypeNamesInFederationRule_1.KnownTypeNamesInFederationRule
32
+ ];
33
+ const FEDERATION_VALIDATION_RULES = specifiedRules_1.specifiedSDLRules.filter(rule => !FEDERATION_OMITTED_VALIDATION_RULES.includes(rule)).concat(FEDERATION_SPECIFIC_VALIDATION_RULES);
34
+ const ALL_DEFAULT_FEDERATION_DIRECTIVE_NAMES = Object.values(federationSpec_1.FederationDirectiveName);
35
+ function validateFieldSetSelections({ directiveName, selectionSet, hasExternalInParents, metadata, onError, allowOnNonExternalLeafFields, allowFieldsWithArguments, }) {
36
+ for (const selection of selectionSet.selections()) {
37
+ const appliedDirectives = selection.element.appliedDirectives;
38
+ if (appliedDirectives.length > 0) {
39
+ onError(error_1.ERROR_CATEGORIES.DIRECTIVE_IN_FIELDS_ARG.get(directiveName).err(`cannot have directive applications in the @${directiveName}(fields:) argument but found ${appliedDirectives.join(', ')}.`));
40
+ }
41
+ if (selection.kind === 'FieldSelection') {
42
+ const field = selection.element.definition;
43
+ const isExternal = metadata.isFieldExternal(field);
44
+ if (!allowFieldsWithArguments && field.hasArguments()) {
45
+ onError(error_1.ERROR_CATEGORIES.FIELDS_HAS_ARGS.get(directiveName).err(`field ${field.coordinate} cannot be included because it has arguments (fields with argument are not allowed in @${directiveName})`, { nodes: field.sourceAST }));
46
+ }
47
+ const mustBeExternal = !selection.selectionSet && !allowOnNonExternalLeafFields && !hasExternalInParents;
48
+ if (!isExternal && mustBeExternal) {
49
+ const errorCode = error_1.ERROR_CATEGORIES.DIRECTIVE_FIELDS_MISSING_EXTERNAL.get(directiveName);
50
+ if (metadata.isFieldFakeExternal(field)) {
51
+ onError(errorCode.err(`field "${field.coordinate}" should not be part of a @${directiveName} since it is already "effectively" provided by this subgraph `
52
+ + `(while it is marked @${federationSpec_1.FederationDirectiveName.EXTERNAL}, it is a @${federationSpec_1.FederationDirectiveName.KEY} field of an extension type, which are not internally considered external for historical/backward compatibility reasons)`, { nodes: field.sourceAST }));
53
+ }
54
+ else {
55
+ onError(errorCode.err(`field "${field.coordinate}" should not be part of a @${directiveName} since it is already provided by this subgraph (it is not marked @${federationSpec_1.FederationDirectiveName.EXTERNAL})`, { nodes: field.sourceAST }));
56
+ }
57
+ }
58
+ if (selection.selectionSet) {
59
+ let newHasExternalInParents = hasExternalInParents || isExternal;
60
+ const parentType = field.parent;
61
+ if (!newHasExternalInParents && (0, definitions_1.isInterfaceType)(parentType)) {
62
+ for (const implem of parentType.possibleRuntimeTypes()) {
63
+ const fieldInImplem = implem.field(field.name);
64
+ if (fieldInImplem && metadata.isFieldExternal(fieldInImplem)) {
65
+ newHasExternalInParents = true;
66
+ break;
67
+ }
68
+ }
69
+ }
70
+ validateFieldSetSelections({
71
+ directiveName,
72
+ selectionSet: selection.selectionSet,
73
+ hasExternalInParents: newHasExternalInParents,
74
+ metadata,
75
+ onError,
76
+ allowOnNonExternalLeafFields,
77
+ allowFieldsWithArguments,
78
+ });
79
+ }
80
+ }
81
+ else {
82
+ validateFieldSetSelections({
83
+ directiveName,
84
+ selectionSet: selection.selectionSet,
85
+ hasExternalInParents,
86
+ metadata,
87
+ onError,
88
+ allowOnNonExternalLeafFields,
89
+ allowFieldsWithArguments,
90
+ });
91
+ }
92
+ }
93
+ }
94
+ function validateFieldSet({ type, directive, metadata, errorCollector, allowOnNonExternalLeafFields, allowFieldsWithArguments, onFields, }) {
95
+ try {
96
+ const fieldAccessor = onFields
97
+ ? (type, fieldName) => {
98
+ const field = type.field(fieldName);
99
+ if (field) {
100
+ onFields(field);
101
+ }
102
+ return field;
103
+ }
104
+ : undefined;
105
+ const selectionSet = parseFieldSetArgument({ parentType: type, directive, fieldAccessor });
106
+ validateFieldSetSelections({
107
+ directiveName: directive.name,
108
+ selectionSet,
109
+ hasExternalInParents: false,
110
+ metadata,
111
+ onError: (error) => errorCollector.push(handleFieldSetValidationError(directive, error)),
112
+ allowOnNonExternalLeafFields,
113
+ allowFieldsWithArguments,
114
+ });
115
+ }
116
+ catch (e) {
117
+ if (e instanceof graphql_1.GraphQLError) {
118
+ errorCollector.push(e);
119
+ }
120
+ else {
121
+ throw e;
122
+ }
123
+ }
124
+ }
125
+ function handleFieldSetValidationError(directive, originalError, messageUpdater) {
126
+ const nodes = (0, definitions_1.sourceASTs)(directive);
127
+ if (originalError.nodes) {
128
+ nodes.push(...originalError.nodes);
129
+ }
130
+ let codeDef = (0, error_1.errorCodeDef)(originalError);
131
+ if (!codeDef || codeDef === error_1.ERRORS.INVALID_GRAPHQL) {
132
+ codeDef = error_1.ERROR_CATEGORIES.DIRECTIVE_INVALID_FIELDS.get(directive.name);
133
+ }
134
+ let msg = originalError.message.trim();
135
+ if (messageUpdater) {
136
+ msg = messageUpdater(msg);
137
+ }
138
+ return codeDef.err(`${fieldSetErrorDescriptor(directive)}: ${msg}`, {
139
+ nodes,
140
+ originalError,
141
+ });
142
+ }
143
+ function fieldSetErrorDescriptor(directive) {
144
+ return `On ${fieldSetTargetDescription(directive)}, for ${directiveStrUsingASTIfPossible(directive)}`;
145
+ }
146
+ function directiveStrUsingASTIfPossible(directive) {
147
+ return directive.sourceAST ? (0, graphql_1.print)(directive.sourceAST) : directive.toString();
148
+ }
149
+ function fieldSetTargetDescription(directive) {
150
+ var _a;
151
+ const targetKind = directive.parent instanceof definitions_1.FieldDefinition ? "field" : "type";
152
+ return `${targetKind} "${(_a = directive.parent) === null || _a === void 0 ? void 0 : _a.coordinate}"`;
153
+ }
154
+ function validateAllFieldSet({ definition, targetTypeExtractor, errorCollector, metadata, isOnParentType = false, allowOnNonExternalLeafFields = false, allowFieldsWithArguments = false, allowOnInterface = false, onFields, }) {
155
+ for (const application of definition.applications()) {
156
+ const elt = application.parent;
157
+ const type = targetTypeExtractor(elt);
158
+ const parentType = isOnParentType ? type : elt.parent;
159
+ if ((0, definitions_1.isInterfaceType)(parentType) && !allowOnInterface) {
160
+ const code = error_1.ERROR_CATEGORIES.DIRECTIVE_UNSUPPORTED_ON_INTERFACE.get(definition.name);
161
+ errorCollector.push(code.err(isOnParentType
162
+ ? `Cannot use ${definition.coordinate} on interface "${parentType.coordinate}": ${definition.coordinate} is not yet supported on interfaces`
163
+ : `Cannot use ${definition.coordinate} on ${fieldSetTargetDescription(application)} of parent type "${parentType}": ${definition.coordinate} is not yet supported within interfaces`, { nodes: (0, definitions_1.sourceASTs)(application).concat(isOnParentType ? [] : (0, definitions_1.sourceASTs)(type)) }));
164
+ }
165
+ validateFieldSet({
166
+ type,
167
+ directive: application,
168
+ metadata,
169
+ errorCollector,
170
+ allowOnNonExternalLeafFields,
171
+ allowFieldsWithArguments,
172
+ onFields,
173
+ });
174
+ }
175
+ }
176
+ function collectUsedFields(metadata) {
177
+ const usedFields = new Set();
178
+ collectUsedFieldsForDirective(metadata.keyDirective(), type => type, usedFields);
179
+ collectUsedFieldsForDirective(metadata.requiresDirective(), field => field.parent, usedFields);
180
+ collectUsedFieldsForDirective(metadata.providesDirective(), field => {
181
+ const type = (0, definitions_1.baseType)(field.type);
182
+ return (0, definitions_1.isCompositeType)(type) ? type : undefined;
183
+ }, usedFields);
184
+ for (const itfType of metadata.schema.interfaceTypes()) {
185
+ const runtimeTypes = itfType.possibleRuntimeTypes();
186
+ for (const field of itfType.fields()) {
187
+ for (const runtimeType of runtimeTypes) {
188
+ const implemField = runtimeType.field(field.name);
189
+ if (implemField) {
190
+ usedFields.add(implemField);
191
+ }
192
+ }
193
+ }
194
+ }
195
+ return usedFields;
196
+ }
197
+ exports.collectUsedFields = collectUsedFields;
198
+ function collectUsedFieldsForDirective(definition, targetTypeExtractor, usedFieldDefs) {
199
+ for (const application of definition.applications()) {
200
+ const type = targetTypeExtractor(application.parent);
201
+ if (!type) {
202
+ continue;
203
+ }
204
+ collectTargetFields({
205
+ parentType: type,
206
+ directive: application,
207
+ includeInterfaceFieldsImplementations: true,
208
+ validate: false,
209
+ }).forEach((field) => usedFieldDefs.add(field));
210
+ }
211
+ }
212
+ function validateAllExternalFieldsUsed(metadata, errorCollector) {
213
+ for (const type of metadata.schema.types()) {
214
+ if (!(0, definitions_1.isObjectType)(type) && !(0, definitions_1.isInterfaceType)(type)) {
215
+ continue;
216
+ }
217
+ for (const field of type.fields()) {
218
+ if (!metadata.isFieldExternal(field) || metadata.isFieldUsed(field)) {
219
+ continue;
220
+ }
221
+ errorCollector.push(error_1.ERRORS.EXTERNAL_UNUSED.err(`Field "${field.coordinate}" is marked @external but is not used in any federation directive (@key, @provides, @requires) or to satisfy an interface;`
222
+ + ' the field declaration has no use and should be removed (or the field should not be @external).', { nodes: field.sourceAST }));
223
+ }
224
+ }
225
+ }
226
+ function validateNoExternalOnInterfaceFields(metadata, errorCollector) {
227
+ for (const itf of metadata.schema.interfaceTypes()) {
228
+ for (const field of itf.fields()) {
229
+ if (metadata.isFieldExternal(field)) {
230
+ errorCollector.push(error_1.ERRORS.EXTERNAL_ON_INTERFACE.err(`Interface type field "${field.coordinate}" is marked @external but @external is not allowed on interface fields (it is nonsensical).`, { nodes: field.sourceAST }));
231
+ }
232
+ }
233
+ }
234
+ }
235
+ function validateKeyOnInterfacesAreAlsoOnAllImplementations(metadata, errorCollector) {
236
+ for (const itfType of metadata.schema.interfaceTypes()) {
237
+ const implementations = itfType.possibleRuntimeTypes();
238
+ for (const keyApplication of itfType.appliedDirectivesOf(metadata.keyDirective())) {
239
+ const fields = parseFieldSetArgument({ parentType: itfType, directive: keyApplication, validate: false });
240
+ const isResolvable = !(keyApplication.arguments().resolvable === false);
241
+ const implementationsWithKeyButNotResolvable = new Array();
242
+ const implementationsMissingKey = new Array();
243
+ for (const type of implementations) {
244
+ const matchingApp = type.appliedDirectivesOf(metadata.keyDirective()).find((app) => {
245
+ const appFields = parseFieldSetArgument({ parentType: type, directive: app, validate: false });
246
+ return fields.equals(appFields);
247
+ });
248
+ if (matchingApp) {
249
+ if (isResolvable && matchingApp.arguments().resolvable === false) {
250
+ implementationsWithKeyButNotResolvable.push(type);
251
+ }
252
+ }
253
+ else {
254
+ implementationsMissingKey.push(type);
255
+ }
256
+ }
257
+ if (implementationsMissingKey.length > 0) {
258
+ const typesString = (0, utils_1.printHumanReadableList)(implementationsMissingKey.map((i) => `"${i.coordinate}"`), {
259
+ prefix: 'type',
260
+ prefixPlural: 'types',
261
+ });
262
+ errorCollector.push(error_1.ERRORS.INTERFACE_KEY_NOT_ON_IMPLEMENTATION.err(`Key ${keyApplication} on interface type "${itfType.coordinate}" is missing on implementation ${typesString}.`, { nodes: (0, definitions_1.sourceASTs)(...implementationsMissingKey) }));
263
+ }
264
+ else if (implementationsWithKeyButNotResolvable.length > 0) {
265
+ const typesString = (0, utils_1.printHumanReadableList)(implementationsWithKeyButNotResolvable.map((i) => `"${i.coordinate}"`), {
266
+ prefix: 'type',
267
+ prefixPlural: 'types',
268
+ });
269
+ errorCollector.push(error_1.ERRORS.INTERFACE_KEY_NOT_ON_IMPLEMENTATION.err(`Key ${keyApplication} on interface type "${itfType.coordinate}" should be resolvable on all implementation types, but is declared with argument "@key(resolvable:)" set to false in ${typesString}.`, { nodes: (0, definitions_1.sourceASTs)(...implementationsWithKeyButNotResolvable) }));
270
+ }
271
+ }
272
+ }
273
+ }
274
+ function validateInterfaceObjectsAreOnEntities(metadata, errorCollector) {
275
+ for (const application of metadata.interfaceObjectDirective().applications()) {
276
+ if (!isEntityType(application.parent)) {
277
+ errorCollector.push(error_1.ERRORS.INTERFACE_OBJECT_USAGE_ERROR.err(`The @interfaceObject directive can only be applied to entity types but type "${application.parent.coordinate}" has no @key in this subgraph.`, { nodes: application.parent.sourceAST }));
278
+ }
279
+ }
280
+ }
281
+ function validateShareableNotRepeatedOnSameDeclaration(element, metadata, errorCollector) {
282
+ const shareableApplications = element.appliedDirectivesOf(metadata.shareableDirective());
283
+ if (shareableApplications.length <= 1) {
284
+ return;
285
+ }
286
+ const byExtensions = shareableApplications.reduce((acc, v) => {
287
+ const ext = v.ofExtension();
288
+ if (ext) {
289
+ acc.with.add(ext, v);
290
+ }
291
+ else {
292
+ acc.without.push(v);
293
+ }
294
+ return acc;
295
+ }, { without: [], with: new utils_1.MultiMap() });
296
+ const groups = [byExtensions.without].concat((0, utils_1.mapValues)(byExtensions.with));
297
+ for (const group of groups) {
298
+ if (group.length > 1) {
299
+ const eltStr = element.kind === 'ObjectType'
300
+ ? `the same type declaration of "${element.coordinate}"`
301
+ : `field "${element.coordinate}"`;
302
+ errorCollector.push(error_1.ERRORS.INVALID_SHAREABLE_USAGE.err(`Invalid duplicate application of @shareable on ${eltStr}: `
303
+ + '@shareable is only repeatable on types so it can be used simultaneously on a type definition and its extensions, but it should not be duplicated on the same definition/extension declaration', { nodes: (0, definitions_1.sourceASTs)(...group) }));
304
+ }
305
+ }
306
+ }
307
+ class FederationMetadata {
308
+ constructor(schema) {
309
+ this.schema = schema;
310
+ }
311
+ onInvalidate() {
312
+ this._externalTester = undefined;
313
+ this._sharingPredicate = undefined;
314
+ this._isFed2Schema = undefined;
315
+ this._fieldUsedPredicate = undefined;
316
+ }
317
+ isFed2Schema() {
318
+ if (!this._isFed2Schema) {
319
+ const feature = this.federationFeature();
320
+ this._isFed2Schema = !!feature && feature.url.version.satisfies(new coreSpec_1.FeatureVersion(2, 0));
321
+ }
322
+ return this._isFed2Schema;
323
+ }
324
+ federationFeature() {
325
+ var _a;
326
+ return (_a = this.schema.coreFeatures) === null || _a === void 0 ? void 0 : _a.getByIdentity(federationSpec.identity);
327
+ }
328
+ externalTester() {
329
+ if (!this._externalTester) {
330
+ this._externalTester = new ExternalTester(this.schema, this.isFed2Schema());
331
+ }
332
+ return this._externalTester;
333
+ }
334
+ sharingPredicate() {
335
+ if (!this._sharingPredicate) {
336
+ this._sharingPredicate = (0, precompute_1.computeShareables)(this.schema);
337
+ }
338
+ return this._sharingPredicate;
339
+ }
340
+ fieldUsedPredicate() {
341
+ if (!this._fieldUsedPredicate) {
342
+ const usedFields = collectUsedFields(this);
343
+ this._fieldUsedPredicate = (field) => !!usedFields.has(field);
344
+ }
345
+ return this._fieldUsedPredicate;
346
+ }
347
+ isFieldUsed(field) {
348
+ return this.fieldUsedPredicate()(field);
349
+ }
350
+ isFieldExternal(field) {
351
+ return this.externalTester().isExternal(field);
352
+ }
353
+ isFieldPartiallyExternal(field) {
354
+ return this.externalTester().isPartiallyExternal(field);
355
+ }
356
+ isFieldFullyExternal(field) {
357
+ return this.externalTester().isFullyExternal(field);
358
+ }
359
+ isFieldFakeExternal(field) {
360
+ return this.externalTester().isFakeExternal(field);
361
+ }
362
+ selectionSelectsAnyExternalField(selectionSet) {
363
+ return this.externalTester().selectsAnyExternalField(selectionSet);
364
+ }
365
+ isFieldShareable(field) {
366
+ return this.sharingPredicate()(field);
367
+ }
368
+ isInterfaceObjectType(type) {
369
+ return (0, definitions_1.isObjectType)(type)
370
+ && hasAppliedDirective(type, this.interfaceObjectDirective());
371
+ }
372
+ federationDirectiveNameInSchema(name) {
373
+ if (this.isFed2Schema()) {
374
+ const coreFeatures = this.schema.coreFeatures;
375
+ (0, utils_1.assert)(coreFeatures, 'Schema should be a core schema');
376
+ const federationFeature = coreFeatures.getByIdentity(federationSpec.identity);
377
+ (0, utils_1.assert)(federationFeature, 'Schema should have the federation feature');
378
+ return federationFeature.directiveNameInSchema(name);
379
+ }
380
+ else {
381
+ return name;
382
+ }
383
+ }
384
+ federationTypeNameInSchema(name) {
385
+ if (name.charAt(0) === '_') {
386
+ return name;
387
+ }
388
+ if (this.isFed2Schema()) {
389
+ const coreFeatures = this.schema.coreFeatures;
390
+ (0, utils_1.assert)(coreFeatures, 'Schema should be a core schema');
391
+ const federationFeature = coreFeatures.getByIdentity(federationSpec.identity);
392
+ (0, utils_1.assert)(federationFeature, 'Schema should have the federation feature');
393
+ return federationFeature.typeNameInSchema(name);
394
+ }
395
+ else {
396
+ return '_' + name;
397
+ }
398
+ }
399
+ getLegacyFederationDirective(name) {
400
+ const directive = this.getFederationDirective(name);
401
+ (0, utils_1.assert)(directive, `The provided schema does not have federation directive @${name}`);
402
+ return directive;
403
+ }
404
+ getFederationDirective(name) {
405
+ return this.schema.directive(this.federationDirectiveNameInSchema(name));
406
+ }
407
+ getPost20FederationDirective(name) {
408
+ var _a;
409
+ return (_a = this.getFederationDirective(name)) !== null && _a !== void 0 ? _a : {
410
+ name,
411
+ applications: () => new Array(),
412
+ };
413
+ }
414
+ keyDirective() {
415
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.KEY);
416
+ }
417
+ overrideDirective() {
418
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.OVERRIDE);
419
+ }
420
+ extendsDirective() {
421
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.EXTENDS);
422
+ }
423
+ externalDirective() {
424
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.EXTERNAL);
425
+ }
426
+ requiresDirective() {
427
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.REQUIRES);
428
+ }
429
+ providesDirective() {
430
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.PROVIDES);
431
+ }
432
+ shareableDirective() {
433
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.SHAREABLE);
434
+ }
435
+ tagDirective() {
436
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.TAG);
437
+ }
438
+ composeDirective() {
439
+ return this.getPost20FederationDirective(federationSpec_1.FederationDirectiveName.COMPOSE_DIRECTIVE);
440
+ }
441
+ inaccessibleDirective() {
442
+ return this.getLegacyFederationDirective(federationSpec_1.FederationDirectiveName.INACCESSIBLE);
443
+ }
444
+ interfaceObjectDirective() {
445
+ return this.getPost20FederationDirective(federationSpec_1.FederationDirectiveName.INTERFACE_OBJECT);
446
+ }
447
+ allFederationDirectives() {
448
+ const baseDirectives = [
449
+ this.keyDirective(),
450
+ this.externalDirective(),
451
+ this.requiresDirective(),
452
+ this.providesDirective(),
453
+ this.tagDirective(),
454
+ this.extendsDirective(),
455
+ ];
456
+ if (!this.isFed2Schema()) {
457
+ return baseDirectives;
458
+ }
459
+ baseDirectives.push(this.shareableDirective());
460
+ baseDirectives.push(this.inaccessibleDirective());
461
+ baseDirectives.push(this.overrideDirective());
462
+ const composeDirective = this.composeDirective();
463
+ if (isFederationDirectiveDefinedInSchema(composeDirective)) {
464
+ baseDirectives.push(composeDirective);
465
+ }
466
+ const interfaceObjectDirective = this.interfaceObjectDirective();
467
+ if (isFederationDirectiveDefinedInSchema(interfaceObjectDirective)) {
468
+ baseDirectives.push(interfaceObjectDirective);
469
+ }
470
+ return baseDirectives;
471
+ }
472
+ entityType() {
473
+ return this.schema.type(this.federationTypeNameInSchema(exports.entityTypeSpec.name));
474
+ }
475
+ anyType() {
476
+ return this.schema.type(this.federationTypeNameInSchema(exports.anyTypeSpec.name));
477
+ }
478
+ serviceType() {
479
+ return this.schema.type(this.federationTypeNameInSchema(exports.serviceTypeSpec.name));
480
+ }
481
+ fieldSetType() {
482
+ return this.schema.type(this.federationTypeNameInSchema(federationSpec_1.FederationTypeName.FIELD_SET));
483
+ }
484
+ allFederationTypes() {
485
+ const baseTypes = [
486
+ this.anyType(),
487
+ this.serviceType(),
488
+ this.fieldSetType(),
489
+ ];
490
+ const entityType = this.entityType();
491
+ if (entityType) {
492
+ baseTypes.push(entityType);
493
+ }
494
+ return baseTypes;
495
+ }
496
+ }
497
+ exports.FederationMetadata = FederationMetadata;
498
+ function isFederationDirectiveDefinedInSchema(definition) {
499
+ return definition instanceof definitions_1.DirectiveDefinition;
500
+ }
501
+ exports.isFederationDirectiveDefinedInSchema = isFederationDirectiveDefinedInSchema;
502
+ function hasAppliedDirective(type, definition) {
503
+ return isFederationDirectiveDefinedInSchema(definition) && type.hasAppliedDirective(definition);
504
+ }
505
+ exports.hasAppliedDirective = hasAppliedDirective;
506
+ class FederationBlueprint extends definitions_1.SchemaBlueprint {
507
+ constructor(withRootTypeRenaming) {
508
+ super();
509
+ this.withRootTypeRenaming = withRootTypeRenaming;
510
+ }
511
+ onAddedCoreFeature(schema, feature) {
512
+ super.onAddedCoreFeature(schema, feature);
513
+ if (feature.url.identity === federationSpec_1.federationIdentity) {
514
+ const spec = federationSpec_1.FEDERATION_VERSIONS.find(feature.url.version);
515
+ if (spec) {
516
+ spec.addElementsToSchema(schema);
517
+ }
518
+ }
519
+ }
520
+ onMissingDirectiveDefinition(schema, name, args) {
521
+ if (name === coreSpec_1.linkDirectiveDefaultName) {
522
+ const url = args && args['url'];
523
+ const as = url && url.startsWith(linkSpec.identity) ? args['as'] : undefined;
524
+ const errors = linkSpec.addDefinitionsToSchema(schema, as);
525
+ return errors.length > 0 ? errors : schema.directive(name);
526
+ }
527
+ return super.onMissingDirectiveDefinition(schema, name, args);
528
+ }
529
+ ignoreParsedField(type, fieldName) {
530
+ if (!exports.FEDERATION_OPERATION_FIELDS.includes(fieldName)) {
531
+ return false;
532
+ }
533
+ const metadata = federationMetadata(type.schema());
534
+ return !!metadata && !metadata.isFed2Schema();
535
+ }
536
+ onConstructed(schema) {
537
+ const existing = federationMetadata(schema);
538
+ if (!existing) {
539
+ schema['_federationMetadata'] = new FederationMetadata(schema);
540
+ }
541
+ }
542
+ onDirectiveDefinitionAndSchemaParsed(schema) {
543
+ const errors = completeSubgraphSchema(schema);
544
+ schema.schemaDefinition.processUnappliedDirectives();
545
+ return errors;
546
+ }
547
+ onInvalidation(schema) {
548
+ super.onInvalidation(schema);
549
+ const metadata = federationMetadata(schema);
550
+ (0, utils_1.assert)(metadata, 'Federation schema should have had its metadata set on construction');
551
+ FederationMetadata.prototype['onInvalidate'].call(metadata);
552
+ }
553
+ onValidation(schema) {
554
+ var _a;
555
+ const errorCollector = super.onValidation(schema);
556
+ if (this.withRootTypeRenaming) {
557
+ for (const k of definitions_1.allSchemaRootKinds) {
558
+ const type = (_a = schema.schemaDefinition.root(k)) === null || _a === void 0 ? void 0 : _a.type;
559
+ const defaultName = (0, definitions_1.defaultRootName)(k);
560
+ if (type && type.name !== defaultName) {
561
+ const existing = schema.type(defaultName);
562
+ if (existing) {
563
+ errorCollector.push(error_1.ERROR_CATEGORIES.ROOT_TYPE_USED.get(k).err(`The schema has a type named "${defaultName}" but it is not set as the ${k} root type ("${type.name}" is instead): `
564
+ + 'this is not supported by federation. '
565
+ + 'If a root type does not use its default name, there should be no other type with that default name.', { nodes: (0, definitions_1.sourceASTs)(type, existing) }));
566
+ }
567
+ type.rename(defaultName);
568
+ }
569
+ }
570
+ }
571
+ const metadata = federationMetadata(schema);
572
+ (0, utils_1.assert)(metadata, 'Federation schema should have had its metadata set on construction');
573
+ if (!metadata.isFed2Schema()) {
574
+ return errorCollector;
575
+ }
576
+ const keyDirective = metadata.keyDirective();
577
+ validateAllFieldSet({
578
+ definition: keyDirective,
579
+ targetTypeExtractor: type => type,
580
+ errorCollector,
581
+ metadata,
582
+ isOnParentType: true,
583
+ allowOnNonExternalLeafFields: true,
584
+ allowOnInterface: metadata.federationFeature().url.version.compareTo(new coreSpec_1.FeatureVersion(2, 3)) >= 0,
585
+ onFields: field => {
586
+ const type = (0, definitions_1.baseType)(field.type);
587
+ if ((0, definitions_1.isUnionType)(type) || (0, definitions_1.isInterfaceType)(type)) {
588
+ let kind = type.kind;
589
+ kind = kind.slice(0, kind.length - 'Type'.length);
590
+ throw error_1.ERRORS.KEY_FIELDS_SELECT_INVALID_TYPE.err(`field "${field.coordinate}" is a ${kind} type which is not allowed in @key`);
591
+ }
592
+ }
593
+ });
594
+ validateAllFieldSet({
595
+ definition: metadata.requiresDirective(),
596
+ targetTypeExtractor: field => field.parent,
597
+ errorCollector,
598
+ metadata,
599
+ allowFieldsWithArguments: true,
600
+ });
601
+ validateAllFieldSet({
602
+ definition: metadata.providesDirective(),
603
+ targetTypeExtractor: field => {
604
+ if (metadata.isFieldExternal(field)) {
605
+ throw error_1.ERRORS.EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE.err(`Cannot have both @provides and @external on field "${field.coordinate}"`, { nodes: field.sourceAST });
606
+ }
607
+ const type = (0, definitions_1.baseType)(field.type);
608
+ if (!(0, definitions_1.isCompositeType)(type)) {
609
+ throw error_1.ERRORS.PROVIDES_ON_NON_OBJECT_FIELD.err(`Invalid @provides directive on field "${field.coordinate}": field has type "${field.type}" which is not a Composite Type`, { nodes: field.sourceAST });
610
+ }
611
+ return type;
612
+ },
613
+ errorCollector,
614
+ metadata,
615
+ });
616
+ validateNoExternalOnInterfaceFields(metadata, errorCollector);
617
+ validateAllExternalFieldsUsed(metadata, errorCollector);
618
+ validateKeyOnInterfacesAreAlsoOnAllImplementations(metadata, errorCollector);
619
+ validateInterfaceObjectsAreOnEntities(metadata, errorCollector);
620
+ const tagDirective = metadata.tagDirective();
621
+ if (tagDirective) {
622
+ const error = tagSpec.checkCompatibleDirective(tagDirective);
623
+ if (error) {
624
+ errorCollector.push(error);
625
+ }
626
+ }
627
+ for (const objectType of schema.objectTypes()) {
628
+ validateShareableNotRepeatedOnSameDeclaration(objectType, metadata, errorCollector);
629
+ for (const field of objectType.fields()) {
630
+ validateShareableNotRepeatedOnSameDeclaration(field, metadata, errorCollector);
631
+ }
632
+ }
633
+ for (const shareableApplication of metadata.shareableDirective().applications()) {
634
+ const element = shareableApplication.parent;
635
+ if (element instanceof definitions_1.FieldDefinition && !(0, definitions_1.isObjectType)(element.parent)) {
636
+ errorCollector.push(error_1.ERRORS.INVALID_SHAREABLE_USAGE.err(`Invalid use of @shareable on field "${element.coordinate}": only object type fields can be marked with @shareable`, { nodes: (0, definitions_1.sourceASTs)(shareableApplication, element.parent) }));
637
+ }
638
+ }
639
+ return errorCollector;
640
+ }
641
+ validationRules() {
642
+ return FEDERATION_VALIDATION_RULES;
643
+ }
644
+ onUnknownDirectiveValidationError(schema, unknownDirectiveName, error) {
645
+ const metadata = federationMetadata(schema);
646
+ (0, utils_1.assert)(metadata, `This method should only have been called on a subgraph schema`);
647
+ if (ALL_DEFAULT_FEDERATION_DIRECTIVE_NAMES.includes(unknownDirectiveName)) {
648
+ if (metadata.isFed2Schema()) {
649
+ const federationFeature = metadata.federationFeature();
650
+ (0, utils_1.assert)(federationFeature, 'Fed2 subgraph _must_ link to the federation feature');
651
+ const directiveNameInSchema = federationFeature.directiveNameInSchema(unknownDirectiveName);
652
+ if (directiveNameInSchema.startsWith(federationFeature.nameInSchema + '__')) {
653
+ 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.`);
654
+ }
655
+ else {
656
+ 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.`);
657
+ }
658
+ }
659
+ else {
660
+ 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.`);
661
+ }
662
+ }
663
+ else if (!metadata.isFed2Schema()) {
664
+ const suggestions = (0, suggestions_1.suggestionList)(unknownDirectiveName, ALL_DEFAULT_FEDERATION_DIRECTIVE_NAMES);
665
+ if (suggestions.length > 0) {
666
+ 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.`);
667
+ }
668
+ }
669
+ return error;
670
+ }
671
+ applyDirectivesAfterParsing() {
672
+ return true;
673
+ }
674
+ }
675
+ exports.FederationBlueprint = FederationBlueprint;
676
+ function findUnusedNamedForLinkDirective(schema) {
677
+ if (!schema.directive(linkSpec.url.name)) {
678
+ return undefined;
679
+ }
680
+ const baseName = linkSpec.url.name;
681
+ let n = 1;
682
+ for (;;) {
683
+ const candidate = baseName + n;
684
+ if (!schema.directive(candidate)) {
685
+ return candidate;
686
+ }
687
+ }
688
+ }
689
+ function setSchemaAsFed2Subgraph(schema) {
690
+ let core = schema.coreFeatures;
691
+ let spec;
692
+ if (core) {
693
+ spec = core.coreDefinition;
694
+ (0, utils_1.assert)(spec.url.version.satisfies(linkSpec.version), `Fed2 schema must use @link with version >= 1.0, but schema uses ${spec.url}`);
695
+ }
696
+ else {
697
+ const alias = findUnusedNamedForLinkDirective(schema);
698
+ const errors = linkSpec.addToSchema(schema, alias);
699
+ if (errors.length > 0) {
700
+ throw (0, definitions_1.ErrGraphQLValidationFailed)(errors);
701
+ }
702
+ spec = linkSpec;
703
+ core = schema.coreFeatures;
704
+ (0, utils_1.assert)(core, 'Schema should now be a core schema');
705
+ }
706
+ (0, utils_1.assert)(!core.getByIdentity(federationSpec.identity), 'Schema already set as a federation subgraph');
707
+ schema.schemaDefinition.applyDirective(core.coreItself.nameInSchema, {
708
+ url: federationSpec.url.toString(),
709
+ import: federationSpec.directiveSpecs().map((spec) => `@${spec.name}`),
710
+ });
711
+ const errors = completeSubgraphSchema(schema);
712
+ if (errors.length > 0) {
713
+ throw (0, definitions_1.ErrGraphQLValidationFailed)(errors);
714
+ }
715
+ }
716
+ exports.setSchemaAsFed2Subgraph = setSchemaAsFed2Subgraph;
717
+ exports.FEDERATION2_LINK_WITH_FULL_IMPORTS = '@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key", "@requires", "@provides", "@external", "@tag", "@extends", "@shareable", "@inaccessible", "@override", "@composeDirective", "@interfaceObject"])';
718
+ function asFed2SubgraphDocument(document, options) {
719
+ var _a, _b;
720
+ const directiveToAdd = ({
721
+ kind: graphql_1.Kind.DIRECTIVE,
722
+ name: { kind: graphql_1.Kind.NAME, value: coreSpec_1.linkDirectiveDefaultName },
723
+ arguments: [
724
+ {
725
+ kind: graphql_1.Kind.ARGUMENT,
726
+ name: { kind: graphql_1.Kind.NAME, value: 'url' },
727
+ value: { kind: graphql_1.Kind.STRING, value: federationSpec.url.toString() }
728
+ },
729
+ {
730
+ kind: graphql_1.Kind.ARGUMENT,
731
+ name: { kind: graphql_1.Kind.NAME, value: 'import' },
732
+ value: { kind: graphql_1.Kind.LIST, values: federationSpec.directiveSpecs().map((spec) => ({ kind: graphql_1.Kind.STRING, value: `@${spec.name}` })) }
733
+ }
734
+ ]
735
+ });
736
+ if ((_a = options === null || options === void 0 ? void 0 : options.addAsSchemaExtension) !== null && _a !== void 0 ? _a : true) {
737
+ return {
738
+ kind: graphql_1.Kind.DOCUMENT,
739
+ loc: document.loc,
740
+ definitions: document.definitions.concat({
741
+ kind: graphql_1.Kind.SCHEMA_EXTENSION,
742
+ directives: [directiveToAdd]
743
+ }),
744
+ };
745
+ }
746
+ const existingSchemaDefinition = document.definitions.find((d) => d.kind == graphql_1.Kind.SCHEMA_DEFINITION);
747
+ if (existingSchemaDefinition) {
748
+ return {
749
+ kind: graphql_1.Kind.DOCUMENT,
750
+ loc: document.loc,
751
+ definitions: document.definitions.filter((d) => d !== existingSchemaDefinition).concat([{
752
+ ...existingSchemaDefinition,
753
+ directives: [directiveToAdd].concat((_b = existingSchemaDefinition.directives) !== null && _b !== void 0 ? _b : []),
754
+ }]),
755
+ };
756
+ }
757
+ else {
758
+ const hasMutation = document.definitions.some((d) => d.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION && d.name.value === 'Mutation');
759
+ const makeOpType = (opType, name) => ({
760
+ kind: graphql_1.Kind.OPERATION_TYPE_DEFINITION,
761
+ operation: opType,
762
+ type: {
763
+ kind: graphql_1.Kind.NAMED_TYPE,
764
+ name: {
765
+ kind: graphql_1.Kind.NAME,
766
+ value: name,
767
+ }
768
+ },
769
+ });
770
+ return {
771
+ kind: graphql_1.Kind.DOCUMENT,
772
+ loc: document.loc,
773
+ definitions: document.definitions.concat({
774
+ kind: graphql_1.Kind.SCHEMA_DEFINITION,
775
+ directives: [directiveToAdd],
776
+ operationTypes: [makeOpType(graphql_1.OperationTypeNode.QUERY, 'Query')].concat(hasMutation ? makeOpType(graphql_1.OperationTypeNode.MUTATION, 'Mutation') : []),
777
+ }),
778
+ };
779
+ }
780
+ }
781
+ exports.asFed2SubgraphDocument = asFed2SubgraphDocument;
782
+ function printSubgraphNames(names) {
783
+ return (0, utils_1.printHumanReadableList)(names.map(n => `"${n}"`), {
784
+ prefix: 'subgraph',
785
+ prefixPlural: 'subgraphs',
786
+ });
787
+ }
788
+ exports.printSubgraphNames = printSubgraphNames;
789
+ function federationMetadata(schema) {
790
+ return schema['_federationMetadata'];
791
+ }
792
+ exports.federationMetadata = federationMetadata;
793
+ function isFederationSubgraphSchema(schema) {
794
+ return !!federationMetadata(schema);
795
+ }
796
+ exports.isFederationSubgraphSchema = isFederationSubgraphSchema;
797
+ function isFederationField(field) {
798
+ var _a;
799
+ if (field.parent === ((_a = field.schema().schemaDefinition.root("query")) === null || _a === void 0 ? void 0 : _a.type)) {
800
+ return exports.FEDERATION_OPERATION_FIELDS.includes(field.name);
801
+ }
802
+ return false;
803
+ }
804
+ exports.isFederationField = isFederationField;
805
+ function isEntityType(type) {
806
+ if (!(0, definitions_1.isObjectType)(type) && !(0, definitions_1.isInterfaceType)(type)) {
807
+ return false;
808
+ }
809
+ const metadata = federationMetadata(type.schema());
810
+ return !!metadata && type.hasAppliedDirective(metadata.keyDirective());
811
+ }
812
+ exports.isEntityType = isEntityType;
813
+ function isInterfaceObjectType(type) {
814
+ if (!(0, definitions_1.isObjectType)(type)) {
815
+ return false;
816
+ }
817
+ const metadata = federationMetadata(type.schema());
818
+ return !!metadata && metadata.isInterfaceObjectType(type);
819
+ }
820
+ exports.isInterfaceObjectType = isInterfaceObjectType;
821
+ function buildSubgraph(name, url, source, withRootTypeRenaming = true) {
822
+ const buildOptions = {
823
+ blueprint: new FederationBlueprint(withRootTypeRenaming),
824
+ validate: false,
825
+ };
826
+ let subgraph;
827
+ try {
828
+ const schema = typeof source === 'string'
829
+ ? (0, buildSchema_1.buildSchema)(new graphql_1.Source(source, name), buildOptions)
830
+ : (0, buildSchema_1.buildSchemaFromAST)(source, buildOptions);
831
+ subgraph = new Subgraph(name, url, schema);
832
+ }
833
+ catch (e) {
834
+ if (e instanceof graphql_1.GraphQLError && name !== exports.FEDERATION_UNNAMED_SUBGRAPH_NAME) {
835
+ throw addSubgraphToError(e, name, error_1.ERRORS.INVALID_GRAPHQL);
836
+ }
837
+ else {
838
+ throw e;
839
+ }
840
+ }
841
+ return subgraph.validate();
842
+ }
843
+ exports.buildSubgraph = buildSubgraph;
844
+ function newEmptyFederation2Schema(config) {
845
+ const schema = new definitions_1.Schema(new FederationBlueprint(true), config);
846
+ setSchemaAsFed2Subgraph(schema);
847
+ return schema;
848
+ }
849
+ exports.newEmptyFederation2Schema = newEmptyFederation2Schema;
850
+ function completeSubgraphSchema(schema) {
851
+ const coreFeatures = schema.coreFeatures;
852
+ if (coreFeatures) {
853
+ const fedFeature = coreFeatures.getByIdentity(federationSpec_1.federationIdentity);
854
+ if (fedFeature) {
855
+ return completeFed2SubgraphSchema(schema);
856
+ }
857
+ else {
858
+ return completeFed1SubgraphSchema(schema);
859
+ }
860
+ }
861
+ else {
862
+ const fedLink = schema.schemaDefinition.appliedDirectivesOf(coreSpec_1.linkDirectiveDefaultName).find(isFedSpecLinkDirective);
863
+ if (fedLink) {
864
+ const errors = linkSpec.addToSchema(schema);
865
+ if (errors.length > 0) {
866
+ return errors;
867
+ }
868
+ return completeFed2SubgraphSchema(schema);
869
+ }
870
+ else {
871
+ return completeFed1SubgraphSchema(schema);
872
+ }
873
+ }
874
+ }
875
+ function isFedSpecLinkDirective(directive) {
876
+ const args = directive.arguments();
877
+ return directive.name === coreSpec_1.linkDirectiveDefaultName && args['url'] && args['url'].startsWith(federationSpec_1.federationIdentity);
878
+ }
879
+ function completeFed1SubgraphSchema(schema) {
880
+ var _a, _b;
881
+ for (const name of [federationSpec_1.FederationDirectiveName.KEY, federationSpec_1.FederationDirectiveName.PROVIDES, federationSpec_1.FederationDirectiveName.REQUIRES]) {
882
+ const directive = schema.directive(name);
883
+ if (!directive) {
884
+ continue;
885
+ }
886
+ (0, utils_1.assert)(directive.applications().length === 0, `${directive} shouldn't have had validation at that places`);
887
+ const fieldType = (_b = (_a = directive.argument('fields')) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.toString();
888
+ const fieldTypeIsWrongInKnownWays = !!fieldType
889
+ && directive.arguments().length === 1
890
+ && (fieldType === 'String' || fieldType === '_FieldSet' || fieldType === 'FieldSet');
891
+ if (directive.arguments().length === 0 || fieldTypeIsWrongInKnownWays) {
892
+ directive.remove();
893
+ }
894
+ }
895
+ const errors = federationSpec_1.FEDERATION1_TYPES.map((spec) => spec.checkOrAdd(schema, '_' + spec.name))
896
+ .concat(federationSpec_1.FEDERATION1_DIRECTIVES.map((spec) => spec.checkOrAdd(schema)))
897
+ .flat();
898
+ return errors.length === 0 ? expandKnownFeatures(schema) : errors;
899
+ }
900
+ function completeFed2SubgraphSchema(schema) {
901
+ const coreFeatures = schema.coreFeatures;
902
+ (0, utils_1.assert)(coreFeatures, 'This method should not have been called on a non-core schema');
903
+ const fedFeature = coreFeatures.getByIdentity(federationSpec_1.federationIdentity);
904
+ (0, utils_1.assert)(fedFeature, 'This method should not have been called on a schema with no @link for federation');
905
+ const spec = federationSpec_1.FEDERATION_VERSIONS.find(fedFeature.url.version);
906
+ if (!spec) {
907
+ return [error_1.ERRORS.UNKNOWN_FEDERATION_LINK_VERSION.err(`Invalid version ${fedFeature.url.version} for the federation feature in @link direction on schema`, { nodes: fedFeature.directive.sourceAST })];
908
+ }
909
+ const errors = spec.addElementsToSchema(schema);
910
+ return errors.length === 0 ? expandKnownFeatures(schema) : errors;
911
+ }
912
+ function expandKnownFeatures(schema) {
913
+ const coreFeatures = schema.coreFeatures;
914
+ if (!coreFeatures) {
915
+ return [];
916
+ }
917
+ let errors = [];
918
+ for (const feature of coreFeatures.allFeatures()) {
919
+ if (feature === coreFeatures.coreItself || feature.url.identity === federationSpec_1.federationIdentity || feature.url.identity === joinSpec_1.joinIdentity) {
920
+ continue;
921
+ }
922
+ const spec = (0, knownCoreFeatures_1.coreFeatureDefinitionIfKnown)(feature.url);
923
+ if (!spec) {
924
+ continue;
925
+ }
926
+ errors = errors.concat(spec.addElementsToSchema(schema));
927
+ }
928
+ return errors;
929
+ }
930
+ function parseFieldSetArgument({ parentType, directive, fieldAccessor, validate, decorateValidationErrors = true, }) {
931
+ try {
932
+ const selectionSet = (0, operations_1.parseSelectionSet)({
933
+ parentType,
934
+ source: validateFieldSetValue(directive),
935
+ fieldAccessor,
936
+ validate,
937
+ });
938
+ if (validate !== null && validate !== void 0 ? validate : true) {
939
+ selectionSet.forEachElement((elt) => {
940
+ if (elt.kind === 'Field' && elt.alias) {
941
+ throw new graphql_1.GraphQLError(`Cannot use alias "${elt.alias}" in "${elt}": aliases are not currently supported in @${directive.name}`);
942
+ }
943
+ });
944
+ }
945
+ return selectionSet;
946
+ }
947
+ catch (e) {
948
+ if (!(e instanceof graphql_1.GraphQLError) || !decorateValidationErrors) {
949
+ throw e;
950
+ }
951
+ throw handleFieldSetValidationError(directive, e, (msg) => {
952
+ if (msg.startsWith('Cannot query field')) {
953
+ if (msg.endsWith('.')) {
954
+ msg = msg.slice(0, msg.length - 1);
955
+ }
956
+ if (directive.name === federationSpec_1.FederationDirectiveName.KEY) {
957
+ msg = msg + ' (the field should either be added to this subgraph or, if it should not be resolved by this subgraph, you need to add it to this subgraph with @external).';
958
+ }
959
+ else {
960
+ msg = msg + ' (if the field is defined in another subgraph, you need to add it to this subgraph with @external).';
961
+ }
962
+ }
963
+ return msg;
964
+ });
965
+ }
966
+ }
967
+ exports.parseFieldSetArgument = parseFieldSetArgument;
968
+ function collectTargetFields({ parentType, directive, includeInterfaceFieldsImplementations, validate = true, }) {
969
+ const fields = [];
970
+ try {
971
+ parseFieldSetArgument({
972
+ parentType,
973
+ directive,
974
+ fieldAccessor: (t, f) => {
975
+ const field = t.field(f);
976
+ if (field) {
977
+ fields.push(field);
978
+ if (includeInterfaceFieldsImplementations && (0, definitions_1.isInterfaceType)(t)) {
979
+ for (const implType of t.possibleRuntimeTypes()) {
980
+ const implField = implType.field(f);
981
+ if (implField) {
982
+ fields.push(implField);
983
+ }
984
+ }
985
+ }
986
+ }
987
+ return field;
988
+ },
989
+ validate,
990
+ });
991
+ }
992
+ catch (e) {
993
+ const isGraphQLError = (0, error_1.errorCauses)(e) !== undefined;
994
+ if (!isGraphQLError || validate) {
995
+ throw e;
996
+ }
997
+ }
998
+ return fields;
999
+ }
1000
+ exports.collectTargetFields = collectTargetFields;
1001
+ function validateFieldSetValue(directive) {
1002
+ var _a;
1003
+ const fields = directive.arguments().fields;
1004
+ const nodes = directive.sourceAST;
1005
+ if (typeof fields !== 'string') {
1006
+ throw error_1.ERROR_CATEGORIES.DIRECTIVE_INVALID_FIELDS_TYPE.get(directive.name).err(`Invalid value for argument "${directive.definition.argument('fields').name}": must be a string.`, { nodes });
1007
+ }
1008
+ if (nodes && nodes.kind === 'Directive') {
1009
+ for (const argNode of (_a = nodes.arguments) !== null && _a !== void 0 ? _a : []) {
1010
+ if (argNode.name.value === 'fields') {
1011
+ if (argNode.value.kind !== 'StringValue') {
1012
+ throw error_1.ERROR_CATEGORIES.DIRECTIVE_INVALID_FIELDS_TYPE.get(directive.name).err(`Invalid value for argument "${directive.definition.argument('fields').name}": must be a string.`, { nodes });
1013
+ }
1014
+ break;
1015
+ }
1016
+ }
1017
+ }
1018
+ return fields;
1019
+ }
1020
+ function subgraphsFromServiceList(serviceList) {
1021
+ var _a;
1022
+ let errors = [];
1023
+ const subgraphs = new Subgraphs();
1024
+ for (const service of serviceList) {
1025
+ try {
1026
+ subgraphs.add(buildSubgraph(service.name, (_a = service.url) !== null && _a !== void 0 ? _a : '', service.typeDefs));
1027
+ }
1028
+ catch (e) {
1029
+ const causes = (0, error_1.errorCauses)(e);
1030
+ if (causes) {
1031
+ errors = errors.concat(causes);
1032
+ }
1033
+ else {
1034
+ throw e;
1035
+ }
1036
+ }
1037
+ }
1038
+ return errors.length === 0 ? subgraphs : errors;
1039
+ }
1040
+ exports.subgraphsFromServiceList = subgraphsFromServiceList;
1041
+ class Subgraphs {
1042
+ constructor() {
1043
+ this.subgraphs = new utils_1.OrderedMap();
1044
+ }
1045
+ add(subgraph) {
1046
+ if (this.subgraphs.has(subgraph.name)) {
1047
+ throw new Error(`A subgraph named ${subgraph.name} already exists` + (subgraph.url ? ` (with url '${subgraph.url}')` : ''));
1048
+ }
1049
+ this.subgraphs.add(subgraph.name, subgraph);
1050
+ return subgraph;
1051
+ }
1052
+ get(name) {
1053
+ return this.subgraphs.get(name);
1054
+ }
1055
+ size() {
1056
+ return this.subgraphs.size;
1057
+ }
1058
+ names() {
1059
+ return this.subgraphs.keys();
1060
+ }
1061
+ values() {
1062
+ return this.subgraphs.values();
1063
+ }
1064
+ *[Symbol.iterator]() {
1065
+ for (const subgraph of this.subgraphs) {
1066
+ yield subgraph;
1067
+ }
1068
+ }
1069
+ validate() {
1070
+ let errors = [];
1071
+ for (const subgraph of this.values()) {
1072
+ try {
1073
+ subgraph.validate();
1074
+ }
1075
+ catch (e) {
1076
+ const causes = (0, error_1.errorCauses)(e);
1077
+ if (!causes) {
1078
+ throw e;
1079
+ }
1080
+ errors = errors.concat(causes);
1081
+ }
1082
+ }
1083
+ return errors.length === 0 ? undefined : errors;
1084
+ }
1085
+ toString() {
1086
+ return '[' + this.subgraphs.keys().join(', ') + ']';
1087
+ }
1088
+ }
1089
+ exports.Subgraphs = Subgraphs;
1090
+ exports.anyTypeSpec = (0, directiveAndTypeSpecification_1.createScalarTypeSpecification)({ name: '_Any' });
1091
+ exports.serviceTypeSpec = (0, directiveAndTypeSpecification_1.createObjectTypeSpecification)({
1092
+ name: '_Service',
1093
+ fieldsFct: (schema) => [{ name: 'sdl', type: schema.stringType() }],
1094
+ });
1095
+ exports.entityTypeSpec = (0, directiveAndTypeSpecification_1.createUnionTypeSpecification)({
1096
+ name: '_Entity',
1097
+ membersFct: (schema) => {
1098
+ return schema.objectTypes().filter(isEntityType).map((t) => t.name);
1099
+ },
1100
+ });
1101
+ exports.FEDERATION_OPERATION_TYPES = [exports.anyTypeSpec, exports.serviceTypeSpec, exports.entityTypeSpec];
1102
+ exports.serviceFieldName = '_service';
1103
+ exports.entitiesFieldName = '_entities';
1104
+ exports.FEDERATION_OPERATION_FIELDS = [exports.serviceFieldName, exports.entitiesFieldName];
1105
+ class Subgraph {
1106
+ constructor(name, url, schema) {
1107
+ this.name = name;
1108
+ this.url = url;
1109
+ this.schema = schema;
1110
+ if (name === exports.FEDERATION_RESERVED_SUBGRAPH_NAME) {
1111
+ throw error_1.ERRORS.INVALID_SUBGRAPH_NAME.err(`Invalid name ${exports.FEDERATION_RESERVED_SUBGRAPH_NAME} for a subgraph: this name is reserved`);
1112
+ }
1113
+ }
1114
+ metadata() {
1115
+ const metadata = federationMetadata(this.schema);
1116
+ (0, utils_1.assert)(metadata, 'The subgraph schema should have built with the federation built-ins.');
1117
+ return metadata;
1118
+ }
1119
+ isFed2Subgraph() {
1120
+ return this.metadata().isFed2Schema();
1121
+ }
1122
+ addFederationOperations() {
1123
+ const metadata = this.metadata();
1124
+ for (const type of exports.FEDERATION_OPERATION_TYPES) {
1125
+ type.checkOrAdd(this.schema);
1126
+ }
1127
+ const queryRoot = this.schema.schemaDefinition.root("query");
1128
+ const queryType = queryRoot ? queryRoot.type : this.schema.addType(new definitions_1.ObjectType("Query"));
1129
+ const entityField = queryType.field(exports.entitiesFieldName);
1130
+ const entityType = metadata.entityType();
1131
+ if (entityType) {
1132
+ const entityFieldType = new definitions_1.NonNullType(new definitions_1.ListType(entityType));
1133
+ if (!entityField) {
1134
+ queryType.addField(exports.entitiesFieldName, entityFieldType)
1135
+ .addArgument('representations', new definitions_1.NonNullType(new definitions_1.ListType(new definitions_1.NonNullType(metadata.anyType()))));
1136
+ }
1137
+ else if (!entityField.type) {
1138
+ entityField.type = entityType;
1139
+ }
1140
+ }
1141
+ else if (entityField) {
1142
+ entityField.remove();
1143
+ }
1144
+ if (!queryType.field(exports.serviceFieldName)) {
1145
+ queryType.addField(exports.serviceFieldName, new definitions_1.NonNullType(metadata.serviceType()));
1146
+ }
1147
+ }
1148
+ validate() {
1149
+ try {
1150
+ this.addFederationOperations();
1151
+ this.schema.validate();
1152
+ return this;
1153
+ }
1154
+ catch (e) {
1155
+ if (e instanceof graphql_1.GraphQLError) {
1156
+ throw addSubgraphToError(e, this.name, error_1.ERRORS.INVALID_GRAPHQL);
1157
+ }
1158
+ else {
1159
+ throw e;
1160
+ }
1161
+ }
1162
+ }
1163
+ isPrintedDirective(d) {
1164
+ var _a;
1165
+ if (this.metadata().allFederationDirectives().includes(d)) {
1166
+ return false;
1167
+ }
1168
+ const core = this.schema.coreFeatures;
1169
+ return !core || ((_a = core.sourceFeature(d)) === null || _a === void 0 ? void 0 : _a.feature.url.identity) !== coreSpec_1.linkIdentity;
1170
+ }
1171
+ isPrintedType(t) {
1172
+ var _a;
1173
+ if (this.metadata().allFederationTypes().includes(t)) {
1174
+ return false;
1175
+ }
1176
+ if ((0, definitions_1.isObjectType)(t) && t.isQueryRootType() && t.fields().filter((f) => !isFederationField(f)).length === 0) {
1177
+ return false;
1178
+ }
1179
+ const core = this.schema.coreFeatures;
1180
+ return !core || ((_a = core.sourceFeature(t)) === null || _a === void 0 ? void 0 : _a.feature.url.identity) !== coreSpec_1.linkIdentity;
1181
+ }
1182
+ isPrintedDirectiveApplication(d) {
1183
+ if (!this.schema.coreFeatures || d.name !== linkSpec.url.name) {
1184
+ return true;
1185
+ }
1186
+ const args = d.arguments();
1187
+ let urlArg = undefined;
1188
+ if ('url' in args) {
1189
+ try {
1190
+ urlArg = coreSpec_1.FeatureUrl.parse(args['url']);
1191
+ }
1192
+ catch (e) {
1193
+ }
1194
+ }
1195
+ const isDefaultLinkToLink = (urlArg === null || urlArg === void 0 ? void 0 : urlArg.identity) === coreSpec_1.linkIdentity && Object.keys(args).length === 1;
1196
+ return !isDefaultLinkToLink;
1197
+ }
1198
+ toString(basePrintOptions = print_1.defaultPrintOptions) {
1199
+ return (0, print_1.printSchema)(this.schema, {
1200
+ ...basePrintOptions,
1201
+ directiveDefinitionFilter: (d) => this.isPrintedDirective(d),
1202
+ typeFilter: (t) => this.isPrintedType(t),
1203
+ fieldFilter: (f) => !isFederationField(f),
1204
+ directiveApplicationFilter: (d) => this.isPrintedDirectiveApplication(d),
1205
+ });
1206
+ }
1207
+ }
1208
+ exports.Subgraph = Subgraph;
1209
+ function addSubgraphToASTNode(node, subgraph) {
1210
+ if ('subgraph' in node) {
1211
+ return node;
1212
+ }
1213
+ return {
1214
+ ...node,
1215
+ subgraph
1216
+ };
1217
+ }
1218
+ exports.addSubgraphToASTNode = addSubgraphToASTNode;
1219
+ function addSubgraphToError(e, subgraphName, errorCode) {
1220
+ const updatedCauses = (0, error_1.errorCauses)(e).map(cause => {
1221
+ var _a;
1222
+ const message = `[${subgraphName}] ${cause.message}`;
1223
+ const nodes = cause.nodes
1224
+ ? cause.nodes.map(node => addSubgraphToASTNode(node, subgraphName))
1225
+ : undefined;
1226
+ const code = (_a = (0, error_1.errorCodeDef)(cause)) !== null && _a !== void 0 ? _a : errorCode;
1227
+ const options = {
1228
+ ...(0, error_1.extractGraphQLErrorOptions)(cause),
1229
+ nodes,
1230
+ originalError: cause,
1231
+ };
1232
+ return code
1233
+ ? code.err(message, options)
1234
+ : new graphql_1.GraphQLError(message, options);
1235
+ });
1236
+ return updatedCauses.length === 1 ? updatedCauses[0] : (0, definitions_1.ErrGraphQLValidationFailed)(updatedCauses);
1237
+ }
1238
+ exports.addSubgraphToError = addSubgraphToError;
1239
+ class ExternalTester {
1240
+ constructor(schema, isFed2Schema) {
1241
+ this.schema = schema;
1242
+ this.isFed2Schema = isFed2Schema;
1243
+ this.fakeExternalFields = new Set();
1244
+ this.providedFields = new Set();
1245
+ this.externalFieldsOnType = new Set();
1246
+ this.externalDirective = this.metadata().externalDirective();
1247
+ this.collectFakeExternals();
1248
+ this.collectProvidedFields();
1249
+ this.collectExternalsOnType();
1250
+ }
1251
+ metadata() {
1252
+ const metadata = federationMetadata(this.schema);
1253
+ (0, utils_1.assert)(metadata, 'Schema should be a subgraphs schema');
1254
+ return metadata;
1255
+ }
1256
+ collectFakeExternals() {
1257
+ const metadata = this.metadata();
1258
+ const extendsDirective = metadata.extendsDirective();
1259
+ for (const key of metadata.keyDirective().applications()) {
1260
+ const parentType = key.parent;
1261
+ if (!(key.ofExtension() || parentType.hasAppliedDirective(extendsDirective))) {
1262
+ continue;
1263
+ }
1264
+ collectTargetFields({
1265
+ parentType,
1266
+ directive: key,
1267
+ includeInterfaceFieldsImplementations: false,
1268
+ validate: false,
1269
+ }).filter((field) => field.hasAppliedDirective(this.externalDirective))
1270
+ .forEach((field) => this.fakeExternalFields.add(field.coordinate));
1271
+ }
1272
+ }
1273
+ collectProvidedFields() {
1274
+ for (const provides of this.metadata().providesDirective().applications()) {
1275
+ const parent = provides.parent;
1276
+ const parentType = (0, definitions_1.baseType)(parent.type);
1277
+ if ((0, definitions_1.isCompositeType)(parentType)) {
1278
+ collectTargetFields({
1279
+ parentType,
1280
+ directive: provides,
1281
+ includeInterfaceFieldsImplementations: true,
1282
+ validate: false,
1283
+ }).forEach((f) => this.providedFields.add(f.coordinate));
1284
+ }
1285
+ }
1286
+ }
1287
+ collectExternalsOnType() {
1288
+ if (!this.isFed2Schema) {
1289
+ return;
1290
+ }
1291
+ for (const type of this.schema.objectTypes()) {
1292
+ if (type.hasAppliedDirective(this.externalDirective)) {
1293
+ for (const field of type.fields()) {
1294
+ this.externalFieldsOnType.add(field.coordinate);
1295
+ }
1296
+ }
1297
+ }
1298
+ }
1299
+ isExternal(field) {
1300
+ return (field.hasAppliedDirective(this.externalDirective) || this.externalFieldsOnType.has(field.coordinate)) && !this.isFakeExternal(field);
1301
+ }
1302
+ isFakeExternal(field) {
1303
+ return this.fakeExternalFields.has(field.coordinate);
1304
+ }
1305
+ selectsAnyExternalField(selectionSet) {
1306
+ for (const selection of selectionSet.selections()) {
1307
+ if (selection.kind === 'FieldSelection' && this.isExternal(selection.element.definition)) {
1308
+ return true;
1309
+ }
1310
+ if (selection.selectionSet) {
1311
+ if (this.selectsAnyExternalField(selection.selectionSet)) {
1312
+ return true;
1313
+ }
1314
+ }
1315
+ }
1316
+ return false;
1317
+ }
1318
+ isPartiallyExternal(field) {
1319
+ return this.isExternal(field) && this.providedFields.has(field.coordinate);
1320
+ }
1321
+ isFullyExternal(field) {
1322
+ return this.isExternal(field) && !this.providedFields.has(field.coordinate);
1323
+ }
1324
+ }
1325
+ function removeInactiveProvidesAndRequires(schema, onModified = () => { }) {
1326
+ const metadata = federationMetadata(schema);
1327
+ if (!metadata) {
1328
+ return;
1329
+ }
1330
+ const providesDirective = metadata.providesDirective();
1331
+ const requiresDirective = metadata.requiresDirective();
1332
+ for (const type of schema.types()) {
1333
+ if (!(0, definitions_1.isObjectType)(type) && !(0, definitions_1.isInterfaceType)(type)) {
1334
+ continue;
1335
+ }
1336
+ for (const field of type.fields()) {
1337
+ const fieldBaseType = (0, definitions_1.baseType)(field.type);
1338
+ removeInactiveApplications(providesDirective, field, fieldBaseType, onModified);
1339
+ removeInactiveApplications(requiresDirective, field, type, onModified);
1340
+ }
1341
+ }
1342
+ }
1343
+ exports.removeInactiveProvidesAndRequires = removeInactiveProvidesAndRequires;
1344
+ function removeInactiveApplications(directiveDefinition, field, parentType, onModified) {
1345
+ for (const application of field.appliedDirectivesOf(directiveDefinition)) {
1346
+ let selection;
1347
+ try {
1348
+ selection = parseFieldSetArgument({ parentType, directive: application });
1349
+ }
1350
+ catch (e) {
1351
+ continue;
1352
+ }
1353
+ if (selectsNonExternalLeafField(selection)) {
1354
+ application.remove();
1355
+ const updated = withoutNonExternalLeafFields(selection);
1356
+ if (!updated.isEmpty()) {
1357
+ const updatedDirective = field.applyDirective(directiveDefinition, { fields: updated.toString(true, false) });
1358
+ onModified(field, application, updatedDirective);
1359
+ }
1360
+ else {
1361
+ onModified(field, application);
1362
+ }
1363
+ }
1364
+ }
1365
+ }
1366
+ function isExternalOrHasExternalImplementations(field) {
1367
+ const metadata = federationMetadata(field.schema());
1368
+ if (!metadata) {
1369
+ return false;
1370
+ }
1371
+ if (field.hasAppliedDirective(metadata.externalDirective())) {
1372
+ return true;
1373
+ }
1374
+ const parentType = field.parent;
1375
+ if ((0, definitions_1.isInterfaceType)(parentType)) {
1376
+ for (const implem of parentType.possibleRuntimeTypes()) {
1377
+ const fieldInImplem = implem.field(field.name);
1378
+ if (fieldInImplem && fieldInImplem.hasAppliedDirective(metadata.externalDirective())) {
1379
+ return true;
1380
+ }
1381
+ }
1382
+ }
1383
+ return false;
1384
+ }
1385
+ function selectsNonExternalLeafField(selection) {
1386
+ return selection.selections().some(s => {
1387
+ if (s.kind === 'FieldSelection') {
1388
+ if (isExternalOrHasExternalImplementations(s.element.definition)) {
1389
+ return false;
1390
+ }
1391
+ return !s.selectionSet || selectsNonExternalLeafField(s.selectionSet);
1392
+ }
1393
+ else {
1394
+ return selectsNonExternalLeafField(s.selectionSet);
1395
+ }
1396
+ });
1397
+ }
1398
+ function withoutNonExternalLeafFields(selectionSet) {
1399
+ return selectionSet.lazyMap((selection) => {
1400
+ if (selection.kind === 'FieldSelection') {
1401
+ if (isExternalOrHasExternalImplementations(selection.element.definition)) {
1402
+ return selection;
1403
+ }
1404
+ }
1405
+ if (selection.selectionSet) {
1406
+ const updated = withoutNonExternalLeafFields(selection.selectionSet);
1407
+ if (!updated.isEmpty()) {
1408
+ return selection.withUpdatedSelectionSet(updated);
1409
+ }
1410
+ }
1411
+ return undefined;
1412
+ });
1413
+ }
1414
+ //# sourceMappingURL=federation.js.map