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.
The contract declares the HTTP method, path, request body, and response body once. The server handler and client call are inferred from that declaration.
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",
request: {
body: {
title: z.string().min(1),
},
},
responses: {
201: 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",
request: {
body: {
title: v.pipe(v.string(), v.minLength(1)),
},
},
responses: {
201: 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",
request: {
body: {
title: type("string>0"),
},
},
responses: {
201: 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",
request: {
body: {
title: type("string>0"),
},
},
responses: {
201: 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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
routes = router<{
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}, handlers: {
...;
}): {
...;
}
router(const api: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>, HttpRouteHandlerContext>;
}
todos: {
create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>, 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 {
status: 201status: 201,
body: {
id: string;
title: string;
completed: boolean;
}
body: 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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
routes = router<{
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}, handlers: {
...;
}): {
...;
}
router(const api: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>, HttpRouteHandlerContext>;
}
todos: {
create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>, 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 {
status: 201status: 201,
body: {
id: string;
title: string;
completed: boolean;
}
body: 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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
routes = router<{
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}, Env>(contract: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}, handlers: {
...;
}): {
...;
}
router(const api: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>, HttpRouteHandlerContext<...>>;
}
todos: {
create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>, 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 {
status: 201status: 201,
body: {
id: string;
title: string;
completed: boolean;
}
body: 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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}, handlers: {
...;
}, options?: CreateRouteHandlerOptions): RouterHandlerMap
createRouterHandler(const api: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api, {
todos: {
readonly create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
}
todos: {
create: RouteHandler<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>
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 {
status: 201status: 201,
body: {
id: string;
title: string;
completed: boolean;
}
body: 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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api } from "./contract";
const const client: {
readonly todos: {
readonly create: ApiClientHappyPathRouteValue<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
client = initClient<{
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}, options: ApiClientOptions): {
...;
}
initClient(const api: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api, {
origin: stringorigin: "http://localhost:3000",
});
const const todo: {
id: string;
title: string;
completed: boolean;
}
todo = await const client: {
readonly todos: {
readonly create: ApiClientHappyPathRouteValue<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
};
}
client.todos: {
readonly create: ApiClientHappyPathRouteValue<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>;
}
todos.create: ApiClientHappyPathRouteValue<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api } from "./contract";
const const tq: TanstackQueryTreeFor<{
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}>
tq = initTanstackQuery<{
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}>(contract: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}, options: TanstackQueryOptions): TanstackQueryTreeFor<...>
initTanstackQuery(const api: {
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}
api, {
origin: stringorigin: "http://localhost:3000",
});
const const createTodo: UseMutationResult<InferRouteQueryData<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>, Error | UndeclaredRouteClientResponse, {
...;
}, unknown>
createTodo = useMutation<InferRouteQueryData<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>, Error | UndeclaredRouteClientResponse, {
...;
}, unknown>(options: UseMutationOptions<...>, queryClient?: QueryClient): UseMutationResult<...>
useMutation(
const tq: TanstackQueryTreeFor<{
readonly todos: {
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
};
}>
tq.todos: TanstackQueryTreeFor<{
readonly create: Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>;
}>
todos.create: TanstackQueryRouteValue<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>
create.mutationOptions: (options?: MutationOptionsFor<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>> | undefined) => MutationOptions<...>
mutationOptions({
onSuccess?: ((data: InferRouteQueryData<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>, variables: {
...;
}, onMutateResult: unknown, context: MutationFunctionContext) => Promise<unknown> | unknown) | undefined
onSuccess(response: InferRouteQueryData<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>
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<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>
response.body: {
id: string;
title: string;
completed: boolean;
}
body.id: stringid);
},
}),
);
const createTodo: UseMutationResult<InferRouteQueryData<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>, Error | UndeclaredRouteClientResponse, {
...;
}, unknown>
createTodo.mutate: (variables: {
title: string;
}, options?: MutateOptions<InferRouteQueryData<Merge<Omit<{
readonly method: "POST";
readonly path: "/todos";
readonly request: {
readonly body: {
readonly title: ZodString;
};
};
readonly responses: {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
};
}, "path" | "metadata" | "responses"> & {
path: "/todos";
metadata: Merge<Omit<EmptyObject, never> & EmptyObject>;
responses: Merge<Omit<EmptyObject, 201> & {
readonly 201: ZodObject<{
id: ZodString;
title: ZodString;
completed: ZodBoolean;
}, $strip>;
}>;
}>>, 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 explains the route declaration shape.
- Server adapters cover framework-specific setup.
- Fetch Client and TanStack Query cover client behavior in more detail.