Skip to content

Commit 55e3e32

Browse files
committed
WIP
1 parent f381c40 commit 55e3e32

22 files changed

+316
-51
lines changed

src/index.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ export {
407407
// DEPRECATED: use coerceInputLiteral
408408
valueFromAST,
409409
// Create a JavaScript value from a GraphQL language AST without a Type.
410+
// DEPRECATED: use literalToValue
410411
valueFromASTUntyped,
411412
// Create a GraphQL language AST from a JavaScript value.
412413
// DEPRECATED: use valueToLiteral
@@ -417,6 +418,8 @@ export {
417418
visitWithTypeInfo,
418419
// Create a GraphQL Literal AST from a JavaScript input value.
419420
valueToLiteral,
421+
// Create a JavaScript input value from a GraphQL Literal AST.
422+
literalToValue,
420423
// Coerces a GraphQL Literal with a GraphQL type.
421424
coerceInputLiteral,
422425
// Coerces a JavaScript value with a GraphQL type, or produces errors.

src/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ export {
396396
// DEPRECATED: use coerceInputLiteral
397397
valueFromAST,
398398
// Create a JavaScript value from a GraphQL language AST without a Type.
399+
// DEPRECATED: use literalToValue
399400
valueFromASTUntyped,
400401
// Create a GraphQL language AST from a JavaScript value.
401402
// DEPRECATED: use valueToLiteral
@@ -406,6 +407,8 @@ export {
406407
visitWithTypeInfo,
407408
// Create a GraphQL Literal AST from a JavaScript input value.
408409
valueToLiteral,
410+
// Create a JavaScript input value from a GraphQL Literal AST.
411+
literalToValue,
409412
// Coerces a GraphQL Literal with a GraphQL type.
410413
coerceInputLiteral,
411414
// Coerces a JavaScript value with a GraphQL type, or produces errors.

src/type/__tests__/definition-test.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
GraphQLEnumType,
1818
GraphQLInputObjectType,
1919
} from '../definition';
20+
import { coerceInputLiteral } from '../../utilities/coerceInputLiteral';
2021

2122
const ScalarType = new GraphQLScalarType({ name: 'Scalar' });
2223
const ObjectType = new GraphQLObjectType({ name: 'Object', fields: {} });
@@ -72,7 +73,6 @@ describe('Type System: Scalars', () => {
7273

7374
expect(scalar.serialize).to.equal(identityFunc);
7475
expect(scalar.parseValue).to.equal(identityFunc);
75-
expect(scalar.parseLiteral).to.be.a('function');
7676
});
7777

7878
it('use parseValue for parsing literals if parseLiteral omitted', () => {
@@ -83,14 +83,16 @@ describe('Type System: Scalars', () => {
8383
},
8484
});
8585

86-
expect(scalar.parseLiteral(parseValue('null'))).to.equal(
87-
'parseValue: null',
86+
expect(coerceInputLiteral(parseValue('null'), scalar)).to.equal(
87+
null,
8888
);
89-
expect(scalar.parseLiteral(parseValue('{ foo: "bar" }'))).to.equal(
89+
expect(coerceInputLiteral(parseValue('{ foo: "bar" }'), scalar)).to.equal(
9090
'parseValue: { foo: "bar" }',
9191
);
9292
expect(
93-
scalar.parseLiteral(parseValue('{ foo: { bar: $var } }'), { var: 'baz' }),
93+
coerceInputLiteral(parseValue('{ foo: { bar: $var } }'), scalar, {
94+
var: 'baz',
95+
}),
9496
).to.equal('parseValue: { foo: { bar: "baz" } }');
9597
});
9698

src/type/__tests__/scalars-test.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from 'chai';
22
import { describe, it } from 'mocha';
33

4-
import { parseValue as parseValueToAST } from '../../language/parser';
4+
import { parseConstValue } from '../../language/parser';
55

66
import {
77
GraphQLID,
@@ -66,7 +66,7 @@ describe('Type System: Specified scalar types', () => {
6666

6767
it('parseLiteral', () => {
6868
function parseLiteral(str: string) {
69-
return GraphQLInt.parseLiteral(parseValueToAST(str), undefined);
69+
return GraphQLInt.parseLiteral?.(parseConstValue(str));
7070
}
7171

7272
expect(parseLiteral('1')).to.equal(1);
@@ -231,7 +231,7 @@ describe('Type System: Specified scalar types', () => {
231231

232232
it('parseLiteral', () => {
233233
function parseLiteral(str: string) {
234-
return GraphQLFloat.parseLiteral(parseValueToAST(str), undefined);
234+
return GraphQLFloat.parseLiteral?.(parseConstValue(str));
235235
}
236236

237237
expect(parseLiteral('1')).to.equal(1);
@@ -344,7 +344,7 @@ describe('Type System: Specified scalar types', () => {
344344

345345
it('parseLiteral', () => {
346346
function parseLiteral(str: string) {
347-
return GraphQLString.parseLiteral(parseValueToAST(str), undefined);
347+
return GraphQLString.parseLiteral?.(parseConstValue(str));
348348
}
349349

350350
expect(parseLiteral('"foo"')).to.equal('foo');
@@ -456,7 +456,7 @@ describe('Type System: Specified scalar types', () => {
456456

457457
it('parseLiteral', () => {
458458
function parseLiteral(str: string) {
459-
return GraphQLBoolean.parseLiteral(parseValueToAST(str), undefined);
459+
return GraphQLBoolean.parseLiteral?.(parseConstValue(str));
460460
}
461461

462462
expect(parseLiteral('true')).to.equal(true);
@@ -571,7 +571,7 @@ describe('Type System: Specified scalar types', () => {
571571

572572
it('parseLiteral', () => {
573573
function parseLiteral(str: string) {
574-
return GraphQLID.parseLiteral(parseValueToAST(str), undefined);
574+
return GraphQLID.parseLiteral?.(parseConstValue(str));
575575
}
576576

577577
expect(parseLiteral('""')).to.equal('');

src/type/definition.d.ts

+13-11
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
OperationDefinitionNode,
2323
FieldNode,
2424
FragmentDefinitionNode,
25-
ValueNode,
2625
ConstValueNode,
2726
ScalarTypeExtensionNode,
2827
UnionTypeExtensionNode,
@@ -316,8 +315,9 @@ export class GraphQLScalarType {
316315
specifiedByURL: Maybe<string>;
317316
serialize: GraphQLScalarSerializer<unknown>;
318317
parseValue: GraphQLScalarValueParser<unknown>;
319-
parseLiteral: GraphQLScalarLiteralParser<unknown>;
318+
parseLiteral: Maybe<GraphQLScalarLiteralParser<unknown>>;
320319
valueToLiteral: Maybe<GraphQLScalarValueToLiteral>;
320+
literalToValue: Maybe<GraphQLScalarLiteralToValue>;
321321
extensions: Maybe<Readonly<GraphQLScalarTypeExtensions>>;
322322
astNode: Maybe<ScalarTypeDefinitionNode>;
323323
extensionASTNodes: ReadonlyArray<ScalarTypeExtensionNode>;
@@ -328,8 +328,9 @@ export class GraphQLScalarType {
328328
specifiedByURL: Maybe<string>;
329329
serialize: GraphQLScalarSerializer<unknown>;
330330
parseValue: GraphQLScalarValueParser<unknown>;
331-
parseLiteral: GraphQLScalarLiteralParser<unknown>;
331+
parseLiteral: Maybe<GraphQLScalarLiteralParser<unknown>>;
332332
valueToLiteral: Maybe<GraphQLScalarValueToLiteral>;
333+
literalToValue: Maybe<GraphQLScalarLiteralToValue>;
333334
extensions: Maybe<Readonly<GraphQLScalarTypeExtensions>>;
334335
extensionASTNodes: ReadonlyArray<ScalarTypeExtensionNode>;
335336
};
@@ -346,13 +347,14 @@ export type GraphQLScalarValueParser<TInternal> = (
346347
value: unknown,
347348
) => Maybe<TInternal>;
348349
export type GraphQLScalarLiteralParser<TInternal> = (
349-
valueNode: ValueNode,
350-
variables: Maybe<ObjMap<unknown>>,
350+
valueNode: ConstValueNode,
351351
) => Maybe<TInternal>;
352-
353352
export type GraphQLScalarValueToLiteral = (
354353
inputValue: unknown,
355354
) => Maybe<ConstValueNode>;
355+
export type GraphQLScalarLiteralToValue = (
356+
valueNode: ConstValueNode,
357+
) => unknown;
356358

357359
export interface GraphQLScalarTypeConfig<TInternal, TExternal> {
358360
name: string;
@@ -364,8 +366,10 @@ export interface GraphQLScalarTypeConfig<TInternal, TExternal> {
364366
parseValue?: GraphQLScalarValueParser<TInternal>;
365367
// Parses an externally provided literal value to use as an input.
366368
parseLiteral?: GraphQLScalarLiteralParser<TInternal>;
367-
// Translates an external input value to an external literal (AST).
369+
// Translates an external input value to a literal (AST).
368370
valueToLiteral?: Maybe<GraphQLScalarValueToLiteral>;
371+
// Translates a literal (AST) to external input value.
372+
literalToValue?: Maybe<GraphQLScalarLiteralToValue>;
369373
extensions?: Maybe<Readonly<GraphQLScalarTypeExtensions>>;
370374
astNode?: Maybe<ScalarTypeDefinitionNode>;
371375
extensionASTNodes?: Maybe<ReadonlyArray<ScalarTypeExtensionNode>>;
@@ -791,11 +795,9 @@ export class GraphQLEnumType {
791795
getValue(name: string): Maybe<GraphQLEnumValue>;
792796
serialize(value: unknown): Maybe<string>;
793797
parseValue(value: unknown): Maybe<any>;
794-
parseLiteral(
795-
valueNode: ValueNode,
796-
_variables: Maybe<ObjMap<unknown>>,
797-
): Maybe<any>;
798+
parseLiteral(valueNode: ConstValueNode): Maybe<any>;
798799
valueToLiteral(value: unknown): Maybe<ConstValueNode>;
800+
literalToValue(valueNode: ConstValueNode): unknown;
799801

800802
toConfig(): GraphQLEnumTypeConfig & {
801803
extensions: Maybe<Readonly<GraphQLEnumTypeExtensions>>;

src/type/definition.js

+19-12
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ import type {
4545
ConstValueNode,
4646
} from '../language/ast';
4747

48-
import { valueFromASTUntyped } from '../utilities/valueFromASTUntyped';
49-
5048
import type { GraphQLSchema } from './schema';
5149

5250
// Predicates & Assertions
@@ -562,8 +560,9 @@ export class GraphQLScalarType {
562560
specifiedByURL: ?string;
563561
serialize: GraphQLScalarSerializer<mixed>;
564562
parseValue: GraphQLScalarValueParser<mixed>;
565-
parseLiteral: GraphQLScalarLiteralParser<mixed>;
563+
parseLiteral: ?GraphQLScalarLiteralParser<mixed>;
566564
valueToLiteral: ?GraphQLScalarValueToLiteral;
565+
literalToValue: ?GraphQLScalarLiteralToValue;
567566
extensions: ?ReadOnlyObjMap<mixed>;
568567
astNode: ?ScalarTypeDefinitionNode;
569568
extensionASTNodes: $ReadOnlyArray<ScalarTypeExtensionNode>;
@@ -575,10 +574,9 @@ export class GraphQLScalarType {
575574
this.specifiedByURL = config.specifiedByURL;
576575
this.serialize = config.serialize ?? identityFunc;
577576
this.parseValue = parseValue;
578-
this.parseLiteral =
579-
config.parseLiteral ??
580-
((node, variables) => parseValue(valueFromASTUntyped(node, variables)));
577+
this.parseLiteral = config.parseLiteral;
581578
this.valueToLiteral = config.valueToLiteral;
579+
this.literalToValue = config.literalToValue;
582580
this.extensions = config.extensions && toObjMap(config.extensions);
583581
this.astNode = config.astNode;
584582
this.extensionASTNodes = config.extensionASTNodes ?? [];
@@ -615,6 +613,7 @@ export class GraphQLScalarType {
615613
parseValue: this.parseValue,
616614
parseLiteral: this.parseLiteral,
617615
valueToLiteral: this.valueToLiteral,
616+
literalToValue: this.literalToValue,
618617
extensions: this.extensions,
619618
astNode: this.astNode,
620619
extensionASTNodes: this.extensionASTNodes,
@@ -644,14 +643,15 @@ export type GraphQLScalarValueParser<TInternal> = (
644643
) => ?TInternal;
645644
646645
export type GraphQLScalarLiteralParser<TInternal> = (
647-
valueNode: ValueNode,
648-
variables: ?ObjMap<mixed>,
646+
valueNode: ConstValueNode,
649647
) => ?TInternal;
650648
651649
export type GraphQLScalarValueToLiteral = (
652650
inputValue: mixed,
653651
) => ?ConstValueNode;
654652
653+
export type GraphQLScalarLiteralToValue = (valueNode: ConstValueNode) => mixed;
654+
655655
export type GraphQLScalarTypeConfig<TInternal, TExternal> = {|
656656
name: string,
657657
description?: ?string,
@@ -661,9 +661,11 @@ export type GraphQLScalarTypeConfig<TInternal, TExternal> = {|
661661
// Parses an externally provided value to use as an input.
662662
parseValue?: GraphQLScalarValueParser<TInternal>,
663663
// Parses an externally provided literal value to use as an input.
664-
parseLiteral?: GraphQLScalarLiteralParser<TInternal>,
665-
// Translates an external input value to an external literal (AST).
664+
parseLiteral?: ?GraphQLScalarLiteralParser<TInternal>,
665+
// Translates an external input value to a literal (AST).
666666
valueToLiteral?: ?GraphQLScalarValueToLiteral,
667+
// Translates a literal (AST) to external input value.
668+
literalToValue?: ?GraphQLScalarLiteralToValue,
667669
extensions?: ?ReadOnlyObjMapLike<mixed>,
668670
astNode?: ?ScalarTypeDefinitionNode,
669671
extensionASTNodes?: ?$ReadOnlyArray<ScalarTypeExtensionNode>,
@@ -673,7 +675,6 @@ type GraphQLScalarTypeNormalizedConfig = {|
673675
...GraphQLScalarTypeConfig<mixed, mixed>,
674676
serialize: GraphQLScalarSerializer<mixed>,
675677
parseValue: GraphQLScalarValueParser<mixed>,
676-
parseLiteral: GraphQLScalarLiteralParser<mixed>,
677678
extensions: ?ReadOnlyObjMap<mixed>,
678679
extensionASTNodes: $ReadOnlyArray<ScalarTypeExtensionNode>,
679680
|};
@@ -1331,7 +1332,7 @@ export class GraphQLEnumType /* <T> */ {
13311332
return enumValue.value;
13321333
}
13331334

1334-
parseLiteral(valueNode: ValueNode, _variables: ?ObjMap<mixed>): ?any /* T */ {
1335+
parseLiteral(valueNode: ValueNode): ?any /* T */ {
13351336
// Note: variables will be resolved to a value before calling this function.
13361337
if (valueNode.kind !== Kind.ENUM) {
13371338
const valueStr = print(valueNode);
@@ -1364,6 +1365,12 @@ export class GraphQLEnumType /* <T> */ {
13641365
}
13651366
}
13661367

1368+
literalToValue(valueNode: ConstValueNode): mixed {
1369+
if (valueNode.kind === Kind.ENUM) {
1370+
return valueNode.value;
1371+
}
1372+
}
1373+
13671374
toConfig(): GraphQLEnumTypeNormalizedConfig {
13681375
const values = keyValMap(
13691376
this.getValues(),

src/type/scalars.js

+6
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,12 @@ export const GraphQLID: GraphQLScalarType = new GraphQLScalarType({
278278
return { kind: Kind.STRING, value };
279279
}
280280
},
281+
literalToValue(valueNode: ConstValueNode): mixed {
282+
// ID Int literals are represented as string values.
283+
if (valueNode.kind === Kind.INT || valueNode.kind === Kind.STRING) {
284+
return valueNode.value;
285+
}
286+
},
281287
});
282288

283289
export const specifiedScalarTypes: $ReadOnlyArray<GraphQLScalarType> = Object.freeze(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { expect } from 'chai';
2+
import { describe, it } from 'mocha';
3+
4+
// import {
5+
// GraphQLID,
6+
// GraphQLInt,
7+
// GraphQLFloat,
8+
// GraphQLString,
9+
// GraphQLBoolean,
10+
// } from '../../type/scalars';
11+
// import {
12+
// GraphQLList,
13+
// GraphQLNonNull,
14+
// GraphQLScalarType,
15+
// GraphQLEnumType,
16+
// GraphQLInputObjectType,
17+
// } from '../../type/definition';
18+
19+
import { parseConstValue } from '../../language/parser';
20+
import { literalToValue } from '../literalToValue';
21+
22+
describe('literalToValue', () => {
23+
it('converts null', () => {
24+
expect(literalToValue(parseConstValue('null'))).to.equal(null);
25+
});
26+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { expect } from 'chai';
2+
import { describe, it } from 'mocha';
3+
4+
import type { ValueNode } from '../../language/ast';
5+
import { parseValue as _parseValue } from '../../language/parser';
6+
import { replaceASTVariables } from '../replaceASTVariables';
7+
8+
function parseValue(ast: string): ValueNode {
9+
return _parseValue(ast, { noLocation: true });
10+
}
11+
12+
describe('replaceASTVariables', () => {
13+
it('does not change simple AST', () => {
14+
const ast = parseValue('null')
15+
expect(replaceASTVariables(ast, undefined)).to.equal(ast);
16+
});
17+
18+
it('replaces simple Variables', () => {
19+
const ast = parseValue('$var')
20+
expect(replaceASTVariables(ast, {var:123})).to.deep.equal(parseValue('123'));
21+
});
22+
23+
it('replaces nested Variables', () => {
24+
const ast = parseValue('{ foo: [ $var ], bar: $var }')
25+
expect(replaceASTVariables(ast, {var:123})).to.deep.equal(parseValue('{ foo: [ 123 ], bar: 123 }'));
26+
});
27+
28+
it('replaces missing Variables with null', () => {
29+
const ast = parseValue('$var')
30+
expect(replaceASTVariables(ast, undefined)).to.deep.equal(parseValue('null'));
31+
});
32+
33+
it('replaces missing Variables in lists with null', () => {
34+
const ast = parseValue('[1, $var]')
35+
expect(replaceASTVariables(ast, undefined)).to.deep.equal(parseValue('[1, null]'));
36+
});
37+
38+
it('omits missing Variables from objects', () => {
39+
const ast = parseValue('{ foo: 1, bar: $var }')
40+
expect(replaceASTVariables(ast, undefined)).to.deep.equal(parseValue('{ foo: 1 }'));
41+
});
42+
});

0 commit comments

Comments
 (0)