@dudousxd/nestjs-durable-testing 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -40,6 +40,13 @@ declare function assertStepAttempts(store: StateStore, runId: string, name: stri
40
40
  *
41
41
  * The camelCase ("preserve") naming is simply the property names themselves (the object keys), so no
42
42
  * separate map is needed for it.
43
+ *
44
+ * A property belongs here only when EVERY adapter declares it — the assertion walks this map and
45
+ * reports a missing property as a mismatch, so listing a column one adapter doesn't have would fail
46
+ * that adapter for a divergence it isn't guilty of. `WorkflowRun.namespace` is the standing example:
47
+ * only the MikroORM adapter has a `namespace` column (it is the one with the tenant read filter), so
48
+ * it stays out. That absence records a real cross-adapter gap, not a naming one; if the other three
49
+ * ever gain the column, it belongs here on the same day.
43
50
  */
44
51
  declare const DURABLE_CANONICAL_COLUMNS: {
45
52
  readonly durable_workflow_runs: {
@@ -56,6 +63,8 @@ declare const DURABLE_CANONICAL_COLUMNS: {
56
63
  readonly recoveryAttempts: "recovery_attempts";
57
64
  readonly tags: "tags";
58
65
  readonly searchAttributes: "search_attributes";
66
+ readonly priority: "priority";
67
+ readonly origin: "origin";
59
68
  readonly createdAt: "created_at";
60
69
  readonly updatedAt: "updated_at";
61
70
  };
package/dist/index.js CHANGED
@@ -224,6 +224,11 @@ var DURABLE_CANONICAL_COLUMNS = {
224
224
  recoveryAttempts: "recovery_attempts",
225
225
  tags: "tags",
226
226
  searchAttributes: "search_attributes",
227
+ priority: "priority",
228
+ // Which library registered the workflow. Single-word, so `snake_case` and `preserve` agree and
229
+ // an adapter can look canonical by accident — which is exactly why it is pinned here rather than
230
+ // left to four per-adapter assertions to keep saying the same thing.
231
+ origin: "origin",
227
232
  createdAt: "created_at",
228
233
  updatedAt: "updated_at"
229
234
  },
@@ -874,6 +879,34 @@ function runStateStoreContract(name, makeStore) {
874
879
  tag: "nope"
875
880
  })).toHaveLength(0);
876
881
  });
