import type { Misina, MisinaOptions, MisinaResponse, MisinaResponsePromise } from "./types.mjs"; export interface EndpointDef { params?: Record; query?: Record; body?: unknown; response?: unknown; responses?: Record; } export type EndpointsMap = Record; /** 2xx codes recognized as success branches by `.safe.*` typed results. */ export type SuccessCodes = 200 | 201 | 202 | 204; /** 4xx/5xx codes recognized as error branches by `.safe.*` typed results. */ export type ErrorCodes = 400 | 401 | 403 | 404 | 409 | 410 | 422 | 429 | 500 | 502 | 503; /** * Normalize an `EndpointDef`'s response declaration into a `Record` * map. `responses` wins; otherwise `response: T` becomes `{ 200: T }`; an * endpoint with neither falls back to `Record`. */ export type ResponsesOf = D extends { responses: infer R; } ? R : D extends { response: infer T; } ? { 200: T; } : Record; export type SuccessBodyOf = [keyof R & SuccessCodes] extends [never] ? unknown : { [K in keyof R & SuccessCodes] : R[K] }[keyof R & SuccessCodes]; export type TypedSafeOk = { ok: true; data: SuccessBodyOf; status: keyof R & SuccessCodes; response: Response; error?: undefined; }; /** * Per-status HTTP error branch. The server responded with a status the * endpoint declared as an error — `error.status` narrows to the union of * declared `ErrorCodes`, and `error.data` narrows to the body shape for * that status. */ export type TypedSafeHttpErr = { ok: false; kind: "http"; data?: undefined; error: [keyof R & ErrorCodes] extends [never] ? { status: number; data: unknown; } : { [K in keyof R & ErrorCodes] : { status: K; data: R[K]; } }[keyof R & ErrorCodes]; response: Response; }; /** * Network / timeout / abort branch. The request never received a server * response — there is no HTTP status to discriminate on. `error` is the * raw thrown `Error` (TypeError, TimeoutError, etc.); `response` is * `undefined`. */ export type TypedSafeNetworkErr = { ok: false; kind: "network"; data?: undefined; error: Error; response: undefined; }; /** * Discriminated union covering both error branches. Use `result.kind` to * separate the wire-level HTTP error (where `result.error.status` is a * declared `ErrorCodes`) from the transport-level failure (where * `result.error` is a raw `Error`). */ export type TypedSafeErr = TypedSafeHttpErr | TypedSafeNetworkErr; export type TypedSafeResult = TypedSafeOk | TypedSafeErr; type Method = S extends `${infer M} ${string}` ? M : never; type Path = S extends `${string} ${infer P}` ? P : never; type EndpointsOfMethod< E extends EndpointsMap, M extends string > = { [K in keyof E & string as Method extends M ? Path : never] : E[K] }; type CallInit = Omit & { headers?: Record; } & (E extends { params: infer P; } ? { params: P; } : {}) & (E extends { query: infer Q; } ? { query: Q; } : { query?: Record; }) & (E extends { body: infer B; } ? { body: B; } : {}); type ResponsePromise = MisinaResponsePromise>>; type HasRequiredFields = E extends { params: unknown; } ? true : E extends { query: unknown; } ? true : E extends { body: unknown; } ? true : false; type CallArgs = HasRequiredFields extends true ? [init: CallInit] : [init?: CallInit]; export interface TypedSafeMisina { get:

& string>(path: P, ...args: CallArgs[P]>) => Promise[P]>>>; post:

& string>(path: P, ...args: CallArgs[P]>) => Promise[P]>>>; put:

& string>(path: P, ...args: CallArgs[P]>) => Promise[P]>>>; patch:

& string>(path: P, ...args: CallArgs[P]>) => Promise[P]>>>; delete:

& string>(path: P, ...args: CallArgs[P]>) => Promise[P]>>>; } export interface TypedMisina { raw: Misina; safe: TypedSafeMisina; get:

& string>(path: P, ...args: CallArgs[P]>) => ResponsePromise[P]>; post:

& string>(path: P, ...args: CallArgs[P]>) => ResponsePromise[P]>; put:

& string>(path: P, ...args: CallArgs[P]>) => ResponsePromise[P]>; patch:

& string>(path: P, ...args: CallArgs[P]>) => ResponsePromise[P]>; delete:

& string>(path: P, ...args: CallArgs[P]>) => ResponsePromise[P]>; } /** * Build a typed Misina client. Adds `.safe.*` for discriminated * `{ ok, data, error }` results on top of the route map declared by `E`. * See the module-level block above for an end-to-end example. */ export declare function createMisinaTyped(defaults?: MisinaOptions): TypedMisina; /** * Extract path-parameter names from a literal template, supporting both * `:name` and `{name}` syntaxes. Used by `path()` to type the params arg. */ export type PathParamsOf = T extends `${string}:${infer Param}/${infer Rest}` ? { [K in Param | keyof PathParamsOf<`/${Rest}`>] : string | number } : T extends `${string}:${infer Param}` ? { [K in Param] : string | number } : T extends `${string}{${infer Param}}${infer Rest}` ? { [K in Param | keyof PathParamsOf] : string | number } : Record; /** * Build a path string from a template + params. Substitutes `:name` and * `{name}` placeholders. Rejects values that would escape the template * (`..`, `/`, `\`, NUL, CR/LF) per misina's security model. * * @example * ```ts * import { path } from "misina" * * path("/users/:id/posts/:postId", { id: "42", postId: "7" }) * // → "/users/42/posts/7" * ``` */ export declare function path(template: T, params: PathParamsOf & Record): string; export declare function substitutePathParams(path: string, params: Record): string; /** * Standard Schema (https://standardschema.dev) validation helper. Pass any * standard-schema validator (zod, valibot, arktype) to validate a parsed * response body. */ export declare function validateSchema(schema: StandardSchemaV1, value: unknown): Promise; /** * Per the [Standard Schema v1 spec](https://standardschema.dev), an * issue's `path` is a sequence of either bare PropertyKeys or * `{ key: PropertyKey }` objects (so vendors can attach extra metadata * like `type` for tuple/intersection/union narrowing). */ export type StandardPathItem = PropertyKey | { key: PropertyKey; }; export interface StandardIssue { message: string; path?: ReadonlyArray; } export interface StandardSchemaV1< I = unknown, O = unknown > { "~standard": { version: 1; vendor: string; validate: (value: unknown) => { value: O; issues?: undefined; } | { issues: ReadonlyArray; } | Promise<{ value: O; issues?: undefined; } | { issues: ReadonlyArray; }>; types?: { input: I; output: O; }; }; } export declare class SchemaValidationError extends Error { override readonly name = "SchemaValidationError"; readonly issues: ReadonlyArray; constructor(message: string, issues: ReadonlyArray); } export declare function isSchemaValidationError(error: unknown): error is SchemaValidationError; /** * Wrap a `MisinaResponse.data` with a Standard Schema validator. Throws * `SchemaValidationError` on mismatch. */ export declare function validated(promise: Promise>, schema: StandardSchemaV1): Promise>; export {};