-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
106 lines (92 loc) · 2.83 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
import { Express, NextFunction, Request, Response } from 'express';
import 'reflect-metadata';
let debug = (...params: any[]) => {
// tslint:disable-next-line
console.log.apply(null, params);
};
export function setLogger(logger: (...params: any[]) => void) {
debug = logger;
}
type httpMethod =
'get'
| 'post'
| 'put'
| 'patch'
| 'head'
| 'options'
| 'connect'
| 'trace'
| 'delete';
interface IMethodDesc {
descriptor: PropertyDescriptor;
method: httpMethod;
path: string;
target: any;
}
interface IMiddlewaresDesc {
descriptor: PropertyDescriptor;
target: any;
middleware: Middleware;
}
let app: Express;
const routesToBind: IMethodDesc[] = [];
export function decoratorFactory(method: httpMethod) {
return (path: string) => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
if (routesToBind.some((routeDesc) => routeDesc.path === path)) {
throw Error(`Route ${path} has already been registred`);
}
routesToBind.push({
descriptor,
method,
path,
target,
});
};
};
}
export const Get = decoratorFactory('get');
export const Post = decoratorFactory('post');
export const Put = decoratorFactory('put');
export const Patch = decoratorFactory('patch');
export const Head = decoratorFactory('head');
export const Options = decoratorFactory('options');
export const Connect = decoratorFactory('connect');
export const Trace = decoratorFactory('trace');
export const Delete = decoratorFactory('delete');
type Middleware = (a: Request, b: Response, c: NextFunction) => void;
interface IMiddlewaresDesc {
descriptor: PropertyDescriptor;
middleware: Middleware;
target: any;
}
const middlewaresToBind: IMiddlewaresDesc[] = [];
export function middleware(fn: Middleware) {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
middlewaresToBind.push({
descriptor,
middleware: fn,
target,
});
};
}
export function bindApp(expApp: Express) {
app = expApp;
while (routesToBind.length > 0) {
const desc = routesToBind.pop();
const middlewares = [
...getMiddleWares(desc),
desc.descriptor.value];
app[desc.method](
desc.path,
...middlewares);
debug(`Registered: ${desc.method.toUpperCase()} ${desc.path}`);
}
}
function getMiddleWares(methodDesc: IMethodDesc): Middleware[] {
return middlewaresToBind
.filter((middlewaresDesc: IMiddlewaresDesc) =>
middlewaresDesc.target === methodDesc.target
&& middlewaresDesc.descriptor === methodDesc.descriptor)
.map((middlewaresDesc) => middlewaresDesc.middleware);
}