Skip to content

Commit

Permalink
first part of the code generator for angular from swagger
Browse files Browse the repository at this point in the history
  • Loading branch information
egandro committed Jun 30, 2017
1 parent d56dcb6 commit 85833d0
Show file tree
Hide file tree
Showing 39 changed files with 273 additions and 864 deletions.
12 changes: 1 addition & 11 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,7 @@
# all
* custom templates

# express.ts.routes

* Add a dynamic BasePath als prefix to all Controller Endpoints
* Add a parameter for "internal" or "external" 400/500 error handling e.g. vi next(err)
* Status Code handling - currently 200, 204, 400 and 500 is created
we need a @Responses attribute to tag the controllers
* Error Object handling
* Maybe give access to req/res to the Controller e.g. via attributes or constructor?
* Support dependency injection for the constroller creation in the routes file

# angular2.client
# angular.client

* Support Status Codes
* Error Object handling
Expand Down
3 changes: 1 addition & 2 deletions lib/actions/addgen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ export class AddGenerator {
protected isGeneratorTypeOK(): boolean {
let arr: string[] = [
'sequelize.ts.dal',
'express.ts.routes',
'angular2.client',
'angular.client',
'unirest.ts.client',
'android.ormlite.dal',
'android.retrofit.client'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ const fs = require('fs');
const process = require('process');

import { GeneratorConfigBasic } from '../../persistance/generatorconfig.basic';
import { GeneratorConfigExpressTSRoutes } from '../../persistance/generatorconfig.express.ts.routes';
import { GeneratorConfigSequelizeTSDal } from '../../persistance/generatorconfig.sequelize.ts.dal';
import { GeneratorConfigAndroidRetrofitClient, AndroidRetrofitFilter } from '../../persistance/generatorconfig.android.retrofit.client';

Expand All @@ -24,7 +23,6 @@ import { AndroidRetrofitJavaMapping } from './android.retrofit.java.mapping';

export class AndroidRetrofitClientGenerator extends BaseGenerator {
protected generatorConfig: GeneratorConfigAndroidRetrofitClient;
protected parentGeneratorConfig: GeneratorConfigExpressTSRoutes;
protected metadataSymbolTable: MetadataSymbolTable;
protected dbSymbolTable: DBSymbolTable;

Expand Down Expand Up @@ -55,7 +53,6 @@ export class AndroidRetrofitClientGenerator extends BaseGenerator {
type: type,
active: true,
targetDir: './unirest-ts-client',
parentServerGeneratorConfigName: 'express.ts.routes',
cleanTargetDir: false,
createProject: false,
projectName: 'unirest-ts-client',
Expand All @@ -68,8 +65,6 @@ export class AndroidRetrofitClientGenerator extends BaseGenerator {
}

protected async generateCode(): Promise<boolean> {
this.parentGeneratorConfig = <any>BaseGenerator.getGeneratorByNameFromString
(this.nicassaJson, this.generatorConfig.parentServerGeneratorConfigName);

this.metadataSymbolTable = MetadataSymbolTableReader.readFromJsonString(this.nicassaJson);
this.setLengthToMetaData();
Expand Down
172 changes: 172 additions & 0 deletions lib/generator/angular.client/angular.client.generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { GeneratorConfigBasic } from '../../persistance/generatorconfig.basic';
import { GeneratorConfigAngularClient, AngularClientFilter } from '../../persistance/generatorconfig.angular.client';

import { ApiParser } from '../../swagger/apiparser.class';
import { ApiDescription } from '../../swagger/entites/apidesciption.class';
import { ControllerType } from '../../swagger/entites/controllertype.class';
import { ComplexType } from '../../swagger/entites/complextype.class';


import { FileManger } from '../filemanager';
import { BaseGenerator } from '../basegenerator';
import { RenderTemplate } from '../rendertemplate';

import { SymbolNameMapper } from '../symbolnamemapper';

export class AngularClientGenerator extends BaseGenerator {
protected generatorConfig: GeneratorConfigAngularClient;

constructor(generatorConfigBasic: GeneratorConfigBasic, nicassaJson: string) {
super(generatorConfigBasic, nicassaJson);
this.generatorConfig = <GeneratorConfigAngularClient>generatorConfigBasic;
if (this.generatorConfig !== undefined && this.generatorConfig !== null) {
if (this.generatorConfig.filter === undefined || this.generatorConfig.filter === null) {
let defaultCfg = this.getDefaultConfig('');
this.generatorConfig.filter = defaultCfg.filter;
}
}
this.templateDir = __dirname + '/templates';
}

public getDefaultConfig(name: string): GeneratorConfigAngularClient {
let angularClientFilter: AngularClientFilter = {
exculdeEntity: [],
exculdeService: [],
onlyEntity: [],
onlyService: []
}

let type = "angular.client";

let result: GeneratorConfigAngularClient = {
name: name,
type: type,
active: true,
swaggerFile: './swagger.json',
customErrorHandler: false,
targetDir: './angular-client',
cleanTargetDir: false,
createProject: false,
projectName: 'angular-client',
ngModuleName: 'AngularClient',
filter: angularClientFilter
};

return result;
}

protected async generateCode(): Promise<boolean> {
let parser = new ApiParser();
let api: ApiDescription = await parser.parseSwaggerFile(this.generatorConfig.swaggerFile);

let createPackageJson: boolean = false;
let createIndex: boolean = false;
let createProject: boolean = this.generatorConfig.createProject;
let createConfiguration: boolean = false;
let createErrorReporter: boolean = false;
let customErrorHandler: boolean = false;
if (createProject) {
createPackageJson = !FileManger.fileExistInProjectDir(this, 'package.json');
createIndex = !FileManger.fileExistInProjectDir(this, 'index.ts');
createConfiguration = !FileManger.fileExistInProjectDir(this, 'configuration.ts');
createErrorReporter = !FileManger.fileExistInProjectDir(this, 'errorreporter.ts');
}
if (this.generatorConfig.customErrorHandler != null && this.generatorConfig.customErrorHandler !== undefined &&
this.generatorConfig.customErrorHandler == true) {
customErrorHandler = true;
}
let projectName = this.generatorConfig.projectName;
if (projectName === undefined || projectName === null) {
projectName = 'undefined';
}
projectName = SymbolNameMapper.titleCase(projectName);
projectName = SymbolNameMapper.headerCase(projectName);
projectName = SymbolNameMapper.lower(projectName);
let ngModuleName = this.generatorConfig.ngModuleName;

let controllers = this.applyControllerFilter(<any>this.generatorConfig.filter, api.controllers);
let complexTypes = this.applyReferenceTypeFilter(<any>this.generatorConfig.filter, api.complexTypes);


let data = {
controllers: controllers,
complexTypes: complexTypes,
projectName: projectName,
ngModuleName: ngModuleName,
customErrorHandler: customErrorHandler
};

// idea from
// https://offering.solutions/blog/articles/2016/02/01/consuming-a-rest-api-with-angular-http-service-in-typescript/

await RenderTemplate.renderTemplate(true, this, 'entities.ts.ejs', data);
//await RenderTemplate.renderTemplate(true, this, 'services.ts.ejs', data);
//await RenderTemplate.renderTemplate(createPackageJson, this, 'package.json.ejs', data);
//await RenderTemplate.renderTemplate(createIndex, this, 'index.ts.ejs', data);
//await RenderTemplate.renderTemplate(createProject, this, 'generated.exports.ts.ejs', data);
//await RenderTemplate.renderTemplate(createConfiguration, this, 'configuration.ts.ejs', data);
//await RenderTemplate.renderTemplate(createErrorReporter, this, 'errorreporter.ts.ejs', data);
//await RenderTemplate.renderTemplate(true, this, 'ng.module.ts.ejs', data);

return await true;
}

// reference - if a custom mapping is implemented
/*
protected setTypeMapper(api: ApiDescription) {
for (let k = 0; k < api.complexTypes.length; k++) {
let type: ComplexType = api.complexTypes[k];
for (let p = 0; p < type.properties.length; p++) {
let prop = type.properties[p];
prop.getMappedType = (kind: string) => {
console.log('trace');
return prop.type;
}
}
}
for (let k = 0; k < api.controllers.length; k++) {
let controller: ControllerType = api.controllers[k];
for (let r = 0; r < controller.routes.length; r++) {
let route = controller.routes[r];
for (let p = 0; p < route.parameter.length; p++) {
let parameter = route.parameter[p];
parameter.getMappedType = (kind: string) => {
console.log('trace');
return parameter.type;
}
}
for (let m = 0; m < route.response.length; m++) {
let response = route.response[m];
response.getMappedType = (kind: string) => {
console.log('trace');
return response.type;
}
}
}
}
}
*/

protected applyControllerFilter(filter: AngularClientFilter, controllers: ControllerType[]): ControllerType[] {
if (filter === undefined || filter === null) {
return controllers;
}

if (controllers === undefined || controllers === null || controllers.length === 0) {
return controllers;
}
console.log('applyControllerFilter not implemented');
return controllers;
}

protected applyReferenceTypeFilter(filter: AngularClientFilter, referenceTypes: ComplexType[]): ComplexType[] {
if (referenceTypes === undefined || referenceTypes === null || referenceTypes.length === 0) {
return referenceTypes;
}
console.log('applyReferenceTypeFilter not implemented');
return referenceTypes;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,29 @@ const fs = require('fs');
const process = require('process');

import { GeneratorConfigBasic } from '../../persistance/generatorconfig.basic';
import { GeneratorConfigExpressTSRoutes } from '../../persistance/generatorconfig.express.ts.routes';
import { GeneratorConfigSequelizeTSDal } from '../../persistance/generatorconfig.sequelize.ts.dal';
import { GeneratorConfigAngular2Client, Angular2ClientFilter } from '../../persistance/generatorconfig.angular2.client';
import { GeneratorConfigAngularClient, AngularClientFilter } from '../../persistance/generatorconfig.angular.client';

import { FileManger } from '../filemanager';
import { BaseGenerator } from '../basegenerator';
import { RenderTemplate } from '../rendertemplate';

import { MetadataSymbolTable } from '../symboltable/metadata/metadatasymboltable';
import { ControllerSymbol } from '../symboltable/metadata/controllersymbol';
import { ReferenceTypeSymbol } from '../symboltable/metadata/referencetypesymbol';
import { MetadataSymbolTableReader } from '../symboltable/metadata/metadatasymboltable.reader';

import { SymbolNameMapper } from '../symbolnamemapper';
import { DBSymbolTable } from '../symboltable/db/dbsymboltable';
import { DBSymbolTableReader } from '../symboltable/db/dbsymboltable.reader';
import { SequelizeTsDalTypeMapper } from '../sequelize.ts.dal/sequelize.ts.dal.typemapper.class';
import { SequelizeTypescriptMapping } from '../sequelize.ts.dal/sequelize.typescript.mapping';

export class Angular2ClientGenerator extends BaseGenerator {
protected generatorConfig: GeneratorConfigAngular2Client;
export class AngularClientGenerator extends BaseGenerator {
protected generatorConfig: GeneratorConfigAngularClient;
protected parentGeneratorConfig: GeneratorConfigExpressTSRoutes;
protected metadataSymbolTable: MetadataSymbolTable;
protected dbSymbolTable: DBSymbolTable;

constructor(generatorConfigBasic: GeneratorConfigBasic, nicassaJson: string) {
super(generatorConfigBasic, nicassaJson);
this.generatorConfig = <GeneratorConfigAngular2Client>generatorConfigBasic;
this.generatorConfig = <GeneratorConfigAngularClient>generatorConfigBasic;
if (this.generatorConfig !== undefined && this.generatorConfig !== null) {
if (this.generatorConfig.filter === undefined || this.generatorConfig.filter === null) {
let defaultCfg = this.getDefaultConfig('');
Expand All @@ -39,28 +34,28 @@ export class Angular2ClientGenerator extends BaseGenerator {
this.templateDir = __dirname + '/templates';
}

public getDefaultConfig(name: string): GeneratorConfigAngular2Client {
let angular2ClientFilter: Angular2ClientFilter = {
public getDefaultConfig(name: string): GeneratorConfigAngularClient {
let angularClientFilter: AngularClientFilter = {
exculdeEntity: [],
exculdeService: [],
onlyEntity: [],
onlyService: []
}

let type = "angular2.client";
let type = "angular.client";

let result: GeneratorConfigAngular2Client = {
let result: GeneratorConfigAngularClient = {
name: name,
type: type,
active: true,
customErrorHandler: false,
targetDir: './angular2-client',
targetDir: './angular-client',
parentServerGeneratorConfigName: 'express.ts.routes',
cleanTargetDir: false,
createProject: false,
projectName: 'angular2-client',
ngModuleName: 'Angular2Client',
filter: angular2ClientFilter
projectName: 'angular-client',
ngModuleName: 'AngularClient',
filter: angularClientFilter
};

return result;
Expand Down Expand Up @@ -126,7 +121,7 @@ export class Angular2ClientGenerator extends BaseGenerator {
}


protected applyControllerFilter(filter: Angular2ClientFilter, controllers: ControllerSymbol[]): ControllerSymbol[] {
protected applyControllerFilter(filter: AngularClientFilter, controllers: ControllerSymbol[]): ControllerSymbol[] {
if (filter === undefined || filter === null) {
return controllers;
}
Expand Down Expand Up @@ -161,7 +156,7 @@ export class Angular2ClientGenerator extends BaseGenerator {
return result;
}

protected applyReferenceTypeFilter(filter: Angular2ClientFilter, referenceTypes: ReferenceTypeSymbol[]): ReferenceTypeSymbol[] {
protected applyReferenceTypeFilter(filter: AngularClientFilter, referenceTypes: ReferenceTypeSymbol[]): ReferenceTypeSymbol[] {
if (referenceTypes === undefined || referenceTypes === null || referenceTypes.length === 0) {
return referenceTypes;
}
Expand Down
26 changes: 26 additions & 0 deletions lib/generator/angular.client/templates/entities.ts.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* tslint:disable:max-line-length */
////////////////////////////////////////////////////////////////////
//
// GENERATED CLASS
//
// DO NOT EDIT
//
////////////////////////////////////////////////////////////////////


<%complexTypes.forEach(function(type){
%><%if(type.type !== type.name) {
%>// mapped from <%- type.name %>
<%}%>export interface <%- type.type%> {<%
type.properties.forEach(function(prop){%><%
if(prop.isMap) {%>
[key: string]<%
}else{%>
<%- prop.name%><%if(!prop.isRequired) {
%>?<%}%><%}
%>: <%- prop.getMappedType('TypeScript')
%><%if(prop.isArray) {%>[]<%}%>;<%
}); %>
};

<%}); %>
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import { ErrorReporter } from './errorreporter';


import {<%
referenceTypes.forEach(function(refType){%>
<%- refType.name%>,<%}
complexTypes.forEach(function(type){%>
<%- type.name%>,<%}
);%>
} from './entities';
<%controllers.forEach(function(ctrl){
Expand Down
18 changes: 0 additions & 18 deletions lib/generator/angular2.client/templates/entities.ts.ejs

This file was deleted.

Loading

0 comments on commit 85833d0

Please sign in to comment.