@hey-api/openapi-ts
Version:
🚀 The OpenAPI to TypeScript codegen. Generate clients, SDKs, validators, and more.
334 lines (316 loc) • 9.6 kB
text/typescript
import type {
FetchOptions as OfetchOptions,
ResponseType as OfetchResponseType,
} from 'ofetch';
import type { ofetch } from 'ofetch';
import type { Auth } from '../core/auth';
import type {
ServerSentEventsOptions,
ServerSentEventsResult,
} from '../core/serverSentEvents';
import type {
Client as CoreClient,
Config as CoreConfig,
} from '../core/types';
import type { Middleware } from './utils';
export type ResponseStyle = 'data' | 'fields';
export interface Config<T extends ClientOptions = ClientOptions>
extends Omit<RequestInit, 'body' | 'headers' | 'method'>,
CoreConfig {
/**
* HTTP(S) agent configuration (Node.js only). Passed through to ofetch.
*/
agent?: OfetchOptions['agent'];
/**
* Base URL for all requests made by this client.
*/
baseUrl?: T['baseUrl'];
/**
* Node-only proxy/agent options.
*/
dispatcher?: OfetchOptions['dispatcher'];
/**
* Fetch API implementation. Used for SSE streaming. You can use this option
* to provide a custom fetch instance.
*
* @default globalThis.fetch
*/
fetch?: typeof fetch;
/**
* Controls the native ofetch behaviour that throws `FetchError` when
* `response.ok === false`. We default to suppressing it to match the fetch
* client semantics and let `throwOnError` drive the outcome.
*/
ignoreResponseError?: OfetchOptions['ignoreResponseError'];
// No custom fetch option: provide custom instance via `ofetch` instead
/**
* Please don't use the Fetch client for Next.js applications. The `next`
* options won't have any effect.
*
* Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
*/
next?: never;
/**
* Custom ofetch instance created via `ofetch.create()`. If provided, it will
* be used for requests instead of the default `ofetch` export.
*/
ofetch?: typeof ofetch;
/**
* ofetch hook called before a request is sent.
*/
onRequest?: OfetchOptions['onRequest'];
/**
* ofetch hook called when a request fails before receiving a response
* (e.g., network errors or aborted requests).
*/
onRequestError?: OfetchOptions['onRequestError'];
/**
* ofetch hook called after a successful response is received and parsed.
*/
onResponse?: OfetchOptions['onResponse'];
/**
* ofetch hook called when the response indicates an error (non-ok status)
* or when response parsing fails.
*/
onResponseError?: OfetchOptions['onResponseError'];
/**
* Return the response data parsed in a specified format. By default, `auto`
* will infer the appropriate method from the `Content-Type` response header.
* You can override this behavior with any of the {@link Body} methods.
* Select `stream` if you don't want to parse response data at all.
*
* @default 'auto'
*/
parseAs?:
| 'arrayBuffer'
| 'auto'
| 'blob'
| 'formData'
| 'json'
| 'stream'
| 'text';
/** Custom response parser (ofetch). */
parseResponse?: OfetchOptions['parseResponse'];
/**
* Should we return only data or multiple fields (data, error, response, etc.)?
*
* @default 'fields'
*/
responseStyle?: ResponseStyle;
/**
* ofetch responseType override. If provided, it will be passed directly to
* ofetch and take precedence over `parseAs`.
*/
responseType?: OfetchResponseType;
/**
* Automatically retry failed requests.
*/
retry?: OfetchOptions['retry'];
/**
* Delay (in ms) between retry attempts.
*/
retryDelay?: OfetchOptions['retryDelay'];
/**
* HTTP status codes that should trigger a retry.
*/
retryStatusCodes?: OfetchOptions['retryStatusCodes'];
/**
* Throw an error instead of returning it in the response?
*
* @default false
*/
throwOnError?: T['throwOnError'];
/**
* Abort the request after the given milliseconds.
*/
timeout?: number;
}
export interface RequestOptions<
TData = unknown,
TResponseStyle extends ResponseStyle = 'fields',
ThrowOnError extends boolean = boolean,
Url extends string = string,
> extends Config<{
responseStyle: TResponseStyle;
throwOnError: ThrowOnError;
}>,
Pick<
ServerSentEventsOptions<TData>,
| 'onSseError'
| 'onSseEvent'
| 'sseDefaultRetryDelay'
| 'sseMaxRetryAttempts'
| 'sseMaxRetryDelay'
> {
/**
* Any body that you want to add to your request.
*
* {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
*/
body?: unknown;
path?: Record<string, unknown>;
query?: Record<string, unknown>;
/**
* Security mechanism(s) to use for the request.
*/
security?: ReadonlyArray<Auth>;
url: Url;
}
export interface ResolvedRequestOptions<
TResponseStyle extends ResponseStyle = 'fields',
ThrowOnError extends boolean = boolean,
Url extends string = string,
> extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> {
serializedBody?: string;
}
export type RequestResult<
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = boolean,
TResponseStyle extends ResponseStyle = 'fields',
> = ThrowOnError extends true
? Promise<
TResponseStyle extends 'data'
? TData extends Record<string, unknown>
? TData[keyof TData]
: TData
: {
data: TData extends Record<string, unknown>
? TData[keyof TData]
: TData;
request: Request;
response: Response;
}
>
: Promise<
TResponseStyle extends 'data'
?
| (TData extends Record<string, unknown>
? TData[keyof TData]
: TData)
| undefined
: (
| {
data: TData extends Record<string, unknown>
? TData[keyof TData]
: TData;
error: undefined;
}
| {
data: undefined;
error: TError extends Record<string, unknown>
? TError[keyof TError]
: TError;
}
) & {
request: Request;
response: Response;
}
>;
export interface ClientOptions {
baseUrl?: string;
responseStyle?: ResponseStyle;
throwOnError?: boolean;
}
type MethodFn = <
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
type SseFn = <
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
) => Promise<ServerSentEventsResult<TData, TError>>;
type RequestFn = <
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
Pick<
Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>,
'method'
>,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
type BuildUrlFn = <
TData extends {
body?: unknown;
path?: Record<string, unknown>;
query?: Record<string, unknown>;
url: string;
},
>(
options: Pick<TData, 'url'> & Options<TData>,
) => string;
export type Client = CoreClient<
RequestFn,
Config,
MethodFn,
BuildUrlFn,
SseFn
> & {
interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>;
};
/**
* The `createClientConfig()` function will be called on client initialization
* and the returned object will become the client's initial configuration.
*
* You may want to initialize your client this way instead of calling
* `setConfig()`. This is useful for example if you're using Next.js
* to ensure your client always has the correct values.
*/
export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
override?: Config<ClientOptions & T>,
) => Config<Required<ClientOptions> & T>;
export interface TDataShape {
body?: unknown;
headers?: unknown;
path?: unknown;
query?: unknown;
url: string;
}
type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
export type Options<
TData extends TDataShape = TDataShape,
ThrowOnError extends boolean = boolean,
TResponse = unknown,
TResponseStyle extends ResponseStyle = 'fields',
> = OmitKeys<
RequestOptions<TResponse, TResponseStyle, ThrowOnError>,
'body' | 'path' | 'query' | 'url'
> &
Omit<TData, 'url'>;
export type OptionsLegacyParser<
TData = unknown,
ThrowOnError extends boolean = boolean,
TResponseStyle extends ResponseStyle = 'fields',
> = TData extends { body?: any }
? TData extends { headers?: any }
? OmitKeys<
RequestOptions<unknown, TResponseStyle, ThrowOnError>,
'body' | 'headers' | 'url'
> &
TData
: OmitKeys<
RequestOptions<unknown, TResponseStyle, ThrowOnError>,
'body' | 'url'
> &
TData &
Pick<RequestOptions<unknown, TResponseStyle, ThrowOnError>, 'headers'>
: TData extends { headers?: any }
? OmitKeys<
RequestOptions<unknown, TResponseStyle, ThrowOnError>,
'headers' | 'url'
> &
TData &
Pick<RequestOptions<unknown, TResponseStyle, ThrowOnError>, 'body'>
: OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, 'url'> &
TData;