Skip to content

Commit 0e22cc4

Browse files
authored
improve upgrade path for new custom scalar parseConstLiteral() method (#4209)
`parseLiteral()` has been marked as deprecated, prompting but not forcing our users to convert to `parseConstLiteral()`. With this additional change: - in v17, if not supplied, the new `parseConstLiteral()` method will be left as undefined, and during execution, we will fall back to`parseLiteral()`. - in v18, we will remove `parseLiteral()` and set up a default function for `parseConstLiteral()` when not supplied. Prior to this change, users of custom scalars with custom `parseLiteral()` functions who did not provide a custom `parseConstLiteral()` function would just get the default `parseConstLiteral()` function during execution, which might not work as expected. This scheme will work except for users of custom scalars who want to embed experimental fragment variables in their custom scalars, which will only work with the new `parseConstLiteral()` method.
1 parent 4dfae39 commit 0e22cc4

File tree

5 files changed

+21
-19
lines changed

5 files changed

+21
-19
lines changed

src/type/__tests__/definition-test.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,23 @@ describe('Type System: Scalars', () => {
7272
expect(scalar.serialize).to.equal(identityFunc);
7373
expect(scalar.parseValue).to.equal(identityFunc);
7474
expect(scalar.parseLiteral).to.be.a('function');
75-
expect(scalar.parseConstLiteral).to.be.a('function');
75+
/* default will be provided in v18 when parseLiteral is removed */
76+
// expect(scalar.parseConstLiteral).to.be.a('function');
7677
});
7778

78-
it('use parseValue for parsing literals if parseConstLiteral omitted', () => {
79+
it('use parseValue for parsing literals if parseLiteral omitted', () => {
7980
const scalar = new GraphQLScalarType({
8081
name: 'Foo',
8182
parseValue(value) {
8283
return 'parseValue: ' + inspect(value);
8384
},
8485
});
8586

86-
expect(scalar.parseConstLiteral(parseConstValue('null'))).to.equal(
87+
expect(scalar.parseLiteral(parseConstValue('null'), undefined)).to.equal(
8788
'parseValue: null',
8889
);
8990
expect(
90-
scalar.parseConstLiteral(parseConstValue('{ foo: "bar" }')),
91+
scalar.parseLiteral(parseConstValue('{ foo: "bar" }'), undefined),
9192
).to.equal('parseValue: { foo: "bar" }');
9293
});
9394

src/type/__tests__/scalars-test.ts

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ describe('Type System: Specified scalar types', () => {
6666

6767
it('parseConstLiteral', () => {
6868
function parseConstLiteral(str: string) {
69+
/* @ts-expect-error to be removed in v18 when all custom scalars will have default method */
6970
return GraphQLInt.parseConstLiteral(parseConstValue(str));
7071
}
7172

@@ -228,6 +229,7 @@ describe('Type System: Specified scalar types', () => {
228229

229230
it('parseConstLiteral', () => {
230231
function parseConstLiteral(str: string) {
232+
/* @ts-expect-error to be removed in v18 when all custom scalars will have default method */
231233
return GraphQLFloat.parseConstLiteral(parseConstValue(str));
232234
}
233235

@@ -338,6 +340,7 @@ describe('Type System: Specified scalar types', () => {
338340

339341
it('parseConstLiteral', () => {
340342
function parseConstLiteral(str: string) {
343+
/* @ts-expect-error to be removed in v18 when all custom scalars will have default method */
341344
return GraphQLString.parseConstLiteral(parseConstValue(str));
342345
}
343346

@@ -447,6 +450,7 @@ describe('Type System: Specified scalar types', () => {
447450

448451
it('parseConstLiteral', () => {
449452
function parseConstLiteral(str: string) {
453+
/* @ts-expect-error to be removed in v18 when all custom scalars will have default method */
450454
return GraphQLBoolean.parseConstLiteral(parseConstValue(str));
451455
}
452456

@@ -559,6 +563,7 @@ describe('Type System: Specified scalar types', () => {
559563

560564
it('parseConstLiteral', () => {
561565
function parseConstLiteral(str: string) {
566+
/* @ts-expect-error to be removed in v18 when all custom scalars will have default method */
562567
return GraphQLID.parseConstLiteral(parseConstValue(str));
563568
}
564569

src/type/definition.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ export class GraphQLScalarType<TInternal = unknown, TExternal = TInternal> {
588588
parseValue: GraphQLScalarValueParser<TInternal>;
589589
/** @deprecated use `replaceVariables()` and `parseConstLiteral()` instead, `parseLiteral()` will be deprecated in v18 */
590590
parseLiteral: GraphQLScalarLiteralParser<TInternal>;
591-
parseConstLiteral: GraphQLScalarConstLiteralParser<TInternal>;
591+
parseConstLiteral: GraphQLScalarConstLiteralParser<TInternal> | undefined;
592592
valueToLiteral: GraphQLScalarValueToLiteral | undefined;
593593
extensions: Readonly<GraphQLScalarTypeExtensions>;
594594
astNode: Maybe<ScalarTypeDefinitionNode>;
@@ -608,9 +608,7 @@ export class GraphQLScalarType<TInternal = unknown, TExternal = TInternal> {
608608
this.parseLiteral =
609609
config.parseLiteral ??
610610
((node, variables) => parseValue(valueFromASTUntyped(node, variables)));
611-
this.parseConstLiteral =
612-
config.parseConstLiteral ??
613-
((node) => parseValue(valueFromASTUntyped(node)));
611+
this.parseConstLiteral = config.parseConstLiteral;
614612
this.valueToLiteral = config.valueToLiteral;
615613
this.extensions = toObjMap(config.extensions);
616614
this.astNode = config.astNode;
@@ -708,7 +706,7 @@ interface GraphQLScalarTypeNormalizedConfig<TInternal, TExternal>
708706
serialize: GraphQLScalarSerializer<TExternal>;
709707
parseValue: GraphQLScalarValueParser<TInternal>;
710708
parseLiteral: GraphQLScalarLiteralParser<TInternal>;
711-
parseConstLiteral: GraphQLScalarConstLiteralParser<TInternal>;
709+
parseConstLiteral: GraphQLScalarConstLiteralParser<TInternal> | undefined;
712710
extensions: Readonly<GraphQLScalarTypeExtensions>;
713711
extensionASTNodes: ReadonlyArray<ScalarTypeExtensionNode>;
714712
}

src/utilities/coerceInputValue.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,12 @@ export function coerceInputLiteral(
371371
}
372372

373373
const leafType = assertLeafType(type);
374-
const constValueNode = replaceVariables(
375-
valueNode,
376-
variableValues,
377-
fragmentVariableValues,
378-
);
379-
380374
try {
381-
return leafType.parseConstLiteral(constValueNode);
375+
return leafType.parseConstLiteral
376+
? leafType.parseConstLiteral(
377+
replaceVariables(valueNode, variableValues, fragmentVariableValues),
378+
)
379+
: leafType.parseLiteral(valueNode, variableValues?.coerced);
382380
} catch (_error) {
383381
// Invalid: ignore error and intentionally return no value.
384382
}

src/validation/rules/ValuesOfCorrectTypeRule.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,12 @@ function isValidValueNode(context: ValidationContext, node: ValueNode): void {
153153
return;
154154
}
155155

156-
const constValueNode = replaceVariables(node);
157-
158156
// Scalars and Enums determine if a literal value is valid via parseConstLiteral(),
159157
// which may throw or return undefined to indicate an invalid value.
160158
try {
161-
const parseResult = type.parseConstLiteral(constValueNode);
159+
const parseResult = type.parseConstLiteral
160+
? type.parseConstLiteral(replaceVariables(node))
161+
: type.parseLiteral(node, undefined);
162162
if (parseResult === undefined) {
163163
const typeStr = inspect(locationType);
164164
context.reportError(

0 commit comments

Comments
 (0)