@@ -35,7 +35,6 @@ import type {
3535 ScalarTypeExtensionNode ,
3636 UnionTypeDefinitionNode ,
3737 UnionTypeExtensionNode ,
38- ValueNode ,
3938} from '../language/ast.js' ;
4039import { Kind } from '../language/kinds.js' ;
4140import { print } from '../language/printer.js' ;
@@ -551,22 +550,52 @@ export interface GraphQLScalarTypeExtensions {
551550 * Example:
552551 *
553552 * ```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+ *
554565 * const OddType = new GraphQLScalarType({
555566 * name: 'Odd',
556567 * 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)`);
567575 * }
568576 * });
569577 * ```
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+ *
570599 */
571600export class GraphQLScalarType <
572601 TInternal = unknown ,
@@ -578,6 +607,7 @@ export class GraphQLScalarType<
578607 serialize : GraphQLScalarSerializer < TExternal > ;
579608 parseValue : GraphQLScalarValueParser < TInternal > ;
580609 parseLiteral : GraphQLScalarLiteralParser < TInternal > ;
610+ valueToLiteral : GraphQLScalarValueToLiteral | undefined ;
581611 extensions : Readonly < GraphQLScalarTypeExtensions > ;
582612 astNode : Maybe < ScalarTypeDefinitionNode > ;
583613 extensionASTNodes : ReadonlyArray < ScalarTypeExtensionNode > ;
@@ -595,8 +625,8 @@ export class GraphQLScalarType<
595625 config . serialize ?? ( identityFunc as GraphQLScalarSerializer < TExternal > ) ;
596626 this . parseValue = parseValue ;
597627 this . parseLiteral =
598- config . parseLiteral ??
599- ( ( node , variables ) => parseValue ( valueFromASTUntyped ( node , variables ) ) ) ;
628+ config . parseLiteral ?? ( ( node ) => parseValue ( valueFromASTUntyped ( node ) ) ) ;
629+ this . valueToLiteral = config . valueToLiteral ;
600630 this . extensions = toObjMap ( config . extensions ) ;
601631 this . astNode = config . astNode ;
602632 this . extensionASTNodes = config . extensionASTNodes ?? [ ] ;
@@ -622,6 +652,7 @@ export class GraphQLScalarType<
622652 serialize : this . serialize ,
623653 parseValue : this . parseValue ,
624654 parseLiteral : this . parseLiteral ,
655+ valueToLiteral : this . valueToLiteral ,
625656 extensions : this . extensions ,
626657 astNode : this . astNode ,
627658 extensionASTNodes : this . extensionASTNodes ,
@@ -638,9 +669,12 @@ export type GraphQLScalarValueParser<TInternal> = (
638669) => TInternal ;
639670
640671export 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 ;
644678
645679export interface GraphQLScalarTypeConfig < TInternal , TExternal > {
646680 name : string ;
@@ -652,6 +686,8 @@ export interface GraphQLScalarTypeConfig<TInternal, TExternal> {
652686 parseValue ?: GraphQLScalarValueParser < TInternal > | undefined ;
653687 /** Parses an externally provided literal value to use as an input. */
654688 parseLiteral ?: GraphQLScalarLiteralParser < TInternal > | undefined ;
689+ /** Translates an externally provided value to a literal (AST). */
690+ valueToLiteral ?: GraphQLScalarValueToLiteral | undefined ;
655691 extensions ?: Maybe < Readonly < GraphQLScalarTypeExtensions > > ;
656692 astNode ?: Maybe < ScalarTypeDefinitionNode > ;
657693 extensionASTNodes ?: Maybe < ReadonlyArray < ScalarTypeExtensionNode > > ;
@@ -1384,10 +1420,7 @@ export class GraphQLEnumType /* <T> */ extends GraphQLSchemaElement {
13841420 return enumValue . value ;
13851421 }
13861422
1387- parseLiteral (
1388- valueNode : ValueNode ,
1389- _variables : Maybe < ObjMap < unknown > > ,
1390- ) : Maybe < any > /* T */ {
1423+ parseLiteral ( valueNode : ConstValueNode ) : Maybe < any > /* T */ {
13911424 // Note: variables will be resolved to a value before calling this function.
13921425 if ( valueNode . kind !== Kind . ENUM ) {
13931426 const valueStr = print ( valueNode ) ;
@@ -1410,6 +1443,12 @@ export class GraphQLEnumType /* <T> */ extends GraphQLSchemaElement {
14101443 return enumValue . value ;
14111444 }
14121445
1446+ valueToLiteral ( value : unknown ) : ConstValueNode | undefined {
1447+ if ( typeof value === 'string' && this . getValue ( value ) ) {
1448+ return { kind : Kind . ENUM , value } ;
1449+ }
1450+ }
1451+
14131452 toConfig ( ) : GraphQLEnumTypeNormalizedConfig {
14141453 return {
14151454 name : this . name ,
0 commit comments