Skip to content

Commit 2fbc0a0

Browse files
author
Sudhir
committed
add custom template options for generate api
1 parent 58d126a commit 2fbc0a0

File tree

6 files changed

+198
-1
lines changed

6 files changed

+198
-1
lines changed

src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ export type Options = {
2727
postfixServices?: string;
2828
postfixModels?: string;
2929
request?: string;
30+
resolveTemplates?: {
31+
service?: string
32+
};
3033
write?: boolean;
3134
};
3235

@@ -48,6 +51,7 @@ export type Options = {
4851
* @param postfixServices Service name postfix
4952
* @param postfixModels Model name postfix
5053
* @param request Path to custom request file
54+
* @param resolveTemplates Template files (in .hbs format) for services generated from OpenAPI spec.
5155
* @param write Write the files to disk (true or false)
5256
*/
5357
export const generate = async ({
@@ -65,6 +69,7 @@ export const generate = async ({
6569
postfixServices = 'Service',
6670
postfixModels = '',
6771
request,
72+
resolveTemplates,
6873
write = true,
6974
}: Options): Promise<void> => {
7075
const openApi = isString(input) ? await getOpenApiSpec(input) : input;
@@ -73,6 +78,7 @@ export const generate = async ({
7378
httpClient,
7479
useUnionTypes,
7580
useOptions,
81+
resolveTemplates
7682
});
7783

7884
switch (openApiVersion) {

src/utils/registerHandlebarTemplates.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ import partialTypeIntersection from '../templates/partials/typeIntersection.hbs'
8484
import partialTypeReference from '../templates/partials/typeReference.hbs';
8585
import partialTypeUnion from '../templates/partials/typeUnion.hbs';
8686
import { registerHandlebarHelpers } from './registerHandlebarHelpers';
87+
import { resolveTemplate } from "./resolveTemplate";
8788

8889
export interface Templates {
8990
index: Handlebars.TemplateDelegate;
@@ -113,17 +114,28 @@ export const registerHandlebarTemplates = (root: {
113114
httpClient: HttpClient;
114115
useOptions: boolean;
115116
useUnionTypes: boolean;
117+
resolveTemplates?: {
118+
service?: string
119+
}
116120
}): Templates => {
117121
registerHandlebarHelpers(root);
118122

123+
const resolvedTemplates = {
124+
service: root.resolveTemplates?.service
125+
? resolveTemplate(root.resolveTemplates.service)
126+
: undefined
127+
}
128+
119129
// Main templates (entry points for the files we write to disk)
120130
const templates: Templates = {
121131
index: Handlebars.template(templateIndex),
122132
client: Handlebars.template(templateClient),
123133
exports: {
124134
model: Handlebars.template(templateExportModel),
125135
schema: Handlebars.template(templateExportSchema),
126-
service: Handlebars.template(templateExportService),
136+
service: resolvedTemplates.service
137+
? Handlebars.template(resolvedTemplates.service)
138+
: Handlebars.template(templateExportService),
127139
},
128140
core: {
129141
settings: Handlebars.template(templateCoreSettings),

src/utils/resolveTemplate.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { readFileSync, writeFileSync, mkdtempSync } from 'fs';
2+
import { join, resolve } from 'path';
3+
import { execSync } from 'child_process';
4+
import handlebars from 'handlebars';
5+
6+
const { precompile } = handlebars;
7+
8+
export function resolveTemplate(templatePath: string) {
9+
const source = readFileSync(templatePath).toString();
10+
const compiled = precompile(source);
11+
12+
const tempDir = mkdtempSync('template-');
13+
const tempFilePath = join(tempDir, 'template.js');
14+
writeFileSync(tempFilePath, `module.exports = ${compiled};`);
15+
16+
const module = require(resolve(tempFilePath));
17+
execSync(`rm -rf ${tempDir}`);
18+
return module;
19+
}

test/customExportService.hbs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
{{>header}}
2+
3+
// Custom comment
4+
5+
{{#equals @root.httpClient 'angular'}}
6+
{{#if @root.exportClient}}
7+
import { Injectable } from '@angular/core';
8+
import type { Observable } from 'rxjs';
9+
{{else}}
10+
import { Injectable } from '@angular/core';
11+
import { HttpClient } from '@angular/common/http';
12+
import type { Observable } from 'rxjs';
13+
{{/if}}
14+
15+
{{/equals}}
16+
{{#if imports}}
17+
{{#each imports}}
18+
import type { {{{this}}} } from '../models/{{{this}}}';
19+
{{/each}}
20+
21+
{{/if}}
22+
{{#notEquals @root.httpClient 'angular'}}
23+
import type { CancelablePromise } from '../core/CancelablePromise';
24+
{{/notEquals}}
25+
{{#if @root.exportClient}}
26+
{{#equals @root.httpClient 'angular'}}
27+
import { BaseHttpRequest } from '../core/BaseHttpRequest';
28+
{{else}}
29+
import type { BaseHttpRequest } from '../core/BaseHttpRequest';
30+
{{/equals}}
31+
{{else}}
32+
import { OpenAPI } from '../core/OpenAPI';
33+
import { request as __request } from '../core/request';
34+
{{/if}}
35+
36+
{{#equals @root.httpClient 'angular'}}
37+
@Injectable({
38+
providedIn: 'root',
39+
})
40+
{{/equals}}
41+
export class {{{name}}}{{{@root.postfix}}} {
42+
{{#if @root.exportClient}}
43+
44+
constructor(public readonly httpRequest: BaseHttpRequest) {}
45+
{{else}}
46+
{{#equals @root.httpClient 'angular'}}
47+
48+
constructor(public readonly http: HttpClient) {}
49+
{{/equals}}
50+
{{/if}}
51+
52+
{{#each operations}}
53+
/**
54+
{{#if deprecated}}
55+
* @deprecated
56+
{{/if}}
57+
{{#if summary}}
58+
* {{{escapeComment summary}}}
59+
{{/if}}
60+
{{#if description}}
61+
* {{{escapeComment description}}}
62+
{{/if}}
63+
{{#unless @root.useOptions}}
64+
{{#if parameters}}
65+
{{#each parameters}}
66+
* @param {{{name}}} {{#if description}}{{{escapeComment description}}}{{/if}}
67+
{{/each}}
68+
{{/if}}
69+
{{/unless}}
70+
{{#each results}}
71+
* @returns {{{type}}} {{#if description}}{{{escapeComment description}}}{{/if}}
72+
{{/each}}
73+
* @throws ApiError
74+
*/
75+
{{#if @root.exportClient}}
76+
{{#equals @root.httpClient 'angular'}}
77+
public {{{name}}}({{>parameters}}): Observable<{{>result}}> {
78+
return this.httpRequest.request({
79+
{{else}}
80+
public {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> {
81+
return this.httpRequest.request({
82+
{{/equals}}
83+
{{else}}
84+
{{#equals @root.httpClient 'angular'}}
85+
public {{{name}}}({{>parameters}}): Observable<{{>result}}> {
86+
return __request(OpenAPI, this.http, {
87+
{{else}}
88+
public static {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> {
89+
return __request(OpenAPI, {
90+
{{/equals}}
91+
{{/if}}
92+
method: '{{{method}}}',
93+
url: '{{{path}}}',
94+
{{#if parametersPath}}
95+
path: {
96+
{{#each parametersPath}}
97+
'{{{prop}}}': {{{name}}},
98+
{{/each}}
99+
},
100+
{{/if}}
101+
{{#if parametersCookie}}
102+
cookies: {
103+
{{#each parametersCookie}}
104+
'{{{prop}}}': {{{name}}},
105+
{{/each}}
106+
},
107+
{{/if}}
108+
{{#if parametersHeader}}
109+
headers: {
110+
{{#each parametersHeader}}
111+
'{{{prop}}}': {{{name}}},
112+
{{/each}}
113+
},
114+
{{/if}}
115+
{{#if parametersQuery}}
116+
query: {
117+
{{#each parametersQuery}}
118+
'{{{prop}}}': {{{name}}},
119+
{{/each}}
120+
},
121+
{{/if}}
122+
{{#if parametersForm}}
123+
formData: {
124+
{{#each parametersForm}}
125+
'{{{prop}}}': {{{name}}},
126+
{{/each}}
127+
},
128+
{{/if}}
129+
{{#if parametersBody}}
130+
{{#equals parametersBody.in 'formData'}}
131+
formData: {{{parametersBody.name}}},
132+
{{/equals}}
133+
{{#equals parametersBody.in 'body'}}
134+
body: {{{parametersBody.name}}},
135+
{{/equals}}
136+
{{#if parametersBody.mediaType}}
137+
mediaType: '{{{parametersBody.mediaType}}}',
138+
{{/if}}
139+
{{/if}}
140+
{{#if responseHeader}}
141+
responseHeader: '{{{responseHeader}}}',
142+
{{/if}}
143+
{{#if errors}}
144+
errors: {
145+
{{#each errors}}
146+
{{{code}}}: `{{{escapeDescription description}}}`,
147+
{{/each}}
148+
},
149+
{{/if}}
150+
});
151+
}
152+
153+
{{/each}}
154+
}

test/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ const generate = async (input, output) => {
1818
// indent: OpenAPI.Indent.SPACE_2,
1919
// postfix: 'Service',
2020
// request: './test/custom/request.ts',
21+
// resolveTemplates: {
22+
// service: 'test/customExportService.hbs'
23+
// }
2124
});
2225
};
2326

types/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export type Options = {
2828
postfixModels?: string;
2929
request?: string;
3030
write?: boolean;
31+
resolveTemplates?: {
32+
service?: string
33+
}
3134
};
3235

3336
export declare function generate(options: Options): Promise<void>;

0 commit comments

Comments
 (0)