Skip to content

Commit 45f4d4d

Browse files
wip - config introduction
1 parent 25e1e83 commit 45f4d4d

File tree

14 files changed

+138
-10
lines changed

14 files changed

+138
-10
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-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
GeneratorMutator,
66
GeneratorVerbOptions,
77
GetterPropType,
8+
OutputModelFactoryMethodsMode,
89
} from '../types';
910
import { camel, upath } from '../utils';
1011

@@ -14,12 +15,16 @@ export const generateImports = ({
1415
isRootKey,
1516
specsName,
1617
specKey: currentSpecKey,
18+
factoryMethodOutput,
19+
factoryMethodPrefix
1720
}: {
1821
imports: GeneratorImport[];
1922
target: string;
2023
isRootKey: boolean;
2124
specsName: Record<string, string>;
2225
specKey: string;
26+
factoryMethodOutput?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
27+
factoryMethodPrefix?: string;
2328
}) => {
2429
if (!imports.length) {
2530
return '';
@@ -47,9 +52,14 @@ export const generateImports = ({
4752
} } from \'./${upath.join(path, camel(name))}\';`;
4853
}
4954

50-
return `import { create${name}, ${name}${
55+
let mainImport = `import ${!values ? 'type ' : ''}{ ${name}${
5156
alias ? ` as ${alias}` : ''
52-
} } from \'./${camel(name)}\';`;
57+
}${factoryMethodOutput == OutputModelFactoryMethodsMode.SINGLE ? `${factoryMethodPrefix}${name}` : ''} } from \'./${camel(name)}\';`;
58+
if (factoryMethodOutput == OutputModelFactoryMethodsMode.SPLIT) {
59+
let factoryMethodImport = `import { ${factoryMethodPrefix}${name} } from \'./${camel(name)}.factory\';`;
60+
mainImport += '\n' + factoryMethodImport;
61+
}
62+
return mainImport;
5363
})
5464
.join('\n');
5565
};

packages/core/src/generators/interface.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { SchemaObject } from 'openapi3-ts/oas30';
22
import { getScalar } from '../getters';
3-
import { ContextSpecs } from '../types';
3+
import { ContextSpecs, OutputModelFactoryMethodsMode } from '../types';
44
import { jsDoc } from '../utils';
55

