Skip to content

Commit

Permalink
feat(api-client): interface generated for service mocking purposes
Browse files Browse the repository at this point in the history
  • Loading branch information
paveltobias authored and vmasek committed Jul 11, 2018
1 parent 0339446 commit f10c9b3
Show file tree
Hide file tree
Showing 33 changed files with 5,710 additions and 35 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ output
│ │ ...
│ ├─ another.model.ts
│ └─ index.ts
├─ api-client.interface.ts
├─ api-client.service.ts
└─ index.ts
```
Expand Down
17 changes: 14 additions & 3 deletions src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ export async function generateAPIClient(options: GenOptions): Promise<void> {
if (!existsSync(outputPath)) {
await ensureDir(outputPath);
}
await generateClient(mustacheData, outputPath);
await generateModels(mustacheData, outputPath);
await Promise.all([
generateClient(mustacheData, outputPath),
generateClientInterface(mustacheData, outputPath),
generateModels(mustacheData, outputPath),
]);
if (!options.skipModuleExport) {
await generateModuleExportIndex(mustacheData, outputPath);
}
Expand All @@ -63,7 +66,15 @@ async function generateClient(viewContext: MustacheData, outputPath: string): Pr
const clientTemplate = (await promisify(readFile)(`${__dirname}/../templates/ngx-service.mustache`)).toString();

const result = Mustache.render(clientTemplate, viewContext);
const outfile = join(outputPath, `${viewContext.fileName}.ts`);
const outfile = join(outputPath, `${viewContext.serviceFileName}.ts`);

await promisify(writeFile)(outfile, result, 'utf-8');
}

async function generateClientInterface(viewContext: MustacheData, outputPath: string): Promise<void> {
const template = (await promisify(readFile)(`${__dirname}/../templates/ngx-service-interface.mustache`)).toString();
const result = Mustache.render(template, viewContext);
const outfile = join(outputPath, `${viewContext.interfaceFileName}.ts`);

await promisify(writeFile)(outfile, result, 'utf-8');
}
Expand Down
3 changes: 2 additions & 1 deletion src/helper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Spec as Swagger, Path, Operation } from 'swagger-schema-official';
import { FileInfix } from './types';

export const BASIC_TS_TYPE_REGEX = /\b(string|number|integer|boolean)\b/;
const BUILD_IN_TS_TYPE_REGEX = /\b(string|number|integer|boolean|null|undefined|any|Object|Date|File|Blob)\b/;
Expand Down Expand Up @@ -78,7 +79,7 @@ export function typeName(name: string = 'any', isArray: boolean = false): string
return `${type}${isArray ? '[]' : ''}`;
}

export function fileName(name: string = '', type: 'model' | 'enum' | 'service' = 'model'): string {
export function fileName(name: string = '', type: FileInfix = 'model'): string {
return `${dashCase(name)}.${type}`;
}

Expand Down
4 changes: 3 additions & 1 deletion src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ export function createMustacheViewModel(swagger: Swagger, swaggerTag?: string):
methods: methods,
definitions: parseDefinitions(swagger.definitions, swagger.parameters, swaggerTag ? methods : undefined),
serviceName: swaggerTag ? `${swaggerTag}Service` : 'APIClient',
fileName: fileName(swaggerTag ? swaggerTag : 'api-client', 'service')
serviceFileName: fileName(swaggerTag ? swaggerTag : 'api-client', 'service'),
interfaceName: swaggerTag ? `${swaggerTag}Interface` : 'APIClientInterface',
interfaceFileName: fileName(swaggerTag ? swaggerTag : 'api-client', 'interface'),
};
}

Expand Down
5 changes: 4 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ export interface MustacheData {
readonly methods: Method[];
readonly definitions: Definition[];
readonly serviceName: string;
readonly fileName: string;
readonly serviceFileName: string;
readonly interfaceName: string;
readonly interfaceFileName: string;
}

export type TypescriptBasicTypes = 'string' | 'number' | 'boolean' | 'undefined' | 'any';
export type In = 'body' | 'path' | 'query' | 'modelbinding' | 'header' | 'formData';
export type MethodType = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
export type FileInfix = 'model' | 'enum' | 'service' | 'interface';

export interface Property {
readonly camelCaseName?: string;
Expand Down
5 changes: 3 additions & 2 deletions templates/ngx-module-export.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { {{&serviceName}}, USE_DOMAIN, USE_HTTP_OPTIONS } from './api-client.ser
export * from './models';
{{/definitions.length}}

export { {{&serviceName}} } from './{{&fileName}}';
export { {{&serviceName}} } from './{{&serviceFileName}}';
export { {{&interfaceName}} } from './{{&interfaceFileName}}';

/**
* provided options, headers and params will be used as default for each request
Expand Down Expand Up @@ -51,4 +52,4 @@ export class {{&serviceName}}Module {
]
};
}
}
}
26 changes: 26 additions & 0 deletions templates/ngx-service-interface.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* tslint:disable */

import { Observable } from 'rxjs';
import { HttpOptions } from './';
import * as models from './models';

export interface {{&interfaceName}} {
{{#methods}}
{{#description}}
/**
* {{&.}}
*/
{{/description}} {{&methodName}}(
{{#parameters.length}}
args: {
{{#parameters}}
{{&camelCaseName}}{{^isRequired}}?{{/isRequired}}: {{importType}}{{#isArray}}[]{{/isArray}},{{#description}} //{{^isRequired}} (optional){{/isRequired}} {{&.}}{{/description}}
{{/parameters}}
},
{{/parameters.length}}
requestHttpOptions?: HttpOptions
): Observable<{{&response}}>;

{{/methods}}
}
4 changes: 2 additions & 2 deletions templates/ngx-service.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { DefaultHttpOptions, HttpOptions } from './';
import { DefaultHttpOptions, HttpOptions, {{&interfaceName}} } from './';

{{#definitions.length}}
import * as models from './models';
Expand All @@ -21,7 +21,7 @@ type APIHttpOptions = HttpOptions & {
* Created with https://github.com/flowup/api-client-generator
*/
@Injectable()
export class {{&serviceName}} {
export class {{&serviceName}} implements {{&interfaceName}} {
readonly options: APIHttpOptions;
Expand Down
46 changes: 46 additions & 0 deletions tests/custom/api/api-client.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* tslint:disable */

import { Observable } from 'rxjs';
import { HttpOptions } from './';
import * as models from './models';

export interface APIClientInterface {

getItems(
args: {
pageSize: number,
page: number, // page number
},
requestHttpOptions?: HttpOptions
): Observable<models.ItemList>;

getItemModels(
args: {
pageSize: number,
page: number, // page number
},
requestHttpOptions?: HttpOptions
): Observable<any>;

getPetsId(
args: {
id: string,
},
requestHttpOptions?: HttpOptions
): Observable<any>;

deletePetsId(
args: {
id: string,
},
requestHttpOptions?: HttpOptions
): Observable<any>;

patchPetsId(
args: {
id: string,
},
requestHttpOptions?: HttpOptions
): Observable<any>;

}
4 changes: 2 additions & 2 deletions tests/custom/api/api-client.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { DefaultHttpOptions, HttpOptions } from './';
import { DefaultHttpOptions, HttpOptions, APIClientInterface } from './';

import * as models from './models';

Expand All @@ -19,7 +19,7 @@ type APIHttpOptions = HttpOptions & {
* Created with https://github.com/flowup/api-client-generator
*/
@Injectable()
export class APIClient {
export class APIClient implements APIClientInterface {

readonly options: APIHttpOptions;

Expand Down
3 changes: 2 additions & 1 deletion tests/custom/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { APIClient, USE_DOMAIN, USE_HTTP_OPTIONS } from './api-client.service';
export * from './models';

export { APIClient } from './api-client.service';
export { APIClientInterface } from './api-client.interface';

/**
* provided options, headers and params will be used as default for each request
Expand Down Expand Up @@ -49,4 +50,4 @@ export class APIClientModule {
]
};
}
}
}
Loading

0 comments on commit f10c9b3

Please sign in to comment.