@toapi/common
@toapi/common holds the shared foundation of the Toapi stack: the type contract that describes a route (Route, Handler, Schema, TRequest, TResponse) plus a handful of runtime utilities (HttpError, CookieStore, isMutation, protocol constants, and the Logger interface).
What lives here
Section titled “What lives here”Because the server and client must agree on exactly what a route looks like — its params, query, body, response, and authorization — those shapes are defined once, in @toapi/common, and consumed by both sides. This is what makes an API end-to-end typed: the client infers its call signatures from the very same types the server implements.
Type contract
Section titled “Type contract”Describes a single endpoint as a map of HTTP methods to Handlers. Each method is optional; a method typed as never for its query means it is not available on the route.
export type Route< Params extends Record<string, string>, GetResponse, GetQuery extends Record<string, unknown>, PostResponse, PostQuery extends Record<string, unknown>, PostBody, DeleteResponse, DeleteQuery extends Record<string, unknown>, PutResponse, PutQuery extends Record<string, unknown>, PutBody, PatchResponse, PatchQuery extends Record<string, unknown>, PatchBody> = { GET?: Handler<GetResponse, Params, GetQuery, undefined>; HEAD?: Handler<undefined, Params, GetQuery, undefined>; POST?: Handler<PostResponse, Params, PostQuery, PostBody>; DELETE?: Handler<DeleteResponse, Params, DeleteQuery, undefined>; PUT?: Handler<PutResponse, Params, PutQuery, PutBody>; PATCH?: Handler<PatchResponse, Params, PatchQuery, PatchBody>;};HEAD mirrors the GET query but always resolves to an empty (undefined) response body. GET, DELETE, HEAD never carry a request body.
BaseRoute
Section titled “BaseRoute”A loosely-typed version of Route (every generic widened to any) used internally where the precise per-method types are not needed.
export type BaseRoute = { GET?: Handler<any, any, any, undefined>; HEAD?: Handler<undefined, any, any, undefined>; POST?: Handler<any, any, any, any>; DELETE?: Handler<any, any, any, undefined>; PUT?: Handler<any, any, any, any>; PATCH?: Handler<any, any, any, any>;};Handler and HandlerFn
Section titled “Handler and HandlerFn”A Handler pairs a Schema with the function that runs the request. HandlerFn is the function signature: it receives a TRequest and resolves to a TResponse.
export type HandlerFn<Response, AuthData, Params, Query, Body> = ( request: TRequest<AuthData, Params, Query, Body>) => Promise<TResponse<Response>>;
export type Handler< Response, Params extends Record<string, string>, Query extends Record<string, unknown>, Body> = { schema: Schema<Response, unknown, Params, Query, Body>; handler: HandlerFn<Response, any, Params, Query, Body>;};You do not usually construct a Handler by hand — defineHandler from @toapi/server produces one for you.
Schema
Section titled “Schema”Describes the runtime validation and authorization for a handler. Each field is a Zod schema (using zod/v4) that both validates input and documents the endpoint (Toapi derives its OpenAPI document from these). The __r, __q, and __b fields are phantom type carriers — they exist only to thread the Response, Query, and Body types through inference and are never populated at runtime.
export type Schema< Response, AuthData, Params extends Record<string, string>, Query extends Record<string, unknown>, Body> = { __r?: Response; __q?: Query; __b?: Body; params?: { [key in keyof Params]: ZodType<Params[key], string> }; query?: { [key in keyof Query]: ZodType<Query[key], string | string[] | undefined>; }; body?: ZodType<Body>; response?: ZodType<Response>; authorize: ( req: TRequest<never, Params, Query, never> ) => MaybePromise<AuthData>;};The authorize callback runs before the handler and returns the auth data later exposed as request.auth(). Throw an HttpError from it to reject the request.
TRequest
Section titled “TRequest”The augmented Request passed to every handler. Documented in full under the server section: see TRequest.
export type TRequest<AuthData, Params, Query, Body> = Request & { params: () => Params; query: () => Query; data: () => Promise<Body>; auth: () => NonNullable<AuthData>; cookies: () => CookieStore; invalidate: (tags: string[]) => Promise<void>;};TResponse
Section titled “TResponse”The Response subclass handlers return, adding cache tagging, cookies, and typed data. Documented in full under the server section: see TResponse.
Path and StrictParams
Section titled “Path and StrictParams”Template-literal helper types used to type route pathnames and extract their parameters. Path is any string starting with /. StrictParams reads a pathname like /users/:id/*rest and produces { id: string; rest: string } — named segments (:id) and wildcards (*rest) become string keys, while a bare * is dropped.
export type Path = `/${string}`;export type StrictParams<Pathname> = /* extracts params from the pathname */;MaybePromise
Section titled “MaybePromise”export type MaybePromise<T> = T | Promise<T>;A value that may or may not be wrapped in a promise. Used wherever a callback (such as authorize) is allowed to be sync or async.
Logger
Section titled “Logger”An optional error sink you can pass to the request handler. Only error is defined; it may return a promise.
export interface Logger { error?: (error: unknown) => MaybePromise<void>;}Runtime values
Section titled “Runtime values”HttpError
Section titled “HttpError”The error class used to return a specific HTTP status from a handler or authorize. See the dedicated page: HttpError.
CookieStore
Section titled “CookieStore”A Cookie Store API-style wrapper over a request’s cookies, obtained inside a handler via request.cookies(). It reads the incoming Cookie header and buffers changes, which TResponse flushes to Set-Cookie headers on the way out.
const cookies = request.cookies();
await cookies.get("__tapi-session"); // CookieListItem | undefinedawait cookies.getAll(); // CookieListItem[]await cookies.set("theme", "dark"); // or set({ name, value, path, ... })await cookies.delete("theme");| Method | Description |
|---|---|
get(nameOrOptions?) |
The first matching cookie, or the first cookie when called with no argument. |
getAll(nameOrOptions?) |
All cookies, or all cookies with a given name. |
set(nameOrOptions, value?) |
Add or update a cookie. Accepts a name + value or a CookieInit object (domain, path, expires, sameSite, partitioned). |
delete(nameOrOptions) |
Remove a cookie by name or CookieStoreDeleteOptions. |
write(headers) |
Flush buffered set/delete operations onto a Headers object as Set-Cookie. Called for you by TResponse. |
isMutation
Section titled “isMutation”Returns true when a request uses a mutating method (POST, PUT, PATCH, or DELETE). Used across the stack to decide whether a request should invalidate cache tags.
import { isMutation } from "@toapi/common";
isMutation(new Request("/x", { method: "POST" })); // trueisMutation(new Request("/x")); // false (GET)Constants
Section titled “Constants”Protocol constants shared by server, client, and worker. You rarely reference these directly, but they define the wire format for cache tagging and invalidation.
export const TAGS_HEADER = "X-TAPI-Tags";export const EXPIRES_AT_HEADER = "X-TAPI-Expires-At";export const TAGS_CONTENT_TYPE = "text/tapi-tags";export const SESSION_COOKIE_NAME = "__tapi-session";export const INVALIDATION_POST_EVENT = "TAPI_INVALIDATE_TAGS";export const INVALIDATIONS_ROUTE = "/__tapi/invalidations";export const OPENAPI_ROUTE = "/__tapi/openapi.json";| Constant | Value | Purpose |
|---|---|---|
TAGS_HEADER |
X-TAPI-Tags |
Header carrying the space-separated cache tags of a response. |
EXPIRES_AT_HEADER |
X-TAPI-Expires-At |
Header carrying a response’s absolute expiry timestamp (ms). |
TAGS_CONTENT_TYPE |
text/tapi-tags |
Content type used when streaming revalidated tags. |
SESSION_COOKIE_NAME |
__tapi-session |
Name of the Toapi session cookie. |
INVALIDATION_POST_EVENT |
TAPI_INVALIDATE_TAGS |
Message event name used to broadcast tag invalidations. |
INVALIDATIONS_ROUTE |
/__tapi/invalidations |
Internal route that streams tag invalidations to clients. |
OPENAPI_ROUTE |
/__tapi/openapi.json |
Internal route serving the generated OpenAPI document. |
Related
Section titled “Related”- HttpError — return typed HTTP error responses.
- TRequest — the request object handlers receive.
- TResponse — the response object handlers return.
- Server overview — how these types are turned into a running API.