UNPKG

@cran/lib.gql.core

Version:

GQL Core Functionality

93 lines (77 loc) 2.23 kB
import type { Plugin } from "../plugins/Plugin"; import { type Derivative, parseError, parseLiteral } from "./parse"; import { GraphQLScalarType, type GraphQLScalarValueParser, type ValueNode, } from "graphql"; export namespace createScalar { export interface Types { string : string; number : number; boolean: boolean; object : Record<string, Derivative>; array : Array<Derivative>; } export type Invalid = ( reason?: string ) => string; export type Casts = { [Key in keyof Types]?: boolean | (( value: Types[Key], invalid: Invalid ) => string); }; export type Serializer = ( value: unknown ) => unknown; } function getTypeOf ( value: Derivative ) { return ( value instanceof Array ? "array" : typeof value ) as keyof createScalar.Casts; } export function createScalar ( name: string, description: string, casts: createScalar.Casts, serialize?: createScalar.Serializer | undefined ) { const asType = createScalarCast(name, casts); return { typeDefs : `scalar ${name}`, resolvers: { [name]: new GraphQLScalarType({ name, description, serialize : serialize!, parseValue: asType, parseLiteral ( ast, variables ) { return asType(parseLiteral(name, ast, variables)); }, }), }, } as const as Plugin; } export function createScalarCast ( name: string, casts: createScalar.Casts ) { return function asType ( value: Derivative, ast?: ValueNode ) { if (null === value) { return null; } const type = getTypeOf(value); let result: unknown = null; try { const cast = casts[type]; if (cast instanceof Function) { result = cast(value as never, function invalid ( reason ) { parseError(type, ast ?? value, reason); }); } else if (cast) { switch (type) { case "object": case "array": result = JSON.stringify(value); break; default: result = String(value); break; } } } catch { /* ignored */ } if (null === result) { parseError(name, ast ?? value); } return result; } as GraphQLScalarValueParser<unknown>; }