Giter Site home page Giter Site logo

jsonma / swagger-egg Goto Github PK

View Code? Open in Web Editor NEW
41.0 2.0 15.0 1.08 MB

Eggjs Swagger-UI API文档自动生成插件(如果喜欢请点赞支持)。Egg swagger documentation generator(welcome to star this project).

License: MIT License

JavaScript 80.49% TypeScript 19.51%
swagger-ui swagger swagger-egg egg-swagger swagger-doc egg-swagger-doc swagger-jsdoc jsdoc swagger-egg-jsdoc

swagger-egg's Introduction

swagger-egg

swagger-egg

NPM version build status Test coverage David deps Known Vulnerabilities npm download

中文文档

An egg-swagger plugin (support Typescript) for serving a Swagger UI, params should follow JSON Schema specification (recommend use Ajv),using Swagger (OpenAPI v2) schemas automatically generated from your controller JSDoc comments.

CAUTION: Require Node.js 10.x or higher!

Install

$ npm i swagger-egg --save

Usage

Enable this plugin, visting index.html under static resource directory and you will get the Swagger UI page. Visiting http://localhost:7001/public/index.html to get the default Swagger-UI page. Project Example:

// {app_root}/config/plugin.js
exports.swaggerEgg = {
  enable: true,
  package: "swagger-egg",
};

Configuration

  • swagger.info is optional and will be generated from your application's package.json if not exist.
  • swagger.tags is required if controller's JSDoc comments used tags.
// {app_root}/config/config.default.js
exports.swaggerEgg = {
  schema: {
    path: '/app/schema', // JSON Schema directory
  },
  swagger: {
    info: {
      title: 'Test swagger',
      description: 'Testing the Fastify swagger API',
      version: '0.1.0'
    },
    externalDocs: {
      url: 'https://swagger.io',
      description: 'Find more info here'
    },
    host: '127.0.0.1:7001', // should be egg server's host, otherwise result in cross origin error
    schemes: ['http', 'https'],
    consumes: ['application/json'],
    produces: ['application/json'],
    tags: [
      { name: 'user', description: 'User related end-points' }
    ],
    securityDefinitions: {
      api_key: {
        type: 'apiKey', // basic/apiKey/oauth2
        name: 'Authorization', // selfdefined parameter, usually use 'Authorization'
        in: 'header', // query or header, usually use 'header'
      },
      github_auth: {
        type: 'oauth2',
        authorizationUrl: 'http://swagger.io/api/oauth/dialog',
        flow: 'implicit',
        scopes: {
          'write:homes': 'modify home info',
          'read:homes': 'read home info',
        },
      },
    },
    security: [
      {
        api_key: [], // select 'api_key' to security(defined in `securityDefinitions`)
      },
    ], // Cacution: security is array type
    typescriptJsonSchema: false, // use typescript json schema. (see: https://github.com/YousefED/typescript-json-schema)
  }
};

see config/config.default.js for more detail.

Grammer

#swagger-api

#swagger-api in front of JSDoc comments is required!

  /**
   * #swagger-api
   *
   * @function index
   */
  async index() {
    this.ctx.body = 'hi, #swagger-api example'
  }

@function {Name}

The JSDoc @function is required, which is used to search router info from app/router.js.

  /**
   * Function example #swagger-api
   *
   * @function index
   */
  async index() {
    this.ctx.body = 'hi, function example'
  }

@summary {functionSummary}

The JSDoc @summary is used to describe the function's summary.

  /**
   * Function example #swagger-api
   *
   * @function index
   * @summary This is function's summary.
   */
  async index() {
    this.ctx.body = 'hi, summary example'
  }

@description #tags {Tag1} {Tag2} ...

#tags is used for logical grouping of operations by resources or any other qualifier.

NOTE: Multiple tags should be separated by whitespace.

  /**
   * Tags example #swagger-api
   *
   * @function index
   * @description #tags user admin
   */
  async index() {
    this.ctx.body = 'hi, tags example'
  }

@description #produces {Mimetype1} {Mimetype2} ...

#produces is used for declaring API response mimetype.

NOTE: Multiple mimetypes should be separated by whitespace.

  /**
   * Produces example #swagger-api
   *
   * @function index
   * @description #produces application/json
   */
  async index() {
    this.ctx.body = 'hi, produces example'
  }

