Add ability to specify middleware in AsyncRouter

This commit is contained in:
Jerko Steiner 2019-04-06 21:32:20 +08:00
parent 364972c97f
commit bbf18ed27a
3 changed files with 83 additions and 18 deletions

View File

@ -27,6 +27,11 @@ describe('AsyncRouter', () => {
patch: IHandler patch: IHandler
head: {}, head: {},
} }
'/middleware': {
get: {
response: IResponse
}
}
} }
const app = express() const app = express()
@ -55,6 +60,16 @@ describe('AsyncRouter', () => {
asyncRouter.head('/test/:param', async req => { asyncRouter.head('/test/:param', async req => {
return '' return ''
}) })
asyncRouter.get('/middleware', [(req, res, next) => {
(req as any).testParam = 'middle'
next()
}, (req, res, next) => {
(req as any).testParam += 'ware'
next()
}], async req => {
const value = (req as any).testParam as string
return {value}
})
it('creates its own router when not provided', () => { it('creates its own router when not provided', () => {
const r = new AsyncRouter<IMyApi>() const r = new AsyncRouter<IMyApi>()
@ -69,5 +84,7 @@ describe('AsyncRouter', () => {
await request(app).options('/test/a').expect(200).expect('{"value":"a"}') await request(app).options('/test/a').expect(200).expect('{"value":"a"}')
await request(app).patch('/test/a').expect(500) await request(app).patch('/test/a').expect(500)
await request(app).head('/test/a').expect(200) await request(app).head('/test/a').expect(200)
await request(app).get('/middleware').expect(200)
.expect('{"value":"middleware"}')
}) })
}) })

View File

@ -1,6 +1,6 @@
import express from 'express' import express from 'express'
import {IRoutes, TMethod} from '@rondo/common' import {IRoutes, TMethod} from '@rondo/common'
import {TTypedHandler} from './TTypedHandler' import {TTypedHandler, TTypedMiddleware} from './TTypedHandler'
export class AsyncRouter<R extends IRoutes> { export class AsyncRouter<R extends IRoutes> {
readonly router: express.Router readonly router: express.Router
@ -14,11 +14,21 @@ export class AsyncRouter<R extends IRoutes> {
protected addRoute<M extends TMethod, P extends keyof R & string>( protected addRoute<M extends TMethod, P extends keyof R & string>(
method: M, method: M,
path: P, path: P,
handler: TTypedHandler<R, P, M>, ...handlers: [TTypedHandler<R, P, M>] | [
Array<TTypedMiddleware<R, P, M>>,
TTypedHandler<R, P, M>,
]
) { ) {
const addRoute = this.router[method].bind(this.router as any) const addRoute = this.router[method].bind(this.router as any)
addRoute(path, this.wrapHandler(handler)) if (handlers.length === 2) {
const middleware = handlers[0]
const handler = handlers[1]
addRoute(path, ...middleware, this.wrapHandler(handler))
} else {
addRoute(path, this.wrapHandler(handlers[0]))
}
} }
protected wrapHandler<M extends TMethod, P extends keyof R & string>( protected wrapHandler<M extends TMethod, P extends keyof R & string>(
@ -35,44 +45,72 @@ export class AsyncRouter<R extends IRoutes> {
get<P extends keyof R & string>( get<P extends keyof R & string>(
path: P, path: P,
handler: TTypedHandler<R, P, 'get'>, ...handlers: [TTypedHandler<R, P, 'get'>] | [
) { Array<TTypedMiddleware<R, P, 'get'>>,
this.addRoute('get', path, handler) TTypedHandler<R, P, 'get'>,
]
): void {
this.addRoute('get', path, ...handlers)
} }
post<P extends keyof R & string>( post<P extends keyof R & string>(
path: P, path: P,
handler: TTypedHandler<R, P, 'post'>, ...handlers: [TTypedHandler<R, P, 'post'>] | [
Array<TTypedMiddleware<R, P, 'post'>>,
TTypedHandler<R, P, 'post'>,
]
) { ) {
this.addRoute('post', path, handler) this.addRoute('post', path, ...handlers)
} }
put<P extends keyof R & string>( put<P extends keyof R & string>(
path: P, handler: TTypedHandler<R, P, 'put'>, path: P,
...handlers: [TTypedHandler<R, P, 'put'>] | [
Array<TTypedMiddleware<R, P, 'put'>>,
TTypedHandler<R, P, 'put'>,
]
) { ) {
this.addRoute('put', path, handler) this.addRoute('put', path, ...handlers)
} }
delete<P extends keyof R & string>( delete<P extends keyof R & string>(
path: P, handler: TTypedHandler<R, P, 'delete'>) { path: P,
this.addRoute('delete', path, handler) ...handlers: [TTypedHandler<R, P, 'delete'>] | [
Array<TTypedMiddleware<R, P, 'delete'>>,
TTypedHandler<R, P, 'delete'>,
]
) {
this.addRoute('delete', path, ...handlers)
} }
head<P extends keyof R & string>( head<P extends keyof R & string>(
path: P, path: P,
handler: TTypedHandler<R, P, 'head'>, ...handlers: [TTypedHandler<R, P, 'head'>] | [
Array<TTypedMiddleware<R, P, 'head'>>,
TTypedHandler<R, P, 'head'>,
]
) { ) {
this.addRoute('head', path, handler) this.addRoute('head', path, ...handlers)
} }
options<P extends keyof R & string>( options<P extends keyof R & string>(
path: P, handler: TTypedHandler<R, P, 'options'>) { path: P,
this.addRoute('options', path, handler) ...handlers: [TTypedHandler<R, P, 'options'>] | [
Array<TTypedMiddleware<R, P, 'options'>>,
TTypedHandler<R, P, 'options'>,
]
) {
this.addRoute('options', path, ...handlers)
} }
patch<P extends keyof R & string>( patch<P extends keyof R & string>(
path: P, handler: TTypedHandler<R, P, 'patch'>) { path: P,
this.addRoute('patch', path, handler) ...handlers: [TTypedHandler<R, P, 'patch'>] | [
Array<TTypedMiddleware<R, P, 'patch'>>,
TTypedHandler<R, P, 'patch'>,
]
) {
this.addRoute('patch', path, ...handlers)
} }
} }

View File

@ -2,6 +2,16 @@ import express from 'express'
import {IRoutes, TMethod} from '@rondo/common' import {IRoutes, TMethod} from '@rondo/common'
import {ITypedRequest} from './ITypedRequest' import {ITypedRequest} from './ITypedRequest'
export type TTypedMiddleware<
R extends IRoutes,
P extends keyof R,
M extends TMethod
> = (
req: ITypedRequest<R[P][M]>,
res: express.Response,
next: express.NextFunction,
) => void
export type TTypedHandler< export type TTypedHandler<
R extends IRoutes, R extends IRoutes,
P extends keyof R, P extends keyof R,