0.0.6 • Published 4 years ago

routing-controllers-openapi-extended v0.0.6

Weekly downloads
11
License
MIT
Repository
github
Last release
4 years ago

routing-controllers-openapi-extended

Build Status

Swagger v2 and OpenAPI v3 schema generation using beautiful typescript decorators.

Table of Contents

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 operation
  • description String - used to specify description information about operation
  • operationId String - used to specify / override operation id about operation
  • consumes Array<string> - used to specify consumer list
  • produces Array<string> - used to specify produces list
  • security 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 language
  • snippet 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 name
  • in String - used to specify type of parameter
  • description String - used to specify description
  • type String - used to data type of the parameter
  • required Boolean - used to required flag
  • schema Object - used to specify schema of the data type
  • examples Object - used to specify examples
  • example any - used to specify sample example
  • default any - used to specify default value
  • format 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 be body 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 or String - used to specify name
  • description String - used to specify description
  • type String - used to data type of the parameter
  • schema Function or String - used to specify schema of the data type
  • examples Object - used to specify examples
  • headers 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 type
  • description String - Used to specify description of the property
  • name String - Used to specify explicit name of the property, By default this will get the property name
  • itemType Function - Used to specify item data type if it is an array. This is mandatory property if the property type is Array
  • required Boolean - Used to specify whether it is required property or not
  • example 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

References