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

@hnsgc/koa-swagger-decorator

v1.8.5

Published

using decorator to automatically generate swagger doc for koa-router

Downloads

48

Readme

koa-swagger-decorator

using decorator to auto generate swagger json docs

build status npm

Installation

npm install koa-swagger-decorator

Contributing Guide

Please refer to contribution.md before creating your PR or issue.

Introduction

Koa Swagger Decorator

using decorator to auto generate swagger json docs add support validation for swagger definitions

based on Swagger OpenAPI Specification 2.0

support both javascript (babel required) and typescript

Example

// using commonds below to start and test the example server

git clone https://github.com/Cody2333/koa-swagger-decorator.git

cd koa-swagger-decorator

npm install

npm run start

finally open:
http://localhost:3000/api/swagger-html

Requirements

  • Koa2
  • @koa/router
  • typescript (or babel required)
// add [transform-decorators-legacy] to .babelrc if using js

npm install --save-dev babel-plugin-transform-decorators-legacy

{
  "presets": [
    ["env", {"targets": {"node": "current"}}]
  ],
  "plugins": ["transform-decorators-legacy"]
}

Detail

for more detail please take a look at the example koa server

first wrapper the @koa/router object

// router.js
import Router from '@koa/router'

import Test from './test'

import { SwaggerRouter } from 'koa-swagger-decorator'

const router = new SwaggerRouter([KoaRouterOpts],[SwaggerOpts]) // extends from koa-router

// swagger docs avaliable at http://localhost:3000/api/swagger-html
router.swagger({
  title: 'Example Server',
  description: 'API DOC',
  version: '1.0.0',

  // [optional] default is root path.
  // if you are using koa-swagger-decorator within nested router, using this param to let swagger know your current router point
  prefix: '/api',

  // [optional] default is /swagger-html
  swaggerHtmlEndpoint: '/swagger-html',

  // [optional] default is /swagger-json
  swaggerJsonEndpoint: '/swagger-json',

  // [optional] additional options for building swagger doc
  // eg. add api_key as shown below
  swaggerOptions: {
    securityDefinitions: {
      api_key: {
        type: 'apiKey',
        in: 'header',
        name: 'api_key',
      },
    },
  },
  // [optional] additional configuration for config how to show swagger view
  swaggerConfiguration: {
    display: {
      defaultModelsExpandDepth: 4, // The default expansion depth for models (set to -1 completely hide the models).
      defaultModelExpandDepth: 3, // The default expansion depth for the model on the model-example section.
      docExpansion: 'list', // Controls the default expansion setting for the operations and tags. 
      defaultModelRendering: 'model' // Controls how the model is shown when the API is first rendered. 
    }
  }
})
// map all static methods at Test class for router
// router.map(Test);

// mapDir will scan the input dir, and automatically call router.map to all Router Class
router.mapDir(_path.resolve(__dirname), {
  // default: true. To recursively scan the dir to make router. If false, will not scan subroutes dir
  // recursive: true,
  // default: true, if true, you can call ctx.validatedBody[Query|Params] to get validated data.
  // doValidation: true,
  // default: [], paths to ignore while looking for decorators 
  // ignore: ["**.spec.ts"],
})

using decorator to make api definition

// test.js

import User from 'models/user'
import { request, summary, query, path, body, tags } from 'koa-swagger-decorator'

const testTag = tags(['test'])

const userSchema = {
  name: { type: 'string', required: true },
  gender: { type: 'string', required: false, example: 'male' },
  groups: {
    type: 'array',
    required: true,
    items: { type: 'string', example: 'group1' }, // item's type will also be validated
  },
}

export default class Test {
  @request('get', '/users')
  @summary('get user list')
  @security([{ api_key: [] }])
  @testTag
  @query({
    type: { type: 'number', required: true, default: 1, description: 'type' },
  })
  static async getUsers(ctx) {
    const users = await User.findAll()
    ctx.body = { users }
  }

