@vibeorm/runtime 2.5.0 → 3.0.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.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -1
  3. package/dist/adapter-kit/adapter-lifecycle.d.ts +79 -0
  4. package/dist/adapter-kit/deferred-control.d.ts +58 -0
  5. package/dist/adapter-kit/index.d.ts +10 -3
  6. package/dist/adapter-kit/index.js +317 -24
  7. package/dist/adapter-kit/index.js.map +10 -7
  8. package/dist/adapter-kit/nested-options.d.ts +16 -2
  9. package/dist/adapter-kit/row-changes.d.ts +15 -1
  10. package/dist/adapter-kit/savepoint-gate.d.ts +17 -3
  11. package/dist/adapter-kit/transaction-budget.d.ts +23 -13
  12. package/dist/adapter-kit/transaction-outcome.d.ts +167 -0
  13. package/dist/adapter.d.ts +103 -11
  14. package/dist/client.d.ts +7 -0
  15. package/dist/codecs.d.ts +35 -0
  16. package/dist/config.d.ts +15 -0
  17. package/dist/extensions.d.ts +10 -0
  18. package/dist/find-page.d.ts +9 -2
  19. package/dist/index.d.ts +8 -4
  20. package/dist/index.js +4088 -1296
  21. package/dist/index.js.map +40 -28
  22. package/dist/keyset-iterator.d.ts +12 -2
  23. package/dist/keyset.d.ts +72 -16
  24. package/dist/lateral-projection.d.ts +31 -1
  25. package/dist/model-meta.d.ts +12 -0
  26. package/dist/nested-fold.d.ts +98 -0
  27. package/dist/nested-update-data.d.ts +11 -0
  28. package/dist/nested-writes.d.ts +38 -1
  29. package/dist/query-builder.d.ts +78 -19
  30. package/dist/read-only.d.ts +5 -0
  31. package/dist/relation-key.d.ts +50 -0
  32. package/dist/relation-loader.d.ts +13 -1
  33. package/dist/relation-plan.d.ts +16 -0
  34. package/dist/strict-args.d.ts +1 -0
  35. package/dist/upsert-fold.d.ts +77 -0
  36. package/dist/write-scope.d.ts +9 -0
  37. package/package.json +7 -5
  38. package/dist/adapter-kit/index.d.ts.map +0 -1
  39. package/dist/adapter-kit/nested-options.d.ts.map +0 -1
  40. package/dist/adapter-kit/row-changes.d.ts.map +0 -1
  41. package/dist/adapter-kit/savepoint-gate.d.ts.map +0 -1
  42. package/dist/adapter-kit/savepoints.d.ts.map +0 -1
  43. package/dist/adapter-kit/session.d.ts.map +0 -1
  44. package/dist/adapter-kit/sqlite-session.d.ts.map +0 -1
  45. package/dist/adapter-kit/transaction-budget.d.ts.map +0 -1
  46. package/dist/adapter.d.ts.map +0 -1
  47. package/dist/advisory-key.d.ts.map +0 -1
  48. package/dist/advisory-lock.d.ts.map +0 -1
  49. package/dist/bulk-upsert.d.ts.map +0 -1
  50. package/dist/client-types.d.ts.map +0 -1
  51. package/dist/client.d.ts.map +0 -1
  52. package/dist/codecs.d.ts.map +0 -1
  53. package/dist/computed.d.ts.map +0 -1
  54. package/dist/database-module.d.ts.map +0 -1
  55. package/dist/db-now.d.ts.map +0 -1
  56. package/dist/diagnostics/index.d.ts.map +0 -1
  57. package/dist/diagnostics/insight.d.ts.map +0 -1
  58. package/dist/diagnostics/plan.d.ts.map +0 -1
  59. package/dist/diagnostics/preview.d.ts.map +0 -1
  60. package/dist/diagnostics/statement-diagnostics.d.ts.map +0 -1
  61. package/dist/diagnostics/types.d.ts.map +0 -1
  62. package/dist/diagnostics/workload.d.ts.map +0 -1
  63. package/dist/extensions.d.ts.map +0 -1
  64. package/dist/find-page.d.ts.map +0 -1
  65. package/dist/index.d.ts.map +0 -1
  66. package/dist/keyset-iterator.d.ts.map +0 -1
  67. package/dist/keyset-projection.d.ts.map +0 -1
  68. package/dist/keyset.d.ts.map +0 -1
  69. package/dist/lateral-projection.d.ts.map +0 -1
  70. package/dist/model-meta.d.ts.map +0 -1
  71. package/dist/module-context.d.ts.map +0 -1
  72. package/dist/nested-writes.d.ts.map +0 -1
  73. package/dist/policy-operation.d.ts.map +0 -1
  74. package/dist/policy.d.ts.map +0 -1
  75. package/dist/query-builder.d.ts.map +0 -1
  76. package/dist/read-only.d.ts.map +0 -1
  77. package/dist/relation-key.d.ts.map +0 -1
  78. package/dist/relation-loader.d.ts.map +0 -1
  79. package/dist/relation-plan.d.ts.map +0 -1
  80. package/dist/render-cache.d.ts.map +0 -1
  81. package/dist/rls-context.d.ts.map +0 -1
  82. package/dist/rls-readiness.d.ts.map +0 -1
  83. package/dist/scoped.d.ts.map +0 -1
  84. package/dist/sql-access.d.ts.map +0 -1
  85. package/dist/sql.d.ts.map +0 -1
  86. package/dist/strict-args.d.ts.map +0 -1
  87. package/dist/telemetry/collector.d.ts.map +0 -1
  88. package/dist/telemetry/config.d.ts.map +0 -1
  89. package/dist/telemetry/fingerprint.d.ts.map +0 -1
  90. package/dist/telemetry/index.d.ts.map +0 -1
  91. package/dist/telemetry/recorder.d.ts.map +0 -1
  92. package/dist/telemetry/statement.d.ts.map +0 -1
  93. package/dist/telemetry/types.d.ts.map +0 -1
  94. package/dist/transaction-row-changes.d.ts.map +0 -1
  95. package/dist/validators.d.ts.map +0 -1
  96. package/dist/views.d.ts.map +0 -1
  97. package/dist/write-scope.d.ts.map +0 -1
