@e22m4u/ts-rest-router 0.0.7 → 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.
Files changed (62) hide show
  1. package/README-ru.md +114 -91
  2. package/README.md +106 -85
  3. package/dist/cjs/index.cjs +427 -123
  4. package/dist/esm/controller-registry.d.ts +53 -11
  5. package/dist/esm/controller-registry.js +242 -104
  6. package/dist/esm/debuggable-service.js +1 -1
  7. package/dist/esm/decorators/after/after-decorator.d.ts +9 -0
  8. package/dist/esm/decorators/after/after-decorator.js +22 -0
  9. package/dist/esm/decorators/after/after-decorator.spec.d.ts +1 -0
  10. package/dist/esm/decorators/after/after-decorator.spec.js +115 -0
  11. package/dist/esm/decorators/after/after-metadata.d.ts +13 -0
  12. package/dist/esm/decorators/after/after-metadata.js +5 -0
  13. package/dist/esm/decorators/after/after-reflector.d.ts +22 -0
  14. package/dist/esm/decorators/after/after-reflector.js +29 -0
  15. package/dist/esm/decorators/after/after-reflector.spec.d.ts +1 -0
  16. package/dist/esm/decorators/after/after-reflector.spec.js +102 -0
  17. package/dist/esm/decorators/after/index.d.ts +3 -0
  18. package/dist/esm/decorators/after/index.js +3 -0
  19. package/dist/esm/decorators/before/before-decorator.d.ts +9 -0
  20. package/dist/esm/decorators/before/before-decorator.js +22 -0
  21. package/dist/esm/decorators/before/before-decorator.spec.d.ts +1 -0
  22. package/dist/esm/decorators/before/before-decorator.spec.js +115 -0
  23. package/dist/esm/decorators/before/before-metadata.d.ts +13 -0
  24. package/dist/esm/decorators/before/before-metadata.js +5 -0
  25. package/dist/esm/decorators/before/before-reflector.d.ts +22 -0
  26. package/dist/esm/decorators/before/before-reflector.js +29 -0
  27. package/dist/esm/decorators/before/before-reflector.spec.d.ts +1 -0
  28. package/dist/esm/decorators/before/before-reflector.spec.js +102 -0
  29. package/dist/esm/decorators/before/index.d.ts +3 -0
  30. package/dist/esm/decorators/before/index.js +3 -0
  31. package/dist/esm/decorators/controller/controller-decorator.d.ts +2 -1
  32. package/dist/esm/decorators/controller/controller-decorator.js +26 -1
  33. package/dist/esm/decorators/controller/controller-decorator.spec.js +28 -0
  34. package/dist/esm/decorators/index.d.ts +2 -0
  35. package/dist/esm/decorators/index.js +2 -0
  36. package/dist/esm/decorators/request-data/request-data-decorator.d.ts +1 -1
  37. package/dist/esm/decorators/request-data/request-data-decorator.js +1 -1
  38. package/dist/esm/decorators/request-data/request-data-decorator.spec.js +5 -5
  39. package/dist/esm/utils/create-debugger.d.ts +35 -2
  40. package/dist/esm/utils/create-debugger.js +71 -5
  41. package/package.json +1 -1
  42. package/src/controller-registry.spec.ts +601 -275
  43. package/src/controller-registry.ts +263 -128
  44. package/src/debuggable-service.ts +1 -1
  45. package/src/decorators/after/after-decorator.spec.ts +92 -0
  46. package/src/decorators/after/after-decorator.ts +40 -0
  47. package/src/decorators/after/after-metadata.ts +17 -0
  48. package/src/decorators/after/after-reflector.spec.ts +107 -0
  49. package/src/decorators/after/after-reflector.ts +45 -0
  50. package/src/decorators/after/index.ts +3 -0
  51. package/src/decorators/before/before-decorator.spec.ts +92 -0
  52. package/src/decorators/before/before-decorator.ts +40 -0
  53. package/src/decorators/before/before-metadata.ts +17 -0
  54. package/src/decorators/before/before-reflector.spec.ts +111 -0
  55. package/src/decorators/before/before-reflector.ts +50 -0
  56. package/src/decorators/before/index.ts +3 -0
  57. package/src/decorators/controller/controller-decorator.spec.ts +22 -0
  58. package/src/decorators/controller/controller-decorator.ts +29 -1
  59. package/src/decorators/index.ts +2 -0
  60. package/src/decorators/request-data/request-data-decorator.spec.ts +5 -5
  61. package/src/decorators/request-data/request-data-decorator.ts +1 -1
  62. package/src/utils/create-debugger.ts +84 -7
