Quickstart
Define one contract, implement it on the server, and call it from a client.
This guide builds one todos.create route from a shared contract.
Install packages
Add the core package, a schema library, and the adapter for the server framework you want to use.
Define the contract
Declare the HTTP method, path, request body, and response body once in a file that both server and client code can import.
Implement the server route
Use the same route tree to write a typed handler for Express, Fastify, Hono, Next.js, or a fetch-native runtime.
Call it from the client
Create a typed fetch client or TanStack Query helpers from the same contract.
Install Packages
This guide uses Zod and Express by default. The same contract works with the other server tabs below.
pnpm add @rest-rpc/core @rest-rpc/express express zodnpm install @rest-rpc/core @rest-rpc/express express zodyarn add @rest-rpc/core @rest-rpc/express express zodbun add @rest-rpc/core @rest-rpc/express express zodIf you use another server tab, replace @rest-rpc/express express with the
adapter and framework package you need:
- Fastify:
@rest-rpc/fastify fastify - Hono:
@rest-rpc/hono hono - Next.js:
@rest-rpc/next - Web
Request/Response:@rest-rpc/web
For the TanStack Query client example, also install:
pnpm add @rest-rpc/tanstack-query @tanstack/react-query
Define A Contract
Create a shared contract file. Put it somewhere both your server and client can import.
import { router } from "@rest-rpc/core";
import { z } from "zod";
const todoSchema = z.object({
id: z.string(),
title: z.string(),
completed: z.boolean(),
});
export const api = router({
todos: {
create: {
method: "POST",
path: "/todos",
body: {
title: z.string().min(1),
},
response: todoSchema,
},
},
});import { router } from "@rest-rpc/core";
import * as v from "valibot";
const todoSchema = v.object({
id: v.string(),
title: v.string(),
completed: v.boolean(),
});
export const api = router({
todos: {
create: {
method: "POST",
path: "/todos",
body: {
title: v.pipe(v.string(), v.minLength(1)),
},
response: todoSchema,
},
},
});import { router } from "@rest-rpc/core";
import { type } from "arktype";
const todoSchema = type({
id: "string",
title: "string",
completed: "boolean",
});
export const api = router({
todos: {
create: {
method: "POST",
path: "/todos",
body: {
title: type("string>0"),
},
response: todoSchema,
},
},
});import { router, type } from "@rest-rpc/core";
const todoSchema = {
id: type<string>(),
title: type<string>(),
completed: type<boolean>(),
};
export const api = router({
todos: {
create: {
method: "POST",
path: "/todos",
body: {
title: type("string>0"),
},
response: todoSchema,
},
},
});Server implementation
Implement the contract on the server with the framework of your choice.
import { const registerRoutes: (app: express.Application, implementations: ImplementationTree<RouteDeclaration>, options?: RegisterRoutesOptions) => voidregisterRoutes, const router: <const TNode extends Contract<RouteDeclaration>>(contract: TNode, handlers: ImplementationShape<TNode, HttpRouteHandlerContext, WebSocketRouteHandlerContext>) => ImplementationTreeFor<TNode, RouteDeclaration>router } from "@rest-rpc/express";
import function express(): ExpressCreates an Express application. The express() function is a top-level function exported by the express module.express from "express";
import { const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api } from "./contract";
const const app: Expressapp = function express(): ExpressCreates an Express application. The express() function is a top-level function exported by the express module.express();
const app: Expressapp.Application<Record<string, any>>.use: (...handlers: RequestHandler<ParamsDictionary, any, any, QueryString.ParsedQs, Record<string, any>>[]) => Express (+8 overloads)use(function express(): ExpressCreates an Express application. The express() function is a top-level function exported by the express module.express.var e.json: (options?: bodyParser.OptionsJson) => createServer.NextHandleFunctionReturns middleware that only parses json and only looks at requests
where the Content-Type header matches the type option.json());
const const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos = new var Map: MapConstructor
new <string, {
id: string;
title: string;
completed: boolean;
}>(iterable?: Iterable<readonly [string, {
id: string;
title: string;
completed: boolean;
}]> | null | undefined) => Map<string, {
id: string;
title: string;
completed: boolean;
}> (+3 overloads)
Map<string, {
id: stringid: string;
title: stringtitle: string;
completed: booleancompleted: boolean;
}>();
const const routes: {
readonly todos: {
readonly create: RouteImplementation<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
routes = router<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}, handlers: {
...;
}): {
...;
}
router(const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>, HttpRouteHandlerContext>;
}
todos: {
create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>, HttpRouteHandlerContext>
create({ title: stringtitle }) {
const const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo = {
id: `${string}-${string}-${string}-${string}-${string}`id: var crypto: Crypto[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto)crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`The **`randomUUID()`** method of the Crypto interface is used to generate a v4 UUID using a cryptographically secure random number generator.
Available only in secure contexts.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto/randomUUID)randomUUID(),
title: stringtitle,
completed: booleancompleted: false,
};
const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos.Map<string, { id: string; title: string; completed: boolean; }>.set(key: string, value: {
id: string;
title: string;
completed: boolean;
}): Map<string, {
id: string;
title: string;
completed: boolean;
}>
Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.set(const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo.id: `${string}-${string}-${string}-${string}-${string}`id, const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo);
return const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo;
},
},
});
function registerRoutes(app: express.Application, implementations: ImplementationTree<RouteDeclaration>, options?: RegisterRoutesOptions): voidregisterRoutes(const app: Expressapp, const routes: {
readonly todos: {
readonly create: RouteImplementation<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
routes);
const app: Expressapp.Application<Record<string, any>>.listen(port: number, callback?: (error?: Error) => void): Server (+5 overloads)Listen for connections.
A node `http.Server` is returned, with this
application (which is a `Function`) as its
callback. If you wish to create both an HTTP
and HTTPS server you may do so with the "http"
and "https" modules as shown here:
var http = require('http')
, https = require('https')
, express = require('express')
, app = express();
http.createServer(app).listen(80);
https.createServer({ ... }, app).listen(443);listen(3000);import { const registerRoutes: (app: FastifyInstance, implementations: ImplementationTree<RouteDeclaration>, options?: RegisterRoutesOptions) => voidregisterRoutes, const router: <const TNode extends Contract<RouteDeclaration>>(contract: TNode, handlers: ImplementationShape<TNode, HttpRouteHandlerContext, WebSocketRouteHandlerContext>) => ImplementationTreeFor<TNode, RouteDeclaration>router } from "@rest-rpc/fastify";
import const Fastify: typeof fastifyFastify from "fastify";
import { const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api } from "./contract";
const const app: FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault> & PromiseLike<FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>> & {
...;
}
app = Fastify<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>(opts?: fastify.FastifyHttpOptions<Server<typeof IncomingMessage, typeof ServerResponse>, FastifyBaseLogger> | undefined): FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault> & PromiseLike<...> & {
...;
} (+3 overloads)
Fastify factory function for the standard fastify http, https, or http2 server instance.
The default function utilizes httpFastify();
const const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos = new var Map: MapConstructor
new <string, {
id: string;
title: string;
completed: boolean;
}>(iterable?: Iterable<readonly [string, {
id: string;
title: string;
completed: boolean;
}]> | null | undefined) => Map<string, {
id: string;
title: string;
completed: boolean;
}> (+3 overloads)
Map<string, {
id: stringid: string;
title: stringtitle: string;
completed: booleancompleted: boolean;
}>();
const const routes: {
readonly todos: {
readonly create: RouteImplementation<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
routes = router<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}, handlers: {
...;
}): {
...;
}
router(const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>, HttpRouteHandlerContext>;
}
todos: {
create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>, HttpRouteHandlerContext>
create({ title: stringtitle }) {
const const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo = {
id: `${string}-${string}-${string}-${string}-${string}`id: var crypto: Crypto[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto)crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`The **`randomUUID()`** method of the Crypto interface is used to generate a v4 UUID using a cryptographically secure random number generator.
Available only in secure contexts.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto/randomUUID)randomUUID(),
title: stringtitle,
completed: booleancompleted: false,
};
const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos.Map<string, { id: string; title: string; completed: boolean; }>.set(key: string, value: {
id: string;
title: string;
completed: boolean;
}): Map<string, {
id: string;
title: string;
completed: boolean;
}>
Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.set(const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo.id: `${string}-${string}-${string}-${string}-${string}`id, const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo);
return const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo;
},
},
});
function registerRoutes(app: FastifyInstance, implementations: ImplementationTree<RouteDeclaration>, options?: RegisterRoutesOptions): voidregisterRoutes(const app: FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault> & PromiseLike<FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>> & {
...;
}
app, const routes: {
readonly todos: {
readonly create: RouteImplementation<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
routes);
await const app: FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault> & PromiseLike<FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>> & {
...;
}
app.FastifyInstance<Server<typeof IncomingMessage, typeof ServerResponse>, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>.listen(opts?: FastifyListenOptions): Promise<string> (+2 overloads)listen({ FastifyListenOptions.port?: number | undefinedDefault to `0` (picks the first available open port).port: 3000 });import { const registerRoutes: <TEnv extends Env = Env>(app: Hono<TEnv>, implementations: ImplementationTree<RouteDeclaration>, options?: RegisterRoutesOptions<TEnv>) => voidregisterRoutes, const router: <const TNode extends Contract<RouteDeclaration>, TEnv extends Env = Env>(contract: TNode, handlers: ImplementationShape<TNode, HttpRouteHandlerContext<TEnv>, WebSocketRouteHandlerContext<TEnv>>) => ImplementationTreeFor<TNode, RouteDeclaration>router } from "@rest-rpc/hono";
import { class Hono<E extends Env = BlankEnv, S extends Schema = BlankSchema, BasePath extends string = "/">The Hono class extends the functionality of the HonoBase class.
It sets up routing and allows for custom options to be passed.Hono } from "hono";
import { const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api } from "./contract";
const const app: Hono<BlankEnv, BlankSchema, "/">app = new new Hono<BlankEnv, BlankSchema, "/">(options?: HonoOptions<BlankEnv> | undefined): Hono<BlankEnv, BlankSchema, "/">Creates an instance of the Hono class.Hono();
const const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos = new var Map: MapConstructor
new <string, {
id: string;
title: string;
completed: boolean;
}>(iterable?: Iterable<readonly [string, {
id: string;
title: string;
completed: boolean;
}]> | null | undefined) => Map<string, {
id: string;
title: string;
completed: boolean;
}> (+3 overloads)
Map<string, {
id: stringid: string;
title: stringtitle: string;
completed: booleancompleted: boolean;
}>();
const const routes: {
readonly todos: {
readonly create: RouteImplementation<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
routes = router<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}, Env>(contract: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}, handlers: {
...;
}): {
...;
}
router(const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>, HttpRouteHandlerContext<...>>;
}
todos: {
create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>, HttpRouteHandlerContext<...>>
create({ title: stringtitle }) {
const const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo = {
id: `${string}-${string}-${string}-${string}-${string}`id: var crypto: Crypto[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto)crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`The **`randomUUID()`** method of the Crypto interface is used to generate a v4 UUID using a cryptographically secure random number generator.
Available only in secure contexts.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto/randomUUID)randomUUID(),
title: stringtitle,
completed: booleancompleted: false,
};
const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos.Map<string, { id: string; title: string; completed: boolean; }>.set(key: string, value: {
id: string;
title: string;
completed: boolean;
}): Map<string, {
id: string;
title: string;
completed: boolean;
}>
Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.set(const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo.id: `${string}-${string}-${string}-${string}-${string}`id, const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo);
return const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo;
},
},
});
registerRoutes<BlankEnv>(app: Hono<BlankEnv, BlankSchema, "/">, implementations: ImplementationTree<RouteDeclaration>, options?: RegisterRoutesOptions<BlankEnv> | undefined): voidregisterRoutes(const app: Hono<BlankEnv, BlankSchema, "/">app, const routes: {
readonly todos: {
readonly create: RouteImplementation<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
routes);
export default const app: Hono<BlankEnv, BlankSchema, "/">app;import { const createRouterHandler: <const TContract extends WebContract>(contract: TContract, handlers: WebRouterHandlers<TContract>, options?: CreateRouteHandlerOptions) => RouterHandlerMapcreateRouterHandler } from "@rest-rpc/next";
import { const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api } from "./contract";
const const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos = new var Map: MapConstructor
new <string, {
id: string;
title: string;
completed: boolean;
}>(iterable?: Iterable<readonly [string, {
id: string;
title: string;
completed: boolean;
}]> | null | undefined) => Map<string, {
id: string;
title: string;
completed: boolean;
}> (+3 overloads)
Map<string, {
id: stringid: string;
title: stringtitle: string;
completed: booleancompleted: boolean;
}>();
export const { const POST: WebRequestHandlerPOST } = createRouterHandler<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}, handlers: {
...;
}, options?: CreateRouteHandlerOptions): RouterHandlerMap
createRouterHandler(const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
}
todos: {
create: RouteHandler<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>
create({ title: stringtitle }) {
const const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo = {
id: `${string}-${string}-${string}-${string}-${string}`id: var crypto: Crypto[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/crypto)crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`The **`randomUUID()`** method of the Crypto interface is used to generate a v4 UUID using a cryptographically secure random number generator.
Available only in secure contexts.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto/randomUUID)randomUUID(),
title: stringtitle,
completed: booleancompleted: false,
};
const todos: Map<string, {
id: string;
title: string;
completed: boolean;
}>
todos.Map<string, { id: string; title: string; completed: boolean; }>.set(key: string, value: {
id: string;
title: string;
completed: boolean;
}): Map<string, {
id: string;
title: string;
completed: boolean;
}>
Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.set(const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo.id: `${string}-${string}-${string}-${string}-${string}`id, const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo);
return const todo: {
id: `${string}-${string}-${string}-${string}-${string}`;
title: string;
completed: boolean;
}
todo;
},
},
});Client implementation
Use the same contract to create a typed client.
import { const initClient: <TContract extends Contract>(contract: TContract, options: ApiClientOptions) => ApiClientFor<TContract>initClient } from "@rest-rpc/core";
import { const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api } from "./contract";
const const client: {
readonly todos: {
readonly create: ApiClientHappyPathRouteValue<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
client = initClient<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}, options: ApiClientOptions): {
...;
}
initClient(const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api, {
baseUrl: stringbaseUrl: "http://localhost:3000",
});
const const todo: {
id: string;
title: string;
completed: boolean;
}
todo = await const client: {
readonly todos: {
readonly create: ApiClientHappyPathRouteValue<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
};
}
client.todos: {
readonly create: ApiClientHappyPathRouteValue<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>;
}
todos.create: ApiClientHappyPathRouteValue<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>
create.fetch: (request: {
title: string;
}, options?: FetchOptions | undefined) => Promise<{
id: string;
title: string;
completed: boolean;
}>
fetch({
title: stringtitle: "Ship v1",
});import { const initTanstackQuery: <TContract extends Contract>(contract: TContract, options: TanstackQueryOptions) => TanstackQuery<TContract>initTanstackQuery } from "@rest-rpc/tanstack-query";
import { function useMutation<TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, queryClient?: QueryClient): UseMutationResult<TData, TError, TVariables, TOnMutateResult>useMutation } from "@tanstack/react-query";
import { const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api } from "./contract";
const const tq: TanstackQueryTreeFor<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}>
tq = initTanstackQuery<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}, options: TanstackQueryOptions): TanstackQueryTreeFor<...>
initTanstackQuery(const api: {
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}
api, {
baseUrl: stringbaseUrl: "http://localhost:3000",
});
const const createTodo: UseMutationResult<InferRouteQueryData<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>, Error | UndeclaredRouteClientResponse, {
...;
}, unknown>
createTodo = useMutation<InferRouteQueryData<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>, Error | UndeclaredRouteClientResponse, {
...;
}, unknown>(options: UseMutationOptions<...>, queryClient?: QueryClient): UseMutationResult<...>
useMutation(
const tq: TanstackQueryTreeFor<{
readonly todos: {
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
};
}>
tq.todos: TanstackQueryTreeFor<{
readonly create: Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>;
}>
todos.create: TanstackQueryRouteValue<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>
create.mutationOptions: (options?: MutationOptionsFor<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>> | undefined) => MutationOptions<...>
mutationOptions({
onSuccess?: ((data: InferRouteQueryData<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>, variables: {
...;
}, onMutateResult: unknown, context: MutationFunctionContext) => Promise<unknown> | unknown) | undefined
onSuccess(response: InferRouteQueryData<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>
response) {
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log(response: InferRouteQueryData<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>
response.body: {
id: string;
title: string;
completed: boolean;
}
body.id: stringid);
},
}),
);
const createTodo: UseMutationResult<InferRouteQueryData<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | "metadata" | "openApi" | "responses"> & {
...;
}>>, Error | UndeclaredRouteClientResponse, {
...;
}, unknown>
createTodo.mutate: (variables: {
title: string;
}, options?: MutateOptions<InferRouteQueryData<Merge<Omit<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly body: {
readonly title: ZodString;
};
readonly response: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}, "responses" | "response"> & {
responses: {
201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip> & ResponseBodySchema;
};
}>, "path" | ... 2 more ... | "responses"> & {
...;
}>>, Error | UndeclaredRouteClientResponse, {
title: string;
}, unknown> | undefined) => void
The mutation function you can call with variables to trigger the mutation and optionally hooks on additional callback options.mutate({
title: stringtitle: "Ship v1",
});Next Steps
- Contract Declaration explains the route declaration shape.
- Schemas explains validation and type-only schemas.
- Server adapters cover framework-specific setup.
- Fetch Client and TanStack Query cover client behavior in more detail.