@apollo/federation-internals 2.0.6-rc.0 → 2.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/buildSchema.d.ts.map +1 -1
- package/dist/buildSchema.js +11 -10
- package/dist/buildSchema.js.map +1 -1
- package/dist/coreSpec.d.ts.map +1 -1
- package/dist/coreSpec.js +15 -42
- package/dist/coreSpec.js.map +1 -1
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +49 -98
- package/dist/definitions.js.map +1 -1
- package/dist/directiveAndTypeSpecification.js +14 -48
- package/dist/directiveAndTypeSpecification.js.map +1 -1
- package/dist/error.d.ts +19 -17
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +40 -7
- package/dist/error.js.map +1 -1
- package/dist/federation.d.ts.map +1 -1
- package/dist/federation.js +70 -123
- package/dist/federation.js.map +1 -1
- package/dist/inaccessibleSpec.js +43 -65
- package/dist/inaccessibleSpec.js.map +1 -1
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +5 -4
- package/dist/operations.js.map +1 -1
- package/dist/schemaUpgrader.js +2 -8
- package/dist/schemaUpgrader.js.map +1 -1
- package/dist/supergraphs.d.ts.map +1 -1
- package/dist/supergraphs.js +4 -4
- package/dist/supergraphs.js.map +1 -1
- package/dist/tagSpec.d.ts.map +1 -1
- package/dist/tagSpec.js +1 -3
- package/dist/tagSpec.js.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +26 -22
- package/dist/validate.js.map +1 -1
- package/dist/validation/KnownTypeNamesInFederationRule.js +1 -1
- package/dist/validation/KnownTypeNamesInFederationRule.js.map +1 -1
- package/dist/values.d.ts.map +1 -1
- package/dist/values.js +19 -18
- package/dist/values.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/subgraphValidation.test.ts +75 -0
- package/src/buildSchema.ts +11 -18
- package/src/coreSpec.ts +47 -43
- package/src/definitions.ts +64 -96
- package/src/directiveAndTypeSpecification.ts +50 -48
- package/src/error.ts +87 -41
- package/src/federation.ts +142 -131
- package/src/inaccessibleSpec.ts +207 -191
- package/src/operations.ts +5 -5
- package/src/schemaUpgrader.ts +8 -8
- package/src/supergraphs.ts +5 -4
- package/src/tagSpec.ts +2 -3
- package/src/validate.ts +60 -52
- package/src/validation/KnownTypeNamesInFederationRule.ts +1 -1
- package/src/values.ts +19 -18
- package/tsconfig.test.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/src/tagSpec.ts
CHANGED
|
@@ -62,9 +62,8 @@ export class TagSpecDefinition extends FeatureDefinition {
|
|
|
62
62
|
const hasValidNameArg = nameArg && sameType(nameArg.type!, new NonNullType(definition.schema().stringType()));
|
|
63
63
|
const hasValidLocations = definition.locations.every(loc => this.tagLocations.includes(loc));
|
|
64
64
|
if (hasUnknownArguments || !hasValidNameArg || !hasValidLocations) {
|
|
65
|
-
return ERRORS.DIRECTIVE_DEFINITION_INVALID.err(
|
|
66
|
-
|
|
67
|
-
}
|
|
65
|
+
return ERRORS.DIRECTIVE_DEFINITION_INVALID.err(
|
|
66
|
+
`Found invalid @tag directive definition. Please ensure the directive definition in your schema's definitions matches the following:\n\t${this.printedTagDefinition}`,
|
|
68
67
|
);
|
|
69
68
|
}
|
|
70
69
|
return undefined;
|
package/src/validate.ts
CHANGED
|
@@ -16,10 +16,11 @@ import {
|
|
|
16
16
|
UnionType,
|
|
17
17
|
VariableDefinitions
|
|
18
18
|
} from "./definitions";
|
|
19
|
-
import { assertName, ASTNode, GraphQLError } from "graphql";
|
|
19
|
+
import { assertName, ASTNode, GraphQLError, GraphQLErrorOptions } from "graphql";
|
|
20
20
|
import { isValidValue, valueToString } from "./values";
|
|
21
21
|
import { isIntrospectionName } from "./introspection";
|
|
22
22
|
import { isSubtype, sameType } from "./types";
|
|
23
|
+
import { ERRORS } from "./error";
|
|
23
24
|
|
|
24
25
|
// Note really meant to be called manually as it is part of `Schema.validate`, but separated for core-organization reasons.
|
|
25
26
|
// This mostly apply the validations that graphQL-js does in `validateSchema` which we don't reuse because it applies to
|
|
@@ -35,7 +36,7 @@ class InputObjectCircularRefsValidator {
|
|
|
35
36
|
// Position in the field path
|
|
36
37
|
private readonly fieldPathIndexByTypeName = new Map<string, number>();
|
|
37
38
|
|
|
38
|
-
constructor(private readonly onError: (
|
|
39
|
+
constructor(private readonly onError: (message: string, options: GraphQLErrorOptions) => void) {
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
detectCycles(type: InputObjectType) {
|
|
@@ -57,10 +58,10 @@ class InputObjectCircularRefsValidator {
|
|
|
57
58
|
} else {
|
|
58
59
|
const cyclePath = this.fieldPath.slice(cycleIndex);
|
|
59
60
|
const pathStr = cyclePath.map((fieldObj) => fieldObj.name).join('.');
|
|
60
|
-
this.onError(
|
|
61
|
+
this.onError(
|
|
61
62
|
`Cannot reference Input Object "${fieldType.name}" within itself through a series of non-null fields: "${pathStr}".`,
|
|
62
|
-
sourceASTs(...cyclePath)
|
|
63
|
-
)
|
|
63
|
+
{ nodes: sourceASTs(...cyclePath) },
|
|
64
|
+
);
|
|
64
65
|
}
|
|
65
66
|
this.fieldPath.pop();
|
|
66
67
|
}
|
|
@@ -112,7 +113,7 @@ class Validator {
|
|
|
112
113
|
// we found any type missing (in which case, there will be some errors and users should fix those
|
|
113
114
|
// first).
|
|
114
115
|
if (!this.hasMissingTypes) {
|
|
115
|
-
const refsValidator = new InputObjectCircularRefsValidator(
|
|
116
|
+
const refsValidator = new InputObjectCircularRefsValidator((msg, opts) => this.addError(msg, opts));
|
|
116
117
|
for (const type of this.schema.types()) {
|
|
117
118
|
switch (type.kind) {
|
|
118
119
|
case 'ObjectType':
|
|
@@ -129,11 +130,15 @@ class Validator {
|
|
|
129
130
|
return this.errors;
|
|
130
131
|
}
|
|
131
132
|
|
|
133
|
+
private addError(message: string, options: GraphQLErrorOptions) {
|
|
134
|
+
this.errors.push(ERRORS.INVALID_GRAPHQL.err(message, options));
|
|
135
|
+
}
|
|
136
|
+
|
|
132
137
|
private validateHasType(elt: { type?: Type, coordinate: string, sourceAST?: ASTNode }): boolean {
|
|
133
138
|
// Note that this error can't happen if you parse the schema since it wouldn't be valid syntax, but it can happen for
|
|
134
139
|
// programmatically constructed schema.
|
|
135
140
|
if (!elt.type) {
|
|
136
|
-
this.
|
|
141
|
+
this.addError(`Element ${elt.coordinate} does not have a type set`, { nodes: elt.sourceAST });
|
|
137
142
|
this.hasMissingTypes = false;
|
|
138
143
|
}
|
|
139
144
|
return !!elt.type;
|
|
@@ -146,13 +151,13 @@ class Validator {
|
|
|
146
151
|
try {
|
|
147
152
|
assertName(elt.name);
|
|
148
153
|
} catch (e) {
|
|
149
|
-
this.
|
|
154
|
+
this.addError(e.message, elt.sourceAST ? { nodes: elt.sourceAST } : {});
|
|
150
155
|
}
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
private validateObjectOrInterfaceType(type: ObjectType | InterfaceType) {
|
|
154
159
|
if (!type.hasFields()) {
|
|
155
|
-
this.
|
|
160
|
+
this.addError(`Type ${type.name} must define one or more fields.`, { nodes: type.sourceAST });
|
|
156
161
|
}
|
|
157
162
|
for (const field of type.fields()) {
|
|
158
163
|
this.validateName(field);
|
|
@@ -165,47 +170,47 @@ class Validator {
|
|
|
165
170
|
|
|
166
171
|
private validateImplementedInterfaces(type: ObjectType | InterfaceType) {
|
|
167
172
|
if (type.implementsInterface(type.name)) {
|
|
168
|
-
this.
|
|
173
|
+
this.addError(
|
|
169
174
|
`Type ${type} cannot implement itself because it would create a circular reference.`,
|
|
170
|
-
sourceASTs(type, type.interfaceImplementation(type.name)!)
|
|
171
|
-
)
|
|
175
|
+
{ nodes: sourceASTs(type, type.interfaceImplementation(type.name)!) },
|
|
176
|
+
);
|
|
172
177
|
}
|
|
173
178
|
|
|
174
179
|
for (const itf of type.interfaces()) {
|
|
175
180
|
for (const itfField of itf.fields()) {
|
|
176
181
|
const field = type.field(itfField.name);
|
|
177
182
|
if (!field) {
|
|
178
|
-
this.
|
|
183
|
+
this.addError(
|
|
179
184
|
`Interface field ${itfField.coordinate} expected but ${type} does not provide it.`,
|
|
180
|
-
sourceASTs(itfField, type)
|
|
181
|
-
)
|
|
185
|
+
{ nodes: sourceASTs(itfField, type) },
|
|
186
|
+
);
|
|
182
187
|
continue;
|
|
183
188
|
}
|
|
184
189
|
// Note that we may not have validated the interface yet, so making sure we have a meaningful error
|
|
185
190
|
// if the type is not set, even if that means a bit of cpu wasted since we'll re-check later (and
|
|
186
191
|
// as many type as the interface is implemented); it's a cheap check anyway.
|
|
187
192
|
if (this.validateHasType(itfField) && !isSubtype(itfField.type!, field.type!)) {
|
|
188
|
-
this.
|
|
193
|
+
this.addError(
|
|
189
194
|
`Interface field ${itfField.coordinate} expects type ${itfField.type} but ${field.coordinate} of type ${field.type} is not a proper subtype.`,
|
|
190
|
-
sourceASTs(itfField, field)
|
|
191
|
-
)
|
|
195
|
+
{ nodes: sourceASTs(itfField, field) },
|
|
196
|
+
);
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
for (const itfArg of itfField.arguments()) {
|
|
195
200
|
const arg = field.argument(itfArg.name);
|
|
196
201
|
if (!arg) {
|
|
197
|
-
this.
|
|
202
|
+
this.addError(
|
|
198
203
|
`Interface field argument ${itfArg.coordinate} expected but ${field.coordinate} does not provide it.`,
|
|
199
|
-
sourceASTs(itfArg, field)
|
|
200
|
-
)
|
|
204
|
+
{ nodes: sourceASTs(itfArg, field) },
|
|
205
|
+
);
|
|
201
206
|
continue;
|
|
202
207
|
}
|
|
203
208
|
// Note that we could use contra-variance but as graphQL-js currently doesn't allow it, we mimic that.
|
|
204
209
|
if (this.validateHasType(itfArg) && !sameType(itfArg.type!, arg.type!)) {
|
|
205
|
-
this.
|
|
210
|
+
this.addError(
|
|
206
211
|
`Interface field argument ${itfArg.coordinate} expects type ${itfArg.type} but ${arg.coordinate} is type ${arg.type}.`,
|
|
207
|
-
sourceASTs(itfArg, arg)
|
|
208
|
-
)
|
|
212
|
+
{ nodes: sourceASTs(itfArg, arg) },
|
|
213
|
+
);
|
|
209
214
|
}
|
|
210
215
|
}
|
|
211
216
|
|
|
@@ -215,10 +220,10 @@ class Validator {
|
|
|
215
220
|
continue;
|
|
216
221
|
}
|
|
217
222
|
if (arg.isRequired()) {
|
|
218
|
-
this.
|
|
223
|
+
this.addError(
|
|
219
224
|
`Field ${field.coordinate} includes required argument ${arg.name} that is missing from the Interface field ${itfField.coordinate}.`,
|
|
220
|
-
sourceASTs(arg, itfField)
|
|
221
|
-
)
|
|
225
|
+
{ nodes: sourceASTs(arg, itfField) },
|
|
226
|
+
);
|
|
222
227
|
}
|
|
223
228
|
}
|
|
224
229
|
}
|
|
@@ -227,12 +232,15 @@ class Validator {
|
|
|
227
232
|
for (const itfOfItf of itf.interfaces()) {
|
|
228
233
|
if (!type.implementsInterface(itfOfItf)) {
|
|
229
234
|
if (itfOfItf === type) {
|
|
230
|
-
this.
|
|
235
|
+
this.addError(
|
|
236
|
+
`Type ${type} cannot implement ${itf} because it would create a circular reference.`,
|
|
237
|
+
{ nodes: sourceASTs(type, itf) },
|
|
238
|
+
);
|
|
231
239
|
} else {
|
|
232
|
-
this.
|
|
240
|
+
this.addError(
|
|
233
241
|
`Type ${type} must implement ${itfOfItf} because it is implemented by ${itf}.`,
|
|
234
|
-
sourceASTs(type, itf, itfOfItf)
|
|
235
|
-
)
|
|
242
|
+
{ nodes: sourceASTs(type, itf, itfOfItf) },
|
|
243
|
+
);
|
|
236
244
|
}
|
|
237
245
|
}
|
|
238
246
|
}
|
|
@@ -241,7 +249,7 @@ class Validator {
|
|
|
241
249
|
|
|
242
250
|
private validateInputObjectType(type: InputObjectType) {
|
|
243
251
|
if (!type.hasFields()) {
|
|
244
|
-
this.
|
|
252
|
+
this.addError(`Input Object type ${type.name} must define one or more fields.`, { nodes: type.sourceAST });
|
|
245
253
|
}
|
|
246
254
|
for (const field of type.fields()) {
|
|
247
255
|
this.validateName(field);
|
|
@@ -249,16 +257,16 @@ class Validator {
|
|
|
249
257
|
continue;
|
|
250
258
|
}
|
|
251
259
|
if (field.isRequired() && field.isDeprecated()) {
|
|
252
|
-
this.
|
|
260
|
+
this.addError(
|
|
253
261
|
`Required input field ${field.coordinate} cannot be deprecated.`,
|
|
254
|
-
sourceASTs(field.appliedDirectivesOf('deprecated')[0], field)
|
|
255
|
-
)
|
|
262
|
+
{ nodes: sourceASTs(field.appliedDirectivesOf('deprecated')[0], field) },
|
|
263
|
+
);
|
|
256
264
|
}
|
|
257
265
|
if (field.defaultValue !== undefined && !isValidValue(field.defaultValue, field, new VariableDefinitions())) {
|
|
258
|
-
this.
|
|
266
|
+
this.addError(
|
|
259
267
|
`Invalid default value (got: ${valueToString(field.defaultValue)}) provided for input field ${field.coordinate} of type ${field.type}.`,
|
|
260
|
-
sourceASTs(field)
|
|
261
|
-
)
|
|
268
|
+
{ nodes: sourceASTs(field) },
|
|
269
|
+
);
|
|
262
270
|
}
|
|
263
271
|
}
|
|
264
272
|
}
|
|
@@ -269,36 +277,36 @@ class Validator {
|
|
|
269
277
|
return;
|
|
270
278
|
}
|
|
271
279
|
if (arg.isRequired() && arg.isDeprecated()) {
|
|
272
|
-
this.
|
|
280
|
+
this.addError(
|
|
273
281
|
`Required argument ${arg.coordinate} cannot be deprecated.`,
|
|
274
|
-
sourceASTs(arg.appliedDirectivesOf('deprecated')[0], arg)
|
|
275
|
-
)
|
|
282
|
+
{ nodes: sourceASTs(arg.appliedDirectivesOf('deprecated')[0], arg) },
|
|
283
|
+
);
|
|
276
284
|
}
|
|
277
285
|
if (arg.defaultValue !== undefined && !isValidValue(arg.defaultValue, arg, new VariableDefinitions())) {
|
|
278
|
-
this.
|
|
286
|
+
this.addError(
|
|
279
287
|
`Invalid default value (got: ${valueToString(arg.defaultValue)}) provided for argument ${arg.coordinate} of type ${arg.type}.`,
|
|
280
|
-
sourceASTs(arg)
|
|
281
|
-
)
|
|
288
|
+
{ nodes: sourceASTs(arg) },
|
|
289
|
+
);
|
|
282
290
|
}
|
|
283
291
|
}
|
|
284
292
|
|
|
285
293
|
private validateUnionType(type: UnionType) {
|
|
286
294
|
if (type.membersCount() === 0) {
|
|
287
|
-
this.
|
|
295
|
+
this.addError(`Union type ${type.coordinate} must define one or more member types.`, { nodes: type.sourceAST });
|
|
288
296
|
}
|
|
289
297
|
}
|
|
290
298
|
|
|
291
299
|
private validateEnumType(type: EnumType) {
|
|
292
300
|
if (type.values.length === 0) {
|
|
293
|
-
this.
|
|
301
|
+
this.addError(`Enum type ${type.coordinate} must define one or more values.`, { nodes: type.sourceAST });
|
|
294
302
|
}
|
|
295
303
|
for (const value of type.values) {
|
|
296
304
|
this.validateName(value);
|
|
297
305
|
if (value.name === 'true' || value.name === 'false' || value.name === 'null') {
|
|
298
|
-
this.
|
|
306
|
+
this.addError(
|
|
299
307
|
`Enum type ${type.coordinate} cannot include value: ${value}.`,
|
|
300
|
-
value.sourceAST
|
|
301
|
-
)
|
|
308
|
+
{ nodes: value.sourceAST },
|
|
309
|
+
);
|
|
302
310
|
}
|
|
303
311
|
}
|
|
304
312
|
}
|
|
@@ -322,10 +330,10 @@ class Validator {
|
|
|
322
330
|
const parentDesc = parent instanceof NamedSchemaElement
|
|
323
331
|
? parent.coordinate
|
|
324
332
|
: 'schema';
|
|
325
|
-
this.
|
|
333
|
+
this.addError(
|
|
326
334
|
`Invalid value for "${argument.coordinate}" of type "${argument.type}" in application of "${definition.coordinate}" to "${parentDesc}".`,
|
|
327
|
-
sourceASTs(application, argument)
|
|
328
|
-
)
|
|
335
|
+
{ nodes: sourceASTs(application, argument) },
|
|
336
|
+
);
|
|
329
337
|
}
|
|
330
338
|
}
|
|
331
339
|
}
|
package/src/values.ts
CHANGED
|
@@ -34,6 +34,7 @@ import { didYouMean, suggestionList } from './suggestions';
|
|
|
34
34
|
import { inspect } from 'util';
|
|
35
35
|
import { sameType } from './types';
|
|
36
36
|
import { assert, assertUnreachable } from './utils';
|
|
37
|
+
import { ERRORS } from './error';
|
|
37
38
|
|
|
38
39
|
// Per-GraphQL spec, max and value for an Int type.
|
|
39
40
|
const MAX_INT = 2147483647;
|
|
@@ -189,7 +190,7 @@ function applyDefaultValues(value: any, type: InputType): any {
|
|
|
189
190
|
|
|
190
191
|
if (value === null) {
|
|
191
192
|
if (isNonNullType(type)) {
|
|
192
|
-
throw
|
|
193
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Invalid null value for non-null type ${type} while computing default values`);
|
|
193
194
|
}
|
|
194
195
|
return null;
|
|
195
196
|
}
|
|
@@ -208,7 +209,7 @@ function applyDefaultValues(value: any, type: InputType): any {
|
|
|
208
209
|
|
|
209
210
|
if (isInputObjectType(type)) {
|
|
210
211
|
if (typeof value !== 'object') {
|
|
211
|
-
throw
|
|
212
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Expected value for type ${type} to be an object, but is ${typeof value}.`);
|
|
212
213
|
}
|
|
213
214
|
|
|
214
215
|
const updated = Object.create(null);
|
|
@@ -221,7 +222,7 @@ function applyDefaultValues(value: any, type: InputType): any {
|
|
|
221
222
|
if (field.defaultValue !== undefined) {
|
|
222
223
|
updated[field.name] = applyDefaultValues(field.defaultValue, field.type);
|
|
223
224
|
} else if (isNonNullType(field.type)) {
|
|
224
|
-
throw
|
|
225
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Field "${field.name}" of required type ${type} was not provided.`);
|
|
225
226
|
}
|
|
226
227
|
} else {
|
|
227
228
|
updated[field.name] = applyDefaultValues(fieldValue, field.type);
|
|
@@ -232,7 +233,7 @@ function applyDefaultValues(value: any, type: InputType): any {
|
|
|
232
233
|
for (const fieldName of Object.keys(value)) {
|
|
233
234
|
if (!type.field(fieldName)) {
|
|
234
235
|
const suggestions = suggestionList(fieldName, type.fields().map(f => f.name));
|
|
235
|
-
throw
|
|
236
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Field "${fieldName}" is not defined by type "${type}".` + didYouMean(suggestions));
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
239
|
return updated;
|
|
@@ -561,7 +562,7 @@ function isValidValueApplication(value: any, locationType: InputType, locationDe
|
|
|
561
562
|
export function valueFromAST(node: ValueNode, expectedType: InputType): any {
|
|
562
563
|
if (node.kind === Kind.NULL) {
|
|
563
564
|
if (isNonNullType(expectedType)) {
|
|
564
|
-
throw
|
|
565
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Invalid null value for non-null type "${expectedType}"`);
|
|
565
566
|
}
|
|
566
567
|
return null;
|
|
567
568
|
}
|
|
@@ -584,11 +585,11 @@ export function valueFromAST(node: ValueNode, expectedType: InputType): any {
|
|
|
584
585
|
|
|
585
586
|
if (isIntType(expectedType)) {
|
|
586
587
|
if (node.kind !== Kind.INT) {
|
|
587
|
-
throw
|
|
588
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Int cannot represent non-integer value ${print(node)}.`);
|
|
588
589
|
}
|
|
589
590
|
const i = parseInt(node.value, 10);
|
|
590
591
|
if (i > MAX_INT || i < MIN_INT) {
|
|
591
|
-
throw
|
|
592
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Int cannot represent non 32-bit signed integer value ${i}.`);
|
|
592
593
|
}
|
|
593
594
|
return i;
|
|
594
595
|
}
|
|
@@ -600,31 +601,31 @@ export function valueFromAST(node: ValueNode, expectedType: InputType): any {
|
|
|
600
601
|
} else if (node.kind === Kind.FLOAT) {
|
|
601
602
|
parsed = parseFloat(node.value);
|
|
602
603
|
} else {
|
|
603
|
-
throw
|
|
604
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Float can only represent integer or float value, but got a ${node.kind}.`);
|
|
604
605
|
}
|
|
605
606
|
if (!isFinite(parsed)) {
|
|
606
|
-
throw
|
|
607
|
+
throw ERRORS.INVALID_GRAPHQL.err( `Float cannot represent non numeric value ${parsed}.`);
|
|
607
608
|
}
|
|
608
609
|
return parsed;
|
|
609
610
|
}
|
|
610
611
|
|
|
611
612
|
if (isBooleanType(expectedType)) {
|
|
612
613
|
if (node.kind !== Kind.BOOLEAN) {
|
|
613
|
-
throw
|
|
614
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Boolean cannot represent a non boolean value ${print(node)}.`);
|
|
614
615
|
}
|
|
615
616
|
return node.value;
|
|
616
617
|
}
|
|
617
618
|
|
|
618
619
|
if (isStringType(expectedType)) {
|
|
619
620
|
if (node.kind !== Kind.STRING) {
|
|
620
|
-
throw
|
|
621
|
+
throw ERRORS.INVALID_GRAPHQL.err(`String cannot represent non string value ${print(node)}.`);
|
|
621
622
|
}
|
|
622
623
|
return node.value;
|
|
623
624
|
}
|
|
624
625
|
|
|
625
626
|
if (isIDType(expectedType)) {
|
|
626
627
|
if (node.kind !== Kind.STRING && node.kind !== Kind.INT) {
|
|
627
|
-
throw
|
|
628
|
+
throw ERRORS.INVALID_GRAPHQL.err(`ID cannot represent value ${print(node)}.`);
|
|
628
629
|
}
|
|
629
630
|
return node.value;
|
|
630
631
|
}
|
|
@@ -635,14 +636,14 @@ export function valueFromAST(node: ValueNode, expectedType: InputType): any {
|
|
|
635
636
|
|
|
636
637
|
if (isInputObjectType(expectedType)) {
|
|
637
638
|
if (node.kind !== Kind.OBJECT) {
|
|
638
|
-
throw
|
|
639
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Input Object Type ${expectedType} cannot represent non-object value ${print(node)}.`);
|
|
639
640
|
}
|
|
640
641
|
const obj = Object.create(null);
|
|
641
642
|
for (const f of node.fields) {
|
|
642
643
|
const name = f.name.value;
|
|
643
644
|
const field = expectedType.field(name);
|
|
644
645
|
if (!field) {
|
|
645
|
-
throw
|
|
646
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Unknown field "${name}" found in value for Input Object Type "${expectedType}".`);
|
|
646
647
|
}
|
|
647
648
|
// TODO: as we recurse in sub-objects, we may get an error on a field value deep in the object
|
|
648
649
|
// and the error will not be precise to where it happens. We could try to build the path to
|
|
@@ -654,10 +655,10 @@ export function valueFromAST(node: ValueNode, expectedType: InputType): any {
|
|
|
654
655
|
|
|
655
656
|
if (isEnumType(expectedType)) {
|
|
656
657
|
if (node.kind !== Kind.STRING && node.kind !== Kind.ENUM) {
|
|
657
|
-
throw
|
|
658
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Enum Type ${expectedType} cannot represent value ${print(node)}.`);
|
|
658
659
|
}
|
|
659
660
|
if (!expectedType.value(node.value)) {
|
|
660
|
-
throw
|
|
661
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Enum Type ${expectedType} has no value ${node.value}.`);
|
|
661
662
|
}
|
|
662
663
|
return node.value;
|
|
663
664
|
}
|
|
@@ -699,7 +700,7 @@ export function argumentsFromAST(
|
|
|
699
700
|
const name = argNode.name.value;
|
|
700
701
|
const expectedType = argsDefiner.argument(name)?.type;
|
|
701
702
|
if (!expectedType) {
|
|
702
|
-
throw
|
|
703
|
+
throw ERRORS.INVALID_GRAPHQL.err(
|
|
703
704
|
`Unknown argument "${name}" found in value: ${context} has no argument named "${name}"`
|
|
704
705
|
);
|
|
705
706
|
}
|
|
@@ -707,7 +708,7 @@ export function argumentsFromAST(
|
|
|
707
708
|
values[name] = valueFromAST(argNode.value, expectedType);
|
|
708
709
|
} catch (e) {
|
|
709
710
|
if (e instanceof GraphQLError) {
|
|
710
|
-
throw
|
|
711
|
+
throw ERRORS.INVALID_GRAPHQL.err(`Invalid value for argument ${name}: ${e.message}`);
|
|
711
712
|
}
|
|
712
713
|
throw e;
|
|
713
714
|
}
|