routing-controllers-openapi-extended v0.0.6
routing-controllers-openapi-extended
Swagger v2 and OpenAPI v3 schema generation using beautiful typescript decorators.
Table of Contents
- About
- Installation
- Usage
- Available API's
- Available Decorators
- Next goals
- References
About
This node module will extract much information about operations, parameters, responses from routing-controller decorator methods. Additinally it provides some more typescript decorators which will be useful to add user defined custom properties to the generated swagger specification. This library uses class-validator decorator to generate schema definitions currently.
Installation
npm i routing-controllers-openapi-extended
Usage
// UserController.ts
import { Body, Get, JsonController, Param, Post } from 'routing-controllers'
import { OperationInfo, ResponseEntry, Parameters, Model, Property } from 'routing-controllers-openapi-extended';
@Model()
export class CreateUserBody {
@Property({ description: 'Name of the user'})
name: string
@Property({ itemType: String, description: 'List of user hobbies' })
hobbies: string[]
}
@JsonController('/users')
export class UsersController {
@Get('/:id')
@OperationInfo({ summary: 'Get user by Id', description: 'Get user by Id' })
@ResponseEntry({ statusCode: 200, schema: CreateUserBody, description: 'Retrived user by the supplied user id', examples: { 'applications/json': { userId: '<sample data>' } } })
getOne(@Param('id') id: number) {
return { name: 'User #' + id }
}
@Post('/:id')
@Parameters([
{ name: 'Authorization', in: 'header', type: 'string', description: 'Used to attached token', required: true, default: 'Basic <token>' },
{ name: 'body', description: 'Detailed information about creat user body', required: true },
{ name: 'id', description: 'Detailed information about id parameter' },
])
@ResponseEntry({ statusCode: 200, schema: CreateUserBody, description: 'Information about created user', examples: { 'applications/json': { userId: '<sample data>' } } })
createUser(@Body() body: CreateUserBody, @Param('id') id: string) {
return { ...body, id: 3 }
}
}
// SchemaGenerator.ts:
import 'reflect-metadata'
import { getMetadataArgsStorage } from 'routing-controllers'
import { generateSwagger } from 'routing-controllers-openapi-extended'
import { UsersController, CreateUserBody } from './UsersController'
const spec = generateSwagger({
controllers: [UsersController],
models: [CreateUserBody],
storage: getMetadataArgsStorage(),
}, {
info: {
description: 'Generated by script',
title: 'A sample API',
version: '1.0.0'
}
});
console.log(JSON.stringify(spec, undefined, 2));This will generate below swagger v2 specification:
{
"swagger": "2.0",
"paths": {
"/users/{id}": {
"get": {
"operationId": "UsersController.getOne",
"summary": "Get user by Id",
"tags": [
"Users"
],
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "Retrived user by the supplied user id",
"examples": {
"applications/json": {
"userId": "<sample data>"
}
},
"schema": {
"$ref": "#/definitions/CreateUserBody"
}
}
},
"description": "Get user by Id"
},
"post": {
"operationId": "UsersController.createUser",
"summary": "Create user",
"tags": [
"Users"
],
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"type": "string",
"description": "Detailed information about id parameter"
},
{
"in": "body",
"name": "body",
"required": true,
"schema": {
"$ref": "#/definitions/CreateUserBody"
},
"description": "Detailed information about creat user body"
},
{
"name": "Authorization",
"in": "header",
"type": "string",
"description": "Used to attached token",
"required": true,
"default": "Basic <token>"
}
],
"responses": {
"200": {
"description": "Information about created user",
"examples": {
"applications/json": {
"userId": "<sample data>"
}
},
"schema": {
"$ref": "#/definitions/CreateUserBody"
}
}
}
}
}
},
"definitions": {
"CreateUserBody": {
"type": "object",
"required": [
"name",
"hobbies"
],
"properties": {
"name": {
"type": "string",
"description": "Name of the user"
},
"hobbies": {
"type": "array",
"description": "List of user hobbies",
"items": {
"type": "string"
}
}
}
}
},
"info": {
"description": "Generated by script",
"title": "A sample API",
"version": "1.0.0"
}
}Check /sample for a complete sample application.
Available API's
.generateSwagger({ controllers, models, storage }, additional)
This API will be used to generate swagger 2.0 specifications.
.generateOpenAPI({ controllers, models, storage }, additional)
This API will be used to generate Open API 3.0 configurations.
Available Decorators
@OperationInfo(options)
This is used to specify most of the basic information about each operations.
Available Options
summaryString- used to specify summary information about operationdescriptionString- used to specify description information about operationoperationIdString- used to specify / override operation id about operationconsumesArray<string>- used to specify consumer listproducesArray<string>- used to specify produces listsecurityany- allow user to define their own security specification
Syntax
{
summary?: string;
description?: string;
operationId?: string;
consumes?: Array<string>;
produces?: Array<string>;
security?: any;
}Example
@OperationInfo({ summary: '<summary info>', description: '<detailed info>', operationId: '<unique operation id>' })@CustomEntry(options)
This is used to add all custom properties which may/ may not be specified in swagger sepcification.
Available Options
<any key name>any- entire object will be attached to the specific operation
Syntax
{
[key: string]: any;
}Example
@CustomEntry({ customField: '<values>', 'x-status': '<status>' })@CodeSnippets(options)
This is another kind of custom entry which can be attached to operation sepcification.
Available Options
Syntax
Array<{
lang: string;
snippet: string;
}>Example
@CodeSnippets([{ lang: '<language>', snippet: '<code snippet>' }])@Parameters(options)
This is used to add additional properties to the existing parameter (including query parameter and body parameters). And allow user to attach any header parameters (like pagination, content-type etc).
Available Options
nameString- used to specify nameinString- used to specify type of parameterdescriptionString- used to specify descriptiontypeString- used to data type of the parameterrequiredBoolean- used to required flagschemaObject- used to specify schema of the data typeexamplesObject- used to specify examplesexampleany- used to specify sample exampledefaultany- used to specify default valueformatany- used to specify format value (like int64)<any key name>any- entire object will be attached to the specific operation
Syntax
{
name: string;
in?: 'query' | 'header' | 'path' | 'body' | 'cookie';
description?: string;
type?: string;
required?: boolean;
deprecated?: boolean;
schema?: { $ref: string };
examples?: {
[key: string]: any;
};
example?: any;
default?: any;
format?: any;
[key: string]: any;
};Example
Users shall attach additinal parameters to the existing operation.
@Parameters({ name: 'Authorization', in: 'header', type: 'string', description: 'Used to attached token' required: true, default: 'Basic <token>'})User shall use the same Parameters decorator to override/ amend existing paramters.
namevalue should match with the@Paramnamefor query and path parameter entiries.
namevalue should bebodyfor@Bodytype paramters.@Post('/:id') @Parameters([{ name: 'Authorization', in: 'header', type: 'string', description: 'Used to attached token' required: true, default: 'Basic <token>'}]) @Parameters([ { name: 'body', description: 'Detailed information about creat user body', required: true } ]) @Parameters([ { name: 'id', description: 'Detailed information about id parameter'} ]) createUser(@Body() reqBody: CreateUserBody, @Param('id') id: string) { return { ...body, id: 3 } }
@ResponseEntry(options)
This is used to add responses entry with proper status code and samples to the operation.
Available Options
statusCodeNumberorString- used to specify namedescriptionString- used to specify descriptiontypeString- used to data type of the parameterschemaFunctionorString- used to specify schema of the data typeexamplesObject- used to specify examplesheadersObject- used to specify examples<any key name>any- entire object will be attached to the specific operation
Syntax
{
statusCode: number | string,
description?: string;
type?: string;
schema?: Function | string,
examples?: {
[key: string]: any;
};
example?: any;
headers?: {
[name: string]: {
type: string;
description?: string;
[key: string]: any;
};
};
[key: string]: any;
};Example
Users shall attach responses to the operation.
@ResponseEntry({ statusCode: 200, schema: CreateUserBody, description: 'detailed information about the response' })User shall add more information along with responses like examples, header information. Users shall add more than one responses to the operations.
@ResponseEntry({ statusCode: 200, schema: CreateUserBody, description: 'detailed information about the response', examples: { 'applications/json': { userId: '<sample data>' } } })
@ResponseEntry({ statusCode: 404, schema: ErrorResponse, description: 'details about the error response', examples: { 'applications/json': { erros: [ { message: 'sample error message' }] } } })@Model(options)
This is used to specify model schema which will be considered for schema definition generation.
Available Options
enabledBoolean- used to specify include/ exclude from schema definition generation.Default: true
Syntax
{
enabled: boolean,
}Example
@Model() // This is enabled model@Model({ enabled: true })@Property(options)
This is used to specify the property which is included in the schema definition generation.
Available Options
typeFunction- Used to specify explicit type, By default this will get the declared typedescriptionString- Used to specify description of the propertynameString- Used to specify explicit name of the property, By default this will get the property nameitemTypeFunction- Used to specify item data type if it is an array. This is mandatory property if the property type isArrayrequiredBoolean- Used to specify whether it is required property or notexampleany- Used to specify an example value<any key>any- Used to specify custom properties which needs to attach with property definiiton
Syntax
{
type?: Function;
description?: string;
name?: string;
itemType?: Function;
required?: boolean;
example?: any;
[key: string]: any;
}Example
@Property({ description: 'Name of the user'})@Property({ itemType: String, description: 'List of user hobbies' })Next goals
- Implement Operation decorator to use without routing-controller decorators
- Refactor code to sperate two different data sources
- Implement logging to troubleshot generaiton operation