Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
21 changes: 14 additions & 7 deletions examples/openapi-ts-fastify/src/client/client/client.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
headers: ReturnType<typeof mergeHeaders>;
};

type ParseAs = NonNullable<Config['parseAs']>;

export const createClient = (config: Config = {}): Client => {
let _config = mergeConfigs(createConfig(), config);

Expand All @@ -29,15 +31,21 @@ export const createClient = (config: Config = {}): Client => {
return getConfig();
};

const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
const interceptors = createInterceptors<
Request,
Response,
unknown,
ResolvedRequestOptions<'fields' | 'data', boolean, string, ParseAs>
>();

const beforeRequest = async <
TData = unknown,
TResponseStyle extends 'data' | 'fields' = 'fields',
ThrowOnError extends boolean = boolean,
Url extends string = string,
TParseAs extends ParseAs = 'auto',
>(
options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url, TParseAs>,
) => {
const opts = {
..._config,
Expand Down Expand Up @@ -65,7 +73,7 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts &
ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;
ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url, TParseAs>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
Expand Down Expand Up @@ -112,10 +120,9 @@ export const createClient = (config: Config = {}): Client => {
};

if (response.ok) {
const parseAs =
(opts.parseAs === 'auto'
? getParseAs(response.headers.get('Content-Type'))
: opts.parseAs) ?? 'json';
const parseAs = ((opts.parseAs === 'auto'
? getParseAs(response.headers.get('Content-Type'))
: opts.parseAs) ?? 'json') as Exclude<ParseAs, 'auto'>;

if (response.status === 204 || response.headers.get('Content-Length') === '0') {
let emptyData: any;
Expand Down
59 changes: 43 additions & 16 deletions examples/openapi-ts-fastify/src/client/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ import type { Middleware } from './utils.gen';

export type ResponseStyle = 'data' | 'fields';

type ParseAs = 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';

type ParsedResponse<TData, TParseAs extends ParseAs> = TParseAs extends 'arrayBuffer'
? ArrayBuffer
: TParseAs extends 'blob'
? Blob
: TParseAs extends 'formData'
? FormData
: TParseAs extends 'stream'
? Response['body']
: TParseAs extends 'text'
? string
: TData extends Record<string, unknown>
? TData[keyof TData]
: TData;

export interface Config<T extends ClientOptions = ClientOptions>
extends Omit<RequestInit, 'body' | 'headers' | 'method'>, CoreConfig {
/**
Expand Down Expand Up @@ -35,7 +51,7 @@ export interface Config<T extends ClientOptions = ClientOptions>
*
* @default 'auto'
*/
parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
parseAs?: T['parseAs'];
/**
* Should we return only data or multiple fields (data, error, response, etc.)?
*
Expand All @@ -55,9 +71,11 @@ export interface RequestOptions<
TResponseStyle extends ResponseStyle = 'fields',
ThrowOnError extends boolean = boolean,
Url extends string = string,
TParseAs extends ParseAs = ParseAs,
>
extends
Config<{
parseAs: TParseAs;
responseStyle: TResponseStyle;
throwOnError: ThrowOnError;
}>,
Expand Down Expand Up @@ -89,7 +107,8 @@ export interface ResolvedRequestOptions<
TResponseStyle extends ResponseStyle = 'fields',
ThrowOnError extends boolean = boolean,
Url extends string = string,
> extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> {
TParseAs extends ParseAs = ParseAs,
> extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url, TParseAs> {
headers: Headers;
serializedBody?: string;
}
Expand All @@ -99,24 +118,23 @@ export type RequestResult<
TError = unknown,
ThrowOnError extends boolean = boolean,
TResponseStyle extends ResponseStyle = 'fields',
TParseAs extends ParseAs = 'auto',
> = ThrowOnError extends true
? Promise<
TResponseStyle extends 'data'
? TData extends Record<string, unknown>
? TData[keyof TData]
: TData
? ParsedResponse<TData, TParseAs>
: {
data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
data: ParsedResponse<TData, TParseAs>;
request: Request;
response: Response;
}
>
: Promise<
TResponseStyle extends 'data'
? (TData extends Record<string, unknown> ? TData[keyof TData] : TData) | undefined
? ParsedResponse<TData, TParseAs> | undefined
: (
| {
data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
data: ParsedResponse<TData, TParseAs>;
error: undefined;
}
| {
Expand All @@ -133,6 +151,7 @@ export type RequestResult<

export interface ClientOptions {
baseUrl?: string;
parseAs?: ParseAs;
responseStyle?: ResponseStyle;
throwOnError?: boolean;
}
Expand All @@ -142,9 +161,10 @@ type MethodFn = <
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
TParseAs extends ParseAs = 'auto',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError, string, TParseAs>, 'method'>,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle, TParseAs>;

type SseFn = <
TData = unknown,
Expand All @@ -161,10 +181,11 @@ type RequestFn = <
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
TParseAs extends ParseAs = 'auto',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError, string, TParseAs>, 'method'> &
Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError, string, TParseAs>>, 'method'>,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle, TParseAs>;

type BuildUrlFn = <
TData extends {
Expand All @@ -174,11 +195,16 @@ type BuildUrlFn = <
url: string;
},
>(
options: TData & Options<TData>,
options: TData & Options<TData, boolean, unknown, 'fields', ParseAs>,
) => string;

export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>;
interceptors: Middleware<
Request,
Response,
unknown,
ResolvedRequestOptions<ResponseStyle, boolean, string, ParseAs>
>;
};

/**
Expand Down Expand Up @@ -208,8 +234,9 @@ export type Options<
ThrowOnError extends boolean = boolean,
TResponse = unknown,
TResponseStyle extends ResponseStyle = 'fields',
TParseAs extends ParseAs = 'auto',
> = OmitKeys<
RequestOptions<TResponse, TResponseStyle, ThrowOnError>,
RequestOptions<TResponse, TResponseStyle, ThrowOnError, string, TParseAs>,
'body' | 'path' | 'query' | 'url'
> &
([TData] extends [never] ? unknown : Omit<TData, 'url'>);
72 changes: 49 additions & 23 deletions examples/openapi-ts-fastify/src/client/sdk.gen.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
// This file is auto-generated by @hey-api/openapi-ts

import type { Client, ClientMeta, Options as Options2, RequestResult, TDataShape } from './client';
import type {
Client,
ClientMeta,
Config,
Options as Options2,
RequestResult,
TDataShape,
} from './client';
import { client } from './client.gen';
import type {
CreatePetsData,
Expand All @@ -18,7 +25,8 @@ export type Options<
TData extends TDataShape = TDataShape,
ThrowOnError extends boolean = boolean,
TResponse = unknown,
> = Options2<TData, ThrowOnError, TResponse> & {
TParseAs extends NonNullable<Config['parseAs']> = 'auto',
> = Options2<TData, ThrowOnError, TResponse, 'fields', TParseAs> & {
/**
* You can provide a client instance returned by `createClient()` instead of
* individual options. This might be also useful if you want to implement a
Expand All @@ -35,32 +43,50 @@ export type Options<
/**
* List all pets
*/
export const listPets = <ThrowOnError extends boolean = false>(
options?: Options<ListPetsData, ThrowOnError>,
): RequestResult<ListPetsResponses, ListPetsErrors, ThrowOnError> =>
(options?.client ?? client).get<ListPetsResponses, ListPetsErrors, ThrowOnError>({
url: '/pets',
...options,
});
export const listPets = <
ThrowOnError extends boolean = false,
TParseAs extends NonNullable<Config['parseAs']> = 'auto',
>(
options?: Options<ListPetsData, ThrowOnError, ListPetsResponses, TParseAs>,
): RequestResult<ListPetsResponses, ListPetsErrors, ThrowOnError, 'fields', TParseAs> =>
(options?.client ?? client).get<
ListPetsResponses,
ListPetsErrors,
ThrowOnError,
'fields',
TParseAs
>({ url: '/pets', ...options });

/**
* Create a pet
*/
export const createPets = <ThrowOnError extends boolean = false>(
options?: Options<CreatePetsData, ThrowOnError>,
): RequestResult<CreatePetsResponses, CreatePetsErrors, ThrowOnError> =>
(options?.client ?? client).post<CreatePetsResponses, CreatePetsErrors, ThrowOnError>({
url: '/pets',
...options,
});
export const createPets = <
ThrowOnError extends boolean = false,
TParseAs extends NonNullable<Config['parseAs']> = 'auto',
>(
options?: Options<CreatePetsData, ThrowOnError, CreatePetsResponses, TParseAs>,
): RequestResult<CreatePetsResponses, CreatePetsErrors, ThrowOnError, 'fields', TParseAs> =>
(options?.client ?? client).post<
CreatePetsResponses,
CreatePetsErrors,
ThrowOnError,
'fields',
TParseAs
>({ url: '/pets', ...options });

/**
* Info for a specific pet
*/
export const showPetById = <ThrowOnError extends boolean = false>(
options: Options<ShowPetByIdData, ThrowOnError>,
): RequestResult<ShowPetByIdResponses, ShowPetByIdErrors, ThrowOnError> =>
(options.client ?? client).get<ShowPetByIdResponses, ShowPetByIdErrors, ThrowOnError>({
url: '/pets/{petId}',
...options,
});
export const showPetById = <
ThrowOnError extends boolean = false,
TParseAs extends NonNullable<Config['parseAs']> = 'auto',
>(
options: Options<ShowPetByIdData, ThrowOnError, ShowPetByIdResponses, TParseAs>,
): RequestResult<ShowPetByIdResponses, ShowPetByIdErrors, ThrowOnError, 'fields', TParseAs> =>
(options.client ?? client).get<
ShowPetByIdResponses,
ShowPetByIdErrors,
ThrowOnError,
'fields',
TParseAs
>({ url: '/pets/{petId}', ...options });
21 changes: 14 additions & 7 deletions examples/openapi-ts-fetch/src/client/client/client.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
headers: ReturnType<typeof mergeHeaders>;
};

type ParseAs = NonNullable<Config['parseAs']>;

export const createClient = (config: Config = {}): Client => {
let _config = mergeConfigs(createConfig(), config);

Expand All @@ -29,15 +31,21 @@ export const createClient = (config: Config = {}): Client => {
return getConfig();
};

const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
const interceptors = createInterceptors<
Request,
Response,
unknown,
ResolvedRequestOptions<'fields' | 'data', boolean, string, ParseAs>
>();

const beforeRequest = async <
TData = unknown,
TResponseStyle extends 'data' | 'fields' = 'fields',
ThrowOnError extends boolean = boolean,
Url extends string = string,
TParseAs extends ParseAs = 'auto',
>(
options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url, TParseAs>,
) => {
const opts = {
..._config,
Expand Down Expand Up @@ -65,7 +73,7 @@ export const createClient = (config: Config = {}): Client => {
}

const resolvedOpts = opts as typeof opts &
ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;
ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url, TParseAs>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
Expand Down Expand Up @@ -112,10 +120,9 @@ export const createClient = (config: Config = {}): Client => {
};

if (response.ok) {
const parseAs =
(opts.parseAs === 'auto'
? getParseAs(response.headers.get('Content-Type'))
: opts.parseAs) ?? 'json';
const parseAs = ((opts.parseAs === 'auto'
? getParseAs(response.headers.get('Content-Type'))
: opts.parseAs) ?? 'json') as Exclude<ParseAs, 'auto'>;

if (response.status === 204 || response.headers.get('Content-Length') === '0') {
let emptyData: any;
Expand Down
Loading
Loading