New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@trapi/swagger

Package Overview
Dependencies
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@trapi/swagger

Generate Swagger files from a decorator APIs.

  • 0.2.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
171
decreased by-16.59%
Maintainers
1
Weekly downloads
 
Created
Source

@trapi/swagger 🚀

main codecov Known Vulnerabilities npm version

This is a tool to generate swagger documentation in json or yml format with a given metadata definition file.

Please read the CHANGELOG.md in the repository for breaking changes.

Table of Contents

Installation

npm install --save @trapi/swagger

Build

You can either build the swagger.yml and swagger.json file by command line or on runtime of your application. The files will be generated in the outputDirectory specified in the SwaggerConfig.

The tsconfig.json file contains the compilerOptions, which are required for this library to work. The compilerOptions could look lke the following example:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@/*": ["src/*"]
        }
    }
}

In case of the above configuration, the library can understand relative imports like import something from '@/something'.

CLI

swagger-generate -c ./swagger-config.json
swagger-generate -c ./swagger-config.js #.js files are also allowed as config files
swagger-generate -c ./swagger-config.json -t true # load {cwd}/tsconfig.json
swagger-generate -c ./swagger-config.json -t false # don't load tsconfig.json
swagger-generate -c ./swagger-config.json -t ./tsconfig.json # load custom tsconfig.json

Where the swagger-config.json file, contains settings about the swagger generation. For example:

{
    "decorator": {
        "useBuildIn": true,
        "useLibrary": ["typescript-rest", "@decorators/express"]
    },
    "swagger": {
        "outputDirectory": "./dist",
        "entryFile": "./tests/data/apis.ts"
    }
}

Runtime

import {Config, generateDocumentation} from "typescript-swagger";

const packageJson = require('package.json');
const tsConfig = require('tsconfig.json');

export const config: Config = {
    decorator: {
        useBuildIn: true,
        useLibrary: ["typescript-rest", "@decorators/express"],
    },
    swagger: {
        yaml: true,
        name: 'API - Documentation',
        description: packageJson.description,
        basePath: '/',
        version: packageJson.version,
        outputDirectory: 'public',
        entryFile: path.join('src', 'controllers', '**', '*.ts'),
        ignore: ['**/node_modules/**'],
        consumes: ['application/json'],
        produces: ['application/json']
    }
}

export async function generateSwaggerDocumentation(): Promise<void> {
    await generateDocumentation(config, tsConfig);
}

Limitations

You can use pretty any type you have declared in your code. The only restriction are types form third party modules.

Also the following built in typescript utility types are supported:

  • NonNullable
  • Omit
  • Partial
  • Readonly
  • Record
  • Required
  • Pick

Usage

General

The documentation will be generated consulting all decorators present on your code.

Which decorator will be used, depends on your swagger-config.json. However, there are some additional information that only can be provided, through some third party decorator or your own defined representations.

To cover all functions the following decorators packs are supported by default:

You can override the used decorator packs in you swagger-config.json.

In the following there are two specific examples in combination with the third party libraries: typescript-rest and @decorators/express.

typescript-rest
import {Path, Accept, GET} from 'typescript-rest';
import {SwaggerTags} from 'typescript-swagger';

interface Person {
    id: number;
    name: string;
    avatar: string;
    password: string;
}

@Path('mypath')
export class MyService {
    @GET
    @SwaggerTags('adminMethod', 'otherTag')
    @Accept('text/html')
    test( ): string {
        return 'OK';
    }

    @GET
    @Path('secondpath')
    test2( @QueryParam('testParam')test?: string ): Pick<Person, 'name' | 'avatar'> {
        return {name: 'OK'};
    }
}
@decorators/express
import {Controller, Get, Query} from '@decorators/express';
import {SwaggerTags} from 'typescript-swagger';

interface Person {
    id: number;
    name: string;
    avatar: string;
    password: string;
}

@Controller('mypath')
export class MyService {
    @Get('')
    @SwaggerTags('adminMethod', 'otherTag')
    test( ): string {
        return res.send('Ok');
    }

    @Get('secondpath')
    test2( @Query('testParam')test?: string ): Pick<Person, 'name' | 'avatar'> {
        return res.json({name: 'OK'});
    }
}

It is also important to notice that all JsDoc (Comments, Tags, ...) provided on your methods, classes, and parameters have influence on the generated swagger file:

@Accept('text/plain')
@Path('mypath')
export class MyService {
    /**
     * This description will be used to describe the get operation of path '/mypath' on the generated swagger
     * @param test And this will describe the parameter test of this same operation
     */
    @GET
    @Path('secondpath')
    test2( @QueryParam('testParam')test?: string ): Person {
        return {name: 'OK'};
    }
}

BuildIn

The provided swagger decorator representations by this library, are listed in the following sections.

