Skip to content

Commit

Permalink
feat: Add response types (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
ffflorian authored and bennycode committed May 3, 2019
1 parent 9614b30 commit 00e54ca
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 13 deletions.
5 changes: 3 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'fs-extra';
import Handlebars from 'handlebars';
import path from 'path';
import prettier from 'prettier';
import {Spec} from 'swagger-schema-official';
import {BaseClient} from './info/BaseClient';
import {ParsedResource} from './info/ParsedResource';
import {SwaxiosGenerator} from './info/SwaxiosGenerator';
Expand Down Expand Up @@ -57,11 +58,11 @@ export async function generateClient(
outputDirectory: string,
writeFiles: boolean = true
): Promise<void> {
const swaggerJson = await fs.readJson(inputFile);
const swaggerJson: Spec = await fs.readJson(inputFile);
await validateConfig(swaggerJson);

for (const url of Object.keys(swaggerJson.paths)) {
const restResource = new ParsedResource(url, swaggerJson.paths[url]);
const restResource = new ParsedResource(url, swaggerJson.paths[url], swaggerJson);
if (writeFiles) {
await writeTemplate(restResource, path.join(outputDirectory, restResource.filePath));
}
Expand Down
10 changes: 4 additions & 6 deletions src/info/ParsedResource.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Path} from 'swagger-schema-official';
import {Path, Spec} from 'swagger-schema-official';
import {StringUtil} from '../util/StringUtil';
import {RequestMethod} from './RequestMethod';
import {SwaxiosGenerator} from './SwaxiosGenerator';
Expand All @@ -7,16 +7,14 @@ class ParsedResource implements SwaxiosGenerator {
public directory: string;
public methods: RequestMethod[];
public name: string;
public url: string;

constructor(url: string, methodDefinitions: Record<string, Path> = {}) {
constructor(url: string, methodDefinitions: Path = {}, spec: Spec) {
this.directory = url.substr(0, url.lastIndexOf('/'));
this.methods = [];
this.name = StringUtil.generateServiceName(url);
this.url = url;

for (const key of Object.keys(methodDefinitions)) {
const methodDefinition = new RequestMethod(url, key);
for (const [method, data] of Object.entries(methodDefinitions)) {
const methodDefinition = new RequestMethod(url, method, data.responses, spec);
this.methods.push(methodDefinition);
}
}
Expand Down
89 changes: 87 additions & 2 deletions src/info/RequestMethod.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,102 @@
import os from 'os';
import {Response, Schema, Spec} from 'swagger-schema-official';
import {inspect} from 'util';

class RequestMethod {
public method: string;
public returnType: string;
public url: string;
private readonly spec: Spec;
private readonly responses: Record<string, Response>;

constructor(url: string, method: string) {
constructor(url: string, method: string, responses: Record<string, Response>, spec: Spec) {
this.url = url;
this.spec = spec;
this.responses = responses;

if (method === 'delete' || method === 'head') {
this.returnType = 'void';
} else {
this.returnType = '{}';
this.returnType = this.buildResponseSchema();
}
this.method = method;
}

private buildType(schema: Schema): string {
const emptyObject = '{}';

let {required, properties, type} = schema;

if (schema.$ref && schema.$ref.startsWith('#/definitions')) {
if (!this.spec.definitions) {
console.info('Spec has no definitions.');
return emptyObject;
}
const definition = schema.$ref.replace('#/definitions', '');
required = this.spec.definitions[definition].required;
properties = this.spec.definitions[definition].properties;
type = this.spec.definitions[definition].type;
}

type = type || 'object';

switch (type) {
case 'string':
case 'number': {
return type;
}
case 'integer': {
return 'number';
}
case 'object': {
if (!properties) {
console.info('Schema definition is "object" but has no properties.');
return emptyObject;
}

const schema: Record<string, string> = {};

for (const property of Object.keys(properties)) {
const propertyName = required && !required.includes(property) ? `${property}?` : property;
schema[propertyName] = this.buildType(properties[property]);
}

return inspect(schema)
.replace(/'/gm, '')
.replace(',', ';')
.replace(new RegExp(os.EOL, 'g'), '');
}
case 'array': {
if (!schema.items) {
console.info('Schema definition is "array" but has no items.');
return 'any[]';
}

if (!(schema.items instanceof Array)) {
return this.buildType(schema.items);
}

const schemes = schema.items.map(itemSchema => this.buildType(itemSchema)).join(',');
return `Array<${schemes}>`;
}
default: {
return emptyObject;
}
}
}

private buildResponseSchema(): string {
const emptyObject = '{}';
const response200 = this.responses['200'];
const responseSchema = response200 && response200.schema;

if (!responseSchema) {
console.info('No schema for code 200 or schema has no definitions.');
return emptyObject;
}

return this.buildType(responseSchema);
}
}

export {RequestMethod};
6 changes: 3 additions & 3 deletions src/template/APIClass.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {AxiosInstance} from 'axios';

class {{name}} {
class {{{name}}} {
private readonly apiClient: AxiosInstance;

constructor(apiClient: AxiosInstance) {
Expand All @@ -11,9 +11,9 @@ class {{name}} {
async {{this.method}}(): Promise<{{{this.returnType}}}> {
const resource = '{{this.url}}';
{{#if this.returnType}}
const response = await this.apiClient.{{this.method}}{{#ifNotEquals this.returnType "void"}}<{{this.returnType}}>{{/ifNotEquals}}(resource);
const response = await this.apiClient.{{{this.method}}}{{#ifNotEquals this.returnType "void"}}<{{{this.returnType}}}>{{/ifNotEquals}}(resource);
{{else}}
const response = await this.apiClient.{{this.method}}(resource);
const response = await this.apiClient.{{{this.method}}}(resource);
{{/if}}
return response.data;
}
Expand Down

0 comments on commit 00e54ca

Please sign in to comment.