graphql-js code-first schema execution: working versions (tested 2026-10-15)
Build a code-first graphql-js schema with an object type, a custom Date scalar, arguments and variables, then execute it and inspect validation and resolver errors offline.
passed4 passed · 0 failed2026-10-15 22:58 UTC- Status
- passed
- Last passed
- 2026-10-15 22:58 UTC
- Tests
- 4 / 4
- Language
- TypeScript
- Runtime
- node v22.23.3
npm install --no-audit --no-fund --ignore-scripts=false npm test
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38820570375
The code
Exactly the files that passed. Your agent can pull them with get_recipe("graphql-js-schema-execute") (install), or see them on GitHub.
{
"name": "graphql-js-schema-execute",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"graphql": "17.0.2"
},
"devDependencies": {
"@types/node": "26.6.5",
"tsx": "4.23.15"
}
}
import {
GraphQLError,
GraphQLList,
GraphQLNonNull,
GraphQLObjectType,
GraphQLScalarType,
GraphQLSchema,
GraphQLString,
Kind,
} from "graphql";
export const GraphQLDate = new GraphQLScalarType<Date, string>({
name: "Date",
description: "An ISO-8601 encoded UTC date time string.",
serialize(value) {
if (value instanceof Date && !Number.isNaN(value.getTime())) {
return value.toISOString();
}
throw new GraphQLError(`Date cannot represent value: ${String(value)}`);
},
parseValue(value) {
if (typeof value === "string") {
const date = new Date(value);
if (!Number.isNaN(date.getTime())) {
return date;
}
}
throw new GraphQLError(`Date cannot represent value: ${String(value)}`);
},
parseLiteral(ast) {
if (ast.kind === Kind.STRING) {
const date = new Date(ast.value);
if (!Number.isNaN(date.getTime())) {
return date;
}
}
throw new GraphQLError("Date cannot represent a non-string value");
},
});
export type User = {
id: string;
name: string;
createdAt: Date;
};
const users = new Map<string, User>([
["1", { id: "1", name: "Ada", createdAt: new Date("2020-01-01T00:00:00.000Z") }],
["2", { id: "2", name: "Alan", createdAt: new Date("2021-06-15T12:30:00.000Z") }],
]);
export const UserType = new GraphQLObjectType({
name: "User",
fields: () => ({
id: { type: new GraphQLNonNull(GraphQLString) },
name: { type: new GraphQLNonNull(GraphQLString) },
createdAt: { type: new GraphQLNonNull(GraphQLDate) },
}),
});
export const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: "Query",
fields: {
user: {
type: UserType,
args: { id: { type: new GraphQLNonNull(GraphQLString) } },
resolve: (_source, args: { id: string }) => users.get(args.id) ?? null,
},
users: {
type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(UserType))),
resolve: () => [...users.values()],
},
failing: {
type: GraphQLString,
resolve: () => {
throw new Error("resolver exploded");
},
},
},
}),
});
import { test } from "node:test";
import assert from "node:assert/strict";
import { graphql } from "graphql";
import { GraphQLDate, schema } from "../src/schema.ts";
// graphql 17 returns null-prototype objects; copy to plain objects before deepEqual.
const plain = (v: unknown) => JSON.parse(JSON.stringify(v));
test("executes a query with arguments and variables", async () => {
const result = await graphql({
schema,
source: `query GetUser($id: String!) { user(id: $id) { id name createdAt } }`,
variableValues: { id: "2" },
});
assert.equal(result.errors, undefined);
assert.deepEqual(plain(result.data), {
user: { id: "2", name: "Alan", createdAt: "2021-06-15T12:30:00.000Z" },
});
});
test("returns validation errors for a bad query", async () => {
const result = await graphql({ schema, source: `query { user { name } }` });
assert.equal(result.data, undefined);
const errors = result.errors;
assert.ok(errors);
assert.equal(errors.length, 1);
assert.match(errors[0]!.message, /Query\.user\(id:\).*required/);
});
test("surfaces resolver errors in result.errors", async () => {
const result = await graphql({ schema, source: `{ failing }` });
assert.deepEqual(plain(result.data), { failing: null });
const errors = result.errors;
assert.ok(errors);
assert.equal(errors.length, 1);
assert.match(errors[0]!.message, /resolver exploded/);
});
test("custom Date scalar round-trips ISO strings", () => {
const parsed = GraphQLDate.parseValue("2020-01-01T00:00:00.000Z");
assert.ok(parsed instanceof Date);
assert.equal(GraphQLDate.serialize(parsed), "2020-01-01T00:00:00.000Z");
assert.throws(() => GraphQLDate.parseValue(42));
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.
Related stacks
Apollo Server 5 resolvers with per-request DataLoader batching
An Apollo Server 5 schema whose nested resolvers use per-request DataLoader instances to batch and dedupe lookups (no N+1), with GraphQLError extension codes and cache invalidation after a mutation, tested in-process with executeOperation.
GraphQL schema mocking with @graphql-tools/schema and @graphql-tools/mock
Build an executable schema with makeExecutableSchema and layer deterministic mocks, a MockStore, MockList and partial real resolvers on top with addMocksToSchema, including mutations that write to the store.
GraphQL Yoga 5 schema, context and errors tested via fetch
Build a GraphQL Yoga server with SDL resolvers, per-request context auth and GraphQLError codes, tested in-process with yoga.fetch.
graphql-request client with typed operations, mocked by MSW graphql handlers
Call a GraphQL API with graphql-request (variables, headers, error handling) and test offline with MSW's graphql.link(url).query/mutation handlers (msw 3 API). Install uses --legacy-peer-deps because graphql-request 7 still peers on graphql 14 - 16, but the client passes its tests against graphql 17.