Skip to content

Commit 4dfae39

Browse files
yaacovCRleebyron
andauthored
Add valueToLiteral() (#3812)
[#3065 rebased on main](#3065). Depends on #3811 @leebyron comments from original PR: > **Provides the "Value to Literal" methods in this [data flow chart](https://user-images.githubusercontent.com/50130/118379946-51ac5300-b593-11eb-839f-c483ecfbc875.png).** > > * Adds `valueToLiteral()` which takes an external input value and translates it to a literal, allowing for custom scalars to define this behavior. > > **This also adds important changes to Input Coercion, especially for custom scalars:** > > * The value provided to `parseLiteral` is now `ConstValueNode` and the second `variables` argument has been removed. For all built-in scalars this has no effect, but any custom scalars which use complex literals no longer need to do variable reconciliation manually (in fact most do not -- this has been an easy subtle bug to miss). > This behavior is possible with the addition of `replaceVariables` Changes to the original: 1. Instead of changing the signature of `parseLiteral()`, a new method `parseConstLiteral()` has been added with the simpler signature. `parseLiteral()` has been marked for deprecation. 2. `replaceVariables()` has access to operation and fragment variables. Co-authored-by: Lee Byron <[email protected]>
1 parent 7dd825e commit 4dfae39

15 files changed

+920
-132
lines changed

integrationTests/ts/kitchenSink-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ new GraphQLScalarType({
88
name: 'SomeScalar',
99
serialize: undefined,
1010
parseValue: undefined,
11-
parseLiteral: undefined,
11+
parseConstLiteral: undefined,
1212
});
1313

1414
new GraphQLError('test', { nodes: undefined });

src/execution/__tests__/variables-test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const TestFaultyScalar = new GraphQLScalarType({
4747
parseValue() {
4848
throw TestFaultyScalarGraphQLError;
4949
},
50-
parseLiteral() {
50+
parseConstLiteral() {
5151
throw TestFaultyScalarGraphQLError;
5252
},
5353
});
@@ -58,7 +58,7 @@ const TestComplexScalar = new GraphQLScalarType({
5858
expect(value).to.equal('SerializedValue');
5959
return 'DeserializedValue';
6060
},
61-
parseLiteral(ast) {
61+
parseConstLiteral(ast) {
6262
expect(ast).to.include({ kind: 'StringValue', value: 'SerializedValue' });
6363
return 'DeserializedValue';
6464
},
@@ -281,7 +281,7 @@ describe('Execute: Handles inputs', () => {
281281
});
282282
});
283283

284-
it('properly runs parseLiteral on complex scalar types', () => {
284+
it('properly runs parseConstLiteral on complex scalar types', () => {
285285
const result = executeQuery(`
286286
{
287287
fieldWithObjectInput(input: {c: "foo", d: "SerializedValue"})

src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,10 @@ export {
445445
// A helper to use within recursive-descent visitors which need to be aware of the GraphQL type system.
446446
TypeInfo,
447447
visitWithTypeInfo,
448+
// Converts a value to a const value by replacing variables.
449+
replaceVariables,
450+
// Create a GraphQL literal (AST) from a JavaScript input value.
451+
valueToLiteral,
448452
// Coerces a JavaScript value to a GraphQL type, or produces errors.
449453
coerceInputValue,
450454
// Coerces a GraphQL literal (AST) to a GraphQL type, or returns undefined.

src/type/__tests__/definition-test.ts

+20-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { identityFunc } from '../../jsutils/identityFunc.js';
55
import { inspect } from '../../jsutils/inspect.js';
66

77
import { Kind } from '../../language/kinds.js';
8-
import { parseValue } from '../../language/parser.js';
8+
import { parseConstValue } from '../../language/parser.js';
99

1010
import type { GraphQLNullableType, GraphQLType } from '../definition.js';
1111
import {
@@ -55,13 +55,13 @@ describe('Type System: Scalars', () => {
5555
).not.to.throw();
5656
});
5757

58-
it('accepts a Scalar type defining parseValue and parseLiteral', () => {
58+
it('accepts a Scalar type defining parseValue and parseConstLiteral', () => {
5959
expect(
6060
() =>
6161
new GraphQLScalarType({
6262
name: 'SomeScalar',
6363
parseValue: dummyFunc,
64-
parseLiteral: dummyFunc,
64+
parseConstLiteral: dummyFunc,
6565
}),
6666
).to.not.throw();
6767
});
@@ -72,25 +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');
7576
});
7677

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

85-
expect(scalar.parseLiteral(parseValue('null'))).to.equal(
86+
expect(scalar.parseConstLiteral(parseConstValue('null'))).to.equal(
8687
'parseValue: null',
8788
);
88-
expect(scalar.parseLiteral(parseValue('{ foo: "bar" }'))).to.equal(
89-
'parseValue: { foo: "bar" }',
90-
);
9189
expect(
92-
scalar.parseLiteral(parseValue('{ foo: { bar: $var } }'), { var: 'baz' }),
93-
).to.equal('parseValue: { foo: { bar: "baz" } }');
90+
scalar.parseConstLiteral(parseConstValue('{ foo: "bar" }')),
91+
).to.equal('parseValue: { foo: "bar" }');
9492
});
9593

9694
it('rejects a Scalar type defining parseLiteral but not parseValue', () => {
@@ -104,6 +102,18 @@ describe('Type System: Scalars', () => {
104102
'SomeScalar must provide both "parseValue" and "parseLiteral" functions.',
105103
);
106104
});
105+
106+
it('rejects a Scalar type defining parseConstLiteral but not parseValue', () => {
107+
expect(
108+
() =>
109+
new GraphQLScalarType({
110+
name: 'SomeScalar',
111+
parseConstLiteral: dummyFunc,
112+
}),
113+
).to.throw(
114+
'SomeScalar must provide both "parseValue" and "parseConstLiteral" functions.',
115+
);
116+
});
107117
});
108118

109119
describe('Type System: Objects', () => {

0 commit comments

Comments
 (0)