@shirudo/ddd-kit 1.0.0-rc.5 → 1.0.0-rc.6
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/README.md +13 -16
- package/dist/index.d.ts +152 -133
- package/dist/index.js +61 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -571,26 +571,26 @@ var AggregateRoot = class extends Entity {
|
|
|
571
571
|
}
|
|
572
572
|
_config;
|
|
573
573
|
_autoVersionBump;
|
|
574
|
-
|
|
574
|
+
_pendingEvents = [];
|
|
575
575
|
/**
|
|
576
|
-
*
|
|
577
|
-
*
|
|
576
|
+
* Read-only list of domain events recorded on this aggregate that have
|
|
577
|
+
* not yet been flushed to the outbox / persistence layer.
|
|
578
578
|
*/
|
|
579
|
-
get
|
|
580
|
-
return Object.freeze(this.
|
|
579
|
+
get pendingEvents() {
|
|
580
|
+
return Object.freeze(this._pendingEvents.slice());
|
|
581
581
|
}
|
|
582
582
|
/**
|
|
583
|
-
* Clears the list
|
|
584
|
-
*
|
|
583
|
+
* Clears the pending-event list. Call this after the events have been
|
|
584
|
+
* dispatched (typically `markPersisted` handles it for you).
|
|
585
585
|
*/
|
|
586
|
-
|
|
587
|
-
this.
|
|
586
|
+
clearPendingEvents() {
|
|
587
|
+
this._pendingEvents = [];
|
|
588
588
|
}
|
|
589
589
|
/**
|
|
590
590
|
* Post-save hook called by a `Repository.save()` implementation to push
|
|
591
|
-
* the persisted version back into the in-memory aggregate and clear
|
|
592
|
-
*
|
|
593
|
-
*
|
|
591
|
+
* the persisted version back into the in-memory aggregate and clear
|
|
592
|
+
* pendingEvents (they are now safely on the write side / in the
|
|
593
|
+
* outbox).
|
|
594
594
|
*
|
|
595
595
|
* Use this so `save()` can keep its `Promise<void>` return type: the
|
|
596
596
|
* caller holds the aggregate reference, which is up to date after this
|
|
@@ -598,7 +598,7 @@ var AggregateRoot = class extends Entity {
|
|
|
598
598
|
*/
|
|
599
599
|
markPersisted(version) {
|
|
600
600
|
this.setVersion(version);
|
|
601
|
-
this.
|
|
601
|
+
this._pendingEvents = [];
|
|
602
602
|
}
|
|
603
603
|
/**
|
|
604
604
|
* Mutates state and records the resulting domain events in the
|
|
@@ -687,7 +687,7 @@ var AggregateRoot = class extends Entity {
|
|
|
687
687
|
* @param event - The domain event to record
|
|
688
688
|
*/
|
|
689
689
|
addDomainEvent(event) {
|
|
690
|
-
this.
|
|
690
|
+
this._pendingEvents.push(event);
|
|
691
691
|
}
|
|
692
692
|
/**
|
|
693
693
|
* Manually bumps the aggregate version.
|
|
@@ -749,8 +749,9 @@ var AggregateRoot = class extends Entity {
|
|
|
749
749
|
* ```
|
|
750
750
|
*/
|
|
751
751
|
restoreFromSnapshot(snapshot) {
|
|
752
|
-
|
|
753
|
-
this.
|
|
752
|
+
const cloned = structuredClone(snapshot.state);
|
|
753
|
+
this.validateState(cloned);
|
|
754
|
+
this._state = freezeShallow(cloned);
|
|
754
755
|
this.setVersion(snapshot.version);
|
|
755
756
|
}
|
|
756
757
|
};
|
|
@@ -826,7 +827,6 @@ var EventSourcedAggregate = class extends Entity {
|
|
|
826
827
|
}
|
|
827
828
|
// --- Event tracking ---
|
|
828
829
|
_pendingEvents = [];
|
|
829
|
-
_autoVersionBump;
|
|
830
830
|
get pendingEvents() {
|
|
831
831
|
return Object.freeze(this._pendingEvents.slice());
|
|
832
832
|
}
|
|
@@ -843,9 +843,8 @@ var EventSourcedAggregate = class extends Entity {
|
|
|
843
843
|
this.setVersion(version);
|
|
844
844
|
this._pendingEvents = [];
|
|
845
845
|
}
|
|
846
|
-
constructor(id, initialState
|
|
846
|
+
constructor(id, initialState) {
|
|
847
847
|
super(id, initialState);
|
|
848
|
-
this._autoVersionBump = config?.autoVersionBump ?? true;
|
|
849
848
|
}
|
|
850
849
|
// --- Event application ---
|
|
851
850
|
/**
|
|
@@ -893,18 +892,9 @@ var EventSourcedAggregate = class extends Entity {
|
|
|
893
892
|
this._state = freezeShallow(nextState);
|
|
894
893
|
if (isNew) {
|
|
895
894
|
this._pendingEvents.push(event);
|
|
896
|
-
|
|
897
|
-
this.setVersion(this._version + 1);
|
|
898
|
-
}
|
|
895
|
+
this.setVersion(this._version + 1);
|
|
899
896
|
}
|
|
900
897
|
}
|
|
901
|
-
/**
|
|
902
|
-
* Manually bumps the aggregate version.
|
|
903
|
-
* Only needed if `autoVersionBump` is disabled.
|
|
904
|
-
*/
|
|
905
|
-
bumpVersion() {
|
|
906
|
-
this.setVersion(this._version + 1);
|
|
907
|
-
}
|
|
908
898
|
// --- History & Snapshots ---
|
|
909
899
|
/**
|
|
910
900
|
* Reconstitutes the aggregate from an event history. Catches `DomainError`
|
|
@@ -930,15 +920,6 @@ var EventSourcedAggregate = class extends Entity {
|
|
|
930
920
|
this.setVersion(startVersion + history.length);
|
|
931
921
|
return ok();
|
|
932
922
|
}
|
|
933
|
-
hasPendingEvents() {
|
|
934
|
-
return this._pendingEvents.length > 0;
|
|
935
|
-
}
|
|
936
|
-
getEventCount() {
|
|
937
|
-
return this._pendingEvents.length;
|
|
938
|
-
}
|
|
939
|
-
getLatestEvent() {
|
|
940
|
-
return this._pendingEvents[this._pendingEvents.length - 1];
|
|
941
|
-
}
|
|
942
923
|
/**
|
|
943
924
|
* Creates a snapshot of the current aggregate state.
|
|
944
925
|
*/
|
|
@@ -962,7 +943,7 @@ var EventSourcedAggregate = class extends Entity {
|
|
|
962
943
|
restoreFromSnapshotWithEvents(snapshot, eventsAfterSnapshot) {
|
|
963
944
|
const previousState = this._state;
|
|
964
945
|
const previousVersion = this._version;
|
|
965
|
-
this._state = freezeShallow(snapshot.state);
|
|
946
|
+
this._state = freezeShallow(structuredClone(snapshot.state));
|
|
966
947
|
this.setVersion(snapshot.version);
|
|
967
948
|
for (const event of eventsAfterSnapshot) {
|
|
968
949
|
try {
|
|
@@ -982,10 +963,9 @@ var CommandBus = class {
|
|
|
982
963
|
static {
|
|
983
964
|
__name(this, "CommandBus");
|
|
984
965
|
}
|
|
985
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
986
966
|
handlers = /* @__PURE__ */ new Map();
|
|
987
967
|
register(commandType, handler) {
|
|
988
|
-
this.handlers.set(commandType, handler);
|
|
968
|
+
this.handlers.set(commandType, (cmd) => handler(cmd));
|
|
989
969
|
}
|
|
990
970
|
async execute(command) {
|
|
991
971
|
const handler = this.handlers.get(command.type);
|
|
@@ -1004,13 +984,21 @@ var CommandBus = class {
|
|
|
1004
984
|
|
|
1005
985
|
// src/app/handler.ts
|
|
1006
986
|
async function withCommit(deps, fn) {
|
|
1007
|
-
const { result, events } = await deps.scope.transactional(
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
987
|
+
const { result, aggregates, events } = await deps.scope.transactional(
|
|
988
|
+
async (ctx) => {
|
|
989
|
+
const fnResult = await fn(ctx);
|
|
990
|
+
const harvested = fnResult.aggregates.flatMap(
|
|
991
|
+
(agg) => agg.pendingEvents
|
|
992
|
+
);
|
|
993
|
+
if (harvested.length > 0) {
|
|
994
|
+
await deps.outbox.add(harvested);
|
|
995
|
+
}
|
|
996
|
+
return { ...fnResult, events: harvested };
|
|
1011
997
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
998
|
+
);
|
|
999
|
+
for (const agg of aggregates) {
|
|
1000
|
+
agg.markPersisted(agg.version);
|
|
1001
|
+
}
|
|
1014
1002
|
if (deps.bus && events.length > 0) {
|
|
1015
1003
|
await deps.bus.publish(events);
|
|
1016
1004
|
}
|
|
@@ -1021,10 +1009,9 @@ var QueryBus = class {
|
|
|
1021
1009
|
static {
|
|
1022
1010
|
__name(this, "QueryBus");
|
|
1023
1011
|
}
|
|
1024
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1025
1012
|
handlers = /* @__PURE__ */ new Map();
|
|
1026
1013
|
register(queryType, handler) {
|
|
1027
|
-
this.handlers.set(queryType, handler);
|
|
1014
|
+
this.handlers.set(queryType, (query) => handler(query));
|
|
1028
1015
|
}
|
|
1029
1016
|
async execute(query) {
|
|
1030
1017
|
const handler = this.handlers.get(query.type);
|
|
@@ -1045,7 +1032,7 @@ var QueryBus = class {
|
|
|
1045
1032
|
if (!handler) {
|
|
1046
1033
|
throw new Error(`No handler registered for query type: ${query.type}`);
|
|
1047
1034
|
}
|
|
1048
|
-
return handler(query);
|
|
1035
|
+
return await handler(query);
|
|
1049
1036
|
}
|
|
1050
1037
|
};
|
|
1051
1038
|
|
|
@@ -1054,7 +1041,6 @@ var EventBusImpl = class {
|
|
|
1054
1041
|
static {
|
|
1055
1042
|
__name(this, "EventBusImpl");
|
|
1056
1043
|
}
|
|
1057
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1058
1044
|
handlers = /* @__PURE__ */ new Map();
|
|
1059
1045
|
subscribe(eventType, handler) {
|
|
1060
1046
|
const type = eventType;
|
|
@@ -1154,6 +1140,29 @@ var EventBusImpl = class {
|
|
|
1154
1140
|
}
|
|
1155
1141
|
};
|
|
1156
1142
|
|
|
1157
|
-
|
|
1143
|
+
// src/events/outbox.ts
|
|
1144
|
+
var InMemoryOutbox = class {
|
|
1145
|
+
static {
|
|
1146
|
+
__name(this, "InMemoryOutbox");
|
|
1147
|
+
}
|
|
1148
|
+
pending = /* @__PURE__ */ new Map();
|
|
1149
|
+
async add(events) {
|
|
1150
|
+
for (const event of events) {
|
|
1151
|
+
this.pending.set(event.eventId, {
|
|
1152
|
+
dispatchId: event.eventId,
|
|
1153
|
+
event
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
async getPending(limit) {
|
|
1158
|
+
const all = [...this.pending.values()];
|
|
1159
|
+
return typeof limit === "number" ? all.slice(0, limit) : all;
|
|
1160
|
+
}
|
|
1161
|
+
async markDispatched(dispatchIds) {
|
|
1162
|
+
for (const id of dispatchIds) this.pending.delete(id);
|
|
1163
|
+
}
|
|
1164
|
+
};
|
|
1165
|
+
|
|
1166
|
+
export { AggregateNotFoundError, AggregateRoot, CommandBus, ConcurrencyConflictError, DomainError, Entity, EventBusImpl, EventSourcedAggregate, InMemoryOutbox, InfrastructureError, MissingHandlerError, QueryBus, ValueObject, copyMetadata, createDomainEvent, createDomainEventWithMetadata, deepEqual, deepEqualExcept, deepFreeze, deepOmit, entityIds, findEntityById, freezeShallow, hasEntityId, mergeMetadata, removeEntityById, replaceEntityById, resetClockFactory, resetEventIdFactory, sameEntity, sameVersion, setClockFactory, setEventIdFactory, updateEntityById, vo, voEquals, voEqualsExcept, voWithValidation, withCommit };
|
|
1158
1167
|
//# sourceMappingURL=index.js.map
|
|
1159
1168
|
//# sourceMappingURL=index.js.map
|