Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c20568d

Browse files
committedNov 23, 2024·
wip - config introduction
1 parent 71e74f6 commit c20568d

File tree

14 files changed

+136
-11
lines changed

14 files changed

+136
-11
lines changed
 

‎packages/core/src/generators/component-definition.ts

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const generateComponentDefinition = (
5555
if (modelName !== type) {
5656
acc.push({
5757
name: modelName,
58+
factoryMethod: '',
5859
model,
5960
imports,
6061
});

‎packages/core/src/generators/imports.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
GeneratorImport,
55
GeneratorMutator,
66
GeneratorVerbOptions,
7-
GetterPropType,
7+
GetterPropType, OutputModelFactoryMethodsMode,
88
} from '../types';
99
import { camel, upath } from '../utils';
1010

@@ -14,12 +14,16 @@ export const generateImports = ({
1414
isRootKey,
1515
specsName,
1616
specKey: currentSpecKey,
17+
factoryMethodOutput,
18+
factoryMethodPrefix
1719
}: {
1820
imports: GeneratorImport[];
1921
target: string;
2022
isRootKey: boolean;
2123
specsName: Record<string, string>;
2224
specKey: string;
25+
factoryMethodOutput?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
26+
factoryMethodPrefix?: string;
2327
}) => {
2428
if (!imports.length) {
2529
return '';
@@ -47,9 +51,14 @@ export const generateImports = ({
4751
} } from \'./${upath.join(path, camel(name))}\';`;
4852
}
4953

50-
return `import { create${name}, ${name}${
54+
let mainImport = `import ${!values ? 'type ' : ''}{ ${name}${
5155
alias ? ` as ${alias}` : ''
52-
} } from \'./${camel(name)}\';`;
56+
}${factoryMethodOutput == 'inline' ? `${factoryMethodPrefix}${name}` : ''} } from \'./${camel(name)}\';`;
57+
if (factoryMethodOutput == 'isolated') {
58+
let factoryMethodImport = `import { ${factoryMethodPrefix}${name} } from \'./${camel(name)}.factory\';`;
59+
mainImport += '\n' + factoryMethodImport;
60+
}
61+
return mainImport;
5362
})
5463
.join('\n');
5564
};

‎packages/core/src/generators/interface.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,28 @@ export const generateInterface = ({
5353
} else {
5454
model += `export type ${name} = ${scalar.value};\n`;
5555
}
56-
model += `export function create${name}(): ${name} ${scalar.factoryMethodValue}\n`;
57-
5856
// Filter out imports that refer to the type defined in current file (OpenAPI recursive schema definitions)
5957
const externalModulesImportsOnly = scalar.imports.filter(
6058
(importName) => importName.name !== name,
6159
);
6260

61+
let factoryMethod: string = '';
62+
if (context?.output.modelFactoryMethods) {
63+
let factoryMethodPrefix = context?.output.override?.modelFactoryMethods?.factoryMethodPrefix!;
64+
factoryMethod = `export function ${factoryMethodPrefix}${name}(): ${name} ${scalar.factoryMethodValue}\n`;
65+
if (context?.output.override?.modelFactoryMethods?.outputMode == 'inline') {
66+
model += factoryMethod;
67+
factoryMethod = '';
68+
}
69+
}
70+
6371
return [
6472
...scalar.schemas,
6573
{
6674
name,
6775
model,
68-
imports: externalModulesImportsOnly,
76+
factoryMethod,
77+
imports: scalar.imports,
6978
},
7079
];
7180
};

