Skip to content

Commit

Permalink
improve new leaf type parseConstLiteral() method (#4218)
Browse files Browse the repository at this point in the history
the new method was introduced in #3812 with upgrade path improved in
#4209.

This PR completes polishes this work a bit:

1. The method is renamed to `coerceInputLiteral()` following the naming
convention suggested in #2357, with the other methods to be renamed in
later PRs.
2. The type of the method `GraphQLScalarInputLiteralCoercer` is
exported, which was not done in the initial work. The old
`GraphQLScalarLiteralParser` type is deprecated.
  • Loading branch information
yaacovCR authored Oct 13, 2024
1 parent 0ea9241 commit 805e3c3
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 117 deletions.
2 changes: 1 addition & 1 deletion integrationTests/ts/kitchenSink-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ new GraphQLScalarType({
name: 'SomeScalar',
serialize: undefined,
parseValue: undefined,
parseConstLiteral: undefined,
coerceInputLiteral: undefined,
});

new GraphQLError('test', { nodes: undefined });
Expand Down
6 changes: 3 additions & 3 deletions src/execution/__tests__/variables-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const TestFaultyScalar = new GraphQLScalarType({
parseValue() {
throw TestFaultyScalarGraphQLError;
},
parseConstLiteral() {
coerceInputLiteral() {
throw TestFaultyScalarGraphQLError;
},
});
Expand All @@ -58,7 +58,7 @@ const TestComplexScalar = new GraphQLScalarType({
expect(value).to.equal('SerializedValue');
return 'DeserializedValue';
},
parseConstLiteral(ast) {
coerceInputLiteral(ast) {
expect(ast).to.include({ kind: 'StringValue', value: 'SerializedValue' });
return 'DeserializedValue';
},
Expand Down Expand Up @@ -281,7 +281,7 @@ describe('Execute: Handles inputs', () => {
});
});

it('properly runs parseConstLiteral on complex scalar types', () => {
it('properly runs coerceInputLiteral on complex scalar types', () => {
const result = executeQuery(`
{
fieldWithObjectInput(input: {c: "foo", d: "SerializedValue"})
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,9 @@ export type {
GraphQLUnionTypeExtensions,
GraphQLScalarSerializer,
GraphQLScalarValueParser,
/* @deprecated in favor of GraphQLScalarInputLiteralCoercer, will be removed in v18 */
GraphQLScalarLiteralParser,
GraphQLScalarInputLiteralCoercer,
GraphQLDefaultValueUsage,
} from './type/index.js';

Expand Down
12 changes: 6 additions & 6 deletions src/type/__tests__/definition-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('Type System: Scalars', () => {
serialize: someScalar.serialize,
parseValue: someScalar.parseValue,
parseLiteral: someScalar.parseLiteral,
parseConstLiteral: undefined,
coerceInputLiteral: undefined,
valueToLiteral: undefined,
extensions: {},
astNode: undefined,
Expand All @@ -76,7 +76,7 @@ describe('Type System: Scalars', () => {
serialize: passThroughFunc,
parseValue: passThroughFunc,
parseLiteral: passThroughFunc,
parseConstLiteral: passThroughFunc,
coerceInputLiteral: passThroughFunc,
valueToLiteral: passThroughFunc,
extensions: { someExtension: 'extension' },
astNode: dummyAny,
Expand All @@ -93,7 +93,7 @@ describe('Type System: Scalars', () => {
expect(scalar.parseValue).to.equal(identityFunc);
expect(scalar.parseLiteral).to.be.a('function');
/* default will be provided in v18 when parseLiteral is removed */
// expect(scalar.parseConstLiteral).to.be.a('function');
// expect(scalar.coerceInputLiteral).to.be.a('function');
});

it('use parseValue for parsing literals if parseLiteral omitted', () => {
Expand Down Expand Up @@ -124,15 +124,15 @@ describe('Type System: Scalars', () => {
);
});

it('rejects a Scalar type defining parseConstLiteral but not parseValue', () => {
it('rejects a Scalar type defining coerceInputLiteral but not parseValue', () => {
expect(
() =>
new GraphQLScalarType({
name: 'SomeScalar',
parseConstLiteral: passThroughFunc,
coerceInputLiteral: passThroughFunc,
}),
).to.throw(
'SomeScalar must provide both "parseValue" and "parseConstLiteral" functions.',
'SomeScalar must provide both "parseValue" and "coerceInputLiteral" functions.',
);
});
});
Expand Down
152 changes: 76 additions & 76 deletions src/type/__tests__/scalars-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,45 +64,45 @@ describe('Type System: Specified scalar types', () => {
);
});

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

expect(parseConstLiteral('1')).to.equal(1);
expect(parseConstLiteral('0')).to.equal(0);
expect(parseConstLiteral('-1')).to.equal(-1);
expect(coerceInputLiteral('1')).to.equal(1);
expect(coerceInputLiteral('0')).to.equal(0);
expect(coerceInputLiteral('-1')).to.equal(-1);

expect(() => parseConstLiteral('9876504321')).to.throw(
expect(() => coerceInputLiteral('9876504321')).to.throw(
'Int cannot represent non 32-bit signed integer value: 9876504321',
);
expect(() => parseConstLiteral('-9876504321')).to.throw(
expect(() => coerceInputLiteral('-9876504321')).to.throw(
'Int cannot represent non 32-bit signed integer value: -9876504321',
);

expect(() => parseConstLiteral('1.0')).to.throw(
expect(() => coerceInputLiteral('1.0')).to.throw(
'Int cannot represent non-integer value: 1.0',
);
expect(() => parseConstLiteral('null')).to.throw(
expect(() => coerceInputLiteral('null')).to.throw(
'Int cannot represent non-integer value: null',
);
expect(() => parseConstLiteral('""')).to.throw(
expect(() => coerceInputLiteral('""')).to.throw(
'Int cannot represent non-integer value: ""',
);
expect(() => parseConstLiteral('"123"')).to.throw(
expect(() => coerceInputLiteral('"123"')).to.throw(
'Int cannot represent non-integer value: "123"',
);
expect(() => parseConstLiteral('false')).to.throw(
expect(() => coerceInputLiteral('false')).to.throw(
'Int cannot represent non-integer value: false',
);
expect(() => parseConstLiteral('[1]')).to.throw(
expect(() => coerceInputLiteral('[1]')).to.throw(
'Int cannot represent non-integer value: [1]',
);
expect(() => parseConstLiteral('{ value: 1 }')).to.throw(
expect(() => coerceInputLiteral('{ value: 1 }')).to.throw(
'Int cannot represent non-integer value: { value: 1 }',
);
expect(() => parseConstLiteral('ENUM_VALUE')).to.throw(
expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw(
'Int cannot represent non-integer value: ENUM_VALUE',
);
});
Expand Down Expand Up @@ -227,40 +227,40 @@ describe('Type System: Specified scalar types', () => {
);
});

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

expect(parseConstLiteral('1')).to.equal(1);
expect(parseConstLiteral('0')).to.equal(0);
expect(parseConstLiteral('-1')).to.equal(-1);
expect(parseConstLiteral('0.1')).to.equal(0.1);
expect(parseConstLiteral(Math.PI.toString())).to.equal(Math.PI);
expect(coerceInputLiteral('1')).to.equal(1);
expect(coerceInputLiteral('0')).to.equal(0);
expect(coerceInputLiteral('-1')).to.equal(-1);
expect(coerceInputLiteral('0.1')).to.equal(0.1);
expect(coerceInputLiteral(Math.PI.toString())).to.equal(Math.PI);

expect(() => parseConstLiteral('null')).to.throw(
expect(() => coerceInputLiteral('null')).to.throw(
'Float cannot represent non numeric value: null',
);
expect(() => parseConstLiteral('""')).to.throw(
expect(() => coerceInputLiteral('""')).to.throw(
'Float cannot represent non numeric value: ""',
);
expect(() => parseConstLiteral('"123"')).to.throw(
expect(() => coerceInputLiteral('"123"')).to.throw(
'Float cannot represent non numeric value: "123"',
);
expect(() => parseConstLiteral('"123.5"')).to.throw(
expect(() => coerceInputLiteral('"123.5"')).to.throw(
'Float cannot represent non numeric value: "123.5"',
);
expect(() => parseConstLiteral('false')).to.throw(
expect(() => coerceInputLiteral('false')).to.throw(
'Float cannot represent non numeric value: false',
);
expect(() => parseConstLiteral('[0.1]')).to.throw(
expect(() => coerceInputLiteral('[0.1]')).to.throw(
'Float cannot represent non numeric value: [0.1]',
);
expect(() => parseConstLiteral('{ value: 0.1 }')).to.throw(
expect(() => coerceInputLiteral('{ value: 0.1 }')).to.throw(
'Float cannot represent non numeric value: { value: 0.1 }',
);
expect(() => parseConstLiteral('ENUM_VALUE')).to.throw(
expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw(
'Float cannot represent non numeric value: ENUM_VALUE',
);
});
Expand Down Expand Up @@ -338,34 +338,34 @@ describe('Type System: Specified scalar types', () => {
);
});

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

expect(parseConstLiteral('"foo"')).to.equal('foo');
expect(parseConstLiteral('"""bar"""')).to.equal('bar');
expect(coerceInputLiteral('"foo"')).to.equal('foo');
expect(coerceInputLiteral('"""bar"""')).to.equal('bar');

expect(() => parseConstLiteral('null')).to.throw(
expect(() => coerceInputLiteral('null')).to.throw(
'String cannot represent a non string value: null',
);
expect(() => parseConstLiteral('1')).to.throw(
expect(() => coerceInputLiteral('1')).to.throw(
'String cannot represent a non string value: 1',
);
expect(() => parseConstLiteral('0.1')).to.throw(
expect(() => coerceInputLiteral('0.1')).to.throw(
'String cannot represent a non string value: 0.1',
);
expect(() => parseConstLiteral('false')).to.throw(
expect(() => coerceInputLiteral('false')).to.throw(
'String cannot represent a non string value: false',
);
expect(() => parseConstLiteral('["foo"]')).to.throw(
expect(() => coerceInputLiteral('["foo"]')).to.throw(
'String cannot represent a non string value: ["foo"]',
);
expect(() => parseConstLiteral('{ value: "foo" }')).to.throw(
expect(() => coerceInputLiteral('{ value: "foo" }')).to.throw(
'String cannot represent a non string value: { value: "foo" }',
);
expect(() => parseConstLiteral('ENUM_VALUE')).to.throw(
expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw(
'String cannot represent a non string value: ENUM_VALUE',
);
});
Expand Down Expand Up @@ -448,40 +448,40 @@ describe('Type System: Specified scalar types', () => {
);
});

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

expect(parseConstLiteral('true')).to.equal(true);
expect(parseConstLiteral('false')).to.equal(false);
expect(coerceInputLiteral('true')).to.equal(true);
expect(coerceInputLiteral('false')).to.equal(false);

expect(() => parseConstLiteral('null')).to.throw(
expect(() => coerceInputLiteral('null')).to.throw(
'Boolean cannot represent a non boolean value: null',
);
expect(() => parseConstLiteral('0')).to.throw(
expect(() => coerceInputLiteral('0')).to.throw(
'Boolean cannot represent a non boolean value: 0',
);
expect(() => parseConstLiteral('1')).to.throw(
expect(() => coerceInputLiteral('1')).to.throw(
'Boolean cannot represent a non boolean value: 1',
);
expect(() => parseConstLiteral('0.1')).to.throw(
expect(() => coerceInputLiteral('0.1')).to.throw(
'Boolean cannot represent a non boolean value: 0.1',
);
expect(() => parseConstLiteral('""')).to.throw(
expect(() => coerceInputLiteral('""')).to.throw(
'Boolean cannot represent a non boolean value: ""',
);
expect(() => parseConstLiteral('"false"')).to.throw(
expect(() => coerceInputLiteral('"false"')).to.throw(
'Boolean cannot represent a non boolean value: "false"',
);
expect(() => parseConstLiteral('[false]')).to.throw(
expect(() => coerceInputLiteral('[false]')).to.throw(
'Boolean cannot represent a non boolean value: [false]',
);
expect(() => parseConstLiteral('{ value: false }')).to.throw(
expect(() => coerceInputLiteral('{ value: false }')).to.throw(
'Boolean cannot represent a non boolean value: { value: false }',
);
expect(() => parseConstLiteral('ENUM_VALUE')).to.throw(
expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw(
'Boolean cannot represent a non boolean value: ENUM_VALUE',
);
});
Expand Down Expand Up @@ -561,44 +561,44 @@ describe('Type System: Specified scalar types', () => {
);
});

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

expect(parseConstLiteral('""')).to.equal('');
expect(parseConstLiteral('"1"')).to.equal('1');
expect(parseConstLiteral('"foo"')).to.equal('foo');
expect(parseConstLiteral('"""foo"""')).to.equal('foo');
expect(parseConstLiteral('1')).to.equal('1');
expect(parseConstLiteral('0')).to.equal('0');
expect(parseConstLiteral('-1')).to.equal('-1');
expect(coerceInputLiteral('""')).to.equal('');
expect(coerceInputLiteral('"1"')).to.equal('1');
expect(coerceInputLiteral('"foo"')).to.equal('foo');
expect(coerceInputLiteral('"""foo"""')).to.equal('foo');
expect(coerceInputLiteral('1')).to.equal('1');
expect(coerceInputLiteral('0')).to.equal('0');
expect(coerceInputLiteral('-1')).to.equal('-1');

// Support arbitrary long numbers even if they can't be represented in JS
expect(parseConstLiteral('90071992547409910')).to.equal(
expect(coerceInputLiteral('90071992547409910')).to.equal(
'90071992547409910',
);
expect(parseConstLiteral('-90071992547409910')).to.equal(
expect(coerceInputLiteral('-90071992547409910')).to.equal(
'-90071992547409910',
);

expect(() => parseConstLiteral('null')).to.throw(
expect(() => coerceInputLiteral('null')).to.throw(
'ID cannot represent a non-string and non-integer value: null',
);
expect(() => parseConstLiteral('0.1')).to.throw(
expect(() => coerceInputLiteral('0.1')).to.throw(
'ID cannot represent a non-string and non-integer value: 0.1',
);
expect(() => parseConstLiteral('false')).to.throw(
expect(() => coerceInputLiteral('false')).to.throw(
'ID cannot represent a non-string and non-integer value: false',
);
expect(() => parseConstLiteral('["1"]')).to.throw(
expect(() => coerceInputLiteral('["1"]')).to.throw(
'ID cannot represent a non-string and non-integer value: ["1"]',
);
expect(() => parseConstLiteral('{ value: "1" }')).to.throw(
expect(() => coerceInputLiteral('{ value: "1" }')).to.throw(
'ID cannot represent a non-string and non-integer value: { value: "1" }',
);
expect(() => parseConstLiteral('ENUM_VALUE')).to.throw(
expect(() => coerceInputLiteral('ENUM_VALUE')).to.throw(
'ID cannot represent a non-string and non-integer value: ENUM_VALUE',
);
});
Expand Down
Loading

0 comments on commit 805e3c3

Please sign in to comment.