@photostructure/sqlite 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +65 -16
  2. package/README.md +5 -10
  3. package/binding.gyp +2 -2
  4. package/dist/index.cjs +314 -11
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +346 -89
  7. package/dist/index.d.mts +346 -89
  8. package/dist/index.d.ts +346 -89
  9. package/dist/index.mjs +311 -10
  10. package/dist/index.mjs.map +1 -1
  11. package/package.json +72 -63
  12. package/prebuilds/darwin-arm64/@photostructure+sqlite.glibc.node +0 -0
  13. package/prebuilds/darwin-x64/@photostructure+sqlite.glibc.node +0 -0
  14. package/prebuilds/linux-arm64/@photostructure+sqlite.glibc.node +0 -0
  15. package/prebuilds/linux-arm64/@photostructure+sqlite.musl.node +0 -0
  16. package/prebuilds/linux-x64/@photostructure+sqlite.glibc.node +0 -0
  17. package/prebuilds/linux-x64/@photostructure+sqlite.musl.node +0 -0
  18. package/prebuilds/test_extension.so +0 -0
  19. package/prebuilds/win32-arm64/@photostructure+sqlite.glibc.node +0 -0
  20. package/prebuilds/win32-x64/@photostructure+sqlite.glibc.node +0 -0
  21. package/src/aggregate_function.cpp +222 -114
  22. package/src/aggregate_function.h +5 -6
  23. package/src/binding.cpp +30 -21
  24. package/src/enhance.ts +552 -0
  25. package/src/index.ts +84 -9
  26. package/src/shims/node_errors.h +34 -15
  27. package/src/shims/sqlite_errors.h +34 -8
  28. package/src/sql-tag-store.ts +6 -9
  29. package/src/sqlite_impl.cpp +1044 -394
  30. package/src/sqlite_impl.h +46 -7
  31. package/src/transaction.ts +178 -0
  32. package/src/types/database-sync-instance.ts +6 -40
  33. package/src/types/pragma-options.ts +23 -0
  34. package/src/types/statement-sync-instance.ts +38 -12
  35. package/src/types/transaction.ts +72 -0
  36. package/src/upstream/node_sqlite.cc +143 -43
  37. package/src/upstream/node_sqlite.h +15 -11
  38. package/src/upstream/sqlite3.c +102 -58
  39. package/src/upstream/sqlite3.h +5 -5
  40. package/src/user_function.cpp +138 -141
  41. package/src/user_function.h +3 -0