882
+ t("round-trips a run origin and filters listRuns by it, never matching an absent one", async () => {
883
+ await store.createRun(run({
884
+ id: "a",
885
+ origin: "@dudousxd/nestjs-catalog-pipeline"
886
+ }));
887
+ await store.createRun(run({
888
+ id: "b",
889
+ origin: "@dudousxd/nestjs-agent"
890
+ }));
891
+ await store.createRun(run({
892
+ id: "c"
893
+ }));
894
+ expect2((await store.getRun("a"))?.origin).toBe("@dudousxd/nestjs-catalog-pipeline");
895
+ expect2((await store.getRun("c"))?.origin).toBeUndefined();
896
+ expect2((await store.listRuns({
897
+ origin: "@dudousxd/nestjs-catalog-pipeline"
898
+ })).map((r) => r.id)).toEqual([
899
+ "a"
900
+ ]);
901
+ expect2(await store.listRuns({
902
+ origin: "unknown"
903
+ })).toEqual([]);
904
+ expect2((await store.listRuns({})).map((r) => r.id).sort()).toEqual([
905
+ "a",
906
+ "b",
907
+ "c"
908
+ ]);
909
+ });
877
910
  t("orders listRuns newest-first and paginates with limit/offset", async () => {
878
911
  await store.createRun(run({
879
912
  id: "old",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/admission-backend-conformance.ts","../src/assertions.ts","../src/durable-columns.ts","../src/harness.ts","../src/replay.ts","../src/state-store-conformance.ts","../src/steps.ts","../src/transport-conformance.ts"],"sourcesContent":["import type { AdmissionBackend, QueueConfig } from '@dudousxd/nestjs-durable-core';\nimport { describe, expect, it } from 'vitest';\n\n/**\n * Builds an {@link AdmissionBackend} bound to the given test clock. Implementations that hold their\n * own resources (e.g. a Redis connection) should register the instance for teardown out-of-band.\n */\nexport type AdmissionBackendFactory = (clock: () => number) => AdmissionBackend;\n\n/**\n * The SHARED cross-backend behavioural contract for the flow-control admission gate. Both the\n * in-process `InMemoryAdmissionBackend` and the Redis `RedisAdmissionBackend` run it, so their\n * concurrency / rate-limit / ordering semantics can never silently drift apart — backend-specific\n * concerns (leases, pub/sub, cross-pod globality) live in each adapter's own spec.\n *\n * The engine always passes a stable `waiterId`, so every gated call is order-tracked: ties with no\n * priority/fairness fall back to arrival FIFO (or LIFO when configured). These cases assert exactly\n * that, on ONE backend instance.\n */\nexport function runAdmissionBackendContract(\n name: string,\n makeBackend: AdmissionBackendFactory,\n): void {\n describe(`AdmissionBackend contract: ${name}`, () => {\n let now = 1_000_000;\n const make = (config: QueueConfig) => {\n now = 1_000_000;\n const backend = makeBackend(() => now);\n backend.register(config);\n return backend;\n };\n\n it('caps concurrency: a second call blocks until the first releases', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('q', { waiterId: 'a' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'b' })).ok).toBe(false);\n await b.release('q', 'a');\n expect((await b.tryAdmit('q', { waiterId: 'b' })).ok).toBe(true);\n });\n\n it('enforces a fixed-window rate limit', async () => {\n const b = make({ name: 'q', rateLimit: { limit: 2, periodMs: 1000 } });\n expect((await b.tryAdmit('q', { waiterId: '1' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: '2' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: '3' })).ok).toBe(false);\n now += 1001;\n expect((await b.tryAdmit('q', { waiterId: '4' })).ok).toBe(true);\n });\n\n it('admits the highest-priority waiter first when a slot frees', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'low', priority: 1 })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'high', priority: 9 })).ok).toBe(false);\n await b.release('q', 'holder');\n expect((await b.tryAdmit('q', { waiterId: 'low', priority: 1 })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'high', priority: 9 })).ok).toBe(true);\n });\n\n it('orders plain-concurrency waiters by arrival (FIFO) — no priority/fairness configured', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);\n await b.release('q', 'holder');\n // The earlier arrival wins the freed slot, on every backend.\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(true);\n });\n\n it('admits the most-recent arrival first when order is LIFO', async () => {\n const b = make({ name: 'q', concurrency: 1, order: 'lifo' });\n expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);\n await b.release('q', 'holder');\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(true);\n });\n\n it('round-robins a contended slot across fairness keys', async () => {\n const b = make({ name: 'q', concurrency: 1, fairness: 'key' });\n expect((await b.tryAdmit('q', { waiterId: 'a0', key: 'A' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'a1', key: 'A' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'b0', key: 'B' })).ok).toBe(false);\n await b.release('q', 'a0');\n // B (never served) wins over A (just served), not arrival order.\n expect((await b.tryAdmit('q', { waiterId: 'a1', key: 'A' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'b0', key: 'B' })).ok).toBe(true);\n });\n\n it('leaves an unregistered queue ungated', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('other', { waiterId: 'x' })).ok).toBe(true);\n expect((await b.tryAdmit('other', { waiterId: 'y' })).ok).toBe(true);\n });\n });\n}\n","import type { RunStatus, StateStore } from '@dudousxd/nestjs-durable-core';\n\nasync function requireRun(store: StateStore, runId: string) {\n const run = await store.getRun(runId);\n if (!run) throw new Error(`assertion failed: run ${runId} not found`);\n return run;\n}\n\nexport async function assertRunStatus(\n store: StateStore,\n runId: string,\n status: RunStatus,\n): Promise<void> {\n const run = await requireRun(store, runId);\n if (run.status !== status) {\n throw new Error(`expected run ${runId} to be \"${status}\", but it was \"${run.status}\"`);\n }\n}\n\nexport async function assertOutput(\n store: StateStore,\n runId: string,\n expected: unknown,\n): Promise<void> {\n const run = await requireRun(store, runId);\n if (JSON.stringify(run.output) !== JSON.stringify(expected)) {\n throw new Error(\n `expected run ${runId} output ${JSON.stringify(expected)}, got ${JSON.stringify(run.output)}`,\n );\n }\n}\n\n/** The names of the steps that have run, in order. */\nexport async function recordedSteps(store: StateStore, runId: string): Promise<string[]> {\n return (await store.listCheckpoints(runId)).map((cp) => cp.name);\n}\n\n/** Assert every named step ran (in any order). */\nexport async function assertStepsRan(\n store: StateStore,\n runId: string,\n names: string[],\n): Promise<void> {\n const ran = await recordedSteps(store, runId);\n for (const name of names) {\n if (!ran.includes(name)) {\n throw new Error(`expected step \"${name}\" to have run; ran: [${ran.join(', ')}]`);\n }\n }\n}\n\n/** Assert a step ran exactly the given number of attempts (e.g. to verify retries). */\nexport async function assertStepAttempts(\n store: StateStore,\n runId: string,\n name: string,\n attempts: number,\n): Promise<void> {\n const cp = (await store.listCheckpoints(runId)).find((c) => c.name === name);\n if (!cp) throw new Error(`expected step \"${name}\" to have run, but it did not`);\n if (cp.attempts !== attempts) {\n throw new Error(`expected step \"${name}\" to take ${attempts} attempt(s), took ${cp.attempts}`);\n }\n}\n","/**\n * The canonical physical column names for the durable tables, keyed by table → entity property →\n * column. This is the cross-adapter contract: a run written by one store adapter must be readable by\n * another, so EVERY adapter (TypeORM, MikroORM, Prisma, Drizzle) must map these properties to these\n * exact columns. The canonical convention is `snake_case`.\n *\n * Each adapter has a spec that asserts its physical columns against this map (see `assertDurableColumns`).\n * Without it, adapters silently diverge — one defaulting to its ORM's `snake_case` naming strategy,\n * another keeping the verbatim camelCase property name — and a store swap fails against an existing\n * table with \"Unknown column\" only at runtime. The map exists so that divergence is a failing unit\n * test, not a production incident.\n *\n * The camelCase (\"preserve\") naming is simply the property names themselves (the object keys), so no\n * separate map is needed for it.\n */\nexport const DURABLE_CANONICAL_COLUMNS = {\n durable_workflow_runs: {\n id: 'id',\n workflow: 'workflow',\n workflowVersion: 'workflow_version',\n status: 'status',\n input: 'input',\n output: 'output',\n error: 'error',\n wakeAt: 'wake_at',\n lockedBy: 'locked_by',\n lockedUntil: 'locked_until',\n recoveryAttempts: 'recovery_attempts',\n tags: 'tags',\n searchAttributes: 'search_attributes',\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n },\n durable_step_checkpoints: {\n runId: 'run_id',\n seq: 'seq',\n name: 'name',\n kind: 'kind',\n stepId: 'step_id',\n status: 'status',\n input: 'input',\n output: 'output',\n error: 'error',\n events: 'events',\n attempts: 'attempts',\n workerGroup: 'worker_group',\n wakeAt: 'wake_at',\n enqueuedAt: 'enqueued_at',\n startedAt: 'started_at',\n finishedAt: 'finished_at',\n },\n durable_run_attributes: {\n runId: 'run_id',\n key: 'key',\n strValue: 'str_value',\n numValue: 'num_value',\n },\n durable_signal_waiters: {\n token: 'token',\n runId: 'run_id',\n seq: 'seq',\n },\n durable_buffered_signals: {\n id: 'id',\n token: 'token',\n payload: 'payload',\n },\n durable_buffered_events: {\n id: 'id',\n name: 'name',\n payload: 'payload',\n publishedAt: 'published_at',\n },\n} as const;\n\nexport type DurableColumnMap = typeof DURABLE_CANONICAL_COLUMNS;\n\n/** A single column-name disagreement found by {@link assertDurableColumns}. */\nexport interface DurableColumnMismatch {\n table: string;\n property: string;\n expected: string;\n actual: string | undefined;\n}\n\n/**\n * Walk every (table, property) in the canonical contract and compare it to what an adapter actually\n * maps, via the supplied `resolve(table, property) => columnName`. Returns the list of mismatches\n * (empty when the adapter is canonical) so a spec can `expect(assertDurableColumns(resolve)).toEqual([])`.\n *\n * Pass `expected = DURABLE_CANONICAL_COLUMNS` (default) for the snake_case contract, or a map of the\n * property names to themselves to assert the camelCase (\"preserve\") naming.\n */\nexport function assertDurableColumns(\n resolve: (table: string, property: string) => string | undefined,\n expected: Record<string, Record<string, string>> = DURABLE_CANONICAL_COLUMNS,\n): DurableColumnMismatch[] {\n const mismatches: DurableColumnMismatch[] = [];\n for (const [table, props] of Object.entries(expected)) {\n for (const [property, column] of Object.entries(props)) {\n const actual = resolve(table, property);\n if (actual !== column) mismatches.push({ table, property, expected: column, actual });\n }\n }\n return mismatches;\n}\n\n/** The \"preserve\" (camelCase) expectation: every property maps to a column of the same name. */\nexport function preserveColumnExpectation(): Record<string, Record<string, string>> {\n const out: Record<string, Record<string, string>> = {};\n for (const [table, props] of Object.entries(DURABLE_CANONICAL_COLUMNS)) {\n out[table] = Object.fromEntries(Object.keys(props).map((p) => [p, p]));\n }\n return out;\n}\n","import {\n InMemoryStateStore,\n InMemoryTransport,\n type RunResult,\n type StartOptions,\n WorkflowEngine,\n type WorkflowRef,\n} from '@dudousxd/nestjs-durable-core';\n\n/** A clock you control, for testing durable sleeps without real time. */\nexport class MutableClock {\n constructor(private current = 1_000) {}\n readonly now = (): number => this.current;\n set(ms: number): void {\n this.current = ms;\n }\n advance(ms: number): void {\n this.current += ms;\n }\n}\n\nexport interface TestEngine {\n engine: WorkflowEngine;\n store: InMemoryStateStore;\n transport: InMemoryTransport;\n clock: MutableClock;\n /** Advance the clock by `ms` and resume any durable sleeps now due. */\n tick(ms: number): Promise<RunResult[]>;\n /**\n * Enqueue a run and wait for it to settle (terminal or suspended). `engine.start` only enqueues\n * now (dispatch model), so use this when a test needs the outcome synchronously.\n */\n run(\n workflow: WorkflowRef,\n input: unknown,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult>;\n}\n\n/**\n * A self-contained engine wired to in-memory store + transport and a controllable clock — run a\n * whole workflow in a unit test, with no Postgres, no Redis, and no real time.\n */\nexport function createTestEngine(): TestEngine {\n const store = new InMemoryStateStore();\n const transport = new InMemoryTransport();\n const clock = new MutableClock();\n const engine = new WorkflowEngine({ store, transport, clock: clock.now });\n return {\n engine,\n store,\n transport,\n clock,\n async tick(ms: number): Promise<RunResult[]> {\n clock.advance(ms);\n return engine.resumeDueTimers(clock.now());\n },\n async run(workflow, input, runId, opts): Promise<RunResult> {\n // `start` is overloaded per ref kind; a `WorkflowRef` union fits neither overload directly, so\n // resolve to the string overload (the engine accepts a class or name at runtime).\n await engine.start(workflow as string, input, runId, opts);\n return engine.waitForRun(runId);\n },\n };\n}\n","import {\n InMemoryStateStore,\n type StepCheckpoint,\n WorkflowEngine,\n type WorkflowRun,\n} from '@dudousxd/nestjs-durable-core';\n\nexport interface RunHistory {\n run: WorkflowRun;\n checkpoints: StepCheckpoint[];\n}\n\n/**\n * Replay a recorded run's history against the CURRENT workflow code and throw if they diverged.\n *\n * Capture a real (ideally in-flight or representative) run from production —\n * `{ run: await store.getRun(id), checkpoints: await store.listCheckpoints(id) }` — commit it as a\n * fixture, and assert here in CI. If a code change renamed/reordered/removed a step at a position the\n * history already recorded, the engine raises a `NonDeterminismError` on replay and this rethrows it,\n * catching the break *before* it reaches an in-flight run on deploy (the moment you'd otherwise\n * silently replay the wrong checkpoint into the wrong step). Register the workflow exactly as the app\n * does:\n *\n * ```ts\n * await assertReplayable((engine) => engine.register('pipeline', '1', pipeline.run), fixture);\n * ```\n */\nexport async function assertReplayable(\n register: (engine: WorkflowEngine) => void,\n history: RunHistory,\n): Promise<void> {\n const store = new InMemoryStateStore();\n // Seed as a suspended run with no lock so resume() replays the body against the recorded\n // checkpoints — no transport is wired, so nothing new is dispatched.\n await store.createRun({\n ...history.run,\n status: 'suspended',\n lockedBy: undefined,\n lockedUntil: undefined,\n });\n for (const cp of history.checkpoints) await store.saveCheckpoint(cp);\n\n const engine = new WorkflowEngine({ store });\n register(engine);\n const result = await engine.resume(history.run.id);\n if (result.status === 'failed' && result.error?.message?.startsWith('non-determinism')) {\n const err = new Error(result.error.message);\n err.name = 'NonDeterminismError';\n throw err;\n }\n}\n","import {\n type StateStore,\n type StepCheckpoint,\n WorkflowEngine,\n type WorkflowRun,\n} from '@dudousxd/nestjs-durable-core';\nimport { beforeEach, describe, expect, it } from 'vitest';\n\n/**\n * A freshly provisioned, empty {@link StateStore} plus a `cleanup` to release its resources (close\n * the connection, drop the schema, etc.). The conformance suite asks for one before each test so\n * every case starts from a clean slate — exactly like the per-store specs that build a `:memory:` DB.\n */\nexport interface StateStoreContext {\n store: StateStore;\n cleanup: () => Promise<void>;\n /**\n * Whether the store's optional `transaction` can run an ASYNC work callback. Defaults to `true`.\n * Set `false` only for a driver that genuinely can't — e.g. Drizzle on the SYNCHRONOUS\n * `better-sqlite3` driver, whose `transaction()` rejects a promise-returning callback (\"Transaction\n * function cannot return a promise\"). The same Drizzle adapter on an async driver (libSQL) works,\n * and the contract still asserts `transaction` for every other store, so this never hides drift.\n */\n supportsAsyncTransaction?: boolean;\n /**\n * Whether the store can filter `listRuns({ tag })`. Defaults to `true`. Set `false` ONLY for\n * Prisma-on-SQLite: the Prisma adapter filters tags with the `array_contains` JSON predicate, which\n * Prisma supports on its real targets (Postgres + MySQL) but NOT on SQLite. SQLite is only the\n * adapter's local TEST database, so the tag case is skipped there; every other store (and Prisma on\n * a real engine) still asserts it, so this doesn't hide drift in the supported configurations.\n */\n supportsTagFilter?: boolean;\n}\n\n/** Builds a fresh, empty store for one test. Called once per `it` (in `beforeEach`). */\nexport type StateStoreFactory = () => Promise<StateStoreContext>;\n\n/**\n * Thrown by a {@link StateStoreFactory} to SKIP the contract for an unavailable backend instead of\n * failing it — e.g. a testcontainers DB spec when Docker isn't running. Every contract case catches\n * it, logs once, and returns (a no-op pass), so `pnpm test:db` is green-with-skips off a dev box\n * without Docker rather than red.\n */\nexport class StateStoreUnavailableError extends Error {\n readonly isStateStoreUnavailable = true;\n constructor(message: string) {\n super(message);\n this.name = 'StateStoreUnavailableError';\n }\n}\n\nfunction isUnavailable(err: unknown): err is StateStoreUnavailableError {\n return !!err && typeof err === 'object' && 'isStateStoreUnavailable' in err;\n}\n\nconst at = new Date('2026-06-11T00:00:00.000Z');\n\nconst run = (over: Partial<WorkflowRun> = {}): WorkflowRun => ({\n id: 'r1',\n workflow: 'checkout',\n workflowVersion: '1',\n status: 'running',\n input: { orderId: 'o1' },\n createdAt: at,\n updatedAt: at,\n ...over,\n});\n\nconst checkpoint = (over: Partial<StepCheckpoint> = {}): StepCheckpoint => ({\n runId: 'r1',\n seq: 0,\n name: 'reserve',\n kind: 'local',\n stepId: 'r1:0',\n status: 'completed',\n output: { ok: true },\n attempts: 1,\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n ...over,\n});\n\n/**\n * The SHARED behavioral contract every `StateStore` must satisfy — in-memory and each ORM adapter\n * alike. Registered as a vitest `describe`; pass a `name` and a {@link StateStoreFactory} that builds\n * a fresh, empty store. The same assertions run against SQLite/in-memory under `pnpm test` and\n * against real Postgres/MySQL (via testcontainers) under `pnpm test:db`, so any drift between an\n * adapter and the canonical (in-memory) semantics — especially the search-attribute side-table\n * pushdown, which is implemented per-store — fails here instead of silently in production.\n *\n * Each adapter's own spec keeps its dialect-specific tests (DDL/longtext/EXISTS-SQL/JSON-tolerance);\n * this suite owns the cross-store behavior so those never drift apart.\n */\nexport function runStateStoreContract(name: string, makeStore: StateStoreFactory): void {\n describe(`StateStore contract: ${name}`, () => {\n let store: StateStore;\n let cleanup: (() => Promise<void>) | undefined;\n let supportsAsyncTransaction = true;\n let supportsTagFilter = true;\n let skipReason: string | undefined;\n let loggedSkip = false;\n\n beforeEach(async () => {\n try {\n const ctx = await makeStore();\n store = ctx.store;\n cleanup = ctx.cleanup;\n supportsAsyncTransaction = ctx.supportsAsyncTransaction ?? true;\n supportsTagFilter = ctx.supportsTagFilter ?? true;\n skipReason = undefined;\n } catch (err) {\n if (isUnavailable(err)) {\n // Backend unavailable (e.g. no Docker for a testcontainers spec): skip — don't fail.\n skipReason = err.message;\n if (!loggedSkip) {\n console.warn(`[state-store-contract] SKIPPING \"${name}\": ${skipReason}`);\n loggedSkip = true;\n }\n return;\n }\n throw err;\n }\n return async () => {\n await cleanup?.();\n };\n });\n\n /** Register a contract case that no-ops (passes) when the backend was reported unavailable. */\n const t = (label: string, fn: () => Promise<void>): void => {\n it(label, async () => {\n if (skipReason) return;\n await fn();\n });\n };\n\n // ---- create / get / update --------------------------------------------------------------\n\n t('creates a run and reads it back with its JSON input', async () => {\n await store.createRun(run());\n const loaded = await store.getRun('r1');\n expect(loaded?.workflow).toBe('checkout');\n expect(loaded?.input).toEqual({ orderId: 'o1' });\n });\n\n t('returns null for a missing run', async () => {\n expect(await store.getRun('nope')).toBeNull();\n });\n\n t('updates a run (status/output) and round-trips recoveryAttempts + dead status', async () => {\n await store.createRun(run({ recoveryAttempts: 3 }));\n await store.updateRun('r1', {\n status: 'completed',\n output: { total: 42 },\n updatedAt: at,\n });\n const done = await store.getRun('r1');\n expect(done?.status).toBe('completed');\n expect(done?.output).toEqual({ total: 42 });\n expect(done?.recoveryAttempts).toBe(3);\n\n await store.updateRun('r1', { status: 'dead', recoveryAttempts: 4 });\n const dead = await store.getRun('r1');\n expect(dead?.status).toBe('dead');\n expect(dead?.recoveryAttempts).toBe(4);\n });\n\n t('round-trips a run dispatch priority', async () => {\n await store.createRun(run({ id: 'withprio', priority: 7 }));\n await store.createRun(run({ id: 'noprio' }));\n expect((await store.getRun('withprio'))?.priority).toBe(7);\n expect((await store.getRun('noprio'))?.priority).toBeUndefined();\n });\n\n t('deleteRun removes the run and all its rows (checkpoints, waiters, attributes)', async () => {\n await store.createRun(run({ searchAttributes: { tier: 'pro' } }));\n await store.saveCheckpoint(checkpoint());\n await store.putSignalWaiter({ token: 'approve-r1', runId: 'r1', seq: 0 });\n\n await store.deleteRun('r1');\n\n // The run and every child row are gone — not merely marked terminal.\n expect(await store.getRun('r1')).toBeNull();\n expect(await store.listCheckpoints('r1')).toEqual([]);\n expect(await store.listSignalWaiters('approve-')).toEqual([]);\n // The normalized attribute side-table no longer matches it.\n expect(\n await store.listRuns({\n attributes: [{ key: 'tier', op: 'eq', value: 'pro' }],\n }),\n ).toEqual([]);\n });\n\n t('deleteRun is a no-op for a missing run', async () => {\n await expect(store.deleteRun('nope')).resolves.toBeUndefined();\n });\n\n t(\n 'updateRun maps every patchable field — clears error and patches tags/lockedBy/input/timers',\n async () => {\n // Guards against per-adapter patch-whitelist drift: a store that maps only a subset of fields\n // (or ignores `undefined` instead of clearing) would silently no-op these and fail here.\n await store.createRun(\n run({ status: 'failed', error: { message: 'boom' }, tags: ['old'], lockedBy: 'owner-1' }),\n );\n await store.updateRun('r1', {\n status: 'completed',\n output: { ok: true },\n error: undefined, // completion CLEARS the prior error\n input: { orderId: 'o2' },\n tags: ['x', 'y'],\n lockedBy: 'owner-2',\n wakeAt: 123_456,\n lockedUntil: 222_222,\n updatedAt: at,\n });\n const r = await store.getRun('r1');\n expect(r?.status).toBe('completed');\n expect(r?.output).toEqual({ ok: true });\n expect(r?.error).toBeUndefined();\n expect(r?.input).toEqual({ orderId: 'o2' });\n expect(r?.tags).toEqual(['x', 'y']);\n expect(r?.lockedBy).toBe('owner-2');\n expect(r?.wakeAt).toBe(123_456);\n expect(r?.lockedUntil).toBe(222_222);\n\n // The multi-instance REMOTE-decision marker must round-trip AND clear: the engine sets it\n // when it suspends on an awaited turn and clears it (`undefined`) when the decision lands. An\n // adapter that drops it on read, or ignores `undefined` instead of writing NULL, would silently\n // break completeRemoteDecision (it reads back the stale/absent marker and discards the decision).\n await store.updateRun('r1', { awaitingDecisionTaskId: 'turn-7' });\n expect((await store.getRun('r1'))?.awaitingDecisionTaskId).toBe('turn-7');\n await store.updateRun('r1', { awaitingDecisionTaskId: undefined });\n expect((await store.getRun('r1'))?.awaitingDecisionTaskId).toBeUndefined();\n },\n );\n\n // ---- checkpoints ------------------------------------------------------------------------\n\n t(\n 'upserts checkpoints, reads them by (runId, seq), and lists them ordered by seq',\n async () => {\n await store.createRun(run());\n await store.saveCheckpoint(checkpoint());\n await store.saveCheckpoint(\n checkpoint({ seq: 1, name: 'charge', output: { chargeId: 'ch_1' } }),\n );\n // Re-save seq 0 with a new output — upsert, not a duplicate row.\n await store.saveCheckpoint(checkpoint({ output: { ok: true, again: true } }));\n\n expect((await store.getCheckpoint('r1', 0))?.output).toEqual({ ok: true, again: true });\n expect((await store.getCheckpoint('r1', 1))?.name).toBe('charge');\n const list = await store.listCheckpoints('r1');\n expect(list.map((c) => c.seq)).toEqual([0, 1]);\n },\n );\n\n t(\n 'getLatestCheckpointByName returns the highest-seq match (and undefined for none)',\n async () => {\n await store.createRun(run());\n await store.saveCheckpoint(\n checkpoint({ seq: 0, name: 'event:progress', output: { pct: 10 } }),\n );\n await store.saveCheckpoint(checkpoint({ seq: 1, name: 'charge', output: { id: 'c1' } }));\n await store.saveCheckpoint(\n checkpoint({ seq: 2, name: 'event:progress', output: { pct: 50 } }),\n );\n await store.saveCheckpoint(\n checkpoint({ seq: 3, name: 'event:progress', output: { pct: 90 } }),\n );\n\n // Optional on the interface (the engine has a fallback), but a conformant store MUST provide\n // it — assert presence, then exercise the fast path.\n const getLatestCheckpointByName = store.getLatestCheckpointByName;\n expect(getLatestCheckpointByName).toBeDefined();\n if (!getLatestCheckpointByName) return;\n\n const latest = await getLatestCheckpointByName.call(store, 'r1', 'event:progress');\n expect(latest?.seq).toBe(3);\n expect(latest?.output).toEqual({ pct: 90 });\n expect(await getLatestCheckpointByName.call(store, 'r1', 'event:missing')).toBeUndefined();\n },\n );\n\n t(\n 'listCheckpointsByNamePrefix returns prefix matches ordered by seq (empty => none)',\n async () => {\n await store.createRun(run());\n await store.saveCheckpoint(checkpoint({ seq: 0, name: 'reserve' }));\n await store.saveCheckpoint(checkpoint({ seq: 1, name: 'spawn:0', output: 'child-a' }));\n await store.saveCheckpoint(checkpoint({ seq: 2, name: 'signal:child:c2' }));\n await store.saveCheckpoint(checkpoint({ seq: 3, name: 'event:progress' }));\n await store.saveCheckpoint(checkpoint({ seq: 4, name: 'spawn:1', output: 'child-b' }));\n\n // Optional on the interface (the engine has a fallback), but a conformant store MUST provide\n // it — assert presence, then exercise the fast path.\n const listCheckpointsByNamePrefix = store.listCheckpointsByNamePrefix;\n expect(listCheckpointsByNamePrefix).toBeDefined();\n if (!listCheckpointsByNamePrefix) return;\n\n const matches = await listCheckpointsByNamePrefix.call(store, 'r1', [\n 'signal:child:',\n 'spawn:',\n ]);\n expect(matches.map((c) => c.name)).toEqual(['spawn:0', 'signal:child:c2', 'spawn:1']);\n expect(await listCheckpointsByNamePrefix.call(store, 'r1', [])).toEqual([]);\n },\n );\n\n t('round-trips checkpoint events and reads back a missing checkpoint as null', async () => {\n await store.createRun(run());\n await store.saveCheckpoint(\n checkpoint({\n events: [{ at: 1, level: 'error', message: 'p-3 failed', name: 'p-3', status: 'failed' }],\n }),\n );\n expect((await store.getCheckpoint('r1', 0))?.events).toEqual([\n { at: 1, level: 'error', message: 'p-3 failed', name: 'p-3', status: 'failed' },\n ]);\n expect(await store.getCheckpoint('r1', 99)).toBeNull();\n });\n\n // ---- recovery / dispatch / timer scans --------------------------------------------------\n\n t('lists incomplete runs, pending runs (FIFO), and due timers', async () => {\n await store.createRun(run({ id: 'running1', status: 'running' }));\n await store.createRun(run({ id: 'suspended1', status: 'suspended', wakeAt: 5_000 }));\n await store.createRun(run({ id: 'done1', status: 'completed' }));\n await store.createRun(\n run({ id: 'pending2', status: 'pending', createdAt: new Date('2026-06-11T00:00:02.000Z') }),\n );\n await store.createRun(\n run({ id: 'pending1', status: 'pending', createdAt: new Date('2026-06-11T00:00:01.000Z') }),\n );\n\n expect((await store.listIncompleteRuns()).map((r) => r.id)).toEqual(['running1']);\n // FIFO by createdAt.\n expect((await store.listPendingRuns(10)).map((r) => r.id)).toEqual(['pending1', 'pending2']);\n expect((await store.listPendingRuns(1)).map((r) => r.id)).toEqual(['pending1']);\n expect((await store.listDueTimers(10_000)).map((r) => r.id)).toEqual(['suspended1']);\n expect(await store.listDueTimers(1_000)).toHaveLength(0);\n });\n\n // ---- lease / lock -----------------------------------------------------------------------\n\n t('tryLockRun is atomic and respects lease expiry', async () => {\n await store.createRun(run({ id: 'r1' }));\n expect(await store.tryLockRun('r1', 'A', 2_000, 1_000)).toBe(true);\n // B can't take it while A's lease is live.\n expect(await store.tryLockRun('r1', 'B', 3_000, 1_500)).toBe(false);\n // Once A's lease (2_000) has passed, B reclaims it.\n expect(await store.tryLockRun('r1', 'B', 4_000, 2_500)).toBe(true);\n // Release lets anyone re-acquire immediately.\n await store.releaseRunLock('r1');\n expect(await store.tryLockRun('r1', 'C', 9_000, 2_600)).toBe(true);\n });\n\n t('renewRunLock only succeeds for the current owner', async () => {\n await store.createRun(run({ id: 'r1' }));\n expect(await store.tryLockRun('r1', 'A', 2_000, 1_000)).toBe(true);\n // The holder heartbeats and keeps the lease.\n expect(await store.renewRunLock('r1', 'A', 5_000)).toBe(true);\n // A different instance can't renew a lease it doesn't hold.\n expect(await store.renewRunLock('r1', 'B', 9_000)).toBe(false);\n // And the renewed lease is honored: B still can't steal it before it expires.\n expect(await store.tryLockRun('r1', 'B', 6_000, 4_000)).toBe(false);\n });\n\n // ---- list filters: status / statuses / tag ----------------------------------------------\n\n t('filters listRuns by workflow and by status', async () => {\n await store.createRun(run({ id: 'a', workflow: 'checkout', status: 'running' }));\n await store.createRun(run({ id: 'b', workflow: 'refund', status: 'running' }));\n await store.createRun(run({ id: 'c', workflow: 'checkout', status: 'completed' }));\n\n expect((await store.listRuns({ workflow: 'checkout' })).map((r) => r.id).sort()).toEqual([\n 'a',\n 'c',\n ]);\n expect((await store.listRuns({ status: 'running' })).map((r) => r.id).sort()).toEqual([\n 'a',\n 'b',\n ]);\n expect(\n (await store.listRuns({ workflow: 'checkout', status: 'running' })).map((r) => r.id),\n ).toEqual(['a']);\n });\n\n t('filters listRuns by a status set (status IN ...) for singleton admission', async () => {\n await store.createRun(run({ id: 'a', status: 'running' }));\n await store.createRun(run({ id: 'b', status: 'suspended' }));\n await store.createRun(run({ id: 'c', status: 'completed' }));\n await store.createRun(run({ id: 'd', status: 'pending' }));\n\n expect(\n (await store.listRuns({ statuses: ['running', 'suspended'] })).map((r) => r.id).sort(),\n ).toEqual(['a', 'b']);\n // Single + set are ANDed (the narrower set wins).\n expect(\n (await store.listRuns({ status: 'running', statuses: ['running', 'suspended'] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n // Empty set matches nothing.\n expect(await store.listRuns({ statuses: [] })).toHaveLength(0);\n });\n\n t('filters listRuns by an exact tag (no substring match)', async () => {\n if (!supportsTagFilter) return; // Prisma + SQLite: array_contains is unsupported there (see flag doc)\n await store.createRun(run({ id: 'a', tags: ['etl', 'critical'] }));\n await store.createRun(run({ id: 'b', tags: ['etl-foo'] }));\n await store.createRun(run({ id: 'c' })); // no tags\n\n expect((await store.getRun('a'))?.tags).toEqual(['etl', 'critical']);\n expect((await store.listRuns({ tag: 'etl' })).map((r) => r.id)).toEqual(['a']);\n expect((await store.listRuns({ tag: 'etl-foo' })).map((r) => r.id)).toEqual(['b']);\n expect(await store.listRuns({ tag: 'nope' })).toHaveLength(0);\n });\n\n t('orders listRuns newest-first and paginates with limit/offset', async () => {\n await store.createRun(run({ id: 'old', createdAt: new Date('2026-06-11T00:00:00.000Z') }));\n await store.createRun(run({ id: 'mid', createdAt: new Date('2026-06-11T00:00:01.000Z') }));\n await store.createRun(run({ id: 'new', createdAt: new Date('2026-06-11T00:00:02.000Z') }));\n\n expect((await store.listRuns({})).map((r) => r.id)).toEqual(['new', 'mid', 'old']);\n expect((await store.listRuns({ limit: 2 })).map((r) => r.id)).toEqual(['new', 'mid']);\n expect((await store.listRuns({ limit: 2, offset: 1 })).map((r) => r.id)).toEqual([\n 'mid',\n 'old',\n ]);\n });\n\n // ---- search-attribute pushdown (range + equality + the missing-key contract) ------------\n\n t('round-trips searchAttributes and answers equality + range attribute queries', async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { amount: 30, tier: 'free' } }));\n await store.createRun(run({ id: 'b', searchAttributes: { amount: 200, tier: 'pro' } }));\n await store.createRun(run({ id: 'c', searchAttributes: { amount: 500, tier: 'pro' } }));\n\n expect((await store.getRun('b'))?.searchAttributes).toEqual({ amount: 200, tier: 'pro' });\n\n // Range (numeric).\n expect(\n (await store.listRuns({ attributes: [{ key: 'amount', op: 'gte', value: 200 }] }))\n .map((r) => r.id)\n .sort(),\n ).toEqual(['b', 'c']);\n // Two ANDed predicates (string eq + numeric range).\n expect(\n (\n await store.listRuns({\n attributes: [\n { key: 'tier', op: 'eq', value: 'pro' },\n { key: 'amount', op: 'lt', value: 300 },\n ],\n })\n ).map((r) => r.id),\n ).toEqual(['b']);\n // `ne` excludes the matching value AND absent keys (missing-key-never-matches contract).\n expect(\n (await store.listRuns({ attributes: [{ key: 'tier', op: 'ne', value: 'free' }] }))\n .map((r) => r.id)\n .sort(),\n ).toEqual(['b', 'c']);\n });\n\n t('matches a boolean search attribute by eq/ne', async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { vip: true } }));\n await store.createRun(run({ id: 'b', searchAttributes: { vip: false } }));\n await store.createRun(run({ id: 'c', searchAttributes: { other: 1 } })); // no `vip`\n\n expect(\n (await store.listRuns({ attributes: [{ key: 'vip', op: 'eq', value: true }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n // ne=true matches the explicit false but NOT the run missing `vip` (missing-key contract).\n expect(\n (await store.listRuns({ attributes: [{ key: 'vip', op: 'ne', value: true }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['b']);\n });\n\n t('a predicate on an absent key matches nothing (every op)', async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { amount: 100 } }));\n for (const op of ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'] as const) {\n expect(\n await store.listRuns({ attributes: [{ key: 'missing', op, value: 1 }] }),\n ).toHaveLength(0);\n }\n });\n\n t(\n 're-indexes the search-attribute side-table on update (old values stop matching)',\n async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { tier: 'free', amount: 10 } }));\n expect(\n (await store.listRuns({ attributes: [{ key: 'tier', op: 'eq', value: 'free' }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n\n await store.updateRun('a', { searchAttributes: { tier: 'pro' } });\n expect(\n (await store.listRuns({ attributes: [{ key: 'tier', op: 'eq', value: 'pro' }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n // Old key/value pairs are gone.\n expect(\n await store.listRuns({ attributes: [{ key: 'tier', op: 'eq', value: 'free' }] }),\n ).toHaveLength(0);\n expect(\n await store.listRuns({ attributes: [{ key: 'amount', op: 'eq', value: 10 }] }),\n ).toHaveLength(0);\n },\n );\n\n t('combines an attribute predicate with a coarse status filter and paginates', async () => {\n await store.createRun(run({ id: 'a', status: 'running', searchAttributes: { amount: 300 } }));\n await store.createRun(\n run({ id: 'b', status: 'completed', searchAttributes: { amount: 400 } }),\n );\n await store.createRun(run({ id: 'c', status: 'running', searchAttributes: { amount: 50 } }));\n\n const res = await store.listRuns({\n status: 'running',\n attributes: [{ key: 'amount', op: 'gte', value: 100 }],\n limit: 10,\n });\n expect(res.map((r) => r.id)).toEqual(['a']);\n });\n\n // ---- signal waiters & buffered signals --------------------------------------------------\n\n t('stores, lists by prefix, and atomically takes a signal waiter', async () => {\n await store.putSignalWaiter({ token: 'approve-1', runId: 'r1', seq: 3 });\n await store.putSignalWaiter({ token: 'approve-2', runId: 'r2', seq: 4 });\n await store.putSignalWaiter({ token: 'other-1', runId: 'r3', seq: 5 });\n\n expect((await store.listSignalWaiters('approve-')).map((w) => w.token).sort()).toEqual([\n 'approve-1',\n 'approve-2',\n ]);\n expect((await store.takeSignalWaiter('approve-1'))?.seq).toBe(3);\n // Taken exactly once.\n expect(await store.takeSignalWaiter('approve-1')).toBeNull();\n });\n\n t(\n 'round-trips a signal waiter parallelGroup (child-fan tag) through put → take → list',\n async () => {\n // A remote `gather_children` fan threads its group onto each child waiter so the resolving\n // `signal:child:` checkpoint carries it; the store must persist it on the waiter row.\n await store.putSignalWaiter({\n token: 'child:r.child.0',\n runId: 'r',\n seq: 0,\n parallelGroup: 'gather:0',\n });\n // A lone (non-fan) child await carries no group.\n await store.putSignalWaiter({ token: 'child:r.child.9', runId: 'r', seq: 9 });\n\n const listed = await store.listSignalWaiters('child:');\n expect(listed.find((w) => w.token === 'child:r.child.0')?.parallelGroup).toBe('gather:0');\n expect(listed.find((w) => w.token === 'child:r.child.9')?.parallelGroup).toBeUndefined();\n\n expect((await store.takeSignalWaiter('child:r.child.0'))?.parallelGroup).toBe('gather:0');\n expect((await store.takeSignalWaiter('child:r.child.9'))?.parallelGroup).toBeUndefined();\n },\n );\n\n t(\n \"removeSignalWaiter deletes only the exact (token, runId, seq) row, never a different run's\",\n async () => {\n // A stale identity for a token that's since been superseded (`token` is the store's primary\n // key — a later `putSignalWaiter` for the same token replaces the row) must be a no-op: it\n // must NOT steal the new owner's row out from under it.\n await store.putSignalWaiter({ token: 'approve-1', runId: 'r1', seq: 3 });\n await store.putSignalWaiter({ token: 'approve-1', runId: 'r2', seq: 7 });\n await store.removeSignalWaiter({ token: 'approve-1', runId: 'r1', seq: 3 });\n expect((await store.listSignalWaiters('approve-')).map((w) => w.runId)).toEqual(['r2']);\n\n // A mismatched runId/seq against the CURRENT row is also a no-op.\n await store.removeSignalWaiter({ token: 'approve-1', runId: 'r2', seq: 999 });\n expect((await store.listSignalWaiters('approve-')).map((w) => w.runId)).toEqual(['r2']);\n\n // The exact match deletes it.\n await store.removeSignalWaiter({ token: 'approve-1', runId: 'r2', seq: 7 });\n expect(await store.listSignalWaiters('approve-')).toEqual([]);\n\n // Removing an absent row entirely is a no-op, not an error.\n await store.removeSignalWaiter({ token: 'never-registered', runId: 'r1', seq: 0 });\n },\n );\n\n t('buffers signals and takes them FIFO per token', async () => {\n await store.bufferSignal('sig', { n: 1 });\n await store.bufferSignal('sig', { n: 2 });\n await store.bufferSignal('other', { n: 9 });\n\n expect(await store.takeBufferedSignal('sig')).toEqual({ payload: { n: 1 } });\n expect(await store.takeBufferedSignal('sig')).toEqual({ payload: { n: 2 } });\n expect(await store.takeBufferedSignal('sig')).toBeNull();\n expect(await store.takeBufferedSignal('other')).toEqual({ payload: { n: 9 } });\n });\n\n t('buffers events per name, oldest-first, and lists them without consuming', async () => {\n await store.bufferEvent({\n name: 'order.paid',\n payload: { n: 1 },\n id: 'e1',\n publishedAt: 100,\n });\n await store.bufferEvent({\n name: 'order.paid',\n payload: { n: 2 },\n id: 'e2',\n publishedAt: 200,\n });\n await store.bufferEvent({\n name: 'other.event',\n payload: { n: 9 },\n id: 'e3',\n publishedAt: 50,\n });\n\n const listed = await store.listBufferedEvents('order.paid', 10);\n expect(listed.map((e) => e.payload)).toEqual([{ n: 1 }, { n: 2 }]); // oldest (publishedAt) first\n expect(listed.map((e) => e.id)).toEqual(['e1', 'e2']);\n expect(listed[0]?.publishedAt).toBe(100);\n // listing does not consume — the same rows are still there.\n expect(await store.listBufferedEvents('order.paid', 10)).toHaveLength(2);\n expect(await store.listBufferedEvents('other.event', 10)).toEqual([\n { id: 'e3', payload: { n: 9 }, publishedAt: 50 },\n ]);\n });\n\n t('listBufferedEvents caps at `limit`', async () => {\n await store.bufferEvent({ name: 'evt', payload: 1, id: 'a', publishedAt: 1 });\n await store.bufferEvent({ name: 'evt', payload: 2, id: 'b', publishedAt: 2 });\n await store.bufferEvent({ name: 'evt', payload: 3, id: 'c', publishedAt: 3 });\n\n expect(await store.listBufferedEvents('evt', 2)).toHaveLength(2);\n });\n\n t(\n 'removeBufferedEvent atomically deletes by id — true iff a row existed, false on a repeat/absent id',\n async () => {\n await store.bufferEvent({ name: 'evt', payload: { ok: true }, id: 'x1', publishedAt: 1 });\n\n expect(await store.removeBufferedEvent('x1')).toBe(true);\n expect(await store.listBufferedEvents('evt', 10)).toEqual([]);\n // Already gone — a second attempt (the concurrent-claim arbiter) reports false, not an error.\n expect(await store.removeBufferedEvent('x1')).toBe(false);\n expect(await store.removeBufferedEvent('never-buffered')).toBe(false);\n },\n );\n\n // ---- transaction (optional) -------------------------------------------------------------\n\n t('transaction commits the checkpoint atomically and returns the work result', async () => {\n if (!store.transaction) return; // store without transactions (rare); skip\n if (!supportsAsyncTransaction) return; // sync driver (Drizzle + better-sqlite3); skip — see flag doc\n await store.createRun(run());\n const result = await store.transaction(async (tx) => {\n await tx.saveCheckpoint(checkpoint({ seq: 7, name: 'tx-step', output: { paid: true } }));\n return 'ok';\n });\n expect(result).toBe('ok');\n const cp = await store.getCheckpoint('r1', 7);\n expect(cp?.name).toBe('tx-step');\n expect(cp?.output).toEqual({ paid: true });\n });\n\n // ---- engine end-to-end durability -------------------------------------------------------\n\n t(\n 'runs the engine end-to-end durably, resuming without re-running completed steps',\n async () => {\n const engine = new WorkflowEngine({ store });\n let aRuns = 0;\n let failOnce = true;\n engine.register('wf', '1', async (ctx) => {\n const a = await ctx.localStep('a', async () => {\n aRuns += 1;\n return 10;\n });\n const b = await ctx.localStep('b', async () => {\n if (failOnce) {\n failOnce = false;\n throw new Error('boom');\n }\n return a + 5;\n });\n return b;\n });\n await engine.start('wf', { x: 1 }, 'run1');\n expect((await engine.waitForRun('run1')).status).toBe('failed');\n const resumed = await engine.resume('run1');\n expect(resumed.status).toBe('completed');\n expect(resumed.output).toBe(15);\n // Step `a` checkpointed `completed` the first turn, so replay returns it instead of re-running.\n expect(aRuns).toBe(1);\n },\n );\n });\n}\n","/** A step body that throws once, then returns `value` — drives a retry, or a crash-then-resume. */\nexport function failOnce<T>(\n value: T,\n error: Error = new Error('injected failure'),\n): () => Promise<T> {\n return failTimes(1, value, error);\n}\n\n/** A step body that throws the first `n` times, then returns `value`. */\nexport function failTimes<T>(\n n: number,\n value: T,\n error: Error = new Error('injected failure'),\n): () => Promise<T> {\n let calls = 0;\n return async () => {\n calls += 1;\n if (calls <= n) throw error;\n return value;\n };\n}\n","import { InMemoryStateStore, type Transport, WorkflowEngine } from '@dudousxd/nestjs-durable-core';\n\n/** A transport that can register worker handlers (every shipped transport does). */\nexport type HandleableTransport = Transport & {\n handle(name: string, fn: (input: unknown) => Promise<unknown>): void;\n close?(): Promise<void>;\n};\n\nconst ECHO_STEP_NAME = 'conformance.echo';\n\n/**\n * A durable `ctx.call` suspends the run; the worker result resumes it asynchronously (on whatever\n * tick/poll the transport delivers on). Poll the store until the run reaches a terminal state —\n * with a generous budget so a poll-based transport (DB/SQS) has time to round-trip.\n */\nasync function settle(store: InMemoryStateStore, runId: string, timeoutMs = 15_000) {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const run = await store.getRun(runId);\n if (run && run.status !== 'pending' && run.status !== 'running' && run.status !== 'suspended')\n return run;\n await new Promise((r) => setTimeout(r, 25));\n }\n throw new Error(`run ${runId} did not settle within ${timeoutMs}ms`);\n}\n\n/**\n * The contract every `Transport` must satisfy: a remote step dispatched through it round-trips to a\n * worker and back (success), and a throwing handler surfaces as a failed run (failure). Point it at\n * a freshly constructed transport (engine-side + worker `group` in one instance) to prove parity —\n * useful when adding a new transport. Throws on any mismatch; closes the transport when done.\n *\n * `idPrefix` keeps run ids unique across invocations against real, shared infra (queues/tables).\n */\nexport async function assertTransportConformance(\n transport: HandleableTransport,\n idPrefix = 'conf',\n): Promise<void> {\n try {\n // One engine/store/transport — a durable remote step routes its result back to this engine,\n // which resumes the run. (Two engines on one transport would fight over the result stream.)\n const store = new InMemoryStateStore();\n const engine = new WorkflowEngine({ store, transport });\n engine.register(\n 'conf-ok',\n '1',\n async (ctx) => (await ctx.step<{ doubled: number }>(ECHO_STEP_NAME, { n: 21 })).doubled,\n );\n engine.register('conf-fail', '1', async (ctx) => ctx.step(ECHO_STEP_NAME, { n: 1 }));\n\n // success: the worker doubles the input\n transport.handle(ECHO_STEP_NAME, async (input) => ({\n doubled: (input as { n: number }).n * 2,\n }));\n await engine.start('conf-ok', {}, `${idPrefix}-ok`);\n const ok = await settle(store, `${idPrefix}-ok`);\n if (ok.status !== 'completed' || ok.output !== 42) {\n throw new Error(`expected completed/42, got ${JSON.stringify(ok)}`);\n }\n\n // failure: a throwing handler surfaces as a failed run (re-register the same step to throw)\n transport.handle(ECHO_STEP_NAME, async () => {\n throw new Error('handler boom');\n });\n await engine.start('conf-fail', {}, `${idPrefix}-fail`);\n const failed = await settle(store, `${idPrefix}-fail`);\n if (failed.status !== 'failed') {\n throw new Error(`expected failed, got ${JSON.stringify(failed)}`);\n }\n } finally {\n await transport.close?.();\n }\n}\n"],"mappings":";;;;AACA,SAASA,UAAUC,QAAQC,UAAU;AAkB9B,SAASC,4BACdC,MACAC,aAAoC;AAEpCC,WAAS,8BAA8BF,IAAAA,IAAQ,MAAA;AAC7C,QAAIG,MAAM;AACV,UAAMC,OAAO,wBAACC,WAAAA;AACZF,YAAM;AACN,YAAMG,UAAUL,YAAY,MAAME,GAAAA;AAClCG,cAAQC,SAASF,MAAAA;AACjB,aAAOC;IACT,GALa;AAObE,OAAG,mEAAmE,YAAA;AACpE,YAAMC,IAAIL,KAAK;QAAEJ,MAAM;QAAKU,aAAa;MAAE,CAAA;AAC3CC,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;AAC3DJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAC3D,YAAMN,EAAEO,QAAQ,KAAK,GAAA;AACrBL,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;IAC7D,CAAA;AAEAP,OAAG,sCAAsC,YAAA;AACvC,YAAMC,IAAIL,KAAK;QAAEJ,MAAM;QAAKiB,WAAW;UAAEC,OAAO;UAAGC,UAAU;QAAK;MAAE,CAAA;AACpER,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;AAC3DJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;AAC3DJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAC3DZ,aAAO;AACPQ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;IAC7D,CAAA;AAEAP,OAAG,8DAA8D,YAAA;AAC/D,YAAMC,IAAIL,KAAK;QAAEJ,MAAM;QAAKU,aAAa;MAAE,CAAA;AAC3CC,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAS,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;AAChEJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAOO,UAAU;MAAE,CAAA,GAAIN,EAAE,EAAEC,KAAK,KAAA;AAC1EJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAQO,UAAU;MAAE,CAAA,GAAIN,EAAE,EAAEC,KAAK,KAAA;AAC3E,YAAMN,EAAEO,QAAQ,KAAK,QAAA;AACrBL,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAOO,UAAU;MAAE,CAAA,GAAIN,EAAE,EAAEC,KAAK,KAAA;AAC1EJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAQO,UAAU;MAAE,CAAA,GAAIN,EAAE,EAAEC,KAAK,IAAA;IAC7E,CAAA;AAEAP,OAAG,6FAAwF,YAAA;AACzF,YAAMC,IAAIL,KAAK;QAAEJ,MAAM;QAAKU,aAAa;MAAE,CAAA;AAC3CC,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAS,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;AAChEJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAQ,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAC/DJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAS,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAChE,YAAMN,EAAEO,QAAQ,KAAK,QAAA;AAErBL,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAS,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAChEJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAQ,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;IACjE,CAAA;AAEAP,OAAG,2DAA2D,YAAA;AAC5D,YAAMC,IAAIL,KAAK;QAAEJ,MAAM;QAAKU,aAAa;QAAGW,OAAO;MAAO,CAAA;AAC1DV,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAS,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;AAChEJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAQ,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAC/DJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAS,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAChE,YAAMN,EAAEO,QAAQ,KAAK,QAAA;AACrBL,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAQ,CAAA,GAAIC,EAAE,EAAEC,KAAK,KAAA;AAC/DJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;MAAS,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;IAClE,CAAA;AAEAP,OAAG,sDAAsD,YAAA;AACvD,YAAMC,IAAIL,KAAK;QAAEJ,MAAM;QAAKU,aAAa;QAAGY,UAAU;MAAM,CAAA;AAC5DX,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAMU,KAAK;MAAI,CAAA,GAAIT,EAAE,EAAEC,KAAK,IAAA;AACtEJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAMU,KAAK;MAAI,CAAA,GAAIT,EAAE,EAAEC,KAAK,KAAA;AACtEJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAMU,KAAK;MAAI,CAAA,GAAIT,EAAE,EAAEC,KAAK,KAAA;AACtE,YAAMN,EAAEO,QAAQ,KAAK,IAAA;AAErBL,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAMU,KAAK;MAAI,CAAA,GAAIT,EAAE,EAAEC,KAAK,KAAA;AACtEJ,cAAQ,MAAMF,EAAEG,SAAS,KAAK;QAAEC,UAAU;QAAMU,KAAK;MAAI,CAAA,GAAIT,EAAE,EAAEC,KAAK,IAAA;IACxE,CAAA;AAEAP,OAAG,wCAAwC,YAAA;AACzC,YAAMC,IAAIL,KAAK;QAAEJ,MAAM;QAAKU,aAAa;MAAE,CAAA;AAC3CC,cAAQ,MAAMF,EAAEG,SAAS,SAAS;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;AAC/DJ,cAAQ,MAAMF,EAAEG,SAAS,SAAS;QAAEC,UAAU;MAAI,CAAA,GAAIC,EAAE,EAAEC,KAAK,IAAA;IACjE,CAAA;EACF,CAAA;AACF;AA9EgBhB;;;ACjBhB,eAAeyB,WAAWC,OAAmBC,OAAa;AACxD,QAAMC,OAAM,MAAMF,MAAMG,OAAOF,KAAAA;AAC/B,MAAI,CAACC,KAAK,OAAM,IAAIE,MAAM,yBAAyBH,KAAAA,YAAiB;AACpE,SAAOC;AACT;AAJeH;AAMf,eAAsBM,gBACpBL,OACAC,OACAK,QAAiB;AAEjB,QAAMJ,OAAM,MAAMH,WAAWC,OAAOC,KAAAA;AACpC,MAAIC,KAAII,WAAWA,QAAQ;AACzB,UAAM,IAAIF,MAAM,gBAAgBH,KAAAA,WAAgBK,MAAAA,kBAAwBJ,KAAII,MAAM,GAAG;EACvF;AACF;AATsBD;AAWtB,eAAsBE,aACpBP,OACAC,OACAO,UAAiB;AAEjB,QAAMN,OAAM,MAAMH,WAAWC,OAAOC,KAAAA;AACpC,MAAIQ,KAAKC,UAAUR,KAAIS,MAAM,MAAMF,KAAKC,UAAUF,QAAAA,GAAW;AAC3D,UAAM,IAAIJ,MACR,gBAAgBH,KAAAA,WAAgBQ,KAAKC,UAAUF,QAAAA,CAAAA,SAAkBC,KAAKC,UAAUR,KAAIS,MAAM,CAAA,EAAG;EAEjG;AACF;AAXsBJ;AActB,eAAsBK,cAAcZ,OAAmBC,OAAa;AAClE,UAAQ,MAAMD,MAAMa,gBAAgBZ,KAAAA,GAAQa,IAAI,CAACC,OAAOA,GAAGC,IAAI;AACjE;AAFsBJ;AAKtB,eAAsBK,eACpBjB,OACAC,OACAiB,OAAe;AAEf,QAAMC,MAAM,MAAMP,cAAcZ,OAAOC,KAAAA;AACvC,aAAWe,QAAQE,OAAO;AACxB,QAAI,CAACC,IAAIC,SAASJ,IAAAA,GAAO;AACvB,YAAM,IAAIZ,MAAM,kBAAkBY,IAAAA,wBAA4BG,IAAIE,KAAK,IAAA,CAAA,GAAQ;IACjF;EACF;AACF;AAXsBJ;AActB,eAAsBK,mBACpBtB,OACAC,OACAe,MACAO,UAAgB;AAEhB,QAAMR,MAAM,MAAMf,MAAMa,gBAAgBZ,KAAAA,GAAQuB,KAAK,CAACC,MAAMA,EAAET,SAASA,IAAAA;AACvE,MAAI,CAACD,GAAI,OAAM,IAAIX,MAAM,kBAAkBY,IAAAA,+BAAmC;AAC9E,MAAID,GAAGQ,aAAaA,UAAU;AAC5B,UAAM,IAAInB,MAAM,kBAAkBY,IAAAA,aAAiBO,QAAAA,qBAA6BR,GAAGQ,QAAQ,EAAE;EAC/F;AACF;AAXsBD;;;ACrCf,IAAMI,4BAA4B;EACvCC,uBAAuB;IACrBC,IAAI;IACJC,UAAU;IACVC,iBAAiB;IACjBC,QAAQ;IACRC,OAAO;IACPC,QAAQ;IACRC,OAAO;IACPC,QAAQ;IACRC,UAAU;IACVC,aAAa;IACbC,kBAAkB;IAClBC,MAAM;IACNC,kBAAkB;IAClBC,WAAW;IACXC,WAAW;EACb;EACAC,0BAA0B;IACxBC,OAAO;IACPC,KAAK;IACLC,MAAM;IACNC,MAAM;IACNC,QAAQ;IACRjB,QAAQ;IACRC,OAAO;IACPC,QAAQ;IACRC,OAAO;IACPe,QAAQ;IACRC,UAAU;IACVC,aAAa;IACbhB,QAAQ;IACRiB,YAAY;IACZC,WAAW;IACXC,YAAY;EACd;EACAC,wBAAwB;IACtBX,OAAO;IACPY,KAAK;IACLC,UAAU;IACVC,UAAU;EACZ;EACAC,wBAAwB;IACtBC,OAAO;IACPhB,OAAO;IACPC,KAAK;EACP;EACAgB,0BAA0B;IACxBjC,IAAI;IACJgC,OAAO;IACPE,SAAS;EACX;EACAC,yBAAyB;IACvBnC,IAAI;IACJkB,MAAM;IACNgB,SAAS;IACTE,aAAa;EACf;AACF;AAoBO,SAASC,qBACdC,SACAC,WAAmDzC,2BAAyB;AAE5E,QAAM0C,aAAsC,CAAA;AAC5C,aAAW,CAACC,OAAOC,KAAAA,KAAUC,OAAOC,QAAQL,QAAAA,GAAW;AACrD,eAAW,CAACM,UAAUC,MAAAA,KAAWH,OAAOC,QAAQF,KAAAA,GAAQ;AACtD,YAAMK,SAAST,QAAQG,OAAOI,QAAAA;AAC9B,UAAIE,WAAWD,OAAQN,YAAWQ,KAAK;QAAEP;QAAOI;QAAUN,UAAUO;QAAQC;MAAO,CAAA;IACrF;EACF;AACA,SAAOP;AACT;AAZgBH;AAeT,SAASY,4BAAAA;AACd,QAAMC,MAA8C,CAAC;AACrD,aAAW,CAACT,OAAOC,KAAAA,KAAUC,OAAOC,QAAQ9C,yBAAAA,GAA4B;AACtEoD,QAAIT,KAAAA,IAASE,OAAOQ,YAAYR,OAAOS,KAAKV,KAAAA,EAAOW,IAAI,CAACC,MAAM;MAACA;MAAGA;KAAE,CAAA;EACtE;AACA,SAAOJ;AACT;AANgBD;;;AC5GhB,SACEM,oBACAC,mBAGAC,sBAEK;AAGA,IAAMC,eAAN,MAAMA;EAVb,OAUaA;;;;EACX,YAAoBC,UAAU,KAAO;SAAjBA,UAAAA;EAAkB;EAC7BC,MAAM,6BAAc,KAAKD,SAAnB;EACfE,IAAIC,IAAkB;AACpB,SAAKH,UAAUG;EACjB;EACAC,QAAQD,IAAkB;AACxB,SAAKH,WAAWG;EAClB;AACF;AAyBO,SAASE,mBAAAA;AACd,QAAMC,QAAQ,IAAIC,mBAAAA;AAClB,QAAMC,YAAY,IAAIC,kBAAAA;AACtB,QAAMC,QAAQ,IAAIX,aAAAA;AAClB,QAAMY,SAAS,IAAIC,eAAe;IAAEN;IAAOE;IAAWE,OAAOA,MAAMT;EAAI,CAAA;AACvE,SAAO;IACLU;IACAL;IACAE;IACAE;IACA,MAAMG,KAAKV,IAAU;AACnBO,YAAMN,QAAQD,EAAAA;AACd,aAAOQ,OAAOG,gBAAgBJ,MAAMT,IAAG,CAAA;IACzC;IACA,MAAMc,IAAIC,UAAUC,OAAOC,OAAOC,MAAI;AAGpC,YAAMR,OAAOS,MAAMJ,UAAoBC,OAAOC,OAAOC,IAAAA;AACrD,aAAOR,OAAOU,WAAWH,KAAAA;IAC3B;EACF;AACF;AArBgBb;;;AC5ChB,SACEiB,sBAAAA,qBAEAC,kBAAAA,uBAEK;AAsBP,eAAsBC,iBACpBC,UACAC,SAAmB;AAEnB,QAAMC,QAAQ,IAAIC,oBAAAA;AAGlB,QAAMD,MAAME,UAAU;IACpB,GAAGH,QAAQI;IACXC,QAAQ;IACRC,UAAUC;IACVC,aAAaD;EACf,CAAA;AACA,aAAWE,MAAMT,QAAQU,YAAa,OAAMT,MAAMU,eAAeF,EAAAA;AAEjE,QAAMG,SAAS,IAAIC,gBAAe;IAAEZ;EAAM,CAAA;AAC1CF,WAASa,MAAAA;AACT,QAAME,SAAS,MAAMF,OAAOG,OAAOf,QAAQI,IAAIY,EAAE;AACjD,MAAIF,OAAOT,WAAW,YAAYS,OAAOG,OAAOC,SAASC,WAAW,iBAAA,GAAoB;AACtF,UAAMC,MAAM,IAAIC,MAAMP,OAAOG,MAAMC,OAAO;AAC1CE,QAAIE,OAAO;AACX,UAAMF;EACR;AACF;AAvBsBtB;;;AC3BtB,SAGEyB,kBAAAA,uBAEK;AACP,SAASC,YAAYC,YAAAA,WAAUC,UAAAA,SAAQC,MAAAA,WAAU;AAqC1C,IAAMC,6BAAN,cAAyCC,MAAAA;EA3ChD,OA2CgDA;;;EACrCC,0BAA0B;EACnC,YAAYC,SAAiB;AAC3B,UAAMA,OAAAA;AACN,SAAKC,OAAO;EACd;AACF;AAEA,SAASC,cAAcC,KAAY;AACjC,SAAO,CAAC,CAACA,OAAO,OAAOA,QAAQ,YAAY,6BAA6BA;AAC1E;AAFSD;AAIT,IAAME,KAAK,oBAAIC,KAAK,0BAAA;AAEpB,IAAMC,MAAM,wBAACC,OAA6B,CAAC,OAAoB;EAC7DC,IAAI;EACJC,UAAU;EACVC,iBAAiB;EACjBC,QAAQ;EACRC,OAAO;IAAEC,SAAS;EAAK;EACvBC,WAAWV;EACXW,WAAWX;EACX,GAAGG;AACL,IATY;AAWZ,IAAMS,aAAa,wBAACT,OAAgC,CAAC,OAAuB;EAC1EU,OAAO;EACPC,KAAK;EACLjB,MAAM;EACNkB,MAAM;EACNC,QAAQ;EACRT,QAAQ;EACRU,QAAQ;IAAEC,IAAI;EAAK;EACnBC,UAAU;EACVC,YAAYpB;EACZqB,WAAWrB;EACXsB,YAAYtB;EACZ,GAAGG;AACL,IAbmB;AA0BZ,SAASoB,sBAAsB1B,MAAc2B,WAA4B;AAC9EC,EAAAA,UAAS,wBAAwB5B,IAAAA,IAAQ,MAAA;AACvC,QAAI6B;AACJ,QAAIC;AACJ,QAAIC,2BAA2B;AAC/B,QAAIC,oBAAoB;AACxB,QAAIC;AACJ,QAAIC,aAAa;AAEjBC,eAAW,YAAA;AACT,UAAI;AACF,cAAMC,MAAM,MAAMT,UAAAA;AAClBE,gBAAQO,IAAIP;AACZC,kBAAUM,IAAIN;AACdC,mCAA2BK,IAAIL,4BAA4B;AAC3DC,4BAAoBI,IAAIJ,qBAAqB;AAC7CC,qBAAaI;MACf,SAASnC,KAAK;AACZ,YAAID,cAAcC,GAAAA,GAAM;AAEtB+B,uBAAa/B,IAAIH;AACjB,cAAI,CAACmC,YAAY;AACfI,oBAAQC,KAAK,oCAAoCvC,IAAAA,MAAUiC,UAAAA,EAAY;AACvEC,yBAAa;UACf;AACA;QACF;AACA,cAAMhC;MACR;AACA,aAAO,YAAA;AACL,cAAM4B,UAAAA;MACR;IACF,CAAA;AAGA,UAAMU,IAAI,wBAACC,OAAeC,OAAAA;AACxBC,MAAAA,IAAGF,OAAO,YAAA;AACR,YAAIR,WAAY;AAChB,cAAMS,GAAAA;MACR,CAAA;IACF,GALU;AASVF,MAAE,uDAAuD,YAAA;AACvD,YAAMX,MAAMe,UAAUvC,IAAAA,CAAAA;AACtB,YAAMwC,SAAS,MAAMhB,MAAMiB,OAAO,IAAA;AAClCC,MAAAA,QAAOF,QAAQrC,QAAAA,EAAUwC,KAAK,UAAA;AAC9BD,MAAAA,QAAOF,QAAQlC,KAAAA,EAAOsC,QAAQ;QAAErC,SAAS;MAAK,CAAA;IAChD,CAAA;AAEA4B,MAAE,kCAAkC,YAAA;AAClCO,MAAAA,QAAO,MAAMlB,MAAMiB,OAAO,MAAA,CAAA,EAASI,SAAQ;IAC7C,CAAA;AAEAV,MAAE,gFAAgF,YAAA;AAChF,YAAMX,MAAMe,UAAUvC,IAAI;QAAE8C,kBAAkB;MAAE,CAAA,CAAA;AAChD,YAAMtB,MAAMuB,UAAU,MAAM;QAC1B1C,QAAQ;QACRU,QAAQ;UAAEiC,OAAO;QAAG;QACpBvC,WAAWX;MACb,CAAA;AACA,YAAMmD,OAAO,MAAMzB,MAAMiB,OAAO,IAAA;AAChCC,MAAAA,QAAOO,MAAM5C,MAAAA,EAAQsC,KAAK,WAAA;AAC1BD,MAAAA,QAAOO,MAAMlC,MAAAA,EAAQ6B,QAAQ;QAAEI,OAAO;MAAG,CAAA;AACzCN,MAAAA,QAAOO,MAAMH,gBAAAA,EAAkBH,KAAK,CAAA;AAEpC,YAAMnB,MAAMuB,UAAU,MAAM;QAAE1C,QAAQ;QAAQyC,kBAAkB;MAAE,CAAA;AAClE,YAAMI,OAAO,MAAM1B,MAAMiB,OAAO,IAAA;AAChCC,MAAAA,QAAOQ,MAAM7C,MAAAA,EAAQsC,KAAK,MAAA;AAC1BD,MAAAA,QAAOQ,MAAMJ,gBAAAA,EAAkBH,KAAK,CAAA;IACtC,CAAA;AAEAR,MAAE,uCAAuC,YAAA;AACvC,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAYiD,UAAU;MAAE,CAAA,CAAA;AACxD,YAAM3B,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;MAAS,CAAA,CAAA;AACzCwC,MAAAA,SAAQ,MAAMlB,MAAMiB,OAAO,UAAA,IAAcU,QAAAA,EAAUR,KAAK,CAAA;AACxDD,MAAAA,SAAQ,MAAMlB,MAAMiB,OAAO,QAAA,IAAYU,QAAAA,EAAUC,cAAa;IAChE,CAAA;AAEAjB,MAAE,iFAAiF,YAAA;AACjF,YAAMX,MAAMe,UAAUvC,IAAI;QAAEqD,kBAAkB;UAAEC,MAAM;QAAM;MAAE,CAAA,CAAA;AAC9D,YAAM9B,MAAM+B,eAAe7C,WAAAA,CAAAA;AAC3B,YAAMc,MAAMgC,gBAAgB;QAAEC,OAAO;QAAc9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AAEvE,YAAMY,MAAMkC,UAAU,IAAA;AAGtBhB,MAAAA,QAAO,MAAMlB,MAAMiB,OAAO,IAAA,CAAA,EAAOI,SAAQ;AACzCH,MAAAA,QAAO,MAAMlB,MAAMmC,gBAAgB,IAAA,CAAA,EAAOf,QAAQ,CAAA,CAAE;AACpDF,MAAAA,QAAO,MAAMlB,MAAMoC,kBAAkB,UAAA,CAAA,EAAahB,QAAQ,CAAA,CAAE;AAE5DF,MAAAA,QACE,MAAMlB,MAAMqC,SAAS;QACnBC,YAAY;UAAC;YAAEC,KAAK;YAAQC,IAAI;YAAMC,OAAO;UAAM;;MACrD,CAAA,CAAA,EACArB,QAAQ,CAAA,CAAE;IACd,CAAA;AAEAT,MAAE,0CAA0C,YAAA;AAC1C,YAAMO,QAAOlB,MAAMkC,UAAU,MAAA,CAAA,EAASQ,SAASd,cAAa;IAC9D,CAAA;AAEAjB,MACE,mGACA,YAAA;AAGE,YAAMX,MAAMe,UACVvC,IAAI;QAAEK,QAAQ;QAAU8D,OAAO;UAAEzE,SAAS;QAAO;QAAG0E,MAAM;UAAC;;QAAQC,UAAU;MAAU,CAAA,CAAA;AAEzF,YAAM7C,MAAMuB,UAAU,MAAM;QAC1B1C,QAAQ;QACRU,QAAQ;UAAEC,IAAI;QAAK;QACnBmD,OAAOnC;QACP1B,OAAO;UAAEC,SAAS;QAAK;QACvB6D,MAAM;UAAC;UAAK;;QACZC,UAAU;QACVC,QAAQ;QACRC,aAAa;QACb9D,WAAWX;MACb,CAAA;AACA,YAAM0E,IAAI,MAAMhD,MAAMiB,OAAO,IAAA;AAC7BC,MAAAA,QAAO8B,GAAGnE,MAAAA,EAAQsC,KAAK,WAAA;AACvBD,MAAAA,QAAO8B,GAAGzD,MAAAA,EAAQ6B,QAAQ;QAAE5B,IAAI;MAAK,CAAA;AACrC0B,MAAAA,QAAO8B,GAAGL,KAAAA,EAAOf,cAAa;AAC9BV,MAAAA,QAAO8B,GAAGlE,KAAAA,EAAOsC,QAAQ;QAAErC,SAAS;MAAK,CAAA;AACzCmC,MAAAA,QAAO8B,GAAGJ,IAAAA,EAAMxB,QAAQ;QAAC;QAAK;OAAI;AAClCF,MAAAA,QAAO8B,GAAGH,QAAAA,EAAU1B,KAAK,SAAA;AACzBD,MAAAA,QAAO8B,GAAGF,MAAAA,EAAQ3B,KAAK,MAAA;AACvBD,MAAAA,QAAO8B,GAAGD,WAAAA,EAAa5B,KAAK,MAAA;AAM5B,YAAMnB,MAAMuB,UAAU,MAAM;QAAE0B,wBAAwB;MAAS,CAAA;AAC/D/B,MAAAA,SAAQ,MAAMlB,MAAMiB,OAAO,IAAA,IAAQgC,sBAAAA,EAAwB9B,KAAK,QAAA;AAChE,YAAMnB,MAAMuB,UAAU,MAAM;QAAE0B,wBAAwBzC;MAAU,CAAA;AAChEU,MAAAA,SAAQ,MAAMlB,MAAMiB,OAAO,IAAA,IAAQgC,sBAAAA,EAAwBrB,cAAa;IAC1E,CAAA;AAKFjB,MACE,kFACA,YAAA;AACE,YAAMX,MAAMe,UAAUvC,IAAAA,CAAAA;AACtB,YAAMwB,MAAM+B,eAAe7C,WAAAA,CAAAA;AAC3B,YAAMc,MAAM+B,eACV7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;QAAUoB,QAAQ;UAAE2D,UAAU;QAAO;MAAE,CAAA,CAAA;AAGpE,YAAMlD,MAAM+B,eAAe7C,WAAW;QAAEK,QAAQ;UAAEC,IAAI;UAAM2D,OAAO;QAAK;MAAE,CAAA,CAAA;AAE1EjC,MAAAA,SAAQ,MAAMlB,MAAMoD,cAAc,MAAM,CAAA,IAAK7D,MAAAA,EAAQ6B,QAAQ;QAAE5B,IAAI;QAAM2D,OAAO;MAAK,CAAA;AACrFjC,MAAAA,SAAQ,MAAMlB,MAAMoD,cAAc,MAAM,CAAA,IAAKjF,IAAAA,EAAMgD,KAAK,QAAA;AACxD,YAAMkC,OAAO,MAAMrD,MAAMmC,gBAAgB,IAAA;AACzCjB,MAAAA,QAAOmC,KAAKC,IAAI,CAACC,MAAMA,EAAEnE,GAAG,CAAA,EAAGgC,QAAQ;QAAC;QAAG;OAAE;IAC/C,CAAA;AAGFT,MACE,oFACA,YAAA;AACE,YAAMX,MAAMe,UAAUvC,IAAAA,CAAAA;AACtB,YAAMwB,MAAM+B,eACV7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;QAAkBoB,QAAQ;UAAEiE,KAAK;QAAG;MAAE,CAAA,CAAA;AAEnE,YAAMxD,MAAM+B,eAAe7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;QAAUoB,QAAQ;UAAEb,IAAI;QAAK;MAAE,CAAA,CAAA;AACrF,YAAMsB,MAAM+B,eACV7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;QAAkBoB,QAAQ;UAAEiE,KAAK;QAAG;MAAE,CAAA,CAAA;AAEnE,YAAMxD,MAAM+B,eACV7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;QAAkBoB,QAAQ;UAAEiE,KAAK;QAAG;MAAE,CAAA,CAAA;AAKnE,YAAMC,4BAA4BzD,MAAMyD;AACxCvC,MAAAA,QAAOuC,yBAAAA,EAA2BC,YAAW;AAC7C,UAAI,CAACD,0BAA2B;AAEhC,YAAME,SAAS,MAAMF,0BAA0BG,KAAK5D,OAAO,MAAM,gBAAA;AACjEkB,MAAAA,QAAOyC,QAAQvE,GAAAA,EAAK+B,KAAK,CAAA;AACzBD,MAAAA,QAAOyC,QAAQpE,MAAAA,EAAQ6B,QAAQ;QAAEoC,KAAK;MAAG,CAAA;AACzCtC,MAAAA,QAAO,MAAMuC,0BAA0BG,KAAK5D,OAAO,MAAM,eAAA,CAAA,EAAkB4B,cAAa;IAC1F,CAAA;AAGFjB,MACE,qFACA,YAAA;AACE,YAAMX,MAAMe,UAAUvC,IAAAA,CAAAA;AACtB,YAAMwB,MAAM+B,eAAe7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;MAAU,CAAA,CAAA;AAChE,YAAM6B,MAAM+B,eAAe7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;QAAWoB,QAAQ;MAAU,CAAA,CAAA;AACnF,YAAMS,MAAM+B,eAAe7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;MAAkB,CAAA,CAAA;AACxE,YAAM6B,MAAM+B,eAAe7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;MAAiB,CAAA,CAAA;AACvE,YAAM6B,MAAM+B,eAAe7C,WAAW;QAAEE,KAAK;QAAGjB,MAAM;QAAWoB,QAAQ;MAAU,CAAA,CAAA;AAInF,YAAMsE,8BAA8B7D,MAAM6D;AAC1C3C,MAAAA,QAAO2C,2BAAAA,EAA6BH,YAAW;AAC/C,UAAI,CAACG,4BAA6B;AAElC,YAAMC,UAAU,MAAMD,4BAA4BD,KAAK5D,OAAO,MAAM;QAClE;QACA;OACD;AACDkB,MAAAA,QAAO4C,QAAQR,IAAI,CAACC,MAAMA,EAAEpF,IAAI,CAAA,EAAGiD,QAAQ;QAAC;QAAW;QAAmB;OAAU;AACpFF,MAAAA,QAAO,MAAM2C,4BAA4BD,KAAK5D,OAAO,MAAM,CAAA,CAAE,CAAA,EAAGoB,QAAQ,CAAA,CAAE;IAC5E,CAAA;AAGFT,MAAE,6EAA6E,YAAA;AAC7E,YAAMX,MAAMe,UAAUvC,IAAAA,CAAAA;AACtB,YAAMwB,MAAM+B,eACV7C,WAAW;QACT6E,QAAQ;UAAC;YAAEzF,IAAI;YAAG0F,OAAO;YAAS9F,SAAS;YAAcC,MAAM;YAAOU,QAAQ;UAAS;;MACzF,CAAA,CAAA;AAEFqC,MAAAA,SAAQ,MAAMlB,MAAMoD,cAAc,MAAM,CAAA,IAAKW,MAAAA,EAAQ3C,QAAQ;QAC3D;UAAE9C,IAAI;UAAG0F,OAAO;UAAS9F,SAAS;UAAcC,MAAM;UAAOU,QAAQ;QAAS;OAC/E;AACDqC,MAAAA,QAAO,MAAMlB,MAAMoD,cAAc,MAAM,EAAA,CAAA,EAAK/B,SAAQ;IACtD,CAAA;AAIAV,MAAE,8DAA8D,YAAA;AAC9D,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAYG,QAAQ;MAAU,CAAA,CAAA;AAC9D,YAAMmB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAcG,QAAQ;QAAaiE,QAAQ;MAAM,CAAA,CAAA;AACjF,YAAM9C,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAASG,QAAQ;MAAY,CAAA,CAAA;AAC7D,YAAMmB,MAAMe,UACVvC,IAAI;QAAEE,IAAI;QAAYG,QAAQ;QAAWG,WAAW,oBAAIT,KAAK,0BAAA;MAA4B,CAAA,CAAA;AAE3F,YAAMyB,MAAMe,UACVvC,IAAI;QAAEE,IAAI;QAAYG,QAAQ;QAAWG,WAAW,oBAAIT,KAAK,0BAAA;MAA4B,CAAA,CAAA;AAG3F2C,MAAAA,SAAQ,MAAMlB,MAAMiE,mBAAkB,GAAIX,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;OAAW;AAEhFF,MAAAA,SAAQ,MAAMlB,MAAMkE,gBAAgB,EAAA,GAAKZ,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;QAAY;OAAW;AAC3FF,MAAAA,SAAQ,MAAMlB,MAAMkE,gBAAgB,CAAA,GAAIZ,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;OAAW;AAC9EF,MAAAA,SAAQ,MAAMlB,MAAMmE,cAAc,GAAA,GAASb,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;OAAa;AACnFF,MAAAA,QAAO,MAAMlB,MAAMmE,cAAc,GAAA,CAAA,EAAQC,aAAa,CAAA;IACxD,CAAA;AAIAzD,MAAE,kDAAkD,YAAA;AAClD,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;MAAK,CAAA,CAAA;AACrCwC,MAAAA,QAAO,MAAMlB,MAAMqE,WAAW,MAAM,KAAK,KAAO,GAAA,CAAA,EAAQlD,KAAK,IAAA;AAE7DD,MAAAA,QAAO,MAAMlB,MAAMqE,WAAW,MAAM,KAAK,KAAO,IAAA,CAAA,EAAQlD,KAAK,KAAA;AAE7DD,MAAAA,QAAO,MAAMlB,MAAMqE,WAAW,MAAM,KAAK,KAAO,IAAA,CAAA,EAAQlD,KAAK,IAAA;AAE7D,YAAMnB,MAAMsE,eAAe,IAAA;AAC3BpD,MAAAA,QAAO,MAAMlB,MAAMqE,WAAW,MAAM,KAAK,KAAO,IAAA,CAAA,EAAQlD,KAAK,IAAA;IAC/D,CAAA;AAEAR,MAAE,oDAAoD,YAAA;AACpD,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;MAAK,CAAA,CAAA;AACrCwC,MAAAA,QAAO,MAAMlB,MAAMqE,WAAW,MAAM,KAAK,KAAO,GAAA,CAAA,EAAQlD,KAAK,IAAA;AAE7DD,MAAAA,QAAO,MAAMlB,MAAMuE,aAAa,MAAM,KAAK,GAAA,CAAA,EAAQpD,KAAK,IAAA;AAExDD,MAAAA,QAAO,MAAMlB,MAAMuE,aAAa,MAAM,KAAK,GAAA,CAAA,EAAQpD,KAAK,KAAA;AAExDD,MAAAA,QAAO,MAAMlB,MAAMqE,WAAW,MAAM,KAAK,KAAO,GAAA,CAAA,EAAQlD,KAAK,KAAA;IAC/D,CAAA;AAIAR,MAAE,8CAA8C,YAAA;AAC9C,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKC,UAAU;QAAYE,QAAQ;MAAU,CAAA,CAAA;AAC7E,YAAMmB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKC,UAAU;QAAUE,QAAQ;MAAU,CAAA,CAAA;AAC3E,YAAMmB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKC,UAAU;QAAYE,QAAQ;MAAY,CAAA,CAAA;AAE/EqC,MAAAA,SAAQ,MAAMlB,MAAMqC,SAAS;QAAE1D,UAAU;MAAW,CAAA,GAAI2E,IAAI,CAACN,MAAMA,EAAEtE,EAAE,EAAE8F,KAAI,CAAA,EAAIpD,QAAQ;QACvF;QACA;OACD;AACDF,MAAAA,SAAQ,MAAMlB,MAAMqC,SAAS;QAAExD,QAAQ;MAAU,CAAA,GAAIyE,IAAI,CAACN,MAAMA,EAAEtE,EAAE,EAAE8F,KAAI,CAAA,EAAIpD,QAAQ;QACpF;QACA;OACD;AACDF,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAE1D,UAAU;QAAYE,QAAQ;MAAU,CAAA,GAAIyE,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EACnF0C,QAAQ;QAAC;OAAI;IACjB,CAAA;AAEAT,MAAE,4EAA4E,YAAA;AAC5E,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKG,QAAQ;MAAU,CAAA,CAAA;AACvD,YAAMmB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKG,QAAQ;MAAY,CAAA,CAAA;AACzD,YAAMmB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKG,QAAQ;MAAY,CAAA,CAAA;AACzD,YAAMmB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKG,QAAQ;MAAU,CAAA,CAAA;AAEvDqC,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAEoC,UAAU;UAAC;UAAW;;MAAa,CAAA,GAAInB,IAAI,CAACN,MAAMA,EAAEtE,EAAE,EAAE8F,KAAI,CAAA,EACpFpD,QAAQ;QAAC;QAAK;OAAI;AAEpBF,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAExD,QAAQ;QAAW4F,UAAU;UAAC;UAAW;;MAAa,CAAA,GAAInB,IAChF,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAEb0C,QAAQ;QAAC;OAAI;AAEfF,MAAAA,QAAO,MAAMlB,MAAMqC,SAAS;QAAEoC,UAAU,CAAA;MAAG,CAAA,CAAA,EAAIL,aAAa,CAAA;IAC9D,CAAA;AAEAzD,MAAE,yDAAyD,YAAA;AACzD,UAAI,CAACR,kBAAmB;AACxB,YAAMH,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKkE,MAAM;UAAC;UAAO;;MAAY,CAAA,CAAA;AAC/D,YAAM5C,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKkE,MAAM;UAAC;;MAAW,CAAA,CAAA;AACvD,YAAM5C,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;MAAI,CAAA,CAAA;AAEpCwC,MAAAA,SAAQ,MAAMlB,MAAMiB,OAAO,GAAA,IAAO2B,IAAAA,EAAMxB,QAAQ;QAAC;QAAO;OAAW;AACnEF,MAAAA,SAAQ,MAAMlB,MAAMqC,SAAS;QAAEqC,KAAK;MAAM,CAAA,GAAIpB,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;OAAI;AAC7EF,MAAAA,SAAQ,MAAMlB,MAAMqC,SAAS;QAAEqC,KAAK;MAAU,CAAA,GAAIpB,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;OAAI;AACjFF,MAAAA,QAAO,MAAMlB,MAAMqC,SAAS;QAAEqC,KAAK;MAAO,CAAA,CAAA,EAAIN,aAAa,CAAA;IAC7D,CAAA;AAEAzD,MAAE,gEAAgE,YAAA;AAChE,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAOM,WAAW,oBAAIT,KAAK,0BAAA;MAA4B,CAAA,CAAA;AACvF,YAAMyB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAOM,WAAW,oBAAIT,KAAK,0BAAA;MAA4B,CAAA,CAAA;AACvF,YAAMyB,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAOM,WAAW,oBAAIT,KAAK,0BAAA;MAA4B,CAAA,CAAA;AAEvF2C,MAAAA,SAAQ,MAAMlB,MAAMqC,SAAS,CAAC,CAAA,GAAIiB,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;QAAO;QAAO;OAAM;AACjFF,MAAAA,SAAQ,MAAMlB,MAAMqC,SAAS;QAAEsC,OAAO;MAAE,CAAA,GAAIrB,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;QAAO;OAAM;AACpFF,MAAAA,SAAQ,MAAMlB,MAAMqC,SAAS;QAAEsC,OAAO;QAAGC,QAAQ;MAAE,CAAA,GAAItB,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAC/E;QACA;OACD;IACH,CAAA;AAIAT,MAAE,+EAA+E,YAAA;AAC/E,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEgD,QAAQ;UAAI/C,MAAM;QAAO;MAAE,CAAA,CAAA;AACpF,YAAM9B,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEgD,QAAQ;UAAK/C,MAAM;QAAM;MAAE,CAAA,CAAA;AACpF,YAAM9B,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEgD,QAAQ;UAAK/C,MAAM;QAAM;MAAE,CAAA,CAAA;AAEpFZ,MAAAA,SAAQ,MAAMlB,MAAMiB,OAAO,GAAA,IAAOY,gBAAAA,EAAkBT,QAAQ;QAAEyD,QAAQ;QAAK/C,MAAM;MAAM,CAAA;AAGvFZ,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAUC,IAAI;YAAOC,OAAO;UAAI;;MAAG,CAAA,GAC5Ea,IAAI,CAACN,MAAMA,EAAEtE,EAAE,EACf8F,KAAI,CAAA,EACPpD,QAAQ;QAAC;QAAK;OAAI;AAEpBF,MAAAA,SAEI,MAAMlB,MAAMqC,SAAS;QACnBC,YAAY;UACV;YAAEC,KAAK;YAAQC,IAAI;YAAMC,OAAO;UAAM;UACtC;YAAEF,KAAK;YAAUC,IAAI;YAAMC,OAAO;UAAI;;MAE1C,CAAA,GACAa,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EACjB0C,QAAQ;QAAC;OAAI;AAEfF,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAQC,IAAI;YAAMC,OAAO;UAAO;;MAAG,CAAA,GAC5Ea,IAAI,CAACN,MAAMA,EAAEtE,EAAE,EACf8F,KAAI,CAAA,EACPpD,QAAQ;QAAC;QAAK;OAAI;IACtB,CAAA;AAEAT,MAAE,+CAA+C,YAAA;AAC/C,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEiD,KAAK;QAAK;MAAE,CAAA,CAAA;AACrE,YAAM9E,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEiD,KAAK;QAAM;MAAE,CAAA,CAAA;AACtE,YAAM9E,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEkD,OAAO;QAAE;MAAE,CAAA,CAAA;AAEpE7D,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAOC,IAAI;YAAMC,OAAO;UAAK;;MAAG,CAAA,GAAIa,IAC9E,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAEb0C,QAAQ;QAAC;OAAI;AAEfF,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAOC,IAAI;YAAMC,OAAO;UAAK;;MAAG,CAAA,GAAIa,IAC9E,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAEb0C,QAAQ;QAAC;OAAI;IACjB,CAAA;AAEAT,MAAE,2DAA2D,YAAA;AAC3D,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEgD,QAAQ;QAAI;MAAE,CAAA,CAAA;AACvE,iBAAWrC,MAAM;QAAC;QAAM;QAAM;QAAM;QAAO;QAAM;SAAiB;AAChEtB,QAAAA,QACE,MAAMlB,MAAMqC,SAAS;UAAEC,YAAY;YAAC;cAAEC,KAAK;cAAWC;cAAIC,OAAO;YAAE;;QAAG,CAAA,CAAA,EACtE2B,aAAa,CAAA;MACjB;IACF,CAAA;AAEAzD,MACE,mFACA,YAAA;AACE,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKmD,kBAAkB;UAAEC,MAAM;UAAQ+C,QAAQ;QAAG;MAAE,CAAA,CAAA;AACpF3D,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAQC,IAAI;YAAMC,OAAO;UAAO;;MAAG,CAAA,GAAIa,IACjF,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAEb0C,QAAQ;QAAC;OAAI;AAEf,YAAMpB,MAAMuB,UAAU,KAAK;QAAEM,kBAAkB;UAAEC,MAAM;QAAM;MAAE,CAAA;AAC/DZ,MAAAA,SACG,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAQC,IAAI;YAAMC,OAAO;UAAM;;MAAG,CAAA,GAAIa,IAChF,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAEb0C,QAAQ;QAAC;OAAI;AAEfF,MAAAA,QACE,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAQC,IAAI;YAAMC,OAAO;UAAO;;MAAG,CAAA,CAAA,EAC9E2B,aAAa,CAAA;AACflD,MAAAA,QACE,MAAMlB,MAAMqC,SAAS;QAAEC,YAAY;UAAC;YAAEC,KAAK;YAAUC,IAAI;YAAMC,OAAO;UAAG;;MAAG,CAAA,CAAA,EAC5E2B,aAAa,CAAA;IACjB,CAAA;AAGFzD,MAAE,6EAA6E,YAAA;AAC7E,YAAMX,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKG,QAAQ;QAAWgD,kBAAkB;UAAEgD,QAAQ;QAAI;MAAE,CAAA,CAAA;AAC1F,YAAM7E,MAAMe,UACVvC,IAAI;QAAEE,IAAI;QAAKG,QAAQ;QAAagD,kBAAkB;UAAEgD,QAAQ;QAAI;MAAE,CAAA,CAAA;AAExE,YAAM7E,MAAMe,UAAUvC,IAAI;QAAEE,IAAI;QAAKG,QAAQ;QAAWgD,kBAAkB;UAAEgD,QAAQ;QAAG;MAAE,CAAA,CAAA;AAEzF,YAAMG,MAAM,MAAMhF,MAAMqC,SAAS;QAC/BxD,QAAQ;QACRyD,YAAY;UAAC;YAAEC,KAAK;YAAUC,IAAI;YAAOC,OAAO;UAAI;;QACpDkC,OAAO;MACT,CAAA;AACAzD,MAAAA,QAAO8D,IAAI1B,IAAI,CAACN,MAAMA,EAAEtE,EAAE,CAAA,EAAG0C,QAAQ;QAAC;OAAI;IAC5C,CAAA;AAIAT,MAAE,iEAAiE,YAAA;AACjE,YAAMX,MAAMgC,gBAAgB;QAAEC,OAAO;QAAa9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AACtE,YAAMY,MAAMgC,gBAAgB;QAAEC,OAAO;QAAa9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AACtE,YAAMY,MAAMgC,gBAAgB;QAAEC,OAAO;QAAW9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AAEpE8B,MAAAA,SAAQ,MAAMlB,MAAMoC,kBAAkB,UAAA,GAAakB,IAAI,CAAC2B,MAAMA,EAAEhD,KAAK,EAAEuC,KAAI,CAAA,EAAIpD,QAAQ;QACrF;QACA;OACD;AACDF,MAAAA,SAAQ,MAAMlB,MAAMkF,iBAAiB,WAAA,IAAe9F,GAAAA,EAAK+B,KAAK,CAAA;AAE9DD,MAAAA,QAAO,MAAMlB,MAAMkF,iBAAiB,WAAA,CAAA,EAAc7D,SAAQ;IAC5D,CAAA;AAEAV,MACE,iGACA,YAAA;AAGE,YAAMX,MAAMgC,gBAAgB;QAC1BC,OAAO;QACP9C,OAAO;QACPC,KAAK;QACL+F,eAAe;MACjB,CAAA;AAEA,YAAMnF,MAAMgC,gBAAgB;QAAEC,OAAO;QAAmB9C,OAAO;QAAKC,KAAK;MAAE,CAAA;AAE3E,YAAMgG,SAAS,MAAMpF,MAAMoC,kBAAkB,QAAA;AAC7ClB,MAAAA,QAAOkE,OAAOC,KAAK,CAACJ,MAAMA,EAAEhD,UAAU,iBAAA,GAAoBkD,aAAAA,EAAehE,KAAK,UAAA;AAC9ED,MAAAA,QAAOkE,OAAOC,KAAK,CAACJ,MAAMA,EAAEhD,UAAU,iBAAA,GAAoBkD,aAAAA,EAAevD,cAAa;AAEtFV,MAAAA,SAAQ,MAAMlB,MAAMkF,iBAAiB,iBAAA,IAAqBC,aAAAA,EAAehE,KAAK,UAAA;AAC9ED,MAAAA,SAAQ,MAAMlB,MAAMkF,iBAAiB,iBAAA,IAAqBC,aAAAA,EAAevD,cAAa;IACxF,CAAA;AAGFjB,MACE,8FACA,YAAA;AAIE,YAAMX,MAAMgC,gBAAgB;QAAEC,OAAO;QAAa9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AACtE,YAAMY,MAAMgC,gBAAgB;QAAEC,OAAO;QAAa9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AACtE,YAAMY,MAAMsF,mBAAmB;QAAErD,OAAO;QAAa9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AACzE8B,MAAAA,SAAQ,MAAMlB,MAAMoC,kBAAkB,UAAA,GAAakB,IAAI,CAAC2B,MAAMA,EAAE9F,KAAK,CAAA,EAAGiC,QAAQ;QAAC;OAAK;AAGtF,YAAMpB,MAAMsF,mBAAmB;QAAErD,OAAO;QAAa9C,OAAO;QAAMC,KAAK;MAAI,CAAA;AAC3E8B,MAAAA,SAAQ,MAAMlB,MAAMoC,kBAAkB,UAAA,GAAakB,IAAI,CAAC2B,MAAMA,EAAE9F,KAAK,CAAA,EAAGiC,QAAQ;QAAC;OAAK;AAGtF,YAAMpB,MAAMsF,mBAAmB;QAAErD,OAAO;QAAa9C,OAAO;QAAMC,KAAK;MAAE,CAAA;AACzE8B,MAAAA,QAAO,MAAMlB,MAAMoC,kBAAkB,UAAA,CAAA,EAAahB,QAAQ,CAAA,CAAE;AAG5D,YAAMpB,MAAMsF,mBAAmB;QAAErD,OAAO;QAAoB9C,OAAO;QAAMC,KAAK;MAAE,CAAA;IAClF,CAAA;AAGFuB,MAAE,iDAAiD,YAAA;AACjD,YAAMX,MAAMuF,aAAa,OAAO;QAAEC,GAAG;MAAE,CAAA;AACvC,YAAMxF,MAAMuF,aAAa,OAAO;QAAEC,GAAG;MAAE,CAAA;AACvC,YAAMxF,MAAMuF,aAAa,SAAS;QAAEC,GAAG;MAAE,CAAA;AAEzCtE,MAAAA,QAAO,MAAMlB,MAAMyF,mBAAmB,KAAA,CAAA,EAAQrE,QAAQ;QAAEsE,SAAS;UAAEF,GAAG;QAAE;MAAE,CAAA;AAC1EtE,MAAAA,QAAO,MAAMlB,MAAMyF,mBAAmB,KAAA,CAAA,EAAQrE,QAAQ;QAAEsE,SAAS;UAAEF,GAAG;QAAE;MAAE,CAAA;AAC1EtE,MAAAA,QAAO,MAAMlB,MAAMyF,mBAAmB,KAAA,CAAA,EAAQpE,SAAQ;AACtDH,MAAAA,QAAO,MAAMlB,MAAMyF,mBAAmB,OAAA,CAAA,EAAUrE,QAAQ;QAAEsE,SAAS;UAAEF,GAAG;QAAE;MAAE,CAAA;IAC9E,CAAA;AAEA7E,MAAE,2EAA2E,YAAA;AAC3E,YAAMX,MAAM2F,YAAY;QACtBxH,MAAM;QACNuH,SAAS;UAAEF,GAAG;QAAE;QAChB9G,IAAI;QACJkH,aAAa;MACf,CAAA;AACA,YAAM5F,MAAM2F,YAAY;QACtBxH,MAAM;QACNuH,SAAS;UAAEF,GAAG;QAAE;QAChB9G,IAAI;QACJkH,aAAa;MACf,CAAA;AACA,YAAM5F,MAAM2F,YAAY;QACtBxH,MAAM;QACNuH,SAAS;UAAEF,GAAG;QAAE;QAChB9G,IAAI;QACJkH,aAAa;MACf,CAAA;AAEA,YAAMR,SAAS,MAAMpF,MAAM6F,mBAAmB,cAAc,EAAA;AAC5D3E,MAAAA,QAAOkE,OAAO9B,IAAI,CAACwC,MAAMA,EAAEJ,OAAO,CAAA,EAAGtE,QAAQ;QAAC;UAAEoE,GAAG;QAAE;QAAG;UAAEA,GAAG;QAAE;OAAE;AACjEtE,MAAAA,QAAOkE,OAAO9B,IAAI,CAACwC,MAAMA,EAAEpH,EAAE,CAAA,EAAG0C,QAAQ;QAAC;QAAM;OAAK;AACpDF,MAAAA,QAAOkE,OAAO,CAAA,GAAIQ,WAAAA,EAAazE,KAAK,GAAA;AAEpCD,MAAAA,QAAO,MAAMlB,MAAM6F,mBAAmB,cAAc,EAAA,CAAA,EAAKzB,aAAa,CAAA;AACtElD,MAAAA,QAAO,MAAMlB,MAAM6F,mBAAmB,eAAe,EAAA,CAAA,EAAKzE,QAAQ;QAChE;UAAE1C,IAAI;UAAMgH,SAAS;YAAEF,GAAG;UAAE;UAAGI,aAAa;QAAG;OAChD;IACH,CAAA;AAEAjF,MAAE,sCAAsC,YAAA;AACtC,YAAMX,MAAM2F,YAAY;QAAExH,MAAM;QAAOuH,SAAS;QAAGhH,IAAI;QAAKkH,aAAa;MAAE,CAAA;AAC3E,YAAM5F,MAAM2F,YAAY;QAAExH,MAAM;QAAOuH,SAAS;QAAGhH,IAAI;QAAKkH,aAAa;MAAE,CAAA;AAC3E,YAAM5F,MAAM2F,YAAY;QAAExH,MAAM;QAAOuH,SAAS;QAAGhH,IAAI;QAAKkH,aAAa;MAAE,CAAA;AAE3E1E,MAAAA,QAAO,MAAMlB,MAAM6F,mBAAmB,OAAO,CAAA,CAAA,EAAIzB,aAAa,CAAA;IAChE,CAAA;AAEAzD,MACE,2GACA,YAAA;AACE,YAAMX,MAAM2F,YAAY;QAAExH,MAAM;QAAOuH,SAAS;UAAElG,IAAI;QAAK;QAAGd,IAAI;QAAMkH,aAAa;MAAE,CAAA;AAEvF1E,MAAAA,QAAO,MAAMlB,MAAM+F,oBAAoB,IAAA,CAAA,EAAO5E,KAAK,IAAA;AACnDD,MAAAA,QAAO,MAAMlB,MAAM6F,mBAAmB,OAAO,EAAA,CAAA,EAAKzE,QAAQ,CAAA,CAAE;AAE5DF,MAAAA,QAAO,MAAMlB,MAAM+F,oBAAoB,IAAA,CAAA,EAAO5E,KAAK,KAAA;AACnDD,MAAAA,QAAO,MAAMlB,MAAM+F,oBAAoB,gBAAA,CAAA,EAAmB5E,KAAK,KAAA;IACjE,CAAA;AAKFR,MAAE,6EAA6E,YAAA;AAC7E,UAAI,CAACX,MAAMgG,YAAa;AACxB,UAAI,CAAC9F,yBAA0B;AAC/B,YAAMF,MAAMe,UAAUvC,IAAAA,CAAAA;AACtB,YAAMyH,SAAS,MAAMjG,MAAMgG,YAAY,OAAOE,OAAAA;AAC5C,cAAMA,GAAGnE,eAAe7C,WAAW;UAAEE,KAAK;UAAGjB,MAAM;UAAWoB,QAAQ;YAAE4G,MAAM;UAAK;QAAE,CAAA,CAAA;AACrF,eAAO;MACT,CAAA;AACAjF,MAAAA,QAAO+E,MAAAA,EAAQ9E,KAAK,IAAA;AACpB,YAAMiF,KAAK,MAAMpG,MAAMoD,cAAc,MAAM,CAAA;AAC3ClC,MAAAA,QAAOkF,IAAIjI,IAAAA,EAAMgD,KAAK,SAAA;AACtBD,MAAAA,QAAOkF,IAAI7G,MAAAA,EAAQ6B,QAAQ;QAAE+E,MAAM;MAAK,CAAA;IAC1C,CAAA;AAIAxF,MACE,mFACA,YAAA;AACE,YAAM0F,SAAS,IAAIC,gBAAe;QAAEtG;MAAM,CAAA;AAC1C,UAAIuG,QAAQ;AACZ,UAAIC,YAAW;AACfH,aAAOI,SAAS,MAAM,KAAK,OAAOlG,QAAAA;AAChC,cAAMmG,IAAI,MAAMnG,IAAIoG,UAAU,KAAK,YAAA;AACjCJ,mBAAS;AACT,iBAAO;QACT,CAAA;AACA,cAAMK,IAAI,MAAMrG,IAAIoG,UAAU,KAAK,YAAA;AACjC,cAAIH,WAAU;AACZA,YAAAA,YAAW;AACX,kBAAM,IAAIxI,MAAM,MAAA;UAClB;AACA,iBAAO0I,IAAI;QACb,CAAA;AACA,eAAOE;MACT,CAAA;AACA,YAAMP,OAAOQ,MAAM,MAAM;QAAEC,GAAG;MAAE,GAAG,MAAA;AACnC5F,MAAAA,SAAQ,MAAMmF,OAAOU,WAAW,MAAA,GAASlI,MAAM,EAAEsC,KAAK,QAAA;AACtD,YAAM6F,UAAU,MAAMX,OAAOY,OAAO,MAAA;AACpC/F,MAAAA,QAAO8F,QAAQnI,MAAM,EAAEsC,KAAK,WAAA;AAC5BD,MAAAA,QAAO8F,QAAQzH,MAAM,EAAE4B,KAAK,EAAA;AAE5BD,MAAAA,QAAOqF,KAAAA,EAAOpF,KAAK,CAAA;IACrB,CAAA;EAEJ,CAAA;AACF;AAvmBgBtB;;;AC7FT,SAASqH,SACdC,OACAC,QAAe,IAAIC,MAAM,kBAAA,GAAmB;AAE5C,SAAOC,UAAU,GAAGH,OAAOC,KAAAA;AAC7B;AALgBF;AAQT,SAASI,UACdC,GACAJ,OACAC,QAAe,IAAIC,MAAM,kBAAA,GAAmB;AAE5C,MAAIG,QAAQ;AACZ,SAAO,YAAA;AACLA,aAAS;AACT,QAAIA,SAASD,EAAG,OAAMH;AACtB,WAAOD;EACT;AACF;AAXgBG;;;ACThB,SAASG,sBAAAA,qBAAoCC,kBAAAA,uBAAsB;AAQnE,IAAMC,iBAAiB;AAOvB,eAAeC,OAAOC,OAA2BC,OAAeC,YAAY,MAAM;AAChF,QAAMC,WAAWC,KAAKC,IAAG,IAAKH;AAC9B,SAAOE,KAAKC,IAAG,IAAKF,UAAU;AAC5B,UAAMG,OAAM,MAAMN,MAAMO,OAAON,KAAAA;AAC/B,QAAIK,QAAOA,KAAIE,WAAW,aAAaF,KAAIE,WAAW,aAAaF,KAAIE,WAAW,YAChF,QAAOF;AACT,UAAM,IAAIG,QAAQ,CAACC,MAAMC,WAAWD,GAAG,EAAA,CAAA;EACzC;AACA,QAAM,IAAIE,MAAM,OAAOX,KAAAA,0BAA+BC,SAAAA,IAAa;AACrE;AATeH;AAmBf,eAAsBc,2BACpBC,WACAC,WAAW,QAAM;AAEjB,MAAI;AAGF,UAAMf,QAAQ,IAAIgB,oBAAAA;AAClB,UAAMC,SAAS,IAAIC,gBAAe;MAAElB;MAAOc;IAAU,CAAA;AACrDG,WAAOE,SACL,WACA,KACA,OAAOC,SAAS,MAAMA,IAAIC,KAA0BvB,gBAAgB;MAAEwB,GAAG;IAAG,CAAA,GAAIC,OAAO;AAEzFN,WAAOE,SAAS,aAAa,KAAK,OAAOC,QAAQA,IAAIC,KAAKvB,gBAAgB;MAAEwB,GAAG;IAAE,CAAA,CAAA;AAGjFR,cAAUU,OAAO1B,gBAAgB,OAAO2B,WAAW;MACjDF,SAAUE,MAAwBH,IAAI;IACxC,EAAA;AACA,UAAML,OAAOS,MAAM,WAAW,CAAC,GAAG,GAAGX,QAAAA,KAAa;AAClD,UAAMY,KAAK,MAAM5B,OAAOC,OAAO,GAAGe,QAAAA,KAAa;AAC/C,QAAIY,GAAGnB,WAAW,eAAemB,GAAGC,WAAW,IAAI;AACjD,YAAM,IAAIhB,MAAM,8BAA8BiB,KAAKC,UAAUH,EAAAA,CAAAA,EAAK;IACpE;AAGAb,cAAUU,OAAO1B,gBAAgB,YAAA;AAC/B,YAAM,IAAIc,MAAM,cAAA;IAClB,CAAA;AACA,UAAMK,OAAOS,MAAM,aAAa,CAAC,GAAG,GAAGX,QAAAA,OAAe;AACtD,UAAMgB,SAAS,MAAMhC,OAAOC,OAAO,GAAGe,QAAAA,OAAe;AACrD,QAAIgB,OAAOvB,WAAW,UAAU;AAC9B,YAAM,IAAII,MAAM,wBAAwBiB,KAAKC,UAAUC,MAAAA,CAAAA,EAAS;IAClE;EACF,UAAA;AACE,UAAMjB,UAAUkB,QAAK;EACvB;AACF;AAtCsBnB;","names":["describe","expect","it","runAdmissionBackendContract","name","makeBackend","describe","now","make","config","backend","register","it","b","concurrency","expect","tryAdmit","waiterId","ok","toBe","release","rateLimit","limit","periodMs","priority","order","fairness","key","requireRun","store","runId","run","getRun","Error","assertRunStatus","status","assertOutput","expected","JSON","stringify","output","recordedSteps","listCheckpoints","map","cp","name","assertStepsRan","names","ran","includes","join","assertStepAttempts","attempts","find","c","DURABLE_CANONICAL_COLUMNS","durable_workflow_runs","id","workflow","workflowVersion","status","input","output","error","wakeAt","lockedBy","lockedUntil","recoveryAttempts","tags","searchAttributes","createdAt","updatedAt","durable_step_checkpoints","runId","seq","name","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt","durable_run_attributes","key","strValue","numValue","durable_signal_waiters","token","durable_buffered_signals","payload","durable_buffered_events","publishedAt","assertDurableColumns","resolve","expected","mismatches","table","props","Object","entries","property","column","actual","push","preserveColumnExpectation","out","fromEntries","keys","map","p","InMemoryStateStore","InMemoryTransport","WorkflowEngine","MutableClock","current","now","set","ms","advance","createTestEngine","store","InMemoryStateStore","transport","InMemoryTransport","clock","engine","WorkflowEngine","tick","resumeDueTimers","run","workflow","input","runId","opts","start","waitForRun","InMemoryStateStore","WorkflowEngine","assertReplayable","register","history","store","InMemoryStateStore","createRun","run","status","lockedBy","undefined","lockedUntil","cp","checkpoints","saveCheckpoint","engine","WorkflowEngine","result","resume","id","error","message","startsWith","err","Error","name","WorkflowEngine","beforeEach","describe","expect","it","StateStoreUnavailableError","Error","isStateStoreUnavailable","message","name","isUnavailable","err","at","Date","run","over","id","workflow","workflowVersion","status","input","orderId","createdAt","updatedAt","checkpoint","runId","seq","kind","stepId","output","ok","attempts","enqueuedAt","startedAt","finishedAt","runStateStoreContract","makeStore","describe","store","cleanup","supportsAsyncTransaction","supportsTagFilter","skipReason","loggedSkip","beforeEach","ctx","undefined","console","warn","t","label","fn","it","createRun","loaded","getRun","expect","toBe","toEqual","toBeNull","recoveryAttempts","updateRun","total","done","dead","priority","toBeUndefined","searchAttributes","tier","saveCheckpoint","putSignalWaiter","token","deleteRun","listCheckpoints","listSignalWaiters","listRuns","attributes","key","op","value","resolves","error","tags","lockedBy","wakeAt","lockedUntil","r","awaitingDecisionTaskId","chargeId","again","getCheckpoint","list","map","c","pct","getLatestCheckpointByName","toBeDefined","latest","call","listCheckpointsByNamePrefix","matches","events","level","listIncompleteRuns","listPendingRuns","listDueTimers","toHaveLength","tryLockRun","releaseRunLock","renewRunLock","sort","statuses","tag","limit","offset","amount","vip","other","res","w","takeSignalWaiter","parallelGroup","listed","find","removeSignalWaiter","bufferSignal","n","takeBufferedSignal","payload","bufferEvent","publishedAt","listBufferedEvents","e","removeBufferedEvent","transaction","result","tx","paid","cp","engine","WorkflowEngine","aRuns","failOnce","register","a","localStep","b","start","x","waitForRun","resumed","resume","failOnce","value","error","Error","failTimes","n","calls","InMemoryStateStore","WorkflowEngine","ECHO_STEP_NAME","settle","store","runId","timeoutMs","deadline","Date","now","run","getRun","status","Promise","r","setTimeout","Error","assertTransportConformance","transport","idPrefix","InMemoryStateStore","engine","WorkflowEngine","register","ctx","step","n","doubled","handle","input","start","ok","output","JSON","stringify","failed","close"]}
