Skip to content

Commit 9511090

Browse files
committed
Separate TS types to be managed manually
1 parent bebf08c commit 9511090

17 files changed

+1050
-594
lines changed

.changeset/fair-carpets-beg.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-fetch": patch
3+
---
4+
5+
Separate TS types to be managed manually

packages/openapi-fetch/package.json

+8-7
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@
4747
"svelte"
4848
],
4949
"scripts": {
50-
"build": "pnpm run build:clean && pnpm run build:ts && pnpm run build:ts-min && pnpm run build:cjs",
50+
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:js-min && pnpm run build:cjs",
5151
"build:clean": "del dist",
52-
"build:ts": "tsc -p tsconfig.build.json",
53-
"build:ts-min": "esbuild --bundle src/index.ts --format=esm --minify --outfile=dist/index.min.js && cp dist/index.d.ts dist/index.min.d.ts",
54-
"build:cjs": "esbuild --bundle src/index.ts --format=cjs --outfile=dist/cjs/index.cjs && cp dist/index.d.ts dist/cjs/index.d.cts",
52+
"build:js": "mkdir -p dist && cp src/* dist",
53+
"build:js-min": "esbuild --bundle src/index.js --format=esm --minify --outfile=dist/index.min.js && cp dist/index.d.ts dist/index.min.d.ts",
54+
"build:cjs": "esbuild --bundle src/index.js --format=cjs --outfile=dist/cjs/index.cjs && cp dist/index.d.ts dist/cjs/index.d.cts",
5555
"lint": "pnpm run lint:js",
5656
"lint:js": "eslint \"{src,test}/**/*.{js,ts}\"",
5757
"lint:prettier": "prettier --check \"{src,test}/**/*\"",
@@ -66,10 +66,11 @@
6666
"openapi-typescript-helpers": "^0.0.4"
6767
},
6868
"devDependencies": {
69-
"axios": "^1.5.1",
69+
"axios": "^1.6.0",
7070
"del-cli": "^5.1.0",
71-
"esbuild": "^0.19.4",
72-
"nanostores": "^0.9.3",
71+
"esbuild": "^0.19.5",
72+
"jsdom": "^22.1.0",
73+
"nanostores": "^0.9.4",
7374
"openapi-typescript": "^6.7.0",
7475
"openapi-typescript-codegen": "^0.25.0",
7576
"openapi-typescript-fetch": "^1.1.3",

packages/openapi-fetch/src/index.d.ts

+272
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
import type {
2+
ErrorResponse,
3+
SuccessResponse,
4+
FilterKeys,
5+
MediaType,
6+
PathsWithMethod,
7+
ResponseObjectMap,
8+
OperationRequestBodyContent,
9+
HasRequiredKeys,
10+
} from "openapi-typescript-helpers";
11+
12+
// Note: though "any" is considered bad practice in general, this library relies
13+
// on "any" for type inference only it can give. Same goes for the "{}" type.
14+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types */
15+
16+
/** Options for each client instance */
17+
export interface ClientOptions extends Omit<RequestInit, "headers"> {
18+
/** set the common root URL for all API requests */
19+
baseUrl?: string;
20+
/** custom fetch (defaults to globalThis.fetch) */
21+
fetch?: typeof fetch;
22+
/** global querySerializer */
23+
querySerializer?: QuerySerializer<unknown>;
24+
/** global bodySerializer */
25+
bodySerializer?: BodySerializer<unknown>;
26+
headers?: HeadersOptions;
27+
}
28+
29+
export type HeadersOptions =
30+
| HeadersInit
31+
| Record<string, string | number | boolean | null | undefined>;
32+
33+
export type QuerySerializer<T> = (
34+
query: T extends { parameters: any }
35+
? NonNullable<T["parameters"]["query"]>
36+
: Record<string, unknown>,
37+
) => string;
38+
39+
export type BodySerializer<T> = (body: OperationRequestBodyContent<T>) => any;
40+
41+
export type ParseAs = "json" | "text" | "blob" | "arrayBuffer" | "stream";
42+
43+
export interface DefaultParamsOption {
44+
params?: {
45+
query?: Record<string, unknown>;
46+
};
47+
}
48+
49+
export type ParamsOption<T> = T extends {
50+
parameters: any;
51+
}
52+
? HasRequiredKeys<T["parameters"]> extends never
53+
? { params?: T["parameters"] }
54+
: { params: T["parameters"] }
55+
: DefaultParamsOption;
56+
57+
export type RequestBodyOption<T> = OperationRequestBodyContent<T> extends never
58+
? { body?: never }
59+
: undefined extends OperationRequestBodyContent<T>
60+
? { body?: OperationRequestBodyContent<T> }
61+
: { body: OperationRequestBodyContent<T> };
62+
63+
export type FetchOptions<T> = RequestOptions<T> & Omit<RequestInit, "body">;
64+
65+
export type FetchResponse<T> =
66+
| {
67+
data: FilterKeys<SuccessResponse<ResponseObjectMap<T>>, MediaType>;
68+
error?: never;
69+
response: Response;
70+
}
71+
| {
72+
data?: never;
73+
error: FilterKeys<ErrorResponse<ResponseObjectMap<T>>, MediaType>;
74+
response: Response;
75+
};
76+
77+
export type RequestOptions<T> = ParamsOption<T> &
78+
RequestBodyOption<T> & {
79+
querySerializer?: QuerySerializer<T>;
80+
bodySerializer?: BodySerializer<T>;
81+
parseAs?: ParseAs;
82+
fetch?: ClientOptions["fetch"];
83+
};
84+
85+
export default function createClient<Paths extends {}>(
86+
clientOptions?: ClientOptions,
87+
): {
88+
/** Call a GET endpoint */
89+
GET<P extends PathsWithMethod<Paths, "get">>(
90+
url: P,
91+
...init: HasRequiredKeys<
92+
FetchOptions<FilterKeys<Paths[P], "get">>
93+
> extends never
94+
? [(FetchOptions<FilterKeys<Paths[P], "get">> | undefined)?]
95+
: [FetchOptions<FilterKeys<Paths[P], "get">>]
96+
): Promise<
97+
FetchResponse<
98+
"get" extends infer T
99+
? T extends "get"
100+
? T extends keyof Paths[P]
101+
? Paths[P][T]
102+
: unknown
103+
: never
104+
: never
105+
>
106+
>;
107+
/** Call a PUT endpoint */
108+
PUT<P extends PathsWithMethod<Paths, "put">>(
109+
url: P,
110+
...init: HasRequiredKeys<
111+
FetchOptions<FilterKeys<Paths[P], "put">>
112+
> extends never
113+
? [(FetchOptions<FilterKeys<Paths[P], "put">> | undefined)?]
114+
: [FetchOptions<FilterKeys<Paths[P], "put">>]
115+
): Promise<
116+
FetchResponse<
117+
"put" extends infer T
118+
? T extends "put"
119+
? T extends keyof Paths[P]
120+
? Paths[P][T]
121+
: unknown
122+
: never
123+
: never
124+
>
125+
>;
126+
/** Call a POST endpoint */
127+
POST<P extends PathsWithMethod<Paths, "post">>(
128+
url: P,
129+
...init: HasRequiredKeys<
130+
FetchOptions<FilterKeys<Paths[P], "post">>
131+
> extends never
132+
? [(FetchOptions<FilterKeys<Paths[P], "post">> | undefined)?]
133+
: [FetchOptions<FilterKeys<Paths[P], "post">>]
134+
): Promise<
135+
FetchResponse<
136+
"post" extends infer T
137+
? T extends "post"
138+
? T extends keyof Paths[P]
139+
? Paths[P][T]
140+
: unknown
141+
: never
142+
: never
143+
>
144+
>;
145+
/** Call a DELETE endpoint */
146+
DELETE<P extends PathsWithMethod<Paths, "delete">>(
147+
url: P,
148+
...init: HasRequiredKeys<
149+
FetchOptions<FilterKeys<Paths[P], "delete">>
150+
> extends never
151+
? [(FetchOptions<FilterKeys<Paths[P], "delete">> | undefined)?]
152+
: [FetchOptions<FilterKeys<Paths[P], "delete">>]
153+
): Promise<
154+
FetchResponse<
155+
"delete" extends infer T
156+
? T extends "delete"
157+
? T extends keyof Paths[P]
158+
? Paths[P][T]
159+
: unknown
160+
: never
161+
: never
162+
>
163+
>;
164+
/** Call a OPTIONS endpoint */
165+
OPTIONS<P extends PathsWithMethod<Paths, "options">>(
166+
url: P,
167+
...init: HasRequiredKeys<
168+
FetchOptions<FilterKeys<Paths[P], "options">>
169+
> extends never
170+
? [(FetchOptions<FilterKeys<Paths[P], "options">> | undefined)?]
171+
: [FetchOptions<FilterKeys<Paths[P], "options">>]
172+
): Promise<
173+
FetchResponse<
174+
"options" extends infer T
175+
? T extends "options"
176+
? T extends keyof Paths[P]
177+
? Paths[P][T]
178+
: unknown
179+
: never
180+
: never
181+
>
182+
>;
183+
/** Call a HEAD endpoint */
184+
HEAD<P extends PathsWithMethod<Paths, "head">>(
185+
url: P,
186+
...init: HasRequiredKeys<
187+
FetchOptions<FilterKeys<Paths[P], "head">>
188+
> extends never
189+
? [(FetchOptions<FilterKeys<Paths[P], "head">> | undefined)?]
190+
: [FetchOptions<FilterKeys<Paths[P], "head">>]
191+
): Promise<
192+
FetchResponse<
193+
"head" extends infer T
194+
? T extends "head"
195+
? T extends keyof Paths[P]
196+
? Paths[P][T]
197+
: unknown
198+
: never
199+
: never
200+
>
201+
>;
202+
/** Call a PATCH endpoint */
203+
PATCH<P extends PathsWithMethod<Paths, "patch">>(
204+
url: P,
205+
...init: HasRequiredKeys<
206+
FetchOptions<FilterKeys<Paths[P], "patch">>
207+
> extends never
208+
? [(FetchOptions<FilterKeys<Paths[P], "patch">> | undefined)?]
209+
: [FetchOptions<FilterKeys<Paths[P], "patch">>]
210+
): Promise<
211+
FetchResponse<
212+
"patch" extends infer T
213+
? T extends "patch"
214+
? T extends keyof Paths[P]
215+
? Paths[P][T]
216+
: unknown
217+
: never
218+
: never
219+
>
220+
>;
221+
/** Call a TRACE endpoint */
222+
TRACE<P extends PathsWithMethod<Paths, "trace">>(
223+
url: P,
224+
...init: HasRequiredKeys<
225+
FetchOptions<FilterKeys<Paths[P], "trace">>
226+
> extends never
227+
? [(FetchOptions<FilterKeys<Paths[P], "trace">> | undefined)?]
228+
: [FetchOptions<FilterKeys<Paths[P], "trace">>]
229+
): Promise<
230+
FetchResponse<
231+
"trace" extends infer T
232+
? T extends "trace"
233+
? T extends keyof Paths[P]
234+
? Paths[P][T]
235+
: unknown
236+
: never
237+
: never
238+
>
239+
>;
240+
};
241+
242+
/** Serialize query params to string */
243+
export declare function defaultQuerySerializer<T = unknown>(q: T): string;
244+
245+
/** Serialize query param schema types according to expected default OpenAPI 3.x behavior */
246+
export declare function defaultQueryParamSerializer<T = unknown>(
247+
key: string[],
248+
value: T,
249+
): string | undefined;
250+
251+
/** Serialize body object to string */
252+
export declare function defaultBodySerializer<T>(body: T): string;
253+
254+
/** Construct URL string from baseUrl and handle path and query params */
255+
export declare function createFinalURL<O>(
256+
pathname: string,
257+
options: {
258+
baseUrl: string;
259+
params: {
260+
query?: Record<string, unknown>;
261+
path?: Record<string, unknown>;
262+
};
263+
querySerializer: QuerySerializer<O>;
264+
},
265+
): string;
266+
267+
/** Merge headers a and b, with b taking priority */
268+
export declare function mergeHeaders(
269+
...allHeaders: (HeadersOptions | undefined)[]
270+
): Headers;
271+
272+
export {};

0 commit comments

Comments
 (0)