@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.
Files changed (26) hide show
  1. package/dist/cjs/index.cjs +81 -21
  2. package/dist/esm/decorators/index.d.ts +1 -0
  3. package/dist/esm/decorators/index.js +1 -0
  4. package/dist/esm/decorators/request-data/request-data-decorator.d.ts +11 -11
  5. package/dist/esm/decorators/request-data/request-data-decorator.js +3 -3
  6. package/dist/esm/decorators/response-body/index.d.ts +3 -0
  7. package/dist/esm/decorators/response-body/index.js +3 -0
  8. package/dist/esm/decorators/response-body/response-body-decorator.d.ts +9 -0
  9. package/dist/esm/decorators/response-body/response-body-decorator.js +23 -0
  10. package/dist/esm/decorators/response-body/response-body-decorator.spec.d.ts +1 -0
  11. package/dist/esm/decorators/response-body/response-body-decorator.spec.js +61 -0
  12. package/dist/esm/decorators/response-body/response-body-metadata.d.ts +16 -0
  13. package/dist/esm/decorators/response-body/response-body-metadata.js +5 -0
  14. package/dist/esm/decorators/response-body/response-body-reflector.d.ts +22 -0
  15. package/dist/esm/decorators/response-body/response-body-reflector.js +29 -0
  16. package/dist/esm/decorators/response-body/response-body-reflector.spec.d.ts +1 -0
  17. package/dist/esm/decorators/response-body/response-body-reflector.spec.js +58 -0
  18. package/package.json +8 -8
  19. package/src/decorators/index.ts +1 -0
  20. package/src/decorators/request-data/request-data-decorator.ts +3 -11
  21. package/src/decorators/response-body/index.ts +3 -0
  22. package/src/decorators/response-body/response-body-decorator.spec.ts +40 -0
  23. package/src/decorators/response-body/response-body-decorator.ts +43 -0
  24. package/src/decorators/response-body/response-body-metadata.ts +20 -0
  25. package/src/decorators/response-body/response-body-reflector.spec.ts +59 -0
  26. package/src/decorators/response-body/response-body-reflector.ts +41 -0
@@ -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, indexOrDescriptor) {
285
- const decoratorType = (0, import_ts_reflector8.getDecoratorTargetType)(target, propertyKey, indexOrDescriptor);
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, indexOrDescriptor, propertyKey);
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/rest-controller/rest-controller-metadata.js
443
+ // dist/esm/decorators/response-body/response-body-metadata.js
441
444
  var import_ts_reflector17 = require("@e22m4u/ts-reflector");
442
- var REST_CONTROLLER_METADATA_KEY = new import_ts_reflector17.MetadataKey("restControllerMetadataKey");
445
+ var RESPONSE_BODY_METADATA_KEY = new import_ts_reflector17.MetadataKey("responseBodyMetadataKey");
443
446
 
444
- // dist/esm/decorators/rest-controller/rest-controller-decorator.js
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/rest-controller/rest-controller-reflector.js
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 import_ts_reflector18.Reflector.defineMetadata(REST_CONTROLLER_METADATA_KEY, metadata, target);
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 import_ts_reflector18.Reflector.getOwnMetadata(REST_CONTROLLER_METADATA_KEY, target);
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, import_ts_reflector20.getDecoratorTargetType)(target);
476
- if (decoratorType !== import_ts_reflector19.DecoratorTargetType.CONSTRUCTOR)
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 import_ts_reflector21 = require("@e22m4u/ts-reflector");
494
- var REQUEST_CONTEXT_METADATA_KEY = new import_ts_reflector21.MetadataKey("requestContextMetadataKey");
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 import_ts_reflector23 = require("@e22m4u/ts-reflector");
498
- var import_ts_reflector24 = require("@e22m4u/ts-reflector");
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 import_ts_reflector22 = require("@e22m4u/ts-reflector");
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 = import_ts_reflector22.Reflector.getOwnMetadata(REQUEST_CONTEXT_METADATA_KEY, target, propertyKey);
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
- import_ts_reflector22.Reflector.defineMetadata(REQUEST_CONTEXT_METADATA_KEY, newMap, target, propertyKey);
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 = import_ts_reflector22.Reflector.getOwnMetadata(REQUEST_CONTEXT_METADATA_KEY, target, propertyKey);
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, import_ts_reflector24.getDecoratorTargetType)(target, propertyKey, indexOrDescriptor);
535
- if (decoratorType !== import_ts_reflector23.DecoratorTargetType.INSTANCE_METHOD_PARAMETER)
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, indexOrDescriptor: number) => void;
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, indexOrDescriptor: number) => void;
19
- export declare const requestParam: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
20
- export declare const requestQueries: () => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
21
- export declare const requestQuery: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
22
- export declare const requestHeaders: () => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
23
- export declare const requestHeader: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
24
- export declare const requestCookies: () => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
25
- export declare const requestCookie: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
26
- export declare const requestField: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
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, indexOrDescriptor: number) => void;
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, indexOrDescriptor) {
13
- const decoratorType = getDecoratorTargetType(target, propertyKey, indexOrDescriptor);
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, indexOrDescriptor, propertyKey);
17
+ RequestDataReflector.setMetadata(options, target.constructor, index, propertyKey);
18
18
  };
19
19
  }
20
20
  /**
@@ -0,0 +1,3 @@
1
+ export * from './response-body-metadata.js';
2
+ export * from './response-body-decorator.js';
3
+ export * from './response-body-reflector.js';
@@ -0,0 +1,3 @@
1
+ export * from './response-body-metadata.js';
2
+ export * from './response-body-decorator.js';
3
+ export * from './response-body-reflector.js';
@@ -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,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,5 @@
1
+ import { MetadataKey } from '@e22m4u/ts-reflector';
2
+ /**
3
+ * Response body metadata key.
4
+ */
5
+ export const RESPONSE_BODY_METADATA_KEY = new MetadataKey('responseBodyMetadataKey');
@@ -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,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.1",
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.26.0",
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.17",
60
+ "@types/node": "~22.15.29",
61
61
  "c8": "~10.1.3",
62
62
  "chai": "~5.2.0",
63
- "esbuild": "~0.25.4",
64
- "eslint": "~9.26.0",
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.0.0",
67
+ "eslint-plugin-mocha": "~11.1.0",
68
68
  "husky": "~9.1.7",
69
- "mocha": "~11.2.2",
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.32.0"
74
+ "typescript-eslint": "~8.33.0"
75
75
  }
76
76
  }
@@ -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: Prototype<T>,
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
- indexOrDescriptor,
33
+ index,
42
34
  propertyKey,
43
35
  );
44
36
  };
@@ -0,0 +1,3 @@
1
+ export * from './response-body-metadata.js';
2
+ export * from './response-body-decorator.js';
3
+ export * from './response-body-reflector.js';
@@ -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
+ }