@shirudo/ddd-kit 3.0.0-rc.12 → 3.0.0-rc.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -8
- package/dist/chunks/kit-errors.d.ts +25 -26
- package/dist/chunks/kit-errors.js +51 -52
- package/dist/chunks/kit-errors.js.map +1 -1
- package/dist/chunks/read-stream-pages.js +91 -1365
- package/dist/chunks/read-stream-pages.js.map +1 -1
- package/dist/chunks/snapshot-store.d.ts +79 -129
- package/dist/chunks/value-object.js +1275 -0
- package/dist/chunks/value-object.js.map +1 -0
- package/dist/index.d.ts +130 -390
- package/dist/index.js +200 -868
- package/dist/index.js.map +1 -1
- package/dist/money.d.ts +3 -3
- package/dist/money.js +3 -3
- package/dist/money.js.map +1 -1
- package/dist/state-machine.d.ts +227 -0
- package/dist/state-machine.js +673 -0
- package/dist/state-machine.js.map +1 -0
- package/dist/testing.d.ts +4 -4
- package/dist/testing.js +12 -11
- package/dist/testing.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -111,7 +111,7 @@ That example is deliberately small, but it shows the core shape:
|
|
|
111
111
|
- The domain throws an error when an invariant is broken.
|
|
112
112
|
- `setState(...)` changes the state and records the event together.
|
|
113
113
|
- `createEvent(...)` captures the immutable domain decision and aggregate source.
|
|
114
|
-
- The application shell adds event identity,
|
|
114
|
+
- The application shell adds event identity, stamp time, and trace metadata.
|
|
115
115
|
- Persistence stays outside the aggregate.
|
|
116
116
|
|
|
117
117
|
In production, a repository and `withCommit` or `UnitOfWork` persist the state,
|
|
@@ -122,12 +122,13 @@ aggregate as persisted after the transaction commits.
|
|
|
122
122
|
|
|
123
123
|
**Domain modeling**
|
|
124
124
|
|
|
125
|
-
- value objects via `
|
|
126
|
-
- exact Money helpers in `@shirudo/ddd-kit/money`
|
|
125
|
+
- value objects via `valueObject()` and `ValueObject<T>`
|
|
126
|
+
- exact Money helpers in `@shirudo/ddd-kit/money` (experimental)
|
|
127
127
|
- child entities with branded identity
|
|
128
128
|
- state-stored and event-sourced aggregate roots
|
|
129
129
|
- domain events with metadata, schema version, and commit stamps
|
|
130
|
-
- a domain state machine for named lifecycle states
|
|
130
|
+
- a domain state machine for named lifecycle states in
|
|
131
|
+
`@shirudo/ddd-kit/state-machine` (experimental)
|
|
131
132
|
|
|
132
133
|
**Application boundaries**
|
|
133
134
|
|
|
@@ -136,7 +137,7 @@ aggregate as persisted after the transaction commits.
|
|
|
136
137
|
runtimes
|
|
137
138
|
- a clear error split: domain code throws, command/query boundaries return
|
|
138
139
|
`Result`
|
|
139
|
-
- `
|
|
140
|
+
- `valueObjectOrIssues` for collecting field-level validation issues
|
|
140
141
|
- optional HTTP/RFC 9457 presentation helpers
|
|
141
142
|
|
|
142
143
|
**Persistence and delivery**
|
|
@@ -144,8 +145,8 @@ aggregate as persisted after the transaction commits.
|
|
|
144
145
|
- repository interfaces for id-based and filtered access
|
|
145
146
|
- a per-operation Identity Map contract
|
|
146
147
|
- optimistic concurrency errors and duplicate-insert errors
|
|
147
|
-
- `withCommit` for transaction, outbox, event
|
|
148
|
-
- `UnitOfWork` for repository registration and
|
|
148
|
+
- `withCommit` for transaction, outbox, event collection, and post-commit cleanup
|
|
149
|
+
- `UnitOfWork` for repository registration and registration
|
|
149
150
|
- outbox dispatcher, projection, event-store, and snapshot ports
|
|
150
151
|
- contract tests for repository and outbox adapters
|
|
151
152
|
|
|
@@ -185,7 +186,7 @@ first adapter or aggregate.
|
|
|
185
186
|
| Repository contracts and Identity Map | [Repository](./docs/guide/repository.md) |
|
|
186
187
|
| Transaction-scoped repositories | [Unit of Work](./docs/guide/unit-of-work.md) |
|
|
187
188
|
| Duplicate-safe commands and inbox handling | [Command Idempotency](./docs/guide/idempotency.md) |
|
|
188
|
-
| Reliable event
|
|
189
|
+
| Reliable event collection and delivery | [Outbox & Transactions](./docs/guide/outbox.md) |
|
|
189
190
|
| Read models and projectors | [Projections](./docs/guide/projections.md) |
|
|
190
191
|
| Event schema changes | [Event Upcasting](./docs/guide/event-upcasting.md) |
|
|
191
192
|
| Optimistic concurrency | [Concurrency](./docs/guide/concurrency.md) |
|
|
@@ -213,6 +214,10 @@ packages side by side until those API-based tools support TypeScript 7.
|
|
|
213
214
|
Tests and package builds run through Vite+ (`pnpm test`, `pnpm build`). Biome
|
|
214
215
|
remains the repository's lint and format policy.
|
|
215
216
|
|
|
217
|
+
A change of the public API follows the [stability policy](./STABILITY.md):
|
|
218
|
+
breaking changes only in a major version, a deprecation before a removal, and
|
|
219
|
+
a pull request description that says whether a change is breaking.
|
|
220
|
+
|
|
216
221
|
Bug reports, questions, and pull requests are welcome on
|
|
217
222
|
[GitHub](https://github.com/shi-rudo/ddd-kit-ts). Please open pull requests
|
|
218
223
|
against `main`.
|
|
@@ -331,7 +331,7 @@ declare class InvalidCommandMessageError extends InfrastructureError<"INVALID_CO
|
|
|
331
331
|
* input at the application edge; model genuinely arbitrary keys with a
|
|
332
332
|
* `Map`, not a plain object.
|
|
333
333
|
*/
|
|
334
|
-
declare class
|
|
334
|
+
declare class PrototypePollutionError extends KitWiringError<"PROTOTYPE_POLLUTION"> {
|
|
335
335
|
readonly key: string;
|
|
336
336
|
constructor(key: string, subject?: string);
|
|
337
337
|
}
|
|
@@ -477,22 +477,21 @@ declare class SnapshotCorruptedError extends InfrastructureError<"SNAPSHOT_CORRU
|
|
|
477
477
|
}
|
|
478
478
|
/**
|
|
479
479
|
* Thrown when an event reaches the aggregate's recording paths
|
|
480
|
-
* (`apply`, `setState`, `addDomainEvent`) without having been
|
|
481
|
-
* the kit's constructors: `createDomainEvent`,
|
|
482
|
-
*
|
|
483
|
-
* aggregate `createEvent` helper. Those constructors deep-freeze the
|
|
480
|
+
* (`apply`, `setState`, `addDomainEvent`) without having been built by
|
|
481
|
+
* the kit's constructors: `createDomainEvent`, `createStampedDomainEvent`, or
|
|
482
|
+
* the aggregate `createEvent` helper. Those constructors deep-freeze the
|
|
484
483
|
* event, defensively copy payload and metadata, and mark the result as
|
|
485
|
-
*
|
|
484
|
+
* kit-built. The mark has two tiers: a
|
|
486
485
|
* module-private one for events of this loaded copy of the kit, and a
|
|
487
|
-
* cooperative `Symbol.for` brand that a second loaded copy
|
|
486
|
+
* cooperative `Symbol.for` brand that a second loaded copy applies and
|
|
488
487
|
* recognizes. Anything else (a hand-rolled literal, a shallow-frozen
|
|
489
488
|
* copy with mutable nested data) is rejected: a mutable event recorded
|
|
490
489
|
* next to a state change can silently diverge from it afterwards. A
|
|
491
490
|
* wiring error: deterministic bug at the call site, the remedy is
|
|
492
|
-
*
|
|
491
|
+
* building through the constructors. The gate catches accidents, not
|
|
493
492
|
* adversaries: code in the same process can fake the brand.
|
|
494
493
|
*/
|
|
495
|
-
declare class
|
|
494
|
+
declare class HandBuiltEventError extends KitWiringError<"HAND_BUILT_EVENT"> {
|
|
496
495
|
constructor(eventType: string);
|
|
497
496
|
}
|
|
498
497
|
/** Constructor options for {@link ReentrantEventRecordingError}. */
|
|
@@ -504,12 +503,12 @@ interface ReentrantEventRecordingErrorOptions {
|
|
|
504
503
|
};
|
|
505
504
|
}
|
|
506
505
|
/**
|
|
507
|
-
* Thrown by `
|
|
506
|
+
* Thrown by `stampPendingEvents` when the aggregate's pending-event list
|
|
508
507
|
* changes while its events are being stamped: a stamp provider that
|
|
509
508
|
* directly or transitively triggers a new decision on the same aggregate
|
|
510
509
|
* would otherwise have that decision silently discarded when recording
|
|
511
510
|
* replaces the pending list. Recording is atomic: when this guard fires,
|
|
512
|
-
* every decision (including the re-entrant one) remains
|
|
511
|
+
* every decision (including the re-entrant one) remains unstamped. A
|
|
513
512
|
* wiring error: deterministic bug at the call site, the remedy is keeping
|
|
514
513
|
* stamp providers free of domain decisions.
|
|
515
514
|
*/
|
|
@@ -529,10 +528,10 @@ interface DuplicateEventIdErrorOptions {
|
|
|
529
528
|
}
|
|
530
529
|
/**
|
|
531
530
|
* Thrown when two facts of one aggregate would carry the same `eventId`.
|
|
532
|
-
* Two causes, two sites: the aggregate rejects a
|
|
531
|
+
* Two causes, two sites: the aggregate rejects a stamped event that is
|
|
533
532
|
* already pending at the append, before the state moves; and
|
|
534
|
-
* `
|
|
535
|
-
* stamp (or repeats an explicit id). Either would
|
|
533
|
+
* `stampPendingEvents` rejects a stamp provider that returns one reused
|
|
534
|
+
* stamp (or repeats an explicit id). Either would create two distinct facts
|
|
536
535
|
* sharing one identity, and downstream idempotent consumers keyed on
|
|
537
536
|
* `eventId` silently drop one of them. A wiring error: deterministic bug at
|
|
538
537
|
* the append site or in the stamp provider, the remedy is one fresh
|
|
@@ -593,7 +592,7 @@ interface PendingEventBatchMismatchErrorOptions {
|
|
|
593
592
|
* pending event at the same position. Acknowledging such a batch would
|
|
594
593
|
* drop decisions the commit never persisted or keep events it did. The
|
|
595
594
|
* pending list stays untouched. A wiring error in application commit
|
|
596
|
-
* orchestration: acknowledge exactly the batch that was
|
|
595
|
+
* orchestration: acknowledge exactly the batch that was registered, once.
|
|
597
596
|
*/
|
|
598
597
|
declare class PendingEventBatchMismatchError extends KitWiringError<"PENDING_EVENT_BATCH_MISMATCH"> {
|
|
599
598
|
readonly identity: PendingEventBatchMismatchErrorOptions["identity"];
|
|
@@ -781,9 +780,9 @@ declare class ReplayRejectedError extends InfrastructureError<"REPLAY_REJECTED">
|
|
|
781
780
|
constructor(options: ReplayRejectedErrorOptions);
|
|
782
781
|
}
|
|
783
782
|
/**
|
|
784
|
-
* Thrown when an event
|
|
783
|
+
* Thrown when an event collected from an aggregate cannot be safely composed
|
|
785
784
|
* into a commit envelope, or when an outbox can prove that accepting a
|
|
786
|
-
* candidate would violate its event identity/source chain.
|
|
785
|
+
* candidate would violate its event identity/source chain. Collect failures
|
|
787
786
|
* include missing `aggregateId` / `aggregateType` (downstream routing would
|
|
788
787
|
* break), or an
|
|
789
788
|
* eventful persisted aggregate did not advance its version (two commits
|
|
@@ -799,7 +798,7 @@ declare class ReplayRejectedError extends InfrastructureError<"REPLAY_REJECTED">
|
|
|
799
798
|
* `UnitOfWork.run` passes it through unchanged instead of wrapping it in
|
|
800
799
|
* `CommitError`.
|
|
801
800
|
*/
|
|
802
|
-
declare class
|
|
801
|
+
declare class EventCollectionError extends KitWiringError<"EVENT_COLLECTION_FAILED"> {
|
|
803
802
|
/** The `type` of the offending event, for programmatic routing. */
|
|
804
803
|
readonly eventType?: string | undefined;
|
|
805
804
|
constructor(message: string,
|
|
@@ -918,8 +917,8 @@ declare class ErrorMapperFailedError extends KitWiringError<"ERROR_MAPPER_FAILED
|
|
|
918
917
|
readonly mapperCause: unknown;
|
|
919
918
|
constructor(options: ErrorMapperFailedErrorOptions);
|
|
920
919
|
}
|
|
921
|
-
/** Constructor options for {@link
|
|
922
|
-
interface
|
|
920
|
+
/** Constructor options for {@link UnregisteredChangesError}. */
|
|
921
|
+
interface UnregisteredChangesErrorOptions {
|
|
923
922
|
/** The aggregate the error names. */
|
|
924
923
|
readonly identity: {
|
|
925
924
|
readonly aggregateType: string;
|
|
@@ -951,9 +950,9 @@ interface UnenrolledChangesErrorOptions {
|
|
|
951
950
|
* message names the rule instead: a loaded append-only aggregate must not
|
|
952
951
|
* change.
|
|
953
952
|
*/
|
|
954
|
-
declare class
|
|
955
|
-
readonly identity:
|
|
956
|
-
constructor(options:
|
|
953
|
+
declare class UnregisteredChangesError extends KitWiringError<"UNREGISTERED_CHANGES"> {
|
|
954
|
+
readonly identity: UnregisteredChangesErrorOptions["identity"];
|
|
955
|
+
constructor(options: UnregisteredChangesErrorOptions);
|
|
957
956
|
}
|
|
958
957
|
/** Constructor options for {@link AggregateDeletedError}. */
|
|
959
958
|
interface AggregateDeletedErrorOptions {
|
|
@@ -1128,7 +1127,7 @@ type ConcurrencyConflictErrorOptions = {
|
|
|
1128
1127
|
* **Retry means a FRESH unit of work** (a new `UnitOfWork.run()` /
|
|
1129
1128
|
* `withCommit` invocation): reload, re-apply, and register `update` again. Do NOT catch this
|
|
1130
1129
|
* inside the same `run()` callback and continue: the failed aggregate
|
|
1131
|
-
* is already
|
|
1130
|
+
* is already registered (its events would be committed for a write that
|
|
1132
1131
|
* never happened) and the identity map still serves the same stale
|
|
1133
1132
|
* instance to any in-place "reload".
|
|
1134
1133
|
*
|
|
@@ -1254,7 +1253,7 @@ declare class IdempotencyCompletionWithoutClaimError extends KitWiringError<"IDE
|
|
|
1254
1253
|
* base-error `matchError` cases that cover kit and consumer codes
|
|
1255
1254
|
* together, without importing anything from base-error.
|
|
1256
1255
|
*/
|
|
1257
|
-
type KitErrorCode = "AGGREGATE_DELETED" | "AGGREGATE_NOT_FOUND" | "AGGREGATE_TRACKING" | "CAPABILITY_REGISTRY_CONFLICT" | "COMMIT_FAILED" | "CONCURRENCY_CONFLICT" | "DIRECT_STATE_MUTATION" | "DOMAIN_TRANSITION_GUARD_REJECTED" | "DUPLICATE_AGGREGATE" | "DUPLICATE_EVENT_ID" | "DUPLICATE_HANDLER_REGISTRATION" | "ERROR_MAPPER_FAILED" | "EVENT_AGGREGATE_IDENTITY_INVALID" | "EVENT_BUS_CLOSED" | "
|
|
1256
|
+
type KitErrorCode = "AGGREGATE_DELETED" | "AGGREGATE_NOT_FOUND" | "AGGREGATE_TRACKING" | "CAPABILITY_REGISTRY_CONFLICT" | "COMMIT_FAILED" | "CONCURRENCY_CONFLICT" | "DIRECT_STATE_MUTATION" | "DOMAIN_TRANSITION_GUARD_REJECTED" | "DUPLICATE_AGGREGATE" | "DUPLICATE_EVENT_ID" | "DUPLICATE_HANDLER_REGISTRATION" | "ERROR_MAPPER_FAILED" | "EVENT_AGGREGATE_IDENTITY_INVALID" | "EVENT_BUS_CLOSED" | "EVENT_COLLECTION_FAILED" | "EVENT_ID_INVALID" | "EVENT_ID_REQUIRED" | "EVENT_OCCURRED_AT_INVALID" | "EVENT_OCCURRED_AT_REQUIRED" | "EVENT_SCHEMA_VERSION_INVALID" | "EVENT_TYPE_INVALID" | "FOLD_RETURNED_NO_STATE" | "FOREIGN_EVENT" | "PROTOTYPE_POLLUTION" | "IDEMPOTENCY_CLAIM_LOST" | "IDEMPOTENCY_COMPLETED_WITHOUT_CLAIM" | "IDEMPOTENCY_IN_FLIGHT" | "IDEMPOTENCY_KEY_REUSE" | "IDEMPOTENCY_RECONCILIATION_REQUIRED" | "IN_MEMORY_CAPACITY_EXCEEDED" | "INVALID_DOMAIN_MACHINE_CONTEXT" | "INVALID_DOMAIN_MACHINE_DEFINITION" | "INVALID_DOMAIN_MACHINE_INPUT" | "INVALID_DOMAIN_MACHINE_SNAPSHOT" | "INVALID_DOMAIN_TRANSITION" | "INVALID_DOMAIN_TRANSITION_GUARD_RESULT" | "INVALID_DOMAIN_TRANSITION_RESULT" | "INVALID_COMMAND_MESSAGE" | "INVALID_EVENT_STREAM_PAGE" | "INVALID_FLUSH_STATEMENT" | "INVALID_INTEGRATION_MESSAGE" | "INVALID_MONEY" | "INVALID_REPOSITORY_ADAPTER" | "INVALID_REPOSITORY_DEFINITION" | "INVALID_VERSION" | "MISATTRIBUTED_EVENT" | "MISSING_ENTITY_ID" | "MISSING_FOLD" | "MISSING_HANDLER" | "MONEY_CURRENCY_MISMATCH" | "MONEY_PRECISION_LOSS" | "MONEY_SCALE_MISMATCH" | "NESTED_UNIT_OF_WORK" | "PENDING_EVENT_BATCH_MISMATCH" | "PENDING_EVENT_LIMIT_EXCEEDED" | "PROJECTION_GAP" | "PROJECTION_IDENTITY_VIOLATION" | "PROJECTION_ORDER_VIOLATION" | "PROJECTION_RECEIPT_VIOLATION" | "PUBLISH_DEPTH_EXCEEDED" | "REENTRANT_DOMAIN_STATE_MACHINE_EVALUATION" | "REENTRANT_EVENT_RECORDING" | "REPLAY_REJECTED" | "REPLAY_TARGET_MISMATCH" | "REPOSITORY_ERROR_MAPPING_FAILED" | "ROLLBACK_FAILED" | "SNAPSHOT_CORRUPTED" | "SNAPSHOT_SCHEMA_MISMATCH" | "SNAPSHOT_TIME_INVALID" | "SNAPSHOT_VERSION_NOT_RESTORED" | "TRANSACTION_CLOSED" | "UNREGISTERED_CHANGES" | "UNKNOWN_CURRENCY" | "UNMANAGED_INSTANCE" | "HAND_BUILT_EVENT" | "UNPROJECTABLE_EVENT" | "UNREGISTERED_HANDLER" | "UNREPLAYABLE_AGGREGATE";
|
|
1258
1257
|
//#endregion
|
|
1259
|
-
export { PendingEventLimitExceededErrorOptions as $, IdempotencyInFlightErrorOptions as A, InvalidEventStreamPageErrorOptions as B, FoldReturnedNoStateError as C, UnreplayableAggregateError as Ct, IdempotencyClaimLostErrorOptions as D, isWiringErrorLike as Dt, IdempotencyClaimLostError as E, isInfrastructureErrorLike as Et, InMemoryCapacityExceededError as F, KitWiringError as G, InvalidVersionError as H, InMemoryCapacityExceededErrorOptions as I, MissingFoldError as J, MisattributedEventError as K, InfrastructureError as L, IdempotencyKeyReuseErrorOptions as M, IdempotencyReconciliationRequiredError as N, IdempotencyCompletionWithoutClaimError as O, IdempotencyReconciliationRequiredErrorOptions as P, PendingEventLimitExceededError as Q, InvalidCommandMessageError as R, EventStreamPageReason as S, UnregisteredHandlerErrorOptions as St,
|
|
1258
|
+
export { PendingEventLimitExceededErrorOptions as $, IdempotencyInFlightErrorOptions as A, InvalidEventStreamPageErrorOptions as B, FoldReturnedNoStateError as C, UnreplayableAggregateError as Ct, IdempotencyClaimLostErrorOptions as D, isWiringErrorLike as Dt, IdempotencyClaimLostError as E, isInfrastructureErrorLike as Et, InMemoryCapacityExceededError as F, KitWiringError as G, InvalidVersionError as H, InMemoryCapacityExceededErrorOptions as I, MissingFoldError as J, MisattributedEventError as K, InfrastructureError as L, IdempotencyKeyReuseErrorOptions as M, IdempotencyReconciliationRequiredError as N, IdempotencyCompletionWithoutClaimError as O, IdempotencyReconciliationRequiredErrorOptions as P, PendingEventLimitExceededError as Q, InvalidCommandMessageError as R, EventStreamPageReason as S, UnregisteredHandlerErrorOptions as St, HandBuiltEventError as T, isDomainErrorLike as Tt, KitErrorCode as U, InvalidIntegrationMessageError as V, KitErrorOptions as W, PendingEventBatchMismatchError as X, MissingHandlerError as Y, PendingEventBatchMismatchErrorOptions as Z, DuplicateHandlerRegistrationError as _, UnmanagedInstanceError as _t, AggregateNotFoundErrorOptions as a, ReentrantEventRecordingError as at, ErrorMapperFailedErrorOptions as b, UnregisteredChangesErrorOptions as bt, ConcurrencyConflictErrorOptions as c, ReplayRejectedErrorOptions as ct, DirectStateMutationErrorOptions as d, ReplayTargetMismatchReason as dt, ProjectionGapError as et, DomainError as f, SnapshotCorruptedError as ft, DuplicateEventIdErrorOptions as g, SnapshotVersionNotRestoredErrorOptions as gt, DuplicateEventIdError as h, SnapshotVersionNotRestoredError as ht, AggregateNotFoundError as i, PrototypePollutionError as it, IdempotencyKeyReuseError as j, IdempotencyInFlightError as k, ConcurrencyConflictReason as l, ReplayTargetMismatchError as lt, DuplicateAggregateErrorOptions as m, SnapshotSchemaMismatchErrorOptions as mt, AggregateDeletedErrorOptions as n, ProjectionOrderViolationError as nt, CapabilityRegistryConflictError as o, ReentrantEventRecordingErrorOptions as ot, DuplicateAggregateError as p, SnapshotSchemaMismatchError as pt, MissingEntityIdError as q, AggregateIdentityMismatchOptions as r, ProjectionReceiptViolationError as rt, ConcurrencyConflictError as s, ReplayRejectedError as st, AggregateDeletedError as t, ProjectionIdentityViolationError as tt, DirectStateMutationError as u, ReplayTargetMismatchErrorOptions as ut, DuplicateHandlerRegistrationErrorOptions as v, UnprojectableEventError as vt, ForeignEventError as w, UnreplayableAggregateErrorOptions as wt, EventCollectionError as x, UnregisteredHandlerError as xt, ErrorMapperFailedError as y, UnregisteredChangesError as yt, InvalidEventStreamPageError as z };
|
|
1260
1259
|
//# sourceMappingURL=kit-errors.d.ts.map
|
|
@@ -282,7 +282,7 @@ var DirectStateMutationError = class extends KitWiringError {
|
|
|
282
282
|
identity;
|
|
283
283
|
constructor(options) {
|
|
284
284
|
super("DIRECT_STATE_MUTATION", `Aggregate ${describeAggregateIdentity(options.identity)} is event-sourced: its state changes only through apply(). Record the fact as an event and fold it in a handler instead of calling setState.`);
|
|
285
|
-
this.identity =
|
|
285
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
286
286
|
}
|
|
287
287
|
};
|
|
288
288
|
/**
|
|
@@ -451,10 +451,10 @@ var InvalidCommandMessageError = class extends InfrastructureError {
|
|
|
451
451
|
* input at the application edge; model genuinely arbitrary keys with a
|
|
452
452
|
* `Map`, not a plain object.
|
|
453
453
|
*/
|
|
454
|
-
var
|
|
454
|
+
var PrototypePollutionError = class extends KitWiringError {
|
|
455
455
|
key;
|
|
456
456
|
constructor(key, subject = "Entity state") {
|
|
457
|
-
super("
|
|
457
|
+
super("PROTOTYPE_POLLUTION", `${subject} carries an own "${key}" key, a prototype-pollution payload that can never be legitimate domain data. Validate and strip untrusted input at the boundary, or model arbitrary keys with a Map.`);
|
|
458
458
|
this.key = key;
|
|
459
459
|
}
|
|
460
460
|
};
|
|
@@ -520,7 +520,7 @@ var UnreplayableAggregateError = class extends KitWiringError {
|
|
|
520
520
|
identity;
|
|
521
521
|
constructor(options) {
|
|
522
522
|
super("UNREPLAYABLE_AGGREGATE", `Cannot replay onto aggregate ${describeAggregateIdentity(options.identity)}: ${options.reason}. Reconstitute on a fresh instance (no factory-recorded events, no unpersisted mutations).`);
|
|
523
|
-
this.identity =
|
|
523
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
524
524
|
}
|
|
525
525
|
};
|
|
526
526
|
/**
|
|
@@ -537,13 +537,13 @@ function describeAggregateIdentity(identity) {
|
|
|
537
537
|
* properties into the log. Kit modules only; not part of the package
|
|
538
538
|
* entries.
|
|
539
539
|
*/
|
|
540
|
-
function
|
|
540
|
+
function copyAggregateIdentity(identity) {
|
|
541
541
|
return Object.freeze({
|
|
542
542
|
aggregateType: identity.aggregateType,
|
|
543
543
|
aggregateId: identity.aggregateId
|
|
544
544
|
});
|
|
545
545
|
}
|
|
546
|
-
function
|
|
546
|
+
function copyPartialAggregateIdentity(identity) {
|
|
547
547
|
return Object.freeze({
|
|
548
548
|
...identity.aggregateType === void 0 ? {} : { aggregateType: identity.aggregateType },
|
|
549
549
|
...identity.aggregateId === void 0 ? {} : { aggregateId: identity.aggregateId }
|
|
@@ -577,8 +577,8 @@ var MisattributedEventError = class extends KitWiringError {
|
|
|
577
577
|
eventType;
|
|
578
578
|
constructor(options) {
|
|
579
579
|
super("MISATTRIBUTED_EVENT", `New event "${options.eventType}" belongs to ${describeEventIdentity(options)} but was applied on ${describeAggregateIdentity(options.expected)}: fix the call site (createEvent stamps the right identity).`);
|
|
580
|
-
this.expected =
|
|
581
|
-
this.actual =
|
|
580
|
+
this.expected = copyAggregateIdentity(options.expected);
|
|
581
|
+
this.actual = copyPartialAggregateIdentity(options.actual);
|
|
582
582
|
this.eventType = options.eventType;
|
|
583
583
|
}
|
|
584
584
|
};
|
|
@@ -596,7 +596,7 @@ var SnapshotVersionNotRestoredError = class extends KitWiringError {
|
|
|
596
596
|
restoredVersion;
|
|
597
597
|
constructor(options) {
|
|
598
598
|
super("SNAPSHOT_VERSION_NOT_RESTORED", `SnapshotModel.reconstitute for ${describeAggregateIdentity(options.identity)} returned an aggregate at version ${options.restoredVersion} for a snapshot at version ${options.snapshotVersion}. Reconstitution must restore the persisted version; call markReconstituted(version) inside the aggregate factory.`);
|
|
599
|
-
this.identity =
|
|
599
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
600
600
|
this.snapshotVersion = options.snapshotVersion;
|
|
601
601
|
this.restoredVersion = options.restoredVersion;
|
|
602
602
|
}
|
|
@@ -622,49 +622,48 @@ var SnapshotCorruptedError = class extends InfrastructureError {
|
|
|
622
622
|
};
|
|
623
623
|
/**
|
|
624
624
|
* Thrown when an event reaches the aggregate's recording paths
|
|
625
|
-
* (`apply`, `setState`, `addDomainEvent`) without having been
|
|
626
|
-
* the kit's constructors: `createDomainEvent`,
|
|
627
|
-
*
|
|
628
|
-
* aggregate `createEvent` helper. Those constructors deep-freeze the
|
|
625
|
+
* (`apply`, `setState`, `addDomainEvent`) without having been built by
|
|
626
|
+
* the kit's constructors: `createDomainEvent`, `createStampedDomainEvent`, or
|
|
627
|
+
* the aggregate `createEvent` helper. Those constructors deep-freeze the
|
|
629
628
|
* event, defensively copy payload and metadata, and mark the result as
|
|
630
|
-
*
|
|
629
|
+
* kit-built. The mark has two tiers: a
|
|
631
630
|
* module-private one for events of this loaded copy of the kit, and a
|
|
632
|
-
* cooperative `Symbol.for` brand that a second loaded copy
|
|
631
|
+
* cooperative `Symbol.for` brand that a second loaded copy applies and
|
|
633
632
|
* recognizes. Anything else (a hand-rolled literal, a shallow-frozen
|
|
634
633
|
* copy with mutable nested data) is rejected: a mutable event recorded
|
|
635
634
|
* next to a state change can silently diverge from it afterwards. A
|
|
636
635
|
* wiring error: deterministic bug at the call site, the remedy is
|
|
637
|
-
*
|
|
636
|
+
* building through the constructors. The gate catches accidents, not
|
|
638
637
|
* adversaries: code in the same process can fake the brand.
|
|
639
638
|
*/
|
|
640
|
-
var
|
|
639
|
+
var HandBuiltEventError = class extends KitWiringError {
|
|
641
640
|
constructor(eventType) {
|
|
642
|
-
super("
|
|
641
|
+
super("HAND_BUILT_EVENT", `Event "${eventType}" was not built by a domain-event constructor or aggregate createEvent(...) helper. Those constructors deep-freeze the event and defensively copy payload and metadata; a mutable event could diverge from the state change it records.`);
|
|
643
642
|
}
|
|
644
643
|
};
|
|
645
644
|
/**
|
|
646
|
-
* Thrown by `
|
|
645
|
+
* Thrown by `stampPendingEvents` when the aggregate's pending-event list
|
|
647
646
|
* changes while its events are being stamped: a stamp provider that
|
|
648
647
|
* directly or transitively triggers a new decision on the same aggregate
|
|
649
648
|
* would otherwise have that decision silently discarded when recording
|
|
650
649
|
* replaces the pending list. Recording is atomic: when this guard fires,
|
|
651
|
-
* every decision (including the re-entrant one) remains
|
|
650
|
+
* every decision (including the re-entrant one) remains unstamped. A
|
|
652
651
|
* wiring error: deterministic bug at the call site, the remedy is keeping
|
|
653
652
|
* stamp providers free of domain decisions.
|
|
654
653
|
*/
|
|
655
654
|
var ReentrantEventRecordingError = class extends KitWiringError {
|
|
656
655
|
identity;
|
|
657
656
|
constructor(options) {
|
|
658
|
-
super("REENTRANT_EVENT_RECORDING", `Pending events of aggregate ${describeAggregateIdentity(options.identity)} changed while
|
|
659
|
-
this.identity =
|
|
657
|
+
super("REENTRANT_EVENT_RECORDING", `Pending events of aggregate ${describeAggregateIdentity(options.identity)} changed while stampPendingEvents was stamping them. A stamp provider must not trigger new decisions on the aggregate being recorded; make every domain decision first, then stamp.`);
|
|
658
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
660
659
|
}
|
|
661
660
|
};
|
|
662
661
|
/**
|
|
663
662
|
* Thrown when two facts of one aggregate would carry the same `eventId`.
|
|
664
|
-
* Two causes, two sites: the aggregate rejects a
|
|
663
|
+
* Two causes, two sites: the aggregate rejects a stamped event that is
|
|
665
664
|
* already pending at the append, before the state moves; and
|
|
666
|
-
* `
|
|
667
|
-
* stamp (or repeats an explicit id). Either would
|
|
665
|
+
* `stampPendingEvents` rejects a stamp provider that returns one reused
|
|
666
|
+
* stamp (or repeats an explicit id). Either would create two distinct facts
|
|
668
667
|
* sharing one identity, and downstream idempotent consumers keyed on
|
|
669
668
|
* `eventId` silently drop one of them. A wiring error: deterministic bug at
|
|
670
669
|
* the append site or in the stamp provider, the remedy is one fresh
|
|
@@ -675,8 +674,8 @@ var DuplicateEventIdError = class extends KitWiringError {
|
|
|
675
674
|
/** The event id two pending events would have shared. */
|
|
676
675
|
eventId;
|
|
677
676
|
constructor(options) {
|
|
678
|
-
super("DUPLICATE_EVENT_ID", `Two pending events of aggregate ${describeAggregateIdentity(options.identity)} carry the same eventId "${options.eventId}". Each fact needs its own event id: append a
|
|
679
|
-
this.identity =
|
|
677
|
+
super("DUPLICATE_EVENT_ID", `Two pending events of aggregate ${describeAggregateIdentity(options.identity)} carry the same eventId "${options.eventId}". Each fact needs its own event id: append a stamped event once, and return a fresh stamp per decision from the stamp provider.`);
|
|
678
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
680
679
|
this.eventId = options.eventId;
|
|
681
680
|
}
|
|
682
681
|
};
|
|
@@ -696,7 +695,7 @@ var PendingEventLimitExceededError = class extends KitWiringError {
|
|
|
696
695
|
added;
|
|
697
696
|
constructor(options) {
|
|
698
697
|
super("PENDING_EVENT_LIMIT_EXCEEDED", `Aggregate ${describeAggregateIdentity(options.identity)} holds ${options.pending} pending event(s) and cannot record ${options.added} more: maxPendingEvents is ${options.limit}. A decision that emits this many facts points at a missing aggregate boundary.`);
|
|
699
|
-
this.identity =
|
|
698
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
700
699
|
this.limit = options.limit;
|
|
701
700
|
this.pending = options.pending;
|
|
702
701
|
this.added = options.added;
|
|
@@ -709,15 +708,15 @@ var PendingEventLimitExceededError = class extends KitWiringError {
|
|
|
709
708
|
* pending event at the same position. Acknowledging such a batch would
|
|
710
709
|
* drop decisions the commit never persisted or keep events it did. The
|
|
711
710
|
* pending list stays untouched. A wiring error in application commit
|
|
712
|
-
* orchestration: acknowledge exactly the batch that was
|
|
711
|
+
* orchestration: acknowledge exactly the batch that was registered, once.
|
|
713
712
|
*/
|
|
714
713
|
var PendingEventBatchMismatchError = class extends KitWiringError {
|
|
715
714
|
identity;
|
|
716
715
|
batchLength;
|
|
717
716
|
pendingLength;
|
|
718
717
|
constructor(options) {
|
|
719
|
-
super("PENDING_EVENT_BATCH_MISMATCH", `The committed batch of ${options.batchLength} event(s) is no longer the pending prefix of aggregate ${describeAggregateIdentity(options.identity)} (${options.pendingLength} pending). Acknowledge exactly the batch that was
|
|
720
|
-
this.identity =
|
|
718
|
+
super("PENDING_EVENT_BATCH_MISMATCH", `The committed batch of ${options.batchLength} event(s) is no longer the pending prefix of aggregate ${describeAggregateIdentity(options.identity)} (${options.pendingLength} pending). Acknowledge exactly the batch that was registered, once.`);
|
|
719
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
721
720
|
this.batchLength = options.batchLength;
|
|
722
721
|
this.pendingLength = options.pendingLength;
|
|
723
722
|
}
|
|
@@ -750,8 +749,8 @@ var ForeignEventError = class extends InfrastructureError {
|
|
|
750
749
|
code: "FOREIGN_EVENT",
|
|
751
750
|
message: `Persisted event "${options.eventType}" belongs to ${describeEventIdentity(options)}, not to ${describeAggregateIdentity(options.expected)}: the stream row belongs to a different aggregate.`
|
|
752
751
|
});
|
|
753
|
-
this.expected =
|
|
754
|
-
this.actual =
|
|
752
|
+
this.expected = copyAggregateIdentity(options.expected);
|
|
753
|
+
this.actual = copyPartialAggregateIdentity(options.actual);
|
|
755
754
|
this.eventType = options.eventType;
|
|
756
755
|
}
|
|
757
756
|
};
|
|
@@ -815,7 +814,7 @@ var InvalidEventStreamPageError = class extends InfrastructureError {
|
|
|
815
814
|
code: "INVALID_EVENT_STREAM_PAGE",
|
|
816
815
|
message: eventStreamPageReasonMessage(stream, options)
|
|
817
816
|
});
|
|
818
|
-
this.identity =
|
|
817
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
819
818
|
this.reason = options.reason;
|
|
820
819
|
this.fromVersion = options.fromVersion;
|
|
821
820
|
this.targetVersion = options.targetVersion;
|
|
@@ -863,7 +862,7 @@ var ReplayTargetMismatchError = class extends InfrastructureError {
|
|
|
863
862
|
code: "REPLAY_TARGET_MISMATCH",
|
|
864
863
|
message
|
|
865
864
|
});
|
|
866
|
-
this.identity =
|
|
865
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
867
866
|
this.reason = options.reason;
|
|
868
867
|
this.fromVersion = options.fromVersion;
|
|
869
868
|
this.targetVersion = options.targetVersion;
|
|
@@ -893,15 +892,15 @@ var ReplayRejectedError = class extends InfrastructureError {
|
|
|
893
892
|
message: options.fromVersion === options.toVersion ? `The replay target of ${stream} rejected an empty history at version ${options.fromVersion} with ${rejected}` : `The aggregate ${stream} rejected a stored event in the page (${options.fromVersion}, ${options.toVersion}] with ${rejected}`,
|
|
894
893
|
cause: options.cause
|
|
895
894
|
});
|
|
896
|
-
this.identity =
|
|
895
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
897
896
|
this.fromVersion = options.fromVersion;
|
|
898
897
|
this.toVersion = options.toVersion;
|
|
899
898
|
}
|
|
900
899
|
};
|
|
901
900
|
/**
|
|
902
|
-
* Thrown when an event
|
|
901
|
+
* Thrown when an event collected from an aggregate cannot be safely composed
|
|
903
902
|
* into a commit envelope, or when an outbox can prove that accepting a
|
|
904
|
-
* candidate would violate its event identity/source chain.
|
|
903
|
+
* candidate would violate its event identity/source chain. Collect failures
|
|
905
904
|
* include missing `aggregateId` / `aggregateType` (downstream routing would
|
|
906
905
|
* break), or an
|
|
907
906
|
* eventful persisted aggregate did not advance its version (two commits
|
|
@@ -917,10 +916,10 @@ var ReplayRejectedError = class extends InfrastructureError {
|
|
|
917
916
|
* `UnitOfWork.run` passes it through unchanged instead of wrapping it in
|
|
918
917
|
* `CommitError`.
|
|
919
918
|
*/
|
|
920
|
-
var
|
|
919
|
+
var EventCollectionError = class extends KitWiringError {
|
|
921
920
|
eventType;
|
|
922
921
|
constructor(message, eventType) {
|
|
923
|
-
super("
|
|
922
|
+
super("EVENT_COLLECTION_FAILED", message);
|
|
924
923
|
this.eventType = eventType;
|
|
925
924
|
}
|
|
926
925
|
};
|
|
@@ -963,8 +962,8 @@ var UnmanagedInstanceError = class extends KitWiringError {
|
|
|
963
962
|
* helpers. One implementation so the contract cannot drift.
|
|
964
963
|
* Module-internal export; not part of the package entries.
|
|
965
964
|
*/
|
|
966
|
-
function
|
|
967
|
-
if (Object.hasOwn(value, "__proto__")) throw new
|
|
965
|
+
function assertNoOwnProtoKey(value, subject) {
|
|
966
|
+
if (Object.hasOwn(value, "__proto__")) throw new PrototypePollutionError("__proto__", subject);
|
|
968
967
|
}
|
|
969
968
|
/**
|
|
970
969
|
* Produced by the in-memory `CommandBus` / `QueryBus` when a message is
|
|
@@ -1055,11 +1054,11 @@ var ErrorMapperFailedError = class extends KitWiringError {
|
|
|
1055
1054
|
* message names the rule instead: a loaded append-only aggregate must not
|
|
1056
1055
|
* change.
|
|
1057
1056
|
*/
|
|
1058
|
-
var
|
|
1057
|
+
var UnregisteredChangesError = class extends KitWiringError {
|
|
1059
1058
|
identity;
|
|
1060
1059
|
constructor(options) {
|
|
1061
|
-
super("
|
|
1062
|
-
this.identity =
|
|
1060
|
+
super("UNREGISTERED_CHANGES", `Aggregate ${describeAggregateIdentity(options.identity)} was loaded and changed in this unit of work, ` + (options.appendOnly ? "but its repository is append-only and installs no update. An append-only aggregate must not change after add." : "but no update intent was registered. Call repository.update(aggregate) after the final domain decision so state and events flush together."));
|
|
1061
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
1063
1062
|
}
|
|
1064
1063
|
};
|
|
1065
1064
|
/**
|
|
@@ -1076,7 +1075,7 @@ var AggregateDeletedError = class extends KitWiringError {
|
|
|
1076
1075
|
identity;
|
|
1077
1076
|
constructor(options) {
|
|
1078
1077
|
super("AGGREGATE_DELETED", `Aggregate ${describeAggregateIdentity(options.identity)} was removed in this unit of work and cannot be added, updated, tracked, or removed through another instance again. Removal is final within an operation. A repeated remove of the SAME instance is an accepted no-op; if the aggregate must remain, do not remove it.`);
|
|
1079
|
-
this.identity =
|
|
1078
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
1080
1079
|
}
|
|
1081
1080
|
};
|
|
1082
1081
|
var AggregateNotFoundError = class extends InfrastructureError {
|
|
@@ -1087,7 +1086,7 @@ var AggregateNotFoundError = class extends InfrastructureError {
|
|
|
1087
1086
|
message: `Aggregate not found: ${describeAggregateIdentity(options.identity)}`,
|
|
1088
1087
|
cause: options.cause
|
|
1089
1088
|
});
|
|
1090
|
-
this.identity =
|
|
1089
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
1091
1090
|
}
|
|
1092
1091
|
};
|
|
1093
1092
|
var DuplicateAggregateError = class extends InfrastructureError {
|
|
@@ -1098,7 +1097,7 @@ var DuplicateAggregateError = class extends InfrastructureError {
|
|
|
1098
1097
|
message: `Duplicate aggregate: ${describeAggregateIdentity(options.identity)} already exists`,
|
|
1099
1098
|
cause: options.cause
|
|
1100
1099
|
});
|
|
1101
|
-
this.identity =
|
|
1100
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
1102
1101
|
}
|
|
1103
1102
|
};
|
|
1104
1103
|
var SnapshotSchemaMismatchError = class extends InfrastructureError {
|
|
@@ -1110,7 +1109,7 @@ var SnapshotSchemaMismatchError = class extends InfrastructureError {
|
|
|
1110
1109
|
code: "SNAPSHOT_SCHEMA_MISMATCH",
|
|
1111
1110
|
message: `Snapshot schema mismatch on ${describeAggregateIdentity(options.identity)}: the snapshot model expects schema ${options.expectedSchemaVersion}, the stored snapshot carries ${options.actualSchemaVersion}. Override the model's migrate function to upgrade old snapshots, or discard the snapshot and refold from the full event stream.`
|
|
1112
1111
|
});
|
|
1113
|
-
this.identity =
|
|
1112
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
1114
1113
|
this.expectedSchemaVersion = options.expectedSchemaVersion;
|
|
1115
1114
|
this.actualSchemaVersion = options.actualSchemaVersion;
|
|
1116
1115
|
}
|
|
@@ -1125,7 +1124,7 @@ var SnapshotSchemaMismatchError = class extends InfrastructureError {
|
|
|
1125
1124
|
* **Retry means a FRESH unit of work** (a new `UnitOfWork.run()` /
|
|
1126
1125
|
* `withCommit` invocation): reload, re-apply, and register `update` again. Do NOT catch this
|
|
1127
1126
|
* inside the same `run()` callback and continue: the failed aggregate
|
|
1128
|
-
* is already
|
|
1127
|
+
* is already registered (its events would be committed for a write that
|
|
1129
1128
|
* never happened) and the identity map still serves the same stale
|
|
1130
1129
|
* instance to any in-place "reload".
|
|
1131
1130
|
*
|
|
@@ -1149,7 +1148,7 @@ var ConcurrencyConflictError = class extends InfrastructureError {
|
|
|
1149
1148
|
cause: options.cause,
|
|
1150
1149
|
retryable: options.reason !== "version_unchanged"
|
|
1151
1150
|
});
|
|
1152
|
-
this.identity =
|
|
1151
|
+
this.identity = copyAggregateIdentity(options.identity);
|
|
1153
1152
|
this.intent = options.intent ?? null;
|
|
1154
1153
|
this.expectedVersion = options.expectedVersion;
|
|
1155
1154
|
this.actualVersion = options.actualVersion ?? null;
|
|
@@ -1300,5 +1299,5 @@ var IdempotencyCompletionWithoutClaimError = class extends KitWiringError {
|
|
|
1300
1299
|
};
|
|
1301
1300
|
|
|
1302
1301
|
//#endregion
|
|
1303
|
-
export { isDomainErrorLike as $, MissingHandlerError as A,
|
|
1302
|
+
export { isDomainErrorLike as $, MissingHandlerError as A, ReplayTargetMismatchError as B, InvalidEventStreamPageError as C, MisattributedEventError as D, KitWiringError as E, ProjectionOrderViolationError as F, UnprojectableEventError as G, SnapshotSchemaMismatchError as H, ProjectionReceiptViolationError as I, UnreplayableAggregateError as J, UnregisteredChangesError as K, PrototypePollutionError as L, PendingEventLimitExceededError as M, ProjectionGapError as N, MissingEntityIdError as O, ProjectionIdentityViolationError as P, describeAggregateIdentity as Q, ReentrantEventRecordingError as R, InvalidCommandMessageError as S, InvalidVersionError as T, SnapshotVersionNotRestoredError as U, SnapshotCorruptedError as V, UnmanagedInstanceError as W, attributeConflictIntent as X, assertNoOwnProtoKey as Y, copyAggregateIdentity as Z, IdempotencyInFlightError as _, DirectStateMutationError as a, InMemoryCapacityExceededError as b, DuplicateEventIdError as c, EventCollectionError as d, isInfrastructureErrorLike as et, FoldReturnedNoStateError as f, IdempotencyCompletionWithoutClaimError as g, IdempotencyClaimLostError as h, ConcurrencyConflictError as i, PendingEventBatchMismatchError as j, MissingFoldError as k, DuplicateHandlerRegistrationError as l, HandBuiltEventError as m, AggregateNotFoundError as n, rewriteErrorMessage as nt, DomainError as o, ForeignEventError as p, UnregisteredHandlerError as q, CapabilityRegistryConflictError as r, DuplicateAggregateError as s, AggregateDeletedError as t, isWiringErrorLike as tt, ErrorMapperFailedError as u, IdempotencyKeyReuseError as v, InvalidIntegrationMessageError as w, InfrastructureError as x, IdempotencyReconciliationRequiredError as y, ReplayRejectedError as z };
|
|
1304
1303
|
//# sourceMappingURL=kit-errors.js.map
|