Skip to Content
API Referenceendpoint()

endpoint(spec)

Defines a single endpoint. The primary purpose of this helper is to provide full type inference on adapter without manual casts — raw is automatically typed from the response schema.

import { endpoint } from '@routar/core' import { z } from 'zod' const TodoSchema = z.object({ id: z.number(), title: z.string() }) // without adapter endpoint({ method: 'GET', path: '/', response: z.array(TodoSchema), }) // with adapter — raw is inferred as z.infer<typeof TodoSchema>[] endpoint({ method: 'GET', path: '/', response: z.array(TodoSchema), adapter: (raw) => raw.map(todo => ({ ...todo, label: todo.title })), })

Parameters

FieldTypeRequiredDescription
method'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'YesHTTP method
pathstringYesPath relative to the router prefix. Use :param for path parameters.
responseValidator<T>YesSchema for validating the response. Any object with .parse(data): T.
requestValidator<R>NoSchema for { path?, query?, body? }.
adapter(raw: T) => UNoTransform the validated response.

Path param enforcement

If path contains :param segments, the request schema must include a matching path object — enforced at compile time.

// ✅ correct endpoint({ path: '/:id', request: z.object({ path: z.object({ id: z.number() }) }), response: TodoSchema, method: 'GET', }) // ❌ compile error — ':id' in path but request.path.id missing endpoint({ path: '/:id', request: z.object({ query: z.object({ q: z.string() }) }), response: TodoSchema, method: 'GET', })

Adapter

response and adapter are always separate. response is a pure Zod schema (stays composable). adapter is a plain function that transforms the validated data.

// ✅ adapter separately — schema stays composable const TodoRawSchema = z.object({ id: z.number(), title: z.string() }) const toTodoItem = (raw: z.infer<typeof TodoRawSchema>) => ({ ...raw, label: raw.title, }) endpoint({ method: 'GET', path: '/', response: z.array(TodoRawSchema), adapter: (raw) => raw.map(toTodoItem), // raw is correctly typed })

Never use .transform() on a response schema. .transform() wraps the schema in a ZodEffects object, which loses .extend(), .merge(), and all other composition methods — your schema can no longer be reused or composed. Put data transformations in adapter instead; the response schema stays a plain ZodObject.

Type utilities

ApiTypes<TApi>

Extracts request and response types from an API client. See the dedicated ApiTypes<T> reference for full usage and patterns.

import type { ApiTypes } from '@routar/core' type TodoApiTypes = ApiTypes<typeof todoApi> type CreateRequest = TodoApiTypes['create']['request'] // { body: { title: string } } type CreateResponse = TodoApiTypes['create']['response'] // Todo

PathParams<TPath>

Extracts :param names from a path string as a union type.

import type { PathParams } from '@routar/core' type P = PathParams<'/:userId/posts/:postId'> // 'userId' | 'postId'
Last updated on