@shirudo/ddd-kit 2.0.0 → 3.0.0-rc.10

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/testing.d.ts CHANGED
@@ -1,252 +1,631 @@
1
- import { I as IAggregateRoot, a as Id, A as AnyDomainEvent } from './aggregate-CePTINEt.js';
2
- import '@shirudo/result';
3
- import '@shirudo/base-error';
4
-
5
- /**
6
- * The repository surface the contract suite exercises: the minimal
7
- * structural subset of the canonical `IUnitOfWorkRepository` (exported
8
- * from the main entry) that the tests need. `getById` is typed over
9
- * the aggregate's own branded id (`TAgg["id"]`), so concrete adapters,
10
- * including arrow-function-property style repositories, which are
11
- * checked contravariantly, match without casts.
12
- */
13
- interface ContractRepository<TAgg extends IAggregateRoot<Id<string>, AnyDomainEvent>> {
14
- getById(id: TAgg["id"]): Promise<TAgg | null>;
15
- save(aggregate: TAgg): Promise<void>;
16
- delete(aggregate: TAgg): Promise<void>;
17
- }
18
- /**
19
- * One isolated test environment: fresh storage, fresh outbox. The
20
- * suite creates one per test via {@link RepositoryContractHarness} and
21
- * tears it down afterwards (a teardown failure never masks an
22
- * in-flight contract violation).
23
- */
24
- interface RepositoryContractEnvironment<TAgg extends IAggregateRoot<Id<string>, Evt>, Evt extends AnyDomainEvent = AnyDomainEvent> {
25
- /**
26
- * Execute one unit of work against the adapter under test: open the
27
- * transaction, hand the suite a tx-bound repository, commit on
28
- * resolve, roll back on throw, and run the post-commit lifecycle
29
- * (event harvest into the outbox, `markPersisted`). Wire this
30
- * through your real `UnitOfWork` / `withCommit` setup: the commit
31
- * boundary IS part of what the suite proves.
32
- */
33
- run<R>(work: (ctx: {
34
- repository: ContractRepository<TAgg>;
35
- }) => Promise<R>): Promise<R>;
36
- /**
37
- * All events currently persisted in the outbox (committed writes
38
- * only; a rolled-back transaction's events must not appear here).
39
- */
40
- committedOutboxEvents(): Promise<ReadonlyArray<Evt>>;
41
- /** Release connections, drop schemas, etc. Called in a finally. */
42
- teardown?(): Promise<void>;
43
- }
44
- /**
45
- * What an adapter supplies to run the contract suite.
46
- *
47
- * The harness MUST provide isolation per environment (fresh
48
- * tables/keyspace or a truncate); tests assume they see only their
49
- * own writes. **For SQL/ORM adapters this must run against a real
50
- * database** (testcontainers or equivalent), not an in-memory fake:
51
- * the mandatory two-writer test proves YOUR `WHERE version = ?`
52
- * predicate, and an in-memory stand-in proves only itself.
53
- *
54
- * Optional capabilities widen the suite: tests for an absent
55
- * capability come back **marked `skipped`** with a `run()` that
56
- * rejects loudly: bind them with `it.skip` so the gap stays visible
57
- * in every report (see {@link RepositoryContractTest}); a naive
58
- * binding fails instead of green-no-op'ing. Capabilities are captured
59
- * once at suite creation. Provide every capability your adapter can
60
- * support; each one closes a real OCC hole.
61
- */
62
- interface RepositoryContractHarness<TAgg extends IAggregateRoot<Id<string>, Evt>, Evt extends AnyDomainEvent = AnyDomainEvent> {
63
- createEnvironment(): Promise<RepositoryContractEnvironment<TAgg, Evt>>;
64
- /**
65
- * A brand-new aggregate (never persisted, unique id,
66
- * `persistedVersion === undefined`).
67
- */
68
- createAggregate(): TAgg;
69
- /**
70
- * Apply exactly ONE version-bumping domain mutation that records at
71
- * least one domain event (a `commit()`-style state change). The
72
- * suite relies on the +1-per-call arithmetic and on the event for
73
- * its outbox assertions.
74
- */
75
- mutate(aggregate: TAgg): void;
76
- /**
77
- * Optional: a version-bumping mutation whose state is deep-equal to
78
- * the previous state (`setState({...state}, true)`). Enables the
79
- * version-only-change-still-persists test: the skip-save/OCC-desync
80
- * trap.
81
- */
82
- mutateVersionOnly?(aggregate: TAgg): void;
83
- /**
84
- * Optional: a mutation that changes ONLY a child collection (a
85
- * non-root-row `changedKeys` entry). Enables the
86
- * child-change-bumps-root-version test for partial-write
87
- * repositories.
88
- */
89
- mutateChildCollection?(aggregate: TAgg): void;
90
- /**
91
- * Optional: construct a NEW (never-persisted) aggregate instance
92
- * carrying a SPECIFIC id. Enables TWO tests: deletion-is-final-
93
- * across-instances (resurrection via a factory after delete) and
94
- * the duplicate-insert test (see
95
- * {@link insertsAreDuplicateChecked} to opt out of the latter
96
- * independently).
97
- */
98
- createAggregateWithId?(id: TAgg["id"]): TAgg;
99
- /**
100
- * Semantic opt-OUT (default `true`): whether `save()`'s INSERT path
101
- * rejects an existing id with `DuplicateAggregateError` (mapping the
102
- * driver's unique-violation: Postgres `23505`, MySQL `1062`, SQLite
103
- * `SQLITE_CONSTRAINT_UNIQUE`). This is the near-mandatory contract:
104
- * `save()` is insert-or-update, never upsert. Create-idempotency
105
- * belongs in the USE CASE (load, then decide), not in the save path.
106
- * Set `false` ONLY for a deliberately upserting adapter
107
- * (idempotent-create design); the duplicate-insert test is then
108
- * reported as skipped under this capability name, without costing
109
- * the deletion-finality coverage that `createAggregateWithId` also
110
- * gates.
111
- */
112
- insertsAreDuplicateChecked?: boolean;
113
- /**
114
- * Optional: a plain-data projection of the aggregate's persisted
115
- * state, compared with deep equality. Enables the mandatory test's
116
- * state assertion (without it, only the version and the outbox are
117
- * compared, and an adapter whose predicate guards the version write
118
- * but not the state write would slip through).
119
- *
120
- * **The projection must be roundtrip-stable**: it compares a
121
- * DB-reloaded aggregate against an in-memory one, so normalize
122
- * anything your store changes in transit: dates to ISO strings at
123
- * your store's precision (MySQL DATETIME truncates millis), no
124
- * `undefined`-valued keys (JSON columns drop them), decimals/bigints
125
- * to one consistent representation. A mismatch here fails the
126
- * mandatory test; the message names the projection as a suspect.
127
- */
128
- snapshotState?(aggregate: TAgg): unknown;
129
- /**
130
- * Optional flag: declare it when your `delete(aggregate)` runs an
131
- * OCC predicate (`DELETE … WHERE id = ? AND version = ?`). Enables
132
- * the stale-delete conflict test. Unpredicated deletes are
133
- * last-write-wins by construction: acceptable for GC-style
134
- * cleanup, rarely for user-initiated deletion of contended
135
- * aggregates (see the repository guide).
136
- */
137
- deletesAreVersionChecked?: boolean;
138
- }
139
- /**
140
- * One named contract test; `run` rejects with a descriptive Error on
141
- * violation. When the harness lacks the capability a test needs, the
142
- * entry is still returned with {@link skipped} set and a `run` that
143
- * REJECTS with an explanatory error: bind it with your runner's skip
144
- * (`(test.skipped ? it.skip : it)(test.name, test.run)`) so the gap is
145
- * visible in every test report: a missing capability must never look
146
- * like green coverage, and a naive binding that ignores `skipped`
147
- * fails loud instead of passing silently.
148
- */
149
- interface RepositoryContractTest {
150
- name: string;
151
- run: () => Promise<void>;
152
- /** Present when the harness lacks the capability this test needs. */
153
- skipped?: {
154
- capability: string;
155
- };
156
- }
157
- /**
158
- * The repository contract test suite: the proof that an adapter
159
- * actually delivers the guarantees the kit's Unit of Work documents.
160
- *
161
- * The kit is ORM-agnostic: the OCC version predicate lives in YOUR
162
- * repository's SQL. That makes optimistic concurrency a **repository
163
- * contract, not a kit guarantee**: the kit ships the boundary, the
164
- * `persistedVersion` baseline, `ConcurrencyConflictError`, and this
165
- * suite; your adapter must pass it. An adapter that has not passed the
166
- * suite (against a real database, for SQL adapters) has not
167
- * demonstrated OCC.
168
- *
169
- * Framework-agnostic: assertions throw plain `Error`s, so the suite
170
- * binds to vitest, jest, or `node:test` the same way:
171
- *
172
- * ```ts
173
- * import { describe, it } from "vitest";
174
- * import { createRepositoryContractTests } from "@shirudo/ddd-kit/testing";
175
- *
176
- * const harness: RepositoryContractHarness<Order, OrderEvent> = {
177
- * createEnvironment: async () => {
178
- * const schema = await provisionTestSchema(); // testcontainers etc.
179
- * const uowDeps = {
180
- * scope: schema.scope,
181
- * outbox: schema.outbox,
182
- * repositories: {
183
- * orders: (tx, session) => new DrizzleOrderRepository(tx, session),
184
- * },
185
- * };
186
- * return {
187
- * run: (work) =>
188
- * new UnitOfWork(uowDeps).run(({ repositories }) =>
189
- * work({ repository: repositories.orders })),
190
- * committedOutboxEvents: () => schema.readOutboxEvents(),
191
- * teardown: () => schema.drop(),
192
- * };
193
- * },
194
- * createAggregate: () => Order.draft(orderIds.next()),
195
- * mutate: (order) => order.changeNote(`note-${counter++}`), // ONE bump + event
196
- * // provide every optional capability your adapter supports:
197
- * createAggregateWithId: (id) => Order.draft(id),
198
- * snapshotState: (order) => normalizeForRoundtrip(order.state),
199
- * deletesAreVersionChecked: true,
200
- * };
201
- *
202
- * describe("DrizzleOrderRepository: repository contract", () => {
203
- * for (const test of createRepositoryContractTests(harness)) {
204
- * (test.skipped ? it.skip : it)(test.name, test.run);
205
- * }
206
- * });
207
- * ```
208
- *
209
- * **`env.run` must provide unit-of-work semantics.** Three core tests
210
- * (identity-map sameness, getById-null-after-delete, deletion
211
- * finality) exercise the session machinery: `session.identityMap`,
212
- * the `isDeleted` probe, the deleted-gate. Wiring `run` through the
213
- * kit's `UnitOfWork` gives you all of it; a hand-rolled `withCommit`
214
- * wiring must provide equivalents or those tests will fail. A
215
- * `withCommit`-only setup that deliberately makes no identity-map /
216
- * deletion-finality claims is outside this suite's scope; the suite
217
- * is the compliance bar for unit-of-work repositories.
218
- *
219
- * **Error matching is by NAME along the `cause` chain, not by
220
- * `instanceof`.** The suite ships in its own bundle entry; comparing
221
- * class identity would spuriously fail whenever the adapter's errors
222
- * come from a different copy of the kit (the main entry's bundle, or a
223
- * second installed version). `error.name === "ConcurrencyConflictError"`
224
- * anywhere in the chain is the contract.
225
- *
226
- * **What each test proves.** The OCC, routing, rollback, and outbox
227
- * tests prove YOUR adapter's SQL and transaction wiring. The
228
- * identity-map, deletion-finality, and event-lifecycle tests prove
229
- * your READ-PATH and unit-of-work WIRING (they exercise kit-provided
230
- * machinery, namely `session.identityMap`, the deleted-gate, and
231
- * `withCommit`'s harvest, and fail when your repository bypasses or
232
- * mis-wires it).
233
- * A deletion-finality failure usually means a missing
234
- * `identityMap.isDeleted` check or an `enrollSaved` placed after the
235
- * row write, not a broken DELETE statement.
236
- *
237
- * **Known limitation: no truly concurrent runs.** The mandatory
238
- * two-writer test is deliberately sequential-deterministic: writer B
239
- * loads, writer A loads/mutates/commits, then B commits its stale
240
- * instance. The stale `persistedVersion` baseline travels with B's
241
- * instance, so the version predicate is exercised exactly as in a true
242
- * race, without depending on lock timing, pool sizes, or
243
- * engine-specific blocking. The flip side: lock interaction is NOT
244
- * covered. A `SELECT … FOR UPDATE`-style repository that blocks
245
- * instead of conflicting, or a SERIALIZABLE engine surfacing raw
246
- * serialization failures (Postgres 40001) your adapter must map to
247
- * `ConcurrencyConflictError`, needs adapter-specific tests on top of
248
- * this suite.
249
- */
250
- declare function createRepositoryContractTests<TAgg extends IAggregateRoot<Id<string>, Evt>, Evt extends AnyDomainEvent = AnyDomainEvent>(harness: RepositoryContractHarness<TAgg, Evt>): RepositoryContractTest[];
251
-
252
- export { type ContractRepository, type RepositoryContractEnvironment, type RepositoryContractHarness, type RepositoryContractTest, createRepositoryContractTests };
1
+ import { Lt as PublishedCommand, P as EventBus, Pt as AggregateAddress, R as Aggregate, W as Id, Y as CommandOutboxCommitCandidate, Z as CommandOutboxWriter, _ as IdempotencyStore, a as StreamReadResult, c as ProjectionCheckpointStore, ct as EventCommitCandidate, f as IdempotencyClaimHandle, i as ReadStreamOptions, n as EventStore, nt as Outbox, st as CommittedDomainEvent, t as SnapshotStore, tt as DispatchTrackingOutbox, ut as AnyDomainEvent, w as DeadlineStore } from "./chunks/snapshot-store.js";
2
+ //#region src/testing/contract-assertions.d.ts
3
+ /**
4
+ * One entry of a contract test suite. Every suite (repository,
5
+ * event-sourced repository, outbox, idempotency store) returns a list
6
+ * of these; bind them with
7
+ * `(test.skipped ? it.skip : it)(test.name, test.run)`.
8
+ */
9
+ interface ContractTest {
10
+ name: string;
11
+ run: () => Promise<void>;
12
+ /** Present when the harness lacks the capability this test needs. */
13
+ skipped?: {
14
+ capability: string;
15
+ };
16
+ }
17
+ //#endregion
18
+ //#region src/testing/command-outbox-contract.d.ts
19
+ interface CommandOutboxContractEnvironment<C extends PublishedCommand> {
20
+ readonly outbox: CommandOutboxWriter<C>;
21
+ readonly addCommitted: (commits: ReadonlyArray<CommandOutboxCommitCandidate<C>>) => Promise<void>;
22
+ readonly addRolledBack?: (commits: ReadonlyArray<CommandOutboxCommitCandidate<C>>) => Promise<void>;
23
+ readonly readAll: () => Promise<ReadonlyArray<CommandOutboxCommitCandidate<C>>>;
24
+ readonly teardown?: () => Promise<void>;
25
+ }
26
+ interface CommandOutboxContractHarness<C extends PublishedCommand> {
27
+ readonly createEnvironment: () => Promise<CommandOutboxContractEnvironment<C>>;
28
+ /**
29
+ * Builds one command for the given seed. The suite derives conflicting
30
+ * commits from different seeds, so `createCommand` MUST return distinct
31
+ * command content per seed (put the seed in the payload). A constant
32
+ * command makes a manufactured conflict deep-equal to its original, and
33
+ * the conflict tests then fail a compliant adapter that deduplicates
34
+ * the exact retry.
35
+ */
36
+ readonly createCommand: (seed: number) => C;
37
+ readonly providesRolledBackAdds?: boolean;
38
+ }
39
+ type CommandOutboxContractTest = ContractTest;
40
+ declare function createCommandOutboxContractTests<C extends PublishedCommand>(harness: CommandOutboxContractHarness<C>): ReadonlyArray<CommandOutboxContractTest>;
41
+ //#endregion
42
+ //#region src/testing/deadline-store-contract.d.ts
43
+ /** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */
44
+ type DeadlineStoreContractTest = ContractTest;
45
+ /** The plain-data payload shape the suite round-trips. */
46
+ interface SuitePayload {
47
+ kind: string;
48
+ step?: number;
49
+ }
50
+ /**
51
+ * One isolated test environment: a fresh deadline store. The suite
52
+ * creates one per test and tears it down afterwards.
53
+ */
54
+ interface DeadlineStoreContractEnvironment {
55
+ /** The adapter under test. */
56
+ store: DeadlineStore<SuitePayload>;
57
+ /**
58
+ * Runs `work` (schedule/cancel calls) the way production does:
59
+ * inside a transaction that COMMITS. For a non-transactional store
60
+ * this simply invokes `work`.
61
+ */
62
+ run<R>(work: () => Promise<R>): Promise<R>;
63
+ /**
64
+ * Optional capability: runs `work` inside a transaction that ROLLS
65
+ * BACK. Enables the rollback tests: a rolled-back schedule must not
66
+ * leave a deadline behind (a ghost input for a state change that
67
+ * never happened), and a rolled-back cancel must not have removed
68
+ * one. Transactional adapters should always provide this.
69
+ */
70
+ runRolledBack?<R>(work: () => Promise<R>): Promise<R>;
71
+ /** Release connections, drop schemas, etc. Called in a finally. */
72
+ teardown?(): Promise<void>;
73
+ }
74
+ /**
75
+ * What an adapter supplies to run the deadline-store contract suite.
76
+ * For SQL adapters, run against a real database (testcontainers or
77
+ * equivalent): the rollback tests prove YOUR transaction wiring, and
78
+ * schedule/cancel joining the write transaction is the port's central
79
+ * correctness rule.
80
+ */
81
+ interface DeadlineStoreContractHarness {
82
+ createEnvironment(): Promise<DeadlineStoreContractEnvironment>;
83
+ /**
84
+ * The adapter's attempt ceiling: how many `markFailed` reports move
85
+ * a deadline to the dead-letter set. Must be at least 2 so the
86
+ * attempts-surfacing test can observe a survivor.
87
+ */
88
+ failuresToDeadLetter: number;
89
+ /**
90
+ * Declare `true` when environments provide {@link
91
+ * DeadlineStoreContractEnvironment.runRolledBack}. Without it, the
92
+ * rollback tests are marked skipped: the honest state of an
93
+ * in-memory fake, and a loud gap for a transactional adapter.
94
+ */
95
+ providesRolledBackRuns?: boolean;
96
+ /**
97
+ * Declare `true` when the adapter's `due` CLAIMS the returned
98
+ * records for competing pollers (lease, visibility timeout), as the
99
+ * port sanctions. Tests that re-poll records an earlier poll
100
+ * returned without resolving them (attempts surfacing, neighbor
101
+ * flow after a dead-letter, successor visibility during a
102
+ * reschedule race) assume a non-claiming read and are marked
103
+ * skipped for claiming adapters; prove your claim/expiry semantics
104
+ * in your own suite.
105
+ */
106
+ claimsOnDue?: boolean;
107
+ }
108
+ /**
109
+ * The deadline-store contract test suite: the proof that an adapter
110
+ * delivers the schedule/cancel/due/acknowledge semantics the port
111
+ * documents. Store semantics are an **adapter contract, not a kit
112
+ * guarantee**; this suite is how an adapter demonstrates them.
113
+ *
114
+ * Framework-agnostic: bind with
115
+ * `(test.skipped ? it.skip : it)(test.name, test.run)`.
116
+ */
117
+ declare function createDeadlineStoreContractTests(harness: DeadlineStoreContractHarness): DeadlineStoreContractTest[];
118
+ //#endregion
119
+ //#region src/testing/es-repository-contract.d.ts
120
+ /** Event-sourced repositories normally expose no physical removal. */
121
+ interface EsContractRepository<TAggregate extends Aggregate<Id<string>, AnyDomainEvent>> {
122
+ findById(id: TAggregate["id"]): Promise<TAggregate | undefined>;
123
+ add(aggregate: TAggregate): void;
124
+ update(aggregate: TAggregate): void;
125
+ }
126
+ interface EsRepositoryContractEnvironment<TAggregate extends Aggregate<Id<string>, TEvent>, TEvent extends AnyDomainEvent = AnyDomainEvent> {
127
+ run<R>(work: (context: {
128
+ repository: EsContractRepository<TAggregate>;
129
+ }) => Promise<R>): Promise<R>;
130
+ committedOutboxEvents(): Promise<ReadonlyArray<CommittedDomainEvent<TEvent>>>;
131
+ failNextOutboxWrite(error: Error): void;
132
+ committedStreamEvents(stream: AggregateAddress<TAggregate["id"]>, options: ReadStreamOptions): Promise<StreamReadResult<TEvent>>;
133
+ teardown?(): Promise<void>;
134
+ }
135
+ interface EsRepositoryContractHarness<TAggregate extends Aggregate<Id<string>, TEvent>, TEvent extends AnyDomainEvent = AnyDomainEvent> {
136
+ createEnvironment(): Promise<EsRepositoryContractEnvironment<TAggregate, TEvent>>;
137
+ /** Fresh aggregate with exactly one recorded creation event. */
138
+ createAggregate(): TAggregate;
139
+ createAggregateWithId?(id: TAggregate["id"]): TAggregate;
140
+ streamKeyFor(id: TAggregate["id"]): AggregateAddress<TAggregate["id"]>;
141
+ /** Applies exactly one event and advances the aggregate version by one. */
142
+ mutate(aggregate: TAggregate): void;
143
+ snapshotState?(aggregate: TAggregate): unknown;
144
+ /**
145
+ * Persists a snapshot of the aggregate at its current version in the
146
+ * environment's snapshot store, so the next load there starts from it.
147
+ * Enables the snapshot catch-up proof.
148
+ */
149
+ captureSnapshot?(aggregate: TAggregate, environment: EsRepositoryContractEnvironment<TAggregate, TEvent>): Promise<void>;
150
+ /**
151
+ * Bound for the overlapping `run` calls, in milliseconds: the second call
152
+ * of the environment preflight, and the committing call of each
153
+ * stale-writer proof. Raise it only for a second connection that needs
154
+ * more time to open, or for a slow commit. Keep twice the bound, plus
155
+ * environment creation and teardown, below the test timeout of the runner.
156
+ */
157
+ overlappingCallsBoundMs?: number;
158
+ }
159
+ type EsRepositoryContractTest = ContractTest;
160
+ /**
161
+ * Contract suite for event-stream adapters using v3 Unit-of-Work receipts.
162
+ *
163
+ * `add` and `update` register intent only. At commit, the adapter appends the
164
+ * receipt's exact event batch with the Unit of Work's expected version, in the
165
+ * same transaction as the outbox. `run` must support overlapping calls so the
166
+ * mandatory stale-writer proof exercises a real stream OCC predicate.
167
+ */
168
+ declare function createEsRepositoryContractTests<TAggregate extends Aggregate<Id<string>, TEvent>, TEvent extends AnyDomainEvent = AnyDomainEvent>(harness: EsRepositoryContractHarness<TAggregate, TEvent>): EsRepositoryContractTest[];
169
+ //#endregion
170
+ //#region src/testing/event-bus-contract.d.ts
171
+ /** One entry of the event-bus contract suite. */
172
+ type EventBusContractTest = ContractTest;
173
+ /**
174
+ * What the suite runs against. The harness creates one per test and tears
175
+ * it down afterwards. No transaction wrapper: the port is in-process and
176
+ * transaction-free by design.
177
+ */
178
+ interface EventBusContractEnvironment<Evt extends AnyDomainEvent> {
179
+ /** The implementation under test. */
180
+ readonly bus: EventBus<Evt>;
181
+ /** Release connections, drop schemas, etc. Called in a finally. */
182
+ teardown?(): Promise<void>;
183
+ }
184
+ /**
185
+ * What an implementation supplies to run the event-bus contract suite.
186
+ *
187
+ * The suite mints no events, so it stays free of any event union. The two
188
+ * factories must produce DIFFERENT `type` values: the suite subscribes to
189
+ * both to prove that ordering holds across types and that a catch-all
190
+ * subscription sees every type.
191
+ */
192
+ interface EventBusContractHarness<Evt extends AnyDomainEvent> {
193
+ createEnvironment(): Promise<EventBusContractEnvironment<Evt>>;
194
+ /** An event of the first type. Called repeatedly; each call may differ. */
195
+ createFirstEvent(): Evt;
196
+ /** An event of the second type, whose `type` differs from the first. */
197
+ createSecondEvent(): Evt;
198
+ }
199
+ /**
200
+ * The event-bus contract test suite: the proof that an implementation
201
+ * delivers the guarantees the `EventBus` port documents. Ordering,
202
+ * parallelism within one event, and error collection after the batch are
203
+ * a **port contract, not a kit guarantee**; this suite is how an
204
+ * implementation demonstrates them.
205
+ *
206
+ * The suite covers the port and nothing else. Construction options of the
207
+ * kit's own adapter, such as a publish-depth bound or an observer bundle,
208
+ * are not port behavior and are not pinned here.
209
+ *
210
+ * Framework-agnostic: bind with
211
+ * `(test.skipped ? it.skip : it)(test.name, test.run)`.
212
+ */
213
+ declare function createEventBusContractTests<Evt extends AnyDomainEvent>(harness: EventBusContractHarness<Evt>): EventBusContractTest[];
214
+ //#endregion
215
+ //#region src/testing/event-store-contract.d.ts
216
+ /** One named contract test for an EventStore adapter. */
217
+ type EventStoreContractTest = ContractTest;
218
+ /** One isolated adapter instance. The suite creates one per test. */
219
+ interface EventStoreContractEnvironment<Evt extends AnyDomainEvent> {
220
+ readonly store: EventStore<Evt>;
221
+ teardown?(): Promise<void>;
222
+ }
223
+ /**
224
+ * Inputs needed to prove the EventStore's observable port contract.
225
+ *
226
+ * `createCollidingStreamKeys` must return two valid stream keys with the same
227
+ * raw aggregate id and different aggregate types. `createEvent` must return an
228
+ * event addressed to the supplied key; different sequence values must produce
229
+ * different event ids.
230
+ */
231
+ interface EventStoreContractHarness<Evt extends AnyDomainEvent> {
232
+ createEnvironment(): Promise<EventStoreContractEnvironment<Evt>>;
233
+ createCollidingStreamKeys(): readonly [AggregateAddress, AggregateAddress];
234
+ createEvent(stream: AggregateAddress, sequence: number): Evt;
235
+ }
236
+ /**
237
+ * Reusable proof of an EventStore adapter's portable semantics: qualified
238
+ * value identity, ordered reads and slicing, OCC error mapping and atomicity,
239
+ * no-op empty appends, and detached return arrays. Physical-position
240
+ * corruption needs adapter-specific fixture support and is tested there.
241
+ */
242
+ declare function createEventStoreContractTests<Evt extends AnyDomainEvent>(harness: EventStoreContractHarness<Evt>): EventStoreContractTest[];
243
+ //#endregion
244
+ //#region src/testing/idempotency-store-contract.d.ts
245
+ /** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */
246
+ type IdempotencyStoreContractTest = ContractTest;
247
+ /**
248
+ * One isolated test environment: a fresh idempotency store. The suite
249
+ * creates one per test and tears it down afterwards.
250
+ */
251
+ interface IdempotencyStoreContractEnvironment<TCtx> {
252
+ /** The adapter under test. */
253
+ store: IdempotencyStore<TCtx>;
254
+ /**
255
+ * Runs `work` inside a transaction that COMMITS, handing it the
256
+ * transaction context the store methods expect, the way
257
+ * `withIdempotentCommit` calls them in production. For a
258
+ * non-transactional store this simply invokes `work` with a dummy
259
+ * context.
260
+ */
261
+ run<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;
262
+ /**
263
+ * For the `"transactional"` family: runs `work` inside a transaction
264
+ * that ROLLS BACK. Required there; the rollback-releases-the-claim
265
+ * test is that family's core proof. Irrelevant for the
266
+ * `"non-transactional"` family.
267
+ */
268
+ runRolledBack?<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;
269
+ /**
270
+ * For the `"non-transactional"` family: advances or edits adapter test
271
+ * state so this exact claim's CURRENT lease is expired. Required there;
272
+ * a fake clock or test-only row update keeps the suite deterministic.
273
+ */
274
+ expireLease?(claim: IdempotencyClaimHandle): Promise<void>;
275
+ /**
276
+ * Moves the adapter's test clock to an exact instant. Required by the
277
+ * non-transactional family so renewal is proved without wall-clock sleeps.
278
+ */
279
+ advanceTimeTo?(instant: Date): Promise<void>;
280
+ /** Release connections, drop schemas, etc. Called in a finally. */
281
+ teardown?(): Promise<void>;
282
+ }
283
+ /**
284
+ * What an adapter supplies to run the idempotency-store contract suite.
285
+ *
286
+ * The port (`IdempotencyStore`) deliberately supports two adapter
287
+ * families with different lifecycle semantics, and the suite follows
288
+ * the declared family instead of forcing one onto the other:
289
+ *
290
+ * - `"transactional"` (the single-transaction pattern): the record
291
+ * lives in the same database as the aggregates; a committed
292
+ * `complete` is final and replayable, a rollback releases everything,
293
+ * and `renew`/`confirm`/`abandon`/`reconcile` are no-ops. The family's core proof is the
294
+ * rollback test, so environments MUST provide `runRolledBack`, and
295
+ * run against a real database for SQL adapters.
296
+ * - `"non-transactional"` (the leased two-phase pattern, e.g. the
297
+ * in-memory reference): the store cannot see commits, so `complete` only
298
+ * STAGES the outcome, `confirm` finalizes it post-commit, `abandon`
299
+ * compensates failed attempts, and expired staged records require
300
+ * reconciliation. Environments MUST provide deterministic `expireLease` and
301
+ * `advanceTimeTo` controls. The rollback test is skipped.
302
+ */
303
+ interface IdempotencyStoreContractHarness<TCtx> {
304
+ createEnvironment(): Promise<IdempotencyStoreContractEnvironment<TCtx>>;
305
+ /** Which lifecycle family the adapter implements; see above. */
306
+ family: "transactional" | "non-transactional";
307
+ }
308
+ /**
309
+ * The idempotency-store contract test suite: the proof that an adapter
310
+ * delivers the claim/renew/complete/confirm/abandon/reconcile lifecycle
311
+ * `withIdempotentCommit` documents, for its declared family. Store
312
+ * semantics are an **adapter contract, not a kit guarantee**; this
313
+ * suite is how an adapter demonstrates them.
314
+ *
315
+ * Framework-agnostic: bind with
316
+ * `(test.skipped ? it.skip : it)(test.name, test.run)`.
317
+ */
318
+ declare function createIdempotencyStoreContractTests<TCtx>(harness: IdempotencyStoreContractHarness<TCtx>): IdempotencyStoreContractTest[];
319
+ //#endregion
320
+ //#region src/testing/outbox-contract.d.ts
321
+ /** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */
322
+ type OutboxContractTest = ContractTest;
323
+ /**
324
+ * One isolated test environment: a fresh outbox store. The suite
325
+ * creates one per test and tears it down afterwards.
326
+ */
327
+ interface OutboxContractEnvironment<Evt extends AnyDomainEvent> {
328
+ /** The adapter under test. */
329
+ outbox: Outbox<Evt> | DispatchTrackingOutbox<Evt>;
330
+ /**
331
+ * Runs `outbox.add(candidates)` inside a transaction that COMMITS, the
332
+ * way `withCommit` calls it in production. The suite supplies complete
333
+ * candidates with explicit source, aggregate version, zero-based commit
334
+ * sequence, and commit size. For a non-transactional store this is simply
335
+ * `outbox.add(candidates)`.
336
+ */
337
+ addCommitted(events: ReadonlyArray<EventCommitCandidate<Evt>>): Promise<void>;
338
+ /**
339
+ * Optional capability: runs `outbox.add(candidates)` inside a
340
+ * transaction that ROLLS BACK. Enables the rollback-purity test: a
341
+ * rolled-back add must leave nothing behind. Transactional adapters
342
+ * should always provide this; it is the half of the outbox promise
343
+ * that in-memory fakes cannot keep.
344
+ */
345
+ addRolledBack?(events: ReadonlyArray<EventCommitCandidate<Evt>>): Promise<void>;
346
+ /** Release connections, drop schemas, etc. Called in a finally. */
347
+ teardown?(): Promise<void>;
348
+ }
349
+ /**
350
+ * What an adapter supplies to run the outbox contract suite.
351
+ *
352
+ * For SQL adapters, run against a real database (testcontainers or
353
+ * equivalent): the commit-order and rollback tests prove YOUR schema
354
+ * and transaction wiring, not the kit's.
355
+ *
356
+ * Note on claiming: multi-instance safety (`getPending` claiming via
357
+ * `FOR UPDATE SKIP LOCKED` or equivalent) is part of the port contract
358
+ * for competing dispatchers but is not covered here; concurrency
359
+ * cannot be proven portably by a generic suite. Test it in your
360
+ * adapter's own suite if you run more than one dispatcher.
361
+ */
362
+ interface OutboxContractHarness<Evt extends AnyDomainEvent> {
363
+ createEnvironment(): Promise<OutboxContractEnvironment<Evt>>;
364
+ /**
365
+ * Deterministic event factory: the same `seed` yields an event with
366
+ * the SAME `eventId` (the suite uses this for the dedupe test), and
367
+ * different seeds yield distinct `eventId`s.
368
+ */
369
+ createEvent(seed: number): Evt;
370
+ /**
371
+ * For a `DispatchTrackingOutbox` adapter: how many `markFailed`
372
+ * reports move a record to the dead-letter set (the adapter's
373
+ * configured attempt ceiling). Omit for plain `Outbox` adapters;
374
+ * the dispatch-tracking tests are then marked skipped. With a
375
+ * ceiling of 1 the attempts-surfacing test is marked skipped too:
376
+ * observing attempts on a PENDING record needs a record that
377
+ * survives one failure.
378
+ */
379
+ failuresToDeadLetter?: number;
380
+ /**
381
+ * Declare `true` when environments provide {@link
382
+ * OutboxContractEnvironment.addRolledBack}. Without it, the
383
+ * rollback-purity test is marked skipped: the honest state of an
384
+ * in-memory fake, and a loud gap for a transactional adapter.
385
+ */
386
+ providesRolledBackAdds?: boolean;
387
+ /**
388
+ * Declare `true` when the adapter's `getPending` CLAIMS the returned
389
+ * records for competing dispatchers (lease, visibility timeout,
390
+ * `FOR UPDATE SKIP LOCKED`), as the port sanctions. Every test that
391
+ * re-polls records a previous poll returned without resolving them
392
+ * (head stability, re-ack non-disturbance, attempts surfacing)
393
+ * assumes a non-claiming read and is marked skipped for claiming
394
+ * adapters; prove your claim/expiry semantics in your own suite.
395
+ */
396
+ claimsOnGetPending?: boolean;
397
+ /**
398
+ * Declare `true` when `add()` dedupes on `eventId` (the unique-key
399
+ * constraint the port RECOMMENDS). The dedupe test is gated on this:
400
+ * an adapter without the constraint satisfies the port's normative
401
+ * requirements and must not fail the suite, but the skip stays
402
+ * visible as the unproven recommendation it is.
403
+ */
404
+ dedupesOnEventId?: boolean;
405
+ }
406
+ /**
407
+ * The outbox contract test suite: the proof that an adapter delivers
408
+ * the guarantees `withCommit` and `OutboxDispatcher` document. The kit
409
+ * is store-agnostic, so commit-order reads, qualified source-position
410
+ * identity, eventful-predecessor linkage, idempotent acks, and rollback
411
+ * purity are an **adapter contract, not a kit guarantee**; this suite is how
412
+ * an adapter demonstrates them. Its source-law tests also prove that colliding
413
+ * raw ids stay isolated by aggregate type and aggregate id.
414
+ *
415
+ * Framework-agnostic: bind with
416
+ * `(test.skipped ? it.skip : it)(test.name, test.run)`.
417
+ */
418
+ declare function createOutboxContractTests<Evt extends AnyDomainEvent>(harness: OutboxContractHarness<Evt>): OutboxContractTest[];
419
+ //#endregion
420
+ //#region src/testing/projection-checkpoint-contract.d.ts
421
+ /** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */
422
+ type ProjectionCheckpointStoreContractTest = ContractTest;
423
+ /**
424
+ * One isolated test environment: a fresh checkpoint store. The suite
425
+ * creates one per test and tears it down afterwards.
426
+ */
427
+ interface ProjectionCheckpointStoreContractEnvironment<TCtx> {
428
+ /** The adapter under test. */
429
+ store: ProjectionCheckpointStore<TCtx>;
430
+ /**
431
+ * Runs `work` inside a transaction that COMMITS, handing it the
432
+ * transaction context the store methods expect, the way the
433
+ * `Projector` calls them in production. For a non-transactional
434
+ * store this simply invokes `work` with a dummy context.
435
+ */
436
+ run<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;
437
+ /**
438
+ * Optional capability: starts every supplied transaction independently and
439
+ * concurrently. Each callback must receive its own transaction context for
440
+ * database adapters (normally a separate pooled connection). Enables the
441
+ * missing-key/existing-key exclusion test; implementing this as sequential
442
+ * calls would make that proof meaningless.
443
+ */
444
+ runConcurrently?<R>(works: ReadonlyArray<(ctx: TCtx) => Promise<R>>): Promise<R[]>;
445
+ /**
446
+ * Optional capability: runs `work` inside a transaction that ROLLS
447
+ * BACK. Enables the rollback test: a rolled-back save must leave no
448
+ * checkpoint behind, the half of the atomic update+checkpoint
449
+ * promise the store contributes. Transactional adapters should
450
+ * always provide this; in-memory fakes cannot.
451
+ */
452
+ runRolledBack?<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;
453
+ /** Release connections, drop schemas, etc. Called in a finally. */
454
+ teardown?(): Promise<void>;
455
+ }
456
+ /**
457
+ * What an adapter supplies to run the projection-checkpoint-store
458
+ * contract suite. For SQL adapters, run against a real database
459
+ * (testcontainers or equivalent): concurrent runs prove missing-key locking,
460
+ * the rollback test proves YOUR transaction wiring, and the checkpoint table
461
+ * must live in the same database as the read models it accounts for.
462
+ */
463
+ interface ProjectionCheckpointStoreContractHarness<TCtx> {
464
+ createEnvironment(): Promise<ProjectionCheckpointStoreContractEnvironment<TCtx>>;
465
+ /**
466
+ * Declare `true` when environments provide {@link
467
+ * ProjectionCheckpointStoreContractEnvironment.runRolledBack}.
468
+ * Without it, the rollback test is marked skipped: the honest state
469
+ * of an in-memory fake, and a loud gap for a transactional adapter.
470
+ */
471
+ providesRolledBackRuns?: boolean;
472
+ /**
473
+ * Declare `true` when environments provide {@link
474
+ * ProjectionCheckpointStoreContractEnvironment.runConcurrently}. Without
475
+ * it, missing-key lock safety is marked skipped and remains an explicitly
476
+ * unproven adapter guarantee.
477
+ */
478
+ providesConcurrentRuns?: boolean;
479
+ }
480
+ /**
481
+ * The projection-checkpoint-store contract test suite: the proof that
482
+ * an adapter delivers the watermark semantics the `Projector`
483
+ * documents. Checkpoint semantics are an **adapter contract, not a
484
+ * kit guarantee**; this suite is how an adapter demonstrates them. Enable its
485
+ * concurrent-runs capability to prove genesis-safe exclusion rather than
486
+ * leaving that guarantee visibly skipped.
487
+ *
488
+ * The concurrent test exercises commit visibility, but cannot deterministically
489
+ * hold an adapter between return from `withCheckpointLocks` and its surrounding
490
+ * transaction commit. It can therefore expose an early lock release only when
491
+ * a waiter enters during that window; holding database locks through commit or
492
+ * rollback remains an explicit adapter responsibility, not a complete proof
493
+ * supplied by this suite.
494
+ *
495
+ * Framework-agnostic: bind with
496
+ * `(test.skipped ? it.skip : it)(test.name, test.run)`.
497
+ */
498
+ declare function createProjectionCheckpointStoreContractTests<TCtx>(harness: ProjectionCheckpointStoreContractHarness<TCtx>): ProjectionCheckpointStoreContractTest[];
499
+ //#endregion
500
+ //#region src/testing/repository-contract.d.ts
501
+ /** Application-facing state-stored repository exercised by the suite. */
502
+ interface ContractRepository<TAggregate extends Aggregate<Id<string>, AnyDomainEvent>> {
503
+ findById(id: TAggregate["id"]): Promise<TAggregate | undefined>;
504
+ add(aggregate: TAggregate): void;
505
+ /** An append-only port declares no update. */
506
+ update?(aggregate: TAggregate): void;
507
+ /** Physical removal is an optional persistence capability. */
508
+ remove?(aggregate: TAggregate): void;
509
+ }
510
+ /** One isolated real-adapter environment. `run` must permit overlapping calls. */
511
+ interface RepositoryContractEnvironment<TAggregate extends Aggregate<Id<string>, TEvent>, TEvent extends AnyDomainEvent = AnyDomainEvent> {
512
+ run<R>(work: (context: {
513
+ repository: ContractRepository<TAggregate>;
514
+ }) => Promise<R>): Promise<R>;
515
+ committedOutboxEvents(): Promise<ReadonlyArray<CommittedDomainEvent<TEvent>>>;
516
+ /** Makes the next transactional outbox write fail for atomicity proof. */
517
+ failNextOutboxWrite(error: Error): void;
518
+ teardown?(): Promise<void>;
519
+ }
520
+ /** Fixtures and observable projections supplied by an adapter package. */
521
+ interface RepositoryContractHarness<TAggregate extends Aggregate<Id<string>, TEvent>, TEvent extends AnyDomainEvent = AnyDomainEvent> {
522
+ createEnvironment(): Promise<RepositoryContractEnvironment<TAggregate, TEvent>>;
523
+ /** A fresh aggregate with a unique id. */
524
+ createAggregate(): TAggregate;
525
+ /** One version-bumping decision that records at least one event. */
526
+ mutate(aggregate: TAggregate): void;
527
+ /** Required for duplicate-add and same-UoW deletion-finality proofs. */
528
+ createAggregateWithId?(id: TAggregate["id"]): TAggregate;
529
+ /**
530
+ * A version-bumping decision with no event whose resulting state is
531
+ * deep-equal to the previous state (`setState({ ...state })`). The
532
+ * deep-equal requirement is load-bearing: it forces a diff-based
533
+ * `PersistenceModel` to derive an EMPTY change set, so the suite proves
534
+ * that an adapter persists the bumped version even when
535
+ * `changes.empty` is true. Skipping that write desyncs the persisted
536
+ * version and produces false concurrency conflicts later.
537
+ */
538
+ mutateVersionOnly?(aggregate: TAggregate): void;
539
+ /** A decision that changes a nested collection. */
540
+ mutateChildCollection?(aggregate: TAggregate): void;
541
+ /** Round-trip-stable adapter persistence projection. */
542
+ snapshotState?(aggregate: TAggregate): unknown;
543
+ /** Opt out only for an intentionally upserting add implementation. */
544
+ insertsAreDuplicateChecked?: boolean;
545
+ /**
546
+ * Opt out only for an append-only port, one that the definition marks
547
+ * with `appendOnly: true`. The suite then skips every update proof. The
548
+ * duplicate-add proof is the concurrency proof that remains, so it is
549
+ * mandatory. Provide `createAggregateWithId` and keep
550
+ * `insertsAreDuplicateChecked`, or the proof fails instead of skipping.
551
+ */
552
+ updatesAreSupported?: boolean;
553
+ /** Enables physical-remove behavior and stale-remove OCC tests. */
554
+ removesAreSupported?: boolean;
555
+ /** The remove flush predicates on the version captured at load. */
556
+ removesAreVersionChecked?: boolean;
557
+ /**
558
+ * Bound for the overlapping `run` calls, in milliseconds: the second call
559
+ * of the environment preflight, and the committing call of each
560
+ * stale-writer proof. Raise it only for a second connection that needs
561
+ * more time to open, or for a slow commit. Keep twice the bound, plus
562
+ * environment creation and teardown, below the test timeout of the runner.
563
+ */
564
+ overlappingCallsBoundMs?: number;
565
+ }
566
+ type RepositoryContractTest = ContractTest;
567
+ /**
568
+ * Contract suite for the v3 explicit-intent, commit-time-flush protocol.
569
+ *
570
+ * The harness must use the public `UnitOfWork` with a real adapter. In
571
+ * particular, `run` must create a fresh Unit of Work and transaction for each
572
+ * call and allow two calls to overlap; the mandatory stale-writer proof keeps
573
+ * writer B open while writer A commits. SQL/ORM adapters therefore need a
574
+ * real database and connection pool. An in-memory harness proves only itself.
575
+ *
576
+ * Writes are synchronous registrations. Durable adapter I/O happens after the
577
+ * callback returns, while the transaction is still open. A test that passes
578
+ * because `add` or `update` writes early is not a conforming implementation.
579
+ */
580
+ declare function createRepositoryContractTests<TAggregate extends Aggregate<Id<string>, TEvent>, TEvent extends AnyDomainEvent = AnyDomainEvent>(harness: RepositoryContractHarness<TAggregate, TEvent>): RepositoryContractTest[];
581
+ //#endregion
582
+ //#region src/testing/snapshot-store-contract.d.ts
583
+ /** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */
584
+ type SnapshotStoreContractTest = ContractTest;
585
+ /** The plain-data state shape the suite round-trips. */
586
+ interface SuiteState {
587
+ total: number;
588
+ items: Array<{
589
+ sku: string;
590
+ qty: number;
591
+ }>;
592
+ note?: string;
593
+ }
594
+ /**
595
+ * One isolated test environment: a fresh snapshot store. The suite
596
+ * creates one per test and tears it down afterwards. No transaction
597
+ * wrapper: the port is transaction-free by design (snapshots are
598
+ * derived data written after the commit; see `SnapshotStore`).
599
+ */
600
+ interface SnapshotStoreContractEnvironment {
601
+ /** The adapter under test. */
602
+ store: SnapshotStore<SuiteState>;
603
+ /** Release connections, drop schemas, etc. Called in a finally. */
604
+ teardown?(): Promise<void>;
605
+ }
606
+ /**
607
+ * What an adapter supplies to run the snapshot-store contract suite.
608
+ * For SQL adapters, run against a real database (testcontainers or
609
+ * equivalent). Note the fidelity demands the suite enforces:
610
+ * `snapshotAt` must survive with millisecond precision (store it as
611
+ * ISO-8601 text or epoch milliseconds; MySQL `DATETIME` without
612
+ * fractional seconds truncates), and an ABSENT `schemaVersion` must
613
+ * come back absent, not as `0` or `null`-coerced.
614
+ */
615
+ interface SnapshotStoreContractHarness {
616
+ createEnvironment(): Promise<SnapshotStoreContractEnvironment>;
617
+ }
618
+ /**
619
+ * The snapshot-store contract test suite: the proof that an adapter
620
+ * delivers the round-trip and isolation semantics the
621
+ * snapshot-plus-recent-events load path relies on. Store semantics are
622
+ * an **adapter contract, not a kit guarantee**; this suite is how an
623
+ * adapter demonstrates them.
624
+ *
625
+ * Framework-agnostic: bind with
626
+ * `(test.skipped ? it.skip : it)(test.name, test.run)`.
627
+ */
628
+ declare function createSnapshotStoreContractTests(harness: SnapshotStoreContractHarness): SnapshotStoreContractTest[];
629
+ //#endregion
630
+ export { type CommandOutboxContractEnvironment, type CommandOutboxContractHarness, type CommandOutboxContractTest, type ContractRepository, type DeadlineStoreContractEnvironment, type DeadlineStoreContractHarness, type DeadlineStoreContractTest, type EsContractRepository, type EsRepositoryContractEnvironment, type EsRepositoryContractHarness, type EsRepositoryContractTest, type EventBusContractEnvironment, type EventBusContractHarness, type EventBusContractTest, type EventStoreContractEnvironment, type EventStoreContractHarness, type EventStoreContractTest, type IdempotencyStoreContractEnvironment, type IdempotencyStoreContractHarness, type IdempotencyStoreContractTest, type OutboxContractEnvironment, type OutboxContractHarness, type OutboxContractTest, type ProjectionCheckpointStoreContractEnvironment, type ProjectionCheckpointStoreContractHarness, type ProjectionCheckpointStoreContractTest, type RepositoryContractEnvironment, type RepositoryContractHarness, type RepositoryContractTest, type SnapshotStoreContractEnvironment, type SnapshotStoreContractHarness, type SnapshotStoreContractTest, createCommandOutboxContractTests, createDeadlineStoreContractTests, createEsRepositoryContractTests, createEventBusContractTests, createEventStoreContractTests, createIdempotencyStoreContractTests, createOutboxContractTests, createProjectionCheckpointStoreContractTests, createRepositoryContractTests, createSnapshotStoreContractTests };
631
+ //# sourceMappingURL=testing.d.ts.map