@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.
Files changed (109) hide show
  1. package/CHANGELOG.md +32 -3
  2. package/dist/buildSchema.d.ts.map +1 -1
  3. package/dist/buildSchema.js +51 -41
  4. package/dist/buildSchema.js.map +1 -1
  5. package/dist/coreSpec.d.ts +16 -8
  6. package/dist/coreSpec.d.ts.map +1 -1
  7. package/dist/coreSpec.js +205 -53
  8. package/dist/coreSpec.js.map +1 -1
  9. package/dist/definitions.d.ts +28 -11
  10. package/dist/definitions.d.ts.map +1 -1
  11. package/dist/definitions.js +185 -67
  12. package/dist/definitions.js.map +1 -1
  13. package/dist/directiveAndTypeSpecification.d.ts +11 -1
  14. package/dist/directiveAndTypeSpecification.d.ts.map +1 -1
  15. package/dist/directiveAndTypeSpecification.js +77 -20
  16. package/dist/directiveAndTypeSpecification.js.map +1 -1
  17. package/dist/error.d.ts +17 -0
  18. package/dist/error.d.ts.map +1 -1
  19. package/dist/error.js +54 -2
  20. package/dist/error.js.map +1 -1
  21. package/dist/extractSubgraphsFromSupergraph.d.ts.map +1 -1
  22. package/dist/extractSubgraphsFromSupergraph.js +7 -1
  23. package/dist/extractSubgraphsFromSupergraph.js.map +1 -1
  24. package/dist/federation.d.ts +22 -5
  25. package/dist/federation.d.ts.map +1 -1
  26. package/dist/federation.js +143 -86
  27. package/dist/federation.js.map +1 -1
  28. package/dist/federationSpec.d.ts +6 -2
  29. package/dist/federationSpec.d.ts.map +1 -1
  30. package/dist/federationSpec.js +47 -22
  31. package/dist/federationSpec.js.map +1 -1
  32. package/dist/inaccessibleSpec.d.ts +10 -2
  33. package/dist/inaccessibleSpec.d.ts.map +1 -1
  34. package/dist/inaccessibleSpec.js +634 -16
  35. package/dist/inaccessibleSpec.js.map +1 -1
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/introspection.d.ts.map +1 -1
  41. package/dist/introspection.js +8 -3
  42. package/dist/introspection.js.map +1 -1
  43. package/dist/joinSpec.d.ts +5 -1
  44. package/dist/joinSpec.d.ts.map +1 -1
  45. package/dist/joinSpec.js +21 -0
  46. package/dist/joinSpec.js.map +1 -1
  47. package/dist/knownCoreFeatures.d.ts +4 -0
  48. package/dist/knownCoreFeatures.d.ts.map +1 -0
  49. package/dist/knownCoreFeatures.js +16 -0
  50. package/dist/knownCoreFeatures.js.map +1 -0
  51. package/dist/operations.d.ts +1 -0
  52. package/dist/operations.d.ts.map +1 -1
  53. package/dist/operations.js +16 -1
  54. package/dist/operations.js.map +1 -1
  55. package/dist/{sharing.d.ts → precompute.d.ts} +1 -1
  56. package/dist/precompute.d.ts.map +1 -0
  57. package/dist/{sharing.js → precompute.js} +3 -3
  58. package/dist/precompute.js.map +1 -0
  59. package/dist/schemaUpgrader.d.ts.map +1 -1
  60. package/dist/schemaUpgrader.js +17 -7
  61. package/dist/schemaUpgrader.js.map +1 -1
  62. package/dist/suggestions.d.ts +1 -1
  63. package/dist/suggestions.d.ts.map +1 -1
  64. package/dist/suggestions.js.map +1 -1
  65. package/dist/supergraphs.d.ts.map +1 -1
  66. package/dist/supergraphs.js +2 -0
  67. package/dist/supergraphs.js.map +1 -1
  68. package/dist/tagSpec.d.ts +7 -2
  69. package/dist/tagSpec.d.ts.map +1 -1
  70. package/dist/tagSpec.js +35 -14
  71. package/dist/tagSpec.js.map +1 -1
  72. package/dist/validate.js +13 -7
  73. package/dist/validate.js.map +1 -1
  74. package/dist/values.d.ts +2 -2
  75. package/dist/values.d.ts.map +1 -1
  76. package/dist/values.js +13 -11
  77. package/dist/values.js.map +1 -1
  78. package/package.json +4 -4
  79. package/src/__tests__/coreSpec.test.ts +212 -0
  80. package/src/__tests__/definitions.test.ts +75 -0
  81. package/src/__tests__/removeInaccessibleElements.test.ts +2229 -137
  82. package/src/__tests__/schemaUpgrader.test.ts +3 -2
  83. package/src/__tests__/subgraphValidation.test.ts +419 -4
  84. package/src/__tests__/values.test.ts +315 -3
  85. package/src/buildSchema.ts +98 -51
  86. package/src/coreSpec.ts +277 -65
  87. package/src/definitions.ts +317 -92
  88. package/src/directiveAndTypeSpecification.ts +98 -21
  89. package/src/error.ts +119 -1
  90. package/src/extractSubgraphsFromSupergraph.ts +7 -1
  91. package/src/federation.ts +184 -102
  92. package/src/federationSpec.ts +56 -24
  93. package/src/inaccessibleSpec.ts +985 -39
  94. package/src/index.ts +2 -0
  95. package/src/introspection.ts +8 -3
  96. package/src/joinSpec.ts +33 -3
  97. package/src/knownCoreFeatures.ts +13 -0
  98. package/src/operations.ts +15 -0
  99. package/src/{sharing.ts → precompute.ts} +3 -6
  100. package/src/schemaUpgrader.ts +29 -13
  101. package/src/suggestions.ts +1 -1
  102. package/src/supergraphs.ts +2 -0
  103. package/src/tagSpec.ts +49 -16
  104. package/src/validate.ts +20 -9
  105. package/src/values.ts +39 -12
  106. package/tsconfig.test.tsbuildinfo +1 -1
  107. package/tsconfig.tsbuildinfo +1 -1
  108. package/dist/sharing.d.ts.map +0 -1
  109. package/dist/sharing.js.map +0 -1