@ResponseDescription

A decorator to document the responses that a given service method can return. It is used to generate documentation for the REST service.

interface MyError {
   message: string
}

@Path('people')
class PeopleService {
  @ResponseDescription<string>(200, 'Retrieve a list of people.')
  @ResponseDescription<MyError>(401, 'The user is unauthorized.', {message: 'The user is not authorized to access this operation.'})
  @GET
  getPeople(@Param('name') name: string) {
     // ...
  }
}

A Default response is already created in swagger documentation from the method return analisys. So any response declared through this decorator is an additional response created.

@ResponseExample

Used to provide an example of method return to be added into the method response section of the generated documentation for this method.

@Path('people')
class PeopleService {
  @ResponseExample<Array<Person>>([{
    name: 'Joe'
  }])
  @GET
  getPeople(@Param('name') name: string): Person[] {
     // ...
  }
}
@ResponseProduces

Document the produces property in generated swagger docs

@Path('people')
@ResponseProduces('text/html')
class PeopleService {
  @GET
  getPeople(@Param('name') name: string) {
     // ...
  }
}

A Default produces is already created in swagger documentation from the method return analisys. You can use this decorator to override this default produces.

@RequestConsumes

Document the consumes property in generated swagger docs

@Path('people')
@RequestConsumes('text/html')
class PeopleService {
  @PUT
  createPeople(@Param('name') name: string, people: People) {
     // ...
  }
}
@SwaggerTags

Add tags for a given method on generated swagger documentation.

@Path('people')
class PeopleService {
  @SwaggerTags('adiministrative', 'department1')
  @GET
  getPeople(@Param('name') name: string) {
     // ...
  }
}
@SwaggerHidden

Allow to hide some APIs from swagger docs (ex: test or dev APIs, etc ...). This decorator can be applied for the whole class or only a single method

@Path('people')
@SwaggerHidden()
class PeopleService {
  @GET
  getPeople(@Param('name') name: string) {
     // ...
  }
}
@IsInt, @IsLong, @IsFloat, @IsDouble

Document the type of a number property or parameter in generated swagger docs. If no decorator is present, the number type defaults to double format.

class Person {
    @IsInt id: number;
}

@Path('people')
class PeopleService {
    @Path(':id')
    @GET
    getById(@PathParam('id') @IsLong id: number) {
        // ...
    }
}

Because decorators don't work on type and interface properties, this can also be specified as a JSDoc tag.

interface Person {
    /**
     * The person's id
     * @IsInt
     */
    id: number;
}

Swagger-config.json

The decorator property object of the config file can have the following properties:

import {Decorator} from 'typescript-swagger';

export namespace Decorator {
    // ...
    export type Config = {
        useLibrary? : Decorator.Library | Array<Decorator.Library> | Record<Library, ID> | Record<Decorator.Library, Decorator.Representation>;
        useBuildIn? : boolean | Array<Decorator.ID> | Record<Decorator.ID, boolean> | Decorator.ID;
        override? : Decorator.Representation;
    };
    // ...
}

Please read the TypeRepresentationMapping (TRM) section for further information to provide valid values to override or extend library or build-in TRMs.

The swagger property object of the config file on the other hand supports the following properties:

PropertyTypeDefaultDescription
basePathstring"/"Base API path; e.g. the 'v1' in https://myapi.com/v1
collectionFormatstring"csv"Default collectionFormat property for the entire API. Possible values are csv, ssv, tsv, pipes, multi. If not specified, Swagger defaults to csv.
consumes[string][]Default consumes property for the entire API
descriptionstringAPI description; defaults to npm package description
entryFilestring or string[][]The entry point to your API (it is possible to use glob patters)
hoststringThe hostname to be informed in the generated swagger file
licensestringAPI license number; defaults to npm package license
namestringAPI name; defaults to npm package name
outputDirectorystringWhere to write the generated swagger file
outputFormat'Swagger_2' or 'OpenApi_3'"Swagger_2"Inform if the generated spec will be in swagger 2.0 format or i open api 3.0
produces[string]Default produces property for the entire API
specanyExtend generated swagger spec with this object. Note that generated properties will always take precedence over what get specified here
securityDefinitions*SecurityDefinitionSecurity Definitions Object. A declaration of the security schemes available to be used in the specification. This does not enforce the security schemes on the operations and only serves to provide the relevant details for each scheme.
versionstring0.0.1API version number; defaults to npm package version
yamlbooleantrueGenerates the output also as a yaml file
SecurityDefinition

Where the SecurityDefinition contract is defined as:

export type SecureDefinition = {
    [name: string]: {
        type: string;
        name?: string;
        authorizationUrl?: string;
        tokenUrl?: string;
        flow?: string;
        in?: string;
        scopes?: { [scopeName: string]: string; }
    }
}
Example

