Skip to content

Commit 4f90ded

Browse files
authored
Merge pull request #2602 from hey-api/feat--multiple-configs-functionality
feat: multiple configs functionality
2 parents 34bc6e7 + c71e0e8 commit 4f90ded

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2052
-1180
lines changed

.changeset/dry-jeans-ring.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hey-api/openapi-ts': patch
3+
---
4+
5+
feat: support multiple configurations

docs/openapi-ts/configuration.md

Lines changed: 102 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,6 @@ export default {
3838

3939
Alternatively, you can use `openapi-ts.config.js` and configure the export statement depending on your project setup.
4040

41-
<!--
42-
TODO: uncomment after c12 supports multiple configs
43-
see https://github.com/unjs/c12/issues/92
44-
-->
45-
<!-- ### Multiple Clients
46-
47-
If you want to generate multiple clients with a single `openapi-ts` command, you can provide an array of configuration objects.
48-
49-
```js
50-
import { defineConfig } from '@hey-api/openapi-ts';
51-
52-
export default defineConfig([
53-
{
54-
input: 'path/to/openapi_one.json',
55-
output: 'src/client_one',
56-
plugins: ['legacy/fetch'],
57-
},
58-
{
59-
input: 'path/to/openapi_two.json',
60-
output: 'src/client_two',
61-
plugins: ['legacy/axios'],
62-
},
63-
])
64-
``` -->
65-
6641
## Input
6742

6843
You must provide an input so we can load your OpenAPI specification.
@@ -163,6 +138,108 @@ Plugins are responsible for generating artifacts from your input. By default, He
163138

164139
You can learn more on the [Output](/openapi-ts/output) page.
165140

141+
## Advanced
142+
143+
More complex configuration scenarios can be handled by providing an array of inputs, outputs, or configurations.
144+
145+
### Multiple jobs
146+
147+
Throughout this documentation, we generally reference single job configurations. However, you can easily run multiple jobs by providing an array of configuration objects.
148+
149+
::: code-group
150+
151+
```js [config]
152+
export default [
153+
{
154+
input: 'foo.yaml',
155+
output: 'src/foo',
156+
},
157+
{
158+
input: 'bar.yaml',
159+
output: 'src/bar',
160+
},
161+
];
162+
```
163+
164+
```md [example]
165+
src/
166+
├── foo/
167+
│ ├── client/
168+
│ ├── core/
169+
│ ├── client.gen.ts
170+
│ ├── index.ts
171+
│ ├── sdk.gen.ts
172+
│ └── types.gen.ts
173+
└── bar/
174+
├── client/
175+
├── core/
176+
├── client.gen.ts
177+
├── index.ts
178+
├── sdk.gen.ts
179+
└── types.gen.ts
180+
```
181+
182+
:::
183+
184+
### Job matrix
185+
186+
Reusing configuration across multiple jobs is possible by defining a job matrix. You can create a job matrix by providing `input` and `output` arrays of matching length.
187+
188+
::: code-group
189+
190+
```js [config]
191+
export default {
192+
input: ['foo.yaml', 'bar.yaml'],
193+
output: ['src/foo', 'src/bar'],
194+
};
195+
```
196+
197+
```md [example]
198+
src/
199+
├── foo/
200+
│ ├── client/
201+
│ ├── core/
202+
│ ├── client.gen.ts
203+
│ ├── index.ts
204+
│ ├── sdk.gen.ts
205+
│ └── types.gen.ts
206+
└── bar/
207+
├── client/
208+
├── core/
209+
├── client.gen.ts
210+
├── index.ts
211+
├── sdk.gen.ts
212+
└── types.gen.ts
213+
```
214+
215+
:::
216+
217+
### Merging inputs
218+
219+
You can merge inputs by defining multiple inputs and a single output.
220+
221+
::: code-group
222+
223+
```js [config]
224+
export default {
225+
input: ['foo.yaml', 'bar.yaml'],
226+
output: 'src/client',
227+
};
228+
```
229+
230+
```md [example]
231+
src/
232+
└── client/
233+
├── client/
234+
├── core/
235+
├── client.gen.ts
236+
├── index.ts
237+
├── sdk.gen.ts
238+
└── types.gen.ts
239+
```
240+
241+
:::
242+
166243
## API
167244

168245
You can view the complete list of options in the [UserConfig](https://github.com/hey-api/openapi-ts/blob/main/packages/openapi-ts/src/types/config.d.ts) interface.

docs/openapi-ts/configuration/input.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export default {
5454

5555
:::
5656

57+
You can learn more about complex use cases in the [Advanced](/openapi-ts/configuration#advanced) section.
58+
5759
::: info
5860
If you use an HTTPS URL with a self-signed certificate in development, you will need to set [`NODE_TLS_REJECT_UNAUTHORIZED=0`](https://github.com/hey-api/openapi-ts/issues/276#issuecomment-2043143501) in your environment.
5961
:::

docs/openapi-ts/configuration/output.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ export default {
3434

3535
:::
3636

37+
You can learn more about complex use cases in the [Advanced](/openapi-ts/configuration#advanced) section.
38+
3739
## File Name
3840

3941
You can customize the naming and casing pattern for files using the `fileName` option.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
"rollup": "4.31.0",
6666
"rollup-plugin-dts": "6.1.1",
6767
"tsup": "8.4.0",
68-
"turbo": "2.5.6",
68+
"turbo": "2.5.8",
6969
"typescript": "5.8.3",
7070
"typescript-eslint": "8.29.1",
7171
"vitest": "3.1.1"

packages/nuxt/src/module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@ export default defineNuxtModule<ModuleOptions>({
6060
config.watch = false;
6161
}
6262

63+
const output =
64+
config.output instanceof Array ? config.output[0] : config.output;
6365
const folder = path.resolve(
6466
nuxt.options.rootDir,
65-
typeof config.output === 'string' ? config.output : config.output.path,
67+
typeof output === 'string' ? output : (output?.path ?? ''),
6668
);
6769

6870
nuxt.options.alias[options.alias!] = folder;

packages/openapi-ts-tests/main/test/2.0.x.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ const version = '2.0.x';
1515
const outputDir = path.join(__dirname, 'generated', version);
1616

1717
describe(`OpenAPI ${version}`, () => {
18-
const createConfig = (userConfig: UserConfig): UserConfig => {
18+
const createConfig = (userConfig: UserConfig) => {
19+
const input =
20+
userConfig.input instanceof Array
21+
? userConfig.input[0]
22+
: userConfig.input;
1923
const inputPath = path.join(
2024
getSpecsPath(),
2125
version,
22-
typeof userConfig.input === 'string'
23-
? userConfig.input
24-
: (userConfig.input.path as string),
26+
typeof input === 'string' ? input : ((input?.path as string) ?? ''),
2527
);
2628
return {
2729
plugins: ['@hey-api/typescript'],
@@ -40,7 +42,7 @@ describe(`OpenAPI ${version}`, () => {
4042
outputDir,
4143
typeof userConfig.output === 'string' ? userConfig.output : '',
4244
),
43-
};
45+
} as const satisfies UserConfig;
4446
};
4547

4648
const scenarios = [
@@ -391,9 +393,7 @@ describe(`OpenAPI ${version}`, () => {
391393
it.each(scenarios)('$description', async ({ config }) => {
392394
await createClient(config);
393395

394-
const outputPath =
395-
typeof config.output === 'string' ? config.output : config.output.path;
396-
const filePaths = getFilePaths(outputPath);
396+
const filePaths = getFilePaths(config.output);
397397

398398
await Promise.all(
399399
filePaths.map(async (filePath) => {

packages/openapi-ts-tests/main/test/3.0.x.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ const version = '3.0.x';
1515
const outputDir = path.join(__dirname, 'generated', version);
1616

1717
describe(`OpenAPI ${version}`, () => {
18-
const createConfig = (userConfig: UserConfig): UserConfig => {
18+
const createConfig = (userConfig: UserConfig) => {
19+
const input =
20+
userConfig.input instanceof Array
21+
? userConfig.input[0]
22+
: userConfig.input;
1923
const inputPath = path.join(
2024
getSpecsPath(),
2125
version,
22-
typeof userConfig.input === 'string'
23-
? userConfig.input
24-
: (userConfig.input.path as string),
26+
typeof input === 'string' ? input : ((input?.path as string) ?? ''),
2527
);
2628
return {
2729
plugins: ['@hey-api/typescript'],
@@ -40,7 +42,7 @@ describe(`OpenAPI ${version}`, () => {
4042
outputDir,
4143
typeof userConfig.output === 'string' ? userConfig.output : '',
4244
),
43-
};
45+
} as const satisfies UserConfig;
4446
};
4547

4648
const scenarios = [
@@ -668,9 +670,7 @@ describe(`OpenAPI ${version}`, () => {
668670
it.each(scenarios)('$description', async ({ config }) => {
669671
await createClient(config);
670672

671-
const outputPath =
672-
typeof config.output === 'string' ? config.output : config.output.path;
673-
const filePaths = getFilePaths(outputPath);
673+
const filePaths = getFilePaths(config.output);
674674

675675
await Promise.all(
676676
filePaths.map(async (filePath) => {

packages/openapi-ts-tests/main/test/3.1.x.test.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,20 @@ const version = '3.1.x';
1515
const outputDir = path.join(__dirname, 'generated', version);
1616

1717
describe(`OpenAPI ${version}`, () => {
18-
const createConfig = (userConfig: UserConfig): UserConfig => {
18+
const createConfig = (userConfig: UserConfig) => {
19+
const input =
20+
userConfig.input instanceof Array
21+
? userConfig.input[0]
22+
: userConfig.input;
1923
const inputPath = path.join(
2024
getSpecsPath(),
2125
version,
22-
typeof userConfig.input === 'string'
23-
? userConfig.input
24-
: (userConfig.input.path as string),
26+
typeof input === 'string' ? input : ((input?.path as string) ?? ''),
2527
);
28+
const output =
29+
userConfig.output instanceof Array
30+
? userConfig.output[0]
31+
: userConfig.output;
2632
return {
2733
plugins: ['@hey-api/typescript'],
2834
...userConfig,
@@ -38,9 +44,9 @@ describe(`OpenAPI ${version}`, () => {
3844
},
3945
output: path.join(
4046
outputDir,
41-
typeof userConfig.output === 'string' ? userConfig.output : '',
47+
typeof output === 'string' ? output : (output?.path ?? ''),
4248
),
43-
};
49+
} as const satisfies UserConfig;
4450
};
4551

4652
const scenarios = [
@@ -969,9 +975,7 @@ describe(`OpenAPI ${version}`, () => {
969975
it.each(scenarios)('$description', async ({ config }) => {
970976
await createClient(config);
971977

972-
const outputPath =
973-
typeof config.output === 'string' ? config.output : config.output.path;
974-
const filePaths = getFilePaths(outputPath);
978+
const filePaths = getFilePaths(config.output);
975979

976980
await Promise.all(
977981
filePaths.map(async (filePath) => {

0 commit comments

Comments
 (0)