-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.ts
112 lines (108 loc) · 3.04 KB
/
index.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
111
112
import * as express from 'express-serve-static-core'
import {RestypedBase, RestypedRoute} from 'restyped'
export interface TypedRequest<T extends RestypedRoute> extends express.Request {
body: T['body']
params: T['params']
query: T['query']
}
type HTTPMethod =
| 'GET'
| 'POST'
| 'PUT'
| 'PATCH'
| 'HEAD'
| 'DELETE'
| 'OPTIONS'
export default function AsyncRouter<APIDef extends RestypedBase>(
app: express.Express | express.Router
) {
const createAsyncRoute = function<
Path extends keyof APIDef,
Method extends HTTPMethod
>(
path: Path,
method: Method,
handler: (
req: TypedRequest<APIDef[Path][Method]>,
res: express.Response
) => Promise<APIDef[Path][Method]['response']>
) {
const route: express.IRouterMatcher<void> = app[method.toLowerCase()]
route(path, function(req, res, next) {
return handler(req, res)
.then(result => {
if (!res.headersSent) {
res.send(result)
}
})
.catch(err => next(err))
})
}
return {
route: createAsyncRoute,
use: app.use.bind(app),
get: function<Path extends keyof APIDef>(
path: Path,
handler: (
req: TypedRequest<APIDef[Path]['GET']>,
res: express.Response
) => Promise<APIDef[Path]['GET']['response']>
) {
return createAsyncRoute(path, 'GET', handler)
},
post: function<Path extends keyof APIDef>(
path: Path,
handler: (
req: TypedRequest<APIDef[Path]['POST']>,
res: express.Response
) => Promise<APIDef[Path]['POST']['response']>
) {
return createAsyncRoute(path, 'POST', handler)
},
put: function<Path extends keyof APIDef>(
path: Path,
handler: (
req: TypedRequest<APIDef[Path]['PUT']>,
res: express.Response
) => Promise<APIDef[Path]['PUT']['response']>
) {
return createAsyncRoute(path, 'PUT', handler)
},
delete: function<Path extends keyof APIDef>(
path: Path,
handler: (
req: TypedRequest<APIDef[Path]['DELETE']>,
res: express.Response
) => Promise<APIDef[Path]['DELETE']['response']>
) {
return createAsyncRoute(path, 'DELETE', handler)
},
patch: function<Path extends keyof APIDef>(
path: Path,
handler: (
req: TypedRequest<APIDef[Path]['PATCH']>,
res: express.Response
) => Promise<APIDef[Path]['PATCH']['response']>
) {
return createAsyncRoute(path, 'PATCH', handler)
},
options: function<Path extends keyof APIDef>(
path: Path,
handler: (
req: TypedRequest<APIDef[Path]['OPTIONS']>,
res: express.Response
) => Promise<APIDef[Path]['OPTIONS']['response']>
) {
return createAsyncRoute(path, 'OPTIONS', handler)
},
head: function<Path extends keyof APIDef>(
path: Path,
handler: (
req: TypedRequest<APIDef[Path]['HEAD']>,
res: express.Response
) => Promise<APIDef[Path]['HEAD']['response']>
) {
return createAsyncRoute(path, 'HEAD', handler)
}
}
}