Skip to content

Commit 72a4a3d

Browse files
author
Anh Nguyen
committed
allow use custom handlebar template to generate service, index, class
1 parent c3ef50b commit 72a4a3d

File tree

10 files changed

+279
-6
lines changed

10 files changed

+279
-6
lines changed

bin/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@ const params = program
1919
.option('--exportCore <value>', 'Write core files to disk', true)
2020
.option('--exportServices <value>', 'Write services to disk', true)
2121
.option('--exportModels <value>', 'Write models to disk', true)
22+
.option('--exportClient <value>', 'Write main Client file to disk', true)
23+
.option('--exportIndex <value>', 'Write Index to disk', true)
2224
.option('--exportSchemas <value>', 'Write schemas to disk', false)
2325
.option('--indent <value>', 'Indentation options [4, 2, tabs]', '4')
2426
.option('--postfixServices <value>', 'Service name postfix', 'Service')
2527
.option('--postfixModels <value>', 'Model name postfix')
2628
.option('--request <value>', 'Path to custom request file')
29+
.option('--serviceTemplate <value>', 'Path to custom service handlebars template to generate the service files')
30+
.option('--clientTemplate <value>', 'Path to custom client handlebars template to generate the client file')
31+
.option('--indexTemplate <value>', 'Path to custom index handlebars template to generate the index file')
2732
.parse(process.argv)
2833
.opts();
2934

