Skip to content

Commit b56e7fd

Browse files
committed
feat: add custom generator to generate only required models
1 parent 5599532 commit b56e7fd

File tree

7 files changed

+17440
-167
lines changed

7 files changed

+17440
-167
lines changed

package-lock.json

Lines changed: 17268 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"release": "rollup --config --environment NODE_ENV:production",
4949
"validate": "tsc --project tsconfig.json --noEmit",
5050
"run": "node ./test/index.js",
51+
"cleanRun": "npm run clean && npm run build && npm run run",
5152
"test": "jest --selectProjects UNIT",
5253
"test:update": "jest --selectProjects UNIT --updateSnapshot",
5354
"test:watch": "jest --selectProjects UNIT --watch",

src/generate.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { HttpClient } from './HttpClient';
2+
import { Indent } from './Indent';
3+
import { parse as parseV2 } from './openApi/v2';
4+
import { parse as parseV3 } from './openApi/v3';
5+
import { getOpenApiSpec } from './utils/getOpenApiSpec';
6+
import { getOpenApiVersion, OpenApiVersion } from './utils/getOpenApiVersion';
7+
import { isString } from './utils/isString';
8+
import { postProcessClient } from './utils/postProcessClient';
9+
import { registerHandlebarTemplates } from './utils/registerHandlebarTemplates';
10+
import { writeClient } from './utils/writeClient';
11+
12+
export type Options = {
13+
input: string | Record<string, any>;
14+
output: string;
15+
httpClient?: HttpClient;
16+
clientName?: string;
17+
useOptions?: boolean;
18+
useUnionTypes?: boolean;
19+
exportCore?: boolean;
20+
exportServices?: boolean;
21+
exportModels?: boolean;
22+
exportSchemas?: boolean;
23+
indent?: Indent;
24+
postfix?: string;
25+
request?: string;
26+
write?: boolean;
27+
exportModelsFileExtension?: string;
28+
};
29+
/**
30+
* Generate the OpenAPI client. This method will read the OpenAPI specification and based on the
31+
* given language it will generate the client, including the typed models, validation schemas,
32+
* service layer, etc.
33+
* @param input The relative ___location of the OpenAPI spec
34+
* @param output The relative ___location of the output directory
35+
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
36+
* @param clientName Custom client class name
37+
* @param useOptions Use options or arguments functions
38+
* @param useUnionTypes Use union types instead of enums
39+
* @param exportCore Generate core client classes
40+
* @param exportServices Generate services
41+
* @param exportModels Generate models
42+
* @param exportSchemas Generate schemas
43+
* @param indent Indentation options (4, 2 or tab)
44+
* @param postfix Service name postfix
45+
* @param request Path to custom request file
46+
* @param write Write the files to disk (true or false)
47+
* @param exportModelsFileExtension File extension for models .ts as default
48+
*/
49+
export const generate = async ({
50+
input,
51+
output,
52+
httpClient = HttpClient.FETCH,
53+
clientName,
54+
useOptions = false,
55+
useUnionTypes = false,
56+
exportCore = true,
57+
exportServices = true,
58+
exportModels = true,
59+
exportSchemas = false,
60+
indent = Indent.SPACE_4,
61+
postfix = 'Service',
62+
request,
63+
write = true,
64+
}: Options): Promise<void> => {
65+
const openApi = isString(input) ? await getOpenApiSpec(input) : input;
66+
const openApiVersion = getOpenApiVersion(openApi);
67+
const templates = registerHandlebarTemplates({
68+
httpClient,
69+
useUnionTypes,
70+
useOptions,
71+
});
72+
73+
switch (openApiVersion) {
74+
case OpenApiVersion.V2: {
75+
const client = parseV2(openApi);
76+
const clientFinal = postProcessClient(client);
77+
if (!write) break;
78+
await writeClient(
79+
clientFinal,
80+
templates,
81+
output,
82+
httpClient,
83+
useOptions,
84+
useUnionTypes,
85+
exportCore,
86+
exportServices,
87+
exportModels,
88+
exportSchemas,
89+
indent,
90+
postfix,
91+
clientName,
92+
request
93+
);
94+
break;
95+
}
96+
97+
case OpenApiVersion.V3: {
98+
const client = parseV3(openApi);
99+
const clientFinal = postProcessClient(client);
100+
if (!write) break;
101+
await writeClient(
102+
clientFinal,
103+
templates,
104+
output,
105+
httpClient,
106+
useOptions,
107+
useUnionTypes,
108+
exportCore,
109+
exportServices,
110+
exportModels,
111+
exportSchemas,
112+
indent,
113+
postfix,
114+
clientName,
115+
request
116+
);
117+
break;
118+
}
119+
}
120+
};
121+
122+
export default generate;