See an example:

{
    "decorator": {
        "useBuildIn": true,
        "useLibrary": [
            "typescript-rest",
            "@decorators/express"
        ]
    },
    "swagger": {
        "outputDirectory": "./dist",
        "entryFile": "./controllers/*.ts",
        "outputFormat": "openapi_3",
        "host": "localhost:3000",
        "version": "1.0",
        "name": "Typescript-rest Test API",
        "description": "a description",
        "license": "MIT",
        "basePath": "/v1",
        "securityDefinitions": {
            "api_key": {
                "type": "apiKey",
                "name": "access_token",
                "in": "query"
            }
        },
        "ignore": [
          "**/node_modules/**"
        ]
    }
}

or in yaml format: See an example:

decorator:
  useBuildIn: true
  useLibrary:
    - @decorators/express
    - typescript-rest
swagger:
  outputDirectory: ./dist
  entryFile:
    - ./controllers/*.ts
  outputFormat: openapi_3
  host: localhost:3000
  version: 1.0
  name: Typescript-rest Test API
  description: A description
  license: MIT
  basePath: /v1
  securityDefinitions:
    api_key:
      type: apiKey
      name: access_token
      in: query
  ignore:
    - /node_modules/**

Decorator(s)

The information which are required to generate swagger documentations are collected by consulting decorators present on your code. Few decorator Type-Representation-Mappings (TRMs) are already provided by this library and can also be disabled. TRMs by third party libraries (f.e @decorators/express or typescript-rest) can be extended/replaced as well. You can also deposit your own DTRMs.

In the following sections, the decorator which can be represented is called: Type. The decorator the configuration (name/text, properties, ...) is called: Representation. DTRMs must be declared and implemented according the requirements (Specification) for the respective decorator.

TypeRepresentationMapping (TRM)

The following snippet, shows how the mapping between decorator Types and the respective Representations should look like.

type TypeRepresentationMapping = Record<Type, Representation | Representation[]>;

The Type can have one of the following values: SWAGGER_TAGS, CLASS_PATH, ... see more.

The Representation is defined as described in the following:

interface Representation {
    id: string;
    properties?: Property[]
}

The id attribute is representative for the actual decorator text/name.

For a few decorators the library expects different properties. How these properties/information are available, should be provided by the properties attribute of the representation config.

export type PropertyType = 'PAYLOAD' | 'STATUS_CODE' | 'DESCRIPTION' | 'OPTIONS' | 'SIMPLE' | 'TYPE';
export interface Property {
    /**
     * Default: 'SIMPLE'
     */
    type?: PropertyType;
    /**
     * Default: 'argument'
     */
    declaredAs?: 'argument' | 'typeArgument';
    /**
     * Default: one
     */
    amount?: 'one' | 'all';
    /**
     * Default: 0
     */
    position?: number;
}

If an attribute (type, declaredAs, amount, position) is not defined the default value(s) will be applied.

Which PropertyType(s) are available for a given decorator is described in the (Specification) section. In case for the build-in decorators the representation is defined as follows:

import {Decorator} from 'typescript-swagger';

const representation: Decorator.TypeRepresentationMapping = {
  /**
   * ID: SWAGGER_TAGS
   * RepresentationConfig: {
   *     name: 'SwaggerTags',
   *     properties: [...]
   * }
   */
  SWAGGER_TAGS: {
    name: 'SwaggerTags',
    properties: [{amount: 'all', declaredAs: "argument"}]
  },

  // Class + Method
  RESPONSE_EXAMPLE: {
    name: 'ResponseExample',
    properties: [
      {type: "TYPE", declaredAs: "typeArgument"},
      {type: "PAYLOAD", declaredAs: "argument"}
    ]
  },
  RESPONSE_DESCRIPTION: {
    name: 'ResponseDescription',
    properties: [
      {type: "TYPE", declaredAs: "typeArgument"},
      {type: "STATUS_CODE", declaredAs: "argument", position: 0},
      {type: "DESCRIPTION", declaredAs: "argument", position: 1},
      {type: "PAYLOAD", declaredAs: "argument", position: 2}
    ]
  },
  REQUEST_CONSUMES: {
    name: 'RequestConsumes',
    properties: [{amount: 'all', declaredAs: "argument"}]
  },
  RESPONSE_PRODUCES: {
    name: 'ResponseProduces',
    properties: [{amount: 'all', declaredAs: "argument"}]
  },
  SWAGGER_HIDDEN: {
    name: 'SwaggerHidden',
    properties: []
  },

  IS_INT: {
    name: 'IsInt',
    properties: []
  },
  IS_LONG: {
    name: 'IsLong',
    properties: []
  },
  IS_FlOAT: {
    name: 'IsFloat',
    properties: []
  },
  IS_DOUBLE: {
    name: 'IsDouble',
    properties: []
  },
  SERVER_FILES_PARAM: {
    name: 'RequestFileParam',
    properties: [{}]
  },
  SERVER_FILE_PARAM: {
    name: 'RequestFileParam',
    properties: [{}]
  },
};

