@meticoeus/ddd-es 0.2.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.
- package/LICENSE +21 -0
- package/README.md +43 -0
- package/dist/package.json +81 -0
- package/dist/src/AbstractEventProcessManager.d.ts +32 -0
- package/dist/src/AbstractEventProcessManager.d.ts.map +1 -0
- package/dist/src/AbstractEventProcessManager.js +142 -0
- package/dist/src/AbstractEventProcessManager.js.map +1 -0
- package/dist/src/AbstractEventProcessManager.mocks.d.ts +27 -0
- package/dist/src/AbstractEventProcessManager.mocks.d.ts.map +1 -0
- package/dist/src/AbstractEventProcessManager.mocks.js +86 -0
- package/dist/src/AbstractEventProcessManager.mocks.js.map +1 -0
- package/dist/src/AbstractEventProcessManager.test.d.ts +2 -0
- package/dist/src/AbstractEventProcessManager.test.d.ts.map +1 -0
- package/dist/src/AbstractEventProcessManager.test.js +109 -0
- package/dist/src/AbstractEventProcessManager.test.js.map +1 -0
- package/dist/src/AggregateRoot.d.ts +52 -0
- package/dist/src/AggregateRoot.d.ts.map +1 -0
- package/dist/src/AggregateRoot.fixtures.d.ts +4 -0
- package/dist/src/AggregateRoot.fixtures.d.ts.map +1 -0
- package/dist/src/AggregateRoot.fixtures.js +45 -0
- package/dist/src/AggregateRoot.fixtures.js.map +1 -0
- package/dist/src/AggregateRoot.js +136 -0
- package/dist/src/AggregateRoot.js.map +1 -0
- package/dist/src/AggregateRoot.mocks.d.ts +26 -0
- package/dist/src/AggregateRoot.mocks.d.ts.map +1 -0
- package/dist/src/AggregateRoot.mocks.js +82 -0
- package/dist/src/AggregateRoot.mocks.js.map +1 -0
- package/dist/src/EventProcessor.d.ts +40 -0
- package/dist/src/EventProcessor.d.ts.map +1 -0
- package/dist/src/EventProcessor.js +112 -0
- package/dist/src/EventProcessor.js.map +1 -0
- package/dist/src/EventProcessor.mocks.d.ts +11 -0
- package/dist/src/EventProcessor.mocks.d.ts.map +1 -0
- package/dist/src/EventProcessor.mocks.js +50 -0
- package/dist/src/EventProcessor.mocks.js.map +1 -0
- package/dist/src/EventProcessor.test.d.ts +2 -0
- package/dist/src/EventProcessor.test.d.ts.map +1 -0
- package/dist/src/EventProcessor.test.js +37 -0
- package/dist/src/EventProcessor.test.js.map +1 -0
- package/dist/src/IRepository.d.ts +14 -0
- package/dist/src/IRepository.d.ts.map +1 -0
- package/dist/src/IRepository.js +25 -0
- package/dist/src/IRepository.js.map +1 -0
- package/dist/src/Repository.d.ts +20 -0
- package/dist/src/Repository.d.ts.map +1 -0
- package/dist/src/Repository.js +127 -0
- package/dist/src/Repository.js.map +1 -0
- package/dist/src/Repository.mocks.d.ts +13 -0
- package/dist/src/Repository.mocks.d.ts.map +1 -0
- package/dist/src/Repository.mocks.js +55 -0
- package/dist/src/Repository.mocks.js.map +1 -0
- package/dist/src/Repository.test.d.ts +2 -0
- package/dist/src/Repository.test.d.ts.map +1 -0
- package/dist/src/Repository.test.js +108 -0
- package/dist/src/Repository.test.js.map +1 -0
- package/dist/src/entities.d.ts +37 -0
- package/dist/src/entities.d.ts.map +1 -0
- package/dist/src/entities.js +25 -0
- package/dist/src/entities.js.map +1 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +34 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logger.d.ts +23 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +37 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/mocks.d.ts +4 -0
- package/dist/src/mocks.d.ts.map +1 -0
- package/dist/src/mocks.js +27 -0
- package/dist/src/mocks.js.map +1 -0
- package/dist/src/otel/AbstractEventProcessManager.d.ts +6 -0
- package/dist/src/otel/AbstractEventProcessManager.d.ts.map +1 -0
- package/dist/src/otel/AbstractEventProcessManager.js +63 -0
- package/dist/src/otel/AbstractEventProcessManager.js.map +1 -0
- package/dist/src/otel/EventProcessor.d.ts +13 -0
- package/dist/src/otel/EventProcessor.d.ts.map +1 -0
- package/dist/src/otel/EventProcessor.js +59 -0
- package/dist/src/otel/EventProcessor.js.map +1 -0
- package/dist/src/otel/Repository.d.ts +12 -0
- package/dist/src/otel/Repository.d.ts.map +1 -0
- package/dist/src/otel/Repository.js +80 -0
- package/dist/src/otel/Repository.js.map +1 -0
- package/dist/src/otel/index.d.ts +6 -0
- package/dist/src/otel/index.d.ts.map +1 -0
- package/dist/src/otel/index.js +29 -0
- package/dist/src/otel/index.js.map +1 -0
- package/dist/src/otel/tracer.d.ts +2 -0
- package/dist/src/otel/tracer.d.ts.map +1 -0
- package/dist/src/otel/tracer.js +27 -0
- package/dist/src/otel/tracer.js.map +1 -0
- package/dist/src/otel/utils.d.ts +8 -0
- package/dist/src/otel/utils.d.ts.map +1 -0
- package/dist/src/otel/utils.js +70 -0
- package/dist/src/otel/utils.js.map +1 -0
- package/dist/src/schemas.d.ts +83 -0
- package/dist/src/schemas.d.ts.map +1 -0
- package/dist/src/schemas.js +77 -0
- package/dist/src/schemas.js.map +1 -0
- package/dist/src/schemas.test.d.ts +2 -0
- package/dist/src/schemas.test.d.ts.map +1 -0
- package/dist/src/schemas.test.js +110 -0
- package/dist/src/schemas.test.js.map +1 -0
- package/dist/src/types.d.ts +124 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.fixtures.d.ts +3 -0
- package/dist/src/types.fixtures.d.ts.map +1 -0
- package/dist/src/types.fixtures.js +28 -0
- package/dist/src/types.fixtures.js.map +1 -0
- package/dist/src/types.js +130 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/types.mocks.d.ts +14 -0
- package/dist/src/types.mocks.d.ts.map +1 -0
- package/dist/src/types.mocks.js +239 -0
- package/dist/src/types.mocks.js.map +1 -0
- package/dist/src/utils.d.ts +11 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +64 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregateRoot.fixtures.d.ts","sourceRoot":"","sources":["../../src/AggregateRoot.fixtures.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,WAAW,wIASvB,CAAA;AAED,eAAO,MAAM,WAAW,wIASvB,CAAA;AAED,eAAO,MAAM,WAAW,wIAQvB,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Justin Bailey
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import { mockPersistedEvent } from './types.mocks.js';
|
|
25
|
+
export const testCreated = mockPersistedEvent({
|
|
26
|
+
type: 'TestCreated',
|
|
27
|
+
data: {
|
|
28
|
+
id: 'Test:1',
|
|
29
|
+
name: 'new name',
|
|
30
|
+
},
|
|
31
|
+
}, 1n);
|
|
32
|
+
export const testRenamed = mockPersistedEvent({
|
|
33
|
+
type: 'TestRenamed',
|
|
34
|
+
data: {
|
|
35
|
+
id: 'Test:1',
|
|
36
|
+
name: 'new name',
|
|
37
|
+
},
|
|
38
|
+
}, 2n);
|
|
39
|
+
export const testDeleted = mockPersistedEvent({
|
|
40
|
+
type: 'TestDeleted',
|
|
41
|
+
data: {
|
|
42
|
+
id: 'Test:1',
|
|
43
|
+
},
|
|
44
|
+
}, 3n);
|
|
45
|
+
//# sourceMappingURL=AggregateRoot.fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregateRoot.fixtures.js","sourceRoot":"","sources":["../../src/AggregateRoot.fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;EAsBE;AAEF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD,MAAM,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAC3C;IACE,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE;QACJ,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,UAAU;KACjB;CACF,EACD,EAAE,CACH,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAC3C;IACE,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE;QACJ,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,UAAU;KACjB;CACF,EACD,EAAE,CACH,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAC3C;IACE,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE;QACJ,EAAE,EAAE,QAAQ;KACb;CACF,EACD,EAAE,CACH,CAAA"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Justin Bailey
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import { logProvider } from './logger.js';
|
|
25
|
+
import { Ok } from './types.js';
|
|
26
|
+
const ApplyLength = 'apply'.length;
|
|
27
|
+
export class AggregateRoot {
|
|
28
|
+
__storeHistory;
|
|
29
|
+
__history = [];
|
|
30
|
+
__changes = [];
|
|
31
|
+
_appliers = new Map();
|
|
32
|
+
constructor(config) {
|
|
33
|
+
this.__storeHistory = config?.storeHistory ?? true;
|
|
34
|
+
const props = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
|
|
35
|
+
for (const prop of props) {
|
|
36
|
+
const fn = this[prop];
|
|
37
|
+
if (typeof fn === 'function' && prop.startsWith('apply') && prop.length > ApplyLength) {
|
|
38
|
+
this._appliers.set(prop.substring(ApplyLength), fn);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// @ts-ignore - will be defined after initializing or loading from history
|
|
43
|
+
_id;
|
|
44
|
+
get id() {
|
|
45
|
+
return this._id;
|
|
46
|
+
}
|
|
47
|
+
_revision;
|
|
48
|
+
get revision() {
|
|
49
|
+
return this._revision;
|
|
50
|
+
}
|
|
51
|
+
/** package scope. do not access externally */
|
|
52
|
+
get history() {
|
|
53
|
+
return this.__history;
|
|
54
|
+
}
|
|
55
|
+
_deleted = false;
|
|
56
|
+
get deleted() {
|
|
57
|
+
return this._deleted;
|
|
58
|
+
}
|
|
59
|
+
static eventsConflict(pending, committed) {
|
|
60
|
+
// override to handle specific conflicts
|
|
61
|
+
// provide a default impl since the same event type usually conflicts
|
|
62
|
+
return committed.type === pending.type;
|
|
63
|
+
}
|
|
64
|
+
getUncommittedChanges() {
|
|
65
|
+
return this.__changes;
|
|
66
|
+
}
|
|
67
|
+
markChangesAsCommitted() {
|
|
68
|
+
this.__changes = [];
|
|
69
|
+
}
|
|
70
|
+
loadFromHistory(history) {
|
|
71
|
+
for (const e of history) {
|
|
72
|
+
this.applyChange(e, false);
|
|
73
|
+
if (this.__storeHistory) {
|
|
74
|
+
this.__history.push(e);
|
|
75
|
+
}
|
|
76
|
+
if (typeof e.revision === 'bigint') {
|
|
77
|
+
this._revision = e.revision;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
applyChange(event, isNew = true) {
|
|
82
|
+
const applier = this._appliers.get(event.type);
|
|
83
|
+
if (!applier) {
|
|
84
|
+
// Panic the unit test, log otherwise
|
|
85
|
+
if (import.meta.vitest || process.env.VITEST) {
|
|
86
|
+
throw new Error(`${this.constructor.name}:: No apply function found for "${event.type}"`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
logProvider.log.warn(`${this.constructor.name}:: No apply function found for "${event.type}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
applier.call(this, event);
|
|
94
|
+
}
|
|
95
|
+
if (isNew)
|
|
96
|
+
this.__changes.push(event);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Either return Ok() or return an error result representing the conflict.
|
|
100
|
+
*/
|
|
101
|
+
hasConflict(_event) {
|
|
102
|
+
// override to handle specific conflicts
|
|
103
|
+
return Ok();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get events that happened between after (exclusive) and to (inclusive).
|
|
107
|
+
* Set notation: (after, to]
|
|
108
|
+
* Requires config.storeHistory to be true or history will not be available.
|
|
109
|
+
*
|
|
110
|
+
* @param after The revision to start after.
|
|
111
|
+
* @param to Optional revision to end at (inclusive). Defaults to current revision.
|
|
112
|
+
*/
|
|
113
|
+
getEventsDiff(after, to) {
|
|
114
|
+
if (typeof this._revision === 'undefined') {
|
|
115
|
+
// TODO: Events are not persisted yet. Return error result?
|
|
116
|
+
}
|
|
117
|
+
to = (to ?? this._revision);
|
|
118
|
+
if (after >= to)
|
|
119
|
+
return [];
|
|
120
|
+
const results = [];
|
|
121
|
+
for (const e of this.__history) {
|
|
122
|
+
if (e.revision > after && e.revision <= to) {
|
|
123
|
+
results.push(e);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return results;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (import.meta.vitest) {
|
|
130
|
+
const { test } = import.meta.vitest;
|
|
131
|
+
// in AggregateRoot::applyChange we need to know if we are in a test to throw errors or log
|
|
132
|
+
// this is here so that we have a test in the file so vitest doesn't fail.
|
|
133
|
+
// normally we want any test files to have tests rather than changing vitest's config
|
|
134
|
+
test('make vitest happy for AggregateRoot', () => { });
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=AggregateRoot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregateRoot.js","sourceRoot":"","sources":["../../src/AggregateRoot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;EAsBE;AAEF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAsC,EAAE,EAAqB,MAAM,YAAY,CAAA;AAEtF,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAA;AA4BlC,MAAM,OAAgB,aAAa;IACzB,cAAc,CAAS;IACvB,SAAS,GAA6B,EAAE,CAAA;IACxC,SAAS,GAAkB,EAAE,CAAA;IACpB,SAAS,GAA0C,IAAI,GAAG,EAAE,CAAA;IAE7E,YAAsB,MAAwB;QAC5C,IAAI,CAAC,cAAc,GAAG,MAAM,EAAE,YAAY,IAAI,IAAI,CAAA;QAElD,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAA;QACrE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,EAAE,GAAI,IAAY,CAAC,IAAI,CAAC,CAAA;YAC9B,IAAI,OAAO,EAAE,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;gBACtF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;IACH,CAAC;IAED,0EAA0E;IAChE,GAAG,CAAQ;IAErB,IAAW,EAAE;QACX,OAAO,IAAI,CAAC,GAAG,CAAA;IACjB,CAAC;IAES,SAAS,CAAoB;IAEvC,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,8CAA8C;IAC9C,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAES,QAAQ,GAAY,KAAK,CAAA;IAEnC,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAEM,MAAM,CAAC,cAAc,CAAC,OAAe,EAAE,SAA0B;QACtE,wCAAwC;QACxC,qEAAqE;QACrE,OAAO,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAA;IACxC,CAAC;IAEM,qBAAqB;QAC1B,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAEM,sBAAsB;QAC3B,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;IACrB,CAAC;IAEM,eAAe,CAAC,OAAyC;QAC9D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;YAC1B,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACxB,CAAC;YACD,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACnC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAA;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAES,WAAW,CAAC,KAAkB,EAAE,QAAiB,IAAI;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,qCAAqC;YACrC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC7C,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,mCAAmC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAA;YAC3F,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,GAAG,CAAC,IAAI,CAClB,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,mCAAmC,KAAK,CAAC,IAAI,EAAE,CACxE,CAAA;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC3B,CAAC;QACD,IAAI,KAAK;YAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC;IAED;;OAEG;IACI,WAAW,CAAC,MAAc;QAC/B,wCAAwC;QACxC,OAAO,EAAE,EAAE,CAAA;IACb,CAAC;IAED;;;;;;;OAOG;IACI,aAAa,CAAC,KAAa,EAAE,EAAW;QAC7C,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAC1C,2DAA2D;QAC7D,CAAC;QAED,EAAE,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,SAAS,CAAW,CAAA;QACrC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,EAAE,CAAA;QAE1B,MAAM,OAAO,GAA6B,EAAE,CAAA;QAC5C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,CAAC,QAAQ,GAAG,KAAK,IAAI,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;gBAC3C,OAAO,CAAC,IAAI,CAAC,CAA2B,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;CACF;AAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAA;IAEnC,2FAA2F;IAC3F,0EAA0E;IAC1E,qFAAqF;IACrF,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;AACvD,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AggregateRoot } from './AggregateRoot.js';
|
|
2
|
+
import { IEvent, IPersistedEvent, Result } from './types.js';
|
|
3
|
+
export interface TestData extends Record<string | number, unknown> {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly name: string;
|
|
6
|
+
}
|
|
7
|
+
export type TestEvent = TestCreatedEvent | TestRenamedEvent | TestDeletedEvent;
|
|
8
|
+
export type TestCreatedEvent = IEvent<'TestCreated', TestData>;
|
|
9
|
+
export type TestRenamedEvent = IEvent<'TestRenamed', TestData>;
|
|
10
|
+
export type TestDeletedEvent = IEvent<'TestDeleted', {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare class Test extends AggregateRoot<TestEvent> {
|
|
14
|
+
constructor();
|
|
15
|
+
static create(id: string, name: string): Promise<Result<Test>>;
|
|
16
|
+
static getStreamName(id: string): string;
|
|
17
|
+
static eventsConflict(pending: IEvent, committed: IPersistedEvent): boolean;
|
|
18
|
+
rename(name: string): Promise<Result<void>>;
|
|
19
|
+
delete(): Promise<Result<void>>;
|
|
20
|
+
getStreamName(id: string): string;
|
|
21
|
+
eventsConflict(pending: IEvent, committed: IPersistedEvent): boolean;
|
|
22
|
+
private applyTestCreated;
|
|
23
|
+
private applyTestRenamed;
|
|
24
|
+
private applyTestDeleted;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=AggregateRoot.mocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregateRoot.mocks.d.ts","sourceRoot":"","sources":["../../src/AggregateRoot.mocks.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,OAAO,EAAe,MAAM,EAAE,eAAe,EAAM,MAAM,EAAE,MAAM,YAAY,CAAA;AAE7E,MAAM,WAAW,QAAS,SAAQ,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC;IAChE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,MAAM,SAAS,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,CAAA;AAE9E,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;AAC9D,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;AAC9D,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,aAAa,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAE7E,qBAAa,IAAK,SAAQ,aAAa,CAAC,SAAS,CAAC;;WAKnC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAYpE,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;WAIxB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,OAAO;IAU9E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAW3C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAWrC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAIjC,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,OAAO;IAIpE,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,gBAAgB;IAExB,OAAO,CAAC,gBAAgB;CAGzB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Justin Bailey
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import { AggregateRoot } from './AggregateRoot.js';
|
|
25
|
+
import { mockMetadata } from './types.fixtures.js';
|
|
26
|
+
import { createEvent, Ok } from './types.js';
|
|
27
|
+
export class Test extends AggregateRoot {
|
|
28
|
+
constructor() {
|
|
29
|
+
super();
|
|
30
|
+
}
|
|
31
|
+
static async create(id, name) {
|
|
32
|
+
const instance = new Test();
|
|
33
|
+
instance.applyChange(createEvent({
|
|
34
|
+
type: 'TestCreated',
|
|
35
|
+
data: { id, name },
|
|
36
|
+
metadata: mockMetadata,
|
|
37
|
+
}));
|
|
38
|
+
return Ok(instance);
|
|
39
|
+
}
|
|
40
|
+
static getStreamName(id) {
|
|
41
|
+
return `test-${id}`;
|
|
42
|
+
}
|
|
43
|
+
static eventsConflict(pending, committed) {
|
|
44
|
+
switch (true) {
|
|
45
|
+
case pending.type === committed.type:
|
|
46
|
+
return true;
|
|
47
|
+
case committed.type === 'TestDeleted':
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
async rename(name) {
|
|
53
|
+
this.applyChange(createEvent({
|
|
54
|
+
type: 'TestRenamed',
|
|
55
|
+
data: { id: this._id, name },
|
|
56
|
+
metadata: mockMetadata,
|
|
57
|
+
}));
|
|
58
|
+
return Ok();
|
|
59
|
+
}
|
|
60
|
+
async delete() {
|
|
61
|
+
this.applyChange(createEvent({
|
|
62
|
+
type: 'TestDeleted',
|
|
63
|
+
data: { id: this._id },
|
|
64
|
+
metadata: mockMetadata,
|
|
65
|
+
}));
|
|
66
|
+
return Ok();
|
|
67
|
+
}
|
|
68
|
+
getStreamName(id) {
|
|
69
|
+
return `test${id}`;
|
|
70
|
+
}
|
|
71
|
+
eventsConflict(pending, committed) {
|
|
72
|
+
return pending.type === committed.type;
|
|
73
|
+
}
|
|
74
|
+
applyTestCreated(event) {
|
|
75
|
+
this._id = event.data.id;
|
|
76
|
+
}
|
|
77
|
+
applyTestRenamed(_event) { }
|
|
78
|
+
applyTestDeleted(_event) {
|
|
79
|
+
this._deleted = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=AggregateRoot.mocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregateRoot.mocks.js","sourceRoot":"","sources":["../../src/AggregateRoot.mocks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;EAsBE;AAEF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,WAAW,EAA2B,EAAE,EAAU,MAAM,YAAY,CAAA;AAa7E,MAAM,OAAO,IAAK,SAAQ,aAAwB;IAChD;QACE,KAAK,EAAE,CAAA;IACT,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,IAAY;QAC1C,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAA;QAC3B,QAAQ,CAAC,WAAW,CAClB,WAAW,CAAmB;YAC5B,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE;YAClB,QAAQ,EAAE,YAAY;SACvB,CAAC,CACH,CAAA;QACD,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAA;IACrB,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,EAAU;QAC7B,OAAO,QAAQ,EAAE,EAAE,CAAA;IACrB,CAAC;IAED,MAAM,CAAU,cAAc,CAAC,OAAe,EAAE,SAA0B;QACxE,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI;gBAClC,OAAO,IAAI,CAAA;YACb,KAAK,SAAS,CAAC,IAAI,KAAK,aAAa;gBACnC,OAAO,IAAI,CAAA;QACf,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,IAAI,CAAC,WAAW,CACd,WAAW,CAAmB;YAC5B,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE;YAC5B,QAAQ,EAAE,YAAY;SACvB,CAAC,CACH,CAAA;QACD,OAAO,EAAE,EAAE,CAAA;IACb,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,WAAW,CACd,WAAW,CAAmB;YAC5B,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACtB,QAAQ,EAAE,YAAY;SACvB,CAAC,CACH,CAAA;QACD,OAAO,EAAE,EAAE,CAAA;IACb,CAAC;IAED,aAAa,CAAC,EAAU;QACtB,OAAO,OAAO,EAAE,EAAE,CAAA;IACpB,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,SAA0B;QACxD,OAAO,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAA;IACxC,CAAC;IAEO,gBAAgB,CAAC,KAAuB;QAC9C,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAA;IAC1B,CAAC;IAEO,gBAAgB,CAAC,MAAwB,IAAG,CAAC;IAE7C,gBAAgB,CAAC,MAAwB;QAC/C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ConcurrencyException, EventRevision, Exception, IEvent, IEventStore, IPersistedEvent, Result } from './types.js';
|
|
2
|
+
export declare class EventProcessorException extends Exception {
|
|
3
|
+
readonly type: string;
|
|
4
|
+
readonly es: EventProcessor.ErrorStrategy;
|
|
5
|
+
readonly cause: any;
|
|
6
|
+
constructor(type: string, es: EventProcessor.ErrorStrategy, cause: any);
|
|
7
|
+
}
|
|
8
|
+
export declare namespace EventProcessor {
|
|
9
|
+
type ErrorHandler = (e: IPersistedEvent, error: unknown) => EventProcessor.ErrorStrategy | undefined;
|
|
10
|
+
type ErrorStrategy = RetryStrategy | CompensateStrategy | PanicStrategy | SkipStrategy;
|
|
11
|
+
/** Fail, blocking the event processor until the event can be processed successfully */
|
|
12
|
+
interface RetryStrategy {
|
|
13
|
+
strategy: 'retry';
|
|
14
|
+
}
|
|
15
|
+
/** Dispatch compensation events then continue processing new events */
|
|
16
|
+
interface CompensateStrategy {
|
|
17
|
+
strategy: 'compensate';
|
|
18
|
+
stream: string;
|
|
19
|
+
events: IEvent[];
|
|
20
|
+
expectedRevision: EventRevision;
|
|
21
|
+
}
|
|
22
|
+
/** Fail, blocking the event processor until the event can be processed successfully */
|
|
23
|
+
interface PanicStrategy {
|
|
24
|
+
strategy: 'panic';
|
|
25
|
+
}
|
|
26
|
+
/** Skip the event and proceed to process other events */
|
|
27
|
+
interface SkipStrategy {
|
|
28
|
+
strategy: 'skip';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export declare abstract class EventProcessor {
|
|
32
|
+
protected _eventStore: IEventStore;
|
|
33
|
+
protected readonly _errorHandlers: EventProcessor.ErrorHandler[];
|
|
34
|
+
protected readonly _handlers: Map<string, (e: IPersistedEvent) => Promise<void>>;
|
|
35
|
+
constructor(_eventStore: IEventStore, _errorHandlers?: EventProcessor.ErrorHandler[]);
|
|
36
|
+
handlesEvent(type: string): boolean;
|
|
37
|
+
handle(e: IPersistedEvent): Promise<Result<void, ConcurrencyException | EventProcessorException>>;
|
|
38
|
+
protected getErrorStrategy(event: IPersistedEvent, error: unknown): Promise<EventProcessor.ErrorStrategy>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=EventProcessor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventProcessor.d.ts","sourceRoot":"","sources":["../../src/EventProcessor.ts"],"names":[],"mappings":"AAyBA,OAAO,EACL,oBAAoB,EAEpB,aAAa,EACb,SAAS,EACT,MAAM,EACN,WAAW,EACX,eAAe,EAEf,MAAM,EACP,MAAM,YAAY,CAAA;AAGnB,qBAAa,uBAAwB,SAAQ,SAAS;aAElC,IAAI,EAAE,MAAM;aACZ,EAAE,EAAE,cAAc,CAAC,aAAa;aAChC,KAAK,EAAE,GAAG;gBAFV,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,cAAc,CAAC,aAAa,EAChC,KAAK,EAAE,GAAG;CAQ7B;AAED,MAAM,CAAC,OAAO,WAAW,cAAc,CAAC;IACtC,KAAY,YAAY,GAAG,CACzB,CAAC,EAAE,eAAe,EAClB,KAAK,EAAE,OAAO,KACX,cAAc,CAAC,aAAa,GAAG,SAAS,CAAA;IAI7C,KAAY,aAAa,GACrB,aAAa,GACb,kBAAkB,GAClB,aAAa,GACb,YAAY,CAAA;IAEhB,uFAAuF;IACvF,UAAiB,aAAa;QAC5B,QAAQ,EAAE,OAAO,CAAA;KAClB;IAED,uEAAuE;IACvE,UAAiB,kBAAkB;QACjC,QAAQ,EAAE,YAAY,CAAA;QACtB,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,MAAM,EAAE,CAAA;QAChB,gBAAgB,EAAE,aAAa,CAAA;KAChC;IAED,uFAAuF;IACvF,UAAiB,aAAa;QAC5B,QAAQ,EAAE,OAAO,CAAA;KAClB;IAED,yDAAyD;IACzD,UAAiB,YAAY;QAC3B,QAAQ,EAAE,MAAM,CAAA;KACjB;CACF;AAID,8BAAsB,cAAc;IAIhC,SAAS,CAAC,WAAW,EAAE,WAAW;IAClC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC,YAAY,EAAE;IAJlE,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAY;gBAGhF,WAAW,EAAE,WAAW,EACf,cAAc,GAAE,cAAc,CAAC,YAAY,EAAO;IAWhE,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,MAAM,CACjB,CAAC,EAAE,eAAe,GACjB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,oBAAoB,GAAG,uBAAuB,CAAC,CAAC;cA0CxD,gBAAgB,CAC9B,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC;CAgBzC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Justin Bailey
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import { logProvider } from './logger.js';
|
|
25
|
+
import { Err, Exception, Ok, } from './types.js';
|
|
26
|
+
import { serializeBigIntJson } from './utils.js';
|
|
27
|
+
export class EventProcessorException extends Exception {
|
|
28
|
+
type;
|
|
29
|
+
es;
|
|
30
|
+
cause;
|
|
31
|
+
constructor(type, es, cause) {
|
|
32
|
+
super('EventProcessorException', `Processing event "${type}" failed with type ${es.strategy}.`, 500);
|
|
33
|
+
this.type = type;
|
|
34
|
+
this.es = es;
|
|
35
|
+
this.cause = cause;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const HandleLength = 'handle'.length;
|
|
39
|
+
export class EventProcessor {
|
|
40
|
+
_eventStore;
|
|
41
|
+
_errorHandlers;
|
|
42
|
+
_handlers = new Map();
|
|
43
|
+
constructor(_eventStore, _errorHandlers = []) {
|
|
44
|
+
this._eventStore = _eventStore;
|
|
45
|
+
this._errorHandlers = _errorHandlers;
|
|
46
|
+
const props = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
|
|
47
|
+
for (const prop of props) {
|
|
48
|
+
const fn = this[prop];
|
|
49
|
+
if (typeof fn === 'function' && prop.startsWith('handle') && prop.length > HandleLength) {
|
|
50
|
+
this._handlers.set(prop.substring(HandleLength), fn);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
handlesEvent(type) {
|
|
55
|
+
return this._handlers.has(type);
|
|
56
|
+
}
|
|
57
|
+
async handle(e) {
|
|
58
|
+
const handler = this._handlers.get(e.type);
|
|
59
|
+
if (!handler) {
|
|
60
|
+
logProvider.log.warn(`[${this.constructor.name}].handle called for "${e.type}" but no handler found`);
|
|
61
|
+
return Ok();
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
await handler.call(this, e);
|
|
65
|
+
return Ok();
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
// print the full error for investigation
|
|
69
|
+
console.log(JSON.stringify(err, null, 2));
|
|
70
|
+
logProvider.log.warn(`[${this.constructor.name}].handle failed for "${e.type}" with "${err?.message}" processing ${serializeBigIntJson(e, 2)}`);
|
|
71
|
+
const es = await this.getErrorStrategy(e, err);
|
|
72
|
+
switch (es.strategy) {
|
|
73
|
+
case 'compensate': {
|
|
74
|
+
if (es.events.length) {
|
|
75
|
+
// no concurrency check for this op
|
|
76
|
+
const res = await this._eventStore.saveEvents(es.stream, es.events, es.expectedRevision);
|
|
77
|
+
if (res.ok)
|
|
78
|
+
return Ok();
|
|
79
|
+
// TODO: what can we do here? when can this legitimately happen?
|
|
80
|
+
else
|
|
81
|
+
return Err(res.error);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'retry':
|
|
86
|
+
case 'skip':
|
|
87
|
+
case 'panic':
|
|
88
|
+
return Err(new EventProcessorException(e.type, es, err));
|
|
89
|
+
default:
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
// match the switch default case. TS is complaining without this for some reason.
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async getErrorStrategy(event, error) {
|
|
97
|
+
if (error?.code === 'ECONNRESET') {
|
|
98
|
+
return {
|
|
99
|
+
strategy: 'retry',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
for (const errorHandler of this._errorHandlers) {
|
|
103
|
+
const es = errorHandler(event, error);
|
|
104
|
+
if (es)
|
|
105
|
+
return es;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
strategy: 'panic',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=EventProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventProcessor.js","sourceRoot":"","sources":["../../src/EventProcessor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { TestCreatedEvent, TestDeletedEvent, TestRenamedEvent } from './AggregateRoot.mocks.js';
|
|
2
|
+
import { EventProcessor } from './EventProcessor.js';
|
|
3
|
+
import { IEventStore } from './types.js';
|
|
4
|
+
export declare class TestEventProcessor extends EventProcessor {
|
|
5
|
+
constructor(eventStore: IEventStore);
|
|
6
|
+
handleTestCreated(_event: TestCreatedEvent): Promise<void>;
|
|
7
|
+
handleTestRenamed(_event: TestRenamedEvent): Promise<void>;
|
|
8
|
+
handleTestDeleted(_event: TestDeletedEvent): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare function getEventStoreMock(): IEventStore;
|
|
11
|
+
//# sourceMappingURL=EventProcessor.mocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventProcessor.mocks.d.ts","sourceRoot":"","sources":["../../src/EventProcessor.mocks.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAIL,WAAW,EAKZ,MAAM,YAAY,CAAA;AAEnB,qBAAa,kBAAmB,SAAQ,cAAc;gBACxC,UAAU,EAAE,WAAW;IAI7B,iBAAiB,CAAC,MAAM,EAAE,gBAAgB;IAE1C,iBAAiB,CAAC,MAAM,EAAE,gBAAgB;IAE1C,iBAAiB,CAAC,MAAM,EAAE,gBAAgB;CACjD;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CA2B/C"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Justin Bailey
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import { EventProcessor } from './EventProcessor.js';
|
|
25
|
+
import { Ok, } from './types.js';
|
|
26
|
+
export class TestEventProcessor extends EventProcessor {
|
|
27
|
+
constructor(eventStore) {
|
|
28
|
+
super(eventStore);
|
|
29
|
+
}
|
|
30
|
+
async handleTestCreated(_event) { }
|
|
31
|
+
async handleTestRenamed(_event) { }
|
|
32
|
+
async handleTestDeleted(_event) { }
|
|
33
|
+
}
|
|
34
|
+
export function getEventStoreMock() {
|
|
35
|
+
return {
|
|
36
|
+
saveEvents(_aggregateId, _events, _expectedVersion) {
|
|
37
|
+
return Promise.resolve(Ok({ nextExpectedRevision: 0n }));
|
|
38
|
+
},
|
|
39
|
+
deleteStream(_streamName, _expectedRevision) {
|
|
40
|
+
return Promise.resolve(Ok());
|
|
41
|
+
},
|
|
42
|
+
getEventsForAggregate(_aggregateId) {
|
|
43
|
+
return Promise.resolve([]);
|
|
44
|
+
},
|
|
45
|
+
getEventsForAggregateFromRevision(_streamName, _fromRevision) {
|
|
46
|
+
return Promise.resolve([]);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=EventProcessor.mocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventProcessor.mocks.js","sourceRoot":"","sources":["../../src/EventProcessor.mocks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;EAsBE;AAGF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAKL,EAAE,GAIH,MAAM,YAAY,CAAA;AAEnB,MAAM,OAAO,kBAAmB,SAAQ,cAAc;IACpD,YAAY,UAAuB;QACjC,KAAK,CAAC,UAAU,CAAC,CAAA;IACnB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,MAAwB,IAAG,CAAC;IAEpD,KAAK,CAAC,iBAAiB,CAAC,MAAwB,IAAG,CAAC;IAEpD,KAAK,CAAC,iBAAiB,CAAC,MAAwB,IAAG,CAAC;CACrD;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,UAAU,CACR,YAAoB,EACpB,OAAiB,EACjB,gBAA+B;YAE/B,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QAC1D,CAAC;QACD,YAAY,CACV,WAAmB,EACnB,iBAAiC;YAEjC,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;QAC9B,CAAC;QACD,qBAAqB,CACnB,YAAoB;YAEpB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC5B,CAAC;QACD,iCAAiC,CAC/B,WAAmB,EACnB,aAAqB;YAErB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC5B,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventProcessor.test.d.ts","sourceRoot":"","sources":["../../src/EventProcessor.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Justin Bailey
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import { describe, expect, test } from 'vitest';
|
|
25
|
+
import { TestEventProcessor, getEventStoreMock } from './EventProcessor.mocks.js';
|
|
26
|
+
describe('EventProcessor', () => {
|
|
27
|
+
test('Should return an event processor', () => {
|
|
28
|
+
const eventStoreMock = getEventStoreMock();
|
|
29
|
+
const ep = new TestEventProcessor(eventStoreMock);
|
|
30
|
+
expect(ep.handlesEvent('TestCreated')).toBe(true);
|
|
31
|
+
expect(ep.handlesEvent('TestRenamed')).toBe(true);
|
|
32
|
+
expect(ep.handlesEvent('TestDeleted')).toBe(true);
|
|
33
|
+
expect(ep.handlesEvent('TeamCreated')).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
test.todo('Should rollback a failed rename event with CompensateStrategy');
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=EventProcessor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventProcessor.test.js","sourceRoot":"","sources":["../../src/EventProcessor.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;EAsBE;AAEF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAEjF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC5C,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAA;QAC1C,MAAM,EAAE,GAAG,IAAI,kBAAkB,CAAC,cAAc,CAAC,CAAA;QAEjD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAA;AAC5E,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AggregateRoot, PersistedAggregate } from './AggregateRoot.js';
|
|
2
|
+
import { VersionedFixedLink } from './entities.js';
|
|
3
|
+
import { ConcurrencyException, EventConflictException, EventRevision, Exception, IEvent, Result, SaveEventSuccess } from './types.js';
|
|
4
|
+
export interface IRepository<DomainEvent extends IEvent, T extends AggregateRoot<DomainEvent>> {
|
|
5
|
+
/**
|
|
6
|
+
* The concurrency exception handling can currently return any kind of exception.
|
|
7
|
+
* API design may need some work to address this.
|
|
8
|
+
*/
|
|
9
|
+
save(aggregate: T, expectedRevision: EventRevision): Promise<Result<SaveEventSuccess, ConcurrencyException | EventConflictException | Exception>>;
|
|
10
|
+
getById(id: string, includeDeleted?: boolean): Promise<PersistedAggregate<DomainEvent, T> | undefined>;
|
|
11
|
+
getRevisionById(id: string, revision: bigint, includeDeleted?: boolean): Promise<PersistedAggregate<DomainEvent, T> | undefined>;
|
|
12
|
+
getByLink<ID extends string>(link: VersionedFixedLink<ID>, includeDeleted?: boolean): Promise<PersistedAggregate<DomainEvent, T> | undefined>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=IRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IRepository.d.ts","sourceRoot":"","sources":["../../src/IRepository.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,aAAa,EACb,SAAS,EACT,MAAM,EACN,MAAM,EACN,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,WAAW,CAAC,WAAW,SAAS,MAAM,EAAE,CAAC,SAAS,aAAa,CAAC,WAAW,CAAC;IAC3F;;;OAGG;IACH,IAAI,CACF,SAAS,EAAE,CAAC,EACZ,gBAAgB,EAAE,aAAa,GAC9B,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,oBAAoB,GAAG,sBAAsB,GAAG,SAAS,CAAC,CAAC,CAAA;IAE/F,OAAO,CACL,EAAE,EAAE,MAAM,EACV,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;IAE1D,eAAe,CACb,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;IAE1D,SAAS,CAAC,EAAE,SAAS,MAAM,EACzB,IAAI,EAAE,kBAAkB,CAAC,EAAE,CAAC,EAC5B,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;CAC3D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2024 Justin Bailey
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=IRepository.js.map
|