@@ -1,16 +1,19 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/adapter-kit/savepoints.ts", "../src/adapter-kit/savepoint-gate.ts", "../src/adapter-kit/nested-options.ts", "../src/adapter-kit/transaction-budget.ts", "../src/adapter-kit/row-changes.ts", "../src/adapter-kit/session.ts", "../src/adapter-kit/sqlite-session.ts"],
3
+ "sources": ["../src/adapter-kit/savepoints.ts", "../src/adapter-kit/savepoint-gate.ts", "../src/adapter-kit/nested-options.ts", "../src/adapter-kit/deferred-control.ts", "../src/adapter-kit/transaction-budget.ts", "../src/adapter-kit/transaction-outcome.ts", "../src/adapter-kit/row-changes.ts", "../src/adapter-kit/session.ts", "../src/adapter-kit/adapter-lifecycle.ts", "../src/adapter-kit/sqlite-session.ts"],
4
4
  "sourcesContent": [
5
5
  "/**\n * Savepoint naming for nested transactions.\n *\n * v1 lesson (LEARNINGS.md): the counter is shared **by reference** across every\n * adapter created for one top-level transaction, so sibling and deeply nested\n * savepoints can never collide on a name.\n */\n\n/** Mutable counter shared by reference across one top-level transaction. */\nexport type SavepointCounter = { n: number };\n\n/** Fresh counter — one per top-level transaction. */\nexport function createSavepointCounter(): SavepointCounter {\n return { n: 0 };\n}\n\n/**\n * Allocate the next savepoint name (`vibeorm_sp_0`, `vibeorm_sp_1`, …) and\n * advance the shared counter. The name is an identifier by construction, so it\n * is safe to interpolate into `SAVEPOINT` / `RELEASE` / `ROLLBACK TO` SQL.\n */\nexport function nextSavepointName(params: { counter: SavepointCounter }): string {\n return `vibeorm_sp_${params.counter.n++}`;\n}\n",
6
- "/**\n * Savepoint lifetimes inside one top-level transaction (F14).\n *\n * A savepoint stack lives on ONE connection: `ROLLBACK TO SAVEPOINT s` undoes\n * everything done after `s`, including work a LATER savepoint already released.\n * Two `transaction()` callbacks opened from the same handle and overlapping in\n * time therefore share that one stack, and the earlier one's rollback silently\n * erases the later one's already committed work. Unique savepoint names do not\n * help — the names never collided, the lifetimes did.\n *\n * The rule enforced here, on every handle of a transaction:\n *\n * > A handle runs when nothing deeper than itself is open. Otherwise it waits\n * > for the innermost open savepoint to settle — unless the call is being made\n * > from INSIDE that savepoint's own callback, which is genuine nesting and\n * > proceeds immediately.\n *\n * The \"from inside\" test is an {@link AsyncLocalStorage} lookup, so the common\n * nesting shapes never wait on themselves: a child opened from its parent's\n * callback, and the parent handle used from within an open child's callback,\n * both proceed. Only genuinely concurrent siblings serialize.\n *\n * Not covered: a callback that awaits a sibling it did not start. That\n * arrangement asks for two savepoints to be open at once, which is exactly what\n * loses work; it now blocks instead. Deliberate — see the notes for this fix.\n *\n * A FAILED `ROLLBACK TO SAVEPOINT` poisons the whole transaction. When the\n * engine cannot undo a savepoint — InnoDB has already rolled the entire\n * transaction back after a deadlock, an implicit-commit DDL cleared every\n * savepoint, the connection dropped — the transaction's outcome is unknown and\n * no handle of it may send another statement: a parent callback that caught\n * the nested error and \"continued\" would otherwise run in autocommit and the\n * final COMMIT would succeed vacuously. Every later turn refuses with the same\n * typed error.\n *\n * An ABORTED transaction (postgres) is tracked here too. PostgreSQL puts the\n * whole transaction into the aborted state after ANY statement error; every\n * later statement fails with 25P02 and `COMMIT` is answered with a `ROLLBACK`\n * command tag and NO error. A callback that catches one statement error and\n * returns normally would therefore \"commit\" nothing while the adapter\n * reported success. The postgres adapters record each driver-reported\n * statement failure at the connection's current savepoint depth\n * ({@link markTransactionAborted}); a `ROLLBACK TO SAVEPOINT` at or above that\n * depth restores the transaction (postgres semantics), and otherwise every\n * later statement, nested savepoint and the commit itself are refused with one\n * typed error carrying the original failure as `cause`. Engines whose\n * transactions survive a statement error (mysql, sqlite) never mark.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { VibeError } from \"@vibeorm/schema\";\nimport { type SavepointCounter, createSavepointCounter, nextSavepointName } from \"./savepoints.ts\";\nimport type { RowChangeCount } from \"../adapter.ts\";\n\n// ─── Types ────────────────────────────────────────────────────────\n\n/**\n * One handle's position in the savepoint stack of a top-level transaction.\n * `state` is shared by reference across every handle of that transaction.\n */\nexport type SavepointScope = {\n /** Physical savepoint depth; 0 is the top-level transaction itself. */\n readonly depth: number;\n /** Shared state: name allocation plus the innermost open savepoint. */\n readonly state: SavepointState;\n};\n\n/** Mutable state shared by every scope of one top-level transaction. */\nexport type SavepointState = {\n /** Savepoint name counter (shared, so names never collide). */\n readonly counter: SavepointCounter;\n /** The innermost savepoint currently open, or `null` when none is. */\n open: OpenSavepoint | null;\n /**\n * Set once a `ROLLBACK TO SAVEPOINT` has failed: the savepoint stack no\n * longer describes the connection, so every later statement and nested\n * savepoint on ANY handle of this transaction is refused with this error.\n */\n poisoned: VibeError | null;\n /**\n * Set once a statement failed on an engine that aborts the whole transaction\n * (postgres): the depth of the innermost savepoint that was open when it\n * failed, and the failure. Cleared by a `ROLLBACK TO SAVEPOINT` at or above\n * that depth; otherwise the commit is refused.\n */\n aborted: AbortedTransaction | null;\n /** Direct effects surviving in this physical transaction, shared by every nested adapter. */\n rowChanges: RowChangeCount;\n};\n\n/** The recorded statement failure that left a postgres transaction aborted. */\nexport type AbortedTransaction = {\n /** Connection depth at the time of the failure; 0 is the top-level transaction. */\n readonly depth: number;\n /** The driver-reported statement failure. */\n readonly cause: unknown;\n};\n\n/** An open savepoint: its handle, its name, and when it finished. */\ntype OpenSavepoint = {\n readonly scope: SavepointScope;\n readonly name: string;\n readonly parent: OpenSavepoint | null;\n readonly settled: Promise<void>;\n readonly settle: () => void;\n rowChangesOnEntry: RowChangeCount;\n};\n\n/**\n * The savepoint whose callback the current async context is running inside.\n * This is the discriminator between genuine nesting (proceed) and an\n * overlapping sibling (wait).\n */\nconst CURRENT = new AsyncLocalStorage<SavepointScope>();\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Fresh scope for one top-level transaction: depth 0, nothing open. */\nexport function createSavepointScope(): SavepointScope {\n return { depth: 0, state: { counter: createSavepointCounter(), open: null, poisoned: null, aborted: null, rowChanges: 0 } };\n}\n\n/**\n * Record that a statement failed on an engine that aborts the transaction\n * (postgres). The failure is recorded at the connection's CURRENT depth — the\n * innermost open savepoint, whichever handle sent the statement — because that\n * is the subtransaction postgres marks as failed. The first failure is kept: a\n * later 25P02 is a consequence, not a cause.\n */\nexport function markTransactionAborted(params: { scope: SavepointScope; cause: unknown }): void {\n const state = params.scope.state;\n if (state.aborted !== null) return;\n state.aborted = { depth: state.open?.scope.depth ?? 0, cause: params.cause };\n}\n\n/**\n * The postgres adapters' statement failure path: a SERVER-reported failure (a\n * mapped `VibeError` carrying `meta.sqlstate`) aborts the transaction; a\n * client-side refusal that never reached the server (a budget, a parameter\n * that could not be serialized) leaves it usable. Rethrows either way.\n */\nexport function abortTransactionOnServerFailure(params: { scope: SavepointScope; error: unknown }): never {\n const { scope, error } = params;\n if (error instanceof VibeError && typeof error.meta.sqlstate === \"string\") {\n markTransactionAborted({ scope, cause: error });\n }\n throw error;\n}\n\n/**\n * Run a top-level transaction callback inside its scope's async context, so\n * nested calls made from it can be told apart from calls made inside an open\n * child.\n */\nexport function runRootScope<T>(params: { scope: SavepointScope; body: () => Promise<T> }): Promise<T> {\n return CURRENT.run(params.scope, async () => {\n assertNotPoisoned({ state: params.scope.state });\n const result = await params.body();\n // Adapters commit after this resolves. Catching a nested failure must not\n // allow a poisoned transaction to report successful completion, and a\n // swallowed statement error must not let an ABORTED transaction commit —\n // postgres would answer that COMMIT with a silent ROLLBACK.\n assertNotPoisoned({ state: params.scope.state });\n assertNotAborted({ state: params.scope.state });\n return result;\n });\n}\n\n/**\n * The wait a statement on `scope` owes before it may run, or `undefined` when\n * it may run now. Returning `undefined` keeps the uncontended path — nothing\n * deeper open — free of an extra promise and microtask.\n */\nexport function scopeTurn(params: { scope: SavepointScope }): Promise<void> | undefined {\n assertNotPoisoned({ state: params.scope.state });\n // Postgres would answer with 25P02; refusing here names the ORIGINAL failure\n // and spends no round trip.\n assertNotAborted({ state: params.scope.state });\n const open = params.scope.state.open;\n if (mayProceed({ scope: params.scope, open })) return undefined;\n return waitForTurn({ scope: params.scope });\n}\n\n/**\n * Open a nested savepoint under `scope`, run `body` inside it and release it —\n * rolling back to it if `body` throws, exactly as before this gate existed.\n *\n * `execute` runs the savepoint control SQL (already wrapped in the adapter's\n * own driver-error mapping). Omit it when the driver manages the savepoint\n * itself (bun:sql's `savepoint()`), in which case only the lifetime is gated.\n */\nexport async function runNestedSavepoint<T>(params: {\n readonly scope: SavepointScope;\n readonly execute?: (statement: string) => Promise<unknown> | unknown;\n readonly body: (scope: SavepointScope) => Promise<T>;\n}): Promise<T> {\n const { scope, execute, body } = params;\n const node = await acquire({ scope });\n try {\n try {\n if (execute !== undefined) await execute(`SAVEPOINT ${node.name}`);\n markSavepointOpened({ scope: node.scope });\n const result = await CURRENT.run(node.scope, () => body(node.scope));\n await drainDescendants({ node });\n assertNotPoisoned({ state: scope.state });\n // A failure swallowed inside this callback left the savepoint aborted:\n // RELEASE would fail with 25P02, so roll it back below and report the\n // abort instead of letting the parent continue on a failed subtransaction.\n assertNotAborted({ state: scope.state });\n if (execute !== undefined) await execute(`RELEASE SAVEPOINT ${node.name}`);\n return result;\n } catch (error) {\n // A descendant the callback started but never awaited must finish before\n // this savepoint may be rolled back — releasing out of order corrupts\n // the stack.\n await drainDescendants({ node });\n assertNotPoisoned({ state: scope.state });\n if (execute !== undefined) {\n try {\n await execute(`ROLLBACK TO SAVEPOINT ${node.name}`);\n } catch (rollbackFailure) {\n // The savepoint could not be undone, so the connection's real state is\n // unknown. Poison the transaction (every handle, every later turn) and\n // surface THAT, with the body failure as the cause — rethrowing the\n // body error alone would let the parent callback continue.\n const poisoned = savepointRollbackFailedError({ cause: error, rollbackFailure });\n scope.state.poisoned = poisoned;\n throw poisoned;\n }\n }\n // The savepoint was undone (by the statement above, or by the driver\n // when it manages savepoints itself — a driver-side rollback failure\n // poisons the scope before reaching here). Postgres restores the\n // transaction to the state at this savepoint, which clears an abort that\n // happened at or below it.\n clearAbortedAtOrBelow({ state: scope.state, depth: node.scope.depth });\n scope.state.rowChanges = node.rowChangesOnEntry;\n throw error;\n }\n } finally {\n closeNode({ node });\n }\n}\n\n/** Snapshot after actual SAVEPOINT establishment, including driver-managed savepoint callbacks. */\nexport function markSavepointOpened(params: { readonly scope: SavepointScope }): void {\n const node = params.scope.state.open;\n if (node !== null && node.scope === params.scope) node.rowChangesOnEntry = params.scope.state.rowChanges;\n}\n\n// ─── Errors ───────────────────────────────────────────────────────\n\n/**\n * The refusal raised when `ROLLBACK TO SAVEPOINT` itself fails, and repeated\n * for every later statement on the poisoned transaction. `VIBE_TRANSACTION`\n * with `meta.reason = \"savepoint-rollback-failed\"` and `meta.outcome =\n * \"unknown\"`; `cause` is the body failure that triggered the rollback. The\n * rollback failure's own code (when it is a `VibeError`) rides along as\n * `meta.rollbackErrorCode` — its message is not copied, because a raw driver\n * failure can carry statement text and this error is meant to be logged.\n */\nexport function savepointRollbackFailedError(params: { cause: unknown; rollbackFailure: unknown }): VibeError {\n const { cause, rollbackFailure } = params;\n const rollbackErrorCode =\n rollbackFailure instanceof VibeError ? rollbackFailure.code : undefined;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"a nested transaction failed and the ROLLBACK TO SAVEPOINT that should have undone it failed too — \" +\n \"the savepoint stack no longer describes this connection, so the commit state of the whole transaction \" +\n \"is UNKNOWN and no further statement is accepted on any of its handles. The top-level transaction is \" +\n \"being rolled back; nothing is retried automatically.\",\n meta: {\n reason: \"savepoint-rollback-failed\",\n outcome: \"unknown\",\n rollbackFailed: true,\n ...(rollbackErrorCode === undefined ? {} : { rollbackErrorCode }),\n },\n cause,\n });\n}\n\n/** Whether `error` is this module's poison refusal (used to pick the cleanup path). */\nexport function isSavepointRollbackFailedError(error: unknown): boolean {\n const reason = (error as { meta?: { reason?: unknown } } | null)?.meta?.reason;\n return reason === \"savepoint-rollback-failed\";\n}\n\n/**\n * The refusal raised for every statement, nested savepoint and the commit of\n * an aborted postgres transaction. `VIBE_TRANSACTION` with `meta.reason =\n * \"aborted\"` and `meta.outcome = \"rolled-back\"` — the outcome is CERTAIN: the\n * server discards an aborted transaction whatever the client sends. `cause`\n * is the statement failure that aborted it, and its `code`/`sqlstate` ride\n * along in `meta` so a log line names the real defect.\n */\nexport function transactionAbortedError(params: { cause?: unknown }): VibeError {\n const cause = params.cause;\n const causeCode = cause instanceof VibeError ? cause.code : undefined;\n const sqlstate = cause instanceof VibeError && typeof cause.meta.sqlstate === \"string\" ? cause.meta.sqlstate : undefined;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"the transaction is aborted: a statement inside it failed and PostgreSQL discards every later statement and the COMMIT itself \" +\n \"(the server answers COMMIT with ROLLBACK and no error). Nothing from this transaction was committed. \" +\n \"Let the failure propagate out of the callback, or run the statement that may fail inside a nested transaction so its savepoint is rolled back.\",\n meta: {\n reason: \"aborted\",\n outcome: \"rolled-back\",\n ...(causeCode === undefined ? {} : { causeCode }),\n ...(sqlstate === undefined ? {} : { sqlstate }),\n },\n ...(cause === undefined ? {} : { cause }),\n });\n}\n\n/** Whether `error` is the aborted-transaction refusal. */\nexport function isTransactionAbortedError(error: unknown): boolean {\n const reason = (error as { meta?: { reason?: unknown } } | null)?.meta?.reason;\n return reason === \"aborted\";\n}\n\n// ─── Internals ────────────────────────────────────────────────────\n\nfunction assertNotPoisoned(params: { state: SavepointState }): void {\n if (params.state.poisoned !== null) throw params.state.poisoned;\n}\n\nfunction assertNotAborted(params: { state: SavepointState }): void {\n if (params.state.aborted !== null) throw transactionAbortedError({ cause: params.state.aborted.cause });\n}\n\n/** `ROLLBACK TO SAVEPOINT` at `depth` undoes everything at or below it. */\nfunction clearAbortedAtOrBelow(params: { state: SavepointState; depth: number }): void {\n const aborted = params.state.aborted;\n if (aborted !== null && aborted.depth >= params.depth) params.state.aborted = null;\n}\n\n/** Whether `scope` may act while `open` is the innermost open savepoint. */\nfunction mayProceed(params: { scope: SavepointScope; open: OpenSavepoint | null }): boolean {\n const { scope, open } = params;\n if (open === null) return true;\n // This handle IS the innermost open savepoint.\n if (open.scope === scope) return true;\n // This handle's own savepoint has already closed (a retained child handle):\n // it can only act at the connection's current depth, and waiting for a\n // shallower savepoint it does not own would never resolve.\n if (open.scope.depth < scope.depth) return true;\n // Genuine nesting: the call is being made from inside the open callback.\n return CURRENT.getStore() === open.scope;\n}\n\nasync function waitForTurn(params: { scope: SavepointScope }): Promise<void> {\n for (;;) {\n assertNotPoisoned({ state: params.scope.state });\n const open = params.scope.state.open;\n if (open === null || mayProceed({ scope: params.scope, open })) return;\n await open.settled;\n }\n}\n\n/**\n * Wait for this handle's turn and take it in the SAME synchronous step — the\n * check and the push must not be separated by an await, or two waiters woken\n * together would both open a savepoint.\n */\nasync function acquire(params: { scope: SavepointScope }): Promise<OpenSavepoint> {\n const { scope } = params;\n for (;;) {\n assertNotPoisoned({ state: scope.state });\n // SAVEPOINT itself fails with 25P02 on an aborted transaction.\n assertNotAborted({ state: scope.state });\n const open = scope.state.open;\n if (mayProceed({ scope, open })) return pushNode({ scope, parent: open });\n // `mayProceed` returns true for a null `open`, so this is never null here.\n await (open as OpenSavepoint).settled;\n }\n}\n\nfunction pushNode(params: { scope: SavepointScope; parent: OpenSavepoint | null }): OpenSavepoint {\n const { scope, parent } = params;\n const state = scope.state;\n let settle: () => void = () => undefined;\n const settled = new Promise<void>((resolve) => {\n settle = () => resolve();\n });\n // Physical depth follows the connection's stack, not the handle that opened\n // it: a savepoint opened from an outer handle inside a child's callback still\n // nests inside that child.\n const node: OpenSavepoint = {\n scope: { depth: (parent === null ? 0 : parent.scope.depth) + 1, state },\n name: nextSavepointName({ counter: state.counter }),\n parent,\n settled,\n settle,\n rowChangesOnEntry: state.rowChanges,\n };\n state.open = node;\n return node;\n}\n\nfunction closeNode(params: { node: OpenSavepoint }): void {\n const { node } = params;\n const state = node.scope.state;\n if (state.open === node) state.open = node.parent;\n node.settle();\n}\n\n/** Wait out savepoints a callback opened below this node and never awaited. */\nasync function drainDescendants(params: { node: OpenSavepoint }): Promise<void> {\n const state = params.node.scope.state;\n for (;;) {\n const open = state.open;\n if (open === null || open === params.node || open.scope.depth <= params.node.scope.depth) return;\n await open.settled;\n }\n}\n",
7
- "/**\n * The nested-transaction option contract — ONE copy, shared by every adapter\n * through `@vibeorm/runtime/adapter-kit` (CORE-B-03). It used to live as six\n * hand-synchronised copies, one per adapter; a fourth option would have had\n * to be refused six times.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type { TransactionOptions } from \"../adapter.ts\";\n\n/**\n * Refuse options on a NESTED `transaction()` call — the same contract on every\n * adapter (see the `DatabaseAdapter.transaction` JSDoc in `adapter.ts`): a\n * nested transaction is a SAVEPOINT, and a savepoint can neither change the\n * isolation level of the transaction it joins, enforce its own timeout, nor\n * carry its own deadline. Silently dropping the option hid exactly that.\n *\n * @throws VibeError `VIBE_VALIDATION` when `isolationLevel`, `timeout` or\n * `deadline` is present (an `undefined` or empty options object is accepted).\n */\nexport function refuseNestedTransactionOptions(params: {\n options?: TransactionOptions;\n provider: string;\n}): void {\n const { options, provider } = params;\n if (options === undefined) return;\n\n const passed: string[] = [];\n if (options.isolationLevel !== undefined) passed.push(\"isolationLevel\");\n if (options.timeout !== undefined) passed.push(\"timeout\");\n if (options.deadline !== undefined) passed.push(\"deadline\");\n if (passed.length === 0) return;\n\n const meta: Record<string, unknown> = { provider, nested: true };\n if (options.isolationLevel !== undefined) meta.isolationLevel = options.isolationLevel;\n if (options.timeout !== undefined) meta.timeout = options.timeout;\n if (options.deadline !== undefined) meta.deadline = options.deadline;\n\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `nested transactions run as savepoints and cannot honor ${passed.join(\" or \")} — a savepoint cannot change the isolation level of the transaction it joins, a nested timeout is not enforceable, and a nested deadline would need its own session setting on a connection it does not own (it inherits the top-level one instead); pass options on the top-level $transaction`,\n meta,\n });\n}\n",
8
- "/**\n * Transaction budgets — the total-deadline clock and the handle-closure gate.\n *\n * ONE copy, shared by every adapter package through the\n * `@vibeorm/runtime/adapter-kit` subpath (like `savepoint-gate.ts`), so a\n * change here reaches all engines at once — a per-adapter copy would drift\n * into a silent per-engine behaviour difference.\n *\n * WHAT A DEADLINE IS, AND IS NOT\n *\n * `TransactionOptions.timeout` is unchanged: a PER-STATEMENT engine-side bound.\n * `TransactionOptions.deadline` is new and different — a TOTAL wall-clock bound\n * on one top-level transaction. Its clock starts immediately before `BEGIN` is\n * sent, so connection acquisition (which has its own budget on the pooled\n * adapters) is deliberately NOT counted.\n *\n * Enforcement is never `Promise.race` over a statement that keeps running:\n *\n * - `\"between-statements\"` (the default, and all six adapters can deliver it):\n * before every statement, every nested `transaction()` and the `COMMIT`, an\n * expired budget refuses. The statement is never sent and the transaction is\n * rolled back. A statement ALREADY IN FLIGHT is not interrupted.\n * - `\"cancel-running-statements\"` (postgres servers only): additionally hands\n * the engine the remaining budget as `statement_timeout`, so the SERVER\n * cancels an over-long statement. An adapter that cannot do this refuses the\n * request outright rather than quietly delivering the weaker level.\n *\n * JavaScript cannot forcibly stop a running callback. A callback that keeps\n * going past the deadline finds its later database calls refused; work it does\n * outside the database (an HTTP call, an SMS) is not stopped and cannot be.\n * There is no automatic retry: a deadline failure is terminal for that\n * transaction, because external side effects may already have happened.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type {\n TransactionDeadlineEnforcement,\n TransactionDeadlineSupport,\n TransactionOptions,\n} from \"../adapter.ts\";\n\n// ─── Types ────────────────────────────────────────────────────────\n\n/** Where a budget check happened, reported as `meta.stage`. */\nexport type BudgetStage = \"statement\" | \"nested\" | \"commit\";\n\n/**\n * What is known about a finished transaction. `\"unknown\"` is a first-class\n * outcome, not a failure to decide: when a rollback itself fails the commit\n * state genuinely cannot be asserted, and claiming \"rolled back\" would be a lie.\n */\nexport type TransactionOutcome = \"committed\" | \"rolled-back\" | \"unknown\";\n\n/** Wall clock, injectable so tests are deterministic instead of sleep-timed. */\nexport type DeadlineClock = () => number;\n\n/** The ambient clock, used whenever no seam is injected. */\nexport const DEFAULT_DEADLINE_CLOCK: DeadlineClock = (): number => Date.now();\n\n/**\n * One top-level transaction's budget. Nested savepoint handles share this\n * object BY REFERENCE — they never get an independent clock, connection or\n * session setting.\n */\nexport type TransactionBudget = {\n /** The enforcement level in force, or `null` when no deadline was requested. */\n readonly enforcement: TransactionDeadlineEnforcement | null;\n /** The requested total budget in milliseconds, or `null` when none was. */\n readonly totalMs: number | null;\n /** Existing per-statement limit, independent of the total deadline. Zero disables it. */\n readonly statementTimeoutMs: number | null;\n /** Milliseconds left (never negative), or `null` when no deadline is set. */\n remainingMs(): number | null;\n /** True only when a deadline is set and has passed. */\n expired(): boolean;\n /** Refuse a closed handle or an expired budget. Called BEFORE anything is sent. */\n assertUsable(params: { stage: BudgetStage }): void;\n /** Record the terminal outcome; the first call wins and later ones are ignored. */\n close(params: { outcome: TransactionOutcome }): void;\n /** The recorded outcome, or `null` while the transaction is still open. */\n readonly outcome: TransactionOutcome | null;\n};\n\n// ─── Validation (before BEGIN, before any write) ──────────────────\n\n/**\n * Check `options.deadline` against what this adapter can honestly deliver.\n * Called BEFORE `BEGIN` — a budget this engine cannot honour must never leave\n * a transaction open behind it.\n *\n * @throws VibeError `VIBE_VALIDATION` when `totalMs` is not a positive integer.\n * @throws VibeError `VIBE_UNSUPPORTED_CAPABILITY` when the requested\n * `enforcement` is stronger than `support` — refused, never silently degraded.\n */\nexport function validateTransactionDeadline(params: {\n options?: TransactionOptions;\n support: TransactionDeadlineSupport;\n provider: string;\n}): void {\n const { options, support, provider } = params;\n const deadline = options?.deadline;\n if (deadline === undefined) return;\n\n if (support === \"unsupported\") {\n throw new VibeError({\n code: \"VIBE_UNSUPPORTED_CAPABILITY\",\n message: `${provider} cannot enforce a transaction deadline — remove the \\`deadline\\` option`,\n meta: { provider, feature: \"transactionDeadline\", supported: support },\n });\n }\n\n if (!Number.isInteger(deadline.totalMs) || deadline.totalMs <= 0) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `transaction deadline \\`totalMs\\` must be a positive integer of milliseconds, received ${String(deadline.totalMs)}`,\n meta: { provider, feature: \"transactionDeadline\", totalMs: deadline.totalMs },\n });\n }\n\n const requested: TransactionDeadlineEnforcement = deadline.enforcement ?? \"between-statements\";\n if (requested === \"cancel-running-statements\" && support !== \"cancel-running-statements\") {\n throw new VibeError({\n code: \"VIBE_UNSUPPORTED_CAPABILITY\",\n message:\n `${provider} cannot cancel a statement that is already running, so the requested ` +\n \"`cancel-running-statements` deadline guarantee is refused rather than silently downgraded — \" +\n 'ask for \"between-statements\" if a budget checked between statements is enough',\n meta: { provider, feature: \"transactionDeadline\", requested, supported: support },\n });\n }\n}\n\n// ─── The budget ───────────────────────────────────────────────────\n\n/**\n * Start the clock for one top-level transaction. Call it immediately before\n * `BEGIN`; {@link validateTransactionDeadline} must already have run.\n */\nexport function startTransactionBudget(params: {\n options?: TransactionOptions;\n provider: string;\n clock?: DeadlineClock;\n}): TransactionBudget {\n const { options, provider } = params;\n const clock = params.clock ?? DEFAULT_DEADLINE_CLOCK;\n const deadline = options?.deadline;\n const totalMs = deadline === undefined ? null : deadline.totalMs;\n const enforcement: TransactionDeadlineEnforcement | null =\n deadline === undefined ? null : (deadline.enforcement ?? \"between-statements\");\n const expiresAt = totalMs === null ? null : clock() + totalMs;\n let outcome: TransactionOutcome | null = null;\n\n const budget: TransactionBudget = {\n enforcement,\n totalMs,\n statementTimeoutMs: options?.timeout ?? null,\n remainingMs(): number | null {\n return expiresAt === null ? null : Math.max(0, expiresAt - clock());\n },\n expired(): boolean {\n return expiresAt !== null && clock() >= expiresAt;\n },\n assertUsable(assertParams: { stage: BudgetStage }): void {\n if (outcome !== null) {\n throw transactionClosedError({ provider, outcome, stage: assertParams.stage });\n }\n if (expiresAt !== null && clock() >= expiresAt) {\n throw transactionDeadlineError({\n provider,\n stage: assertParams.stage,\n totalMs: totalMs as number,\n overdueMs: clock() - expiresAt,\n });\n }\n },\n close(closeParams: { outcome: TransactionOutcome }): void {\n if (outcome === null) outcome = closeParams.outcome;\n },\n get outcome(): TransactionOutcome | null {\n return outcome;\n },\n };\n return budget;\n}\n\n/**\n * The engine-side bound for the NEXT statement, or `null` when the caller did\n * not buy `\"cancel-running-statements\"`. Floored at 1 ms: on postgres `0` means\n * \"no limit\", so a spent budget must never be handed over as a zero.\n */\nexport function engineStatementBudgetMs(params: { budget: TransactionBudget }): number | null {\n const { budget } = params;\n if (budget.enforcement !== \"cancel-running-statements\") return null;\n const remaining = budget.remainingMs();\n if (remaining === null) return null;\n const totalBound = Math.max(1, Math.ceil(remaining));\n return budget.statementTimeoutMs !== null && budget.statementTimeoutMs > 0\n ? Math.min(totalBound, budget.statementTimeoutMs) : totalBound;\n}\n\n// ─── Errors ───────────────────────────────────────────────────────\n\n/**\n * The refusal an expired budget raises. `VIBE_TRANSACTION` with a stable\n * `meta.reason` — no SQL text, no parameter values, no credentials.\n */\nexport function transactionDeadlineError(params: {\n provider: string;\n stage: BudgetStage;\n totalMs: number;\n overdueMs: number;\n}): VibeError {\n const { provider, stage, totalMs, overdueMs } = params;\n const what =\n stage === \"commit\"\n ? \"the transaction was rolled back instead of committed\"\n : \"the statement was never sent and the transaction is being rolled back\";\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n `transaction deadline of ${totalMs} ms expired ${Math.max(0, Math.round(overdueMs))} ms ago — ${what}. ` +\n \"Nothing is retried automatically: work the callback did outside the database may already have happened.\",\n meta: { provider, reason: \"transaction-deadline\", stage, totalMs, overdueMs: Math.max(0, Math.round(overdueMs)) },\n });\n}\n\n/**\n * The refusal an ESCAPED transaction handle raises — a transactional adapter\n * kept past the end of its transaction. Without this it would run on a\n * connection that is back in the pool, outside any transaction.\n */\nexport function transactionClosedError(params: {\n provider: string;\n outcome: TransactionOutcome;\n stage: BudgetStage;\n}): VibeError {\n const { provider, outcome, stage } = params;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n `this transaction has already finished (${outcome}), so its client can no longer be used — ` +\n \"a handle kept past the end of `$transaction` would run outside the transaction, on a connection \" +\n \"that now belongs to someone else\",\n meta: { provider, reason: \"transaction-closed\", outcome, stage },\n });\n}\n\n/**\n * The stable typed outcome for \"the deadline expired and the rollback that was\n * supposed to clean up failed too\". Promising a rollback here would be false;\n * promising a retry would be worse.\n *\n * `cause` is the CAUSAL error (the deadline refusal), so the reason the\n * transaction was being abandoned survives. The rollback failure itself is\n * reported only as `meta.rollbackFailed`: a raw driver failure can carry\n * statement text, and this error is meant to be logged.\n */\nexport function transactionOutcomeUnknownError(params: {\n provider: string;\n totalMs: number;\n cause: unknown;\n}): VibeError {\n const { provider, totalMs, cause } = params;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n `transaction deadline of ${totalMs} ms expired and the rollback that should have cleaned up failed — ` +\n \"the commit state of this transaction is UNKNOWN. It is not retried automatically; inspect the data \" +\n \"before deciding.\",\n meta: {\n provider,\n reason: \"transaction-outcome-unknown\",\n outcome: \"unknown\",\n totalMs,\n rollbackFailed: true,\n },\n cause,\n });\n}\n\n/** Whether `error` is this module's deadline refusal (used to pick the cleanup path). */\nexport function isTransactionDeadlineError(error: unknown): boolean {\n const reason = (error as { meta?: { reason?: unknown } } | null)?.meta?.reason;\n return reason === \"transaction-deadline\";\n}\n",
9
- "import type { RowChangeCount, StatementEffect } from \"../adapter.ts\";\nimport type { SavepointScope } from \"./savepoint-gate.ts\";\n\n/** Only structured intent attests complete direct effects; raw command tags do not. */\nexport function statementRowChanges(params: {\n readonly effect?: StatementEffect;\n readonly count?: unknown;\n readonly command?: string;\n}): RowChangeCount {\n const { effect, count } = params;\n if (effect === \"read\") return 0;\n if (effect !== \"write\") return \"unknown\";\n return typeof count === \"number\" && Number.isSafeInteger(count) && count >= 0 ? count : \"unknown\";\n}\n\n/** Fold one successfully executed direct effect into its physical transaction's surviving tally. */\nexport function observeRowChanges(params: { readonly scope: SavepointScope; readonly count: RowChangeCount }): void {\n const state = params.scope.state;\n if (state.rowChanges === \"unknown\") return;\n const count = params.count;\n if (count === \"unknown\" || !Number.isSafeInteger(count) || count < 0 || !Number.isSafeInteger(state.rowChanges + count)) {\n state.rowChanges = \"unknown\";\n return;\n }\n state.rowChanges += count;\n}\n\n/**\n * Observe one synchronous driver dispatch that forbids reentrant writes on the\n * same connection. Failed writes can retain partial effects, so mark unknown\n * before stepping and restore the snapshot only after successful attestation.\n */\nexport function dispatchSynchronousRowChanges<T>(params: {\n readonly scope?: SavepointScope;\n readonly effect?: StatementEffect;\n readonly run: () => T;\n readonly count: (result: T) => RowChangeCount;\n}): T {\n const { scope } = params;\n if (scope === undefined) return params.run();\n const before = scope.state.rowChanges;\n if (params.effect !== \"read\") scope.state.rowChanges = \"unknown\";\n const result = params.run();\n const count = params.count(result);\n scope.state.rowChanges = before;\n observeRowChanges({ scope, count });\n return result;\n}\n\n/** Tentative surviving effects; poisoned/aborted transactions cannot supply a trusted numeric sample. */\nexport function readRowChanges(params: { readonly scope: SavepointScope }): RowChangeCount {\n const state = params.scope.state;\n return state.poisoned !== null || state.aborted !== null ? \"unknown\" : state.rowChanges;\n}\n",
6
+ "/**\n * Savepoint lifetimes inside one top-level transaction (F14).\n *\n * A savepoint stack lives on ONE connection: `ROLLBACK TO SAVEPOINT s` undoes\n * everything done after `s`, including work a LATER savepoint already released.\n * Two `transaction()` callbacks opened from the same handle and overlapping in\n * time therefore share that one stack, and the earlier one's rollback silently\n * erases the later one's already committed work. Unique savepoint names do not\n * help — the names never collided, the lifetimes did.\n *\n * The rule enforced here, on every handle of a transaction:\n *\n * > A handle runs when nothing deeper than itself is open. Otherwise it waits\n * > for the innermost open savepoint to settle — unless the call is being made\n * > from INSIDE that savepoint's own callback, which is genuine nesting and\n * > proceeds immediately.\n *\n * The \"from inside\" test is an {@link AsyncLocalStorage} lookup, so the common\n * nesting shapes never wait on themselves: a child opened from its parent's\n * callback, and the parent handle used from within an open child's callback,\n * both proceed. Only genuinely concurrent siblings serialize.\n *\n * Not covered: a callback that awaits a sibling it did not start. That\n * arrangement asks for two savepoints to be open at once, which is exactly what\n * loses work; it now blocks instead. Deliberate — see the notes for this fix.\n *\n * A FAILED `ROLLBACK TO SAVEPOINT` poisons the whole transaction. When the\n * engine cannot undo a savepoint — InnoDB has already rolled the entire\n * transaction back after a deadlock, an implicit-commit DDL cleared every\n * savepoint, the connection dropped — the transaction's outcome is unknown and\n * no handle of it may send another statement: a parent callback that caught\n * the nested error and \"continued\" would otherwise run in autocommit and the\n * final COMMIT would succeed vacuously. Every later turn refuses with the same\n * typed error.\n *\n * An ABORTED transaction (postgres) is tracked here too. PostgreSQL puts the\n * whole transaction into the aborted state after ANY statement error; every\n * later statement fails with 25P02 and `COMMIT` is answered with a `ROLLBACK`\n * command tag and NO error. A callback that catches one statement error and\n * returns normally would therefore \"commit\" nothing while the adapter\n * reported success. The postgres adapters record each driver-reported\n * statement failure at the connection's current savepoint depth\n * ({@link markTransactionAborted}); a `ROLLBACK TO SAVEPOINT` at or above that\n * depth restores the transaction (postgres semantics), and otherwise every\n * later statement, nested savepoint and the commit itself are refused with one\n * typed error carrying the original failure as `cause`. Engines whose\n * transactions survive a statement error (mysql, sqlite) never mark.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { VibeError } from \"@vibeorm/schema\";\nimport { type SavepointCounter, createSavepointCounter, nextSavepointName } from \"./savepoints.ts\";\nimport type { RowChangeCount } from \"../adapter.ts\";\n\n// ─── Types ────────────────────────────────────────────────────────\n\n/**\n * One handle's position in the savepoint stack of a top-level transaction.\n * `state` is shared by reference across every handle of that transaction.\n */\nexport type SavepointScope = {\n /** Physical savepoint depth; 0 is the top-level transaction itself. */\n readonly depth: number;\n /** Shared state: name allocation plus the innermost open savepoint. */\n readonly state: SavepointState;\n};\n\n/** Mutable state shared by every scope of one top-level transaction. */\nexport type SavepointState = {\n /** Savepoint name counter (shared, so names never collide). */\n readonly counter: SavepointCounter;\n /** The innermost savepoint currently open, or `null` when none is. */\n open: OpenSavepoint | null;\n /**\n * Set once savepoint rollback or its cleanup release has failed: the stack no\n * longer describes the connection, so every later statement and nested\n * savepoint on ANY handle of this transaction is refused with this error.\n */\n poisoned: VibeError | null;\n /**\n * Set once a statement failed on an engine that aborts the whole transaction\n * (postgres): the depth of the innermost savepoint that was open when it\n * failed, and the failure. Cleared by a `ROLLBACK TO SAVEPOINT` at or above\n * that depth; otherwise the commit is refused.\n */\n aborted: AbortedTransaction | null;\n /** Direct effects surviving in this physical transaction, shared by every nested adapter. */\n rowChanges: RowChangeCount;\n};\n\n/** The recorded statement failure that left a postgres transaction aborted. */\nexport type AbortedTransaction = {\n /** Connection depth at the time of the failure; 0 is the top-level transaction. */\n readonly depth: number;\n /** The driver-reported statement failure. */\n readonly cause: unknown;\n};\n\n/** An open savepoint: its handle, its name, and when it finished. */\ntype OpenSavepoint = {\n readonly scope: SavepointScope;\n readonly name: string;\n readonly parent: OpenSavepoint | null;\n readonly settled: Promise<void>;\n readonly settle: () => void;\n rowChangesOnEntry: RowChangeCount;\n};\n\n/**\n * The savepoint whose callback the current async context is running inside.\n * This is the discriminator between genuine nesting (proceed) and an\n * overlapping sibling (wait).\n */\nconst CURRENT = new AsyncLocalStorage<SavepointScope>();\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Fresh scope for one top-level transaction: depth 0, nothing open. */\nexport function createSavepointScope(): SavepointScope {\n return { depth: 0, state: { counter: createSavepointCounter(), open: null, poisoned: null, aborted: null, rowChanges: 0 } };\n}\n\n/**\n * Record that a statement failed on an engine that aborts the transaction\n * (postgres). The failure is recorded at the connection's CURRENT depth — the\n * innermost open savepoint, whichever handle sent the statement — because that\n * is the subtransaction postgres marks as failed. The first failure is kept: a\n * later 25P02 is a consequence, not a cause.\n */\nexport function markTransactionAborted(params: { scope: SavepointScope; cause: unknown }): void {\n const state = params.scope.state;\n if (state.aborted !== null) return;\n state.aborted = { depth: state.open?.scope.depth ?? 0, cause: params.cause };\n}\n\n/**\n * The postgres adapters' statement failure path: a SERVER-reported failure (a\n * mapped `VibeError` carrying `meta.sqlstate`) aborts the transaction; a\n * client-side refusal that never reached the server (a budget, a parameter\n * that could not be serialized) leaves it usable. Rethrows either way.\n */\nexport function abortTransactionOnServerFailure(params: { scope: SavepointScope; error: unknown }): never {\n const { scope, error } = params;\n if (error instanceof VibeError && typeof error.meta.sqlstate === \"string\") {\n markTransactionAborted({ scope, cause: error });\n }\n throw error;\n}\n\n/**\n * Run a top-level transaction callback inside its scope's async context, so\n * nested calls made from it can be told apart from calls made inside an open\n * child.\n */\nexport function runRootScope<T>(params: { scope: SavepointScope; body: () => Promise<T> }): Promise<T> {\n return CURRENT.run(params.scope, async () => {\n assertNotPoisoned({ state: params.scope.state });\n const result = await params.body();\n // Adapters commit after this resolves. Catching a nested failure must not\n // allow a poisoned transaction to report successful completion, and a\n // swallowed statement error must not let an ABORTED transaction commit —\n // postgres would answer that COMMIT with a silent ROLLBACK.\n assertNotPoisoned({ state: params.scope.state });\n assertNotAborted({ state: params.scope.state });\n return result;\n });\n}\n\n/**\n * The wait a statement on `scope` owes before it may run, or `undefined` when\n * it may run now. Returning `undefined` keeps the uncontended path — nothing\n * deeper open — free of an extra promise and microtask.\n */\nexport function scopeTurn(params: { scope: SavepointScope }): Promise<void> | undefined {\n assertNotPoisoned({ state: params.scope.state });\n // Postgres would answer with 25P02; refusing here names the ORIGINAL failure\n // and spends no round trip.\n assertNotAborted({ state: params.scope.state });\n const open = params.scope.state.open;\n if (mayProceed({ scope: params.scope, open })) return undefined;\n return waitForTurn({ scope: params.scope });\n}\n\n/**\n * Open a nested savepoint under `scope`, run `body` inside it and release it —\n * rolling back to it if `body` throws, exactly as before this gate existed.\n *\n * `execute` runs the savepoint control SQL (already wrapped in the adapter's\n * own driver-error mapping). Omit it when the driver manages the savepoint\n * itself (bun:sql's `savepoint()`), in which case only the lifetime is gated.\n */\nexport async function runNestedSavepoint<T>(params: {\n readonly scope: SavepointScope;\n readonly execute?: (statement: string) => Promise<unknown> | unknown;\n /** Budget-independent rollback and post-rollback release; defaults to execute. */\n readonly cleanup?: (statement: string) => Promise<unknown> | unknown;\n readonly body: (scope: SavepointScope) => Promise<T>;\n}): Promise<T> {\n const { scope, execute, body } = params;\n const node = await acquire({ scope });\n try {\n try {\n if (execute !== undefined) await execute(`SAVEPOINT ${node.name}`);\n markSavepointOpened({ scope: node.scope });\n const result = await CURRENT.run(node.scope, () => body(node.scope));\n await drainDescendants({ node });\n assertNotPoisoned({ state: scope.state });\n // A failure swallowed inside this callback left the savepoint aborted:\n // RELEASE would fail with 25P02, so roll it back below and report the\n // abort instead of letting the parent continue on a failed subtransaction.\n assertNotAborted({ state: scope.state });\n if (execute !== undefined) await execute(`RELEASE SAVEPOINT ${node.name}`);\n return result;\n } catch (error) {\n // A descendant the callback started but never awaited must finish before\n // this savepoint may be rolled back — releasing out of order corrupts\n // the stack.\n await drainDescendants({ node });\n assertNotPoisoned({ state: scope.state });\n if (execute !== undefined) {\n const cleanup = params.cleanup ?? execute;\n let cleanupStage: \"rollback\" | \"release\" = \"rollback\";\n try {\n await cleanup(`ROLLBACK TO SAVEPOINT ${node.name}`);\n cleanupStage = \"release\";\n await cleanup(`RELEASE SAVEPOINT ${node.name}`);\n } catch (rollbackFailure) {\n // An unconfirmed rollback or release leaves the stack uncertain. Keep\n // the callback failure as the cause and refuse every later handle.\n const poisoned = savepointRollbackFailedError({ cause: error, rollbackFailure, cleanupStage });\n scope.state.poisoned = poisoned;\n throw poisoned;\n }\n }\n // The savepoint was undone (by the statement above, or by the driver\n // when it manages savepoints itself — a driver-side rollback failure\n // poisons the scope before reaching here). Postgres restores the\n // transaction to the state at this savepoint, which clears an abort that\n // happened at or below it.\n clearAbortedAtOrBelow({ state: scope.state, depth: node.scope.depth });\n scope.state.rowChanges = node.rowChangesOnEntry;\n throw error;\n }\n } finally {\n closeNode({ node });\n }\n}\n\n/** Snapshot after actual SAVEPOINT establishment, including driver-managed savepoint callbacks. */\nexport function markSavepointOpened(params: { readonly scope: SavepointScope }): void {\n const node = params.scope.state.open;\n if (node !== null && node.scope === params.scope) node.rowChangesOnEntry = params.scope.state.rowChanges;\n}\n\n// ─── Errors ───────────────────────────────────────────────────────\n\n/**\n * The refusal raised when savepoint rollback or its cleanup release fails, repeated\n * for every later statement on the poisoned transaction. `VIBE_TRANSACTION`\n * with `meta.reason = \"savepoint-rollback-failed\"` and `meta.outcome =\n * \"unknown\"`; `cause` is the body failure that triggered the rollback. The\n * rollback failure's own code (when it is a `VibeError`) rides along as\n * `meta.rollbackErrorCode` — its message is not copied, because a raw driver\n * failure can carry statement text and this error is meant to be logged.\n */\nexport function savepointRollbackFailedError(params: {\n cause: unknown;\n rollbackFailure: unknown;\n cleanupStage?: \"rollback\" | \"release\";\n}): VibeError {\n const { cause, rollbackFailure } = params;\n const releaseFailed = params.cleanupStage === \"release\";\n const rollbackErrorCode =\n rollbackFailure instanceof VibeError ? rollbackFailure.code : undefined;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n (releaseFailed\n ? \"a nested transaction failed and RELEASE SAVEPOINT after its confirmed rollback failed too. \"\n : \"a nested transaction failed and ROLLBACK TO SAVEPOINT failed too. \") +\n \"The savepoint stack no longer describes this connection, so the commit state of the whole transaction \" +\n \"is UNKNOWN and no further statement is accepted on any of its handles. The top-level transaction is \" +\n \"being rolled back; nothing is retried automatically.\",\n meta: {\n reason: \"savepoint-rollback-failed\",\n outcome: \"unknown\",\n rollbackFailed: !releaseFailed,\n ...(releaseFailed ? { cleanupStage: \"release\" } : {}),\n ...(rollbackErrorCode === undefined ? {} : { rollbackErrorCode }),\n },\n cause,\n });\n}\n\n/** Whether `error` is this module's poison refusal (used to pick the cleanup path). */\nexport function isSavepointRollbackFailedError(error: unknown): boolean {\n const reason = (error as { meta?: { reason?: unknown } } | null)?.meta?.reason;\n return reason === \"savepoint-rollback-failed\";\n}\n\n/**\n * The refusal raised for every statement, nested savepoint and the commit of\n * an aborted postgres transaction. `VIBE_TRANSACTION` with `meta.reason =\n * \"aborted\"` and `meta.outcome = \"not-committed\"` — the outcome is CERTAIN: the\n * server discards an aborted transaction whatever the client sends. `cause`\n * is the statement failure that aborted it, and its `code`/`sqlstate` ride\n * along in `meta` so a log line names the real defect.\n */\nexport function transactionAbortedError(params: { cause?: unknown }): VibeError {\n const cause = mappedCauseOf({ error: params.cause }) ?? params.cause;\n const causeCode = cause instanceof VibeError ? cause.code : undefined;\n const sqlstate = cause instanceof VibeError && typeof cause.meta.sqlstate === \"string\" ? cause.meta.sqlstate : undefined;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"the transaction is aborted: a statement inside it failed and PostgreSQL discards every later statement and the COMMIT itself \" +\n \"(the server answers COMMIT with ROLLBACK and no error). Nothing from this transaction was committed. \" +\n \"Let the failure propagate out of the callback, or run the statement that may fail inside a nested transaction so its savepoint is rolled back.\",\n meta: {\n reason: \"aborted\",\n outcome: \"not-committed\",\n ...(causeCode === undefined ? {} : { causeCode }),\n ...(sqlstate === undefined ? {} : { sqlstate }),\n },\n ...(cause === undefined ? {} : { cause }),\n });\n}\n\n/**\n * Global symbol key (shared by every bundled copy of this module: the runtime\n * entry and `adapter-kit` are separate bundles) under which a statement\n * failure records the error the RUNTIME turned it into.\n */\nconst MAPPED_CAUSE: symbol = Symbol.for(\"vibeorm.adapter-kit.mapped-cause\");\n\n/**\n * Record that the runtime raised `mapped` in place of the driver failure `raw`\n * (the nested-fold veto: a failing cast the caller sees as today's\n * not-found). If `raw` aborted a postgres transaction, the aborted refusal then\n * names `mapped` as its cause — the error the caller actually saw (EPIC F\n * decision 2). Non-enumerable; the raw error is otherwise unchanged.\n */\nexport function recordMappedCause(params: { raw: VibeError; mapped: VibeError }): void {\n Object.defineProperty(params.raw, MAPPED_CAUSE, { value: params.mapped, enumerable: false, configurable: true, writable: false });\n}\n\nfunction mappedCauseOf(params: { error: unknown }): VibeError | undefined {\n if (!(params.error instanceof Error)) return undefined;\n const mapped = (params.error as unknown as Record<symbol, unknown>)[MAPPED_CAUSE];\n return mapped instanceof VibeError ? mapped : undefined;\n}\n\n/** Whether `error` is the aborted-transaction refusal. */\nexport function isTransactionAbortedError(error: unknown): boolean {\n const reason = (error as { meta?: { reason?: unknown } } | null)?.meta?.reason;\n return reason === \"aborted\";\n}\n\n// ─── Internals ────────────────────────────────────────────────────\n\nfunction assertNotPoisoned(params: { state: SavepointState }): void {\n if (params.state.poisoned !== null) throw params.state.poisoned;\n}\n\nfunction assertNotAborted(params: { state: SavepointState }): void {\n if (params.state.aborted !== null) throw transactionAbortedError({ cause: params.state.aborted.cause });\n}\n\n/** `ROLLBACK TO SAVEPOINT` at `depth` undoes everything at or below it. */\nfunction clearAbortedAtOrBelow(params: { state: SavepointState; depth: number }): void {\n const aborted = params.state.aborted;\n if (aborted !== null && aborted.depth >= params.depth) params.state.aborted = null;\n}\n\n/** Whether `scope` may act while `open` is the innermost open savepoint. */\nfunction mayProceed(params: { scope: SavepointScope; open: OpenSavepoint | null }): boolean {\n const { scope, open } = params;\n if (open === null) return true;\n // This handle IS the innermost open savepoint.\n if (open.scope === scope) return true;\n // This handle's own savepoint has already closed (a retained child handle):\n // it can only act at the connection's current depth, and waiting for a\n // shallower savepoint it does not own would never resolve.\n if (open.scope.depth < scope.depth) return true;\n // Genuine nesting: the call is being made from inside the open callback.\n return CURRENT.getStore() === open.scope;\n}\n\nasync function waitForTurn(params: { scope: SavepointScope }): Promise<void> {\n for (;;) {\n assertNotPoisoned({ state: params.scope.state });\n const open = params.scope.state.open;\n if (open === null || mayProceed({ scope: params.scope, open })) return;\n await open.settled;\n }\n}\n\n/** One blocked acquisition. Queue links move with ownership instead of waking every sibling. */\ntype AdmissionWaiter = {\n readonly scope: SavepointScope;\n readonly resolve: (node: OpenSavepoint) => void;\n readonly reject: (error: VibeError) => void;\n next: AdmissionWaiter | null;\n};\n\ntype AdmissionQueue = { head: AdmissionWaiter; tail: AdmissionWaiter };\n\n// Kept outside the exported scope/state shape. Empty/uncontended scopes have no queue.\nconst ADMISSIONS = new WeakMap<OpenSavepoint, AdmissionQueue>();\n\n/**\n * Reserve immediately when eligible. Otherwise attach to the highest blocking\n * ancestor: closing a deeper descendant cannot make this request eligible.\n */\nasync function acquire(params: { scope: SavepointScope }): Promise<OpenSavepoint> {\n const { scope } = params;\n assertNotPoisoned({ state: scope.state });\n assertNotAborted({ state: scope.state });\n const open = scope.state.open;\n if (mayProceed({ scope, open })) return pushNode({ scope, parent: open });\n let blocker = open as OpenSavepoint;\n while (blocker.parent !== null && !mayProceed({ scope, open: blocker.parent })) {\n blocker = blocker.parent;\n }\n return new Promise<OpenSavepoint>((resolve, reject) => {\n const waiter: AdmissionWaiter = { scope, resolve, reject, next: null };\n const queue = ADMISSIONS.get(blocker);\n if (queue === undefined) ADMISSIONS.set(blocker, { head: waiter, tail: waiter });\n else {\n queue.tail.next = waiter;\n queue.tail = waiter;\n }\n });\n}\n\n/** Move the blocked tail to the successor before resolving that successor's turn. */\nfunction handOffAdmissions(params: { node: OpenSavepoint }): void {\n const queue = ADMISSIONS.get(params.node);\n if (queue === undefined) return;\n ADMISSIONS.delete(params.node);\n const state = params.node.scope.state;\n const refusal = state.poisoned ?? (state.aborted === null ? null : transactionAbortedError({ cause: state.aborted.cause }));\n if (refusal !== null) {\n let waiter: AdmissionWaiter | null = queue.head;\n while (waiter !== null) {\n waiter.reject(refusal);\n waiter = waiter.next;\n }\n return;\n }\n const first = queue.head;\n const successor = pushNode({ scope: first.scope, parent: state.open });\n if (first.next !== null) ADMISSIONS.set(successor, { head: first.next, tail: queue.tail });\n first.next = null;\n first.resolve(successor);\n}\n\nfunction pushNode(params: { scope: SavepointScope; parent: OpenSavepoint | null }): OpenSavepoint {\n const { scope, parent } = params;\n const state = scope.state;\n let settle: () => void = () => undefined;\n const settled = new Promise<void>((resolve) => {\n settle = () => resolve();\n });\n // Physical depth follows the connection's stack, not the handle that opened\n // it: a savepoint opened from an outer handle inside a child's callback still\n // nests inside that child.\n const node: OpenSavepoint = {\n scope: { depth: (parent === null ? 0 : parent.scope.depth) + 1, state },\n name: nextSavepointName({ counter: state.counter }),\n parent,\n settled,\n settle,\n rowChangesOnEntry: state.rowChanges,\n };\n state.open = node;\n return node;\n}\n\nfunction closeNode(params: { node: OpenSavepoint }): void {\n const { node } = params;\n const state = node.scope.state;\n if (state.open === node) state.open = node.parent;\n node.settle();\n handOffAdmissions({ node });\n}\n\n/** Wait out savepoints a callback opened below this node and never awaited. */\nasync function drainDescendants(params: { node: OpenSavepoint }): Promise<void> {\n const state = params.node.scope.state;\n for (;;) {\n const open = state.open;\n if (open === null || open === params.node || open.scope.depth <= params.node.scope.depth) return;\n await open.settled;\n }\n}\n",
7
+ "/**\n * The nested-transaction option contract — ONE copy, shared by every adapter\n * through `@vibeorm/runtime/adapter-kit` (CORE-B-03). It used to live as six\n * hand-synchronised copies, one per adapter; a fourth option would have had\n * to be refused six times.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type { TransactionOptions } from \"../adapter.ts\";\n\n/**\n * Refuse options on a NESTED `transaction()` call — the same contract on every\n * adapter (see the `DatabaseAdapter.transaction` JSDoc in `adapter.ts`): a\n * nested transaction is a SAVEPOINT, and a savepoint can neither change the\n * isolation level of the transaction it joins, enforce its own timeout, nor\n * carry its own deadline. Silently dropping the option hid exactly that.\n *\n * @throws VibeError `VIBE_VALIDATION` when `isolationLevel`, `timeout`,\n * `deadline` or `accessMode` is present (an `undefined` or empty options\n * object is accepted).\n */\nexport function refuseNestedTransactionOptions(params: {\n options?: TransactionOptions;\n provider: string;\n}): void {\n const { options, provider } = params;\n if (options === undefined) return;\n\n const passed: string[] = [];\n if (options.isolationLevel !== undefined) passed.push(\"isolationLevel\");\n if (options.timeout !== undefined) passed.push(\"timeout\");\n if (options.deadline !== undefined) passed.push(\"deadline\");\n if (options.accessMode !== undefined) passed.push(\"accessMode\");\n if (passed.length === 0) return;\n\n const meta: Record<string, unknown> = { provider, nested: true };\n if (options.isolationLevel !== undefined) meta.isolationLevel = options.isolationLevel;\n if (options.timeout !== undefined) meta.timeout = options.timeout;\n if (options.deadline !== undefined) meta.deadline = options.deadline;\n if (options.accessMode !== undefined) meta.accessMode = options.accessMode;\n\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `nested transactions run as savepoints and cannot honor ${passed.join(\" or \")} — a savepoint cannot change the isolation level of the transaction it joins, a nested timeout is not enforceable, and a nested deadline would need its own session setting on a connection it does not own (it inherits the top-level one instead); pass options on the top-level $transaction`,\n meta,\n });\n}\n\n/**\n * Whether a TOP-LEVEL transaction asked for `accessMode: \"readOnly\"`. ONE\n * copy of the value check, shared by every adapter that honours the option:\n * an untyped caller's other value is refused instead of silently opening a\n * read/write transaction.\n *\n * @throws VibeError `VIBE_VALIDATION` when `accessMode` is present and is not\n * `\"readOnly\"`.\n */\nexport function readOnlyRequested(params: { options?: TransactionOptions; provider: string }): boolean {\n const accessMode: unknown = params.options?.accessMode;\n if (accessMode === undefined) return false;\n if (accessMode === \"readOnly\") return true;\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `transaction accessMode must be \"readOnly\" or omitted, received ${JSON.stringify(accessMode) ?? String(accessMode)}`,\n meta: { provider: params.provider, accessMode },\n });\n}\n",
8
+ "/**\n * Deferred transaction control (round-trip EPIC 6, pipelining).\n *\n * The opening of a transaction (`BEGIN …`, the `timeout` option's `SET LOCAL`)\n * and every `SAVEPOINT` need no answer before the next statement may be sent:\n * nothing in JavaScript reads their replies except error handling. An adapter\n * that can put several statements on the wire at once (adapter-pg's one-Sync\n * batch, adapter-bun's pipelined extended queries) therefore keeps them here\n * and sends them AHEAD OF the next statement, in the same burst.\n *\n * Bookkeeping only — this module sends nothing and knows no driver:\n * - {@link DeferredControl.take} hands the pending texts to the statement that\n * is about to be sent; that statement carries them.\n * - A transaction whose callback sends nothing never takes the opening, so the\n * adapter sends neither `BEGIN` nor `COMMIT`/`ROLLBACK`\n * ({@link DeferredControl.opened}).\n * - A nested transaction whose body sends nothing never takes its `SAVEPOINT`,\n * so its `RELEASE SAVEPOINT` / `ROLLBACK TO SAVEPOINT` are elided as well\n * ({@link DeferredControl.routeSavepoint}). The savepoint gate's admission,\n * sibling order and abort tracking are untouched: only WHEN the text leaves\n * the client moves.\n *\n * ONE copy, shared by the postgres server adapters (constitution: adapter-kit).\n */\n\n// ─── Types ────────────────────────────────────────────────────────\n\n/** What the adapter does with one savepoint control text from the gate. */\nexport type SavepointControlRoute =\n /** `SAVEPOINT x` queued: it rides with the next statement. */\n | \"deferred\"\n /** The matching `SAVEPOINT` never left the client: send nothing. */\n | \"elided\"\n /** Send it now, as today. */\n | \"send\";\n\n/** Pending control texts of ONE top-level transaction (one connection). */\nexport type DeferredControl = {\n /** True once the opening texts were handed out: the server has (or failed to open) the transaction. */\n readonly opened: () => boolean;\n /** Whether a control text waits to ride with the next statement. */\n readonly hasPending: () => boolean;\n /** Hand out every pending text in send order and empty the queue. */\n readonly take: () => readonly string[];\n /**\n * Route a savepoint control text produced by `runNestedSavepoint`\n * (`SAVEPOINT x`, `RELEASE SAVEPOINT x`, `ROLLBACK TO SAVEPOINT x`).\n * Any other text routes to `\"send\"`.\n */\n readonly routeSavepoint: (params: { readonly text: string }) => SavepointControlRoute;\n};\n\n// ─── Implementation ───────────────────────────────────────────────\n\nconst SAVEPOINT_TEXT = /^SAVEPOINT (\\S+)$/;\nconst RELEASE_TEXT = /^RELEASE SAVEPOINT (\\S+)$/;\nconst ROLLBACK_TO_TEXT = /^ROLLBACK TO SAVEPOINT (\\S+)$/;\n\n/**\n * Start the bookkeeping for one top-level transaction. `opening` holds the\n * texts that open it, in order (for example `[\"BEGIN\", \"SET LOCAL\n * statement_timeout = 5000\"]`); they stay pending until the first statement.\n */\nexport function createDeferredControl(params: { readonly opening: readonly string[] }): DeferredControl {\n let pending: string[] = [...params.opening];\n let opened = params.opening.length === 0;\n /** Savepoints rolled back before they were sent: their cleanup RELEASE is elided too. */\n const elided = new Set<string>();\n\n const dropFrom = (name: string): boolean => {\n const index = pending.indexOf(`SAVEPOINT ${name}`);\n if (index === -1) return false;\n // A deeper savepoint deferred after this one is closed before it (gate\n // order); cutting from the index keeps the queue honest either way.\n pending = pending.slice(0, index);\n return true;\n };\n\n return {\n opened: () => opened,\n hasPending: () => pending.length > 0,\n take: () => {\n const taken = pending;\n pending = [];\n if (taken.length > 0) opened = true;\n return taken;\n },\n routeSavepoint: ({ text }) => {\n const savepoint = SAVEPOINT_TEXT.exec(text);\n if (savepoint !== null) {\n pending.push(text);\n return \"deferred\";\n }\n const release = RELEASE_TEXT.exec(text);\n if (release !== null) {\n const name = release[1] as string;\n if (elided.delete(name)) return \"elided\";\n return dropFrom(name) ? \"elided\" : \"send\";\n }\n const rollbackTo = ROLLBACK_TO_TEXT.exec(text);\n if (rollbackTo !== null) {\n const name = rollbackTo[1] as string;\n if (!dropFrom(name)) return \"send\";\n elided.add(name);\n return \"elided\";\n }\n return \"send\";\n },\n };\n}\n",
9
+ "/**\n * Transaction budgets — the total-deadline clock and the handle-closure gate.\n *\n * ONE copy, shared by every adapter package through the\n * `@vibeorm/runtime/adapter-kit` subpath (like `savepoint-gate.ts`), so a\n * change here reaches all engines at once — a per-adapter copy would drift\n * into a silent per-engine behaviour difference.\n *\n * WHAT A DEADLINE IS, AND IS NOT\n *\n * `TransactionOptions.timeout` is unchanged: a PER-STATEMENT engine-side bound.\n * `TransactionOptions.deadline` is new and different — a TOTAL wall-clock bound\n * on one top-level transaction. Its clock starts immediately before `BEGIN` is\n * sent, so connection acquisition (which has its own budget on the pooled\n * adapters) is deliberately NOT counted.\n *\n * Enforcement is never `Promise.race` over a statement that keeps running:\n *\n * - `\"between-statements\"` (the default, and all six adapters can deliver it):\n * before every statement, every nested `transaction()` and the `COMMIT`, an\n * expired budget refuses. The statement is never sent and the transaction is\n * rolled back. A statement ALREADY IN FLIGHT is not interrupted.\n * - `\"cancel-running-statements\"` (postgres servers only): additionally hands\n * the engine the remaining budget as `statement_timeout`, so the SERVER\n * cancels an over-long statement. An adapter that cannot do this refuses the\n * request outright rather than quietly delivering the weaker level.\n *\n * JavaScript cannot forcibly stop a running callback. A callback that keeps\n * going past the deadline finds its later database calls refused; work it does\n * outside the database (an HTTP call, an SMS) is not stopped and cannot be.\n * There is no automatic retry: a deadline failure is terminal for that\n * transaction, because external side effects may already have happened.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type {\n TransactionDeadlineEnforcement,\n TransactionDeadlineSupport,\n TransactionOptions,\n} from \"../adapter.ts\";\n\n// ─── Types ────────────────────────────────────────────────────────\n\n/** Where a budget check happened, reported as `meta.stage`. */\nexport type BudgetStage = \"statement\" | \"nested\" | \"commit\";\n\n/**\n * The COMMIT outcome of a finished transaction — one meaning only (EPIC T).\n * `\"not-committed\"`: COMMIT was never sent, or the engine answered it with an\n * error. `\"unknown\"` is a first-class outcome, not a failure to decide: a sent\n * COMMIT got no answer (or the savepoint stack was lost first), so nothing on\n * the client can say whether the write is durable. What happened to the\n * cleanup ROLLBACK and the connection is reported apart from it — see\n * `TransactionOutcomeReport` (./transaction-outcome.ts).\n */\nexport type TransactionOutcome = \"committed\" | \"not-committed\" | \"unknown\";\n\n/** Wall clock, injectable so tests are deterministic instead of sleep-timed. */\nexport type DeadlineClock = () => number;\n\n/** The ambient clock, used whenever no seam is injected. */\nexport const DEFAULT_DEADLINE_CLOCK: DeadlineClock = (): number => Date.now();\n\n/**\n * One top-level transaction's budget. Nested savepoint handles share this\n * object BY REFERENCE — they never get an independent clock, connection or\n * session setting.\n */\nexport type TransactionBudget = {\n /** The enforcement level in force, or `null` when no deadline was requested. */\n readonly enforcement: TransactionDeadlineEnforcement | null;\n /** The requested total budget in milliseconds, or `null` when none was. */\n readonly totalMs: number | null;\n /** Existing per-statement limit, independent of the total deadline. Zero disables it. */\n readonly statementTimeoutMs: number | null;\n /** Milliseconds left (never negative), or `null` when no deadline is set. */\n remainingMs(): number | null;\n /** True only when a deadline is set and has passed. */\n expired(): boolean;\n /** Refuse a closed handle or an expired budget. Called BEFORE anything is sent. */\n assertUsable(params: { stage: BudgetStage }): void;\n /** Record the commit outcome and close every handle; the first call wins and later ones are ignored. */\n close(params: { outcome: TransactionOutcome }): void;\n /** The recorded commit outcome, or `null` while the transaction is still open. */\n readonly outcome: TransactionOutcome | null;\n};\n\n// ─── Validation (before BEGIN, before any write) ──────────────────\n\n/**\n * Check `options.deadline` against what this adapter can honestly deliver.\n * Called BEFORE `BEGIN` — a budget this engine cannot honour must never leave\n * a transaction open behind it.\n *\n * @throws VibeError `VIBE_VALIDATION` when `totalMs` is not a positive integer.\n * @throws VibeError `VIBE_UNSUPPORTED_CAPABILITY` when the requested\n * `enforcement` is stronger than `support` — refused, never silently degraded.\n */\nexport function validateTransactionDeadline(params: {\n options?: TransactionOptions;\n support: TransactionDeadlineSupport;\n provider: string;\n}): void {\n const { options, support, provider } = params;\n const deadline = options?.deadline;\n if (deadline === undefined) return;\n\n if (support === \"unsupported\") {\n throw new VibeError({\n code: \"VIBE_UNSUPPORTED_CAPABILITY\",\n message: `${provider} cannot enforce a transaction deadline — remove the \\`deadline\\` option`,\n meta: { provider, feature: \"transactionDeadline\", supported: support },\n });\n }\n\n if (!Number.isInteger(deadline.totalMs) || deadline.totalMs <= 0) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `transaction deadline \\`totalMs\\` must be a positive integer of milliseconds, received ${String(deadline.totalMs)}`,\n meta: { provider, feature: \"transactionDeadline\", totalMs: deadline.totalMs },\n });\n }\n\n const requested: TransactionDeadlineEnforcement = deadline.enforcement ?? \"between-statements\";\n if (requested === \"cancel-running-statements\" && support !== \"cancel-running-statements\") {\n throw new VibeError({\n code: \"VIBE_UNSUPPORTED_CAPABILITY\",\n message:\n `${provider} cannot cancel a statement that is already running, so the requested ` +\n \"`cancel-running-statements` deadline guarantee is refused rather than silently downgraded — \" +\n 'ask for \"between-statements\" if a budget checked between statements is enough',\n meta: { provider, feature: \"transactionDeadline\", requested, supported: support },\n });\n }\n}\n\n// ─── The budget ───────────────────────────────────────────────────\n\n/**\n * Start the clock for one top-level transaction. Call it immediately before\n * `BEGIN`; {@link validateTransactionDeadline} must already have run.\n */\nexport function startTransactionBudget(params: {\n options?: TransactionOptions;\n provider: string;\n clock?: DeadlineClock;\n}): TransactionBudget {\n const { options, provider } = params;\n const clock = params.clock ?? DEFAULT_DEADLINE_CLOCK;\n const deadline = options?.deadline;\n const totalMs = deadline === undefined ? null : deadline.totalMs;\n const enforcement: TransactionDeadlineEnforcement | null =\n deadline === undefined ? null : (deadline.enforcement ?? \"between-statements\");\n const expiresAt = totalMs === null ? null : clock() + totalMs;\n let outcome: TransactionOutcome | null = null;\n\n const budget: TransactionBudget = {\n enforcement,\n totalMs,\n statementTimeoutMs: options?.timeout ?? null,\n remainingMs(): number | null {\n return expiresAt === null ? null : Math.max(0, expiresAt - clock());\n },\n expired(): boolean {\n return expiresAt !== null && clock() >= expiresAt;\n },\n assertUsable(assertParams: { stage: BudgetStage }): void {\n if (outcome !== null) {\n throw transactionClosedError({ provider, outcome, stage: assertParams.stage });\n }\n if (expiresAt !== null && clock() >= expiresAt) {\n throw transactionDeadlineError({\n provider,\n stage: assertParams.stage,\n totalMs: totalMs as number,\n overdueMs: clock() - expiresAt,\n });\n }\n },\n close(closeParams: { outcome: TransactionOutcome }): void {\n if (outcome === null) outcome = closeParams.outcome;\n },\n get outcome(): TransactionOutcome | null {\n return outcome;\n },\n };\n return budget;\n}\n\n/**\n * The engine-side bound for the NEXT statement, or `null` when the caller did\n * not buy `\"cancel-running-statements\"`. Floored at 1 ms: on postgres `0` means\n * \"no limit\", so a spent budget must never be handed over as a zero.\n */\nexport function engineStatementBudgetMs(params: { budget: TransactionBudget }): number | null {\n const { budget } = params;\n if (budget.enforcement !== \"cancel-running-statements\") return null;\n const remaining = budget.remainingMs();\n if (remaining === null) return null;\n const totalBound = Math.max(1, Math.ceil(remaining));\n return budget.statementTimeoutMs !== null && budget.statementTimeoutMs > 0\n ? Math.min(totalBound, budget.statementTimeoutMs) : totalBound;\n}\n\n// ─── Errors ───────────────────────────────────────────────────────\n\n/**\n * The refusal an expired budget raises. `VIBE_TRANSACTION` with a stable\n * `meta.reason` — no SQL text, no parameter values, no credentials.\n */\nexport function transactionDeadlineError(params: {\n provider: string;\n stage: BudgetStage;\n totalMs: number;\n overdueMs: number;\n}): VibeError {\n const { provider, stage, totalMs, overdueMs } = params;\n const what =\n stage === \"commit\"\n ? \"COMMIT was never sent, so the transaction did not commit\"\n : \"the statement was never sent, and the transaction will not commit\";\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n `transaction deadline of ${totalMs} ms expired ${Math.max(0, Math.round(overdueMs))} ms ago — ${what}. ` +\n \"Nothing is retried automatically: work the callback did outside the database may already have happened.\",\n meta: { provider, reason: \"transaction-deadline\", stage, totalMs, overdueMs: Math.max(0, Math.round(overdueMs)) },\n });\n}\n\n/**\n * The refusal an ESCAPED transaction handle raises — a transactional adapter\n * kept past the end of its transaction. Without this it would run on a\n * connection that is back in the pool, outside any transaction.\n */\nexport function transactionClosedError(params: {\n provider: string;\n outcome: TransactionOutcome;\n stage: BudgetStage;\n}): VibeError {\n const { provider, outcome, stage } = params;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n `this transaction has already finished (${outcome}), so its client can no longer be used — ` +\n \"a handle kept past the end of `$transaction` would run outside the transaction, on a connection \" +\n \"that now belongs to someone else\",\n meta: { provider, reason: \"transaction-closed\", outcome, stage },\n });\n}\n\n/**\n * The stable typed outcome for \"a client-side deadline stopped waiting for a\n * COMMIT that had already left the client\" — the commit state is UNKNOWN.\n * Thrown only by `settleFailedTransaction` (./transaction-outcome.ts), and only\n * for that case: a deadline that refused the COMMIT BEFORE it was sent is a\n * known outcome (not committed) and rethrows its own deadline error, even when\n * the cleanup ROLLBACK failed (EPIC T). No adapter in this repository abandons\n * a sent COMMIT — each checks the deadline before COMMIT is sent, or lets the\n * server enforce it — so their lost-COMMIT errors are their own\n * `transaction-outcome-unknown` errors.\n *\n * `cause` is the CAUSAL error (the deadline refusal). What happened to the\n * cleanup ROLLBACK and the connection is in `transactionOutcomeOf({ error })`, not\n * in `meta`: a raw driver failure can carry statement text, and this error is\n * meant to be logged.\n */\nexport function transactionOutcomeUnknownError(params: {\n provider: string;\n totalMs: number;\n cause: unknown;\n}): VibeError {\n const { provider, totalMs, cause } = params;\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n `transaction deadline of ${totalMs} ms expired while COMMIT was in flight and the client stopped waiting for its answer — ` +\n \"the commit state of this transaction is UNKNOWN. It is not retried automatically; inspect the data \" +\n \"before deciding.\",\n meta: {\n provider,\n reason: \"transaction-outcome-unknown\",\n outcome: \"unknown\",\n stage: \"commit\",\n totalMs,\n },\n cause,\n });\n}\n\n/** Whether `error` is this module's deadline refusal (used to pick the cleanup path). */\nexport function isTransactionDeadlineError(error: unknown): boolean {\n const reason = (error as { meta?: { reason?: unknown } } | null)?.meta?.reason;\n return reason === \"transaction-deadline\";\n}\n",
10
+ "/**\n * Transaction outcome reports — what a FAILED top-level transaction did and\n * did not do (EPIC T).\n *\n * ONE copy, shared by every adapter package through the\n * `@vibeorm/runtime/adapter-kit` subpath (like `transaction-budget.ts`), so the\n * rule cannot drift into a per-engine difference.\n *\n * THE RULE\n *\n * The commit outcome follows from how far the adapter's OWN `COMMIT` got —\n * never from the type of the error that ended the transaction:\n *\n * - `\"not-committed\"`: `COMMIT` never left the client (the callback failed, a\n * deadline or a closed handle refused it, or the driver had already seen the\n * connection die and refused it locally), or the engine ANSWERED it with an\n * error or a ROLLBACK tag. Only this session can send `COMMIT`, and a\n * server ends an open transaction when its connection closes, so a failed\n * cleanup `ROLLBACK` does not change this.\n * - `\"unknown\"`: a `COMMIT` that left the client got no answer — the\n * connection was lost while it was in flight, or a client-side deadline\n * stopped waiting for it. Also when the savepoint stack was lost before\n * `COMMIT` (`savepoint-rollback-failed`): an implicit commit (MySQL DDL) or a\n * raw `COMMIT` may already have ended the transaction.\n * - `\"committed\"`: the engine acknowledged `COMMIT`. A successful transaction\n * throws nothing, so no report is recorded for it.\n *\n * The cleanup is reported APART from the commit outcome: whether the cleanup\n * `ROLLBACK` was acknowledged, failed or not needed, and whether the\n * connection went back to the pool or was discarded.\n *\n * WHERE THE FACTS LIVE\n *\n * The error a failed transaction throws stays the SAME value — callers match\n * their own errors and stable codes. The facts ride beside it in a registry\n * keyed by that value, read with {@link transactionOutcomeOf}. The registry is\n * a `WeakMap` held on `globalThis` under a `Symbol.for` key: the runtime's\n * main entry and this subpath are separate bundles, each with its own copy of\n * this module, and both must read the same map. A `WeakMap` never keeps an\n * error alive and never changes the error object. Under a frozen or sealed\n * `globalThis` (SES, hardened JavaScript) the key cannot be added: each copy\n * then keeps a module-local map, so a report recorded by one bundle is not\n * visible from the other, and the accessor returns `undefined` — the runtime\n * stays importable.\n *\n * A CROSS-VERSION CONTRACT\n *\n * Two installed copies of `@vibeorm/runtime` (an adapter built against one,\n * a framework reading with another) share the one global map. Each stored\n * record therefore carries a `version`. The report shape is append-only:\n * fields are only ever added; a change of meaning bumps the version, and a\n * reader that does not know a record's version returns `undefined` (\"no\n * facts\") rather than misreading it.\n */\n\nimport { isSavepointRollbackFailedError, type SavepointScope } from \"./savepoint-gate.ts\";\nimport {\n isTransactionDeadlineError,\n transactionOutcomeUnknownError,\n type TransactionBudget,\n type TransactionOutcome,\n} from \"./transaction-budget.ts\";\n\n// ─── Types ────────────────────────────────────────────────────────\n\n/**\n * How far an adapter's own `COMMIT` got. The adapter moves it to `\"sent\"`\n * IMMEDIATELY before `COMMIT` is handed to the driver, and on a failure\n * classifies a sent `COMMIT` as `\"answered\"` (the engine replied with an error\n * or a ROLLBACK tag) or `\"unanswered\"` (the reply was lost or abandoned). A\n * `\"sent\"` that was never classified counts as unanswered: without an answer\n * nothing proves that the write did not commit.\n */\nexport type CommitProgress = \"not-sent\" | \"sent\" | \"answered\" | \"unanswered\";\n\n/** What the cleanup `ROLLBACK` of a failed top-level transaction did. */\nexport type RollbackOutcome = \"acknowledged\" | \"failed\" | \"not-needed\";\n\n/** Where the transaction's connection went after the failure. */\nexport type ConnectionOutcome = \"returned\" | \"discarded\";\n\n/**\n * The facts of one failed top-level transaction, read with\n * {@link transactionOutcomeOf}.\n *\n * - `commit`: the commit outcome (see the module rule). `\"not-committed\"` is\n * safe to retry as far as the database is concerned; `\"unknown\"` is not.\n * - `commitSent`: whether the adapter handed its `COMMIT` to the driver.\n * - `rollback`: `\"acknowledged\"` (the engine confirmed the cleanup\n * `ROLLBACK`), `\"failed\"` (it was sent and failed — the connection is lost,\n * or the engine refused it), `\"not-needed\"` (no transaction was open on the\n * connection: nothing was sent yet, or the engine had already ended it\n * when it answered `COMMIT`).\n * - `connection`: `\"returned\"` to the pool (or kept, on a single-connection\n * engine) or `\"discarded\"` (destroyed, so the server ends whatever it still\n * holds when it sees the close).\n */\nexport type TransactionOutcomeReport = {\n readonly commit: FailedCommitOutcome;\n readonly commitSent: boolean;\n readonly rollback: RollbackOutcome;\n readonly connection: ConnectionOutcome;\n};\n\n/**\n * The commit outcome of a FAILED transaction. `\"committed\"` is never recorded:\n * a transaction that committed throws nothing.\n */\nexport type FailedCommitOutcome = Exclude<TransactionOutcome, \"committed\">;\n\n// ─── The registry ─────────────────────────────────────────────────\n\n/** The record version this copy writes and reads (see \"A CROSS-VERSION CONTRACT\"). */\nconst REPORT_VERSION = 1;\n\n/** One stored record: the report, stamped with the version of its shape. */\ntype StoredOutcome = { readonly version: number; readonly report: TransactionOutcomeReport };\n\ntype OutcomeRegistry = WeakMap<object, StoredOutcome>;\n\n/** Global symbol key, so every bundled copy of this module shares one map. */\nconst REGISTRY_KEY: symbol = Symbol.for(\"vibeorm.adapter-kit.transaction-outcome\");\n\nfunction sharedRegistry(): OutcomeRegistry {\n const existing: unknown = (globalThis as unknown as Record<symbol, unknown>)[REGISTRY_KEY];\n if (existing instanceof WeakMap) return existing as OutcomeRegistry;\n const created: OutcomeRegistry = new WeakMap();\n // A frozen or sealed global (SES, hardened JavaScript) cannot take the key:\n // keep a module-local map instead of failing the import.\n if (!Object.isExtensible(globalThis)) return created;\n Object.defineProperty(globalThis, REGISTRY_KEY, { value: created, enumerable: false, configurable: false, writable: false });\n return created;\n}\n\nconst REPORTS: OutcomeRegistry = sharedRegistry();\n\n/** Whether `value` can key a `WeakMap` (objects and functions only). */\nfunction isReportable(value: unknown): value is object {\n return (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n}\n\n/**\n * Attach `report` to the value a failed top-level transaction is about to\n * throw. A later report for the same value replaces the earlier one, so a\n * value rethrown through several top-level transactions carries the facts of\n * the LAST one it left. A primitive thrown value (a string, a number,\n * `undefined`) cannot key a `WeakMap`, so nothing is recorded for it.\n */\nexport function recordTransactionOutcome(params: { error: unknown; report: TransactionOutcomeReport }): void {\n const { error, report } = params;\n if (!isReportable(error)) return;\n REPORTS.set(error, Object.freeze({ version: REPORT_VERSION, report: Object.freeze({ ...report }) }));\n}\n\n/**\n * The facts of the failed top-level transaction that threw `error`, or\n * `undefined` when there are none.\n *\n * `undefined` means one of: the adapter does not declare\n * `transactionOutcome: \"reported\"`; `error` did not leave a top-level\n * `transaction()` (a nested savepoint records nothing); the transaction was\n * refused before it started (an invalid option, a connection that could not be\n * acquired — nothing was sent); the thrown value is not an object (a\n * primitive cannot key the registry — throw `Error` objects to keep the facts);\n * the record was written by a runtime copy with a report version this copy\n * does not know; or `globalThis` is frozen and the report was recorded by the\n * other bundle (see the module doc).\n */\nexport function transactionOutcomeOf(params: { error: unknown }): TransactionOutcomeReport | undefined {\n const { error } = params;\n if (!isReportable(error)) return undefined;\n const stored = REPORTS.get(error);\n return stored?.version === REPORT_VERSION ? stored.report : undefined;\n}\n\n// ─── The rule ─────────────────────────────────────────────────────\n\n/** The commit outcome of a failed transaction — the ONE rule (see the module doc). */\nexport function failedCommitOutcome(params: { commit: CommitProgress; stateLost: boolean }): FailedCommitOutcome {\n const { commit, stateLost } = params;\n if (commit === \"sent\" || commit === \"unanswered\") return \"unknown\";\n return stateLost ? \"unknown\" : \"not-committed\";\n}\n\n/**\n * Close a failed top-level transaction's budget with its commit outcome (the\n * rule above) and return that outcome. The first close wins: an adapter that\n * closed `unknown` the moment it lost a COMMIT reply keeps that.\n *\n * {@link settleFailedTransaction} calls it. An adapter whose connection must\n * leave BEFORE it can settle (adapter-mysql resets the session and releases the\n * connection to learn where it went) calls it first, so every handle of the\n * failed transaction is refused before the connection is handed back.\n */\nexport function closeFailedTransactionBudget(params: {\n error: unknown;\n budget: TransactionBudget;\n scope: SavepointScope;\n commit: CommitProgress;\n}): FailedCommitOutcome {\n const { error, budget, scope, commit } = params;\n const stateLost = isSavepointRollbackFailedError(error) || isSavepointRollbackFailedError(scope.state.poisoned);\n const outcome = failedCommitOutcome({ commit, stateLost });\n budget.close({ outcome });\n return outcome;\n}\n\n/**\n * Settle a failed top-level transaction AFTER its cleanup ran: close the\n * budget with the commit outcome, choose the value to throw, and record the\n * facts on it. Returns that value; the adapter throws it.\n *\n * The value is `error` itself — the same object, the same code — except when\n * a client-side deadline abandoned a COMMIT that had already left the client\n * (`commit: \"unanswered\"` with the deadline refusal as `error`): only then is\n * it {@link transactionOutcomeUnknownError}. A deadline that refused the\n * COMMIT before it was sent is a known outcome (`\"not-committed\"`), and its own\n * deadline error is rethrown even when the cleanup `ROLLBACK` failed.\n */\nexport function settleFailedTransaction(params: {\n error: unknown;\n provider: string;\n budget: TransactionBudget;\n scope: SavepointScope;\n commit: CommitProgress;\n rollback: RollbackOutcome;\n connection: ConnectionOutcome;\n}): unknown {\n const { error, provider, budget, scope, commit, rollback, connection } = params;\n const outcome = closeFailedTransactionBudget({ error, budget, scope, commit });\n const abandoned = commit === \"unanswered\" && budget.totalMs !== null && isTransactionDeadlineError(error);\n const thrown = abandoned\n ? transactionOutcomeUnknownError({ provider, totalMs: budget.totalMs as number, cause: error })\n : error;\n recordTransactionOutcome({\n error: thrown,\n report: { commit: outcome, commitSent: commit !== \"not-sent\", rollback, connection },\n });\n return thrown;\n}\n",
11
+ "import type { RowChangeCount, StatementEffect } from \"../adapter.ts\";\nimport type { SavepointScope } from \"./savepoint-gate.ts\";\n\n/**\n * Only structured intent attests complete direct effects; raw command tags do not.\n * `count` is the driver's affected/command count (used for `write`); `rows` is the\n * number of result rows the driver returned (used for `writeRows`, whose result\n * rows ARE its direct effects — a statement chain's command tag is `SELECT n`).\n */\nexport function statementRowChanges(params: {\n readonly effect?: StatementEffect;\n readonly count?: unknown;\n readonly rows?: unknown;\n /** The result rows themselves (used for `writeTally`, which reads {@link ROW_CHANGES_COLUMN}). */\n readonly resultRows?: readonly Record<string, unknown>[];\n readonly command?: string;\n}): RowChangeCount {\n const { effect } = params;\n if (effect === \"read\") return 0;\n if (effect === \"writeTally\") return tallyOf({ rows: params.resultRows });\n const count = effect === \"write\" ? params.count : effect === \"writeRows\" ? params.rows : undefined;\n if (effect !== \"write\" && effect !== \"writeRows\") return \"unknown\";\n return typeof count === \"number\" && Number.isSafeInteger(count) && count >= 0 ? count : \"unknown\";\n}\n\n/**\n * The result column a `writeTally` statement reports its direct effects in\n * (round-trip campaign EPIC F): the number of rows its data-modifying steps\n * changed, on every result row. The runtime strips it before decoding.\n */\nexport const ROW_CHANGES_COLUMN: string = \"__vibe_row_changes\";\n\n/** Sum of {@link ROW_CHANGES_COLUMN} over the rows; drivers report the count as a number, a digit string or a bigint. */\nfunction tallyOf(params: { rows: readonly Record<string, unknown>[] | undefined }): RowChangeCount {\n const { rows } = params;\n if (rows === undefined || rows.length === 0) return \"unknown\";\n let total = 0;\n for (const row of rows) {\n const value = row[ROW_CHANGES_COLUMN];\n const count = typeof value === \"number\" ? value\n : typeof value === \"bigint\" ? Number(value)\n : typeof value === \"string\" && /^\\d+$/.test(value) ? Number(value)\n : Number.NaN;\n if (!Number.isSafeInteger(count) || count < 0) return \"unknown\";\n total += count;\n }\n return Number.isSafeInteger(total) ? total : \"unknown\";\n}\n\n/** Fold one successfully executed direct effect into its physical transaction's surviving tally. */\nexport function observeRowChanges(params: { readonly scope: SavepointScope; readonly count: RowChangeCount }): void {\n const state = params.scope.state;\n if (state.rowChanges === \"unknown\") return;\n const count = params.count;\n if (count === \"unknown\" || !Number.isSafeInteger(count) || count < 0 || !Number.isSafeInteger(state.rowChanges + count)) {\n state.rowChanges = \"unknown\";\n return;\n }\n state.rowChanges += count;\n}\n\n/**\n * Observe one synchronous driver dispatch that forbids reentrant writes on the\n * same connection. Failed writes can retain partial effects, so mark unknown\n * before stepping and restore the snapshot only after successful attestation.\n */\nexport function dispatchSynchronousRowChanges<T>(params: {\n readonly scope?: SavepointScope;\n readonly effect?: StatementEffect;\n readonly run: () => T;\n readonly count: (result: T) => RowChangeCount;\n}): T {\n const { scope } = params;\n if (scope === undefined || scope.state.rowChanges === \"unknown\") return params.run();\n const before = scope.state.rowChanges;\n if (params.effect !== \"read\") scope.state.rowChanges = \"unknown\";\n const result = params.run();\n const count = params.count(result);\n scope.state.rowChanges = before;\n observeRowChanges({ scope, count });\n return result;\n}\n\n/** Tentative surviving effects; poisoned/aborted transactions cannot supply a trusted numeric sample. */\nexport function readRowChanges(params: { readonly scope: SavepointScope }): RowChangeCount {\n const state = params.scope.state;\n return state.poisoned !== null || state.aborted !== null ? \"unknown\" : state.rowChanges;\n}\n",
10
12
  "import { VibeError } from \"@vibeorm/schema\";\nimport type { SqlExecutor } from \"../adapter.ts\";\n\n/** Own one physical session until the callback and dispatched work have settled. */\nexport function runPinnedSession<T>(params: {\n readonly execute: SqlExecutor;\n readonly run: (executor: SqlExecutor) => Promise<T>;\n readonly release: () => Promise<void>;\n readonly isLost: (error: unknown) => boolean;\n}): Promise<T> {\n let active = true;\n let lost: VibeError | undefined;\n let tail: Promise<void> = Promise.resolve();\n const executor: SqlExecutor = (query) => {\n const result = tail.then(async () => {\n if (lost !== undefined) throw lost;\n if (!active) throw new VibeError({\n code: \"VIBE_ADAPTER\",\n message: \"The reserved database session has finished; acquire a new session before executing SQL.\",\n meta: { reason: \"session-closed\" },\n });\n return params.execute(query).catch((cause: unknown) => {\n if (params.isLost(cause)) {\n lost = new VibeError({\n code: \"VIBE_ADAPTER\",\n message: \"The reserved database session was lost. No further SQL will be sent; inspect migration progress before retrying.\",\n meta: { reason: \"session-lost\", outcome: \"unknown\" },\n cause,\n });\n throw lost;\n }\n throw cause;\n });\n });\n tail = result.then(() => undefined, () => undefined);\n return result;\n };\n const settle = async (): Promise<void> => {\n active = false;\n await tail;\n };\n // The migration's own failure stays the primary outcome (the e643012 rule):\n // the operator acts on ITS verdict — session-lost, outcome unknown — not on\n // cleanup. A release failure rides along as evidence.\n const fail = async (cause: unknown): Promise<never> => {\n await params.release().catch((cleanupCause: unknown) => {\n throw withCleanupCause({ cause, cleanupCause });\n });\n throw cause;\n };\n return Promise.resolve().then(() => params.run(executor)).then(\n async (result) => {\n await settle();\n if (lost !== undefined) return fail(lost);\n await params.release();\n return result;\n },\n async (cause: unknown) => {\n await settle();\n return fail(cause);\n },\n );\n}\n\n/**\n * Rethrow `cause` with `cleanupCause` attached as `meta.cleanupCause` when it\n * is a `VibeError`; a foreign failure is rethrown as is (its identity matters\n * more than the evidence — callers matched it, never the cleanup).\n */\nexport function withCleanupCause(params: { cause: unknown; cleanupCause: unknown }): unknown {\n const { cause, cleanupCause } = params;\n if (cause instanceof VibeError) {\n return new VibeError({ code: cause.code, message: cause.message, meta: { ...cause.meta, cleanupCause }, cause });\n }\n return cause;\n}\n",
13
+ "/**\n * The terminal lifetime of a root adapter (EPIC A2): `disconnect()` ends an\n * adapter for good. ONE copy, shared by all six first-party adapters.\n *\n * - `admit` registers a root operation (statement, transaction, session,\n * connect) synchronously, BEFORE it reaches its first await, and refuses\n * with `VIBE_ADAPTER_CLOSED` once `disconnect()` was called. Admitted\n * operations run independently: this is lifecycle accounting, not a queue —\n * server statements stay concurrent.\n * - `inCallback` marks a transaction/session callback as running, so the\n * callback's own call of the root `disconnect()` refuses instead of waiting\n * for itself to finish.\n * - `disconnect` seals admission synchronously, waits until every admitted\n * operation has settled (their callbacks may still issue child statements),\n * then runs the adapter's cleanup once. Every later or concurrent call gets\n * the same completion — success or failure — and admission never reopens.\n *\n * There is no timer, no cancellation and no scheduler: an unfinished admitted\n * callback keeps `disconnect()` waiting. Stop producers and await pending work\n * before closing.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { VibeError } from \"@vibeorm/schema\";\nimport { withCleanupCause } from \"./session.ts\";\n\n// ─── Types ────────────────────────────────────────────────────────\n\n/** The adapter a lifecycle gate belongs to; carried as `meta.driver` by its refusals. */\nexport type AdapterLifecycleDriver = \"pg\" | \"bun\" | \"mysql\" | \"pglite\" | \"sqlite\" | \"better-sqlite3\";\n\n/** One root adapter's terminal lifetime. */\nexport type AdapterLifecycleGate = {\n /** Run a root operation, or refuse it with `VIBE_ADAPTER_CLOSED` once `disconnect()` was called. */\n readonly admit: <T>(params: { readonly run: () => Promise<T> }) => Promise<T>;\n /** Run a transaction/session callback with this gate's active-callback marker set. */\n readonly inCallback: <T>(params: { readonly run: () => Promise<T> }) => Promise<T>;\n /** Seal, drain admitted work, clean up once; every call shares the one completion. */\n readonly disconnect: () => Promise<void>;\n};\n\n// ─── Refusals ─────────────────────────────────────────────────────\n\n/** New root work on an adapter whose `disconnect()` was called. Fixed meta, never an address. */\nexport function adapterClosedError(params: {\n readonly driver: AdapterLifecycleDriver;\n readonly state: \"closing\" | \"closed\";\n}): VibeError {\n const { driver, state } = params;\n return new VibeError({\n code: \"VIBE_ADAPTER_CLOSED\",\n message: `This ${driver} adapter was disconnected${state === \"closing\" ? \" and is closing\" : \"\"}; it accepts no new work. Create a new adapter to connect again.`,\n meta: { driver, state },\n });\n}\n\n/** The root `disconnect()` called from inside one of its own running callbacks. */\nexport function disconnectInActiveCallbackError(params: { readonly driver: AdapterLifecycleDriver }): VibeError {\n return new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"disconnect() was called from inside this adapter's own running transaction or session callback; it would wait for that callback to finish. Return from the callback first, then disconnect.\",\n meta: { reason: \"disconnect-in-active-callback\", driver: params.driver },\n });\n}\n\n/**\n * `connect` / `disconnect` on a transaction handle (or `$connect` /\n * `$disconnect` on a transaction client). The connection belongs to the\n * transaction for its whole lifetime: reconnecting mid-transaction is\n * meaningless and disconnecting would tear down an open transaction's own\n * connection. The generated transaction type omits both; this refusal is the\n * authority, because a type cannot stop a JavaScript caller.\n */\nexport function transactionLifecycleRefusal(params: { readonly method: string }): VibeError {\n const { method } = params;\n return new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `${method}() is not available on a transaction client — the connection is owned by the open transaction; call it on the client that started the transaction`,\n meta: { method, inTransaction: true },\n });\n}\n\n// ─── Gate ─────────────────────────────────────────────────────────\n\n/**\n * Create the lifecycle gate of ONE root adapter. `cleanup` closes what the\n * adapter owns (raw session, owned pool/instance/database) and is called at\n * most once, after admitted work drained. `isConnectionReentrant` lets an\n * embedded adapter report a running callback of the connection it shares with\n * other wrappers; that callback's `disconnect()` refuses too.\n */\nexport function createAdapterLifecycleGate(params: {\n readonly driver: AdapterLifecycleDriver;\n readonly cleanup: () => Promise<void>;\n readonly isConnectionReentrant?: () => boolean;\n}): AdapterLifecycleGate {\n const { driver, cleanup, isConnectionReentrant } = params;\n const callbacks = new AsyncLocalStorage<{ active: boolean }>();\n let state: \"open\" | \"closing\" | \"closed\" = \"open\";\n let active = 0;\n let drained: (() => void) | null = null;\n let completion: Promise<void> | null = null;\n\n const settleOne = (): void => {\n active -= 1;\n if (active === 0 && drained !== null) {\n const resolve = drained;\n drained = null;\n resolve();\n }\n };\n\n return {\n admit<T>(admitParams: { readonly run: () => Promise<T> }): Promise<T> {\n if (state !== \"open\") return Promise.reject(adapterClosedError({ driver, state }));\n active += 1;\n // Started synchronously, like the adapter method it wraps; a synchronous\n // throw becomes this promise's rejection, never a lost decrement.\n const result = new Promise<T>((resolve) => { resolve(admitParams.run()); });\n result.then(settleOne, settleOne);\n return result;\n },\n\n inCallback<T>(callbackParams: { readonly run: () => Promise<T> }): Promise<T> {\n const token = { active: true };\n // The marker expires with the callback: a timer or promise it left\n // behind inherits the context but must not refuse a later disconnect().\n return callbacks\n .run(token, () => new Promise<T>((resolve) => { resolve(callbackParams.run()); }))\n .finally(() => { token.active = false; });\n },\n\n disconnect(): Promise<void> {\n // Checked BEFORE joining a pending close: a callback awaiting the shared\n // completion would wait for itself.\n if (callbacks.getStore()?.active === true || isConnectionReentrant?.() === true) {\n return Promise.reject(disconnectInActiveCallbackError({ driver }));\n }\n if (completion !== null) return completion;\n state = \"closing\";\n const drain = active === 0 ? Promise.resolve() : new Promise<void>((resolve) => { drained = resolve; });\n completion = drain.then(() => cleanup()).then(\n () => { state = \"closed\"; },\n (error: unknown) => {\n // A failed cleanup is reported to every caller; admission stays sealed.\n state = \"closed\";\n throw error;\n },\n );\n return completion;\n },\n };\n}\n\n// ─── Shutdown cleanup ─────────────────────────────────────────────\n\n/**\n * The named shutdown-cleanup boundary of the adapters' `disconnect()`: run\n * every step in order even when an earlier one failed (a failed raw-session\n * rollback must still let the owned pool close), then reject with the FIRST\n * failure, later failures attached as `meta.cleanupCause` evidence.\n */\nexport function runShutdownCleanup(params: { readonly steps: readonly (() => Promise<void>)[] }): Promise<void> {\n let failure: { readonly error: unknown } | undefined;\n let chain: Promise<void> = Promise.resolve();\n for (const step of params.steps) {\n chain = chain.then(step).then(undefined, (error: unknown) => {\n failure = failure === undefined ? { error } : { error: withCleanupCause({ cause: failure.error, cleanupCause: error }) };\n });\n }\n return chain.then(() => {\n if (failure !== undefined) throw failure.error;\n });\n}\n",
11
14
  "import { VibeError } from \"@vibeorm/schema\";\nimport { SQLITE_SESSION_SQL } from \"@vibeorm/sql\";\nimport type { SqlExecutor } from \"../adapter.ts\";\nimport { runPinnedSession, withCleanupCause } from \"./session.ts\";\n\n/** Hold SQLite's native file lock across transaction boundaries, then restore it. */\nexport async function runSqliteSession<T>(params: {\n readonly execute: SqlExecutor;\n readonly run: (executor: SqlExecutor) => Promise<T>;\n readonly inTransaction: () => boolean;\n}): Promise<T> {\n if (params.inTransaction()) throw new VibeError({\n code: \"VIBE_TRANSACTION\",\n message: \"A migration session cannot borrow a SQLite connection with an open transaction.\",\n meta: { reason: \"session-in-transaction\" },\n });\n const rows = await params.execute({ text: SQLITE_SESSION_SQL.lockingMode, values: [] });\n const mode = rows[0]?.locking_mode;\n if (mode !== \"normal\" && mode !== \"exclusive\") throw new VibeError({\n code: \"VIBE_ADAPTER\",\n message: \"SQLite did not report its locking mode; no migration was started.\",\n meta: { reason: \"session-lock-mode\" },\n });\n await params.execute({ text: SQLITE_SESSION_SQL.exclusive });\n const restore = async (): Promise<void> => {\n if (params.inTransaction()) await params.execute({ text: SQLITE_SESSION_SQL.rollback });\n await params.execute({ text: SQLITE_SESSION_SQL.foreignKeysOn });\n if (mode === \"normal\") {\n await params.execute({ text: SQLITE_SESSION_SQL.normal });\n // NORMAL alone does not release the lock: SQLite requires a database read.\n await params.execute({ text: SQLITE_SESSION_SQL.touch, values: [] });\n }\n };\n return Promise.resolve().then(async () => {\n // The transaction acquires the file lock; EXCLUSIVE retains it after COMMIT.\n await params.execute({ text: SQLITE_SESSION_SQL.acquire });\n await params.execute({ text: SQLITE_SESSION_SQL.commit });\n return runPinnedSession({\n execute: params.execute,\n run: params.run,\n isLost: () => false, // The captured native handle never reconnects.\n release: async () => {\n if (params.inTransaction()) await params.execute({ text: SQLITE_SESSION_SQL.rollback });\n },\n });\n }).then(\n async (result) => {\n await restore();\n return result;\n },\n async (cause: unknown) => {\n // The migration's own failure stays primary; a restore failure (the\n // database is locked or read-only by now) rides along as evidence.\n await restore().catch((cleanupCause: unknown) => {\n throw withCleanupCause({ cause, cleanupCause });\n });\n throw cause;\n },\n );\n}\n"