@@ -4,13 +4,38 @@ import { ControllerReflector } from './controller-reflector.js';
4
4
  /**
5
5
  * Controller decorator.
6
6
  *
7
+ * @param pathOrOptions
7
8
  * @param options
8
9
  */
9
- export function controller(options) {
10
+ export function controller(pathOrOptions, options) {
10
11
  return function (target) {
11
12
  const decoratorType = getDecoratorTargetType(target);
12
13
  if (decoratorType !== DecoratorTargetType.CONSTRUCTOR)
13
14
  throw new Error('@controller decorator is only supported on a class.');
15
+ // если первый аргумент является строкой,
16
+ // то значение используется в качестве
17
+ // базового пути контроллера
18
+ if (typeof pathOrOptions === 'string') {
19
+ // если второй аргумент не определен,
20
+ // то создается новый объект опций,
21
+ // который включает базовый путь
22
+ if (!options) {
23
+ options = { path: pathOrOptions };
24
+ }
25
+ // если второй аргумент определен,
26
+ // то базовый путь из первого аргумента
27
+ // передается в объект опций декоратора
28
+ else {
29
+ options.path = pathOrOptions;
30
+ }
31
+ }
32
+ // если первый аргумент является объектом,
33
+ // то его значение используется в качестве
34
+ // объекта опций декоратора, а второй
35
+ // аргумент игнорируется
36
+ else if (typeof pathOrOptions === 'object') {
37
+ options = pathOrOptions;
38
+ }
14
39
  ControllerReflector.setMetadata({ ...options, className: target.name }, target);
15
40
  };
16
41
  }
@@ -44,4 +44,32 @@ describe('controller', function () {
44
44
  const res = ControllerReflector.getMetadata(Target);
45
45
  expect(res).to.be.eql({ className: 'Target' });
46
46
  });
47
+ it('allows to pass the path option to the first parameter', function () {
48
+ let Target = class Target {
49
+ };
50
+ Target = __decorate([
51
+ controller('myPath')
52
+ ], Target);
53
+ const res = ControllerReflector.getMetadata(Target);
54
+ expect(res).to.be.eql({ className: 'Target', path: 'myPath' });
55
+ });
56
+ it('merges two given arguments in the target metadata', function () {
57
+ const before = () => undefined;
58
+ let Target = class Target {
59
+ };
60
+ Target = __decorate([
61
+ controller('myPath', { before })
62
+ ], Target);
63
+ const res = ControllerReflector.getMetadata(Target);
64
+ expect(res).to.be.eql({ className: 'Target', path: 'myPath', before });
65
+ });
66
+ it('overrides the path option by the first argument', function () {
67
+ let Target = class Target {
68
+ };
69
+ Target = __decorate([
70
+ controller('myPath1', { path: 'myPath2' })
71
+ ], Target);
72
+ const res = ControllerReflector.getMetadata(Target);
73
+ expect(res).to.be.eql({ className: 'Target', path: 'myPath1' });
74
+ });
47
75
  });
@@ -1,3 +1,5 @@
1
+ export * from './after/index.js';
2
+ export * from './before/index.js';
1
3
  export * from './action/index.js';
2
4
  export * from './controller/index.js';
3
5
  export * from './request-data/index.js';
@@ -1,3 +1,5 @@
1
+ export * from './after/index.js';
2
+ export * from './before/index.js';
1
3
  export * from './action/index.js';
2
4
  export * from './controller/index.js';
3
5
  export * from './request-data/index.js';
