npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

routing-controllers-openapi-extended

v0.0.6

Published

Runtime Swagger v2 / OpenAPI v2 specification generation for routing-controllers

Downloads

73

Readme

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