12
15
  ],
13
- "mappings": "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",
14
- "debugId": "9043FC0FD9D8EA9E64756E2164756E21",
16
+ "mappings": "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",
17
+ "debugId": "DA2DF3165F53603864756E2164756E21",
15
18
  "names": []
16
19
  }
@@ -12,11 +12,25 @@ import type { TransactionOptions } from "../adapter.ts";
12
12
  * isolation level of the transaction it joins, enforce its own timeout, nor
13
13
  * carry its own deadline. Silently dropping the option hid exactly that.
14
14
  *
15
- * @throws VibeError `VIBE_VALIDATION` when `isolationLevel`, `timeout` or
16
- * `deadline` is present (an `undefined` or empty options object is accepted).
15
+ * @throws VibeError `VIBE_VALIDATION` when `isolationLevel`, `timeout`,
16
+ * `deadline` or `accessMode` is present (an `undefined` or empty options
17
+ * object is accepted).
17
18
  */
18
19
  export declare function refuseNestedTransactionOptions(params: {
19
20
  options?: TransactionOptions;
20
21
  provider: string;
21
22
  }): void;
23
+ /**
24
+ * Whether a TOP-LEVEL transaction asked for `accessMode: "readOnly"`. ONE
25
+ * copy of the value check, shared by every adapter that honours the option:
26
+ * an untyped caller's other value is refused instead of silently opening a
27
+ * read/write transaction.
28
+ *
29
+ * @throws VibeError `VIBE_VALIDATION` when `accessMode` is present and is not
30
+ * `"readOnly"`.
31
+ */
32
+ export declare function readOnlyRequested(params: {
33
+ options?: TransactionOptions;
34
+ provider: string;
35
+ }): boolean;
22
36
  //# sourceMappingURL=nested-options.d.ts.map