@@ -23,7 +23,7 @@ export declare const headers: () => (target: Prototype<object>, propertyKey: str
23
23
  export declare const header: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
24
24
  export declare const cookies: () => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
25
25
  export declare const cookie: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
26
- export declare const bodyParam: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
26
+ export declare const bodyProp: (propertyKey: string, schemaOrType?: DataSchema | DataType) => (target: Prototype<object>, propertyKey: string, indexOrDescriptor: number) => void;
27
27
  /**
28
28
  * Request body decorator.
29
29
  *
@@ -63,7 +63,7 @@ export const headers = createRequestDataDecoratorWithSource(RequestDataSource.HE
63
63
  export const header = createRequestDataPropertyDecoratorWithSource(RequestDataSource.HEADERS);
64
64
  export const cookies = createRequestDataDecoratorWithSource(RequestDataSource.COOKIE);
65
65
  export const cookie = createRequestDataPropertyDecoratorWithSource(RequestDataSource.COOKIE);
66
- export const bodyParam = createRequestDataPropertyDecoratorWithSource(RequestDataSource.BODY);
66
+ export const bodyProp = createRequestDataPropertyDecoratorWithSource(RequestDataSource.BODY);
67
67
  /**
68
68
  * Request body decorator.
69
69
  *
@@ -22,7 +22,7 @@ import { params } from './request-data-decorator.js';
22
22
  import { queries } from './request-data-decorator.js';
23
23
  import { cookies } from './request-data-decorator.js';
24
24
  import { headers } from './request-data-decorator.js';
25
- import { bodyParam } from './request-data-decorator.js';
25
+ import { bodyProp } from './request-data-decorator.js';
26
26
  import { requestData } from './request-data-decorator.js';
27
27
  import { RequestDataSource } from './request-data-metadata.js';
28
28
  import { RequestDataReflector } from './request-data-reflector.js';
@@ -460,13 +460,13 @@ describe('requestData', function () {
460
460
  });
461
461
  });
462
462
  });
463
- describe('bodyParam', function () {
463
+ describe('bodyProp', function () {
464
464
  it('sets a given "propertyKey" to the target metadata', function () {
465
465
  class Target {
466
466
  myMethod(prop) { }
467
467
  }
468
468
  __decorate([
469
- __param(0, bodyParam('myPropertyKey')),
469
+ __param(0, bodyProp('myPropertyKey')),
470
470
  __metadata("design:type", Function),
471
471
  __metadata("design:paramtypes", [Object]),
472
472
  __metadata("design:returntype", void 0)
@@ -485,7 +485,7 @@ describe('requestData', function () {
485
485
  myMethod(prop) { }
486
486
  }
487
487
  __decorate([
488
- __param(0, bodyParam(propertyKey, propertyType)),
488
+ __param(0, bodyProp(propertyKey, propertyType)),
489
489
  __metadata("design:type", Function),
490
490
  __metadata("design:paramtypes", [Object]),
491
491
  __metadata("design:returntype", void 0)
@@ -514,7 +514,7 @@ describe('requestData', function () {
514
514
  myMethod(prop) { }
515
515
  }
516
516
  __decorate([
517
- __param(0, bodyParam(propertyKey, schema)),
517
+ __param(0, bodyProp(propertyKey, schema)),
518
518
  __metadata("design:type", Function),
519
519
  __metadata("design:paramtypes", [Object]),
520
520
  __metadata("design:returntype", void 0)
@@ -1,11 +1,44 @@
1
- import { format } from '@e22m4u/js-format';
2
1
  /**
3
2
  * Debugger.
4
3
  */
5
- export type Debugger = (...args: Parameters<typeof format>) => void;
4
+ export type Debugger = (messageOrData: string | unknown, ...args: any[]) => void;
6
5
  /**
7
6
  * Create debugger.
8
7
  *
8
+ * Base usage:
9
+ * ```ts
10
+ * const debug = createDebugger('myService');
11
+ * debug('Service created.');
12
+ * // ujut:myService Service created.
13
+ * ```
14
+ *
15
+ * Nested namespaces:
16
+ * ```ts
17
+ * const debug1 = debug.bind('namespace1');
18
+ * const debug2 = debug.bind('namespace2');
19
+ * debug1('Application started'); // ujut:myService [namespace1] Application started
20
+ * debug2('Connection established'); // ujut:myService [namespace2] Connection established
21
+ * ```
22
+ *
23
+ * Value inspection:
24
+ * ```ts
25
+ * debug({foo: 'lorem', bar: 'ipsum'})
26
+ * // ujut:myService {
27
+ * // ujut:myService "foo": "lorem",
28
+ * // ujut:myService "bar": "ipsum"
29
+ * // ujut:myService }
30
+ * ```
31
+ *
32
+ * Titled inspection output:
33
+ * ```ts
34
+ * debug({foo: 'lorem', bar: 'ipsum'}, 'My awesome output:')
35
+ * // ujut:myService My awesome output:
36
+ * // ujut:myService {
37
+ * // ujut:myService "foo": "lorem",
38
+ * // ujut:myService "bar": "ipsum"
39
+ * // ujut:myService }
40
+ * ```
41
+ *
9
42
  * @param name
10
43
  */
11
44
  export declare function createDebugger(name: string): Debugger;
@@ -1,15 +1,81 @@
1
- import DebugFactory from 'debug';
1
+ import { inspect } from 'util';
2
+ import DebugModule from 'debug';
2
3
  import { format } from '@e22m4u/js-format';
4
+ /**
5
+ * Colorize string.
6
+ *
7
+ * @param input
8
+ */
9
+ function colorizeString(input) {
10
+ const c = Number(DebugModule['selectColor'](input));
11
+ const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
12
+ return `${colorCode};1m${input}\u001B[0m`;
13
+ }
3
14
  /**
4
15
  * Create debugger.
5
16
  *
17
+ * Base usage:
18
+ * ```ts
19
+ * const debug = createDebugger('myService');
20
+ * debug('Service created.');
21
+ * // ujut:myService Service created.
22
+ * ```
23
+ *
24
+ * Nested namespaces:
25
+ * ```ts
26
+ * const debug1 = debug.bind('namespace1');
27
+ * const debug2 = debug.bind('namespace2');
28
+ * debug1('Application started'); // ujut:myService [namespace1] Application started
29
+ * debug2('Connection established'); // ujut:myService [namespace2] Connection established
30
+ * ```
31
+ *
32
+ * Value inspection:
33
+ * ```ts
34
+ * debug({foo: 'lorem', bar: 'ipsum'})
35
+ * // ujut:myService {
36
+ * // ujut:myService "foo": "lorem",
37
+ * // ujut:myService "bar": "ipsum"
38
+ * // ujut:myService }
39
+ * ```
40
+ *
41
+ * Titled inspection output:
42
+ * ```ts
43
+ * debug({foo: 'lorem', bar: 'ipsum'}, 'My awesome output:')
44
+ * // ujut:myService My awesome output:
45
+ * // ujut:myService {
46
+ * // ujut:myService "foo": "lorem",
47
+ * // ujut:myService "bar": "ipsum"
48
+ * // ujut:myService }
49
+ * ```
50
+ *
6
51
  * @param name
7
52
  */
8
53
  export function createDebugger(name) {
9
- const debug = DebugFactory(`tsRestRouter:${name}`);
54
+ const debuggerName = `tsRestRouter:${name}`;
55
+ // включить вывод логов можно принудительно
56
+ // if (!process.env.DEBUG) DebugModule.enable('ujut*');
57
+ const debug = DebugModule(debuggerName);
58
+ return function (messageOrData,
10
59
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
- return function (message, ...args) {
12
- const interpolatedMessage = format(message, ...args);
13
- return debug(interpolatedMessage);
60
+ ...args) {
61
+ let prefix = '';
62
+ if (typeof this === 'string') {
63
+ const isDebugUsesColors = debug.useColors;
64
+ prefix = isDebugUsesColors ? colorizeString(`[${this}] `) : `[${this}] `;
65
+ }
66
+ if (typeof messageOrData === 'string') {
67
+ const interpolatedMessage = format(messageOrData, ...args);
68
+ return debug(prefix + interpolatedMessage);
69
+ }
70
+ const inspectOptions = {
71
+ showHidden: false,
72
+ depth: null,
73
+ colors: true,
74
+ compact: false,
75
+ };
76
+ const multiString = inspect(messageOrData, inspectOptions);
77
+ const rows = multiString.split('\n');
78
+ const colorizedDebuggerName = colorizeString(debuggerName);
79
+ [...args, ...rows].forEach(v => console.log(` ${colorizedDebuggerName} ${prefix}${v}`));
14
80
  };
15
81
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/ts-rest-router",
3
- "version": "0.0.7",
3
+ "version": "0.1.0",
4
4
  "description": "Controllers-based REST router implementation for TypeScript",
5
5
  "author": "e22m4u <e22m4u@yandex.ru>",
6
6
  "keywords": [