@@ -35,7 +35,6 @@ import type {
35
35
ScalarTypeExtensionNode ,
36
36
UnionTypeDefinitionNode ,
37
37
UnionTypeExtensionNode ,
38
- ValueNode ,
39
38
} from '../language/ast.js' ;
40
39
import { Kind } from '../language/kinds.js' ;
41
40
import { print } from '../language/printer.js' ;
@@ -551,22 +550,52 @@ export interface GraphQLScalarTypeExtensions {
551
550
* Example:
552
551
*
553
552
* ```ts
553
+ * function ensureOdd(value) {
554
+ * if (!Number.isFinite(value)) {
555
+ * throw new Error(
556
+ * `Scalar "Odd" cannot represent "${value}" since it is not a finite number.`,
557
+ * );
558
+ * }
559
+ *
560
+ * if (value % 2 === 0) {
561
+ * throw new Error(`Scalar "Odd" cannot represent "${value}" since it is even.`);
562
+ * }
563
+ * }
564
+ *
554
565
* const OddType = new GraphQLScalarType({
555
566
* name: 'Odd',
556
567
* serialize(value) {
557
- * if (!Number.isFinite(value)) {
558
- * throw new Error(
559
- * `Scalar "Odd" cannot represent "${value}" since it is not a finite number.`,
560
- * );
561
- * }
562
- *
563
- * if (value % 2 === 0) {
564
- * throw new Error(`Scalar "Odd" cannot represent "${value}" since it is even.`);
565
- * }
566
- * return value;
568
+ * return ensureOdd(value);
569
+ * },
570
+ * parseValue(value) {
571
+ * return ensureOdd(value);
572
+ * }
573
+ * valueToLiteral(value) {
574
+ * return parse(`${ensureOdd(value)`);
567
575
* }
568
576
* });
569
577
* ```
578
+ *
579
+ * Custom scalars behavior is defined via the following functions:
580
+ *
581
+ * - serialize(value): Implements "Result Coercion". Given an internal value,
582
+ * produces an external value valid for this type. Returns undefined or
583
+ * throws an error to indicate invalid values.
584
+ *
585
+ * - parseValue(value): Implements "Input Coercion" for values. Given an
586
+ * external value (for example, variable values), produces an internal value
587
+ * valid for this type. Returns undefined or throws an error to indicate
588
+ * invalid values.
589
+ *
590
+ * - parseLiteral(ast): Implements "Input Coercion" for literals. Given an
591
+ * GraphQL literal (AST) (for example, an argument value), produces an
592
+ * internal value valid for this type. Returns undefined or throws an error
593
+ * to indicate invalid values.
594
+ *
595
+ * - valueToLiteral(value): Converts an external value to a GraphQL
596
+ * literal (AST). Returns undefined or throws an error to indicate
597
+ * invalid values.
598
+ *
570
599
*/
571
600
export class GraphQLScalarType <
572
601
TInternal = unknown ,
@@ -578,6 +607,7 @@ export class GraphQLScalarType<
578
607
serialize : GraphQLScalarSerializer < TExternal > ;
579
608
parseValue : GraphQLScalarValueParser < TInternal > ;
580
609
parseLiteral : GraphQLScalarLiteralParser < TInternal > ;
610
+ valueToLiteral : GraphQLScalarValueToLiteral | undefined ;
581
611
extensions : Readonly < GraphQLScalarTypeExtensions > ;
582
612
astNode : Maybe < ScalarTypeDefinitionNode > ;
583
613
extensionASTNodes : ReadonlyArray < ScalarTypeExtensionNode > ;
@@ -595,8 +625,8 @@ export class GraphQLScalarType<
595
625
config . serialize ?? ( identityFunc as GraphQLScalarSerializer < TExternal > ) ;
596
626
this . parseValue = parseValue ;
597
627
this . parseLiteral =
598
- config . parseLiteral ??
599
- ( ( node , variables ) => parseValue ( valueFromASTUntyped ( node , variables ) ) ) ;
628
+ config . parseLiteral ?? ( ( node ) => parseValue ( valueFromASTUntyped ( node ) ) ) ;
629
+ this . valueToLiteral = config . valueToLiteral ;
600
630
this . extensions = toObjMap ( config . extensions ) ;
601
631
this . astNode = config . astNode ;
602
632
this . extensionASTNodes = config . extensionASTNodes ?? [ ] ;
@@ -622,6 +652,7 @@ export class GraphQLScalarType<
622
652
serialize : this . serialize ,
623
653
parseValue : this . parseValue ,
624
654
parseLiteral : this . parseLiteral ,
655
+ valueToLiteral : this . valueToLiteral ,
625
656
extensions : this . extensions ,
626
657
astNode : this . astNode ,
627
658
extensionASTNodes : this . extensionASTNodes ,
@@ -638,9 +669,12 @@ export type GraphQLScalarValueParser<TInternal> = (
638
669
) => TInternal ;
639
670
640
671
export type GraphQLScalarLiteralParser < TInternal > = (
641
- valueNode : ValueNode ,
642
- variables ?: Maybe < ObjMap < unknown > > ,
643
- ) => TInternal ;
672
+ valueNode : ConstValueNode ,
673
+ ) => Maybe < TInternal > ;
674
+
675
+ export type GraphQLScalarValueToLiteral = (
676
+ inputValue : unknown ,
677
+ ) => ConstValueNode | undefined ;
644
678
645
679
export interface GraphQLScalarTypeConfig < TInternal , TExternal > {
646
680
name : string ;
@@ -652,6 +686,8 @@ export interface GraphQLScalarTypeConfig<TInternal, TExternal> {
652
686
parseValue ?: GraphQLScalarValueParser < TInternal > | undefined ;
653
687
/** Parses an externally provided literal value to use as an input. */
654
688
parseLiteral ?: GraphQLScalarLiteralParser < TInternal > | undefined ;
689
+ /** Translates an externally provided value to a literal (AST). */
690
+ valueToLiteral ?: GraphQLScalarValueToLiteral | undefined ;
655
691
extensions ?: Maybe < Readonly < GraphQLScalarTypeExtensions > > ;
656
692
astNode ?: Maybe < ScalarTypeDefinitionNode > ;
657
693
extensionASTNodes ?: Maybe < ReadonlyArray < ScalarTypeExtensionNode > > ;
@@ -1381,10 +1417,7 @@ export class GraphQLEnumType /* <T> */ extends GraphQLSchemaElement {
1381
1417
return enumValue . value ;
1382
1418
}
1383
1419
1384
- parseLiteral (
1385
- valueNode : ValueNode ,
1386
- _variables : Maybe < ObjMap < unknown > > ,
1387
- ) : Maybe < any > /* T */ {
1420
+ parseLiteral ( valueNode : ConstValueNode ) : Maybe < any > /* T */ {
1388
1421
// Note: variables will be resolved to a value before calling this function.
1389
1422
if ( valueNode . kind !== Kind . ENUM ) {
1390
1423
const valueStr = print ( valueNode ) ;
@@ -1407,6 +1440,12 @@ export class GraphQLEnumType /* <T> */ extends GraphQLSchemaElement {
1407
1440
return enumValue . value ;
1408
1441
}
1409
1442
1443
+ valueToLiteral ( value : unknown ) : ConstValueNode | undefined {
1444
+ if ( typeof value === 'string' && this . getValue ( value ) ) {
1445
+ return { kind : Kind . ENUM , value } ;
1446
+ }
1447
+ }
1448
+
1410
1449
toConfig ( ) : GraphQLEnumTypeNormalizedConfig {
1411
1450
return {
1412
1451
name : this . name ,
0 commit comments