‎packages/core/src/generators/parameter-definition.ts

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const generateParameterDefinition = (
2929
if (!schema.schema || imports.length) {
3030
acc.push({
3131
name: modelName,
32+
factoryMethod: '',
3233
imports: imports.length
3334
? [
3435
{
@@ -63,6 +64,7 @@ export const generateParameterDefinition = (
6364
if (modelName !== resolvedObject.value) {
6465
acc.push({
6566
name: modelName,
67+
factoryMethod: '',
6668
model,
6769
imports: resolvedObject.imports,
6870
});

‎packages/core/src/generators/schema-definition.ts

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export const generateSchemasDefinition = (
127127

128128
acc.push(...resolvedValue.schemas, {
129129
name: schemaName,
130+
factoryMethod: '',
130131
model: output,
131132
imports,
132133
});

‎packages/core/src/getters/combine.ts

+1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ export const combineSchemas = ({
193193
})),
194194
],
195195
model: newEnum,
196+
factoryMethod: '',
196197
name: name,
197198
},
198199
],

‎packages/core/src/getters/props.ts

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export const getProps = ({
9696
required: true,
9797
schema: {
9898
name: parameterTypeName,
99+
factoryMethod: '',
99100
model: namedParametersTypeDefinition,
100101
imports: params.flatMap((property) => property.imports),
101102
},

‎packages/core/src/getters/query-params.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ const getQueryParamsTypes = (
8282
imports: [{ name: enumName }],
8383
schemas: [
8484
...resolvedValue.schemas,
85-
{ name: enumName, model: enumValue, imports: resolvedValue.imports },
85+
{ name: enumName, model: enumValue, factoryMethod: '', imports: resolvedValue.imports },
8686
],
8787
originalSchema: resolvedValue.originalSchema,
8888
};
@@ -125,6 +125,7 @@ export const getQueryParams = ({
125125

126126
const schema = {
127127
name,
128+
factoryMethod: '',
128129
model: `export type ${name} = {\n${type}\n};\n`,
129130
imports,
130131
};

‎packages/core/src/resolvers/object.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const resolveObjectOriginal = ({
3636
...resolvedValue.schemas,
3737
{
3838
name: propName,
39+
factoryMethod: `export function ${context.output.override.modelFactoryMethods?.factoryMethodPrefix}${propName}(): ${propName}${resolvedValue.factoryMethodValue}`,
3940
model: `${doc}export type ${propName} = ${resolvedValue.value};\n`,
4041
imports: resolvedValue.imports,
4142
},
@@ -55,14 +56,19 @@ const resolveObjectOriginal = ({
5556
resolvedValue.originalSchema?.['x-enumNames'],
5657
context.output.override.useNativeEnums,
5758
);
59+
const factoryMethodValue = context?.output.override?.useTypeOverInterfaces
60+
? `${propName}[${resolvedValue.value.split(' | ')[0]}]`
61+
: `${resolvedValue.value.split(' | ')[0]}`;
62+
5863

5964
return {
6065
value: propName,
61-
factoryMethodValue: `${propName}[${resolvedValue.value.split(' | ')[0]}]`,
66+
factoryMethodValue,
6267
imports: [{ name: propName }],
6368
schemas: [
6469
...resolvedValue.schemas,
6570
{
71+
factoryMethod: '',
6672
name: propName,
6773
model: doc + enumValue,
6874
imports: resolvedValue.imports,

‎packages/core/src/resolvers/value.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const resolveValue = ({
4444

4545
return {
4646
value: resolvedImport.name,
47-
factoryMethodValue: `create${resolvedImport.name}()`,
47+
factoryMethodValue: `${context.output.override.modelFactoryMethods?.factoryMethodPrefix}${resolvedImport.name}()`,
4848
imports: [
4949
{
5050
name: resolvedImport.name,

‎packages/core/src/types.ts

+21
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export type NormalizedOutputOptions = {
4949
override: NormalizedOverrideOutput;
5050
client: OutputClient | OutputClientFunc;
5151
httpClient: OutputHttpClient;
52+
modelFactoryMethods?: boolean;
5253
clean: boolean | string[];
5354
prettier: boolean;
5455
tslint: boolean;
@@ -68,6 +69,16 @@ export type NormalizedParamsSerializerOptions = {
6869
qs?: Record<string, any>;
6970
};
7071

72+
export const OutputModelFactoryMethodsMode = {
73+
INLINE: 'inline',
74+
ISOLATED: 'isolated',
75+
} as const;
76+
77+
export type NormalizedModelFactoryMethodsOptions = {
78+
factoryMethodPrefix?: string;
79+
outputMode?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
80+
};
81+
7182
export type NormalizedOverrideOutput = {
7283
title?: (title: string) => string;
7384
transformer?: OutputTransformer;
@@ -81,6 +92,7 @@ export type NormalizedOverrideOutput = {
8192
formUrlEncoded: boolean | NormalizedMutator;
8293
paramsSerializer?: NormalizedMutator;
8394
paramsSerializerOptions?: NormalizedParamsSerializerOptions;
95+
modelFactoryMethods?: NormalizedModelFactoryMethodsOptions;
8496
components: {
8597
schemas: {
8698
suffix: string;
@@ -173,6 +185,7 @@ export type OutputOptions = {
173185
override?: OverrideOutput;
174186
client?: OutputClient | OutputClientFunc;
175187
httpClient?: OutputHttpClient;
188+
modelFactoryMethods?: boolean;
176189
clean?: boolean | string[];
177190
prettier?: boolean;
178191
tslint?: boolean;
@@ -321,6 +334,11 @@ export type ParamsSerializerOptions = {
321334
qs?: Record<string, any>;
322335
};
323336

337+
export type ModelFactoryMethodsOptions = {
338+
factoryMethodPrefix?: string;
339+
outputMode?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
340+
};
341+
324342
export type OverrideOutput = {
325343
title?: (title: string) => string;
326344
transformer?: OutputTransformer;
@@ -334,6 +352,7 @@ export type OverrideOutput = {
334352
formUrlEncoded?: boolean | Mutator;
335353
paramsSerializer?: Mutator;
336354
paramsSerializerOptions?: ParamsSerializerOptions;
355+
modelFactoryMethods?: ModelFactoryMethodsOptions;
337356
components?: {
338357
schemas?: {
339358
suffix?: string;
@@ -596,6 +615,7 @@ export interface GlobalOptions {
596615
mock?: boolean | GlobalMockOptions;
597616
client?: OutputClient;
598617
httpClient?: OutputHttpClient;
618+
modelFactoryMethods?: boolean;
599619
mode?: OutputMode;
600620
tsconfig?: string | Tsconfig;
601621
packageJson?: string;
@@ -637,6 +657,7 @@ export interface PackageJson {
637657
export type GeneratorSchema = {
638658
name: string;
639659
model: string;
660+
factoryMethod: string;
640661
imports: GeneratorImport[];
641662
};
642663

‎packages/core/src/writers/schemas.ts

+61-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import fs from 'fs-extra';
22
import { generateImports } from '../generators';
3-
import { GeneratorSchema } from '../types';
3+
import { GeneratorSchema, OutputModelFactoryMethodsMode } from '../types';
44
import { camel, upath } from '../utils';
55

66
const getSchema = ({
@@ -35,6 +35,44 @@ const getSchema = ({
3535
return file;
3636
};
3737

38+
const getFactoryMethod = ({
39+
schema: { imports, model, factoryMethod },
40+
target,
41+
isRootKey,
42+
specsName,
43+
header,
44+
specKey,
45+
factoryMethodOutput,
46+
factoryMethodPrefix
47+
}: {
48+
schema: GeneratorSchema;
49+
target: string;
50+
isRootKey: boolean;
51+
specsName: Record<string, string>;
52+
header: string;
53+
specKey: string;
54+
factoryMethodOutput?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
55+
factoryMethodPrefix?: string;
56+
}): string => {
57+
let file = header;
58+
file += generateImports({
59+
imports: imports.filter(
60+
(imp) =>
61+
!model.includes(`type ${imp.alias || imp.name} =`) &&
62+
!model.includes(`interface ${imp.alias || imp.name} {`),
63+
),
64+
target,
65+
isRootKey,
66+
specsName,
67+
specKey,
68+
factoryMethodOutput,
69+
factoryMethodPrefix
70+
});
71+
file += imports.length ? '\n\n' : '\n';
72+
file += factoryMethod;
73+
return file;
74+
};
75+
3876
const getPath = (path: string, name: string, fileExtension: string): string =>
3977
upath.join(path, `/${name}${fileExtension}`);
4078

@@ -53,6 +91,9 @@ export const writeSchema = async ({
5391
isRootKey,
5492
specsName,
5593
header,
94+
factoryMethodInclude,
95+
factoryMethodOutput,
96+
factoryMethodPrefix
5697
}: {
5798
path: string;
5899
schema: GeneratorSchema;
@@ -62,6 +103,10 @@ export const writeSchema = async ({
62103
isRootKey: boolean;
63104
specsName: Record<string, string>;
64105
header: string;
106+
factoryMethodInclude: boolean;
107+
factoryMethodOutput?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
108+
factoryMethodPrefix?: string;
109+
65110
}) => {
66111
const name = camel(schema.name);
67112

@@ -70,6 +115,12 @@ export const writeSchema = async ({
70115
getPath(path, name, fileExtension),
71116
getSchema({ schema, target, isRootKey, specsName, header, specKey }),
72117
);
118+
if (factoryMethodInclude && schema.factoryMethod.length > 0) {
119+
await fs.outputFile(
120+
getPath(path, name + '.factory', fileExtension),
121+
getFactoryMethod({ schema, target, isRootKey, specsName, header, specKey, factoryMethodOutput, factoryMethodPrefix }),
122+
);
123+
}
73124
} catch (e) {
74125
throw `Oups... 🍻. An Error occurred while writing schema ${name} => ${e}`;
75126
}
@@ -85,6 +136,9 @@ export const writeSchemas = async ({
85136
specsName,
86137
header,
87138
indexFiles,
139+
factoryMethodInclude,
140+
factoryMethodOutput,
141+
factoryMethodPrefix
88142
}: {
89143
schemaPath: string;
90144
schemas: GeneratorSchema[];
@@ -95,6 +149,9 @@ export const writeSchemas = async ({
95149
specsName: Record<string, string>;
96150
header: string;
97151
indexFiles: boolean;
152+
factoryMethodInclude: boolean;
153+
factoryMethodOutput?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
154+
factoryMethodPrefix?: string;
98155
}) => {
99156
await Promise.all(
100157
schemas.map((schema) =>
@@ -107,6 +164,9 @@ export const writeSchemas = async ({
107164
isRootKey,
108165
specsName,
109166
header,
167+
factoryMethodInclude,
168+
factoryMethodOutput,
169+
factoryMethodPrefix
110170
}),
111171
),
112172
);

‎packages/orval/src/utils/options.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const normalizeOptions = async (
7878
workspace,
7979
);
8080

81-
const { clean, prettier, client, httpClient, mode, tslint, biome } =
81+
const { clean, prettier, client, httpClient, modelFactoryMethods, mode, tslint, biome } =
8282
globalOptions;
8383

8484
const tsconfig = await loadTsconfig(
@@ -143,6 +143,8 @@ export const normalizeOptions = async (
143143
fileExtension: outputOptions.fileExtension || defaultFileExtension,
144144
workspace: outputOptions.workspace ? outputWorkspace : undefined,
145145
client: outputOptions.client ?? client ?? OutputClient.AXIOS_FUNCTIONS,
146+
modelFactoryMethods:
147+
outputOptions.modelFactoryMethods ?? modelFactoryMethods ?? false,
146148
httpClient:
147149
outputOptions.httpClient ?? httpClient ?? OutputHttpClient.AXIOS,
148150
mode: normalizeOutputMode(outputOptions.mode ?? mode),
@@ -208,6 +210,14 @@ export const normalizeOptions = async (
208210
? outputOptions.override?.header!
209211
: getDefaultFilesHeader,
210212
requestOptions: outputOptions.override?.requestOptions ?? true,
213+
modelFactoryMethods: {
214+
factoryMethodPrefix:
215+
outputOptions.override?.modelFactoryMethods?.factoryMethodPrefix
216+
?? 'new',
217+
outputMode:
218+
outputOptions.override?.modelFactoryMethods?.outputMode
219+
?? 'isolated'
220+
},
211221
components: {
212222
schemas: {
213223
suffix: RefComponentSuffix.schemas,

‎packages/orval/src/write-specs.ts

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ export const writeSpecs = async (
8282
isRootKey: isRootKey(specKey, target),
8383
header,
8484
indexFiles: output.indexFiles,
85+
factoryMethodInclude: output.modelFactoryMethods ?? false,
86+
factoryMethodOutput: output.override?.modelFactoryMethods?.outputMode,
87+
factoryMethodPrefix: output.override?.modelFactoryMethods?.factoryMethodPrefix
8588
});
8689
}),
8790
);

0 commit comments

Comments
 (0)
Please sign in to comment.