@hey-api/openapi-ts 0.80.18 → 0.81.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,97 +1,14 @@
1
1
  import { getAuthToken } from '../core/auth';
2
- import type {
3
- QuerySerializer,
4
- QuerySerializerOptions,
5
- } from '../core/bodySerializer';
2
+ import type { QuerySerializerOptions } from '../core/bodySerializer';
6
3
  import { jsonBodySerializer } from '../core/bodySerializer';
7
4
  import {
8
5
  serializeArrayParam,
9
6
  serializeObjectParam,
10
7
  serializePrimitiveParam,
11
8
  } from '../core/pathSerializer';
9
+ import { getUrl } from '../core/utils';
12
10
  import type { Client, ClientOptions, Config, RequestOptions } from './types';
13
11
 
14
- interface PathSerializer {
15
- path: Record<string, unknown>;
16
- url: string;
17
- }
18
-
19
- const PATH_PARAM_RE = /\{[^{}]+\}/g;
20
-
21
- type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
22
- type MatrixStyle = 'label' | 'matrix' | 'simple';
23
- type ArraySeparatorStyle = ArrayStyle | MatrixStyle;
24
-
25
- const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
26
- let url = _url;
27
- const matches = _url.match(PATH_PARAM_RE);
28
- if (matches) {
29
- for (const match of matches) {
30
- let explode = false;
31
- let name = match.substring(1, match.length - 1);
32
- let style: ArraySeparatorStyle = 'simple';
33
-
34
- if (name.endsWith('*')) {
35
- explode = true;
36
- name = name.substring(0, name.length - 1);
37
- }
38
-
39
- if (name.startsWith('.')) {
40
- name = name.substring(1);
41
- style = 'label';
42
- } else if (name.startsWith(';')) {
43
- name = name.substring(1);
44
- style = 'matrix';
45
- }
46
-
47
- const value = path[name];
48
-
49
- if (value === undefined || value === null) {
50
- continue;
51
- }
52
-
53
- if (Array.isArray(value)) {
54
- url = url.replace(
55
- match,
56
- serializeArrayParam({ explode, name, style, value }),
57
- );
58
- continue;
59
- }
60
-
61
- if (typeof value === 'object') {
62
- url = url.replace(
63
- match,
64
- serializeObjectParam({
65
- explode,
66
- name,
67
- style,
68
- value: value as Record<string, unknown>,
69
- valueOnly: true,
70
- }),
71
- );
72
- continue;
73
- }
74
-
75
- if (style === 'matrix') {
76
- url = url.replace(
77
- match,
78
- `;${serializePrimitiveParam({
79
- name,
80
- value: value as string,
81
- })}`,
82
- );
83
- continue;
84
- }
85
-
86
- const replaceValue = encodeURIComponent(
87
- style === 'label' ? `.${value as string}` : (value as string),
88
- );
89
- url = url.replace(match, replaceValue);
90
- }
91
- }
92
- return url;
93
- };
94
-
95
12
  export const createQuerySerializer = <T = unknown>({
96
13
  allowReserved,
97
14
  array,
@@ -243,8 +160,8 @@ export const setAuthParams = async ({
243
160
  }
244
161
  };
245
162
 
246
- export const buildUrl: Client['buildUrl'] = (options) => {
247
- const url = getUrl({
163
+ export const buildUrl: Client['buildUrl'] = (options) =>
164
+ getUrl({
248
165
  baseUrl: options.baseUrl as string,
249
166
  path: options.path,
250
167
  query: options.query,
@@ -254,36 +171,6 @@ export const buildUrl: Client['buildUrl'] = (options) => {
254
171
  : createQuerySerializer(options.querySerializer),
255
172
  url: options.url,
256
173
  });
257
- return url;
258
- };
259
-
260
- export const getUrl = ({
261
- baseUrl,
262
- path,
263
- query,
264
- querySerializer,
265
- url: _url,
266
- }: {
267
- baseUrl?: string;
268
- path?: Record<string, unknown>;
269
- query?: Record<string, unknown>;
270
- querySerializer: QuerySerializer;
271
- url: string;
272
- }) => {
273
- const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
274
- let url = (baseUrl ?? '') + pathUrl;
275
- if (path) {
276
- url = defaultPathSerializer({ path, url });
277
- }
278
- let search = query ? querySerializer(query) : '';
279
- if (search.startsWith('?')) {
280
- search = search.substring(1);
281
- }
282
- if (search) {
283
- url += `?${search}`;
284
- }
285
- return url;
286
- };
287
174
 
288
175
  export const mergeConfigs = (a: Config, b: Config): Config => {
289
176
  const config = { ...a, ...b };
@@ -1,4 +1,11 @@
1
- import type { Client, Config, ResolvedRequestOptions } from './types';
1
+ import { createSseClient } from '../core/serverSentEvents';
2
+ import type { HttpMethod } from '../core/types';
3
+ import type {
4
+ Client,
5
+ Config,
6
+ RequestOptions,
7
+ ResolvedRequestOptions,
8
+ } from './types';
2
9
  import {
3
10
  buildUrl,
4
11
  createConfig,
@@ -30,8 +37,7 @@ export const createClient = (config: Config = {}): Client => {
30
37
  ResolvedRequestOptions
31
38
  >();
32
39
 
33
- // @ts-expect-error
34
- const request: Client['request'] = async (options) => {
40
+ const beforeRequest = async (options: RequestOptions) => {
35
41
  const opts = {
36
42
  ..._config,
37
43
  ...options,
@@ -60,13 +66,22 @@ export const createClient = (config: Config = {}): Client => {
60
66
  opts.headers.delete('Content-Type');
61
67
  }
62
68
 
69
+ const url = buildUrl(opts);
70
+
71
+ return { opts, url };
72
+ };
73
+
74
+ // @ts-expect-error
75
+ const request: Client['request'] = async (options) => {
76
+ // @ts-expect-error
77
+ const { opts, url } = await beforeRequest(options);
78
+
63
79
  for (const fn of interceptors.request._fns) {
64
80
  if (fn) {
65
81
  await fn(opts);
66
82
  }
67
83
  }
68
84
 
69
- const url = buildUrl(opts);
70
85
  // fetch must be assigned here, otherwise it would throw the error:
71
86
  // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
72
87
  const _fetch = opts.fetch!;
@@ -163,20 +178,47 @@ export const createClient = (config: Config = {}): Client => {
163
178
  };
164
179
  };
165
180
 
181
+ const makeMethodFn =
182
+ (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
183
+ request({ ...options, method });
184
+
185
+ const makeSseFn =
186
+ (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
187
+ const { opts, url } = await beforeRequest(options);
188
+ return createSseClient({
189
+ ...opts,
190
+ body: opts.body as BodyInit | null | undefined,
191
+ headers: opts.headers as unknown as Record<string, string>,
192
+ method,
193
+ url,
194
+ });
195
+ };
196
+
166
197
  return {
167
198
  buildUrl,
168
- connect: (options) => request({ ...options, method: 'CONNECT' }),
169
- delete: (options) => request({ ...options, method: 'DELETE' }),
170
- get: (options) => request({ ...options, method: 'GET' }),
199
+ connect: makeMethodFn('CONNECT'),
200
+ delete: makeMethodFn('DELETE'),
201
+ get: makeMethodFn('GET'),
171
202
  getConfig,
172
- head: (options) => request({ ...options, method: 'HEAD' }),
203
+ head: makeMethodFn('HEAD'),
173
204
  interceptors,
174
- options: (options) => request({ ...options, method: 'OPTIONS' }),
175
- patch: (options) => request({ ...options, method: 'PATCH' }),
176
- post: (options) => request({ ...options, method: 'POST' }),
177
- put: (options) => request({ ...options, method: 'PUT' }),
205
+ options: makeMethodFn('OPTIONS'),
206
+ patch: makeMethodFn('PATCH'),
207
+ post: makeMethodFn('POST'),
208
+ put: makeMethodFn('PUT'),
178
209
  request,
179
210
  setConfig,
180
- trace: (options) => request({ ...options, method: 'TRACE' }),
181
- };
211
+ sse: {
212
+ connect: makeSseFn('CONNECT'),
213
+ delete: makeSseFn('DELETE'),
214
+ get: makeSseFn('GET'),
215
+ head: makeSseFn('HEAD'),
216
+ options: makeSseFn('OPTIONS'),
217
+ patch: makeSseFn('PATCH'),
218
+ post: makeSseFn('POST'),
219
+ put: makeSseFn('PUT'),
220
+ trace: makeSseFn('TRACE'),
221
+ },
222
+ trace: makeMethodFn('TRACE'),
223
+ } as Client;
182
224
  };
@@ -1,4 +1,8 @@
1
1
  import type { Auth } from '../core/auth';
2
+ import type {
3
+ ServerSentEventsOptions,
4
+ ServerSentEventsResult,
5
+ } from '../core/serverSentEvents';
2
6
  import type {
3
7
  Client as CoreClient,
4
8
  Config as CoreConfig,
@@ -44,11 +48,20 @@ export interface Config<T extends ClientOptions = ClientOptions>
44
48
  }
45
49
 
46
50
  export interface RequestOptions<
51
+ TData = unknown,
47
52
  ThrowOnError extends boolean = boolean,
48
53
  Url extends string = string,
49
54
  > extends Config<{
50
- throwOnError: ThrowOnError;
51
- }> {
55
+ throwOnError: ThrowOnError;
56
+ }>,
57
+ Pick<
58
+ ServerSentEventsOptions<TData>,
59
+ | 'onSseError'
60
+ | 'onSseEvent'
61
+ | 'sseDefaultRetryDelay'
62
+ | 'sseMaxRetryAttempts'
63
+ | 'sseMaxRetryDelay'
64
+ > {
52
65
  /**
53
66
  * Any body that you want to add to your request.
54
67
  *
@@ -67,7 +80,7 @@ export interface RequestOptions<
67
80
  export interface ResolvedRequestOptions<
68
81
  ThrowOnError extends boolean = boolean,
69
82
  Url extends string = string,
70
- > extends RequestOptions<ThrowOnError, Url> {
83
+ > extends RequestOptions<unknown, ThrowOnError, Url> {
71
84
  serializedBody?: string;
72
85
  }
73
86
 
@@ -109,16 +122,24 @@ type MethodFn = <
109
122
  TError = unknown,
110
123
  ThrowOnError extends boolean = false,
111
124
  >(
112
- options: Omit<RequestOptions<ThrowOnError>, 'method'>,
125
+ options: Omit<RequestOptions<TData, ThrowOnError>, 'method'>,
113
126
  ) => RequestResult<TData, TError, ThrowOnError>;
114
127
 
128
+ type SseFn = <
129
+ TData = unknown,
130
+ TError = unknown,
131
+ ThrowOnError extends boolean = false,
132
+ >(
133
+ options: Omit<RequestOptions<TData, ThrowOnError>, 'method'>,
134
+ ) => Promise<ServerSentEventsResult<TData, TError>>;
135
+
115
136
  type RequestFn = <
116
137
  TData = unknown,
117
138
  TError = unknown,
118
139
  ThrowOnError extends boolean = false,
119
140
  >(
120
- options: Omit<RequestOptions<ThrowOnError>, 'method'> &
121
- Pick<Required<RequestOptions<ThrowOnError>>, 'method'>,
141
+ options: Omit<RequestOptions<TData, ThrowOnError>, 'method'> &
142
+ Pick<Required<RequestOptions<TData, ThrowOnError>>, 'method'>,
122
143
  ) => RequestResult<TData, TError, ThrowOnError>;
123
144
 
124
145
  type BuildUrlFn = <
@@ -132,7 +153,13 @@ type BuildUrlFn = <
132
153
  options: Pick<TData, 'url'> & Options<TData>,
133
154
  ) => string;
134
155
 
135
- export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn> & {
156
+ export type Client = CoreClient<
157
+ RequestFn,
158
+ Config,
159
+ MethodFn,
160
+ BuildUrlFn,
161
+ SseFn
162
+ > & {
136
163
  interceptors: Middleware<Response, unknown, ResolvedRequestOptions>;
137
164
  };
138
165
 
@@ -161,7 +188,11 @@ type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
161
188
  export type Options<
162
189
  TData extends TDataShape = TDataShape,
163
190
  ThrowOnError extends boolean = boolean,
164
- > = OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'path' | 'query' | 'url'> &
191
+ TResponse = unknown,
192
+ > = OmitKeys<
193
+ RequestOptions<TResponse, ThrowOnError>,
194
+ 'body' | 'path' | 'query' | 'url'
195
+ > &
165
196
  Omit<TData, 'url'>;
166
197
 
167
198
  export type OptionsLegacyParser<
@@ -169,12 +200,16 @@ export type OptionsLegacyParser<
169
200
  ThrowOnError extends boolean = boolean,
170
201
  > = TData extends { body?: any }
171
202
  ? TData extends { headers?: any }
172
- ? OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'headers' | 'url'> & TData
173
- : OmitKeys<RequestOptions<ThrowOnError>, 'body' | 'url'> &
203
+ ? OmitKeys<
204
+ RequestOptions<unknown, ThrowOnError>,
205
+ 'body' | 'headers' | 'url'
206
+ > &
207
+ TData
208
+ : OmitKeys<RequestOptions<unknown, ThrowOnError>, 'body' | 'url'> &
174
209
  TData &
175
- Pick<RequestOptions<ThrowOnError>, 'headers'>
210
+ Pick<RequestOptions<unknown, ThrowOnError>, 'headers'>
176
211
  : TData extends { headers?: any }
177
- ? OmitKeys<RequestOptions<ThrowOnError>, 'headers' | 'url'> &
212
+ ? OmitKeys<RequestOptions<unknown, ThrowOnError>, 'headers' | 'url'> &
178
213
  TData &
179
- Pick<RequestOptions<ThrowOnError>, 'body'>
180
- : OmitKeys<RequestOptions<ThrowOnError>, 'url'> & TData;
214
+ Pick<RequestOptions<unknown, ThrowOnError>, 'body'>
215
+ : OmitKeys<RequestOptions<unknown, ThrowOnError>, 'url'> & TData;
@@ -6,7 +6,9 @@ import {
6
6
  } from 'nuxt/app';
7
7
  import { reactive, ref, watch } from 'vue';
8
8
 
9
- import type { Client, Config } from './types';
9
+ import { createSseClient } from '../core/serverSentEvents';
10
+ import type { HttpMethod } from '../core/types';
11
+ import type { Client, Config, RequestOptions } from './types';
10
12
  import {
11
13
  buildUrl,
12
14
  createConfig,
@@ -16,6 +18,7 @@ import {
16
18
  mergeInterceptors,
17
19
  serializeBody,
18
20
  setAuthParams,
21
+ unwrapRefs,
19
22
  } from './utils';
20
23
 
21
24
  export const createClient = (config: Config = {}): Client => {
@@ -28,6 +31,32 @@ export const createClient = (config: Config = {}): Client => {
28
31
  return getConfig();
29
32
  };
30
33
 
34
+ const beforeRequest = async (options: RequestOptions) => {
35
+ const opts = {
36
+ ..._config,
37
+ ...options,
38
+ $fetch: options.$fetch ?? _config.$fetch ?? $fetch,
39
+ headers: mergeHeaders(_config.headers, options.headers),
40
+ onRequest: mergeInterceptors(_config.onRequest, options.onRequest),
41
+ onResponse: mergeInterceptors(_config.onResponse, options.onResponse),
42
+ };
43
+
44
+ if (opts.security) {
45
+ await setAuthParams({
46
+ ...opts,
47
+ security: opts.security,
48
+ });
49
+ }
50
+
51
+ if (opts.requestValidator) {
52
+ await opts.requestValidator(opts);
53
+ }
54
+
55
+ const url = buildUrl(opts);
56
+
57
+ return { opts, url };
58
+ };
59
+
31
60
  const request: Client['request'] = ({
32
61
  asyncDataOptions,
33
62
  composable,
@@ -107,7 +136,11 @@ export const createClient = (config: Config = {}): Client => {
107
136
  const fetchFn = opts.$fetch;
108
137
 
109
138
  if (composable === '$fetch') {
110
- return executeFetchFn(opts, fetchFn);
139
+ return executeFetchFn(
140
+ // @ts-expect-error
141
+ opts,
142
+ fetchFn,
143
+ );
111
144
  }
112
145
 
113
146
  if (composable === 'useFetch' || composable === 'useLazyFetch') {
@@ -126,7 +159,12 @@ export const createClient = (config: Config = {}): Client => {
126
159
  : useFetch(() => buildUrl(opts), opts);
127
160
  }
128
161
 
129
- const handler: any = () => executeFetchFn(opts, fetchFn);
162
+ const handler: any = () =>
163
+ executeFetchFn(
164
+ // @ts-expect-error
165
+ opts,
166
+ fetchFn,
167
+ );
130
168
 
131
169
  if (composable === 'useAsyncData') {
132
170
  return key
@@ -143,19 +181,46 @@ export const createClient = (config: Config = {}): Client => {
143
181
  return undefined as any;
144
182
  };
145
183
 
184
+ const makeMethodFn =
185
+ (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
186
+ request({ ...options, method });
187
+
188
+ const makeSseFn =
189
+ (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
190
+ const { opts, url } = await beforeRequest(options);
191
+ return createSseClient({
192
+ ...unwrapRefs(opts),
193
+ body: opts.body as BodyInit | null | undefined,
194
+ method,
195
+ signal: unwrapRefs(opts.signal) as AbortSignal,
196
+ url,
197
+ });
198
+ };
199
+
146
200
  return {
147
201
  buildUrl,
148
- connect: (options) => request({ ...options, method: 'CONNECT' }),
149
- delete: (options) => request({ ...options, method: 'DELETE' }),
150
- get: (options) => request({ ...options, method: 'GET' }),
202
+ connect: makeMethodFn('CONNECT'),
203
+ delete: makeMethodFn('DELETE'),
204
+ get: makeMethodFn('GET'),
151
205
  getConfig,
152
- head: (options) => request({ ...options, method: 'HEAD' }),
153
- options: (options) => request({ ...options, method: 'OPTIONS' }),
154
- patch: (options) => request({ ...options, method: 'PATCH' }),
155
- post: (options) => request({ ...options, method: 'POST' }),
156
- put: (options) => request({ ...options, method: 'PUT' }),
206
+ head: makeMethodFn('HEAD'),
207
+ options: makeMethodFn('OPTIONS'),
208
+ patch: makeMethodFn('PATCH'),
209
+ post: makeMethodFn('POST'),
210
+ put: makeMethodFn('PUT'),
157
211
  request,
158
212
  setConfig,
159
- trace: (options) => request({ ...options, method: 'TRACE' }),
160
- };
213
+ sse: {
214
+ connect: makeSseFn('CONNECT'),
215
+ delete: makeSseFn('DELETE'),
216
+ get: makeSseFn('GET'),
217
+ head: makeSseFn('HEAD'),
218
+ options: makeSseFn('OPTIONS'),
219
+ patch: makeSseFn('PATCH'),
220
+ post: makeSseFn('POST'),
221
+ put: makeSseFn('PUT'),
222
+ trace: makeSseFn('TRACE'),
223
+ },
224
+ trace: makeMethodFn('TRACE'),
225
+ } as Client;
161
226
  };
@@ -10,6 +10,10 @@ import type { Ref } from 'vue';
10
10
 
11
11
  import type { Auth } from '../core/auth';
12
12
  import type { QuerySerializerOptions } from '../core/bodySerializer';
13
+ import type {
14
+ ServerSentEventsOptions,
15
+ ServerSentEventsResult,
16
+ } from '../core/serverSentEvents';
13
17
  import type {
14
18
  Client as CoreClient,
15
19
  Config as CoreConfig,
@@ -73,7 +77,15 @@ export interface RequestOptions<
73
77
  path?: FetchOptions<unknown>['query'];
74
78
  query?: FetchOptions<unknown>['query'];
75
79
  rawBody?: unknown;
76
- }> {
80
+ }>,
81
+ Pick<
82
+ ServerSentEventsOptions<ResT>,
83
+ | 'onSseError'
84
+ | 'onSseEvent'
85
+ | 'sseDefaultRetryDelay'
86
+ | 'sseMaxRetryAttempts'
87
+ | 'sseMaxRetryDelay'
88
+ > {
77
89
  asyncDataOptions?: AsyncDataOptions<ResT, ResT, KeysOf<ResT>, DefaultT>;
78
90
  composable: TComposable;
79
91
  key?: string;
@@ -113,6 +125,15 @@ type MethodFn = <
113
125
  options: Omit<RequestOptions<TComposable, ResT, DefaultT>, 'method'>,
114
126
  ) => RequestResult<TComposable, ResT, TError>;
115
127
 
128
+ type SseFn = <
129
+ TComposable extends Composable,
130
+ ResT = unknown,
131
+ TError = unknown,
132
+ DefaultT = undefined,
133
+ >(
134
+ options: Omit<RequestOptions<TComposable, ResT, DefaultT>, 'method'>,
135
+ ) => Promise<ServerSentEventsResult<RequestResult<TComposable, ResT, TError>>>;
136
+
116
137
  type RequestFn = <
117
138
  TComposable extends Composable,
118
139
  ResT = unknown,
@@ -153,7 +174,7 @@ type BuildUrlFn = <TData extends Omit<TDataShape, 'headers'>>(
153
174
  options: BuildUrlOptions<TData>,
154
175
  ) => string;
155
176
 
156
- export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn>;
177
+ export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn>;
157
178
 
158
179
  type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
159
180
 
@@ -334,7 +334,7 @@ type UnwrapRefs<T> =
334
334
  ? { [K in keyof T]: UnwrapRefs<T[K]> }
335
335
  : T;
336
336
 
337
- const unwrapRefs = <T>(value: T): UnwrapRefs<T> => {
337
+ export const unwrapRefs = <T>(value: T): UnwrapRefs<T> => {
338
338
  if (value === null || typeof value !== 'object' || value instanceof Headers) {
339
339
  return (isRef(value) ? unref(value) : value) as UnwrapRefs<T>;
340
340
  }