rads-db 3.1.12 → 3.1.14
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.
|
@@ -7,27 +7,27 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
8
|
var _radsDb = require("rads-db");
|
|
9
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
-
var _default =
|
|
10
|
+
var _default = options => {
|
|
11
11
|
return {
|
|
12
12
|
name: "eventSourcing",
|
|
13
13
|
init(db, context) {
|
|
14
|
-
verifyEventSourcingSetup(context.schema, context.effects);
|
|
14
|
+
verifyEventSourcingSetup(context.schema, context.effects, options || {});
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
18
|
module.exports = _default;
|
|
19
|
-
function verifyEventSourcingSetup(schema, effects) {
|
|
19
|
+
function verifyEventSourcingSetup(schema, effects, options) {
|
|
20
20
|
for (const entityName in schema) {
|
|
21
21
|
if (!schema[entityName].decorators.entity) continue;
|
|
22
22
|
if (schema[entityName].decorators.precomputed?.preset !== "eventSourcing") continue;
|
|
23
23
|
const eventEntityName = `${entityName}Event`;
|
|
24
24
|
const aggregateRelationField = _lodash.default.lowerFirst(entityName);
|
|
25
25
|
validateEventSourcingSetup(schema, entityName, eventEntityName, aggregateRelationField);
|
|
26
|
-
const effect = getEffectFor(entityName, aggregateRelationField, eventEntityName, schema);
|
|
26
|
+
const effect = getEffectFor(entityName, aggregateRelationField, eventEntityName, schema, options);
|
|
27
27
|
effects[eventEntityName].push(effect);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
function getEffectFor(entityName, aggregateRelationField, eventEntityName, schema) {
|
|
30
|
+
function getEffectFor(entityName, aggregateRelationField, eventEntityName, schema, options) {
|
|
31
31
|
return {
|
|
32
32
|
async beforePut(context, docs, ctx) {
|
|
33
33
|
const docsByAggId = {};
|
|
@@ -62,7 +62,7 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
62
62
|
const existingAggregatesById = _lodash.default.keyBy(existingAggregates, "id");
|
|
63
63
|
const result = [];
|
|
64
64
|
for (const aggId in docsByAggId) {
|
|
65
|
-
|
|
65
|
+
let events = _lodash.default.orderBy([...docsByAggId[aggId], ...(existingEventsByAggId[aggId] || [])], ["date"], "asc");
|
|
66
66
|
if (events[0].type !== "creation") throw new Error(`First event must have type = "creation". (type: ${events[0].type}, id: ${events[0].id})`);
|
|
67
67
|
if (events.slice(1).some(ev => ev.type === "creation")) {
|
|
68
68
|
throw new Error(`Only first event may have type = "creation"`);
|
|
@@ -76,6 +76,9 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
76
76
|
const originalChange = ev.change;
|
|
77
77
|
ev.change = (0, _radsDb.diff)(newAggDoc, aggDoc);
|
|
78
78
|
handleKeepHistory(schema[entityName].keepHistoryFields, originalChange, ev);
|
|
79
|
+
if (options.applyEventIf && !options.applyEventIf(ev, context, ctx)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
79
82
|
aggDoc = newAggDoc;
|
|
80
83
|
if (!context.options.keepNulls) (0, _radsDb.cleanUndefinedAndNull)(aggDoc);
|
|
81
84
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import type { RadsFeature } from '@/types';
|
|
2
|
-
|
|
1
|
+
import type { ComputedContext, RadsFeature, RadsRequestContext } from '@/types';
|
|
2
|
+
export interface EventSourcingFeatureOptions {
|
|
3
|
+
applyEventIf?: (event: any, context: ComputedContext, ctx: RadsRequestContext) => boolean;
|
|
4
|
+
}
|
|
5
|
+
declare const _default: (options?: EventSourcingFeatureOptions) => RadsFeature;
|
|
3
6
|
export default _default;
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
2
|
import { cleanUndefinedAndNull, diff, handlePrecomputed, merge } from "rads-db";
|
|
3
|
-
export default () => {
|
|
3
|
+
export default (options) => {
|
|
4
4
|
return {
|
|
5
5
|
name: "eventSourcing",
|
|
6
6
|
init(db, context) {
|
|
7
|
-
verifyEventSourcingSetup(context.schema, context.effects);
|
|
7
|
+
verifyEventSourcingSetup(context.schema, context.effects, options || {});
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
|
-
function verifyEventSourcingSetup(schema, effects) {
|
|
11
|
+
function verifyEventSourcingSetup(schema, effects, options) {
|
|
12
12
|
for (const entityName in schema) {
|
|
13
13
|
if (!schema[entityName].decorators.entity) continue;
|
|
14
14
|
if (schema[entityName].decorators.precomputed?.preset !== "eventSourcing") continue;
|
|
15
15
|
const eventEntityName = `${entityName}Event`;
|
|
16
16
|
const aggregateRelationField = _.lowerFirst(entityName);
|
|
17
17
|
validateEventSourcingSetup(schema, entityName, eventEntityName, aggregateRelationField);
|
|
18
|
-
const effect = getEffectFor(entityName, aggregateRelationField, eventEntityName, schema);
|
|
18
|
+
const effect = getEffectFor(entityName, aggregateRelationField, eventEntityName, schema, options);
|
|
19
19
|
effects[eventEntityName].push(effect);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
function getEffectFor(entityName, aggregateRelationField, eventEntityName, schema) {
|
|
22
|
+
function getEffectFor(entityName, aggregateRelationField, eventEntityName, schema, options) {
|
|
23
23
|
return {
|
|
24
24
|
async beforePut(context, docs, ctx) {
|
|
25
25
|
const docsByAggId = {};
|
|
@@ -52,7 +52,7 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
52
52
|
const existingAggregatesById = _.keyBy(existingAggregates, "id");
|
|
53
53
|
const result = [];
|
|
54
54
|
for (const aggId in docsByAggId) {
|
|
55
|
-
|
|
55
|
+
let events = _.orderBy([...docsByAggId[aggId], ...existingEventsByAggId[aggId] || []], ["date"], "asc");
|
|
56
56
|
if (events[0].type !== "creation")
|
|
57
57
|
throw new Error(`First event must have type = "creation". (type: ${events[0].type}, id: ${events[0].id})`);
|
|
58
58
|
if (events.slice(1).some((ev) => ev.type === "creation")) {
|
|
@@ -65,6 +65,9 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
65
65
|
const originalChange = ev.change;
|
|
66
66
|
ev.change = diff(newAggDoc, aggDoc);
|
|
67
67
|
handleKeepHistory(schema[entityName].keepHistoryFields, originalChange, ev);
|
|
68
|
+
if (options.applyEventIf && !options.applyEventIf(ev, context, ctx)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
68
71
|
aggDoc = newAggDoc;
|
|
69
72
|
if (!context.options.keepNulls) cleanUndefinedAndNull(aggDoc);
|
|
70
73
|
}
|