src/generateCustomSpec.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generate, Options } from './generate';
12
import { OpenApi } from './openApi/v3/interfaces/OpenApi';
23
import { OpenApiMediaType } from './openApi/v3/interfaces/OpenApiMediaType';
34
import { OpenApiOperation } from './openApi/v3/interfaces/OpenApiOperation';
@@ -7,7 +8,13 @@ import { OpenApiServer } from './openApi/v3/interfaces/OpenApiServer';
78
import { getOpenApiSpec } from './utils/getOpenApiSpec';
89
import { Dictionary } from './utils/types';
910

10-
export const generateCustomSpec = async (gen: any, input: string, output: string, config: Record<string, unknown>) => {
11+
type Config = Options & {
12+
filterMethod: 'greedy' | 'ascetic';
13+
filterArray: string[];
14+
input: string;
15+
};
16+
17+
export const generateCustomSpec = async (config: Config) => {
1118
const getSchemaRefFromContent = (content: OpenApiMediaType): string => {
1219
let ref: string = '';
1320

@@ -16,15 +23,20 @@ export const generateCustomSpec = async (gen: any, input: string, output: string
1623
return ref.split('/').slice(-1)[0];
1724
};
1825

19-
const list: OpenApi = await getOpenApiSpec(input);
26+
const list: OpenApi = await getOpenApiSpec(config.input);
2027

21-
const requiredPathsList: string[] = ['/api/agreement', '/api/agreement/{id}'];
28+
// const filterArray: string[] = ['/api/agreement', '/api/agreement/{id}'];
2229

2330
const requiredPaths: OpenApi['paths'] = {};
2431

2532
for (const path in list.paths) {
26-
if (requiredPathsList.some(it => it === path)) {
27-
requiredPaths[path] = list.paths[path];
33+
if (!list.paths.hasOwnProperty(path)) return;
34+
35+
if (config.filterMethod === 'ascetic') {
36+
if (config.filterArray.some(it => it === path)) requiredPaths[path] = list.paths[path];
37+
}
38+
if (config.filterMethod === 'greedy') {
39+
if (!config.filterArray.some(it => it === path)) requiredPaths[path] = list.paths[path];
2840
}
2941
}
3042

@@ -84,5 +96,7 @@ export const generateCustomSpec = async (gen: any, input: string, output: string
8496
},
8597
};
8698

87-
await gen(listWithRequiredPaths, output);
99+
await generate({ ...config, input: listWithRequiredPaths });
88100
};
101+
102+
export default generateCustomSpec;

src/index.ts

Lines changed: 5 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,15 @@
1+
import { generate } from './generate';
2+
import { generateCustomSpec } from './generateCustomSpec';
13
import { HttpClient } from './HttpClient';
24
import { Indent } from './Indent';
3-
import { parse as parseV2 } from './openApi/v2';
4-
import { parse as parseV3 } from './openApi/v3';
5-
import { getOpenApiSpec } from './utils/getOpenApiSpec';
6-
import { getOpenApiVersion, OpenApiVersion } from './utils/getOpenApiVersion';
7-
import { isString } from './utils/isString';
8-
import { postProcessClient } from './utils/postProcessClient';
9-
import { registerHandlebarTemplates } from './utils/registerHandlebarTemplates';
10-
import { writeClient } from './utils/writeClient';
115

12-
export { generateCustomSpec } from './generateCustomSpec';
6+
export { generateCustomSpec };
7+
export { generate };
138
export { HttpClient } from './HttpClient';
149
export { Indent } from './Indent';
1510

16-
export type Options = {
17-
input: string | Record<string, any>;
18-
output: string;
19-
httpClient?: HttpClient;
20-
clientName?: string;
21-
useOptions?: boolean;
22-
useUnionTypes?: boolean;
23-
exportCore?: boolean;
24-
exportServices?: boolean;
25-
exportModels?: boolean;
26-
exportSchemas?: boolean;
27-
indent?: Indent;
28-
postfix?: string;
29-
request?: string;
30-
write?: boolean;
31-
};
32-
33-
/**
34-
* Generate the OpenAPI client. This method will read the OpenAPI specification and based on the
35-
* given language it will generate the client, including the typed models, validation schemas,
36-
* service layer, etc.
37-
* @param input The relative ___location of the OpenAPI spec
38-
* @param output The relative ___location of the output directory
39-
* @param httpClient The selected httpClient (fetch, xhr, node or axios)
40-
* @param clientName Custom client class name
41-
* @param useOptions Use options or arguments functions
42-
* @param useUnionTypes Use union types instead of enums
43-
* @param exportCore Generate core client classes
44-
* @param exportServices Generate services
45-
* @param exportModels Generate models
46-
* @param exportSchemas Generate schemas
47-
* @param indent Indentation options (4, 2 or tab)
48-
* @param postfix Service name postfix
49-
* @param request Path to custom request file
50-
* @param write Write the files to disk (true or false)
51-
*/
52-
export const generate = async ({
53-
input,
54-
output,
55-
httpClient = HttpClient.FETCH,
56-
clientName,
57-
useOptions = false,
58-
useUnionTypes = false,
59-
exportCore = true,
60-
exportServices = true,
61-
exportModels = true,
62-
exportSchemas = false,
63-
indent = Indent.SPACE_4,
64-
postfix = 'Service',
65-
request,
66-
write = true,
67-
}: Options): Promise<void> => {
68-
const openApi = isString(input) ? await getOpenApiSpec(input) : input;
69-
const openApiVersion = getOpenApiVersion(openApi);
70-
const templates = registerHandlebarTemplates({
71-
httpClient,
72-
useUnionTypes,
73-
useOptions,
74-
});
75-
76-
switch (openApiVersion) {
77-
case OpenApiVersion.V2: {
78-
const client = parseV2(openApi);
79-
const clientFinal = postProcessClient(client);
80-
if (!write) break;
81-
await writeClient(
82-
clientFinal,
83-
templates,
84-
output,
85-
httpClient,
86-
useOptions,
87-
useUnionTypes,
88-
exportCore,
89-
exportServices,
90-
exportModels,
91-
exportSchemas,
92-
indent,
93-
postfix,
94-
clientName,
95-
request
96-
);
97-
break;
98-
}
99-
100-
case OpenApiVersion.V3: {
101-
const client = parseV3(openApi);
102-
const clientFinal = postProcessClient(client);
103-
if (!write) break;
104-
await writeClient(
105-
clientFinal,
106-
templates,
107-
output,
108-
httpClient,
109-
useOptions,
110-
useUnionTypes,
111-
exportCore,
112-
exportServices,
113-
exportModels,
114-
exportSchemas,
115-
indent,
116-
postfix,
117-
clientName,
118-
request
119-
);
120-
break;
121-
}
122-
}
123-
};
124-
12511
export default {
12612
HttpClient,
12713
generate,
14+
generateCustomSpec,
12815
};

test/index.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,22 @@ const generateRealWorldSpecs = async () => {
5959
const main = async () => {
6060
await generate('./test/spec/v2.json', './test/generated/v2/');
6161
await generate('./test/spec/v3.json', './test/generated/v3/');
62-
await OpenAPI.generateCustomSpec(generate, './test/spec/saddlebackApi.json', './test/generated/saddleback/');
62+
await OpenAPI.generateCustomSpec({
63+
input: './test/spec/saddlebackApi.json',
64+
output: './test/generated/saddleback/',
65+
httpClient: 'axios',
66+
clientName: 'TestAxiosClassName',
67+
useOptions: true,
68+
useUnionTypes: false,
69+
exportCore: true,
70+
exportServices: true,
71+
exportModels: true,
72+
exportSchemas: false,
73+
indent: '4',
74+
postfix: '',
75+
filterMethod: 'greedy',
76+
filterArray: ['/api/agreement', '/api/agreement/{id}'],
77+
});
6378
// await generateRealWorldSpecs();
6479
};
6580

types/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,20 @@ export type Options = {
2929
write?: boolean;
3030
};
3131

32+
export type CustomConfig = Options & {
33+
filterMethod: 'greedy' | 'ascetic';
34+
filterArray: string[];
35+
input: string;
36+
};
37+
3238
export declare function generate(options: Options): Promise<void>;
39+
export declare function generateCustomSpec(config: CustomConfig): Promise<void>;
3340

3441
declare type OpenAPI = {
3542
HttpClient: HttpClient;
3643
Indent: Indent;
3744
generate: typeof generate;
45+
generateCustomSpec: typeof generateCustomSpec;
3846
};
3947

4048
export default OpenAPI;

0 commit comments

Comments
 (0)