1
+ {"version":3,"sources":["../src/admission-backend-conformance.ts","../src/assertions.ts","../src/durable-columns.ts","../src/harness.ts","../src/replay.ts","../src/state-store-conformance.ts","../src/steps.ts","../src/transport-conformance.ts"],"sourcesContent":["import type { AdmissionBackend, QueueConfig } from '@dudousxd/nestjs-durable-core';\nimport { describe, expect, it } from 'vitest';\n\n/**\n * Builds an {@link AdmissionBackend} bound to the given test clock. Implementations that hold their\n * own resources (e.g. a Redis connection) should register the instance for teardown out-of-band.\n */\nexport type AdmissionBackendFactory = (clock: () => number) => AdmissionBackend;\n\n/**\n * The SHARED cross-backend behavioural contract for the flow-control admission gate. Both the\n * in-process `InMemoryAdmissionBackend` and the Redis `RedisAdmissionBackend` run it, so their\n * concurrency / rate-limit / ordering semantics can never silently drift apart — backend-specific\n * concerns (leases, pub/sub, cross-pod globality) live in each adapter's own spec.\n *\n * The engine always passes a stable `waiterId`, so every gated call is order-tracked: ties with no\n * priority/fairness fall back to arrival FIFO (or LIFO when configured). These cases assert exactly\n * that, on ONE backend instance.\n */\nexport function runAdmissionBackendContract(\n name: string,\n makeBackend: AdmissionBackendFactory,\n): void {\n describe(`AdmissionBackend contract: ${name}`, () => {\n let now = 1_000_000;\n const make = (config: QueueConfig) => {\n now = 1_000_000;\n const backend = makeBackend(() => now);\n backend.register(config);\n return backend;\n };\n\n it('caps concurrency: a second call blocks until the first releases', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('q', { waiterId: 'a' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'b' })).ok).toBe(false);\n await b.release('q', 'a');\n expect((await b.tryAdmit('q', { waiterId: 'b' })).ok).toBe(true);\n });\n\n it('enforces a fixed-window rate limit', async () => {\n const b = make({ name: 'q', rateLimit: { limit: 2, periodMs: 1000 } });\n expect((await b.tryAdmit('q', { waiterId: '1' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: '2' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: '3' })).ok).toBe(false);\n now += 1001;\n expect((await b.tryAdmit('q', { waiterId: '4' })).ok).toBe(true);\n });\n\n it('admits the highest-priority waiter first when a slot frees', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'low', priority: 1 })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'high', priority: 9 })).ok).toBe(false);\n await b.release('q', 'holder');\n expect((await b.tryAdmit('q', { waiterId: 'low', priority: 1 })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'high', priority: 9 })).ok).toBe(true);\n });\n\n it('orders plain-concurrency waiters by arrival (FIFO) — no priority/fairness configured', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);\n await b.release('q', 'holder');\n // The earlier arrival wins the freed slot, on every backend.\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(true);\n });\n\n it('admits the most-recent arrival first when order is LIFO', async () => {\n const b = make({ name: 'q', concurrency: 1, order: 'lifo' });\n expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);\n await b.release('q', 'holder');\n expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(true);\n });\n\n it('round-robins a contended slot across fairness keys', async () => {\n const b = make({ name: 'q', concurrency: 1, fairness: 'key' });\n expect((await b.tryAdmit('q', { waiterId: 'a0', key: 'A' })).ok).toBe(true);\n expect((await b.tryAdmit('q', { waiterId: 'a1', key: 'A' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'b0', key: 'B' })).ok).toBe(false);\n await b.release('q', 'a0');\n // B (never served) wins over A (just served), not arrival order.\n expect((await b.tryAdmit('q', { waiterId: 'a1', key: 'A' })).ok).toBe(false);\n expect((await b.tryAdmit('q', { waiterId: 'b0', key: 'B' })).ok).toBe(true);\n });\n\n it('leaves an unregistered queue ungated', async () => {\n const b = make({ name: 'q', concurrency: 1 });\n expect((await b.tryAdmit('other', { waiterId: 'x' })).ok).toBe(true);\n expect((await b.tryAdmit('other', { waiterId: 'y' })).ok).toBe(true);\n });\n });\n}\n","import type { RunStatus, StateStore } from '@dudousxd/nestjs-durable-core';\n\nasync function requireRun(store: StateStore, runId: string) {\n const run = await store.getRun(runId);\n if (!run) throw new Error(`assertion failed: run ${runId} not found`);\n return run;\n}\n\nexport async function assertRunStatus(\n store: StateStore,\n runId: string,\n status: RunStatus,\n): Promise<void> {\n const run = await requireRun(store, runId);\n if (run.status !== status) {\n throw new Error(`expected run ${runId} to be \"${status}\", but it was \"${run.status}\"`);\n }\n}\n\nexport async function assertOutput(\n store: StateStore,\n runId: string,\n expected: unknown,\n): Promise<void> {\n const run = await requireRun(store, runId);\n if (JSON.stringify(run.output) !== JSON.stringify(expected)) {\n throw new Error(\n `expected run ${runId} output ${JSON.stringify(expected)}, got ${JSON.stringify(run.output)}`,\n );\n }\n}\n\n/** The names of the steps that have run, in order. */\nexport async function recordedSteps(store: StateStore, runId: string): Promise<string[]> {\n return (await store.listCheckpoints(runId)).map((cp) => cp.name);\n}\n\n/** Assert every named step ran (in any order). */\nexport async function assertStepsRan(\n store: StateStore,\n runId: string,\n names: string[],\n): Promise<void> {\n const ran = await recordedSteps(store, runId);\n for (const name of names) {\n if (!ran.includes(name)) {\n throw new Error(`expected step \"${name}\" to have run; ran: [${ran.join(', ')}]`);\n }\n }\n}\n\n/** Assert a step ran exactly the given number of attempts (e.g. to verify retries). */\nexport async function assertStepAttempts(\n store: StateStore,\n runId: string,\n name: string,\n attempts: number,\n): Promise<void> {\n const cp = (await store.listCheckpoints(runId)).find((c) => c.name === name);\n if (!cp) throw new Error(`expected step \"${name}\" to have run, but it did not`);\n if (cp.attempts !== attempts) {\n throw new Error(`expected step \"${name}\" to take ${attempts} attempt(s), took ${cp.attempts}`);\n }\n}\n","/**\n * The canonical physical column names for the durable tables, keyed by table → entity property →\n * column. This is the cross-adapter contract: a run written by one store adapter must be readable by\n * another, so EVERY adapter (TypeORM, MikroORM, Prisma, Drizzle) must map these properties to these\n * exact columns. The canonical convention is `snake_case`.\n *\n * Each adapter has a spec that asserts its physical columns against this map (see `assertDurableColumns`).\n * Without it, adapters silently diverge — one defaulting to its ORM's `snake_case` naming strategy,\n * another keeping the verbatim camelCase property name — and a store swap fails against an existing\n * table with \"Unknown column\" only at runtime. The map exists so that divergence is a failing unit\n * test, not a production incident.\n *\n * The camelCase (\"preserve\") naming is simply the property names themselves (the object keys), so no\n * separate map is needed for it.\n *\n * A property belongs here only when EVERY adapter declares it — the assertion walks this map and\n * reports a missing property as a mismatch, so listing a column one adapter doesn't have would fail\n * that adapter for a divergence it isn't guilty of. `WorkflowRun.namespace` is the standing example:\n * only the MikroORM adapter has a `namespace` column (it is the one with the tenant read filter), so\n * it stays out. That absence records a real cross-adapter gap, not a naming one; if the other three\n * ever gain the column, it belongs here on the same day.\n */\nexport const DURABLE_CANONICAL_COLUMNS = {\n durable_workflow_runs: {\n id: 'id',\n workflow: 'workflow',\n workflowVersion: 'workflow_version',\n status: 'status',\n input: 'input',\n output: 'output',\n error: 'error',\n wakeAt: 'wake_at',\n lockedBy: 'locked_by',\n lockedUntil: 'locked_until',\n recoveryAttempts: 'recovery_attempts',\n tags: 'tags',\n searchAttributes: 'search_attributes',\n priority: 'priority',\n // Which library registered the workflow. Single-word, so `snake_case` and `preserve` agree and\n // an adapter can look canonical by accident — which is exactly why it is pinned here rather than\n // left to four per-adapter assertions to keep saying the same thing.\n origin: 'origin',\n createdAt: 'created_at',\n updatedAt: 'updated_at',\n },\n durable_step_checkpoints: {\n runId: 'run_id',\n seq: 'seq',\n name: 'name',\n kind: 'kind',\n stepId: 'step_id',\n status: 'status',\n input: 'input',\n output: 'output',\n error: 'error',\n events: 'events',\n attempts: 'attempts',\n workerGroup: 'worker_group',\n wakeAt: 'wake_at',\n enqueuedAt: 'enqueued_at',\n startedAt: 'started_at',\n finishedAt: 'finished_at',\n },\n durable_run_attributes: {\n runId: 'run_id',\n key: 'key',\n strValue: 'str_value',\n numValue: 'num_value',\n },\n durable_signal_waiters: {\n token: 'token',\n runId: 'run_id',\n seq: 'seq',\n },\n durable_buffered_signals: {\n id: 'id',\n token: 'token',\n payload: 'payload',\n },\n durable_buffered_events: {\n id: 'id',\n name: 'name',\n payload: 'payload',\n publishedAt: 'published_at',\n },\n} as const;\n\nexport type DurableColumnMap = typeof DURABLE_CANONICAL_COLUMNS;\n\n/** A single column-name disagreement found by {@link assertDurableColumns}. */\nexport interface DurableColumnMismatch {\n table: string;\n property: string;\n expected: string;\n actual: string | undefined;\n}\n\n/**\n * Walk every (table, property) in the canonical contract and compare it to what an adapter actually\n * maps, via the supplied `resolve(table, property) => columnName`. Returns the list of mismatches\n * (empty when the adapter is canonical) so a spec can `expect(assertDurableColumns(resolve)).toEqual([])`.\n *\n * Pass `expected = DURABLE_CANONICAL_COLUMNS` (default) for the snake_case contract, or a map of the\n * property names to themselves to assert the camelCase (\"preserve\") naming.\n */\nexport function assertDurableColumns(\n resolve: (table: string, property: string) => string | undefined,\n expected: Record<string, Record<string, string>> = DURABLE_CANONICAL_COLUMNS,\n): DurableColumnMismatch[] {\n const mismatches: DurableColumnMismatch[] = [];\n for (const [table, props] of Object.entries(expected)) {\n for (const [property, column] of Object.entries(props)) {\n const actual = resolve(table, property);\n if (actual !== column) mismatches.push({ table, property, expected: column, actual });\n }\n }\n return mismatches;\n}\n\n/** The \"preserve\" (camelCase) expectation: every property maps to a column of the same name. */\nexport function preserveColumnExpectation(): Record<string, Record<string, string>> {\n const out: Record<string, Record<string, string>> = {};\n for (const [table, props] of Object.entries(DURABLE_CANONICAL_COLUMNS)) {\n out[table] = Object.fromEntries(Object.keys(props).map((p) => [p, p]));\n }\n return out;\n}\n","import {\n InMemoryStateStore,\n InMemoryTransport,\n type RunResult,\n type StartOptions,\n WorkflowEngine,\n type WorkflowRef,\n} from '@dudousxd/nestjs-durable-core';\n\n/** A clock you control, for testing durable sleeps without real time. */\nexport class MutableClock {\n constructor(private current = 1_000) {}\n readonly now = (): number => this.current;\n set(ms: number): void {\n this.current = ms;\n }\n advance(ms: number): void {\n this.current += ms;\n }\n}\n\nexport interface TestEngine {\n engine: WorkflowEngine;\n store: InMemoryStateStore;\n transport: InMemoryTransport;\n clock: MutableClock;\n /** Advance the clock by `ms` and resume any durable sleeps now due. */\n tick(ms: number): Promise<RunResult[]>;\n /**\n * Enqueue a run and wait for it to settle (terminal or suspended). `engine.start` only enqueues\n * now (dispatch model), so use this when a test needs the outcome synchronously.\n */\n run(\n workflow: WorkflowRef,\n input: unknown,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult>;\n}\n\n/**\n * A self-contained engine wired to in-memory store + transport and a controllable clock — run a\n * whole workflow in a unit test, with no Postgres, no Redis, and no real time.\n */\nexport function createTestEngine(): TestEngine {\n const store = new InMemoryStateStore();\n const transport = new InMemoryTransport();\n const clock = new MutableClock();\n const engine = new WorkflowEngine({ store, transport, clock: clock.now });\n return {\n engine,\n store,\n transport,\n clock,\n async tick(ms: number): Promise<RunResult[]> {\n clock.advance(ms);\n return engine.resumeDueTimers(clock.now());\n },\n async run(workflow, input, runId, opts): Promise<RunResult> {\n // `start` is overloaded per ref kind; a `WorkflowRef` union fits neither overload directly, so\n // resolve to the string overload (the engine accepts a class or name at runtime).\n await engine.start(workflow as string, input, runId, opts);\n return engine.waitForRun(runId);\n },\n };\n}\n","import {\n InMemoryStateStore,\n type StepCheckpoint,\n WorkflowEngine,\n type WorkflowRun,\n} from '@dudousxd/nestjs-durable-core';\n\nexport interface RunHistory {\n run: WorkflowRun;\n checkpoints: StepCheckpoint[];\n}\n\n/**\n * Replay a recorded run's history against the CURRENT workflow code and throw if they diverged.\n *\n * Capture a real (ideally in-flight or representative) run from production —\n * `{ run: await store.getRun(id), checkpoints: await store.listCheckpoints(id) }` — commit it as a\n * fixture, and assert here in CI. If a code change renamed/reordered/removed a step at a position the\n * history already recorded, the engine raises a `NonDeterminismError` on replay and this rethrows it,\n * catching the break *before* it reaches an in-flight run on deploy (the moment you'd otherwise\n * silently replay the wrong checkpoint into the wrong step). Register the workflow exactly as the app\n * does:\n *\n * ```ts\n * await assertReplayable((engine) => engine.register('pipeline', '1', pipeline.run), fixture);\n * ```\n */\nexport async function assertReplayable(\n register: (engine: WorkflowEngine) => void,\n history: RunHistory,\n): Promise<void> {\n const store = new InMemoryStateStore();\n // Seed as a suspended run with no lock so resume() replays the body against the recorded\n // checkpoints — no transport is wired, so nothing new is dispatched.\n await store.createRun({\n ...history.run,\n status: 'suspended',\n lockedBy: undefined,\n lockedUntil: undefined,\n });\n for (const cp of history.checkpoints) await store.saveCheckpoint(cp);\n\n const engine = new WorkflowEngine({ store });\n register(engine);\n const result = await engine.resume(history.run.id);\n if (result.status === 'failed' && result.error?.message?.startsWith('non-determinism')) {\n const err = new Error(result.error.message);\n err.name = 'NonDeterminismError';\n throw err;\n }\n}\n","import {\n type StateStore,\n type StepCheckpoint,\n WorkflowEngine,\n type WorkflowRun,\n} from '@dudousxd/nestjs-durable-core';\nimport { beforeEach, describe, expect, it } from 'vitest';\n\n/**\n * A freshly provisioned, empty {@link StateStore} plus a `cleanup` to release its resources (close\n * the connection, drop the schema, etc.). The conformance suite asks for one before each test so\n * every case starts from a clean slate — exactly like the per-store specs that build a `:memory:` DB.\n */\nexport interface StateStoreContext {\n store: StateStore;\n cleanup: () => Promise<void>;\n /**\n * Whether the store's optional `transaction` can run an ASYNC work callback. Defaults to `true`.\n * Set `false` only for a driver that genuinely can't — e.g. Drizzle on the SYNCHRONOUS\n * `better-sqlite3` driver, whose `transaction()` rejects a promise-returning callback (\"Transaction\n * function cannot return a promise\"). The same Drizzle adapter on an async driver (libSQL) works,\n * and the contract still asserts `transaction` for every other store, so this never hides drift.\n */\n supportsAsyncTransaction?: boolean;\n /**\n * Whether the store can filter `listRuns({ tag })`. Defaults to `true`. Set `false` ONLY for\n * Prisma-on-SQLite: the Prisma adapter filters tags with the `array_contains` JSON predicate, which\n * Prisma supports on its real targets (Postgres + MySQL) but NOT on SQLite. SQLite is only the\n * adapter's local TEST database, so the tag case is skipped there; every other store (and Prisma on\n * a real engine) still asserts it, so this doesn't hide drift in the supported configurations.\n */\n supportsTagFilter?: boolean;\n}\n\n/** Builds a fresh, empty store for one test. Called once per `it` (in `beforeEach`). */\nexport type StateStoreFactory = () => Promise<StateStoreContext>;\n\n/**\n * Thrown by a {@link StateStoreFactory} to SKIP the contract for an unavailable backend instead of\n * failing it — e.g. a testcontainers DB spec when Docker isn't running. Every contract case catches\n * it, logs once, and returns (a no-op pass), so `pnpm test:db` is green-with-skips off a dev box\n * without Docker rather than red.\n */\nexport class StateStoreUnavailableError extends Error {\n readonly isStateStoreUnavailable = true;\n constructor(message: string) {\n super(message);\n this.name = 'StateStoreUnavailableError';\n }\n}\n\nfunction isUnavailable(err: unknown): err is StateStoreUnavailableError {\n return !!err && typeof err === 'object' && 'isStateStoreUnavailable' in err;\n}\n\nconst at = new Date('2026-06-11T00:00:00.000Z');\n\nconst run = (over: Partial<WorkflowRun> = {}): WorkflowRun => ({\n id: 'r1',\n workflow: 'checkout',\n workflowVersion: '1',\n status: 'running',\n input: { orderId: 'o1' },\n createdAt: at,\n updatedAt: at,\n ...over,\n});\n\nconst checkpoint = (over: Partial<StepCheckpoint> = {}): StepCheckpoint => ({\n runId: 'r1',\n seq: 0,\n name: 'reserve',\n kind: 'local',\n stepId: 'r1:0',\n status: 'completed',\n output: { ok: true },\n attempts: 1,\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n ...over,\n});\n\n/**\n * The SHARED behavioral contract every `StateStore` must satisfy — in-memory and each ORM adapter\n * alike. Registered as a vitest `describe`; pass a `name` and a {@link StateStoreFactory} that builds\n * a fresh, empty store. The same assertions run against SQLite/in-memory under `pnpm test` and\n * against real Postgres/MySQL (via testcontainers) under `pnpm test:db`, so any drift between an\n * adapter and the canonical (in-memory) semantics — especially the search-attribute side-table\n * pushdown, which is implemented per-store — fails here instead of silently in production.\n *\n * Each adapter's own spec keeps its dialect-specific tests (DDL/longtext/EXISTS-SQL/JSON-tolerance);\n * this suite owns the cross-store behavior so those never drift apart.\n */\nexport function runStateStoreContract(name: string, makeStore: StateStoreFactory): void {\n describe(`StateStore contract: ${name}`, () => {\n let store: StateStore;\n let cleanup: (() => Promise<void>) | undefined;\n let supportsAsyncTransaction = true;\n let supportsTagFilter = true;\n let skipReason: string | undefined;\n let loggedSkip = false;\n\n beforeEach(async () => {\n try {\n const ctx = await makeStore();\n store = ctx.store;\n cleanup = ctx.cleanup;\n supportsAsyncTransaction = ctx.supportsAsyncTransaction ?? true;\n supportsTagFilter = ctx.supportsTagFilter ?? true;\n skipReason = undefined;\n } catch (err) {\n if (isUnavailable(err)) {\n // Backend unavailable (e.g. no Docker for a testcontainers spec): skip — don't fail.\n skipReason = err.message;\n if (!loggedSkip) {\n console.warn(`[state-store-contract] SKIPPING \"${name}\": ${skipReason}`);\n loggedSkip = true;\n }\n return;\n }\n throw err;\n }\n return async () => {\n await cleanup?.();\n };\n });\n\n /** Register a contract case that no-ops (passes) when the backend was reported unavailable. */\n const t = (label: string, fn: () => Promise<void>): void => {\n it(label, async () => {\n if (skipReason) return;\n await fn();\n });\n };\n\n // ---- create / get / update --------------------------------------------------------------\n\n t('creates a run and reads it back with its JSON input', async () => {\n await store.createRun(run());\n const loaded = await store.getRun('r1');\n expect(loaded?.workflow).toBe('checkout');\n expect(loaded?.input).toEqual({ orderId: 'o1' });\n });\n\n t('returns null for a missing run', async () => {\n expect(await store.getRun('nope')).toBeNull();\n });\n\n t('updates a run (status/output) and round-trips recoveryAttempts + dead status', async () => {\n await store.createRun(run({ recoveryAttempts: 3 }));\n await store.updateRun('r1', {\n status: 'completed',\n output: { total: 42 },\n updatedAt: at,\n });\n const done = await store.getRun('r1');\n expect(done?.status).toBe('completed');\n expect(done?.output).toEqual({ total: 42 });\n expect(done?.recoveryAttempts).toBe(3);\n\n await store.updateRun('r1', { status: 'dead', recoveryAttempts: 4 });\n const dead = await store.getRun('r1');\n expect(dead?.status).toBe('dead');\n expect(dead?.recoveryAttempts).toBe(4);\n });\n\n t('round-trips a run dispatch priority', async () => {\n await store.createRun(run({ id: 'withprio', priority: 7 }));\n await store.createRun(run({ id: 'noprio' }));\n expect((await store.getRun('withprio'))?.priority).toBe(7);\n expect((await store.getRun('noprio'))?.priority).toBeUndefined();\n });\n\n t('deleteRun removes the run and all its rows (checkpoints, waiters, attributes)', async () => {\n await store.createRun(run({ searchAttributes: { tier: 'pro' } }));\n await store.saveCheckpoint(checkpoint());\n await store.putSignalWaiter({ token: 'approve-r1', runId: 'r1', seq: 0 });\n\n await store.deleteRun('r1');\n\n // The run and every child row are gone — not merely marked terminal.\n expect(await store.getRun('r1')).toBeNull();\n expect(await store.listCheckpoints('r1')).toEqual([]);\n expect(await store.listSignalWaiters('approve-')).toEqual([]);\n // The normalized attribute side-table no longer matches it.\n expect(\n await store.listRuns({\n attributes: [{ key: 'tier', op: 'eq', value: 'pro' }],\n }),\n ).toEqual([]);\n });\n\n t('deleteRun is a no-op for a missing run', async () => {\n await expect(store.deleteRun('nope')).resolves.toBeUndefined();\n });\n\n t(\n 'updateRun maps every patchable field — clears error and patches tags/lockedBy/input/timers',\n async () => {\n // Guards against per-adapter patch-whitelist drift: a store that maps only a subset of fields\n // (or ignores `undefined` instead of clearing) would silently no-op these and fail here.\n await store.createRun(\n run({ status: 'failed', error: { message: 'boom' }, tags: ['old'], lockedBy: 'owner-1' }),\n );\n await store.updateRun('r1', {\n status: 'completed',\n output: { ok: true },\n error: undefined, // completion CLEARS the prior error\n input: { orderId: 'o2' },\n tags: ['x', 'y'],\n lockedBy: 'owner-2',\n wakeAt: 123_456,\n lockedUntil: 222_222,\n updatedAt: at,\n });\n const r = await store.getRun('r1');\n expect(r?.status).toBe('completed');\n expect(r?.output).toEqual({ ok: true });\n expect(r?.error).toBeUndefined();\n expect(r?.input).toEqual({ orderId: 'o2' });\n expect(r?.tags).toEqual(['x', 'y']);\n expect(r?.lockedBy).toBe('owner-2');\n expect(r?.wakeAt).toBe(123_456);\n expect(r?.lockedUntil).toBe(222_222);\n\n // The multi-instance REMOTE-decision marker must round-trip AND clear: the engine sets it\n // when it suspends on an awaited turn and clears it (`undefined`) when the decision lands. An\n // adapter that drops it on read, or ignores `undefined` instead of writing NULL, would silently\n // break completeRemoteDecision (it reads back the stale/absent marker and discards the decision).\n await store.updateRun('r1', { awaitingDecisionTaskId: 'turn-7' });\n expect((await store.getRun('r1'))?.awaitingDecisionTaskId).toBe('turn-7');\n await store.updateRun('r1', { awaitingDecisionTaskId: undefined });\n expect((await store.getRun('r1'))?.awaitingDecisionTaskId).toBeUndefined();\n },\n );\n\n // ---- checkpoints ------------------------------------------------------------------------\n\n t(\n 'upserts checkpoints, reads them by (runId, seq), and lists them ordered by seq',\n async () => {\n await store.createRun(run());\n await store.saveCheckpoint(checkpoint());\n await store.saveCheckpoint(\n checkpoint({ seq: 1, name: 'charge', output: { chargeId: 'ch_1' } }),\n );\n // Re-save seq 0 with a new output — upsert, not a duplicate row.\n await store.saveCheckpoint(checkpoint({ output: { ok: true, again: true } }));\n\n expect((await store.getCheckpoint('r1', 0))?.output).toEqual({ ok: true, again: true });\n expect((await store.getCheckpoint('r1', 1))?.name).toBe('charge');\n const list = await store.listCheckpoints('r1');\n expect(list.map((c) => c.seq)).toEqual([0, 1]);\n },\n );\n\n t(\n 'getLatestCheckpointByName returns the highest-seq match (and undefined for none)',\n async () => {\n await store.createRun(run());\n await store.saveCheckpoint(\n checkpoint({ seq: 0, name: 'event:progress', output: { pct: 10 } }),\n );\n await store.saveCheckpoint(checkpoint({ seq: 1, name: 'charge', output: { id: 'c1' } }));\n await store.saveCheckpoint(\n checkpoint({ seq: 2, name: 'event:progress', output: { pct: 50 } }),\n );\n await store.saveCheckpoint(\n checkpoint({ seq: 3, name: 'event:progress', output: { pct: 90 } }),\n );\n\n // Optional on the interface (the engine has a fallback), but a conformant store MUST provide\n // it — assert presence, then exercise the fast path.\n const getLatestCheckpointByName = store.getLatestCheckpointByName;\n expect(getLatestCheckpointByName).toBeDefined();\n if (!getLatestCheckpointByName) return;\n\n const latest = await getLatestCheckpointByName.call(store, 'r1', 'event:progress');\n expect(latest?.seq).toBe(3);\n expect(latest?.output).toEqual({ pct: 90 });\n expect(await getLatestCheckpointByName.call(store, 'r1', 'event:missing')).toBeUndefined();\n },\n );\n\n t(\n 'listCheckpointsByNamePrefix returns prefix matches ordered by seq (empty => none)',\n async () => {\n await store.createRun(run());\n await store.saveCheckpoint(checkpoint({ seq: 0, name: 'reserve' }));\n await store.saveCheckpoint(checkpoint({ seq: 1, name: 'spawn:0', output: 'child-a' }));\n await store.saveCheckpoint(checkpoint({ seq: 2, name: 'signal:child:c2' }));\n await store.saveCheckpoint(checkpoint({ seq: 3, name: 'event:progress' }));\n await store.saveCheckpoint(checkpoint({ seq: 4, name: 'spawn:1', output: 'child-b' }));\n\n // Optional on the interface (the engine has a fallback), but a conformant store MUST provide\n // it — assert presence, then exercise the fast path.\n const listCheckpointsByNamePrefix = store.listCheckpointsByNamePrefix;\n expect(listCheckpointsByNamePrefix).toBeDefined();\n if (!listCheckpointsByNamePrefix) return;\n\n const matches = await listCheckpointsByNamePrefix.call(store, 'r1', [\n 'signal:child:',\n 'spawn:',\n ]);\n expect(matches.map((c) => c.name)).toEqual(['spawn:0', 'signal:child:c2', 'spawn:1']);\n expect(await listCheckpointsByNamePrefix.call(store, 'r1', [])).toEqual([]);\n },\n );\n\n t('round-trips checkpoint events and reads back a missing checkpoint as null', async () => {\n await store.createRun(run());\n await store.saveCheckpoint(\n checkpoint({\n events: [{ at: 1, level: 'error', message: 'p-3 failed', name: 'p-3', status: 'failed' }],\n }),\n );\n expect((await store.getCheckpoint('r1', 0))?.events).toEqual([\n { at: 1, level: 'error', message: 'p-3 failed', name: 'p-3', status: 'failed' },\n ]);\n expect(await store.getCheckpoint('r1', 99)).toBeNull();\n });\n\n // ---- recovery / dispatch / timer scans --------------------------------------------------\n\n t('lists incomplete runs, pending runs (FIFO), and due timers', async () => {\n await store.createRun(run({ id: 'running1', status: 'running' }));\n await store.createRun(run({ id: 'suspended1', status: 'suspended', wakeAt: 5_000 }));\n await store.createRun(run({ id: 'done1', status: 'completed' }));\n await store.createRun(\n run({ id: 'pending2', status: 'pending', createdAt: new Date('2026-06-11T00:00:02.000Z') }),\n );\n await store.createRun(\n run({ id: 'pending1', status: 'pending', createdAt: new Date('2026-06-11T00:00:01.000Z') }),\n );\n\n expect((await store.listIncompleteRuns()).map((r) => r.id)).toEqual(['running1']);\n // FIFO by createdAt.\n expect((await store.listPendingRuns(10)).map((r) => r.id)).toEqual(['pending1', 'pending2']);\n expect((await store.listPendingRuns(1)).map((r) => r.id)).toEqual(['pending1']);\n expect((await store.listDueTimers(10_000)).map((r) => r.id)).toEqual(['suspended1']);\n expect(await store.listDueTimers(1_000)).toHaveLength(0);\n });\n\n // ---- lease / lock -----------------------------------------------------------------------\n\n t('tryLockRun is atomic and respects lease expiry', async () => {\n await store.createRun(run({ id: 'r1' }));\n expect(await store.tryLockRun('r1', 'A', 2_000, 1_000)).toBe(true);\n // B can't take it while A's lease is live.\n expect(await store.tryLockRun('r1', 'B', 3_000, 1_500)).toBe(false);\n // Once A's lease (2_000) has passed, B reclaims it.\n expect(await store.tryLockRun('r1', 'B', 4_000, 2_500)).toBe(true);\n // Release lets anyone re-acquire immediately.\n await store.releaseRunLock('r1');\n expect(await store.tryLockRun('r1', 'C', 9_000, 2_600)).toBe(true);\n });\n\n t('renewRunLock only succeeds for the current owner', async () => {\n await store.createRun(run({ id: 'r1' }));\n expect(await store.tryLockRun('r1', 'A', 2_000, 1_000)).toBe(true);\n // The holder heartbeats and keeps the lease.\n expect(await store.renewRunLock('r1', 'A', 5_000)).toBe(true);\n // A different instance can't renew a lease it doesn't hold.\n expect(await store.renewRunLock('r1', 'B', 9_000)).toBe(false);\n // And the renewed lease is honored: B still can't steal it before it expires.\n expect(await store.tryLockRun('r1', 'B', 6_000, 4_000)).toBe(false);\n });\n\n // ---- list filters: status / statuses / tag / origin --------------------------------------\n\n t('filters listRuns by workflow and by status', async () => {\n await store.createRun(run({ id: 'a', workflow: 'checkout', status: 'running' }));\n await store.createRun(run({ id: 'b', workflow: 'refund', status: 'running' }));\n await store.createRun(run({ id: 'c', workflow: 'checkout', status: 'completed' }));\n\n expect((await store.listRuns({ workflow: 'checkout' })).map((r) => r.id).sort()).toEqual([\n 'a',\n 'c',\n ]);\n expect((await store.listRuns({ status: 'running' })).map((r) => r.id).sort()).toEqual([\n 'a',\n 'b',\n ]);\n expect(\n (await store.listRuns({ workflow: 'checkout', status: 'running' })).map((r) => r.id),\n ).toEqual(['a']);\n });\n\n t('filters listRuns by a status set (status IN ...) for singleton admission', async () => {\n await store.createRun(run({ id: 'a', status: 'running' }));\n await store.createRun(run({ id: 'b', status: 'suspended' }));\n await store.createRun(run({ id: 'c', status: 'completed' }));\n await store.createRun(run({ id: 'd', status: 'pending' }));\n\n expect(\n (await store.listRuns({ statuses: ['running', 'suspended'] })).map((r) => r.id).sort(),\n ).toEqual(['a', 'b']);\n // Single + set are ANDed (the narrower set wins).\n expect(\n (await store.listRuns({ status: 'running', statuses: ['running', 'suspended'] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n // Empty set matches nothing.\n expect(await store.listRuns({ statuses: [] })).toHaveLength(0);\n });\n\n t('filters listRuns by an exact tag (no substring match)', async () => {\n if (!supportsTagFilter) return; // Prisma + SQLite: array_contains is unsupported there (see flag doc)\n await store.createRun(run({ id: 'a', tags: ['etl', 'critical'] }));\n await store.createRun(run({ id: 'b', tags: ['etl-foo'] }));\n await store.createRun(run({ id: 'c' })); // no tags\n\n expect((await store.getRun('a'))?.tags).toEqual(['etl', 'critical']);\n expect((await store.listRuns({ tag: 'etl' })).map((r) => r.id)).toEqual(['a']);\n expect((await store.listRuns({ tag: 'etl-foo' })).map((r) => r.id)).toEqual(['b']);\n expect(await store.listRuns({ tag: 'nope' })).toHaveLength(0);\n });\n\n t(\n 'round-trips a run origin and filters listRuns by it, never matching an absent one',\n async () => {\n // `origin` (which library registered the workflow) is derived at registration, never declared,\n // so ABSENCE is a first-class value: `undefined` means UNKNOWN — a row written before the\n // column existed, a `registerRemote`, convention routing, an unresolvable package. It must\n // survive the round trip as `undefined` rather than as any plausible-looking stand-in, which a\n // real registration would then be indistinguishable from.\n await store.createRun(run({ id: 'a', origin: '@dudousxd/nestjs-catalog-pipeline' }));\n await store.createRun(run({ id: 'b', origin: '@dudousxd/nestjs-agent' }));\n await store.createRun(run({ id: 'c' })); // unattributed — unknown origin\n\n expect((await store.getRun('a'))?.origin).toBe('@dudousxd/nestjs-catalog-pipeline');\n expect((await store.getRun('c'))?.origin).toBeUndefined();\n\n // `RunQuery.origin` is plain equality, so the unattributed run matches NO origin value — it is\n // excluded here exactly as `b` is, and is never folded into a bucket to make a facet look\n // complete. A store that widened this to `= x OR IS NULL` would return `c` and fail.\n expect(\n (await store.listRuns({ origin: '@dudousxd/nestjs-catalog-pipeline' })).map((r) => r.id),\n ).toEqual(['a']);\n // Nor does it answer to a name invented for it.\n expect(await store.listRuns({ origin: 'unknown' })).toEqual([]);\n // Which is why \"all origins\" has to stay the default view: with the filter off — and only\n // then — the unattributed run is reachable.\n expect((await store.listRuns({})).map((r) => r.id).sort()).toEqual(['a', 'b', 'c']);\n },\n );\n\n t('orders listRuns newest-first and paginates with limit/offset', async () => {\n await store.createRun(run({ id: 'old', createdAt: new Date('2026-06-11T00:00:00.000Z') }));\n await store.createRun(run({ id: 'mid', createdAt: new Date('2026-06-11T00:00:01.000Z') }));\n await store.createRun(run({ id: 'new', createdAt: new Date('2026-06-11T00:00:02.000Z') }));\n\n expect((await store.listRuns({})).map((r) => r.id)).toEqual(['new', 'mid', 'old']);\n expect((await store.listRuns({ limit: 2 })).map((r) => r.id)).toEqual(['new', 'mid']);\n expect((await store.listRuns({ limit: 2, offset: 1 })).map((r) => r.id)).toEqual([\n 'mid',\n 'old',\n ]);\n });\n\n // ---- search-attribute pushdown (range + equality + the missing-key contract) ------------\n\n t('round-trips searchAttributes and answers equality + range attribute queries', async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { amount: 30, tier: 'free' } }));\n await store.createRun(run({ id: 'b', searchAttributes: { amount: 200, tier: 'pro' } }));\n await store.createRun(run({ id: 'c', searchAttributes: { amount: 500, tier: 'pro' } }));\n\n expect((await store.getRun('b'))?.searchAttributes).toEqual({ amount: 200, tier: 'pro' });\n\n // Range (numeric).\n expect(\n (await store.listRuns({ attributes: [{ key: 'amount', op: 'gte', value: 200 }] }))\n .map((r) => r.id)\n .sort(),\n ).toEqual(['b', 'c']);\n // Two ANDed predicates (string eq + numeric range).\n expect(\n (\n await store.listRuns({\n attributes: [\n { key: 'tier', op: 'eq', value: 'pro' },\n { key: 'amount', op: 'lt', value: 300 },\n ],\n })\n ).map((r) => r.id),\n ).toEqual(['b']);\n // `ne` excludes the matching value AND absent keys (missing-key-never-matches contract).\n expect(\n (await store.listRuns({ attributes: [{ key: 'tier', op: 'ne', value: 'free' }] }))\n .map((r) => r.id)\n .sort(),\n ).toEqual(['b', 'c']);\n });\n\n t('matches a boolean search attribute by eq/ne', async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { vip: true } }));\n await store.createRun(run({ id: 'b', searchAttributes: { vip: false } }));\n await store.createRun(run({ id: 'c', searchAttributes: { other: 1 } })); // no `vip`\n\n expect(\n (await store.listRuns({ attributes: [{ key: 'vip', op: 'eq', value: true }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n // ne=true matches the explicit false but NOT the run missing `vip` (missing-key contract).\n expect(\n (await store.listRuns({ attributes: [{ key: 'vip', op: 'ne', value: true }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['b']);\n });\n\n t('a predicate on an absent key matches nothing (every op)', async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { amount: 100 } }));\n for (const op of ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'] as const) {\n expect(\n await store.listRuns({ attributes: [{ key: 'missing', op, value: 1 }] }),\n ).toHaveLength(0);\n }\n });\n\n t(\n 're-indexes the search-attribute side-table on update (old values stop matching)',\n async () => {\n await store.createRun(run({ id: 'a', searchAttributes: { tier: 'free', amount: 10 } }));\n expect(\n (await store.listRuns({ attributes: [{ key: 'tier', op: 'eq', value: 'free' }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n\n await store.updateRun('a', { searchAttributes: { tier: 'pro' } });\n expect(\n (await store.listRuns({ attributes: [{ key: 'tier', op: 'eq', value: 'pro' }] })).map(\n (r) => r.id,\n ),\n ).toEqual(['a']);\n // Old key/value pairs are gone.\n expect(\n await store.listRuns({ attributes: [{ key: 'tier', op: 'eq', value: 'free' }] }),\n ).toHaveLength(0);\n expect(\n await store.listRuns({ attributes: [{ key: 'amount', op: 'eq', value: 10 }] }),\n ).toHaveLength(0);\n },\n );\n\n t('combines an attribute predicate with a coarse status filter and paginates', async () => {\n await store.createRun(run({ id: 'a', status: 'running', searchAttributes: { amount: 300 } }));\n await store.createRun(\n run({ id: 'b', status: 'completed', searchAttributes: { amount: 400 } }),\n );\n await store.createRun(run({ id: 'c', status: 'running', searchAttributes: { amount: 50 } }));\n\n const res = await store.listRuns({\n status: 'running',\n attributes: [{ key: 'amount', op: 'gte', value: 100 }],\n limit: 10,\n });\n expect(res.map((r) => r.id)).toEqual(['a']);\n });\n\n // ---- signal waiters & buffered signals --------------------------------------------------\n\n t('stores, lists by prefix, and atomically takes a signal waiter', async () => {\n await store.putSignalWaiter({ token: 'approve-1', runId: 'r1', seq: 3 });\n await store.putSignalWaiter({ token: 'approve-2', runId: 'r2', seq: 4 });\n await store.putSignalWaiter({ token: 'other-1', runId: 'r3', seq: 5 });\n\n expect((await store.listSignalWaiters('approve-')).map((w) => w.token).sort()).toEqual([\n 'approve-1',\n 'approve-2',\n ]);\n expect((await store.takeSignalWaiter('approve-1'))?.seq).toBe(3);\n // Taken exactly once.\n expect(await store.takeSignalWaiter('approve-1')).toBeNull();\n });\n\n t(\n 'round-trips a signal waiter parallelGroup (child-fan tag) through put → take → list',\n async () => {\n // A remote `gather_children` fan threads its group onto each child waiter so the resolving\n // `signal:child:` checkpoint carries it; the store must persist it on the waiter row.\n await store.putSignalWaiter({\n token: 'child:r.child.0',\n runId: 'r',\n seq: 0,\n parallelGroup: 'gather:0',\n });\n // A lone (non-fan) child await carries no group.\n await store.putSignalWaiter({ token: 'child:r.child.9', runId: 'r', seq: 9 });\n\n const listed = await store.listSignalWaiters('child:');\n expect(listed.find((w) => w.token === 'child:r.child.0')?.parallelGroup).toBe('gather:0');\n expect(listed.find((w) => w.token === 'child:r.child.9')?.parallelGroup).toBeUndefined();\n\n expect((await store.takeSignalWaiter('child:r.child.0'))?.parallelGroup).toBe('gather:0');\n expect((await store.takeSignalWaiter('child:r.child.9'))?.parallelGroup).toBeUndefined();\n },\n );\n\n t(\n \"removeSignalWaiter deletes only the exact (token, runId, seq) row, never a different run's\",\n async () => {\n // A stale identity for a token that's since been superseded (`token` is the store's primary\n // key — a later `putSignalWaiter` for the same token replaces the row) must be a no-op: it\n // must NOT steal the new owner's row out from under it.\n await store.putSignalWaiter({ token: 'approve-1', runId: 'r1', seq: 3 });\n await store.putSignalWaiter({ token: 'approve-1', runId: 'r2', seq: 7 });\n await store.removeSignalWaiter({ token: 'approve-1', runId: 'r1', seq: 3 });\n expect((await store.listSignalWaiters('approve-')).map((w) => w.runId)).toEqual(['r2']);\n\n // A mismatched runId/seq against the CURRENT row is also a no-op.\n await store.removeSignalWaiter({ token: 'approve-1', runId: 'r2', seq: 999 });\n expect((await store.listSignalWaiters('approve-')).map((w) => w.runId)).toEqual(['r2']);\n\n // The exact match deletes it.\n await store.removeSignalWaiter({ token: 'approve-1', runId: 'r2', seq: 7 });\n expect(await store.listSignalWaiters('approve-')).toEqual([]);\n\n // Removing an absent row entirely is a no-op, not an error.\n await store.removeSignalWaiter({ token: 'never-registered', runId: 'r1', seq: 0 });\n },\n );\n\n t('buffers signals and takes them FIFO per token', async () => {\n await store.bufferSignal('sig', { n: 1 });\n await store.bufferSignal('sig', { n: 2 });\n await store.bufferSignal('other', { n: 9 });\n\n expect(await store.takeBufferedSignal('sig')).toEqual({ payload: { n: 1 } });\n expect(await store.takeBufferedSignal('sig')).toEqual({ payload: { n: 2 } });\n expect(await store.takeBufferedSignal('sig')).toBeNull();\n expect(await store.takeBufferedSignal('other')).toEqual({ payload: { n: 9 } });\n });\n\n t('buffers events per name, oldest-first, and lists them without consuming', async () => {\n await store.bufferEvent({\n name: 'order.paid',\n payload: { n: 1 },\n id: 'e1',\n publishedAt: 100,\n });\n await store.bufferEvent({\n name: 'order.paid',\n payload: { n: 2 },\n id: 'e2',\n publishedAt: 200,\n });\n await store.bufferEvent({\n name: 'other.event',\n payload: { n: 9 },\n id: 'e3',\n publishedAt: 50,\n });\n\n const listed = await store.listBufferedEvents('order.paid', 10);\n expect(listed.map((e) => e.payload)).toEqual([{ n: 1 }, { n: 2 }]); // oldest (publishedAt) first\n expect(listed.map((e) => e.id)).toEqual(['e1', 'e2']);\n expect(listed[0]?.publishedAt).toBe(100);\n // listing does not consume — the same rows are still there.\n expect(await store.listBufferedEvents('order.paid', 10)).toHaveLength(2);\n expect(await store.listBufferedEvents('other.event', 10)).toEqual([\n { id: 'e3', payload: { n: 9 }, publishedAt: 50 },\n ]);\n });\n\n t('listBufferedEvents caps at `limit`', async () => {\n await store.bufferEvent({ name: 'evt', payload: 1, id: 'a', publishedAt: 1 });\n await store.bufferEvent({ name: 'evt', payload: 2, id: 'b', publishedAt: 2 });\n await store.bufferEvent({ name: 'evt', payload: 3, id: 'c', publishedAt: 3 });\n\n expect(await store.listBufferedEvents('evt', 2)).toHaveLength(2);\n });\n\n t(\n 'removeBufferedEvent atomically deletes by id — true iff a row existed, false on a repeat/absent id',\n async () => {\n await store.bufferEvent({ name: 'evt', payload: { ok: true }, id: 'x1', publishedAt: 1 });\n\n expect(await store.removeBufferedEvent('x1')).toBe(true);\n expect(await store.listBufferedEvents('evt', 10)).toEqual([]);\n // Already gone — a second attempt (the concurrent-claim arbiter) reports false, not an error.\n expect(await store.removeBufferedEvent('x1')).toBe(false);\n expect(await store.removeBufferedEvent('never-buffered')).toBe(false);\n },\n );\n\n // ---- transaction (optional) -------------------------------------------------------------\n\n t('transaction commits the checkpoint atomically and returns the work result', async () => {\n if (!store.transaction) return; // store without transactions (rare); skip\n if (!supportsAsyncTransaction) return; // sync driver (Drizzle + better-sqlite3); skip — see flag doc\n await store.createRun(run());\n const result = await store.transaction(async (tx) => {\n await tx.saveCheckpoint(checkpoint({ seq: 7, name: 'tx-step', output: { paid: true } }));\n return 'ok';\n });\n expect(result).toBe('ok');\n const cp = await store.getCheckpoint('r1', 7);\n expect(cp?.name).toBe('tx-step');\n expect(cp?.output).toEqual({ paid: true });\n });\n\n // ---- engine end-to-end durability -------------------------------------------------------\n\n t(\n 'runs the engine end-to-end durably, resuming without re-running completed steps',\n async () => {\n const engine = new WorkflowEngine({ store });\n let aRuns = 0;\n let failOnce = true;\n engine.register('wf', '1', async (ctx) => {\n const a = await ctx.localStep('a', async () => {\n aRuns += 1;\n return 10;\n });\n const b = await ctx.localStep('b', async () => {\n if (failOnce) {\n failOnce = false;\n throw new Error('boom');\n }\n return a + 5;\n });\n return b;\n });\n await engine.start('wf', { x: 1 }, 'run1');\n expect((await engine.waitForRun('run1')).status).toBe('failed');\n const resumed = await engine.resume('run1');\n expect(resumed.status).toBe('completed');\n expect(resumed.output).toBe(15);\n // Step `a` checkpointed `completed` the first turn, so replay returns it instead of re-running.\n expect(aRuns).toBe(1);\n },\n );\n });\n}\n","/** A step body that throws once, then returns `value` — drives a retry, or a crash-then-resume. */\nexport function failOnce<T>(\n value: T,\n error: Error = new Error('injected failure'),\n): () => Promise<T> {\n return failTimes(1, value, error);\n}\n\n/** A step body that throws the first `n` times, then returns `value`. */\nexport function failTimes<T>(\n n: number,\n value: T,\n error: Error = new Error('injected failure'),\n): () => Promise<T> {\n let calls = 0;\n return async () => {\n calls += 1;\n if (calls <= n) throw error;\n return value;\n };\n}\n","import { InMemoryStateStore, type Transport, WorkflowEngine } from '@dudousxd/nestjs-durable-core';\n\n/** A transport that can register worker handlers (every shipped transport does). */\nexport type HandleableTransport = Transport & {\n handle(name: string, fn: (input: unknown) => Promise<unknown>): void;\n close?(): Promise<void>;\n};\n\nconst ECHO_STEP_NAME = 'conformance.echo';\n\n/**\n * A durable `ctx.call` suspends the run; the worker result resumes it asynchronously (on whatever\n * tick/poll the transport delivers on). Poll the store until the run reaches a terminal state —\n * with a generous budget so a poll-based transport (DB/SQS) has time to round-trip.\n */\nasync function settle(store: InMemoryStateStore, runId: string, timeoutMs = 15_000) {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const run = await store.getRun(runId);\n if (run && run.status !== 'pending' && run.status !== 'running' && run.status !== 'suspended')\n return run;\n await new Promise((r) => setTimeout(r, 25));\n }\n throw new Error(`run ${runId} did not settle within ${timeoutMs}ms`);\n}\n\n/**\n * The contract every `Transport` must satisfy: a remote step dispatched through it round-trips to a\n * worker and back (success), and a throwing handler surfaces as a failed run (failure). Point it at\n * a freshly constructed transport (engine-side + worker `group` in one instance) to prove parity —\n * useful when adding a new transport. Throws on any mismatch; closes the transport when done.\n *\n * `idPrefix` keeps run ids unique across invocations against real, shared infra (queues/tables).\n */\nexport async function assertTransportConformance(\n transport: HandleableTransport,\n idPrefix = 'conf',\n): Promise<void> {\n try {\n // One engine/store/transport — a durable remote step routes its result back to this engine,\n // which resumes the run. (Two engines on one transport would fight over the result stream.)\n const store = new InMemoryStateStore();\n const engine = new WorkflowEngine({ store, transport });\n engine.register(\n 'conf-ok',\n '1',\n async (ctx) => (await ctx.step<{ doubled: number }>(ECHO_STEP_NAME, { n: 21 })).doubled,\n );\n engine.register('conf-fail', '1', async (ctx) => ctx.step(ECHO_STEP_NAME, { n: 1 }));\n\n // success: the worker doubles the input\n transport.handle(ECHO_STEP_NAME, async (input) => ({\n doubled: (input as { n: number }).n * 2,\n }));\n await engine.start('conf-ok', {}, `${idPrefix}-ok`);\n const ok = await settle(store, `${idPrefix}-ok`);\n if (ok.status !== 'completed' || ok.output !== 42) {\n throw new Error(`expected completed/42, got ${JSON.stringify(ok)}`);\n }\n\n // failure: a throwing handler surfaces as a failed run (re-register the same step to throw)\n transport.handle(ECHO_STEP_NAME, async () => {\n throw new Error('handler boom');\n });\n await engine.start('conf-fail', {}, `${idPrefix}-fail`);\n const failed = await settle(store, `${idPrefix}-fail`);\n if (failed.status !== 'failed') {\n throw new Error(`expected failed, got ${JSON.stringify(failed)}`);\n }\n } finally {\n await transport.close?.();\n }\n}\n"],"mappings":"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","names":["describe","expect","it","runAdmissionBackendContract","name","makeBackend","describe","now","make","config","backend","register","it","b","concurrency","expect","tryAdmit","waiterId","ok","toBe","release","rateLimit","limit","periodMs","priority","order","fairness","key","requireRun","store","runId","run","getRun","Error","assertRunStatus","status","assertOutput","expected","JSON","stringify","output","recordedSteps","listCheckpoints","map","cp","name","assertStepsRan","names","ran","includes","join","assertStepAttempts","attempts","find","c","DURABLE_CANONICAL_COLUMNS","durable_workflow_runs","id","workflow","workflowVersion","status","input","output","error","wakeAt","lockedBy","lockedUntil","recoveryAttempts","tags","searchAttributes","priority","origin","createdAt","updatedAt","durable_step_checkpoints","runId","seq","name","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt","durable_run_attributes","key","strValue","numValue","durable_signal_waiters","token","durable_buffered_signals","payload","durable_buffered_events","publishedAt","assertDurableColumns","resolve","expected","mismatches","table","props","Object","entries","property","column","actual","push","preserveColumnExpectation","out","fromEntries","keys","map","p","InMemoryStateStore","InMemoryTransport","WorkflowEngine","MutableClock","current","now","set","ms","advance","createTestEngine","store","InMemoryStateStore","transport","InMemoryTransport","clock","engine","WorkflowEngine","tick","resumeDueTimers","run","workflow","input","runId","opts","start","waitForRun","InMemoryStateStore","WorkflowEngine","assertReplayable","register","history","store","InMemoryStateStore","createRun","run","status","lockedBy","undefined","lockedUntil","cp","checkpoints","saveCheckpoint","engine","WorkflowEngine","result","resume","id","error","message","startsWith","err","Error","name","WorkflowEngine","beforeEach","describe","expect","it","StateStoreUnavailableError","Error","isStateStoreUnavailable","message","name","isUnavailable","err","at","Date","run","over","id","workflow","workflowVersion","status","input","orderId","createdAt","updatedAt","checkpoint","runId","seq","kind","stepId","output","ok","attempts","enqueuedAt","startedAt","finishedAt","runStateStoreContract","makeStore","describe","store","cleanup","supportsAsyncTransaction","supportsTagFilter","skipReason","loggedSkip","beforeEach","ctx","undefined","console","warn","t","label","fn","it","createRun","loaded","getRun","expect","toBe","toEqual","toBeNull","recoveryAttempts","updateRun","total","done","dead","priority","toBeUndefined","searchAttributes","tier","saveCheckpoint","putSignalWaiter","token","deleteRun","listCheckpoints","listSignalWaiters","listRuns","attributes","key","op","value","resolves","error","tags","lockedBy","wakeAt","lockedUntil","r","awaitingDecisionTaskId","chargeId","again","getCheckpoint","list","map","c","pct","getLatestCheckpointByName","toBeDefined","latest","call","listCheckpointsByNamePrefix","matches","events","level","listIncompleteRuns","listPendingRuns","listDueTimers","toHaveLength","tryLockRun","releaseRunLock","renewRunLock","sort","statuses","tag","origin","limit","offset","amount","vip","other","res","w","takeSignalWaiter","parallelGroup","listed","find","removeSignalWaiter","bufferSignal","n","takeBufferedSignal","payload","bufferEvent","publishedAt","listBufferedEvents","e","removeBufferedEvent","transaction","result","tx","paid","cp","engine","WorkflowEngine","aRuns","failOnce","register","a","localStep","b","start","x","waitForRun","resumed","resume","failOnce","value","error","Error","failTimes","n","calls","InMemoryStateStore","WorkflowEngine","ECHO_STEP_NAME","settle","store","runId","timeoutMs","deadline","Date","now","run","getRun","status","Promise","r","setTimeout","Error","assertTransportConformance","transport","idPrefix","InMemoryStateStore","engine","WorkflowEngine","register","ctx","step","n","doubled","handle","input","start","ok","output","JSON","stringify","failed","close"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-durable-testing",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Testing utilities for nestjs-durable — a test engine harness, crash/flaky-step injection, and replay assertions",
5
5
  "license": "MIT",
6
6
  "author": "Davide Carvalho",
@@ -28,7 +28,7 @@
28
28
  "typescript": "5.9.3",
29
29
  "vitest": "2.1.9",
30
30
  "tsup": "8.3.5",
31
- "@dudousxd/nestjs-durable-core": "^0.54.0"
31
+ "@dudousxd/nestjs-durable-core": "^0.63.0"
32
32
  },
33
33
  "module": "./dist/index.js",
34
34
  "exports": {