package/CHANGELOG.md CHANGED
@@ -2,13 +2,60 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.5.0] (2026-02-06)
6
+
7
+ ### Added
8
+
9
+ - **Statement modes via `enhance()`**: `stmt.pluck()`, `stmt.raw()`, `stmt.expand()` for better-sqlite3 compatibility
10
+ - `.pluck()` returns only the first column value from queries
11
+ - `.raw()` returns rows as arrays instead of objects
12
+ - `.expand()` returns rows namespaced by table, correctly handling duplicate column names across JOINs
13
+ - All three modes are mutually exclusive, matching better-sqlite3's toggle semantics
14
+ - **`stmt.database`**: Back-reference from prepared statements to their parent database instance
15
+ - **`EnhancedStatementMethods` type**: TypeScript interface for `pluck()`, `raw()`, `expand()`, and `database`
16
+
17
+ ## [0.4.0] (2026-02-04)
18
+
19
+ API compatible with `node:sqlite` from Node.js v25.6.1.
20
+
21
+ ### Added
22
+
23
+ - **`enhance()` function**: Adds better-sqlite3-style `.pragma()` and `.transaction()` methods to any compatible database instance
24
+ - **`isEnhanced()` type guard**: Check if a database has enhanced methods
25
+ - **Transaction helper**: Automatic BEGIN/COMMIT/ROLLBACK with savepoint support for nested transactions
26
+ - **Pragma convenience method**: Simple API for reading and setting SQLite pragmas with `simple` option
27
+ - **Node.js test sync script**: `npm run sync:tests` downloads and adapts upstream Node.js SQLite tests
28
+ - **Percentile extension**: `SQLITE_ENABLE_PERCENTILE` now enabled, adding `percentile()`, `median()`, `percentile_cont()`, `percentile_disc()` SQL functions (Node.js v25+)
29
+ - **Prepare options**: `db.prepare(sql, options)` now accepts per-statement options (`readBigInts`, `returnArrays`, `allowBareNamedParameters`, `allowUnknownNamedParameters`) to override database-level defaults. This is a Node.js v25+ feature; `node:sqlite` on v24 and earlier silently ignores these options.
30
+ - **StatementColumnMetadata type**: `stmt.columns()` now returns richer metadata including `column`, `database`, `table`, and `type` properties alongside `name`
31
+ - **SQLite 3.51.2**: Updated from 3.51.1
32
+
33
+ ### Changed
34
+
35
+ - **BREAKING**: Removed API extensions to achieve exact parity with `node:sqlite`:
36
+ - Removed `stmt.finalize()` method (use database close for cleanup)
37
+ - Removed `stmt.finalized` property
38
+ - Removed `stmt[Symbol.dispose]` (still available on `DatabaseSync` and `Session`)
39
+ - Removed `db.backup()` instance method (use standalone `backup(db, path)` function instead)
40
+ - **BREAKING**: `Session.changeset()` and `Session.patchset()` now return `Uint8Array` instead of `Buffer` to match `node:sqlite` API
41
+ - **BREAKING**: Defensive mode now defaults to `true` instead of `false` to match Node.js v25+ behavior. Use `{ defensive: false }` to restore old behavior.
42
+
43
+ ### Fixed
44
+
45
+ - **Alpine Linux / musl stability**: Fixed native crashes by removing N-API reference cleanup from destructors that corrupted V8 JIT state
46
+ - **Session lifecycle management**: Fixed use-after-free, double-free, and mutex deadlock when databases are garbage collected before their sessions
47
+ - **Worker thread stability**: Added cleanup hooks and exception handling for worker thread termination
48
+ - **Callback error preservation**: `applyChangeset()` now preserves the original error message when JavaScript callbacks throw
49
+ - `createTagStore()` now throws errors with `code: 'ERR_INVALID_STATE'` property when database is closed, matching Node.js error format
50
+
5
51
  ## [0.3.0] (2025-12-16)
6
52
 
7
53
  ### Changed
8
54
 
