@vibeorm/runtime 2.6.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 +4086 -1295
  21. package/dist/index.js.map +40 -28
  22. package/dist/keyset-iterator.d.ts +12 -2
  23. package/dist/keyset.d.ts +65 -10
  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
@@ -62,10 +62,14 @@ async function runNestedSavepoint(params) {
62
62
  await drainDescendants({ node });
63
63
  assertNotPoisoned({ state: scope.state });
64
64
  if (execute !== undefined) {
65
+ const cleanup = params.cleanup ?? execute;
66
+ let cleanupStage = "rollback";
65
67
  try {
66
- await execute(`ROLLBACK TO SAVEPOINT ${node.name}`);
68
+ await cleanup(`ROLLBACK TO SAVEPOINT ${node.name}`);
69
+ cleanupStage = "release";
70
+ await cleanup(`RELEASE SAVEPOINT ${node.name}`);
67
71
  } catch (rollbackFailure) {
68
- const poisoned = savepointRollbackFailedError({ cause: error, rollbackFailure });
72
+ const poisoned = savepointRollbackFailedError({ cause: error, rollbackFailure, cleanupStage });
69
73
  scope.state.poisoned = poisoned;
70
74
  throw poisoned;
71
75
  }
@@ -85,14 +89,16 @@ function markSavepointOpened(params) {
85
89
  }
86
90
  function savepointRollbackFailedError(params) {
87
91
  const { cause, rollbackFailure } = params;
92
+ const releaseFailed = params.cleanupStage === "release";
88
93
  const rollbackErrorCode = rollbackFailure instanceof VibeError ? rollbackFailure.code : undefined;
89
94
  return new VibeError({
90
95
  code: "VIBE_TRANSACTION",
91
- message: "a nested transaction failed and the ROLLBACK TO SAVEPOINT that should have undone it failed too \u2014 " + "the savepoint stack no longer describes this connection, so the commit state of the whole transaction " + "is UNKNOWN and no further statement is accepted on any of its handles. The top-level transaction is " + "being rolled back; nothing is retried automatically.",
96
+ message: (releaseFailed ? "a nested transaction failed and RELEASE SAVEPOINT after its confirmed rollback failed too. " : "a nested transaction failed and ROLLBACK TO SAVEPOINT failed too. ") + "The savepoint stack no longer describes this connection, so the commit state of the whole transaction " + "is UNKNOWN and no further statement is accepted on any of its handles. The top-level transaction is " + "being rolled back; nothing is retried automatically.",
92
97
  meta: {
93
98
  reason: "savepoint-rollback-failed",
94
99
  outcome: "unknown",
95
- rollbackFailed: true,
100
+ rollbackFailed: !releaseFailed,
101
+ ...releaseFailed ? { cleanupStage: "release" } : {},
96
102
  ...rollbackErrorCode === undefined ? {} : { rollbackErrorCode }
97
103
  },
98
104
  cause
@@ -103,7 +109,7 @@ function isSavepointRollbackFailedError(error) {
103
109
  return reason === "savepoint-rollback-failed";
104
110
  }
105
111
  function transactionAbortedError(params) {
106
- const cause = params.cause;
112
+ const cause = mappedCauseOf({ error: params.cause }) ?? params.cause;
107
113
  const causeCode = cause instanceof VibeError ? cause.code : undefined;
108
114
  const sqlstate = cause instanceof VibeError && typeof cause.meta.sqlstate === "string" ? cause.meta.sqlstate : undefined;
109
115
  return new VibeError({
@@ -111,13 +117,23 @@ function transactionAbortedError(params) {
111
117
  message: "the transaction is aborted: a statement inside it failed and PostgreSQL discards every later statement and the COMMIT itself " + "(the server answers COMMIT with ROLLBACK and no error). Nothing from this transaction was committed. " + "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.",
112
118
  meta: {
113
119
  reason: "aborted",
114
- outcome: "rolled-back",
120
+ outcome: "not-committed",
115
121
  ...causeCode === undefined ? {} : { causeCode },
116
122
  ...sqlstate === undefined ? {} : { sqlstate }
117
123
  },
118
124
  ...cause === undefined ? {} : { cause }
119
125
  });
120
126
  }
127
+ var MAPPED_CAUSE = Symbol.for("vibeorm.adapter-kit.mapped-cause");
128
+ function recordMappedCause(params) {
129
+ Object.defineProperty(params.raw, MAPPED_CAUSE, { value: params.mapped, enumerable: false, configurable: true, writable: false });
130
+ }
131
+ function mappedCauseOf(params) {
132
+ if (!(params.error instanceof Error))
133
+ return;
134
+ const mapped = params.error[MAPPED_CAUSE];
135
+ return mapped instanceof VibeError ? mapped : undefined;
136
+ }
121
137
  function isTransactionAbortedError(error) {
122
138
  const reason = error?.meta?.reason;
123
139
  return reason === "aborted";
@@ -154,16 +170,50 @@ async function waitForTurn(params) {
154
170
  await open.settled;
155
171
  }
156
172
  }
173
+ var ADMISSIONS = new WeakMap;
157
174
  async function acquire(params) {
158
175
  const { scope } = params;
159
- for (;; ) {
160
- assertNotPoisoned({ state: scope.state });
161
- assertNotAborted({ state: scope.state });
162
- const open = scope.state.open;
163
- if (mayProceed({ scope, open }))
164
- return pushNode({ scope, parent: open });
165
- await open.settled;
176
+ assertNotPoisoned({ state: scope.state });
177
+ assertNotAborted({ state: scope.state });
178
+ const open = scope.state.open;
179
+ if (mayProceed({ scope, open }))
180
+ return pushNode({ scope, parent: open });
181
+ let blocker = open;
182
+ while (blocker.parent !== null && !mayProceed({ scope, open: blocker.parent })) {
183
+ blocker = blocker.parent;
184
+ }
185
+ return new Promise((resolve, reject) => {
186
+ const waiter = { scope, resolve, reject, next: null };
187
+ const queue = ADMISSIONS.get(blocker);
188
+ if (queue === undefined)
189
+ ADMISSIONS.set(blocker, { head: waiter, tail: waiter });
190
+ else {
191
+ queue.tail.next = waiter;
192
+ queue.tail = waiter;
193
+ }
194
+ });
195
+ }
196
+ function handOffAdmissions(params) {
197
+ const queue = ADMISSIONS.get(params.node);
198
+ if (queue === undefined)
199
+ return;
200
+ ADMISSIONS.delete(params.node);
201
+ const state = params.node.scope.state;
202
+ const refusal = state.poisoned ?? (state.aborted === null ? null : transactionAbortedError({ cause: state.aborted.cause }));
203
+ if (refusal !== null) {
204
+ let waiter = queue.head;
205
+ while (waiter !== null) {
206
+ waiter.reject(refusal);
207
+ waiter = waiter.next;
208
+ }
209
+ return;
166
210
  }
211
+ const first = queue.head;
212
+ const successor = pushNode({ scope: first.scope, parent: state.open });
213
+ if (first.next !== null)
214
+ ADMISSIONS.set(successor, { head: first.next, tail: queue.tail });
215
+ first.next = null;
216
+ first.resolve(successor);
167
217
  }
168
218
  function pushNode(params) {
169
219
  const { scope, parent } = params;
@@ -191,6 +241,7 @@ function closeNode(params) {
191
241
  if (state.open === node)
192
242
  state.open = node.parent;
193
243
  node.settle();
244
+ handOffAdmissions({ node });
194
245
  }
195
246
  async function drainDescendants(params) {
196
247
  const state = params.node.scope.state;
@@ -214,6 +265,8 @@ function refuseNestedTransactionOptions(params) {
214
265
  passed.push("timeout");
215
266
  if (options.deadline !== undefined)
216
267
  passed.push("deadline");
268
+ if (options.accessMode !== undefined)
269
+ passed.push("accessMode");
217
270
  if (passed.length === 0)
218
271
  return;
219
272
  const meta = { provider, nested: true };
@@ -223,12 +276,76 @@ function refuseNestedTransactionOptions(params) {
223
276
  meta.timeout = options.timeout;
224
277
  if (options.deadline !== undefined)
225
278
  meta.deadline = options.deadline;
279
+ if (options.accessMode !== undefined)
280
+ meta.accessMode = options.accessMode;
226
281
  throw new VibeError2({
227
282
  code: "VIBE_VALIDATION",
228
283
  message: `nested transactions run as savepoints and cannot honor ${passed.join(" or ")} \u2014 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`,
229
284
  meta
230
285
  });
231
286
  }
287
+ function readOnlyRequested(params) {
288
+ const accessMode = params.options?.accessMode;
289
+ if (accessMode === undefined)
290
+ return false;
291
+ if (accessMode === "readOnly")
292
+ return true;
293
+ throw new VibeError2({
294
+ code: "VIBE_VALIDATION",
295
+ message: `transaction accessMode must be "readOnly" or omitted, received ${JSON.stringify(accessMode) ?? String(accessMode)}`,
296
+ meta: { provider: params.provider, accessMode }
297
+ });
298
+ }
299
+ // packages/runtime/src/adapter-kit/deferred-control.ts
300
+ var SAVEPOINT_TEXT = /^SAVEPOINT (\S+)$/;
301
+ var RELEASE_TEXT = /^RELEASE SAVEPOINT (\S+)$/;
302
+ var ROLLBACK_TO_TEXT = /^ROLLBACK TO SAVEPOINT (\S+)$/;
303
+ function createDeferredControl(params) {
304
+ let pending = [...params.opening];
305
+ let opened = params.opening.length === 0;
306
+ const elided = new Set;
307
+ const dropFrom = (name) => {
308
+ const index = pending.indexOf(`SAVEPOINT ${name}`);
309
+ if (index === -1)
310
+ return false;
311
+ pending = pending.slice(0, index);
312
+ return true;
313
+ };
314
+ return {
315
+ opened: () => opened,
316
+ hasPending: () => pending.length > 0,
317
+ take: () => {
318
+ const taken = pending;
319
+ pending = [];
320
+ if (taken.length > 0)
321
+ opened = true;
322
+ return taken;
323
+ },
324
+ routeSavepoint: ({ text }) => {
325
+ const savepoint = SAVEPOINT_TEXT.exec(text);
326
+ if (savepoint !== null) {
327
+ pending.push(text);
328
+ return "deferred";
329
+ }
330
+ const release = RELEASE_TEXT.exec(text);
331
+ if (release !== null) {
332
+ const name = release[1];
333
+ if (elided.delete(name))
334
+ return "elided";
335
+ return dropFrom(name) ? "elided" : "send";
336
+ }
337
+ const rollbackTo = ROLLBACK_TO_TEXT.exec(text);
338
+ if (rollbackTo !== null) {
339
+ const name = rollbackTo[1];
340
+ if (!dropFrom(name))
341
+ return "send";
342
+ elided.add(name);
343
+ return "elided";
344
+ }
345
+ return "send";
346
+ }
347
+ };
348
+ }
232
349
  // packages/runtime/src/adapter-kit/transaction-budget.ts
233
350
  import { VibeError as VibeError3 } from "@vibeorm/schema";
234
351
  var DEFAULT_DEADLINE_CLOCK = () => Date.now();
@@ -313,7 +430,7 @@ function engineStatementBudgetMs(params) {
313
430
  }
314
431
  function transactionDeadlineError(params) {
315
432
  const { provider, stage, totalMs, overdueMs } = params;
316
- const what = stage === "commit" ? "the transaction was rolled back instead of committed" : "the statement was never sent and the transaction is being rolled back";
433
+ const what = stage === "commit" ? "COMMIT was never sent, so the transaction did not commit" : "the statement was never sent, and the transaction will not commit";
317
434
  return new VibeError3({
318
435
  code: "VIBE_TRANSACTION",
319
436
  message: `transaction deadline of ${totalMs} ms expired ${Math.max(0, Math.round(overdueMs))} ms ago \u2014 ${what}. ` + "Nothing is retried automatically: work the callback did outside the database may already have happened.",
@@ -332,13 +449,13 @@ function transactionOutcomeUnknownError(params) {
332
449
  const { provider, totalMs, cause } = params;
333
450
  return new VibeError3({
334
451
  code: "VIBE_TRANSACTION",
335
- message: `transaction deadline of ${totalMs} ms expired and the rollback that should have cleaned up failed \u2014 ` + "the commit state of this transaction is UNKNOWN. It is not retried automatically; inspect the data " + "before deciding.",
452
+ message: `transaction deadline of ${totalMs} ms expired while COMMIT was in flight and the client stopped waiting for its answer \u2014 ` + "the commit state of this transaction is UNKNOWN. It is not retried automatically; inspect the data " + "before deciding.",
336
453
  meta: {
337
454
  provider,
338
455
  reason: "transaction-outcome-unknown",
339
456
  outcome: "unknown",
340
- totalMs,
341
- rollbackFailed: true
457
+ stage: "commit",
458
+ totalMs
342
459
  },
343
460
  cause
344
461
  });
@@ -347,15 +464,87 @@ function isTransactionDeadlineError(error) {
347
464
  const reason = error?.meta?.reason;
348
465
  return reason === "transaction-deadline";
349
466
  }
467
+ // packages/runtime/src/adapter-kit/transaction-outcome.ts
468
+ var REPORT_VERSION = 1;
469
+ var REGISTRY_KEY = Symbol.for("vibeorm.adapter-kit.transaction-outcome");
470
+ function sharedRegistry() {
471
+ const existing = globalThis[REGISTRY_KEY];
472
+ if (existing instanceof WeakMap)
473
+ return existing;
474
+ const created = new WeakMap;
475
+ if (!Object.isExtensible(globalThis))
476
+ return created;
477
+ Object.defineProperty(globalThis, REGISTRY_KEY, { value: created, enumerable: false, configurable: false, writable: false });
478
+ return created;
479
+ }
480
+ var REPORTS = sharedRegistry();
481
+ function isReportable(value) {
482
+ return typeof value === "object" && value !== null || typeof value === "function";
483
+ }
484
+ function recordTransactionOutcome(params) {
485
+ const { error, report } = params;
486
+ if (!isReportable(error))
487
+ return;
488
+ REPORTS.set(error, Object.freeze({ version: REPORT_VERSION, report: Object.freeze({ ...report }) }));
489
+ }
490
+ function transactionOutcomeOf(params) {
491
+ const { error } = params;
492
+ if (!isReportable(error))
493
+ return;
494
+ const stored = REPORTS.get(error);
495
+ return stored?.version === REPORT_VERSION ? stored.report : undefined;
496
+ }
497
+ function failedCommitOutcome(params) {
498
+ const { commit, stateLost } = params;
499
+ if (commit === "sent" || commit === "unanswered")
500
+ return "unknown";
501
+ return stateLost ? "unknown" : "not-committed";
502
+ }
503
+ function closeFailedTransactionBudget(params) {
504
+ const { error, budget, scope, commit } = params;
505
+ const stateLost = isSavepointRollbackFailedError(error) || isSavepointRollbackFailedError(scope.state.poisoned);
506
+ const outcome = failedCommitOutcome({ commit, stateLost });
507
+ budget.close({ outcome });
508
+ return outcome;
509
+ }
510
+ function settleFailedTransaction(params) {
511
+ const { error, provider, budget, scope, commit, rollback, connection } = params;
512
+ const outcome = closeFailedTransactionBudget({ error, budget, scope, commit });
513
+ const abandoned = commit === "unanswered" && budget.totalMs !== null && isTransactionDeadlineError(error);
514
+ const thrown = abandoned ? transactionOutcomeUnknownError({ provider, totalMs: budget.totalMs, cause: error }) : error;
515
+ recordTransactionOutcome({
516
+ error: thrown,
517
+ report: { commit: outcome, commitSent: commit !== "not-sent", rollback, connection }
518
+ });
519
+ return thrown;
520
+ }
350
521
  // packages/runtime/src/adapter-kit/row-changes.ts
351
522
  function statementRowChanges(params) {
352
- const { effect, count } = params;
523
+ const { effect } = params;
353
524
  if (effect === "read")
354
525
  return 0;
355
- if (effect !== "write")
526
+ if (effect === "writeTally")
527
+ return tallyOf({ rows: params.resultRows });
528
+ const count = effect === "write" ? params.count : effect === "writeRows" ? params.rows : undefined;
529
+ if (effect !== "write" && effect !== "writeRows")
356
530
  return "unknown";
357
531
  return typeof count === "number" && Number.isSafeInteger(count) && count >= 0 ? count : "unknown";
358
532
  }
533
+ var ROW_CHANGES_COLUMN = "__vibe_row_changes";
534
+ function tallyOf(params) {
535
+ const { rows } = params;
536
+ if (rows === undefined || rows.length === 0)
537
+ return "unknown";
538
+ let total = 0;
539
+ for (const row of rows) {
540
+ const value = row[ROW_CHANGES_COLUMN];
541
+ const count = typeof value === "number" ? value : typeof value === "bigint" ? Number(value) : typeof value === "string" && /^\d+$/.test(value) ? Number(value) : Number.NaN;
542
+ if (!Number.isSafeInteger(count) || count < 0)
543
+ return "unknown";
544
+ total += count;
545
+ }
546
+ return Number.isSafeInteger(total) ? total : "unknown";
547
+ }
359
548
  function observeRowChanges(params) {
360
549
  const state = params.scope.state;
361
550
  if (state.rowChanges === "unknown")
@@ -369,7 +558,7 @@ function observeRowChanges(params) {
369
558
  }
370
559
  function dispatchSynchronousRowChanges(params) {
371
560
  const { scope } = params;
372
- if (scope === undefined)
561
+ if (scope === undefined || scope.state.rowChanges === "unknown")
373
562
  return params.run();
374
563
  const before = scope.state.rowChanges;
375
564
  if (params.effect !== "read")
@@ -448,12 +637,105 @@ function withCleanupCause(params) {
448
637
  }
449
638
  return cause;
450
639
  }
451
- // packages/runtime/src/adapter-kit/sqlite-session.ts
640
+ // packages/runtime/src/adapter-kit/adapter-lifecycle.ts
641
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
452
642
  import { VibeError as VibeError5 } from "@vibeorm/schema";
643
+ function adapterClosedError(params) {
644
+ const { driver, state } = params;
645
+ return new VibeError5({
646
+ code: "VIBE_ADAPTER_CLOSED",
647
+ message: `This ${driver} adapter was disconnected${state === "closing" ? " and is closing" : ""}; it accepts no new work. Create a new adapter to connect again.`,
648
+ meta: { driver, state }
649
+ });
650
+ }
651
+ function disconnectInActiveCallbackError(params) {
652
+ return new VibeError5({
653
+ code: "VIBE_TRANSACTION",
654
+ message: "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.",
655
+ meta: { reason: "disconnect-in-active-callback", driver: params.driver }
656
+ });
657
+ }
658
+ function transactionLifecycleRefusal(params) {
659
+ const { method } = params;
660
+ return new VibeError5({
661
+ code: "VIBE_VALIDATION",
662
+ message: `${method}() is not available on a transaction client \u2014 the connection is owned by the open transaction; call it on the client that started the transaction`,
663
+ meta: { method, inTransaction: true }
664
+ });
665
+ }
666
+ function createAdapterLifecycleGate(params) {
667
+ const { driver, cleanup, isConnectionReentrant } = params;
668
+ const callbacks = new AsyncLocalStorage2;
669
+ let state = "open";
670
+ let active = 0;
671
+ let drained = null;
672
+ let completion = null;
673
+ const settleOne = () => {
674
+ active -= 1;
675
+ if (active === 0 && drained !== null) {
676
+ const resolve = drained;
677
+ drained = null;
678
+ resolve();
679
+ }
680
+ };
681
+ return {
682
+ admit(admitParams) {
683
+ if (state !== "open")
684
+ return Promise.reject(adapterClosedError({ driver, state }));
685
+ active += 1;
686
+ const result = new Promise((resolve) => {
687
+ resolve(admitParams.run());
688
+ });
689
+ result.then(settleOne, settleOne);
690
+ return result;
691
+ },
692
+ inCallback(callbackParams) {
693
+ const token = { active: true };
694
+ return callbacks.run(token, () => new Promise((resolve) => {
695
+ resolve(callbackParams.run());
696
+ })).finally(() => {
697
+ token.active = false;
698
+ });
699
+ },
700
+ disconnect() {
701
+ if (callbacks.getStore()?.active === true || isConnectionReentrant?.() === true) {
702
+ return Promise.reject(disconnectInActiveCallbackError({ driver }));
703
+ }
704
+ if (completion !== null)
705
+ return completion;
706
+ state = "closing";
707
+ const drain = active === 0 ? Promise.resolve() : new Promise((resolve) => {
708
+ drained = resolve;
709
+ });
710
+ completion = drain.then(() => cleanup()).then(() => {
711
+ state = "closed";
712
+ }, (error) => {
713
+ state = "closed";
714
+ throw error;
715
+ });
716
+ return completion;
717
+ }
718
+ };
719
+ }
720
+ function runShutdownCleanup(params) {
721
+ let failure;
722
+ let chain = Promise.resolve();
723
+ for (const step of params.steps) {
724
+ chain = chain.then(step).then(undefined, (error) => {
725
+ failure = failure === undefined ? { error } : { error: withCleanupCause({ cause: failure.error, cleanupCause: error }) };
726
+ });
727
+ }
728
+ return chain.then(() => {
729
+ if (failure !== undefined)
730
+ throw failure.error;
731
+ });
732
+ }
733
+ // packages/runtime/src/adapter-kit/sqlite-session.ts
734
+ import { VibeError as VibeError6 } from "@vibeorm/schema";
453
735
  import { SQLITE_SESSION_SQL } from "@vibeorm/sql";
454
736
  async function runSqliteSession(params) {
455
737
  if (params.inTransaction())
456
- throw new VibeError5({
738
+ throw new VibeError6({
457
739
  code: "VIBE_TRANSACTION",
458
740
  message: "A migration session cannot borrow a SQLite connection with an open transaction.",
459
741
  meta: { reason: "session-in-transaction" }
@@ -461,7 +743,7 @@ async function runSqliteSession(params) {
461
743
  const rows = await params.execute({ text: SQLITE_SESSION_SQL.lockingMode, values: [] });
462
744
  const mode = rows[0]?.locking_mode;
463
745
  if (mode !== "normal" && mode !== "exclusive")
464
- throw new VibeError5({
746
+ throw new VibeError6({
465
747
  code: "VIBE_ADAPTER",
466
748
  message: "SQLite did not report its locking mode; no migration was started.",
467
749
  meta: { reason: "session-lock-mode" }
@@ -500,11 +782,16 @@ async function runSqliteSession(params) {
500
782
  }
501
783
  export {
502
784
  DEFAULT_DEADLINE_CLOCK,
785
+ ROW_CHANGES_COLUMN,
503
786
  abortTransactionOnServerFailure,
787
+ closeFailedTransactionBudget,
788
+ createAdapterLifecycleGate,
789
+ createDeferredControl,
504
790
  createSavepointCounter,
505
791
  createSavepointScope,
506
792
  dispatchSynchronousRowChanges,
507
793
  engineStatementBudgetMs,
794
+ failedCommitOutcome,
508
795
  isSavepointRollbackFailedError,
509
796
  isTransactionAbortedError,
510
797
  isTransactionDeadlineError,
@@ -512,21 +799,27 @@ export {
512
799
  markTransactionAborted,
513
800
  nextSavepointName,
514
801
  observeRowChanges,
802
+ readOnlyRequested,
515
803
  readRowChanges,
804
+ recordTransactionOutcome,
516
805
  refuseNestedTransactionOptions,
517
806
  runNestedSavepoint,
518
807
  runPinnedSession,
519
808
  runRootScope,
809
+ runShutdownCleanup,
520
810
  runSqliteSession,
521
811
  savepointRollbackFailedError,
522
812
  scopeTurn,
813
+ settleFailedTransaction,
523
814
  startTransactionBudget,
524
815
  statementRowChanges,
525
816
  transactionAbortedError,
526
817
  transactionClosedError,
527
818
  transactionDeadlineError,
819
+ transactionLifecycleRefusal,
820
+ transactionOutcomeOf,
528
821
  transactionOutcomeUnknownError,
529
822
  validateTransactionDeadline
530
823
  };
531
824
 
532
- //# debugId=9043FC0FD9D8EA9E64756E2164756E21
825
+ //# debugId=DA2DF3165F53603864756E2164756E21