@vibeorm/adapter-sqlite 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +149 -38
- package/dist/index.js.map +7 -6
- package/dist/prepared-sql.d.ts +13 -0
- package/dist/prepared-sql.d.ts.map +1 -0
- package/dist/queue.d.ts +10 -0
- package/dist/queue.d.ts.map +1 -1
- package/dist/transaction-options.d.ts +1 -13
- package/dist/transaction-options.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -68,7 +68,10 @@ export type SqliteAdapterOptions = {
|
|
|
68
68
|
* changes its journal mode, and still applies `PRAGMA foreign_keys = ON`
|
|
69
69
|
* (the ORM requires it). For lossless >2^53 BigInt reads the adapter sets
|
|
70
70
|
* statement-level safeIntegers on every statement it prepares, so an
|
|
71
|
-
* injected database needs no special construction flags.
|
|
71
|
+
* injected database needs no special construction flags. Wrappers sharing
|
|
72
|
+
* the same Database also share transaction exclusion. Initialization refuses
|
|
73
|
+
* if foreign keys remain OFF (for example, inside the owner's transaction);
|
|
74
|
+
* retry after that transaction ends. FK-ON active handles remain supported.
|
|
72
75
|
*/
|
|
73
76
|
readonly database?: Database;
|
|
74
77
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,OAAO,KAAK,EAEV,eAAe,EAIhB,MAAM,kBAAkB,CAAC;AAsB1B,kHAAkH;AAClH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B,CAAC;AAkEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,eAAe,CAsV7E;AAID,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,SAAS,EACT,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACzF,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEtG,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,8BAA8B,EAC9B,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/adapter-sqlite/src/index.ts
|
|
3
3
|
import { Database } from "bun:sqlite";
|
|
4
|
-
import {
|
|
5
|
-
import { VibeError as VibeError3, internalError } from "@vibeorm/schema";
|
|
4
|
+
import { VibeError as VibeError4, internalError } from "@vibeorm/schema";
|
|
6
5
|
import {
|
|
6
|
+
runSqliteSession,
|
|
7
7
|
createSavepointScope,
|
|
8
8
|
isTransactionDeadlineError,
|
|
9
9
|
runNestedSavepoint,
|
|
@@ -112,7 +112,121 @@ function normalizeRows(params) {
|
|
|
112
112
|
return params.rows;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
// packages/adapter-sqlite/src/prepared-sql.ts
|
|
116
|
+
import { VibeError as VibeError2 } from "@vibeorm/schema";
|
|
117
|
+
var SPACE = /[\t\n\v\f\r ]/;
|
|
118
|
+
var IDENTIFIER = /[A-Za-z0-9_$\u0080-\uffff]/;
|
|
119
|
+
function commentEnd(params) {
|
|
120
|
+
const { text, offset } = params;
|
|
121
|
+
if (text.startsWith("--", offset)) {
|
|
122
|
+
const end = text.indexOf(`
|
|
123
|
+
`, offset + 2);
|
|
124
|
+
return end < 0 ? text.length : end + 1;
|
|
125
|
+
}
|
|
126
|
+
if (text.startsWith("/*", offset)) {
|
|
127
|
+
const end = text.indexOf("*/", offset + 2);
|
|
128
|
+
return end < 0 ? text.length : end + 2;
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
function terminators(params) {
|
|
133
|
+
const { text } = params;
|
|
134
|
+
const offsets = [];
|
|
135
|
+
for (let i = 0;i < text.length; ) {
|
|
136
|
+
const end = commentEnd({ text, offset: i });
|
|
137
|
+
if (end !== undefined) {
|
|
138
|
+
i = end;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const char = text[i];
|
|
142
|
+
if (char === "'" || char === '"' || char === "`" || char === "[") {
|
|
143
|
+
const quote = char === "[" ? "]" : char;
|
|
144
|
+
i++;
|
|
145
|
+
while (i < text.length) {
|
|
146
|
+
if (text[i++] !== quote)
|
|
147
|
+
continue;
|
|
148
|
+
if (quote !== "]" && text[i] === quote) {
|
|
149
|
+
i++;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (char === "$" || char === ":" || char === "@" || char === "#") {
|
|
157
|
+
i++;
|
|
158
|
+
while (i < text.length) {
|
|
159
|
+
if (IDENTIFIER.test(text[i])) {
|
|
160
|
+
i++;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (text.startsWith("::", i)) {
|
|
164
|
+
i += 2;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (text[i] === "(") {
|
|
168
|
+
i++;
|
|
169
|
+
while (i < text.length && text[i] !== ")" && !SPACE.test(text[i]))
|
|
170
|
+
i++;
|
|
171
|
+
if (text[i] === ")")
|
|
172
|
+
i++;
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (IDENTIFIER.test(char)) {
|
|
179
|
+
while (i < text.length && IDENTIFIER.test(text[i]))
|
|
180
|
+
i++;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (char === ";")
|
|
184
|
+
offsets.push(i);
|
|
185
|
+
i++;
|
|
186
|
+
}
|
|
187
|
+
return offsets;
|
|
188
|
+
}
|
|
189
|
+
function assertSinglePreparedStatement(params) {
|
|
190
|
+
const { text, expanded } = params;
|
|
191
|
+
if (text.includes("\x00"))
|
|
192
|
+
throw preparedTailError();
|
|
193
|
+
const count = terminators({ text: expanded }).length;
|
|
194
|
+
if (count === 0)
|
|
195
|
+
return;
|
|
196
|
+
const boundary = terminators({ text })[count - 1];
|
|
197
|
+
if (boundary === undefined)
|
|
198
|
+
throw preparedTailError();
|
|
199
|
+
for (let i = boundary + 1;i < text.length; ) {
|
|
200
|
+
if (SPACE.test(text[i]) || text[i] === ";") {
|
|
201
|
+
i++;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const end = commentEnd({ text, offset: i });
|
|
205
|
+
if (end === undefined)
|
|
206
|
+
throw preparedTailError();
|
|
207
|
+
i = end;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function preparedTailError() {
|
|
211
|
+
return new VibeError2({
|
|
212
|
+
code: "VIBE_ADAPTER",
|
|
213
|
+
message: "Prepared SQLite SQL must contain one statement; omit values only when intentionally executing a script",
|
|
214
|
+
meta: { provider: "sqlite", reason: "prepared-statement-tail" }
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
115
218
|
// packages/adapter-sqlite/src/queue.ts
|
|
219
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
220
|
+
var INJECTED_OWNERSHIP = new WeakMap;
|
|
221
|
+
function connectionOwnership(params) {
|
|
222
|
+
const existing = params.database === undefined ? undefined : INJECTED_OWNERSHIP.get(params.database);
|
|
223
|
+
if (existing !== undefined)
|
|
224
|
+
return existing;
|
|
225
|
+
const ownership = { queue: createOperationQueue(), txContext: new AsyncLocalStorage };
|
|
226
|
+
if (params.database !== undefined)
|
|
227
|
+
INJECTED_OWNERSHIP.set(params.database, ownership);
|
|
228
|
+
return ownership;
|
|
229
|
+
}
|
|
116
230
|
function createOperationQueue() {
|
|
117
231
|
let tail = Promise.resolve();
|
|
118
232
|
return {
|
|
@@ -129,52 +243,27 @@ function createOperationQueue() {
|
|
|
129
243
|
}
|
|
130
244
|
|
|
131
245
|
// packages/adapter-sqlite/src/transaction-options.ts
|
|
132
|
-
import { VibeError as
|
|
246
|
+
import { VibeError as VibeError3 } from "@vibeorm/schema";
|
|
247
|
+
import { refuseNestedTransactionOptions } from "@vibeorm/runtime/adapter-kit";
|
|
133
248
|
function validateTransactionOptions(params) {
|
|
134
249
|
const { options } = params;
|
|
135
250
|
if (options === undefined)
|
|
136
251
|
return;
|
|
137
252
|
if (options.isolationLevel !== undefined && options.isolationLevel !== "Serializable") {
|
|
138
|
-
throw new
|
|
253
|
+
throw new VibeError3({
|
|
139
254
|
code: "VIBE_VALIDATION",
|
|
140
255
|
message: `sqlite transactions are always serializable \u2014 isolationLevel "${options.isolationLevel}" cannot be honored; pass "Serializable" or omit the option`,
|
|
141
256
|
meta: { dialect: "sqlite", isolationLevel: options.isolationLevel }
|
|
142
257
|
});
|
|
143
258
|
}
|
|
144
259
|
if (options.timeout !== undefined) {
|
|
145
|
-
throw new
|
|
260
|
+
throw new VibeError3({
|
|
146
261
|
code: "VIBE_VALIDATION",
|
|
147
262
|
message: "sqlite has no per-statement timeout, so a transaction `timeout` cannot be enforced database-side (busy_timeout only bounds lock acquisition, not statement runtime) \u2014 remove the option",
|
|
148
263
|
meta: { dialect: "sqlite", timeout: options.timeout }
|
|
149
264
|
});
|
|
150
265
|
}
|
|
151
266
|
}
|
|
152
|
-
function refuseNestedTransactionOptions(params) {
|
|
153
|
-
const { options, provider } = params;
|
|
154
|
-
if (options === undefined)
|
|
155
|
-
return;
|
|
156
|
-
const passed = [];
|
|
157
|
-
if (options.isolationLevel !== undefined)
|
|
158
|
-
passed.push("isolationLevel");
|
|
159
|
-
if (options.timeout !== undefined)
|
|
160
|
-
passed.push("timeout");
|
|
161
|
-
if (options.deadline !== undefined)
|
|
162
|
-
passed.push("deadline");
|
|
163
|
-
if (passed.length === 0)
|
|
164
|
-
return;
|
|
165
|
-
const meta = { provider, nested: true };
|
|
166
|
-
if (options.isolationLevel !== undefined)
|
|
167
|
-
meta.isolationLevel = options.isolationLevel;
|
|
168
|
-
if (options.timeout !== undefined)
|
|
169
|
-
meta.timeout = options.timeout;
|
|
170
|
-
if (options.deadline !== undefined)
|
|
171
|
-
meta.deadline = options.deadline;
|
|
172
|
-
throw new VibeError2({
|
|
173
|
-
code: "VIBE_VALIDATION",
|
|
174
|
-
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`,
|
|
175
|
-
meta
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
267
|
|
|
179
268
|
// packages/adapter-sqlite/src/index.ts
|
|
180
269
|
import { createSavepointCounter, nextSavepointName } from "@vibeorm/runtime/adapter-kit";
|
|
@@ -210,19 +299,18 @@ function withSafeIntegers(statement) {
|
|
|
210
299
|
function sqliteAdapter(options) {
|
|
211
300
|
const busyTimeoutMs = options?.busyTimeoutMs;
|
|
212
301
|
if (busyTimeoutMs !== undefined && (!Number.isInteger(busyTimeoutMs) || busyTimeoutMs < 0)) {
|
|
213
|
-
throw new
|
|
302
|
+
throw new VibeError4({
|
|
214
303
|
code: "VIBE_VALIDATION",
|
|
215
304
|
message: `busyTimeoutMs must be a non-negative integer of milliseconds, received ${String(busyTimeoutMs)}`,
|
|
216
305
|
meta: { busyTimeoutMs }
|
|
217
306
|
});
|
|
218
307
|
}
|
|
219
|
-
const queue =
|
|
308
|
+
const { queue, txContext } = connectionOwnership({ database: options?.database });
|
|
220
309
|
const ownsDatabase = options?.database === undefined;
|
|
221
310
|
const filename = options?.filename ?? ":memory:";
|
|
222
|
-
const txContext = new AsyncLocalStorage;
|
|
223
311
|
function assertNotInsideTransaction() {
|
|
224
312
|
if (txContext.getStore() === true) {
|
|
225
|
-
throw new
|
|
313
|
+
throw new VibeError4({
|
|
226
314
|
code: "VIBE_TRANSACTION",
|
|
227
315
|
message: "root client used inside a transaction callback \u2014 use the tx client the callback receives; the root connection would deadlock behind the open transaction",
|
|
228
316
|
meta: { provider: PROVIDER }
|
|
@@ -234,6 +322,14 @@ function sqliteAdapter(options) {
|
|
|
234
322
|
function applyPragmas(params) {
|
|
235
323
|
const { db } = params;
|
|
236
324
|
db.run("PRAGMA foreign_keys = ON");
|
|
325
|
+
const foreignKeys = db.query("PRAGMA foreign_keys").get();
|
|
326
|
+
if (foreignKeys.foreign_keys !== 1 && foreignKeys.foreign_keys !== 1n) {
|
|
327
|
+
throw new VibeError4({
|
|
328
|
+
code: "VIBE_ADAPTER",
|
|
329
|
+
message: "SQLite foreign-key enforcement is disabled; finish the injected database transaction before connecting",
|
|
330
|
+
meta: { provider: PROVIDER, reason: "foreign-keys-disabled" }
|
|
331
|
+
});
|
|
332
|
+
}
|
|
237
333
|
if (ownsDatabase || busyTimeoutMs !== undefined) {
|
|
238
334
|
db.run(`PRAGMA busy_timeout = ${busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS}`);
|
|
239
335
|
}
|
|
@@ -268,6 +364,7 @@ function sqliteAdapter(options) {
|
|
|
268
364
|
}
|
|
269
365
|
const statement = withSafeIntegers(db.prepare(text));
|
|
270
366
|
try {
|
|
367
|
+
assertSinglePreparedStatement({ text, expanded: statement.toString() });
|
|
271
368
|
const bound = asBindings(serializeParamsRaw({ values }));
|
|
272
369
|
if (statement.columnNames.length > 0) {
|
|
273
370
|
const rows = statement.all(...bound);
|
|
@@ -328,6 +425,17 @@ function sqliteAdapter(options) {
|
|
|
328
425
|
provider: PROVIDER,
|
|
329
426
|
wire: WIRE,
|
|
330
427
|
budgets: BUDGETS,
|
|
428
|
+
async withSession({ run }) {
|
|
429
|
+
assertNotInsideTransaction();
|
|
430
|
+
return queue.run(async () => {
|
|
431
|
+
const db = getDatabase();
|
|
432
|
+
return txContext.run(true, () => runSqliteSession({
|
|
433
|
+
run,
|
|
434
|
+
execute: async (query) => runExecuteUnsafe({ db, ...query }).rows,
|
|
435
|
+
inTransaction: () => db.inTransaction
|
|
436
|
+
}));
|
|
437
|
+
});
|
|
438
|
+
},
|
|
331
439
|
async execute(params) {
|
|
332
440
|
assertNotInsideTransaction();
|
|
333
441
|
return queue.run(async () => runExecute({ db: getDatabase(), ...params }));
|
|
@@ -358,7 +466,7 @@ function sqliteAdapter(options) {
|
|
|
358
466
|
} catch (error) {
|
|
359
467
|
try {
|
|
360
468
|
db.run("ROLLBACK");
|
|
361
|
-
budget.close({ outcome: "rolled-back" });
|
|
469
|
+
budget.close({ outcome: scope.state.poisoned === null ? "rolled-back" : "unknown" });
|
|
362
470
|
} catch {
|
|
363
471
|
budget.close({ outcome: "unknown" });
|
|
364
472
|
if (budget.totalMs !== null && isTransactionDeadlineError(error)) {
|
|
@@ -374,7 +482,10 @@ function sqliteAdapter(options) {
|
|
|
374
482
|
});
|
|
375
483
|
},
|
|
376
484
|
async connect() {
|
|
377
|
-
|
|
485
|
+
assertNotInsideTransaction();
|
|
486
|
+
await queue.run(async () => {
|
|
487
|
+
getDatabase();
|
|
488
|
+
});
|
|
378
489
|
},
|
|
379
490
|
async disconnect() {
|
|
380
491
|
assertNotInsideTransaction();
|
|
@@ -419,4 +530,4 @@ export {
|
|
|
419
530
|
DEFAULT_DEADLINE_CLOCK
|
|
420
531
|
};
|
|
421
532
|
|
|
422
|
-
//# debugId=
|
|
533
|
+
//# debugId=FA4A641AD356B7F564756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../src/errors.ts", "../src/params.ts", "../src/queue.ts", "../src/transaction-options.ts"],
|
|
3
|
+
"sources": ["../src/index.ts", "../src/errors.ts", "../src/params.ts", "../src/prepared-sql.ts", "../src/queue.ts", "../src/transaction-options.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * @vibeorm/adapter-sqlite — bun:sqlite (embedded SQLite) adapter for\n * VibeORM v2.\n *\n * bun:sqlite is a *synchronous* single-connection driver, so every call\n * completes without I/O waits and the adapter wraps results in\n * already-resolved promises — the cheapest possible `execute`. Like PGlite,\n * one connection means every operation runs through one serial queue:\n * a whole `transaction()` holds the queue until it commits or rolls back, so\n * concurrent client calls can never interleave into an open transaction.\n *\n * INTEGER WIDTH (the BigInt story): SQLite INTEGER columns are 64-bit, but JS\n * numbers are only exact to ±(2^53−1) — a plain read of a large BigInt column\n * silently corrupts (pinned on Bun 1.3.14: `SELECT 9007199254740993` returns\n * `9007199254740992` without safeIntegers). The adapter therefore ALWAYS reads\n * through bun:sqlite's `safeIntegers` (database-level for connections it\n * opens, statement-level `stmt.safeIntegers(true)` for every statement it\n * prepares, which also covers injected databases), then normalizes rows:\n * bigints inside the safe range become `number`, larger ones stay `bigint`.\n * That is exactly the shape the runtime's `SQLITE_CODECS` expect — Int and\n * Boolean columns arrive as numbers, and >2^53 BigInt columns round-trip\n * losslessly as bigint. See params.ts for the full reasoning.\n *\n * PRAGMAS applied on open (each documented on {@link SqliteAdapterOptions}):\n * `foreign_keys = ON` (mandatory — SQLite defaults OFF and the ORM's FK\n * semantics depend on it), `busy_timeout` (lock-wait bound), and\n * `journal_mode = WAL` for file databases (readers no longer block the\n * writer). Transactions open with `BEGIN IMMEDIATE`: the write lock is taken\n * up front, so a write after a read inside the transaction can never hit the\n * SQLITE_BUSY deadlock that lock *upgrades* are prone to.\n */\n\nimport { Database } from \"bun:sqlite\";\nimport type { SQLQueryBindings } from \"bun:sqlite\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { VibeError, internalError } from \"@vibeorm/schema\";\nimport type { Dialect, Provider } from \"@vibeorm/schema\";\nimport type {\n AdapterBudgetSupport,\n DatabaseAdapter,\n QueryResult,\n TransactionOptions,\n WireFidelity,\n} from \"@vibeorm/runtime\";\nimport {\n createSavepointScope,\n isTransactionDeadlineError,\n runNestedSavepoint,\n runRootScope,\n type SavepointScope,\n scopeTurn,\n startTransactionBudget,\n type TransactionBudget,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nimport { mapSqliteDriverError, runMapped } from \"./errors.ts\";\nimport { normalizeRows, serializeParamsRaw } from \"./params.ts\";\nimport { createOperationQueue } from \"./queue.ts\";\nimport { refuseNestedTransactionOptions, validateTransactionOptions } from \"./transaction-options.ts\";\n\n// ─── Options ──────────────────────────────────────────────────────\n\n/** Options for {@link sqliteAdapter}. (Factories are the documented exception allowed a plain options object.) */\nexport type SqliteAdapterOptions = {\n /**\n * Database file to open. Defaults to `\":memory:\"` — a fresh private\n * in-memory database, the usual choice for tests. Ignored when `database`\n * is injected.\n */\n readonly filename?: string;\n /**\n * Open the file read-only (`SQLITE_READONLY` errors on writes, mapped to\n * `VIBE_ADAPTER`). The WAL pragma is skipped on read-only connections —\n * switching journal modes is a write. Ignored when `database` is injected.\n */\n readonly readonly?: boolean;\n /**\n * `PRAGMA busy_timeout` in milliseconds — how long a statement blocks on a\n * competing lock before failing with SQLITE_BUSY (mapped to\n * `VIBE_TRANSACTION`, `meta.reason: \"busy\"`). Default 5000. On an injected\n * `database` the pragma is applied only when this option is passed\n * explicitly, so the adapter never silently overrides the owner's setting.\n */\n readonly busyTimeoutMs?: number;\n /**\n * Switch file databases to `PRAGMA journal_mode = WAL` on open (default\n * true): readers stop blocking the writer, the sane default for anything\n * long-lived. Skipped for `\":memory:\"` databases (they have no WAL),\n * read-only connections, and injected `database` instances (the owner\n * decides their journal mode).\n */\n readonly wal?: boolean;\n /**\n * An already-open `bun:sqlite` Database to run on — sharing one in-memory\n * database across adapters makes multi-adapter tests trivial. The adapter\n * never closes an injected instance (`disconnect()` is a no-op), never\n * changes its journal mode, and still applies `PRAGMA foreign_keys = ON`\n * (the ORM requires it). For lossless >2^53 BigInt reads the adapter sets\n * statement-level safeIntegers on every statement it prepares, so an\n * injected database needs no special construction flags.\n */\n readonly database?: Database;\n};\n\n// ─── Internals ────────────────────────────────────────────────────\n\nconst DIALECT: Dialect = \"sqlite\";\nconst PROVIDER: Provider = \"sqlite\";\n\n/**\n * bun:sqlite wire (board #30, live-verified): INTEGER/REAL → numbers (large\n * INTEGER → native `bigint`, which every decoder passes through); DateTime and\n * Json ride TEXT, so their decoders do real work and are declared \"text\"\n * (prunes nothing — the declaration is the honest record).\n */\nconst WIRE: WireFidelity = Object.freeze({ dateTime: \"text\", json: \"text\", numbers: \"native\" } as const);\n\n/**\n * Timing budgets this adapter genuinely enforces (EPIC 6).\n *\n * - `acquireTimeout: false` — bun:sqlite is ONE synchronous connection behind\n * an in-process queue. There is no pool to exhaust and no wait to bound.\n * - `statementTimeout: \"unsupported\"` — sqlite has no per-statement timeout;\n * `busy_timeout` bounds LOCK acquisition only, which is why the `timeout`\n * option is already refused outright (./transaction-options.ts).\n * - `transactionDeadline: \"between-statements\"` — an expired budget stops the\n * next statement and the commit, which is real enforcement. It is NOT\n * cancellation: bun:sqlite runs statements synchronously on the JS thread, so\n * a long statement blocks the event loop and no timer of any kind can fire\n * while it runs. Asking for `\"cancel-running-statements\"` is refused.\n */\nconst BUDGETS: AdapterBudgetSupport = Object.freeze({\n acquireTimeout: false,\n statementTimeout: \"unsupported\",\n transactionDeadline: \"between-statements\",\n} as const);\nconst DEFAULT_BUSY_TIMEOUT_MS = 5000;\n\n/** `\":memory:\"` (also in URI form) and `\"\"` (anonymous temp) have no WAL. */\nfunction isMemoryFilename(params: { filename: string }): boolean {\n return params.filename === \"\" || params.filename.includes(\":memory:\");\n}\n\n/**\n * The one cast at the driver boundary. ORM-path values were encoded by the\n * runtime codec table into driver-native shapes; raw-path values went through\n * `serializeParamsRaw`. Verified by the param-passthrough unit tests.\n */\nfunction asBindings(values: readonly unknown[]): SQLQueryBindings[] {\n return values as SQLQueryBindings[];\n}\n\n/**\n * `Statement.safeIntegers()` exists at runtime since Bun 1.1.14 (pinned by\n * the integer-width unit tests: it returns the statement and applies to\n * cached statements too) but is missing from the installed @types/bun — this\n * minimal structural view bridges the gap without `any`.\n */\ntype SafeIntegersStatement = { safeIntegers(toggle: boolean): unknown };\n\n/** Flip a prepared statement to lossless 64-bit integer reads (see module doc). */\nfunction withSafeIntegers<S>(statement: S): S {\n (statement as unknown as SafeIntegersStatement).safeIntegers(true);\n return statement;\n}\n\n// ─── Adapter ──────────────────────────────────────────────────────\n\n/**\n * Create a VibeORM adapter backed by bun:sqlite.\n *\n * @example In-memory database (tests)\n * ```ts\n * const adapter = sqliteAdapter();\n * await adapter.executeUnsafe({ text: `CREATE TABLE \"User\" (\"id\" INTEGER PRIMARY KEY)` });\n * ```\n *\n * @example File database / shared instance\n * ```ts\n * const file = sqliteAdapter({ filename: \"./app.db\" });\n * const shared = sqliteAdapter({ database: existingDatabase });\n * ```\n *\n * `disconnect()` closes a database the adapter opened; a later call opens a\n * fresh one (lazy reconnect, matching the pool-backed adapters). With the\n * default `\":memory:\"` filename that fresh database is a new, empty one.\n *\n * @throws VibeError `VIBE_VALIDATION` when `busyTimeoutMs` is not a\n * non-negative integer — validated eagerly, the value lands in PRAGMA text.\n */\nexport function sqliteAdapter(options?: SqliteAdapterOptions): DatabaseAdapter {\n const busyTimeoutMs = options?.busyTimeoutMs;\n if (busyTimeoutMs !== undefined && (!Number.isInteger(busyTimeoutMs) || busyTimeoutMs < 0)) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `busyTimeoutMs must be a non-negative integer of milliseconds, received ${String(busyTimeoutMs)}`,\n meta: { busyTimeoutMs },\n });\n }\n\n const queue = createOperationQueue();\n const ownsDatabase = options?.database === undefined;\n const filename = options?.filename ?? \":memory:\";\n\n /**\n * Deadlock guard (the pglite F6 lesson): a whole transaction holds the\n * operation queue, so a ROOT-adapter call issued from inside a\n * `transaction()` callback would queue behind the very transaction it is\n * running in and hang forever. Root entry points refuse instead; the\n * tx-bound adapter bypasses the queue and stays fully usable.\n */\n const txContext = new AsyncLocalStorage<true>();\n\n function assertNotInsideTransaction(): void {\n if (txContext.getStore() === true) {\n throw new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"root client used inside a transaction callback — use the tx client the callback receives; the root connection would deadlock behind the open transaction\",\n meta: { provider: PROVIDER },\n });\n }\n }\n\n let database: Database | null = options?.database ?? null;\n let configured = false;\n\n /**\n * Session pragmas, applied once per opened connection (see module doc).\n * On an injected database only `foreign_keys` is unconditional; the\n * busy timeout is applied only when explicitly configured, and the journal\n * mode is never touched.\n */\n function applyPragmas(params: { db: Database }): void {\n const { db } = params;\n // MANDATORY: sqlite ships with foreign-key enforcement OFF; every FK\n // semantic the ORM promises (RESTRICT errors, ON DELETE CASCADE) needs it.\n db.run(\"PRAGMA foreign_keys = ON\");\n if (ownsDatabase || busyTimeoutMs !== undefined) {\n db.run(`PRAGMA busy_timeout = ${busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS}`);\n }\n if (\n ownsDatabase &&\n options?.wal !== false &&\n options?.readonly !== true &&\n !isMemoryFilename({ filename })\n ) {\n db.run(\"PRAGMA journal_mode = WAL\");\n }\n }\n\n /** Open (or reuse) the connection lazily; sync because the driver is. */\n function getDatabase(): Database {\n if (database === null) {\n database = runMapped(\n () =>\n new Database(\n filename,\n options?.readonly === true\n ? { readonly: true, safeIntegers: true }\n : { create: true, readwrite: true, safeIntegers: true },\n ),\n );\n configured = false;\n }\n if (!configured) {\n runMapped(() => applyPragmas({ db: database as Database }));\n configured = true;\n }\n return database;\n }\n\n /**\n * ORM hot path: `db.query()` prepares through bun:sqlite's built-in\n * per-connection statement cache (pinned: same text ⇒ same Statement\n * object), so no adapter-side LRU is needed. Values bind verbatim — the\n * runtime codec table already encoded them (params.ts).\n */\n function runExecute(params: {\n db: Database;\n text: string;\n values: unknown[];\n }): Record<string, unknown>[] {\n return runMapped(() => {\n const statement = withSafeIntegers(params.db.query(params.text));\n const rows = statement.all(...asBindings(params.values)) as Record<string, unknown>[];\n return normalizeRows({ rows });\n });\n }\n\n /**\n * Raw path — uncached (`db.prepare`), finalized after use, raw-path\n * serialization for user-supplied values.\n *\n * With `values` present the text must be a SINGLE statement: bun:sqlite's\n * prepare SILENTLY DROPS everything after the first statement (pinned on\n * Bun 1.3.14), so multi-statement text with parameters would half-run.\n * Rows come from `all()` when the statement has result columns\n * (`columnNames`), with `affectedRows` = the row count (exact for\n * DML…RETURNING); otherwise from `run()`, whose driver-reported `changes`\n * is exact for UPDATE/DELETE/INSERT.\n *\n * With `values` absent the text runs as a multi-statement batch through\n * `db.run()` — the shape @vibeorm/migrate emits for DDL. The driver executes\n * every statement and reports cumulative changes; rows are always `[]` on\n * this path (the sync driver cannot both batch and read), so callers that\n * want rows from a single statement pass `values: []` — the runtime's\n * `$queryRawUnsafe` always does.\n */\n function runExecuteUnsafe(params: { db: Database; text: string; values?: unknown[] }): QueryResult {\n return runMapped(() => {\n const { db, text, values } = params;\n if (values === undefined) {\n const changes = db.run(text);\n return { rows: [], affectedRows: changes.changes };\n }\n const statement = withSafeIntegers(db.prepare(text));\n try {\n const bound = asBindings(serializeParamsRaw({ values }));\n if (statement.columnNames.length > 0) {\n const rows = statement.all(...bound) as Record<string, unknown>[];\n return { rows: normalizeRows({ rows }), affectedRows: rows.length };\n }\n const result = statement.run(...bound);\n return { rows: [], affectedRows: result.changes };\n } finally {\n statement.finalize();\n }\n });\n }\n\n /**\n * Adapter bound to an open transaction. It never re-enters the queue — the\n * enclosing `transaction()` call already owns the connection — and nested\n * `transaction()` calls become savepoints whose LIFETIMES are serialized by\n * the savepoint gate (F14): overlapping siblings would share one savepoint\n * stack, and the earlier one's rollback would erase the later one's work.\n */\n function createTransactionAdapter(params: {\n db: Database;\n scope: SavepointScope;\n budget: TransactionBudget;\n }): DatabaseAdapter {\n const { db, scope, budget } = params;\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async execute(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n // After the turn, not before: waiting for a sibling savepoint spends\n // the same budget the statement is about to run against.\n budget.assertUsable({ stage: \"statement\" });\n return runExecute({ db, ...execParams });\n },\n\n async executeUnsafe(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteUnsafe({ db, ...execParams });\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n nestedOptions?: TransactionOptions,\n ): Promise<T> {\n refuseNestedTransactionOptions({ options: nestedOptions, provider: PROVIDER });\n budget.assertUsable({ stage: \"nested\" });\n return runNestedSavepoint({\n scope,\n execute: (statement) => runMapped(() => db.run(statement)),\n // The child shares the ROOT budget by reference: a savepoint never\n // gets an independent clock or session setting.\n body: (child) => fn(createTransactionAdapter({ db, scope: child, budget })),\n });\n },\n\n async connect(): Promise<void> {\n // Already connected — this adapter is bound to an open transaction.\n },\n\n async disconnect(): Promise<void> {\n // The database outlives the transaction; closing here would be wrong.\n },\n\n formatArrayParam(values: unknown[]): unknown {\n throw arrayParamBug({ values });\n },\n };\n }\n\n /**\n * sqlite has no array parameters — the sqlite dialect declares\n * `scalarArrays: false` and expands `IN` lists to individual placeholders\n * (`inArrayStrategy: \"expand\"`), so this method being reached means an\n * upstream runtime bug routed an array here.\n */\n function arrayParamBug(params: { values: unknown[] }): VibeError {\n return internalError({\n message:\n \"formatArrayParam called on the sqlite adapter — sqlite has no array parameters; the dialect expands IN lists to individual placeholders, so this call is an upstream runtime bug\",\n meta: { provider: PROVIDER, valueCount: params.values.length },\n });\n }\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async execute(params) {\n assertNotInsideTransaction();\n return queue.run(async () => runExecute({ db: getDatabase(), ...params }));\n },\n\n async executeUnsafe(params) {\n assertNotInsideTransaction();\n return queue.run(async () => runExecuteUnsafe({ db: getDatabase(), ...params }));\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n transactionOptions?: TransactionOptions,\n ): Promise<T> {\n assertNotInsideTransaction();\n // Refuse unsupportable options BEFORE taking the queue or issuing BEGIN,\n // so a bad option fails fast and leaves no transaction open.\n validateTransactionOptions({ options: transactionOptions });\n validateTransactionDeadline({\n options: transactionOptions,\n support: BUDGETS.transactionDeadline,\n provider: PROVIDER,\n });\n\n return queue.run(async () => {\n const db = getDatabase();\n const scope = createSavepointScope();\n // The deadline clock starts here — after the queue turn, immediately\n // before BEGIN. Waiting for the connection is not charged to it.\n const budget = startTransactionBudget({ options: transactionOptions, provider: PROVIDER });\n // Write-intent lock up front — see module doc on BEGIN IMMEDIATE.\n runMapped(() => db.run(\"BEGIN IMMEDIATE\"));\n try {\n const result = await txContext.run(true, () =>\n runRootScope({ scope, body: () => fn(createTransactionAdapter({ db, scope, budget })) }),\n );\n // An expired budget must never commit, however the callback ended.\n budget.assertUsable({ stage: \"commit\" });\n runMapped(() => db.run(\"COMMIT\"));\n budget.close({ outcome: \"committed\" });\n return result;\n } catch (error) {\n // Best effort: never mask the original failure (the user callback's\n // own error, or a failed COMMIT) with a rollback failure.\n try {\n db.run(\"ROLLBACK\");\n budget.close({ outcome: \"rolled-back\" });\n } catch {\n // The rollback that should have cleaned up failed: the commit state\n // is genuinely unknown, and saying \"rolled back\" would be a lie.\n budget.close({ outcome: \"unknown\" });\n if (budget.totalMs !== null && isTransactionDeadlineError(error)) {\n throw transactionOutcomeUnknownError({\n provider: PROVIDER,\n totalMs: budget.totalMs,\n cause: error,\n });\n }\n }\n throw error;\n }\n });\n },\n\n async connect(): Promise<void> {\n getDatabase();\n },\n\n /**\n * ONE ordered lifecycle (F15): the reference is cleared and the handle\n * closed INSIDE the queue, so work this adapter already accepted runs on\n * the database it was accepted against. Clearing `database` up front — as\n * this did — sent that queued work through `getDatabase()` with nothing in\n * hand, silently opening a FRESH (for `\":memory:\"`, empty) database while\n * the close went to the old handle.\n *\n * Refuses inside a transaction callback for the same reason the other entry\n * points do: the close would queue behind the transaction that is waiting\n * for it. Before this guard that call hung forever.\n */\n async disconnect(): Promise<void> {\n assertNotInsideTransaction();\n if (!ownsDatabase) return;\n await queue.run(async () => {\n if (database === null) return;\n const closing = database;\n database = null;\n configured = false;\n runMapped(() => closing.close());\n });\n },\n\n formatArrayParam(values: unknown[]): unknown {\n throw arrayParamBug({ values });\n },\n };\n}\n\n// ─── Re-exports (driver-error table, helpers) ─────────────────────\n\nexport {\n SQLITE_ERROR_CODES,\n SQLITE_ERROR_REASONS,\n mapSqliteDriverError,\n runMapped,\n sqliteErrorCode,\n} from \"./errors.ts\";\nexport { normalizeRow, normalizeRows, serializeParamsRaw } from \"./params.ts\";\nexport { createOperationQueue } from \"./queue.ts\";\nexport type { OperationQueue } from \"./queue.ts\";\nexport { createSavepointCounter, nextSavepointName } from \"@vibeorm/runtime/adapter-kit\";\nexport type { SavepointCounter } from \"@vibeorm/runtime/adapter-kit\";\nexport { refuseNestedTransactionOptions, validateTransactionOptions } from \"./transaction-options.ts\";\n// ─── EPIC 6: transaction budgets (shared, @vibeorm/runtime/adapter-kit) ───\nexport {\n DEFAULT_DEADLINE_CLOCK,\n engineStatementBudgetMs,\n isTransactionDeadlineError,\n startTransactionBudget,\n transactionClosedError,\n transactionDeadlineError,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nexport type { BudgetStage, DeadlineClock, TransactionBudget, TransactionOutcome } from \"@vibeorm/runtime/adapter-kit\";\n",
|
|
5
|
+
"/**\n * @vibeorm/adapter-sqlite — bun:sqlite (embedded SQLite) adapter for\n * VibeORM v2.\n *\n * bun:sqlite is a *synchronous* single-connection driver, so every call\n * completes without I/O waits and the adapter wraps results in\n * already-resolved promises — the cheapest possible `execute`. Like PGlite,\n * one connection means every operation runs through one serial queue:\n * a whole `transaction()` holds the queue until it commits or rolls back, so\n * concurrent client calls can never interleave into an open transaction.\n *\n * INTEGER WIDTH (the BigInt story): SQLite INTEGER columns are 64-bit, but JS\n * numbers are only exact to ±(2^53−1) — a plain read of a large BigInt column\n * silently corrupts (pinned on Bun 1.3.14: `SELECT 9007199254740993` returns\n * `9007199254740992` without safeIntegers). The adapter therefore ALWAYS reads\n * through bun:sqlite's `safeIntegers` (database-level for connections it\n * opens, statement-level `stmt.safeIntegers(true)` for every statement it\n * prepares, which also covers injected databases), then normalizes rows:\n * bigints inside the safe range become `number`, larger ones stay `bigint`.\n * That is exactly the shape the runtime's `SQLITE_CODECS` expect — Int and\n * Boolean columns arrive as numbers, and >2^53 BigInt columns round-trip\n * losslessly as bigint. See params.ts for the full reasoning.\n *\n * PRAGMAS applied on open (each documented on {@link SqliteAdapterOptions}):\n * `foreign_keys = ON` (mandatory — SQLite defaults OFF and the ORM's FK\n * semantics depend on it), `busy_timeout` (lock-wait bound), and\n * `journal_mode = WAL` for file databases (readers no longer block the\n * writer). Transactions open with `BEGIN IMMEDIATE`: the write lock is taken\n * up front, so a write after a read inside the transaction can never hit the\n * SQLITE_BUSY deadlock that lock *upgrades* are prone to.\n */\n\nimport { Database } from \"bun:sqlite\";\nimport type { SQLQueryBindings } from \"bun:sqlite\";\nimport { VibeError, internalError } from \"@vibeorm/schema\";\nimport type { Dialect, Provider } from \"@vibeorm/schema\";\nimport type {\n AdapterBudgetSupport,\n DatabaseAdapter,\n QueryResult,\n TransactionOptions,\n WireFidelity,\n} from \"@vibeorm/runtime\";\nimport {\n runSqliteSession,\n createSavepointScope,\n isTransactionDeadlineError,\n runNestedSavepoint,\n runRootScope,\n type SavepointScope,\n scopeTurn,\n startTransactionBudget,\n type TransactionBudget,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nimport { mapSqliteDriverError, runMapped } from \"./errors.ts\";\nimport { normalizeRows, serializeParamsRaw } from \"./params.ts\";\nimport { assertSinglePreparedStatement } from \"./prepared-sql.ts\";\nimport { connectionOwnership } from \"./queue.ts\";\nimport { refuseNestedTransactionOptions, validateTransactionOptions } from \"./transaction-options.ts\";\n\n// ─── Options ──────────────────────────────────────────────────────\n\n/** Options for {@link sqliteAdapter}. (Factories are the documented exception allowed a plain options object.) */\nexport type SqliteAdapterOptions = {\n /**\n * Database file to open. Defaults to `\":memory:\"` — a fresh private\n * in-memory database, the usual choice for tests. Ignored when `database`\n * is injected.\n */\n readonly filename?: string;\n /**\n * Open the file read-only (`SQLITE_READONLY` errors on writes, mapped to\n * `VIBE_ADAPTER`). The WAL pragma is skipped on read-only connections —\n * switching journal modes is a write. Ignored when `database` is injected.\n */\n readonly readonly?: boolean;\n /**\n * `PRAGMA busy_timeout` in milliseconds — how long a statement blocks on a\n * competing lock before failing with SQLITE_BUSY (mapped to\n * `VIBE_TRANSACTION`, `meta.reason: \"busy\"`). Default 5000. On an injected\n * `database` the pragma is applied only when this option is passed\n * explicitly, so the adapter never silently overrides the owner's setting.\n */\n readonly busyTimeoutMs?: number;\n /**\n * Switch file databases to `PRAGMA journal_mode = WAL` on open (default\n * true): readers stop blocking the writer, the sane default for anything\n * long-lived. Skipped for `\":memory:\"` databases (they have no WAL),\n * read-only connections, and injected `database` instances (the owner\n * decides their journal mode).\n */\n readonly wal?: boolean;\n /**\n * An already-open `bun:sqlite` Database to run on — sharing one in-memory\n * database across adapters makes multi-adapter tests trivial. The adapter\n * never closes an injected instance (`disconnect()` is a no-op), never\n * changes its journal mode, and still applies `PRAGMA foreign_keys = ON`\n * (the ORM requires it). For lossless >2^53 BigInt reads the adapter sets\n * statement-level safeIntegers on every statement it prepares, so an\n * injected database needs no special construction flags. Wrappers sharing\n * the same Database also share transaction exclusion. Initialization refuses\n * if foreign keys remain OFF (for example, inside the owner's transaction);\n * retry after that transaction ends. FK-ON active handles remain supported.\n */\n readonly database?: Database;\n};\n\n// ─── Internals ────────────────────────────────────────────────────\n\nconst DIALECT: Dialect = \"sqlite\";\nconst PROVIDER: Provider = \"sqlite\";\n\n/**\n * bun:sqlite wire (board #30, live-verified): INTEGER/REAL → numbers (large\n * INTEGER → native `bigint`, which every decoder passes through); DateTime and\n * Json ride TEXT, so their decoders do real work and are declared \"text\"\n * (prunes nothing — the declaration is the honest record).\n */\nconst WIRE: WireFidelity = Object.freeze({ dateTime: \"text\", json: \"text\", numbers: \"native\" } as const);\n\n/**\n * Timing budgets this adapter genuinely enforces (EPIC 6).\n *\n * - `acquireTimeout: false` — bun:sqlite is ONE synchronous connection behind\n * an in-process queue. There is no pool to exhaust and no wait to bound.\n * - `statementTimeout: \"unsupported\"` — sqlite has no per-statement timeout;\n * `busy_timeout` bounds LOCK acquisition only, which is why the `timeout`\n * option is already refused outright (./transaction-options.ts).\n * - `transactionDeadline: \"between-statements\"` — an expired budget stops the\n * next statement and the commit, which is real enforcement. It is NOT\n * cancellation: bun:sqlite runs statements synchronously on the JS thread, so\n * a long statement blocks the event loop and no timer of any kind can fire\n * while it runs. Asking for `\"cancel-running-statements\"` is refused.\n */\nconst BUDGETS: AdapterBudgetSupport = Object.freeze({\n acquireTimeout: false,\n statementTimeout: \"unsupported\",\n transactionDeadline: \"between-statements\",\n} as const);\nconst DEFAULT_BUSY_TIMEOUT_MS = 5000;\n\n/** `\":memory:\"` (also in URI form) and `\"\"` (anonymous temp) have no WAL. */\nfunction isMemoryFilename(params: { filename: string }): boolean {\n return params.filename === \"\" || params.filename.includes(\":memory:\");\n}\n\n/**\n * The one cast at the driver boundary. ORM-path values were encoded by the\n * runtime codec table into driver-native shapes; raw-path values went through\n * `serializeParamsRaw`. Verified by the param-passthrough unit tests.\n */\nfunction asBindings(values: readonly unknown[]): SQLQueryBindings[] {\n return values as SQLQueryBindings[];\n}\n\n/**\n * `Statement.safeIntegers()` exists at runtime since Bun 1.1.14 (pinned by\n * the integer-width unit tests: it returns the statement and applies to\n * cached statements too) but is missing from the installed @types/bun — this\n * minimal structural view bridges the gap without `any`.\n */\ntype SafeIntegersStatement = { safeIntegers(toggle: boolean): unknown };\n\n/** Flip a prepared statement to lossless 64-bit integer reads (see module doc). */\nfunction withSafeIntegers<S>(statement: S): S {\n (statement as unknown as SafeIntegersStatement).safeIntegers(true);\n return statement;\n}\n\n// ─── Adapter ──────────────────────────────────────────────────────\n\n/**\n * Create a VibeORM adapter backed by bun:sqlite.\n *\n * @example In-memory database (tests)\n * ```ts\n * const adapter = sqliteAdapter();\n * await adapter.executeUnsafe({ text: `CREATE TABLE \"User\" (\"id\" INTEGER PRIMARY KEY)` });\n * ```\n *\n * @example File database / shared instance\n * ```ts\n * const file = sqliteAdapter({ filename: \"./app.db\" });\n * const shared = sqliteAdapter({ database: existingDatabase });\n * ```\n *\n * `disconnect()` closes a database the adapter opened; a later call opens a\n * fresh one (lazy reconnect, matching the pool-backed adapters). With the\n * default `\":memory:\"` filename that fresh database is a new, empty one.\n *\n * @throws VibeError `VIBE_VALIDATION` when `busyTimeoutMs` is not a\n * non-negative integer — validated eagerly, the value lands in PRAGMA text.\n */\nexport function sqliteAdapter(options?: SqliteAdapterOptions): DatabaseAdapter {\n const busyTimeoutMs = options?.busyTimeoutMs;\n if (busyTimeoutMs !== undefined && (!Number.isInteger(busyTimeoutMs) || busyTimeoutMs < 0)) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `busyTimeoutMs must be a non-negative integer of milliseconds, received ${String(busyTimeoutMs)}`,\n meta: { busyTimeoutMs },\n });\n }\n\n const { queue, txContext } = connectionOwnership({ database: options?.database });\n const ownsDatabase = options?.database === undefined;\n const filename = options?.filename ?? \":memory:\";\n\n /**\n * Deadlock guard (the pglite F6 lesson): a whole transaction holds the\n * operation queue, so a ROOT-adapter call issued from inside a\n * `transaction()` callback would queue behind the very transaction it is\n * running in and hang forever. Root entry points refuse instead; the\n * tx-bound adapter bypasses the queue and stays fully usable.\n */\n function assertNotInsideTransaction(): void {\n if (txContext.getStore() === true) {\n throw new VibeError({\n code: \"VIBE_TRANSACTION\",\n message:\n \"root client used inside a transaction callback — use the tx client the callback receives; the root connection would deadlock behind the open transaction\",\n meta: { provider: PROVIDER },\n });\n }\n }\n\n let database: Database | null = options?.database ?? null;\n let configured = false;\n\n /**\n * Session pragmas, applied once per opened connection (see module doc).\n * On an injected database only `foreign_keys` is unconditional; the\n * busy timeout is applied only when explicitly configured, and the journal\n * mode is never touched.\n */\n function applyPragmas(params: { db: Database }): void {\n const { db } = params;\n // MANDATORY: sqlite ships with foreign-key enforcement OFF; every FK\n // semantic the ORM promises (RESTRICT errors, ON DELETE CASCADE) needs it.\n db.run(\"PRAGMA foreign_keys = ON\");\n const foreignKeys = db.query(\"PRAGMA foreign_keys\").get() as { foreign_keys: number | bigint };\n if (foreignKeys.foreign_keys !== 1 && foreignKeys.foreign_keys !== 1n) {\n throw new VibeError({\n code: \"VIBE_ADAPTER\",\n message: \"SQLite foreign-key enforcement is disabled; finish the injected database transaction before connecting\",\n meta: { provider: PROVIDER, reason: \"foreign-keys-disabled\" },\n });\n }\n if (ownsDatabase || busyTimeoutMs !== undefined) {\n db.run(`PRAGMA busy_timeout = ${busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS}`);\n }\n if (\n ownsDatabase &&\n options?.wal !== false &&\n options?.readonly !== true &&\n !isMemoryFilename({ filename })\n ) {\n db.run(\"PRAGMA journal_mode = WAL\");\n }\n }\n\n /** Open (or reuse) the connection lazily; sync because the driver is. */\n function getDatabase(): Database {\n if (database === null) {\n database = runMapped(\n () =>\n new Database(\n filename,\n options?.readonly === true\n ? { readonly: true, safeIntegers: true }\n : { create: true, readwrite: true, safeIntegers: true },\n ),\n );\n configured = false;\n }\n if (!configured) {\n runMapped(() => applyPragmas({ db: database as Database }));\n configured = true;\n }\n return database;\n }\n\n /**\n * ORM hot path: `db.query()` prepares through bun:sqlite's built-in\n * per-connection statement cache (pinned: same text ⇒ same Statement\n * object), so no adapter-side LRU is needed. Values bind verbatim — the\n * runtime codec table already encoded them (params.ts).\n */\n function runExecute(params: {\n db: Database;\n text: string;\n values: unknown[];\n }): Record<string, unknown>[] {\n return runMapped(() => {\n const statement = withSafeIntegers(params.db.query(params.text));\n const rows = statement.all(...asBindings(params.values)) as Record<string, unknown>[];\n return normalizeRows({ rows });\n });\n }\n\n /**\n * Raw path — uncached (`db.prepare`), finalized after use, raw-path\n * serialization for user-supplied values.\n *\n * With `values` present the text must be a SINGLE statement: bun:sqlite's\n * prepare SILENTLY DROPS everything after the first statement, so the\n * compiled boundary is checked before binding or stepping the statement.\n * Rows come from `all()` when the statement has result columns\n * (`columnNames`), with `affectedRows` = the row count (exact for\n * DML…RETURNING); otherwise from `run()`, whose driver-reported `changes`\n * is exact for UPDATE/DELETE/INSERT.\n *\n * With `values` absent the text runs as a multi-statement batch through\n * `db.run()` — the shape @vibeorm/migrate emits for DDL. The driver executes\n * every statement and reports cumulative changes; rows are always `[]` on\n * this path (the sync driver cannot both batch and read), so callers that\n * want rows from a single statement pass `values: []` — the runtime's\n * `$queryRawUnsafe` always does.\n */\n function runExecuteUnsafe(params: { db: Database; text: string; values?: unknown[] }): QueryResult {\n return runMapped(() => {\n const { db, text, values } = params;\n if (values === undefined) {\n const changes = db.run(text);\n return { rows: [], affectedRows: changes.changes };\n }\n const statement = withSafeIntegers(db.prepare(text));\n try {\n assertSinglePreparedStatement({ text, expanded: statement.toString() });\n const bound = asBindings(serializeParamsRaw({ values }));\n if (statement.columnNames.length > 0) {\n const rows = statement.all(...bound) as Record<string, unknown>[];\n return { rows: normalizeRows({ rows }), affectedRows: rows.length };\n }\n const result = statement.run(...bound);\n return { rows: [], affectedRows: result.changes };\n } finally {\n statement.finalize();\n }\n });\n }\n\n /**\n * Adapter bound to an open transaction. It never re-enters the queue — the\n * enclosing `transaction()` call already owns the connection — and nested\n * `transaction()` calls become savepoints whose LIFETIMES are serialized by\n * the savepoint gate (F14): overlapping siblings would share one savepoint\n * stack, and the earlier one's rollback would erase the later one's work.\n */\n function createTransactionAdapter(params: {\n db: Database;\n scope: SavepointScope;\n budget: TransactionBudget;\n }): DatabaseAdapter {\n const { db, scope, budget } = params;\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async execute(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n // After the turn, not before: waiting for a sibling savepoint spends\n // the same budget the statement is about to run against.\n budget.assertUsable({ stage: \"statement\" });\n return runExecute({ db, ...execParams });\n },\n\n async executeUnsafe(execParams) {\n const turn = scopeTurn({ scope });\n if (turn !== undefined) await turn;\n budget.assertUsable({ stage: \"statement\" });\n return runExecuteUnsafe({ db, ...execParams });\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n nestedOptions?: TransactionOptions,\n ): Promise<T> {\n refuseNestedTransactionOptions({ options: nestedOptions, provider: PROVIDER });\n budget.assertUsable({ stage: \"nested\" });\n return runNestedSavepoint({\n scope,\n execute: (statement) => runMapped(() => db.run(statement)),\n // The child shares the ROOT budget by reference: a savepoint never\n // gets an independent clock or session setting.\n body: (child) => fn(createTransactionAdapter({ db, scope: child, budget })),\n });\n },\n\n async connect(): Promise<void> {\n // Already connected — this adapter is bound to an open transaction.\n },\n\n async disconnect(): Promise<void> {\n // The database outlives the transaction; closing here would be wrong.\n },\n\n formatArrayParam(values: unknown[]): unknown {\n throw arrayParamBug({ values });\n },\n };\n }\n\n /**\n * sqlite has no array parameters — the sqlite dialect declares\n * `scalarArrays: false` and expands `IN` lists to individual placeholders\n * (`inArrayStrategy: \"expand\"`), so this method being reached means an\n * upstream runtime bug routed an array here.\n */\n function arrayParamBug(params: { values: unknown[] }): VibeError {\n return internalError({\n message:\n \"formatArrayParam called on the sqlite adapter — sqlite has no array parameters; the dialect expands IN lists to individual placeholders, so this call is an upstream runtime bug\",\n meta: { provider: PROVIDER, valueCount: params.values.length },\n });\n }\n\n return {\n dialect: DIALECT,\n provider: PROVIDER,\n wire: WIRE,\n budgets: BUDGETS,\n\n async withSession({ run }) {\n assertNotInsideTransaction();\n return queue.run(async () => {\n const db = getDatabase();\n return txContext.run(true, () => runSqliteSession({\n run,\n execute: async (query) => runExecuteUnsafe({ db, ...query }).rows,\n inTransaction: () => db.inTransaction,\n }));\n });\n },\n\n async execute(params) {\n assertNotInsideTransaction();\n return queue.run(async () => runExecute({ db: getDatabase(), ...params }));\n },\n\n async executeUnsafe(params) {\n assertNotInsideTransaction();\n return queue.run(async () => runExecuteUnsafe({ db: getDatabase(), ...params }));\n },\n\n async transaction<T>(\n fn: (txAdapter: DatabaseAdapter) => Promise<T>,\n transactionOptions?: TransactionOptions,\n ): Promise<T> {\n assertNotInsideTransaction();\n // Refuse unsupportable options BEFORE taking the queue or issuing BEGIN,\n // so a bad option fails fast and leaves no transaction open.\n validateTransactionOptions({ options: transactionOptions });\n validateTransactionDeadline({\n options: transactionOptions,\n support: BUDGETS.transactionDeadline,\n provider: PROVIDER,\n });\n\n return queue.run(async () => {\n const db = getDatabase();\n const scope = createSavepointScope();\n // The deadline clock starts here — after the queue turn, immediately\n // before BEGIN. Waiting for the connection is not charged to it.\n const budget = startTransactionBudget({ options: transactionOptions, provider: PROVIDER });\n // Write-intent lock up front — see module doc on BEGIN IMMEDIATE.\n runMapped(() => db.run(\"BEGIN IMMEDIATE\"));\n try {\n const result = await txContext.run(true, () =>\n runRootScope({ scope, body: () => fn(createTransactionAdapter({ db, scope, budget })) }),\n );\n // An expired budget must never commit, however the callback ended.\n budget.assertUsable({ stage: \"commit\" });\n runMapped(() => db.run(\"COMMIT\"));\n budget.close({ outcome: \"committed\" });\n return result;\n } catch (error) {\n // Best effort: never mask the original failure (the user callback's\n // own error, or a failed COMMIT) with a rollback failure.\n try {\n db.run(\"ROLLBACK\");\n budget.close({ outcome: scope.state.poisoned === null ? \"rolled-back\" : \"unknown\" });\n } catch {\n // The rollback that should have cleaned up failed: the commit state\n // is genuinely unknown, and saying \"rolled back\" would be a lie.\n budget.close({ outcome: \"unknown\" });\n if (budget.totalMs !== null && isTransactionDeadlineError(error)) {\n throw transactionOutcomeUnknownError({\n provider: PROVIDER,\n totalMs: budget.totalMs,\n cause: error,\n });\n }\n }\n throw error;\n }\n });\n },\n\n async connect(): Promise<void> {\n assertNotInsideTransaction();\n await queue.run(async () => { getDatabase(); });\n },\n\n /**\n * ONE ordered lifecycle (F15): the reference is cleared and the handle\n * closed INSIDE the queue, so work this adapter already accepted runs on\n * the database it was accepted against. Clearing `database` up front — as\n * this did — sent that queued work through `getDatabase()` with nothing in\n * hand, silently opening a FRESH (for `\":memory:\"`, empty) database while\n * the close went to the old handle.\n *\n * Refuses inside a transaction callback for the same reason the other entry\n * points do: the close would queue behind the transaction that is waiting\n * for it. Before this guard that call hung forever.\n */\n async disconnect(): Promise<void> {\n assertNotInsideTransaction();\n if (!ownsDatabase) return;\n await queue.run(async () => {\n if (database === null) return;\n const closing = database;\n database = null;\n configured = false;\n runMapped(() => closing.close());\n });\n },\n\n formatArrayParam(values: unknown[]): unknown {\n throw arrayParamBug({ values });\n },\n };\n}\n\n// ─── Re-exports (driver-error table, helpers) ─────────────────────\n\nexport {\n SQLITE_ERROR_CODES,\n SQLITE_ERROR_REASONS,\n mapSqliteDriverError,\n runMapped,\n sqliteErrorCode,\n} from \"./errors.ts\";\nexport { normalizeRow, normalizeRows, serializeParamsRaw } from \"./params.ts\";\nexport { createOperationQueue } from \"./queue.ts\";\nexport type { OperationQueue } from \"./queue.ts\";\nexport { createSavepointCounter, nextSavepointName } from \"@vibeorm/runtime/adapter-kit\";\nexport type { SavepointCounter } from \"@vibeorm/runtime/adapter-kit\";\nexport { refuseNestedTransactionOptions, validateTransactionOptions } from \"./transaction-options.ts\";\n// ─── EPIC 6: transaction budgets (shared, @vibeorm/runtime/adapter-kit) ───\nexport {\n DEFAULT_DEADLINE_CLOCK,\n engineStatementBudgetMs,\n isTransactionDeadlineError,\n startTransactionBudget,\n transactionClosedError,\n transactionDeadlineError,\n transactionOutcomeUnknownError,\n validateTransactionDeadline,\n} from \"@vibeorm/runtime/adapter-kit\";\nexport type { BudgetStage, DeadlineClock, TransactionBudget, TransactionOutcome } from \"@vibeorm/runtime/adapter-kit\";\n",
|
|
6
6
|
"/**\n * Driver-error mapping for `bun:sqlite`.\n *\n * bun:sqlite throws `SQLiteError` carrying the SQLite *extended* result-code\n * name in `code` (e.g. `\"SQLITE_CONSTRAINT_UNIQUE\"`) and the numeric extended\n * result code in `errno` (e.g. `2067`). Real shapes pinned against Bun 1.3.14:\n *\n * unique → code \"SQLITE_CONSTRAINT_UNIQUE\" errno 2067\n * pk → code \"SQLITE_CONSTRAINT_PRIMARYKEY\" errno 1555\n * notnull → code \"SQLITE_CONSTRAINT_NOTNULL\" errno 1299\n * check → code \"SQLITE_CONSTRAINT_CHECK\" errno 275\n * fk → code \"SQLITE_CONSTRAINT_FOREIGNKEY\" errno 787\n * busy → code \"SQLITE_BUSY\" errno 5\n *\n * Constitution rule 5: only `VibeError` escapes the adapter.\n */\n\nimport { VibeError, type VibeErrorCode } from \"@vibeorm/schema\";\n\n// ─── Result-code table ────────────────────────────────────────────\n\n/**\n * SQLite extended result-code name → stable VibeError code. Frozen and\n * mirrored by tests; anything absent from this table maps to `VIBE_ADAPTER`.\n */\nexport const SQLITE_ERROR_CODES: Readonly<Record<string, VibeErrorCode>> = Object.freeze({\n /** UNIQUE constraint failed on a declared unique index. */\n SQLITE_CONSTRAINT_UNIQUE: \"VIBE_UNIQUE_VIOLATION\",\n /** UNIQUE constraint failed on the primary key. */\n SQLITE_CONSTRAINT_PRIMARYKEY: \"VIBE_UNIQUE_VIOLATION\",\n /** rowid collision — the rowid alias flavour of a PK violation. */\n SQLITE_CONSTRAINT_ROWID: \"VIBE_UNIQUE_VIOLATION\",\n /** FOREIGN KEY constraint failed (requires `PRAGMA foreign_keys = ON`). */\n SQLITE_CONSTRAINT_FOREIGNKEY: \"VIBE_FK_VIOLATION\",\n /** NOT NULL constraint failed. */\n SQLITE_CONSTRAINT_NOTNULL: \"VIBE_VALIDATION\",\n /** CHECK constraint failed (enum emulation uses CHECK on sqlite). */\n SQLITE_CONSTRAINT_CHECK: \"VIBE_VALIDATION\",\n /** STRICT-table type mismatch. */\n SQLITE_CONSTRAINT_DATATYPE: \"VIBE_VALIDATION\",\n /** Another connection holds a conflicting lock. */\n SQLITE_BUSY: \"VIBE_TRANSACTION\",\n /** WAL snapshot invalidated by a concurrent writer. */\n SQLITE_BUSY_SNAPSHOT: \"VIBE_TRANSACTION\",\n /** Locked while another connection recovers the WAL. */\n SQLITE_BUSY_RECOVERY: \"VIBE_TRANSACTION\",\n /** busy_timeout elapsed while blocking (sqlite ≥3.41 setlk timeouts). */\n SQLITE_BUSY_TIMEOUT: \"VIBE_TRANSACTION\",\n /** Conflict on the same connection (e.g. dropping a table mid-read). */\n SQLITE_LOCKED: \"VIBE_TRANSACTION\",\n /** Shared-cache lock contention. */\n SQLITE_LOCKED_SHAREDCACHE: \"VIBE_TRANSACTION\",\n});\n\n/**\n * Result codes that additionally explain themselves through `meta.reason`.\n *\n * `VIBE_LOCK_NOT_AVAILABLE` deliberately does NOT appear here. sqlite has no\n * locking-read clause — `SELECT … FOR UPDATE` is a syntax error, and the ORM\n * refuses the request before any SQL is built — so no lock REQUEST can fail.\n * `SQLITE_BUSY` is transaction contention on the database file, which is what\n * `VIBE_TRANSACTION` / `\"busy\"` has always meant here; re-coding it would\n * change an unrelated, established contract.\n */\nexport const SQLITE_ERROR_REASONS: Readonly<Record<string, string>> = Object.freeze({\n SQLITE_BUSY: \"busy\",\n SQLITE_BUSY_SNAPSHOT: \"busy\",\n SQLITE_BUSY_RECOVERY: \"busy\",\n SQLITE_BUSY_TIMEOUT: \"busy\",\n SQLITE_LOCKED: \"busy\",\n SQLITE_LOCKED_SHAREDCACHE: \"busy\",\n});\n\n// ─── Reading driver errors ────────────────────────────────────────\n\n/** bun:sqlite result-code names are SCREAMING_SNAKE with the SQLITE_ prefix. */\nconst RESULT_CODE_PATTERN = /^SQLITE_[A-Z0-9_]+$/;\n\nfunction readStringField(params: { source: Record<string, unknown>; key: string }): string | undefined {\n const value = params.source[params.key];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/**\n * Extract the SQLite result-code name from a bun:sqlite error. Failures raised\n * outside the database engine (a closed handle, a bad filename) may carry no\n * `SQLITE_*` code and yield `undefined`.\n */\nexport function sqliteErrorCode(params: { error: unknown }): string | undefined {\n const { error } = params;\n if (error === null || typeof error !== \"object\") return undefined;\n const code = readStringField({ source: error as Record<string, unknown>, key: \"code\" });\n return code !== undefined && RESULT_CODE_PATTERN.test(code) ? code : undefined;\n}\n\n// ─── Mapping ──────────────────────────────────────────────────────\n\n/**\n * Map any error thrown by bun:sqlite onto a `VibeError`.\n *\n * A `VibeError` passes through unchanged, so an error raised deeper inside the\n * ORM (or by a nested adapter call) is never re-wrapped. Everything else keeps\n * the original error as `cause` and carries `{ code, errno }` in `meta`.\n */\nexport function mapSqliteDriverError(params: { error: unknown }): VibeError {\n const { error } = params;\n if (error instanceof VibeError) return error;\n\n const source: Record<string, unknown> =\n error !== null && typeof error === \"object\" ? (error as Record<string, unknown>) : {};\n const driverCode = sqliteErrorCode({ error });\n const code: VibeErrorCode =\n (driverCode === undefined ? undefined : SQLITE_ERROR_CODES[driverCode]) ?? \"VIBE_ADAPTER\";\n\n const meta: Record<string, unknown> = {};\n if (driverCode !== undefined) meta.code = driverCode;\n const errno = source.errno;\n if (typeof errno === \"number\") meta.errno = errno;\n const reason = driverCode === undefined ? undefined : SQLITE_ERROR_REASONS[driverCode];\n if (reason !== undefined) meta.reason = reason;\n\n const message =\n readStringField({ source, key: \"message\" }) ??\n (typeof error === \"string\" ? error : \"unknown bun:sqlite driver error\");\n\n return new VibeError({ code, message, meta, cause: error });\n}\n\n/**\n * Run a driver call, mapping anything it throws onto a `VibeError`. Synchronous\n * because bun:sqlite is a synchronous driver — the adapter's async surface\n * wraps results in already-resolved promises.\n */\nexport function runMapped<T>(fn: () => T): T {\n try {\n return fn();\n } catch (error) {\n throw mapSqliteDriverError({ error });\n }\n}\n",
|
|
7
7
|
"/**\n * Parameter serialization and row normalization for bun:sqlite.\n *\n * TWO SERIALIZATION PATHS (LEARNINGS.md — raw vs ORM differ):\n *\n * ORM hot path — NO conversion at all. The runtime codec table\n * (`SQLITE_CODECS` in @vibeorm/runtime) already encoded every parameter:\n * booleans are 0/1, Dates are ISO-8601 text, Json is stringified, BigInt is\n * decimal text. Converting again here would be exactly the double-coercion\n * v1's constitution rule 6 forbids, so `execute` binds values verbatim.\n *\n * Raw path (`$queryRaw*` / `$executeRaw*` / DDL) — user-supplied values that\n * never met a codec. bun:sqlite silently binds JS values it does not\n * understand as NULL (pinned on Bun 1.3.14: a `Date` and a plain object both\n * arrive as NULL), so {@link serializeParamsRaw} converts them explicitly\n * instead of letting data vanish.\n *\n * ROW NORMALIZATION: the adapter always reads INTEGER columns with\n * `safeIntegers` (see index.ts), so the driver hands back `bigint` for every\n * integer value. {@link normalizeRows} converts each bigint that fits the\n * IEEE-754 safe range back to `number`, and keeps the rest as `bigint`:\n *\n * - Int columns arrive as `number` (the Int codec passes numbers through),\n * - Boolean 0/1 arrive as `number` → decoded to boolean by the codec,\n * - BigInt columns ≤ 2^53−1 arrive as `number` → `BigInt(value)` (lossless),\n * - BigInt columns > 2^53−1 STAY `bigint` → codec passes them through — the\n * round-trip is lossless where plain number reads would silently corrupt.\n */\n\n// ─── Raw-path serialization ───────────────────────────────────────\n\n/**\n * Serialize raw-path parameters into values bun:sqlite binds faithfully:\n * `Date` → ISO-8601 text (matches the DateTime column encoding), `boolean` →\n * 1/0 (matches the Boolean column encoding), plain objects **and arrays** →\n * JSON text (sqlite has no array parameters — a JS array can only be a JSON\n * value here), `undefined` → NULL. Strings, numbers, bigints, NULL and binary\n * views pass through untouched.\n */\nexport function serializeParamsRaw(params: { values: readonly unknown[] }): unknown[] {\n return params.values.map((value) => {\n if (value === undefined) return null;\n if (typeof value === \"boolean\") return value ? 1 : 0;\n if (value === null || typeof value !== \"object\") return value;\n if (value instanceof Date) return value.toISOString();\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value;\n return JSON.stringify(value);\n });\n}\n\n// ─── Row normalization (safeIntegers → JS expectations) ───────────\n\nconst MAX_SAFE: bigint = BigInt(Number.MAX_SAFE_INTEGER);\nconst MIN_SAFE: bigint = -MAX_SAFE;\n\n/**\n * Downcast every lossless `bigint` in a row to `number`, in place. Values\n * outside ±(2^53−1) stay `bigint` so oversized BigInt columns round-trip\n * exactly (see the module doc for why this matches the runtime codec table).\n */\nexport function normalizeRow(params: { row: Record<string, unknown> }): Record<string, unknown> {\n const { row } = params;\n for (const key of Object.keys(row)) {\n const value = row[key];\n if (typeof value === \"bigint\" && value <= MAX_SAFE && value >= MIN_SAFE) {\n row[key] = Number(value);\n }\n }\n return row;\n}\n\n/** {@link normalizeRow} over a result set (mutates and returns the same array). */\nexport function normalizeRows(params: { rows: Record<string, unknown>[] }): Record<string, unknown>[] {\n for (const row of params.rows) normalizeRow({ row });\n return params.rows;\n}\n",
|
|
8
|
-
"
|
|
9
|
-
"/**\n *
|
|
8
|
+
"import { VibeError } from \"@vibeorm/schema\";\n\nconst SPACE = /[\\t\\n\\v\\f\\r ]/;\nconst IDENTIFIER = /[A-Za-z0-9_$\\u0080-\\uffff]/;\n\n/** End of a SQLite comment, or undefined when this is not a comment. */\nfunction commentEnd(params: { text: string; offset: number }): number | undefined {\n const { text, offset } = params;\n if (text.startsWith(\"--\", offset)) {\n const end = text.indexOf(\"\\n\", offset + 2);\n return end < 0 ? text.length : end + 1;\n }\n if (text.startsWith(\"/*\", offset)) {\n const end = text.indexOf(\"*/\", offset + 2);\n return end < 0 ? text.length : end + 2;\n }\n return undefined;\n}\n\n/** Locate terminators, not statements: SQLite itself parses compound trigger bodies. */\nfunction terminators(params: { text: string }): number[] {\n const { text } = params;\n const offsets: number[] = [];\n for (let i = 0; i < text.length;) {\n const end = commentEnd({ text, offset: i });\n if (end !== undefined) { i = end; continue; }\n const char = text[i]!;\n if (char === \"'\" || char === '\"' || char === \"`\" || char === \"[\") {\n const quote = char === \"[\" ? \"]\" : char;\n i++;\n while (i < text.length) {\n if (text[i++] !== quote) continue;\n if (quote !== \"]\" && text[i] === quote) { i++; continue; }\n break;\n }\n continue;\n }\n // SQLite's Tcl-style variable suffix can itself contain semicolons or\n // quote/comment characters. sqlite3_expanded_sql replaces the WHOLE token.\n if (char === \"$\" || char === \":\" || char === \"@\" || char === \"#\") {\n i++;\n while (i < text.length) {\n if (IDENTIFIER.test(text[i]!)) { i++; continue; }\n if (text.startsWith(\"::\", i)) { i += 2; continue; }\n if (text[i] === \"(\") {\n i++;\n while (i < text.length && text[i] !== \")\" && !SPACE.test(text[i]!)) i++;\n if (text[i] === \")\") i++;\n }\n break;\n }\n continue;\n }\n // A dollar sign inside an ordinary identifier is not a parameter prefix.\n if (IDENTIFIER.test(char)) {\n while (i < text.length && IDENTIFIER.test(text[i]!)) i++;\n continue;\n }\n if (char === \";\") offsets.push(i);\n i++;\n }\n return offsets;\n}\n\n/**\n * Reject a prepared tail before stepping the statement. Bun's documented\n * Statement.toString() is sqlite3_expanded_sql: it contains only the compiled\n * first statement. Called BEFORE binding, expansion replaces parameters with\n * NULL, preserving every real terminator (including those inside a trigger).\n * Map its terminator count back to the original text, then allow only SQLite\n * whitespace, empty separators and comments. Script execution never calls this.\n */\nexport function assertSinglePreparedStatement(params: { text: string; expanded: string }): void {\n const { text, expanded } = params;\n if (text.includes(\"\\0\")) throw preparedTailError();\n const count = terminators({ text: expanded }).length;\n if (count === 0) return;\n const boundary = terminators({ text })[count - 1];\n if (boundary === undefined) throw preparedTailError();\n for (let i = boundary + 1; i < text.length;) {\n if (SPACE.test(text[i]!) || text[i] === \";\") { i++; continue; }\n const end = commentEnd({ text, offset: i });\n if (end === undefined) throw preparedTailError();\n i = end;\n }\n}\n\nfunction preparedTailError(): VibeError {\n return new VibeError({\n code: \"VIBE_ADAPTER\",\n message: \"Prepared SQLite SQL must contain one statement; omit values only when intentionally executing a script\",\n meta: { provider: \"sqlite\", reason: \"prepared-statement-tail\" },\n });\n}\n",
|
|
9
|
+
"/**\n * Operation queue for bun:sqlite.\n *\n * The driver itself is synchronous — a single statement can never interleave —\n * but a `transaction()` callback is async: while it awaits, a concurrent root\n * adapter call would run on the SAME connection and silently join the open\n * transaction. Every adapter entry point therefore runs through one serial\n * chain — including whole `transaction()` calls, which occupy the chain until\n * they commit or roll back (mirroring adapter-pglite).\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n/** A serial chain: jobs run one at a time, in the order they were queued. */\nexport type OperationQueue = {\n /** Queue `job`, resolving with its result once every earlier job has settled. */\n run<T>(job: () => Promise<T>): Promise<T>;\n};\n\n/** Connection-wide exclusion, including callback reentry through another wrapper. */\nexport type ConnectionOwnership = {\n readonly queue: OperationQueue;\n readonly txContext: AsyncLocalStorage<true>;\n};\n\nconst INJECTED_OWNERSHIP: WeakMap<object, ConnectionOwnership> = new WeakMap();\n\n/** Share ownership by injected handle identity without retaining closed databases. */\nexport function connectionOwnership(params: { database?: object }): ConnectionOwnership {\n const existing = params.database === undefined ? undefined : INJECTED_OWNERSHIP.get(params.database);\n if (existing !== undefined) return existing;\n const ownership = { queue: createOperationQueue(), txContext: new AsyncLocalStorage<true>() };\n if (params.database !== undefined) INJECTED_OWNERSHIP.set(params.database, ownership);\n return ownership;\n}\n\n/** Create an empty operation queue. */\nexport function createOperationQueue(): OperationQueue {\n let tail: Promise<unknown> = Promise.resolve();\n\n return {\n run<T>(job: () => Promise<T>): Promise<T> {\n // Run after the previous job settles, whether it resolved or rejected.\n const result = tail.then(job, job);\n // Keep the chain alive: a rejected job must not reject every later job.\n tail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n },\n };\n}\n",
|
|
10
|
+
"/**\n * Transaction-option validation for sqlite — dialect honesty (constitution\n * rule 4): what sqlite cannot honor is refused loudly at the earliest knowable\n * moment, before `BEGIN` is ever issued, instead of being silently ignored.\n *\n * - SQLite transactions are always serializable. `Serializable` (and omitting\n * the option) is accepted; `ReadCommitted` / `RepeatableRead` would be a\n * silent upgrade the caller did not ask for, so they throw `VIBE_VALIDATION`.\n * - SQLite has no per-statement timeout. `busy_timeout` only bounds LOCK\n * ACQUISITION, not statement runtime, so it is NOT an honest implementation\n * of the contract's transaction-scoped `timeout` — the option throws\n * `VIBE_VALIDATION`.\n * - NESTED transactions are savepoints: no adapter can change the isolation\n * level mid-transaction or enforce a nested timeout, so nested options are\n * refused with `VIBE_VALIDATION` on EVERY adapter (the shared contract in\n * @vibeorm/runtime's adapter.ts).\n */\n\nimport type { TransactionOptions } from \"@vibeorm/runtime\";\nimport { VibeError } from \"@vibeorm/schema\";\n\n/**\n * Validate `$transaction` options against what sqlite can actually honor.\n *\n * @throws VibeError `VIBE_VALIDATION` for `ReadCommitted` / `RepeatableRead`\n * isolation or any `timeout` (see module doc).\n */\nexport function validateTransactionOptions(params: { options?: TransactionOptions }): void {\n const { options } = params;\n if (options === undefined) return;\n\n if (options.isolationLevel !== undefined && options.isolationLevel !== \"Serializable\") {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message: `sqlite transactions are always serializable — isolationLevel \"${options.isolationLevel}\" cannot be honored; pass \"Serializable\" or omit the option`,\n meta: { dialect: \"sqlite\", isolationLevel: options.isolationLevel },\n });\n }\n\n if (options.timeout !== undefined) {\n throw new VibeError({\n code: \"VIBE_VALIDATION\",\n message:\n \"sqlite has no per-statement timeout, so a transaction `timeout` cannot be enforced database-side (busy_timeout only bounds lock acquisition, not statement runtime) — remove the option\",\n meta: { dialect: \"sqlite\", timeout: options.timeout },\n });\n }\n}\n\n// The NESTED option refusal is ONE copy, shared by every adapter through the\n// runtime's adapter-kit; re-exported here so this adapter's surface is unchanged.\nexport { refuseNestedTransactionOptions } from \"@vibeorm/runtime/adapter-kit\";\n"
|
|
10
11
|
],
|
|
11
|
-
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "FA4A641AD356B7F564756E2164756E21",
|
|
13
14
|
"names": []
|
|
14
15
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reject a prepared tail before stepping the statement. Bun's documented
|
|
3
|
+
* Statement.toString() is sqlite3_expanded_sql: it contains only the compiled
|
|
4
|
+
* first statement. Called BEFORE binding, expansion replaces parameters with
|
|
5
|
+
* NULL, preserving every real terminator (including those inside a trigger).
|
|
6
|
+
* Map its terminator count back to the original text, then allow only SQLite
|
|
7
|
+
* whitespace, empty separators and comments. Script execution never calls this.
|
|
8
|
+
*/
|
|
9
|
+
export declare function assertSinglePreparedStatement(params: {
|
|
10
|
+
text: string;
|
|
11
|
+
expanded: string;
|
|
12
|
+
}): void;
|
|
13
|
+
//# sourceMappingURL=prepared-sql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepared-sql.d.ts","sourceRoot":"","sources":["../src/prepared-sql.ts"],"names":[],"mappings":"AAgEA;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAa9F"}
|
package/dist/queue.d.ts
CHANGED
|
@@ -8,11 +8,21 @@
|
|
|
8
8
|
* chain — including whole `transaction()` calls, which occupy the chain until
|
|
9
9
|
* they commit or roll back (mirroring adapter-pglite).
|
|
10
10
|
*/
|
|
11
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
12
|
/** A serial chain: jobs run one at a time, in the order they were queued. */
|
|
12
13
|
export type OperationQueue = {
|
|
13
14
|
/** Queue `job`, resolving with its result once every earlier job has settled. */
|
|
14
15
|
run<T>(job: () => Promise<T>): Promise<T>;
|
|
15
16
|
};
|
|
17
|
+
/** Connection-wide exclusion, including callback reentry through another wrapper. */
|
|
18
|
+
export type ConnectionOwnership = {
|
|
19
|
+
readonly queue: OperationQueue;
|
|
20
|
+
readonly txContext: AsyncLocalStorage<true>;
|
|
21
|
+
};
|
|
22
|
+
/** Share ownership by injected handle identity without retaining closed databases. */
|
|
23
|
+
export declare function connectionOwnership(params: {
|
|
24
|
+
database?: object;
|
|
25
|
+
}): ConnectionOwnership;
|
|
16
26
|
/** Create an empty operation queue. */
|
|
17
27
|
export declare function createOperationQueue(): OperationQueue;
|
|
18
28
|
//# sourceMappingURL=queue.d.ts.map
|
package/dist/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GAAG;IAC3B,iFAAiF;IACjF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3C,CAAC;AAEF,uCAAuC;AACvC,wBAAgB,oBAAoB,IAAI,cAAc,CAerD"}
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GAAG;IAC3B,iFAAiF;IACjF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3C,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;CAC7C,CAAC;AAIF,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,mBAAmB,CAMtF;AAED,uCAAuC;AACvC,wBAAgB,oBAAoB,IAAI,cAAc,CAerD"}
|
|
@@ -25,17 +25,5 @@ import type { TransactionOptions } from "@vibeorm/runtime";
|
|
|
25
25
|
export declare function validateTransactionOptions(params: {
|
|
26
26
|
options?: TransactionOptions;
|
|
27
27
|
}): void;
|
|
28
|
-
|
|
29
|
-
* Refuse options on a NESTED `transaction()` call — the same contract on every
|
|
30
|
-
* adapter (see the `DatabaseAdapter.transaction` JSDoc in @vibeorm/runtime):
|
|
31
|
-
* a nested transaction is a SAVEPOINT, and a savepoint can neither change the
|
|
32
|
-
* isolation level of the transaction it joins nor enforce its own timeout.
|
|
33
|
-
*
|
|
34
|
-
* @throws VibeError `VIBE_VALIDATION` when `isolationLevel` or `timeout` is
|
|
35
|
-
* present (an `undefined` or empty options object is accepted).
|
|
36
|
-
*/
|
|
37
|
-
export declare function refuseNestedTransactionOptions(params: {
|
|
38
|
-
options?: TransactionOptions;
|
|
39
|
-
provider: string;
|
|
40
|
-
}): void;
|
|
28
|
+
export { refuseNestedTransactionOptions } from "@vibeorm/runtime/adapter-kit";
|
|
41
29
|
//# sourceMappingURL=transaction-options.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-options.d.ts","sourceRoot":"","sources":["../src/transaction-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3D;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,IAAI,CAoBzF;
|
|
1
|
+
{"version":3,"file":"transaction-options.d.ts","sourceRoot":"","sources":["../src/transaction-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3D;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,IAAI,CAoBzF;AAID,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeorm/adapter-sqlite",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "bun:sqlite adapter for VibeORM v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"orm",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"bun": ">=1.2.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@vibeorm/runtime": "2.
|
|
45
|
-
"@vibeorm/schema": "2.
|
|
44
|
+
"@vibeorm/runtime": "2.3.0",
|
|
45
|
+
"@vibeorm/schema": "2.2.0"
|
|
46
46
|
},
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|