@shirudo/ddd-kit 3.0.0-rc.10 → 3.0.0-rc.12
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/chunks/kit-errors.d.ts +287 -108
- package/dist/chunks/kit-errors.js +250 -111
- package/dist/chunks/kit-errors.js.map +1 -1
- package/dist/chunks/{ports.js → read-stream-pages.js} +713 -225
- package/dist/chunks/read-stream-pages.js.map +1 -0
- package/dist/chunks/snapshot-store.d.ts +597 -115
- package/dist/index.d.ts +608 -437
- package/dist/index.js +1508 -637
- package/dist/index.js.map +1 -1
- package/dist/money.d.ts +1 -1
- package/dist/testing.d.ts +106 -15
- package/dist/testing.js +546 -52
- package/dist/testing.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunks/ports.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { $ as
|
|
1
|
+
import { $ as PendingEventLimitExceededErrorOptions, A as IdempotencyInFlightErrorOptions, B as InvalidEventStreamPageErrorOptions, C as FoldReturnedNoStateError, Ct as UnreplayableAggregateError, D as IdempotencyClaimLostErrorOptions, Dt as isWiringErrorLike, E as IdempotencyClaimLostError, Et as isInfrastructureErrorLike, F as InMemoryCapacityExceededError, G as KitWiringError, H as InvalidVersionError, I as InMemoryCapacityExceededErrorOptions, J as MissingFoldError, K as MisattributedEventError, L as InfrastructureError, M as IdempotencyKeyReuseErrorOptions, N as IdempotencyReconciliationRequiredError, O as IdempotencyCompletionWithoutClaimError, P as IdempotencyReconciliationRequiredErrorOptions, Q as PendingEventLimitExceededError, R as InvalidCommandMessageError, S as EventStreamPageReason, St as UnregisteredHandlerErrorOptions, T as HostileStateKeyError, Tt as isDomainErrorLike, U as KitErrorCode, V as InvalidIntegrationMessageError, W as KitErrorOptions, X as PendingEventBatchMismatchError, Y as MissingHandlerError, Z as PendingEventBatchMismatchErrorOptions, _ as DuplicateHandlerRegistrationError, _t as UnenrolledChangesErrorOptions, a as AggregateNotFoundErrorOptions, at as ReentrantEventRecordingErrorOptions, b as ErrorMapperFailedErrorOptions, bt as UnprojectableEventError, c as ConcurrencyConflictErrorOptions, ct as ReplayTargetMismatchError, d as DirectStateMutationErrorOptions, dt as SnapshotCorruptedError, et as ProjectionGapError, f as DomainError, ft as SnapshotSchemaMismatchError, g as DuplicateEventIdErrorOptions, gt as UnenrolledChangesError, h as DuplicateEventIdError, ht as SnapshotVersionNotRestoredErrorOptions, i as AggregateNotFoundError, it as ReentrantEventRecordingError, j as IdempotencyKeyReuseError, k as IdempotencyInFlightError, l as ConcurrencyConflictReason, lt as ReplayTargetMismatchErrorOptions, m as DuplicateAggregateErrorOptions, mt as SnapshotVersionNotRestoredError, n as AggregateDeletedErrorOptions, nt as ProjectionOrderViolationError, o as CapabilityRegistryConflictError, ot as ReplayRejectedError, p as DuplicateAggregateError, pt as SnapshotSchemaMismatchErrorOptions, q as MissingEntityIdError, r as AggregateIdentityMismatchOptions, rt as ProjectionReceiptViolationError, s as ConcurrencyConflictError, st as ReplayRejectedErrorOptions, t as AggregateDeletedError, tt as ProjectionIdentityViolationError, u as DirectStateMutationError, ut as ReplayTargetMismatchReason, v as DuplicateHandlerRegistrationErrorOptions, vt as UnmanagedInstanceError, w as ForeignEventError, wt as UnreplayableAggregateErrorOptions, x as EventHarvestError, xt as UnregisteredHandlerError, y as ErrorMapperFailedError, yt as UnmintedEventError, z as InvalidEventStreamPageError } from "./chunks/kit-errors.js";
|
|
2
|
+
import { $ as EventHandler, $t as Command, A as IdempotencyClaimHandle, At as CreateDomainEventFromFactsOptions, B as withIdempotentCommit, Bt as PendingDomainEvent, C as IdentityMap, Ct as ExecutionContext, D as ProjectionPosition, Dt as EventCommitCandidatePosition, E as ProjectionCheckpointStore, Et as EventCommitCandidate, F as IdempotencyStore, Ft as DomainEventFactory, G as CommitEnrollment, Gt as createDomainEventFactory, H as DeadlineStore, Ht as UncommittedDomainEventOf, I as IdempotentCommitRequest, It as DomainEventFactoryOptions, J as WithCommitWorkResult, Jt as defaultDomainEventFactory, K as CommitEnrollmentOptions, Kt as createDomainEventFromFacts, L as IdempotentCommitResult, Lt as DomainEventStamp, M as IdempotencyOperationErrorContext, Mt as CreateDomainEventStampOptions, N as IdempotencyReconciliation, Nt as CreateUncommittedDomainEventOptions, O as isPositionAfter, Ot as AnyDomainEvent, P as IdempotencyReconciliationDecision, Pt as DomainEvent, Q as EventBus, Qt as AggregateIdentity, R as IdempotentExecution, Rt as EventIdFactory, S as AggregateClass, St as OutboxWriter, T as ProjectionCheckpoint, Tt as CommittedDomainEvent, U as DueDeadline, Ut as copyMetadata, V as DeadLetterDeadline, Vt as UncommittedDomainEvent, W as AggregateCommitToken, Wt as createDomainEvent, X as TransactionScope, Xt as recordDomainEvent, Y as withCommit, Yt as mergeMetadata, Z as TransactionalOptions, Zt as ClockFactory, _ as capturePersistenceBaseline, _t as routeEventsToCommandOutbox, a as EventStoreAppendOptions, at as Version, b as persistenceProjectionDrifted, bt as Outbox, c as StreamReadResult, ct as Id, d as RepositoryTracking, dt as CommandMessageContent, en as CommandHandler, et as OnceOptions, f as UnitOfWorkIdentityMap, ft as CommandMessageRelationships, g as PersistenceModel, gt as DurableCommandMessage, h as PersistenceLifecycle, ht as CommandOutboxWriter, i as EventStore, in as JsonValue, it as ReplayableAggregate, j as IdempotencyLease, jt as CreateDomainEventOptions, k as IdempotencyClaim, kt as AnyUncommittedDomainEvent, l as AggregatePersistenceWrite, lt as IdGenerator, m as PersistenceChanges, mt as CommandOutboxMapper, n as ReplayableStreamPages, nn as JsonObject, nt as Aggregate, o as EventStreamReader, ot as sameVersion, p as PersistenceBaseline, pt as CommandOutboxCommitCandidate, q as WithCommitDeps, qt as createUncommittedDomainEvent, r as reconstituteAggregateFromStreamPages, rn as JsonPrimitive, rt as AggregateSnapshot, s as ReadStreamOptions, st as toVersion, t as SnapshotStore, tn as PublishedCommand, tt as PublishOptions, u as AggregateWriteIntent, ut as CommandCommitOriginCandidate, v as derivePersistenceChanges, vt as DeadLetterRecord, w as Projection, wt as CommitPosition, x as recapturePersistenceBaseline, xt as OutboxRecord, y as insertPersistenceBaseline, yt as DispatchTrackingOutbox, z as WithIdempotentCommitDeps, zt as EventMetadata } from "./chunks/snapshot-store.js";
|
|
3
3
|
import { Result } from "@shirudo/result";
|
|
4
4
|
import { ValidationError } from "@shirudo/base-error";
|
|
5
5
|
//#region src/application/cqrs/internal/bus-internals.d.ts
|
|
@@ -410,6 +410,32 @@ declare class QueryBus<TMap extends QueryTypeMap = QueryTypeMap, E = string> imp
|
|
|
410
410
|
executeUnsafe<Q extends Query, R>(query: UntypedMapDispatch<TMap, Q>): Promise<R>;
|
|
411
411
|
}
|
|
412
412
|
//#endregion
|
|
413
|
+
//#region src/persistence/repository/in-memory-transaction.d.ts
|
|
414
|
+
/**
|
|
415
|
+
* The transaction of one registered store inside an
|
|
416
|
+
* `InMemoryTransactionScope`. The scope ends it once, with `commit` or
|
|
417
|
+
* `rollback`.
|
|
418
|
+
*/
|
|
419
|
+
interface InMemoryTransaction {
|
|
420
|
+
/**
|
|
421
|
+
* Ends the transaction and keeps its writes. It must not throw. If a commit
|
|
422
|
+
* throws, the scope still commits the other stores and rejects with the
|
|
423
|
+
* first failure, so the writes stay partly committed.
|
|
424
|
+
*/
|
|
425
|
+
commit(): void;
|
|
426
|
+
/** Ends the transaction and undoes its writes. */
|
|
427
|
+
rollback(): void;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* An in-memory store that you can register with an
|
|
431
|
+
* `InMemoryTransactionScope`. The store prepares its rollback when a
|
|
432
|
+
* transaction begins. The scope never reads the state of a store.
|
|
433
|
+
*/
|
|
434
|
+
interface InMemoryTransactionParticipant {
|
|
435
|
+
/** Begins a transaction. Only an `InMemoryTransactionScope` calls this method. */
|
|
436
|
+
beginTransaction(): InMemoryTransaction;
|
|
437
|
+
}
|
|
438
|
+
//#endregion
|
|
413
439
|
//#region src/application/deadlines/adapters/in-memory-deadline-store.d.ts
|
|
414
440
|
/** Construction options for {@link InMemoryDeadlineStore}. */
|
|
415
441
|
interface InMemoryDeadlineStoreOptions {
|
|
@@ -428,23 +454,46 @@ interface InMemoryDeadlineStoreOptions {
|
|
|
428
454
|
* limit rejects a new address before mutation; delivery state is never
|
|
429
455
|
* silently evicted.
|
|
430
456
|
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
457
|
+
* On its own, the store knows nothing about your `TransactionScope`
|
|
458
|
+
* rollbacks: a rolled-back `schedule` or `cancel` stays applied. Register
|
|
459
|
+
* the store with an `InMemoryTransactionScope` for tests that roll back or
|
|
460
|
+
* retry.
|
|
461
|
+
*
|
|
462
|
+
* A processor reads only committed deadlines. While a transaction is open,
|
|
463
|
+
* `due` skips a deadline that the transaction scheduled. For an address that
|
|
464
|
+
* the transaction rescheduled or cancelled, it returns the committed
|
|
465
|
+
* deadline as it was at the first write of the transaction. A failure report
|
|
466
|
+
* against that deadline counts its attempts. At the ceiling, `due` stops
|
|
467
|
+
* returning it until the transaction ends. A rollback also undoes an acknowledgement or a failure report
|
|
468
|
+
* that a processor made while the transaction was open. The processor then
|
|
469
|
+
* delivers that deadline again. For production, prove the transactional half
|
|
470
|
+
* of the contract with `createDeadlineStoreContractTests` and its rollback
|
|
471
|
+
* capability.
|
|
436
472
|
*
|
|
437
473
|
* Payloads are deep-copied on schedule and on delivery
|
|
438
474
|
* (`structuredClone`), so neither side can mutate the other's copy.
|
|
439
475
|
*/
|
|
440
|
-
declare class InMemoryDeadlineStore<TPayload = unknown> implements DeadlineStore<TPayload
|
|
476
|
+
declare class InMemoryDeadlineStore<TPayload = unknown> implements DeadlineStore<TPayload>, InMemoryTransactionParticipant {
|
|
441
477
|
private readonly pending;
|
|
442
478
|
/** Keyed by deliveryId: several incarnations of one address can be dead. */
|
|
443
479
|
private readonly dead;
|
|
444
480
|
private readonly maxDeliveryAttempts;
|
|
445
481
|
private readonly maxRecords;
|
|
446
482
|
private nextSequence;
|
|
483
|
+
/**
|
|
484
|
+
* The committed deadline of each address that the open transaction wrote,
|
|
485
|
+
* captured at its first write. `undefined` marks an address without one.
|
|
486
|
+
*/
|
|
487
|
+
private committedVersions;
|
|
447
488
|
constructor(options?: InMemoryDeadlineStoreOptions);
|
|
489
|
+
/**
|
|
490
|
+
* Records the state that a rollback of an `InMemoryTransactionScope`
|
|
491
|
+
* returns to: the pending and the dead-letter records. The rollback
|
|
492
|
+
* keeps the sequence counter, as a database sequence does, so a
|
|
493
|
+
* delivery id stays unique. Until the transaction ends, `due` returns the
|
|
494
|
+
* committed deadline of each address that the transaction writes.
|
|
495
|
+
*/
|
|
496
|
+
beginTransaction(): InMemoryTransaction;
|
|
448
497
|
schedule(deadline: {
|
|
449
498
|
scope: string;
|
|
450
499
|
key: string;
|
|
@@ -453,6 +502,15 @@ declare class InMemoryDeadlineStore<TPayload = unknown> implements DeadlineStore
|
|
|
453
502
|
}): Promise<void>;
|
|
454
503
|
cancel(scope: string, key: string): Promise<void>;
|
|
455
504
|
due(now: Date, limit: number): Promise<ReadonlyArray<DueDeadline<TPayload>>>;
|
|
505
|
+
private recordCommittedVersion;
|
|
506
|
+
/**
|
|
507
|
+
* The pending deadlines that a processor may see. For an address that the
|
|
508
|
+
* open transaction wrote, it is the committed deadline, if any, and not
|
|
509
|
+
* the live record.
|
|
510
|
+
*/
|
|
511
|
+
private committedPending;
|
|
512
|
+
/** The address of the committed deadline with this delivery id, if any. */
|
|
513
|
+
private committedVersionAddress;
|
|
456
514
|
markDelivered(deliveryIds: ReadonlyArray<string>): Promise<void>;
|
|
457
515
|
markFailed(deliveryId: string, error?: unknown): Promise<DeadLetterDeadline<TPayload> | undefined>;
|
|
458
516
|
deadLetters(): Promise<ReadonlyArray<DeadLetterDeadline<TPayload>>>;
|
|
@@ -728,14 +786,26 @@ interface InMemoryIdempotencyStoreOptions {
|
|
|
728
786
|
* process must configure the limit or use a durable adapter; exhaustion
|
|
729
787
|
* rejects new keys before mutation and never forgets an idempotency decision.
|
|
730
788
|
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
789
|
+
* On its own, the store is the reference for the leased family: it cannot
|
|
790
|
+
* see commits or rollbacks. Claims and staged outcomes carry bounded leases,
|
|
791
|
+
* while every mutation compares the store-minted token. An expired pending
|
|
792
|
+
* claim may be replaced; an expired staged outcome cannot be guessed away and
|
|
793
|
+
* instead returns `reconciliation-required`. Only an authoritative
|
|
794
|
+
* `committed` / `not-committed` decision can settle it.
|
|
795
|
+
*
|
|
796
|
+
* Register the store with an `InMemoryTransactionScope` for tests that roll
|
|
797
|
+
* back or retry. A rollback then undoes the writes of `claim` and `complete`,
|
|
798
|
+
* which the port runs inside the transaction. It returns each key that they
|
|
799
|
+
* wrote to its earlier entry. The lease operations `renew`, `confirm`,
|
|
800
|
+
* `abandon`, and `reconcile` stay out of band, as the port defines them. A
|
|
801
|
+
* rollback keeps their writes on every other key. A confirmation that
|
|
802
|
+
* arrives after the next transaction began therefore survives the rollback
|
|
803
|
+
* of that transaction.
|
|
736
804
|
*/
|
|
737
|
-
declare class InMemoryIdempotencyStore<TCtx = unknown> implements IdempotencyStore<TCtx
|
|
805
|
+
declare class InMemoryIdempotencyStore<TCtx = unknown> implements IdempotencyStore<TCtx>, InMemoryTransactionParticipant {
|
|
738
806
|
private readonly entries;
|
|
807
|
+
/** The entries that `claim` and `complete` replaced in the open transaction. */
|
|
808
|
+
private replacedInTransaction;
|
|
739
809
|
private readonly clock;
|
|
740
810
|
private readonly claimTokenFactory;
|
|
741
811
|
private readonly leaseDurationMs;
|
|
@@ -743,6 +813,12 @@ declare class InMemoryIdempotencyStore<TCtx = unknown> implements IdempotencySto
|
|
|
743
813
|
private readonly maxEntries;
|
|
744
814
|
private tokenGeneration;
|
|
745
815
|
constructor(options?: InMemoryIdempotencyStoreOptions);
|
|
816
|
+
/**
|
|
817
|
+
* Starts to record the entries that `claim` and `complete` replace. The
|
|
818
|
+
* rollback restores them in reverse order. It keeps the token generation,
|
|
819
|
+
* so a token from a rolled-back claim never names a later claim.
|
|
820
|
+
*/
|
|
821
|
+
beginTransaction(): InMemoryTransaction;
|
|
746
822
|
claim(_ctx: TCtx, key: string, fingerprint: string): Promise<IdempotencyClaim>;
|
|
747
823
|
complete(_ctx: TCtx, claim: IdempotencyClaimHandle, outcome: unknown): Promise<void>;
|
|
748
824
|
renew(claim: IdempotencyClaimHandle): Promise<IdempotencyLease | undefined>;
|
|
@@ -753,7 +829,15 @@ declare class InMemoryIdempotencyStore<TCtx = unknown> implements IdempotencySto
|
|
|
753
829
|
get size(): number;
|
|
754
830
|
/** Test hook: drops every record. */
|
|
755
831
|
clear(): void;
|
|
832
|
+
/**
|
|
833
|
+
* Returns the claim that the stored entry of the key decides, or
|
|
834
|
+
* `undefined` when the store can create a pending claim. Throws for a
|
|
835
|
+
* reused key, a claim in flight, and a full store.
|
|
836
|
+
*/
|
|
837
|
+
private decideFromStoredEntry;
|
|
838
|
+
private newTokenPart;
|
|
756
839
|
private createPending;
|
|
840
|
+
private writeInTransaction;
|
|
757
841
|
private lease;
|
|
758
842
|
private nowMs;
|
|
759
843
|
private claimLost;
|
|
@@ -761,7 +845,7 @@ declare class InMemoryIdempotencyStore<TCtx = unknown> implements IdempotencySto
|
|
|
761
845
|
//#endregion
|
|
762
846
|
//#region src/application/projections/adapters/in-memory-checkpoint-store.d.ts
|
|
763
847
|
interface InMemoryProjectionCheckpointStoreOptions {
|
|
764
|
-
/** Maximum checkpoints across all projection names and aggregate
|
|
848
|
+
/** Maximum checkpoints across all projection names and aggregate identities. */
|
|
765
849
|
readonly maxCheckpoints?: number;
|
|
766
850
|
}
|
|
767
851
|
/**
|
|
@@ -770,16 +854,19 @@ interface InMemoryProjectionCheckpointStoreOptions {
|
|
|
770
854
|
* serves tests and in-memory read models.
|
|
771
855
|
*
|
|
772
856
|
* Its checkpoint-key locks serialize competing projectors only inside one
|
|
773
|
-
* process and only when they share this store instance.
|
|
774
|
-
*
|
|
775
|
-
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
778
|
-
*
|
|
857
|
+
* process and only when they share this store instance. The store ignores
|
|
858
|
+
* the `ctx` parameter. On its own, it knows nothing about your
|
|
859
|
+
* `TransactionScope` rollbacks: a rolled-back projector batch keeps its
|
|
860
|
+
* checkpoints. Register the store with an `InMemoryTransactionScope` for
|
|
861
|
+
* tests that roll back or retry. While a transaction is open, `hasReached`
|
|
862
|
+
* answers from the checkpoints at the start of the transaction. Use it for
|
|
863
|
+
* tests and disposable in-memory read models; production atomicity is the
|
|
864
|
+
* durable adapter's contract, proved with
|
|
865
|
+
* `createProjectionCheckpointStoreContractTests` and its rollback capability.
|
|
779
866
|
*
|
|
780
867
|
* Without `maxCheckpoints`, checkpoint retention is unbounded and supported
|
|
781
868
|
* only for finite-lifetime tests and demos. A configured limit rejects a new
|
|
782
|
-
*
|
|
869
|
+
* identity before mutation; existing watermarks remain updatable and are never
|
|
783
870
|
* evicted because forgetting one would change projection correctness.
|
|
784
871
|
*
|
|
785
872
|
* Do not nest `withCheckpointLocks` calls whose key sets overlap. This
|
|
@@ -787,18 +874,27 @@ interface InMemoryProjectionCheckpointStoreOptions {
|
|
|
787
874
|
* on the key its caller still holds and therefore neither enters nor fails
|
|
788
875
|
* loudly.
|
|
789
876
|
*/
|
|
790
|
-
declare class InMemoryProjectionCheckpointStore implements ProjectionCheckpointStore<unknown
|
|
877
|
+
declare class InMemoryProjectionCheckpointStore implements ProjectionCheckpointStore<unknown>, InMemoryTransactionParticipant {
|
|
791
878
|
/** projection name -> JSON [aggregateType, aggregateId] -> receipt */
|
|
792
879
|
private readonly checkpoints;
|
|
793
880
|
/** Full checkpoint key -> tail of the process-local exclusive-access queue. */
|
|
794
881
|
private readonly lockTails;
|
|
795
882
|
private readonly maxCheckpoints;
|
|
796
883
|
private checkpointCount;
|
|
884
|
+
/** The checkpoints at the start of the open transaction. */
|
|
885
|
+
private committedCheckpoints;
|
|
797
886
|
constructor(options?: InMemoryProjectionCheckpointStoreOptions);
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
887
|
+
/**
|
|
888
|
+
* Records the state that a rollback of an `InMemoryTransactionScope`
|
|
889
|
+
* returns to: the checkpoints and their count. Until the transaction
|
|
890
|
+
* ends, `hasReached` reads these recorded checkpoints. The rollback
|
|
891
|
+
* keeps the checkpoint locks, because a caller still holds them.
|
|
892
|
+
*/
|
|
893
|
+
beginTransaction(): InMemoryTransaction;
|
|
894
|
+
withCheckpointLocks<R>(_ctx: unknown, projection: string, identities: ReadonlyArray<AggregateIdentity>, work: () => Promise<R>): Promise<R>;
|
|
895
|
+
load(_ctx: unknown, projection: string, identity: AggregateIdentity): Promise<ProjectionCheckpoint | undefined>;
|
|
896
|
+
save(_ctx: unknown, projection: string, identity: AggregateIdentity, checkpoint: ProjectionCheckpoint): Promise<void>;
|
|
897
|
+
hasReached(projection: string, identity: AggregateIdentity, position: ProjectionPosition): Promise<boolean>;
|
|
802
898
|
reset(_ctx: unknown, projection: string): Promise<void>;
|
|
803
899
|
}
|
|
804
900
|
//#endregion
|
|
@@ -1181,8 +1277,8 @@ interface ProjectionBatchResult {
|
|
|
1181
1277
|
* Because checkpoints advance only across a verified chain, a position
|
|
1182
1278
|
* at or behind the watermark is already traversed and can be skipped under
|
|
1183
1279
|
* the source's one-logical-event-per-position contract.
|
|
1184
|
-
* - **Feeds are complete per aggregate
|
|
1185
|
-
*
|
|
1280
|
+
* - **Feeds are complete per aggregate identity.** Once a feed supplies one
|
|
1281
|
+
* identity, it must supply every committed envelope in that aggregate's cursor
|
|
1186
1282
|
* chain. Do not event-type-filter a projector subscription. Irrelevant event
|
|
1187
1283
|
* types are explicit no-ops in `Projection.apply`; invoking the handler and
|
|
1188
1284
|
* checkpointing their positions preserves continuity.
|
|
@@ -1201,13 +1297,13 @@ interface ProjectionBatchResult {
|
|
|
1201
1297
|
* redeliveries.
|
|
1202
1298
|
* - **Malformed envelopes reject loudly.** A missing/empty `eventId`, a
|
|
1203
1299
|
* missing/invalid `position`, missing `source.aggregateId` /
|
|
1204
|
-
* `source.aggregateType`, or an optional event
|
|
1300
|
+
* `source.aggregateType`, or an optional event identity contradicting its
|
|
1205
1301
|
* authoritative envelope source fails the batch BEFORE anything is applied.
|
|
1206
1302
|
* The domain event remains persistence-agnostic.
|
|
1207
1303
|
* - **Competing instances serialize by checkpoint key.** The required
|
|
1208
1304
|
* {@link ProjectionCheckpointStore.withCheckpointLocks} callback covers the
|
|
1209
|
-
* complete load / apply / save critical section for every
|
|
1210
|
-
*
|
|
1305
|
+
* complete load / apply / save critical section for every aggregate of
|
|
1306
|
+
* the batch. The adapter must lock a key even when its checkpoint row does
|
|
1211
1307
|
* not exist yet; a plain row lock is insufficient at genesis. Without that
|
|
1212
1308
|
* adapter guarantee, only a hard single-projector deployment is safe.
|
|
1213
1309
|
*
|
|
@@ -1231,7 +1327,7 @@ declare class Projector<Evt extends AnyDomainEvent, TCtx = unknown> {
|
|
|
1231
1327
|
* per advanced aggregate. Rejects
|
|
1232
1328
|
* (after rollback) when a handler throws or an envelope carries no
|
|
1233
1329
|
* valid cursor; the caller's at-least-once redelivery retries the batch.
|
|
1234
|
-
* The input must be a complete, ordered feed per aggregate
|
|
1330
|
+
* The input must be a complete, ordered feed per aggregate identity; an
|
|
1235
1331
|
* event-type-filtered subscription cannot satisfy the cursor contract.
|
|
1236
1332
|
* An already-aborted signal rejects before validation or transaction setup.
|
|
1237
1333
|
* In-flight cancellation is forwarded to the transaction scope rather than
|
|
@@ -1240,19 +1336,19 @@ declare class Projector<Evt extends AnyDomainEvent, TCtx = unknown> {
|
|
|
1240
1336
|
project(events: ReadonlyArray<CommittedDomainEvent<Evt>>, options?: ProjectOptions): Promise<ProjectionBatchResult>;
|
|
1241
1337
|
/**
|
|
1242
1338
|
* The wait-for-version query: `true` when this projection has
|
|
1243
|
-
* processed the
|
|
1339
|
+
* processed the given aggregate at least up to `position`. Pass the
|
|
1244
1340
|
* position of the last event the awaited commit emitted (see
|
|
1245
1341
|
* {@link ProjectionCheckpointStore.hasReached} for why the full
|
|
1246
1342
|
* cursor, not just the version).
|
|
1247
1343
|
*/
|
|
1248
|
-
hasProcessed(
|
|
1344
|
+
hasProcessed(identity: AggregateIdentity, position: ProjectionPosition): Promise<boolean>;
|
|
1249
1345
|
/**
|
|
1250
1346
|
* Rebuild entry point: one transaction that clears this
|
|
1251
1347
|
* projection's checkpoints and, when the projection provides
|
|
1252
1348
|
* `truncate`, the read model with them. Replay the source through
|
|
1253
1349
|
* {@link Projector.project} afterwards. Stop all live consumers for this
|
|
1254
1350
|
* projection before reset and keep them stopped through catch-up replay;
|
|
1255
|
-
* rebuild is not coordinated by the per-
|
|
1351
|
+
* rebuild is not coordinated by the per-aggregate delivery locks.
|
|
1256
1352
|
*/
|
|
1257
1353
|
reset(): Promise<void>;
|
|
1258
1354
|
/**
|
|
@@ -1271,291 +1367,6 @@ declare class Projector<Evt extends AnyDomainEvent, TCtx = unknown> {
|
|
|
1271
1367
|
toOutboxSink(): OutboxSink<Evt>;
|
|
1272
1368
|
}
|
|
1273
1369
|
//#endregion
|
|
1274
|
-
//#region src/persistence/repository/identity-map.d.ts
|
|
1275
|
-
/**
|
|
1276
|
-
* A class reference used as the type key of the identity map. Keying
|
|
1277
|
-
* on the CLASS (not a name string) makes collisions impossible by
|
|
1278
|
-
* construction: `Restaurant` and `Booking` are different keys even if
|
|
1279
|
-
* someone names two aggregates identically across modules, and there
|
|
1280
|
-
* is no string-discipline to maintain.
|
|
1281
|
-
*
|
|
1282
|
-
* `Function & { prototype: TAgg }` carries this alone. The kit's aggregate
|
|
1283
|
-
* convention is a **protected constructor** plus static factories, and
|
|
1284
|
-
* TypeScript rejects assigning such a class to a construct-signature type, so
|
|
1285
|
-
* the prototype witness is what accepts them. It infers `TAgg` as well.
|
|
1286
|
-
* Measured: a construct signature beside it changes neither what the type
|
|
1287
|
-
* accepts nor what it infers, and it was the last `any` in the published
|
|
1288
|
-
* types.
|
|
1289
|
-
*/
|
|
1290
|
-
type AggregateClass<TAgg> = Function & {
|
|
1291
|
-
prototype: TAgg;
|
|
1292
|
-
};
|
|
1293
|
-
/**
|
|
1294
|
-
* Per-unit-of-work Identity Map (Fowler, PoEAA): within one operation,
|
|
1295
|
-
* one aggregate type+id maps to exactly ONE in-memory instance.
|
|
1296
|
-
*
|
|
1297
|
-
* This is the shipped implementation of the contract the
|
|
1298
|
-
* Repository guide (`docs/guide/repository.md`) places on
|
|
1299
|
-
* `AggregatePersistence` implementations: two `findById(id)` calls in the same
|
|
1300
|
-
* unit of work MUST return the same instance, because commit-token
|
|
1301
|
-
* write registration dedupes by JavaScript object identity. Two instances for
|
|
1302
|
-
* one logical aggregate can otherwise produce two tokens, two harvests,
|
|
1303
|
-
* and two post-commit lifecycle calls.
|
|
1304
|
-
*
|
|
1305
|
-
* Storage is two-level (per-type stores created lazily), so
|
|
1306
|
-
* `Restaurant:123` and `Booking:123` can never collide: the type key
|
|
1307
|
-
* is the aggregate CLASS, not the id alone and not a name string.
|
|
1308
|
-
*
|
|
1309
|
-
* Repository read-path contract:
|
|
1310
|
-
*
|
|
1311
|
-
* ```ts
|
|
1312
|
-
* async findById(id: OrderId): Promise<Order | undefined> {
|
|
1313
|
-
* const cached = this.tracking.identityMap.get(Order, id);
|
|
1314
|
-
* if (cached) return cached;
|
|
1315
|
-
* // Deleted in this unit of work = gone, even if the physical
|
|
1316
|
-
* // delete is deferred and the row is still visible in the tx.
|
|
1317
|
-
* if (this.tracking.identityMap.isDeleted(Order, id)) return undefined;
|
|
1318
|
-
*
|
|
1319
|
-
* const row = await this.loadRow(id);
|
|
1320
|
-
* if (!row) return undefined;
|
|
1321
|
-
* const order = Order.reconstitute(row.id, row.state, row.version);
|
|
1322
|
-
* return this.tracking.trackLoaded(order);
|
|
1323
|
-
* }
|
|
1324
|
-
* ```
|
|
1325
|
-
*
|
|
1326
|
-
* Deletion is final within an operation: {@link delete} removes the
|
|
1327
|
-
* entry AND records a tombstone, so a later {@link set} of the same
|
|
1328
|
-
* type+id throws `AggregateDeletedError`: a second instance of a
|
|
1329
|
-
* deleted aggregate can never sneak back into the unit of work, even
|
|
1330
|
-
* through a repository whose row delete is deferred.
|
|
1331
|
-
*
|
|
1332
|
-
* Lifetime is ONE unit of work: the `UnitOfWork` creates a fresh map
|
|
1333
|
-
* per `run()` and clears it on close. Never cache across operations;
|
|
1334
|
-
* that would silently bypass optimistic concurrency control.
|
|
1335
|
-
*/
|
|
1336
|
-
declare class IdentityMap {
|
|
1337
|
-
private readonly _stores;
|
|
1338
|
-
private readonly _deleted;
|
|
1339
|
-
private _pendingAtRegistration;
|
|
1340
|
-
/** The cached instance for type+id, or `undefined` (also after {@link delete}). */
|
|
1341
|
-
get<TAgg>(type: AggregateClass<TAgg>, id: Id<string>): TAgg | undefined;
|
|
1342
|
-
/** Whether an instance is registered for type+id (false after {@link delete}). */
|
|
1343
|
-
has<TAgg>(type: AggregateClass<TAgg>, id: Id<string>): boolean;
|
|
1344
|
-
/**
|
|
1345
|
-
* Whether type+id was {@link delete}d in this unit of work. The
|
|
1346
|
-
* read path checks this BEFORE hydrating and returns `null`, so
|
|
1347
|
-
* "deleted in this operation" reads uniformly as not-found,
|
|
1348
|
-
* regardless of whether the repository's physical delete already
|
|
1349
|
-
* removed the row or is deferred within the transaction. Without
|
|
1350
|
-
* the check, a read-only probe of a deleted aggregate would crash
|
|
1351
|
-
* in {@link set} for deferred-write repositories and return `null`
|
|
1352
|
-
* for immediate-write ones.
|
|
1353
|
-
*/
|
|
1354
|
-
isDeleted<TAgg>(type: AggregateClass<TAgg>, id: Id<string>): boolean;
|
|
1355
|
-
/**
|
|
1356
|
-
* Registers the hydrated instance for type+id.
|
|
1357
|
-
*
|
|
1358
|
-
* - Re-registering the SAME instance is a no-op (idempotent).
|
|
1359
|
-
* - Registering a DIFFERENT instance for an occupied type+id throws:
|
|
1360
|
-
* that is precisely the identity-map violation this class exists
|
|
1361
|
-
* to prevent (the repository hydrated twice instead of checking
|
|
1362
|
-
* {@link get} first), and letting it pass would double-harvest
|
|
1363
|
-
* events downstream.
|
|
1364
|
-
* - Registering a type+id that was {@link delete}d in this unit of
|
|
1365
|
-
* work throws `AggregateDeletedError`: deletion is final within
|
|
1366
|
-
* the operation.
|
|
1367
|
-
*/
|
|
1368
|
-
set<TAgg>(type: AggregateClass<TAgg>, id: Id<string>, aggregate: TAgg): void;
|
|
1369
|
-
/**
|
|
1370
|
-
* Registered instances that have recorded MORE pending events than they
|
|
1371
|
-
* carried when first registered (loaded). Used by the unit of work's
|
|
1372
|
-
* end-of-run guard: an aggregate that gained events after load but was
|
|
1373
|
-
* never enrolled would silently drop them. A read-only load, or a
|
|
1374
|
-
* reconstitution that already carried events, shows no increase and is
|
|
1375
|
-
* not reported.
|
|
1376
|
-
*/
|
|
1377
|
-
instancesWithNewPendingEvents(): unknown[];
|
|
1378
|
-
/**
|
|
1379
|
-
* Takes back a registration WITHOUT a tombstone: the entry is removed
|
|
1380
|
-
* only when the stored instance IS the given one, and a later
|
|
1381
|
-
* {@link set} of the same type+id stays legal. The Unit of Work calls
|
|
1382
|
-
* this when a registration step fails after {@link set} already ran, so
|
|
1383
|
-
* the failed instance cannot be served by `findById` as a phantom.
|
|
1384
|
-
* This is rollback, not deletion; deletion finality belongs to
|
|
1385
|
-
* {@link delete}.
|
|
1386
|
-
*/
|
|
1387
|
-
discard<TAgg>(type: AggregateClass<TAgg>, id: Id<string>, aggregate: TAgg): void;
|
|
1388
|
-
/**
|
|
1389
|
-
* Removes the entry for type+id and records a tombstone: subsequent
|
|
1390
|
-
* {@link get} / {@link has} report absence, and a subsequent
|
|
1391
|
-
* {@link set} of the same type+id throws `AggregateDeletedError`.
|
|
1392
|
-
* The Unit of Work calls this as part of `repository.remove(aggregate)`;
|
|
1393
|
-
* repository adapters receive only the read-only
|
|
1394
|
-
* identity-map view.
|
|
1395
|
-
*/
|
|
1396
|
-
delete<TAgg>(type: AggregateClass<TAgg>, id: Id<string>): void;
|
|
1397
|
-
/** Empties all stores and tombstones. Called by the unit of work on close. */
|
|
1398
|
-
clear(): void;
|
|
1399
|
-
}
|
|
1400
|
-
//#endregion
|
|
1401
|
-
//#region src/persistence/repository/persistence-model.d.ts
|
|
1402
|
-
/** Whether a baseline represents an existing row or a pending insert. */
|
|
1403
|
-
type PersistenceLifecycle = "loaded" | "new";
|
|
1404
|
-
/**
|
|
1405
|
-
* Adapter-owned projection and change derivation for one aggregate type.
|
|
1406
|
-
*
|
|
1407
|
-
* The domain model does not implement this contract. A repository adapter
|
|
1408
|
-
* chooses what it persists, how that projection is captured at load, and
|
|
1409
|
-
* whether a change set is a partial diff or a full replacement.
|
|
1410
|
-
*/
|
|
1411
|
-
interface PersistenceModel<TAggregate, TBaseline, TChangeSet> {
|
|
1412
|
-
/**
|
|
1413
|
-
* Captures the adapter's persistence projection at the current moment.
|
|
1414
|
-
* Return a detached value or an immutable value object: the Unit of Work
|
|
1415
|
-
* retains it as a baseline and cannot make an arbitrary adapter type safe.
|
|
1416
|
-
*
|
|
1417
|
-
* Capture must be deterministic for an unchanged aggregate: the Unit of
|
|
1418
|
-
* Work compares successive captures to detect mutation after write
|
|
1419
|
-
* registration. A capture that embeds ambient values (clock reads,
|
|
1420
|
-
* random ids) would make every commit look mutated. The default
|
|
1421
|
-
* comparison is the package's structural deep equality, which matches
|
|
1422
|
-
* `Set` members and `Map` keys by reference (JS `SameValueZero`
|
|
1423
|
-
* semantics): a capture that re-materializes object Set members or Map
|
|
1424
|
-
* keys on every call must supply {@link captureEquals}.
|
|
1425
|
-
*
|
|
1426
|
-
* A column that the store owns stays out of the capture, for example an
|
|
1427
|
-
* `updatedAt` that the adapter stamps; `flush` writes it. A captured store
|
|
1428
|
-
* column pushes a stale value back on the next write, or it marks every
|
|
1429
|
-
* row as changed.
|
|
1430
|
-
*/
|
|
1431
|
-
capture(aggregate: TAggregate): TBaseline;
|
|
1432
|
-
/**
|
|
1433
|
-
* Adapter-owned equality for two captures of the persistence projection.
|
|
1434
|
-
* Optional: the default is the package's structural deep equality (Set
|
|
1435
|
-
* members and Map keys by reference). Supply it when the capture shape
|
|
1436
|
-
* needs domain-specific comparison, for example rebuilt value-object Set
|
|
1437
|
-
* members compared by value.
|
|
1438
|
-
*/
|
|
1439
|
-
readonly captureEquals?: (a: TBaseline, b: TBaseline) => boolean;
|
|
1440
|
-
/**
|
|
1441
|
-
* Derives the adapter's write payload from its own baseline.
|
|
1442
|
-
*
|
|
1443
|
-
* `baseline` is absent for a new aggregate. `lifecycle` disambiguates that
|
|
1444
|
-
* case from an adapter whose loaded baseline type itself admits `undefined`.
|
|
1445
|
-
* The returned payload must not share mutable references with the aggregate;
|
|
1446
|
-
* it is the exact value later handed to `flush`.
|
|
1447
|
-
*/
|
|
1448
|
-
changes(baseline: TBaseline | undefined, aggregate: TAggregate, lifecycle: PersistenceLifecycle): TChangeSet;
|
|
1449
|
-
/** Tells orchestration whether the derived state write is empty. */
|
|
1450
|
-
isEmpty(changes: TChangeSet): boolean;
|
|
1451
|
-
}
|
|
1452
|
-
declare const persistenceBaselineBrand: unique symbol;
|
|
1453
|
-
/**
|
|
1454
|
-
* Opaque, typed receipt for an adapter-owned persistence baseline.
|
|
1455
|
-
*
|
|
1456
|
-
* It intentionally exposes no data. The Unit of Work may retain the token and
|
|
1457
|
-
* ask the owning adapter capability to derive changes, but cannot branch on or
|
|
1458
|
-
* couple itself to the baseline's shape.
|
|
1459
|
-
*/
|
|
1460
|
-
interface PersistenceBaseline<TAggregate, TChangeSet> {
|
|
1461
|
-
readonly [persistenceBaselineBrand]: (aggregate: TAggregate) => TChangeSet;
|
|
1462
|
-
}
|
|
1463
|
-
/** A derived adapter change set plus its adapter-defined emptiness result. */
|
|
1464
|
-
interface PersistenceChanges<TChangeSet> {
|
|
1465
|
-
readonly value: TChangeSet;
|
|
1466
|
-
readonly empty: boolean;
|
|
1467
|
-
}
|
|
1468
|
-
/** Captures a baseline for an aggregate restored by a repository adapter. */
|
|
1469
|
-
declare function capturePersistenceBaseline<TAggregate, TBaseline, TChangeSet>(model: PersistenceModel<TAggregate, TBaseline, TChangeSet>, aggregate: TAggregate): PersistenceBaseline<TAggregate, TChangeSet>;
|
|
1470
|
-
/** Creates the explicit no-row baseline for a newly added aggregate. */
|
|
1471
|
-
declare function insertPersistenceBaseline<TAggregate, TBaseline, TChangeSet>(model: PersistenceModel<TAggregate, TBaseline, TChangeSet>): PersistenceBaseline<TAggregate, TChangeSet>;
|
|
1472
|
-
/**
|
|
1473
|
-
* Captures the aggregate's current adapter projection using the capability
|
|
1474
|
-
* carried by an existing baseline. Used to seal persistence-last registration.
|
|
1475
|
-
*/
|
|
1476
|
-
declare function recapturePersistenceBaseline<TAggregate, TChangeSet>(baseline: PersistenceBaseline<TAggregate, TChangeSet>, aggregate: TAggregate): PersistenceBaseline<TAggregate, TChangeSet>;
|
|
1477
|
-
/**
|
|
1478
|
-
* Recaptures the adapter projection and reports whether it drifted from the
|
|
1479
|
-
* baseline's stored capture, using the model's `captureEquals` when supplied
|
|
1480
|
-
* and structural deep equality otherwise.
|
|
1481
|
-
*
|
|
1482
|
-
* This, not `changes()`/`isEmpty()`, is the mutation detector: the
|
|
1483
|
-
* `PersistenceModel` contract explicitly permits a full-replacement change
|
|
1484
|
-
* set whose `isEmpty` is never true, so a non-empty change set proves
|
|
1485
|
-
* nothing about mutation. Comparing capture to capture asks the honest
|
|
1486
|
-
* question independent of the model's diffing strategy. A `"new"` lifecycle
|
|
1487
|
-
* baseline has no stored capture and never reports drift.
|
|
1488
|
-
*/
|
|
1489
|
-
declare function persistenceProjectionDrifted<TAggregate, TChangeSet>(baseline: PersistenceBaseline<TAggregate, TChangeSet>, aggregate: TAggregate): boolean;
|
|
1490
|
-
/** Derives a typed adapter change set without exposing the stored baseline. */
|
|
1491
|
-
declare function derivePersistenceChanges<TAggregate, TChangeSet>(baseline: PersistenceBaseline<TAggregate, TChangeSet>, aggregate: TAggregate): PersistenceChanges<TChangeSet>;
|
|
1492
|
-
//#endregion
|
|
1493
|
-
//#region src/application/unit-of-work/persistence-contract.d.ts
|
|
1494
|
-
/** The explicit persistence intent registered for one tracked aggregate. */
|
|
1495
|
-
type AggregateWriteIntent = "add" | "update" | "remove";
|
|
1496
|
-
/** Read-only Identity Map operations available to repository adapters. */
|
|
1497
|
-
type UnitOfWorkIdentityMap = Pick<IdentityMap, "get" | "has" | "isDeleted">;
|
|
1498
|
-
/**
|
|
1499
|
-
* Repository-specific tracking capability handed only to its adapter.
|
|
1500
|
-
*
|
|
1501
|
-
* Read paths call {@link RepositoryTracking.trackLoaded} before returning a
|
|
1502
|
-
* restored aggregate.
|
|
1503
|
-
* Write methods exposed to application code are replaced by Unit-of-Work-owned
|
|
1504
|
-
* `add`, `update`, and `remove` registrations, so an adapter implementation of
|
|
1505
|
-
* those methods cannot perform durable I/O early or skip event harvesting.
|
|
1506
|
-
*
|
|
1507
|
-
* Contract for repository implementations:
|
|
1508
|
-
* - `findById(id)` checks `identityMap.get` BEFORE hydrating, treats
|
|
1509
|
-
* `identityMap.isDeleted` as not-found (`undefined`), and returns
|
|
1510
|
-
* `tracking.trackLoaded(aggregate)` after hydration. This captures the
|
|
1511
|
-
* expected version before application code can mutate the instance.
|
|
1512
|
-
* - Adapter objects do not need lifecycle methods; the facade installs the
|
|
1513
|
-
* Unit-of-Work-owned `add`, `update` unless the definition is append-only,
|
|
1514
|
-
* and `remove` with `physicalRemoval`. If a concrete adapter has a method
|
|
1515
|
-
* named `add`, `update`, or `remove` anyway, the facade masks it, installed
|
|
1516
|
-
* or not.
|
|
1517
|
-
* - Other repository methods are reads. A custom method that performs a write
|
|
1518
|
-
* would bypass the Unit of Work and violates the adapter contract.
|
|
1519
|
-
*/
|
|
1520
|
-
interface RepositoryTracking<TAggregate extends Aggregate<Id<string>, AnyDomainEvent>> {
|
|
1521
|
-
/**
|
|
1522
|
-
* Registers an aggregate restored by a repository before returning it to
|
|
1523
|
-
* application code. The Unit of Work identity-maps the instance and captures
|
|
1524
|
-
* its current version as the optimistic-concurrency expectation.
|
|
1525
|
-
*/
|
|
1526
|
-
trackLoaded(aggregate: TAggregate): TAggregate;
|
|
1527
|
-
/**
|
|
1528
|
-
* Read-only view of the per-operation Identity Map (Fowler): one aggregate type+id,
|
|
1529
|
-
* one in-memory instance. Created fresh per `run()`, cleared on
|
|
1530
|
-
* close; accessing it after close throws
|
|
1531
|
-
* {@link TransactionClosedError}.
|
|
1532
|
-
*/
|
|
1533
|
-
readonly identityMap: UnitOfWorkIdentityMap;
|
|
1534
|
-
}
|
|
1535
|
-
/**
|
|
1536
|
-
* Immutable adapter input for one registered aggregate write.
|
|
1537
|
-
*
|
|
1538
|
-
* `expectedVersion` is captured when a loaded aggregate joins the Unit of
|
|
1539
|
-
* Work and is absent for `add`. `version`, `changes`, and `events` describe
|
|
1540
|
-
* the exact moment at which the application registered its write intent.
|
|
1541
|
-
* Adapters must use the expected/current version pair for their OCC predicate
|
|
1542
|
-
* and must not read mutable write state back from an aggregate reference.
|
|
1543
|
-
*
|
|
1544
|
-
* The predicate itself is adapter code. The compare-and-set must run in the
|
|
1545
|
-
* store's own write statement. The kit does not know the store, so it cannot
|
|
1546
|
-
* write that statement. The kit owns the version pair and
|
|
1547
|
-
* {@link ConcurrencyConflictError}; the repository contract suite proves the
|
|
1548
|
-
* predicate.
|
|
1549
|
-
*/
|
|
1550
|
-
interface AggregatePersistenceWrite<TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TChangeSet> {
|
|
1551
|
-
readonly intent: AggregateWriteIntent;
|
|
1552
|
-
readonly aggregateId: TAggregate["id"];
|
|
1553
|
-
readonly expectedVersion: Version | undefined;
|
|
1554
|
-
readonly version: Version;
|
|
1555
|
-
readonly changes: PersistenceChanges<TChangeSet>;
|
|
1556
|
-
readonly events: TAggregate["pendingEvents"];
|
|
1557
|
-
}
|
|
1558
|
-
//#endregion
|
|
1559
1370
|
//#region src/application/unit-of-work/errors.d.ts
|
|
1560
1371
|
/**
|
|
1561
1372
|
* Thrown when `UnitOfWork.run()` is called while the same instance is
|
|
@@ -1579,10 +1390,13 @@ declare class NestedUnitOfWorkError extends KitWiringError<"NESTED_UNIT_OF_WORK"
|
|
|
1579
1390
|
constructor();
|
|
1580
1391
|
}
|
|
1581
1392
|
/**
|
|
1582
|
-
* Thrown when the unit-of-work context is used after
|
|
1583
|
-
*
|
|
1584
|
-
* `tracking.trackLoaded`, or using a repository facade after the
|
|
1585
|
-
*
|
|
1393
|
+
* Thrown when the unit-of-work context is used after the unit of work closed
|
|
1394
|
+
* it: reading `context.repositories`, calling an adapter-held
|
|
1395
|
+
* `tracking.trackLoaded`, or using a repository facade after the flush of its
|
|
1396
|
+
* attempt, while the transaction commits, or after it committed or rolled
|
|
1397
|
+
* back. An `add`, `update`, or `remove` between the start of the flush and the
|
|
1398
|
+
* last check before the commit fails the attempt with `AggregateTrackingError`
|
|
1399
|
+
* instead.
|
|
1586
1400
|
*
|
|
1587
1401
|
* Use-after-close is a programming bug (typically a leaked context
|
|
1588
1402
|
* reference or a fire-and-forget promise outliving the callback), so
|
|
@@ -1599,11 +1413,27 @@ declare class TransactionClosedError extends KitWiringError<"TRANSACTION_CLOSED"
|
|
|
1599
1413
|
readonly operation: string;
|
|
1600
1414
|
constructor(operation: string);
|
|
1601
1415
|
}
|
|
1416
|
+
/** Why a repository factory result cannot become a facade. */
|
|
1417
|
+
type InvalidRepositoryAdapterReason = "not_an_object" | "defines_lifecycle_operation";
|
|
1418
|
+
/** Constructor options for {@link InvalidRepositoryAdapterError}. */
|
|
1419
|
+
type InvalidRepositoryAdapterErrorOptions = {
|
|
1420
|
+
readonly repository: string;
|
|
1421
|
+
readonly reason: "not_an_object";
|
|
1422
|
+
/** The `typeof` of the value that the factory returned, or `null`. */
|
|
1423
|
+
readonly receivedType: string;
|
|
1424
|
+
} | {
|
|
1425
|
+
readonly repository: string;
|
|
1426
|
+
readonly reason: "defines_lifecycle_operation";
|
|
1427
|
+
/** The lifecycle member that the adapter defines. */
|
|
1428
|
+
readonly operation: AggregateWriteIntent;
|
|
1429
|
+
};
|
|
1602
1430
|
/** A repository factory returned a value that cannot be wrapped as a facade. */
|
|
1603
1431
|
declare class InvalidRepositoryAdapterError extends KitWiringError<"INVALID_REPOSITORY_ADAPTER"> {
|
|
1604
1432
|
readonly repository: string;
|
|
1605
|
-
readonly
|
|
1606
|
-
|
|
1433
|
+
readonly reason: InvalidRepositoryAdapterReason;
|
|
1434
|
+
readonly receivedType: string | undefined;
|
|
1435
|
+
readonly operation: AggregateWriteIntent | undefined;
|
|
1436
|
+
constructor(options: InvalidRepositoryAdapterErrorOptions);
|
|
1607
1437
|
}
|
|
1608
1438
|
/** A Unit of Work received repository wiring that bypassed {@link defineRepository}. */
|
|
1609
1439
|
declare class InvalidRepositoryDefinitionError extends KitWiringError<"INVALID_REPOSITORY_DEFINITION"> {
|
|
@@ -1612,34 +1442,38 @@ declare class InvalidRepositoryDefinitionError extends KitWiringError<"INVALID_R
|
|
|
1612
1442
|
}
|
|
1613
1443
|
/** A repository's persistence-error policy threw or returned a non-kit error. */
|
|
1614
1444
|
declare class RepositoryErrorMappingFailedError extends KitWiringError<"REPOSITORY_ERROR_MAPPING_FAILED"> {
|
|
1615
|
-
readonly
|
|
1445
|
+
readonly identity: AggregateIdentity;
|
|
1616
1446
|
readonly intent: AggregateWriteIntent;
|
|
1617
1447
|
readonly mapperCause: unknown;
|
|
1618
|
-
constructor(options:
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1448
|
+
constructor(options: RepositoryErrorMappingFailedErrorOptions);
|
|
1449
|
+
}
|
|
1450
|
+
/** Constructor options for {@link RepositoryErrorMappingFailedError}. */
|
|
1451
|
+
interface RepositoryErrorMappingFailedErrorOptions {
|
|
1452
|
+
/** The aggregate the error names. */
|
|
1453
|
+
readonly identity: AggregateIdentity;
|
|
1454
|
+
readonly intent: AggregateWriteIntent;
|
|
1455
|
+
/** The store failure the mapper was translating. */
|
|
1456
|
+
readonly persistenceError: unknown;
|
|
1457
|
+
/** The failure of the mapper itself. */
|
|
1458
|
+
readonly mapperError: unknown;
|
|
1624
1459
|
}
|
|
1625
1460
|
/** What is wrong with the store statements that build a flush. */
|
|
1626
|
-
type FlushStatementReason = "statement_absent" | "no_row_count" | "no_expected_version" | "duplicate_check_failed";
|
|
1461
|
+
type FlushStatementReason = "statement_absent" | "no_row_count" | "no_expected_version" | "no_version" | "duplicate_check_failed";
|
|
1627
1462
|
/**
|
|
1628
1463
|
* A deterministic defect in the store statements that build a flush.
|
|
1629
1464
|
*
|
|
1630
1465
|
* This is a wiring error, not a persistence failure: the statements cannot
|
|
1631
1466
|
* run the write the Unit of Work registered, and a retry repeats the same
|
|
1632
|
-
* outcome.
|
|
1633
|
-
* repository's `mapError
|
|
1634
|
-
*
|
|
1635
|
-
* error, and the reason stays in the cause chain.
|
|
1467
|
+
* outcome. The commit phase hands it to the caller unchanged, never to the
|
|
1468
|
+
* repository's `mapError`, because a mapper returns an `InfrastructureError`
|
|
1469
|
+
* and would relabel the defect as a store failure.
|
|
1636
1470
|
*/
|
|
1637
1471
|
declare class InvalidFlushStatementError extends KitWiringError<"INVALID_FLUSH_STATEMENT"> {
|
|
1638
|
-
readonly
|
|
1639
|
-
|
|
1640
|
-
readonly intent: AggregateWriteIntent;
|
|
1472
|
+
readonly identity: InvalidFlushStatementErrorOptions["identity"];
|
|
1473
|
+
/** The write, or `null` when the code that found the defect does not know it. */
|
|
1474
|
+
readonly intent: AggregateWriteIntent | null;
|
|
1641
1475
|
readonly reason: FlushStatementReason;
|
|
1642
|
-
/**
|
|
1476
|
+
/** The value that the flush received in place of a valid one. */
|
|
1643
1477
|
readonly received: string | undefined;
|
|
1644
1478
|
/** The failure of `isDuplicate`, when the classifier itself threw. */
|
|
1645
1479
|
readonly classifierCause: unknown;
|
|
@@ -1647,9 +1481,9 @@ declare class InvalidFlushStatementError extends KitWiringError<"INVALID_FLUSH_S
|
|
|
1647
1481
|
}
|
|
1648
1482
|
/** The fields that describe one defect of the flush statements. */
|
|
1649
1483
|
interface InvalidFlushStatementErrorOptions {
|
|
1650
|
-
|
|
1651
|
-
readonly
|
|
1652
|
-
readonly intent
|
|
1484
|
+
/** The aggregate the error names. */
|
|
1485
|
+
readonly identity: AggregateIdentity;
|
|
1486
|
+
readonly intent?: AggregateWriteIntent | null;
|
|
1653
1487
|
readonly reason: FlushStatementReason;
|
|
1654
1488
|
readonly received?: string;
|
|
1655
1489
|
/** The store failure that the flush was handling, kept for diagnosis. */
|
|
@@ -1657,7 +1491,7 @@ interface InvalidFlushStatementErrorOptions {
|
|
|
1657
1491
|
readonly classifierCause?: unknown;
|
|
1658
1492
|
}
|
|
1659
1493
|
/** Why an aggregate lifecycle registration was rejected. */
|
|
1660
|
-
type AggregateTrackingReason = "not_loaded" | "loaded_as_new" | "different_repository" | "conflicting_intent" | "mutated_after_registration";
|
|
1494
|
+
type AggregateTrackingReason = "not_loaded" | "loaded_as_new" | "different_repository" | "conflicting_intent" | "mutated_after_registration" | "registered_during_flush" | "identity_already_tracked";
|
|
1661
1495
|
/**
|
|
1662
1496
|
* A deterministic violation of the Unit of Work's aggregate lifecycle.
|
|
1663
1497
|
*
|
|
@@ -1666,13 +1500,23 @@ type AggregateTrackingReason = "not_loaded" | "loaded_as_new" | "different_repos
|
|
|
1666
1500
|
* cannot execute truthfully. Retrying the same callback cannot repair it.
|
|
1667
1501
|
*/
|
|
1668
1502
|
declare class AggregateTrackingError extends KitWiringError<"AGGREGATE_TRACKING"> {
|
|
1669
|
-
readonly
|
|
1503
|
+
readonly identity: AggregateIdentity;
|
|
1670
1504
|
readonly operation: AggregateWriteIntent | "load" | "commit";
|
|
1671
1505
|
readonly reason: AggregateTrackingReason;
|
|
1672
|
-
readonly registeredIntent
|
|
1673
|
-
constructor(
|
|
1674
|
-
|
|
1675
|
-
|
|
1506
|
+
readonly registeredIntent: AggregateWriteIntent | undefined;
|
|
1507
|
+
constructor(options: AggregateTrackingErrorOptions);
|
|
1508
|
+
}
|
|
1509
|
+
/** Constructor options for {@link AggregateTrackingError}. */
|
|
1510
|
+
interface AggregateTrackingErrorOptions {
|
|
1511
|
+
/** The aggregate the error names. */
|
|
1512
|
+
readonly identity: AggregateIdentity;
|
|
1513
|
+
/** The registration or phase that failed. */
|
|
1514
|
+
readonly operation: AggregateWriteIntent | "load" | "commit";
|
|
1515
|
+
readonly reason: AggregateTrackingReason;
|
|
1516
|
+
/** The intent registered before, for the reasons that name one. */
|
|
1517
|
+
readonly registeredIntent?: AggregateWriteIntent;
|
|
1518
|
+
/** Whether the repository of the aggregate is append-only. */
|
|
1519
|
+
readonly appendOnly?: boolean;
|
|
1676
1520
|
}
|
|
1677
1521
|
/**
|
|
1678
1522
|
* The unit of work failed AFTER the work callback completed
|
|
@@ -1698,17 +1542,21 @@ declare class CommitError extends InfrastructureError<"COMMIT_FAILED"> {
|
|
|
1698
1542
|
constructor(cause: unknown);
|
|
1699
1543
|
}
|
|
1700
1544
|
/**
|
|
1701
|
-
*
|
|
1702
|
-
*
|
|
1703
|
-
*
|
|
1704
|
-
*
|
|
1705
|
-
*
|
|
1706
|
-
*
|
|
1707
|
-
*
|
|
1708
|
-
*
|
|
1709
|
-
*
|
|
1710
|
-
*
|
|
1711
|
-
*
|
|
1545
|
+
* A step inside the transaction threw, and the transaction scope rejected
|
|
1546
|
+
* with a different error that does not wrap that failure in its cause chain.
|
|
1547
|
+
* This is the strongest available signal that the rollback itself failed.
|
|
1548
|
+
* The step is the work callback, or a step after it and before the commit,
|
|
1549
|
+
* for example the outbox write. The failure inside the transaction is the
|
|
1550
|
+
* `cause`, so cause-chain helpers (`someChainRetryable`, `findInCauseChain`)
|
|
1551
|
+
* still see a wrapped `ConcurrencyConflictError` & co. The scope's error is
|
|
1552
|
+
* in {@link rollbackCause}. A wiring error as that failure is the cause too,
|
|
1553
|
+
* so both facts stay visible.
|
|
1554
|
+
*
|
|
1555
|
+
* A scope that rethrows the failure (Drizzle and Prisma do) never produces
|
|
1556
|
+
* this. A scope that wraps the failure is detected through the cause chain.
|
|
1557
|
+
* A wrapped failure of the work passes through unchanged. A wrapped failure
|
|
1558
|
+
* after the work becomes a `CommitError`, or passes through when it is a
|
|
1559
|
+
* wiring error.
|
|
1712
1560
|
*/
|
|
1713
1561
|
declare class RollbackError extends InfrastructureError<"ROLLBACK_FAILED"> {
|
|
1714
1562
|
readonly rollbackCause: unknown;
|
|
@@ -1856,20 +1704,49 @@ type Then<TChecked, TNext> = unknown extends TChecked ? TNext : TChecked;
|
|
|
1856
1704
|
type IsUnion<T, TEach = T> = T extends unknown ? [TEach] extends [T] ? false : true : never;
|
|
1857
1705
|
/** @inline */
|
|
1858
1706
|
type PortShapeConstraint<TRepositoryPort> = [Extract<TRepositoryPort, CallableValue>] extends [never] ? true extends IsUnion<TRepositoryPort> ? RepositoryPortViolation<"the port must be one object type, not a union"> : unknown : RepositoryPortViolation<"the port must be an object type, not a function">;
|
|
1707
|
+
/** @inline */
|
|
1708
|
+
type InstalledRegistration<TAggregate extends Aggregate<Id<string>, AnyDomainEvent>> = AggregateWriteRegistration<TAggregate> & PhysicalRemovalRegistration<TAggregate>;
|
|
1709
|
+
/**
|
|
1710
|
+
* Checks a lifecycle member that the port declares: it is required, it
|
|
1711
|
+
* accepts the definition's aggregate, and it returns what the installed
|
|
1712
|
+
* registration returns. An optional member is the trap of a port that
|
|
1713
|
+
* extends a type with `update?` or `remove?`, so it gets its own message.
|
|
1714
|
+
* The return check exists because TypeScript lets a member that returns a
|
|
1715
|
+
* promise or `this` stand in for one that returns void.
|
|
1716
|
+
* @inline
|
|
1717
|
+
*/
|
|
1718
|
+
type MemberAcceptsAggregate<TRepositoryPort, TMember extends "add" | "update" | "remove", TAggregate extends Aggregate<Id<string>, AnyDomainEvent>> = undefined extends TRepositoryPort[TMember & keyof TRepositoryPort] ? RepositoryPortViolation<`the port's ${TMember} must not be optional`> : [TRepositoryPort] extends [Pick<InstalledRegistration<TAggregate>, TMember>] ? ReturnsWhatTheRegistrationReturns<ReturnType<Extract<TRepositoryPort[TMember & keyof TRepositoryPort], CallableValue>>, ReturnType<InstalledRegistration<TAggregate>[TMember]>> extends true ? unknown : RepositoryPortViolation<`the port's ${TMember} must return void`> : RepositoryPortViolation<`the port's ${TMember} must accept the definition's aggregate`>;
|
|
1719
|
+
/**
|
|
1720
|
+
* An `any` result would let a caller use a value that the installed
|
|
1721
|
+
* registration never returns, so it does not count as a match.
|
|
1722
|
+
* @inline
|
|
1723
|
+
*/
|
|
1724
|
+
type ReturnsWhatTheRegistrationReturns<TDeclared, TInstalled> = 0 extends 1 & TDeclared ? false : [TDeclared] extends [TInstalled] ? true : false;
|
|
1859
1725
|
/**
|
|
1860
|
-
*
|
|
1861
|
-
*
|
|
1862
|
-
*
|
|
1863
|
-
*
|
|
1726
|
+
* What an adapter type may say about `add`, `update`, and `remove`: nothing.
|
|
1727
|
+
* The Unit of Work installs them on the facade, and a raw adapter that can
|
|
1728
|
+
* write would bypass it wherever it leaves the facade. As a bound on the
|
|
1729
|
+
* adapter type, the rule also holds for a generic adapter and for each
|
|
1730
|
+
* member of a union.
|
|
1864
1731
|
* @inline
|
|
1865
1732
|
*/
|
|
1866
|
-
type
|
|
1733
|
+
type LifecycleFreeAdapter = {
|
|
1734
|
+
readonly add?: RepositoryPortViolation<"the adapter must not define add; the unit of work installs it">;
|
|
1735
|
+
readonly update?: RepositoryPortViolation<"the adapter must not define update; the unit of work installs it">;
|
|
1736
|
+
readonly remove?: RepositoryPortViolation<"the adapter must not define remove; the unit of work installs it">;
|
|
1737
|
+
};
|
|
1738
|
+
/**
|
|
1739
|
+
* The keys that a port declares by name. A string index signature makes every
|
|
1740
|
+
* name a key, which would count an undeclared `update` or `remove` as present.
|
|
1741
|
+
* @inline
|
|
1742
|
+
*/
|
|
1743
|
+
type DeclaredKeys<T> = keyof { [TKey in keyof T as string extends TKey ? never : number extends TKey ? never : symbol extends TKey ? never : TKey]: T[TKey]; };
|
|
1867
1744
|
/** @inline */
|
|
1868
|
-
type AddConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>> = "add" extends
|
|
1745
|
+
type AddConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>> = "add" extends DeclaredKeys<TRepositoryPort> ? MemberAcceptsAggregate<TRepositoryPort, "add", TAggregate> : RepositoryPortViolation<"the port must declare add(aggregate): void">;
|
|
1869
1746
|
/** @inline */
|
|
1870
|
-
type UpdateConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TAppendOnly extends boolean> = "update" extends
|
|
1747
|
+
type UpdateConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TAppendOnly extends boolean> = "update" extends DeclaredKeys<TRepositoryPort> ? boolean extends TAppendOnly ? RepositoryPortViolation<"the port declares update, so the definition must not set appendOnly"> : [TAppendOnly] extends [true] ? RepositoryPortViolation<"appendOnly is true, so the port must not declare update"> : MemberAcceptsAggregate<TRepositoryPort, "update", TAggregate> : [TAppendOnly] extends [true] ? unknown : RepositoryPortViolation<"the port declares no update, so the definition must set appendOnly: true">;
|
|
1871
1748
|
/** @inline */
|
|
1872
|
-
type RemovalConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TRemoval extends boolean> = "remove" extends
|
|
1749
|
+
type RemovalConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TRemoval extends boolean> = "remove" extends DeclaredKeys<TRepositoryPort> ? [TRemoval] extends [true] ? MemberAcceptsAggregate<TRepositoryPort, "remove", TAggregate> : RepositoryPortViolation<"the port declares remove, so the definition must set physicalRemoval: true"> : [TRemoval] extends [true] ? RepositoryPortViolation<"physicalRemoval is true, so the port must declare remove(aggregate): void"> : unknown;
|
|
1873
1750
|
/**
|
|
1874
1751
|
* Checks the port against every constraint of {@link defineRepository}, one
|
|
1875
1752
|
* at a time, so the report names the first violated constraint. Resolves to
|
|
@@ -1881,7 +1758,7 @@ type RemovalConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>,
|
|
|
1881
1758
|
*/
|
|
1882
1759
|
type RepositoryPortConstraint<TRepositoryPort, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TRemoval extends boolean, TAppendOnly extends boolean> = unknown extends TRepositoryPort ? unknown : Then<PortShapeConstraint<TRepositoryPort>, Then<AddConstraint<TRepositoryPort, TAggregate>, Then<UpdateConstraint<TRepositoryPort, TAggregate, TAppendOnly>, RemovalConstraint<TRepositoryPort, TAggregate, TRemoval>>>>;
|
|
1883
1760
|
/** @inline */
|
|
1884
|
-
type RepositoryDefinitionBuilder<TRepositoryPort extends object> = <TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TCreate extends (transaction: never, tracking: RepositoryTracking<TAggregate>) => Omit<TRepositoryPort, "add" | "update" | "remove"
|
|
1761
|
+
type RepositoryDefinitionBuilder<TRepositoryPort extends object> = <TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TCreate extends (transaction: never, tracking: RepositoryTracking<TAggregate>) => Omit<TRepositoryPort, "add" | "update" | "remove"> & LifecycleFreeAdapter, TBaseline, TChangeSet, TRemoval extends boolean = false, TAppendOnly extends boolean = false>(definition: RepositoryDefinitionOptions<Parameters<TCreate>[0], TRepositoryPort, TAggregate, TBaseline, TChangeSet, TRemoval, TAppendOnly> & {
|
|
1885
1762
|
readonly create: TCreate;
|
|
1886
1763
|
} & RepositoryPortConstraint<TRepositoryPort, TAggregate, TRemoval, TAppendOnly>) => RepositoryDefinition<Parameters<TCreate>[0], TRepositoryPort, TAggregate, TBaseline, TChangeSet, TRemoval, TAppendOnly>;
|
|
1887
1764
|
/**
|
|
@@ -1891,7 +1768,8 @@ type RepositoryDefinitionBuilder<TRepositoryPort extends object> = <TAggregate e
|
|
|
1891
1768
|
* aggregate, persistence, event, and lifecycle types from the adapter wiring.
|
|
1892
1769
|
* The port must declare `add` for the aggregate. It declares `update` unless
|
|
1893
1770
|
* the definition sets `appendOnly: true`. If it declares `remove`, the
|
|
1894
|
-
* definition must set `physicalRemoval: true`.
|
|
1771
|
+
* definition must set `physicalRemoval: true`. The adapter that `create`
|
|
1772
|
+
* returns does not define `add`, `update`, or `remove`. A violated constraint fails
|
|
1895
1773
|
* the call with a compiler error that names the constraint. The adapter
|
|
1896
1774
|
* created by the definition implements only the remaining methods because
|
|
1897
1775
|
* lifecycle writes are installed by the Unit of Work.
|
|
@@ -2062,8 +1940,6 @@ type VersionedWrite<TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TC
|
|
|
2062
1940
|
* A statements object that changes later has no effect.
|
|
2063
1941
|
*/
|
|
2064
1942
|
type VersionedFlushStatements<TCtx, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TChangeSet> = {
|
|
2065
|
-
/** The aggregate type that the raised errors name. */
|
|
2066
|
-
readonly aggregateType: string;
|
|
2067
1943
|
/**
|
|
2068
1944
|
* Inserts the rows of a new aggregate and stamps `write.version`. The
|
|
2069
1945
|
* store's unique constraint on the aggregate id rejects a second insert.
|
|
@@ -2120,6 +1996,31 @@ type VersionedFlushStatements<TCtx, TAggregate extends Aggregate<Id<string>, Any
|
|
|
2120
1996
|
* `currentVersion` fail here, when the flush is built.
|
|
2121
1997
|
*/
|
|
2122
1998
|
declare function versionedFlush<TCtx, TAggregate extends Aggregate<Id<string>, AnyDomainEvent>, TChangeSet>(statements: VersionedFlushStatements<TCtx, TAggregate, TChangeSet>): (transaction: TCtx, write: AggregatePersistenceWrite<TAggregate, TChangeSet>) => Promise<void>;
|
|
1999
|
+
/** Options of {@link classifyConcurrencyConflict}. */
|
|
2000
|
+
interface ClassifyConcurrencyConflictOptions<TCtx, TAggregateId extends string> {
|
|
2001
|
+
/** The aggregate of the write whose compare-and-set matched no row. */
|
|
2002
|
+
readonly identity: AggregateIdentity<TAggregateId>;
|
|
2003
|
+
/** The version that the compare-and-set predicate used. */
|
|
2004
|
+
readonly expectedVersion: number;
|
|
2005
|
+
readonly transaction: TCtx;
|
|
2006
|
+
/**
|
|
2007
|
+
* Reads the version that the store holds now, or `undefined` when the
|
|
2008
|
+
* aggregate no longer exists. It is the same statement as the
|
|
2009
|
+
* `currentVersion` of {@link VersionedFlushStatements}.
|
|
2010
|
+
*/
|
|
2011
|
+
readonly currentVersion: (transaction: TCtx, aggregateId: TAggregateId) => number | undefined | Promise<number | undefined>;
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Builds the conflict of a compare-and-set that matched no row. It reads the
|
|
2015
|
+
* stored version and names the reason of the conflict. The zero row count
|
|
2016
|
+
* already proves the conflict, so the read is diagnostic: a read that fails
|
|
2017
|
+
* becomes `version_unknown`, with the failure as the cause.
|
|
2018
|
+
*
|
|
2019
|
+
* A version read that returns neither a stored version nor `undefined`, and
|
|
2020
|
+
* an expected version that is no version, are defects of the statements. They
|
|
2021
|
+
* throw {@link InvalidFlushStatementError}.
|
|
2022
|
+
*/
|
|
2023
|
+
declare function classifyConcurrencyConflict<TCtx, TAggregateId extends string>(options: ClassifyConcurrencyConflictOptions<TCtx, TAggregateId>): Promise<ConcurrencyConflictError>;
|
|
2123
2024
|
//#endregion
|
|
2124
2025
|
//#region src/domain/entity/entity.d.ts
|
|
2125
2026
|
/** A pure invariant check that throws when a candidate state is invalid. */
|
|
@@ -2516,6 +2417,7 @@ interface AggregateConfig<TState = unknown> extends EntityConfig<TState> {
|
|
|
2516
2417
|
* (emitting any event becomes a compile error).
|
|
2517
2418
|
*/
|
|
2518
2419
|
declare abstract class BaseAggregate<TState, TId extends Id<string>, TEvent extends AnyDomainEvent = never> extends Entity<TState, TId> implements Aggregate<TId, TEvent> {
|
|
2420
|
+
#private;
|
|
2519
2421
|
/**
|
|
2520
2422
|
* The aggregate's domain type as a string, used to populate
|
|
2521
2423
|
* `aggregateType` on events created via {@link createEvent}.
|
|
@@ -2537,6 +2439,12 @@ declare abstract class BaseAggregate<TState, TId extends Id<string>, TEvent exte
|
|
|
2537
2439
|
* subclass renaming).
|
|
2538
2440
|
*/
|
|
2539
2441
|
protected abstract readonly aggregateType: string;
|
|
2442
|
+
/**
|
|
2443
|
+
* The full identity of the aggregate: its declared `aggregateType` and
|
|
2444
|
+
* its `id`, as one frozen value. The id alone is unique only within the
|
|
2445
|
+
* type, so this value names the aggregate unambiguously.
|
|
2446
|
+
*/
|
|
2447
|
+
get aggregateIdentity(): AggregateIdentity<TId>;
|
|
2540
2448
|
private _version;
|
|
2541
2449
|
/**
|
|
2542
2450
|
* Version the persistence layer last confirmed for this instance:
|
|
@@ -2630,8 +2538,8 @@ declare abstract class BaseAggregate<TState, TId extends Id<string>, TEvent exte
|
|
|
2630
2538
|
/**
|
|
2631
2539
|
* Appends a domain event to the pending list. The event must be minted
|
|
2632
2540
|
* by a kit constructor; a missing `aggregateId` or `aggregateType` is
|
|
2633
|
-
* stamped from this aggregate, and an
|
|
2634
|
-
* aggregate throws {@link
|
|
2541
|
+
* stamped from this aggregate, and an aggregate identity that names another
|
|
2542
|
+
* aggregate throws {@link MisattributedEventError} before anything is
|
|
2635
2543
|
* recorded. Each append is one fact. A decision appended twice becomes
|
|
2636
2544
|
* two facts with distinct ids. A recorded event that is already pending
|
|
2637
2545
|
* throws {@link DuplicateEventIdError}, and a list at `maxPendingEvents`
|
|
@@ -2663,7 +2571,7 @@ declare abstract class BaseAggregate<TState, TId extends Id<string>, TEvent exte
|
|
|
2663
2571
|
protected assertPendingEventLimit(added: number): void;
|
|
2664
2572
|
/**
|
|
2665
2573
|
* Appends an event that the caller already passed through
|
|
2666
|
-
* {@link
|
|
2574
|
+
* {@link stampNewEventIdentity}, {@link assertEventIdsNotPending} and
|
|
2667
2575
|
* {@link assertPendingEventLimit}. `setState()` and `apply()` run the
|
|
2668
2576
|
* three before the state moves and append afterwards, so each gate
|
|
2669
2577
|
* runs once per event.
|
|
@@ -2676,17 +2584,18 @@ declare abstract class BaseAggregate<TState, TId extends Id<string>, TEvent exte
|
|
|
2676
2584
|
*/
|
|
2677
2585
|
protected discardPendingDecisions(): void;
|
|
2678
2586
|
/**
|
|
2679
|
-
*
|
|
2587
|
+
* Aggregate identity discipline for NEW facts, shared by both flavours: a
|
|
2680
2588
|
* present-but-foreign `aggregateId` / `aggregateType` is a wiring bug and
|
|
2681
|
-
* throws {@link
|
|
2682
|
-
* from the aggregate, so a recorded event
|
|
2683
|
-
* can never fail the harvest or the replay guard
|
|
2589
|
+
* throws {@link MisattributedEventError}; missing fields are filled in
|
|
2590
|
+
* from the aggregate, so a recorded event always carries its full
|
|
2591
|
+
* aggregate identity and can never fail the harvest or the replay guard
|
|
2592
|
+
* later. The mint gate
|
|
2684
2593
|
* runs first, so an unminted event fails before anything else. The
|
|
2685
2594
|
* stamped copy is frozen like the original (payload and metadata are
|
|
2686
|
-
* shared, already deep-frozen by the constructors); a fully
|
|
2595
|
+
* shared, already deep-frozen by the constructors); a fully stamped
|
|
2687
2596
|
* event is returned as is.
|
|
2688
2597
|
*/
|
|
2689
|
-
protected
|
|
2598
|
+
protected stampNewEventIdentity<E extends PendingDomainEvent<TEvent>>(event: E): E;
|
|
2690
2599
|
/**
|
|
2691
2600
|
* Mint gate for every recording path: only an event that a kit
|
|
2692
2601
|
* constructor produced passes. The kit marks two shapes: a recorded
|
|
@@ -2808,9 +2717,9 @@ declare abstract class EventSourcedAggregate<TState, TId extends Id<string>, TEv
|
|
|
2808
2717
|
* Throws `MissingFoldError` if no fold is declared for `event.type`.
|
|
2809
2718
|
* Throws `FoldReturnedNoStateError` (wiring) when the fold returns
|
|
2810
2719
|
* `undefined`, the signature of a fold without a `return`.
|
|
2811
|
-
* Throws `
|
|
2720
|
+
* Throws `MisattributedEventError` (wiring) when the event carries an
|
|
2812
2721
|
* `aggregateId` or `aggregateType` naming a different aggregate;
|
|
2813
|
-
* missing
|
|
2722
|
+
* missing aggregate identity fields are stamped from the aggregate instead.
|
|
2814
2723
|
*
|
|
2815
2724
|
* State is not mutated if any step throws: the fold is invoked into
|
|
2816
2725
|
* a local and only stored once all checks pass.
|
|
@@ -2842,16 +2751,16 @@ declare abstract class EventSourcedAggregate<TState, TId extends Id<string>, TEv
|
|
|
2842
2751
|
* and the discriminator is resolved via the (statically-sound)
|
|
2843
2752
|
* `folds` map.
|
|
2844
2753
|
*
|
|
2845
|
-
* Replay
|
|
2754
|
+
* Replay aggregate identity check: a history event that names a DIFFERENT
|
|
2846
2755
|
* aggregate id or type is a persisted row that belongs to someone
|
|
2847
2756
|
* else (a miswired stream read, colliding ids across types, a
|
|
2848
2757
|
* corrupted store). Throws `ForeignEventError`, an
|
|
2849
2758
|
* `InfrastructureError`, which PROPAGATES through the replay
|
|
2850
2759
|
* methods (their `Result` channel is reserved for `DomainError`
|
|
2851
2760
|
* stream corruption) after the all-or-nothing rollback. History
|
|
2852
|
-
* events without the optional
|
|
2761
|
+
* events without the optional aggregate identity fields pass unchecked (the
|
|
2853
2762
|
* fields are optional on the event shape); NEW events are covered
|
|
2854
|
-
* by the stricter `
|
|
2763
|
+
* by the stricter `stampNewEventIdentity` on the apply path.
|
|
2855
2764
|
*/
|
|
2856
2765
|
private assertReplayedEventBelongsHere;
|
|
2857
2766
|
private fold;
|
|
@@ -2875,8 +2784,8 @@ declare abstract class EventSourcedAggregate<TState, TId extends Id<string>, TEv
|
|
|
2875
2784
|
* a reconstituted aggregate at v=P catching up on M newer events ends at
|
|
2876
2785
|
* v=P+M. Events carry no stream position, so an overlap with the current
|
|
2877
2786
|
* version is invisible here: the caller passes only the events after
|
|
2878
|
-
* that version and
|
|
2879
|
-
*
|
|
2787
|
+
* that version, and it compares the final version with the version it
|
|
2788
|
+
* expects.
|
|
2880
2789
|
*
|
|
2881
2790
|
* The replay target must not carry pending decisions. Factory-vs-load
|
|
2882
2791
|
* lifecycle is owned by the Unit of Work rather than inferred from an
|
|
@@ -2908,10 +2817,10 @@ declare abstract class EventSourcedAggregate<TState, TId extends Id<string>, TEv
|
|
|
2908
2817
|
/**
|
|
2909
2818
|
* Reconstitutes an event-sourced aggregate from one page of history and
|
|
2910
2819
|
* yields it only on success. `createReplayTarget` builds the instance: a
|
|
2911
|
-
* fresh one, or one
|
|
2820
|
+
* fresh one, or one reconstituted from a snapshot. The instance exists only
|
|
2912
2821
|
* inside this call. A rejected replay therefore leaves the caller with
|
|
2913
|
-
* nothing to return by mistake.
|
|
2914
|
-
* `
|
|
2822
|
+
* nothing to return by mistake. A stream read in pages goes through
|
|
2823
|
+
* `reconstituteAggregateFromStreamPages` instead. A `DomainError` from a fold rides the
|
|
2915
2824
|
* `Result`; wiring errors and a foreign row throw, as in `replayHistory`.
|
|
2916
2825
|
* The creator runs outside the `Result`: what it throws propagates.
|
|
2917
2826
|
*/
|
|
@@ -2931,10 +2840,10 @@ declare abstract class StateStoredAggregate<TState, TId extends Id<string>, TEve
|
|
|
2931
2840
|
/**
|
|
2932
2841
|
* Replaces the state, advances the OCC version, and records the events
|
|
2933
2842
|
* of the change, in that order. State validation, the event mint gate,
|
|
2934
|
-
* the
|
|
2935
|
-
* event limit check run before the change becomes
|
|
2936
|
-
* rejected decision records nothing and moves nothing.
|
|
2937
|
-
* change.
|
|
2843
|
+
* the aggregate identity check of the event, the pending event-id check,
|
|
2844
|
+
* and the pending event limit check run before the change becomes
|
|
2845
|
+
* observable, so a rejected decision records nothing and moves nothing.
|
|
2846
|
+
* Without events the call is a plain versioned state change.
|
|
2938
2847
|
*/
|
|
2939
2848
|
protected setState(newState: TState, events?: PendingDomainEvent<TEvent> | readonly PendingDomainEvent<TEvent>[]): void;
|
|
2940
2849
|
/**
|
|
@@ -2947,7 +2856,7 @@ declare abstract class StateStoredAggregate<TState, TId extends Id<string>, TEve
|
|
|
2947
2856
|
}
|
|
2948
2857
|
//#endregion
|
|
2949
2858
|
//#region src/domain/event/domain-event-errors.d.ts
|
|
2950
|
-
type DomainEventValidationCode = "EVENT_ID_REQUIRED" | "EVENT_ID_INVALID" | "EVENT_TYPE_INVALID" | "EVENT_OCCURRED_AT_REQUIRED" | "EVENT_OCCURRED_AT_INVALID" | "EVENT_SCHEMA_VERSION_INVALID" | "
|
|
2859
|
+
type DomainEventValidationCode = "EVENT_ID_REQUIRED" | "EVENT_ID_INVALID" | "EVENT_TYPE_INVALID" | "EVENT_OCCURRED_AT_REQUIRED" | "EVENT_OCCURRED_AT_INVALID" | "EVENT_SCHEMA_VERSION_INVALID" | "EVENT_AGGREGATE_IDENTITY_INVALID";
|
|
2951
2860
|
type DomainEventValidationField = "eventId" | "type" | "occurredAt" | "schemaVersion" | "aggregateId" | "aggregateType";
|
|
2952
2861
|
/**
|
|
2953
2862
|
* Stable contract error for malformed domain-event data.
|
|
@@ -3679,22 +3588,40 @@ declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
|
3679
3588
|
* built-in are dropped. A function or a symbol value throws a raw
|
|
3680
3589
|
* `DataCloneError`. An Error, a Promise, a WeakMap, or a WeakSet cannot be
|
|
3681
3590
|
* detached at all. A SharedArrayBuffer and a view over one keep sharing
|
|
3682
|
-
* their memory. A Proxy
|
|
3683
|
-
* clone
|
|
3591
|
+
* their memory. A Proxy fails in the walk or in the clone; a failure in
|
|
3592
|
+
* the clone is rethrown as a `TypeError` with the cause. An error that a
|
|
3593
|
+
* Proxy trap throws in the walk passes unchanged, so a coded error of the
|
|
3594
|
+
* caller keeps its code.
|
|
3595
|
+
*
|
|
3596
|
+
* The walk reads the graph through property descriptors and walks a Map
|
|
3597
|
+
* or a Set with the built-in iteration, so no accessor and no own iterator
|
|
3598
|
+
* of the state runs. A Proxy runs its traps during the walk. A trap can
|
|
3599
|
+
* change the graph, and an accessor that a trap adds runs during the
|
|
3600
|
+
* clone. A second walk checks the clone, so a value that a trap swapped in
|
|
3601
|
+
* and the content of a built-in whose prototype was replaced are rejected
|
|
3602
|
+
* too. A trap that changes the graph after the first walk can still hide a
|
|
3603
|
+
* value that the copy drops: the walks catch accidents, not a hostile
|
|
3604
|
+
* Proxy. The second walk also follows the steps of the first walk: the kind
|
|
3605
|
+
* of each object and the key of each data property, in walk order. A copy
|
|
3606
|
+
* that differs throws, because a built-in whose prototype was replaced is
|
|
3607
|
+
* a built-in again in the copy and loses its own properties. `subject`
|
|
3608
|
+
* names the state in the messages.
|
|
3684
3609
|
*
|
|
3685
3610
|
* Plain objects (from any realm), arrays, Dates, Maps, Sets, bigints, and
|
|
3686
3611
|
* typed arrays pass. A RegExp passes: pattern and flags survive the clone,
|
|
3687
3612
|
* and `lastIndex` restores as 0. The scan state of a global or sticky
|
|
3688
|
-
* pattern is not domain data.
|
|
3689
|
-
*
|
|
3690
|
-
*
|
|
3613
|
+
* pattern is not domain data. On a built-in, the mutator shadows of a deep
|
|
3614
|
+
* freeze, the `lastIndex` of a RegExp, and the `length` of a boxed String
|
|
3615
|
+
* pass: they are machinery, not data. Every other non-enumerable property
|
|
3616
|
+
* throws. A non-enumerable symbol key passes anywhere: it is metadata by
|
|
3617
|
+
* convention.
|
|
3691
3618
|
*
|
|
3692
3619
|
* The concrete entity uses it for a detached read DTO of a plain-data
|
|
3693
3620
|
* state. The snapshot model uses it for the captured DTO and the restored
|
|
3694
3621
|
* state. A state that carries a class-based child is mapped to plain data
|
|
3695
3622
|
* first, in the entity or in the model.
|
|
3696
3623
|
*/
|
|
3697
|
-
declare function detachState<T>(state: T): T;
|
|
3624
|
+
declare function detachState<T>(state: T, subject?: string): T;
|
|
3698
3625
|
//#endregion
|
|
3699
3626
|
//#region src/messaging/event-bus/errors.d.ts
|
|
3700
3627
|
/**
|
|
@@ -4016,7 +3943,7 @@ interface IntegrationMessageContent<TType extends string, TPayload extends JsonV
|
|
|
4016
3943
|
interface IntegrationMessage<TType extends string = string, TPayload extends JsonValue = JsonValue, TMetadata extends JsonObject = JsonObject> extends IntegrationMessageContent<TType, TPayload, TMetadata> {
|
|
4017
3944
|
readonly messageId: string;
|
|
4018
3945
|
readonly occurredAt: string;
|
|
4019
|
-
readonly source:
|
|
3946
|
+
readonly source: AggregateIdentity;
|
|
4020
3947
|
readonly position: CommitPosition;
|
|
4021
3948
|
}
|
|
4022
3949
|
/** Maps a private domain event to its explicit public message schema. */
|
|
@@ -4084,7 +4011,8 @@ interface InMemoryOutboxOptions {
|
|
|
4084
4011
|
* candidate commit position) retained for idempotent `add` retries and
|
|
4085
4012
|
* collision detection. Older receipts are evicted in dispatch order; a later
|
|
4086
4013
|
* candidate behind its source head then rejects instead of rewinding the
|
|
4087
|
-
* cursor.
|
|
4014
|
+
* cursor. A retry of an event at its source head still dedupes, because the
|
|
4015
|
+
* source cursor names that event.
|
|
4088
4016
|
* Default `10_000`.
|
|
4089
4017
|
*/
|
|
4090
4018
|
maxRetainedDispatchedEventIds?: number;
|
|
@@ -4103,12 +4031,16 @@ interface InMemoryOutboxOptions {
|
|
|
4103
4031
|
* recent-dispatch receipt cache keeps retries idempotent after acknowledgement.
|
|
4104
4032
|
* Re-adding a pending event refreshes the stored commit envelope while the
|
|
4105
4033
|
* delivery attempt count survives. Its commit sequence and size remain
|
|
4106
|
-
* immutable
|
|
4107
|
-
*
|
|
4108
|
-
* add. Dead-lettered and acknowledged
|
|
4109
|
-
* candidate receipt. Reusing an `eventId` for another source or commit position
|
|
4034
|
+
* immutable. Only this in-memory adapter may move a still-pending event to
|
|
4035
|
+
* another aggregate version. Without an `InMemoryTransactionScope`, it keeps
|
|
4036
|
+
* the first add of a rolled-back attempt. Dead-lettered and acknowledged
|
|
4037
|
+
* retries must match the complete original candidate receipt. Reusing an `eventId` for another source or commit position
|
|
4110
4038
|
* throws {@link EventHarvestError} while the pending, dead-letter, or bounded
|
|
4111
|
-
* dispatched receipt still proves the collision.
|
|
4039
|
+
* dispatched receipt still proves the collision. `add` also throws
|
|
4040
|
+
* {@link EventHarvestError} for a malformed candidate: a part that is not an
|
|
4041
|
+
* object, an `eventId` or `type` that is not an own string data property, a
|
|
4042
|
+
* source field that is not a string, or a position that is not a valid
|
|
4043
|
+
* commit position. Insertion order is preserved:
|
|
4112
4044
|
* `getPending` returns records in commit order, as the port contract requires.
|
|
4113
4045
|
*
|
|
4114
4046
|
* Dispatch tracking: `markFailed` increments the record's attempt count
|
|
@@ -4118,7 +4050,9 @@ interface InMemoryOutboxOptions {
|
|
|
4118
4050
|
* inverse of `deadLetters()`); `markDispatched` acks pending AND
|
|
4119
4051
|
* dead-lettered records (manual redelivery then ack).
|
|
4120
4052
|
* To link future eventful commits, the implementation also retains one
|
|
4121
|
-
* source cursor per qualified aggregate after dispatch.
|
|
4053
|
+
* source cursor per qualified aggregate after dispatch. `endEventSources`
|
|
4054
|
+
* marks the cursor of a removed aggregate as ended, and a new event of that
|
|
4055
|
+
* source then throws {@link EventHarvestError}. Consequently a
|
|
4122
4056
|
* long-lived instance is bounded only when `maxRecords` and `maxSources` are
|
|
4123
4057
|
* configured, plus `maxRetainedDispatchedEventIds`; use a durable adapter with
|
|
4124
4058
|
* an explicit source-head lifecycle and an event-id unique key for unbounded
|
|
@@ -4132,12 +4066,21 @@ interface InMemoryOutboxOptions {
|
|
|
4132
4066
|
* that are never `markDispatched` accumulate until `maxRecords` rejects a new
|
|
4133
4067
|
* add, or without that option grow unbounded. For a deliberate no-delivery
|
|
4134
4068
|
* setup use {@link outboxWriterAcceptingEventLoss} instead. Sharper still:
|
|
4135
|
-
*
|
|
4136
|
-
*
|
|
4137
|
-
* that
|
|
4138
|
-
*
|
|
4139
|
-
*
|
|
4140
|
-
*
|
|
4069
|
+
* on its own, the outbox knows nothing about your scope's rollback. Events
|
|
4070
|
+
* `add()`ed inside a transaction that later rolls back stay, and a source
|
|
4071
|
+
* that `endEventSources` ended inside such a transaction stays ended: the
|
|
4072
|
+
* outbox then rejects every later event of that aggregate, also on the retry
|
|
4073
|
+
* of a `RetryingTransactionScope`. For tests that roll back or retry,
|
|
4074
|
+
* register the outbox with an `InMemoryTransactionScope`. A rollback then
|
|
4075
|
+
* returns the outbox to its state at the start of the attempt.
|
|
4076
|
+
*
|
|
4077
|
+
* A relay reads only committed records. While a transaction is open,
|
|
4078
|
+
* `getPending` returns a record that the transaction wrote as it was
|
|
4079
|
+
* committed at the first write, with its current attempts. It skips a record
|
|
4080
|
+
* that was not pending at that write, such as a new or a requeued record. A
|
|
4081
|
+
* rollback also undoes an acknowledgement or a failure report that a
|
|
4082
|
+
* dispatcher made while the transaction was open. The dispatcher then
|
|
4083
|
+
* delivers that record again.
|
|
4141
4084
|
*
|
|
4142
4085
|
* @example
|
|
4143
4086
|
* ```ts
|
|
@@ -4155,13 +4098,20 @@ interface InMemoryOutboxOptions {
|
|
|
4155
4098
|
* });
|
|
4156
4099
|
* ```
|
|
4157
4100
|
*/
|
|
4158
|
-
declare class InMemoryOutbox<Evt extends AnyDomainEvent> implements DispatchTrackingOutbox<Evt
|
|
4101
|
+
declare class InMemoryOutbox<Evt extends AnyDomainEvent> implements DispatchTrackingOutbox<Evt>, InMemoryTransactionParticipant {
|
|
4159
4102
|
private readonly pending;
|
|
4160
4103
|
private readonly dead;
|
|
4161
4104
|
/** Latest eventful commit and its predecessor per qualified source. */
|
|
4162
4105
|
private readonly sourceCursors;
|
|
4106
|
+
/** Keys of source cursors whose aggregate was removed. */
|
|
4107
|
+
private readonly endedSourceKeys;
|
|
4163
4108
|
/** Bounded insertion-ordered receipts for exact retries after acknowledgement. */
|
|
4164
4109
|
private readonly dispatchedEventIds;
|
|
4110
|
+
/**
|
|
4111
|
+
* The committed pending record of each event id that the open transaction
|
|
4112
|
+
* wrote, captured at its first write. `undefined` marks an id without one.
|
|
4113
|
+
*/
|
|
4114
|
+
private committedVersions;
|
|
4165
4115
|
private readonly maxDeliveryAttempts;
|
|
4166
4116
|
private readonly maxRetainedDispatchedEventIds;
|
|
4167
4117
|
private readonly maxRecords;
|
|
@@ -4173,6 +4123,36 @@ declare class InMemoryOutbox<Evt extends AnyDomainEvent> implements DispatchTrac
|
|
|
4173
4123
|
private assertBatchPositionIntegrity;
|
|
4174
4124
|
getPending(limit?: number): Promise<ReadonlyArray<OutboxRecord<Evt>>>;
|
|
4175
4125
|
markDispatched(dispatchIds: ReadonlyArray<string>): Promise<void>;
|
|
4126
|
+
/**
|
|
4127
|
+
* Records the state that a rollback of an `InMemoryTransactionScope`
|
|
4128
|
+
* returns to: pending and dead-letter records, receipts, source cursors,
|
|
4129
|
+
* and ended sources, in their order. Until the transaction ends,
|
|
4130
|
+
* `getPending` returns the committed record of each event id that the
|
|
4131
|
+
* transaction writes.
|
|
4132
|
+
*/
|
|
4133
|
+
beginTransaction(): InMemoryTransaction;
|
|
4134
|
+
/** A record that a dispatcher removed is no longer pending in the committed state. */
|
|
4135
|
+
private forgetCommittedVersion;
|
|
4136
|
+
private recordCommittedVersion;
|
|
4137
|
+
endEventSources(sources: ReadonlyArray<AggregateIdentity>): Promise<void>;
|
|
4138
|
+
/**
|
|
4139
|
+
* Rejects a new event of an ended source above its head. An exact retry of
|
|
4140
|
+
* a stored event of an ended source stays a retry; the caller skips
|
|
4141
|
+
* retries at the source head before this check. The stale-head, commit
|
|
4142
|
+
* size, and position checks reject a candidate below the head or at a
|
|
4143
|
+
* position that another event owns, and their messages name the
|
|
4144
|
+
* re-created identity as a cause.
|
|
4145
|
+
*/
|
|
4146
|
+
private assertSourceNotEnded;
|
|
4147
|
+
/**
|
|
4148
|
+
* Event ids of the batch that the source head names at their position
|
|
4149
|
+
* although no receipt, pending record, or dead letter remains: events
|
|
4150
|
+
* that were dispatched and whose receipt was evicted. They are decided
|
|
4151
|
+
* against the heads before the batch, so their place in the batch does
|
|
4152
|
+
* not matter. Their receipts are restored after the batch.
|
|
4153
|
+
*/
|
|
4154
|
+
private retriesAtSourceHead;
|
|
4155
|
+
private recordedAtSourceHead;
|
|
4176
4156
|
private rememberDispatched;
|
|
4177
4157
|
markFailed(dispatchId: string, error?: unknown): Promise<DeadLetterRecord<Evt> | undefined>;
|
|
4178
4158
|
deadLetters(): Promise<ReadonlyArray<DeadLetterRecord<Evt>>>;
|
|
@@ -4196,29 +4176,204 @@ interface InMemoryEventStoreOptions {
|
|
|
4196
4176
|
* `InMemoryCapacityExceededError`; histories are never silently evicted.
|
|
4197
4177
|
* Implements the full port contract: expectedVersion-guarded appends
|
|
4198
4178
|
* (throwing `ConcurrencyConflictError` on mismatch), atomic rejected
|
|
4199
|
-
* appends, explicit
|
|
4179
|
+
* appends, explicit absent/existing stream state with the actual head,
|
|
4200
4180
|
* append-order reads, mandatory page bounds, and `(fromVersion, toVersion]`
|
|
4201
|
-
* slicing. Invalid limits or positions reject with `RangeError`.
|
|
4181
|
+
* slicing. Invalid limits or positions reject with `RangeError`. A read
|
|
4182
|
+
* with an aborted `signal` rejects with its `reason`.
|
|
4202
4183
|
*
|
|
4203
4184
|
* For production, back the port with a durable store whose append and
|
|
4204
4185
|
* the aggregate transaction share atomicity (a table with a
|
|
4205
4186
|
* `(aggregate_type, aggregate_id, position)` unique key inside the same
|
|
4206
4187
|
* transaction, or a dedicated event store). Same caveat as
|
|
4207
|
-
* `InMemoryOutbox`: this class
|
|
4208
|
-
*
|
|
4209
|
-
*
|
|
4210
|
-
*
|
|
4211
|
-
* reference environment shows the snapshot/restore pattern for
|
|
4212
|
-
* rollback-pure in-memory testing.
|
|
4188
|
+
* `InMemoryOutbox`: this class lives in memory only. On its own, it knows
|
|
4189
|
+
* nothing about your `TransactionScope` rollbacks, so events appended inside
|
|
4190
|
+
* a transaction that later rolls back stay. Register the store with an
|
|
4191
|
+
* `InMemoryTransactionScope` for tests that roll back or retry.
|
|
4213
4192
|
*/
|
|
4214
|
-
declare class InMemoryEventStore<Evt extends AnyDomainEvent> implements EventStore<Evt
|
|
4193
|
+
declare class InMemoryEventStore<Evt extends AnyDomainEvent> implements EventStore<Evt>, InMemoryTransactionParticipant {
|
|
4215
4194
|
private readonly streams;
|
|
4216
4195
|
private readonly maxStreams;
|
|
4217
4196
|
private readonly maxEvents;
|
|
4218
4197
|
private totalEvents;
|
|
4219
4198
|
constructor(options?: InMemoryEventStoreOptions);
|
|
4220
|
-
|
|
4221
|
-
|
|
4199
|
+
/**
|
|
4200
|
+
* Records the state that a rollback of an `InMemoryTransactionScope`
|
|
4201
|
+
* returns to: every stream and the event count.
|
|
4202
|
+
*/
|
|
4203
|
+
beginTransaction(): InMemoryTransaction;
|
|
4204
|
+
append(stream: AggregateIdentity, events: ReadonlyArray<Evt>, options: EventStoreAppendOptions): Promise<void>;
|
|
4205
|
+
/**
|
|
4206
|
+
* The stream that an append of `count` events at `expectedVersion`
|
|
4207
|
+
* writes to, or `undefined` for a new stream. Throws when the version
|
|
4208
|
+
* is stale or a capacity would overflow.
|
|
4209
|
+
*/
|
|
4210
|
+
private existingStreamForAppend;
|
|
4211
|
+
readStream(stream: AggregateIdentity, options: ReadStreamOptions): Promise<StreamReadResult<Evt>>;
|
|
4212
|
+
}
|
|
4213
|
+
//#endregion
|
|
4214
|
+
//#region src/persistence/event-store/read-stream-pages.d.ts
|
|
4215
|
+
/** Options for {@link readStreamPages}. */
|
|
4216
|
+
interface ReadStreamPagesOptions extends Pick<ReadStreamOptions, "limit" | "fromVersion" | "signal"> {
|
|
4217
|
+
/**
|
|
4218
|
+
* The version a point-in-time read asks for (inclusive, 1-based event
|
|
4219
|
+
* count). Without it, the target version is the head that the first page
|
|
4220
|
+
* reports. A value beyond the head does not clamp: see
|
|
4221
|
+
* {@link pinTargetVersion}. Must be a positive safe integer when present.
|
|
4222
|
+
* Version 0 is the state before the first event, and no replay can end
|
|
4223
|
+
* there.
|
|
4224
|
+
*/
|
|
4225
|
+
readonly toVersion?: number;
|
|
4226
|
+
}
|
|
4227
|
+
/**
|
|
4228
|
+
* A stream read with the target version pinned on its first page.
|
|
4229
|
+
*
|
|
4230
|
+
* The first page decides the state of the stream once, in three branches.
|
|
4231
|
+
* An absent stream is `exists: false`. An existing stream whose window lies
|
|
4232
|
+
* outside it is `reachable: false` and carries the actual head. The
|
|
4233
|
+
* remaining branch carries the target version and the pages after the
|
|
4234
|
+
* cursor. The other two branches both carry `reachable: false`, so one
|
|
4235
|
+
* guard narrows to the branch that
|
|
4236
|
+
* {@link reconstituteAggregateFromStreamPages} accepts. The caller decides
|
|
4237
|
+
* what the other two branches mean before the replay.
|
|
4238
|
+
*/
|
|
4239
|
+
type StreamPages<Evt extends AnyDomainEvent> = AbsentStreamPages | UnreachableStreamPages | ReachableStreamPages<Evt>;
|
|
4240
|
+
/** The branch of {@link StreamPages} for a stream the store does not hold. */
|
|
4241
|
+
interface AbsentStreamPages {
|
|
4242
|
+
readonly exists: false;
|
|
4243
|
+
readonly reachable: false;
|
|
4244
|
+
}
|
|
4245
|
+
/**
|
|
4246
|
+
* The branch of {@link StreamPages} for a window that lies outside an
|
|
4247
|
+
* existing stream: the cursor lies beyond the target version, or the
|
|
4248
|
+
* target version lies beyond the head ({@link pinTargetVersion}).
|
|
4249
|
+
*
|
|
4250
|
+
* The caller tells the causes apart from its own inputs. A snapshot
|
|
4251
|
+
* version above `lastVersion` means that the snapshot outlived its stream:
|
|
4252
|
+
* discard it and replay from zero. A `toVersion` above `lastVersion` means
|
|
4253
|
+
* that the stream has not reached that version: answer not found and keep
|
|
4254
|
+
* the snapshot. A snapshot version above `toVersion` means that the
|
|
4255
|
+
* snapshot is too new for the request: keep it and replay from zero up to
|
|
4256
|
+
* `toVersion`.
|
|
4257
|
+
*/
|
|
4258
|
+
interface UnreachableStreamPages {
|
|
4259
|
+
readonly exists: true;
|
|
4260
|
+
readonly reachable: false;
|
|
4261
|
+
/** The cursor the read started at: `fromVersion`, or `0`. */
|
|
4262
|
+
readonly fromVersion: number;
|
|
4263
|
+
/** The actual stream head on the first page. */
|
|
4264
|
+
readonly lastVersion: number;
|
|
4265
|
+
}
|
|
4266
|
+
/** The branch of {@link StreamPages} that the replay accepts. */
|
|
4267
|
+
interface ReachableStreamPages<Evt extends AnyDomainEvent> extends ReplayableStreamPages<Evt> {
|
|
4268
|
+
readonly exists: true;
|
|
4269
|
+
readonly reachable: true;
|
|
4270
|
+
}
|
|
4271
|
+
/** Options for {@link pinTargetVersion}. */
|
|
4272
|
+
interface PinTargetVersionOptions {
|
|
4273
|
+
/** The cursor of the read: the replay starts after this version. */
|
|
4274
|
+
readonly fromVersion: number;
|
|
4275
|
+
/** The version a point-in-time read asks for. Defaults to `lastVersion`. */
|
|
4276
|
+
readonly toVersion?: number;
|
|
4277
|
+
/** The head of the existing stream: its event count. */
|
|
4278
|
+
readonly lastVersion: number;
|
|
4279
|
+
}
|
|
4280
|
+
/** The verdict of {@link pinTargetVersion}. */
|
|
4281
|
+
type PinnedTargetVersion = {
|
|
4282
|
+
readonly reachable: true;
|
|
4283
|
+
readonly targetVersion: number;
|
|
4284
|
+
} | {
|
|
4285
|
+
readonly reachable: false;
|
|
4286
|
+
};
|
|
4287
|
+
/**
|
|
4288
|
+
* Pins the target version of a replay window on an existing stream, or
|
|
4289
|
+
* reports the window as unreachable.
|
|
4290
|
+
*
|
|
4291
|
+
* The target version is `toVersion` when given, else `lastVersion`. The
|
|
4292
|
+
* window is unreachable when `fromVersion` lies beyond the target version,
|
|
4293
|
+
* or the target version lies beyond `lastVersion`. The call never clamps
|
|
4294
|
+
* such a window to the head, so a request for version 10 of a stream that
|
|
4295
|
+
* ends at 7 never loads the latest state by accident.
|
|
4296
|
+
*
|
|
4297
|
+
* This is the decision `readStreamPages` makes on its first page. An
|
|
4298
|
+
* adapter that pages on its own makes it with this call, then hands its
|
|
4299
|
+
* pages to `reconstituteAggregateFromStreamPages`. Values that are not safe
|
|
4300
|
+
* integers, a negative `fromVersion`, and a `toVersion` or `lastVersion`
|
|
4301
|
+
* below 1 reject with `RangeError`: an existing stream holds at least one
|
|
4302
|
+
* event, and no replay can end at version 0.
|
|
4303
|
+
*/
|
|
4304
|
+
declare function pinTargetVersion(options: PinTargetVersionOptions): PinnedTargetVersion;
|
|
4305
|
+
/**
|
|
4306
|
+
* Reads one stream in bounded pages up to a pinned target version.
|
|
4307
|
+
*
|
|
4308
|
+
* The call reads the first page. That page decides existence and reports
|
|
4309
|
+
* the head. The call then makes the window decision of
|
|
4310
|
+
* {@link pinTargetVersion}: the target version is `toVersion` when given,
|
|
4311
|
+
* else the head, and a window outside the stream is unreachable.
|
|
4312
|
+
*
|
|
4313
|
+
* The first iteration of `pages` yields the first page that the call read
|
|
4314
|
+
* and then reads the continuation pages, one page at a time. Every later
|
|
4315
|
+
* iteration reads all pages from the store again, so no two iterations
|
|
4316
|
+
* share an event object. Each of these reads passes the target version as
|
|
4317
|
+
* `toVersion` and starts after the events that the earlier pages
|
|
4318
|
+
* returned. Streams are append-only, so an iteration yields one stable
|
|
4319
|
+
* prefix even when another writer appends during the replay.
|
|
4320
|
+
*
|
|
4321
|
+
* The call checks every page against the `readStream` contract and throws
|
|
4322
|
+
* {@link InvalidEventStreamPageError} for a page that breaks it: a head
|
|
4323
|
+
* that is not a safe integer of at least 1, an empty page while events
|
|
4324
|
+
* remain in the window, a page with more events than its window has left
|
|
4325
|
+
* or than `limit`, and a continuation page that reports the stream absent
|
|
4326
|
+
* or a head below the head of the first page.
|
|
4327
|
+
*
|
|
4328
|
+
* Invalid options reject with `RangeError` before any page is read:
|
|
4329
|
+
* `limit` and `toVersion` must be positive safe integers, `fromVersion` a
|
|
4330
|
+
* non-negative one. The call passes `signal` to every page read, and it
|
|
4331
|
+
* checks the signal before each page read as well. An aborted signal
|
|
4332
|
+
* rejects with its `reason`.
|
|
4333
|
+
*/
|
|
4334
|
+
declare function readStreamPages<Evt extends AnyDomainEvent>(reader: EventStreamReader<Evt>, stream: AggregateIdentity, options: ReadStreamPagesOptions): Promise<StreamPages<Evt>>;
|
|
4335
|
+
//#endregion
|
|
4336
|
+
//#region src/persistence/repository/adapters/in-memory-transaction-scope.d.ts
|
|
4337
|
+
/**
|
|
4338
|
+
* A {@link TransactionScope} for tests and demos that gives in-memory stores
|
|
4339
|
+
* a rollback. Register every store that the work writes inside the
|
|
4340
|
+
* transaction. When the work fails, each registered store undoes the writes
|
|
4341
|
+
* of the attempt, so the retry of a `RetryingTransactionScope` does not see
|
|
4342
|
+
* them. Each store decides what its rollback undoes, and its documentation
|
|
4343
|
+
* says so.
|
|
4344
|
+
*
|
|
4345
|
+
* **One transaction at a time.** A store cannot tell which of two open
|
|
4346
|
+
* transactions a write belongs to. The scope therefore runs its transactions
|
|
4347
|
+
* one after the other, in call order. A queued transaction stops its wait
|
|
4348
|
+
* when its abort signal fires. Work that waits inside a transaction for
|
|
4349
|
+
* another transaction of the same scope never finishes, because the inner
|
|
4350
|
+
* transaction waits for the outer one. Only the abort signal of the inner
|
|
4351
|
+
* transaction ends that wait. A database with only one connection behaves
|
|
4352
|
+
* the same way. Use a database with real isolation to test concurrent
|
|
4353
|
+
* transactions.
|
|
4354
|
+
*
|
|
4355
|
+
* **Code outside a transaction.** A dispatcher, a deadline processor, and a
|
|
4356
|
+
* `hasReached` check run outside the transactions. Outbox `getPending`,
|
|
4357
|
+
* deadline `due`, and checkpoint `hasReached` read only committed writes.
|
|
4358
|
+
* Other reads also see the writes of an open transaction. A store that
|
|
4359
|
+
* restores its whole state on rollback also undoes the writes that code
|
|
4360
|
+
* outside the transaction made meanwhile. An example is an acknowledgement
|
|
4361
|
+
* of an outbox dispatcher. The dispatcher then delivers the record again,
|
|
4362
|
+
* which the at-least-once contract allows.
|
|
4363
|
+
*
|
|
4364
|
+
* **A store belongs to one scope.** A scope works like one in-memory
|
|
4365
|
+
* database, so register all stores of a test with one scope. A second scope
|
|
4366
|
+
* with a registered store throws at construction, because the rollback of
|
|
4367
|
+
* one scope would undo a commit of the other.
|
|
4368
|
+
*
|
|
4369
|
+
* A store that is not registered keeps its own behavior: it does not roll
|
|
4370
|
+
* back.
|
|
4371
|
+
*/
|
|
4372
|
+
declare class InMemoryTransactionScope implements TransactionScope<undefined> {
|
|
4373
|
+
private readonly participants;
|
|
4374
|
+
private lastTransaction;
|
|
4375
|
+
constructor(participants: ReadonlyArray<InMemoryTransactionParticipant>);
|
|
4376
|
+
transactional<T>(fn: (ctx: undefined) => Promise<T>, options?: TransactionalOptions): Promise<T>;
|
|
4222
4377
|
}
|
|
4223
4378
|
//#endregion
|
|
4224
4379
|
//#region src/persistence/repository/repository.d.ts
|
|
@@ -4368,6 +4523,10 @@ interface RetryPolicy {
|
|
|
4368
4523
|
* After `maxAttempts` the last error is rethrown unchanged, so a caller
|
|
4369
4524
|
* can still match `ConcurrencyConflictError` and map it to HTTP 409.
|
|
4370
4525
|
*
|
|
4526
|
+
* **Attempts.** Before each attempt, the scope calls `onAttemptStart` from
|
|
4527
|
+
* the `transactional` options, so the caller can attribute a failure to the
|
|
4528
|
+
* attempt that raised it.
|
|
4529
|
+
*
|
|
4371
4530
|
* **Cancellation.** The `AbortSignal` from `transactional` options is
|
|
4372
4531
|
* checked before each attempt and aborts the backoff wait, so an
|
|
4373
4532
|
* `AbortSignal.timeout(ms)` bounds total elapsed time (there is
|
|
@@ -4407,16 +4566,28 @@ interface InMemorySnapshotStoreOptions {
|
|
|
4407
4566
|
* rebuildable derived data, so `maxEntries` may evict the least recently used
|
|
4408
4567
|
* entry and `ttlMs` may expire it safely. A load updates LRU recency but does
|
|
4409
4568
|
* not extend TTL; only another save does.
|
|
4569
|
+
*
|
|
4570
|
+
* The port keeps snapshot writes out of the write transaction, so the store
|
|
4571
|
+
* does not roll back on its own. If you register it with an
|
|
4572
|
+
* `InMemoryTransactionScope`, a rollback restores the snapshots, their LRU
|
|
4573
|
+
* order, and their expiry from the start of the transaction. It also undoes
|
|
4574
|
+
* a save or a delete that code made outside the transaction meanwhile. This
|
|
4575
|
+
* is safe, because a snapshot is derived data.
|
|
4410
4576
|
*/
|
|
4411
|
-
declare class InMemorySnapshotStore<TState = unknown> implements SnapshotStore<TState
|
|
4577
|
+
declare class InMemorySnapshotStore<TState = unknown> implements SnapshotStore<TState>, InMemoryTransactionParticipant {
|
|
4412
4578
|
private readonly snapshots;
|
|
4413
4579
|
private readonly maxEntries;
|
|
4414
4580
|
private readonly ttlMs;
|
|
4415
4581
|
private readonly clock;
|
|
4416
4582
|
constructor(options?: InMemorySnapshotStoreOptions);
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4583
|
+
/**
|
|
4584
|
+
* Records the state that a rollback of an `InMemoryTransactionScope`
|
|
4585
|
+
* returns to: every snapshot in LRU order.
|
|
4586
|
+
*/
|
|
4587
|
+
beginTransaction(): InMemoryTransaction;
|
|
4588
|
+
load(identity: AggregateIdentity): Promise<AggregateSnapshot<TState> | undefined>;
|
|
4589
|
+
save(identity: AggregateIdentity, snapshot: AggregateSnapshot<TState>): Promise<void>;
|
|
4590
|
+
delete(identity: AggregateIdentity): Promise<void>;
|
|
4420
4591
|
private readClock;
|
|
4421
4592
|
private deleteExpired;
|
|
4422
4593
|
}
|
|
@@ -4434,7 +4605,7 @@ interface SnapshotAggregate {
|
|
|
4434
4605
|
* valid domain object; it does not know when or how snapshots are stored.
|
|
4435
4606
|
*/
|
|
4436
4607
|
interface SnapshotModel<TAggregate extends SnapshotAggregate, TSnapshotState> {
|
|
4437
|
-
/** Stable type name
|
|
4608
|
+
/** Stable type name that names the aggregate in schema errors and snapshot storage. */
|
|
4438
4609
|
readonly aggregateType: string;
|
|
4439
4610
|
/** Current schema version of the stored snapshot DTO. */
|
|
4440
4611
|
readonly schemaVersion: number;
|
|
@@ -4489,5 +4660,5 @@ declare function captureAggregateSnapshot<TAggregate extends SnapshotAggregate,
|
|
|
4489
4660
|
*/
|
|
4490
4661
|
declare function reconstituteAggregateFromSnapshot<TAggregate extends SnapshotAggregate, TSnapshotState>(model: SnapshotModel<TAggregate, TSnapshotState>, id: TAggregate["id"], snapshot: AggregateSnapshot<unknown>): TAggregate;
|
|
4491
4662
|
//#endregion
|
|
4492
|
-
export { type Aggregate, type
|
|
4663
|
+
export { type AbsentStreamPages, type Aggregate, type AggregateClass, type AggregateCommitToken, type AggregateConfig, AggregateDeletedError, type AggregateDeletedErrorOptions, type AggregateIdentity, type AggregateIdentityMismatchOptions, AggregateNotFoundError, type AggregateNotFoundErrorOptions, type AggregatePersistence, type AggregatePersistenceWrite, type AggregateSnapshot, AggregateTrackingError, type AggregateTrackingErrorOptions, type AggregateTrackingReason, type AggregateWriteIntent, type AggregateWriteRegistration, type AnyDomainEvent, type AnyUncommittedDomainEvent, type AppendOnlyWriteRegistration, CapabilityRegistryConflictError, type ClassifyConcurrencyConflictOptions, type ClockFactory, type Command, CommandBus, type CommandBusOptions, type CommandCommitOriginCandidate, type CommandHandler, type CommandMessageContent, type CommandMessageRelationships, type CommandOutboxCommitCandidate, type CommandOutboxMapper, type CommandOutboxWriter, type CommitEnrollment, type CommitEnrollmentOptions, CommitError, type CommitPosition, type CommittedDomainEvent, type CompatibleRepositoryDefinitions, ConcurrencyConflictError, type ConcurrencyConflictErrorOptions, type ConcurrencyConflictReason, type CreateDomainEventFromFactsOptions, type CreateDomainEventOptions, type CreateDomainEventStampOptions, type CreateUncommittedDomainEventOptions, type DeadLetterDeadline, type DeadLetterRecord, DeadlineProcessor, type DeadlineProcessorObservers, type DeadlineProcessorOptions, type DeadlineStore, type DeepEqualExceptOptions, type DeepOmitKey, type DeepOmitOptions, type DeepOmitPathSegment, type DeliveryFailureAssessment, type DeliveryFailureClassifier, type DeliveryFailureKind, DirectStateMutationError, type DirectStateMutationErrorOptions, type DispatchTrackingOutbox, DomainError, type DomainErrorClass, type DomainEvent, type DomainEventFactory, type DomainEventFactoryOptions, type DomainEventStamp, type DomainEventStampFactory, type DomainEventStampProvider, type DomainEventValidationCode, DomainEventValidationError, type DomainEventValidationField, type DomainMachineDefinition, type DomainMachineDefinitionAnalysis, type DomainMachineDefinitionDiagnostic, type DomainMachineInput, type DomainMachineReadonly, type DomainMachineSnapshot, type DomainMachineTransitionDescription, DomainStateMachine, type DomainStateNode, type DomainTransition, DomainTransitionGuardRejectedError, type DomainTransitionGuardResult, type DomainTransitionOutcome, type DomainTransitionResult, type DueDeadline, DuplicateAggregateError, type DuplicateAggregateErrorOptions, DuplicateEventIdError, type DuplicateEventIdErrorOptions, DuplicateHandlerRegistrationError, type DuplicateHandlerRegistrationErrorOptions, type DurableCommandMessage, Entity, type EntityConfig, ErrorMapperFailedError, type ErrorMapperFailedErrorOptions, type EventBus, EventBusClosedError, EventBusImpl, type EventBusObservers, type EventBusOptions, type EventCommitCandidate, type EventCommitCandidatePosition, type EventHandler, EventHarvestError, type EventIdFactory, type EventMetadata, EventSourcedAggregate, type EventStore, type EventStoreAppendOptions, type EventStreamPageReason, type EventStreamReader, type ExecutionContext, type FlushStatementReason, FoldReturnedNoStateError, ForeignEventError, type HandlerFailureReport, HostileStateKeyError, type ICommandBus, type IEntity, type IQueryBus, type IValueObject, type Id, type IdGenerator, type IdempotencyClaim, type IdempotencyClaimHandle, IdempotencyClaimLostError, type IdempotencyClaimLostErrorOptions, IdempotencyCompletionWithoutClaimError, IdempotencyInFlightError, type IdempotencyInFlightErrorOptions, IdempotencyKeyReuseError, type IdempotencyKeyReuseErrorOptions, type IdempotencyLease, type IdempotencyOperationErrorContext, type IdempotencyReconciliation, type IdempotencyReconciliationDecision, IdempotencyReconciliationRequiredError, type IdempotencyReconciliationRequiredErrorOptions, type IdempotencyStore, type IdempotentCommitRequest, type IdempotentCommitResult, type IdempotentExecution, type Identifiable, IdentityMap, InMemoryCapacityExceededError, type InMemoryCapacityExceededErrorOptions, InMemoryDeadlineStore, type InMemoryDeadlineStoreOptions, InMemoryEventStore, type InMemoryEventStoreOptions, InMemoryIdempotencyStore, type InMemoryIdempotencyStoreOptions, InMemoryOutbox, type InMemoryOutboxOptions, InMemoryProjectionCheckpointStore, type InMemoryProjectionCheckpointStoreOptions, InMemorySnapshotStore, type InMemorySnapshotStoreOptions, type InMemoryTransaction, type InMemoryTransactionParticipant, InMemoryTransactionScope, InfrastructureError, type IntegrationMessage, type IntegrationMessageContent, type IntegrationMessageMapper, type IntegrationMessageRelationships, InvalidCommandMessageError, InvalidDomainMachineContextError, InvalidDomainMachineDefinitionError, InvalidDomainMachineInputError, InvalidDomainMachineSnapshotError, InvalidDomainTransitionError, InvalidDomainTransitionGuardResultError, InvalidDomainTransitionResultError, InvalidEventStreamPageError, type InvalidEventStreamPageErrorOptions, InvalidFlushStatementError, type InvalidFlushStatementErrorOptions, InvalidIntegrationMessageError, InvalidRepositoryAdapterError, type InvalidRepositoryAdapterErrorOptions, type InvalidRepositoryAdapterReason, InvalidRepositoryDefinitionError, InvalidVersionError, type JsonObject, type JsonPrimitive, type JsonValue, type KitErrorCode, type KitErrorOptions, type MatchedRows, MisattributedEventError, MissingEntityIdError, MissingFoldError, MissingHandlerError, NestedUnitOfWorkError, type OnceOptions, type Outbox, OutboxDispatcher, type OutboxDispatcherObservers, type OutboxDispatcherOptions, type OutboxRecord, type OutboxSink, type OutboxWriter, type PendingDomainEvent, PendingEventBatchMismatchError, type PendingEventBatchMismatchErrorOptions, PendingEventLimitExceededError, type PendingEventLimitExceededErrorOptions, type PersistenceBaseline, type PersistenceChanges, type PersistenceLifecycle, type PersistenceModel, type PhysicalRemovalRegistration, type PinTargetVersionOptions, type PinnedTargetVersion, type PreparedDomainMachineDefinition, type ProjectOptions, type Projection, type ProjectionBatchResult, type ProjectionCheckpoint, type ProjectionCheckpointStore, type ProjectionEventHandler, type ProjectionFromHandlersOptions, ProjectionGapError, type ProjectionHandlers, ProjectionIdentityViolationError, ProjectionOrderViolationError, type ProjectionPosition, ProjectionReceiptViolationError, Projector, type ProjectorOptions, type PublishAbortedReport, type PublishChainState, type PublishChainStore, PublishDepthExceededError, type PublishOptions, type PublishedCommand, type Query, QueryBus, type QueryBusOptions, type QueryHandler, type ReachableStreamPages, type ReadStreamOptions, type ReadStreamPagesOptions, ReentrantDomainStateMachineEvaluationError, ReentrantEventRecordingError, type ReentrantEventRecordingErrorOptions, ReplayRejectedError, type ReplayRejectedErrorOptions, ReplayTargetMismatchError, type ReplayTargetMismatchErrorOptions, type ReplayTargetMismatchReason, type ReplayableAggregate, type ReplayableStreamPages, type RepositoriesOf, type Repository, type RepositoryDefinition, type RepositoryDefinitionOptions, RepositoryErrorMappingFailedError, type RepositoryErrorMappingFailedErrorOptions, type RepositoryTracking, type RetryPolicy, RetryingTransactionScope, RollbackError, type RunOptions, type SharedDomainEventStampOptions, SnapshotCorruptedError, type SnapshotModel, SnapshotSchemaMismatchError, type SnapshotSchemaMismatchErrorOptions, type SnapshotStore, SnapshotTimeValidationError, SnapshotVersionNotRestoredError, type SnapshotVersionNotRestoredErrorOptions, Specification, type SpecificationComposite, StateStoredAggregate, type StateValidator, type StreamPages, type StreamReadResult, type SubscriptionThresholdReport, TransactionClosedError, type TransactionScope, type TransactionalOptions, type UncommittedDomainEvent, type UncommittedDomainEventOf, UnenrolledChangesError, type UnenrolledChangesErrorOptions, UnitOfWork, type UnitOfWorkContext, type UnitOfWorkDeps, type UnitOfWorkIdentityMap, UnmanagedInstanceError, UnmintedEventError, UnprojectableEventError, type UnreachableStreamPages, UnregisteredHandlerError, type UnregisteredHandlerErrorOptions, UnreplayableAggregateError, type UnreplayableAggregateErrorOptions, type VO, ValueObject, type Version, type VersionedFlushStatements, type VersionedWrite, type WithCommitDeps, type WithCommitWorkResult, type WithIdempotentCommitDeps, analyzeDomainMachineDefinition, canTransitionDomainState, captureAggregateSnapshot, capturePersistenceBaseline, classifyConcurrencyConflict, copyMetadata, createDomainEvent, createDomainEventFactory, createDomainEventFromFacts, createInitialDomainMachineSnapshot, createIntegrationMessage, createUncommittedDomainEvent, decodeIntegrationMessage, deepEqual, deepEqualExcept, deepFreeze, deepOmit, defaultDomainEventFactory, defineRepository, defineSnapshotModel, derivePersistenceChanges, detachState, domainErrorToResult, encodeIntegrationMessage, entityIds, eventBusSink, findEntityById, freezeShallow, hasEntityId, ignoreProjectionEvent, insertPersistenceBaseline, integrationMessageToCommittedEvent, isDomainErrorLike, isInfrastructureErrorLike, isPositionAfter, isWiringErrorLike, mergeMetadata, outboxWriterAcceptingEventLoss, persistenceProjectionDrifted, pinTargetVersion, prepareDomainMachineDefinition, projectionFromHandlers, readStreamPages, recapturePersistenceBaseline, reconstituteAggregateFromHistory, reconstituteAggregateFromSnapshot, reconstituteAggregateFromStreamPages, recordDomainEvent, recordPendingEvents, removeEntityById, replaceEntityById, routeEventsToCommandOutbox, sameEntity, sameVersion, specification, toVersion, transitionDomainState, updateEntityById, versionedFlush, vo, voEquals, voEqualsExcept, voValidated, voWithValidation, withCommit, withIdempotentCommit };
|
|
4493
4664
|
//# sourceMappingURL=index.d.ts.map
|