Skip to content

Commit 4b78d0d

Browse files
authored
Adds isValidValue and isValidLiteral to Scalar and Enum types. (#861)
Used for more semantically correct validity checking after #848
1 parent ff845f7 commit 4b78d0d

File tree

4 files changed

+31
-14
lines changed

4 files changed

+31
-14
lines changed

src/type/definition.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
import invariant from '../jsutils/invariant';
12+
import isNullish from '../jsutils/isNullish';
1213
import { ENUM } from '../language/kinds';
1314
import { assertValidName } from '../utilities/assertValidName';
1415
import type {
@@ -323,16 +324,28 @@ export class GraphQLScalarType {
323324
return serializer(value);
324325
}
325326

327+
// Determines if an internal value is valid for this type.
328+
// Equivalent to checking for if the parsedValue is nullish.
329+
isValidValue(value: mixed): boolean {
330+
return !isNullish(this.parseValue(value));
331+
}
332+
326333
// Parses an externally provided value to use as an input.
327334
parseValue(value: mixed): mixed {
328335
const parser = this._scalarConfig.parseValue;
329-
return parser ? parser(value) : null;
336+
return parser && !isNullish(value) ? parser(value) : undefined;
337+
}
338+
339+
// Determines if an internal value is valid for this type.
340+
// Equivalent to checking for if the parsedLiteral is nullish.
341+
isValidLiteral(valueNode: ValueNode): boolean {
342+
return !isNullish(this.parseLiteral(valueNode));
330343
}
331344

332345
// Parses an externally provided literal value to use as an input.
333346
parseLiteral(valueNode: ValueNode): mixed {
334347
const parser = this._scalarConfig.parseLiteral;
335-
return parser ? parser(valueNode) : null;
348+
return parser ? parser(valueNode) : undefined;
336349
}
337350

338351
toString(): string {
@@ -896,6 +909,11 @@ export class GraphQLEnumType/* <T> */ {
896909
return enumValue ? enumValue.name : null;
897910
}
898911

912+
isValidValue(value: mixed): boolean {
913+
return typeof value === 'string' &&
914+
this._getNameLookup()[value] !== undefined;
915+
}
916+
899917
parseValue(value: mixed): ?any/* T */ {
900918
if (typeof value === 'string') {
901919
const enumValue = this._getNameLookup()[value];
@@ -905,6 +923,11 @@ export class GraphQLEnumType/* <T> */ {
905923
}
906924
}
907925

926+
isValidLiteral(valueNode: ValueNode): boolean {
927+
return valueNode.kind === ENUM &&
928+
this._getNameLookup()[valueNode.value] !== undefined;
929+
}
930+
908931
parseLiteral(valueNode: ValueNode): ?any/* T */ {
909932
if (valueNode.kind === ENUM) {
910933
const enumValue = this._getNameLookup()[valueNode.value];

src/utilities/isValidJSValue.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export function isValidJSValue(
9595
// a non-null value.
9696
try {
9797
const parseResult = type.parseValue(value);
98-
if (isNullish(parseResult)) {
98+
if (isNullish(parseResult) && !type.isValidValue(value)) {
9999
return [
100100
`Expected type "${type.name}", found ${JSON.stringify(value)}.`
101101
];

src/utilities/isValidLiteralValue.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import {
3030
import type { GraphQLInputType } from '../type/definition';
3131
import invariant from '../jsutils/invariant';
3232
import keyMap from '../jsutils/keyMap';
33-
import isNullish from '../jsutils/isNullish';
3433

3534

3635
/**
@@ -115,11 +114,8 @@ export function isValidLiteralValue(
115114
'Must be input type'
116115
);
117116

118-
// Scalars must parse to a non-null value, Enums may be null but must
119-
// serialize back to a named value.
120-
const parseResult = type.parseLiteral(valueNode);
121-
if (type instanceof GraphQLEnumType ?
122-
!type.serialize(parseResult) : isNullish(parseResult)) {
117+
// Scalars determine if a literal values is valid.
118+
if (!type.isValidLiteral(valueNode)) {
123119
return [ `Expected type "${type.name}", found ${print(valueNode)}.` ];
124120
}
125121

src/utilities/valueFromAST.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,9 @@ export function valueFromAST(
152152
);
153153

154154
const parsed = type.parseLiteral(valueNode);
155-
if (type instanceof GraphQLEnumType ?
156-
!type.serialize(parsed) : isNullish(parsed)) {
157-
// null or invalid values represent a failure to parse correctly (unless
158-
// we have a legitimately null-valued Enum), in which case no value is
159-
// returned.
155+
if (isNullish(parsed) && !type.isValidLiteral(valueNode)) {
156+
// Invalid values represent a failure to parse correctly, in which case
157+
// no value is returned.
160158
return;
161159
}
162160

0 commit comments

Comments
 (0)