@hey-api/openapi-ts 0.94.5 → 0.96.0

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.
package/README.md CHANGED
@@ -33,7 +33,7 @@ Part of the Hey API ecosystem.
33
33
  ## Features
34
34
 
35
35
  - production-ready code that compiles
36
- - runs in any Node.js 20+ environment
36
+ - runs in any Node.js 22+ environment
37
37
  - accepts any OpenAPI specification
38
38
  - core plugins for SDKs, types, and schemas
39
39
  - HTTP clients for Fetch API, Angular, Axios, Next.js, Nuxt, and more
@@ -41,12 +41,18 @@ Part of the Hey API ecosystem.
41
41
  - highly customizable via plugins
42
42
  - [sync with Hey API Registry](https://heyapi.dev/openapi-ts/integrations) for spec management
43
43
 
44
+ <!-- template-contributing-start -->
45
+
44
46
  ## Contributing
45
47
 
46
48
  Want to see your code in products used by millions?
47
49
 
48
50
  Start with our [Contributing](https://heyapi.dev/openapi-ts/community/contributing) guide and release your first feature.
49
51
 
52
+ <!-- template-contributing-end -->
53
+
54
+ <!-- template-sponsors-start -->
55
+
50
56
  ## Sponsors
51
57
 
52
58
  Hey API is sponsor-funded. If you rely on Hey API in production, consider becoming a [sponsor](https://github.com/sponsors/hey-api) to accelerate the roadmap.
@@ -93,26 +99,6 @@ Hey API is sponsor-funded. If you rely on Hey API in production, consider becomi
93
99
  <p></p>
94
100
  </td>
95
101
  </tr>
96
- <tr>
97
- <td align="center" width="336px">
98
- <p></p>
99
- <p>
100
- <a href="https://kutt.to/6vrYy9" target="_blank">
101
- <picture height="50px">
102
- <source media="(prefers-color-scheme: dark)" srcset="https://heyapi.dev/assets/mintlify/logo-light.svg">
103
- <img alt="Mintlify logo" height="50px" src="https://heyapi.dev/assets/mintlify/logo-dark.svg">
104
- </picture>
105
- </a>
106
- <br/>
107
- The intelligent knowledge platform.
108
- <br/>
109
- <a href="https://kutt.to/6vrYy9" style="text-decoration:none;" target="_blank">
110
- mintlify.com
111
- </a>
112
- </p>
113
- <p></p>
114
- </td>
115
- </tr>
116
102
  </tbody>
117
103
  </table>
118
104
 
@@ -173,6 +159,7 @@ Hey API is sponsor-funded. If you rely on Hey API in production, consider becomi
173
159
  </tr>
174
160
  </tbody>
175
161
  </table>
162
+ <!-- template-sponsors-end -->
176
163
 
177
164
  ## Quick Start
178
165
 
@@ -191,7 +178,7 @@ You can download `@hey-api/openapi-ts` from npm using your favorite package mana
191
178
  #### npm
192
179
 
193
180
  ```sh
194
- npm install @hey-api/openapi-ts -D -E
181
+ npm add @hey-api/openapi-ts -D -E
195
182
  ```
196
183
 
197
184
  #### pnpm
@@ -247,6 +234,56 @@ createClient({
247
234
  });
248
235
  ```
249
236
 
237
+ ### Vite
238
+
239
+ If you're using [Vite](https://vite.dev), you can integrate `@hey-api/openapi-ts` directly into your build pipeline with `@hey-api/vite-plugin`. Install it alongside the main package:
240
+
241
+ #### npm
242
+
243
+ ```sh
244
+ npm add @hey-api/vite-plugin -D -E
245
+ ```
246
+
247
+ #### pnpm
248
+
249
+ ```sh
250
+ pnpm add @hey-api/vite-plugin -D -E
251
+ ```
252
+
253
+ #### yarn
254
+
255
+ ```sh
256
+ yarn add @hey-api/vite-plugin -D -E
257
+ ```
258
+
259
+ #### bun
260
+
261
+ ```sh
262
+ bun add @hey-api/vite-plugin -D -E
263
+ ```
264
+
265
+ Then add the plugin to your Vite configuration:
266
+
267
+ #### `vite.config.ts`
268
+
269
+ ```ts
270
+ import { heyApiPlugin } from '@hey-api/vite-plugin';
271
+ import { defineConfig } from 'vite';
272
+
273
+ export default defineConfig({
274
+ plugins: [
275
+ heyApiPlugin({
276
+ config: {
277
+ input: 'hey-api/backend', // sign up at app.heyapi.dev
278
+ output: 'src/client',
279
+ },
280
+ }),
281
+ ],
282
+ });
283
+ ```
284
+
285
+ See the [Vite](https://heyapi.dev/openapi-ts/configuration/vite) page for full configuration options.
286
+
250
287
  ## Configuration
251
288
 
252
289
  `@hey-api/openapi-ts` supports loading configuration from any file inside your project root folder supported by [jiti loader](https://github.com/unjs/c12?tab=readme-ov-file#-features). Below are the most common file formats.
@@ -378,6 +415,10 @@ Don't see your plugin? [Build your own](https://heyapi.dev/openapi-ts/plugins/cu
378
415
 
379
416
  You can learn more on the [Migrating](https://heyapi.dev/openapi-ts/migrating) page.
380
417
 
418
+ <!-- template-license-start -->
419
+
381
420
  ## License
382
421
 
383
422
  Released under the [MIT License](https://github.com/hey-api/openapi-ts/blob/main/LICENSE.md).
423
+
424
+ <!-- template-license-end -->
@@ -95,7 +95,14 @@ export const createClient = (config: Config = {}): Client => {
95
95
  return { opts, req, url };
96
96
  };
97
97
 
98
- const beforeRequest = async (options: RequestOptions) => {
98
+ const beforeRequest = async <
99
+ TData = unknown,
100
+ TResponseStyle extends ResponseStyle = 'fields',
101
+ ThrowOnError extends boolean = boolean,
102
+ Url extends string = string,
103
+ >(
104
+ options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
105
+ ) => {
99
106
  const { opts, req, url } = requestOptions(options);
100
107
 
101
108
  if (opts.security) {
@@ -113,7 +120,6 @@ export const createClient = (config: Config = {}): Client => {
113
120
  };
114
121
 
115
122
  const request: Client['request'] = async (options) => {
116
- // @ts-expect-error
117
123
  const { opts, req: initialReq } = await beforeRequest(options);
118
124
 
119
125
  let req = initialReq;
@@ -157,7 +157,7 @@ type SseFn = <
157
157
  ThrowOnError extends boolean = false,
158
158
  TResponseStyle extends ResponseStyle = 'fields',
159
159
  >(
160
- options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
160
+ options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
161
161
  ) => Promise<ServerSentEventsResult<TData, TError>>;
162
162
 
163
163
  type RequestFn = <
@@ -33,7 +33,13 @@ export const createClient = (config: Config = {}): Client => {
33
33
  return getConfig();
34
34
  };
35
35
 
36
- const beforeRequest = async (options: RequestOptions) => {
36
+ const beforeRequest = async <
37
+ TData = unknown,
38
+ ThrowOnError extends boolean = boolean,
39
+ Url extends string = string,
40
+ >(
41
+ options: RequestOptions<TData, ThrowOnError, Url>,
42
+ ) => {
37
43
  const opts = {
38
44
  ..._config,
39
45
  ...options,
@@ -63,7 +69,6 @@ export const createClient = (config: Config = {}): Client => {
63
69
 
64
70
  // @ts-expect-error
65
71
  const request: Client['request'] = async (options) => {
66
- // @ts-expect-error
67
72
  const { opts, url } = await beforeRequest(options);
68
73
  try {
69
74
  // assign Axios here for consistency with fetch
@@ -106,7 +106,7 @@ type MethodFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean
106
106
  ) => RequestResult<TData, TError, ThrowOnError>;
107
107
 
108
108
  type SseFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(
109
- options: Omit<RequestOptions<TData, ThrowOnError>, 'method'>,
109
+ options: Omit<RequestOptions<never, ThrowOnError>, 'method'>,
110
110
  ) => Promise<ServerSentEventsResult<TData, TError>>;
111
111
 
112
112
  type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(
@@ -116,13 +116,16 @@ type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolea
116
116
 
117
117
  type BuildUrlFn = <
118
118
  TData extends {
119
- body?: unknown;
120
119
  path?: Record<string, unknown>;
121
120
  query?: Record<string, unknown>;
122
121
  url: string;
123
122
  },
124
123
  >(
125
- options: TData & Options<TData>,
124
+ options: TData &
125
+ Pick<
126
+ RequestOptions<unknown, boolean>,
127
+ 'axios' | 'baseURL' | 'paramsSerializer' | 'querySerializer'
128
+ >,
126
129
  ) => string;
127
130
 
128
131
  export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
@@ -77,7 +77,7 @@ export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unkn
77
77
  >;
78
78
  };
79
79
 
80
- export const createSseClient = <TData = unknown>({
80
+ export function createSseClient<TData = unknown>({
81
81
  onRequest,
82
82
  onSseError,
83
83
  onSseEvent,
@@ -89,7 +89,7 @@ export const createSseClient = <TData = unknown>({
89
89
  sseSleepFn,
90
90
  url,
91
91
  ...options
92
- }: ServerSentEventsOptions): ServerSentEventsResult<TData> => {
92
+ }: ServerSentEventsOptions): ServerSentEventsResult<TData> {
93
93
  let lastEventId: string | undefined;
94
94
 
95
95
  const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
@@ -153,8 +153,7 @@ export const createSseClient = <TData = unknown>({
153
153
  const { done, value } = await reader.read();
154
154
  if (done) break;
155
155
  buffer += value;
156
- // Normalize line endings: CRLF -> LF, then CR -> LF
157
- buffer = buffer.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
156
+ buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings
158
157
 
159
158
  const chunks = buffer.split('\n\n');
160
159
  buffer = chunks.pop() ?? '';
@@ -238,4 +237,4 @@ export const createSseClient = <TData = unknown>({
238
237
  const stream = createStream();
239
238
 
240
239
  return { stream };
241
- };
240
+ }
@@ -29,7 +29,14 @@ export const createClient = (config: Config = {}): Client => {
29
29
 
30
30
  const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
31
31
 
32
- const beforeRequest = async (options: RequestOptions) => {
32
+ const beforeRequest = async <
33
+ TData = unknown,
34
+ TResponseStyle extends 'data' | 'fields' = 'fields',
35
+ ThrowOnError extends boolean = boolean,
36
+ Url extends string = string,
37
+ >(
38
+ options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
39
+ ) => {
33
40
  const opts = {
34
41
  ..._config,
35
42
  ...options,
@@ -58,13 +65,14 @@ export const createClient = (config: Config = {}): Client => {
58
65
  opts.headers.delete('Content-Type');
59
66
  }
60
67
 
61
- const url = buildUrl(opts);
68
+ const resolvedOpts = opts as typeof opts &
69
+ ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;
70
+ const url = buildUrl(resolvedOpts);
62
71
 
63
- return { opts, url };
72
+ return { opts: resolvedOpts, url };
64
73
  };
65
74
 
66
75
  const request: Client['request'] = async (options) => {
67
- // @ts-expect-error
68
76
  const { opts, url } = await beforeRequest(options);
69
77
  const requestInit: ReqInit = {
70
78
  redirect: 'follow',
@@ -150,7 +150,7 @@ type SseFn = <
150
150
  ThrowOnError extends boolean = false,
151
151
  TResponseStyle extends ResponseStyle = 'fields',
152
152
  >(
153
- options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
153
+ options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
154
154
  ) => Promise<ServerSentEventsResult<TData, TError>>;
155
155
 
156
156
  type RequestFn = <
@@ -28,7 +28,14 @@ export const createClient = (config: Config = {}): Client => {
28
28
 
29
29
  const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
30
30
 
31
- const beforeRequest = async (options: RequestOptions) => {
31
+ const beforeRequest = async <
32
+ TData = unknown,
33
+ TResponseStyle extends 'data' | 'fields' = 'fields',
34
+ ThrowOnError extends boolean = boolean,
35
+ Url extends string = string,
36
+ >(
37
+ options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
38
+ ) => {
32
39
  const opts = {
33
40
  ..._config,
34
41
  ...options,
@@ -56,9 +63,11 @@ export const createClient = (config: Config = {}): Client => {
56
63
  opts.headers.delete('Content-Type');
57
64
  }
58
65
 
59
- const url = buildUrl(opts);
66
+ const resolvedOpts = opts as typeof opts &
67
+ ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;
68
+ const url = buildUrl(resolvedOpts);
60
69
 
61
- return { opts, url };
70
+ return { opts: resolvedOpts, url };
62
71
  };
63
72
 
64
73
  const parseErrorResponse = async (
@@ -105,7 +114,6 @@ export const createClient = (config: Config = {}): Client => {
105
114
  };
106
115
 
107
116
  const request: Client['request'] = async (options) => {
108
- // @ts-expect-error
109
117
  const { opts, url } = await beforeRequest(options);
110
118
 
111
119
  const kyInstance = opts.ky!;
@@ -182,7 +182,7 @@ type SseFn = <
182
182
  ThrowOnError extends boolean = false,
183
183
  TResponseStyle extends ResponseStyle = 'fields',
184
184
  >(
185
- options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
185
+ options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
186
186
  ) => Promise<ServerSentEventsResult<TData, TError>>;
187
187
 
188
188
  type RequestFn = <
@@ -29,7 +29,13 @@ export const createClient = (config: Config = {}): Client => {
29
29
 
30
30
  const interceptors = createInterceptors<Response, unknown, ResolvedRequestOptions>();
31
31
 
32
- const beforeRequest = async (options: RequestOptions) => {
32
+ const beforeRequest = async <
33
+ TData = unknown,
34
+ ThrowOnError extends boolean = boolean,
35
+ Url extends string = string,
36
+ >(
37
+ options: RequestOptions<TData, ThrowOnError, Url>,
38
+ ) => {
33
39
  const opts = {
34
40
  ..._config,
35
41
  ...options,
@@ -58,14 +64,14 @@ export const createClient = (config: Config = {}): Client => {
58
64
  opts.headers.delete('Content-Type');
59
65
  }
60
66
 
61
- const url = buildUrl(opts);
67
+ const resolvedOpts = opts as typeof opts & ResolvedRequestOptions<ThrowOnError, Url>;
68
+ const url = buildUrl(resolvedOpts);
62
69
 
63
- return { opts, url };
70
+ return { opts: resolvedOpts, url };
64
71
  };
65
72
 
66
73
  // @ts-expect-error
67
74
  const request: Client['request'] = async (options) => {
68
- // @ts-expect-error
69
75
  const { opts, url } = await beforeRequest(options);
70
76
 
71
77
  for (const fn of interceptors.request.fns) {
@@ -110,7 +110,7 @@ type MethodFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean
110
110
  ) => RequestResult<TData, TError, ThrowOnError>;
111
111
 
112
112
  type SseFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(
113
- options: Omit<RequestOptions<TData, ThrowOnError>, 'method'>,
113
+ options: Omit<RequestOptions<never, ThrowOnError>, 'method'>,
114
114
  ) => Promise<ServerSentEventsResult<TData, TError>>;
115
115
 
116
116
  type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(
@@ -213,7 +213,7 @@ type SseFn = <
213
213
  ThrowOnError extends boolean = false,
214
214
  TResponseStyle extends ResponseStyle = 'fields',
215
215
  >(
216
- options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
216
+ options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
217
217
  ) => Promise<ServerSentEventsResult<TData, TError>>;
218
218
 
219
219
  type RequestFn = <