  @request('get', '/users/{id}')
  @summary('get user info by id')
  @security([{ api_key: [] }])
  @testTag
  @path({
    id: { type: 'number', required: true, default: 1, description: 'id' },
  })
  static async getUser(ctx) {
    const { id } = ctx.validatedParams
    const user = await User.findById(id)
    ctx.body = { user }
  }

  @request('post', '/users')
  @testTag
  @body(userSchema)
  static async postUser(ctx) {
    // const body = ctx.request.body;
    const body = ctx.validatedBody
    ctx.body = { result: body }
  }

  static async temp(ctx) {
    ctx.body = { result: 'success' }
  }
}

using decorator to make api body

import Router from '@koa/router';
import { request, summary, query, path, body, tags, swaggerClass, swaggerProperty } from 'koa-swagger-decorator'

@swaggerClass()
export class subObject {
  @swaggerProperty({ type: "string", required: true }) Email: string = "";
  @swaggerProperty({ type: "string", required: true }) NickName: string = "";
  @swaggerProperty({ type: "string", required: true }) Password: string = "";
};

@swaggerClass()
export class userInfo {
  @swaggerProperty({ type: "string", required: true }) Email: string = "";
  @swaggerProperty({ type: "string", required: true }) NickName: string = "";
  @swaggerProperty({ type: "string", required: true }) Password: string = "";
  @swaggerProperty({type:"object",properties:(subObject as any).swaggerDocument}) UserInfo:subObject;
};

export default class Test {
  @request('POST', '/user/Register')
  @summary('register user')
  @description('example of api')
  @body((userInfo as any).swaggerDocument)
  static async Register(ctx: Router.IRouterContext) {
    var params = (ctx as any).validatedBody as userInfo;
    console.log(params);
  }
}

avaliable annotations

  • tags
  • query
  • path
  • body
  • formData
  • middlewares
  • security
  • summary
  • description
  • responses
  • deprecated

class annotations

  • orderAll
  • tagsAll
  • responsesAll
  • middlewaresAll
  • securityAll
  • deprecatedAll
  • queryAll
request // @request('POST', '/users')

tags // @tags(['example'])
query // @query({limit: {type: 'number', required: true, default: 10, description: 'desc'}})

path // @path({limit: {type: 'number', required: true, default: 10, description: 'desc'}})

body // @body({groups: {type: 'array', required: true, items: { type: 'string', example: 'group1' }}})

formData // @formData({file: {type: 'file', required: true, description: 'file content'}})

middlewares
// support koa middlewares.
// eg. @middlewares([func1,func2])

security 
// define authentication method, key must be same as one of methods defined in swaggerOptions.securityDefinitions
// @security([{ api_key: [] }]) 

summary // @summary('api summary')

description // @description('api description')

responses
// @responses({ 200: { description: 'success'}, 400: { description: 'error'}})
// responses is optional

deprecated // @deprecated

@orderAll(1)  // weight 1 means the router class will be ordered at position 1 in generated doc
@tagsAll(['A', 'B'])
@deprecatedAll
@securityAll([{ api_key: [] }])
@middlewaresAll([log1, log2]) // add middlewares [log1, log2] to all routers in this class
@queryAll({ limit: { type: 'number', default: 444, required: true } }) // can be merged with @query
export default class SampleRouter {
  ...
}

validation

support validation type: string, number, boolean, object, array.

properties in {type: 'object'} and items in {type: 'array'} can alse be validated.

other types eg. integer will not be validated, and will return the raw value.

by default, validation is activated and you can call ctx.validatedQuery[Body|Params] to access the validated value.

to turn off validation:

router.mapDir(_path.resolve(__dirname), {
  // default: true, if true, you can call ctx.validatedBody[Query|Params] to get validated data.
  doValidation: false,
})
runing the project and it will generate docs through swagger ui

image.png

generate swagger.json without starting the server
import path from 'path';
import { SwaggerRouter } from '../../dist';

// init router
const router = new SwaggerRouter();

// load controllers
router.mapDir(path.resolve(__dirname, '../routes'));

// dump swagger json
router.dumpSwaggerJson({
  filename: 'swagger.json', // default is swagger.json
  dir: process.cwd(), // default is process.cwd()
});

License

© MIT