@description #consumes {Mimetype1} {Mimetype1} ...

#consumes is used for declaring API request mimetype.

NOTE: Multiple mimetypes should be separated by whitespace.

  /**
   * Consumes example #swagger-api
   *
   * @function index
   * @description #consumes application/json
   */
  async index() {
    this.ctx.body = 'hi, consumes example'
  }

@description #parameters {PrameterName} {In} {ParameterSchema|Type} {Required} - {Description}

#parameters is used for declaring api request parameters.

NOTE: Description is separated by - and others are separated by whitespace.

NOTE:

  • In should be within 'query', 'header', 'path', 'formData', 'body' according to Swagger specification.
  • Required should be boolean type.
  • Type should be within 'string', 'number', 'integer', 'boolean', 'array', 'file'.
  /**
   * Parameters example #swagger-api
   *
   * @function index
   * @description #parameters id path schema.id true - id parameter
   */
  async index() {
    this.ctx.body = 'hi, parameters example'
  }

@description #responses {HttpStatus} {ResponseSchema} - {Description}

#responses is used for declaring api response info.

NOTE: Description is separated by - and others are separated by whitespace.

  /**
   * Responses example #swagger-api
   *
   * @function index
   * @description #responses schema.user - user responses
   */
  async index() {
    this.ctx.body = 'hi, responses example'
  }

Schema Example

Schema should follow the JSON Schema specification. You can use Ajv to validate it.

Change swaggerEgg.schema.path field in config file if you want to redefine it.

// {app_root}/app/schema/users.js

module.exports = {
  type: 'object',
  properties: {
    id: {
      type: 'string',
      description: 'user id'
    },
    name: {
      type: 'string',
      description: 'user name'
    },
    age: {
      type: 'number',
      description: 'user age'
    },
  },
  required: [ 'id', 'name', 'age' ],
  additionalProperties: false,
};

Controller Example

// {app_root}/app/controller/users.js

const Controller = require('egg').Controller;

class UserController extends Controller {

  /**
   * Index action #swagger-api
   *
   * @function index
   * @memberof UserController
   * @description #tags user
   * @description #produces application/json
   * @description #parameters index query schema.definitions.index true - parameter index
   * @description #responses 200 schema.user - index response
   */
  async index() {
    this.ctx.body = 'hi, index action' + this.app.plugins.swaggerEgg.name;
  }

  /**
   * New action #swagger-api
   *
   * @function new
   * @memberof UserController
   * @description #tags user
   * @description #consumes application/x-www-form-urlencoded
   * @description #produces application/json
   * @description #parameters userInfo body schema.user true - parameter userInfo
   * @description #responses 200 schema.user - new response
   */
  async new() {
    this.ctx.body = 'hi, new action' + this.app.plugins.swaggerEgg.name;
  }

  /**
   * Show action #swagger-api
   *
   * @function show
   * @memberof UserController
   * @description #tags user
   * @description #produces application/json
   * @description #parameters id path schema.definitions.id true - parameter id
   * @description #responses 200 schema.user - show response
   */
  async show() {
    this.ctx.body = 'hi, show action' + this.app.plugins.swaggerEgg.name;
  }

  /**
   * Edit action #swagger-api
   *
   * @function edit
   * @memberof UserController
   * @description #tags user
   * @description #consumes application/x-www-form-urlencoded
   * @description #produces application/json
   * @description #parameters id path schema.definitions.id true - parameter id
   * @description #parameters userInfo body schema.user true - parameter userInfo
   * @description #responses 200 schema.user - edit response
   */
  async edit() {
    this.ctx.body = 'hi, edit action ' + this.app.plugins.swaggerEgg.name;
  }

  /**
   * Create action #swagger-api
   *
   * @function create
   * @memberof UserController
   * @description #tags user
   * @description #consumes application/x-www-form-urlencoded
   * @description #produces application/json
   * @description #parameters userInfo body schema.user true - parameter userInfo
   * @description #responses 200 schema.user - create response
   */
  async create() {
    this.ctx.body = 'hi, create action ' + this.app.plugins.swaggerEgg.name;
  }

