@my-devkit/firebase 1.0.194 → 1.0.195
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/app-factory.js +1 -1
- package/dist/app-factory.js.map +1 -1
- package/dist/bus.js +1 -4
- package/dist/bus.js.map +1 -1
- package/dist/decorators/controller/body.js.map +1 -1
- package/dist/decorators/controller/body.spec.js.map +1 -1
- package/dist/decorators/controller/param.js.map +1 -1
- package/dist/decorators/controller/param.spec.js.map +1 -1
- package/dist/decorators/controller/query.js.map +1 -1
- package/dist/decorators/controller/query.spec.js.map +1 -1
- package/dist/decorators/handler/command-handler.js.map +1 -1
- package/dist/decorators/handler/command-handler.spec.js.map +1 -1
- package/dist/decorators/handler/event-handler.js.map +1 -1
- package/dist/decorators/handler/event-handler.spec.js.map +1 -1
- package/dist/firestore-client.js +3 -3
- package/dist/firestore-client.js.map +1 -1
- package/dist/handler-helper.js.map +1 -1
- package/dist/reflect.js.map +1 -1
- package/dist/server/middlewares/authentication-middleware.js +1 -3
- package/dist/server/middlewares/authentication-middleware.js.map +1 -1
- package/dist/server/middlewares/create-context-middleware.js.map +1 -1
- package/dist/server/middlewares/error-middleware.js.map +1 -1
- package/dist/server/middlewares/headers-middleware.js.map +1 -1
- package/dist/server/server.js.map +1 -1
- package/package.json +4 -4
- package/src/app-factory.ts +14 -52
- package/src/bus.ts +5 -22
- package/src/decorators/controller/body.spec.ts +2 -8
- package/src/decorators/controller/body.ts +3 -9
- package/src/decorators/controller/param.spec.ts +3 -12
- package/src/decorators/controller/param.ts +2 -7
- package/src/decorators/controller/query.spec.ts +2 -8
- package/src/decorators/controller/query.ts +2 -7
- package/src/decorators/handler/command-handler.spec.ts +2 -6
- package/src/decorators/handler/command-handler.ts +3 -9
- package/src/decorators/handler/event-handler.spec.ts +2 -6
- package/src/decorators/handler/event-handler.ts +3 -9
- package/src/firestore-client.ts +20 -67
- package/src/handler-helper.ts +5 -18
- package/src/interfaces/from-array.ts +1 -2
- package/src/reflect.ts +3 -12
- package/src/server/middlewares/authentication-middleware.ts +4 -14
- package/src/server/middlewares/create-context-middleware.ts +1 -5
- package/src/server/middlewares/error-middleware.ts +1 -5
- package/src/server/middlewares/headers-middleware.ts +1 -5
- package/src/server/server.ts +10 -32
|
@@ -32,10 +32,7 @@ describe('Given a Body decorator', () => {
|
|
|
32
32
|
|
|
33
33
|
const request1 = <any>{ body: '2021-02-08T11:14:23.318Z' };
|
|
34
34
|
|
|
35
|
-
expect(config.routes[0].argumentInjectors.length).equal(
|
|
36
|
-
1,
|
|
37
|
-
'Wrong argumentInjectors length'
|
|
38
|
-
);
|
|
35
|
+
expect(config.routes[0].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length');
|
|
39
36
|
expect(config.routes[0].argumentInjectors[0](request1)).to.be.a('Date');
|
|
40
37
|
expect(config.routes[0].argumentInjectors[0](request1).toISOString()).equals(
|
|
41
38
|
new Date('2021-02-08T11:14:23.318Z').toISOString()
|
|
@@ -47,10 +44,7 @@ describe('Given a Body decorator', () => {
|
|
|
47
44
|
expectedBody2.testString = 'test';
|
|
48
45
|
expectedBody2.testDate = null;
|
|
49
46
|
|
|
50
|
-
expect(config.routes[1].argumentInjectors.length).equal(
|
|
51
|
-
1,
|
|
52
|
-
'Wrong argumentInjectors length'
|
|
53
|
-
);
|
|
47
|
+
expect(config.routes[1].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length');
|
|
54
48
|
expect(config.routes[1].argumentInjectors[0](request2)).to.be.instanceOf(Command);
|
|
55
49
|
expect(config.routes[1].argumentInjectors[0](request2)).deep.equal(expectedBody2);
|
|
56
50
|
});
|
|
@@ -7,17 +7,11 @@ export function Body(): ParameterDecorator {
|
|
|
7
7
|
return (target, propertyKey, parameterIndex) => {
|
|
8
8
|
const methodArguments = reflect(target, propertyKey).getParameters();
|
|
9
9
|
if (!methodArguments.hasOwnProperty(parameterIndex)) {
|
|
10
|
-
throw new Error(
|
|
11
|
-
`Body: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`
|
|
12
|
-
);
|
|
10
|
+
throw new Error(`Body: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`);
|
|
13
11
|
}
|
|
14
12
|
|
|
15
|
-
const injector: RequestArgumentInjector = (req: Server.Request) =>
|
|
16
|
-
deserialize(req.body, methodArguments[parameterIndex]);
|
|
13
|
+
const injector: RequestArgumentInjector = (req: Server.Request) => deserialize(req.body, methodArguments[parameterIndex]);
|
|
17
14
|
|
|
18
|
-
reflect(target, propertyKey).registerControllerRouteArgumentInjector(
|
|
19
|
-
injector,
|
|
20
|
-
parameterIndex
|
|
21
|
-
);
|
|
15
|
+
reflect(target, propertyKey).registerControllerRouteArgumentInjector(injector, parameterIndex);
|
|
22
16
|
};
|
|
23
17
|
}
|
|
@@ -19,10 +19,7 @@ describe('Given a Param decorator', () => {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
@Get(':gender/:minDate')
|
|
22
|
-
public getByGenderOlderThan(
|
|
23
|
-
@Param('minDate') minDate: Date,
|
|
24
|
-
@Param('gender') gender: Gender
|
|
25
|
-
): string {
|
|
22
|
+
public getByGenderOlderThan(@Param('minDate') minDate: Date, @Param('gender') gender: Gender): string {
|
|
26
23
|
return `getByGenderOlderThan: ${gender} ${minDate.toISOString()}`;
|
|
27
24
|
}
|
|
28
25
|
}
|
|
@@ -33,19 +30,13 @@ describe('Given a Param decorator', () => {
|
|
|
33
30
|
expect(config.routes.length).equal(2, 'Wrong route count detected');
|
|
34
31
|
|
|
35
32
|
const request1 = <any>{ params: { id: 'guid 1' } };
|
|
36
|
-
expect(config.routes[0].argumentInjectors.length).equal(
|
|
37
|
-
1,
|
|
38
|
-
'Wrong argumentInjectors length for getById'
|
|
39
|
-
);
|
|
33
|
+
expect(config.routes[0].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length for getById');
|
|
40
34
|
expect(config.routes[0].argumentInjectors[0](request1)).to.be.a('string');
|
|
41
35
|
expect(config.routes[0].argumentInjectors[0](request1)).equals('guid 1');
|
|
42
36
|
|
|
43
37
|
const request2 = <any>{ params: { gender: 0, minDate: '2021-02-15T14:23:00.318Z' } };
|
|
44
38
|
|
|
45
|
-
expect(config.routes[1].argumentInjectors.length).equal(
|
|
46
|
-
2,
|
|
47
|
-
'Wrong argumentInjectors length for getByGenderOlderThan'
|
|
48
|
-
);
|
|
39
|
+
expect(config.routes[1].argumentInjectors.length).equal(2, 'Wrong argumentInjectors length for getByGenderOlderThan');
|
|
49
40
|
|
|
50
41
|
expect(config.routes[1].argumentInjectors[0](request2)).to.be.a('Date');
|
|
51
42
|
expect(config.routes[1].argumentInjectors[0](request2).toISOString()).equals(
|
|
@@ -7,9 +7,7 @@ export function Param(key: string): ParameterDecorator {
|
|
|
7
7
|
return (target, propertyKey, parameterIndex) => {
|
|
8
8
|
const methodArguments = reflect(target, propertyKey).getParameters();
|
|
9
9
|
if (!methodArguments.hasOwnProperty(parameterIndex)) {
|
|
10
|
-
throw new Error(
|
|
11
|
-
`Param: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`
|
|
12
|
-
);
|
|
10
|
+
throw new Error(`Param: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`);
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
const injector: RequestArgumentInjector = (req: Server.Request) => {
|
|
@@ -18,9 +16,6 @@ export function Param(key: string): ParameterDecorator {
|
|
|
18
16
|
}
|
|
19
17
|
};
|
|
20
18
|
|
|
21
|
-
reflect(target, propertyKey).registerControllerRouteArgumentInjector(
|
|
22
|
-
injector,
|
|
23
|
-
parameterIndex
|
|
24
|
-
);
|
|
19
|
+
reflect(target, propertyKey).registerControllerRouteArgumentInjector(injector, parameterIndex);
|
|
25
20
|
};
|
|
26
21
|
}
|
|
@@ -30,19 +30,13 @@ describe('Given a Query decorator', () => {
|
|
|
30
30
|
expect(config.routes.length).equal(2, 'Wrong route count detected');
|
|
31
31
|
|
|
32
32
|
const request1 = <any>{ query: { id: 'guid 1' } };
|
|
33
|
-
expect(config.routes[0].argumentInjectors.length).equal(
|
|
34
|
-
1,
|
|
35
|
-
'Wrong argumentInjectors length for getById'
|
|
36
|
-
);
|
|
33
|
+
expect(config.routes[0].argumentInjectors.length).equal(1, 'Wrong argumentInjectors length for getById');
|
|
37
34
|
expect(config.routes[0].argumentInjectors[0](request1)).to.be.a('string');
|
|
38
35
|
expect(config.routes[0].argumentInjectors[0](request1)).equals('guid 1');
|
|
39
36
|
|
|
40
37
|
const request2 = <any>{ query: { gender: 0, minDate: '2021-02-15T14:23:00.318Z' } };
|
|
41
38
|
|
|
42
|
-
expect(config.routes[1].argumentInjectors.length).equal(
|
|
43
|
-
2,
|
|
44
|
-
'Wrong argumentInjectors length for getByGenderOlderThan'
|
|
45
|
-
);
|
|
39
|
+
expect(config.routes[1].argumentInjectors.length).equal(2, 'Wrong argumentInjectors length for getByGenderOlderThan');
|
|
46
40
|
|
|
47
41
|
expect(config.routes[1].argumentInjectors[0](request2)).to.be.a('Date');
|
|
48
42
|
expect(config.routes[1].argumentInjectors[0](request2).toISOString()).equals(
|
|
@@ -7,9 +7,7 @@ export function Query(key: string): ParameterDecorator {
|
|
|
7
7
|
return (target, propertyKey, parameterIndex) => {
|
|
8
8
|
const methodArguments = reflect(target, propertyKey).getParameters();
|
|
9
9
|
if (!methodArguments.hasOwnProperty(parameterIndex)) {
|
|
10
|
-
throw new Error(
|
|
11
|
-
`Query: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`
|
|
12
|
-
);
|
|
10
|
+
throw new Error(`Query: can't find argument ${parameterIndex} on ${target.constructor.name}.${propertyKey.toString()}`);
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
const injector: RequestArgumentInjector = (req: Server.Request) => {
|
|
@@ -18,9 +16,6 @@ export function Query(key: string): ParameterDecorator {
|
|
|
18
16
|
}
|
|
19
17
|
};
|
|
20
18
|
|
|
21
|
-
reflect(target, propertyKey).registerControllerRouteArgumentInjector(
|
|
22
|
-
injector,
|
|
23
|
-
parameterIndex
|
|
24
|
-
);
|
|
19
|
+
reflect(target, propertyKey).registerControllerRouteArgumentInjector(injector, parameterIndex);
|
|
25
20
|
};
|
|
26
21
|
}
|
|
@@ -56,9 +56,7 @@ describe('Given a CommandHandler decorator', () => {
|
|
|
56
56
|
|
|
57
57
|
reflect(TestClass).getHandlerConfiguration();
|
|
58
58
|
} catch (error) {
|
|
59
|
-
expect(error.message).equal(
|
|
60
|
-
'TestClass.create should have a command as argument!'
|
|
61
|
-
);
|
|
59
|
+
expect(error.message).equal('TestClass.create should have a command as argument!');
|
|
62
60
|
}
|
|
63
61
|
});
|
|
64
62
|
});
|
|
@@ -80,9 +78,7 @@ describe('Given a CommandHandler decorator', () => {
|
|
|
80
78
|
}
|
|
81
79
|
}
|
|
82
80
|
it('Then we should retrieve information via reflect', async () => {
|
|
83
|
-
const commandHandlers = Array.from(
|
|
84
|
-
reflect(TestClass).getHandlerConfiguration().commandHandlers.values()
|
|
85
|
-
);
|
|
81
|
+
const commandHandlers = Array.from(reflect(TestClass).getHandlerConfiguration().commandHandlers.values());
|
|
86
82
|
|
|
87
83
|
expect(commandHandlers.length).equal(2, 'Wrong route count detected');
|
|
88
84
|
|
|
@@ -7,21 +7,15 @@ export function CommandHandler(): MethodDecorator {
|
|
|
7
7
|
const paramTypes = reflect(target, propertyKey).getParameters();
|
|
8
8
|
|
|
9
9
|
if (paramTypes.length === 0) {
|
|
10
|
-
throw new Error(
|
|
11
|
-
`${target.constructor.name}.${propertyKey.toString()} should have one argument!`
|
|
12
|
-
);
|
|
10
|
+
throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have one argument!`);
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
if (paramTypes.length > 1) {
|
|
16
|
-
throw new Error(
|
|
17
|
-
`${target.constructor.name}.${propertyKey.toString()} should have only one argument!`
|
|
18
|
-
);
|
|
14
|
+
throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have only one argument!`);
|
|
19
15
|
}
|
|
20
16
|
|
|
21
17
|
if (!(paramTypes[0].prototype instanceof Command)) {
|
|
22
|
-
throw new Error(
|
|
23
|
-
`${target.constructor.name}.${propertyKey.toString()} should have a command as argument!`
|
|
24
|
-
);
|
|
18
|
+
throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have a command as argument!`);
|
|
25
19
|
}
|
|
26
20
|
|
|
27
21
|
reflect(target, propertyKey).registerCommandHandler(<any>paramTypes[0].prototype);
|
|
@@ -57,9 +57,7 @@ describe('Given a EventHandler decorator', () => {
|
|
|
57
57
|
|
|
58
58
|
reflect(TestClass).getHandlerConfiguration();
|
|
59
59
|
} catch (error) {
|
|
60
|
-
expect(error.message).equal(
|
|
61
|
-
'TestClass.created should have an event as argument!'
|
|
62
|
-
);
|
|
60
|
+
expect(error.message).equal('TestClass.created should have an event as argument!');
|
|
63
61
|
}
|
|
64
62
|
});
|
|
65
63
|
});
|
|
@@ -81,9 +79,7 @@ describe('Given a EventHandler decorator', () => {
|
|
|
81
79
|
}
|
|
82
80
|
}
|
|
83
81
|
it('Then we should retrieve information via reflect', async () => {
|
|
84
|
-
const eventHandlers = Array.from(
|
|
85
|
-
reflect(TestClass).getHandlerConfiguration().eventHandlers.values()
|
|
86
|
-
);
|
|
82
|
+
const eventHandlers = Array.from(reflect(TestClass).getHandlerConfiguration().eventHandlers.values());
|
|
87
83
|
|
|
88
84
|
expect(eventHandlers.length).equal(2, 'Wrong route count detected');
|
|
89
85
|
|
|
@@ -8,21 +8,15 @@ export function EventHandler(mode: ExecutionMode): MethodDecorator {
|
|
|
8
8
|
const paramTypes = reflect(target, propertyKey).getParameters();
|
|
9
9
|
|
|
10
10
|
if (paramTypes.length === 0) {
|
|
11
|
-
throw new Error(
|
|
12
|
-
`${target.constructor.name}.${propertyKey.toString()} should have one argument!`
|
|
13
|
-
);
|
|
11
|
+
throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have one argument!`);
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
if (paramTypes.length > 1) {
|
|
17
|
-
throw new Error(
|
|
18
|
-
`${target.constructor.name}.${propertyKey.toString()} should have only one argument!`
|
|
19
|
-
);
|
|
15
|
+
throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have only one argument!`);
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
if (!(paramTypes[0].prototype instanceof Event)) {
|
|
23
|
-
throw new Error(
|
|
24
|
-
`${target.constructor.name}.${propertyKey.toString()} should have an event as argument!`
|
|
25
|
-
);
|
|
19
|
+
throw new Error(`${target.constructor.name}.${propertyKey.toString()} should have an event as argument!`);
|
|
26
20
|
}
|
|
27
21
|
|
|
28
22
|
reflect(target, propertyKey).registerEventHandler(<any>paramTypes[0].prototype, mode);
|
package/src/firestore-client.ts
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
_orderBy,
|
|
3
|
-
Cacheable,
|
|
4
|
-
deserialize,
|
|
5
|
-
Document,
|
|
6
|
-
Logger,
|
|
7
|
-
NotFoundError,
|
|
8
|
-
serialize
|
|
9
|
-
} from '@my-devkit/core';
|
|
1
|
+
import { _orderBy, Cacheable, deserialize, Document, Logger, NotFoundError, serialize } from '@my-devkit/core';
|
|
10
2
|
import { getFirestore } from 'firebase-admin/firestore';
|
|
11
3
|
|
|
12
4
|
import { Injectable, TransactionalClient } from './decorators';
|
|
@@ -60,9 +52,7 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
60
52
|
const documents = await this._getWhere<T>(collection, whereClauses, options);
|
|
61
53
|
|
|
62
54
|
if (documents.length > 1) {
|
|
63
|
-
throw new Error(
|
|
64
|
-
`Transactional Repository: Too many documents found (${documents.length})`
|
|
65
|
-
);
|
|
55
|
+
throw new Error(`Transactional Repository: Too many documents found (${documents.length})`);
|
|
66
56
|
}
|
|
67
57
|
|
|
68
58
|
return documents[0] || null;
|
|
@@ -78,10 +68,7 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
78
68
|
return result;
|
|
79
69
|
}
|
|
80
70
|
|
|
81
|
-
public async _getAll<T extends Document>(
|
|
82
|
-
collection: string,
|
|
83
|
-
options?: FirestoreClient.QueryOptions
|
|
84
|
-
): Promise<T[]> {
|
|
71
|
+
public async _getAll<T extends Document>(collection: string, options?: FirestoreClient.QueryOptions): Promise<T[]> {
|
|
85
72
|
return this._getWhere(collection, [], options);
|
|
86
73
|
}
|
|
87
74
|
|
|
@@ -90,9 +77,7 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
90
77
|
whereClauses: [string, FirestoreClient.Operator, any | any[]][] = [],
|
|
91
78
|
options?: FirestoreClient.QueryOptions
|
|
92
79
|
): Promise<T[]> {
|
|
93
|
-
Logger.info(
|
|
94
|
-
`Repository: getWhere ${collection} whereClauses: ${JSON.stringify(whereClauses)}`
|
|
95
|
-
);
|
|
80
|
+
Logger.info(`Repository: getWhere ${collection} whereClauses: ${JSON.stringify(whereClauses)}`);
|
|
96
81
|
const documentMap = await this.queryCollection<T>(collection, whereClauses, options);
|
|
97
82
|
|
|
98
83
|
for (const operation of Array.from(this.operations.values())) {
|
|
@@ -102,36 +87,26 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
102
87
|
case FirestoreClient.Action.Create:
|
|
103
88
|
if (this.doesDocumentMatchQuery(operation.document, collection, whereClauses)) {
|
|
104
89
|
documentMap.set(operation.document._path, <T>operation.document);
|
|
105
|
-
Logger.info(
|
|
106
|
-
`Repository: Document ${operation.document._path} added to result`
|
|
107
|
-
);
|
|
90
|
+
Logger.info(`Repository: Document ${operation.document._path} added to result`);
|
|
108
91
|
}
|
|
109
92
|
break;
|
|
110
93
|
case FirestoreClient.Action.Update:
|
|
111
94
|
if (this.doesDocumentMatchQuery(operation.document, collection, whereClauses)) {
|
|
112
|
-
Logger.info(
|
|
113
|
-
`Repository: Document ${operation.document._path} ${exists ? 'updated from' : 'added to'} result`
|
|
114
|
-
);
|
|
95
|
+
Logger.info(`Repository: Document ${operation.document._path} ${exists ? 'updated from' : 'added to'} result`);
|
|
115
96
|
documentMap.set(operation.document._path, <T>operation.document);
|
|
116
97
|
} else if (exists) {
|
|
117
98
|
documentMap.delete(operation.document._path);
|
|
118
|
-
Logger.info(
|
|
119
|
-
`Repository: Document ${operation.document._path} removed from result`
|
|
120
|
-
);
|
|
99
|
+
Logger.info(`Repository: Document ${operation.document._path} removed from result`);
|
|
121
100
|
}
|
|
122
101
|
break;
|
|
123
102
|
case FirestoreClient.Action.Delete:
|
|
124
103
|
if (exists) {
|
|
125
104
|
documentMap.delete(operation.document._path);
|
|
126
|
-
Logger.info(
|
|
127
|
-
`Repository: Document ${operation.document._path} removed from result`
|
|
128
|
-
);
|
|
105
|
+
Logger.info(`Repository: Document ${operation.document._path} removed from result`);
|
|
129
106
|
}
|
|
130
107
|
break;
|
|
131
108
|
default:
|
|
132
|
-
throw new Error(
|
|
133
|
-
`FirestoreClient: Unhandled existing operation ${operation.action} on ${operation.document._path}`
|
|
134
|
-
);
|
|
109
|
+
throw new Error(`FirestoreClient: Unhandled existing operation ${operation.action} on ${operation.document._path}`);
|
|
135
110
|
}
|
|
136
111
|
}
|
|
137
112
|
|
|
@@ -156,21 +131,15 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
156
131
|
if (existingOperation) {
|
|
157
132
|
switch (existingOperation.action) {
|
|
158
133
|
case FirestoreClient.Action.Create:
|
|
159
|
-
throw new Error(
|
|
160
|
-
`FirestoreClient: can't create twice document ${document._path}`
|
|
161
|
-
);
|
|
134
|
+
throw new Error(`FirestoreClient: can't create twice document ${document._path}`);
|
|
162
135
|
case FirestoreClient.Action.Update:
|
|
163
|
-
throw new Error(
|
|
164
|
-
`FirestoreClient: can't create already existing document ${document._path}`
|
|
165
|
-
);
|
|
136
|
+
throw new Error(`FirestoreClient: can't create already existing document ${document._path}`);
|
|
166
137
|
case FirestoreClient.Action.Delete:
|
|
167
138
|
existingOperation.action = FirestoreClient.Action.Update;
|
|
168
139
|
existingOperation.document = document;
|
|
169
140
|
break;
|
|
170
141
|
default:
|
|
171
|
-
throw new Error(
|
|
172
|
-
`FirestoreClient: Unhandled existing operation ${existingOperation.action} on ${document._path}`
|
|
173
|
-
);
|
|
142
|
+
throw new Error(`FirestoreClient: Unhandled existing operation ${existingOperation.action} on ${document._path}`);
|
|
174
143
|
}
|
|
175
144
|
} else {
|
|
176
145
|
this.operations.set(document._path, {
|
|
@@ -191,13 +160,9 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
191
160
|
existingOperation.document = document;
|
|
192
161
|
break;
|
|
193
162
|
case FirestoreClient.Action.Delete:
|
|
194
|
-
throw new Error(
|
|
195
|
-
`FirestoreClient: can't update deleted document ${document._path}`
|
|
196
|
-
);
|
|
163
|
+
throw new Error(`FirestoreClient: can't update deleted document ${document._path}`);
|
|
197
164
|
default:
|
|
198
|
-
throw new Error(
|
|
199
|
-
`FirestoreClient: Unhandled existing operation ${existingOperation.action} on ${document._path}`
|
|
200
|
-
);
|
|
165
|
+
throw new Error(`FirestoreClient: Unhandled existing operation ${existingOperation.action} on ${document._path}`);
|
|
201
166
|
}
|
|
202
167
|
} else {
|
|
203
168
|
this.operations.set(document._path, {
|
|
@@ -221,13 +186,9 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
221
186
|
existingOperation.action = FirestoreClient.Action.Delete;
|
|
222
187
|
break;
|
|
223
188
|
case FirestoreClient.Action.Delete:
|
|
224
|
-
throw new Error(
|
|
225
|
-
`FirestoreClient: can't delete already deleted document ${document._path}`
|
|
226
|
-
);
|
|
189
|
+
throw new Error(`FirestoreClient: can't delete already deleted document ${document._path}`);
|
|
227
190
|
default:
|
|
228
|
-
throw new Error(
|
|
229
|
-
`FirestoreClient: Unhandled existing operation ${existingOperation.action} on ${document._path}`
|
|
230
|
-
);
|
|
191
|
+
throw new Error(`FirestoreClient: Unhandled existing operation ${existingOperation.action} on ${document._path}`);
|
|
231
192
|
}
|
|
232
193
|
} else {
|
|
233
194
|
this.operations.set(document._path, {
|
|
@@ -238,9 +199,7 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
238
199
|
}
|
|
239
200
|
}
|
|
240
201
|
|
|
241
|
-
private getCollectionReference(
|
|
242
|
-
collection: string
|
|
243
|
-
): FirebaseFirestore.CollectionReference | FirebaseFirestore.Query {
|
|
202
|
+
private getCollectionReference(collection: string): FirebaseFirestore.CollectionReference | FirebaseFirestore.Query {
|
|
244
203
|
if (collection.startsWith('**/')) {
|
|
245
204
|
return this.db.collectionGroup(collection.replace('**/', ''));
|
|
246
205
|
} else {
|
|
@@ -313,9 +272,7 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
313
272
|
case '<=':
|
|
314
273
|
return documentValue <= expectedValue;
|
|
315
274
|
case 'array-contains':
|
|
316
|
-
return (
|
|
317
|
-
Array.isArray(documentValue) && documentValue.includes(expectedValue)
|
|
318
|
-
);
|
|
275
|
+
return Array.isArray(documentValue) && documentValue.includes(expectedValue);
|
|
319
276
|
case 'array-contains-any':
|
|
320
277
|
return (
|
|
321
278
|
Array.isArray(documentValue) &&
|
|
@@ -323,13 +280,9 @@ export class FirestoreClient implements ITransactionalClient {
|
|
|
323
280
|
documentValue.some(v => expectedValue.includes(v))
|
|
324
281
|
);
|
|
325
282
|
case 'in':
|
|
326
|
-
return (
|
|
327
|
-
Array.isArray(expectedValue) && expectedValue.includes(documentValue)
|
|
328
|
-
);
|
|
283
|
+
return Array.isArray(expectedValue) && expectedValue.includes(documentValue);
|
|
329
284
|
case 'not-in':
|
|
330
|
-
return (
|
|
331
|
-
Array.isArray(expectedValue) && !expectedValue.includes(documentValue)
|
|
332
|
-
);
|
|
285
|
+
return Array.isArray(expectedValue) && !expectedValue.includes(documentValue);
|
|
333
286
|
default:
|
|
334
287
|
throw new Error(`Operator ${operator} not handled!`);
|
|
335
288
|
}
|
package/src/handler-helper.ts
CHANGED
|
@@ -6,10 +6,7 @@ import { ExecutionMode } from './execution-mode-enum';
|
|
|
6
6
|
import { FirestoreClient } from './firestore-client';
|
|
7
7
|
|
|
8
8
|
export class HandlerHelper {
|
|
9
|
-
public static async create<A extends Aggregate, R>(
|
|
10
|
-
aggregate: A,
|
|
11
|
-
callback: (a: A) => Promise<R>
|
|
12
|
-
): Promise<R> {
|
|
9
|
+
public static async create<A extends Aggregate, R>(aggregate: A, callback: (a: A) => Promise<R>): Promise<R> {
|
|
13
10
|
const result = await callback(aggregate);
|
|
14
11
|
|
|
15
12
|
this.client.createDocument(aggregate);
|
|
@@ -18,15 +15,10 @@ export class HandlerHelper {
|
|
|
18
15
|
return result;
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
public static async update<A extends Aggregate, R>(
|
|
22
|
-
aggregateOrId: A | string,
|
|
23
|
-
callback: (a: A) => Promise<R>
|
|
24
|
-
): Promise<R> {
|
|
18
|
+
public static async update<A extends Aggregate, R>(aggregateOrId: A | string, callback: (a: A) => Promise<R>): Promise<R> {
|
|
25
19
|
const aggregate = await this.getAggregate(aggregateOrId);
|
|
26
20
|
if (aggregate.events.length > 0) {
|
|
27
|
-
Logger.warn(
|
|
28
|
-
`${aggregate._type} ${aggregate.id} has ${aggregate.events.length} events!!`
|
|
29
|
-
);
|
|
21
|
+
Logger.warn(`${aggregate._type} ${aggregate.id} has ${aggregate.events.length} events!!`);
|
|
30
22
|
}
|
|
31
23
|
const hashBefore = aggregate.hash;
|
|
32
24
|
|
|
@@ -36,19 +28,14 @@ export class HandlerHelper {
|
|
|
36
28
|
this.client.updateDocument(aggregate);
|
|
37
29
|
await this.publishEvents(aggregate);
|
|
38
30
|
} else {
|
|
39
|
-
Logger.debug(
|
|
40
|
-
`${aggregate._type} ${aggregate.id} didn't change, ${aggregate.events.length} events skipped`
|
|
41
|
-
);
|
|
31
|
+
Logger.debug(`${aggregate._type} ${aggregate.id} didn't change, ${aggregate.events.length} events skipped`);
|
|
42
32
|
aggregate.clearEvents();
|
|
43
33
|
}
|
|
44
34
|
|
|
45
35
|
return result;
|
|
46
36
|
}
|
|
47
37
|
|
|
48
|
-
public static async delete<A extends Aggregate, R>(
|
|
49
|
-
aggregateOrId: A | string,
|
|
50
|
-
callback: (a: A) => Promise<R>
|
|
51
|
-
): Promise<R> {
|
|
38
|
+
public static async delete<A extends Aggregate, R>(aggregateOrId: A | string, callback: (a: A) => Promise<R>): Promise<R> {
|
|
52
39
|
const aggregate = await this.getAggregate(aggregateOrId);
|
|
53
40
|
|
|
54
41
|
const result = await callback(aggregate);
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export type FromArray<T extends ReadonlyArray<unknown>> =
|
|
2
|
-
T extends ReadonlyArray<infer FromArray> ? FromArray : never;
|
|
1
|
+
export type FromArray<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer FromArray> ? FromArray : never;
|
package/src/reflect.ts
CHANGED
|
@@ -58,10 +58,7 @@ class ReflectHelper<T extends ReflectTarget<any>> {
|
|
|
58
58
|
this.getControllerRoute().requestMethod = route.requestMethod;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
public registerControllerRouteArgumentInjector<T>(
|
|
62
|
-
injector: RequestArgumentInjector<T>,
|
|
63
|
-
index: number
|
|
64
|
-
): void {
|
|
61
|
+
public registerControllerRouteArgumentInjector<T>(injector: RequestArgumentInjector<T>, index: number): void {
|
|
65
62
|
this.getControllerRoute().argumentInjectors[index] = injector;
|
|
66
63
|
}
|
|
67
64
|
|
|
@@ -83,10 +80,7 @@ class ReflectHelper<T extends ReflectTarget<any>> {
|
|
|
83
80
|
});
|
|
84
81
|
}
|
|
85
82
|
|
|
86
|
-
public registerEventHandler<E extends Event>(
|
|
87
|
-
event: new () => E,
|
|
88
|
-
executionMode: ExecutionMode
|
|
89
|
-
): void {
|
|
83
|
+
public registerEventHandler<E extends Event>(event: new () => E, executionMode: ExecutionMode): void {
|
|
90
84
|
this.getHandlerConfiguration().eventHandlers.set(this.methodName.toString(), {
|
|
91
85
|
methodName: this.methodName.toString(),
|
|
92
86
|
executionMode,
|
|
@@ -163,10 +157,7 @@ export interface HandlerConfiguration {
|
|
|
163
157
|
|
|
164
158
|
export type RequestArgumentInjector<T = any> = (req: Server.Request) => T;
|
|
165
159
|
|
|
166
|
-
export function reflect<T extends ReflectTarget<any>>(
|
|
167
|
-
target: T,
|
|
168
|
-
methodName?: string | symbol
|
|
169
|
-
): ReflectHelper<T> {
|
|
160
|
+
export function reflect<T extends ReflectTarget<any>>(target: T, methodName?: string | symbol): ReflectHelper<T> {
|
|
170
161
|
return new ReflectHelper(target, methodName);
|
|
171
162
|
}
|
|
172
163
|
|
|
@@ -5,14 +5,8 @@ import { Context } from '../../context';
|
|
|
5
5
|
import { Server } from '../server';
|
|
6
6
|
|
|
7
7
|
export function AuthenticationMiddleware(auth: Auth, publicPaths: string[]): Server.RequestHandler {
|
|
8
|
-
return async (
|
|
9
|
-
request:
|
|
10
|
-
_response: Server.Response,
|
|
11
|
-
next: Server.NextFunction
|
|
12
|
-
): Promise<void> => {
|
|
13
|
-
const authorizationHeader = request.headers.authorization
|
|
14
|
-
? request.headers.authorization.toString()
|
|
15
|
-
: null;
|
|
8
|
+
return async (request: Server.Request, _response: Server.Response, next: Server.NextFunction): Promise<void> => {
|
|
9
|
+
const authorizationHeader = request.headers.authorization ? request.headers.authorization.toString() : null;
|
|
16
10
|
Logger.info(`${request.method} ${request.path}: Authentication check`);
|
|
17
11
|
|
|
18
12
|
if (publicPaths.includes(request.path)) {
|
|
@@ -31,9 +25,7 @@ export function AuthenticationMiddleware(auth: Auth, publicPaths: string[]): Ser
|
|
|
31
25
|
Context.user = await auth.getUser(userId);
|
|
32
26
|
next();
|
|
33
27
|
} catch (error) {
|
|
34
|
-
throw new UnauthorizedError(
|
|
35
|
-
`Error while verifying token ${error.message ? error.message : null}`
|
|
36
|
-
);
|
|
28
|
+
throw new UnauthorizedError(`Error while verifying token ${error.message ? error.message : null}`);
|
|
37
29
|
}
|
|
38
30
|
} else if (authorizationHeader.startsWith('Basic')) {
|
|
39
31
|
const idToken = authorizationHeader.split('Basic ')[1];
|
|
@@ -45,9 +37,7 @@ export function AuthenticationMiddleware(auth: Auth, publicPaths: string[]): Ser
|
|
|
45
37
|
Context.user = await auth.getUser(userId);
|
|
46
38
|
next();
|
|
47
39
|
} catch (error) {
|
|
48
|
-
throw new UnauthorizedError(
|
|
49
|
-
`Error while verifying token ${error.message ? error.message : null}`
|
|
50
|
-
);
|
|
40
|
+
throw new UnauthorizedError(`Error while verifying token ${error.message ? error.message : null}`);
|
|
51
41
|
}
|
|
52
42
|
} else {
|
|
53
43
|
throw new UnauthorizedError('Incorrect authorization header');
|
|
@@ -5,11 +5,7 @@ import { Context } from '../../context';
|
|
|
5
5
|
import { Server } from '../server';
|
|
6
6
|
|
|
7
7
|
export function CreateContextMiddleware(bus: Bus): Server.RequestHandler {
|
|
8
|
-
return async (
|
|
9
|
-
request: Server.Request,
|
|
10
|
-
_response: Server.Response,
|
|
11
|
-
next: Server.NextFunction
|
|
12
|
-
): Promise<void> => {
|
|
8
|
+
return async (request: Server.Request, _response: Server.Response, next: Server.NextFunction): Promise<void> => {
|
|
13
9
|
Context.create(bus);
|
|
14
10
|
Context.correlationId = request.header('X-Correlation-ID') || guid();
|
|
15
11
|
|
|
@@ -4,11 +4,7 @@ import { Context } from '../../context';
|
|
|
4
4
|
import { Server } from '../server';
|
|
5
5
|
|
|
6
6
|
export function ErrorMiddleWare(): Server.ErrorHandler {
|
|
7
|
-
return async (
|
|
8
|
-
error: any,
|
|
9
|
-
_request: Server.Request,
|
|
10
|
-
response: Server.Response
|
|
11
|
-
): Promise<void> => {
|
|
7
|
+
return async (error: any, _request: Server.Request, response: Server.Response): Promise<void> => {
|
|
12
8
|
if (!(error instanceof Error)) {
|
|
13
9
|
error = new Error(error);
|
|
14
10
|
}
|
|
@@ -2,11 +2,7 @@ import { Context } from '../../context';
|
|
|
2
2
|
import { Server } from '../server';
|
|
3
3
|
|
|
4
4
|
export function HeadersMiddleWare(): Server.RequestHandler {
|
|
5
|
-
return async (
|
|
6
|
-
_request: Server.Request,
|
|
7
|
-
response: Server.Response,
|
|
8
|
-
next: Server.NextFunction
|
|
9
|
-
): Promise<void> => {
|
|
5
|
+
return async (_request: Server.Request, response: Server.Response, next: Server.NextFunction): Promise<void> => {
|
|
10
6
|
response.removeHeader('X-Powered-By'); // Remove verbose express
|
|
11
7
|
response.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); // HTTP 1.1.
|
|
12
8
|
response.setHeader('Pragma', 'no-cache'); // HTTP 1.0.
|