@@ -1,11 +1,25 @@
1
1
  import type { RowChangeCount, StatementEffect } from "../adapter.ts";
2
2
  import type { SavepointScope } from "./savepoint-gate.ts";
3
- /** Only structured intent attests complete direct effects; raw command tags do not. */
3
+ /**
4
+ * Only structured intent attests complete direct effects; raw command tags do not.
5
+ * `count` is the driver's affected/command count (used for `write`); `rows` is the
6
+ * number of result rows the driver returned (used for `writeRows`, whose result
7
+ * rows ARE its direct effects — a statement chain's command tag is `SELECT n`).
8
+ */
4
9
  export declare function statementRowChanges(params: {
5
10
  readonly effect?: StatementEffect;
6
11
  readonly count?: unknown;
12
+ readonly rows?: unknown;
13
+ /** The result rows themselves (used for `writeTally`, which reads {@link ROW_CHANGES_COLUMN}). */
14
+ readonly resultRows?: readonly Record<string, unknown>[];
7
15
  readonly command?: string;
8
16
  }): RowChangeCount;
17
+ /**
18
+ * The result column a `writeTally` statement reports its direct effects in
19
+ * (round-trip campaign EPIC F): the number of rows its data-modifying steps
20
+ * changed, on every result row. The runtime strips it before decoding.
21
+ */
22
+ export declare const ROW_CHANGES_COLUMN: string;
9
23
  /** Fold one successfully executed direct effect into its physical transaction's surviving tally. */
