All Projects → epiphone → Routing Controllers Openapi

epiphone / Routing Controllers Openapi

Licence: mit
Runtime OpenAPI v3 schema generation for routing-controllers.

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Routing Controllers Openapi

Generator Express No Stress
🚂 A Yeoman generator for Express.js based 12-factor apps and apis
Stars: ✭ 534 (+214.12%)
Mutual labels:  openapi, openapi3, expressjs
Express Openapi Validator
🦋 Auto-validates api requests, responses, and securities using ExpressJS and an OpenAPI 3.x specification
Stars: ✭ 436 (+156.47%)
Mutual labels:  openapi, openapi3, expressjs
Generator Express No Stress Typescript
🚄 A Yeoman generator for Express.js based 12-factor apps and apis using Typescript
Stars: ✭ 297 (+74.71%)
Mutual labels:  openapi, openapi3, expressjs
Express Jsdoc Swagger
Swagger OpenAPI 3.x generator
Stars: ✭ 69 (-59.41%)
Mutual labels:  openapi, openapi3, expressjs
Api2html
A CLI tool to transform Swagger/OpenAPI/AsyncAPI docs to beautiful HTML pages via Shins/Widdershins.
Stars: ✭ 103 (-39.41%)
Mutual labels:  openapi, openapi3
Kaizen Openapi Editor
Eclipse Editor for the Swagger-OpenAPI Description Language
Stars: ✭ 97 (-42.94%)
Mutual labels:  openapi, openapi3
Openapi Psr7 Validator
It validates PSR-7 messages (HTTP request/response) against OpenAPI specifications
Stars: ✭ 168 (-1.18%)
Mutual labels:  openapi, openapi3
Quenya
Quenya is a framework to build high-quality REST API applications based on extended OpenAPI spec
Stars: ✭ 121 (-28.82%)
Mutual labels:  openapi, openapi3
Openapivalidators
Use Jest or Chai to assert that HTTP responses satisfy an OpenAPI spec
Stars: ✭ 77 (-54.71%)
Mutual labels:  openapi, openapi3
Fastapi Plugins
FastAPI framework plugins
Stars: ✭ 104 (-38.82%)
Mutual labels:  openapi, openapi3
Http Router
🎉 Release 2.0 is released! Very fast HTTP router for PHP 7.1+ (incl. PHP8 with attributes) based on PSR-7 and PSR-15 with support for annotations and OpenApi (Swagger)
Stars: ✭ 124 (-27.06%)
Mutual labels:  openapi, openapi3
Rororo
Implement aiohttp.web OpenAPI 3 server applications with schema first approach.
Stars: ✭ 95 (-44.12%)
Mutual labels:  openapi, openapi3
Swurg
Parse OpenAPI documents into Burp Suite for automating OpenAPI-based APIs security assessments (approved by PortSwigger for inclusion in their official BApp Store).
Stars: ✭ 94 (-44.71%)
Mutual labels:  openapi, openapi3
Tcases
A model-based test case generator
Stars: ✭ 103 (-39.41%)
Mutual labels:  openapi, openapi3
Openapi Viewer
Browse and test a REST API described with the OpenAPI 3.0 Specification
Stars: ✭ 82 (-51.76%)
Mutual labels:  openapi, openapi3
Openapi Core
OpenAPI core
Stars: ✭ 119 (-30%)
Mutual labels:  openapi, openapi3
Rapipdf
PDF generation from OpenAPI / Swagger Spec
Stars: ✭ 132 (-22.35%)
Mutual labels:  openapi, openapi3
Restful React
A consistent, declarative way of interacting with RESTful backends, featuring code-generation from Swagger and OpenAPI specs 🔥
Stars: ✭ 1,814 (+967.06%)
Mutual labels:  openapi, openapi3
Prance
Resolving Swagger/OpenAPI 2.0 and 3.0 Parser
Stars: ✭ 133 (-21.76%)
Mutual labels:  openapi, openapi3
Openapi Spring Webflux Validator
🌱 A friendly kotlin library to validate API endpoints using an OpenApi 3.0 and Swagger 2.0 specification
Stars: ✭ 67 (-60.59%)
Mutual labels:  openapi, openapi3

routing-controllers-openapi

codecov npm version

Runtime OpenAPI v3 schema generation for routing-controllers.

Installation

npm install --save routing-controllers-openapi

Usage

import { getMetadataArgsStorage } from 'routing-controllers'
import { routingControllersToSpec } from 'routing-controllers-openapi'

// Define your controllers as usual:

@JsonController('/users')
class UsersController {
  @Get('/:userId')
  getUser(@Param('userId') userId: string) {
    // ...
  }

  @HttpCode(201)
  @Post('/')
  createUser(@Body() body: CreateUserBody) {
    // ...
  }
}

// Generate a schema:

const storage = getMetadataArgsStorage()
const spec = routingControllersToSpec(storage)
console.log(spec)

prints out the following specification:

{
  "components": {
    "schemas": {}
  },
  "info": {
    "title": "",
    "version": "1.0.0"
  },
  "openapi": "3.0.0",
  "paths": {
    "/users/{userId}": {
      "get": {
        "operationId": "UsersController.getUser",
        "parameters": [
          {
            "in": "path",
            "name": "userId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {}
            },
            "description": "Successful response"
          }
        },
        "summary": "List users",
        "tags": ["Users"]
      }
    },
    "/users/": {
      "post": {
        "operationId": "UsersController.createUser",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUserBody"
              }
            }
          },
          "description": "CreateUserBody",
          "required": false
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {}
            },
            "description": "Successful response"
          }
        },
        "summary": "Create user",
        "tags": ["Users"]
      }
    }
  }
}

