@@ -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' ;
@@ -526,22 +525,52 @@ export interface GraphQLScalarTypeExtensions {
526525 * Example:
527526 *
528527 * ```ts
528+ * function ensureOdd(value) {
529+ * if (!Number.isFinite(value)) {
530+ * throw new Error(
531+ * `Scalar "Odd" cannot represent "${value}" since it is not a finite number.`,
532+ * );
533+ * }
534+ *
535+ * if (value % 2 === 0) {
536+ * throw new Error(`Scalar "Odd" cannot represent "${value}" since it is even.`);
537+ * }
538+ * }
539+ *
529540 * const OddType = new GraphQLScalarType({
530541 * name: 'Odd',
531542 * serialize(value) {
532- * if (!Number.isFinite(value)) {
533- * throw new Error(
534- * `Scalar "Odd" cannot represent "${value}" since it is not a finite number.`,
535- * );
536- * }
537- *
538- * if (value % 2 === 0) {
539- * throw new Error(`Scalar "Odd" cannot represent "${value}" since it is even.`);
540- * }
541- * return value;
543+ * return ensureOdd(value);
544+ * },
545+ * parseValue(value) {
546+ * return ensureOdd(value);
547+ * }
548+ * valueToLiteral(value) {
549+ * return parse(`${ensureOdd(value)`);
542550 * }
543551 * });
544552 * ```
553+ *
554+ * Custom scalars behavior is defined via the following functions:
555+ *
556+ * - serialize(value): Implements "Result Coercion". Given an internal value,
557+ * produces an external value valid for this type. Returns undefined or
558+ * throws an error to indicate invalid values.
559+ *
560+ * - parseValue(value): Implements "Input Coercion" for values. Given an
561+ * external value (for example, variable values), produces an internal value
562+ * valid for this type. Returns undefined or throws an error to indicate
563+ * invalid values.
564+ *
565+ * - parseLiteral(ast): Implements "Input Coercion" for literals. Given an
566+ * GraphQL literal (AST) (for example, an argument value), produces an
567+ * internal value valid for this type. Returns undefined or throws an error
568+ * to indicate invalid values.
569+ *
570+ * - valueToLiteral(value): Converts an external value to a GraphQL
571+ * literal (AST). Returns undefined or throws an error to indicate
572+ * invalid values.
573+ *
545574 */
546575export class GraphQLScalarType < TInternal = unknown , TExternal = TInternal > {
547576 name : string ;
@@ -550,6 +579,7 @@ export class GraphQLScalarType<TInternal = unknown, TExternal = TInternal> {
550579 serialize : GraphQLScalarSerializer < TExternal > ;
551580 parseValue : GraphQLScalarValueParser < TInternal > ;
552581 parseLiteral : GraphQLScalarLiteralParser < TInternal > ;
582+ valueToLiteral : GraphQLScalarValueToLiteral | undefined ;
553583 extensions : Readonly < GraphQLScalarTypeExtensions > ;
554584 astNode : Maybe < ScalarTypeDefinitionNode > ;
555585 extensionASTNodes : ReadonlyArray < ScalarTypeExtensionNode > ;
@@ -566,8 +596,8 @@ export class GraphQLScalarType<TInternal = unknown, TExternal = TInternal> {
566596 config . serialize ?? ( identityFunc as GraphQLScalarSerializer < TExternal > ) ;
567597 this . parseValue = parseValue ;
568598 this . parseLiteral =
569- config . parseLiteral ??
570- ( ( node , variables ) => parseValue ( valueFromASTUntyped ( node , variables ) ) ) ;
599+ config . parseLiteral ?? ( ( node ) => parseValue ( valueFromASTUntyped ( node ) ) ) ;
600+ this . valueToLiteral = config . valueToLiteral ;
571601 this . extensions = toObjMap ( config . extensions ) ;
572602 this . astNode = config . astNode ;
573603 this . extensionASTNodes = config . extensionASTNodes ?? [ ] ;
@@ -593,6 +623,7 @@ export class GraphQLScalarType<TInternal = unknown, TExternal = TInternal> {
593623 serialize : this . serialize ,
594624 parseValue : this . parseValue ,
595625 parseLiteral : this . parseLiteral ,
626+ valueToLiteral : this . valueToLiteral ,
596627 extensions : this . extensions ,
597628 astNode : this . astNode ,
598629 extensionASTNodes : this . extensionASTNodes ,
@@ -617,9 +648,12 @@ export type GraphQLScalarValueParser<TInternal> = (
617648) => TInternal ;
618649
619650export type GraphQLScalarLiteralParser < TInternal > = (
620- valueNode : ValueNode ,
621- variables ?: Maybe < ObjMap < unknown > > ,
622- ) => TInternal ;
651+ valueNode : ConstValueNode ,
652+ ) => Maybe < TInternal > ;
653+
654+ export type GraphQLScalarValueToLiteral = (
655+ inputValue : unknown ,
656+ ) => ConstValueNode | undefined ;
623657
624658export interface GraphQLScalarTypeConfig < TInternal , TExternal > {
625659 name : string ;
@@ -631,6 +665,8 @@ export interface GraphQLScalarTypeConfig<TInternal, TExternal> {
631665 parseValue ?: GraphQLScalarValueParser < TInternal > | undefined ;
632666 /** Parses an externally provided literal value to use as an input. */
633667 parseLiteral ?: GraphQLScalarLiteralParser < TInternal > | undefined ;
668+ /** Translates an externally provided value to a literal (AST). */
669+ valueToLiteral ?: GraphQLScalarValueToLiteral | undefined ;
634670 extensions ?: Maybe < Readonly < GraphQLScalarTypeExtensions > > ;
635671 astNode ?: Maybe < ScalarTypeDefinitionNode > ;
636672 extensionASTNodes ?: Maybe < ReadonlyArray < ScalarTypeExtensionNode > > ;
@@ -1374,10 +1410,7 @@ export class GraphQLEnumType /* <T> */ {
13741410 return enumValue . value ;
13751411 }
13761412
1377- parseLiteral (
1378- valueNode : ValueNode ,
1379- _variables : Maybe < ObjMap < unknown > > ,
1380- ) : Maybe < any > /* T */ {
1413+ parseLiteral ( valueNode : ConstValueNode ) : Maybe < any > /* T */ {
13811414 // Note: variables will be resolved to a value before calling this function.
13821415 if ( valueNode . kind !== Kind . ENUM ) {
13831416 const valueStr = print ( valueNode ) ;
@@ -1400,6 +1433,12 @@ export class GraphQLEnumType /* <T> */ {
14001433 return enumValue . value ;
14011434 }
14021435
1436+ valueToLiteral ( value : unknown ) : ConstValueNode | undefined {
1437+ if ( typeof value === 'string' && this . getValue ( value ) ) {
1438+ return { kind : Kind . ENUM , value } ;
1439+ }
1440+ }
1441+
14031442 toConfig ( ) : GraphQLEnumTypeNormalizedConfig {
14041443 const values = keyValMap (
14051444 this . getValues ( ) ,
0 commit comments