forked from koajs/joi-router
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrouter.ts
110 lines (97 loc) · 2.76 KB
/
router.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import {
identityValidator,
makeBodyParser,
makeValidator,
injectSpec,
} from './helpers'
import KoaRouter from '@koa/router'
import { Spec, ValidatorBuilder } from './types'
import createDebug from 'debug'
const debug = createDebug('koa-joi-router')
export class Router<Meta, Schema> {
public routes: Spec<Meta, Schema>[] = []
public router = new KoaRouter()
constructor(
private validatorBuilder: ValidatorBuilder<Schema> = identityValidator
) {}
public prefix = this.router.prefix.bind(this.router)
public use = this.router.use.bind(this.router)
public param = this.router.param.bind(this.router)
public allowedMethods = this.router.allowedMethods.bind(this.router)
public middleware() {
return this.router.routes()
}
/**
* Adds a route or array of routes to this router, storing the route
* in `this.routes`.
*
* Example:
*
* var admin = router();
*
* admin.route({
* method: 'get',
* path: '/do/stuff/:id',
* handler: function *(next){},
* validate: {
* header: Joi object
* params: Joi object (:id)
* query: Joi object (validate key/val pairs in the querystring)
* body: Joi object (the request payload body) (json or form)
* maxBody: '64kb' // (json, x-www-form-urlencoded only - not stream size)
* // optional
* type: 'json|form|multipart' (required when body is specified)
* failure: 400 // http error code to use
* },
* meta: { // this is ignored but useful for doc generators etc
* desc: 'We can use this for docs generation.'
* produces: ['application/json']
* model: {} // response object definition
* }
* })
*
* @param {Object} spec
* @return {Router} self
* @api public
*/
public route(spec: Spec<Meta, Schema> | Spec<Meta, Schema>[]) {
if (Array.isArray(spec)) {
for (let i = 0; i < spec.length; i++) {
this.addRoute(spec[i])
}
} else {
this.addRoute(spec)
}
return this
}
/**
* Adds a route to this router, storing the route
* in `this.routes`.
*
* @param {Object} spec
* @api private
*/
private addRoute(spec: Spec<Meta, Schema>) {
this.routes.push(spec)
debug('add %s "%s"', spec.method, spec.path)
const bodyParser = makeBodyParser(spec)
const validator =
spec.validationEnabled === false
? null
: makeValidator(spec, this.validatorBuilder)
const preHandlers = Array.isArray(spec.pre)
? spec.pre.flat(Infinity)
: [spec.pre]
const handlers = Array.isArray(spec.handler)
? spec.handler.flat(Infinity)
: [spec.handler]
const args = [
injectSpec(spec),
...(preHandlers ?? []),
bodyParser,
validator,
...handlers,
].filter((middleware) => !!middleware)
this.router[spec.method](spec.path, ...args)
}
}