@e22m4u/ts-rest-router 0.2.1 → 0.2.2
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/dist/cjs/index.cjs +81 -21
- package/dist/esm/decorators/index.d.ts +1 -0
- package/dist/esm/decorators/index.js +1 -0
- package/dist/esm/decorators/request-data/request-data-decorator.d.ts +11 -11
- package/dist/esm/decorators/request-data/request-data-decorator.js +3 -3
- package/dist/esm/decorators/response-body/index.d.ts +3 -0
- package/dist/esm/decorators/response-body/index.js +3 -0
- package/dist/esm/decorators/response-body/response-body-decorator.d.ts +9 -0
- package/dist/esm/decorators/response-body/response-body-decorator.js +23 -0
- package/dist/esm/decorators/response-body/response-body-decorator.spec.d.ts +1 -0
- package/dist/esm/decorators/response-body/response-body-decorator.spec.js +61 -0
- package/dist/esm/decorators/response-body/response-body-metadata.d.ts +16 -0
- package/dist/esm/decorators/response-body/response-body-metadata.js +5 -0
- package/dist/esm/decorators/response-body/response-body-reflector.d.ts +22 -0
- package/dist/esm/decorators/response-body/response-body-reflector.js +29 -0
- package/dist/esm/decorators/response-body/response-body-reflector.spec.d.ts +1 -0
- package/dist/esm/decorators/response-body/response-body-reflector.spec.js +58 -0
- package/package.json +8 -8
- package/src/decorators/index.ts +1 -0
- package/src/decorators/request-data/request-data-decorator.ts +3 -11
- package/src/decorators/response-body/index.ts +3 -0
- package/src/decorators/response-body/response-body-decorator.spec.ts +40 -0
- package/src/decorators/response-body/response-body-decorator.ts +43 -0
- package/src/decorators/response-body/response-body-metadata.ts +20 -0
- package/src/decorators/response-body/response-body-reflector.spec.ts +59 -0
- package/src/decorators/response-body/response-body-reflector.ts +41 -0
package/dist/cjs/index.cjs
CHANGED
@@ -29,11 +29,13 @@ __export(index_exports, {
|
|
29
29
|
NotAControllerError: () => NotAControllerError,
|
30
30
|
REQUEST_CONTEXT_METADATA_KEY: () => REQUEST_CONTEXT_METADATA_KEY,
|
31
31
|
REQUEST_DATA_METADATA_KEY: () => REQUEST_DATA_METADATA_KEY,
|
32
|
+
RESPONSE_BODY_METADATA_KEY: () => RESPONSE_BODY_METADATA_KEY,
|
32
33
|
REST_ACTIONS_METADATA_KEY: () => REST_ACTIONS_METADATA_KEY,
|
33
34
|
REST_CONTROLLER_METADATA_KEY: () => REST_CONTROLLER_METADATA_KEY,
|
34
35
|
RequestContextReflector: () => RequestContextReflector,
|
35
36
|
RequestDataReflector: () => RequestDataReflector,
|
36
37
|
RequestDataSource: () => RequestDataSource,
|
38
|
+
ResponseBodyReflector: () => ResponseBodyReflector,
|
37
39
|
RestActionReflector: () => RestActionReflector,
|
38
40
|
RestControllerReflector: () => RestControllerReflector,
|
39
41
|
RestRouter: () => RestRouter,
|
@@ -60,6 +62,7 @@ __export(index_exports, {
|
|
60
62
|
requestParams: () => requestParams,
|
61
63
|
requestQueries: () => requestQueries,
|
62
64
|
requestQuery: () => requestQuery,
|
65
|
+
responseBody: () => responseBody,
|
63
66
|
restAction: () => restAction,
|
64
67
|
restController: () => restController,
|
65
68
|
toCamelCase: () => toCamelCase
|
@@ -281,11 +284,11 @@ var RequestDataReflector = _RequestDataReflector;
|
|
281
284
|
|
282
285
|
// dist/esm/decorators/request-data/request-data-decorator.js
|
283
286
|
function requestData(options) {
|
284
|
-
return function(target, propertyKey,
|
285
|
-
const decoratorType = (0, import_ts_reflector8.getDecoratorTargetType)(target, propertyKey,
|
287
|
+
return function(target, propertyKey, index) {
|
288
|
+
const decoratorType = (0, import_ts_reflector8.getDecoratorTargetType)(target, propertyKey, index);
|
286
289
|
if (decoratorType !== import_ts_reflector7.DecoratorTargetType.INSTANCE_METHOD_PARAMETER)
|
287
290
|
throw new Error("@requestData decorator is only supported on an instance method parameter.");
|
288
|
-
RequestDataReflector.setMetadata(options, target.constructor,
|
291
|
+
RequestDataReflector.setMetadata(options, target.constructor, index, propertyKey);
|
289
292
|
};
|
290
293
|
}
|
291
294
|
__name(requestData, "requestData");
|
@@ -437,16 +440,70 @@ function beforeAction(middleware) {
|
|
437
440
|
}
|
438
441
|
__name(beforeAction, "beforeAction");
|
439
442
|
|
440
|
-
// dist/esm/decorators/
|
443
|
+
// dist/esm/decorators/response-body/response-body-metadata.js
|
441
444
|
var import_ts_reflector17 = require("@e22m4u/ts-reflector");
|
442
|
-
var
|
445
|
+
var RESPONSE_BODY_METADATA_KEY = new import_ts_reflector17.MetadataKey("responseBodyMetadataKey");
|
443
446
|
|
444
|
-
// dist/esm/decorators/
|
447
|
+
// dist/esm/decorators/response-body/response-body-decorator.js
|
445
448
|
var import_ts_reflector19 = require("@e22m4u/ts-reflector");
|
446
449
|
var import_ts_reflector20 = require("@e22m4u/ts-reflector");
|
447
450
|
|
448
|
-
// dist/esm/decorators/
|
451
|
+
// dist/esm/decorators/response-body/response-body-reflector.js
|
449
452
|
var import_ts_reflector18 = require("@e22m4u/ts-reflector");
|
453
|
+
var _ResponseBodyReflector = class _ResponseBodyReflector {
|
454
|
+
/**
|
455
|
+
* Set metadata.
|
456
|
+
*
|
457
|
+
* @param metadata
|
458
|
+
* @param target
|
459
|
+
* @param propertyKey
|
460
|
+
*/
|
461
|
+
static setMetadata(metadata, target, propertyKey) {
|
462
|
+
const oldMap = import_ts_reflector18.Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, target);
|
463
|
+
const newMap = new Map(oldMap);
|
464
|
+
newMap.set(propertyKey, metadata);
|
465
|
+
import_ts_reflector18.Reflector.defineMetadata(RESPONSE_BODY_METADATA_KEY, newMap, target);
|
466
|
+
}
|
467
|
+
/**
|
468
|
+
* Get metadata.
|
469
|
+
*
|
470
|
+
* @param target
|
471
|
+
*/
|
472
|
+
static getMetadata(target) {
|
473
|
+
const metadata = import_ts_reflector18.Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, target);
|
474
|
+
return metadata ?? /* @__PURE__ */ new Map();
|
475
|
+
}
|
476
|
+
};
|
477
|
+
__name(_ResponseBodyReflector, "ResponseBodyReflector");
|
478
|
+
var ResponseBodyReflector = _ResponseBodyReflector;
|
479
|
+
|
480
|
+
// dist/esm/decorators/response-body/response-body-decorator.js
|
481
|
+
function responseBody(schemaOrType) {
|
482
|
+
return function(target, propertyKey, descriptor) {
|
483
|
+
const decoratorType = (0, import_ts_reflector20.getDecoratorTargetType)(target, propertyKey, descriptor);
|
484
|
+
if (decoratorType !== import_ts_reflector19.DecoratorTargetType.INSTANCE_METHOD)
|
485
|
+
throw new Error("@responseBody decorator is only supported on an instance method.");
|
486
|
+
let schema;
|
487
|
+
if (typeof schemaOrType === "object") {
|
488
|
+
schema = schemaOrType;
|
489
|
+
} else if (typeof schemaOrType === "string") {
|
490
|
+
schema = { type: schemaOrType };
|
491
|
+
}
|
492
|
+
ResponseBodyReflector.setMetadata(schema ? { schema } : {}, target.constructor, propertyKey);
|
493
|
+
};
|
494
|
+
}
|
495
|
+
__name(responseBody, "responseBody");
|
496
|
+
|
497
|
+
// dist/esm/decorators/rest-controller/rest-controller-metadata.js
|
498
|
+
var import_ts_reflector21 = require("@e22m4u/ts-reflector");
|
499
|
+
var REST_CONTROLLER_METADATA_KEY = new import_ts_reflector21.MetadataKey("restControllerMetadataKey");
|
500
|
+
|
501
|
+
// dist/esm/decorators/rest-controller/rest-controller-decorator.js
|
502
|
+
var import_ts_reflector23 = require("@e22m4u/ts-reflector");
|
503
|
+
var import_ts_reflector24 = require("@e22m4u/ts-reflector");
|
504
|
+
|
505
|
+
// dist/esm/decorators/rest-controller/rest-controller-reflector.js
|
506
|
+
var import_ts_reflector22 = require("@e22m4u/ts-reflector");
|
450
507
|
var _RestControllerReflector = class _RestControllerReflector {
|
451
508
|
/**
|
452
509
|
* Set metadata.
|
@@ -455,7 +512,7 @@ var _RestControllerReflector = class _RestControllerReflector {
|
|
455
512
|
* @param target
|
456
513
|
*/
|
457
514
|
static setMetadata(metadata, target) {
|
458
|
-
return
|
515
|
+
return import_ts_reflector22.Reflector.defineMetadata(REST_CONTROLLER_METADATA_KEY, metadata, target);
|
459
516
|
}
|
460
517
|
/**
|
461
518
|
* Get metadata.
|
@@ -463,7 +520,7 @@ var _RestControllerReflector = class _RestControllerReflector {
|
|
463
520
|
* @param target
|
464
521
|
*/
|
465
522
|
static getMetadata(target) {
|
466
|
-
return
|
523
|
+
return import_ts_reflector22.Reflector.getOwnMetadata(REST_CONTROLLER_METADATA_KEY, target);
|
467
524
|
}
|
468
525
|
};
|
469
526
|
__name(_RestControllerReflector, "RestControllerReflector");
|
@@ -472,8 +529,8 @@ var RestControllerReflector = _RestControllerReflector;
|
|
472
529
|
// dist/esm/decorators/rest-controller/rest-controller-decorator.js
|
473
530
|
function restController(pathOrOptions, options) {
|
474
531
|
return function(target) {
|
475
|
-
const decoratorType = (0,
|
476
|
-
if (decoratorType !==
|
532
|
+
const decoratorType = (0, import_ts_reflector24.getDecoratorTargetType)(target);
|
533
|
+
if (decoratorType !== import_ts_reflector23.DecoratorTargetType.CONSTRUCTOR)
|
477
534
|
throw new Error("@restController decorator is only supported on a class.");
|
478
535
|
if (typeof pathOrOptions === "string") {
|
479
536
|
if (!options) {
|
@@ -490,15 +547,15 @@ function restController(pathOrOptions, options) {
|
|
490
547
|
__name(restController, "restController");
|
491
548
|
|
492
549
|
// dist/esm/decorators/request-context/request-context-metadata.js
|
493
|
-
var
|
494
|
-
var REQUEST_CONTEXT_METADATA_KEY = new
|
550
|
+
var import_ts_reflector25 = require("@e22m4u/ts-reflector");
|
551
|
+
var REQUEST_CONTEXT_METADATA_KEY = new import_ts_reflector25.MetadataKey("requestContextMetadataKey");
|
495
552
|
|
496
553
|
// dist/esm/decorators/request-context/request-context-decorator.js
|
497
|
-
var
|
498
|
-
var
|
554
|
+
var import_ts_reflector27 = require("@e22m4u/ts-reflector");
|
555
|
+
var import_ts_reflector28 = require("@e22m4u/ts-reflector");
|
499
556
|
|
500
557
|
// dist/esm/decorators/request-context/request-context-reflector.js
|
501
|
-
var
|
558
|
+
var import_ts_reflector26 = require("@e22m4u/ts-reflector");
|
502
559
|
var _RequestContextReflector = class _RequestContextReflector {
|
503
560
|
/**
|
504
561
|
* Set metadata.
|
@@ -509,10 +566,10 @@ var _RequestContextReflector = class _RequestContextReflector {
|
|
509
566
|
* @param propertyKey
|
510
567
|
*/
|
511
568
|
static setMetadata(metadata, target, index, propertyKey) {
|
512
|
-
const oldMap =
|
569
|
+
const oldMap = import_ts_reflector26.Reflector.getOwnMetadata(REQUEST_CONTEXT_METADATA_KEY, target, propertyKey);
|
513
570
|
const newMap = new Map(oldMap);
|
514
571
|
newMap.set(index, metadata);
|
515
|
-
|
572
|
+
import_ts_reflector26.Reflector.defineMetadata(REQUEST_CONTEXT_METADATA_KEY, newMap, target, propertyKey);
|
516
573
|
}
|
517
574
|
/**
|
518
575
|
* Get metadata.
|
@@ -521,7 +578,7 @@ var _RequestContextReflector = class _RequestContextReflector {
|
|
521
578
|
* @param propertyKey
|
522
579
|
*/
|
523
580
|
static getMetadata(target, propertyKey) {
|
524
|
-
const metadata =
|
581
|
+
const metadata = import_ts_reflector26.Reflector.getOwnMetadata(REQUEST_CONTEXT_METADATA_KEY, target, propertyKey);
|
525
582
|
return metadata ?? /* @__PURE__ */ new Map();
|
526
583
|
}
|
527
584
|
};
|
@@ -531,8 +588,8 @@ var RequestContextReflector = _RequestContextReflector;
|
|
531
588
|
// dist/esm/decorators/request-context/request-context-decorator.js
|
532
589
|
function requestContext(propertyName) {
|
533
590
|
return function(target, propertyKey, indexOrDescriptor) {
|
534
|
-
const decoratorType = (0,
|
535
|
-
if (decoratorType !==
|
591
|
+
const decoratorType = (0, import_ts_reflector28.getDecoratorTargetType)(target, propertyKey, indexOrDescriptor);
|
592
|
+
if (decoratorType !== import_ts_reflector27.DecoratorTargetType.INSTANCE_METHOD_PARAMETER)
|
536
593
|
throw new Error("@requestContext decorator is only supported on an instance method parameter.");
|
537
594
|
RequestContextReflector.setMetadata({ property: propertyName }, target.constructor, indexOrDescriptor, propertyKey);
|
538
595
|
};
|
@@ -938,11 +995,13 @@ var RestRouter = _RestRouter;
|
|
938
995
|
NotAControllerError,
|
939
996
|
REQUEST_CONTEXT_METADATA_KEY,
|
940
997
|
REQUEST_DATA_METADATA_KEY,
|
998
|
+
RESPONSE_BODY_METADATA_KEY,
|
941
999
|
REST_ACTIONS_METADATA_KEY,
|
942
1000
|
REST_CONTROLLER_METADATA_KEY,
|
943
1001
|
RequestContextReflector,
|
944
1002
|
RequestDataReflector,
|
945
1003
|
RequestDataSource,
|
1004
|
+
ResponseBodyReflector,
|
946
1005
|
RestActionReflector,
|
947
1006
|
RestControllerReflector,
|
948
1007
|
RestRouter,
|
@@ -969,6 +1028,7 @@ var RestRouter = _RestRouter;
|
|
969
1028
|
requestParams,
|
970
1029
|
requestQueries,
|
971
1030
|
requestQuery,
|
1031
|
+
responseBody,
|
972
1032
|
restAction,
|
973
1033
|
restController,
|
974
1034
|
toCamelCase
|
@@ -2,5 +2,6 @@ export * from './rest-action/index.js';
|
|
2
2
|
export * from './request-data/index.js';
|
3
3
|
export * from './after-action/index.js';
|
4
4
|
export * from './before-action/index.js';
|
5
|
+
export * from './response-body/index.js';
|
5
6
|
export * from './rest-controller/index.js';
|
6
7
|
export * from './request-context/index.js';
|
@@ -2,5 +2,6 @@ export * from './rest-action/index.js';
|
|
2
2
|
export * from './request-data/index.js';
|
3
3
|
export * from './after-action/index.js';
|
4
4
|
export * from './before-action/index.js';
|
5
|
+
export * from './response-body/index.js';
|
5
6
|
export * from './rest-controller/index.js';
|
6
7
|
export * from './request-context/index.js';
|
@@ -11,22 +11,22 @@ export type RequestDataOptions = RequestDataMetadata;
|
|
11
11
|
*
|
12
12
|
* @param options
|
13
13
|
*/
|
14
|
-
export declare function requestData<T extends object>(options: RequestDataOptions): (target: Prototype<T>, propertyKey: string,
|
14
|
+
export declare function requestData<T extends object>(options: RequestDataOptions): (target: Prototype<T>, propertyKey: string, index: number) => void;
|
15
15
|
/**
|
16
16
|
* Decorator aliases.
|
17
17
|
*/
|
18
|
-
export declare const requestParams: () => (target: Prototype<object>, propertyKey: string,
|
19
|
-
export declare const requestParam: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string,
|
20
|
-
export declare const requestQueries: () => (target: Prototype<object>, propertyKey: string,
|
21
|
-
export declare const requestQuery: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string,
|
22
|
-
export declare const requestHeaders: () => (target: Prototype<object>, propertyKey: string,
|
23
|
-
export declare const requestHeader: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string,
|
24
|
-
export declare const requestCookies: () => (target: Prototype<object>, propertyKey: string,
|
25
|
-
export declare const requestCookie: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string,
|
26
|
-
export declare const requestField: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string,
|
18
|
+
export declare const requestParams: () => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
19
|
+
export declare const requestParam: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
20
|
+
export declare const requestQueries: () => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
21
|
+
export declare const requestQuery: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
22
|
+
export declare const requestHeaders: () => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
23
|
+
export declare const requestHeader: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
24
|
+
export declare const requestCookies: () => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
25
|
+
export declare const requestCookie: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
26
|
+
export declare const requestField: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
27
27
|
/**
|
28
28
|
* Request body decorator.
|
29
29
|
*
|
30
30
|
* @param schemaOrType
|
31
31
|
*/
|
32
|
-
export declare function requestBody(schemaOrType?: DataSchema | DataType): (target: Prototype<object>, propertyKey: string,
|
32
|
+
export declare function requestBody(schemaOrType?: DataSchema | DataType): (target: Prototype<object>, propertyKey: string, index: number) => void;
|
@@ -9,12 +9,12 @@ import { RequestDataReflector } from './request-data-reflector.js';
|
|
9
9
|
* @param options
|
10
10
|
*/
|
11
11
|
export function requestData(options) {
|
12
|
-
return function (target, propertyKey,
|
13
|
-
const decoratorType = getDecoratorTargetType(target, propertyKey,
|
12
|
+
return function (target, propertyKey, index) {
|
13
|
+
const decoratorType = getDecoratorTargetType(target, propertyKey, index);
|
14
14
|
if (decoratorType !== DecoratorTargetType.INSTANCE_METHOD_PARAMETER)
|
15
15
|
throw new Error('@requestData decorator is only supported ' +
|
16
16
|
'on an instance method parameter.');
|
17
|
-
RequestDataReflector.setMetadata(options, target.constructor,
|
17
|
+
RequestDataReflector.setMetadata(options, target.constructor, index, propertyKey);
|
18
18
|
};
|
19
19
|
}
|
20
20
|
/**
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Prototype } from '../../types.js';
|
2
|
+
import { DataType } from '@e22m4u/ts-data-schema';
|
3
|
+
import { DataSchema } from '@e22m4u/ts-data-schema';
|
4
|
+
/**
|
5
|
+
* Response body decorator.
|
6
|
+
*
|
7
|
+
* @param schemaOrType
|
8
|
+
*/
|
9
|
+
export declare function responseBody<T extends object>(schemaOrType?: DataSchema | DataType): (target: Prototype<T>, propertyKey: string, descriptor: PropertyDescriptor) => void;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { DecoratorTargetType } from '@e22m4u/ts-reflector';
|
2
|
+
import { getDecoratorTargetType } from '@e22m4u/ts-reflector';
|
3
|
+
import { ResponseBodyReflector } from './response-body-reflector.js';
|
4
|
+
/**
|
5
|
+
* Response body decorator.
|
6
|
+
*
|
7
|
+
* @param schemaOrType
|
8
|
+
*/
|
9
|
+
export function responseBody(schemaOrType) {
|
10
|
+
return function (target, propertyKey, descriptor) {
|
11
|
+
const decoratorType = getDecoratorTargetType(target, propertyKey, descriptor);
|
12
|
+
if (decoratorType !== DecoratorTargetType.INSTANCE_METHOD)
|
13
|
+
throw new Error('@responseBody decorator is only supported on an instance method.');
|
14
|
+
let schema;
|
15
|
+
if (typeof schemaOrType === 'object') {
|
16
|
+
schema = schemaOrType;
|
17
|
+
}
|
18
|
+
else if (typeof schemaOrType === 'string') {
|
19
|
+
schema = { type: schemaOrType };
|
20
|
+
}
|
21
|
+
ResponseBodyReflector.setMetadata(schema ? { schema } : {}, target.constructor, propertyKey);
|
22
|
+
};
|
23
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,61 @@
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
+
};
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
9
|
+
};
|
10
|
+
import { expect } from 'chai';
|
11
|
+
import { DataType } from '@e22m4u/ts-data-schema';
|
12
|
+
import { responseBody } from './response-body-decorator.js';
|
13
|
+
import { ResponseBodyReflector } from './response-body-reflector.js';
|
14
|
+
describe('responseBody', function () {
|
15
|
+
it('does not require arguments', function () {
|
16
|
+
class Target {
|
17
|
+
myMethod() { }
|
18
|
+
}
|
19
|
+
__decorate([
|
20
|
+
responseBody(),
|
21
|
+
__metadata("design:type", Function),
|
22
|
+
__metadata("design:paramtypes", []),
|
23
|
+
__metadata("design:returntype", void 0)
|
24
|
+
], Target.prototype, "myMethod", null);
|
25
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
26
|
+
expect(res.get('myMethod')).to.be.eql({});
|
27
|
+
});
|
28
|
+
it('sets the given DataType to the target metadata', function () {
|
29
|
+
class Target {
|
30
|
+
myMethod() { }
|
31
|
+
}
|
32
|
+
__decorate([
|
33
|
+
responseBody(DataType.STRING),
|
34
|
+
__metadata("design:type", Function),
|
35
|
+
__metadata("design:paramtypes", []),
|
36
|
+
__metadata("design:returntype", void 0)
|
37
|
+
], Target.prototype, "myMethod", null);
|
38
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
39
|
+
expect(res.get('myMethod')).to.be.eql({ schema: { type: DataType.STRING } });
|
40
|
+
});
|
41
|
+
it('sets the given schema to the target metadata', function () {
|
42
|
+
const schema = {
|
43
|
+
type: DataType.OBJECT,
|
44
|
+
properties: {
|
45
|
+
foo: { type: DataType.STRING },
|
46
|
+
bar: { type: DataType.NUMBER },
|
47
|
+
},
|
48
|
+
};
|
49
|
+
class Target {
|
50
|
+
myMethod() { }
|
51
|
+
}
|
52
|
+
__decorate([
|
53
|
+
responseBody(schema),
|
54
|
+
__metadata("design:type", Function),
|
55
|
+
__metadata("design:paramtypes", []),
|
56
|
+
__metadata("design:returntype", void 0)
|
57
|
+
], Target.prototype, "myMethod", null);
|
58
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
59
|
+
expect(res.get('myMethod')).to.be.eql({ schema });
|
60
|
+
});
|
61
|
+
});
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { MetadataKey } from '@e22m4u/ts-reflector';
|
2
|
+
import { DataSchema } from '@e22m4u/ts-data-schema';
|
3
|
+
/**
|
4
|
+
* Response body metadata.
|
5
|
+
*/
|
6
|
+
export type ResponseBodyMetadata = {
|
7
|
+
schema?: DataSchema;
|
8
|
+
};
|
9
|
+
/**
|
10
|
+
* Response body metadata map.
|
11
|
+
*/
|
12
|
+
export type ResponseBodyMetadataMap = Map<string, ResponseBodyMetadata>;
|
13
|
+
/**
|
14
|
+
* Response body metadata key.
|
15
|
+
*/
|
16
|
+
export declare const RESPONSE_BODY_METADATA_KEY: MetadataKey<ResponseBodyMetadataMap>;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { Constructor } from '../../types.js';
|
2
|
+
import { ResponseBodyMetadata } from './response-body-metadata.js';
|
3
|
+
import { ResponseBodyMetadataMap } from './response-body-metadata.js';
|
4
|
+
/**
|
5
|
+
* Response body reflector.
|
6
|
+
*/
|
7
|
+
export declare class ResponseBodyReflector {
|
8
|
+
/**
|
9
|
+
* Set metadata.
|
10
|
+
*
|
11
|
+
* @param metadata
|
12
|
+
* @param target
|
13
|
+
* @param propertyKey
|
14
|
+
*/
|
15
|
+
static setMetadata(metadata: ResponseBodyMetadata, target: Constructor, propertyKey: string): void;
|
16
|
+
/**
|
17
|
+
* Get metadata.
|
18
|
+
*
|
19
|
+
* @param target
|
20
|
+
*/
|
21
|
+
static getMetadata(target: Constructor): ResponseBodyMetadataMap;
|
22
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { Reflector } from '@e22m4u/ts-reflector';
|
2
|
+
import { RESPONSE_BODY_METADATA_KEY } from './response-body-metadata.js';
|
3
|
+
/**
|
4
|
+
* Response body reflector.
|
5
|
+
*/
|
6
|
+
export class ResponseBodyReflector {
|
7
|
+
/**
|
8
|
+
* Set metadata.
|
9
|
+
*
|
10
|
+
* @param metadata
|
11
|
+
* @param target
|
12
|
+
* @param propertyKey
|
13
|
+
*/
|
14
|
+
static setMetadata(metadata, target, propertyKey) {
|
15
|
+
const oldMap = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, target);
|
16
|
+
const newMap = new Map(oldMap);
|
17
|
+
newMap.set(propertyKey, metadata);
|
18
|
+
Reflector.defineMetadata(RESPONSE_BODY_METADATA_KEY, newMap, target);
|
19
|
+
}
|
20
|
+
/**
|
21
|
+
* Get metadata.
|
22
|
+
*
|
23
|
+
* @param target
|
24
|
+
*/
|
25
|
+
static getMetadata(target) {
|
26
|
+
const metadata = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, target);
|
27
|
+
return metadata ?? new Map();
|
28
|
+
}
|
29
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import { expect } from 'chai';
|
2
|
+
import { Reflector } from '@e22m4u/ts-reflector';
|
3
|
+
import { ResponseBodyReflector } from './response-body-reflector.js';
|
4
|
+
import { RESPONSE_BODY_METADATA_KEY } from './response-body-metadata.js';
|
5
|
+
describe('ResponseBodyReflector', function () {
|
6
|
+
describe('setMetadata', function () {
|
7
|
+
it('sets a given value as target metadata', function () {
|
8
|
+
class Target {
|
9
|
+
}
|
10
|
+
const md1 = {};
|
11
|
+
const md2 = {};
|
12
|
+
ResponseBodyReflector.setMetadata(md1, Target, 'propertyKey1');
|
13
|
+
ResponseBodyReflector.setMetadata(md2, Target, 'propertyKey2');
|
14
|
+
const res = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, Target);
|
15
|
+
expect(res).to.be.instanceof(Map);
|
16
|
+
expect(res.get('propertyKey1')).to.be.eq(md1);
|
17
|
+
expect(res.get('propertyKey2')).to.be.eq(md2);
|
18
|
+
});
|
19
|
+
it('overrides existing metadata', function () {
|
20
|
+
class Target {
|
21
|
+
}
|
22
|
+
const md1 = {};
|
23
|
+
const md2 = {};
|
24
|
+
ResponseBodyReflector.setMetadata(md1, Target, 'propertyKey');
|
25
|
+
const res1 = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, Target);
|
26
|
+
expect(res1).to.be.instanceof(Map);
|
27
|
+
expect(res1.get('propertyKey')).to.be.eq(md1);
|
28
|
+
ResponseBodyReflector.setMetadata(md2, Target, 'propertyKey');
|
29
|
+
const res2 = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, Target);
|
30
|
+
expect(res2).to.be.instanceof(Map);
|
31
|
+
expect(res2.get('propertyKey')).to.be.eq(md2);
|
32
|
+
});
|
33
|
+
});
|
34
|
+
describe('getMetadata', function () {
|
35
|
+
it('returns an existing metadata of the target', function () {
|
36
|
+
class Target {
|
37
|
+
}
|
38
|
+
const md1 = {};
|
39
|
+
const md2 = {};
|
40
|
+
const mdMap = new Map([
|
41
|
+
['propertyKey1', md1],
|
42
|
+
['propertyKey2', md2],
|
43
|
+
]);
|
44
|
+
Reflector.defineMetadata(RESPONSE_BODY_METADATA_KEY, mdMap, Target);
|
45
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
46
|
+
expect(res).to.be.instanceof(Map);
|
47
|
+
expect(res.get('propertyKey1')).to.be.eq(md1);
|
48
|
+
expect(res.get('propertyKey2')).to.be.eq(md2);
|
49
|
+
});
|
50
|
+
it('returns an empty map if no metadata', function () {
|
51
|
+
class Target {
|
52
|
+
}
|
53
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
54
|
+
expect(res).to.be.instanceof(Map);
|
55
|
+
expect(res).to.be.empty;
|
56
|
+
});
|
57
|
+
});
|
58
|
+
});
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@e22m4u/ts-rest-router",
|
3
|
-
"version": "0.2.
|
3
|
+
"version": "0.2.2",
|
4
4
|
"description": "REST маршрутизатор на основе контроллеров для TypeScript",
|
5
5
|
"author": "e22m4u <e22m4u@yandex.ru>",
|
6
6
|
"license": "MIT",
|
@@ -52,25 +52,25 @@
|
|
52
52
|
"devDependencies": {
|
53
53
|
"@commitlint/cli": "~19.8.1",
|
54
54
|
"@commitlint/config-conventional": "~19.8.1",
|
55
|
-
"@eslint/js": "~9.
|
55
|
+
"@eslint/js": "~9.28.0",
|
56
56
|
"@types/chai": "~5.2.2",
|
57
57
|
"@types/debug": "~4.1.12",
|
58
58
|
"@types/http-errors": "~2.0.4",
|
59
59
|
"@types/mocha": "~10.0.10",
|
60
|
-
"@types/node": "~22.15.
|
60
|
+
"@types/node": "~22.15.29",
|
61
61
|
"c8": "~10.1.3",
|
62
62
|
"chai": "~5.2.0",
|
63
|
-
"esbuild": "~0.25.
|
64
|
-
"eslint": "~9.
|
63
|
+
"esbuild": "~0.25.5",
|
64
|
+
"eslint": "~9.28.0",
|
65
65
|
"eslint-config-prettier": "~10.1.5",
|
66
66
|
"eslint-plugin-chai-expect": "~3.1.0",
|
67
|
-
"eslint-plugin-mocha": "~11.
|
67
|
+
"eslint-plugin-mocha": "~11.1.0",
|
68
68
|
"husky": "~9.1.7",
|
69
|
-
"mocha": "~11.
|
69
|
+
"mocha": "~11.5.0",
|
70
70
|
"prettier": "~3.5.3",
|
71
71
|
"rimraf": "~6.0.1",
|
72
72
|
"tsx": "~4.19.4",
|
73
73
|
"typescript": "~5.8.3",
|
74
|
-
"typescript-eslint": "~8.
|
74
|
+
"typescript-eslint": "~8.33.0"
|
75
75
|
}
|
76
76
|
}
|
package/src/decorators/index.ts
CHANGED
@@ -2,5 +2,6 @@ export * from './rest-action/index.js';
|
|
2
2
|
export * from './request-data/index.js';
|
3
3
|
export * from './after-action/index.js';
|
4
4
|
export * from './before-action/index.js';
|
5
|
+
export * from './response-body/index.js';
|
5
6
|
export * from './rest-controller/index.js';
|
6
7
|
export * from './request-context/index.js';
|
@@ -20,16 +20,8 @@ export type RequestDataOptions = RequestDataMetadata;
|
|
20
20
|
* @param options
|
21
21
|
*/
|
22
22
|
export function requestData<T extends object>(options: RequestDataOptions) {
|
23
|
-
return function (
|
24
|
-
target
|
25
|
-
propertyKey: string,
|
26
|
-
indexOrDescriptor: number,
|
27
|
-
) {
|
28
|
-
const decoratorType = getDecoratorTargetType(
|
29
|
-
target,
|
30
|
-
propertyKey,
|
31
|
-
indexOrDescriptor,
|
32
|
-
);
|
23
|
+
return function (target: Prototype<T>, propertyKey: string, index: number) {
|
24
|
+
const decoratorType = getDecoratorTargetType(target, propertyKey, index);
|
33
25
|
if (decoratorType !== DecoratorTargetType.INSTANCE_METHOD_PARAMETER)
|
34
26
|
throw new Error(
|
35
27
|
'@requestData decorator is only supported ' +
|
@@ -38,7 +30,7 @@ export function requestData<T extends object>(options: RequestDataOptions) {
|
|
38
30
|
RequestDataReflector.setMetadata(
|
39
31
|
options,
|
40
32
|
target.constructor as Constructor<T>,
|
41
|
-
|
33
|
+
index,
|
42
34
|
propertyKey,
|
43
35
|
);
|
44
36
|
};
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import {expect} from 'chai';
|
2
|
+
import {DataType} from '@e22m4u/ts-data-schema';
|
3
|
+
import {responseBody} from './response-body-decorator.js';
|
4
|
+
import {ResponseBodyReflector} from './response-body-reflector.js';
|
5
|
+
|
6
|
+
describe('responseBody', function () {
|
7
|
+
it('does not require arguments', function () {
|
8
|
+
class Target {
|
9
|
+
@responseBody()
|
10
|
+
myMethod() {}
|
11
|
+
}
|
12
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
13
|
+
expect(res.get('myMethod')).to.be.eql({});
|
14
|
+
});
|
15
|
+
|
16
|
+
it('sets the given DataType to the target metadata', function () {
|
17
|
+
class Target {
|
18
|
+
@responseBody(DataType.STRING)
|
19
|
+
myMethod() {}
|
20
|
+
}
|
21
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
22
|
+
expect(res.get('myMethod')).to.be.eql({schema: {type: DataType.STRING}});
|
23
|
+
});
|
24
|
+
|
25
|
+
it('sets the given schema to the target metadata', function () {
|
26
|
+
const schema = {
|
27
|
+
type: DataType.OBJECT,
|
28
|
+
properties: {
|
29
|
+
foo: {type: DataType.STRING},
|
30
|
+
bar: {type: DataType.NUMBER},
|
31
|
+
},
|
32
|
+
};
|
33
|
+
class Target {
|
34
|
+
@responseBody(schema)
|
35
|
+
myMethod() {}
|
36
|
+
}
|
37
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
38
|
+
expect(res.get('myMethod')).to.be.eql({schema});
|
39
|
+
});
|
40
|
+
});
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import {Prototype} from '../../types.js';
|
2
|
+
import {Constructor} from '../../types.js';
|
3
|
+
import {DataType} from '@e22m4u/ts-data-schema';
|
4
|
+
import {DataSchema} from '@e22m4u/ts-data-schema';
|
5
|
+
import {DecoratorTargetType} from '@e22m4u/ts-reflector';
|
6
|
+
import {getDecoratorTargetType} from '@e22m4u/ts-reflector';
|
7
|
+
import {ResponseBodyReflector} from './response-body-reflector.js';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Response body decorator.
|
11
|
+
*
|
12
|
+
* @param schemaOrType
|
13
|
+
*/
|
14
|
+
export function responseBody<T extends object>(
|
15
|
+
schemaOrType?: DataSchema | DataType,
|
16
|
+
) {
|
17
|
+
return function (
|
18
|
+
target: Prototype<T>,
|
19
|
+
propertyKey: string,
|
20
|
+
descriptor: PropertyDescriptor,
|
21
|
+
) {
|
22
|
+
const decoratorType = getDecoratorTargetType(
|
23
|
+
target,
|
24
|
+
propertyKey,
|
25
|
+
descriptor,
|
26
|
+
);
|
27
|
+
if (decoratorType !== DecoratorTargetType.INSTANCE_METHOD)
|
28
|
+
throw new Error(
|
29
|
+
'@responseBody decorator is only supported on an instance method.',
|
30
|
+
);
|
31
|
+
let schema: DataSchema | undefined;
|
32
|
+
if (typeof schemaOrType === 'object') {
|
33
|
+
schema = schemaOrType;
|
34
|
+
} else if (typeof schemaOrType === 'string') {
|
35
|
+
schema = {type: schemaOrType};
|
36
|
+
}
|
37
|
+
ResponseBodyReflector.setMetadata(
|
38
|
+
schema ? {schema} : {},
|
39
|
+
target.constructor as Constructor<T>,
|
40
|
+
propertyKey,
|
41
|
+
);
|
42
|
+
};
|
43
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import {MetadataKey} from '@e22m4u/ts-reflector';
|
2
|
+
import {DataSchema} from '@e22m4u/ts-data-schema';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Response body metadata.
|
6
|
+
*/
|
7
|
+
export type ResponseBodyMetadata = {
|
8
|
+
schema?: DataSchema;
|
9
|
+
};
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Response body metadata map.
|
13
|
+
*/
|
14
|
+
export type ResponseBodyMetadataMap = Map<string, ResponseBodyMetadata>;
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Response body metadata key.
|
18
|
+
*/
|
19
|
+
export const RESPONSE_BODY_METADATA_KEY =
|
20
|
+
new MetadataKey<ResponseBodyMetadataMap>('responseBodyMetadataKey');
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import {expect} from 'chai';
|
2
|
+
import {Reflector} from '@e22m4u/ts-reflector';
|
3
|
+
import {ResponseBodyMetadata} from './response-body-metadata.js';
|
4
|
+
import {ResponseBodyReflector} from './response-body-reflector.js';
|
5
|
+
import {RESPONSE_BODY_METADATA_KEY} from './response-body-metadata.js';
|
6
|
+
|
7
|
+
describe('ResponseBodyReflector', function () {
|
8
|
+
describe('setMetadata', function () {
|
9
|
+
it('sets a given value as target metadata', function () {
|
10
|
+
class Target {}
|
11
|
+
const md1 = {};
|
12
|
+
const md2 = {};
|
13
|
+
ResponseBodyReflector.setMetadata(md1, Target, 'propertyKey1');
|
14
|
+
ResponseBodyReflector.setMetadata(md2, Target, 'propertyKey2');
|
15
|
+
const res = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, Target);
|
16
|
+
expect(res).to.be.instanceof(Map);
|
17
|
+
expect(res!.get('propertyKey1')).to.be.eq(md1);
|
18
|
+
expect(res!.get('propertyKey2')).to.be.eq(md2);
|
19
|
+
});
|
20
|
+
|
21
|
+
it('overrides existing metadata', function () {
|
22
|
+
class Target {}
|
23
|
+
const md1 = {};
|
24
|
+
const md2 = {};
|
25
|
+
ResponseBodyReflector.setMetadata(md1, Target, 'propertyKey');
|
26
|
+
const res1 = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, Target);
|
27
|
+
expect(res1).to.be.instanceof(Map);
|
28
|
+
expect(res1!.get('propertyKey')).to.be.eq(md1);
|
29
|
+
ResponseBodyReflector.setMetadata(md2, Target, 'propertyKey');
|
30
|
+
const res2 = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, Target);
|
31
|
+
expect(res2).to.be.instanceof(Map);
|
32
|
+
expect(res2!.get('propertyKey')).to.be.eq(md2);
|
33
|
+
});
|
34
|
+
});
|
35
|
+
|
36
|
+
describe('getMetadata', function () {
|
37
|
+
it('returns an existing metadata of the target', function () {
|
38
|
+
class Target {}
|
39
|
+
const md1 = {};
|
40
|
+
const md2 = {};
|
41
|
+
const mdMap = new Map<string, ResponseBodyMetadata>([
|
42
|
+
['propertyKey1', md1],
|
43
|
+
['propertyKey2', md2],
|
44
|
+
]);
|
45
|
+
Reflector.defineMetadata(RESPONSE_BODY_METADATA_KEY, mdMap, Target);
|
46
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
47
|
+
expect(res).to.be.instanceof(Map);
|
48
|
+
expect(res!.get('propertyKey1')).to.be.eq(md1);
|
49
|
+
expect(res!.get('propertyKey2')).to.be.eq(md2);
|
50
|
+
});
|
51
|
+
|
52
|
+
it('returns an empty map if no metadata', function () {
|
53
|
+
class Target {}
|
54
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
55
|
+
expect(res).to.be.instanceof(Map);
|
56
|
+
expect(res).to.be.empty;
|
57
|
+
});
|
58
|
+
});
|
59
|
+
});
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import {Constructor} from '../../types.js';
|
2
|
+
import {Reflector} from '@e22m4u/ts-reflector';
|
3
|
+
import {ResponseBodyMetadata} from './response-body-metadata.js';
|
4
|
+
import {ResponseBodyMetadataMap} from './response-body-metadata.js';
|
5
|
+
import {RESPONSE_BODY_METADATA_KEY} from './response-body-metadata.js';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Response body reflector.
|
9
|
+
*/
|
10
|
+
export class ResponseBodyReflector {
|
11
|
+
/**
|
12
|
+
* Set metadata.
|
13
|
+
*
|
14
|
+
* @param metadata
|
15
|
+
* @param target
|
16
|
+
* @param propertyKey
|
17
|
+
*/
|
18
|
+
static setMetadata(
|
19
|
+
metadata: ResponseBodyMetadata,
|
20
|
+
target: Constructor,
|
21
|
+
propertyKey: string,
|
22
|
+
) {
|
23
|
+
const oldMap = Reflector.getOwnMetadata(RESPONSE_BODY_METADATA_KEY, target);
|
24
|
+
const newMap = new Map(oldMap);
|
25
|
+
newMap.set(propertyKey, metadata);
|
26
|
+
Reflector.defineMetadata(RESPONSE_BODY_METADATA_KEY, newMap, target);
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Get metadata.
|
31
|
+
*
|
32
|
+
* @param target
|
33
|
+
*/
|
34
|
+
static getMetadata(target: Constructor): ResponseBodyMetadataMap {
|
35
|
+
const metadata = Reflector.getOwnMetadata(
|
36
|
+
RESPONSE_BODY_METADATA_KEY,
|
37
|
+
target,
|
38
|
+
);
|
39
|
+
return metadata ?? new Map();
|
40
|
+
}
|
41
|
+
}
|