Pothos GraphQL
Searching...

Scalars

Adding Custom GraphQL Scalars

To add a custom scalar that has been implemented as GraphQLScalar from graphql-js you need to provide some type information in SchemaTypes generic parameter of the builder:

const builder = new SchemaBuilder<{
  Scalars: {
    Date: {
      Input: Date;
      Output: Date;
    };
  };
}>({});

builder.addScalarType('Date', CustomDateScalar);

The Input type is the type that will be used when the type is used in an argument or InputObject. The Output type is used to validate the resolvers return the correct value when using the scalar in their return type.

For many scalars Input and Outout will be the same, but they do not always need to match. The Scalars generic can be used to change types for the built-in scalars.

For example, the defaults for the ID scalar might not be exactly what you want, you can customize the values like so:

const builder = new SchemaBuilder<{
  Scalars: {
    ID: {
      // type all ID arguments and input values as string
      Input: string;
      // Allow resolvers for ID fields to return strings, numbers, or bigints
      Output: string | number | bigint;
    };
  };
}>({});

Adding Scalars from graphql-scalars

Similarly to adding your own custom scalars, you can utilize scalars from the graphql-scalars library by also providing the types through the SchemaTypes generic parameter.

Note that when implementing the graphql-scalars library, the best types to use for Input and Output types are not always intuitive. For example, you might assume that the JSON type from graphql-scalars would utilize the global JSON type, or another JSON type imported from a library that tries to enumarate potential JSON values, but it is ussually better to just use unknown. A good place to start if you are unsure what type to use it the check the codegenScalarType inside file where the scalar is defined by graphql-scalars (BigInt scalar definition, for reference). This isn't defined for all scalars, and some scalars use any in which case unknown might be a better option.

import { DateResolver, JSONResolver } from 'graphql-scalars';

const builder = new SchemaBuilder<{
  Scalars: {
    JSON: {
      Input: unknown;
      Output: unknown;
    };
    Date: {
      Input: Date;
      Output: Date;
    };
  };
}>({});

builder.addScalarType('JSON', JSONResolver);
builder.addScalarType('Date', DateResolver);

Defining your own scalars

const builder = new SchemaBuilder<{
  Scalars: {
    PositiveInt: {
      Input: number;
      Output: number;
    };
  };
}>({});

builder.scalarType('PositiveInt', {
  serialize: (n) => n,
  parseValue: (n) => {
    if (n >= 0) {
      return n;
    }

    throw new Error('Value must be positive');
  },
});

Using scalars

builder.queryFields((t) => ({
  date: t.field({
    type: 'Date',
    resolve: () => new Date(),
  }),

  positive: t.field({
    type: 'PositiveInt',
    resolve: () => 5,
  }),
}));