@lokalise/api-contracts
Version:
83 lines (82 loc) • 4.45 kB
TypeScript
import type { z } from 'zod/v4';
import type { HttpStatusCode, WildcardStatusCodeKey } from '../HttpStatusCodes.ts';
import { ContractNoBody } from './constants.ts';
export type ResponseOptions = {
readonly description?: string;
};
export type TypedTextResponse = {
readonly _tag: 'TextResponse';
readonly contentType: string;
readonly description?: string;
};
export declare const textResponse: (contentType: string, options?: ResponseOptions) => TypedTextResponse;
export declare const isTextResponse: (value: ApiContractResponse) => value is TypedTextResponse;
export type TypedBlobResponse = {
readonly _tag: 'BlobResponse';
readonly contentType: string;
readonly description?: string;
};
export declare const blobResponse: (contentType: string, options?: ResponseOptions) => TypedBlobResponse;
export declare const isBlobResponse: (value: ApiContractResponse) => value is TypedBlobResponse;
export type SseSchemaByEventName = Record<string, z.ZodType>;
export type TypedSseResponse<T extends SseSchemaByEventName = SseSchemaByEventName> = {
readonly _tag: 'SseResponse';
readonly schemaByEventName: T;
readonly description?: string;
};
export declare const sseResponse: <T extends SseSchemaByEventName>(schemaByEventName: T, options?: ResponseOptions) => TypedSseResponse<T>;
export declare const isSseResponse: (value: ApiContractResponse) => value is TypedSseResponse;
export type TypedJsonResponse = z.ZodType;
export declare const isJsonResponse: (value: ApiContractResponse) => value is TypedJsonResponse;
export type TypedApiContractResponse = TypedJsonResponse | TypedTextResponse | TypedBlobResponse | TypedSseResponse;
export type AnyOfResponses<T extends TypedApiContractResponse = TypedApiContractResponse> = {
readonly _tag: 'AnyOfResponses';
readonly responses: T[];
readonly description?: string;
};
export declare const anyOfResponses: <T extends TypedApiContractResponse>(responses: T[], options?: ResponseOptions) => AnyOfResponses<T>;
export declare const isAnyOfResponses: (value: ApiContractResponse) => value is AnyOfResponses;
export type NoBodyResponse = {
readonly _tag: 'NoBodyResponse';
readonly description?: string;
};
export declare const noBodyResponse: (options?: ResponseOptions) => NoBodyResponse;
export declare const isNoBodyResponse: (value: ApiContractResponse) => value is NoBodyResponse;
export type ApiContractResponse = typeof ContractNoBody | NoBodyResponse | TypedApiContractResponse | AnyOfResponses;
export type ResponsesByStatusCode = Partial<Record<HttpStatusCode | WildcardStatusCodeKey, ApiContractResponse>>;
export type ResponseKind = {
kind: 'noContent';
} | {
kind: 'text';
} | {
kind: 'blob';
} | {
kind: 'json';
schema: z.ZodType;
} | {
kind: 'sse';
schemaByEventName: SseSchemaByEventName;
};
/**
* Resolves a contract's response entry for a given status code into a concrete `ResponseKind`,
* taking the response `content-type` into account.
*
* Returns `null` when the content-type cannot be matched to any entry in the contract,
* indicating the response is unexpected and should be treated as an error by the caller.
*
* @param schemaEntry - The contract entry for the matched status code (`ContractNoBody`,
* a Zod schema, `textResponse`, `blobResponse`, `sseResponse`, or `anyOfResponses`).
* @param contentType - The `content-type` header value from the actual HTTP response,
* or `undefined` when the header is absent.
* @param strict - When `true` (default), returns `null` if the `content-type` is absent or does
* not match the contract entry. When `false`, falls back to the entry's declared kind instead of
* returning `null` — only applies to single-entry responses; `anyOfResponses` always requires a
* content-type to disambiguate regardless of this flag.
*/
export declare const resolveContractResponse: (schemaEntry: ApiContractResponse, contentType: string | undefined, strict?: boolean) => ResponseKind | null;
/**
* Combines status-code lookup and content-type resolution into a single call.
* Lookup precedence: exact code → range key (e.g. `'4xx'`) → `'default'`.
* Returns `null` when no entry matches or the content-type cannot be matched.
*/
export declare function resolveResponseEntry(responsesByStatusCode: ResponsesByStatusCode, statusCode: number, contentType: string | undefined, strictContentType: boolean): ResponseKind | null;