···11// This file is auto-generated by @hey-api/openapi-ts
2233import {
44- type ClientOptions as DefaultClientOptions,
44+ type ClientOptions,
55 type Config,
66 createClient,
77 createConfig,
88} from './client';
99-import type { ClientOptions } from './types.gen';
99+import type { ClientOptions as ClientOptions2 } from './types.gen';
10101111/**
1212 * The `createClientConfig()` function will be called on client initialization
···1616 * `setConfig()`. This is useful for example if you're using Next.js
1717 * to ensure your client always has the correct values.
1818 */
1919-export type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> =
2020- (
2121- override?: Config<DefaultClientOptions & T>,
2222- ) => Config<Required<DefaultClientOptions> & T>;
1919+export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (
2020+ override?: Config<ClientOptions & T>,
2121+) => Config<Required<ClientOptions> & T>;
23222423export const client = createClient(
2525- createConfig<ClientOptions>({
2424+ createConfig<ClientOptions2>({
2625 baseUrl: 'https://petstore3.swagger.io/api/v3',
2726 }),
2827);
···2222export interface Config<T extends ClientOptions = ClientOptions>
2323 extends Omit<RequestInit, 'body' | 'headers' | 'method'>,
2424 CoreConfig {
2525+ /**
2626+ * HTTP(S) agent configuration (Node.js only). Passed through to ofetch.
2727+ */
2528 agent?: OfetchOptions['agent'];
2629 /**
2730 * Base URL for all requests made by this client.
2831 */
2932 baseUrl?: T['baseUrl'];
3030- /** Node-only proxy/agent options */
3333+ /**
3434+ * Node-only proxy/agent options.
3535+ */
3136 dispatcher?: OfetchOptions['dispatcher'];
3232- /** Optional fetch instance used for SSE streaming */
3737+ /**
3838+ * Fetch API implementation. Used for SSE streaming. You can use this option
3939+ * to provide a custom fetch instance.
4040+ *
4141+ * @default globalThis.fetch
4242+ */
3343 fetch?: typeof fetch;
4444+ /**
4545+ * Controls the native ofetch behaviour that throws `FetchError` when
4646+ * `response.ok === false`. We default to suppressing it to match the fetch
4747+ * client semantics and let `throwOnError` drive the outcome.
4848+ */
4949+ ignoreResponseError?: OfetchOptions['ignoreResponseError'];
3450 // No custom fetch option: provide custom instance via `ofetch` instead
3551 /**
3652 * Please don't use the Fetch client for Next.js applications. The `next`
···4460 * be used for requests instead of the default `ofetch` export.
4561 */
4662 ofetch?: typeof ofetch;
4747- /** ofetch interceptors and runtime options */
6363+ /**
6464+ * ofetch hook called before a request is sent.
6565+ */
4866 onRequest?: OfetchOptions['onRequest'];
6767+ /**
6868+ * ofetch hook called when a request fails before receiving a response
6969+ * (e.g., network errors or aborted requests).
7070+ */
4971 onRequestError?: OfetchOptions['onRequestError'];
7272+ /**
7373+ * ofetch hook called after a successful response is received and parsed.
7474+ */
5075 onResponse?: OfetchOptions['onResponse'];
7676+ /**
7777+ * ofetch hook called when the response indicates an error (non-ok status)
7878+ * or when response parsing fails.
7979+ */
5180 onResponseError?: OfetchOptions['onResponseError'];
5281 /**
5382 * Return the response data parsed in a specified format. By default, `auto`
···82111 * Automatically retry failed requests.
83112 */
84113 retry?: OfetchOptions['retry'];
114114+ /**
115115+ * Delay (in ms) between retry attempts.
116116+ */
85117 retryDelay?: OfetchOptions['retryDelay'];
118118+ /**
119119+ * HTTP status codes that should trigger a retry.
120120+ */
86121 retryStatusCodes?: OfetchOptions['retryStatusCodes'];
87122 /**
88123 * Throw an error instead of returning it in the response?
···316316export const buildOfetchOptions = (
317317 opts: ResolvedRequestOptions,
318318 body: BodyInit | null | undefined,
319319+ responseType: OfetchResponseType | undefined,
319320 retryOverride?: OfetchOptions['retry'],
320320-): OfetchOptions => {
321321- const responseType = mapParseAsToResponseType(
322322- opts.parseAs,
323323- opts.responseType,
324324- );
325325- return {
321321+): OfetchOptions =>
322322+ ({
326323 agent: opts.agent as OfetchOptions['agent'],
327327- body: body as any,
324324+ body,
325325+ credentials: opts.credentials as OfetchOptions['credentials'],
328326 dispatcher: opts.dispatcher as OfetchOptions['dispatcher'],
329327 headers: opts.headers as Headers,
328328+ ignoreResponseError:
329329+ (opts.ignoreResponseError as OfetchOptions['ignoreResponseError']) ??
330330+ true,
330331 method: opts.method,
331332 onRequest: opts.onRequest as OfetchOptions['onRequest'],
332333 onRequestError: opts.onRequestError as OfetchOptions['onRequestError'],
333334 onResponse: opts.onResponse as OfetchOptions['onResponse'],
334335 onResponseError: opts.onResponseError as OfetchOptions['onResponseError'],
335336 parseResponse: opts.parseResponse as OfetchOptions['parseResponse'],
336336- query: undefined, // URL already includes query
337337+ // URL already includes query
338338+ query: undefined,
337339 responseType,
338338- retry: (retryOverride ??
339339- (opts.retry as OfetchOptions['retry'])) as OfetchOptions['retry'],
340340+ retry: retryOverride ?? (opts.retry as OfetchOptions['retry']),
340341 retryDelay: opts.retryDelay as OfetchOptions['retryDelay'],
341342 retryStatusCodes:
342343 opts.retryStatusCodes as OfetchOptions['retryStatusCodes'],
343344 signal: opts.signal,
344345 timeout: opts.timeout as number | undefined,
345345- } as OfetchOptions;
346346-};
346346+ }) as OfetchOptions;
347347348348/**
349349 * Parse a successful response, handling empty bodies and stream cases.
···382382 }
383383 }
384384385385- // Prefer ofetch-populated data
385385+ // Prefer ofetch-populated data unless we explicitly need raw `formData`
386386 let data: unknown = (response as any)._data;
387387- if (typeof data === 'undefined') {
387387+ if (inferredParseAs === 'formData' || typeof data === 'undefined') {
388388 switch (inferredParseAs) {
389389 case 'arrayBuffer':
390390 case 'blob':
391391 case 'formData':
392392- case 'json':
393392 case 'text':
394393 data = await (response as any)[inferredParseAs]();
395394 break;
395395+ case 'json': {
396396+ // Some servers return 200 with no Content-Length and empty body.
397397+ // response.json() would throw; detect empty via clone().text() first.
398398+ const txt = await response.clone().text();
399399+ if (!txt) {
400400+ data = {};
401401+ } else {
402402+ data = await (response as any).json();
403403+ }
404404+ break;
405405+ }
396406 case 'stream':
397407 return response.body;
398408 }
···526536): Config<Omit<ClientOptions, keyof T> & T> => ({
527537 ...jsonBodySerializer,
528538 headers: defaultHeaders,
539539+ ignoreResponseError: true,
529540 parseAs: 'auto',
530541 querySerializer: defaultQuerySerializer,
531542 ...override,
+1-1
examples/openapi-ts-ofetch/src/client/index.ts
···11// This file is auto-generated by @hey-api/openapi-ts
2233export * from './sdk.gen';
44-export * from './types.gen';
44+export type * from './types.gen';
+2-2
examples/openapi-ts-ofetch/src/client/sdk.gen.ts
···11// This file is auto-generated by @hey-api/openapi-ts
2233-import type { Client, Options as ClientOptions, TDataShape } from './client';
33+import type { Client, Options as Options2, TDataShape } from './client';
44import { client } from './client.gen';
55import type {
66 AddPetData,
···6565export type Options<
6666 TData extends TDataShape = TDataShape,
6767 ThrowOnError extends boolean = boolean,
6868-> = ClientOptions<TData, ThrowOnError> & {
6868+> = Options2<TData, ThrowOnError> & {
6969 /**
7070 * You can provide a client instance returned by `createClient()` instead of
7171 * individual options. This might be also useful if you want to implement a