@@ -40,11 +45,16 @@ if (OpenAPI) {
4045
exportCore: JSON.parse(params.exportCore) === true,
4146
exportServices: JSON.parse(params.exportServices) === true,
4247
exportModels: JSON.parse(params.exportModels) === true,
48+
exportClient: JSON.parse(params.exportClient) === true,
49+
exportIndex: JSON.parse(params.exportIndex) === true,
4350
exportSchemas: JSON.parse(params.exportSchemas) === true,
4451
indent: params.indent,
4552
postfixServices: params.postfixServices,
4653
postfixModels: params.postfixModels,
4754
request: params.request,
55+
serviceTemplate: params.serviceTemplate,
56+
clientTemplate: params.clientTemplate,
57+
indexTemplate: params.indexTemplate,
4858
})
4959
.then(() => {
5060
process.exit(0);

src/index.ts

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Client } from './client/interfaces/Client';
12
import { HttpClient } from './HttpClient';
23
import { Indent } from './Indent';
34
import { parse as parseV2 } from './openApi/v2';
@@ -8,6 +9,9 @@ import { isString } from './utils/isString';
89
import { postProcessClient } from './utils/postProcessClient';
910
import { registerHandlebarTemplates } from './utils/registerHandlebarTemplates';
1011
import { writeClient } from './utils/writeClient';
12+
import { writeClientClassCustomTemplate } from './utils/writeCustomTemplate/clientClass';
13+
import { writeClientIndexCustomTemplate } from './utils/writeCustomTemplate/clientIndex';
14+
import { writeClientServicesCustomTemplate } from './utils/writeCustomTemplate/clientServices';
1115

1216
export { HttpClient } from './HttpClient';
1317
export { Indent } from './Indent';
@@ -22,11 +26,16 @@ export type Options = {
2226
exportCore?: boolean;
2327
exportServices?: boolean;
2428
exportModels?: boolean;
29+
exportClient?: boolean;
30+
exportIndex?: boolean;
2531
exportSchemas?: boolean;
2632
indent?: Indent;
2733
postfixServices?: string;
2834
postfixModels?: string;
2935
request?: string;
36+
serviceTemplate?: string;
37+
clientTemplate?: string;
38+
indexTemplate?: string;
3039
write?: boolean;
3140
};
3241

@@ -60,11 +69,16 @@ export const generate = async ({
6069
exportCore = true,
6170
exportServices = true,
6271
exportModels = true,
72+
exportClient = true,
73+
exportIndex = true,
6374
exportSchemas = false,
6475
indent = Indent.SPACE_4,
6576
postfixServices = 'Service',
6677
postfixModels = '',
6778
request,
79+
serviceTemplate,
80+
clientTemplate,
81+
indexTemplate,
6882
write = true,
6983
}: Options): Promise<void> => {
7084
const openApi = isString(input) ? await getOpenApiSpec(input) : input;
@@ -75,10 +89,11 @@ export const generate = async ({
7589
useOptions,
7690
});
7791

92+
let clientFinal: Client;
7893
switch (openApiVersion) {
7994
case OpenApiVersion.V2: {
8095
const client = parseV2(openApi);
81-
const clientFinal = postProcessClient(client);
96+
clientFinal = postProcessClient(client);
8297
if (!write) break;
8398
await writeClient(
8499
clientFinal,
@@ -90,6 +105,8 @@ export const generate = async ({
90105
exportCore,
91106
exportServices,
92107
exportModels,
108+
exportClient,
109+
exportIndex,
93110
exportSchemas,
94111
indent,
95112
postfixServices,
@@ -102,7 +119,7 @@ export const generate = async ({
102119

103120
case OpenApiVersion.V3: {
104121
const client = parseV3(openApi);
105-
const clientFinal = postProcessClient(client);
122+
clientFinal = postProcessClient(client);
106123
if (!write) break;
107124
await writeClient(
108125
clientFinal,
@@ -114,6 +131,8 @@ export const generate = async ({
114131
exportCore,
115132
exportServices,
116133
exportModels,
134+
exportClient,
135+
exportIndex,
117136
exportSchemas,
118137
indent,
119138
postfixServices,
@@ -124,6 +143,55 @@ export const generate = async ({
124143
break;
125144
}
126145
}
146+
147+
if (serviceTemplate)
148+
await writeClientServicesCustomTemplate(
149+
clientFinal,
150+
output,
151+
httpClient,
152+
useOptions,
153+
useUnionTypes,
154+
indent,
155+
postfixServices,
156+
postfixModels,
157+
serviceTemplate,
158+
exportClient,
159+
exportModels,
160+
exportSchemas,
161+
clientName
162+
);
163+
164+
if (clientTemplate)
165+
await writeClientClassCustomTemplate(
166+
clientFinal,
167+
output,
168+
httpClient,
169+
useOptions,
170+
useUnionTypes,
171+
indent,
172+
postfixServices,
173+
clientTemplate,
174+
clientName
175+
);
176+
177+
if (indexTemplate)
178+
await writeClientIndexCustomTemplate(
179+
clientFinal,
180+
output,
181+
httpClient,
182+
useOptions,
183+
useUnionTypes,
184+
indent,
185+
postfixServices,
186+
postfixModels,
187+
indexTemplate,
188+
exportCore,
189+
exportServices,
190+
exportModels,
191+
exportSchemas,
192+
exportClient,
193+
clientName
194+
);
127195
};
128196

129197
export default {

src/utils/registerHandlebarHelpers.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import camelCase from 'camelcase';
2-
import Handlebars from 'handlebars/runtime';
2+
import HandlebarsRuntime from 'handlebars/runtime';
33
import { EOL } from 'os';
44

55
import type { Enum } from '../client/interfaces/Enum';
@@ -11,7 +11,10 @@ export const registerHandlebarHelpers = (root: {
1111
httpClient: HttpClient;
1212
useOptions: boolean;
1313
useUnionTypes: boolean;
14+
handlebars?: typeof HandlebarsRuntime;
1415
}): void => {
16+
const Handlebars = root.handlebars || HandlebarsRuntime;
17+
1518
Handlebars.registerHelper('ifdef', function (this: any, ...args): string {
1619
const options = args.pop();
1720
if (!args.every(value => !value)) {

src/utils/registerHandlebarTemplates.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Handlebars from 'handlebars/runtime';
1+
import HandlebarsRuntime from 'handlebars/runtime';
22

33
import { HttpClient } from '../HttpClient';
44
import templateClient from '../templates/client.hbs';
@@ -113,7 +113,10 @@ export const registerHandlebarTemplates = (root: {
113113
httpClient: HttpClient;
114114
useOptions: boolean;
115115
useUnionTypes: boolean;
116+
handlebars?: typeof HandlebarsRuntime;
116117
}): Templates => {
118+
const Handlebars = root.handlebars || HandlebarsRuntime;
119+
117120
registerHandlebarHelpers(root);
118121

119122
// Main templates (entry points for the files we write to disk)

src/utils/writeClient.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ describe('writeClient', () => {
4747
true,
4848
true,
4949
true,
50+
true,
51+
true,
5052
Indent.SPACE_4,
5153
'Service',
5254
'AppClient'

src/utils/writeClient.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export const writeClient = async (
4343
exportCore: boolean,
4444
exportServices: boolean,
4545
exportModels: boolean,
46+
exportClient: boolean,
47+
exportIndex: boolean,
4648
exportSchemas: boolean,
4749
indent: Indent,
4850
postfixServices: string,
@@ -94,12 +96,12 @@ export const writeClient = async (
9496
await writeClientModels(client.models, templates, outputPathModels, httpClient, useUnionTypes, indent);
9597
}
9698

97-
if (isDefined(clientName)) {
99+
if (isDefined(clientName) && exportClient) {
98100
await mkdir(outputPath);
99101
await writeClientClass(client, templates, outputPath, httpClient, clientName, indent, postfixServices);
100102
}
101103

102-
if (exportCore || exportServices || exportSchemas || exportModels) {
104+
if ((exportCore || exportServices || exportSchemas || exportModels) && exportIndex) {
103105
await mkdir(outputPath);
104106
await writeClientIndex(
105107
client,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { readFile, remove } from 'fs-extra';
2+
import Handlebars from 'handlebars';
3+
import { resolve } from 'path';
4+
5+
import { Client } from '../../client/interfaces/Client';
6+
import { HttpClient } from '../../HttpClient';
7+
import { Indent } from '../../Indent';
8+
import { writeFile } from '../fileSystem';
9+
import { formatCode } from '../formatCode';
10+
import { formatIndentation } from '../formatIndentation';
11+
import { getHttpRequestName } from '../getHttpRequestName';
12+
import { registerHandlebarTemplates } from '../registerHandlebarTemplates';
13+
import { sortModelsByName } from '../sortModelsByName';
14+
import { sortServicesByName } from '../sortServicesByName';
15+
16+
export const writeClientClassCustomTemplate = async (
17+
client: Client,
18+
outputPath: string,
19+
httpClient: HttpClient,
20+
useOptions: boolean,
21+
useUnionTypes: boolean,
22+
indent: Indent,
23+
postfix: string,
24+
templatePath: string,
25+
clientName?: string
26+
) => {
27+
registerHandlebarTemplates({
28+
httpClient,
29+
useUnionTypes,
30+
useOptions,
31+
handlebars: Handlebars, // since we're not using precompiled templates, we need a different object here
32+
});
33+
Handlebars.registerHelper('capitalize', str => {
34+
return str.charAt(0).toUpperCase() + str.slice(1);
35+
});
36+
37+
const clientClassTemplate = Handlebars.compile(await readFile(templatePath, 'utf8'));
38+
39+
const clientClassFile = resolve(outputPath, `${clientName}.ts`);
40+
await remove(clientClassFile);
41+
42+
const templateResult = clientClassTemplate({
43+
clientName,
44+
httpClient,
45+
postfix,
46+
server: client.server,
47+
version: client.version,
48+
models: sortModelsByName(client.models),
49+
services: sortServicesByName(client.services),
50+
httpRequest: getHttpRequestName(httpClient),
51+
});
52+
53+
await writeFile(resolve(outputPath, `${clientName}.ts`), formatIndentation(formatCode(templateResult), indent));
54+
};
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { readFile, remove } from 'fs-extra';
2+
import Handlebars from 'handlebars';
3+
import { resolve } from 'path';
4+
5+
import { Client } from '../../client/interfaces/Client';
6+
import { HttpClient } from '../../HttpClient';
7+
import { Indent } from '../../Indent';
8+
import { writeFile } from '../fileSystem';
9+
import { formatCode } from '../formatCode';
10+
import { formatIndentation } from '../formatIndentation';
11+
import { isDefined } from '../isDefined';
12+
import { registerHandlebarTemplates } from '../registerHandlebarTemplates';
13+
import { sortModelsByName } from '../sortModelsByName';
14+
import { sortServicesByName } from '../sortServicesByName';
15+
16+
export const writeClientIndexCustomTemplate = async (
17+
client: Client,
18+
outputPath: string,
19+
httpClient: HttpClient,
20+
useOptions: boolean,
21+
useUnionTypes: boolean,
22+
indent: Indent,
23+
postfixServices: string,
24+
postfixModels: string,
25+
templatePath: string,
26+
exportCore: boolean,
27+
exportServices: boolean,
28+
exportModels: boolean,
29+
exportSchemas: boolean,
30+
exportClient: boolean,
31+
clientName?: string
32+
) => {
33+
registerHandlebarTemplates({
34+
httpClient,
35+
useUnionTypes,
36+
useOptions,
37+
handlebars: Handlebars, // since we're not using precompiled templates, we need a different object here
38+
});
39+
Handlebars.registerHelper('capitalize', str => {
40+
return str.charAt(0).toUpperCase() + str.slice(1);
41+
});
42+
43+
const indexTemplate = Handlebars.compile(await readFile(templatePath, 'utf8'));
44+
45+
const dir = resolve(outputPath, 'index.ts');
46+
await remove(dir);
47+
48+
const templateResult = indexTemplate({
49+
serviceBaseUrl: client.server,
50+
exportCore,
51+
exportServices,
52+
exportModels,
53+
exportSchemas,
54+
useUnionTypes,
55+
postfixServices,
56+
postfixModels,
57+
clientName,
58+
server: client.server,
59+
version: client.version,
60+
models: sortModelsByName(client.models),
61+
services: sortServicesByName(client.services),
62+
exportClient: isDefined(clientName) && exportClient,
63+
});
64+
await writeFile(resolve(outputPath, 'index.ts'), formatIndentation(formatCode(templateResult), indent));
65+
};

0 commit comments

Comments
 (0)