npm i koa-joi-swagger
or
yarn add koa-joi-swagger
for v3, install optional dependencies
npm i swagger-ui-dist # or yarn add swagger-ui-dist
git clone https://github.com/zaaack/koa-joi-swagger.git
cd koa-joi-swagger
yarn # or npm i
SERVE=1 npx babel-node ./test/fixtures/server.js
Now open http://127.0.0.1:3456/swagger!
app.js
import { toSwaggerDoc, ui, mixedValidate } from '../../src'
import mixedDoc from './mixed-doc'
import Koa from 'koa'
import DecRouter from 'koa-dec-router'
import bodyparser from 'koa-bodyparser'
const app = new Koa()
const decRouter = DecRouter({
controllersDir: `${__dirname}/controllers`,
})
app.use(bodyparser())
const swaggerDoc = toSwaggerDoc(mixedDoc)
// mount swagger ui in `/swagger`
app.use(ui(swaggerDoc, {pathRoot: '/swagger'}))
// handle validation errors
app.use(async (ctx, next) => {
try {
await next()
} catch (e) {
if (e.name === 'RequestValidationError') {
ctx.status = 400
ctx.body = {
code: 1,
message: e.message,
data: e.data,
}
} else if (e.name === 'ResponseValidationError') {
ctx.status = 500
ctx.body = {
code: 1,
message: e.message,
data: e.data,
}
}
}
})
// validate request and response by mixedDoc
app.use(mixedValidate(mixedDoc, {
onError: e => console.log(e.details, e._object),
}))
// koa-dec-router
app.use(decRouter.router.routes())
app.use(decRouter.router.allowedMethods())
app.listen(3456)
"I see the api is simple, but how to write the joi schema and the swagger document?"
That's the point, you don't need to write a joi schema to validation and a swagger document to create API documents.
"Oh, no, Should I learn a new schema?"
Of cause not, I hate new schemas, too, especially those made by someone or some company without long support, it's just a waste of time and my brain cell.
Therefore, to make this library simple and reliable, I just mixed joi and swagger document, and using joi-to-json-schema to transform joi schema to swagger schema. You don't have to learn a new schema, just replace the JSON schema in your swagger document to joi schema, then let this library to do the rest.
I call it mixed document, here is an example.
export default {
swagger: '2.0',
info: {
title: 'Test API',
description: 'Test API',
version: '1.0.0',
},
// the domain of the service
// host: 127.0.0.1:3457
// array of all schemes that your API supports
schemes: ['https', 'http'],
// will be prefixed to all paths
basePath: '/api/v1',
consumes: ['application/x-www-form-urlencoded'],
produces: ['application/json'],
paths: {
'/posts': {
get: {
summary: 'Some posts',
tags: ['Post'],
parameters: {
query: Joi.object().keys({
type: Joi.string().valid(['news', 'article']),
}),
},
responses: {
'200': {
x: 'Post list',
schema: Joi.object().keys({
lists: Joi.array().items(Joi.object().keys({
title: Joi.string().description('Post title'),
content: Joi.string().required().description('Post content'),
}))
}),
},
'default': {
description: 'Error happened',
schema: Joi.object().json().keys({
code: Joi.number().integer(),
message: Joi.string(),
data: Joi.object(),
}),
},
}
}
},
},
}
You can see the differences between this and the real swagger document, just replace parameters
and responses
to joi schema instead of JSON schema,
Here is the swagger document that generate from mixed document above.
import JoiSwagger, {
toSwaggerDoc, mixedValidate, joiValidate, ui
} from 'koa-joi-swagger'
import Koa from 'koa'
const app = new Koa()
/*
JoiSwagger = {
toSwaggerDoc,
mixedValidate,
joiValidate,
ui,
Joi,
}
*/
const mixedDoc = require('./mixed-doc')
const swaggerDoc = toSwaggerDoc(mixedDoc) // parse mixed document to swagger document for swagger-ui
//
// const defaultResJoiOpts = {
// stripUnknown: true,
// convert: true,
// }
app.use(mixedValidate(mixedDoc, {
reqOpts: {
stripUnknown: false,
convert: true,
}, // optional, ctx.request joi validation options, here is default
resOpts: { // optional, ctx.response joi validation options, here is default
stripUnknown: true, // this would remove additional properties
convert: true, // this would convert field types
},
onError: err => console.error(err), // Do something with the error, the error would throw anyway.
}))
app.use(ui(swaggerDoc, {
pathRoot: '/swagger', // optional, swagger path
skipPaths: [], // optional, skip paths
UIHtml: defaultUIHtml, // optional, get ui html
swaggerConfig: '', // optional, a json5 string, e.g. `{ <field>: <value>, .... }` to display in html for overriding swagger ui options.
sendConfig: { maxage: 3600 * 1000 * 24 * 30 }, // optional, config for koa-send, default maxage is 1 month.
v3: false, // optional, default is v2, you need to install optional dependencies `swagger-ui-dist` first.
}))
// joiValidate // the internal joi validation function used by mixedValidate, in case you need one.
// JoiSwagger.Joi // The joi used to validate, with some opinionated extension, you can override it or using it.
I have think it before, but hit some problems like validating javascript date object, remove additionalProperties, etc. And writing JSON schema is too verbose. Joi is the best validation library in NodeJS, we should take the advantage.
YAML is not easy to reuse, although JSON schema can reuse model, and how to reuse shared properties between models? I can't find a way. Pure javascrip can easily reuse or wrap model schema, and you can wrap each final schema with a function, don't feel pain when adding properties for each request schema in the future.
Sorry, joi's philosophy is too strict for me, I really don't need to explicit declare the string could be empty, so I override the original Joi.string()
to make Joi.string().empty('')
is a default behavior.
Also, add a .force()
method for string/number type, to coerce the field to string/number regardless of the original type, it's really useful when validating some bson type like Long, Deciaml or Custom object.
Added a Joi.object().json()
to coerce object with toJSON
method to a plain JSON object. This would useful when validation some ORM/ODM's model object (like mongorito).
And I highly recommend using this extended joi to write your schemas, and adding your extension if you need.
You can also using other version of Joi to validate.
import JoiSwagger from 'koa-joi-swagger'
import myJoi from './myJoi'
// using
export const Joi = JoiSwagger.Joi
// override
JoiSwagger.Joi = myJoi
Koa-Joi-Router Docs Generator This project is based on paul42/joi-router-swagger-docs. A node module for generating Swagger 2.0 JSONdefinitions from existing koa-joi-routerroutes. Aiming to be a repla
Joi 是用于 JavaScript 的强大的模式描述语言和数据验证器,让你可以使用简单、直观且可读的语言来描述数据。 示例: const Joi = require('joi');const schema = Joi.object({ username: Joi.string() .alphanum() .min(3) .max(30)
joi-router Easy, rich and fully validated koa routing. Features: built in input validation using joi built in output validation using joi built in body parsing using co-body and await-busboy built on
Koa art-template view render middleware. support all feature of art-template. Install npm install --save art-template npm install --save koa-art-template Example const Koa = require('koa'); const ren
koa是Express的下一代基于Node.js的web框架,目前有1.x和2.0两个版本。 历史 1. Express Express是第一代最流行的web框架,它对Node.js的http进行了封装,用起来如下: var express = require('express'); var app = express(); app.get('/', function (req, res) {
Koa 是下一代的 Node.js 的 Web 框架。由 Express 团队设计。旨在提供一个更小型、更富有表现力、更可靠的 Web 应用和 API 的开发基础。 Koa可以通过生成器摆脱回调,极大地改进错误处理。Koa核心不绑定任何中间件,但提供了优雅的一组可以快速和愉悦地编写服务器应用的方法。 示例代码: var koa = require('koa');var app = koa();//