66
/**
@@ -53,18 +53,27 @@ 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 == OutputModelFactoryMethodsMode.SINGLE) {
66+
model += factoryMethod;
67+
factoryMethod = '';
68+
}
69+
}
70+
6371
return [
6472
...scalar.schemas,
6573
{
6674
name,
6775
model,
76+
factoryMethod,
6877
imports: externalModulesImportsOnly,
6978
},
7079
];

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
@@ -50,6 +50,7 @@ export type NormalizedOutputOptions = {
5050
override: NormalizedOverrideOutput;
5151
client: OutputClient | OutputClientFunc;
5252
httpClient: OutputHttpClient;
53+
modelFactoryMethods?: boolean;
5354
clean: boolean | string[];
5455
docs: boolean | OutputDocsOptions;
5556
prettier: boolean;
@@ -70,6 +71,16 @@ export type NormalizedParamsSerializerOptions = {
7071
qs?: Record<string, any>;
7172
};
7273

74+
export const OutputModelFactoryMethodsMode = {
75+
SINGLE: 'single',
76+
SPLIT: 'split',
77+
} as const;
78+
79+
export type NormalizedModelFactoryMethodsOptions = {
80+
factoryMethodPrefix?: string;
81+
outputMode?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
82+
};
83+
7384
export type NormalizedOverrideOutput = {
7485
title?: (title: string) => string;
7586
transformer?: OutputTransformer;
@@ -83,6 +94,7 @@ export type NormalizedOverrideOutput = {
8394
formUrlEncoded: boolean | NormalizedMutator;
8495
paramsSerializer?: NormalizedMutator;
8596
paramsSerializerOptions?: NormalizedParamsSerializerOptions;
97+
modelFactoryMethods?: NormalizedModelFactoryMethodsOptions;
8698
components: {
8799
schemas: {
88100
suffix: string;
@@ -175,6 +187,7 @@ export type OutputOptions = {
175187
override?: OverrideOutput;
176188
client?: OutputClient | OutputClientFunc;
177189
httpClient?: OutputHttpClient;
190+
modelFactoryMethods?: boolean;
178191
clean?: boolean | string[];
179192
docs?: boolean | OutputDocsOptions;
180193
prettier?: boolean;
@@ -328,6 +341,11 @@ export type ParamsSerializerOptions = {
328341
qs?: Record<string, any>;
329342
};
330343

344+
export type ModelFactoryMethodsOptions = {
345+
factoryMethodPrefix?: string;
346+
outputMode?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
347+
};
348+
331349
export type OverrideOutput = {
332350
title?: (title: string) => string;
333351
transformer?: OutputTransformer;
@@ -341,6 +359,7 @@ export type OverrideOutput = {
341359
formUrlEncoded?: boolean | Mutator;
342360
paramsSerializer?: Mutator;
343361
paramsSerializerOptions?: ParamsSerializerOptions;
362+
modelFactoryMethods?: ModelFactoryMethodsOptions;
344363
components?: {
345364
schemas?: {
346365
suffix?: string;
@@ -603,6 +622,7 @@ export interface GlobalOptions {
603622
mock?: boolean | GlobalMockOptions;
604623
client?: OutputClient;
605624
httpClient?: OutputHttpClient;
625+
modelFactoryMethods?: boolean;
606626
mode?: OutputMode;
607627
tsconfig?: string | Tsconfig;
608628
packageJson?: string;
@@ -644,6 +664,7 @@ export interface PackageJson {
644664
export type GeneratorSchema = {
645665
name: string;
646666
model: string;
667+
factoryMethod: string;
647668
imports: GeneratorImport[];
648669
};
649670

packages/core/src/writers/schemas.ts

+63-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,46 @@ const getSchema = ({
3535
return file;
3636
};
3737

38+
const getFactoryMethod = ({
39+
schema: { name, 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 += `import { ${name}} from \'./${camel(name)}\';`;
72+
file += '\n\n';
73+
74+
file += factoryMethod;
75+
return file;
76+
};
77+
3878
const getPath = (path: string, name: string, fileExtension: string): string =>
3979
upath.join(path, `/${name}${fileExtension}`);
4080

@@ -53,6 +93,9 @@ export const writeSchema = async ({
5393
isRootKey,
5494
specsName,
5595
header,
96+
factoryMethodInclude,
97+
factoryMethodOutput,
98+
factoryMethodPrefix
5699
}: {
57100
path: string;
58101
schema: GeneratorSchema;
@@ -62,6 +105,10 @@ export const writeSchema = async ({
62105
isRootKey: boolean;
63106
specsName: Record<string, string>;
64107
header: string;
108+
factoryMethodInclude: boolean;
109+
factoryMethodOutput?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
110+
factoryMethodPrefix?: string;
111+
65112
}) => {
66113
const name = camel(schema.name);
67114

@@ -70,6 +117,12 @@ export const writeSchema = async ({
70117
getPath(path, name, fileExtension),
71118
getSchema({ schema, target, isRootKey, specsName, header, specKey }),
72119
);
120+
if (factoryMethodInclude && schema.factoryMethod.length > 0) {
121+
await fs.outputFile(
122+
getPath(path, name + '.factory', fileExtension),
123+
getFactoryMethod({ schema, target, isRootKey, specsName, header, specKey, factoryMethodOutput, factoryMethodPrefix }),
124+
);
125+
}
73126
} catch (e) {
74127
throw `Oups... 🍻. An Error occurred while writing schema ${name} => ${e}`;
75128
}
@@ -85,6 +138,9 @@ export const writeSchemas = async ({
85138
specsName,
86139
header,
87140
indexFiles,
141+
factoryMethodInclude,
142+
factoryMethodOutput,
143+
factoryMethodPrefix
88144
}: {
89145
schemaPath: string;
90146
schemas: GeneratorSchema[];
@@ -95,6 +151,9 @@ export const writeSchemas = async ({
95151
specsName: Record<string, string>;
96152
header: string;
97153
indexFiles: boolean;
154+
factoryMethodInclude: boolean;
155+
factoryMethodOutput?: (typeof OutputModelFactoryMethodsMode)[keyof typeof OutputModelFactoryMethodsMode];
156+
factoryMethodPrefix?: string;
98157
}) => {
99158
await Promise.all(
100159
schemas.map((schema) =>
@@ -107,6 +166,9 @@ export const writeSchemas = async ({
107166
isRootKey,
108167
specsName,
109168
header,
169+
factoryMethodInclude,
170+
factoryMethodOutput,
171+
factoryMethodPrefix
110172
}),
111173
),
112174
);

0 commit comments

Comments
 (0)