export default representation;

Specification

How you can reference decorators, is described in the following.

SWAGGER_HIDDEN

Target:

  • Class
  • Method

Properties:

Example:

  • Decorator: @SwaggerHidden()
  • Representation:
    {
      "SWAGGER_HIDDEN": {
        "name": "SwaggerHidden",
        "properties": []
      }
    }
    
SWAGGER_TAGS

Target:

  • Class
  • Method

Properties:

  • SIMPLE:
    • Type: string | Array
    • Description: assign the endpoint to one or more swagger tags.

Example:

  • Decorator: @SwaggerTags('tag-one'), @SwaggerTags('tag-one', 'tag-two')
  • Representation:
    {
      "SWAGGER_TAGS": {
        "name": "SwaggerTags",
        "properties": [
          {"amount": "all", "declaredAs": "argument"}
        ]
      }
    }
    
CLASS_PATH

Target:

  • Class

Properties:

  • SIMPLE:
    • Type: string
    • Description: base path for methods in class

Example:

  • Decorator: @Path('/path')
  • Representation:
    {
      "CLASS_PATH": {
        "name": "Path",
        "properties": [
            {"amount": "one", "declaredAs": "argument"}
        ]
      }
    }
    
REQUEST_CONSUMES

Target:

  • Class
  • Method

Properties:

  • SIMPLE:
    • Type: string | Array
    • Description: supported media type(s) for request.

Example:

  • Decorator: @RequestConsumes('application/json'), @RequestConsumes('application/json', 'text/html')
  • Representation:
    {
      "REQUEST_CONSUMES": {
        "name": "RequestConsumes",
        "properties": [
            {"amount": "all", "declaredAs": "argument"}
        ]
      }
    }
    
RESPONSE_DESCRIPTION

Target:

  • Class
  • Method

Properties:

  • TYPE:
    • Type: any
    • Description: (typescript) type of the example
  • STATUS_CODE:
    • Type: number
    • Description: response status code (f.e 200)
  • DESCRIPTION:
    • Type: string
    • Description: response description
  • PAYLOAD:
    • Type: any
    • Description: example value or error of the description

Example:

  • Decorator: @ResponseDescription<{name: string}>(200, 'Return object with name attribute.', '{name: 'Peter'})
  • Representation
    {
      "RESPONSE_DESCRIPTION": {
        "name": "ResponseDescription",
        "properties": [
            {"type": "TYPE", "declaredAs": "typeArgument"},
            {"type": "STATUS_CODE", "declaredAs": "argument", "position": 0},
            {"type": "DESCRIPTION", "declaredAs": "argument", "position": 1},
            {"type": "PAYLOAD", "declaredAs": "argument", "position": 2}
        ]
      }
    }
    
RESPONSE_EXAMPLE

Target:

  • Class
  • Method

Properties:

  • TYPE:
    • Type: any
    • Description: (typescript) type of the example
  • PAYLOAD:
    • Type: any
    • Description: value of the example

Example:

  • Decorator: @ResponseExample<{name: string}>({name: 'Peter'})
  • Representation:
    {
      "RESPONSE_EXAMPLE": {
        "name": "Path",
        "properties": [
            {"type": "TYPE", "declaredAs": "typeArgument"},
            {"type": "PAYLOAD", "declaredAs": "argument"}
        ]
      }
    }
    
RESPONSE_PRODUCES

Target:

  • Class
  • Method

Properties:

  • SIMPLE:
    • Type: string | Array
    • Description: media type(s) available for a response message

Example:

  • Decorator: @ResponseProduces('application/json'), @ResponseProduces('application/json', 'text/html')
  • Representation:
    {
      "RESPONSE_PRODUCES": {
        "name": "ResponseProduces",
        "properties": [
            {"amount": "all", "declaredAs": "argument"}
        ]
      }
    }
    
METHOD_PATH

Target:

  • Method

Properties:

  • SIMPLE:
    • Type: string
    • Description: additional path specification to class path.

Example:

  • Decorator: @Path('/path')
  • Representation:
    {
      "METHOD_PATH": {
        "name": "Path",
        "properties": [
            {"amount": "one", "declaredAs": "argument"}
        ]
      }
    }
    

According to this schema you can:

How to provide the representation for decorators is described in the section of the swagger-config.json.

Credits

It was originally a fork of the typescript-rest-swagger project.

Keywords

FAQs

Package last updated on 01 Oct 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc