1.0.10 • Published 3 years ago

@lxsbw/koa-joi-swagger-ts v1.0.10

Weekly downloads
-
License
ISC
Repository
github
Last release
3 years ago

@lxsbw/koa-joi-swagger-ts NPM version

How to use

npm install @lxsbw/koa-joi-swagger-ts --save

Documentation

Methods

Each controller can use 5 predefined rest methods GET, PUT, POST, PATCH, DELETE

Example of using

@controller("/user")
class UserController extends BaseController {
    @put("/{userId}")
    @parameter("userId", joi.string().min(2).description("userId"), ENUM_PARAM_IN.path)
    addSomeUser(ctx) {
        ctx.body = "cant add user";
    }

    @del("/{userId}")
    @parameter("userId", joi.string().min(2).description("userId"), ENUM_PARAM_IN.path)
    deleteSomeUser(ctx) {
        ctx.body = "user not found";
    }
}

Resolvers

We have 3 type of resolvers (aka middlewares, but without next() functions) - functions which can be called before (or after) your controller method:

  • safe - this resolver can wrap on method by try-catch
  • before - call function (or list of functions) before our target controller method
  • after - call function (or list of functions) after our target method

@safe(fn?: ErrorHandlerFunction, throwNext?: boolean)

This decorator can wrap on your method into try-catch, and if something wrong - call function which specifiyed into parameter fn with Error argument

Parameters:

  • fn - function (optional) - call if throwed error
  • throwNext - boolean (optional) - if true, will throw error to upper level
Example of using @safe() resolver
import {safe, parameter, del, controller, ENUM_PARAM_IN} from "@lxsbw/koa-joi-swagger-ts";

// ...somecodehere...

@controller("/user")
class UserController extends BaseController {
    @del("/{userId}")
    @parameter("userId", joi.string().min(2).description("userId"), ENUM_PARAM_IN.path)
    @safe( (err) => { console.log(err) } )
    deleteSomeUser() {
        throw Error("Some bad error");
    }
}

@before(...fn: MiddlewareFunction[])

This decorator can add additional functions which will called before your controller method.

Parameters:

  • fn - function - functions which will be called
Example of using @before() resolver
import {before, parameter, del, controller, ENUM_PARAM_IN} from "@lxsbw/koa-joi-swagger-ts";

// ...somecodehere...

@controller("/user")
class UserController extends BaseController {
    @del("/{userId}")
    @parameter("userId", joi.string().min(2).description("userId"), ENUM_PARAM_IN.path)
    @before( (ctx) => { console.log("first resolver") } )
    @before( (ctx) => { console.log("second resolver") }, (ctx) => { console.log("third resolver") } )
    deleteSomeUser(ctx) {
        ctx.body = "user not found";
    }
}

@after(...fn: MiddlewareFunction[])

This decorator can add additional functions which will called after your controller method.

ATTENTION! Specific of decorators calling - is reversed order of calls, thats why, if you use few @after decorators - last after will be called as first, and first as last, thats why I recommend to use list of functions as multiple arguments if order matters something for your logic

Parameters:

  • fn - function - functions which will be called
Example of using @after() resolver
import {after, parameter, del, controller, ENUM_PARAM_IN} from "@lxsbw/koa-joi-swagger-ts";

// ...somecodehere...

@controller("/user")
class UserController extends BaseController {
    @del("/{userId}")
    @parameter("userId", joi.string().min(2).description("userId"), ENUM_PARAM_IN.path)
    @after( (ctx) => { console.log("called THIRD afetr method") } )
    @after( (ctx) => { console.log("called FIRST after method") }, (ctx) => { console.log("called SECOND after method") } )
    deleteSomeUser(ctx) {
        ctx.body = "user not found";
    }
}

Example (TypeScript)

