···11+---
22+'@hey-api/openapi-ts': minor
33+'@hey-api/docs': minor
44+---
55+66+feat: add watch mode
77+88+## Watch Mode
99+1010+::: warning
1111+Watch mode currently supports only remote files via URL.
1212+:::
1313+1414+If your schema changes frequently, you may want to automatically regenerate the output during development. To watch your input file for changes, enable `watch` mode in your configuration or pass the `--watch` flag to the CLI.
1515+1616+### Config
1717+1818+```js
1919+export default {
2020+ client: '@hey-api/client-fetch',
2121+ input: 'path/to/openapi.json',
2222+ output: 'src/client',
2323+ watch: true, // [!code ++]
2424+};
2525+```
2626+2727+### CLI
2828+2929+```sh
3030+npx @hey-api/openapi-ts -i path/to/openapi.json -o src/client -c @hey-api/client-fetch -w
3131+```
+89-64
docs/openapi-ts/configuration.md
···43434444## Input
45454646-Input is the first thing you must define. It can be a local path, remote URL, or a string content resolving to an OpenAPI specification. Hey API supports all valid OpenAPI versions and file formats.
4646+Input is the first thing you must define. It can be a path, URL, or a string content resolving to an OpenAPI specification. Hey API supports all valid OpenAPI versions and file formats.
47474848::: info
4949-We use [`@apidevtools/json-schema-ref-parser`](https://github.com/APIDevTools/json-schema-ref-parser) to resolve file locations. Please note that accessing a HTTPS URL on localhost has a known [workaround](https://github.com/hey-api/openapi-ts/issues/276).
4949+We use [`@hey-api/json-schema-ref-parser`](https://github.com/hey-api/json-schema-ref-parser) to resolve file locations. Please note that accessing a HTTPS URL on localhost has a known [workaround](https://github.com/hey-api/openapi-ts/issues/276).
5050:::
51515252## Output
···5656::: tip
5757You should treat the output folder as a dependency. Do not directly modify its contents as your changes might be erased when you run `@hey-api/openapi-ts` again.
5858:::
5959+6060+## Clients
6161+6262+Clients are responsible for sending the actual HTTP requests. The `client` value is not required, but you must define it if you're generating SDKs (enabled by default).
6363+6464+You can learn more on the [Clients](/openapi-ts/clients) page.
6565+6666+<!--
6767+TODO: uncomment after c12 supports multiple configs
6868+see https://github.com/unjs/c12/issues/92
6969+-->
7070+<!-- ### Multiple Clients
7171+7272+If you want to generate multiple clients with a single `openapi-ts` command, you can provide an array of configuration objects.
7373+7474+```js
7575+import { defineConfig } from '@hey-api/openapi-ts';
7676+7777+export default defineConfig([
7878+ {
7979+ client: 'legacy/fetch',
8080+ input: 'path/to/openapi_one.json',
8181+ output: 'src/client_one',
8282+ },
8383+ {
8484+ client: 'legacy/axios',
8585+ input: 'path/to/openapi_two.json',
8686+ output: 'src/client_two',
8787+ },
8888+])
8989+``` -->
9090+9191+## Plugins
9292+9393+Plugins are responsible for generating artifacts from your input. By default, Hey API will generate TypeScript interfaces and SDK from your OpenAPI specification. You can add, remove, or customize any of the plugins. In fact, we highly encourage you to do so!
9494+9595+You can learn more on the [Output](/openapi-ts/output) page.
9696+9797+## Parser
9898+9999+If you're using OpenAPI 3.0 or newer, we encourage you to try out the experimental parser. In the future this will become the default parser, but until it's been tested it's an opt-in feature. To try it out, set the `experimentalParser` flag in your configuration to `true`.
100100+101101+::: code-group
102102+103103+```js [config]
104104+export default {
105105+ client: '@hey-api/client-fetch',
106106+ experimentalParser: true, // [!code ++]
107107+ input: 'path/to/openapi.json',
108108+ output: 'src/client',
109109+};
110110+```
111111+112112+```sh [cli]
113113+npx @hey-api/openapi-ts -i path/to/openapi.json -o src/client -c @hey-api/client-fetch -e
114114+```
115115+116116+:::
117117+118118+The experimental parser produces a cleaner output while being faster than the legacy parser. It also supports features such as [Filters](#filters) and more are being added.
119119+120120+The legacy parser will be used with the [legacy clients](/openapi-ts/clients/legacy) regardless of the `experimentalParser` flag value. However, it's unlikely to receive any further updates.
5912160122## Formatting
61123···154216155217You can also prevent your output from being linted by adding your output path to the linter's ignore file.
156218157157-## Clients
158158-159159-Clients are responsible for sending the actual HTTP requests. The `client` value is not required, but you must define it if you're generating SDKs (enabled by default).
160160-161161-You can learn more on the [Clients](/openapi-ts/clients) page.
162162-163163-<!--
164164-TODO: uncomment after c12 supports multiple configs
165165-see https://github.com/unjs/c12/issues/92
166166--->
167167-<!-- ### Multiple Clients
168168-169169-If you want to generate multiple clients with a single `openapi-ts` command, you can provide an array of configuration objects.
170170-171171-```js
172172-import { defineConfig } from '@hey-api/openapi-ts';
173173-174174-export default defineConfig([
175175- {
176176- client: 'legacy/fetch',
177177- input: 'path/to/openapi_one.json',
178178- output: 'src/client_one',
179179- },
180180- {
181181- client: 'legacy/axios',
182182- input: 'path/to/openapi_two.json',
183183- output: 'src/client_two',
184184- },
185185-])
186186-``` -->
187187-188188-## Plugins
189189-190190-Plugins are responsible for generating artifacts from your input. By default, Hey API will generate TypeScript interfaces and SDK from your OpenAPI specification. You can add, remove, or customize any of the plugins. In fact, we highly encourage you to do so!
191191-192192-You can learn more on the [Output](/openapi-ts/output) page.
193193-194194-## Parser
195195-196196-If you're using OpenAPI 3.0 or newer, we encourage you to try out the experimental parser. In the future this will become the default parser, but until it's been tested it's an opt-in feature. To try it out, set the `experimentalParser` flag in your configuration to `true`.
197197-198198-::: code-group
199199-200200-```js [config]
201201-export default {
202202- client: '@hey-api/client-fetch',
203203- experimentalParser: true, // [!code ++]
204204- input: 'path/to/openapi.json',
205205- output: 'src/client',
206206-};
207207-```
208208-209209-```sh [cli]
210210-npx @hey-api/openapi-ts -i path/to/openapi.json -o src/client -c @hey-api/client-fetch -e
211211-```
212212-213213-:::
214214-215215-The experimental parser produces a cleaner output while being faster than the legacy parser. It also supports features such as [Filters](#filters) and more are being added.
216216-217217-The legacy parser will be used with the [legacy clients](/openapi-ts/clients/legacy) regardless of the `experimentalParser` flag value. However, it's unlikely to receive any further updates.
218218-219219## Filters
220220221221::: warning
···250250 },
251251 output: 'src/client',
252252};
253253+```
254254+255255+:::
256256+257257+## Watch Mode
258258+259259+::: warning
260260+Watch mode currently supports only remote files via URL.
261261+:::
262262+263263+If your schema changes frequently, you may want to automatically regenerate the output during development. To watch your input file for changes, enable `watch` mode in your configuration or pass the `--watch` flag to the CLI.
264264+265265+::: code-group
266266+267267+```js [config]
268268+export default {
269269+ client: '@hey-api/client-fetch',
270270+ input: 'path/to/openapi.json',
271271+ output: 'src/client',
272272+ watch: true, // [!code ++]
273273+};
274274+```
275275+276276+```sh [cli]
277277+npx @hey-api/openapi-ts -i path/to/openapi.json -o src/client -c @hey-api/client-fetch -w
253278```
254279255280:::
+6
docs/openapi-ts/migrating.md
···27272828This config option is deprecated and will be removed.
29293030+## v0.61.0
3131+3232+### Added `watch` option
3333+3434+While this is a new feature, supporting it involved replacing the `@apidevtools/json-schema-ref-parser` dependency with our own implementation. Since this was a big change, we're applying caution and marking this as a breaking change.
3535+3036## v0.60.0
31373238### Added `sdk.transformer` option
+12-2
packages/openapi-ts/bin/index.cjs
···3434 'DEPRECATED. Manually set base in OpenAPI config instead of inferring from server value',
3535 )
3636 .option('-s, --silent', 'Set log level to silent')
3737+ .option(
3838+ '-w, --watch [value]',
3939+ 'Regenerate the client when the input file changes?',
4040+ )
3741 .option('--exportCore [value]', 'DEPRECATED. Write core files to disk')
3842 .option('--name <value>', 'DEPRECATED. Custom client class name')
3943 .option('--request <value>', 'DEPRECATED. Path to custom request file')
···102106 userConfig.logs.level = 'silent';
103107 }
104108105105- await createClient(userConfig);
106106- process.exit(0);
109109+ if (typeof params.watch === 'string') {
110110+ userConfig.watch = Number.parseInt(params.watch, 10);
111111+ }
112112+113113+ const context = await createClient(userConfig);
114114+ if (!context[0] || !context[0].config.watch) {
115115+ process.exit(0);
116116+ }
107117 } catch (error) {
108118 process.exit(1);
109119 }
···645645 const irSchema: IR.SchemaObject = {};
646646647647 // refs using unicode characters become encoded, didn't investigate why
648648- // but the suspicion is this comes from `@apidevtools/json-schema-ref-parser`
648648+ // but the suspicion is this comes from `@hey-api/json-schema-ref-parser`
649649 irSchema.$ref = decodeURI(schema.$ref);
650650651651 return irSchema;
···682682 const irSchema = initIrSchema({ schema });
683683684684 // refs using unicode characters become encoded, didn't investigate why
685685- // but the suspicion is this comes from `@apidevtools/json-schema-ref-parser`
685685+ // but the suspicion is this comes from `@hey-api/json-schema-ref-parser`
686686 irSchema.$ref = decodeURI(schema.$ref);
687687688688 return irSchema;
···11+import type { Config } from '../../../types/config';
12import type { OpenApiParameter } from '../../v3/interfaces/OpenApiParameter';
2334export interface ModelComposition
···150151}
151152152153export interface Client {
154154+ /**
155155+ * Configuration for parsing and generating the output. This
156156+ * is a mix of user-provided and default values.
157157+ */
158158+ config: Config;
153159 models: Model[];
154160 operations: Operation[];
155161 server: string;
+5-1
packages/openapi-ts/src/openApi/index.ts
···3535 * all the models, services and schema's we should output.
3636 * @param openApi The OpenAPI spec that we have loaded from disk.
3737 */
3838-export function parseLegacy({ openApi }: { openApi: unknown }): Client {
3838+export function parseLegacy({
3939+ openApi,
4040+}: {
4141+ openApi: unknown;
4242+}): Omit<Client, 'config'> {
3943 const spec = openApi as LegacyOpenApi;
40444145 if ('openapi' in spec) {
+1-1
packages/openapi-ts/src/openApi/v2/index.ts
···1010 * all the models, operations and schema's we should output.
1111 * @param openApi The OpenAPI spec that we have loaded from disk.
1212 */
1313-export const parse = (openApi: OpenApi): Client => {
1313+export const parse = (openApi: OpenApi): Omit<Client, 'config'> => {
1414 const version = getServiceVersion(openApi.info.version);
1515 const server = getServer(openApi);
1616 const { models, types } = getModels(openApi);
+1-1
packages/openapi-ts/src/openApi/v3/index.ts
···1010 * all the models, operations and schema's we should output.
1111 * @param openApi The OpenAPI spec that we have loaded from disk.
1212 */
1313-export const parse = (openApi: OpenApi): Client => {
1313+export const parse = (openApi: OpenApi): Omit<Client, 'config'> => {
1414 const version = getServiceVersion(openApi.info.version);
1515 const server = getServer(openApi);
1616 const { models, types } = getModels(openApi);
···65656666 if ('$ref' in schema) {
6767 // refs using unicode characters become encoded, didn't investigate why
6868- // but the suspicion is this comes from `@apidevtools/json-schema-ref-parser`
6868+ // but the suspicion is this comes from `@hey-api/json-schema-ref-parser`
6969 schema.$ref = decodeURI(schema.$ref);
7070 return schema;
7171 }
···163163164164 if (schema.$ref) {
165165 // refs using unicode characters become encoded, didn't investigate why
166166- // but the suspicion is this comes from `@apidevtools/json-schema-ref-parser`
166166+ // but the suspicion is this comes from `@hey-api/json-schema-ref-parser`
167167 schema.$ref = decodeURI(schema.$ref);
168168 }
169169
···11import type { Client as ParserClient, Model } from '../openApi';
22import { sanitizeNamespaceIdentifier } from '../openApi';
33import type { Client, Operation, Service } from '../types/client';
44+import type { Config } from '../types/config';
45import { getConfig, legacyNameFromConfig } from './config';
56import { sort } from './sort';
67import { stringCase } from './stringCase';
···1011 * Post process client
1112 * @param client Client object with all the models, services, etc.
1213 */
1313-export function postProcessClient(client: ParserClient): Client {
1414+export function postProcessClient(
1515+ client: Omit<ParserClient, 'config'>,
1616+ config: Config,
1717+): Client {
1418 return {
1519 ...client,
2020+ config,
1621 models: client.models.map((model) => postProcessModel(model)),
1722 services: postProcessOperations(client.operations).map(postProcessService),
1823 types: {},
+2-2
packages/openapi-ts/src/utils/ref.ts
···1313 const parts = refToParts($ref);
1414 const name = parts[parts.length - 1]!;
1515 // refs using unicode characters become encoded, didn't investigate why
1616- // but the suspicion is this comes from `@apidevtools/json-schema-ref-parser`
1616+ // but the suspicion is this comes from `@hey-api/json-schema-ref-parser`
1717 return decodeURI(name);
1818};
1919···3131 spec: Record<string, any>;
3232}): T => {
3333 // refs using unicode characters become encoded, didn't investigate why
3434- // but the suspicion is this comes from `@apidevtools/json-schema-ref-parser`
3434+ // but the suspicion is this comes from `@hey-api/json-schema-ref-parser`
3535 const parts = refToParts(decodeURI($ref));
36363737 let current = spec;
···327327 */
328328export const getParseAs = (
329329 contentType: string | null,
330330-): Exclude<Config['parseAs'], 'auto' | 'stream'> => {
330330+): Exclude<Config['parseAs'], 'auto'> => {
331331 if (!contentType) {
332332- return;
332332+ // If no Content-Type header is provided, the best we can do is return the raw response body,
333333+ // which is effectively the same as the 'stream' option.
334334+ return 'stream';
333335 }
334336335337 const cleanContent = contentType.split(';')[0]?.trim();
···327327 */
328328export const getParseAs = (
329329 contentType: string | null,
330330-): Exclude<Config['parseAs'], 'auto' | 'stream'> => {
330330+): Exclude<Config['parseAs'], 'auto'> => {
331331 if (!contentType) {
332332- return;
332332+ // If no Content-Type header is provided, the best we can do is return the raw response body,
333333+ // which is effectively the same as the 'stream' option.
334334+ return 'stream';
333335 }
334336335337 const cleanContent = contentType.split(';')[0]?.trim();