@e22m4u/ts-rest-router 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-ru.md +227 -0
- package/README.md +227 -0
- package/dist/cjs/index.cjs +448 -153
- package/dist/esm/controller-registry.d.ts +53 -11
- package/dist/esm/controller-registry.js +242 -104
- package/dist/esm/debuggable-service.js +1 -1
- package/dist/esm/decorators/action/action-decorator.d.ts +7 -8
- package/dist/esm/decorators/action/action-decorator.js +1 -5
- package/dist/esm/decorators/action/action-decorator.spec.js +16 -16
- package/dist/esm/decorators/action/action-metadata.d.ts +0 -1
- package/dist/esm/decorators/after/after-decorator.d.ts +9 -0
- package/dist/esm/decorators/after/after-decorator.js +22 -0
- package/dist/esm/decorators/after/after-decorator.spec.d.ts +1 -0
- package/dist/esm/decorators/after/after-decorator.spec.js +115 -0
- package/dist/esm/decorators/after/after-metadata.d.ts +13 -0
- package/dist/esm/decorators/after/after-metadata.js +5 -0
- package/dist/esm/decorators/after/after-reflector.d.ts +22 -0
- package/dist/esm/decorators/after/after-reflector.js +29 -0
- package/dist/esm/decorators/after/after-reflector.spec.d.ts +1 -0
- package/dist/esm/decorators/after/after-reflector.spec.js +102 -0
- package/dist/esm/decorators/after/index.d.ts +3 -0
- package/dist/esm/decorators/after/index.js +3 -0
- package/dist/esm/decorators/before/before-decorator.d.ts +9 -0
- package/dist/esm/decorators/before/before-decorator.js +22 -0
- package/dist/esm/decorators/before/before-decorator.spec.d.ts +1 -0
- package/dist/esm/decorators/before/before-decorator.spec.js +115 -0
- package/dist/esm/decorators/before/before-metadata.d.ts +13 -0
- package/dist/esm/decorators/before/before-metadata.js +5 -0
- package/dist/esm/decorators/before/before-reflector.d.ts +22 -0
- package/dist/esm/decorators/before/before-reflector.js +29 -0
- package/dist/esm/decorators/before/before-reflector.spec.d.ts +1 -0
- package/dist/esm/decorators/before/before-reflector.spec.js +102 -0
- package/dist/esm/decorators/before/index.d.ts +3 -0
- package/dist/esm/decorators/before/index.js +3 -0
- package/dist/esm/decorators/controller/controller-decorator.d.ts +2 -1
- package/dist/esm/decorators/controller/controller-decorator.js +27 -6
- package/dist/esm/decorators/controller/controller-decorator.spec.js +37 -15
- package/dist/esm/decorators/controller/controller-metadata.d.ts +0 -1
- package/dist/esm/decorators/index.d.ts +2 -0
- package/dist/esm/decorators/index.js +2 -0
- package/dist/esm/decorators/request-context/request-context-decorator.d.ts +2 -3
- package/dist/esm/decorators/request-context/request-context-decorator.js +3 -6
- package/dist/esm/decorators/request-context/request-context-decorator.spec.js +2 -17
- package/dist/esm/decorators/request-context/request-context-metadata.d.ts +0 -1
- package/dist/esm/decorators/request-data/request-data-decorator.d.ts +7 -3
- package/dist/esm/decorators/request-data/request-data-decorator.js +16 -16
- package/dist/esm/decorators/request-data/request-data-decorator.spec.js +12 -10
- package/dist/esm/decorators/request-data/request-data-metadata.d.ts +0 -1
- package/dist/esm/utils/create-debugger.d.ts +35 -2
- package/dist/esm/utils/create-debugger.js +71 -5
- package/package.json +17 -17
- package/src/controller-registry.spec.ts +601 -275
- package/src/controller-registry.ts +263 -128
- package/src/debuggable-service.ts +1 -1
- package/src/decorators/action/action-decorator.spec.ts +16 -16
- package/src/decorators/action/action-decorator.ts +10 -12
- package/src/decorators/action/action-metadata.ts +0 -1
- package/src/decorators/after/after-decorator.spec.ts +92 -0
- package/src/decorators/after/after-decorator.ts +40 -0
- package/src/decorators/after/after-metadata.ts +17 -0
- package/src/decorators/after/after-reflector.spec.ts +107 -0
- package/src/decorators/after/after-reflector.ts +45 -0
- package/src/decorators/after/index.ts +3 -0
- package/src/decorators/before/before-decorator.spec.ts +92 -0
- package/src/decorators/before/before-decorator.ts +40 -0
- package/src/decorators/before/before-metadata.ts +17 -0
- package/src/decorators/before/before-reflector.spec.ts +111 -0
- package/src/decorators/before/before-reflector.ts +50 -0
- package/src/decorators/before/index.ts +3 -0
- package/src/decorators/controller/controller-decorator.spec.ts +33 -16
- package/src/decorators/controller/controller-decorator.ts +33 -6
- package/src/decorators/controller/controller-metadata.ts +0 -1
- package/src/decorators/index.ts +2 -0
- package/src/decorators/request-context/request-context-decorator.spec.ts +2 -15
- package/src/decorators/request-context/request-context-decorator.ts +3 -8
- package/src/decorators/request-context/request-context-metadata.ts +0 -1
- package/src/decorators/request-data/request-data-decorator.spec.ts +12 -11
- package/src/decorators/request-data/request-data-decorator.ts +41 -16
- package/src/decorators/request-data/request-data-metadata.ts +0 -1
- package/src/utils/create-debugger.ts +84 -7
@@ -4,14 +4,15 @@ import {Errorf} from '@e22m4u/js-format';
|
|
4
4
|
import {TrieRouter} from '@e22m4u/js-trie-router';
|
5
5
|
import {RouteHandler} from '@e22m4u/js-trie-router';
|
6
6
|
import {DataValidator} from '@e22m4u/ts-data-schema';
|
7
|
+
import {AfterReflector} from './decorators/index.js';
|
7
8
|
import {DataTypeCaster} from '@e22m4u/ts-data-schema';
|
8
9
|
import {ActionReflector} from './decorators/index.js';
|
10
|
+
import {BeforeReflector} from './decorators/index.js';
|
9
11
|
import {NotAControllerError} from './errors/index.js';
|
10
12
|
import {RequestContext} from '@e22m4u/js-trie-router';
|
11
13
|
import {RoutePreHandler} from '@e22m4u/js-trie-router';
|
12
14
|
import {RoutePostHandler} from '@e22m4u/js-trie-router';
|
13
15
|
import {RequestDataSource} from './decorators/index.js';
|
14
|
-
import {ControllerMetadata} from './decorators/index.js';
|
15
16
|
import {DebuggableService} from './debuggable-service.js';
|
16
17
|
import {ControllerReflector} from './decorators/index.js';
|
17
18
|
import {RequestDataReflector} from './decorators/index.js';
|
@@ -45,6 +46,7 @@ export class ControllerRegistry extends DebuggableService {
|
|
45
46
|
ctor: Constructor<T>,
|
46
47
|
options?: ControllerRootOptions,
|
47
48
|
): this {
|
49
|
+
const debug = this.debug.bind(this.addController.name);
|
48
50
|
// проверка повторной регистрации помогает
|
49
51
|
// заметить ошибку в коде, который использует
|
50
52
|
// интерфейс данного сервиса
|
@@ -55,66 +57,66 @@ export class ControllerRegistry extends DebuggableService {
|
|
55
57
|
// метаданных применяемых декоратором
|
56
58
|
const controllerMd = ControllerReflector.getMetadata(ctor);
|
57
59
|
if (!controllerMd) throw new NotAControllerError(ctor);
|
58
|
-
|
60
|
+
debug('Adding controller %s.', ctor.name);
|
59
61
|
// определение префикса применяемого
|
60
62
|
// к маршрутам контроллера
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
);
|
65
|
-
|
63
|
+
let pathPrefix = '';
|
64
|
+
pathPrefix += this.getPathPrefixFromControllerRootOptions(options);
|
65
|
+
pathPrefix += '/';
|
66
|
+
pathPrefix += this.getPathPrefixFromControllerMetadata(ctor);
|
67
|
+
pathPrefix = pathPrefix.replace(/\/{2,}/g, '/').replace(/\/$/, '');
|
68
|
+
debug('Controller path prefix is %v.', pathPrefix);
|
66
69
|
// подготовка pre-обработчиков
|
67
|
-
const preHandlers =
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
70
|
+
const preHandlers = [
|
71
|
+
...this.getPreHandlersFromControllerRootOptions(options),
|
72
|
+
...this.getPreHandlersFromBeforeMetadata(ctor),
|
73
|
+
...this.getPreHandlersFromControllerMetadata(ctor),
|
74
|
+
];
|
75
|
+
debug('Controller has %v pre-handlers.', preHandlers.length);
|
72
76
|
// подготовка post-обработчиков
|
73
|
-
const postHandlers =
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
77
|
+
const postHandlers = [
|
78
|
+
...this.getPostHandlersFromControllerRootOptions(options),
|
79
|
+
...this.getPostHandlersFromAfterMetadata(ctor),
|
80
|
+
...this.getPostHandlersFromControllerMetadata(ctor),
|
81
|
+
];
|
82
|
+
debug('Controller has %v post-handlers.', postHandlers.length);
|
78
83
|
// обход всех операций контроллера
|
79
84
|
// для определения маршрутов
|
80
85
|
const actionsMd = ActionReflector.getMetadata(ctor);
|
81
|
-
|
86
|
+
debug('%v actions found.', actionsMd.size);
|
82
87
|
const router = this.getService(TrieRouter);
|
83
88
|
actionsMd.forEach((actionMd, actionName) => {
|
84
|
-
|
89
|
+
debug('Adding route for %s.%s.', ctor.name, actionName);
|
85
90
|
// подготовка пути маршрута с префиксом
|
86
|
-
|
87
|
-
const prefixedRoutePath = `${pathPrefix}/${actionMd.path}
|
88
|
-
|
89
|
-
'
|
90
|
-
);
|
91
|
-
this.debug('Prefixed route path is %v.', prefixedRoutePath);
|
91
|
+
debug('Route path is %v.', actionMd.path);
|
92
|
+
const prefixedRoutePath = `${pathPrefix}/${actionMd.path}`
|
93
|
+
.replace(/\/{2,}/g, '/')
|
94
|
+
.replace(/\/$/, '');
|
95
|
+
debug('Prefixed route path is %v.', prefixedRoutePath);
|
92
96
|
// подготовка pre-обработчиков операции
|
93
|
-
const actionPreHandlers =
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
const mergedPreHandlers = [...preHandlers, ...actionPreHandlers];
|
97
|
+
const actionPreHandlers = [
|
98
|
+
...preHandlers,
|
99
|
+
...this.getPreHandlersFromBeforeMetadata(ctor, actionName),
|
100
|
+
...this.getPreHandlersFromActionMetadata(ctor, actionName),
|
101
|
+
];
|
102
|
+
debug('%v action pre-handlers in total.', actionPreHandlers.length);
|
100
103
|
// подготовка post-обработчиков операции
|
101
|
-
const actionPostHandlers =
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
const mergedPostHandlers = [...postHandlers, ...actionPostHandlers];
|
104
|
+
const actionPostHandlers = [
|
105
|
+
...postHandlers,
|
106
|
+
...this.getPostHandlersFromAfterMetadata(ctor, actionName),
|
107
|
+
...this.getPostHandlersFromActionMetadata(ctor, actionName),
|
108
|
+
];
|
109
|
+
debug('%v action post-handlers in total.', actionPostHandlers.length);
|
108
110
|
// подготовка обработчика маршрута
|
109
111
|
const routeHandler = this.createRouteHandler(ctor, actionName);
|
110
112
|
router.defineRoute({
|
111
113
|
method: actionMd.method,
|
112
114
|
path: prefixedRoutePath,
|
113
|
-
preHandler:
|
115
|
+
preHandler: actionPreHandlers,
|
114
116
|
handler: routeHandler,
|
115
|
-
postHandler:
|
117
|
+
postHandler: actionPostHandlers,
|
116
118
|
});
|
117
|
-
|
119
|
+
debug(
|
118
120
|
'Route %s %v is added.',
|
119
121
|
actionMd.method.toUpperCase(),
|
120
122
|
prefixedRoutePath,
|
@@ -134,90 +136,229 @@ export class ControllerRegistry extends DebuggableService {
|
|
134
136
|
}
|
135
137
|
|
136
138
|
/**
|
137
|
-
* Get path prefix
|
139
|
+
* Get path prefix from controller root options.
|
138
140
|
*
|
139
|
-
* @param controllerMd
|
140
141
|
* @param options
|
141
142
|
*/
|
142
|
-
|
143
|
-
controllerMd: ControllerMetadata,
|
143
|
+
protected getPathPrefixFromControllerRootOptions(
|
144
144
|
options?: ControllerRootOptions,
|
145
145
|
) {
|
146
|
-
const
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
const
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
146
|
+
const debug = this.debug.bind(
|
147
|
+
this.getPathPrefixFromControllerRootOptions.name,
|
148
|
+
);
|
149
|
+
debug('Getting path prefix from controller root options.');
|
150
|
+
const res = options?.pathPrefix || '';
|
151
|
+
debug('Controller path prefix is %v.', res);
|
152
|
+
return res;
|
153
|
+
}
|
154
|
+
|
155
|
+
/**
|
156
|
+
* Get path prefix from controller metadata.
|
157
|
+
*
|
158
|
+
* @param ctor
|
159
|
+
*/
|
160
|
+
protected getPathPrefixFromControllerMetadata<T>(ctor: Constructor<T>) {
|
161
|
+
const debug = this.debug.bind(
|
162
|
+
this.getPathPrefixFromControllerMetadata.name,
|
163
|
+
);
|
164
|
+
debug('Getting path prefix from @controller metadata.');
|
165
|
+
debug('Metadata target is %s.', ctor.name);
|
166
|
+
const md = ControllerReflector.getMetadata(ctor);
|
167
|
+
if (!md) throw new Errorf('Controller %v has no metadata.', ctor);
|
168
|
+
const res = md.path || '';
|
169
|
+
debug('Controller path prefix is %v.', res);
|
170
|
+
return md.path || '';
|
155
171
|
}
|
156
172
|
|
157
173
|
/**
|
158
|
-
*
|
174
|
+
* Getting pre-handlers from controller root options.
|
159
175
|
*
|
160
|
-
* @param controllerMd
|
161
176
|
* @param options
|
162
177
|
*/
|
163
|
-
|
164
|
-
controllerMd: ControllerMetadata,
|
178
|
+
protected getPreHandlersFromControllerRootOptions(
|
165
179
|
options?: ControllerRootOptions,
|
166
180
|
) {
|
167
|
-
|
168
|
-
|
169
|
-
|
181
|
+
const debug = this.debug.bind(
|
182
|
+
this.getPreHandlersFromControllerRootOptions.name,
|
183
|
+
);
|
184
|
+
debug('Getting pre-handlers from controller root options.');
|
185
|
+
let res: RoutePreHandler[] = [];
|
170
186
|
if (options?.before)
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
this.debug('%v root pre-handlers found.', rootPreHandlers.length);
|
175
|
-
// подготовка pre-обработчиков
|
176
|
-
// запроса контроллера
|
177
|
-
let ctlPreHandlers: RoutePreHandler[] = [];
|
178
|
-
if (controllerMd.before)
|
179
|
-
ctlPreHandlers = Array.isArray(controllerMd.before)
|
180
|
-
? controllerMd.before
|
181
|
-
: [controllerMd.before];
|
182
|
-
this.debug('%v controller pre-handlers found.', ctlPreHandlers.length);
|
183
|
-
// подготовка объединенного набора
|
184
|
-
// pre-обработчиков запроса
|
185
|
-
const mergedPreHandlers = [...rootPreHandlers, ...ctlPreHandlers];
|
186
|
-
this.debug('%v merged pre-handlers.', mergedPreHandlers.length);
|
187
|
-
return mergedPreHandlers;
|
187
|
+
res = Array.isArray(options.before) ? options.before : [options.before];
|
188
|
+
debug('%v pre-handlers found.', res.length);
|
189
|
+
return res;
|
188
190
|
}
|
189
191
|
|
190
192
|
/**
|
191
|
-
*
|
193
|
+
* Getting post-handlers from controller root options.
|
192
194
|
*
|
193
|
-
* @param controllerMd
|
194
195
|
* @param options
|
195
196
|
*/
|
196
|
-
|
197
|
-
controllerMd: ControllerMetadata,
|
197
|
+
protected getPostHandlersFromControllerRootOptions(
|
198
198
|
options?: ControllerRootOptions,
|
199
199
|
) {
|
200
|
-
|
201
|
-
|
202
|
-
|
200
|
+
const debug = this.debug.bind(
|
201
|
+
this.getPostHandlersFromControllerRootOptions.name,
|
202
|
+
);
|
203
|
+
debug('Getting post-handlers from controller root options.');
|
204
|
+
let res: RoutePostHandler[] = [];
|
203
205
|
if (options?.after)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
this.debug(
|
220
|
-
|
206
|
+
res = Array.isArray(options.after) ? options.after : [options.after];
|
207
|
+
debug('%v post-handlers found.', res.length);
|
208
|
+
return res;
|
209
|
+
}
|
210
|
+
|
211
|
+
/**
|
212
|
+
* Get pre-handlers from before metadata.
|
213
|
+
*
|
214
|
+
* @param ctor
|
215
|
+
* @param actionName
|
216
|
+
*/
|
217
|
+
protected getPreHandlersFromBeforeMetadata<T>(
|
218
|
+
ctor: Constructor<T>,
|
219
|
+
actionName?: string,
|
220
|
+
) {
|
221
|
+
const debug = this.debug.bind(this.getPreHandlersFromBeforeMetadata.name);
|
222
|
+
debug('Getting pre-handlers from @before metadata.');
|
223
|
+
if (actionName) {
|
224
|
+
debug('Target is %s.%s.', ctor.name, actionName);
|
225
|
+
} else {
|
226
|
+
debug('Target is %s.', ctor.name);
|
227
|
+
}
|
228
|
+
let preHandlers: RoutePreHandler[] = [];
|
229
|
+
const mdArray = BeforeReflector.getMetadata(ctor, actionName);
|
230
|
+
mdArray.forEach(md => {
|
231
|
+
if (Array.isArray(md.middleware)) {
|
232
|
+
preHandlers = [...preHandlers, ...md.middleware];
|
233
|
+
} else {
|
234
|
+
preHandlers.push(md.middleware);
|
235
|
+
}
|
236
|
+
});
|
237
|
+
if (mdArray.length) {
|
238
|
+
debug('%v pre-handlers found.', mdArray.length);
|
239
|
+
} else {
|
240
|
+
debug('No pre-handlers found.');
|
241
|
+
}
|
242
|
+
return preHandlers;
|
243
|
+
}
|
244
|
+
|
245
|
+
/**
|
246
|
+
* Get post-handlers from after metadata.
|
247
|
+
*
|
248
|
+
* @param ctor
|
249
|
+
* @param actionName
|
250
|
+
*/
|
251
|
+
protected getPostHandlersFromAfterMetadata<T>(
|
252
|
+
ctor: Constructor<T>,
|
253
|
+
actionName?: string,
|
254
|
+
) {
|
255
|
+
const debug = this.debug.bind(this.getPostHandlersFromAfterMetadata.name);
|
256
|
+
debug('Getting post-handlers from @after metadata.');
|
257
|
+
if (actionName) {
|
258
|
+
debug('Target is %s.%s.', ctor.name, actionName);
|
259
|
+
} else {
|
260
|
+
debug('Target is %s.', ctor.name);
|
261
|
+
}
|
262
|
+
let res: RoutePostHandler[] = [];
|
263
|
+
const mdArray = AfterReflector.getMetadata(ctor, actionName);
|
264
|
+
mdArray.forEach(md => {
|
265
|
+
if (Array.isArray(md.middleware)) {
|
266
|
+
res = [...res, ...md.middleware];
|
267
|
+
} else {
|
268
|
+
res.push(md.middleware);
|
269
|
+
}
|
270
|
+
});
|
271
|
+
if (mdArray.length) {
|
272
|
+
debug('%v post-handlers found.', mdArray.length);
|
273
|
+
} else {
|
274
|
+
debug('No post-handlers found.');
|
275
|
+
}
|
276
|
+
return res;
|
277
|
+
}
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Get pre-handlers from controller metadata.
|
281
|
+
*
|
282
|
+
* @param ctor
|
283
|
+
*/
|
284
|
+
protected getPreHandlersFromControllerMetadata<T>(ctor: Constructor<T>) {
|
285
|
+
const debug = this.debug.bind(
|
286
|
+
this.getPreHandlersFromControllerMetadata.name,
|
287
|
+
);
|
288
|
+
debug('Getting pre-handlers from @controller metadata.');
|
289
|
+
debug('Target is %s.', ctor.name);
|
290
|
+
const md = ControllerReflector.getMetadata(ctor);
|
291
|
+
if (!md) throw new Errorf('Controller %v has no metadata.', ctor);
|
292
|
+
let res: RoutePreHandler[] = [];
|
293
|
+
if (md.before) res = Array.isArray(md.before) ? md.before : [md.before];
|
294
|
+
debug('%v pre-handlers found.', res.length);
|
295
|
+
return res;
|
296
|
+
}
|
297
|
+
|
298
|
+
/**
|
299
|
+
* Get post-handlers from controller metadata.
|
300
|
+
*
|
301
|
+
* @param ctor
|
302
|
+
*/
|
303
|
+
protected getPostHandlersFromControllerMetadata<T>(ctor: Constructor<T>) {
|
304
|
+
const debug = this.debug.bind(
|
305
|
+
this.getPostHandlersFromControllerMetadata.name,
|
306
|
+
);
|
307
|
+
debug('Getting post-handlers from @controller metadata.');
|
308
|
+
const md = ControllerReflector.getMetadata(ctor);
|
309
|
+
if (!md) throw new Errorf('Controller %v has no metadata.', ctor);
|
310
|
+
let res: RoutePostHandler[] = [];
|
311
|
+
if (md.after) res = Array.isArray(md.after) ? md.after : [md.after];
|
312
|
+
debug('%v post-handlers found.', res.length);
|
313
|
+
return res;
|
314
|
+
}
|
315
|
+
|
316
|
+
/**
|
317
|
+
* Get pre-handlers from action metadata.
|
318
|
+
*
|
319
|
+
* @param ctor
|
320
|
+
* @param actionName
|
321
|
+
*/
|
322
|
+
protected getPreHandlersFromActionMetadata<T>(
|
323
|
+
ctor: Constructor<T>,
|
324
|
+
actionName: string,
|
325
|
+
) {
|
326
|
+
const debug = this.debug.bind(this.getPreHandlersFromActionMetadata.name);
|
327
|
+
debug('Getting pre-handlers from @action metadata.');
|
328
|
+
const actionsMd = ActionReflector.getMetadata(ctor);
|
329
|
+
const actionMd = actionsMd.get(actionName);
|
330
|
+
if (!actionMd)
|
331
|
+
throw new Errorf('Action %s.%s has no metadata.', ctor.name, actionName);
|
332
|
+
let res: RoutePreHandler[] = [];
|
333
|
+
if (actionMd.before)
|
334
|
+
res = Array.isArray(actionMd.before)
|
335
|
+
? actionMd.before
|
336
|
+
: [actionMd.before];
|
337
|
+
debug('%v pre-handlers found.', res.length);
|
338
|
+
return res;
|
339
|
+
}
|
340
|
+
|
341
|
+
/**
|
342
|
+
* Get post-handlers from action metadata.
|
343
|
+
*
|
344
|
+
* @param ctor
|
345
|
+
* @param actionName
|
346
|
+
*/
|
347
|
+
protected getPostHandlersFromActionMetadata<T>(
|
348
|
+
ctor: Constructor<T>,
|
349
|
+
actionName: string,
|
350
|
+
) {
|
351
|
+
const debug = this.debug.bind(this.getPreHandlersFromActionMetadata.name);
|
352
|
+
debug('Getting post-handlers from @action metadata.');
|
353
|
+
const actionsMd = ActionReflector.getMetadata(ctor);
|
354
|
+
const actionMd = actionsMd.get(actionName);
|
355
|
+
if (!actionMd)
|
356
|
+
throw new Errorf('Action %s.%s has no metadata.', ctor.name, actionName);
|
357
|
+
let res: RoutePostHandler[] = [];
|
358
|
+
if (actionMd.after)
|
359
|
+
res = Array.isArray(actionMd.after) ? actionMd.after : [actionMd.after];
|
360
|
+
debug('%v pre-handlers found.', res.length);
|
361
|
+
return res;
|
221
362
|
}
|
222
363
|
|
223
364
|
/**
|
@@ -227,15 +368,12 @@ export class ControllerRegistry extends DebuggableService {
|
|
227
368
|
* @param actionName
|
228
369
|
* @protected
|
229
370
|
*/
|
230
|
-
createRouteHandler<T extends object>(
|
371
|
+
protected createRouteHandler<T extends object>(
|
231
372
|
controllerCtor: Constructor<T>,
|
232
373
|
actionName: string,
|
233
374
|
): RouteHandler {
|
234
|
-
this.debug(
|
235
|
-
|
236
|
-
controllerCtor.name,
|
237
|
-
actionName,
|
238
|
-
);
|
375
|
+
const debug = this.debug.bind(this.createRouteHandler.name);
|
376
|
+
debug('Creating route handler for %s.%s.', controllerCtor.name, actionName);
|
239
377
|
const requestContextMetadataMap = RequestContextReflector.getMetadata(
|
240
378
|
controllerCtor,
|
241
379
|
actionName,
|
@@ -248,7 +386,7 @@ export class ControllerRegistry extends DebuggableService {
|
|
248
386
|
const dataTypeCaster = this.getService(DataTypeCaster);
|
249
387
|
const dataValidator = this.getService(DataValidator);
|
250
388
|
return (requestContext: RequestContext) => {
|
251
|
-
|
389
|
+
debug(
|
252
390
|
'Executing route handler for %s.%s.',
|
253
391
|
controllerCtor.name,
|
254
392
|
actionName,
|
@@ -260,13 +398,13 @@ export class ControllerRegistry extends DebuggableService {
|
|
260
398
|
// значениями из контекста запроса
|
261
399
|
const requestContextMd = requestContextMetadataMap.get(index);
|
262
400
|
if (requestContextMd != null) {
|
263
|
-
|
401
|
+
debug('Argument %v has request context metadata.', index);
|
264
402
|
// если свойство контекста не определено,
|
265
403
|
// то используем весь объект контекста
|
266
404
|
// в качестве значения текущего аргумента
|
267
405
|
if (requestContextMd.property == null) {
|
268
|
-
|
269
|
-
|
406
|
+
debug('Request context property is not specified.');
|
407
|
+
debug('Argument %v is set to %v.', index, requestContext);
|
270
408
|
return requestContext;
|
271
409
|
}
|
272
410
|
// если свойство контекста определено,
|
@@ -274,11 +412,11 @@ export class ControllerRegistry extends DebuggableService {
|
|
274
412
|
// в качестве текущего аргумента
|
275
413
|
const propName = requestContextMd.property;
|
276
414
|
const propValue = requestContext[propName];
|
277
|
-
|
278
|
-
|
415
|
+
debug('Request context property is %v.', propName);
|
416
|
+
debug('Argument %v is set to %v.', index, propValue);
|
279
417
|
return propValue;
|
280
418
|
} else {
|
281
|
-
|
419
|
+
debug(
|
282
420
|
'No RequestContextMetadata specified for %v argument.',
|
283
421
|
index,
|
284
422
|
);
|
@@ -287,7 +425,7 @@ export class ControllerRegistry extends DebuggableService {
|
|
287
425
|
// значениями из данных запроса
|
288
426
|
const requestDataMd = requestDataMetadataMap.get(index);
|
289
427
|
if (requestDataMd != null) {
|
290
|
-
|
428
|
+
debug('Argument %v has request data metadata.', index);
|
291
429
|
// получение данных
|
292
430
|
// согласно источнику
|
293
431
|
let data: unknown;
|
@@ -308,7 +446,7 @@ export class ControllerRegistry extends DebuggableService {
|
|
308
446
|
data = requestContext.body;
|
309
447
|
break;
|
310
448
|
}
|
311
|
-
|
449
|
+
debug('Request data source is %v.', requestDataMd.source);
|
312
450
|
// при наличии схемы данных выполняется
|
313
451
|
// их конвертация и валидация
|
314
452
|
if (requestDataMd.schema) {
|
@@ -316,20 +454,20 @@ export class ControllerRegistry extends DebuggableService {
|
|
316
454
|
noTypeCastError: true,
|
317
455
|
sourcePath: requestDataMd.source,
|
318
456
|
});
|
319
|
-
|
457
|
+
debug('Data type casting is passed.');
|
320
458
|
dataValidator.validate(
|
321
459
|
data,
|
322
460
|
requestDataMd.schema,
|
323
461
|
requestDataMd.source,
|
324
462
|
);
|
325
|
-
|
463
|
+
debug('Data validation is passed.');
|
326
464
|
}
|
327
465
|
// если свойство данных не определено,
|
328
466
|
// то используем весь объекта данных
|
329
467
|
// в качестве значения текущего аргумента
|
330
468
|
if (requestDataMd.property == null) {
|
331
|
-
|
332
|
-
|
469
|
+
debug('Request data property is not specified.');
|
470
|
+
debug('Argument %v is set to %v.', index, data);
|
333
471
|
return data;
|
334
472
|
}
|
335
473
|
// если свойство данных определено,
|
@@ -338,14 +476,11 @@ export class ControllerRegistry extends DebuggableService {
|
|
338
476
|
const dataAsObject = data as Record<string, unknown>;
|
339
477
|
const propName = requestDataMd.property;
|
340
478
|
const propValue = dataAsObject[propName];
|
341
|
-
|
342
|
-
|
479
|
+
debug('Request data property is %v.', propName);
|
480
|
+
debug('Argument %v is set to %v.', index, propValue);
|
343
481
|
return propValue;
|
344
482
|
} else {
|
345
|
-
|
346
|
-
'No RequestDataMetadata specified for %v argument.',
|
347
|
-
index,
|
348
|
-
);
|
483
|
+
debug('No RequestDataMetadata specified for %v argument.', index);
|
349
484
|
}
|
350
485
|
});
|
351
486
|
// выполнение операции контроллера
|
@@ -22,6 +22,6 @@ export class DebuggableService extends Service {
|
|
22
22
|
super(container);
|
23
23
|
const serviceName = toCamelCase(this.constructor.name);
|
24
24
|
this.debug = createDebugger(serviceName);
|
25
|
-
this.debug('
|
25
|
+
this.debug.bind('constructor')('Service created.');
|
26
26
|
}
|
27
27
|
}
|
@@ -5,38 +5,38 @@ import {ActionReflector} from './action-reflector.js';
|
|
5
5
|
|
6
6
|
describe('action', function () {
|
7
7
|
it('sets given options to the target metadata', function () {
|
8
|
-
const
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
const options = {
|
9
|
+
method: HttpMethod.GET,
|
10
|
+
path: 'myPath',
|
11
|
+
before: () => undefined,
|
12
|
+
after: () => undefined,
|
13
|
+
customOption: 'customOption',
|
14
|
+
};
|
13
15
|
class Target {
|
14
|
-
@action(
|
16
|
+
@action(options)
|
15
17
|
method() {}
|
16
18
|
}
|
17
19
|
const res = ActionReflector.getMetadata(Target);
|
18
20
|
expect(res.get('method')).to.be.eql({
|
21
|
+
...options,
|
19
22
|
propertyKey: 'method',
|
20
|
-
method,
|
21
|
-
path,
|
22
|
-
before,
|
23
|
-
after,
|
24
|
-
customOption,
|
25
23
|
});
|
26
24
|
});
|
27
25
|
|
28
26
|
it('overrides a given "propertyKey" option by the target method name', function () {
|
29
|
-
const
|
30
|
-
|
27
|
+
const options = {
|
28
|
+
propertyKey: 'myMethod',
|
29
|
+
method: HttpMethod.GET,
|
30
|
+
path: 'myPath',
|
31
|
+
};
|
31
32
|
class Target {
|
32
|
-
@action(
|
33
|
+
@action(options)
|
33
34
|
method() {}
|
34
35
|
}
|
35
36
|
const res = ActionReflector.getMetadata(Target);
|
36
37
|
expect(res.get('method')).to.be.eql({
|
38
|
+
...options,
|
37
39
|
propertyKey: 'method',
|
38
|
-
method,
|
39
|
-
path,
|
40
40
|
});
|
41
41
|
});
|
42
42
|
});
|