routing-controllers-openapi-extended
v0.0.6
Published
Runtime Swagger v2 / OpenAPI v2 specification generation for routing-controllers
Downloads
51
Maintainers
Readme
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
summary
[String
] - used to specify summary information about operationdescription
[String
] - used to specify description information about operationoperationId
[String
] - used to specify / override operation id about operationconsumes
[Array<string>
] - used to specify consumer listproduces
[Array<string>
] - used to specify produces listsecurity
[any
] - 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
lang
[String
] - used to specify languagesnippet
[String
] - used to specify sample code
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
name
[String
] - used to specify namein
[String
] - used to specify type of parameterdescription
[String
] - used to specify descriptiontype
[String
] - used to data type of the parameterrequired
[Boolean
] - used to required flagschema
[Object
] - used to specify schema of the data typeexamples
[Object
] - used to specify examplesexample
[any
] - used to specify sample exampledefault
[any
] - used to specify default valueformat
[any
] - 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.
name
value should match with the@Param
name
for query and path parameter entiries.
name
value should bebody
for@Body
type 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
statusCode
[Number
orString
] - used to specify namedescription
[String
] - used to specify descriptiontype
[String
] - used to data type of the parameterschema
[Function
orString
] - used to specify schema of the data typeexamples
[Object
] - used to specify examplesheaders
[Object
] - 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
enabled
[Boolean
] - 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
type
[Function
] - Used to specify explicit type, By default this will get the declared typedescription
[String
] - Used to specify description of the propertyname
[String
] - Used to specify explicit name of the property, By default this will get the property nameitemType
[Function
] - Used to specify item data type if it is an array. This is mandatory property if the property type isArray
required
[Boolean
] - Used to specify whether it is required property or notexample
[any
] - 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