Check /sample for a complete sample application.

Configuration

routingControllersToSpec has the following type signature:

export function routingControllersToSpec(
  storage: MetadataArgsStorage,
  routingControllerOptions: RoutingControllersOptions = {},
  additionalProperties: Partial<OpenAPIObject> = {}
): OpenAPIObject

routingControllerOptions refers to the options object used to configure routing-controllers. Pass in the same options here to have your routePrefix and defaults options reflected in the resulting OpenAPI spec.

additionalProperties is a partial OpenAPI object that gets merged into the result spec. You can for example set your own info or components keywords here.

Validation classes

Use class-validator-jsonschema to convert your validation classes into OpenAPI-compatible schemas:

import { validationMetadatasToSchemas } from 'class-validator-jsonschema'

// ...

const schemas = validationMetadatasToSchemas({
  refPointerPrefix: '#/components/schemas/',
})

const spec = routingControllersToSpec(storage, routingControllerOptions, {
  components: { schemas },
  info: { title: 'My app', version: '1.2.0' },
})

Decorating with additional keywords

Use the @OpenAPI decorator to supply your actions with additional keywords:

import { OpenAPI } from 'routing-controllers-openapi'

@JsonController('/users')
export class UsersController {
  @Get('/')
  @OpenAPI({
    description: 'List all available users',
    responses: {
      '400': {
        description: 'Bad request',
      },
    },
  })
  listUsers() {
    // ...
  }
}

The parameter object consists of any number of properties from the Operation object. These properties are then merged into the spec, overwriting any existing values.

Alternatively you can call @OpenAPI with a function of type (source: OperationObject, route: IRoute) => OperationObject, i.e. a function receiving the existing spec as well as the target route, spitting out an updated spec. This function parameter can be used to implement for example your own merging logic or custom decorators.

Multiple @OpenAPI decorators

A single handler can be decorated with multiple @OpenAPIs. Note though that since decorators are applied top-down, any possible duplicate keys are overwritten by subsequent decorators:

  @OpenAPI({
    summary: 'This value will be overwritten!',
    description: 'This value will remain'
  })
  @OpenAPI({
    summary: 'This value will remain'
  })
  listUsers() {
    // ...
  }

Multiple @OpenAPIs are merged together with lodash/merge which has a few interesting properties to keep in mind when it comes to arrays. Use the function parameter described above when strict control over merging logic is required.

Class @OpenAPI decorator

Using @OpenAPI on the controller class effectively applies given spec to each class method. Method-level @OpenAPIs are merged into class specs, with the former having precedence:

@OpenAPI({
  security: [{ basicAuth: [] }], // Applied to each method
})
@JsonController('/users')
export class UsersController {
  // ...
}

Annotating response schemas

Extracting response types automatically in runtime isn't currently allowed by Typescript's reflection system. Specifically the problem is that routing-controllers-openapi can't unwrap generic types like Promise or Array: see e.g. here for discussion. As a workaround you can use the @ResponseSchema decorator to supply the response body schema:

import { ResponseSchema } from 'routing-controllers-openapi'

@JsonController('/users')
export class UsersController {
  @Get('/:id')
  @ResponseSchema(User)
  getUser() {
    // ...
  }
}

@ResponseSchema takes as an argument either a class-validator class or a plain string schema name. You can also supply an optional secondary options argument:

  @Post('/')
  @ResponseSchema(User, {
    contentType: 'text/csv',
    description: 'A list of created user objects',
    isArray: true
    statusCode: '201'})
  createUsers() {
    // ...
  }

contentType and statusCode default to routing-controller's @ContentType and @HttpCode values. To specify a response schema of an array, set options.isArray as true. You can also annotate a single handler with multiple ResponseSchemas to specify responses with different status codes.

Note that when using @ResponseSchema together with @JSONSchema, the outer decorator will overwrite keys of inner decorators. So in the following example, information from @ResponseSchema would be overwritten by @JSONSchema:

@JSONSchema({responses: {
  '200': {
    'content': {
      'application/json': {
        schema: {
          '$ref': '#/components/schemas/Pet'
        }
      }
    ]
  }
}})
@ResponseSchema(SomeResponseObject)
handler() { ... }

Multiple ResponseSchemas

Multiple ResponseSchemas with different status codes are supported as follows.

@ResponseSchema(Response1)
@ResponseSchema(Response2, {statusCode: '400'})

In case of multiple ResponseSchemas being registered with the same status code, we resolve them using the oneOf operator.

@ResponseSchema(Response1)
@ResponseSchema(Response2)

will generate

"200": {
  "content": {
    "application/json":{
      "schema": {
        "oneOf": [
          {$ref: "#/components/schemas/Response1"},
          {$ref: "#/components/schemas/Response2"}
        ]
      }
    }
  }
}

Supported features

  • @Controller/@JsonController base route and default content-type
  • options.routePrefix
  • @Get, @Post and other action decorators
  • Parse path parameters straight from path strings and optionally supplement with @Param decorator
    • Regex and optional path parameters (e.g. /users/:id(\d+)/:type?) are also supported
  • @QueryParam and @QueryParams
  • @HeaderParam and @HeaderParams
  • @Body and @BodyParam
  • Parse response keywords from @HttpCode and @ContentType values
  • Global options.defaults.paramOptions.required option and local override with {required: true} in decorator params
  • Parse summary, operationId and tags keywords from controller/method names

Future work

Feel free to submit a PR!

Related projects

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].