import {parameter, get, post, del, controller, definition, KoaSwaggerRouter, summary, response, tag, ENUM_PARAM_IN} from "@lxsbw/koa-joi-swagger-ts";
import * as joi from "joi";
import * as fs from "fs";
import {array, string} from "joi";
import * as koa from "koa";

@definition("User", "User Entity")
class UserSchema {
    userName = joi.string().min(6).description("username").required();
    userPass = joi.string().min(6).description("password").required();
}

@controller("/v3/api")
class BaseController {
    @get("/")
    index() {
    }
}

/**
 * This method will be called by middleware instead of controller
 */
const baseControllerFunction = async (controller, ctx, next, summary): Promise<void> => {
    console.log(`${ctx.request.method} ${ctx.request.url}`);
    try {
        await controller(ctx);
    } catch (e) {
        console.log(e, `Error while executing "${summary}"`);
    }
};

@controller("/user")
class UserController extends BaseController {

    @del("/{userId}")
    @parameter("userId", joi.string().min(2).description("userId"), ENUM_PARAM_IN.path)
    index() {

    }

    @get("/")
    @parameter("userId", joi.string().required(), ENUM_PARAM_IN.query)
    doGet(ctx) {
        ctx.body = Date.now();
    }

    @get("/{userId}")
    @parameter("userId", joi.number().min(2).description("userId"), ENUM_PARAM_IN.path)
    @response(200, {$ref: UserSchema})
    getUser(ctx) {
        ctx.body = {userName: ctx.params.userId.toString(), userPass: Date.now().toString()};
    }

    @post("/upload")
    @parameter("file1", {type: "file"}, ENUM_PARAM_IN.formData)
    doUpload(ctx) {
        ctx.body = { fileObj: ctx.body.file1};
    }

    @post("/")
    doPost() {
    }

    @get("s")
    @response(200, {type: "array", items: {$ref: UserSchema}})
    getUsers() {
    }
}

@definition("Admin", "Admin Entity")
class AdminSchema {
    userName = joi.string().required().min(6).uppercase();
    userPass = joi.string();
}

@controller("/admin")
class AdminController extends UserController {

    @post("/login")
    @parameter("name", joi.string().description("name"))
    @parameter("list", array().items(string()).required(), ENUM_PARAM_IN.query)
    @summary("AdminController.index")
    @response(200, {$ref: AdminSchema})
    @response(202, joi.string().description("aaa"))
    @tag("Admin")
    @tag("User")
    index() {
    }
}

const router = new KoaSwaggerRouter({
  swagger: '2.0',
  info: {
    description:
      'This is a sample server Koa2 server.  You can find out more about     Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).      For this sample, you can use the api key `special-key` to test the authorization     filters.',
    title: 'Koa2 TypeScript Swagger',
    version: '1.0.0',
    concat: {
      email: 'xxx@outlook.com'
    },
    // 开源协议
    license: {
      name: 'Apache 2.0',
      url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
    }
  },
  // host: '',
  basePath: '',
  schemes: ['http', 'https'],
  paths: {},
  definitions: {},
  securityDefinitions: {
    JWT: {
      type: 'apiKey',
      in: 'header',
      name: 'Authorization'
    }
  }
});

router.loadDefinition(UserSchema);
router.loadDefinition(AdminSchema);
// Or you can:
// router.loadDefinition([UserSchema, AdminSchema]);
router.loadController(BaseController);
// Process controller through pattern Decorator
router.loadController(UserController, baseControllerFunction);
router.loadController(AdminController);

router.setSwaggerFile("swagger.json");

router.loadSwaggerUI("/");

fs.writeFileSync("./swagger.json", JSON.stringify(router.swagger));

// console.log(router.getRouter());

const app = new koa();

app.use(router.getRouter().routes());

app.use(router.getRouter().allowedMethods());

app.listen(3002);

Project example

You can quickly test @lxsbw/koa-joi-swagger-ts with the project example koa-base-ts.

1.0.9

3 years ago

1.0.10

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago