Skip to content

Commit a870cc5

Browse files
committed
fix: the goods
1 parent 58f07ab commit a870cc5

File tree

24 files changed

+184
-59
lines changed

24 files changed

+184
-59
lines changed

.vscode/settings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"cSpell.words": ["listitem", "Petstore", "tanstack"]
2+
"cSpell.words": ["listitem", "openapi", "Orval", "Petstore", "tanstack"]
33
}

docs/src/pages/reference/configuration/full-example.md

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ module.exports = {
4646
delay: 500,
4747
},
4848
},
49+
allParamsOptional: true,
50+
urlEncodeParameters: true,
4951
},
5052
input: {
5153
target: './petstore.yaml',

docs/src/pages/reference/configuration/output.md

+36
Original file line numberDiff line numberDiff line change
@@ -1379,3 +1379,39 @@ module.exports = {
13791379
},
13801380
};
13811381
```
1382+
1383+
### allParamsOptional
1384+
1385+
Type: `Boolean`
1386+
1387+
Valid values: true or false. Defaults to false. Applies to all clients, but probably only makes sense for Tanstack Query.
1388+
1389+
Use this property to make all parameters optional. This is useful to take advantage of the Orval's auto-enable feature for Tanstack Query, see https://github.com/anymaniax/orval/pull/894
1390+
1391+
```js
1392+
module.exports = {
1393+
petstore: {
1394+
output: {
1395+
allParamsOptional: true,
1396+
},
1397+
},
1398+
};
1399+
```
1400+
1401+
### urlEncodeParameters
1402+
1403+
Type: `Boolean`
1404+
1405+
Valid values: true or false. Defaults to false. **Note:** this only works for Tanstack Query clients for now.
1406+
1407+
Use this property to enable URL encoding of path/query parameters. This is highly recommended, and will probably become a default in the future, see https://github.com/anymaniax/orval/pull/895
1408+
1409+
```js
1410+
module.exports = {
1411+
petstore: {
1412+
output: {
1413+
urlEncodeParameters: true,
1414+
},
1415+
},
1416+
};
1417+
```

packages/core/src/types.ts

+9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ResponsesObject,
1010
SchemaObject,
1111
} from 'openapi3-ts';
12+
// @ts-ignore // FIXME when running `yarn test` getting `orval:test: ../core/src/types.ts(12,34): error TS7016: Could not find a declaration file for module 'swagger2openapi'. '/home/maxim/orval/node_modules/swagger2openapi/index.js' implicitly has an 'any' type.`
1213
import swagger2openapi from 'swagger2openapi';
1314
import type { allLocales } from '@faker-js/faker';
1415

@@ -55,6 +56,7 @@ export type NormalizedOutputOptions = {
5556
indexFiles: boolean;
5657
baseUrl?: string;
5758
allParamsOptional: boolean;
59+
urlEncodeParameters: boolean;
5860
};
5961

6062
export type NormalizedParamsSerializerOptions = {
@@ -172,6 +174,7 @@ export type OutputOptions = {
172174
indexFiles?: boolean;
173175
baseUrl?: string;
174176
allParamsOptional?: boolean;
177+
urlEncodeParameters?: boolean;
175178
};
176179

177180
export type SwaggerParserOptions = Omit<SwaggerParser.Options, 'validate'> & {
@@ -197,6 +200,7 @@ export const OutputClient = {
197200
SVELTE_QUERY: 'svelte-query',
198201
VUE_QUERY: 'vue-query',
199202
SWR: 'swr',
203+
ZOD: 'zod',
200204
} as const;
201205

202206
export type OutputClient = typeof OutputClient[keyof typeof OutputClient];
@@ -606,6 +610,7 @@ export type ClientBuilder = (
606610
verbOptions: GeneratorVerbOptions,
607611
options: GeneratorOptions,
608612
outputClient: OutputClient | OutputClientFunc,
613+
output?: NormalizedOutputOptions,
609614
) => GeneratorClient | Promise<GeneratorClient>;
610615

611616
export type ClientHeaderBuilder = (params: {
@@ -818,6 +823,7 @@ export type GeneratorClientTitle = (data: {
818823
outputClient?: OutputClient | OutputClientFunc;
819824
title: string;
820825
customTitleFunc?: (title: string) => string;
826+
output: NormalizedOutputOptions;
821827
}) => GeneratorClientExtra;
822828

823829
export type GeneratorClientHeader = (data: {
@@ -828,6 +834,7 @@ export type GeneratorClientHeader = (data: {
828834
provideIn: boolean | 'root' | 'any';
829835
hasAwaitedType: boolean;
830836
titles: GeneratorClientExtra;
837+
output: NormalizedOutputOptions;
831838
}) => GeneratorClientExtra;
832839

833840
export type GeneratorClientFooter = (data: {
@@ -836,6 +843,7 @@ export type GeneratorClientFooter = (data: {
836843
hasMutator: boolean;
837844
hasAwaitedType: boolean;
838845
titles: GeneratorClientExtra;
846+
output: NormalizedOutputOptions;
839847
}) => GeneratorClientExtra;
840848

841849
export type GeneratorClientImports = (data: {
@@ -851,6 +859,7 @@ export type GeneratorClientImports = (data: {
851859
hasGlobalMutator: boolean;
852860
hasParamsSerializerOptions: boolean;
853861
packageJson?: PackageJson;
862+
output: NormalizedOutputOptions;
854863
}) => string;
855864

856865
export type GenerateMockImports = (data: {

packages/core/src/writers/single-mode.ts

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export const writeSingleMode = async ({
6565
hasGlobalMutator: !!output.override.mutator,
6666
hasParamsSerializerOptions: !!output.override.paramsSerializerOptions,
6767
packageJson: output.packageJson,
68+
output,
6869
});
6970

7071
if (output.mock) {

packages/core/src/writers/split-mode.ts

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const writeSplitMode = async ({
5757
hasGlobalMutator: !!output.override.mutator,
5858
hasParamsSerializerOptions: !!output.override.paramsSerializerOptions,
5959
packageJson: output.packageJson,
60+
output,
6061
});
6162
mockData += builder.importsMock({
6263
implementation: implementationMock,

packages/core/src/writers/split-tags-mode.ts

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export const writeSplitTagsMode = async ({
6262
hasGlobalMutator: !!output.override.mutator,
6363
hasParamsSerializerOptions: !!output.override.paramsSerializerOptions,
6464
packageJson: output.packageJson,
65+
output,
6566
});
6667
mockData += builder.importsMock({
6768
implementation: implementationMock,

packages/core/src/writers/tags-mode.ts

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export const writeTagsMode = async ({
6868
hasGlobalMutator: !!output.override.mutator,
6969
hasParamsSerializerOptions: !!output.override.paramsSerializerOptions,
7070
packageJson: output.packageJson,
71+
output,
7172
});
7273

7374
if (output.mock) {

packages/core/src/writers/target-tags.ts

+3
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export const generateTargetForTags = (
118118
outputClient: options.client,
119119
title: pascal(tag),
120120
customTitleFunc: options.override.title,
121+
output: options,
121122
});
122123

123124
const footer = builder.footer({
@@ -126,6 +127,7 @@ export const generateTargetForTags = (
126127
hasMutator: !!target.mutators?.length,
127128
hasAwaitedType,
128129
titles,
130+
output: options,
129131
});
130132

131133
const header = builder.header({
@@ -136,6 +138,7 @@ export const generateTargetForTags = (
136138
provideIn: options.override.angular.provideIn,
137139
hasAwaitedType,
138140
titles,
141+
output: options,
139142
});
140143

141144
acc[tag] = {

packages/core/src/writers/target.ts

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const generateTarget = (
2020
outputClient: options.client,
2121
title: pascal(builder.info.title),
2222
customTitleFunc: options.override.title,
23+
output: options,
2324
});
2425

2526
const target = Object.values(builder.operations).reduce(
@@ -67,6 +68,7 @@ export const generateTarget = (
6768
provideIn: options.override.angular.provideIn,
6869
hasAwaitedType,
6970
titles,
71+
output: options,
7072
});
7173
acc.implementation = header.implementation + acc.implementation;
7274
acc.implementationMock.handler =
@@ -78,6 +80,7 @@ export const generateTarget = (
7880
hasMutator: !!acc.mutators.length,
7981
hasAwaitedType,
8082
titles,
83+
output: options,
8184
});
8285
acc.implementation += footer.implementation;
8386
acc.implementationMock.handler += footer.implementationMock;

packages/orval/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
"build": "tsup ./src/bin/orval.ts ./src/index.ts --target node12 --clean --dts",
4545
"dev": "tsup ./src/bin/orval.ts ./src/index.ts --target node12 --clean --watch ./src --onSuccess 'yarn generate-api'",
4646
"lint": "eslint src/**/*.ts",
47-
"generate-api": "node ./dist/bin/orval.js --config ../../samples/react-query/basic/orval.config.ts"
47+
"generate-api": "node ./dist/bin/orval.js --config ../../samples/react-query/basic/orval.config.ts",
48+
"test": "tsc --noEmit && vitest --passWithNoTests"
4849
},
4950
"devDependencies": {
5051
"@types/inquirer": "^9.0.6",

packages/orval/src/api.ts

+2
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ export const getApiBuilder = async ({
111111
override: output.override,
112112
context: resolvedContext,
113113
mock: output.mock,
114+
// @ts-expect-error // FIXME
114115
output: output.target,
115116
},
117+
output,
116118
);
117119

118120
acc.schemas.push(...schemas);

packages/orval/src/client.ts

+36-17
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
GeneratorVerbOptions,
1414
GeneratorVerbsOptions,
1515
isFunction,
16+
NormalizedOutputOptions,
1617
OutputClient,
1718
OutputClientFunc,
1819
pascal,
@@ -24,18 +25,21 @@ import zod from '@orval/zod';
2425

2526
const DEFAULT_CLIENT = OutputClient.AXIOS;
2627

27-
export const GENERATOR_CLIENT: GeneratorClients = {
28-
axios: axios({ type: 'axios' })(),
29-
'axios-functions': axios({ type: 'axios-functions' })(),
30-
angular: angular()(),
31-
'react-query': query({ type: 'react-query' })(),
32-
'svelte-query': query({ type: 'svelte-query' })(),
33-
'vue-query': query({ type: 'vue-query' })(),
34-
swr: swr()(),
35-
zod: zod()(),
36-
};
28+
const getGeneratorClient = (
29+
outputClient: OutputClient | OutputClientFunc,
30+
output: NormalizedOutputOptions,
31+
) => {
32+
const GENERATOR_CLIENT: GeneratorClients = {
33+
axios: axios({ type: 'axios' })(),
34+
'axios-functions': axios({ type: 'axios-functions' })(),
35+
angular: angular()(),
36+
'react-query': query({ output, type: 'react-query' })(),
37+
'svelte-query': query({ output, type: 'svelte-query' })(),
38+
'vue-query': query({ output, type: 'vue-query' })(),
39+
swr: swr()(),
40+
zod: zod()(),
41+
};
3742

38-
const getGeneratorClient = (outputClient: OutputClient | OutputClientFunc) => {
3943
const generator = isFunction(outputClient)
4044
? outputClient(GENERATOR_CLIENT)
4145
: GENERATOR_CLIENT[outputClient];
@@ -57,8 +61,9 @@ export const generateClientImports: GeneratorClientImports = ({
5761
hasGlobalMutator,
5862
hasParamsSerializerOptions,
5963
packageJson,
64+
output,
6065
}) => {
61-
const { dependencies } = getGeneratorClient(client);
66+
const { dependencies } = getGeneratorClient(client, output);
6267
return generateDependencyImports(
6368
implementation,
6469
dependencies
@@ -85,8 +90,9 @@ export const generateClientHeader: GeneratorClientHeader = ({
8590
provideIn,
8691
hasAwaitedType,
8792
titles,
93+
output,
8894
}) => {
89-
const { header } = getGeneratorClient(outputClient);
95+
const { header } = getGeneratorClient(outputClient, output);
9096
return {
9197
implementation: header
9298
? header({
@@ -108,8 +114,9 @@ export const generateClientFooter: GeneratorClientFooter = ({
108114
hasMutator,
109115
hasAwaitedType,
110116
titles,
117+
output,
111118
}) => {
112-
const { footer } = getGeneratorClient(outputClient);
119+
const { footer } = getGeneratorClient(outputClient, output);
113120

114121
if (!footer) {
115122
return {
@@ -155,8 +162,9 @@ export const generateClientTitle: GeneratorClientTitle = ({
155162
outputClient = DEFAULT_CLIENT,
156163
title,
157164
customTitleFunc,
165+
output,
158166
}) => {
159-
const { title: generatorTitle } = getGeneratorClient(outputClient);
167+
const { title: generatorTitle } = getGeneratorClient(outputClient, output);
160168

161169
if (!generatorTitle) {
162170
return {
@@ -196,18 +204,27 @@ const generateMock = (
196204
return options.mock(verbOption, options);
197205
}
198206

199-
return mock.generateMock(verbOption, options);
207+
return mock.generateMock(
208+
verbOption,
209+
options as typeof options & {
210+
mock: Exclude<typeof options['mock'], Function | undefined>;
211+
},
212+
);
200213
};
201214

202215
export const generateOperations = (
203216
outputClient: OutputClient | OutputClientFunc = DEFAULT_CLIENT,
204217
verbsOptions: GeneratorVerbsOptions,
205218
options: GeneratorOptions,
219+
output: NormalizedOutputOptions,
206220
): Promise<GeneratorOperations> => {
207221
return asyncReduce(
208222
verbsOptions,
209223
async (acc, verbOption) => {
210-
const { client: generatorClient } = getGeneratorClient(outputClient);
224+
const { client: generatorClient } = getGeneratorClient(
225+
outputClient,
226+
output,
227+
);
211228
const client = await generatorClient(verbOption, options, outputClient);
212229
const generatedMock = generateMock(verbOption, options);
213230

@@ -218,7 +235,9 @@ export const generateOperations = (
218235
acc[verbOption.operationId] = {
219236
implementation: verbOption.doc + client.implementation,
220237
imports: client.imports,
238+
// @ts-expect-error // FIXME
221239
implementationMock: generatedMock.implementation,
240+
// @ts-expect-error // FIXME
222241
importsMock: generatedMock.imports,
223242
tags: verbOption.tags,
224243
mutator: verbOption.mutator,

packages/orval/src/import-open-api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export const importOpenApi = async ({
3333
const schemas = getApiSchemas({ output, target, workspace, specs });
3434

3535
const api = await getApiBuilder({
36+
// @ts-expect-error // FIXME
3637
input,
3738
output,
3839
context: {

packages/orval/src/import-specs.ts

+5
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,19 @@ export const importSpecs = async (
6363
if (isObject(input.target)) {
6464
return importOpenApi({
6565
data: { [workspace]: input.target },
66+
// @ts-expect-error // FIXME
6667
input,
6768
output,
6869
target: workspace,
6970
workspace,
7071
});
7172
}
7273

74+
// @ts-expect-error // FIXME
7375
const isPathUrl = isUrl(input.target);
7476

7577
const data = await resolveSpecs(
78+
// @ts-expect-error // FIXME
7679
input.target,
7780
input.parserOptions,
7881
isPathUrl,
@@ -81,8 +84,10 @@ export const importSpecs = async (
8184

8285
return importOpenApi({
8386
data,
87+
// @ts-expect-error // FIXME
8488
input,
8589
output,
90+
// @ts-expect-error // FIXME
8691
target: input.target,
8792
workspace,
8893
});

packages/orval/src/utils/options.ts

+1
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ export const normalizeOptions = async (
215215
useNativeEnums: outputOptions.override?.useNativeEnums ?? false,
216216
},
217217
allParamsOptional: outputOptions.allParamsOptional ?? false,
218+
urlEncodeParameters: outputOptions.urlEncodeParameters ?? false,
218219
},
219220
hooks: options.hooks ? normalizeHooks(options.hooks) : {},
220221
};

0 commit comments

Comments
 (0)