Package Exports
- swagger-ts-generator
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (swagger-ts-generator) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Swagger TypeScript code generator
Node module to generate TypeScript code for Angular (2 and above) based on Webapi meta data in Swagger v2 format.
Use it in combination with the sibling package angular-swagger-form-field to implement reactive forms.
See angular-swagger-form-field-sample for a sample how to use the generated classes.
Setup
Download the moduel with npm:
npm install --save-dev swagger-ts-generator
Usage in Gulp
gulp.config
Create a gulp.config
file with the settings you want:
'use strict';
module.exports = config();
function config() {
var root = './src/';
var srcAppFolder = root + 'app/';
var folders = {
// root
root: root,
// sources
srcWebapiFolder: srcAppFolder + 'models/webapi/',
srcLanguagesFolder: root + 'assets/i18n/',
// swagger
swaggerFolder: root + 'swagger/',
}
var files = {
swaggerJson: 'swagger.json',
//swaggerJson: 'swagger-zib.json',
//swaggerJson: 'swagger-zib-v2.json',
}
var swagger = {
url: 'http://petstore.swagger.io/v2/swagger.json',
//url: 'http://127.0.0.1/ZIB.WebApi.v2/swagger/docs/v1',
swaggerFile: folders.swaggerFolder + files.swaggerJson,
swaggerFolder: folders.swaggerFolder,
swaggerTSGeneratorOptions: {
modelFolder: folders.srcWebapiFolder,
enumTSFile: folders.srcWebapiFolder + 'enums.ts',
enumLanguageFiles: [
folders.srcLanguagesFolder + 'nl.json',
folders.srcLanguagesFolder + 'en.json',
],
modelModuleName: 'webapi.models',
enumModuleName: 'webapi.enums',
enumRef: './enums',
namespacePrefixesToRemove: [
],
typeNameSuffixesToRemove: [
]
}
}
var config = {
root: root,
files: files,
swagger: swagger,
}
return config;
}
gulpfile.js
Create a gulpfile.js
:
/*global __dirname */
'use strict';
var gulp = require('gulp');
var $ = require('gulp-load-plugins')({ lazy: true });
var args = require('yargs').argv;
var swaggerTSGenerator = require('swagger-ts-generator');
var request = require('request');
var source = require('vinyl-source-stream');
var config = require('./gulp.config');
//--------------- gulp tasks ---------------
gulp.task('default', ['show-help']); // Set default gulp tasks
gulp.task('show-help', $.taskListing);
gulp.task('gen', ['gen-webapi']);
gulp.task('gen-webapi', ['gen-webapi-download-swagger'], genWebapi);
gulp.task('gen-webapi-download-swagger', genWebapiDownloadSwagger);
//--------------- generator tasks ---------------
function genWebapi(done) {
swaggerTSGenerator.generateTSFiles(config.swagger.swaggerFile, config.swagger.swaggerTSGeneratorOptions);
done();
}
function genWebapiDownloadSwagger(done) {
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // Ignore 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' authorization error
return request
.get({
url: config.swagger.url,
headers: {
'User-Agent': 'request',
'content-type': 'application/json'
}
})
.pipe(customPlumber('Error gen-webapi-autorest'))
.pipe(source(config.files.swaggerJson))
.pipe($.streamify($.jsbeautifier(/*{ mode: 'VERIFY_AND_WRITE' }*/)))
.pipe(gulp.dest(config.folders.swaggerFolder));
}
function customPlumber(errTitle) {
return $.plumber({
errorHandler: $.notify.onError({
// Customizing error title
title: errTitle || "Error running Gulp",
message: "Error: <%= error.message %>",
sound: "Glass"
})
});
}
function log(msg) {
$.util.log($.util.colors.yellow(msg));
}
Execute the gulp task(s)
Download the swagger file and generate the code:
gulp gen
Generated files
validators.ts
The generated validators.ts is fixed (its always generated regardless of the Swagger). It contains some extra validators to implement validation rules for the Swagger which are not part of the standard Angular validators:
maxValueValidator
minValueValidator
base-model.ts
The generated base-model.ts is fixed (its always generated regardless of the Swagger). It contains the base class for all generated models. The next members can be used in your own software:
/**
* use $formGroup in angular's formBuilder to make a model driven (reactive) form.
* this.form = this.formBuilder.group({
* pet: this.pet.$formGroup,
* });
*/
$formGroup: FormGroup;
/**
* add one or more additional validators to the control
* @param key Name of the control (is the same as the name of the attached model property)
* @param validators Validator(s) to add to the control
*/
addValidatorToControl(controlName: string, validators: ValidatorFn | ValidatorFn[]) {
...
}
}
*.model.ts
For each definition in the Swagger an Interface and a Class are generated.
The class contains the $FormGroup
property to be used in the Angular FormBuilder to make a model driven form.
The controls in the FormGroup
contain the validators which implement the validation rules from the Swagger defnition.
Properties of an enum type are generated referencing this type which are generated in the next section.
This is an example of a generated TypeScript file with one model (definition) from the Swagger file:
// THIS IS GENERATED CODE. DO NOT CHANGE MANUALLY!
/* tslint:disable */
import { Validators, FormControl, FormGroup, FormArray, ValidatorFn } from '@angular/forms';
import { minValueValidator, maxValueValidator } from './validators';
import { BaseModel } from './base-model';
import { type } from './enums';
import { gender } from './enums';
import { Address } from './address.model';
import { Veterinarian } from './veterinarian.model';
import { Tag } from './tag.model';
import { NullableOrEmpty } from './nullable-or-empty.model';
export interface IPet {
name: string;
age?: number;
dob?: Date;
type: type;
gender?: gender;
address?: Address;
vet?: Veterinarian;
tags?: Array<Tag>;
isFavorate?: boolean;
testDate?: NullableOrEmpty<Date>;
primitiveArray?: Array<string>;
}
export class Pet extends BaseModel implements IPet {
name: string;
age: number;
dob: Date;
type: type;
gender: gender;
address: Address;
vet: Veterinarian;
tags: Array<Tag>;
isFavorate: boolean;
testDate: NullableOrEmpty<Date>;
primitiveArray: Array<string>;
/**
* constructor
* @param values Can be used to set a webapi response to this newly constructed model
*/
constructor(values?: any) {
super();
this.address = new Address();
this.vet = new Veterinarian();
this.tags = new Array<Tag>();
this.testDate = new NullableOrEmpty<Date>();
this.primitiveArray = new Array<string>();
if (values) {
this.setValues(values);
}
}
/**
* set the values.
* @param values Can be used to set a webapi response to this newly constructed model
*/
setValues(values: any): void {
this.name = values.name;
this.age = values.age;
this.dob = values.dob;
this.type = values.type;
this.gender = values.gender;
this.address.setValues(values.address);
this.vet.setValues(values.vet);
this.fillModelArray<Tag>(this, 'tags', values.tags, Tag);
this.isFavorate = values.isFavorate;
this.testDate.setValues(values.testDate);
this.fillModelArray<string>(this, 'primitiveArray', values.primitiveArray);
}
protected getFormGroup(): FormGroup {
if (!this._formGroup) {
this._formGroup = new FormGroup({
name: new FormControl(this.name, [Validators.required, Validators.minLength(4), Validators.pattern('^[a-zA-Z0-9- ]+$'), ]),
age: new FormControl(this.age),
dob: new FormControl(this.dob),
type: new FormControl(this.type, [Validators.required, ]),
gender: new FormControl(this.gender),
address: this.address.$formGroup,
vet: this.vet.$formGroup,
tags: new FormArray([]),
isFavorate: new FormControl(this.isFavorate),
testDate: this.testDate.$formGroup,
primitiveArray: new FormArray([]),
});
// generate FormArray control elements
this.fillFormArray<Tag>('tags', this.tags, Tag);
this.fillFormArray<string>('primitiveArray', this.primitiveArray);
}
return this._formGroup;
}
}
enums.ts
This is een exerpt from a generated TypeScript file with enums.
// THIS IS GENERATED CODE. DO NOT CHANGE MANUALLY!
/* tslint:disable */
// generate enum based on strings instead of numbers
// (see https://blog.rsuter.com/how-to-implement-an-enum-with-string-values-in-typescript/)
export enum type {
cat = <any>"cat",
dog = <any>"dog",
bird = <any>"bird",
whale = <any>"whale",
}
export enum gender {
unknown = <any>"unknown",
male = <any>"male",
female = <any>"female",
}
export enum hairColor {
red = <any>"red",
blond = <any>"blond",
brown = <any>"brown",
black = <any>"black",
white = <any>"white",
gray = <any>"gray",
}
/**
* bundle of all enums for databinding to options, radio-buttons etc.
* usage in component:
* import { AllEnums, minValueValidator, maxValueValidator } from '../../models/webapi';
*
* @Component({
* ...
* })
* export class xxxComponent implements OnInit {
* allEnums = AllEnums;
* ...
* ngOnInit() {
* this.allEnums = AllEnums.instance;
* }
* }
*/
export class AllEnums {
private static _instance: AllEnums = new AllEnums();
constructor() {
if (AllEnums._instance) {
throw new Error("Error: Instantiation failed: Use AllEnums.instance instead of new");
}
AllEnums._instance = this;
}
static get instance(): AllEnums {
return AllEnums._instance;
}
type = type;
gender = gender;
hairColor = hairColor;
}
Normally enums are numbers based in TypeScript. In out Webapi's whe use stringbased Enums.
The thrick with cat =
is used to make the TypeScript enums string based.<any>
"cat"
enums language files
Each new enum value is added to the given enumLanguageFile(s). Enum values already present are left intact.
{
"type": "-------ENUM-TYPE-------",
"cat": "kat",
"dog": "hond",
"bird": "vogel",
"whale": "whale",
"gender": "-------ENUM-TYPE-------",
"unknown": "onbekend",
"male": "man",
"female": "vrouw",
"hairColor": "-------ENUM-TYPE-------",
"red": "rood",
"blond": "blond",
"brown": "bruin",
"black": "zwart",
"white": "wit",
"gray": "grijs"
}
index.ts
This barrel file contains references to all generated files.