10
24
  export declare function observeRowChanges(params: {
11
25
  readonly scope: SavepointScope;
@@ -66,7 +66,7 @@ export type SavepointState = {
66
66
  /** The innermost savepoint currently open, or `null` when none is. */
67
67
  open: OpenSavepoint | null;
68
68
  /**
69
- * Set once a `ROLLBACK TO SAVEPOINT` has failed: the savepoint stack no
69
+ * Set once savepoint rollback or its cleanup release has failed: the stack no
70
70
  * longer describes the connection, so every later statement and nested
71
71
  * savepoint on ANY handle of this transaction is refused with this error.
72
72
  */
@@ -148,6 +148,8 @@ export declare function scopeTurn(params: {
148
148
  export declare function runNestedSavepoint<T>(params: {
149
149
  readonly scope: SavepointScope;
150
150
  readonly execute?: (statement: string) => Promise<unknown> | unknown;
151
+ /** Budget-independent rollback and post-rollback release; defaults to execute. */
152
+ readonly cleanup?: (statement: string) => Promise<unknown> | unknown;
151
153
  readonly body: (scope: SavepointScope) => Promise<T>;
152
154
  }): Promise<T>;
153
155
  /** Snapshot after actual SAVEPOINT establishment, including driver-managed savepoint callbacks. */
@@ -155,7 +157,7 @@ export declare function markSavepointOpened(params: {
155
157
  readonly scope: SavepointScope;
156
158
  }): void;
157
159
  /**
158
- * The refusal raised when `ROLLBACK TO SAVEPOINT` itself fails, and repeated
160
+ * The refusal raised when savepoint rollback or its cleanup release fails, repeated
159
161
  * for every later statement on the poisoned transaction. `VIBE_TRANSACTION`
160
162
  * with `meta.reason = "savepoint-rollback-failed"` and `meta.outcome =
161
163
  * "unknown"`; `cause` is the body failure that triggered the rollback. The
@@ -166,13 +168,14 @@ export declare function markSavepointOpened(params: {
166
168
  export declare function savepointRollbackFailedError(params: {
167
169
  cause: unknown;
168
170
  rollbackFailure: unknown;
171
+ cleanupStage?: "rollback" | "release";
169
172
  }): VibeError;
170
173
  /** Whether `error` is this module's poison refusal (used to pick the cleanup path). */
171
174
  export declare function isSavepointRollbackFailedError(error: unknown): boolean;
172
175
  /**
173
176
  * The refusal raised for every statement, nested savepoint and the commit of
174
177
  * an aborted postgres transaction. `VIBE_TRANSACTION` with `meta.reason =
175
- * "aborted"` and `meta.outcome = "rolled-back"` — the outcome is CERTAIN: the
178
+ * "aborted"` and `meta.outcome = "not-committed"` — the outcome is CERTAIN: the
176
179
  * server discards an aborted transaction whatever the client sends. `cause`
177
180
  * is the statement failure that aborted it, and its `code`/`sqlstate` ride
178
181
  * along in `meta` so a log line names the real defect.
@@ -180,6 +183,17 @@ export declare function isSavepointRollbackFailedError(error: unknown): boolean;
180
183
  export declare function transactionAbortedError(params: {
181
184
  cause?: unknown;
182
185
  }): VibeError;
186
+ /**
187
+ * Record that the runtime raised `mapped` in place of the driver failure `raw`
188
+ * (the nested-fold veto: a failing cast the caller sees as today's
189
+ * not-found). If `raw` aborted a postgres transaction, the aborted refusal then
190
+ * names `mapped` as its cause — the error the caller actually saw (EPIC F
191
+ * decision 2). Non-enumerable; the raw error is otherwise unchanged.
192
+ */
193
+ export declare function recordMappedCause(params: {
194
+ raw: VibeError;
195
+ mapped: VibeError;
196
+ }): void;
183
197
  /** Whether `error` is the aborted-transaction refusal. */
184
198
  export declare function isTransactionAbortedError(error: unknown): boolean;
185
199
  export {};
@@ -36,11 +36,15 @@ import type { TransactionDeadlineEnforcement, TransactionDeadlineSupport, Transa
36
36
  /** Where a budget check happened, reported as `meta.stage`. */
37
37
  export type BudgetStage = "statement" | "nested" | "commit";
38
38
  /**
39
- * What is known about a finished transaction. `"unknown"` is a first-class
40
- * outcome, not a failure to decide: when a rollback itself fails the commit
41
- * state genuinely cannot be asserted, and claiming "rolled back" would be a lie.
39
+ * The COMMIT outcome of a finished transaction — one meaning only (EPIC T).
40
+ * `"not-committed"`: COMMIT was never sent, or the engine answered it with an
41
+ * error. `"unknown"` is a first-class outcome, not a failure to decide: a sent
42
+ * COMMIT got no answer (or the savepoint stack was lost first), so nothing on
43
+ * the client can say whether the write is durable. What happened to the
44
+ * cleanup ROLLBACK and the connection is reported apart from it — see
45
+ * `TransactionOutcomeReport` (./transaction-outcome.ts).
42
46
  */
43
- export type TransactionOutcome = "committed" | "rolled-back" | "unknown";
47
+ export type TransactionOutcome = "committed" | "not-committed" | "unknown";
44
48
  /** Wall clock, injectable so tests are deterministic instead of sleep-timed. */
45
49
  export type DeadlineClock = () => number;
46
50
  /** The ambient clock, used whenever no seam is injected. */
@@ -65,11 +69,11 @@ export type TransactionBudget = {
65
69
  assertUsable(params: {
66
70
  stage: BudgetStage;
67
71
  }): void;
68
- /** Record the terminal outcome; the first call wins and later ones are ignored. */
72
+ /** Record the commit outcome and close every handle; the first call wins and later ones are ignored. */
69
73
  close(params: {
70
74
  outcome: TransactionOutcome;
71
75
  }): void;
72
- /** The recorded outcome, or `null` while the transaction is still open. */
76
+ /** The recorded commit outcome, or `null` while the transaction is still open. */
73
77
  readonly outcome: TransactionOutcome | null;
74
78
  };
75
79
  /**
@@ -124,14 +128,20 @@ export declare function transactionClosedError(params: {
124
128
  stage: BudgetStage;
125
129
  }): VibeError;
126
130
  /**
127
- * The stable typed outcome for "the deadline expired and the rollback that was
128
- * supposed to clean up failed too". Promising a rollback here would be false;
129
- * promising a retry would be worse.
131
+ * The stable typed outcome for "a client-side deadline stopped waiting for a
132
+ * COMMIT that had already left the client" — the commit state is UNKNOWN.
133
+ * Thrown only by `settleFailedTransaction` (./transaction-outcome.ts), and only
134
+ * for that case: a deadline that refused the COMMIT BEFORE it was sent is a
135
+ * known outcome (not committed) and rethrows its own deadline error, even when
136
+ * the cleanup ROLLBACK failed (EPIC T). No adapter in this repository abandons
137
+ * a sent COMMIT — each checks the deadline before COMMIT is sent, or lets the
138
+ * server enforce it — so their lost-COMMIT errors are their own
139
+ * `transaction-outcome-unknown` errors.
130
140
  *
131
- * `cause` is the CAUSAL error (the deadline refusal), so the reason the
132
- * transaction was being abandoned survives. The rollback failure itself is
133
- * reported only as `meta.rollbackFailed`: a raw driver failure can carry
134
- * statement text, and this error is meant to be logged.
141
+ * `cause` is the CAUSAL error (the deadline refusal). What happened to the
142
+ * cleanup ROLLBACK and the connection is in `transactionOutcomeOf({ error })`, not
143
+ * in `meta`: a raw driver failure can carry statement text, and this error is
144
+ * meant to be logged.
135
145
  */
136
146
  export declare function transactionOutcomeUnknownError(params: {
137
147
  provider: string;