import { Promisable } from '../common.js'; import { type HttpAction, type HttpResource, type HttpRouteTree } from '../http.js'; import { type ClientResponsePlugin } from '../response.js'; import type { RouteFetchOptions, RouteInput, RouteOptions } from '../types/args.js'; import type { RawBodySchema } from '../types/schema.js'; import type { InferRouteResponse } from '../types/response.js'; import type { RouteSchema } from '../types/schema.js'; /** Lifecycle event emitted by generated client action functions. */ export type RouzerClientHookEvent = { type: 'request.start'; opId: string; routeName: string; method: string; pathPattern: string; payload: unknown; } | { type: 'request.success'; opId: string; routeName: string; method: string; pathPattern: string; payload: unknown; response: unknown; status?: number; durationMs: number; } | { type: 'request.error'; opId: string; routeName: string; method: string; pathPattern: string; payload: unknown; error: unknown; status?: number; durationMs: number; }; /** Best-effort observer for generated client action lifecycles. */ export type RouzerClientHook = (event: RouzerClientHookEvent) => void; /** Client type inferred from an HTTP route tree passed to `createClient`. */ export type RouzerClient> = ReturnType>; /** * Create a typed fetch client for an HTTP route tree. * * @remarks The returned client mirrors the resource tree and attaches direct * action functions such as `client.users.list(...)`. */ export declare function createClient>(config: { /** * Absolute base URL used for generated request URLs. * * @remarks A trailing slash is added when missing. In browsers, derive a * relative API path with `new URL('/api/', window.location.origin).href`. */ baseURL: string; /** * Default headers sent with every request. * * @remarks Per-request headers are merged on top of these values. Undefined * per-request headers are removed before `fetch`. */ headers?: Record; /** * HTTP route tree to attach as direct client action functions. * * @example * ```ts * const client = createClient({ baseURL: 'https://example.com/api/', routes }) * await client.users.list({ page: 1 }) * ``` */ routes: TRoutes; /** Response codec plugins used by generated action functions. */ plugins?: readonly ClientResponsePlugin[]; /** * Custom handler for non-2xx responses from generated client action * functions. * * @remarks When provided, the return value is returned from the client action * as-is; Rouzer does not automatically parse a `Response` returned by this * hook. */ onJsonError?: (response: Response) => Promisable; /** Custom `fetch` implementation to use for requests. */ fetch?: typeof globalThis.fetch; /** * Best-effort lifecycle observer for generated client action calls. * * @remarks Hook errors are swallowed and never change request behavior. */ clientHook?: RouzerClientHook; }): ClientTree & { clientConfig: { /** * Absolute base URL used for generated request URLs. * * @remarks A trailing slash is added when missing. In browsers, derive a * relative API path with `new URL('/api/', window.location.origin).href`. */ baseURL: string; /** * Default headers sent with every request. * * @remarks Per-request headers are merged on top of these values. Undefined * per-request headers are removed before `fetch`. */ headers?: Record; /** * HTTP route tree to attach as direct client action functions. * * @example * ```ts * const client = createClient({ baseURL: 'https://example.com/api/', routes }) * await client.users.list({ page: 1 }) * ``` */ routes: TRoutes; /** Response codec plugins used by generated action functions. */ plugins?: readonly ClientResponsePlugin[]; /** * Custom handler for non-2xx responses from generated client action * functions. * * @remarks When provided, the return value is returned from the client action * as-is; Rouzer does not automatically parse a `Response` returned by this * hook. */ onJsonError?: (response: Response) => Promisable; /** Custom `fetch` implementation to use for requests. */ fetch?: typeof globalThis.fetch; /** * Best-effort lifecycle observer for generated client action calls. * * @remarks Hook errors are swallowed and never change request behavior. */ clientHook?: RouzerClientHook; }; }; type Join = A extends '' ? B : B extends '' ? A : `${A}/${B}`; /** Client object shape produced from an HTTP route tree. */ export type ClientTree = { [K in keyof T]: T[K] extends HttpResource ? ClientTree> : T[K] extends HttpAction ? RouteFunction> : never; }; /** * Client action function attached for each HTTP action leaf. * * @remarks Actions whose schema has `response: $type()` return parsed JSON * as `T`. Actions whose schema has a status-keyed response map return a tuple * union of `[null, value, status]` success entries and `[error, null, status]` * error entries. Actions whose schema has a plugin response marker return the * plugin's client result type. Actions without a response marker return the raw * `Response`. Raw-body actions with no path or query input accept * `(body, options)`; raw-body actions with route input accept * `(input, { body, ...options })`. */ export type RouteFunction = T extends { body: RawBodySchema; } ? RouteInput extends infer TInput ? {} extends TInput ? (body: BodyInit | null, options?: RouteFetchOptions) => Promise : Response> : (input: TInput, options: RouteOptions) => Promise : Response> : never : (...p: RouteInput extends infer TInput ? {} extends TInput ? [input?: TInput, options?: RouteOptions] : [input: TInput, options?: RouteOptions] : never) => Promise : Response>; export {};