@@ -4,22 +4,61 @@ exports.removeInaccessibleElements = exports.INACCESSIBLE_VERSIONS = exports.Ina
4
4
  const coreSpec_1 = require("./coreSpec");
5
5
  const definitions_1 = require("./definitions");
6
6
  const graphql_1 = require("graphql");
7
+ const knownCoreFeatures_1 = require("./knownCoreFeatures");
8
+ const error_1 = require("./error");
9
+ const directiveAndTypeSpecification_1 = require("./directiveAndTypeSpecification");
10
+ const utils_1 = require("./utils");
7
11
  exports.inaccessibleIdentity = 'https://specs.apollo.dev/inaccessible';
8
12
  class InaccessibleSpecDefinition extends coreSpec_1.FeatureDefinition {
9
13
  constructor(version) {
10
14
  super(new coreSpec_1.FeatureUrl(exports.inaccessibleIdentity, 'inaccessible', version));
15
+ this.inaccessibleLocations = [
16
+ graphql_1.DirectiveLocation.FIELD_DEFINITION,
17
+ graphql_1.DirectiveLocation.OBJECT,
18
+ graphql_1.DirectiveLocation.INTERFACE,
19
+ graphql_1.DirectiveLocation.UNION,
20
+ ];
21
+ this.printedInaccessibleDefinition = 'directive @inaccessible on FIELD_DEFINITION | INTERFACE | OBJECT | UNION';
22
+ if (!this.isV01()) {
23
+ this.inaccessibleLocations.push(graphql_1.DirectiveLocation.ARGUMENT_DEFINITION, graphql_1.DirectiveLocation.SCALAR, graphql_1.DirectiveLocation.ENUM, graphql_1.DirectiveLocation.ENUM_VALUE, graphql_1.DirectiveLocation.INPUT_OBJECT, graphql_1.DirectiveLocation.INPUT_FIELD_DEFINITION);
24
+ this.printedInaccessibleDefinition = 'directive @inaccessible on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION';
25
+ }
26
+ this.inaccessibleDirectiveSpec = (0, directiveAndTypeSpecification_1.createDirectiveSpecification)({
27
+ name: 'inaccessible',
28
+ locations: this.inaccessibleLocations,
29
+ });
30
+ }
31
+ isV01() {
32
+ return this.version.equals(new coreSpec_1.FeatureVersion(0, 1));
11
33
  }
12
34
  addElementsToSchema(schema) {
13
- this.addDirective(schema, 'inaccessible').addLocations(graphql_1.DirectiveLocation.FIELD_DEFINITION, graphql_1.DirectiveLocation.OBJECT, graphql_1.DirectiveLocation.INTERFACE, graphql_1.DirectiveLocation.UNION);
35
+ return this.addDirectiveSpec(schema, this.inaccessibleDirectiveSpec);
14
36
  }
15
37
  inaccessibleDirective(schema) {
16
38
  return this.directive(schema, 'inaccessible');
17
39
  }
40
+ checkCompatibleDirective(definition) {
41
+ const hasUnknownArguments = Object.keys(definition.arguments()).length > 0;
42
+ const hasRepeatable = definition.repeatable;
43
+ const hasValidLocations = definition.locations.every(loc => this.inaccessibleLocations.includes(loc));
44
+ if (hasUnknownArguments || hasRepeatable || !hasValidLocations) {
45
+ return error_1.ERRORS.DIRECTIVE_DEFINITION_INVALID.err({
46
+ message: `Found invalid @inaccessible directive definition. Please ensure the directive definition in your schema's definitions matches the following:\n\t${this.printedInaccessibleDefinition}`,
47
+ });
48
+ }
49
+ return undefined;
50
+ }
51
+ allElementNames() {
52
+ return ['@inaccessible'];
53
+ }
18
54
  }