  /**
   * Update action #swagger-api
   *
   * @function update
   * @memberof UserController
   * @description #tags user
   * @description #consumes application/x-www-form-urlencoded
   * @description #produces application/json
   * @description #parameters id path schema.definitions.id true - parameter id
   * @description #parameters userInfo body schema.user true - parameter userInfo
   * @description #responses 200 schema.user - update response
   */
  async update() {
    this.ctx.body = 'hi, update action ' + this.app.plugins.swaggerEgg.name;
  }

  /**
   * Destory action #swagger-api
   *
   * @function destory
   * @memberof UserController
   * @description #tags user
   * @description #consumes application/json
   * @description #produces application/json
   * @description #parameters id path schema.definitions.id false - parameter id
   * @description #responses 200 schema.user - destory response
   */
  async destory() {
    this.ctx.body = 'hi, destory action ' + this.app.plugins.swaggerEgg.name;
  }
}

module.exports = UserController;

Questions & Suggestions

Please open an issue here.

License

MIT

swagger-egg's People

Contributors

aixinyongheng avatar jsonma avatar smackgg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

swagger-egg's Issues

建议暴露ts编译出的 `schemaObject` 以便复用于参数校验

当配置 typescriptJsonSchema: true 时, app/schema/**/*.ts 中会编译成 schemaObject ,虽然可以在注释中引用 schemaObject 进行声明,但看起来没法在 app/controller/**/*.ts 的代码中引用 schemaObject

建议插件把 schemaObject 挂载到 appctx ,以便复用于 ctx.valudate(rules, data) 的规则中,否则需要在 rules 中重复声明参数类型等信息。

TS应用中默认的 `yarn start` 命令启动报错

问题复现步骤

eggjs新建 TS 项目。 [email protected], [email protected]

正常写 app/schema/definitions.ts

yarn run tsc ,再 yarn start

问题表现

[egg-scripts] File '<egg-app>/app/schema/definitions.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
[egg-scripts]   The file is in the program because:
[egg-scripts]     Root file specified for compilation

奇怪为什么 app/schema/definitions.js 会成为 root file。

在 egg-scripts 中断点拿到的此异常的信息 error TS6504: File '*.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?

尝试解决未果

eggjs为TS应用生成的 tsconfig.json 中为 compilerOptions.allowJs: false ,不确定eggjs是否对此强依赖。如果改成 true,那么在 yarn run tsc 时会报错,或许是强依赖,没继续深入研究。

error TS2347: Untyped function calls may not accept type arguments.
error TS2339: Property 'mongoose' does not exist on type 'MockApplication'.
const invalidAccountAppId = (new app.mongoose.Types.ObjectId()).toString();

解析不出 controller action

问题表现

解析不出 controller action

复现数据示例

// app/router.ts
router
  .get(
    'path/to/foo',
    middlewareBar,
    // 注意末尾有逗号
    app.controller.foo.action,
  )

根本原因

34, 35行解析得太理想化了,建议在单元测试中补充边界case。

image

#responses 不写 Description 会报错

@description #responses {HttpStatus} {ResponseSchema} - {Description}

#responses 不写 Description 会报错

问题表现:
2022-03-29 16:26:30,117 ERROR 167275 [swagger-egg] Cannot read properties of null (reading 'pop')
抛出异常导致中断后续流程,解析不完整。

根本原因:
71行的正则写得太死,认为总是会存在 Description 。
image

另外, responnseParser 单词拼写错误。

controller文件名带有'-'生成不了api文档

// router.js
router.resources('xxx-test', '/api/xxx-test', controller.xxxTest);

// controller/xxx-test.js
class XxxTestController extends Controller {
  /**
   * #swagger-api
   * @function index
   * @summary 查询
   * @description #tags xxx-test
   */
  async index() {
      this.ctx.body = 'select!!!';
  }

路由信息解析不出来

因为 swagger-egg 是自己用正则解析 app/router.ts 文件内容,获取路由信息。
参考 node_modules/swagger-egg/lib/router_loader.js 中的 getRouter() 方法。

导致很多情况解析不出来,比如

  • 使用 egg-router-plus
  • 使用 `'router-name'``
  • 'path-match' 不是字符串字面量,而是一个表达式或变量
router.verb('path-match', app.controller.action);
router.verb('router-name', 'path-match', app.controller.action);
router.verb('path-match', middleware1, ..., middlewareN, app.controller.action);
router.verb('router-name', 'path-match', middleware1, ..., middlewareN, app.controller.action);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.