@shirudo/ddd-kit 1.2.0 → 1.3.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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ok, err } from '@shirudo/result';
2
- import { BaseError, ValidationError } from '@shirudo/base-error';
2
+ import { BaseError, someChainRetryable, ValidationError } from '@shirudo/base-error';
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -944,7 +944,7 @@ var BaseAggregate = class extends Entity {
944
944
  * `changedKeys`/`hasChanges`. An override that skips `super` leaves
945
945
  * that baseline uncaptured: `changedKeys` permanently reports ALL
946
946
  * keys and `hasChanges` never returns `false`, so a partial-write
947
- * repository silently degrades to full writes on every save on top
947
+ * repository silently degrades to full writes on every save, on top
948
948
  * of the broken version sync.
949
949
  *
950
950
  * @param version - The version the row currently holds in the DB
@@ -1237,7 +1237,7 @@ var AggregateRoot = class extends BaseAggregate {
1237
1237
  * If you override this, call `super.markRestored(version)` FIRST:
1238
1238
  * skipping it leaves the baseline uncaptured, so `changedKeys`
1239
1239
  * permanently reports ALL keys and `hasChanges` never returns `false`
1240
- * partial-write repositories silently degrade to full writes on
1240
+ * (partial-write repositories silently degrade to full writes), on
1241
1241
  * top of breaking version sync.
1242
1242
  */
1243
1243
  markRestored(version) {
@@ -1260,7 +1260,7 @@ var AggregateRoot = class extends BaseAggregate {
1260
1260
  * **How it works.** `setState()` replaces state immutably and the
1261
1261
  * state object is shallow-frozen, so unchanged top-level sub-objects
1262
1262
  * keep reference identity across mutations. The diff is therefore a
1263
- * shallow per-key `!==` against the baseline reference O(top-level
1263
+ * shallow per-key `!==` against the baseline reference: O(top-level
1264
1264
  * keys), no proxies, no deep diff. A key also counts as dirty when its
1265
1265
  * *presence* differs (added or removed, even with an `undefined`
1266
1266
  * value). Computed fresh on every access (a new `Set` each time), so
@@ -1273,12 +1273,12 @@ var AggregateRoot = class extends BaseAggregate {
1273
1273
  * class-instance `TState` mutated through its own methods defeats
1274
1274
  * tracking entirely (the reference never changes). A keyless `TState`
1275
1275
  * (primitive, bare `Date`) has no keys to report, so `changedKeys`
1276
- * stays empty for it use {@link hasChanges}, whose reference
1276
+ * stays empty for it; use {@link hasChanges}, whose reference
1277
1277
  * fallback covers keyless states. A deep-equal but newly-referenced
1278
1278
  * value reports a false POSITIVE (harmless extra write); under the
1279
1279
  * contract above there are no false negatives.
1280
1280
  *
1281
- * Granularity is per top-level key table-granular, not row-granular:
1281
+ * Granularity is per top-level key, table-granular, not row-granular:
1282
1282
  * a dirty collection key means "this child table changed", not which
1283
1283
  * rows. `EventSourcedAggregate` deliberately has no `changedKeys`;
1284
1284
  * its `pendingEvents` are the change record.
@@ -1293,16 +1293,16 @@ var AggregateRoot = class extends BaseAggregate {
1293
1293
  * Safe skip signal: `false` only when there is genuinely nothing to
1294
1294
  * persist or flush. `true` when the aggregate has never been
1295
1295
  * persisted, the version moved past `persistedVersion`, there are
1296
- * unflushed {@link pendingEvents}, any state key is dirty, or for
1296
+ * unflushed {@link pendingEvents}, any state key is dirty, or, for
1297
1297
  * keyless states the per-key diff cannot see (primitive `TState`,
1298
- * zero-own-key objects like a bare `Date`) the state reference
1298
+ * zero-own-key objects like a bare `Date`), the state reference
1299
1299
  * changed since the baseline.
1300
1300
  *
1301
1301
  * The version clause is deliberate: `setState({...state}, true)` with
1302
1302
  * identical per-key values yields empty {@link changedKeys} but a
1303
1303
  * bumped version. If a repository skipped `save()` on a state-only
1304
1304
  * check, `withCommit` would still call `markPersisted(version)` after
1305
- * commit, desyncing `persistedVersion` from the DB row and the next
1305
+ * commit, desyncing `persistedVersion` from the DB row; and the next
1306
1306
  * uncontended save would throw a false `ConcurrencyConflictError`.
1307
1307
  *
1308
1308
  * The pending-events clause covers the sanctioned decoupled
@@ -1447,6 +1447,28 @@ var MissingHandlerError = class extends BaseError {
1447
1447
  __name(this, "MissingHandlerError");
1448
1448
  }
1449
1449
  };
1450
+ var EventHarvestError = class extends BaseError {
1451
+ constructor(message, eventType) {
1452
+ super(message, void 0, { name: "EventHarvestError" });
1453
+ this.eventType = eventType;
1454
+ }
1455
+ static {
1456
+ __name(this, "EventHarvestError");
1457
+ }
1458
+ };
1459
+ var UnenrolledChangesError = class extends BaseError {
1460
+ constructor(aggregateId) {
1461
+ super(
1462
+ `Aggregate ${aggregateId} was loaded in this unit of work and has pending events, but was never enrolled (no save), so its events would be silently dropped. Call repository.save(aggregate), and ensure save() calls session.enrollSaved before the row write.`,
1463
+ void 0,
1464
+ { name: "UnenrolledChangesError" }
1465
+ );
1466
+ this.aggregateId = aggregateId;
1467
+ }
1468
+ static {
1469
+ __name(this, "UnenrolledChangesError");
1470
+ }
1471
+ };
1450
1472
  var AggregateDeletedError = class extends BaseError {
1451
1473
  constructor(aggregateId) {
1452
1474
  super(
@@ -1675,8 +1697,17 @@ var CommandBus = class {
1675
1697
  }
1676
1698
  };
1677
1699
 
1700
+ // src/utils/abort.ts
1701
+ function abortReason(signal, fallbackMessage) {
1702
+ return signal.reason ?? new Error(fallbackMessage);
1703
+ }
1704
+ __name(abortReason, "abortReason");
1705
+
1678
1706
  // src/app/handler.ts
1679
1707
  async function withCommit(deps, fn) {
1708
+ if (deps.signal?.aborted) {
1709
+ throw abortReason(deps.signal, "withCommit aborted before opening a transaction");
1710
+ }
1680
1711
  const { result, aggregates, deleted, events } = await deps.scope.transactional(
1681
1712
  async (ctx) => {
1682
1713
  const fnResult = await fn(ctx);
@@ -1690,8 +1721,9 @@ async function withCommit(deps, fn) {
1690
1721
  });
1691
1722
  }
1692
1723
  if (event.aggregateVersion > agg.version) {
1693
- throw new Error(
1694
- `withCommit: event "${event.type}" carries a pre-set aggregateVersion (${event.aggregateVersion}) AHEAD of its aggregate's commit version (${agg.version}). A stale-or-copied pre-set would advance consumer idempotency watermarks past real history; remove the manual aggregateVersion or correct it.`
1724
+ throw new EventHarvestError(
1725
+ `withCommit: event "${event.type}" carries a pre-set aggregateVersion (${event.aggregateVersion}) AHEAD of its aggregate's commit version (${agg.version}). A stale-or-copied pre-set would advance consumer idempotency watermarks past real history; remove the manual aggregateVersion or correct it.`,
1726
+ event.type
1695
1727
  );
1696
1728
  }
1697
1729
  return event;
@@ -1702,10 +1734,11 @@ async function withCommit(deps, fn) {
1702
1734
  if (!event.aggregateId) missing.push("aggregateId");
1703
1735
  if (!event.aggregateType) missing.push("aggregateType");
1704
1736
  if (missing.length > 0) {
1705
- throw new Error(
1737
+ throw new EventHarvestError(
1706
1738
  `withCommit: event "${event.type}" is missing ${missing.join(
1707
1739
  " and "
1708
- )}. Use this.recordEvent(type, payload) inside aggregate methods instead of createDomainEvent(...); recordEvent auto-injects aggregateId and aggregateType. Outbox dispatchers and projection handlers rely on these fields for routing.`
1740
+ )}. Use this.recordEvent(type, payload) inside aggregate methods instead of createDomainEvent(...); recordEvent auto-injects aggregateId and aggregateType. Outbox dispatchers and projection handlers rely on these fields for routing.`,
1741
+ event.type
1709
1742
  );
1710
1743
  }
1711
1744
  }
@@ -1718,7 +1751,8 @@ async function withCommit(deps, fn) {
1718
1751
  deleted: new Set(fnResult.deleted ?? []),
1719
1752
  events: harvested
1720
1753
  };
1721
- }
1754
+ },
1755
+ { signal: deps.signal }
1722
1756
  );
1723
1757
  for (const agg of aggregates) {
1724
1758
  try {
@@ -1751,6 +1785,10 @@ var IdentityMap = class {
1751
1785
  }
1752
1786
  _stores = /* @__PURE__ */ new Map();
1753
1787
  _deleted = /* @__PURE__ */ new Map();
1788
+ // pendingEvents length captured when an instance was first registered
1789
+ // (load time), so the unit of work can tell events RECORDED AFTER load
1790
+ // apart from a "dirty" reconstitution that already carried events.
1791
+ _pendingAtRegistration = /* @__PURE__ */ new WeakMap();
1754
1792
  /** The cached instance for type+id, or `undefined` (also after {@link delete}). */
1755
1793
  get(type, id) {
1756
1794
  return this._stores.get(type)?.get(id);
@@ -1762,7 +1800,7 @@ var IdentityMap = class {
1762
1800
  /**
1763
1801
  * Whether type+id was {@link delete}d in this unit of work. The
1764
1802
  * read path checks this BEFORE hydrating and returns `null`, so
1765
- * "deleted in this operation" reads uniformly as not-found
1803
+ * "deleted in this operation" reads uniformly as not-found,
1766
1804
  * regardless of whether the repository's physical delete already
1767
1805
  * removed the row or is deferred within the transaction. Without
1768
1806
  * the check, a read-only probe of a deleted aggregate would crash
@@ -1801,6 +1839,34 @@ var IdentityMap = class {
1801
1839
  );
1802
1840
  }
1803
1841
  store.set(id, aggregate);
1842
+ if (aggregate !== null && typeof aggregate === "object" && !this._pendingAtRegistration.has(aggregate)) {
1843
+ const pending = pendingEventsOf(aggregate);
1844
+ if (pending) {
1845
+ this._pendingAtRegistration.set(aggregate, pending.length);
1846
+ }
1847
+ }
1848
+ }
1849
+ /**
1850
+ * Registered instances that have recorded MORE pending events than they
1851
+ * carried when first registered (loaded). Used by the unit of work's
1852
+ * end-of-run guard: an aggregate that gained events after load but was
1853
+ * never enrolled would silently drop them. A read-only load, or a
1854
+ * reconstitution that already carried events, shows no increase and is
1855
+ * not reported.
1856
+ */
1857
+ instancesWithNewPendingEvents() {
1858
+ const result = [];
1859
+ for (const store of this._stores.values()) {
1860
+ for (const instance of store.values()) {
1861
+ const pending = pendingEventsOf(instance);
1862
+ if (!pending) continue;
1863
+ const atRegistration = this._pendingAtRegistration.get(instance) ?? 0;
1864
+ if (pending.length > atRegistration) {
1865
+ result.push(instance);
1866
+ }
1867
+ }
1868
+ }
1869
+ return result;
1804
1870
  }
1805
1871
  /**
1806
1872
  * Removes the entry for type+id and records a tombstone: subsequent
@@ -1824,6 +1890,12 @@ var IdentityMap = class {
1824
1890
  this._deleted.clear();
1825
1891
  }
1826
1892
  };
1893
+ function pendingEventsOf(value) {
1894
+ if (value === null || typeof value !== "object") return void 0;
1895
+ const pending = value.pendingEvents;
1896
+ return Array.isArray(pending) ? pending : void 0;
1897
+ }
1898
+ __name(pendingEventsOf, "pendingEventsOf");
1827
1899
 
1828
1900
  // src/app/unit-of-work.ts
1829
1901
  var NestedUnitOfWorkError = class extends BaseError {
@@ -1857,7 +1929,7 @@ var CommitError = class extends InfrastructureError {
1857
1929
  }
1858
1930
  constructor(cause) {
1859
1931
  super(
1860
- "Unit of work failed after the work callback completed: the event harvest, outbox write, or transaction commit rejected. The transaction did not commit; see cause.",
1932
+ "Unit of work failed after the work callback completed: the outbox write or the transaction commit rejected. The transaction did not commit; this failure may be transient, inspect the cause (e.g. someChainRetryable) before retrying.",
1861
1933
  cause,
1862
1934
  { name: "CommitError" }
1863
1935
  );
@@ -1890,7 +1962,10 @@ var UnitOfWork = class {
1890
1962
  * run the post-commit lifecycle (markPersisted, publish) for every
1891
1963
  * enrolled aggregate. Returns the callback's result.
1892
1964
  */
1893
- async run(work) {
1965
+ async run(work, options) {
1966
+ if (options?.signal?.aborted) {
1967
+ throw abortReason(options.signal, "UnitOfWork.run aborted before opening a transaction");
1968
+ }
1894
1969
  if (this._active) {
1895
1970
  throw new NestedUnitOfWorkError();
1896
1971
  }
@@ -1905,7 +1980,8 @@ var UnitOfWork = class {
1905
1980
  outbox: this.deps.outbox,
1906
1981
  bus: this.deps.bus,
1907
1982
  scope: this.deps.scope,
1908
- onPublishError: this.deps.onPublishError
1983
+ onPublishError: this.deps.onPublishError,
1984
+ signal: options?.signal
1909
1985
  },
1910
1986
  async (tx) => {
1911
1987
  session?.close();
@@ -1915,9 +1991,10 @@ var UnitOfWork = class {
1915
1991
  workThrew = false;
1916
1992
  workError = void 0;
1917
1993
  const repositories = this.buildRepositories(tx, s);
1918
- const context = makeContext(repositories, tx, s);
1994
+ const context = makeContext(repositories, tx, s, options?.signal);
1919
1995
  try {
1920
1996
  const result = await work(context);
1997
+ s.assertAllChangesEnrolled();
1921
1998
  workCompleted = true;
1922
1999
  const aggregates = s.enrolledAggregates;
1923
2000
  const deleted = s.deletedAggregates;
@@ -1938,6 +2015,10 @@ var UnitOfWork = class {
1938
2015
  throw new RollbackError(workError, error);
1939
2016
  }
1940
2017
  if (workCompleted) {
2018
+ const harvestError = findHarvestErrorInChain(error);
2019
+ if (harvestError) {
2020
+ throw harvestError;
2021
+ }
1941
2022
  throw new CommitError(error);
1942
2023
  }
1943
2024
  throw error;
@@ -1987,6 +2068,24 @@ var Session = class {
1987
2068
  );
1988
2069
  this._enrolled.add(aggregate);
1989
2070
  }
2071
+ /**
2072
+ * End-of-run safety net: a loaded aggregate (registered in the identity
2073
+ * map via `getById`) that carries pending events but was never enrolled
2074
+ * is almost certainly a forgotten `save()` / `enrollSaved`, whose events
2075
+ * would otherwise be silently dropped. Convert that silent loss into a
2076
+ * loud, rolling-back {@link UnenrolledChangesError}. Only sees loaded
2077
+ * aggregates; a freshly created one that was never enrolled is invisible
2078
+ * to the kit (the contract test suite remains the full mitigation).
2079
+ */
2080
+ assertAllChangesEnrolled() {
2081
+ for (const instance of this._identityMap.instancesWithNewPendingEvents()) {
2082
+ if (this._enrolled.has(instance) || this._deleted.has(instance)) {
2083
+ continue;
2084
+ }
2085
+ const id = instance.id;
2086
+ throw new UnenrolledChangesError(String(id));
2087
+ }
2088
+ }
1990
2089
  get enrolledAggregates() {
1991
2090
  return [...this._enrolled];
1992
2091
  }
@@ -2003,7 +2102,7 @@ var Session = class {
2003
2102
  }
2004
2103
  }
2005
2104
  };
2006
- function makeContext(repositories, transaction, session) {
2105
+ function makeContext(repositories, transaction, session, signal) {
2007
2106
  return {
2008
2107
  get repositories() {
2009
2108
  session.assertOpen("context.repositories");
@@ -2013,10 +2112,32 @@ function makeContext(repositories, transaction, session) {
2013
2112
  session.assertOpen("context.rawTransaction");
2014
2113
  return transaction;
2015
2114
  },
2016
- session
2115
+ session,
2116
+ // The caller's own signal: exposed directly, not gated by
2117
+ // assertOpen, so polling `aborted` after close stays harmless.
2118
+ signal
2017
2119
  };
2018
2120
  }
2019
2121
  __name(makeContext, "makeContext");
2122
+ function findHarvestErrorInChain(error) {
2123
+ const seen = /* @__PURE__ */ new Set();
2124
+ let current = error;
2125
+ while (current !== null && typeof current === "object" && !seen.has(current)) {
2126
+ seen.add(current);
2127
+ if (current instanceof EventHarvestError) {
2128
+ return current;
2129
+ }
2130
+ let next;
2131
+ try {
2132
+ next = current.cause;
2133
+ } catch {
2134
+ return void 0;
2135
+ }
2136
+ current = next;
2137
+ }
2138
+ return void 0;
2139
+ }
2140
+ __name(findHarvestErrorInChain, "findHarvestErrorInChain");
2020
2141
  function causeChainContains(error, target) {
2021
2142
  if (target === void 0 || target === null) {
2022
2143
  return false;
@@ -2103,7 +2224,7 @@ var EventBusImpl = class {
2103
2224
  once(eventType, options) {
2104
2225
  return new Promise((resolve, reject) => {
2105
2226
  if (options?.signal?.aborted) {
2106
- reject(options.signal.reason ?? new Error("EventBus.once aborted"));
2227
+ reject(abortReason(options.signal, "EventBus.once aborted"));
2107
2228
  return;
2108
2229
  }
2109
2230
  let timer;
@@ -2125,9 +2246,7 @@ var EventBusImpl = class {
2125
2246
  if (options?.signal) {
2126
2247
  abortListener = /* @__PURE__ */ __name(() => {
2127
2248
  cleanup();
2128
- reject(
2129
- options.signal.reason ?? new Error("EventBus.once aborted")
2130
- );
2249
+ reject(abortReason(options.signal, "EventBus.once aborted"));
2131
2250
  }, "abortListener");
2132
2251
  options.signal.addEventListener("abort", abortListener);
2133
2252
  }
@@ -2207,6 +2326,101 @@ var InMemoryOutbox = class {
2207
2326
  for (const id of dispatchIds) this.pending.delete(id);
2208
2327
  }
2209
2328
  };
2329
+ var DEFAULT_MAX_ATTEMPTS = 3;
2330
+ var DEFAULT_BASE_DELAY_MS = 50;
2331
+ var DEFAULT_MAX_DELAY_MS = 1e3;
2332
+ function computeBackoffDelay(attempt, opts) {
2333
+ const exponential = opts.baseDelayMs * 2 ** (attempt - 1);
2334
+ const capped = Math.min(opts.maxDelayMs, exponential);
2335
+ const jitter = 0.8 + opts.random() * 0.4;
2336
+ return Math.max(0, Math.min(opts.maxDelayMs, Math.round(capped * jitter)));
2337
+ }
2338
+ __name(computeBackoffDelay, "computeBackoffDelay");
2339
+ function assertNonNegativeFinite(field, value) {
2340
+ if (!Number.isFinite(value) || value < 0) {
2341
+ throw new Error(
2342
+ `RetryingTransactionScope: ${field} must be a non-negative finite number, got ${value}`
2343
+ );
2344
+ }
2345
+ }
2346
+ __name(assertNonNegativeFinite, "assertNonNegativeFinite");
2347
+ var ABORT_MESSAGE = "RetryingTransactionScope aborted";
2348
+ function defaultSleep(ms, signal) {
2349
+ return new Promise((resolve, reject) => {
2350
+ if (signal?.aborted) {
2351
+ reject(abortReason(signal, ABORT_MESSAGE));
2352
+ return;
2353
+ }
2354
+ let onAbort;
2355
+ const timer = setTimeout(() => {
2356
+ if (onAbort && signal) signal.removeEventListener("abort", onAbort);
2357
+ resolve();
2358
+ }, ms);
2359
+ if (signal) {
2360
+ onAbort = /* @__PURE__ */ __name(() => {
2361
+ clearTimeout(timer);
2362
+ reject(abortReason(signal, ABORT_MESSAGE));
2363
+ }, "onAbort");
2364
+ signal.addEventListener("abort", onAbort, { once: true });
2365
+ }
2366
+ });
2367
+ }
2368
+ __name(defaultSleep, "defaultSleep");
2369
+ var RetryingTransactionScope = class {
2370
+ constructor(inner, policy = {}) {
2371
+ this.inner = inner;
2372
+ this.maxAttempts = policy.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
2373
+ this.baseDelayMs = policy.baseDelayMs ?? DEFAULT_BASE_DELAY_MS;
2374
+ this.maxDelayMs = policy.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
2375
+ if (!Number.isInteger(this.maxAttempts) || this.maxAttempts < 1) {
2376
+ throw new Error(
2377
+ `RetryingTransactionScope: maxAttempts must be an integer >= 1, got ${this.maxAttempts}`
2378
+ );
2379
+ }
2380
+ assertNonNegativeFinite("baseDelayMs", this.baseDelayMs);
2381
+ assertNonNegativeFinite("maxDelayMs", this.maxDelayMs);
2382
+ this.isRetryable = policy.isRetryable ?? someChainRetryable;
2383
+ this.sleep = policy.sleep ?? defaultSleep;
2384
+ this.random = policy.random ?? Math.random;
2385
+ this.onRetry = policy.onRetry;
2386
+ }
2387
+ static {
2388
+ __name(this, "RetryingTransactionScope");
2389
+ }
2390
+ // Policy resolved and validated once at construction (a misconfigured
2391
+ // policy is a wiring bug and fails fast, never at run time).
2392
+ maxAttempts;
2393
+ baseDelayMs;
2394
+ maxDelayMs;
2395
+ isRetryable;
2396
+ sleep;
2397
+ random;
2398
+ onRetry;
2399
+ async transactional(fn, options) {
2400
+ const { maxAttempts, isRetryable, sleep } = this;
2401
+ const signal = options?.signal;
2402
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
2403
+ if (signal?.aborted) {
2404
+ throw abortReason(signal, ABORT_MESSAGE);
2405
+ }
2406
+ try {
2407
+ return await this.inner.transactional(fn, options);
2408
+ } catch (error) {
2409
+ if (attempt === maxAttempts || !isRetryable(error)) {
2410
+ throw error;
2411
+ }
2412
+ const delayMs = computeBackoffDelay(attempt, {
2413
+ baseDelayMs: this.baseDelayMs,
2414
+ maxDelayMs: this.maxDelayMs,
2415
+ random: this.random
2416
+ });
2417
+ this.onRetry?.({ attempt, error, delayMs });
2418
+ await sleep(delayMs, signal);
2419
+ }
2420
+ }
2421
+ throw new Error("RetryingTransactionScope: exhausted without result");
2422
+ }
2423
+ };
2210
2424
  function voValidated(t, validate, message = "Validation failed") {
2211
2425
  const issues = new ValidationError(message);
2212
2426
  validate(issues, t);
@@ -2214,6 +2428,6 @@ function voValidated(t, validate, message = "Validation failed") {
2214
2428
  }
2215
2429
  __name(voValidated, "voValidated");
2216
2430
 
2217
- export { AggregateDeletedError, AggregateNotFoundError, AggregateRoot, CommandBus, CommitError, ConcurrencyConflictError, DomainError, DuplicateAggregateError, Entity, EventBusImpl, EventSourcedAggregate, IdentityMap, InMemoryOutbox, InfrastructureError, MissingHandlerError, NestedUnitOfWorkError, QueryBus, RollbackError, TransactionClosedError, UnitOfWork, 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, voValidated, voWithValidation, withClockFactory, withCommit, withEventIdFactory };
2431
+ export { AggregateDeletedError, AggregateNotFoundError, AggregateRoot, CommandBus, CommitError, ConcurrencyConflictError, DomainError, DuplicateAggregateError, Entity, EventBusImpl, EventHarvestError, EventSourcedAggregate, IdentityMap, InMemoryOutbox, InfrastructureError, MissingHandlerError, NestedUnitOfWorkError, QueryBus, RetryingTransactionScope, RollbackError, TransactionClosedError, UnenrolledChangesError, UnitOfWork, ValueObject, computeBackoffDelay, copyMetadata, createDomainEvent, createDomainEventWithMetadata, deepEqual, deepEqualExcept, deepFreeze, deepOmit, entityIds, findEntityById, freezeShallow, hasEntityId, mergeMetadata, removeEntityById, replaceEntityById, resetClockFactory, resetEventIdFactory, sameEntity, sameVersion, setClockFactory, setEventIdFactory, updateEntityById, vo, voEquals, voEqualsExcept, voValidated, voWithValidation, withClockFactory, withCommit, withEventIdFactory };
2218
2432
  //# sourceMappingURL=index.js.map
2219
2433
  //# sourceMappingURL=index.js.map