19
55
  exports.InaccessibleSpecDefinition = InaccessibleSpecDefinition;
20
56
  exports.INACCESSIBLE_VERSIONS = new coreSpec_1.FeatureDefinitions(exports.inaccessibleIdentity)
21
- .add(new InaccessibleSpecDefinition(new coreSpec_1.FeatureVersion(0, 1)));
57
+ .add(new InaccessibleSpecDefinition(new coreSpec_1.FeatureVersion(0, 1)))
58
+ .add(new InaccessibleSpecDefinition(new coreSpec_1.FeatureVersion(0, 2)));
59
+ (0, knownCoreFeatures_1.registerKnownFeature)(exports.INACCESSIBLE_VERSIONS);
22
60
  function removeInaccessibleElements(schema) {
61
+ schema.validate();
23
62
  const coreFeatures = schema.coreFeatures;
24
63
  if (!coreFeatures) {
25
64
  return;
@@ -30,31 +69,610 @@ function removeInaccessibleElements(schema) {
30
69
  }
31
70
  const inaccessibleSpec = exports.INACCESSIBLE_VERSIONS.find(inaccessibleFeature.url.version);
32
71
  if (!inaccessibleSpec) {
33
- throw new graphql_1.GraphQLError(`Cannot remove inaccessible elements: the schema uses unsupported inaccessible spec version ${inaccessibleFeature.url.version} (supported versions: ${exports.INACCESSIBLE_VERSIONS.versions().join(', ')})`);
72
+ throw (0, definitions_1.ErrGraphQLAPISchemaValidationFailed)([new graphql_1.GraphQLError(`Cannot remove inaccessible elements: the schema uses unsupported` +
73
+ ` inaccessible spec version ${inaccessibleFeature.url.version}` +
74
+ ` (supported versions: ${exports.INACCESSIBLE_VERSIONS.versions().join(', ')})`)]);
34
75
  }
35
76
  const inaccessibleDirective = inaccessibleSpec.inaccessibleDirective(schema);
36
77
  if (!inaccessibleDirective) {
37
- throw new graphql_1.GraphQLError(`Invalid schema: declares ${inaccessibleSpec.url} spec but does not define a @inaccessible directive`);
78
+ throw (0, definitions_1.ErrGraphQLAPISchemaValidationFailed)([new graphql_1.GraphQLError(`Invalid schema: declares ${inaccessibleSpec.url} spec but does not` +
79
+ ` define a @inaccessible directive.`)]);
38
80
  }
39
- for (const type of schema.types()) {
40
- if (!(0, definitions_1.isCompositeType)(type)) {
81
+ const incompatibleError = inaccessibleSpec.checkCompatibleDirective(inaccessibleDirective);
82
+ if (incompatibleError) {
83
+ throw (0, definitions_1.ErrGraphQLAPISchemaValidationFailed)([incompatibleError]);
84
+ }
85
+ validateInaccessibleElements(schema, coreFeatures, inaccessibleSpec, inaccessibleDirective);
86
+ removeInaccessibleElementsAssumingValid(schema, inaccessibleDirective);
87
+ }
88
+ exports.removeInaccessibleElements = removeInaccessibleElements;
89
+ function validateInaccessibleElements(schema, coreFeatures, inaccessibleSpec, inaccessibleDirective) {
90
+ var _a, _b, _c;
91
+ function isInaccessible(element) {
92
+ return element.hasAppliedDirective(inaccessibleDirective);
93
+ }
94
+ const featureList = [...coreFeatures.allFeatures()];
95
+ function isFeatureDefinition(element) {
96
+ return featureList.some((feature) => feature.isFeatureDefinition(element));
97
+ }
98
+ function isInAPISchema(element) {
99
+ if (!(element instanceof definitions_1.DirectiveDefinition) &&
100
+ isInaccessible(element))
101
+ return false;
102
+ if ((element instanceof definitions_1.ObjectType) ||
103
+ (element instanceof definitions_1.InterfaceType) ||
104
+ (element instanceof definitions_1.UnionType) ||
105
+ (element instanceof definitions_1.ScalarType) ||
106
+ (element instanceof definitions_1.EnumType) ||
107
+ (element instanceof definitions_1.InputObjectType) ||
108
+ (element instanceof definitions_1.DirectiveDefinition)) {
109
+ return !isFeatureDefinition(element);
110
+ }
111
+ else if ((element instanceof definitions_1.FieldDefinition) ||
112
+ (element instanceof definitions_1.ArgumentDefinition) ||
113
+ (element instanceof definitions_1.InputFieldDefinition) ||
114
+ (element instanceof definitions_1.EnumValue)) {
115
+ return isInAPISchema(element.parent);
116
+ }
117
+ (0, utils_1.assert)(false, "Unreachable code, element is of unknown type.");
118
+ }
119
+ function fetchInaccessibleElementsDeep(element) {
120
+ const inaccessibleElements = [];
121
+ if (isInaccessible(element)) {
122
+ inaccessibleElements.push(element);
123
+ }
124
+ if ((element instanceof definitions_1.ObjectType) ||
125
+ (element instanceof definitions_1.InterfaceType) ||
126
+ (element instanceof definitions_1.InputObjectType)) {
127
+ for (const field of element.fields()) {
128
+ inaccessibleElements.push(...fetchInaccessibleElementsDeep(field));
129
+ }
130
+ return inaccessibleElements;
131
+ }
132
+ else if (element instanceof definitions_1.EnumType) {
133
+ for (const enumValue of element.values) {
134
+ inaccessibleElements.push(...fetchInaccessibleElementsDeep(enumValue));
135
+ }
136
+ return inaccessibleElements;
137
+ }
138
+ else if ((element instanceof definitions_1.DirectiveDefinition) ||
139
+ (element instanceof definitions_1.FieldDefinition)) {
140
+ for (const argument of element.arguments()) {
141
+ inaccessibleElements.push(...fetchInaccessibleElementsDeep(argument));
142
+ }
143
+ return inaccessibleElements;
144
+ }
145
+ else if ((element instanceof definitions_1.UnionType) ||
146
+ (element instanceof definitions_1.ScalarType) ||
147
+ (element instanceof definitions_1.ArgumentDefinition) ||
148
+ (element instanceof definitions_1.InputFieldDefinition) ||
149
+ (element instanceof definitions_1.EnumValue)) {
150
+ return inaccessibleElements;
151
+ }
152
+ (0, utils_1.assert)(false, "Unreachable code, element is of unknown type.");
153
+ }
154
+ const errors = [];
155
+ let defaultValueReferencers = undefined;
156
+ if (!inaccessibleSpec.isV01()) {
157
+ defaultValueReferencers = computeDefaultValueReferencers(schema);
158
+ }
159
+ for (const type of schema.allTypes()) {
160
+ if (hasBuiltInName(type)) {
161
+ const inaccessibleElements = fetchInaccessibleElementsDeep(type);
162
+ if (inaccessibleElements.length > 0) {
163
+ errors.push(error_1.ERRORS.DISALLOWED_INACCESSIBLE.err({
164
+ message: `Built-in type "${type.coordinate}" cannot use @inaccessible.`,
165
+ nodes: type.sourceAST,
166
+ extensions: {
167
+ inaccessible_elements: inaccessibleElements
168
+ .map((element) => element.coordinate),
169
+ inaccessible_referencers: [type.coordinate],
170
+ }
171
+ }));
172
+ }
173
+ }
174
+ else if (isFeatureDefinition(type)) {
175
+ const inaccessibleElements = fetchInaccessibleElementsDeep(type);
176
+ if (inaccessibleElements.length > 0) {
177
+ errors.push(error_1.ERRORS.DISALLOWED_INACCESSIBLE.err({
178
+ message: `Core feature type "${type.coordinate}" cannot use @inaccessible.`,
179
+ nodes: type.sourceAST,
180
+ extensions: {
181
+ inaccessible_elements: inaccessibleElements
182
+ .map((element) => element.coordinate),
183
+ inaccessible_referencers: [type.coordinate],
184
+ }
185
+ }));
186
+ }
187
+ }
188
+ else if (isInaccessible(type)) {
189
+ const referencers = type.referencers();
190
+ for (const referencer of referencers) {
191
+ if (referencer instanceof definitions_1.FieldDefinition ||
192
+ referencer instanceof definitions_1.ArgumentDefinition ||
193
+ referencer instanceof definitions_1.InputFieldDefinition) {
194
+ if (isInAPISchema(referencer)) {
195
+ errors.push(error_1.ERRORS.REFERENCED_INACCESSIBLE.err({
196
+ message: `Type "${type.coordinate}" is @inaccessible but is referenced` +
197
+ ` by "${referencer.coordinate}", which is in the API schema.`,
198
+ nodes: type.sourceAST,
199
+ extensions: {
200
+ inaccessible_elements: [type.coordinate],
201
+ inaccessible_referencers: [referencer.coordinate],
202
+ }
203
+ }));
204
+ }
205
+ }
206
+ else if (referencer instanceof definitions_1.SchemaDefinition) {
207
+ if (type === referencer.rootType('query')) {
208
+ errors.push(error_1.ERRORS.QUERY_ROOT_TYPE_INACCESSIBLE.err({
209
+ message: `Type "${type.coordinate}" is @inaccessible but is the root` +
210
+ ` query type, which must be in the API schema.`,
211
+ nodes: type.sourceAST,
212
+ extensions: {
213
+ inaccessible_elements: [type.coordinate],
214
+ }
215
+ }));
216
+ }
217
+ }
218
+ }
219
+ }
220
+ else {
221
+ if ((type instanceof definitions_1.ObjectType) ||
222
+ (type instanceof definitions_1.InterfaceType) ||
223
+ (type instanceof definitions_1.InputObjectType)) {
224
+ let isEmpty = true;
225
+ for (const field of type.fields()) {
226
+ if (!isInaccessible(field))
227
+ isEmpty = false;
228
+ }
229
+ if (isEmpty) {
230
+ errors.push(error_1.ERRORS.ONLY_INACCESSIBLE_CHILDREN.err({
231
+ message: `Type "${type.coordinate}" is in the API schema but all of its` +
232
+ ` ${(type instanceof definitions_1.InputObjectType) ? 'input ' : ''}fields` +
233
+ ` are @inaccessible.`,
234
+ nodes: type.sourceAST,
235
+ extensions: {
236
+ inaccessible_elements: type.fields()
237
+ .map((field) => field.coordinate),
238
+ inaccessible_referencers: [type.coordinate],
239
+ }
240
+ }));
241
+ }
242
+ }
243
+ else if (type instanceof definitions_1.UnionType) {
244
+ let isEmpty = true;
245
+ for (const member of type.types()) {
246
+ if (!isInaccessible(member))
247
+ isEmpty = false;
248
+ }
249
+ if (isEmpty) {
250
+ errors.push(error_1.ERRORS.ONLY_INACCESSIBLE_CHILDREN.err({
251
+ message: `Type "${type.coordinate}" is in the API schema but all of its` +
252
+ ` members are @inaccessible.`,
253
+ nodes: type.sourceAST,
254
+ extensions: {
255
+ inaccessible_elements: type.types()
256
+ .map((type) => type.coordinate),
257
+ inaccessible_referencers: [type.coordinate],
258
+ }
259
+ }));
260
+ }
261
+ }
262
+ else if (type instanceof definitions_1.EnumType) {
263
+ let isEmpty = true;
264
+ for (const enumValue of type.values) {
265
+ if (!isInaccessible(enumValue))
266
+ isEmpty = false;
267
+ }
268
+ if (isEmpty) {
269
+ errors.push(error_1.ERRORS.ONLY_INACCESSIBLE_CHILDREN.err({
270
+ message: `Type "${type.coordinate}" is in the API schema but all of its` +
271
+ ` values are @inaccessible.`,
272
+ nodes: type.sourceAST,
273
+ extensions: {
274
+ inaccessible_elements: type.values
275
+ .map((enumValue) => enumValue.coordinate),
276
+ inaccessible_referencers: [type.coordinate],
277
+ }
278
+ }));
279
+ }
280
+ }
281
+ if ((type instanceof definitions_1.ObjectType) ||
282
+ (type instanceof definitions_1.InterfaceType)) {
283
+ const implementedInterfaces = type.interfaces();
284
+ const implementingTypes = [];
285
+ if (type instanceof definitions_1.InterfaceType) {
286
+ for (const referencer of type.referencers()) {
287
+ if ((referencer instanceof definitions_1.ObjectType) ||
288
+ (referencer instanceof definitions_1.InterfaceType)) {
289
+ implementingTypes.push(referencer);
290
+ }
291
+ }
292
+ }
293
+ for (const field of type.fields()) {
294
+ if (isInaccessible(field)) {
295
+ for (const implementedInterface of implementedInterfaces) {
296
+ const implementedField = implementedInterface.field(field.name);
297
+ if (implementedField && isInAPISchema(implementedField)) {
298
+ errors.push(error_1.ERRORS.IMPLEMENTED_BY_INACCESSIBLE.err({
299
+ message: `Field "${field.coordinate}" is @inaccessible but` +
300
+ ` implements the interface field` +
301
+ ` "${implementedField.coordinate}", which is in the API` +
302
+ ` schema.`,
303
+ nodes: field.sourceAST,
304
+ extensions: {
305
+ inaccessible_elements: [field.coordinate],
306
+ inaccessible_referencers: [implementedField.coordinate],
307
+ }
308
+ }));
309
+ }
310
+ }
311
+ }
312
+ else {
313
+ for (const argument of field.arguments()) {
314
+ if (isInaccessible(argument)) {
315
+ if (argument.isRequired()) {
316
+ errors.push(error_1.ERRORS.REQUIRED_INACCESSIBLE.err({
317
+ message: `Argument "${argument.coordinate}" is @inaccessible but` +
318
+ ` is a required argument of its field.`,
319
+ nodes: argument.sourceAST,
320
+ extensions: {
321
+ inaccessible_elements: [argument.coordinate],
322
+ inaccessible_referencers: [argument.coordinate],
323
+ }
324
+ }));
325
+ }
326
+ for (const implementingType of implementingTypes) {
327
+ const implementingField = implementingType.field(field.name);
328
+ (0, utils_1.assert)(implementingField, "Schema should have been valid, but an implementing type" +
329
+ " did not implement one of this type's fields.");
330
+ const implementingArgument = implementingField
331
+ .argument(argument.name);
332
+ (0, utils_1.assert)(implementingArgument, "Schema should have been valid, but an implementing type" +
333
+ " did not implement one of this type's field's arguments.");
334
+ if (isInAPISchema(implementingArgument) &&
335
+ implementingArgument.isRequired()) {
336
+ errors.push(error_1.ERRORS.REQUIRED_INACCESSIBLE.err({
337
+ message: `Argument "${argument.coordinate}" is @inaccessible` +
338
+ ` but is implemented by the required argument` +
339
+ ` "${implementingArgument.coordinate}", which is` +
340
+ ` in the API schema.`,
341
+ nodes: argument.sourceAST,
342
+ extensions: {
343
+ inaccessible_elements: [argument.coordinate],
344
+ inaccessible_referencers: [
345
+ implementingArgument.coordinate,
346
+ ],
347
+ }
348
+ }));
349
+ }
350
+ }
351
+ for (const implementedInterface of implementedInterfaces) {
352
+ const implementedArgument = (_a = implementedInterface
353
+ .field(field.name)) === null || _a === void 0 ? void 0 : _a.argument(argument.name);
354
+ if (implementedArgument &&
355
+ isInAPISchema(implementedArgument)) {
356
+ errors.push(error_1.ERRORS.IMPLEMENTED_BY_INACCESSIBLE.err({
357
+ message: `Argument "${argument.coordinate}" is @inaccessible` +
358
+ ` but implements the interface argument` +
359
+ ` "${implementedArgument.coordinate}", which is in` +
360
+ ` the API schema.`,
361
+ nodes: argument.sourceAST,
362
+ extensions: {
363
+ inaccessible_elements: [argument.coordinate],
364
+ inaccessible_referencers: [
365
+ implementedArgument.coordinate,
366
+ ],
367
+ }
368
+ }));
369
+ }
370
+ }
371
+ }
372
+ }
373
+ }
374
+ }
375
+ }
376
+ else if (type instanceof definitions_1.InputObjectType) {
377
+ for (const inputField of type.fields()) {
378
+ if (isInaccessible(inputField)) {
379
+ if (inputField.isRequired()) {
380
+ errors.push(error_1.ERRORS.REQUIRED_INACCESSIBLE.err({
381
+ message: `Input field "${inputField.coordinate}" is @inaccessible` +
382
+ ` but is a required input field of its type.`,
383
+ nodes: inputField.sourceAST,
384
+ extensions: {
385
+ inaccessible_elements: [inputField.coordinate],
386
+ inaccessible_referencers: [inputField.coordinate],
387
+ }
388
+ }));
389
+ }
390
+ (0, utils_1.assert)(defaultValueReferencers, "Input fields can't be @inaccessible in v0.1, but default value" +
391
+ " referencers weren't computed (which is only skipped for v0.1).");
392
+ const referencers = (_b = defaultValueReferencers.get(inputField)) !== null && _b !== void 0 ? _b : [];
393
+ for (const referencer of referencers) {
394
+ if (isInAPISchema(referencer)) {
395
+ errors.push(error_1.ERRORS.DEFAULT_VALUE_USES_INACCESSIBLE.err({
396
+ message: `Input field "${inputField.coordinate}" is @inaccessible` +
397
+ ` but is used in the default value of` +
398
+ ` "${referencer.coordinate}", which is in the API schema.`,
399
+ nodes: type.sourceAST,
400
+ extensions: {
401
+ inaccessible_elements: [type.coordinate],
402
+ inaccessible_referencers: [referencer.coordinate],
403
+ }
404
+ }));
405
+ }
406
+ }
407
+ }
408
+ }
409
+ }
410
+ else if (type instanceof definitions_1.EnumType) {
411
+ for (const enumValue of type.values) {
412
+ if (isInaccessible(enumValue)) {
413
+ (0, utils_1.assert)(defaultValueReferencers, "Enum values can't be @inaccessible in v0.1, but default value" +
414
+ " referencers weren't computed (which is only skipped for v0.1).");
415
+ const referencers = (_c = defaultValueReferencers.get(enumValue)) !== null && _c !== void 0 ? _c : [];
416
+ for (const referencer of referencers) {
417
+ if (isInAPISchema(referencer)) {
418
+ errors.push(error_1.ERRORS.DEFAULT_VALUE_USES_INACCESSIBLE.err({
419
+ message: `Enum value "${enumValue.coordinate}" is @inaccessible` +
420
+ ` but is used in the default value of` +
421
+ ` "${referencer.coordinate}", which is in the API schema.`,
422
+ nodes: type.sourceAST,
423
+ extensions: {
424
+ inaccessible_elements: [type.coordinate],
425
+ inaccessible_referencers: [referencer.coordinate],
426
+ }
427
+ }));
428
+ }
429
+ }
430
+ }
431
+ }
432
+ }
433
+ }
434
+ }
435
+ const executableDirectiveLocationSet = new Set(definitions_1.executableDirectiveLocations);
436
+ for (const directive of schema.allDirectives()) {
437
+ const typeSystemLocations = directive.locations.filter((loc) => !executableDirectiveLocationSet.has(loc));
438
+ if (hasBuiltInName(directive)) {
439
+ const inaccessibleElements = fetchInaccessibleElementsDeep(directive);
440
+ if (inaccessibleElements.length > 0) {
441
+ errors.push(error_1.ERRORS.DISALLOWED_INACCESSIBLE.err({
442
+ message: `Built-in directive "${directive.coordinate}" cannot use` +
443
+ ` @inaccessible.`,
444
+ nodes: directive.sourceAST,
445
+ extensions: {
446
+ inaccessible_elements: inaccessibleElements
447
+ .map((element) => element.coordinate),
448
+ inaccessible_referencers: [directive.coordinate],
449
+ }
450
+ }));
451
+ }
452
+ }
453
+ else if (isFeatureDefinition(directive)) {
454
+ const inaccessibleElements = fetchInaccessibleElementsDeep(directive);
455
+ if (inaccessibleElements.length > 0) {
456
+ errors.push(error_1.ERRORS.DISALLOWED_INACCESSIBLE.err({
457
+ message: `Core feature directive "${directive.coordinate}" cannot use` +
458
+ ` @inaccessible.`,
459
+ nodes: directive.sourceAST,
460
+ extensions: {
461
+ inaccessible_elements: inaccessibleElements
462
+ .map((element) => element.coordinate),
463
+ inaccessible_referencers: [directive.coordinate],
464
+ }
465
+ }));
466
+ }
467
+ }
468
+ else if (typeSystemLocations.length > 0) {
469
+ const inaccessibleElements = fetchInaccessibleElementsDeep(directive);
470
+ if (inaccessibleElements.length > 0) {
471
+ errors.push(error_1.ERRORS.DISALLOWED_INACCESSIBLE.err({
472
+ message: `Directive "${directive.coordinate}" cannot use @inaccessible` +
473
+ ` because it may be applied to these type-system locations:` +
474
+ ` ${typeSystemLocations.join(', ')}.`,
475
+ nodes: directive.sourceAST,
476
+ extensions: {
477
+ inaccessible_elements: inaccessibleElements
478
+ .map((element) => element.coordinate),
479
+ inaccessible_referencers: [directive.coordinate],
480
+ }
481
+ }));
482
+ }
483
+ }
484
+ else {
485
+ for (const argument of directive.arguments()) {
486
+ if (argument.isRequired()) {
487
+ if (isInaccessible(argument)) {
488
+ errors.push(error_1.ERRORS.REQUIRED_INACCESSIBLE.err({
489
+ message: `Argument "${argument.coordinate}" is @inaccessible but is a` +
490
+ ` required argument of its directive.`,
491
+ nodes: argument.sourceAST,
492
+ extensions: {
493
+ inaccessible_elements: [argument.coordinate],
494
+ inaccessible_referencers: [argument.coordinate],
495
+ }
496
+ }));
497
+ }
498
+ }
499
+ }
500
+ }
501
+ }
502
+ if (errors.length > 0) {
503
+ throw (0, definitions_1.ErrGraphQLAPISchemaValidationFailed)(errors);
504
+ }
505
+ }
506
+ function computeDefaultValueReferencers(schema) {
507
+ const referencers = new Map();
508
+ function addReference(reference, referencer) {
509
+ var _a;
510
+ const referencerList = (_a = referencers.get(reference)) !== null && _a !== void 0 ? _a : [];
511
+ if (referencerList.length === 0) {
512
+ referencers.set(reference, referencerList);
513
+ }
514
+ referencerList.push(referencer);
515
+ }
516
+ for (const type of schema.allTypes()) {
517
+ if (hasBuiltInName(type))
518
+ continue;
519
+ if ((type instanceof definitions_1.ObjectType) ||
520
+ (type instanceof definitions_1.InterfaceType)) {
521
+ for (const field of type.fields()) {
522
+ for (const argument of field.arguments()) {
523
+ for (const reference of computeDefaultValueReferences(argument)) {
524
+ addReference(reference, argument);
525
+ }
526
+ }
527
+ }
528
+ }
529
+ if (type instanceof definitions_1.InputObjectType) {
530
+ for (const inputField of type.fields()) {
531
+ for (const reference of computeDefaultValueReferences(inputField)) {
532
+ addReference(reference, inputField);
533
+ }
534
+ }
535
+ }
536
+ }
537
+ for (const directive of schema.allDirectives()) {
538
+ if (hasBuiltInName(directive))
41
539
  continue;
540
+ for (const argument of directive.arguments()) {
541
+ for (const reference of computeDefaultValueReferences(argument)) {
542
+ addReference(reference, argument);
543
+ }
544
+ }
545
+ }
546
+ return referencers;
547
+ }
548
+ function computeDefaultValueReferences(element) {
549
+ const references = [];
550
+ addValueReferences(element.defaultValue, getInputType(element), references);
551
+ return references;
552
+ }
553
+ function getInputType(element) {
554
+ const type = element.type;
555
+ (0, utils_1.assert)(type, "Schema should have been valid, but argument/input field did not have type.");
556
+ return type;
557
+ }
558
+ function addValueReferences(value, type, references) {
559
+ if (value === undefined || value === null) {
560
+ return;
561
+ }
562
+ if ((0, definitions_1.isNonNullType)(type)) {
563
+ return addValueReferences(value, type.ofType, references);
564
+ }
565
+ if ((0, definitions_1.isScalarType)(type)) {
566
+ return;
567
+ }
568
+ if ((0, definitions_1.isVariable)(value)) {
569
+ return;
570
+ }
571
+ if (Array.isArray(value)) {
572
+ if ((0, definitions_1.isListType)(type)) {
573
+ const itemType = type.ofType;
574
+ for (const item of value) {
575
+ addValueReferences(item, itemType, references);
576
+ }
577
+ }
578
+ else {
42
579
  }
43
- if (type.hasAppliedDirective(inaccessibleDirective)) {
44
- const references = type.remove();
45
- for (const reference of references) {
46
- if (reference.kind === 'FieldDefinition') {
47
- if (!reference.hasAppliedDirective(inaccessibleDirective)) {
48
- throw new graphql_1.GraphQLError(`Field ${reference.coordinate} returns an @inaccessible type without being marked @inaccessible itself.`, reference.sourceAST);
580
+ return;
581
+ }
582
+ if ((0, definitions_1.isListType)(type)) {
583
+ return addValueReferences(value, type.ofType, references);
584
+ }
585
+ if (typeof value === 'object') {
586
+ if ((0, definitions_1.isInputObjectType)(type)) {
587
+ for (const field of type.fields()) {
588
+ const fieldValue = value[field.name];
589
+ if (fieldValue !== undefined) {
590
+ references.push(field);
591
+ addValueReferences(fieldValue, field.type, references);
592
+ }
593
+ else {
594
+ }
595
+ }
596
+ }
597
+ else {
598
+ }
599
+ return;
600
+ }
601
+ if (typeof value === 'string') {
602
+ if ((0, definitions_1.isEnumType)(type)) {
603
+ const enumValue = type.value(value);
604
+ if (enumValue !== undefined) {
605
+ references.push(enumValue);
606
+ }
607
+ else {
608
+ }
609
+ }
610
+ else {
611
+ }
612
+ return;
613
+ }
614
+ return;
615
+ }
616
+ function hasBuiltInName(element) {
617
+ const schema = element.schema();
618
+ if ((element instanceof definitions_1.ObjectType) ||
619
+ (element instanceof definitions_1.InterfaceType) ||
620
+ (element instanceof definitions_1.UnionType) ||
621
+ (element instanceof definitions_1.ScalarType) ||
622
+ (element instanceof definitions_1.EnumType) ||
623
+ (element instanceof definitions_1.InputObjectType)) {
624
+ return schema.builtInTypes(true).some((type) => type.name === element.name);
625
+ }
626
+ else if (element instanceof definitions_1.DirectiveDefinition) {
627
+ return schema.builtInDirectives(true).some((directive) => directive.name === element.name);
628
+ }
629
+ (0, utils_1.assert)(false, "Unreachable code, element is of unknown type.");
630
+ }
631
+ function removeInaccessibleElementsAssumingValid(schema, inaccessibleDirective) {
632
+ function isInaccessible(element) {
633
+ return element.hasAppliedDirective(inaccessibleDirective);
634
+ }
635
+ for (const type of schema.types()) {
636
+ if (isInaccessible(type)) {
637
+ type.remove();
638
+ }
639
+ else {
640
+ if ((type instanceof definitions_1.ObjectType) || (type instanceof definitions_1.InterfaceType)) {
641
+ for (const field of type.fields()) {
642
+ if (isInaccessible(field)) {
643
+ field.remove();
644
+ }
645
+ else {
646
+ for (const argument of field.arguments()) {
647
+ if (isInaccessible(argument)) {
648
+ argument.remove();
649
+ }
650
+ }
651
+ }
652
+ }
653
+ }
654
+ else if (type instanceof definitions_1.InputObjectType) {
655
+ for (const inputField of type.fields()) {
656
+ if (isInaccessible(inputField)) {
657
+ inputField.remove();
658
+ }
659
+ }
660
+ }
661
+ else if (type instanceof definitions_1.EnumType) {
662
+ for (const enumValue of type.values) {
663
+ if (isInaccessible(enumValue)) {
664
+ enumValue.remove();
49
665
  }
50
666
  }
51
667
  }
52
668
  }
53
- else if ((0, definitions_1.isObjectType)(type) || (0, definitions_1.isInterfaceType)(type)) {
54
- const toRemove = type.fields().filter(f => f.hasAppliedDirective(inaccessibleDirective));
55
- toRemove.forEach(f => f.remove());
669
+ }
670
+ for (const directive of schema.directives()) {
671
+ for (const argument of directive.arguments()) {
672
+ if (isInaccessible(argument)) {
673
+ argument.remove();
674
+ }
56
675
  }
57
676
  }
58
677
  }
59
- exports.removeInaccessibleElements = removeInaccessibleElements;
60
678
  //# sourceMappingURL=inaccessibleSpec.js.map