Skip to content

Commit 88aca06

Browse files
committed
add --serviceTemplate option
1 parent e03dc2b commit 88aca06

File tree

6 files changed

+123
-4
lines changed

6 files changed

+123
-4
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,36 @@
11
# OpenAPI Typescript Codegen
22

3+
Fork ([diff](https://github.com/ferdikoomen/openapi-typescript-codegen/compare/master...DND-IT:openapi-typescript-codegen:master))
4+
which adds a `--serviceTemplate` option. A variant of this fork is also in [this pull request](https://github.com/ferdikoomen/openapi-typescript-codegen/pull/1268) to the original upstream repo.
5+
6+
Can be used in another project by adding to `package.json`:
7+
8+
```json
9+
"openapi-typescript-codegen": "https://github.com/DND-IT/openapi-typescript-codegen.git#master",
10+
```
11+
12+
To update or modify this fork, check it out locally:
13+
14+
git clone [email protected]:DND-IT/openapi-typescript-codegen.git
15+
cd openapi-typescript-codegen
16+
git remote add upstream [email protected]:ferdikoomen/openapi-typescript-codegen.git
17+
18+
To pull in changes from original repo:
19+
20+
git fetch upstream
21+
git rebase upstream/master master
22+
npm ci
23+
24+
To build a new version and test it locally in disco project:
25+
26+
npm run release
27+
cp dist/index.js ../disco/node_modules/openapi-typescript-codegen/dist/index.js`
28+
29+
To release a new version, run `npm run release` and push everything, including the `dist/index.js` file to GitHub. Then, in the project using it, delete the
30+
`openapi-typescript-codegen` entry in the `package-lock.json` and run `npm install` to install the new version.
31+
32+
---
33+
334
[![NPM][npm-image]][npm-url]
435
[![License][license-image]][license-url]
536
[![Coverage][coverage-image]][coverage-url]
@@ -51,6 +82,7 @@ $ openapi --help
5182
--postfixServices Service name postfix (default: "Service")
5283
--postfixModels Model name postfix
5384
--request <value> Path to custom request file
85+
--serviceTemplate Path to custom service handlebars template to generate the service files
5486
-h, --help display help for command
5587
5688
Examples

bin/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const params = program
2525
.option('--postfixServices <value>', 'Service name postfix', 'Service')
2626
.option('--postfixModels <value>', 'Model name postfix')
2727
.option('--request <value>', 'Path to custom request file')
28+
.option('--serviceTemplate <value>', 'Path to custom service handlebars template to generate the service files')
2829
.parse(process.argv)
2930
.opts();
3031

@@ -46,6 +47,7 @@ if (OpenAPI) {
4647
postfixServices: params.postfixServices ?? params.postfix,
4748
postfixModels: params.postfixModels,
4849
request: params.request,
50+
serviceTemplate: params.serviceTemplate,
4951
})
5052
.then(() => {
5153
process.exit(0);

src/index.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { isString } from './utils/isString';
88
import { postProcessClient } from './utils/postProcessClient';
99
import { registerHandlebarTemplates } from './utils/registerHandlebarTemplates';
1010
import { writeClient } from './utils/writeClient';
11+
import { writeClientServicesCustomTemplate } from './utils/writeClientServicesCustomTemplate';
1112

1213
export { HttpClient } from './HttpClient';
1314
export { Indent } from './Indent';
@@ -27,6 +28,7 @@ export type Options = {
2728
postfixServices?: string;
2829
postfixModels?: string;
2930
request?: string;
31+
serviceTemplate?: string;
3032
write?: boolean;
3133
};
3234

@@ -65,6 +67,7 @@ export const generate = async ({
6567
postfixServices = 'Service',
6668
postfixModels = '',
6769
request,
70+
serviceTemplate,
6871
write = true,
6972
}: Options): Promise<void> => {
7073
const openApi = isString(input) ? await getOpenApiSpec(input) : input;
@@ -75,10 +78,15 @@ export const generate = async ({
7578
useOptions,
7679
});
7780

81+
if (serviceTemplate) {
82+
exportServices = false;
83+
}
84+
85+
let clientFinal;
7886
switch (openApiVersion) {
7987
case OpenApiVersion.V2: {
8088
const client = parseV2(openApi);
81-
const clientFinal = postProcessClient(client);
89+
clientFinal = postProcessClient(client);
8290
if (!write) break;
8391
await writeClient(
8492
clientFinal,
@@ -102,7 +110,7 @@ export const generate = async ({
102110

103111
case OpenApiVersion.V3: {
104112
const client = parseV3(openApi);
105-
const clientFinal = postProcessClient(client);
113+
clientFinal = postProcessClient(client);
106114
if (!write) break;
107115
await writeClient(
108116
clientFinal,
@@ -124,6 +132,19 @@ export const generate = async ({
124132
break;
125133
}
126134
}
135+
136+
if (serviceTemplate) {
137+
await writeClientServicesCustomTemplate(
138+
clientFinal,
139+
output,
140+
httpClient,
141+
useOptions,
142+
useUnionTypes,
143+
indent,
144+
postfixServices,
145+
serviceTemplate
146+
);
147+
}
127148
};
128149

129150
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)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { mkdir, 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 { OperationParameter } from '../client/interfaces/OperationParameter';
7+
import { HttpClient } from '../HttpClient';
8+
import { Indent } from '../Indent';
9+
import { writeFile } from './fileSystem';
10+
import { formatCode } from './formatCode';
11+
import { formatIndentation } from './formatIndentation';
12+
import { registerHandlebarTemplates } from './registerHandlebarTemplates';
13+
14+
export const writeClientServicesCustomTemplate = async (
15+
client: Client,
16+
outputPath: string,
17+
httpClient: HttpClient,
18+
useOptions: boolean,
19+
useUnionTypes: boolean,
20+
indent: Indent,
21+
postfix: string,
22+
templatePath: string
23+
) => {
24+
registerHandlebarTemplates({
25+
httpClient,
26+
useUnionTypes,
27+
useOptions,
28+
handlebars: Handlebars, // since we're not using precompiled templates, we need a different object here
29+
});
30+
Handlebars.registerHelper('capitalize', (str: string) => {
31+
return str.charAt(0).toUpperCase() + str.slice(1);
32+
});
33+
Handlebars.registerHelper('buildUrlStr', (path: string, parametersPath?: OperationParameter[]) => {
34+
parametersPath?.forEach(param => {
35+
path = path.replace(`{${param.prop}}`, '${' + param.name + '}');
36+
});
37+
return path;
38+
});
39+
40+
const serviceTemplate = Handlebars.compile(await readFile(templatePath, 'utf8'));
41+
42+
const servicesDir = resolve(outputPath, 'services');
43+
await remove(servicesDir);
44+
await mkdir(servicesDir);
45+
46+
for (const service of client.services) {
47+
const file = resolve(outputPath, `services/${service.name}${postfix}.ts`);
48+
const templateResult = serviceTemplate({
49+
...service,
50+
serviceBaseUrl: client.server,
51+
httpClient,
52+
useUnionTypes,
53+
useOptions,
54+
postfix,
55+
});
56+
await writeFile(file, formatIndentation(formatCode(templateResult), indent));
57+
}
58+
};

0 commit comments

Comments
 (0)