tangled
alpha
login
or
join now
mokkenstorm.dev
/
openapi-ts
0
fork
atom
fork of hey-api/openapi-ts because I need some additional things
0
fork
atom
overview
issues
pulls
pipelines
chore: clean up fetch client API
Lubos
2 years ago
b213fb5c
5d522f81
+216
-163
7 changed files
expand all
collapse all
unified
split
examples
openapi-ts-fetch
src
App.tsx
client
services.gen.ts
packages
client-fetch
src
index.ts
types.ts
utils.ts
openapi-ts
src
utils
enum.ts
write
services.ts
+16
-2
examples/openapi-ts-fetch/src/App.tsx
···
15
15
baseUrl: 'https://api.fake-museum-example.com/v1.1',
16
16
});
17
17
18
18
+
const localClient = createClient({
19
19
+
baseUrl: 'https://api.fake-museum-example.com/v2',
20
20
+
global: false,
21
21
+
});
22
22
+
23
23
+
localClient.interceptors.request.use((request, options) => {
24
24
+
console.log(options);
25
25
+
return request;
26
26
+
});
27
27
+
18
28
function App() {
19
29
// const [pet, setPet] = useState<Awaited<ReturnType<typeof getPetById>>['data']>();
20
30
21
31
const onGetSpecialEvent = async () => {
22
32
const { data, error } = await getSpecialEvent({
33
33
+
client: localClient,
23
34
path: {
24
35
eventId: 'dad4bce8-f5cb-4078-a211-995864315e39',
25
36
},
···
32
43
};
33
44
34
45
const onBuyMuseumTickets = () => {
35
35
-
// @ts-ignore
36
46
buyMuseumTickets({
37
37
-
body: '',
47
47
+
body: {
48
48
+
email: '',
49
49
+
ticketDate: '',
50
50
+
ticketType: 'event',
51
51
+
},
38
52
});
39
53
};
40
54
+31
-11
examples/openapi-ts-fetch/src/client/services.gen.ts
···
34
34
* Get upcoming museum operating hours.
35
35
*/
36
36
export const getMuseumHours = (options?: Options<GetMuseumHoursData>) =>
37
37
-
client.get<GetMuseumHoursResponse2, GetMuseumHoursError>({
38
38
-
...options,
39
39
-
url: '/museum-hours',
40
40
-
});
37
37
+
(options?.client ?? client).get<GetMuseumHoursResponse2, GetMuseumHoursError>(
38
38
+
{
39
39
+
...options,
40
40
+
url: '/museum-hours',
41
41
+
},
42
42
+
);
41
43
42
44
/**
43
45
* Create special events
44
46
* Creates a new special event for the museum.
45
47
*/
46
48
export const createSpecialEvent = (options: Options<CreateSpecialEventData>) =>
47
47
-
client.post<CreateSpecialEventResponse, CreateSpecialEventError>({
49
49
+
(options?.client ?? client).post<
50
50
+
CreateSpecialEventResponse,
51
51
+
CreateSpecialEventError
52
52
+
>({
48
53
...options,
49
54
url: '/special-events',
50
55
});
···
54
59
* Return a list of upcoming special events at the museum.
55
60
*/
56
61
export const listSpecialEvents = (options?: Options<ListSpecialEventsData>) =>
57
57
-
client.get<ListSpecialEventsResponse2, ListSpecialEventsError>({
62
62
+
(options?.client ?? client).get<
63
63
+
ListSpecialEventsResponse2,
64
64
+
ListSpecialEventsError
65
65
+
>({
58
66
...options,
59
67
url: '/special-events',
60
68
});
···
64
72
* Get details about a special event.
65
73
*/
66
74
export const getSpecialEvent = (options: Options<GetSpecialEventData>) =>
67
67
-
client.get<GetSpecialEventResponse, GetSpecialEventError>({
75
75
+
(options?.client ?? client).get<
76
76
+
GetSpecialEventResponse,
77
77
+
GetSpecialEventError
78
78
+
>({
68
79
...options,
69
80
url: '/special-events/{eventId}',
70
81
});
···
74
85
* Update the details of a special event.
75
86
*/
76
87
export const updateSpecialEvent = (options: Options<UpdateSpecialEventData>) =>
77
77
-
client.patch<UpdateSpecialEventResponse, UpdateSpecialEventError>({
88
88
+
(options?.client ?? client).patch<
89
89
+
UpdateSpecialEventResponse,
90
90
+
UpdateSpecialEventError
91
91
+
>({
78
92
...options,
79
93
url: '/special-events/{eventId}',
80
94
});
···
84
98
* Delete a special event from the collection. Allows museum to cancel planned events.
85
99
*/
86
100
export const deleteSpecialEvent = (options: Options<DeleteSpecialEventData>) =>
87
87
-
client.delete<DeleteSpecialEventResponse, DeleteSpecialEventError>({
101
101
+
(options?.client ?? client).delete<
102
102
+
DeleteSpecialEventResponse,
103
103
+
DeleteSpecialEventError
104
104
+
>({
88
105
...options,
89
106
url: '/special-events/{eventId}',
90
107
});
···
94
111
* Purchase museum tickets for general entry or special events.
95
112
*/
96
113
export const buyMuseumTickets = (options: Options<BuyMuseumTicketsData>) =>
97
97
-
client.post<BuyMuseumTicketsResponse2, BuyMuseumTicketsError>({
114
114
+
(options?.client ?? client).post<
115
115
+
BuyMuseumTicketsResponse2,
116
116
+
BuyMuseumTicketsError
117
117
+
>({
98
118
...options,
99
119
url: '/tickets',
100
120
});
···
104
124
* Return an image of your ticket with scannable QR code. Used for event entry.
105
125
*/
106
126
export const getTicketCode = (options: Options<GetTicketCodeData>) =>
107
107
-
client.get<GetTicketCodeResponse2, GetTicketCodeError>({
127
127
+
(options?.client ?? client).get<GetTicketCodeResponse2, GetTicketCodeError>({
108
128
...options,
109
129
url: '/tickets/{ticketId}/qr',
110
130
});
+31
-55
packages/client-fetch/src/index.ts
···
1
1
-
import type { Config, Req, RequestResult } from './types';
1
1
+
import type { Config, FetchClient, FinalRequestOptions } from './types';
2
2
import {
3
3
createDefaultConfig,
4
4
createInterceptors,
···
82
82
// }
83
83
// };
84
84
85
85
-
type Options = Omit<Req, 'method'>;
86
86
-
87
87
-
type ReqInit = Omit<RequestInit, 'headers'> & {
85
85
+
type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
86
86
+
body?: any;
88
87
headers: ReturnType<typeof mergeHeaders>;
89
88
};
90
90
-
91
91
-
type Opts = Req &
92
92
-
Config & {
93
93
-
headers: ReturnType<typeof mergeHeaders>;
94
94
-
};
95
89
96
90
let globalConfig = createDefaultConfig();
97
91
98
98
-
const globalInterceptors = createInterceptors<Request, Response, Opts>();
92
92
+
const globalInterceptors = createInterceptors<
93
93
+
Request,
94
94
+
Response,
95
95
+
FinalRequestOptions
96
96
+
>();
99
97
100
100
-
export const createClient = (config: Partial<Config>) => {
98
98
+
export const createClient = (config: Config): FetchClient => {
101
99
const defaultConfig = createDefaultConfig();
102
100
const _config = { ...defaultConfig, ...config };
103
101
104
104
-
if (_config.baseUrl.endsWith('/')) {
102
102
+
if (_config.baseUrl?.endsWith('/')) {
105
103
_config.baseUrl = _config.baseUrl.substring(0, _config.baseUrl.length - 1);
106
104
}
107
105
_config.headers = mergeHeaders(defaultConfig.headers, _config.headers);
···
114
112
115
113
const interceptors = _config.global
116
114
? globalInterceptors
117
117
-
: createInterceptors<Request, Response, Opts>();
115
115
+
: createInterceptors<Request, Response, FinalRequestOptions>();
118
116
119
119
-
const request = async <Data = unknown, Error = unknown>(
120
120
-
options: Req,
121
121
-
): RequestResult<Data, Error> => {
117
117
+
// @ts-ignore
118
118
+
const request: FetchClient['request'] = async (options) => {
122
119
const config = getConfig();
123
120
124
124
-
const opts: Opts = {
121
121
+
const opts: FinalRequestOptions = {
125
122
...config,
126
123
...options,
127
124
headers: mergeHeaders(config.headers, options.headers),
128
125
};
126
126
+
if (opts.body && opts.bodySerializer) {
127
127
+
opts.body = opts.bodySerializer(opts.body);
128
128
+
}
129
129
130
130
const url = getUrl({
131
131
-
baseUrl: opts.baseUrl,
131
131
+
baseUrl: opts.baseUrl ?? '',
132
132
path: opts.path,
133
133
query: opts.query,
134
134
querySerializer:
···
142
142
redirect: 'follow',
143
143
...opts,
144
144
};
145
145
-
if (opts.body) {
146
146
-
requestInit.body = opts.bodySerializer(opts.body);
147
147
-
}
148
145
// remove Content-Type if serialized body is FormData; browser will correctly set Content-Type and boundary expression
149
146
if (requestInit.body instanceof FormData) {
150
147
requestInit.headers.delete('Content-Type');
···
156
153
request = await fn(request, opts);
157
154
}
158
155
159
159
-
const _fetch = opts.fetch;
156
156
+
const _fetch = opts.fetch!;
160
157
let response = await _fetch(request);
161
158
162
159
for (const fn of interceptors.response._fns) {
···
175
172
) {
176
173
if (response.ok) {
177
174
return {
178
178
-
// @ts-ignore
179
175
data: {},
180
176
...result,
181
177
};
182
178
}
183
179
return {
184
184
-
// @ts-ignore
185
180
error: {},
186
181
...result,
187
182
};
···
190
185
if (response.ok) {
191
186
if (opts.parseAs === 'stream') {
192
187
return {
193
193
-
// @ts-ignore
194
188
data: response.body,
195
189
...result,
196
190
};
197
191
}
198
192
return {
199
199
-
data: await response[opts.parseAs](),
193
193
+
data: await response[opts.parseAs ?? 'json'](),
200
194
...result,
201
195
};
202
196
}
···
208
202
// noop
209
203
}
210
204
return {
211
211
-
// @ts-ignore
212
205
error,
213
206
...result,
214
207
};
215
208
};
216
209
217
217
-
type Interceptors = {
218
218
-
[P in keyof typeof interceptors]: Pick<
219
219
-
(typeof interceptors)[P],
220
220
-
'eject' | 'use'
221
221
-
>;
222
222
-
};
223
223
-
224
224
-
const client = {
225
225
-
connect: <Data = unknown, Error = unknown>(options: Options) =>
226
226
-
request<Data, Error>({ ...options, method: 'CONNECT' }),
227
227
-
delete: <Data = unknown, Error = unknown>(options: Options) =>
228
228
-
request<Data, Error>({ ...options, method: 'DELETE' }),
229
229
-
get: <Data = unknown, Error = unknown>(options: Options) =>
230
230
-
request<Data, Error>({ ...options, method: 'GET' }),
210
210
+
return {
211
211
+
connect: (options) => request({ ...options, method: 'CONNECT' }),
212
212
+
delete: (options) => request({ ...options, method: 'DELETE' }),
213
213
+
get: (options) => request({ ...options, method: 'GET' }),
231
214
getConfig,
232
232
-
head: <Data = unknown, Error = unknown>(options: Options) =>
233
233
-
request<Data, Error>({ ...options, method: 'HEAD' }),
234
234
-
interceptors: interceptors as Interceptors,
235
235
-
options: <Data = unknown, Error = unknown>(options: Options) =>
236
236
-
request<Data, Error>({ ...options, method: 'OPTIONS' }),
237
237
-
patch: <Data = unknown, Error = unknown>(options: Options) =>
238
238
-
request<Data, Error>({ ...options, method: 'PATCH' }),
239
239
-
post: <Data = unknown, Error = unknown>(options: Options) =>
240
240
-
request<Data, Error>({ ...options, method: 'POST' }),
241
241
-
put: <Data = unknown, Error = unknown>(options: Options) =>
242
242
-
request<Data, Error>({ ...options, method: 'PUT' }),
215
215
+
head: (options) => request({ ...options, method: 'HEAD' }),
216
216
+
interceptors,
217
217
+
options: (options) => request({ ...options, method: 'OPTIONS' }),
218
218
+
patch: (options) => request({ ...options, method: 'PATCH' }),
219
219
+
post: (options) => request({ ...options, method: 'POST' }),
220
220
+
put: (options) => request({ ...options, method: 'PUT' }),
243
221
request,
244
244
-
trace: <Data = unknown, Error = unknown>(options: Options) =>
245
245
-
request<Data, Error>({ ...options, method: 'TRACE' }),
222
222
+
trace: (options) => request({ ...options, method: 'TRACE' }),
246
223
};
247
247
-
return client;
248
224
};
249
225
250
226
export const client = createClient(globalConfig);
+111
-57
packages/client-fetch/src/types.ts
···
1
1
import type {
2
2
BodySerializer,
3
3
-
FetchOptions,
3
3
+
Middleware,
4
4
QuerySerializer,
5
5
QuerySerializerOptions,
6
6
} from './utils';
7
7
8
8
-
type ApiRequestOptions = {
9
9
-
readonly body?: any;
10
10
-
readonly cookies?: Record<string, unknown>;
11
11
-
readonly errors?: Record<number, string>;
12
12
-
readonly formData?: Record<string, unknown>;
13
13
-
readonly headers?: Record<string, unknown>;
14
14
-
readonly mediaType?: string;
15
15
-
readonly method:
8
8
+
type OmitKey<T, K> = Pick<T, Exclude<keyof T, K>>;
9
9
+
10
10
+
export interface Config
11
11
+
extends Omit<RequestInit, 'body' | 'headers' | 'method'> {
12
12
+
/**
13
13
+
* Base URL for all requests made by this client.
14
14
+
* @default ''
15
15
+
*/
16
16
+
baseUrl?: string;
17
17
+
/**
18
18
+
* Any body that you want to add to your request.
19
19
+
*
20
20
+
* {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
21
21
+
*/
22
22
+
body?: RequestInit['body'] | Record<string, unknown>;
23
23
+
/**
24
24
+
* A function for serializing request body parameter. By default,
25
25
+
* {@link JSON.stringify()} will be used.
26
26
+
*/
27
27
+
bodySerializer?: BodySerializer;
28
28
+
/**
29
29
+
* Fetch API implementation. You can use this option to provide a custom
30
30
+
* fetch instance.
31
31
+
* @default globalThis.fetch
32
32
+
*/
33
33
+
fetch?: (request: Request) => ReturnType<typeof fetch>;
34
34
+
/**
35
35
+
* By default, options passed to this call will be applied to the global
36
36
+
* client instance. Set to false to create a local client instance.
37
37
+
* @default true
38
38
+
*/
39
39
+
global?: boolean;
40
40
+
/**
41
41
+
* An object containing any HTTP headers that you want to pre-populate your
42
42
+
* `Headers` object with.
43
43
+
*
44
44
+
* {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
45
45
+
*/
46
46
+
headers?:
47
47
+
| RequestInit['headers']
48
48
+
| Record<
49
49
+
string,
50
50
+
| string
51
51
+
| number
52
52
+
| boolean
53
53
+
| (string | number | boolean)[]
54
54
+
| null
55
55
+
| undefined
56
56
+
>;
57
57
+
/**
58
58
+
* The request method.
59
59
+
*
60
60
+
* {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
61
61
+
*/
62
62
+
method?:
16
63
| 'CONNECT'
17
64
| 'DELETE'
18
65
| 'GET'
···
22
69
| 'POST'
23
70
| 'PUT'
24
71
| 'TRACE';
25
25
-
readonly path?: Record<string, unknown>;
26
26
-
readonly query?: Record<string, unknown>;
27
27
-
readonly responseHeader?: string;
28
28
-
readonly url: string;
29
29
-
};
30
30
-
31
31
-
interface FetchConfig extends FetchOptions {
32
72
/**
33
33
-
* custom fetch
34
34
-
* @default globalThis.fetch
73
73
+
* Return the response data parsed in a specified format. Any of the
74
74
+
* {@link Body} methods are allowed. By default, {@link Body.json()} will be
75
75
+
* used. Select `stream` if you don't want to parse response data.
76
76
+
* @default 'json'
35
77
*/
36
36
-
fetch: (request: Request) => ReturnType<typeof fetch>;
78
78
+
parseAs?: Exclude<keyof Body, 'body' | 'bodyUsed'> | 'stream';
79
79
+
/**
80
80
+
* A function for serializing request query parameters. By default, arrays
81
81
+
* will be exploded in form style, objects will be exploded in deepObject
82
82
+
* style, and reserved characters are percent-encoded.
83
83
+
*
84
84
+
* {@link https://swagger.io/docs/specification/serialization/#query View examples}
85
85
+
*/
86
86
+
querySerializer?: QuerySerializer | QuerySerializerOptions;
37
87
}
38
88
39
39
-
interface BodyType<T = unknown> {
40
40
-
arrayBuffer: Awaited<ReturnType<Response['arrayBuffer']>>;
41
41
-
blob: Awaited<ReturnType<Response['blob']>>;
42
42
-
json: T;
43
43
-
stream: Response['body'];
44
44
-
text: Awaited<ReturnType<Response['text']>>;
89
89
+
interface RequestOptions extends Omit<Config, 'global'> {
90
90
+
path?: Record<string, unknown>;
91
91
+
query?: Record<string, unknown>;
92
92
+
url: string;
45
93
}
46
94
47
47
-
interface RequestResponse<Data = unknown, Error = unknown> {
95
95
+
type RequestResult<Data = unknown, Error = unknown> = Promise<{
48
96
error?: Error;
49
97
data?: Data;
50
98
request: Request;
51
99
response: Response;
100
100
+
}>;
101
101
+
102
102
+
type MethodFn = <Data = unknown, Error = unknown>(
103
103
+
options: RequestOptions,
104
104
+
) => RequestResult<Data, Error>;
105
105
+
type RequestFn = <Data = unknown, Error = unknown>(
106
106
+
options: RequestOptions & Pick<Required<RequestOptions>, 'method'>,
107
107
+
) => RequestResult<Data, Error>;
108
108
+
109
109
+
interface Client<Request = unknown, Response = unknown, Options = unknown> {
110
110
+
connect: MethodFn;
111
111
+
delete: MethodFn;
112
112
+
get: MethodFn;
113
113
+
getConfig: () => Config;
114
114
+
head: MethodFn;
115
115
+
interceptors: Middleware<Request, Response, Options>;
116
116
+
options: MethodFn;
117
117
+
patch: MethodFn;
118
118
+
post: MethodFn;
119
119
+
put: MethodFn;
120
120
+
request: RequestFn;
121
121
+
trace: MethodFn;
52
122
}
53
123
54
54
-
export type RequestResult<Data = unknown, Error = unknown> = Promise<
55
55
-
RequestResponse<Data, Error>
56
56
-
>;
124
124
+
export type FinalRequestOptions = RequestOptions &
125
125
+
Config & {
126
126
+
headers: Headers;
127
127
+
};
57
128
58
58
-
export interface Config extends FetchConfig {
59
59
-
/**
60
60
-
* Base URL...
61
61
-
* @default ''
62
62
-
*/
63
63
-
baseUrl: string;
64
64
-
/**
65
65
-
* Body serializer...
66
66
-
*/
67
67
-
bodySerializer: BodySerializer<unknown>;
68
68
-
/**
69
69
-
* Global??
70
70
-
* @default true
71
71
-
*/
72
72
-
global: boolean;
73
73
-
/**
74
74
-
* Parse as...
75
75
-
* @default 'json'
76
76
-
*/
77
77
-
parseAs: keyof BodyType;
129
129
+
export type FetchClient = Client<Request, Response, FinalRequestOptions>;
130
130
+
131
131
+
type OptionsBase = Omit<RequestOptions, 'url'> & {
78
132
/**
79
79
-
* Query serializer...
133
133
+
* You can provide a client instance returned by `createClient()` instead of
134
134
+
* individual options. This might be also useful if you want to implement a
135
135
+
* custom client.
80
136
*/
81
81
-
querySerializer: QuerySerializer<unknown> | QuerySerializerOptions;
82
82
-
}
137
137
+
client?: FetchClient;
138
138
+
};
83
139
84
84
-
export interface Req
85
85
-
extends Omit<ApiRequestOptions, 'headers'>,
86
86
-
Omit<Partial<Config>, 'body' | 'method'> {}
87
87
-
88
88
-
export type Options<T = unknown> = Omit<Req, 'method' | 'url'> & T;
140
140
+
export type Options<T = unknown> = T extends { body: any }
141
141
+
? OmitKey<OptionsBase, 'body'> & T
142
142
+
: OptionsBase & T;
+25
-36
packages/client-fetch/src/utils.ts
···
13
13
type ObjectStyle = 'form' | 'deepObject';
14
14
type ObjectSeparatorStyle = ObjectStyle | MatrixStyle;
15
15
16
16
-
export interface FetchOptions extends Omit<RequestInit, 'headers'> {
17
17
-
/**
18
18
-
* Headers...
19
19
-
*/
20
20
-
headers?: HeadersOptions;
21
21
-
}
16
16
+
export type QuerySerializer = (query: Record<string, unknown>) => string;
22
17
23
23
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
24
24
-
export type QuerySerializer<T = unknown> = (
25
25
-
query: Record<string, unknown>,
26
26
-
) => string;
27
27
-
28
28
-
// type BodySerializer<T> = (body: OperationRequestBodyContent<T>) => any;
29
29
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
30
30
-
export type BodySerializer<T> = (body: any) => any;
18
18
+
export type BodySerializer = (body: any) => any;
31
19
32
20
interface SerializerOptions<T> {
33
21
/**
···
48
36
value: string;
49
37
}
50
38
51
51
-
export type HeadersOptions =
52
52
-
| HeadersInit
53
53
-
| Record<
54
54
-
string,
55
55
-
| string
56
56
-
| number
57
57
-
| boolean
58
58
-
| (string | number | boolean)[]
59
59
-
| null
60
60
-
| undefined
61
61
-
>;
62
62
-
63
39
export interface QuerySerializerOptions {
64
40
allowReserved?: boolean;
65
41
array?: SerializerOptions<ArrayStyle>;
66
42
object?: SerializerOptions<ObjectStyle>;
67
43
}
68
44
69
69
-
export function serializePrimitiveParam({
45
45
+
function serializePrimitiveParam({
70
46
allowReserved,
71
47
name,
72
48
value,
···
123
99
}
124
100
};
125
101
126
126
-
export function serializeArrayParam({
102
102
+
function serializeArrayParam({
127
103
allowReserved,
128
104
explode,
129
105
name,
···
165
141
return style === 'label' || style === 'matrix' ? separator + final : final;
166
142
}
167
143
168
168
-
export const serializeObjectParam = ({
144
144
+
const serializeObjectParam = ({
169
145
allowReserved,
170
146
explode,
171
147
name,
···
208
184
return style === 'label' || style === 'matrix' ? separator + final : final;
209
185
};
210
186
211
211
-
export function defaultPathSerializer({ path, url: _url }: PathSerializer) {
187
187
+
function defaultPathSerializer({ path, url: _url }: PathSerializer) {
212
188
let url = _url;
213
189
const matches = _url.match(PATH_PARAM_RE);
214
190
if (matches) {
···
362
338
return url;
363
339
}
364
340
365
365
-
export const mergeHeaders = (...headers: Array<HeadersOptions | undefined>) => {
366
366
-
const finalHeaders = new Headers();
341
341
+
export const mergeHeaders = (
342
342
+
...headers: Array<Required<Config>['headers'] | undefined>
343
343
+
) => {
344
344
+
const mergedHeaders = new Headers();
367
345
for (const header of headers) {
368
346
if (!header || typeof header !== 'object') {
369
347
continue;
···
374
352
375
353
for (const [key, value] of iterator) {
376
354
if (value === null) {
377
377
-
finalHeaders.delete(key);
355
355
+
mergedHeaders.delete(key);
378
356
} else if (Array.isArray(value)) {
379
357
for (const v of value) {
380
380
-
finalHeaders.append(key, v as string);
358
358
+
mergedHeaders.append(key, v as string);
381
359
}
382
360
} else if (value !== undefined) {
383
383
-
finalHeaders.set(key, value as string);
361
361
+
mergedHeaders.set(key, value as string);
384
362
}
385
363
}
386
364
}
387
387
-
return finalHeaders;
365
365
+
return mergedHeaders;
388
366
};
389
367
390
368
type ReqInterceptor<Req, Options> = (
···
417
395
}
418
396
}
419
397
398
398
+
// `createInterceptors()` response, meant for external use as it does not
399
399
+
// expose internals
400
400
+
export interface Middleware<Req, Res, Options> {
401
401
+
request: Pick<Interceptors<ReqInterceptor<Req, Options>>, 'eject' | 'use'>;
402
402
+
response: Pick<
403
403
+
Interceptors<ResInterceptor<Res, Req, Options>>,
404
404
+
'eject' | 'use'
405
405
+
>;
406
406
+
}
407
407
+
408
408
+
// do not add `Middleware` as return type so we can use _fns internally
420
409
export const createInterceptors = <Req, Res, Options>() => ({
421
410
request: new Interceptors<ReqInterceptor<Req, Options>>(),
422
411
response: new Interceptors<ResInterceptor<Res, Req, Options>>(),
+1
-1
packages/openapi-ts/src/utils/enum.ts
···
12
12
* 3: Add '_' where the string transitions from lowercase to uppercase
13
13
* 4: Transform the whole string to uppercase
14
14
*
15
15
-
* Javascript identifier regexp pattern retrieved from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers
15
15
+
* Javascript identifier regexp pattern retrieved from https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers
16
16
*/
17
17
export const enumKey = (value?: string | number, customName?: string) => {
18
18
if (customName) {
+1
-1
packages/openapi-ts/src/utils/write/services.ts
···
331
331
return [
332
332
compiler.return.functionCall({
333
333
args: [options],
334
334
-
name: `client.${operation.method.toLocaleLowerCase()}`,
334
334
+
name: `(options?.client ?? client).${operation.method.toLocaleLowerCase()}`,
335
335
types:
336
336
errorType && responseType
337
337
? [responseType, errorType]