@photostructure/sqlite 0.4.0 → 1.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.
- package/CHANGELOG.md +30 -1
- package/README.md +4 -8
- package/binding.gyp +2 -0
- package/dist/index.cjs +247 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -24
- package/dist/index.d.mts +145 -24
- package/dist/index.d.ts +145 -24
- package/dist/index.mjs +247 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
- package/prebuilds/darwin-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/darwin-x64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-arm64/@photostructure+sqlite.musl.node +0 -0
- package/prebuilds/linux-x64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/linux-x64/@photostructure+sqlite.musl.node +0 -0
- package/prebuilds/test_extension.so +0 -0
- package/prebuilds/win32-arm64/@photostructure+sqlite.glibc.node +0 -0
- package/prebuilds/win32-x64/@photostructure+sqlite.glibc.node +0 -0
- package/src/enhance.ts +382 -55
- package/src/index.ts +85 -2
- package/src/sqlite_impl.cpp +133 -10
- package/src/sqlite_impl.h +19 -0
- package/src/types/database-sync-instance.ts +43 -0
- package/src/types/database-sync-options.ts +19 -0
- package/src/upstream/node_sqlite.cc +312 -17
- package/src/upstream/node_sqlite.h +80 -0
- package/src/upstream/sqlite.js +0 -3
- package/src/upstream/sqlite3.c +5027 -3518
- package/src/upstream/sqlite3.h +195 -58
- package/src/upstream/sqlite3ext.h +10 -1
package/dist/index.mjs
CHANGED
|
@@ -317,6 +317,148 @@ function getBeginStatement(mode) {
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
// src/enhance.ts
|
|
320
|
+
var ENHANCED_PREPARE = /* @__PURE__ */ Symbol.for("@photostructure/sqlite:enhancedPrepare");
|
|
321
|
+
function extractFirstColumn(row) {
|
|
322
|
+
if (row == null) return row;
|
|
323
|
+
if (Array.isArray(row)) return row[0];
|
|
324
|
+
const keys = Object.keys(row);
|
|
325
|
+
return keys.length > 0 ? row[keys[0]] : void 0;
|
|
326
|
+
}
|
|
327
|
+
function buildColumnTableMap(stmt) {
|
|
328
|
+
if (typeof stmt.columns !== "function") return void 0;
|
|
329
|
+
const cols = stmt.columns();
|
|
330
|
+
return cols.map((c) => ({
|
|
331
|
+
table: c.table ?? "$",
|
|
332
|
+
column: c.name
|
|
333
|
+
}));
|
|
334
|
+
}
|
|
335
|
+
function expandRowFromArray(row, columnMap) {
|
|
336
|
+
const result = {};
|
|
337
|
+
for (let i = 0; i < columnMap.length && i < row.length; i++) {
|
|
338
|
+
const { table, column } = columnMap[i];
|
|
339
|
+
result[table] ??= {};
|
|
340
|
+
result[table][column] = row[i];
|
|
341
|
+
}
|
|
342
|
+
return result;
|
|
343
|
+
}
|
|
344
|
+
function expandRowFromObject(row, columnMap) {
|
|
345
|
+
const result = {};
|
|
346
|
+
const keys = Object.keys(row);
|
|
347
|
+
for (let i = 0; i < keys.length && i < columnMap.length; i++) {
|
|
348
|
+
const { table, column } = columnMap[i];
|
|
349
|
+
result[table] ??= {};
|
|
350
|
+
result[table][column] = row[keys[i]];
|
|
351
|
+
}
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
function validateToggle(value) {
|
|
355
|
+
const use = value === void 0 ? true : value;
|
|
356
|
+
if (typeof use !== "boolean") {
|
|
357
|
+
throw new TypeError("Expected first argument to be a boolean");
|
|
358
|
+
}
|
|
359
|
+
return use;
|
|
360
|
+
}
|
|
361
|
+
function transformRow(row, mode, columnMap) {
|
|
362
|
+
if (row == null || mode === "flat") return row;
|
|
363
|
+
if (mode === "pluck") return extractFirstColumn(row);
|
|
364
|
+
if (mode === "expand") {
|
|
365
|
+
if (Array.isArray(row)) {
|
|
366
|
+
return expandRowFromArray(row, columnMap);
|
|
367
|
+
}
|
|
368
|
+
return expandRowFromObject(row, columnMap);
|
|
369
|
+
}
|
|
370
|
+
return row;
|
|
371
|
+
}
|
|
372
|
+
function enhanceStatement(stmt) {
|
|
373
|
+
if (typeof stmt.pluck === "function") {
|
|
374
|
+
return stmt;
|
|
375
|
+
}
|
|
376
|
+
let mode = "flat";
|
|
377
|
+
let columnMap;
|
|
378
|
+
const originalGet = typeof stmt.get === "function" ? stmt.get.bind(stmt) : void 0;
|
|
379
|
+
const originalAll = stmt.all.bind(stmt);
|
|
380
|
+
const originalIterate = typeof stmt.iterate === "function" ? stmt.iterate.bind(stmt) : void 0;
|
|
381
|
+
function setMode(target, use) {
|
|
382
|
+
if (use) {
|
|
383
|
+
mode = target;
|
|
384
|
+
if (target === "expand" && columnMap == null) {
|
|
385
|
+
columnMap = buildColumnTableMap(stmt);
|
|
386
|
+
if (columnMap == null) {
|
|
387
|
+
throw new TypeError(
|
|
388
|
+
"expand() requires the statement to have a columns() method"
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
} else if (mode === target) {
|
|
393
|
+
mode = "flat";
|
|
394
|
+
}
|
|
395
|
+
if (typeof stmt.setReturnArrays === "function") {
|
|
396
|
+
stmt.setReturnArrays(mode === "raw" || mode === "expand");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
Object.defineProperty(stmt, "pluck", {
|
|
400
|
+
value: function pluck(toggle) {
|
|
401
|
+
setMode("pluck", validateToggle(toggle));
|
|
402
|
+
return stmt;
|
|
403
|
+
},
|
|
404
|
+
writable: true,
|
|
405
|
+
configurable: true,
|
|
406
|
+
enumerable: false
|
|
407
|
+
});
|
|
408
|
+
Object.defineProperty(stmt, "raw", {
|
|
409
|
+
value: function raw(toggle) {
|
|
410
|
+
setMode("raw", validateToggle(toggle));
|
|
411
|
+
return stmt;
|
|
412
|
+
},
|
|
413
|
+
writable: true,
|
|
414
|
+
configurable: true,
|
|
415
|
+
enumerable: false
|
|
416
|
+
});
|
|
417
|
+
Object.defineProperty(stmt, "expand", {
|
|
418
|
+
value: function expand(toggle) {
|
|
419
|
+
setMode("expand", validateToggle(toggle));
|
|
420
|
+
return stmt;
|
|
421
|
+
},
|
|
422
|
+
writable: true,
|
|
423
|
+
configurable: true,
|
|
424
|
+
enumerable: false
|
|
425
|
+
});
|
|
426
|
+
if (originalGet != null) {
|
|
427
|
+
Object.defineProperty(stmt, "get", {
|
|
428
|
+
value: (...params) => {
|
|
429
|
+
const row = originalGet(...params);
|
|
430
|
+
return transformRow(row, mode, columnMap);
|
|
431
|
+
},
|
|
432
|
+
writable: true,
|
|
433
|
+
configurable: true,
|
|
434
|
+
enumerable: false
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
Object.defineProperty(stmt, "all", {
|
|
438
|
+
value: (...params) => {
|
|
439
|
+
const rows = originalAll(...params);
|
|
440
|
+
if (mode === "flat" || mode === "raw") return rows;
|
|
441
|
+
return rows.map((row) => transformRow(row, mode, columnMap));
|
|
442
|
+
},
|
|
443
|
+
writable: true,
|
|
444
|
+
configurable: true,
|
|
445
|
+
enumerable: false
|
|
446
|
+
});
|
|
447
|
+
if (originalIterate != null) {
|
|
448
|
+
Object.defineProperty(stmt, "iterate", {
|
|
449
|
+
value: function* (...params) {
|
|
450
|
+
const iter = originalIterate(...params);
|
|
451
|
+
for (const row of iter) {
|
|
452
|
+
yield transformRow(row, mode, columnMap);
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
writable: true,
|
|
456
|
+
configurable: true,
|
|
457
|
+
enumerable: false
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
return stmt;
|
|
461
|
+
}
|
|
320
462
|
function pragmaImpl(source, options) {
|
|
321
463
|
if (typeof source !== "string") {
|
|
322
464
|
throw new TypeError("Expected first argument to be a string");
|
|
@@ -329,20 +471,10 @@ function pragmaImpl(source, options) {
|
|
|
329
471
|
throw new TypeError('Expected the "simple" option to be a boolean');
|
|
330
472
|
}
|
|
331
473
|
const stmt = this.prepare(`PRAGMA ${source}`);
|
|
332
|
-
const rows = stmt.all();
|
|
333
474
|
if (simple) {
|
|
334
|
-
|
|
335
|
-
if (firstRow == null) {
|
|
336
|
-
return void 0;
|
|
337
|
-
}
|
|
338
|
-
const keys = Object.keys(firstRow);
|
|
339
|
-
const firstKey = keys[0];
|
|
340
|
-
if (firstKey == null) {
|
|
341
|
-
return void 0;
|
|
342
|
-
}
|
|
343
|
-
return firstRow[firstKey];
|
|
475
|
+
return extractFirstColumn(stmt.all()[0]);
|
|
344
476
|
}
|
|
345
|
-
return
|
|
477
|
+
return stmt.all();
|
|
346
478
|
}
|
|
347
479
|
function transactionImpl(fn) {
|
|
348
480
|
return createTransaction(this, fn);
|
|
@@ -351,21 +483,45 @@ function hasEnhancedMethods(db) {
|
|
|
351
483
|
return typeof db.pragma === "function" && typeof db.transaction === "function";
|
|
352
484
|
}
|
|
353
485
|
function enhance(db) {
|
|
354
|
-
if (hasEnhancedMethods(db)) {
|
|
355
|
-
|
|
486
|
+
if (!hasEnhancedMethods(db)) {
|
|
487
|
+
Object.defineProperty(db, "pragma", {
|
|
488
|
+
value: pragmaImpl,
|
|
489
|
+
writable: true,
|
|
490
|
+
configurable: true,
|
|
491
|
+
enumerable: false
|
|
492
|
+
});
|
|
493
|
+
Object.defineProperty(db, "transaction", {
|
|
494
|
+
value: transactionImpl,
|
|
495
|
+
writable: true,
|
|
496
|
+
configurable: true,
|
|
497
|
+
enumerable: false
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
if (!db[ENHANCED_PREPARE]) {
|
|
501
|
+
const originalPrepare = db.prepare.bind(db);
|
|
502
|
+
Object.defineProperty(db, "prepare", {
|
|
503
|
+
value: (...args) => {
|
|
504
|
+
const stmt = originalPrepare(...args);
|
|
505
|
+
enhanceStatement(stmt);
|
|
506
|
+
Object.defineProperty(stmt, "database", {
|
|
507
|
+
value: db,
|
|
508
|
+
writable: false,
|
|
509
|
+
configurable: true,
|
|
510
|
+
enumerable: false
|
|
511
|
+
});
|
|
512
|
+
return stmt;
|
|
513
|
+
},
|
|
514
|
+
writable: true,
|
|
515
|
+
configurable: true,
|
|
516
|
+
enumerable: false
|
|
517
|
+
});
|
|
518
|
+
Object.defineProperty(db, ENHANCED_PREPARE, {
|
|
519
|
+
value: true,
|
|
520
|
+
writable: false,
|
|
521
|
+
configurable: false,
|
|
522
|
+
enumerable: false
|
|
523
|
+
});
|
|
356
524
|
}
|
|
357
|
-
Object.defineProperty(db, "pragma", {
|
|
358
|
-
value: pragmaImpl,
|
|
359
|
-
writable: true,
|
|
360
|
-
configurable: true,
|
|
361
|
-
enumerable: false
|
|
362
|
-
});
|
|
363
|
-
Object.defineProperty(db, "transaction", {
|
|
364
|
-
value: transactionImpl,
|
|
365
|
-
writable: true,
|
|
366
|
-
configurable: true,
|
|
367
|
-
enumerable: false
|
|
368
|
-
});
|
|
369
525
|
return db;
|
|
370
526
|
}
|
|
371
527
|
function isEnhanced(db) {
|
|
@@ -388,6 +544,71 @@ DatabaseSync.prototype = _DatabaseSync.prototype;
|
|
|
388
544
|
DatabaseSync.prototype.createTagStore = function(capacity) {
|
|
389
545
|
return new SQLTagStore(this, capacity);
|
|
390
546
|
};
|
|
547
|
+
var LIMIT_MAPPING = [
|
|
548
|
+
{ name: "length", id: 0 },
|
|
549
|
+
{ name: "sqlLength", id: 1 },
|
|
550
|
+
{ name: "column", id: 2 },
|
|
551
|
+
{ name: "exprDepth", id: 3 },
|
|
552
|
+
{ name: "compoundSelect", id: 4 },
|
|
553
|
+
{ name: "vdbeOp", id: 5 },
|
|
554
|
+
{ name: "functionArg", id: 6 },
|
|
555
|
+
{ name: "attach", id: 7 },
|
|
556
|
+
{ name: "likePatternLength", id: 8 },
|
|
557
|
+
{ name: "variableNumber", id: 9 },
|
|
558
|
+
{ name: "triggerDepth", id: 10 }
|
|
559
|
+
];
|
|
560
|
+
var INT_MAX = 2147483647;
|
|
561
|
+
var limitsCache = /* @__PURE__ */ new WeakMap();
|
|
562
|
+
function validateLimitValue(value) {
|
|
563
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
564
|
+
throw new TypeError(
|
|
565
|
+
"Limit value must be a non-negative integer or Infinity."
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
if (value === Infinity) {
|
|
569
|
+
return INT_MAX;
|
|
570
|
+
}
|
|
571
|
+
if (!Number.isFinite(value) || value !== Math.trunc(value)) {
|
|
572
|
+
throw new TypeError(
|
|
573
|
+
"Limit value must be a non-negative integer or Infinity."
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
if (value < 0) {
|
|
577
|
+
throw new RangeError("Limit value must be non-negative.");
|
|
578
|
+
}
|
|
579
|
+
return value;
|
|
580
|
+
}
|
|
581
|
+
function createLimitsObject(db) {
|
|
582
|
+
const obj = /* @__PURE__ */ Object.create(null);
|
|
583
|
+
for (const { name, id } of LIMIT_MAPPING) {
|
|
584
|
+
Object.defineProperty(obj, name, {
|
|
585
|
+
get() {
|
|
586
|
+
return db.getLimit(id);
|
|
587
|
+
},
|
|
588
|
+
set(value) {
|
|
589
|
+
const validated = validateLimitValue(value);
|
|
590
|
+
db.setLimit(id, validated);
|
|
591
|
+
},
|
|
592
|
+
enumerable: true,
|
|
593
|
+
configurable: false
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
return obj;
|
|
597
|
+
}
|
|
598
|
+
if (!Object.getOwnPropertyDescriptor(DatabaseSync.prototype, "limits")) {
|
|
599
|
+
Object.defineProperty(DatabaseSync.prototype, "limits", {
|
|
600
|
+
get() {
|
|
601
|
+
let obj = limitsCache.get(this);
|
|
602
|
+
if (obj == null) {
|
|
603
|
+
obj = createLimitsObject(this);
|
|
604
|
+
limitsCache.set(this, obj);
|
|
605
|
+
}
|
|
606
|
+
return obj;
|
|
607
|
+
},
|
|
608
|
+
enumerable: true,
|
|
609
|
+
configurable: true
|
|
610
|
+
});
|
|
611
|
+
}
|
|
391
612
|
var _StatementSync = binding.StatementSync;
|
|
392
613
|
var StatementSync = function StatementSync2() {
|
|
393
614
|
const err = new TypeError("Illegal constructor");
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/index.ts","../src/stack-path.ts","../src/dirname.ts","../src/lru-cache.ts","../src/sql-tag-store.ts","../src/transaction.ts","../src/enhance.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","// Load the native binding with support for both CJS and ESM\nimport nodeGypBuild from \"node-gyp-build\";\nimport { join } from \"node:path\";\nimport { _dirname } from \"./dirname\";\nimport { SQLTagStore } from \"./sql-tag-store\";\nimport { DatabaseSyncInstance } from \"./types/database-sync-instance\";\nimport { DatabaseSyncOptions } from \"./types/database-sync-options\";\nimport { SQLTagStoreInstance } from \"./types/sql-tag-store-instance\";\nimport { SqliteAuthorizationActions } from \"./types/sqlite-authorization-actions\";\nimport { SqliteAuthorizationResults } from \"./types/sqlite-authorization-results\";\nimport { SqliteChangesetConflictTypes } from \"./types/sqlite-changeset-conflict-types\";\nimport { SqliteChangesetResolution } from \"./types/sqlite-changeset-resolution\";\nimport { SqliteOpenFlags } from \"./types/sqlite-open-flags\";\nimport { StatementSyncInstance } from \"./types/statement-sync-instance\";\n\nexport type { AggregateOptions } from \"./types/aggregate-options\";\nexport type { ChangesetApplyOptions } from \"./types/changeset-apply-options\";\nexport type { DatabaseSyncInstance } from \"./types/database-sync-instance\";\nexport type { DatabaseSyncOptions } from \"./types/database-sync-options\";\nexport type { PragmaOptions } from \"./types/pragma-options\";\nexport type { SessionOptions } from \"./types/session-options\";\nexport type { SQLTagStoreInstance } from \"./types/sql-tag-store-instance\";\nexport type { SqliteAuthorizationActions } from \"./types/sqlite-authorization-actions\";\nexport type { SqliteAuthorizationResults } from \"./types/sqlite-authorization-results\";\nexport type { SqliteChangesetConflictTypes } from \"./types/sqlite-changeset-conflict-types\";\nexport type { SqliteChangesetResolution } from \"./types/sqlite-changeset-resolution\";\nexport type { SqliteOpenFlags } from \"./types/sqlite-open-flags\";\nexport type {\n StatementColumnMetadata,\n StatementSyncInstance,\n} from \"./types/statement-sync-instance\";\nexport type { TransactionFunction, TransactionMode } from \"./types/transaction\";\nexport type { UserFunctionOptions } from \"./types/user-functions-options\";\n\n// Enhancement utilities for adding better-sqlite3-style methods to any compatible database\nexport {\n enhance,\n isEnhanced,\n type EnhanceableDatabaseSync,\n type EnhancedDatabaseSync,\n type EnhancedMethods,\n} from \"./enhance\";\n\n// Use _dirname() helper that works in both CJS/ESM and Jest\nconst binding = nodeGypBuild(join(_dirname(), \"..\"));\n\n/**\n * All SQLite constants exported by this module.\n *\n * This is a union of all constant category interfaces:\n * - {@link SqliteOpenFlags} - Database open flags (extension beyond `node:sqlite`)\n * - {@link SqliteChangesetResolution} - Changeset conflict resolution values\n * - {@link SqliteChangesetConflictTypes} - Changeset conflict type codes\n * - {@link SqliteAuthorizationResults} - Authorization return values\n * - {@link SqliteAuthorizationActions} - Authorization action codes\n *\n * **Note:** The categorized interfaces (`SqliteOpenFlags`, etc.) are extensions\n * provided by `@photostructure/sqlite`. The `node:sqlite` module exports only\n * a flat `constants` object without these type categories.\n */\nexport type SqliteConstants = SqliteOpenFlags &\n SqliteChangesetResolution &\n SqliteChangesetConflictTypes &\n SqliteAuthorizationResults &\n SqliteAuthorizationActions;\n\n/**\n * Options for creating a prepared statement.\n *\n * **Note:** The per-statement override options (`readBigInts`, `returnArrays`,\n * `allowBareNamedParameters`, `allowUnknownNamedParameters`) are a **Node.js v25+**\n * feature. On Node.js v24 and earlier, `node:sqlite` silently ignores these options.\n * This library implements them for forward compatibility with Node.js v25+.\n */\nexport interface StatementOptions {\n /** If true, the prepared statement's expandedSQL property will contain the expanded SQL. @default false */\n readonly expandedSQL?: boolean;\n /** If true, anonymous parameters are enabled for the statement. @default false */\n readonly anonymousParameters?: boolean;\n /**\n * If true, read integer values as JavaScript BigInt. Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly readBigInts?: boolean;\n /**\n * If true, return results as arrays rather than objects. Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly returnArrays?: boolean;\n /**\n * If true, allows bare named parameters (without prefix). Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly allowBareNamedParameters?: boolean;\n /**\n * If true, unknown named parameters are ignored. Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly allowUnknownNamedParameters?: boolean;\n}\n\nexport interface Session {\n /**\n * Generate a changeset containing all changes recorded by the session.\n * @returns A Uint8Array containing the changeset data.\n */\n changeset(): Uint8Array;\n /**\n * Generate a patchset containing all changes recorded by the session.\n * @returns A Uint8Array containing the patchset data.\n */\n patchset(): Uint8Array;\n /**\n * Close the session and release its resources.\n */\n close(): void;\n}\n\n/**\n * The main SQLite module interface.\n */\nexport interface SqliteModule {\n /**\n * The DatabaseSync class represents a synchronous connection to a SQLite database.\n * All operations are performed synchronously, blocking until completion.\n */\n DatabaseSync: new (\n location?: string | Buffer | URL,\n options?: DatabaseSyncOptions,\n ) => DatabaseSyncInstance;\n /**\n * The StatementSync class represents a synchronous prepared statement.\n * This class should not be instantiated directly; use Database.prepare() instead.\n */\n StatementSync: new (\n database: DatabaseSyncInstance,\n sql: string,\n options?: StatementOptions,\n ) => StatementSyncInstance;\n /**\n * The Session class for recording database changes.\n * This class should not be instantiated directly; use Database.createSession() instead.\n */\n Session: new () => Session;\n /**\n * SQLite constants for various operations and flags.\n * @see {@link SqliteConstants} for the type definition\n * @see {@link SqliteOpenFlags} for database open flags (extension beyond `node:sqlite`)\n * @see {@link SqliteChangesetResolution} for changeset conflict resolution values\n * @see {@link SqliteChangesetConflictTypes} for changeset conflict type codes\n * @see {@link SqliteAuthorizationResults} for authorization return values\n * @see {@link SqliteAuthorizationActions} for authorization action codes\n */\n constants: SqliteConstants;\n}\n\n/**\n * The DatabaseSync class represents a synchronous connection to a SQLite database.\n * All database operations are performed synchronously, blocking the thread until completion.\n *\n * @example\n * ```typescript\n * import { DatabaseSync } from '@photostructure/sqlite';\n *\n * // Create an in-memory database\n * const db = new DatabaseSync(':memory:');\n *\n * // Create a file-based database\n * const fileDb = new DatabaseSync('./mydata.db');\n *\n * // Create with options\n * const readOnlyDb = new DatabaseSync('./data.db', { readOnly: true });\n * ```\n */\n// Store the native binding's DatabaseSync\nconst _DatabaseSync = binding.DatabaseSync;\n// Wrapper around the native constructor to enforce usage of `new` with the correct error code.\n// We use a function wrapper instead of a Proxy for better performance and explicit prototype handling.\nexport const DatabaseSync = function DatabaseSync(this: any, ...args: any[]) {\n if (!new.target) {\n const err = new TypeError(\"Cannot call constructor without `new`\");\n (err as NodeJS.ErrnoException).code = \"ERR_CONSTRUCT_CALL_REQUIRED\";\n throw err;\n }\n return Reflect.construct(_DatabaseSync, args, new.target);\n} as unknown as SqliteModule[\"DatabaseSync\"];\nObject.setPrototypeOf(DatabaseSync, _DatabaseSync);\nDatabaseSync.prototype = _DatabaseSync.prototype;\n\n// node:sqlite implements createTagStore and SQLTagStore entirely in native C++.\n// We use a TypeScript implementation instead, attached via prototype extension.\n// This maintains API compatibility with node:sqlite while avoiding the complexity\n// of a native LRU cache. Performance is equivalent since the real cost is SQLite\n// execution, not cache lookups - V8's Map is highly optimized for string keys.\n(DatabaseSync.prototype as DatabaseSyncInstance).createTagStore = function (\n this: DatabaseSyncInstance,\n capacity?: number,\n): SQLTagStoreInstance {\n return new SQLTagStore(this, capacity);\n};\n\n// NOTE: .pragma() and .transaction() are NOT added to the prototype by default.\n// This keeps DatabaseSync 100% API-compatible with node:sqlite.\n// Users who want better-sqlite3-style methods should use enhance():\n//\n// import { DatabaseSync, enhance } from '@photostructure/sqlite';\n// const db = enhance(new DatabaseSync(':memory:'));\n// db.pragma('journal_mode', { simple: true });\n// db.transaction(() => { ... });\n\n/**\n * The StatementSync class represents a prepared SQL statement.\n * This class should not be instantiated directly; use DatabaseSync.prepare() instead.\n *\n * @example\n * ```typescript\n * const stmt = db.prepare('SELECT * FROM users WHERE id = ?');\n * const user = stmt.get(123);\n * stmt.finalize();\n * ```\n */\n// Store the native binding's StatementSync for internal use\nconst _StatementSync = binding.StatementSync;\n// Export a wrapper that throws ERR_ILLEGAL_CONSTRUCTOR when called directly\n// but preserves instanceof checks and prototype chain\nexport const StatementSync = function StatementSync() {\n const err = new TypeError(\"Illegal constructor\");\n (err as NodeJS.ErrnoException).code = \"ERR_ILLEGAL_CONSTRUCTOR\";\n throw err;\n} as unknown as SqliteModule[\"StatementSync\"];\n// Use the native prototype directly so instanceof checks work correctly\n// (stmt instanceof StatementSync will check if StatementSync.prototype is in stmt's chain)\nStatementSync.prototype = _StatementSync.prototype;\n\n/**\n * The Session class for recording database changes.\n * This class should not be instantiated directly; use DatabaseSync.createSession() instead.\n *\n * @example\n * ```typescript\n * const session = db.createSession({ table: 'users' });\n * // Make some changes to the users table\n * const changeset = session.changeset();\n * session.close();\n * ```\n */\nexport const Session = binding.Session as SqliteModule[\"Session\"];\n\n/**\n * The SQLTagStore class for cached prepared statements via tagged template syntax.\n * This class should not be instantiated directly; use DatabaseSync.createTagStore() instead.\n *\n * @example\n * ```typescript\n * const sql = db.createTagStore();\n * sql.run`INSERT INTO users VALUES (${id}, ${name})`;\n * const user = sql.get`SELECT * FROM users WHERE id = ${id}`;\n * ```\n */\nexport { SQLTagStore };\n\n/**\n * SQLite constants for various operations and flags.\n *\n * @example\n * ```typescript\n * import { constants } from '@photostructure/sqlite';\n *\n * const db = new DatabaseSync('./data.db', {\n * readOnly: true,\n * // Uses SQLITE_OPEN_READONLY internally\n * });\n * ```\n */\nexport const constants: SqliteConstants = binding.constants;\n\n/**\n * Options for the backup() function.\n */\nexport interface BackupOptions {\n /** Number of pages to be transmitted in each batch of the backup. @default 100 */\n rate?: number;\n /** Name of the source database. Can be 'main' or any attached database. @default 'main' */\n source?: string;\n /** Name of the target database. Can be 'main' or any attached database. @default 'main' */\n target?: string;\n /** Callback function that will be called with progress information. */\n progress?: (info: { totalPages: number; remainingPages: number }) => void;\n}\n\n/**\n * Standalone function to make a backup of a database.\n *\n * This function matches the Node.js `node:sqlite` module API which exports\n * `backup()` as a standalone function in addition to the `db.backup()` method.\n *\n * @param sourceDb The database to backup from.\n * @param destination The path where the backup will be created.\n * @param options Optional configuration for the backup operation.\n * @returns A promise that resolves when the backup is completed.\n *\n * @example\n * ```typescript\n * import { DatabaseSync, backup } from '@photostructure/sqlite';\n *\n * const db = new DatabaseSync('./source.db');\n * await backup(db, './backup.db');\n *\n * // With options\n * await backup(db, './backup.db', {\n * rate: 10,\n * progress: ({ totalPages, remainingPages }) => {\n * console.log(`Progress: ${totalPages - remainingPages}/${totalPages}`);\n * }\n * });\n * ```\n */\nexport const backup: (\n sourceDb: DatabaseSyncInstance,\n destination: string | Buffer | URL,\n options?: BackupOptions,\n) => Promise<number> = binding.backup;\n\n// Default export for CommonJS compatibility\nexport default binding as SqliteModule;\n","import { dirname } from \"node:path\";\n\nexport function getCallerDirname(): string {\n const e = new Error();\n if (e.stack == null) {\n Error.captureStackTrace(e);\n }\n return dirname(extractCallerPath(e.stack as string));\n}\n\n// Comprehensive regex patterns for different stack frame formats\nconst patterns =\n process.platform === \"win32\"\n ? [\n // File URLs: \"at functionName (file:///C:/path/file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>file:\\/\\/\\/.+?):\\d+:\\d+\\)$/,\n // File URLs direct: \"at file:///C:/path/file.js:1:1\"\n /\\bat\\s(?<path>file:\\/\\/\\/.+?):\\d+:\\d+$/,\n // Standard: \"at functionName (C:\\path\\file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>[A-Z]:\\\\.+):\\d+:\\d+\\)$/,\n // direct: \"at C:\\path\\file.js:1:1\"\n /\\bat\\s(?<path>[A-Z]:\\\\.+):\\d+:\\d+$/,\n // UNC: \"at functionName (\\\\server\\share\\path\\file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>\\\\\\\\.+):\\d+:\\d+\\)$/,\n // direct: \"at \\\\server\\share\\path\\file.js:1:1\"\n /\\bat\\s(?<path>\\\\\\\\.+):\\d+:\\d+$/,\n ]\n : [\n // Standard: \"at functionName (/path/file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>\\/.+?):\\d+:\\d+\\)$/,\n // Anonymous or direct: \"at /path/file.js:1:1\"\n // eslint-disable-next-line security/detect-unsafe-regex -- Pattern is safe: no nested quantifiers\n /\\bat\\s(?:[^\\s()]+\\s)?(?<path>\\/[^:]+):\\d+:\\d+$/,\n ];\n\nconst MaybeUrlRE = /^[a-z]{2,5}:\\/\\//i;\n\n// only exposed for tests:\nexport function extractCallerPath(stack: string): string {\n const frames = stack.split(\"\\n\").filter(Boolean);\n\n // First find getCallerDirname() in the stack:\n const callerFrame = frames.findIndex((frame) =>\n frame.includes(\"getCallerDirname\"),\n );\n if (callerFrame === -1) {\n throw new Error(\"Invalid stack trace format: missing caller frame\");\n }\n for (let i = callerFrame + 1; i < frames.length; i++) {\n // eslint-disable-next-line security/detect-object-injection -- Index is from controlled for-loop\n const frame = frames[i];\n for (const pattern of patterns) {\n const g = frame?.trim().match(pattern)?.groups;\n if (g != null && g[\"path\"]) {\n const path = g[\"path\"];\n // Windows requires us to check if it's a reasonable URL, as URL accepts\n // \"C:\\\\path\\\\file.txt\" as valid (!!)\n if (MaybeUrlRE.test(path)) {\n try {\n return new URL(path).pathname;\n } catch {\n // ignore\n }\n }\n return path;\n }\n }\n }\n throw new Error(\"Invalid stack trace format: no parsable frames\");\n}\n","import { getCallerDirname } from \"./stack-path\";\n\n// Thanks to tsup shims, __dirname should always be defined except when run by\n// jest (which will use the stack_path shim)\nexport function _dirname() {\n try {\n if (typeof __dirname !== \"undefined\") return __dirname;\n } catch {\n // ignore\n }\n // we must be in jest. Use the stack_path ~~hack~~ shim:\n return getCallerDirname();\n}\n","/**\n * Simple LRU (Least Recently Used) cache implementation.\n * Uses Map's insertion order to track recency - first key is oldest.\n */\nexport class LRUCache<K, V> {\n private cache = new Map<K, V>();\n private readonly maxCapacity: number;\n\n constructor(capacity: number) {\n if (capacity < 1) {\n throw new RangeError(\"LRU cache capacity must be at least 1\");\n }\n this.maxCapacity = capacity;\n }\n\n /**\n * Get a value from the cache.\n * If found, moves the entry to the end (most recently used).\n */\n get(key: K): V | undefined {\n const value = this.cache.get(key);\n if (value !== undefined) {\n // Move to end (most recently used) by reinserting\n this.cache.delete(key);\n this.cache.set(key, value);\n }\n return value;\n }\n\n /**\n * Set a value in the cache.\n * If key exists, updates and moves to end.\n * If at capacity, evicts the oldest entry first.\n */\n set(key: K, value: V): void {\n if (this.cache.has(key)) {\n // Update existing - delete and reinsert at end\n this.cache.delete(key);\n } else if (this.cache.size >= this.maxCapacity) {\n // Evict oldest (first key in Map iteration order)\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * Delete an entry from the cache.\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Check if a key exists in the cache.\n * Does NOT update recency.\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * Clear all entries from the cache.\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get the current number of entries in the cache.\n */\n size(): number {\n return this.cache.size;\n }\n\n /**\n * Get the maximum capacity of the cache.\n */\n capacity(): number {\n return this.maxCapacity;\n }\n}\n","import { LRUCache } from \"./lru-cache\";\nimport { DatabaseSyncInstance } from \"./types/database-sync-instance\";\nimport type { StatementSyncInstance } from \"./types/statement-sync-instance\";\n\n/**\n * Default capacity for the statement cache.\n * Matches Node.js SQLTagStore default.\n */\nconst DEFAULT_CAPACITY = 1000;\n\n/**\n * SQLTagStore provides cached prepared statements via tagged template syntax.\n *\n * @example\n * ```js\n * const sql = db.createTagStore();\n * sql.run`INSERT INTO users VALUES (${id}, ${name})`;\n * const user = sql.get`SELECT * FROM users WHERE id = ${id}`;\n * ```\n */\nexport class SQLTagStore {\n private readonly database: DatabaseSyncInstance;\n private readonly cache: LRUCache<string, StatementSyncInstance>;\n private readonly maxCapacity: number;\n\n constructor(db: DatabaseSyncInstance, capacity: number = DEFAULT_CAPACITY) {\n if (!db.isOpen) {\n const err = new Error(\"database is not open\");\n (err as NodeJS.ErrnoException).code = \"ERR_INVALID_STATE\";\n throw err;\n }\n this.database = db;\n this.maxCapacity = capacity;\n this.cache = new LRUCache(capacity);\n }\n\n /**\n * Returns the associated database instance.\n */\n get db(): DatabaseSyncInstance {\n return this.database;\n }\n\n /**\n * Returns the maximum capacity of the statement cache.\n */\n get capacity(): number {\n return this.maxCapacity;\n }\n\n /**\n * Returns the current number of cached statements.\n */\n get size(): number {\n return this.cache.size();\n }\n\n /**\n * Clears all cached statements.\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Execute an INSERT, UPDATE, DELETE or other statement that doesn't return rows.\n * Returns an object with `changes` and `lastInsertRowid`.\n */\n run(\n strings: TemplateStringsArray,\n ...values: unknown[]\n ): { changes: number; lastInsertRowid: number | bigint } {\n const stmt = this.getOrPrepare(strings);\n return stmt.run(...values);\n }\n\n /**\n * Execute a query and return the first row, or undefined if no rows.\n */\n get(strings: TemplateStringsArray, ...values: unknown[]): unknown {\n const stmt = this.getOrPrepare(strings);\n return stmt.get(...values);\n }\n\n /**\n * Execute a query and return all rows as an array.\n */\n all(strings: TemplateStringsArray, ...values: unknown[]): unknown[] {\n const stmt = this.getOrPrepare(strings);\n return stmt.all(...values);\n }\n\n /**\n * Execute a query and return an iterator over the rows.\n */\n iterate(\n strings: TemplateStringsArray,\n ...values: unknown[]\n ): IterableIterator<unknown> {\n const stmt = this.getOrPrepare(strings);\n return stmt.iterate(...values);\n }\n\n /**\n * Get a cached statement or prepare a new one.\n */\n private getOrPrepare(strings: TemplateStringsArray): StatementSyncInstance {\n if (!this.database.isOpen) {\n throw new Error(\"database is not open\");\n }\n\n const sql = this.buildSQL(strings);\n\n // Check cache\n const cached = this.cache.get(sql);\n if (cached) {\n return cached;\n }\n\n // Prepare new statement and cache it\n const stmt = this.database.prepare(sql);\n this.cache.set(sql, stmt);\n return stmt;\n }\n\n /**\n * Build the SQL string by joining template parts with `?` placeholders.\n */\n private buildSQL(strings: TemplateStringsArray): string {\n let sql = strings[0] ?? \"\";\n for (let i = 1; i < strings.length; i++) {\n // eslint-disable-next-line security/detect-object-injection -- Index is from controlled for-loop\n sql += \"?\" + (strings[i] ?? \"\");\n }\n return sql;\n }\n}\n","import type { DatabaseSyncInstance } from \"./types/database-sync-instance\";\nimport type { TransactionFunction, TransactionMode } from \"./types/transaction\";\n\n/**\n * Internal counter for generating unique savepoint names.\n * Using a global counter ensures uniqueness even with deeply nested transactions.\n */\nlet savepointCounter = 0;\n\n/**\n * Creates a transaction-wrapped version of a function.\n *\n * When the returned function is called, it will:\n * 1. Begin a transaction (or create a savepoint if already in a transaction)\n * 2. Execute the wrapped function\n * 3. Commit the transaction (or release the savepoint) on success\n * 4. Rollback the transaction (or rollback to savepoint) on error\n *\n * The wrapped function **must not** return a Promise. SQLite transactions are\n * synchronous, and allowing async operations would leave the transaction open\n * across event loop ticks, which is dangerous and can cause deadlocks.\n *\n * @example\n * ```typescript\n * const db = new DatabaseSync(':memory:');\n * db.exec('CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT)');\n *\n * const insert = db.prepare('INSERT INTO items (name) VALUES (?)');\n *\n * // Create a transaction function\n * const insertMany = db.transaction((names: string[]) => {\n * for (const name of names) {\n * insert.run(name);\n * }\n * return names.length;\n * });\n *\n * // Execute - automatically wrapped in BEGIN/COMMIT\n * const count = insertMany(['Alice', 'Bob', 'Charlie']);\n * console.log(count); // 3\n *\n * // If an error occurs, automatically rolls back\n * try {\n * insertMany(['Dave', 'FAIL']); // Assume this throws\n * } catch (e) {\n * // Transaction was rolled back, Dave was not inserted\n * }\n *\n * // Use different transaction modes\n * insertMany.immediate(['Eve']); // BEGIN IMMEDIATE\n * insertMany.exclusive(['Frank']); // BEGIN EXCLUSIVE\n * ```\n *\n * @param db - The database connection\n * @param fn - The function to wrap in a transaction\n * @returns A transaction function with `.deferred`, `.immediate`, and `.exclusive` variants\n */\nexport function createTransaction<F extends (...args: any[]) => any>(\n db: DatabaseSyncInstance,\n fn: F,\n): TransactionFunction<F> {\n if (typeof fn !== \"function\") {\n throw new TypeError(\"Expected first argument to be a function\");\n }\n\n // Create all four variants\n const variants = {\n deferred: createVariant(db, fn, \"deferred\"),\n immediate: createVariant(db, fn, \"immediate\"),\n exclusive: createVariant(db, fn, \"exclusive\"),\n };\n\n // The default function uses DEFERRED mode (SQLite's default)\n const defaultFn = variants.deferred as TransactionFunction<F>;\n\n // Set up the variant properties on each function\n // Each variant has access to all other variants\n for (const variant of Object.values(variants)) {\n Object.defineProperties(variant, {\n deferred: { value: variants.deferred, enumerable: true },\n immediate: { value: variants.immediate, enumerable: true },\n exclusive: { value: variants.exclusive, enumerable: true },\n database: { value: db, enumerable: true },\n });\n }\n\n return defaultFn;\n}\n\n/**\n * Creates a single transaction variant for a specific mode.\n */\nfunction createVariant<F extends (...args: any[]) => any>(\n db: DatabaseSyncInstance,\n fn: F,\n mode: TransactionMode,\n): (...args: Parameters<F>) => ReturnType<F> {\n const beginStatement = getBeginStatement(mode);\n\n return function transactionWrapper(\n this: unknown,\n ...args: Parameters<F>\n ): ReturnType<F> {\n // Check if we're already in a transaction (nested transaction)\n const isNested = db.isTransaction;\n\n let begin: string;\n let commit: string;\n let rollback: string;\n\n if (isNested) {\n // Use savepoints for nested transactions\n // The savepoint name uses backticks to allow special characters\n // and a counter to ensure uniqueness\n const savepointName = `\\`_txn_${++savepointCounter}\\``;\n begin = `SAVEPOINT ${savepointName}`;\n commit = `RELEASE ${savepointName}`;\n rollback = `ROLLBACK TO ${savepointName}`;\n } else {\n // Top-level transaction\n begin = beginStatement;\n commit = \"COMMIT\";\n rollback = \"ROLLBACK\";\n }\n\n // Begin the transaction or savepoint\n db.exec(begin);\n\n try {\n // Execute the wrapped function\n const result = fn.apply(this, args);\n\n // Check for promises - async functions break transaction semantics\n if (result !== null && typeof result === \"object\" && \"then\" in result) {\n throw new TypeError(\n \"Transaction function must not return a Promise. \" +\n \"SQLite transactions are synchronous and cannot span across async operations. \" +\n \"Use synchronous code within transactions.\",\n );\n }\n\n // Commit the transaction or release the savepoint\n db.exec(commit);\n\n return result;\n } catch (error) {\n // Only attempt rollback if we're still in a transaction\n // (SQLite may have already rolled back due to constraint violations, etc.)\n if (db.isTransaction) {\n db.exec(rollback);\n // For nested transactions, we also need to release the savepoint\n // after rolling back to it (the savepoint still exists after ROLLBACK TO)\n if (isNested) {\n db.exec(commit);\n }\n }\n\n throw error;\n }\n };\n}\n\n/**\n * Returns the appropriate BEGIN statement for a transaction mode.\n */\nfunction getBeginStatement(mode: TransactionMode): string {\n switch (mode) {\n case \"deferred\":\n return \"BEGIN DEFERRED\";\n case \"immediate\":\n return \"BEGIN IMMEDIATE\";\n case \"exclusive\":\n return \"BEGIN EXCLUSIVE\";\n default:\n // TypeScript should catch this, but just in case\n throw new Error(`Unknown transaction mode: ${mode}`);\n }\n}\n","/**\n * Enhancement utilities for adding better-sqlite3-style methods to any\n * compatible database, including `node:sqlite` DatabaseSync and this package's\n * DatabaseSync.\n *\n * This module provides the `enhance()` function which adds `.pragma()` and\n * `.transaction()` methods to database instances that don't have them (e.g.,\n * node:sqlite DatabaseSync).\n */\n\nimport { createTransaction } from \"./transaction\";\nimport type { PragmaOptions } from \"./types/pragma-options\";\nimport type { TransactionFunction } from \"./types/transaction\";\n\n/**\n * Minimal interface for a database that can be enhanced. This matches the\n * subset of functionality needed by pragma() and transaction().\n */\nexport interface EnhanceableDatabaseSync {\n /** Execute SQL without returning results */\n exec(sql: string): void;\n /** Prepare a statement that can return results */\n prepare(sql: string): { all(): unknown[] };\n /** Whether a transaction is currently active */\n readonly isTransaction: boolean;\n}\n\n/**\n * Interface for an enhanced database with pragma() and transaction() methods.\n */\nexport interface EnhancedMethods {\n /**\n * Executes a PRAGMA statement and returns its result.\n *\n * @param source The PRAGMA command (without \"PRAGMA\" prefix)\n * @param options Optional configuration\n * @returns Array of rows, or single value if `simple: true`\n *\n * @example\n * ```typescript\n * db.pragma('cache_size', { simple: true }); // -16000\n * db.pragma('journal_mode = wal');\n * ```\n */\n pragma(source: string, options?: PragmaOptions): unknown;\n\n /**\n * Creates a function that always runs inside a transaction.\n *\n * @param fn The function to wrap in a transaction\n * @returns A transaction function with `.deferred`, `.immediate`,\n * `.exclusive` variants\n *\n * @example\n * ```typescript\n * const insertMany = db.transaction((items) => {\n * for (const item of items) insert.run(item);\n * });\n * insertMany(['a', 'b', 'c']); // All in one transaction\n * ```\n */\n transaction<F extends (...args: any[]) => any>(fn: F): TransactionFunction<F>;\n}\n\n/**\n * A database instance that has been enhanced with pragma() and transaction() methods.\n */\nexport type EnhancedDatabaseSync<T extends EnhanceableDatabaseSync> = T &\n EnhancedMethods;\n\n/**\n * Implementation of pragma() that works on any EnhanceableDatabaseSync.\n */\nfunction pragmaImpl(\n this: EnhanceableDatabaseSync,\n source: string,\n options?: PragmaOptions,\n): unknown {\n if (typeof source !== \"string\") {\n throw new TypeError(\"Expected first argument to be a string\");\n }\n if (options != null && typeof options !== \"object\") {\n throw new TypeError(\"Expected second argument to be an options object\");\n }\n\n const simple = options?.simple === true;\n\n // Validate that simple is a boolean if provided\n if (\n options != null &&\n \"simple\" in options &&\n typeof options.simple !== \"boolean\"\n ) {\n throw new TypeError('Expected the \"simple\" option to be a boolean');\n }\n\n const stmt = this.prepare(`PRAGMA ${source}`);\n const rows = stmt.all() as Record<string, unknown>[];\n\n if (simple) {\n // Return the first column of the first row, or undefined if no rows\n const firstRow = rows[0];\n if (firstRow == null) {\n return undefined;\n }\n const keys = Object.keys(firstRow);\n const firstKey = keys[0];\n if (firstKey == null) {\n return undefined;\n }\n return firstRow[firstKey];\n }\n\n return rows;\n}\n\n/**\n * Implementation of transaction() that works on any EnhanceableDatabaseSync.\n */\nfunction transactionImpl<F extends (...args: any[]) => any>(\n this: EnhanceableDatabaseSync,\n fn: F,\n): TransactionFunction<F> {\n // createTransaction expects DatabaseSyncInstance but only uses the subset\n // defined in EnhanceableDatabaseSync, so this cast is safe\n return createTransaction(this as any, fn);\n}\n\n/**\n * Checks if a database instance already has the enhanced methods.\n */\nfunction hasEnhancedMethods(\n db: EnhanceableDatabaseSync,\n): db is EnhanceableDatabaseSync & EnhancedMethods {\n return (\n typeof (db as any).pragma === \"function\" &&\n typeof (db as any).transaction === \"function\"\n );\n}\n\n/**\n * Ensures that `.pragma()` and `.transaction()` methods are available on the\n * given database.\n *\n * This function can enhance:\n * - `node:sqlite` DatabaseSync instances (adds the methods)\n * - `@photostructure/sqlite` DatabaseSync instances (no-op, already has these\n * methods)\n * - Any object with compatible `exec()`, `prepare()`, and `isTransaction`\n *\n * The enhancement is done by adding methods directly to the instance, not the\n * prototype, so it won't affect other instances or the original class.\n *\n * @param db The database instance to enhance\n * @returns The same instance with `.pragma()` and `.transaction()` methods\n * guaranteed\n *\n * @example\n * ```typescript\n * // With node:sqlite\n * import { DatabaseSync } from 'node:sqlite';\n * import { enhance } from '@photostructure/sqlite';\n *\n * const db = enhance(new DatabaseSync(':memory:'));\n *\n * // Now you can use better-sqlite3-style methods\n * db.pragma('journal_mode = wal');\n * const insertMany = db.transaction((items) => {\n * for (const item of items) insert.run(item);\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With @photostructure/sqlite (no-op, already enhanced)\n * import { DatabaseSync, enhance } from '@photostructure/sqlite';\n *\n * const db = enhance(new DatabaseSync(':memory:'));\n * // db already had these methods, enhance() just returns it unchanged\n * ```\n */\nexport function enhance<T extends EnhanceableDatabaseSync>(\n db: T,\n): EnhancedDatabaseSync<T> {\n // If already enhanced, return as-is\n if (hasEnhancedMethods(db)) {\n return db;\n }\n\n // Add methods directly to the instance\n // Using Object.defineProperty to make them non-enumerable like native methods\n Object.defineProperty(db, \"pragma\", {\n value: pragmaImpl,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n Object.defineProperty(db, \"transaction\", {\n value: transactionImpl,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n return db as EnhancedDatabaseSync<T>;\n}\n\n/**\n * Type guard to check if a database has enhanced methods.\n *\n * @param db The database to check\n * @returns True if the database has `.pragma()` and `.transaction()` methods\n *\n * @example\n * ```typescript\n * import { isEnhanced } from '@photostructure/sqlite';\n *\n * if (isEnhanced(db)) {\n * db.pragma('cache_size', { simple: true });\n * }\n * ```\n */\nexport function isEnhanced(\n db: EnhanceableDatabaseSync,\n): db is EnhanceableDatabaseSync & EnhancedMethods {\n return hasEnhancedMethods(db);\n}\n"],"mappings":"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","names":["path","DatabaseSync","StatementSync"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/index.ts","../src/stack-path.ts","../src/dirname.ts","../src/lru-cache.ts","../src/sql-tag-store.ts","../src/transaction.ts","../src/enhance.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","// Load the native binding with support for both CJS and ESM\nimport nodeGypBuild from \"node-gyp-build\";\nimport { join } from \"node:path\";\nimport { _dirname } from \"./dirname\";\nimport { SQLTagStore } from \"./sql-tag-store\";\nimport {\n DatabaseSyncInstance,\n DatabaseSyncLimits,\n} from \"./types/database-sync-instance\";\nimport { DatabaseSyncOptions } from \"./types/database-sync-options\";\nimport { SQLTagStoreInstance } from \"./types/sql-tag-store-instance\";\nimport { SqliteAuthorizationActions } from \"./types/sqlite-authorization-actions\";\nimport { SqliteAuthorizationResults } from \"./types/sqlite-authorization-results\";\nimport { SqliteChangesetConflictTypes } from \"./types/sqlite-changeset-conflict-types\";\nimport { SqliteChangesetResolution } from \"./types/sqlite-changeset-resolution\";\nimport { SqliteOpenFlags } from \"./types/sqlite-open-flags\";\nimport { StatementSyncInstance } from \"./types/statement-sync-instance\";\n\nexport type { AggregateOptions } from \"./types/aggregate-options\";\nexport type { ChangesetApplyOptions } from \"./types/changeset-apply-options\";\nexport type {\n DatabaseSyncInstance,\n DatabaseSyncLimits,\n} from \"./types/database-sync-instance\";\nexport type { DatabaseSyncOptions } from \"./types/database-sync-options\";\nexport type { PragmaOptions } from \"./types/pragma-options\";\nexport type { SessionOptions } from \"./types/session-options\";\nexport type { SQLTagStoreInstance } from \"./types/sql-tag-store-instance\";\nexport type { SqliteAuthorizationActions } from \"./types/sqlite-authorization-actions\";\nexport type { SqliteAuthorizationResults } from \"./types/sqlite-authorization-results\";\nexport type { SqliteChangesetConflictTypes } from \"./types/sqlite-changeset-conflict-types\";\nexport type { SqliteChangesetResolution } from \"./types/sqlite-changeset-resolution\";\nexport type { SqliteOpenFlags } from \"./types/sqlite-open-flags\";\nexport type {\n StatementColumnMetadata,\n StatementSyncInstance,\n} from \"./types/statement-sync-instance\";\nexport type { TransactionFunction, TransactionMode } from \"./types/transaction\";\nexport type { UserFunctionOptions } from \"./types/user-functions-options\";\n\n// Enhancement utilities for adding better-sqlite3-style methods to any compatible database\nexport {\n enhance,\n isEnhanced,\n type EnhanceableDatabaseSync,\n type EnhancedDatabaseSync,\n type EnhancedMethods,\n type EnhancedStatementMethods,\n} from \"./enhance\";\n\n// Use _dirname() helper that works in both CJS/ESM and Jest\nconst binding = nodeGypBuild(join(_dirname(), \"..\"));\n\n/**\n * All SQLite constants exported by this module.\n *\n * This is a union of all constant category interfaces:\n * - {@link SqliteOpenFlags} - Database open flags (extension beyond `node:sqlite`)\n * - {@link SqliteChangesetResolution} - Changeset conflict resolution values\n * - {@link SqliteChangesetConflictTypes} - Changeset conflict type codes\n * - {@link SqliteAuthorizationResults} - Authorization return values\n * - {@link SqliteAuthorizationActions} - Authorization action codes\n *\n * **Note:** The categorized interfaces (`SqliteOpenFlags`, etc.) are extensions\n * provided by `@photostructure/sqlite`. The `node:sqlite` module exports only\n * a flat `constants` object without these type categories.\n */\nexport type SqliteConstants = SqliteOpenFlags &\n SqliteChangesetResolution &\n SqliteChangesetConflictTypes &\n SqliteAuthorizationResults &\n SqliteAuthorizationActions;\n\n/**\n * Options for creating a prepared statement.\n *\n * **Note:** The per-statement override options (`readBigInts`, `returnArrays`,\n * `allowBareNamedParameters`, `allowUnknownNamedParameters`) are a **Node.js v25+**\n * feature. On Node.js v24 and earlier, `node:sqlite` silently ignores these options.\n * This library implements them for forward compatibility with Node.js v25+.\n */\nexport interface StatementOptions {\n /** If true, the prepared statement's expandedSQL property will contain the expanded SQL. @default false */\n readonly expandedSQL?: boolean;\n /** If true, anonymous parameters are enabled for the statement. @default false */\n readonly anonymousParameters?: boolean;\n /**\n * If true, read integer values as JavaScript BigInt. Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly readBigInts?: boolean;\n /**\n * If true, return results as arrays rather than objects. Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly returnArrays?: boolean;\n /**\n * If true, allows bare named parameters (without prefix). Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly allowBareNamedParameters?: boolean;\n /**\n * If true, unknown named parameters are ignored. Overrides database-level setting.\n * **Node.js v25+ feature** - silently ignored by `node:sqlite` on v24 and earlier.\n * @default database default\n */\n readonly allowUnknownNamedParameters?: boolean;\n}\n\nexport interface Session {\n /**\n * Generate a changeset containing all changes recorded by the session.\n * @returns A Uint8Array containing the changeset data.\n */\n changeset(): Uint8Array;\n /**\n * Generate a patchset containing all changes recorded by the session.\n * @returns A Uint8Array containing the patchset data.\n */\n patchset(): Uint8Array;\n /**\n * Close the session and release its resources.\n */\n close(): void;\n}\n\n/**\n * The main SQLite module interface.\n */\nexport interface SqliteModule {\n /**\n * The DatabaseSync class represents a synchronous connection to a SQLite database.\n * All operations are performed synchronously, blocking until completion.\n */\n DatabaseSync: new (\n location?: string | Buffer | URL,\n options?: DatabaseSyncOptions,\n ) => DatabaseSyncInstance;\n /**\n * The StatementSync class represents a synchronous prepared statement.\n * This class should not be instantiated directly; use Database.prepare() instead.\n */\n StatementSync: new (\n database: DatabaseSyncInstance,\n sql: string,\n options?: StatementOptions,\n ) => StatementSyncInstance;\n /**\n * The Session class for recording database changes.\n * This class should not be instantiated directly; use Database.createSession() instead.\n */\n Session: new () => Session;\n /**\n * SQLite constants for various operations and flags.\n * @see {@link SqliteConstants} for the type definition\n * @see {@link SqliteOpenFlags} for database open flags (extension beyond `node:sqlite`)\n * @see {@link SqliteChangesetResolution} for changeset conflict resolution values\n * @see {@link SqliteChangesetConflictTypes} for changeset conflict type codes\n * @see {@link SqliteAuthorizationResults} for authorization return values\n * @see {@link SqliteAuthorizationActions} for authorization action codes\n */\n constants: SqliteConstants;\n}\n\n/**\n * The DatabaseSync class represents a synchronous connection to a SQLite database.\n * All database operations are performed synchronously, blocking the thread until completion.\n *\n * @example\n * ```typescript\n * import { DatabaseSync } from '@photostructure/sqlite';\n *\n * // Create an in-memory database\n * const db = new DatabaseSync(':memory:');\n *\n * // Create a file-based database\n * const fileDb = new DatabaseSync('./mydata.db');\n *\n * // Create with options\n * const readOnlyDb = new DatabaseSync('./data.db', { readOnly: true });\n * ```\n */\n// Store the native binding's DatabaseSync\nconst _DatabaseSync = binding.DatabaseSync;\n// Wrapper around the native constructor to enforce usage of `new` with the correct error code.\n// We use a function wrapper instead of a Proxy for better performance and explicit prototype handling.\nexport const DatabaseSync = function DatabaseSync(this: any, ...args: any[]) {\n if (!new.target) {\n const err = new TypeError(\"Cannot call constructor without `new`\");\n (err as NodeJS.ErrnoException).code = \"ERR_CONSTRUCT_CALL_REQUIRED\";\n throw err;\n }\n return Reflect.construct(_DatabaseSync, args, new.target);\n} as unknown as SqliteModule[\"DatabaseSync\"];\nObject.setPrototypeOf(DatabaseSync, _DatabaseSync);\nDatabaseSync.prototype = _DatabaseSync.prototype;\n\n// node:sqlite implements createTagStore and SQLTagStore entirely in native C++.\n// We use a TypeScript implementation instead, attached via prototype extension.\n// This maintains API compatibility with node:sqlite while avoiding the complexity\n// of a native LRU cache. Performance is equivalent since the real cost is SQLite\n// execution, not cache lookups - V8's Map is highly optimized for string keys.\n(DatabaseSync.prototype as DatabaseSyncInstance).createTagStore = function (\n this: DatabaseSyncInstance,\n capacity?: number,\n): SQLTagStoreInstance {\n return new SQLTagStore(this, capacity);\n};\n\n// Limit name to SQLite limit ID mapping (matches upstream kLimitMapping order)\nconst LIMIT_MAPPING: ReadonlyArray<{\n name: keyof DatabaseSyncLimits;\n id: number;\n}> = [\n { name: \"length\", id: 0 },\n { name: \"sqlLength\", id: 1 },\n { name: \"column\", id: 2 },\n { name: \"exprDepth\", id: 3 },\n { name: \"compoundSelect\", id: 4 },\n { name: \"vdbeOp\", id: 5 },\n { name: \"functionArg\", id: 6 },\n { name: \"attach\", id: 7 },\n { name: \"likePatternLength\", id: 8 },\n { name: \"variableNumber\", id: 9 },\n { name: \"triggerDepth\", id: 10 },\n];\n\nconst INT_MAX = 2147483647;\n\n// WeakMap to cache limits objects per database instance\nconst limitsCache = new WeakMap<DatabaseSyncInstance, DatabaseSyncLimits>();\n\nfunction validateLimitValue(value: unknown): number {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new TypeError(\n \"Limit value must be a non-negative integer or Infinity.\",\n );\n }\n if (value === Infinity) {\n return INT_MAX;\n }\n if (!Number.isFinite(value) || value !== Math.trunc(value)) {\n throw new TypeError(\n \"Limit value must be a non-negative integer or Infinity.\",\n );\n }\n if (value < 0) {\n throw new RangeError(\"Limit value must be non-negative.\");\n }\n return value;\n}\n\nfunction createLimitsObject(db: DatabaseSyncInstance): DatabaseSyncLimits {\n const obj = Object.create(null) as DatabaseSyncLimits;\n for (const { name, id } of LIMIT_MAPPING) {\n Object.defineProperty(obj, name, {\n get() {\n return db.getLimit(id);\n },\n set(value: unknown) {\n const validated = validateLimitValue(value);\n db.setLimit(id, validated);\n },\n enumerable: true,\n configurable: false,\n });\n }\n return obj;\n}\n\nif (!Object.getOwnPropertyDescriptor(DatabaseSync.prototype, \"limits\")) {\n Object.defineProperty(DatabaseSync.prototype, \"limits\", {\n get(this: DatabaseSyncInstance) {\n let obj = limitsCache.get(this);\n if (obj == null) {\n obj = createLimitsObject(this);\n limitsCache.set(this, obj);\n }\n return obj;\n },\n enumerable: true,\n configurable: true,\n });\n}\n\n// NOTE: .pragma() and .transaction() are NOT added to the prototype by default.\n// This keeps DatabaseSync 100% API-compatible with node:sqlite.\n// Users who want better-sqlite3-style methods should use enhance():\n//\n// import { DatabaseSync, enhance } from '@photostructure/sqlite';\n// const db = enhance(new DatabaseSync(':memory:'));\n// db.pragma('journal_mode', { simple: true });\n// db.transaction(() => { ... });\n\n/**\n * The StatementSync class represents a prepared SQL statement.\n * This class should not be instantiated directly; use DatabaseSync.prepare() instead.\n *\n * @example\n * ```typescript\n * const stmt = db.prepare('SELECT * FROM users WHERE id = ?');\n * const user = stmt.get(123);\n * stmt.finalize();\n * ```\n */\n// Store the native binding's StatementSync for internal use\nconst _StatementSync = binding.StatementSync;\n// Export a wrapper that throws ERR_ILLEGAL_CONSTRUCTOR when called directly\n// but preserves instanceof checks and prototype chain\nexport const StatementSync = function StatementSync() {\n const err = new TypeError(\"Illegal constructor\");\n (err as NodeJS.ErrnoException).code = \"ERR_ILLEGAL_CONSTRUCTOR\";\n throw err;\n} as unknown as SqliteModule[\"StatementSync\"];\n// Use the native prototype directly so instanceof checks work correctly\n// (stmt instanceof StatementSync will check if StatementSync.prototype is in stmt's chain)\nStatementSync.prototype = _StatementSync.prototype;\n\n/**\n * The Session class for recording database changes.\n * This class should not be instantiated directly; use DatabaseSync.createSession() instead.\n *\n * @example\n * ```typescript\n * const session = db.createSession({ table: 'users' });\n * // Make some changes to the users table\n * const changeset = session.changeset();\n * session.close();\n * ```\n */\nexport const Session = binding.Session as SqliteModule[\"Session\"];\n\n/**\n * The SQLTagStore class for cached prepared statements via tagged template syntax.\n * This class should not be instantiated directly; use DatabaseSync.createTagStore() instead.\n *\n * @example\n * ```typescript\n * const sql = db.createTagStore();\n * sql.run`INSERT INTO users VALUES (${id}, ${name})`;\n * const user = sql.get`SELECT * FROM users WHERE id = ${id}`;\n * ```\n */\nexport { SQLTagStore };\n\n/**\n * SQLite constants for various operations and flags.\n *\n * @example\n * ```typescript\n * import { constants } from '@photostructure/sqlite';\n *\n * const db = new DatabaseSync('./data.db', {\n * readOnly: true,\n * // Uses SQLITE_OPEN_READONLY internally\n * });\n * ```\n */\nexport const constants: SqliteConstants = binding.constants;\n\n/**\n * Options for the backup() function.\n */\nexport interface BackupOptions {\n /** Number of pages to be transmitted in each batch of the backup. @default 100 */\n rate?: number;\n /** Name of the source database. Can be 'main' or any attached database. @default 'main' */\n source?: string;\n /** Name of the target database. Can be 'main' or any attached database. @default 'main' */\n target?: string;\n /** Callback function that will be called with progress information. */\n progress?: (info: { totalPages: number; remainingPages: number }) => void;\n}\n\n/**\n * Standalone function to make a backup of a database.\n *\n * This function matches the Node.js `node:sqlite` module API which exports\n * `backup()` as a standalone function in addition to the `db.backup()` method.\n *\n * @param sourceDb The database to backup from.\n * @param destination The path where the backup will be created.\n * @param options Optional configuration for the backup operation.\n * @returns A promise that resolves when the backup is completed.\n *\n * @example\n * ```typescript\n * import { DatabaseSync, backup } from '@photostructure/sqlite';\n *\n * const db = new DatabaseSync('./source.db');\n * await backup(db, './backup.db');\n *\n * // With options\n * await backup(db, './backup.db', {\n * rate: 10,\n * progress: ({ totalPages, remainingPages }) => {\n * console.log(`Progress: ${totalPages - remainingPages}/${totalPages}`);\n * }\n * });\n * ```\n */\nexport const backup: (\n sourceDb: DatabaseSyncInstance,\n destination: string | Buffer | URL,\n options?: BackupOptions,\n) => Promise<number> = binding.backup;\n\n// Default export for CommonJS compatibility\nexport default binding as SqliteModule;\n","import { dirname } from \"node:path\";\n\nexport function getCallerDirname(): string {\n const e = new Error();\n if (e.stack == null) {\n Error.captureStackTrace(e);\n }\n return dirname(extractCallerPath(e.stack as string));\n}\n\n// Comprehensive regex patterns for different stack frame formats\nconst patterns =\n process.platform === \"win32\"\n ? [\n // File URLs: \"at functionName (file:///C:/path/file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>file:\\/\\/\\/.+?):\\d+:\\d+\\)$/,\n // File URLs direct: \"at file:///C:/path/file.js:1:1\"\n /\\bat\\s(?<path>file:\\/\\/\\/.+?):\\d+:\\d+$/,\n // Standard: \"at functionName (C:\\path\\file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>[A-Z]:\\\\.+):\\d+:\\d+\\)$/,\n // direct: \"at C:\\path\\file.js:1:1\"\n /\\bat\\s(?<path>[A-Z]:\\\\.+):\\d+:\\d+$/,\n // UNC: \"at functionName (\\\\server\\share\\path\\file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>\\\\\\\\.+):\\d+:\\d+\\)$/,\n // direct: \"at \\\\server\\share\\path\\file.js:1:1\"\n /\\bat\\s(?<path>\\\\\\\\.+):\\d+:\\d+$/,\n ]\n : [\n // Standard: \"at functionName (/path/file.js:1:1)\"\n /\\bat\\s.+?\\((?<path>\\/.+?):\\d+:\\d+\\)$/,\n // Anonymous or direct: \"at /path/file.js:1:1\"\n // eslint-disable-next-line security/detect-unsafe-regex -- Pattern is safe: no nested quantifiers\n /\\bat\\s(?:[^\\s()]+\\s)?(?<path>\\/[^:]+):\\d+:\\d+$/,\n ];\n\nconst MaybeUrlRE = /^[a-z]{2,5}:\\/\\//i;\n\n// only exposed for tests:\nexport function extractCallerPath(stack: string): string {\n const frames = stack.split(\"\\n\").filter(Boolean);\n\n // First find getCallerDirname() in the stack:\n const callerFrame = frames.findIndex((frame) =>\n frame.includes(\"getCallerDirname\"),\n );\n if (callerFrame === -1) {\n throw new Error(\"Invalid stack trace format: missing caller frame\");\n }\n for (let i = callerFrame + 1; i < frames.length; i++) {\n // eslint-disable-next-line security/detect-object-injection -- Index is from controlled for-loop\n const frame = frames[i];\n for (const pattern of patterns) {\n const g = frame?.trim().match(pattern)?.groups;\n if (g != null && g[\"path\"]) {\n const path = g[\"path\"];\n // Windows requires us to check if it's a reasonable URL, as URL accepts\n // \"C:\\\\path\\\\file.txt\" as valid (!!)\n if (MaybeUrlRE.test(path)) {\n try {\n return new URL(path).pathname;\n } catch {\n // ignore\n }\n }\n return path;\n }\n }\n }\n throw new Error(\"Invalid stack trace format: no parsable frames\");\n}\n","import { getCallerDirname } from \"./stack-path\";\n\n// Thanks to tsup shims, __dirname should always be defined except when run by\n// jest (which will use the stack_path shim)\nexport function _dirname() {\n try {\n if (typeof __dirname !== \"undefined\") return __dirname;\n } catch {\n // ignore\n }\n // we must be in jest. Use the stack_path ~~hack~~ shim:\n return getCallerDirname();\n}\n","/**\n * Simple LRU (Least Recently Used) cache implementation.\n * Uses Map's insertion order to track recency - first key is oldest.\n */\nexport class LRUCache<K, V> {\n private cache = new Map<K, V>();\n private readonly maxCapacity: number;\n\n constructor(capacity: number) {\n if (capacity < 1) {\n throw new RangeError(\"LRU cache capacity must be at least 1\");\n }\n this.maxCapacity = capacity;\n }\n\n /**\n * Get a value from the cache.\n * If found, moves the entry to the end (most recently used).\n */\n get(key: K): V | undefined {\n const value = this.cache.get(key);\n if (value !== undefined) {\n // Move to end (most recently used) by reinserting\n this.cache.delete(key);\n this.cache.set(key, value);\n }\n return value;\n }\n\n /**\n * Set a value in the cache.\n * If key exists, updates and moves to end.\n * If at capacity, evicts the oldest entry first.\n */\n set(key: K, value: V): void {\n if (this.cache.has(key)) {\n // Update existing - delete and reinsert at end\n this.cache.delete(key);\n } else if (this.cache.size >= this.maxCapacity) {\n // Evict oldest (first key in Map iteration order)\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * Delete an entry from the cache.\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Check if a key exists in the cache.\n * Does NOT update recency.\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * Clear all entries from the cache.\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get the current number of entries in the cache.\n */\n size(): number {\n return this.cache.size;\n }\n\n /**\n * Get the maximum capacity of the cache.\n */\n capacity(): number {\n return this.maxCapacity;\n }\n}\n","import { LRUCache } from \"./lru-cache\";\nimport { DatabaseSyncInstance } from \"./types/database-sync-instance\";\nimport type { StatementSyncInstance } from \"./types/statement-sync-instance\";\n\n/**\n * Default capacity for the statement cache.\n * Matches Node.js SQLTagStore default.\n */\nconst DEFAULT_CAPACITY = 1000;\n\n/**\n * SQLTagStore provides cached prepared statements via tagged template syntax.\n *\n * @example\n * ```js\n * const sql = db.createTagStore();\n * sql.run`INSERT INTO users VALUES (${id}, ${name})`;\n * const user = sql.get`SELECT * FROM users WHERE id = ${id}`;\n * ```\n */\nexport class SQLTagStore {\n private readonly database: DatabaseSyncInstance;\n private readonly cache: LRUCache<string, StatementSyncInstance>;\n private readonly maxCapacity: number;\n\n constructor(db: DatabaseSyncInstance, capacity: number = DEFAULT_CAPACITY) {\n if (!db.isOpen) {\n const err = new Error(\"database is not open\");\n (err as NodeJS.ErrnoException).code = \"ERR_INVALID_STATE\";\n throw err;\n }\n this.database = db;\n this.maxCapacity = capacity;\n this.cache = new LRUCache(capacity);\n }\n\n /**\n * Returns the associated database instance.\n */\n get db(): DatabaseSyncInstance {\n return this.database;\n }\n\n /**\n * Returns the maximum capacity of the statement cache.\n */\n get capacity(): number {\n return this.maxCapacity;\n }\n\n /**\n * Returns the current number of cached statements.\n */\n get size(): number {\n return this.cache.size();\n }\n\n /**\n * Clears all cached statements.\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Execute an INSERT, UPDATE, DELETE or other statement that doesn't return rows.\n * Returns an object with `changes` and `lastInsertRowid`.\n */\n run(\n strings: TemplateStringsArray,\n ...values: unknown[]\n ): { changes: number; lastInsertRowid: number | bigint } {\n const stmt = this.getOrPrepare(strings);\n return stmt.run(...values);\n }\n\n /**\n * Execute a query and return the first row, or undefined if no rows.\n */\n get(strings: TemplateStringsArray, ...values: unknown[]): unknown {\n const stmt = this.getOrPrepare(strings);\n return stmt.get(...values);\n }\n\n /**\n * Execute a query and return all rows as an array.\n */\n all(strings: TemplateStringsArray, ...values: unknown[]): unknown[] {\n const stmt = this.getOrPrepare(strings);\n return stmt.all(...values);\n }\n\n /**\n * Execute a query and return an iterator over the rows.\n */\n iterate(\n strings: TemplateStringsArray,\n ...values: unknown[]\n ): IterableIterator<unknown> {\n const stmt = this.getOrPrepare(strings);\n return stmt.iterate(...values);\n }\n\n /**\n * Get a cached statement or prepare a new one.\n */\n private getOrPrepare(strings: TemplateStringsArray): StatementSyncInstance {\n if (!this.database.isOpen) {\n throw new Error(\"database is not open\");\n }\n\n const sql = this.buildSQL(strings);\n\n // Check cache\n const cached = this.cache.get(sql);\n if (cached) {\n return cached;\n }\n\n // Prepare new statement and cache it\n const stmt = this.database.prepare(sql);\n this.cache.set(sql, stmt);\n return stmt;\n }\n\n /**\n * Build the SQL string by joining template parts with `?` placeholders.\n */\n private buildSQL(strings: TemplateStringsArray): string {\n let sql = strings[0] ?? \"\";\n for (let i = 1; i < strings.length; i++) {\n // eslint-disable-next-line security/detect-object-injection -- Index is from controlled for-loop\n sql += \"?\" + (strings[i] ?? \"\");\n }\n return sql;\n }\n}\n","import type { DatabaseSyncInstance } from \"./types/database-sync-instance\";\nimport type { TransactionFunction, TransactionMode } from \"./types/transaction\";\n\n/**\n * Internal counter for generating unique savepoint names.\n * Using a global counter ensures uniqueness even with deeply nested transactions.\n */\nlet savepointCounter = 0;\n\n/**\n * Creates a transaction-wrapped version of a function.\n *\n * When the returned function is called, it will:\n * 1. Begin a transaction (or create a savepoint if already in a transaction)\n * 2. Execute the wrapped function\n * 3. Commit the transaction (or release the savepoint) on success\n * 4. Rollback the transaction (or rollback to savepoint) on error\n *\n * The wrapped function **must not** return a Promise. SQLite transactions are\n * synchronous, and allowing async operations would leave the transaction open\n * across event loop ticks, which is dangerous and can cause deadlocks.\n *\n * @example\n * ```typescript\n * const db = new DatabaseSync(':memory:');\n * db.exec('CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT)');\n *\n * const insert = db.prepare('INSERT INTO items (name) VALUES (?)');\n *\n * // Create a transaction function\n * const insertMany = db.transaction((names: string[]) => {\n * for (const name of names) {\n * insert.run(name);\n * }\n * return names.length;\n * });\n *\n * // Execute - automatically wrapped in BEGIN/COMMIT\n * const count = insertMany(['Alice', 'Bob', 'Charlie']);\n * console.log(count); // 3\n *\n * // If an error occurs, automatically rolls back\n * try {\n * insertMany(['Dave', 'FAIL']); // Assume this throws\n * } catch (e) {\n * // Transaction was rolled back, Dave was not inserted\n * }\n *\n * // Use different transaction modes\n * insertMany.immediate(['Eve']); // BEGIN IMMEDIATE\n * insertMany.exclusive(['Frank']); // BEGIN EXCLUSIVE\n * ```\n *\n * @param db - The database connection\n * @param fn - The function to wrap in a transaction\n * @returns A transaction function with `.deferred`, `.immediate`, and `.exclusive` variants\n */\nexport function createTransaction<F extends (...args: any[]) => any>(\n db: DatabaseSyncInstance,\n fn: F,\n): TransactionFunction<F> {\n if (typeof fn !== \"function\") {\n throw new TypeError(\"Expected first argument to be a function\");\n }\n\n // Create all four variants\n const variants = {\n deferred: createVariant(db, fn, \"deferred\"),\n immediate: createVariant(db, fn, \"immediate\"),\n exclusive: createVariant(db, fn, \"exclusive\"),\n };\n\n // The default function uses DEFERRED mode (SQLite's default)\n const defaultFn = variants.deferred as TransactionFunction<F>;\n\n // Set up the variant properties on each function\n // Each variant has access to all other variants\n for (const variant of Object.values(variants)) {\n Object.defineProperties(variant, {\n deferred: { value: variants.deferred, enumerable: true },\n immediate: { value: variants.immediate, enumerable: true },\n exclusive: { value: variants.exclusive, enumerable: true },\n database: { value: db, enumerable: true },\n });\n }\n\n return defaultFn;\n}\n\n/**\n * Creates a single transaction variant for a specific mode.\n */\nfunction createVariant<F extends (...args: any[]) => any>(\n db: DatabaseSyncInstance,\n fn: F,\n mode: TransactionMode,\n): (...args: Parameters<F>) => ReturnType<F> {\n const beginStatement = getBeginStatement(mode);\n\n return function transactionWrapper(\n this: unknown,\n ...args: Parameters<F>\n ): ReturnType<F> {\n // Check if we're already in a transaction (nested transaction)\n const isNested = db.isTransaction;\n\n let begin: string;\n let commit: string;\n let rollback: string;\n\n if (isNested) {\n // Use savepoints for nested transactions\n // The savepoint name uses backticks to allow special characters\n // and a counter to ensure uniqueness\n const savepointName = `\\`_txn_${++savepointCounter}\\``;\n begin = `SAVEPOINT ${savepointName}`;\n commit = `RELEASE ${savepointName}`;\n rollback = `ROLLBACK TO ${savepointName}`;\n } else {\n // Top-level transaction\n begin = beginStatement;\n commit = \"COMMIT\";\n rollback = \"ROLLBACK\";\n }\n\n // Begin the transaction or savepoint\n db.exec(begin);\n\n try {\n // Execute the wrapped function\n const result = fn.apply(this, args);\n\n // Check for promises - async functions break transaction semantics\n if (result !== null && typeof result === \"object\" && \"then\" in result) {\n throw new TypeError(\n \"Transaction function must not return a Promise. \" +\n \"SQLite transactions are synchronous and cannot span across async operations. \" +\n \"Use synchronous code within transactions.\",\n );\n }\n\n // Commit the transaction or release the savepoint\n db.exec(commit);\n\n return result;\n } catch (error) {\n // Only attempt rollback if we're still in a transaction\n // (SQLite may have already rolled back due to constraint violations, etc.)\n if (db.isTransaction) {\n db.exec(rollback);\n // For nested transactions, we also need to release the savepoint\n // after rolling back to it (the savepoint still exists after ROLLBACK TO)\n if (isNested) {\n db.exec(commit);\n }\n }\n\n throw error;\n }\n };\n}\n\n/**\n * Returns the appropriate BEGIN statement for a transaction mode.\n */\nfunction getBeginStatement(mode: TransactionMode): string {\n switch (mode) {\n case \"deferred\":\n return \"BEGIN DEFERRED\";\n case \"immediate\":\n return \"BEGIN IMMEDIATE\";\n case \"exclusive\":\n return \"BEGIN EXCLUSIVE\";\n default:\n // TypeScript should catch this, but just in case\n throw new Error(`Unknown transaction mode: ${mode}`);\n }\n}\n","/**\n * Enhancement utilities for adding better-sqlite3-style methods to any\n * compatible database, including `node:sqlite` DatabaseSync and this package's\n * DatabaseSync.\n *\n * This module provides the `enhance()` function which adds `.pragma()`,\n * `.transaction()`, and statement modes (`.pluck()`, `.raw()`, `.expand()`)\n * to database instances that don't have them (e.g., node:sqlite DatabaseSync).\n */\n\nimport { createTransaction } from \"./transaction\";\nimport type { PragmaOptions } from \"./types/pragma-options\";\nimport type { TransactionFunction } from \"./types/transaction\";\n\n/**\n * Minimal interface for a database that can be enhanced. This matches the\n * subset of functionality needed by pragma() and transaction().\n */\nexport interface EnhanceableDatabaseSync {\n /** Execute SQL without returning results */\n exec(sql: string): void;\n /** Prepare a statement that can return results */\n prepare(sql: string): { all(): unknown[] };\n /** Whether the database connection is open */\n readonly isOpen?: boolean;\n /** Whether a transaction is currently active */\n readonly isTransaction: boolean;\n}\n\n/**\n * Statement mode matching better-sqlite3's mutually exclusive modes.\n * - \"flat\": Default — rows as `{ column: value }` objects\n * - \"pluck\": First column value only\n * - \"raw\": Rows as arrays of values\n * - \"expand\": Rows namespaced by table, e.g. `{ users: { id: 1 }, posts: { title: \"...\" } }`\n */\ntype StatementMode = \"flat\" | \"pluck\" | \"raw\" | \"expand\";\n\n/**\n * A statement enhanced with better-sqlite3-style `.pluck()`, `.raw()`, and\n * `.expand()` methods. These are mutually exclusive — enabling one disables\n * the others.\n */\nexport interface EnhancedStatementMethods {\n /**\n * Causes the statement to return only the first column value of each row.\n *\n * When plucking is turned on, raw and expand modes are turned off.\n *\n * @param toggle Enable (true) or disable (false) pluck mode. Defaults to true.\n * @returns The same statement for chaining.\n *\n * @example\n * ```typescript\n * const count = db.prepare(\"SELECT COUNT(*) FROM users\").pluck().get();\n * // Returns: 42 (not { \"COUNT(*)\": 42 })\n *\n * const names = db.prepare(\"SELECT name FROM users\").pluck().all();\n * // Returns: [\"Alice\", \"Bob\"] (not [{ name: \"Alice\" }, { name: \"Bob\" }])\n * ```\n */\n pluck(toggle?: boolean): this;\n\n /**\n * Causes the statement to return rows as arrays of values instead of objects.\n *\n * When raw mode is turned on, pluck and expand modes are turned off.\n *\n * @param toggle Enable (true) or disable (false) raw mode. Defaults to true.\n * @returns The same statement for chaining.\n *\n * @example\n * ```typescript\n * const rows = db.prepare(\"SELECT id, name FROM users\").raw().all();\n * // Returns: [[1, \"Alice\"], [2, \"Bob\"]] (not [{ id: 1, name: \"Alice\" }, ...])\n * ```\n */\n raw(toggle?: boolean): this;\n\n /**\n * Causes the statement to return data namespaced by table. Each key in a row\n * object will be a table name, and each corresponding value will be a nested\n * object containing that table's columns. Columns from expressions or\n * subqueries are placed under the special `$` namespace.\n *\n * When expand mode is turned on, pluck and raw modes are turned off.\n *\n * Requires the statement to have a `.columns()` method (available on real\n * statements but not minimal mocks).\n *\n * @param toggle Enable (true) or disable (false) expand mode. Defaults to true.\n * @returns The same statement for chaining.\n *\n * @example\n * ```typescript\n * const rows = db.prepare(\"SELECT u.id, u.name, p.title FROM users u JOIN posts p ON ...\").expand().all();\n * // Returns: [{ users: { id: 1, name: \"Alice\" }, posts: { title: \"Hello\" } }]\n * ```\n */\n expand(toggle?: boolean): this;\n\n /** The database instance this statement was prepared from. */\n readonly database: EnhanceableDatabaseSync;\n}\n\n/**\n * Interface for an enhanced database with pragma() and transaction() methods.\n */\nexport interface EnhancedMethods {\n /**\n * Executes a PRAGMA statement and returns its result.\n *\n * @param source The PRAGMA command (without \"PRAGMA\" prefix)\n * @param options Optional configuration\n * @returns Array of rows, or single value if `simple: true`\n *\n * @example\n * ```typescript\n * db.pragma('cache_size', { simple: true }); // -16000\n * db.pragma('journal_mode = wal');\n * ```\n */\n pragma(source: string, options?: PragmaOptions): unknown;\n\n /**\n * Creates a function that always runs inside a transaction.\n *\n * @param fn The function to wrap in a transaction\n * @returns A transaction function with `.deferred`, `.immediate`,\n * `.exclusive` variants\n *\n * @example\n * ```typescript\n * const insertMany = db.transaction((items) => {\n * for (const item of items) insert.run(item);\n * });\n * insertMany(['a', 'b', 'c']); // All in one transaction\n * ```\n */\n transaction<F extends (...args: any[]) => any>(fn: F): TransactionFunction<F>;\n}\n\n/**\n * A database instance that has been enhanced with pragma(), transaction(),\n * and statement modes (pluck/raw/expand) on statements returned by prepare().\n */\nexport type EnhancedDatabaseSync<T extends EnhanceableDatabaseSync> = Omit<\n T,\n \"prepare\"\n> &\n EnhancedMethods & {\n prepare(\n ...args: Parameters<T[\"prepare\"]>\n ): ReturnType<T[\"prepare\"]> & EnhancedStatementMethods;\n };\n\n/** Symbol to track whether prepare() has been wrapped */\nconst ENHANCED_PREPARE = Symbol.for(\"@photostructure/sqlite:enhancedPrepare\");\n\n/**\n * Extract the first column value from a row object or array.\n */\nfunction extractFirstColumn(row: unknown): unknown {\n if (row == null) return row;\n if (Array.isArray(row)) return row[0];\n const keys = Object.keys(row as Record<string, unknown>);\n return keys.length > 0\n ? (row as Record<string, unknown>)[keys[0]!]\n : undefined;\n}\n\n/**\n * Build a column-to-table mapping from statement metadata, used by expand mode.\n * Returns an array parallel to column order: each entry is the table name\n * (or \"$\" for expressions/subqueries) and the column name.\n */\nfunction buildColumnTableMap(\n stmt: any,\n): Array<{ table: string; column: string }> | undefined {\n if (typeof stmt.columns !== \"function\") return undefined;\n const cols: Array<{ name: string; table: string | null }> = stmt.columns();\n return cols.map((c) => ({\n table: c.table ?? \"$\",\n column: c.name,\n }));\n}\n\n/**\n * Transform a row array into a table-namespaced expanded object.\n * Uses array indices to match columns, avoiding data loss from duplicate names.\n */\nfunction expandRowFromArray(\n row: unknown[],\n columnMap: Array<{ table: string; column: string }>,\n): Record<string, Record<string, unknown>> {\n const result: Record<string, Record<string, unknown>> = {};\n for (let i = 0; i < columnMap.length && i < row.length; i++) {\n const { table, column } = columnMap[i]!; // eslint-disable-line security/detect-object-injection\n // eslint-disable-next-line security/detect-object-injection -- table/column from our own columnMap\n result[table] ??= {};\n result[table]![column] = row[i]; // eslint-disable-line security/detect-object-injection\n }\n return result;\n}\n\n/**\n * Transform a flat row object into a table-namespaced expanded object.\n * Fallback for mocks without setReturnArrays — cannot handle duplicate column\n * names correctly, but mocks typically don't produce them.\n */\nfunction expandRowFromObject(\n row: Record<string, unknown>,\n columnMap: Array<{ table: string; column: string }>,\n): Record<string, Record<string, unknown>> {\n const result: Record<string, Record<string, unknown>> = {};\n const keys = Object.keys(row);\n for (let i = 0; i < keys.length && i < columnMap.length; i++) {\n const { table, column } = columnMap[i]!; // eslint-disable-line security/detect-object-injection\n // eslint-disable-next-line security/detect-object-injection -- table/column from our own columnMap\n result[table] ??= {};\n result[table]![column] = row[keys[i]!]; // eslint-disable-line security/detect-object-injection\n }\n return result;\n}\n\n/**\n * Validate a boolean toggle argument, matching better-sqlite3's pattern.\n */\nfunction validateToggle(value: unknown): boolean {\n const use = value === undefined ? true : value;\n if (typeof use !== \"boolean\") {\n throw new TypeError(\"Expected first argument to be a boolean\");\n }\n return use;\n}\n\n/**\n * Transform a row based on the current statement mode.\n */\nfunction transformRow(\n row: unknown,\n mode: StatementMode,\n columnMap: Array<{ table: string; column: string }> | undefined,\n): unknown {\n if (row == null || mode === \"flat\") return row;\n if (mode === \"pluck\") return extractFirstColumn(row);\n if (mode === \"expand\") {\n // columnMap is guaranteed non-null here — setMode() throws if columns() is\n // unavailable, so we'll never reach this branch with columnMap == null.\n // Prefer array-based expand (used when setReturnArrays is available)\n // to correctly handle duplicate column names across tables.\n // Fall back to object-based expand for mocks without setReturnArrays.\n if (Array.isArray(row)) {\n return expandRowFromArray(row, columnMap!);\n }\n return expandRowFromObject(row as Record<string, unknown>, columnMap!);\n }\n // \"raw\" mode is handled natively by setReturnArrays(), so no transform needed\n return row;\n}\n\n/**\n * Add `.pluck()`, `.raw()`, and `.expand()` methods to a statement instance.\n * These modes are mutually exclusive — enabling one disables the others,\n * matching better-sqlite3's behavior.\n */\nfunction enhanceStatement<S extends { all(): unknown[] }>(\n stmt: S,\n): S & EnhancedStatementMethods {\n // Idempotency: if already enhanced, return as-is\n if (typeof (stmt as any).pluck === \"function\") {\n return stmt as S & EnhancedStatementMethods;\n }\n\n let mode: StatementMode = \"flat\";\n let columnMap: Array<{ table: string; column: string }> | undefined;\n\n // Cast to any to avoid TypeScript strictness around bound method signatures.\n // At runtime these are native C++ methods that accept variadic bind parameters.\n const originalGet: any =\n typeof (stmt as any).get === \"function\"\n ? (stmt as any).get.bind(stmt)\n : undefined;\n const originalAll: any = (stmt as any).all.bind(stmt);\n const originalIterate: any =\n typeof (stmt as any).iterate === \"function\"\n ? (stmt as any).iterate.bind(stmt)\n : undefined;\n\n // Toggle helper matching better-sqlite3's mode switching:\n // enable(true) sets to target mode; enable(false) resets to flat ONLY if\n // currently in that mode, otherwise leaves mode unchanged.\n function setMode(target: StatementMode, use: boolean): void {\n if (use) {\n mode = target;\n // Cache column map on first expand() call\n if (target === \"expand\" && columnMap == null) {\n columnMap = buildColumnTableMap(stmt);\n if (columnMap == null) {\n throw new TypeError(\n \"expand() requires the statement to have a columns() method\",\n );\n }\n }\n } else if (mode === target) {\n mode = \"flat\";\n }\n // If use=false and mode !== target, no-op (matches better-sqlite3)\n\n // Sync native array mode: both raw and expand need arrays from the native layer.\n // Expand needs arrays to correctly handle duplicate column names across tables.\n if (typeof (stmt as any).setReturnArrays === \"function\") {\n (stmt as any).setReturnArrays(mode === \"raw\" || mode === \"expand\");\n }\n }\n\n Object.defineProperty(stmt, \"pluck\", {\n value: function pluck(toggle?: boolean): S {\n setMode(\"pluck\", validateToggle(toggle));\n return stmt;\n },\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n Object.defineProperty(stmt, \"raw\", {\n value: function raw(toggle?: boolean): S {\n setMode(\"raw\", validateToggle(toggle));\n return stmt;\n },\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n Object.defineProperty(stmt, \"expand\", {\n value: function expand(toggle?: boolean): S {\n setMode(\"expand\", validateToggle(toggle));\n return stmt;\n },\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n if (originalGet != null) {\n Object.defineProperty(stmt, \"get\", {\n value: (...params: any[]) => {\n const row = originalGet(...params);\n return transformRow(row, mode, columnMap);\n },\n writable: true,\n configurable: true,\n enumerable: false,\n });\n }\n\n Object.defineProperty(stmt, \"all\", {\n value: (...params: any[]) => {\n const rows = originalAll(...params);\n if (mode === \"flat\" || mode === \"raw\") return rows;\n return rows.map((row: unknown) => transformRow(row, mode, columnMap));\n },\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n if (originalIterate != null) {\n Object.defineProperty(stmt, \"iterate\", {\n value: function* (...params: any[]) {\n const iter = originalIterate(...params);\n for (const row of iter) {\n yield transformRow(row, mode, columnMap);\n }\n },\n writable: true,\n configurable: true,\n enumerable: false,\n });\n }\n\n return stmt as S & EnhancedStatementMethods;\n}\n\n/**\n * Implementation of pragma() that works on any EnhanceableDatabaseSync.\n */\nfunction pragmaImpl(\n this: EnhanceableDatabaseSync,\n source: string,\n options?: PragmaOptions,\n): unknown {\n if (typeof source !== \"string\") {\n throw new TypeError(\"Expected first argument to be a string\");\n }\n if (options != null && typeof options !== \"object\") {\n throw new TypeError(\"Expected second argument to be an options object\");\n }\n\n const simple = options?.simple === true;\n\n // Validate that simple is a boolean if provided\n if (\n options != null &&\n \"simple\" in options &&\n typeof options.simple !== \"boolean\"\n ) {\n throw new TypeError('Expected the \"simple\" option to be a boolean');\n }\n\n const stmt = this.prepare(`PRAGMA ${source}`);\n\n if (simple) {\n return extractFirstColumn(stmt.all()[0]);\n }\n\n return stmt.all();\n}\n\n/**\n * Implementation of transaction() that works on any EnhanceableDatabaseSync.\n */\nfunction transactionImpl<F extends (...args: any[]) => any>(\n this: EnhanceableDatabaseSync,\n fn: F,\n): TransactionFunction<F> {\n // createTransaction expects DatabaseSyncInstance but only uses the subset\n // defined in EnhanceableDatabaseSync, so this cast is safe\n return createTransaction(this as any, fn);\n}\n\n/**\n * Checks if a database instance already has the enhanced methods.\n */\nfunction hasEnhancedMethods(\n db: EnhanceableDatabaseSync,\n): db is EnhanceableDatabaseSync & EnhancedMethods {\n return (\n typeof (db as any).pragma === \"function\" &&\n typeof (db as any).transaction === \"function\"\n );\n}\n\n/**\n * Ensures that `.pragma()`, `.transaction()`, and statement modes\n * (`.pluck()`, `.raw()`, `.expand()`) are available on the given database.\n *\n * This function can enhance:\n * - `node:sqlite` DatabaseSync instances (adds the methods)\n * - `@photostructure/sqlite` DatabaseSync instances (adds the methods)\n * - Any object with compatible `exec()`, `prepare()`, and `isTransaction`\n *\n * The enhancement is done by adding methods directly to the instance, not the\n * prototype, so it won't affect other instances or the original class.\n *\n * @param db The database instance to enhance\n * @returns The same instance with `.pragma()`, `.transaction()`, and\n * `.pluck()` / `.raw()` / `.expand()` (on prepared statements) guaranteed\n *\n * @example\n * ```typescript\n * import { DatabaseSync, enhance } from '@photostructure/sqlite';\n *\n * const db = enhance(new DatabaseSync(':memory:'));\n *\n * // better-sqlite3-style pragma\n * db.pragma('journal_mode = wal');\n *\n * // better-sqlite3-style transactions\n * const insertMany = db.transaction((items) => {\n * for (const item of items) insert.run(item);\n * });\n *\n * // better-sqlite3-style pluck\n * const count = db.prepare(\"SELECT COUNT(*) FROM users\").pluck().get();\n * const names = db.prepare(\"SELECT name FROM users\").pluck().all();\n * ```\n */\nexport function enhance<T extends EnhanceableDatabaseSync>(\n db: T,\n): EnhancedDatabaseSync<T> {\n // Add pragma and transaction if not already present\n if (!hasEnhancedMethods(db)) {\n // Using Object.defineProperty to make them non-enumerable like native methods\n Object.defineProperty(db, \"pragma\", {\n value: pragmaImpl,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n Object.defineProperty(db, \"transaction\", {\n value: transactionImpl,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n }\n\n // Wrap prepare() to add pluck() to returned statements\n // eslint-disable-next-line security/detect-object-injection -- ENHANCED_PREPARE is a Symbol\n if (!(db as any)[ENHANCED_PREPARE]) {\n const originalPrepare: any = db.prepare.bind(db);\n\n Object.defineProperty(db, \"prepare\", {\n value: (...args: any[]) => {\n const stmt = originalPrepare(...args);\n enhanceStatement(stmt);\n // Add stmt.database back-reference for better-sqlite3 compat\n Object.defineProperty(stmt, \"database\", {\n value: db,\n writable: false,\n configurable: true,\n enumerable: false,\n });\n return stmt;\n },\n writable: true,\n configurable: true,\n enumerable: false,\n });\n\n Object.defineProperty(db, ENHANCED_PREPARE, {\n value: true,\n writable: false,\n configurable: false,\n enumerable: false,\n });\n }\n\n return db as unknown as EnhancedDatabaseSync<T>;\n}\n\n/**\n * Type guard to check if a database has enhanced methods.\n *\n * @param db The database to check\n * @returns True if the database has `.pragma()` and `.transaction()` methods\n *\n * @example\n * ```typescript\n * import { isEnhanced } from '@photostructure/sqlite';\n *\n * if (isEnhanced(db)) {\n * db.pragma('cache_size', { simple: true });\n * }\n * ```\n */\nexport function isEnhanced(\n db: EnhanceableDatabaseSync,\n): db is EnhanceableDatabaseSync & EnhancedMethods {\n return hasEnhancedMethods(db);\n}\n"],"mappings":"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","names":["path","DatabaseSync","StatementSync"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@photostructure/sqlite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Drop-in replacement for node:sqlite",
|
|
5
5
|
"homepage": "https://photostructure.github.io/node-sqlite/",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"lint:full": "run-s lint lint:native lint:api",
|
|
71
71
|
"//fmt": "code formatting",
|
|
72
72
|
"fmt": "run-p fmt:prettier fmt:native",
|
|
73
|
-
"fmt:prettier": "prettier --write .",
|
|
73
|
+
"fmt:prettier": "prettier --cache --write .",
|
|
74
74
|
"fmt:native": "clang-format --style=LLVM -i src/shims/*.h src/*.cpp src/*.h test/fixtures/test-extension/*.c || true",
|
|
75
75
|
"//memory": "memory analysis tools",
|
|
76
76
|
"memory:check": "npx --yes tsx scripts/check-memory.ts",
|
|
@@ -128,11 +128,11 @@
|
|
|
128
128
|
"performance"
|
|
129
129
|
],
|
|
130
130
|
"dependencies": {
|
|
131
|
-
"node-addon-api": "^8.
|
|
131
|
+
"node-addon-api": "^8.6.0",
|
|
132
132
|
"node-gyp-build": "^4.8.4"
|
|
133
133
|
},
|
|
134
134
|
"devDependencies": {
|
|
135
|
-
"@
|
|
135
|
+
"@photostructure/sqlite-vec": "^1.1.1",
|
|
136
136
|
"@types/jest": "^30.0.0",
|
|
137
137
|
"@types/node": "^25.0.3",
|
|
138
138
|
"better-sqlite3": "^12.6.2",
|
|
@@ -140,11 +140,11 @@
|
|
|
140
140
|
"del-cli": "^7.0.0",
|
|
141
141
|
"eslint": "^9.39.2",
|
|
142
142
|
"eslint-plugin-regexp": "^3.0.0",
|
|
143
|
-
"eslint-plugin-security": "^
|
|
144
|
-
"globals": "^17.
|
|
143
|
+
"eslint-plugin-security": "^4.0.0",
|
|
144
|
+
"globals": "^17.3.0",
|
|
145
145
|
"jest": "^30.2.0",
|
|
146
146
|
"node-gyp": "^12.2.0",
|
|
147
|
-
"npm-check-updates": "^19",
|
|
147
|
+
"npm-check-updates": "^19.6.3",
|
|
148
148
|
"npm-run-all2": "8.0.4",
|
|
149
149
|
"prebuildify": "^6.0.1",
|
|
150
150
|
"prettier": "^3.8.1",
|
|
@@ -152,12 +152,12 @@
|
|
|
152
152
|
"ts-jest": "^29.4.6",
|
|
153
153
|
"tsup": "^8.5.1",
|
|
154
154
|
"tsx": "^4.21.0",
|
|
155
|
-
"typedoc": "^0.28.
|
|
155
|
+
"typedoc": "^0.28.17",
|
|
156
156
|
"typescript": "^5.9.3",
|
|
157
|
-
"typescript-eslint": "^8.
|
|
157
|
+
"typescript-eslint": "^8.56.1"
|
|
158
158
|
},
|
|
159
159
|
"versions": {
|
|
160
|
-
"nodejs": "v25.
|
|
161
|
-
"sqlite": "3.
|
|
160
|
+
"nodejs": "v25.8.1@f91cf7f",
|
|
161
|
+
"sqlite": "3.52.0"
|
|
162
162
|
}
|
|
163
163
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|