@my-devkit/firebase 1.0.81 → 1.0.85

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 (198) hide show
  1. package/.eslintrc.js +15 -0
  2. package/.vscode/settings.json +7 -0
  3. package/{aggregate.d.ts → dist/aggregate.d.ts} +0 -0
  4. package/{aggregate.js → dist/aggregate.js} +0 -0
  5. package/{aggregate.js.map → dist/aggregate.js.map} +0 -0
  6. package/{app-factory.d.ts → dist/app-factory.d.ts} +0 -0
  7. package/{app-factory.js → dist/app-factory.js} +0 -0
  8. package/{app-factory.js.map → dist/app-factory.js.map} +0 -0
  9. package/{bus.d.ts → dist/bus.d.ts} +0 -0
  10. package/{bus.js → dist/bus.js} +0 -0
  11. package/{bus.js.map → dist/bus.js.map} +0 -0
  12. package/{constants.d.ts → dist/constants.d.ts} +0 -0
  13. package/{constants.js → dist/constants.js} +0 -0
  14. package/{constants.js.map → dist/constants.js.map} +0 -0
  15. package/{context.d.ts → dist/context.d.ts} +0 -0
  16. package/{context.js → dist/context.js} +0 -0
  17. package/{context.js.map → dist/context.js.map} +0 -0
  18. package/{decorators → dist/decorators}/controller/body.d.ts +0 -0
  19. package/{decorators → dist/decorators}/controller/body.js +0 -0
  20. package/{decorators → dist/decorators}/controller/body.js.map +0 -0
  21. package/{decorators → dist/decorators}/controller/body.spec.d.ts +0 -0
  22. package/{decorators → dist/decorators}/controller/body.spec.js +0 -0
  23. package/{decorators → dist/decorators}/controller/body.spec.js.map +0 -0
  24. package/{decorators → dist/decorators}/controller/controller.d.ts +0 -0
  25. package/{decorators → dist/decorators}/controller/controller.js +0 -0
  26. package/{decorators → dist/decorators}/controller/controller.js.map +0 -0
  27. package/{decorators → dist/decorators}/controller/controller.spec.d.ts +0 -0
  28. package/{decorators → dist/decorators}/controller/controller.spec.js +0 -0
  29. package/{decorators → dist/decorators}/controller/controller.spec.js.map +0 -0
  30. package/{decorators → dist/decorators}/controller/get.d.ts +0 -0
  31. package/{decorators → dist/decorators}/controller/get.js +0 -0
  32. package/{decorators → dist/decorators}/controller/get.js.map +0 -0
  33. package/{decorators → dist/decorators}/controller/get.spec.d.ts +0 -0
  34. package/{decorators → dist/decorators}/controller/get.spec.js +0 -0
  35. package/{decorators → dist/decorators}/controller/get.spec.js.map +0 -0
  36. package/{decorators → dist/decorators}/controller/index.d.ts +0 -0
  37. package/{decorators → dist/decorators}/controller/index.js +0 -0
  38. package/{decorators → dist/decorators}/controller/index.js.map +0 -0
  39. package/{decorators → dist/decorators}/controller/param.d.ts +0 -0
  40. package/{decorators → dist/decorators}/controller/param.js +0 -0
  41. package/{decorators → dist/decorators}/controller/param.js.map +0 -0
  42. package/{decorators → dist/decorators}/controller/param.spec.d.ts +0 -0
  43. package/{decorators → dist/decorators}/controller/param.spec.js +0 -0
  44. package/{decorators → dist/decorators}/controller/param.spec.js.map +0 -0
  45. package/{decorators → dist/decorators}/controller/post.d.ts +0 -0
  46. package/{decorators → dist/decorators}/controller/post.js +0 -0
  47. package/{decorators → dist/decorators}/controller/post.js.map +0 -0
  48. package/{decorators → dist/decorators}/controller/post.spec.d.ts +0 -0
  49. package/{decorators → dist/decorators}/controller/post.spec.js +0 -0
  50. package/{decorators → dist/decorators}/controller/post.spec.js.map +0 -0
  51. package/{decorators → dist/decorators}/controller/query.d.ts +0 -0
  52. package/{decorators → dist/decorators}/controller/query.js +0 -0
  53. package/{decorators → dist/decorators}/controller/query.js.map +0 -0
  54. package/{decorators → dist/decorators}/controller/query.spec.d.ts +0 -0
  55. package/{decorators → dist/decorators}/controller/query.spec.js +0 -0
  56. package/{decorators → dist/decorators}/controller/query.spec.js.map +0 -0
  57. package/{decorators → dist/decorators}/handler/command-handler.d.ts +0 -0
  58. package/{decorators → dist/decorators}/handler/command-handler.js +0 -0
  59. package/{decorators → dist/decorators}/handler/command-handler.js.map +0 -0
  60. package/{decorators → dist/decorators}/handler/command-handler.spec.d.ts +0 -0
  61. package/{decorators → dist/decorators}/handler/command-handler.spec.js +0 -0
  62. package/{decorators → dist/decorators}/handler/command-handler.spec.js.map +0 -0
  63. package/{decorators → dist/decorators}/handler/event-handler.d.ts +0 -0
  64. package/{decorators → dist/decorators}/handler/event-handler.js +0 -0
  65. package/{decorators → dist/decorators}/handler/event-handler.js.map +0 -0
  66. package/{decorators → dist/decorators}/handler/event-handler.spec.d.ts +0 -0
  67. package/{decorators → dist/decorators}/handler/event-handler.spec.js +0 -0
  68. package/{decorators → dist/decorators}/handler/event-handler.spec.js.map +0 -0
  69. package/{decorators → dist/decorators}/handler/index.d.ts +0 -0
  70. package/{decorators → dist/decorators}/handler/index.js +0 -0
  71. package/{decorators → dist/decorators}/handler/index.js.map +0 -0
  72. package/{decorators → dist/decorators}/index.d.ts +0 -0
  73. package/{decorators → dist/decorators}/index.js +0 -0
  74. package/{decorators → dist/decorators}/index.js.map +0 -0
  75. package/{decorators → dist/decorators}/injectable.d.ts +0 -0
  76. package/{decorators → dist/decorators}/injectable.js +0 -0
  77. package/{decorators → dist/decorators}/injectable.js.map +0 -0
  78. package/{decorators → dist/decorators}/module.d.ts +0 -0
  79. package/{decorators → dist/decorators}/module.js +0 -0
  80. package/{decorators → dist/decorators}/module.js.map +0 -0
  81. package/{decorators → dist/decorators}/transactional-client.d.ts +0 -0
  82. package/{decorators → dist/decorators}/transactional-client.js +0 -0
  83. package/{decorators → dist/decorators}/transactional-client.js.map +0 -0
  84. package/{execution-mode-enum.d.ts → dist/execution-mode-enum.d.ts} +0 -0
  85. package/{execution-mode-enum.js → dist/execution-mode-enum.js} +0 -0
  86. package/{execution-mode-enum.js.map → dist/execution-mode-enum.js.map} +0 -0
  87. package/{firestore-client.d.ts → dist/firestore-client.d.ts} +0 -0
  88. package/{firestore-client.js → dist/firestore-client.js} +0 -0
  89. package/{firestore-client.js.map → dist/firestore-client.js.map} +0 -0
  90. package/{handler-helper.d.ts → dist/handler-helper.d.ts} +0 -0
  91. package/{handler-helper.js → dist/handler-helper.js} +0 -0
  92. package/{handler-helper.js.map → dist/handler-helper.js.map} +0 -0
  93. package/{index.d.ts → dist/index.d.ts} +0 -0
  94. package/{index.js → dist/index.js} +0 -0
  95. package/{index.js.map → dist/index.js.map} +0 -0
  96. package/{injector.d.ts → dist/injector.d.ts} +0 -0
  97. package/{injector.js → dist/injector.js} +0 -0
  98. package/{injector.js.map → dist/injector.js.map} +0 -0
  99. package/{interfaces → dist/interfaces}/app-config.d.ts +0 -0
  100. package/{interfaces → dist/interfaces}/app-config.js +0 -0
  101. package/{interfaces → dist/interfaces}/app-config.js.map +0 -0
  102. package/{interfaces → dist/interfaces}/from-array.d.ts +0 -0
  103. package/{interfaces → dist/interfaces}/from-array.js +0 -0
  104. package/{interfaces → dist/interfaces}/from-array.js.map +0 -0
  105. package/{interfaces → dist/interfaces}/index.d.ts +0 -0
  106. package/{interfaces → dist/interfaces}/index.js +0 -0
  107. package/{interfaces → dist/interfaces}/index.js.map +0 -0
  108. package/{interfaces → dist/interfaces}/newable.d.ts +0 -0
  109. package/{interfaces → dist/interfaces}/newable.js +0 -0
  110. package/{interfaces → dist/interfaces}/newable.js.map +0 -0
  111. package/{interfaces → dist/interfaces}/transactional-client.d.ts +0 -0
  112. package/{interfaces → dist/interfaces}/transactional-client.js +0 -0
  113. package/{interfaces → dist/interfaces}/transactional-client.js.map +0 -0
  114. package/{interfaces → dist/interfaces}/type.d.ts +0 -0
  115. package/{interfaces → dist/interfaces}/type.js +0 -0
  116. package/{interfaces → dist/interfaces}/type.js.map +0 -0
  117. package/{reflect.d.ts → dist/reflect.d.ts} +0 -0
  118. package/{reflect.js → dist/reflect.js} +0 -0
  119. package/{reflect.js.map → dist/reflect.js.map} +0 -0
  120. package/{request-method.enum.d.ts → dist/request-method.enum.d.ts} +0 -0
  121. package/{request-method.enum.js → dist/request-method.enum.js} +0 -0
  122. package/{request-method.enum.js.map → dist/request-method.enum.js.map} +0 -0
  123. package/{server → dist/server}/index.d.ts +0 -0
  124. package/{server → dist/server}/index.js +0 -0
  125. package/{server → dist/server}/index.js.map +0 -0
  126. package/{server → dist/server}/middlewares/authentication-middleware.d.ts +0 -0
  127. package/{server → dist/server}/middlewares/authentication-middleware.js +0 -0
  128. package/{server → dist/server}/middlewares/authentication-middleware.js.map +0 -0
  129. package/{server → dist/server}/middlewares/create-context-middleware.d.ts +0 -0
  130. package/{server → dist/server}/middlewares/create-context-middleware.js +0 -0
  131. package/{server → dist/server}/middlewares/create-context-middleware.js.map +0 -0
  132. package/{server → dist/server}/middlewares/error-middleware.d.ts +0 -0
  133. package/{server → dist/server}/middlewares/error-middleware.js +0 -0
  134. package/{server → dist/server}/middlewares/error-middleware.js.map +0 -0
  135. package/{server → dist/server}/middlewares/headers-middleware.d.ts +0 -0
  136. package/{server → dist/server}/middlewares/headers-middleware.js +0 -0
  137. package/{server → dist/server}/middlewares/headers-middleware.js.map +0 -0
  138. package/{server → dist/server}/middlewares/index.d.ts +0 -0
  139. package/{server → dist/server}/middlewares/index.js +0 -0
  140. package/{server → dist/server}/middlewares/index.js.map +0 -0
  141. package/{server → dist/server}/middlewares/not-found-middleware.d.ts +0 -0
  142. package/{server → dist/server}/middlewares/not-found-middleware.js +0 -0
  143. package/{server → dist/server}/middlewares/not-found-middleware.js.map +0 -0
  144. package/{server → dist/server}/server.d.ts +0 -0
  145. package/{server → dist/server}/server.js +0 -0
  146. package/{server → dist/server}/server.js.map +0 -0
  147. package/dist/tsconfig.tsbuildinfo +1 -0
  148. package/package.json +5 -5
  149. package/src/aggregate.ts +54 -0
  150. package/src/app-factory.ts +252 -0
  151. package/src/bus.ts +70 -0
  152. package/src/constants.ts +5 -0
  153. package/src/context.ts +108 -0
  154. package/src/decorators/controller/body.spec.ts +52 -0
  155. package/src/decorators/controller/body.ts +17 -0
  156. package/src/decorators/controller/controller.spec.ts +19 -0
  157. package/src/decorators/controller/controller.ts +10 -0
  158. package/src/decorators/controller/get.spec.ts +32 -0
  159. package/src/decorators/controller/get.ts +8 -0
  160. package/src/decorators/controller/index.ts +8 -0
  161. package/src/decorators/controller/param.spec.ts +51 -0
  162. package/src/decorators/controller/param.ts +21 -0
  163. package/src/decorators/controller/post.spec.ts +60 -0
  164. package/src/decorators/controller/post.ts +8 -0
  165. package/src/decorators/controller/query.spec.ts +51 -0
  166. package/src/decorators/controller/query.ts +21 -0
  167. package/src/decorators/handler/command-handler.spec.ts +101 -0
  168. package/src/decorators/handler/command-handler.ts +23 -0
  169. package/src/decorators/handler/event-handler.spec.ts +104 -0
  170. package/src/decorators/handler/event-handler.ts +24 -0
  171. package/src/decorators/handler/index.ts +2 -0
  172. package/src/decorators/index.ts +5 -0
  173. package/src/decorators/injectable.ts +7 -0
  174. package/src/decorators/module.ts +29 -0
  175. package/src/decorators/transactional-client.ts +7 -0
  176. package/src/execution-mode-enum.ts +4 -0
  177. package/src/firestore-client.ts +125 -0
  178. package/src/handler-helper.ts +68 -0
  179. package/src/index.ts +7 -0
  180. package/src/injector.ts +31 -0
  181. package/src/interfaces/app-config.ts +1 -0
  182. package/src/interfaces/from-array.ts +1 -0
  183. package/src/interfaces/index.ts +4 -0
  184. package/src/interfaces/newable.ts +1 -0
  185. package/src/interfaces/transactional-client.ts +3 -0
  186. package/src/interfaces/type.ts +3 -0
  187. package/src/reflect.ts +164 -0
  188. package/src/request-method.enum.ts +4 -0
  189. package/src/server/index.ts +1 -0
  190. package/src/server/middlewares/authentication-middleware.ts +47 -0
  191. package/src/server/middlewares/create-context-middleware.ts +16 -0
  192. package/src/server/middlewares/error-middleware.ts +33 -0
  193. package/src/server/middlewares/headers-middleware.ts +16 -0
  194. package/src/server/middlewares/index.ts +5 -0
  195. package/src/server/middlewares/not-found-middleware.ts +9 -0
  196. package/src/server/server.ts +96 -0
  197. package/tsconfig.json +24 -0
  198. package/tsconfig.tsbuildinfo +0 -1
