Scalars
GraphQL custom scalars can be defined by placing a @gqlScalar
docblock directly before a:
- Type alias declaration
/**
* A description of my custom scalar.
* @gqlScalar <optional name of the scalar, if different from type name>
*/
export type MyCustomString = string;
Built-In Scalars
For built-in GraphQL scalars that don't have a corresponding TypeScript type, Grats ships with type aliases you can import. You may be prompted to use one of these by Grats if you try to use number
in a position from which Grats needs to infer a GraphQL type.
import { Float, Int, ID } from "grats";
/** @gqlType */
class Math {
id: ID;
/** @gqlField */
round(args: { float: Float }): Int {
return Math.round(args.float);
}
}
@specifiedBy
Directive
The GraphQL specification defines the @specifiedBy
directive which can be added to custom scalar definitions. The directive provides a "scalar specification URL for specifying the behavior of custom scalar types.". Grats' support for annotating your schema with directives lets you add this directive to your custom scalars:
- TypeScript
- GraphQL
/**
* @gqlScalar
* @gqlAnnotate specifiedBy(url: "https://tools.ietf.org/html/rfc4122")
*/
export type UUID = string;
scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122")
Serialization and Parsing of Custom Scalars
When defining a custom scalar, Grats will require that when constructing your schema you provide a configuration object for the scalar which can optionally define how to serialize and parse values of that type.
For example if you had a Date
type in your schema:
/** @gqlScalar Date */
export type GqlDate = Date;
Grats' generated getSchema
would require a config object where you could supply serialize/parseValue/parseLiteral
transform for this type. If Date
were serialized as a Unix timestamp, you could do the following:
import { getSchema, SchemaConfig } from "./schema"; // Generated by Grats
import { GqlDate } from "./scalars";
const config: SchemaConfig = {
scalars: {
Date: {
serialize(value): number {
if (!(value instanceof Date)) {
throw new Error("Date.serialize: value is not a Date object");
}
return value.getTime();
},
parseValue(value): Date {
if (typeof value !== "number") {
throw new Error("Date.parseValue: value is not a number");
}
return new Date(value);
},
parseLiteral(ast): Date {
if (!(ast.kind === "IntValue" || ast.kind === "StringValue")) {
throw new Error(
"Date.parseLiteral: ast.kind is not IntValue or StringValue",
);
}
return new Date(Number(ast.value));
},
},
},
};
const schema = getSchema(config);
// ... Continue on, using the schema to create a GraphQL server