9
- - **BREAKING**: `SQLTagStore.size` changed from method to getter for Node.js API parity (Node.js PR #60246)
55
+ - **BREAKING**: `SQLTagStore.size` changed from method to getter for Node.js API parity ([Node.js PR #60246](https://github.com/nodejs/node/pull/60246))
10
56
  - Before: `sql.size()`
11
57
  - After: `sql.size`
58
+ - **Note**: This change was merged into Node.js main on December 11, 2025 and will appear in a future Node.js release. Current Node.js v24.x still uses `sql.size()` as a method.
12
59
 
13
60
  ## [0.2.1] (2025-12-01)
14
61
 
@@ -30,11 +77,11 @@ All notable changes to this project will be documented in this file.
30
77
  - **Defensive mode**: `enableDefensive()` method to prevent SQL from deliberately corrupting the database
31
78
  - **Statement enhancements**: `setAllowUnknownNamedParameters()` method, `finalized` property
32
79
  - **Type identification**: `sqlite-type` symbol property on DatabaseSync (Node.js PR #59405)
33
- - **Enhanced SQLite errors**: New properties `sqliteCode`, `sqliteExtendedCode`, `code`, `sqliteErrorString`, `systemErrno`
80
+ - **SQLite error properties**: `sqliteCode`, `sqliteExtendedCode`, `code`, `sqliteErrorString`, `systemErrno`
34
81
  - **ARM64 prebuilds**: macOS Apple Silicon and Windows ARM64 binaries
35
82
  - **Tagged template literals**: `db.createTagStore()` for cached prepared statements (Node.js PR #58748)
36
83
  - **Authorization API**: `db.setAuthorizer()` for security callbacks (Node.js PR #59928)
37
- - **Standalone backup**: `backup(srcDb, destFile, options?)` for one-liner database backups with progress callbacks
84
+ - **Standalone backup**: `backup(srcDb, destFile, options?)` for database backups with progress callbacks
38
85
 
39
86
  ### Fixed
40
87
 
@@ -48,16 +95,16 @@ All notable changes to this project will be documented in this file.
48
95
 
49
96
  ### Added
50
97
 
51
- - Initial release of `@photostructure/sqlite` - standalone SQLite for Node.js 20+
52
- - Full compatibility with Node.js built-in SQLite module API
98
+ - Initial release of `@photostructure/sqlite`, standalone SQLite for Node.js 20+
99
+ - Compatible with Node.js built-in SQLite module API
53
100
  - Core SQLite operations with `DatabaseSync` and `StatementSync` classes
54
- - User-defined scalar and aggregate functions with full window function support
55
- - Database backup and restoration capabilities
101
+ - User-defined scalar and aggregate functions with window function support
102
+ - Database backup and restoration
56
103
  - SQLite sessions and changesets for change tracking
57
- - Extension loading support with automatic platform-specific file resolution
58
- - TypeScript definitions with complete type coverage
104
+ - Extension loading with automatic platform-specific file resolution
105
+ - TypeScript definitions
59
106
  - Cross-platform prebuilt binaries for Windows, macOS, and Linux (x64, ARM64)
60
- - Comprehensive test suite with 89+ tests covering all functionality
107
+ - Test suite with 89+ tests
61
108
  - Memory safety validation with Valgrind and sanitizers
62
109
  - Performance benchmarking suite comparing to better-sqlite3
63
110
  - Automated synchronization from Node.js upstream SQLite implementation
@@ -65,15 +112,15 @@ All notable changes to this project will be documented in this file.
65
112
 
66
113
  ### Features
67
114
 
68
- - **Synchronous API**: Fast, blocking database operations ideal for scripts and tools
69
- - **Parameter binding**: Support for all SQLite data types including BigInt
115
+ - **Synchronous API**: Blocking database operations for scripts and tools
116
+ - **Parameter binding**: All SQLite data types including BigInt
70
117
  - **Error handling**: Detailed error messages with SQLite error codes
71
118
  - **Resource limits**: Control memory usage and query complexity
72
119
  - **Safe integer handling**: JavaScript-safe integer conversion with overflow detection
73
- - **Multi-process support**: Safe concurrent access from multiple Node.js processes
74
- - **Worker thread support**: Full functionality in worker threads
75
- - **URI filename support**: Full SQLite URI syntax support for advanced database configuration
76
- - **Strict tables**: Support for SQLite's strict table mode
120
+ - **Multi-process support**: Concurrent access from multiple Node.js processes
121
+ - **Worker thread support**: Works in worker threads
122
+ - **URI filename support**: SQLite URI syntax for advanced database configuration
123
+ - **Strict tables**: SQLite strict table mode
77
124
  - **Double-quoted strings**: Configurable SQL syntax compatibility
78
125
 
79
126
  ### Platform Support
@@ -83,6 +130,8 @@ All notable changes to this project will be documented in this file.
83
130
  - macOS (x64, ARM64)
84
131
  - Linux (x64, ARM64), (glibc 2.28+, musl)
85
132
 
133
+ [0.5.0]: https://github.com/PhotoStructure/node-sqlite/releases/tag/v0.5.0
134
+ [0.4.0]: https://github.com/PhotoStructure/node-sqlite/releases/tag/v0.4.0
86
135
  [0.3.0]: https://github.com/PhotoStructure/node-sqlite/releases/tag/v0.3.0
87
136
  [0.2.1]: https://github.com/PhotoStructure/node-sqlite/releases/tag/v0.2.1
88
137
  [0.2.0]: https://github.com/PhotoStructure/node-sqlite/releases/tag/v0.2.0
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@photostructure/sqlite.svg)](https://www.npmjs.com/package/@photostructure/sqlite)
4
4
  [![CI](https://github.com/photostructure/node-sqlite/actions/workflows/build.yml/badge.svg)](https://github.com/photostructure/node-sqlite/actions/workflows/build.yml)
5
5
 
6
- Native SQLite for Node.js 20+ without the experimental flag. Drop-in replacement for `node:sqlite`. Updated to Node.js v25 for latest features and native Symbol.dispose resource management.
6
+ Native SQLite for Node.js 20+ without the experimental flag. Drop-in replacement for `node:sqlite`. Synced with Node.js v25.6.1 for the latest features including native `Symbol.dispose` resource management.
7
7
 
8
8
  ## Installation
9
9
 
@@ -27,17 +27,18 @@ db.close();
27
27
 
28
28
  ## Features
29
29
 
30
- - 100% compatible with Node.js v25 built-in `node:sqlite` module\*
30
+ - 100% compatible with Node.js v25.6.1 built-in `node:sqlite` module\*
31
31
  - Zero dependencies - native SQLite implementation
32
32
  - Synchronous API - no async overhead
33
- - Performance matches leading SQLite libraries
33
+ - Performance comparable to better-sqlite3
34
34
  - Full SQLite feature set ([details](./doc/features.md))
35
35
  - TypeScript support with complete type definitions
36
36
  - Cross-platform prebuilt binaries (Windows/macOS/Linux, x64/ARM64)
37
37
  - User-defined functions and aggregates
38
38
  - Database backups and session/changeset support
39
39
  - Session class exposed for advanced replication workflows
40
- - Native Symbol.dispose for improved resource management
40
+ - Native `Symbol.dispose` for resource management
41
+ - `enhance()` function for better-sqlite3 style `.pragma()` and `.transaction()` methods
41
42
  - URI filename support for advanced configuration
42
43
  - Worker thread safe
43
44
  - [Compare with other libraries →](./doc/library-comparison.md)
@@ -69,12 +70,6 @@ db.close();
69
70
  - [Build Flags & Configuration](./doc/build-flags.md)
70
71
  - [Library Comparison](./doc/library-comparison.md)
71
72
 
72
- ## Support
73
-
74
- - 🐛 [Issues](https://github.com/photostructure/node-sqlite/issues)
75
- - 💬 [Discussions](https://github.com/photostructure/node-sqlite/discussions)
76
- - 📧 [Security](./SECURITY.md)
77
-
78
73
  ## License
79
74
 
80
75
  MIT - see [LICENSE](./LICENSE) for details.
package/binding.gyp CHANGED
@@ -11,13 +11,12 @@
11
11
  "src/upstream/sqlite3.c"
12
12
  ],
13
13
  "include_dirs": [
14
- "<!@(node -p \"require('node-addon-api').include\")",
15
14
  "src",
16
15
  "src/upstream",
17
16
  "src/shims"
18
17
  ],
19
18
  "dependencies": [
20
- "<!(node -p \"require('node-addon-api').gyp\")"
19
+ "<!(node -p \"require('node-addon-api').targets + ':node_addon_api_except'\")"
21
20
  ],
22
21
  # SQLite build flags - see doc/build-flags.md for comprehensive documentation
23
22
  # including comparison with Node.js configuration and rationale for our choices
@@ -40,6 +39,7 @@
40
39
  "SQLITE_ENABLE_JSON1",
41
40
  "SQLITE_ENABLE_MATH_FUNCTIONS",
42
41
  "SQLITE_ENABLE_NORMALIZE",
42
+ "SQLITE_ENABLE_PERCENTILE",
43
43
  "SQLITE_ENABLE_PREUPDATE_HOOK",
44
44
  "SQLITE_ENABLE_RBU",
45
45
  "SQLITE_ENABLE_RTREE",
package/dist/index.cjs CHANGED
@@ -36,7 +36,9 @@ __export(index_exports, {
36
36
  StatementSync: () => StatementSync,
37
37
  backup: () => backup,
38
38
  constants: () => constants,
39
- default: () => index_default
39
+ default: () => index_default,
40
+ enhance: () => enhance,
41
+ isEnhanced: () => isEnhanced
40
42
  });
41
43
  module.exports = __toCommonJS(index_exports);
42
44
  var import_node_gyp_build = __toESM(require("node-gyp-build"));
@@ -187,7 +189,9 @@ var SQLTagStore = class {
187
189
  maxCapacity;
188
190
  constructor(db, capacity = DEFAULT_CAPACITY) {
189
191
  if (!db.isOpen) {
190
- throw new Error("Database is not open");
192
+ const err = new Error("database is not open");
193
+ err.code = "ERR_INVALID_STATE";
194
+ throw err;
191
195
  }
192
196
  this.database = db;
193
197
  this.maxCapacity = capacity;
@@ -248,19 +252,15 @@ var SQLTagStore = class {
248
252
  }
249
253
  /**
250
254
  * Get a cached statement or prepare a new one.
251
- * If a cached statement has been finalized, it's evicted and a new one is prepared.
252
255
  */
253
256
  getOrPrepare(strings) {
254
257
  if (!this.database.isOpen) {
255
- throw new Error("Database is not open");
258
+ throw new Error("database is not open");
256
259
  }
257
260
  const sql = this.buildSQL(strings);
258
261
  const cached = this.cache.get(sql);
259
262
  if (cached) {
260
- if (!cached.finalized) {
261
- return cached;
262
- }
263
- this.cache.delete(sql);
263
+ return cached;
264
264
  }
265
265
  const stmt = this.database.prepare(sql);
266
266
  this.cache.set(sql, stmt);
@@ -278,13 +278,314 @@ var SQLTagStore = class {
278
278
  }
279
279
  };
280
280
 
281
+ // src/transaction.ts
282
+ var savepointCounter = 0;
283
+ function createTransaction(db, fn) {
284
+ if (typeof fn !== "function") {
285
+ throw new TypeError("Expected first argument to be a function");
286
+ }
287
+ const variants = {
288
+ deferred: createVariant(db, fn, "deferred"),
289
+ immediate: createVariant(db, fn, "immediate"),
290
+ exclusive: createVariant(db, fn, "exclusive")
291
+ };
292
+ const defaultFn = variants.deferred;
293
+ for (const variant of Object.values(variants)) {
294
+ Object.defineProperties(variant, {
295
+ deferred: { value: variants.deferred, enumerable: true },
296
+ immediate: { value: variants.immediate, enumerable: true },
297
+ exclusive: { value: variants.exclusive, enumerable: true },
298
+ database: { value: db, enumerable: true }
299
+ });
300
+ }
301
+ return defaultFn;
302
+ }
303
+ function createVariant(db, fn, mode) {
304
+ const beginStatement = getBeginStatement(mode);
305
+ return function transactionWrapper(...args) {
306
+ const isNested = db.isTransaction;
307
+ let begin;
308
+ let commit;
309
+ let rollback;
310
+ if (isNested) {
311
+ const savepointName = `\`_txn_${++savepointCounter}\``;
312
+ begin = `SAVEPOINT ${savepointName}`;
313
+ commit = `RELEASE ${savepointName}`;
314
+ rollback = `ROLLBACK TO ${savepointName}`;
315
+ } else {
316
+ begin = beginStatement;
317
+ commit = "COMMIT";
318
+ rollback = "ROLLBACK";
319
+ }
320
+ db.exec(begin);
321
+ try {
322
+ const result = fn.apply(this, args);
323
+ if (result !== null && typeof result === "object" && "then" in result) {
324
+ throw new TypeError(
325
+ "Transaction function must not return a Promise. SQLite transactions are synchronous and cannot span across async operations. Use synchronous code within transactions."
326
+ );
327
+ }
328
+ db.exec(commit);
329
+ return result;
330
+ } catch (error) {
331
+ if (db.isTransaction) {
332
+ db.exec(rollback);
333
+ if (isNested) {
334
+ db.exec(commit);
335
+ }
336
+ }
337
+ throw error;
338
+ }
339
+ };
340
+ }
341
+ function getBeginStatement(mode) {
342
+ switch (mode) {
343
+ case "deferred":
344
+ return "BEGIN DEFERRED";
345
+ case "immediate":
346
+ return "BEGIN IMMEDIATE";
347
+ case "exclusive":
348
+ return "BEGIN EXCLUSIVE";
349
+ default:
350
+ throw new Error(`Unknown transaction mode: ${mode}`);
351
+ }
352
+ }
353
+
354
+ // src/enhance.ts
355
+ var ENHANCED_PREPARE = /* @__PURE__ */ Symbol.for("@photostructure/sqlite:enhancedPrepare");
356
+ function extractFirstColumn(row) {
357
+ if (row == null) return row;
358
+ if (Array.isArray(row)) return row[0];
359
+ const keys = Object.keys(row);
360
+ return keys.length > 0 ? row[keys[0]] : void 0;
361
+ }
362
+ function buildColumnTableMap(stmt) {
363
+ if (typeof stmt.columns !== "function") return void 0;
364
+ const cols = stmt.columns();
365
+ return cols.map((c) => ({
366
+ table: c.table ?? "$",
367
+ column: c.name
368
+ }));
369
+ }
370
+ function expandRowFromArray(row, columnMap) {
371
+ const result = {};
372
+ for (let i = 0; i < columnMap.length && i < row.length; i++) {
373
+ const { table, column } = columnMap[i];
374
+ result[table] ??= {};
375
+ result[table][column] = row[i];
376
+ }
377
+ return result;
378
+ }
379
+ function expandRowFromObject(row, columnMap) {
380
+ const result = {};
381
+ const keys = Object.keys(row);
382
+ for (let i = 0; i < keys.length && i < columnMap.length; i++) {
383
+ const { table, column } = columnMap[i];
384
+ result[table] ??= {};
385
+ result[table][column] = row[keys[i]];
386
+ }
387
+ return result;
388
+ }
389
+ function validateToggle(value) {
390
+ const use = value === void 0 ? true : value;
391
+ if (typeof use !== "boolean") {
392
+ throw new TypeError("Expected first argument to be a boolean");
393
+ }
394
+ return use;
395
+ }
396
+ function transformRow(row, mode, columnMap) {
397
+ if (row == null || mode === "flat") return row;
398
+ if (mode === "pluck") return extractFirstColumn(row);
399
+ if (mode === "expand") {
400
+ if (Array.isArray(row)) {
401
+ return expandRowFromArray(row, columnMap);
402
+ }
403
+ return expandRowFromObject(row, columnMap);
404
+ }
405
+ return row;
406
+ }
407
+ function enhanceStatement(stmt) {
408
+ if (typeof stmt.pluck === "function") {
409
+ return stmt;
410
+ }
411
+ let mode = "flat";
412
+ let columnMap;
413
+ const originalGet = typeof stmt.get === "function" ? stmt.get.bind(stmt) : void 0;
414
+ const originalAll = stmt.all.bind(stmt);
415
+ const originalIterate = typeof stmt.iterate === "function" ? stmt.iterate.bind(stmt) : void 0;
416
+ function setMode(target, use) {
417
+ if (use) {
418
+ mode = target;
419
+ if (target === "expand" && columnMap == null) {
420
+ columnMap = buildColumnTableMap(stmt);
421
+ if (columnMap == null) {
422
+ throw new TypeError(
423
+ "expand() requires the statement to have a columns() method"
424
+ );
425
+ }
426
+ }
427
+ } else if (mode === target) {
428
+ mode = "flat";
429
+ }
430
+ if (typeof stmt.setReturnArrays === "function") {
431
+ stmt.setReturnArrays(mode === "raw" || mode === "expand");
432
+ }
433
+ }
434
+ Object.defineProperty(stmt, "pluck", {
435
+ value: function pluck(toggle) {
436
+ setMode("pluck", validateToggle(toggle));
437
+ return stmt;
438
+ },
439
+ writable: true,
440
+ configurable: true,
441
+ enumerable: false
442
+ });
443
+ Object.defineProperty(stmt, "raw", {
444
+ value: function raw(toggle) {
445
+ setMode("raw", validateToggle(toggle));
446
+ return stmt;
447
+ },
448
+ writable: true,
449
+ configurable: true,
450
+ enumerable: false
451
+ });
452
+ Object.defineProperty(stmt, "expand", {
453
+ value: function expand(toggle) {
454
+ setMode("expand", validateToggle(toggle));
455
+ return stmt;
456
+ },
457
+ writable: true,
458
+ configurable: true,
459
+ enumerable: false
460
+ });
461
+ if (originalGet != null) {
462
+ Object.defineProperty(stmt, "get", {
463
+ value: (...params) => {
464
+ const row = originalGet(...params);
465
+ return transformRow(row, mode, columnMap);
466
+ },
467
+ writable: true,
468
+ configurable: true,
469
+ enumerable: false
470
+ });
471
+ }
472
+ Object.defineProperty(stmt, "all", {
473
+ value: (...params) => {
474
+ const rows = originalAll(...params);
475
+ if (mode === "flat" || mode === "raw") return rows;
476
+ return rows.map((row) => transformRow(row, mode, columnMap));
477
+ },
478
+ writable: true,
479
+ configurable: true,
480
+ enumerable: false
481
+ });
482
+ if (originalIterate != null) {
483
+ Object.defineProperty(stmt, "iterate", {
484
+ value: function* (...params) {
485
+ const iter = originalIterate(...params);
486
+ for (const row of iter) {
487
+ yield transformRow(row, mode, columnMap);
488
+ }
489
+ },
490
+ writable: true,
491
+ configurable: true,
492
+ enumerable: false
493
+ });
494
+ }
495
+ return stmt;
496
+ }
497
+ function pragmaImpl(source, options) {
498
+ if (typeof source !== "string") {
499
+ throw new TypeError("Expected first argument to be a string");
500
+ }
501
+ if (options != null && typeof options !== "object") {
502
+ throw new TypeError("Expected second argument to be an options object");
503
+ }
504
+ const simple = options?.simple === true;
505
+ if (options != null && "simple" in options && typeof options.simple !== "boolean") {
506
+ throw new TypeError('Expected the "simple" option to be a boolean');
507
+ }
508
+ const stmt = this.prepare(`PRAGMA ${source}`);
509
+ if (simple) {
510
+ return extractFirstColumn(stmt.all()[0]);
511
+ }
512
+ return stmt.all();
513
+ }
514
+ function transactionImpl(fn) {
515
+ return createTransaction(this, fn);
516
+ }
517
+ function hasEnhancedMethods(db) {
518
+ return typeof db.pragma === "function" && typeof db.transaction === "function";
519
+ }
520
+ function enhance(db) {
521
+ if (!hasEnhancedMethods(db)) {
522
+ Object.defineProperty(db, "pragma", {
523
+ value: pragmaImpl,
524
+ writable: true,
525
+ configurable: true,
526
+ enumerable: false
527
+ });
528
+ Object.defineProperty(db, "transaction", {
529
+ value: transactionImpl,
530
+ writable: true,
531
+ configurable: true,
532
+ enumerable: false
533
+ });
534
+ }
535
+ if (!db[ENHANCED_PREPARE]) {
536
+ const originalPrepare = db.prepare.bind(db);
537
+ Object.defineProperty(db, "prepare", {
538
+ value: (...args) => {
539
+ const stmt = originalPrepare(...args);
540
+ enhanceStatement(stmt);
541
+ Object.defineProperty(stmt, "database", {
542
+ value: db,
543
+ writable: false,
544
+ configurable: true,
545
+ enumerable: false
546
+ });
547
+ return stmt;
548
+ },
549
+ writable: true,
550
+ configurable: true,
551
+ enumerable: false
552
+ });
553
+ Object.defineProperty(db, ENHANCED_PREPARE, {
554
+ value: true,
555
+ writable: false,
556
+ configurable: false,
557
+ enumerable: false
558
+ });
559
+ }
560
+ return db;
561
+ }
562
+ function isEnhanced(db) {
563
+ return hasEnhancedMethods(db);
564
+ }
565
+
281
566
  // src/index.ts
282
567
  var binding = (0, import_node_gyp_build.default)((0, import_node_path2.join)(_dirname(), ".."));
283
- var DatabaseSync = binding.DatabaseSync;
568
+ var _DatabaseSync = binding.DatabaseSync;
569
+ var DatabaseSync = function DatabaseSync2(...args) {
570
+ if (!new.target) {
571
+ const err = new TypeError("Cannot call constructor without `new`");
572
+ err.code = "ERR_CONSTRUCT_CALL_REQUIRED";
573
+ throw err;
574
+ }
575
+ return Reflect.construct(_DatabaseSync, args, new.target);
576
+ };
577
+ Object.setPrototypeOf(DatabaseSync, _DatabaseSync);
578
+ DatabaseSync.prototype = _DatabaseSync.prototype;
284
579
  DatabaseSync.prototype.createTagStore = function(capacity) {
285
580
  return new SQLTagStore(this, capacity);
286
581
  };
287
- var StatementSync = binding.StatementSync;
582
+ var _StatementSync = binding.StatementSync;
583
+ var StatementSync = function StatementSync2() {
584
+ const err = new TypeError("Illegal constructor");
585
+ err.code = "ERR_ILLEGAL_CONSTRUCTOR";
586
+ throw err;
587
+ };
588
+ StatementSync.prototype = _StatementSync.prototype;
288
589
  var Session = binding.Session;
289
590
  var constants = binding.constants;
290
591
  var backup = binding.backup;
@@ -296,6 +597,8 @@ var index_default = binding;
296
597
  Session,
297
598
  StatementSync,
298
599
  backup,
299
- constants
600
+ constants,
601
+ enhance,
602
+ isEnhanced
300
603
  });
301
604
  //# sourceMappingURL=index.cjs.map