package/src/context.ts ADDED
@@ -0,0 +1,108 @@
1
+ import { Logger } from '@my-devkit/core';
2
+ import { AsyncHook, createHook, executionAsyncId } from 'async_hooks';
3
+
4
+ import { Bus } from './bus';
5
+ import { Injector } from './injector';
6
+ import { ITransactionalClient, Type } from './interfaces';
7
+
8
+ interface ContextStore {
9
+ injector: Injector;
10
+ bus: Bus;
11
+ correlationId?: string;
12
+ eventId?: string;
13
+ user?: UserRecord;
14
+ }
15
+
16
+ interface UserRecord {
17
+ uid: string;
18
+ email?: string;
19
+ displayName?: string;
20
+ photoURL?: string;
21
+ disabled: boolean;
22
+ }
23
+
24
+ export class Context {
25
+ private static store = new Map<number, ContextStore>();
26
+ private static asyncHook: AsyncHook;
27
+
28
+ public static init(): void {
29
+ this.asyncHook = createHook({
30
+ init: (asyncId: number, _type: string, triggerAsyncId: number) => {
31
+ if (this.store.has(triggerAsyncId)) {
32
+ this.store.set(asyncId, this.store.get(triggerAsyncId))
33
+ }
34
+ },
35
+ destroy: (asyncId: number) => {
36
+ this.store.delete(asyncId);
37
+ }
38
+ });
39
+ this.asyncHook.enable();
40
+ }
41
+
42
+ public static create(bus: Bus): void {
43
+ this.store.set(executionAsyncId(), { injector: new Injector(), bus });
44
+ }
45
+
46
+ public static resolve<T>(type: Type<T>): T {
47
+ if (!this.store.has(executionAsyncId())) {
48
+ throw new Error(`Create context before resolving an injection!`);
49
+ }
50
+ return this.store.get(executionAsyncId()).injector.resolve(type);
51
+ }
52
+
53
+ public static getTransactionalClients(): ITransactionalClient[] {
54
+ if (!this.store.has(executionAsyncId())) {
55
+ throw new Error(`Create context before getting transactional clients!`);
56
+ }
57
+ return this.store.get(executionAsyncId()).injector.getTransactionalClients();
58
+ }
59
+
60
+ public static get bus(): Bus {
61
+ return this.store.get(executionAsyncId())?.bus;
62
+ }
63
+
64
+ public static set correlationId(correlationId: string) {
65
+ if (!this.store.has(executionAsyncId())) {
66
+ throw new Error(`Create context before setting correlationId!`);
67
+ }
68
+ this.store.get(executionAsyncId()).correlationId = correlationId;
69
+ }
70
+
71
+ public static get correlationId(): string {
72
+ return this.store.get(executionAsyncId())?.correlationId;
73
+ }
74
+
75
+ public static set eventId(eventId: string) {
76
+ if (!this.store.has(executionAsyncId())) {
77
+ throw new Error(`Create context before setting eventId!`);
78
+ }
79
+ this.store.get(executionAsyncId()).eventId = eventId;
80
+ }
81
+
82
+ public static get eventId(): string {
83
+ return this.store.get(executionAsyncId())?.eventId;
84
+ }
85
+
86
+ public static set user(user: UserRecord) {
87
+ if (!this.store.has(executionAsyncId())) {
88
+ throw new Error(`Create context before setting user!`);
89
+ }
90
+ this.store.get(executionAsyncId()).user = user;
91
+ }
92
+
93
+ public static get user(): UserRecord {
94
+ return this.store.get(executionAsyncId())?.user;
95
+ }
96
+
97
+ public static destroy(): void {
98
+ this.store.delete(executionAsyncId());
99
+ }
100
+
101
+ public static size(): number {
102
+ return this.store.size;
103
+ }
104
+
105
+ public static logRemainingKeys(): void {
106
+ Logger.info(Array.from(this.store.keys()).join(' '));
107
+ }
108
+ }
@@ -0,0 +1,52 @@
1
+ import { autoserializeAs } from '@my-devkit/core';
2
+ import { expect } from 'chai';
3
+
4
+ import { reflect } from '../../reflect';
5
+ import { Body } from './body';
6
+ import { Controller } from './controller';
7
+
8
+ describe('Given a Body decorator', () => {
9
+
10
+ class Command {
11
+ @autoserializeAs(String)
12
+ public testString: string = null;
13
+
14
+ @autoserializeAs(Date)
15
+ public testDate: Date = null;
16
+ }
17
+
18
+
19
+ @Controller('test')
20
+ class TestClass {
21
+ public testDate(@Body() param1: Date): string {
22
+ return `testDate: ${param1}`;
23
+ }
24
+
25
+ public testCommand(@Body() param1: Command): string {
26
+ return `testCommand: ${param1}`;
27
+ }
28
+ }
29
+
30
+ describe('When decorator is called', () => {
31
+ it('Then we should retrieve information via reflect', async () => {
32
+ const config = reflect(TestClass).getControllerConfiguration();
33
+ expect(config.routes.length).equal(2, 'Wrong route count detected');
34
+
35
+ const request1 = <any>{ body: '2021-02-08T11:14:23.318Z' };
36
+
37
+ expect(config.routes[0].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length');
38
+ expect(config.routes[0].argumentInjectors[0](request1)).to.be.a('Date');
39
+ expect(config.routes[0].argumentInjectors[0](request1).toISOString()).equals((new Date('2021-02-08T11:14:23.318Z')).toISOString());
40
+
41
+ const request2 = <any>{ body: { testString: 'test' } };
42
+
43
+ const expectedBody2 = new Command();
44
+ expectedBody2.testString = 'test';
45
+ expectedBody2.testDate = null;
46
+
47
+ expect(config.routes[1].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length');
48
+ expect(config.routes[1].argumentInjectors[0](request2)).to.be.instanceOf(Command);
49
+ expect(config.routes[1].argumentInjectors[0](request2)).deep.equal(expectedBody2);
50
+ });
51
+ });
52
+ });
@@ -0,0 +1,17 @@
1
+ import { deserialize } from '@my-devkit/core';
2
+
3
+ import { reflect, RequestArgumentInjector } from '../../reflect';
4
+ import { Server } from '../../server';
5
+
6
+ export function Body(): ParameterDecorator {
7
+ return (target, propertyKey, parameterIndex) => {
8
+ const methodArguments = reflect(target, propertyKey).getParameters();
9
+ if (!methodArguments.hasOwnProperty(parameterIndex)) {
10
+ throw new Error(`Body: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`);
11
+ }
12
+
13
+ const injector: RequestArgumentInjector = (req: Server.Request) => deserialize(req.body, methodArguments[parameterIndex]);
14
+
15
+ reflect(target, propertyKey).registerControllerRouteArgumentInjector(injector, parameterIndex);
16
+ }
17
+ }
@@ -0,0 +1,19 @@
1
+ import { expect } from 'chai';
2
+
3
+ import { reflect } from '../../reflect';
4
+ import { Controller } from './controller';
5
+
6
+ describe('Given a Controller decorator', () => {
7
+
8
+ @Controller('test')
9
+ class TestClass {
10
+ }
11
+
12
+ describe('When decorator is called', () => {
13
+ it('Then we should retrieve information via reflect', async () => {
14
+ const config = reflect(TestClass).getControllerConfiguration();
15
+
16
+ expect(config.basePath).equals('test');
17
+ });
18
+ });
19
+ });
@@ -0,0 +1,10 @@
1
+ import { reflect } from '../../reflect';
2
+ import { Injectable } from './../injectable';
3
+
4
+ export function Controller(basePath: string): ClassDecorator {
5
+ return target => {
6
+ reflect(target).registerController(basePath);
7
+ // Register controller as injectable ressource
8
+ Injectable()(target);
9
+ };
10
+ }
@@ -0,0 +1,32 @@
1
+ import { guid } from '@my-devkit/core';
2
+ import { expect } from 'chai';
3
+
4
+ import { Get } from '.';
5
+ import { reflect } from '../../reflect';
6
+ import { RequestMethod } from '../../request-method.enum';
7
+ import { Controller } from './controller';
8
+
9
+ describe('Given a Get decorator', () => {
10
+
11
+ @Controller('test')
12
+ class TestClass {
13
+ public test = guid();
14
+
15
+ @Get('create')
16
+ public get(): string {
17
+ return `create`;
18
+ }
19
+ }
20
+
21
+ describe('When decorator is called', () => {
22
+ it('Then we should retrieve information via reflect', async () => {
23
+ const config = reflect(TestClass).getControllerConfiguration();
24
+
25
+ expect(config.routes.length).equal(1, 'Wrong route count detected');
26
+
27
+ expect(config.routes[0].path).equal('create');
28
+ expect(config.routes[0].methodName).equal('get');
29
+ expect(config.routes[0].requestMethod).equal(RequestMethod.GET);
30
+ });
31
+ });
32
+ });
@@ -0,0 +1,8 @@
1
+ import { reflect } from '../../reflect';
2
+ import { RequestMethod } from '../../request-method.enum';
3
+
4
+ export function Get(path: string): MethodDecorator {
5
+ return (target, propertyKey) => {
6
+ reflect(target.constructor, propertyKey).registerControllerRoute({ path, requestMethod: RequestMethod.GET });
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ export * from './controller';
2
+
3
+ export * from './body';
4
+ export * from './param';
5
+ export * from './query';
6
+
7
+ export * from './get';
8
+ export * from './post';
@@ -0,0 +1,51 @@
1
+ import { expect } from 'chai';
2
+
3
+ import { reflect } from '../../reflect';
4
+ import { Controller } from './controller';
5
+ import { Get } from './get';
6
+ import { Param } from './param';
7
+
8
+ describe('Given a Param decorator', () => {
9
+
10
+ enum Gender {
11
+ Male = 0,
12
+ Female = 'Female'
13
+ }
14
+
15
+ @Controller('test')
16
+ class TestClass {
17
+ @Get(':id')
18
+ public getById(@Param('id') id: string): string {
19
+ return `getById: ${id}`;
20
+ }
21
+
22
+ @Get(':gender/:minDate')
23
+ public getByGenderOlderThan(@Param('minDate') minDate: Date, @Param('gender') gender: Gender): string {
24
+ return `getByGenderOlderThan: ${gender} ${minDate.toISOString()}`;
25
+ }
26
+ }
27
+
28
+ describe('When decorator is called', () => {
29
+ it('Then we should retrieve information via reflect', async () => {
30
+ const config = reflect(TestClass).getControllerConfiguration();
31
+ expect(config.routes.length).equal(2, 'Wrong route count detected');
32
+
33
+ const request1 = <any>{ params: { id: 'guid 1' } };
34
+ expect(config.routes[0].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length for getById');
35
+ expect(config.routes[0].argumentInjectors[0](request1)).to.be.a('string');
36
+ expect(config.routes[0].argumentInjectors[0](request1)).equals('guid 1');
37
+
38
+ const request2 = <any>{ params: { gender: 0, minDate: '2021-02-15T14:23:00.318Z' } };
39
+
40
+ expect(config.routes[1].argumentInjectors.length).equal(2, 'Wrong argumentInjectors length for getByGenderOlderThan');
41
+
42
+ expect(config.routes[1].argumentInjectors[0](request2)).to.be.a('Date');
43
+ expect(config.routes[1].argumentInjectors[0](request2).toISOString()).equals((new Date('2021-02-15T14:23:00.318Z')).toISOString());
44
+
45
+ expect(config.routes[1].argumentInjectors[1](request2)).equals(Gender.Male);
46
+
47
+ request2.params.gender = 'Female';
48
+ expect(config.routes[1].argumentInjectors[1](request2)).equals(Gender.Female);
49
+ });
50
+ });
51
+ });
@@ -0,0 +1,21 @@
1
+ import { deserialize } from '@my-devkit/core';
2
+
3
+ import { reflect, RequestArgumentInjector } from '../../reflect';
4
+ import { Server } from '../../server';
5
+
6
+ export function Param(key: string): ParameterDecorator {
7
+ return (target, propertyKey, parameterIndex) => {
8
+ const methodArguments = reflect(target, propertyKey).getParameters();
9
+ if (!methodArguments.hasOwnProperty(parameterIndex)) {
10
+ throw new Error(`Param: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`);
11
+ }
12
+
13
+ const injector: RequestArgumentInjector = (req: Server.Request) => {
14
+ if (req.params.hasOwnProperty(key)) {
15
+ return deserialize(req.params[key], methodArguments[parameterIndex]);
16
+ }
17
+ };
18
+
19
+ reflect(target, propertyKey).registerControllerRouteArgumentInjector(injector, parameterIndex);
20
+ }
21
+ }
@@ -0,0 +1,60 @@
1
+ import { autoserializeAs, guid } from '@my-devkit/core';
2
+ import { expect } from 'chai';
3
+
4
+ import { reflect } from '../../reflect';
5
+ import { RequestMethod } from '../../request-method.enum';
6
+ import { Body } from './body';
7
+ import { Controller } from './controller';
8
+ import { Post } from './post';
9
+
10
+ describe('Given a Post decorator', () => {
11
+
12
+ class Command {
13
+ @autoserializeAs(String)
14
+ public testString: string = null;
15
+
16
+ @autoserializeAs(Date)
17
+ public testDate: Date = null;
18
+ }
19
+
20
+
21
+ @Controller('test')
22
+ class TestClass {
23
+ public test = guid();
24
+
25
+ @Post('create')
26
+ public createMethod(@Body() param1: Date): string {
27
+ return `createMethod: ${param1}`;
28
+ }
29
+
30
+ @Post('update')
31
+ public updateMethod(@Body() param1: Command): string {
32
+ return `updateMethod: ${param1}`;
33
+ }
34
+
35
+ @Post('delete')
36
+ public deleteMethod(@Body() param1: Command): string {
37
+ return `deleteMethod: ${param1}`;
38
+ }
39
+ }
40
+
41
+ describe('When decorator is called', () => {
42
+ it('Then we should retrieve information via reflect', async () => {
43
+ const config = reflect(TestClass).getControllerConfiguration();
44
+
45
+ expect(config.routes.length).equal(3, 'Wrong route count detected');
46
+
47
+ expect(config.routes[0].path).equal('create');
48
+ expect(config.routes[0].methodName).equal('createMethod');
49
+ expect(config.routes[0].requestMethod).equal(RequestMethod.POST);
50
+
51
+ expect(config.routes[1].path).equal('update');
52
+ expect(config.routes[1].methodName).equal('updateMethod');
53
+ expect(config.routes[1].requestMethod).equal(RequestMethod.POST);
54
+
55
+ expect(config.routes[2].path).equal('delete');
56
+ expect(config.routes[2].methodName).equal('deleteMethod');
57
+ expect(config.routes[2].requestMethod).equal(RequestMethod.POST);
58
+ });
59
+ });
60
+ });
@@ -0,0 +1,8 @@
1
+ import { reflect } from '../../reflect';
2
+ import { RequestMethod } from '../../request-method.enum';
3
+
4
+ export function Post(path: string): MethodDecorator {
5
+ return (target, propertyKey) => {
6
+ reflect(target.constructor, propertyKey).registerControllerRoute({ path, requestMethod: RequestMethod.POST });
7
+ }
8
+ }
@@ -0,0 +1,51 @@
1
+ import { expect } from 'chai';
2
+
3
+ import { reflect } from '../../reflect';
4
+ import { Controller } from './controller';
5
+ import { Get } from './get';
6
+ import { Query } from './query';
7
+
8
+ describe('Given a Query decorator', () => {
9
+
10
+ enum Gender {
11
+ Male = 0,
12
+ Female = 'Female'
13
+ }
14
+
15
+ @Controller('test')
16
+ class TestClass {
17
+ @Get('by-id')
18
+ public getById(@Query('id') id: string): string {
19
+ return `getById: ${id}`;
20
+ }
21
+
22
+ @Get('all')
23
+ public all(@Query('minDate') minDate: Date, @Query('gender') gender: Gender): string {
24
+ return `getByGenderOlderThan: ${gender} ${minDate.toISOString()}`;
25
+ }
26
+ }
27
+
28
+ describe('When decorator is called', () => {
29
+ it('Then we should retrieve information via reflect', async () => {
30
+ const config = reflect(TestClass).getControllerConfiguration();
31
+ expect(config.routes.length).equal(2, 'Wrong route count detected');
32
+
33
+ const request1 = <any>{ query: { id: 'guid 1' } };
34
+ expect(config.routes[0].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length for getById');
35
+ expect(config.routes[0].argumentInjectors[0](request1)).to.be.a('string');
36
+ expect(config.routes[0].argumentInjectors[0](request1)).equals('guid 1');
37
+
38
+ const request2 = <any>{ query: { gender: 0, minDate: '2021-02-15T14:23:00.318Z' } };
39
+
40
+ expect(config.routes[1].argumentInjectors.length).equal(2, 'Wrong argumentInjectors length for getByGenderOlderThan');
41
+
42
+ expect(config.routes[1].argumentInjectors[0](request2)).to.be.a('Date');
43
+ expect(config.routes[1].argumentInjectors[0](request2).toISOString()).equals((new Date('2021-02-15T14:23:00.318Z')).toISOString());
44
+
45
+ expect(config.routes[1].argumentInjectors[1](request2)).equals(Gender.Male);
46
+
47
+ request2.query.gender = 'Female';
48
+ expect(config.routes[1].argumentInjectors[1](request2)).equals(Gender.Female);
49
+ });
50
+ });
51
+ });
@@ -0,0 +1,21 @@
1
+ import { deserialize } from '@my-devkit/core';
2
+
3
+ import { reflect, RequestArgumentInjector } from '../../reflect';
4
+ import { Server } from '../../server';
5
+
6
+ export function Query(key: string): ParameterDecorator {
7
+ return (target, propertyKey, parameterIndex) => {
8
+ const methodArguments = reflect(target, propertyKey).getParameters();
9
+ if (!methodArguments.hasOwnProperty(parameterIndex)) {
10
+ throw new Error(`Query: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`);
11
+ }
12
+
13
+ const injector: RequestArgumentInjector = (req: Server.Request) => {
14
+ if (req.query.hasOwnProperty(key)) {
15
+ return deserialize(req.query[key], methodArguments[parameterIndex]);
16
+ }
17
+ };
18
+
19
+ reflect(target, propertyKey).registerControllerRouteArgumentInjector(injector, parameterIndex);
20
+ }
21
+ }
@@ -0,0 +1,101 @@
1
+ import { Command } from '@my-devkit/core';
2
+ import { expect } from 'chai';
3
+
4
+ import { reflect } from '../../reflect';
5
+ import { CommandHandler } from './command-handler';
6
+
7
+ describe('Given a CommandHandler decorator', () => {
8
+
9
+ describe('When decorator is called', () => {
10
+
11
+ describe('And decorated method has no parameter', () => {
12
+ it('Then we should retrieve information via reflect', async () => {
13
+
14
+ try {
15
+ class TestClass {
16
+ @CommandHandler()
17
+ public create(): string {
18
+ return `create`;
19
+ }
20
+ }
21
+
22
+ reflect(TestClass).getHandlerConfiguration();
23
+ } catch (error) {
24
+ expect(error.message).equal('TestClass.create should have one argument!');
25
+ }
26
+ });
27
+ });
28
+
29
+ describe('And decorated method has more than 1 parameter', () => {
30
+ it('Then we should retrieve information via reflect', async () => {
31
+
32
+ try {
33
+ class TestClass {
34
+ @CommandHandler()
35
+ public create(param1: string, param2: string): string {
36
+ return `create ${param1} / ${param2}`;
37
+ }
38
+ }
39
+
40
+ reflect(TestClass).getHandlerConfiguration();
41
+ } catch (error) {
42
+ expect(error.message).equal('TestClass.create should have only one argument!');
43
+ }
44
+ });
45
+ });
46
+
47
+ describe('And decorated method parameter is not a command', () => {
48
+ it('Then we should retrieve information via reflect', async () => {
49
+
50
+ try {
51
+ class FakeCommand {
52
+ test: string;
53
+ }
54
+
55
+ class TestClass {
56
+ @CommandHandler()
57
+ public create(fakeCommand: FakeCommand): string {
58
+ return `create ${fakeCommand}`;
59
+ }
60
+ }
61
+
62
+ reflect(TestClass).getHandlerConfiguration();
63
+ } catch (error) {
64
+ expect(error.message).equal('TestClass.create should have a command as argument!');
65
+ }
66
+ });
67
+ });
68
+
69
+ describe('And handler is correctly implemented', () => {
70
+
71
+ class CreateCommand extends Command {
72
+ }
73
+
74
+ class UpdateCommand extends Command {
75
+ }
76
+
77
+ class TestClass {
78
+ @CommandHandler()
79
+ public create(command: CreateCommand): string {
80
+ return `create: ${command}`;
81
+ }
82
+
83
+ @CommandHandler()
84
+ public update(command: UpdateCommand): string {
85
+ return `update: ${command}`;
86
+ }
87
+ }
88
+ it('Then we should retrieve information via reflect', async () => {
89
+ const config = reflect(TestClass).getHandlerConfiguration();
90
+ expect(config.commandHandlers.size).equal(2, 'Wrong route count detected');
91
+
92
+ expect(config.commandHandlers[0].methodName).equal('create');
93
+ expect(config.commandHandlers[0].command.constructor.name).equal('CreateCommand');
94
+
95
+ expect(config.commandHandlers[1].methodName).equal('update');
96
+ expect(config.commandHandlers[1].command.constructor.name).equal('UpdateCommand');
97
+
98
+ });
99
+ });
100
+ });
101
+ });
@@ -0,0 +1,23 @@
1
+ import { Command } from '@my-devkit/core';
2
+
3
+ import { reflect } from '../../reflect';
4
+
5
+ export function CommandHandler(): MethodDecorator {
6
+ return (target, propertyKey) => {
7
+ const paramTypes = reflect(target, propertyKey).getParameters();
8
+
9
+ if (paramTypes.length === 0) {
10
+ throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have one argument!`);
11
+ }
12
+
13
+ if (paramTypes.length > 1) {
14
+ throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have only one argument!`);
15
+ }
16
+
17
+ if (!(paramTypes[0].prototype instanceof Command)) {
18
+ throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have a command as argument!`);
19
+ }
20
+
21
+ reflect(target, propertyKey).registerCommandHandler(<any>paramTypes[0].prototype);
22
+ }
23
+ }