GraphQL as a transport for @tahanabavi/typefetch contracts —
so a GraphQL route lives in the same contract file, behind the same client, as
your REST routes.
pnpm add @tahanabavi/typefetch-graphqlWhy this and not a GraphQL client
The selection set is generated from your Zod response schema. No codegen step, no document to keep in sync, and no way for the shape that requests the data to drift from the shape that validates it.
getUser: {
transport: "graphql",
operation: "query",
root: "user",
request: z.object({ id: z.string() }),
response: z.object({ id: z.string(), name: z.string() }),
variableTypes: { id: "ID!" },
}sends
query UserGetUser($id: ID!) { user(id: $id) { id name } }Add a field to response and it is requested. Remove one and it stops being
requested. Misspell one and it is a type error, not a null in production.
And because it is a typefetch transport rather than a second client, everything
else you already configured keeps working unchanged: middleware, onError,
retries, timeouts, AbortSignal, mock mode, instrumentation, devtools, and the
query engine's cache keys.