Skip to content

Commit 3492d8f

Browse files
committed
feat(api-client): models imported as module
- eliminates need for importing each model - fixes unused model import issue fixes #22
1 parent e19fffe commit 3492d8f

File tree

5 files changed

+38
-25
lines changed

5 files changed

+38
-25
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ node_modules
33
.vs
44
.vscode
55
obj
6-
output
76
temp
87
npm-debug.log
8+
output*/
9+
ref*/
10+
dist/

src/generator.ts

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { promisify } from 'util';
88

99
export type RenderFileName = (text: string, render: any) => string;
1010

11+
const BASIC_TS_TYPE_REGEX = /^string|number|integer|boolean|undefined|any|object$/i;
12+
1113
export interface Definition {
1214
name?: string;
1315
properties: Parameter[];
@@ -45,6 +47,7 @@ export interface Parameter {
4547
readonly schema?: any,
4648
type?: string,
4749
typescriptType?: TypescriptBasicTypes | string;
50+
readonly importType?: string;
4851
}
4952

5053
export interface Method {
@@ -92,7 +95,7 @@ export class Generator {
9295
/**
9396
* Removes duplicate words from type name
9497
*
95-
* example: shipmentShipmentAddress --> ShipmentAddress
98+
* example: shipmentShipmentAddress --> shipmentAddress
9699
*
97100
* note: minimum is 3 letters otherwise words are not striped
98101
*
@@ -128,7 +131,7 @@ export class Generator {
128131
private static typeName(typeName: string = '', isArray: boolean = false): string {
129132
let type: string;
130133

131-
if (/^(?:string)|(?:number)|(?:integer)|(?:boolean)|(?:undefined)|(?:any)|(?:object)$/i.test(typeName)) {
134+
if (BASIC_TS_TYPE_REGEX.test(typeName)) {
132135
type = typeName;
133136
} else {
134137
type = Generator.camelCase(typeName, false);
@@ -148,7 +151,7 @@ export class Generator {
148151
const protocol = host && schemes && schemes.length > 0 ? `${schemes[0]}://` : '//';
149152

150153
// if no host exists in the swagger file default to effectively a relative path.
151-
const domain = host ? host : "${window.location.hostname}${window.location.port ? ':'+window.location.port : ''}";
154+
const domain = host ? host : '${window.location.hostname}${window.location.port ? \':\'+window.location.port : \'\'}';
152155
const base = ('/' === basePath || !basePath ? '' : basePath);
153156
return `${protocol}${domain}${base}`;
154157
}
@@ -251,6 +254,10 @@ export class Generator {
251254
return 'any';
252255
}
253256

257+
private static prefixImportedModels(type: string): string {
258+
return BASIC_TS_TYPE_REGEX.test(type) ? type : `models.${type}`;
259+
}
260+
254261
private static transformParameters(parameters: Parameter[]): Parameter[] {
255262
return Array.isArray(parameters)
256263
// todo: required params
@@ -263,6 +270,7 @@ export class Generator {
263270

264271
parameter.camelCaseName = Generator.camelCase(param.name);
265272
parameter.typescriptType = Generator.toTypescriptType(parameter);
273+
parameter.importType = Generator.prefixImportedModels(parameter.typescriptType);
266274

267275
if (param.in === 'body') {
268276
parameter.isBodyParameter = true;
@@ -284,7 +292,7 @@ export class Generator {
284292
: [];
285293
}
286294

287-
async generateAPIClient() {
295+
async generateAPIClient(): Promise<void> {
288296
/* Create output folder if not already present */
289297
if (!await promisify(fs.exists)(this.outputPath)) {
290298
await promisify(fs.mkdir)(this.outputPath);
@@ -294,28 +302,33 @@ export class Generator {
294302

295303
await this.generateClient(mustacheData);
296304
await this.generateModels(mustacheData);
297-
await this.generateExportDefinition(mustacheData);
305+
await this.generateModuleExportIndex(mustacheData);
298306
}
299307

300-
async generateClient(viewContext: MustacheData) {
308+
async generateClient(viewContext: MustacheData): Promise<void> {
301309
/* generate main API client class */
302310
const clientTemplate = (await promisify(fs.readFile)(__dirname + '/../templates/ngx-service.mustache')).toString();
303311

304-
let result = Mustache.render(clientTemplate, viewContext);
305-
let outfile = join(this.outputPath, 'api-client-service.ts');
312+
const result = Mustache.render(clientTemplate, viewContext);
313+
const outfile = join(this.outputPath, 'api-client-service.ts');
306314

307315
await promisify(fs.writeFile)(outfile, result, 'utf-8');
308316
}
309317

310-
async generateModels(viewContext: MustacheData) {
311-
let outputDir = join(this.outputPath, 'models');
318+
async generateModels(viewContext: MustacheData): Promise<void> {
319+
const outputDir = join(this.outputPath, 'models');
320+
const outIndexFile = join(outputDir, '/index.ts');
312321

313322
const modelTemplate = (await promisify(fs.readFile)(__dirname + '/../templates/ngx-model.mustache')).toString();
323+
const modelExportTemplate = (await promisify(fs.readFile)(__dirname + '/../templates/ngx-models-export.mustache')).toString();
314324

315325
if (!await promisify(fs.exists)(outputDir)) {
316326
await promisify(fs.mkdir)(outputDir);
317327
}
318328

329+
// generate model export index here
330+
fs.writeFileSync(outIndexFile, Mustache.render(modelExportTemplate, viewContext), 'utf-8');
331+
319332
// generate API models
320333
viewContext.definitions.forEach((definition) => {
321334
let result = Mustache.render(modelTemplate, definition);
@@ -327,10 +340,10 @@ export class Generator {
327340
});
328341
}
329342

330-
async generateExportDefinition(viewContext: MustacheData) {
331-
const exportTemplate = (await promisify(fs.readFile)(__dirname + '/../templates/ngx-models-export.mustache')).toString();
332-
let result = Mustache.render(exportTemplate, viewContext);
333-
let outfile = join(this.outputPath, '/index.ts');
343+
async generateModuleExportIndex(viewContext: MustacheData): Promise<void> {
344+
const exportTemplate = (await promisify(fs.readFile)(__dirname + '/../templates/ngx-module-export.mustache')).toString();
345+
const result = Mustache.render(exportTemplate, viewContext);
346+
const outfile = join(this.outputPath, '/index.ts');
334347

335348
fs.writeFileSync(outfile, result, 'utf-8');
336349
}
@@ -359,7 +372,7 @@ export class Generator {
359372
isSecure: swagger.security !== undefined || op.security !== undefined,
360373
parameters: Generator.transformParameters(op.parameters),
361374
hasJsonResponse: true,
362-
response: Generator.determineResponseType(op.responses),
375+
response: Generator.prefixImportedModels(Generator.determineResponseType(op.responses)),
363376
})
364377
)
365378
)),
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
/* tslint:disable */
22

33
{{#definitions}}
4-
export { {{name}} } from './models/{{#renderFileName}}{{name}}{{/renderFileName}}';
4+
export { {{name}} } from './{{#renderFileName}}{{name}}{{/renderFileName}}';
55
{{/definitions}}
6-
7-
export { ApiClientService } from './api-client-service';
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/* tslint:disable */
2+
3+
export * from './models';
4+
export { ApiClientService } from './api-client-service';

templates/ngx-service.mustache

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
44
import { Inject, Injectable, Optional } from '@angular/core';
55
import { Observable } from 'rxjs/Observable';
66

7-
import {
8-
{{#definitions}}
9-
{{name}},
10-
{{/definitions}}
11-
} from '.';
7+
import * as models from './models';
128

139
interface HttpOptions {
1410
headers?: HttpHeaders,
@@ -41,7 +37,7 @@ export class ApiClientService {
4137
}
4238

4339
{{#methods}}
44-
{{&methodName}}({{#parameters}}{{&camelCaseName}}: {{typescriptType}}, {{/parameters}}options?: HttpOptions): Observable<{{&response}}> {
40+
{{&methodName}}({{#parameters}}{{&camelCaseName}}: {{importType}}, {{/parameters}}options?: HttpOptions): Observable<{{&response}}> {
4541
const path = `{{&path}}`;
4642
options = {...this.options, ...options};
4743

0 commit comments

Comments
 (0)