indexeddbshim 17.0.0 → 17.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +62 -0
  2. package/badges/licenses-badge-dev.svg +1 -1
  3. package/badges/licenses-badge.svg +1 -1
  4. package/dist/CFG.d.ts +1 -0
  5. package/dist/CFG.d.ts.map +1 -1
  6. package/dist/IDBCursor.d.ts +9 -2
  7. package/dist/IDBCursor.d.ts.map +1 -1
  8. package/dist/IDBFactory.d.ts.map +1 -1
  9. package/dist/IDBIndex.d.ts.map +1 -1
  10. package/dist/IDBTransaction.d.ts +21 -0
  11. package/dist/IDBTransaction.d.ts.map +1 -1
  12. package/dist/Key.d.ts.map +1 -1
  13. package/dist/indexeddbshim-Key.js +25 -6
  14. package/dist/indexeddbshim-Key.js.map +1 -1
  15. package/dist/indexeddbshim-Key.min.js +2 -2
  16. package/dist/indexeddbshim-Key.min.js.map +1 -1
  17. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +1402 -818
  18. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
  19. package/dist/indexeddbshim-UnicodeIdentifiers.js +467 -298
  20. package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
  21. package/dist/indexeddbshim-UnicodeIdentifiers.min.js +4 -4
  22. package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
  23. package/dist/indexeddbshim-node.cjs +1402 -818
  24. package/dist/indexeddbshim-node.cjs.map +1 -1
  25. package/dist/indexeddbshim-noninvasive.js +467 -298
  26. package/dist/indexeddbshim-noninvasive.js.map +1 -1
  27. package/dist/indexeddbshim-noninvasive.min.js +4 -4
  28. package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
  29. package/dist/indexeddbshim.js +471 -295
  30. package/dist/indexeddbshim.js.map +1 -1
  31. package/dist/indexeddbshim.min.js +4 -4
  32. package/dist/indexeddbshim.min.js.map +1 -1
  33. package/dist/node-UnicodeIdentifiers.d.ts.map +1 -1
  34. package/dist/node.d.ts.map +1 -1
  35. package/dist/nodeSQLiteDatabase.d.ts +65 -0
  36. package/dist/nodeSQLiteDatabase.d.ts.map +1 -0
  37. package/dist/nodeWebSQL.d.ts.map +1 -1
  38. package/dist/util.d.ts +5 -0
  39. package/dist/util.d.ts.map +1 -1
  40. package/package.json +17 -13
  41. package/src/CFG.js +3 -0
  42. package/src/IDBCursor.js +136 -86
  43. package/src/IDBFactory.js +10 -6
  44. package/src/IDBIndex.js +1 -2
  45. package/src/IDBTransaction.js +32 -2
  46. package/src/Key.js +10 -2
  47. package/src/node-UnicodeIdentifiers.js +5 -1
  48. package/src/node.js +5 -1
  49. package/src/nodeSQLiteDatabase.js +174 -0
  50. package/src/nodeWebSQL.js +1 -3
  51. package/src/util.js +62 -3
@@ -1,12 +1,11 @@
1
- /*! indexeddbshim - v17.0.0 - 7/28/2026 */
1
+ /*! indexeddbshim - v17.1.0 - 8/6/2026 */
2
2
 
3
3
  'use strict';
4
4
 
5
5
  var fs$1 = require('node:fs');
6
6
  var path = require('path');
7
7
  var require$$0 = require('fs');
8
- var require$$2 = require('events');
9
- var require$$0$1 = require('util');
8
+ var require$$2 = require('util');
10
9
 
11
10
  function _typeof(obj) {
12
11
  "@babel/helpers - typeof";
@@ -980,6 +979,7 @@ function setPrototypeOfCustomEvent() {
980
979
  * sqlBusyTimeout: number,
981
980
  * sqlTrace: () => void,
982
981
  * sqlProfile: () => void,
982
+ * escapeNULForSQLiteStatements: boolean,
983
983
  * createIndexes: boolean
984
984
  * }} ConfigValues
985
985
  */
@@ -1134,8 +1134,8 @@ val => {
1134
1134
  // Callback not used by default
1135
1135
  'sqlProfile',
1136
1136
  // Callback not used by default
1137
-
1138
- 'createIndexes'].forEach(prop => {
1137
+ // Defaults to true except in Node builds where we can preserve literal NUL with better-sqlite3
1138
+ 'escapeNULForSQLiteStatements', 'createIndexes'].forEach(prop => {
1139
1139
  /** @type {(val: any) => void} */
1140
1140
  let validator;
1141
1141
  if (Array.isArray(prop)) {
@@ -1215,7 +1215,8 @@ function escapeNameForSQLiteIdentifier(arg) {
1215
1215
  * @returns {string}
1216
1216
  */
1217
1217
  function escapeSQLiteStatement(arg) {
1218
- return escapeUnmatchedSurrogates(arg.replaceAll('^', '^^').replaceAll('\0', '^0'));
1218
+ const escaped = arg.replaceAll('^', '^^');
1219
+ return escapeUnmatchedSurrogates(CFG.escapeNULForSQLiteStatements === false ? escaped : escaped.replaceAll('\0', '^0'));
1219
1220
  }
1220
1221
 
1221
1222
  /**
@@ -1223,7 +1224,11 @@ function escapeSQLiteStatement(arg) {
1223
1224
  * @returns {string}
1224
1225
  */
1225
1226
  function unescapeSQLiteResponse(arg) {
1226
- return unescapeUnmatchedSurrogates(arg).replaceAll(/(\^+)0/gu, (_, esc) => {
1227
+ const unescaped = unescapeUnmatchedSurrogates(arg);
1228
+ if (CFG.escapeNULForSQLiteStatements === false) {
1229
+ return unescaped.replaceAll('^^', '^');
1230
+ }
1231
+ return unescaped.replaceAll(/(\^+)0/gu, (_, esc) => {
1227
1232
  return esc.length % 2 ? esc.slice(1) + '\0' : _;
1228
1233
  }).replaceAll('^^', '^');
1229
1234
  }
@@ -1638,6 +1643,56 @@ function isNullish(v) {
1638
1643
  return v === null || v === undefined;
1639
1644
  }
1640
1645
 
1646
+ /**
1647
+ * Cursor/request continuation chains can call each other synchronously
1648
+ * (e.g. walking a large prefetched buffer, or advancing many interleaved
1649
+ * cursors in one transaction) which, for large enough record counts, can
1650
+ * exceed the JS engine's call stack ("Maximum call stack size exceeded").
1651
+ *
1652
+ * This can't be fixed by deferring continuations to a microtask/macrotask:
1653
+ * the transaction machinery synchronously checks (once the current call
1654
+ * stack unwinds) whether there are any pending requests left in order to
1655
+ * decide it's safe to commit; deferring a continuation opens a real gap in
1656
+ * which that check runs first and the transaction completes prematurely,
1657
+ * with the deferred continuation then acting on an already-finished
1658
+ * transaction (a hang, since it can never resolve).
1659
+ *
1660
+ * Instead, this implements a true trampoline: the first call starts a
1661
+ * synchronous work queue and drains it in a flat loop; any call made while
1662
+ * already draining (i.e. a continuation triggering another continuation)
1663
+ * is simply appended to that same queue and returns immediately instead of
1664
+ * recursing. This keeps everything synchronous (so no completion-check
1665
+ * race is introduced) while preventing the call stack from growing with
1666
+ * each successive continuation.
1667
+ */
1668
+ const continuationState = {
1669
+ /** @type {Array<() => void>|null} */
1670
+ queue: null
1671
+ };
1672
+
1673
+ /**
1674
+ * @param {() => void} fn
1675
+ * @returns {void}
1676
+ */
1677
+ function runContinuationSafely(fn) {
1678
+ if (continuationState.queue) {
1679
+ continuationState.queue.push(fn);
1680
+ return;
1681
+ }
1682
+ const queue = [fn];
1683
+ continuationState.queue = queue;
1684
+ try {
1685
+ while (queue.length) {
1686
+ const next = /** @type {() => void} */queue.shift();
1687
+ next();
1688
+ }
1689
+ } finally {
1690
+ // Ensure a thrown exception can't leave the queue permanently
1691
+ // stuck (which would silently swallow all future continuations).
1692
+ continuationState.queue = null;
1693
+ }
1694
+ }
1695
+
1641
1696
  /**
1642
1697
  * @typedef {Error} DebuggingError
1643
1698
  */
@@ -2313,16 +2368,15 @@ Object.defineProperty(IDBOpenDBRequest, 'prototype', {
2313
2368
  /* eslint-disable promise/prefer-await-to-callbacks -- Needed for API */
2314
2369
  /* eslint-disable promise/catch-or-return, n/callback-return,
2315
2370
  promise/always-return -- Not needed */
2316
- /* eslint-disable unicorn/no-this-assignment -- Clarity */
2317
2371
  // Since [immediate](https://github.com/calvinmetcalf/immediate) is
2318
2372
  // not doing the trick for our WebSQL transactions (at least in Node),
2319
2373
  // we are forced to make the promises run fully synchronously.
2320
2374
 
2321
- // Todo: Use ES6 classes
2322
-
2375
+ /* eslint-disable jsdoc/reject-any-type -- Truly arbitrary */
2323
2376
  /**
2324
2377
  * @typedef {any} ArbitraryValue
2325
2378
  */
2379
+ /* eslint-enable jsdoc/reject-any-type -- Truly arbitrary */
2326
2380
 
2327
2381
  /**
2328
2382
  * @callback Resolve
@@ -2382,209 +2436,219 @@ const PENDING = 2,
2382
2436
  REJECTED = 1;
2383
2437
 
2384
2438
  /**
2385
- * @class
2386
- * @param {(
2387
- * resolve: (value: ArbitraryValue | PromiseLike<ArbitraryValue>) => void,
2388
- * reject: (reason?: any) => void
2389
- * ) => void} fn
2439
+ *
2390
2440
  */
2391
- function SyncPromise(fn) {
2392
- const that = this;
2393
- // Value, this will be set to either a resolved value or rejected reason
2394
- that.v = 0;
2395
- // State of the promise
2396
- that.s = PENDING;
2397
- // Callbacks c[0] is fulfillment and c[1] contains rejection callbacks
2398
- /** @type {Callbacks|null} */
2399
- that.c = [[], []];
2441
+ class SyncPromise {
2400
2442
  /**
2401
- *
2402
- * @param {ArbitraryValue} val
2403
- * @param {0|1} state
2404
- * @returns {void}
2443
+ * @param {unknown[]|[]} promises
2444
+ * @returns {SyncPromise}
2405
2445
  */
2406
- function transist(val, state) {
2407
- that.v = val;
2408
- that.s = state;
2409
-
2410
- // console.log('state', state);
2411
- /** @type {Callbacks} */
2412
- that.c[state].forEach(function (func) {
2413
- func(val);
2446
+ static all(promises) {
2447
+ return new SyncPromise(/** @type {ResolveReject} */
2448
+ (resolve, reject) => {
2449
+ let l = promises.length;
2450
+ /** @type {ArbitraryValue[]} */
2451
+ const newPromises = [];
2452
+ if (!l) {
2453
+ resolve(newPromises);
2454
+ return;
2455
+ }
2456
+ promises.forEach((p, i) => {
2457
+ if (isPromise(/** @type {PromiseLike<ArbitraryValue>} */p)) {
2458
+ addReject(/** @type {PromiseLike<ArbitraryValue>} */p.then(/** @type {OnFulfilled} */
2459
+ res => {
2460
+ newPromises[i] = res;
2461
+ --l;
2462
+ if (!l) {
2463
+ resolve(newPromises);
2464
+ }
2465
+ }), reject);
2466
+ } else {
2467
+ newPromises[i] = p;
2468
+ --l;
2469
+ if (!l) {
2470
+ resolve(promises);
2471
+ }
2472
+ }
2473
+ });
2414
2474
  });
2415
- // Release memory, but if no handlers have been added, as we
2416
- // assume that we will resolve/reject (truly) synchronously
2417
- // and thus we avoid flagging checks about whether we've
2418
- // already resolved/rejected.
2419
- if (/** @type {Callbacks} */that.c[state].length) {
2420
- that.c = null;
2421
- }
2422
2475
  }
2423
2476
 
2424
- /** @type {Resolve} */
2425
- function resolve(val) {
2426
- if (!that.c) ; else if (isPromise(val)) {
2427
- addReject(val.then(resolve), reject);
2428
- } else {
2429
- transist(val, FULFILLED);
2430
- }
2477
+ /**
2478
+ * @param {unknown[]|[]} promises
2479
+ * @returns {SyncPromise}
2480
+ */
2481
+ static race(promises) {
2482
+ let resolved = false;
2483
+ return new SyncPromise(/** @type {ResolveReject} */
2484
+ (resolve, reject) => {
2485
+ // eslint-disable-next-line @stylistic/max-len -- Long
2486
+ // eslint-disable-next-line unicorn/no-unused-array-method-return -- Shortcuts
2487
+ promises.some(p => {
2488
+ if (isPromise(/** @type {PromiseLike<ArbitraryValue>} */p)) {
2489
+ addReject(/** @type {PromiseLike<ArbitraryValue>} */p.then(/** @type {OnFulfilled} */
2490
+ res => {
2491
+ if (resolved) {
2492
+ return;
2493
+ }
2494
+ resolve(res);
2495
+ resolved = true;
2496
+ }), reject);
2497
+ return false;
2498
+ }
2499
+ resolve(p);
2500
+ resolved = true;
2501
+ return true;
2502
+ });
2503
+ });
2431
2504
  }
2432
2505
 
2433
- /** @type {Reject} */
2434
- function reject(reason) {
2435
- if (!that.c) ; else if (isPromise(reason)) {
2436
- addReject(reason.then(reject), reject);
2437
- } else {
2438
- transist(reason, REJECTED);
2439
- }
2440
- }
2441
- try {
2442
- fn(resolve, reject);
2443
- } catch (err) {
2444
- reject(err);
2506
+ /**
2507
+ * @param {ArbitraryValue} val
2508
+ * @returns {SyncPromise}
2509
+ */
2510
+ static resolve(val) {
2511
+ return new SyncPromise(/** @type {ResolveReject} */
2512
+ resolve => {
2513
+ resolve(val);
2514
+ });
2445
2515
  }
2446
- }
2447
2516
 
2448
- /* eslint-disable unicorn/no-thenable -- Promise API */
2449
- /**
2450
- * @param {((value: ArbitraryValue) => ArbitraryValue)|null|undefined} [cb]
2451
- * @param {(reason: any) => PromiseLike<never>} [errBack]
2452
- * @returns {SyncPromise}
2453
- */
2454
- SyncPromise.prototype.then = function (cb, errBack) {
2455
- /* eslint-enable unicorn/no-thenable -- Promise API */
2456
- const that = this;
2457
- return new SyncPromise(/** @type {ResolveReject} */
2458
- function (resolve, reject) {
2459
- const rej = typeof errBack === 'function' ? errBack : reject;
2517
+ /**
2518
+ * @param {ArbitraryValue} val
2519
+ * @returns {SyncPromise}
2520
+ */
2521
+ static reject(val) {
2522
+ return new SyncPromise(/** @type {ResolveReject} */
2523
+ (resolve, reject) => {
2524
+ reject(val);
2525
+ });
2526
+ }
2460
2527
 
2461
- /** @type {Settle} */
2462
- function settle() {
2463
- try {
2464
- resolve(cb ? cb(that.v) : that.v);
2465
- } catch (e) {
2466
- rej(e);
2467
- }
2468
- }
2469
- if (that.s === FULFILLED) {
2470
- settle();
2471
- } else if (that.s === REJECTED) {
2472
- rej(that.v);
2473
- } else {
2474
- /** @type {Callbacks} */that.c[FULFILLED].push(settle);
2475
- /** @type {Callbacks} */
2476
- that.c[REJECTED].push(rej);
2477
- }
2478
- });
2479
- };
2528
+ // Value, this will be set to either a resolved value or rejected reason
2529
+ v = 0;
2480
2530
 
2481
- /**
2482
- * @param {(reason: any) => PromiseLike<never>|null|undefined} cb
2483
- * @returns {SyncPromise}
2484
- */
2485
- SyncPromise.prototype.catch = function (cb) {
2486
- const that = this;
2487
- return new SyncPromise(/** @type {ResolveReject} */
2488
- function (resolve, reject) {
2531
+ /**
2532
+ * @param {(
2533
+ * resolve: (value: ArbitraryValue | PromiseLike<ArbitraryValue>) => void,
2534
+ * reject: (reason?: ArbitraryValue) => void
2535
+ * ) => void} fn
2536
+ */
2537
+ constructor(fn) {
2538
+ // State of the promise
2539
+ this.s = PENDING;
2540
+ // Callbacks c[0] is fulfillment and c[1] contains rejection callbacks
2541
+ /** @type {Callbacks|null} */
2542
+ this.c = [[], []];
2489
2543
  /**
2544
+ *
2545
+ * @param {ArbitraryValue} val
2546
+ * @param {0|1} state
2490
2547
  * @returns {void}
2491
2548
  */
2492
- function settle() {
2493
- try {
2494
- resolve(cb(that.v));
2495
- } catch (e) {
2496
- reject(e);
2497
- }
2498
- }
2499
- if (that.s === REJECTED) {
2500
- settle();
2501
- } else if (that.s === FULFILLED) {
2502
- resolve(that.v);
2503
- } else {
2504
- /** @type {Callbacks} */that.c[REJECTED].push(settle);
2549
+ const transist = (val, state) => {
2550
+ this.v = val;
2551
+ this.s = state;
2552
+
2553
+ // console.log('state', state);
2505
2554
  /** @type {Callbacks} */
2506
- that.c[FULFILLED].push(resolve);
2507
- }
2508
- });
2509
- };
2555
+ this.c[state].forEach(func => {
2556
+ func(val);
2557
+ });
2558
+ // Release memory, but if no handlers have been added, as we
2559
+ // assume that we will resolve/reject (truly) synchronously
2560
+ // and thus we avoid flagging checks about whether we've
2561
+ // already resolved/rejected.
2562
+ if (/** @type {Callbacks} */this.c[state].length) {
2563
+ this.c = null;
2564
+ }
2565
+ };
2510
2566
 
2511
- /**
2512
- * @param {unknown[]|[]} promises
2513
- * @returns {SyncPromise}
2514
- */
2515
- SyncPromise.all = function (promises) {
2516
- return new SyncPromise(/** @type {ResolveReject} */
2517
- (resolve, reject) => {
2518
- let l = promises.length;
2519
- /** @type {ArbitraryValue[]} */
2520
- const newPromises = [];
2521
- if (!l) {
2522
- resolve(newPromises);
2523
- return;
2567
+ /** @type {Resolve} */
2568
+ const resolve = val => {
2569
+ if (!this.c) ; else if (isPromise(val)) {
2570
+ addReject(val.then(resolve), reject);
2571
+ } else {
2572
+ transist(val, FULFILLED);
2573
+ }
2574
+ };
2575
+
2576
+ /** @type {Reject} */
2577
+ const reject = reason => {
2578
+ if (!this.c) ; else if (isPromise(reason)) {
2579
+ addReject(reason.then(reject), reject);
2580
+ } else {
2581
+ transist(reason, REJECTED);
2582
+ }
2583
+ };
2584
+ try {
2585
+ fn(resolve, reject);
2586
+ } catch (err) {
2587
+ reject(err);
2524
2588
  }
2525
- promises.forEach((p, i) => {
2526
- if (isPromise(/** @type {PromiseLike<any>} */p)) {
2527
- addReject(/** @type {PromiseLike<any>} */p.then(/** @type {OnFulfilled} */
2528
- res => {
2529
- newPromises[i] = res;
2530
- --l || resolve(newPromises);
2531
- }), reject);
2589
+ }
2590
+
2591
+ /* eslint-disable unicorn/no-thenable -- Promise API */
2592
+ /**
2593
+ * @param {((value: ArbitraryValue) => ArbitraryValue)|null|undefined} [cb]
2594
+ * @param {(reason: ArbitraryValue) => PromiseLike<never>} [errBack]
2595
+ * @returns {SyncPromise}
2596
+ */
2597
+ then(cb, errBack) {
2598
+ /* eslint-enable unicorn/no-thenable -- Promise API */
2599
+ return new SyncPromise(/** @type {ResolveReject} */
2600
+ (resolve, reject) => {
2601
+ const rej = typeof errBack === 'function' ? errBack : reject;
2602
+
2603
+ /** @type {Settle} */
2604
+ const settle = () => {
2605
+ try {
2606
+ resolve(cb ? cb(this.v) : this.v);
2607
+ } catch (e) {
2608
+ rej(e);
2609
+ }
2610
+ };
2611
+ if (this.s === FULFILLED) {
2612
+ settle();
2613
+ } else if (this.s === REJECTED) {
2614
+ rej(this.v);
2532
2615
  } else {
2533
- newPromises[i] = p;
2534
- --l || resolve(promises);
2616
+ /** @type {Callbacks} */this.c[FULFILLED].push(settle);
2617
+ /** @type {Callbacks} */
2618
+ this.c[REJECTED].push(rej);
2535
2619
  }
2536
2620
  });
2537
- });
2538
- };
2621
+ }
2539
2622
 
2540
- /**
2541
- * @param {unknown[]|[]} promises
2542
- * @returns {SyncPromise}
2543
- */
2544
- SyncPromise.race = function (promises) {
2545
- let resolved = false;
2546
- return new SyncPromise(/** @type {ResolveReject} */
2547
- (resolve, reject) => {
2548
- promises.some((p, i) => {
2549
- if (isPromise(/** @type {PromiseLike<any>} */p)) {
2550
- addReject(/** @type {PromiseLike<any>} */p.then(/** @type {OnFulfilled} */
2551
- res => {
2552
- if (resolved) {
2553
- return;
2554
- }
2555
- resolve(res);
2556
- resolved = true;
2557
- }), reject);
2558
- return false;
2623
+ /**
2624
+ * @param {(reason: ArbitraryValue) => PromiseLike<never>|null|undefined} cb
2625
+ * @returns {SyncPromise}
2626
+ */
2627
+ catch(cb) {
2628
+ return new SyncPromise(/** @type {ResolveReject} */
2629
+ (resolve, reject) => {
2630
+ /**
2631
+ * @returns {void}
2632
+ */
2633
+ const settle = () => {
2634
+ try {
2635
+ resolve(cb(this.v));
2636
+ } catch (e) {
2637
+ reject(e);
2638
+ }
2639
+ };
2640
+ if (this.s === REJECTED) {
2641
+ settle();
2642
+ } else if (this.s === FULFILLED) {
2643
+ resolve(this.v);
2644
+ } else {
2645
+ /** @type {Callbacks} */this.c[REJECTED].push(settle);
2646
+ /** @type {Callbacks} */
2647
+ this.c[FULFILLED].push(resolve);
2559
2648
  }
2560
- resolve(p);
2561
- resolved = true;
2562
- return true;
2563
2649
  });
2564
- });
2565
- };
2566
-
2567
- /**
2568
- * @param {ArbitraryValue} val
2569
- * @returns {SyncPromise}
2570
- */
2571
- SyncPromise.resolve = function (val) {
2572
- return new SyncPromise(/** @type {ResolveReject} */
2573
- (resolve, reject) => {
2574
- resolve(val);
2575
- });
2576
- };
2577
-
2578
- /**
2579
- * @param {ArbitraryValue} val
2580
- * @returns {SyncPromise}
2581
- */
2582
- SyncPromise.reject = function (val) {
2583
- return new SyncPromise(/** @type {ResolveReject} */
2584
- (resolve, reject) => {
2585
- reject(val);
2586
- });
2587
- };
2650
+ }
2651
+ }
2588
2652
 
2589
2653
  /**
2590
2654
  * Compares two keys.
@@ -2885,14 +2949,22 @@ const types = {
2885
2949
  encoded[i] = encodedItem;
2886
2950
  }
2887
2951
  encoded.push(keyTypeToEncodedChar.invalid + '-'); // append an extra item, so empty arrays sort correctly
2888
- return keyTypeToEncodedChar.array + '-' + JSON.stringify(encoded);
2952
+ let encodedKey = JSON.stringify(encoded);
2953
+ if (CFG.escapeNULForSQLiteStatements === false) {
2954
+ encodedKey = encodedKey.replaceAll(String.raw`\u0000`, '\0');
2955
+ }
2956
+ return keyTypeToEncodedChar.array + '-' + encodedKey;
2889
2957
  },
2890
2958
  /**
2891
2959
  * @param {string} key
2892
2960
  * @returns {ValueTypeArray}
2893
2961
  */
2894
2962
  decode(key) {
2895
- const decoded = JSON.parse(key.slice(2));
2963
+ let decodedKey = key.slice(2);
2964
+ if (CFG.escapeNULForSQLiteStatements === false) {
2965
+ decodedKey = decodedKey.replaceAll('\0', String.raw`\u0000`);
2966
+ }
2967
+ const decoded = JSON.parse(decodedKey);
2896
2968
  decoded.pop(); // remove the extra item
2897
2969
  for (let i = 0; i < decoded.length; i++) {
2898
2970
  const item = decoded[i];
@@ -4312,6 +4384,7 @@ const readonlyProperties$3 = ['objectStoreNames', 'mode', 'db', 'error'];
4312
4384
  * },
4313
4385
  * __requestsFinished: boolean,
4314
4386
  * __transFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
4387
+ * __callTransFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
4315
4388
  * __transactionEndCallback: () => void,
4316
4389
  * __transactionFinished: boolean,
4317
4390
  * __completed: boolean,
@@ -4420,6 +4493,35 @@ IDBTransaction.prototype = EventTargetFactory.createInstance({
4420
4493
  IDBTransaction.prototype.__transFinishedCb = function (err, cb) {
4421
4494
  cb(Boolean(err));
4422
4495
  };
4496
+
4497
+ /**
4498
+ * In Node, the real (SQL-commit-capable) `__transFinishedCb` is only
4499
+ * installed once the underlying WebSQL driver's own SQL-queue-idle check
4500
+ * has fired at least once for this transaction (asynchronously, via the
4501
+ * `nonstandardTransCb` passed to `db.transaction`/`.readTransaction`).
4502
+ * Since our own request processing can now finish synchronously (e.g., a
4503
+ * trivial upgrade using a synchronous SQL driver), it is possible to reach
4504
+ * transaction completion here before that has happened, in which case
4505
+ * `__transFinishedCb` is still the non-committing default above. Calling
4506
+ * that default directly would silently skip the actual SQL commit and
4507
+ * leave the underlying WebSQL transaction "running" forever, hanging any
4508
+ * later transaction on that same database connection. So, if the real
4509
+ * callback isn't installed yet, defer and retry until it is.
4510
+ * @this {IDBTransactionFull}
4511
+ * @param {boolean} err
4512
+ * @param {(bool?: boolean) => void} cb
4513
+ * @returns {void}
4514
+ */
4515
+ IDBTransaction.prototype.__callTransFinishedCb = function (err, cb) {
4516
+ const me = this;
4517
+ if (me.__transFinishedCb === IDBTransaction.prototype.__transFinishedCb) {
4518
+ setTimeout(() => {
4519
+ me.__callTransFinishedCb(err, cb);
4520
+ }, 0);
4521
+ return;
4522
+ }
4523
+ me.__transFinishedCb(err, cb);
4524
+ };
4423
4525
  /**
4424
4526
  * @this {IDBTransactionFull}
4425
4527
  * @returns {void}
@@ -4479,7 +4581,7 @@ IDBTransaction.prototype.__executeRequests = function () {
4479
4581
  me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after success).'));
4480
4582
  return;
4481
4583
  }
4482
- executeNextRequest();
4584
+ runContinuationSafely(executeNextRequest);
4483
4585
  }
4484
4586
 
4485
4587
  /**
@@ -4551,7 +4653,7 @@ IDBTransaction.prototype.__executeRequests = function () {
4551
4653
  try {
4552
4654
  q = me.__requests[i];
4553
4655
  if (!q.req) {
4554
- q.op(tx, q.args, executeNextRequest, error);
4656
+ q.op(tx, q.args, () => runContinuationSafely(executeNextRequest), error);
4555
4657
  return;
4556
4658
  }
4557
4659
  if (q.req.__done) {
@@ -6925,7 +7027,7 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
6925
7027
  reject(err);
6926
7028
  });
6927
7029
  }));
6928
- SyncPromise.all(indexCreations).then(finish, /** @type {(reason: any) => PromiseLike<never>} */
7030
+ SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: any) => PromiseLike<never>} */
6929
7031
  error).catch(err => {
6930
7032
  console.log('Index rename error');
6931
7033
  throw err;
@@ -9070,7 +9172,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
9070
9172
  /** @type {import('./IDBDatabase.js').IDBDatabaseFull} */
9071
9173
  req.__result.__versionTransaction = null;
9072
9174
  sysdbFinishedCb(systx, false, function () {
9073
- req.transaction.__transFinishedCb(false, function () {
9175
+ req.transaction.__callTransFinishedCb(false, function () {
9074
9176
  ev.complete();
9075
9177
  req.__transaction = null;
9076
9178
  });
@@ -9181,6 +9283,13 @@ IDBFactory.prototype.open = function (name /* , version */) {
9181
9283
  function openDB(oldVersion) {
9182
9284
  /** @type {DatabaseFull} */
9183
9285
  let db;
9286
+ if (version === undefined) {
9287
+ // Resolve before use as a cache key below, or a `open(name)` call
9288
+ // (no explicit version) would cache/look up under `undefined`
9289
+ // instead of the actual version, causing a second, separate
9290
+ // connection to be opened for the same database on reopen.
9291
+ version = oldVersion || 1;
9292
+ }
9184
9293
  if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
9185
9294
  db = websqlDBCache[name][version];
9186
9295
  } else {
@@ -9192,9 +9301,6 @@ IDBFactory.prototype.open = function (name /* , version */) {
9192
9301
  websqlDBCache[name][version] = db;
9193
9302
  }
9194
9303
  }
9195
- if (version === undefined) {
9196
- version = oldVersion || 1;
9197
- }
9198
9304
  if (oldVersion > version) {
9199
9305
  const err = createDOMException('VersionError', 'An attempt was made to open a database using a lower version than the existing version.', version);
9200
9306
  if (useDatabaseCache) {
@@ -9363,7 +9469,6 @@ IDBFactory.prototype.deleteDatabase = function (name) {
9363
9469
  } = data.rows.item(0));
9364
9470
  const openConnections = me.__connections[name] || [];
9365
9471
  triggerAnyVersionChangeAndBlockedEvents(openConnections, req, version, null).then(function () {
9366
- // eslint-disable-line promise/catch-or-return -- Sync promise
9367
9472
  // Since we need two databases which can't be in a single transaction, we
9368
9473
  // do this deleting from `dbVersions` first since the `__sys__` deleting
9369
9474
  // only impacts file memory whereas this one is critical for avoiding it
@@ -9392,7 +9497,7 @@ IDBFactory.prototype.deleteDatabase = function (name) {
9392
9497
  });
9393
9498
  return undefined;
9394
9499
  // @ts-expect-error It's ok
9395
- }, dbError);
9500
+ }).catch(dbError);
9396
9501
  return undefined;
9397
9502
  }, dbError);
9398
9503
  });
@@ -9574,6 +9679,9 @@ const shimIndexedDB = IDBFactory.__createInstance();
9574
9679
  * __unique: boolean,
9575
9680
  * __sqlDirection: "DESC"|"ASC",
9576
9681
  * __matchedKeys: {[key: string]: true},
9682
+ * __continuationKey: import('./Key.js').Key|undefined,
9683
+ * __continuationPrimaryKey: import('./Key.js').Key|undefined,
9684
+ * __multiEntryExhausted: boolean,
9577
9685
  * __invalidateCache: () => void
9578
9686
  * }} IDBCursorFull
9579
9687
  */
@@ -9647,6 +9755,9 @@ IDBCursor.__super = function IDBCursor(query, direction, store, source, keyColum
9647
9755
  this.__valueDecoder = this.__keyOnly ? Key : Sca;
9648
9756
  this.__count = count;
9649
9757
  this.__prefetchedIndex = -1;
9758
+ this.__continuationKey = undefined;
9759
+ this.__continuationPrimaryKey = undefined;
9760
+ this.__multiEntryExhausted = false;
9650
9761
  this.__multiEntryIndex = this.__indexSource ? 'multiEntry' in source && source.multiEntry : false;
9651
9762
  this.__unique = this.direction.includes('unique');
9652
9763
  this.__sqlDirection = ['prev', 'prevunique'].includes(this.direction) ? 'DESC' : 'ASC';
@@ -9799,73 +9910,96 @@ const leftBracketRegex = /\[/gu;
9799
9910
  * @param {SQLTransaction} tx
9800
9911
  * @param {KeySuccess} success
9801
9912
  * @param {FindError} error
9802
- * @param {Integer|undefined} recordsToLoad
9913
+ * @param {Integer} [recordsToLoad]
9803
9914
  * @this {IDBCursorFull}
9804
9915
  * @returns {void}
9805
9916
  */
9806
- IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error, recordsToLoad) {
9917
+ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error, recordsToLoad = 1) {
9807
9918
  const me = this;
9808
- if (me.__prefetchedData && me.__prefetchedData.length === me.__prefetchedIndex) {
9919
+ if (me.__multiEntryExhausted) {
9809
9920
  if (CFG.DEBUG) {
9810
- console.log('Reached end of multiEntry cursor');
9921
+ console.log('[multiEntry] Reached end of multiEntry cursor (already exhausted)');
9811
9922
  }
9812
9923
  success(undefined, undefined, undefined);
9813
9924
  return;
9814
9925
  }
9815
9926
  const quotedKeyColumnName = sqlQuote(me.__keyColumnName);
9816
- const sql = ['SELECT * FROM', escapeStoreNameForSQL(me.__store.__currentName)];
9817
- /** @type {string[]} */
9818
- const sqlValues = [];
9819
- sql.push('WHERE', quotedKeyColumnName, 'NOT NULL');
9820
- if (me.__range && me.__range.lower !== undefined && Array.isArray(me.__range.upper)) {
9821
- if (me.__range.upper.indexOf(me.__range.lower) === 0) {
9822
- sql.push('AND', quotedKeyColumnName, "LIKE ? ESCAPE '^'");
9823
- sqlValues.push('%' + sqlLIKEEscape(/** @type {string} */me.__range.__lowerCached.slice(0, -1)) + '%');
9824
- }
9825
- }
9927
+ const quotedKey = sqlQuote('key');
9826
9928
 
9827
9929
  // Determine the ORDER BY direction based on the cursor.
9828
9930
  const direction = me.__sqlDirection;
9829
9931
  const op = direction === 'ASC' ? '>' : '<';
9830
- const quotedKey = sqlQuote('key');
9831
- if (primaryKey !== undefined) {
9832
- sql.push('AND', quotedKey, op + '= ?');
9833
- // Key.convertValueToKey(primaryKey); // Already checked by `continuePrimaryKey`
9834
- sqlValues.push(/** @type {string} */encode$1(primaryKey));
9835
- }
9836
- if (key !== undefined) {
9837
- sql.push('AND', quotedKeyColumnName, op + '= ?');
9838
- // Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
9839
- sqlValues.push(/** @type {string} */encode$1(key));
9840
- } else if (me.__key !== undefined) {
9841
- sql.push('AND', quotedKeyColumnName, op + ' ?');
9842
- // Key.convertValueToKey(me.__key); // Already checked when entered
9843
- sqlValues.push(/** @type {string} */encode$1(me.__key));
9844
- }
9845
- if (!me.__count) {
9846
- // 1. Sort by key
9847
- sql.push('ORDER BY', quotedKeyColumnName, direction);
9848
9932
 
9849
- // 2. Sort by primaryKey (if defined and not unique)
9850
- if (!me.__unique && me.__keyColumnName !== 'key') {
9851
- // Avoid adding 'key' twice
9852
- sql.push(',', sqlQuote('key'), direction);
9933
+ /**
9934
+ * Runs (and, if a batch of underlying rows produces no matching
9935
+ * multi-entry values, repeatedly re-runs) the query for the next batch
9936
+ * of underlying rows, advancing `me.__continuationKey`/
9937
+ * `me.__continuationPrimaryKey` (tracking the last *physical* row
9938
+ * scanned) each time, until either some matches are found or the
9939
+ * underlying table is exhausted.
9940
+ * @returns {void}
9941
+ */
9942
+ function runQuery() {
9943
+ const sql = ['SELECT * FROM', escapeStoreNameForSQL(me.__store.__currentName)];
9944
+ /** @type {string[]} */
9945
+ const sqlValues = [];
9946
+ sql.push('WHERE', quotedKeyColumnName, 'NOT NULL');
9947
+ if (me.__range && me.__range.lower !== undefined && Array.isArray(me.__range.upper)) {
9948
+ if (me.__range.upper.indexOf(me.__range.lower) === 0) {
9949
+ sql.push('AND', quotedKeyColumnName, "LIKE ? ESCAPE '^'");
9950
+ sqlValues.push('%' + sqlLIKEEscape(/** @type {string} */me.__range.__lowerCached.slice(0, -1)) + '%');
9951
+ }
9952
+ }
9953
+ if (primaryKey !== undefined) {
9954
+ sql.push('AND', quotedKey, op + '= ?');
9955
+ // Key.convertValueToKey(primaryKey); // Already checked by `continuePrimaryKey`
9956
+ sqlValues.push(/** @type {string} */encode$1(primaryKey));
9853
9957
  }
9854
-
9855
- // 3. Sort by position (if defined)
9856
-
9857
- if (!me.__unique && me.__indexSource) {
9858
- // 4. Sort by object store position (if defined and not unique)
9859
- sql.push(',', sqlQuote(me.__valueColumnName), direction);
9958
+ if (key !== undefined) {
9959
+ sql.push('AND', quotedKeyColumnName, op + '= ?');
9960
+ // Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
9961
+ sqlValues.push(/** @type {string} */encode$1(key));
9962
+ } else if (me.__continuationKey !== undefined) {
9963
+ // Resume from the last underlying (physical) row we scanned, not
9964
+ // from the last *matching* multi-entry value (which lives in a
9965
+ // different key-space than the raw index column and cannot be
9966
+ // reliably compared against it, e.g. for array index keys).
9967
+ sql.push('AND (', quotedKeyColumnName, op, '?', 'OR (', quotedKeyColumnName, '= ?', 'AND', quotedKey, op, '?))');
9968
+ const encodedContinuationKey = /** @type {string} */
9969
+ encode$1(me.__continuationKey, true);
9970
+ sqlValues.push(encodedContinuationKey, encodedContinuationKey, /** @type {string} */encode$1(me.__continuationPrimaryKey));
9971
+ }
9972
+ if (!me.__count) {
9973
+ // 1. Sort by key
9974
+ sql.push('ORDER BY', quotedKeyColumnName, direction);
9975
+
9976
+ // 2. Sort by primaryKey (if defined and not unique)
9977
+ if (!me.__unique && me.__keyColumnName !== 'key') {
9978
+ // Avoid adding 'key' twice
9979
+ sql.push(',', sqlQuote('key'), direction);
9980
+ }
9981
+
9982
+ // 3. Sort by position (if defined)
9983
+
9984
+ if (!me.__unique && me.__indexSource) {
9985
+ // 4. Sort by object store position (if defined and not unique)
9986
+ sql.push(',', sqlQuote(me.__valueColumnName), direction);
9987
+ }
9988
+ sql.push('LIMIT', String(recordsToLoad));
9989
+ }
9990
+ const sqlStr = sql.join(' ');
9991
+ if (CFG.DEBUG) {
9992
+ console.log('[multiEntry] query', sqlStr, sqlValues);
9860
9993
  }
9861
- sql.push('LIMIT', String(recordsToLoad));
9862
- }
9863
- const sqlStr = sql.join(' ');
9864
- if (CFG.DEBUG) {
9865
- console.log(sqlStr, sqlValues);
9866
- }
9867
- tx.executeSql(sqlStr, sqlValues, function (tx, data) {
9868
- if (data.rows.length > 0) {
9994
+ tx.executeSql(sqlStr, sqlValues, function (tx, data) {
9995
+ if (data.rows.length === 0) {
9996
+ me.__multiEntryExhausted = true;
9997
+ if (CFG.DEBUG) {
9998
+ console.log('[multiEntry] Reached end of multiEntry cursor (no more rows)');
9999
+ }
10000
+ success(undefined, undefined, undefined);
10001
+ return;
10002
+ }
9869
10003
  if (me.__count) {
9870
10004
  // Avoid caching and other processing below
9871
10005
  let ct = 0;
@@ -9878,6 +10012,16 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
9878
10012
  success(undefined, ct, undefined);
9879
10013
  return;
9880
10014
  }
10015
+
10016
+ // Track how far we've physically scanned, regardless of whether
10017
+ // this batch produced any matches, so the next batch (if any)
10018
+ // resumes after this one instead of re-scanning or stopping early.
10019
+ const lastRawRow = data.rows.item(data.rows.length - 1);
10020
+ me.__continuationKey = decode$1(lastRawRow[me.__keyColumnName], true);
10021
+ me.__continuationPrimaryKey = decode$1(lastRawRow.key);
10022
+ if (data.rows.length < recordsToLoad) {
10023
+ me.__multiEntryExhausted = true;
10024
+ }
9881
10025
  const rows = [];
9882
10026
  for (let i = 0; i < data.rows.length; i++) {
9883
10027
  const rowItem = data.rows.item(i);
@@ -9897,6 +10041,20 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
9897
10041
  rows.push(clone);
9898
10042
  }
9899
10043
  }
10044
+ if (rows.length === 0) {
10045
+ if (me.__multiEntryExhausted) {
10046
+ if (CFG.DEBUG) {
10047
+ console.log('[multiEntry] Reached end of multiEntry cursor (last batch had no matches)');
10048
+ }
10049
+ success(undefined, undefined, undefined);
10050
+ return;
10051
+ }
10052
+ if (CFG.DEBUG) {
10053
+ console.log('[multiEntry] batch had no matches; fetching next batch');
10054
+ }
10055
+ runQuery();
10056
+ return;
10057
+ }
9900
10058
  const reverse = me.direction.indexOf('prev') === 0;
9901
10059
  rows.sort(function (a, b) {
9902
10060
  if (a.matchingKey.replaceAll(leftBracketRegex, 'z') < b.matchingKey.replaceAll(leftBracketRegex, 'z')) {
@@ -9913,47 +10071,31 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
9913
10071
  }
9914
10072
  return 0;
9915
10073
  });
9916
- if (rows.length > 1) {
9917
- me.__prefetchedIndex = 0;
9918
- me.__prefetchedData = {
9919
- data: rows,
9920
- length: rows.length,
9921
- /**
9922
- * @param {Integer} index
9923
- * @returns {RowItemNonNull}
9924
- */
9925
- item(index) {
9926
- return this.data[index];
9927
- }
9928
- };
9929
- if (CFG.DEBUG) {
9930
- console.log('Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
9931
- }
9932
- me.__decode(rows[0], success);
9933
- } else if (rows.length === 1) {
9934
- if (CFG.DEBUG) {
9935
- console.log('Reached end of multiEntry cursor');
9936
- }
9937
- me.__decode(rows[0], success);
9938
- } else {
9939
- if (CFG.DEBUG) {
9940
- console.log('Reached end of multiEntry cursor');
10074
+ me.__prefetchedIndex = 0;
10075
+ me.__prefetchedData = {
10076
+ data: rows,
10077
+ length: rows.length,
10078
+ /**
10079
+ * @param {Integer} index
10080
+ * @returns {RowItemNonNull}
10081
+ */
10082
+ item(index) {
10083
+ return this.data[index];
9941
10084
  }
9942
- success(undefined, undefined, undefined);
10085
+ };
10086
+ if (CFG.DEBUG) {
10087
+ console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
9943
10088
  }
9944
- } else {
10089
+ me.__decode(rows[0], success);
10090
+ }, function (tx, err) {
9945
10091
  if (CFG.DEBUG) {
9946
- console.log('Reached end of multiEntry cursor');
10092
+ console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
9947
10093
  }
9948
- success(undefined, undefined, undefined);
9949
- }
9950
- }, function (tx, err) {
9951
- if (CFG.DEBUG) {
9952
- console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
9953
- }
9954
- error(err);
9955
- return false;
9956
- });
10094
+ error(err);
10095
+ return false;
10096
+ });
10097
+ }
10098
+ runQuery();
9957
10099
  };
9958
10100
 
9959
10101
  /**
@@ -10062,6 +10204,7 @@ IDBCursor.prototype.__sourceOrEffectiveObjStoreDeleted = function () {
10062
10204
  IDBCursor.prototype.__invalidateCache = function () {
10063
10205
  // @ts-expect-error Why is this not being found?
10064
10206
  this.__prefetchedData = null;
10207
+ this.__multiEntryExhausted = false;
10065
10208
  };
10066
10209
 
10067
10210
  /**
@@ -10117,8 +10260,8 @@ IDBCursor.prototype.__continueFinish = function (key, primaryKey, advanceState)
10117
10260
  me.__advanceCount--;
10118
10261
  me.__key = k;
10119
10262
  me.__continue(undefined, true);
10120
- /** @type {() => void} */
10121
- executeNextRequest(); // We don't call success yet but do need to advance the transaction queue
10263
+ // We don't call success yet but do need to advance the transaction queue
10264
+ runContinuationSafely(/** @type {() => void} */executeNextRequest);
10122
10265
  return;
10123
10266
  }
10124
10267
  me.__advanceCount = undefined;
@@ -10140,11 +10283,11 @@ IDBCursor.prototype.__continueFinish = function (key, primaryKey, advanceState)
10140
10283
  return;
10141
10284
  }
10142
10285
  // @ts-expect-error Todo: Our bug to fix
10143
- cursorContinue(tx, args, success, error);
10286
+ runContinuationSafely(() => cursorContinue(tx, args, success, error));
10144
10287
  }
10145
10288
  if (me.__unique && !me.__multiEntryIndex && encKey === encode$1(me.key, me.__multiEntryIndex)) {
10146
10289
  // @ts-expect-error Todo: Our bug to fix
10147
- cursorContinue(tx, args, success, error);
10290
+ runContinuationSafely(() => cursorContinue(tx, args, success, error));
10148
10291
  return;
10149
10292
  }
10150
10293
  checkKey();
@@ -10747,21 +10890,21 @@ function requireNextTick() {
10747
10890
  return nextTick;
10748
10891
  }
10749
10892
 
10750
- var queueMicrotask = {};
10893
+ var queueMicrotask$1 = {};
10751
10894
 
10752
10895
  var hasRequiredQueueMicrotask;
10753
10896
  function requireQueueMicrotask() {
10754
- if (hasRequiredQueueMicrotask) return queueMicrotask;
10897
+ if (hasRequiredQueueMicrotask) return queueMicrotask$1;
10755
10898
  hasRequiredQueueMicrotask = 1;
10756
- queueMicrotask.test = function () {
10899
+ queueMicrotask$1.test = function () {
10757
10900
  return typeof commonjsGlobal.queueMicrotask === 'function';
10758
10901
  };
10759
- queueMicrotask.install = function (func) {
10902
+ queueMicrotask$1.install = function (func) {
10760
10903
  return function () {
10761
10904
  commonjsGlobal.queueMicrotask(func);
10762
10905
  };
10763
10906
  };
10764
- return queueMicrotask;
10907
+ return queueMicrotask$1;
10765
10908
  }
10766
10909
 
10767
10910
  var mutation = {};
@@ -10860,11 +11003,11 @@ function requireTimeout() {
10860
11003
  return timeout;
10861
11004
  }
10862
11005
 
10863
- var lib;
10864
- var hasRequiredLib;
10865
- function requireLib() {
10866
- if (hasRequiredLib) return lib;
10867
- hasRequiredLib = 1;
11006
+ var lib$1;
11007
+ var hasRequiredLib$1;
11008
+ function requireLib$1() {
11009
+ if (hasRequiredLib$1) return lib$1;
11010
+ hasRequiredLib$1 = 1;
10868
11011
  var types = [requireNextTick(), requireQueueMicrotask(), requireMutation(), requireMessageChannel(), requireStateChange(), requireTimeout()];
10869
11012
  var draining;
10870
11013
  var currentQueue;
@@ -10939,7 +11082,7 @@ function requireLib() {
10939
11082
  return fun.apply(null, array);
10940
11083
  }
10941
11084
  };
10942
- lib = immediate;
11085
+ lib$1 = immediate;
10943
11086
  function immediate(task) {
10944
11087
  var args = new Array(arguments.length - 1);
10945
11088
  if (arguments.length > 1) {
@@ -10953,11 +11096,11 @@ function requireLib() {
10953
11096
  scheduleDrain();
10954
11097
  }
10955
11098
  }
10956
- return lib;
11099
+ return lib$1;
10957
11100
  }
10958
11101
 
10959
- var libExports = requireLib();
10960
- var immediate = /*@__PURE__*/getDefaultExportFromCjs(libExports);
11102
+ var libExports$1 = requireLib$1();
11103
+ var immediate = /*@__PURE__*/getDefaultExportFromCjs(libExports$1);
10961
11104
 
10962
11105
  var tinyQueue;
10963
11106
  var hasRequiredTinyQueue;
@@ -11314,584 +11457,1026 @@ function customOpenDatabase(SQLiteDatabase, opts) {
11314
11457
  return (...args) => openDatabase(args);
11315
11458
  }
11316
11459
 
11317
- var sqlite3$1 = {exports: {}};
11460
+ var lib = {exports: {}};
11318
11461
 
11319
- function commonjsRequire(path) {
11320
- throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
11462
+ var util = {};
11463
+
11464
+ var hasRequiredUtil;
11465
+ function requireUtil() {
11466
+ if (hasRequiredUtil) return util;
11467
+ hasRequiredUtil = 1;
11468
+ util.getBooleanOption = (options, key) => {
11469
+ let value = false;
11470
+ if (key in options && typeof (value = options[key]) !== 'boolean') {
11471
+ throw new TypeError(`Expected the "${key}" option to be a boolean`);
11472
+ }
11473
+ return value;
11474
+ };
11475
+ util.cppdb = Symbol();
11476
+ util.inspect = Symbol.for('nodejs.util.inspect.custom');
11477
+ return util;
11321
11478
  }
11322
11479
 
11323
- var bindings = {exports: {}};
11480
+ var sqliteError;
11481
+ var hasRequiredSqliteError;
11482
+ function requireSqliteError() {
11483
+ if (hasRequiredSqliteError) return sqliteError;
11484
+ hasRequiredSqliteError = 1;
11485
+ class SqliteError extends Error {
11486
+ constructor(message, code) {
11487
+ if (typeof code !== 'string') {
11488
+ throw new TypeError('Expected second argument to be a string');
11489
+ }
11490
+ super('' + message);
11491
+ this.code = code;
11492
+ if (typeof Error.captureStackTrace === 'function') {
11493
+ Error.captureStackTrace(this, SqliteError);
11494
+ }
11495
+ }
11496
+ }
11497
+ Object.defineProperty(SqliteError.prototype, 'name', {
11498
+ value: 'SqliteError',
11499
+ writable: true,
11500
+ enumerable: false,
11501
+ configurable: true
11502
+ });
11503
+ sqliteError = SqliteError;
11504
+ return sqliteError;
11505
+ }
11324
11506
 
11325
- var fileUriToPath_1;
11326
- var hasRequiredFileUriToPath;
11327
- function requireFileUriToPath() {
11328
- if (hasRequiredFileUriToPath) return fileUriToPath_1;
11329
- hasRequiredFileUriToPath = 1;
11330
- /**
11331
- * Module dependencies.
11332
- */
11507
+ var wrappers = {};
11333
11508
 
11334
- var sep = path.sep || '/';
11509
+ var hasRequiredWrappers;
11510
+ function requireWrappers() {
11511
+ if (hasRequiredWrappers) return wrappers;
11512
+ hasRequiredWrappers = 1;
11513
+ const {
11514
+ cppdb
11515
+ } = requireUtil();
11516
+ wrappers.prepare = function prepare(sql) {
11517
+ return this[cppdb].prepare(sql, this, false, false);
11518
+ };
11519
+ wrappers.exec = function exec(sql) {
11520
+ this[cppdb].exec(sql);
11521
+ return this;
11522
+ };
11523
+ wrappers.close = function close() {
11524
+ this[cppdb].close();
11525
+ return this;
11526
+ };
11527
+ wrappers.loadExtension = function loadExtension(...args) {
11528
+ this[cppdb].loadExtension(...args);
11529
+ return this;
11530
+ };
11531
+ wrappers.defaultSafeIntegers = function defaultSafeIntegers(...args) {
11532
+ this[cppdb].defaultSafeIntegers(...args);
11533
+ return this;
11534
+ };
11535
+ wrappers.unsafeMode = function unsafeMode(...args) {
11536
+ this[cppdb].unsafeMode(...args);
11537
+ return this;
11538
+ };
11539
+ wrappers.getters = {
11540
+ name: {
11541
+ get: function name() {
11542
+ return this[cppdb].name;
11543
+ },
11544
+ enumerable: true
11545
+ },
11546
+ open: {
11547
+ get: function open() {
11548
+ return this[cppdb].open;
11549
+ },
11550
+ enumerable: true
11551
+ },
11552
+ inTransaction: {
11553
+ get: function inTransaction() {
11554
+ return this[cppdb].inTransaction;
11555
+ },
11556
+ enumerable: true
11557
+ },
11558
+ readonly: {
11559
+ get: function readonly() {
11560
+ return this[cppdb].readonly;
11561
+ },
11562
+ enumerable: true
11563
+ },
11564
+ memory: {
11565
+ get: function memory() {
11566
+ return this[cppdb].memory;
11567
+ },
11568
+ enumerable: true
11569
+ }
11570
+ };
11571
+ return wrappers;
11572
+ }
11335
11573
 
11336
- /**
11337
- * Module exports.
11338
- */
11574
+ var transaction;
11575
+ var hasRequiredTransaction;
11576
+ function requireTransaction() {
11577
+ if (hasRequiredTransaction) return transaction;
11578
+ hasRequiredTransaction = 1;
11579
+ const {
11580
+ cppdb
11581
+ } = requireUtil();
11582
+ const controllers = new WeakMap();
11583
+ transaction = function transaction(fn) {
11584
+ if (typeof fn !== 'function') throw new TypeError('Expected first argument to be a function');
11585
+ const db = this[cppdb];
11586
+ const controller = getController(db, this);
11587
+ const {
11588
+ apply
11589
+ } = Function.prototype;
11339
11590
 
11340
- fileUriToPath_1 = fileUriToPath;
11591
+ // Each version of the transaction function has these same properties
11592
+ const properties = {
11593
+ default: {
11594
+ value: wrapTransaction(apply, fn, db, controller.default)
11595
+ },
11596
+ deferred: {
11597
+ value: wrapTransaction(apply, fn, db, controller.deferred)
11598
+ },
11599
+ immediate: {
11600
+ value: wrapTransaction(apply, fn, db, controller.immediate)
11601
+ },
11602
+ exclusive: {
11603
+ value: wrapTransaction(apply, fn, db, controller.exclusive)
11604
+ },
11605
+ database: {
11606
+ value: this,
11607
+ enumerable: true
11608
+ }
11609
+ };
11610
+ Object.defineProperties(properties.default.value, properties);
11611
+ Object.defineProperties(properties.deferred.value, properties);
11612
+ Object.defineProperties(properties.immediate.value, properties);
11613
+ Object.defineProperties(properties.exclusive.value, properties);
11341
11614
 
11342
- /**
11343
- * File URI to Path function.
11344
- *
11345
- * @param {String} uri
11346
- * @return {String} path
11347
- * @api public
11348
- */
11615
+ // Return the default version of the transaction function
11616
+ return properties.default.value;
11617
+ };
11349
11618
 
11350
- function fileUriToPath(uri) {
11351
- if ('string' != typeof uri || uri.length <= 7 || 'file://' != uri.substring(0, 7)) {
11352
- throw new TypeError('must pass in a file:// URI to convert to a file path');
11619
+ // Return the database's cached transaction controller, or create a new one
11620
+ const getController = (db, self) => {
11621
+ let controller = controllers.get(db);
11622
+ if (!controller) {
11623
+ const shared = {
11624
+ commit: db.prepare('COMMIT', self, false, false),
11625
+ rollback: db.prepare('ROLLBACK', self, false, false),
11626
+ savepoint: db.prepare('SAVEPOINT `\t_bs3.\t`', self, false, false),
11627
+ release: db.prepare('RELEASE `\t_bs3.\t`', self, false, false),
11628
+ rollbackTo: db.prepare('ROLLBACK TO `\t_bs3.\t`', self, false, false)
11629
+ };
11630
+ controllers.set(db, controller = {
11631
+ default: Object.assign({
11632
+ begin: db.prepare('BEGIN', self, false, false)
11633
+ }, shared),
11634
+ deferred: Object.assign({
11635
+ begin: db.prepare('BEGIN DEFERRED', self, false, false)
11636
+ }, shared),
11637
+ immediate: Object.assign({
11638
+ begin: db.prepare('BEGIN IMMEDIATE', self, false, false)
11639
+ }, shared),
11640
+ exclusive: Object.assign({
11641
+ begin: db.prepare('BEGIN EXCLUSIVE', self, false, false)
11642
+ }, shared)
11643
+ });
11353
11644
  }
11354
- var rest = decodeURI(uri.substring(7));
11355
- var firstSlash = rest.indexOf('/');
11356
- var host = rest.substring(0, firstSlash);
11357
- var path = rest.substring(firstSlash + 1);
11645
+ return controller;
11646
+ };
11358
11647
 
11359
- // 2. Scheme Definition
11360
- // As a special case, <host> can be the string "localhost" or the empty
11361
- // string; this is interpreted as "the machine from which the URL is
11362
- // being interpreted".
11363
- if ('localhost' == host) host = '';
11364
- if (host) {
11365
- host = sep + sep + host;
11648
+ // Return a new transaction function by wrapping the given function
11649
+ const wrapTransaction = (apply, fn, db, {
11650
+ begin,
11651
+ commit,
11652
+ rollback,
11653
+ savepoint,
11654
+ release,
11655
+ rollbackTo
11656
+ }) => function sqliteTransaction() {
11657
+ let before, after, undo;
11658
+ if (db.inTransaction) {
11659
+ before = savepoint;
11660
+ after = release;
11661
+ undo = rollbackTo;
11662
+ } else {
11663
+ before = begin;
11664
+ after = commit;
11665
+ undo = rollback;
11366
11666
  }
11667
+ before.run();
11668
+ try {
11669
+ const result = apply.call(fn, this, arguments);
11670
+ if (result && typeof result.then === 'function') {
11671
+ throw new TypeError('Transaction function cannot return a promise');
11672
+ }
11673
+ after.run();
11674
+ return result;
11675
+ } catch (ex) {
11676
+ if (db.inTransaction) {
11677
+ undo.run();
11678
+ if (undo !== rollback) after.run();
11679
+ }
11680
+ throw ex;
11681
+ }
11682
+ };
11683
+ return transaction;
11684
+ }
11367
11685
 
11368
- // 3.2 Drives, drive letters, mount points, file system root
11369
- // Drive letters are mapped into the top of a file URI in various ways,
11370
- // depending on the implementation; some applications substitute
11371
- // vertical bar ("|") for the colon after the drive letter, yielding
11372
- // "file:///c|/tmp/test.txt". In some cases, the colon is left
11373
- // unchanged, as in "file:///c:/tmp/test.txt". In other cases, the
11374
- // colon is simply omitted, as in "file:///c/tmp/test.txt".
11375
- path = path.replace(/^(.+)\|/, '$1:');
11686
+ var pragma;
11687
+ var hasRequiredPragma;
11688
+ function requirePragma() {
11689
+ if (hasRequiredPragma) return pragma;
11690
+ hasRequiredPragma = 1;
11691
+ const {
11692
+ getBooleanOption,
11693
+ cppdb
11694
+ } = requireUtil();
11695
+ pragma = function pragma(source, options) {
11696
+ if (options == null) options = {};
11697
+ if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
11698
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
11699
+ const simple = getBooleanOption(options, 'simple');
11700
+ const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true, false);
11701
+ return simple ? stmt.pluck().get() : stmt.all();
11702
+ };
11703
+ return pragma;
11704
+ }
11376
11705
 
11377
- // for Windows, we need to invert the path separators from what a URI uses
11378
- if (sep == '\\') {
11379
- path = path.replace(/\//g, '\\');
11380
- }
11381
- if (/^.+\:/.test(path)) ; else {
11382
- // unix path…
11383
- path = sep + path;
11384
- }
11385
- return host + path;
11386
- }
11387
- return fileUriToPath_1;
11706
+ var explain;
11707
+ var hasRequiredExplain;
11708
+ function requireExplain() {
11709
+ if (hasRequiredExplain) return explain;
11710
+ hasRequiredExplain = 1;
11711
+ const {
11712
+ cppdb
11713
+ } = requireUtil();
11714
+ explain = function explain(source) {
11715
+ if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
11716
+ const stmt = this[cppdb].prepare(`EXPLAIN ${source}`, this, false, true);
11717
+ return stmt.all();
11718
+ };
11719
+ return explain;
11388
11720
  }
11389
11721
 
11390
- /**
11391
- * Module dependencies.
11392
- */
11393
- var hasRequiredBindings;
11394
- function requireBindings() {
11395
- if (hasRequiredBindings) return bindings.exports;
11396
- hasRequiredBindings = 1;
11397
- (function (module, exports) {
11398
- var fs = require$$0,
11399
- path$1 = path,
11400
- fileURLToPath = requireFileUriToPath(),
11401
- join = path$1.join,
11402
- dirname = path$1.dirname,
11403
- exists = fs.accessSync && function (path) {
11722
+ var backup;
11723
+ var hasRequiredBackup;
11724
+ function requireBackup() {
11725
+ if (hasRequiredBackup) return backup;
11726
+ hasRequiredBackup = 1;
11727
+ const fs = require$$0;
11728
+ const path$1 = path;
11729
+ const {
11730
+ promisify
11731
+ } = require$$2;
11732
+ const {
11733
+ cppdb
11734
+ } = requireUtil();
11735
+ const fsAccess = promisify(fs.access);
11736
+ backup = async function backup(filename, options) {
11737
+ if (options == null) options = {};
11738
+
11739
+ // Validate arguments
11740
+ if (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');
11741
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
11742
+
11743
+ // Interpret options
11744
+ filename = filename.trim();
11745
+ const attachedName = 'attached' in options ? options.attached : 'main';
11746
+ const handler = 'progress' in options ? options.progress : null;
11747
+
11748
+ // Validate interpreted options
11749
+ if (!filename) throw new TypeError('Backup filename cannot be an empty string');
11750
+ if (filename === ':memory:') throw new TypeError('Invalid backup filename ":memory:"');
11751
+ if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
11752
+ if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
11753
+ if (handler != null && typeof handler !== 'function') throw new TypeError('Expected the "progress" option to be a function');
11754
+
11755
+ // Make sure the specified directory exists
11756
+ await fsAccess(path$1.dirname(filename)).catch(() => {
11757
+ throw new TypeError('Cannot save backup because the directory does not exist');
11758
+ });
11759
+ const isNewFile = await fsAccess(filename).then(() => false, () => true);
11760
+ return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
11761
+ };
11762
+ const runBackup = (backup, handler) => {
11763
+ let rate = 0;
11764
+ let useDefault = true;
11765
+ return new Promise((resolve, reject) => {
11766
+ setImmediate(function step() {
11404
11767
  try {
11405
- fs.accessSync(path);
11406
- } catch (e) {
11407
- return false;
11768
+ const progress = backup.transfer(rate);
11769
+ if (!progress.remainingPages) {
11770
+ backup.close();
11771
+ resolve(progress);
11772
+ return;
11773
+ }
11774
+ if (useDefault) {
11775
+ useDefault = false;
11776
+ rate = 100;
11777
+ }
11778
+ if (handler) {
11779
+ const ret = handler(progress);
11780
+ if (ret !== undefined) {
11781
+ if (typeof ret === 'number' && ret === ret) rate = Math.max(0, Math.min(0x7fffffff, Math.round(ret)));else throw new TypeError('Expected progress callback to return a number or undefined');
11782
+ }
11783
+ }
11784
+ setImmediate(step);
11785
+ } catch (err) {
11786
+ backup.close();
11787
+ reject(err);
11408
11788
  }
11409
- return true;
11410
- } || fs.existsSync || path$1.existsSync,
11411
- defaults = {
11412
- arrow: process.env.NODE_BINDINGS_ARROW || ' → ',
11413
- compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled',
11414
- platform: process.platform,
11415
- arch: process.arch,
11416
- nodePreGyp: 'node-v' + process.versions.modules + '-' + process.platform + '-' + process.arch,
11417
- version: process.versions.node,
11418
- bindings: 'bindings.node',
11419
- try: [
11420
- // node-gyp's linked version in the "build" dir
11421
- ['module_root', 'build', 'bindings'],
11422
- // node-waf and gyp_addon (a.k.a node-gyp)
11423
- ['module_root', 'build', 'Debug', 'bindings'], ['module_root', 'build', 'Release', 'bindings'],
11424
- // Debug files, for development (legacy behavior, remove for node v0.9)
11425
- ['module_root', 'out', 'Debug', 'bindings'], ['module_root', 'Debug', 'bindings'],
11426
- // Release files, but manually compiled (legacy behavior, remove for node v0.9)
11427
- ['module_root', 'out', 'Release', 'bindings'], ['module_root', 'Release', 'bindings'],
11428
- // Legacy from node-waf, node <= 0.4.x
11429
- ['module_root', 'build', 'default', 'bindings'],
11430
- // Production "Release" buildtype binary (meh...)
11431
- ['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'],
11432
- // node-qbs builds
11433
- ['module_root', 'addon-build', 'release', 'install-root', 'bindings'], ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'], ['module_root', 'addon-build', 'default', 'install-root', 'bindings'],
11434
- // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}
11435
- ['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings']]
11436
- };
11437
-
11438
- /**
11439
- * The main `bindings()` function loads the compiled bindings for a given module.
11440
- * It uses V8's Error API to determine the parent filename that this function is
11441
- * being invoked from, which is then used to find the root directory.
11442
- */
11789
+ });
11790
+ });
11791
+ };
11792
+ return backup;
11793
+ }
11443
11794
 
11444
- function bindings(opts) {
11445
- // Argument surgery
11446
- if (typeof opts == 'string') {
11447
- opts = {
11448
- bindings: opts
11449
- };
11450
- } else if (!opts) {
11451
- opts = {};
11452
- }
11795
+ var serialize;
11796
+ var hasRequiredSerialize;
11797
+ function requireSerialize() {
11798
+ if (hasRequiredSerialize) return serialize;
11799
+ hasRequiredSerialize = 1;
11800
+ const {
11801
+ cppdb
11802
+ } = requireUtil();
11803
+ serialize = function serialize(options) {
11804
+ if (options == null) options = {};
11805
+
11806
+ // Validate arguments
11807
+ if (typeof options !== 'object') throw new TypeError('Expected first argument to be an options object');
11808
+
11809
+ // Interpret and validate options
11810
+ const attachedName = 'attached' in options ? options.attached : 'main';
11811
+ if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
11812
+ if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
11813
+ return this[cppdb].serialize(attachedName);
11814
+ };
11815
+ return serialize;
11816
+ }
11453
11817
 
11454
- // maps `defaults` onto `opts` object
11455
- Object.keys(defaults).map(function (i) {
11456
- if (!(i in opts)) opts[i] = defaults[i];
11457
- });
11818
+ var _function;
11819
+ var hasRequired_function;
11820
+ function require_function() {
11821
+ if (hasRequired_function) return _function;
11822
+ hasRequired_function = 1;
11823
+ const {
11824
+ getBooleanOption,
11825
+ cppdb
11826
+ } = requireUtil();
11827
+ _function = function defineFunction(name, options, fn) {
11828
+ // Apply defaults
11829
+ if (options == null) options = {};
11830
+ if (typeof options === 'function') {
11831
+ fn = options;
11832
+ options = {};
11833
+ }
11834
+
11835
+ // Validate arguments
11836
+ if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
11837
+ if (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');
11838
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
11839
+ if (!name) throw new TypeError('User-defined function name cannot be an empty string');
11840
+
11841
+ // Interpret options
11842
+ const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
11843
+ const deterministic = getBooleanOption(options, 'deterministic');
11844
+ const directOnly = getBooleanOption(options, 'directOnly');
11845
+ const varargs = getBooleanOption(options, 'varargs');
11846
+ let argCount = -1;
11847
+
11848
+ // Determine argument count
11849
+ if (!varargs) {
11850
+ argCount = fn.length;
11851
+ if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');
11852
+ if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
11853
+ }
11854
+ this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
11855
+ return this;
11856
+ };
11857
+ return _function;
11858
+ }
11458
11859
 
11459
- // Get the module root
11460
- if (!opts.module_root) {
11461
- opts.module_root = exports.getRoot(exports.getFileName());
11462
- }
11860
+ var aggregate;
11861
+ var hasRequiredAggregate;
11862
+ function requireAggregate() {
11863
+ if (hasRequiredAggregate) return aggregate;
11864
+ hasRequiredAggregate = 1;
11865
+ const {
11866
+ getBooleanOption,
11867
+ cppdb
11868
+ } = requireUtil();
11869
+ aggregate = function defineAggregate(name, options) {
11870
+ // Validate arguments
11871
+ if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
11872
+ if (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');
11873
+ if (!name) throw new TypeError('User-defined function name cannot be an empty string');
11874
+
11875
+ // Interpret options
11876
+ const start = 'start' in options ? options.start : null;
11877
+ const step = getFunctionOption(options, 'step', true);
11878
+ const inverse = getFunctionOption(options, 'inverse', false);
11879
+ const result = getFunctionOption(options, 'result', false);
11880
+ const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
11881
+ const deterministic = getBooleanOption(options, 'deterministic');
11882
+ const directOnly = getBooleanOption(options, 'directOnly');
11883
+ const varargs = getBooleanOption(options, 'varargs');
11884
+ let argCount = -1;
11885
+
11886
+ // Determine argument count
11887
+ if (!varargs) {
11888
+ argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
11889
+ if (argCount > 0) argCount -= 1;
11890
+ if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
11891
+ }
11892
+ this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
11893
+ return this;
11894
+ };
11895
+ const getFunctionOption = (options, key, required) => {
11896
+ const value = key in options ? options[key] : null;
11897
+ if (typeof value === 'function') return value;
11898
+ if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
11899
+ if (required) throw new TypeError(`Missing required option "${key}"`);
11900
+ return null;
11901
+ };
11902
+ const getLength = ({
11903
+ length
11904
+ }) => {
11905
+ if (Number.isInteger(length) && length >= 0) return length;
11906
+ throw new TypeError('Expected function.length to be a positive integer');
11907
+ };
11908
+ return aggregate;
11909
+ }
11463
11910
 
11464
- // Ensure the given bindings name ends with .node
11465
- if (path$1.extname(opts.bindings) != '.node') {
11466
- opts.bindings += '.node';
11467
- }
11911
+ var table;
11912
+ var hasRequiredTable;
11913
+ function requireTable() {
11914
+ if (hasRequiredTable) return table;
11915
+ hasRequiredTable = 1;
11916
+ const {
11917
+ cppdb
11918
+ } = requireUtil();
11919
+ table = function defineTable(name, factory) {
11920
+ // Validate arguments
11921
+ if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
11922
+ if (!name) throw new TypeError('Virtual table module name cannot be an empty string');
11923
+
11924
+ // Determine whether the module is eponymous-only or not
11925
+ let eponymous = false;
11926
+ if (typeof factory === 'object' && factory !== null) {
11927
+ eponymous = true;
11928
+ factory = defer(parseTableDefinition(factory, 'used', name));
11929
+ } else {
11930
+ if (typeof factory !== 'function') throw new TypeError('Expected second argument to be a function or a table definition object');
11931
+ factory = wrapFactory(factory);
11932
+ }
11933
+ this[cppdb].table(factory, name, eponymous);
11934
+ return this;
11935
+ };
11936
+ function wrapFactory(factory) {
11937
+ return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
11938
+ const thisObject = {
11939
+ module: moduleName,
11940
+ database: databaseName,
11941
+ table: tableName
11942
+ };
11468
11943
 
11469
- // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035
11470
- var requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : commonjsRequire;
11471
- var tries = [],
11472
- i = 0,
11473
- l = opts.try.length,
11474
- n,
11475
- b,
11476
- err;
11477
- for (; i < l; i++) {
11478
- n = join.apply(null, opts.try[i].map(function (p) {
11479
- return opts[p] || p;
11480
- }));
11481
- tries.push(n);
11482
- try {
11483
- b = opts.path ? requireFunc.resolve(n) : requireFunc(n);
11484
- if (!opts.path) {
11485
- b.path = n;
11486
- }
11487
- return b;
11488
- } catch (e) {
11489
- if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' && !/not find/i.test(e.message)) {
11490
- throw e;
11491
- }
11492
- }
11944
+ // Generate a new table definition by invoking the factory
11945
+ const def = apply.call(factory, thisObject, args);
11946
+ if (typeof def !== 'object' || def === null) {
11947
+ throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
11493
11948
  }
11494
- err = new Error('Could not locate the bindings file. Tried:\n' + tries.map(function (a) {
11495
- return opts.arrow + a;
11496
- }).join('\n'));
11497
- err.tries = tries;
11498
- throw err;
11949
+ return parseTableDefinition(def, 'returned', moduleName);
11950
+ };
11951
+ }
11952
+ function parseTableDefinition(def, verb, moduleName) {
11953
+ // Validate required properties
11954
+ if (!hasOwnProperty.call(def, 'rows')) {
11955
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
11956
+ }
11957
+ if (!hasOwnProperty.call(def, 'columns')) {
11958
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
11499
11959
  }
11500
- module.exports = exports = bindings;
11501
-
11502
- /**
11503
- * Gets the filename of the JavaScript file that invokes this function.
11504
- * Used to help find the root directory of a module.
11505
- * Optionally accepts an filename argument to skip when searching for the invoking filename
11506
- */
11507
11960
 
11508
- exports.getFileName = function getFileName(calling_file) {
11509
- var origPST = Error.prepareStackTrace,
11510
- origSTL = Error.stackTraceLimit,
11511
- dummy = {},
11512
- fileName;
11513
- Error.stackTraceLimit = 10;
11514
- Error.prepareStackTrace = function (e, st) {
11515
- for (var i = 0, l = st.length; i < l; i++) {
11516
- fileName = st[i].getFileName();
11517
- if (fileName !== __filename) {
11518
- if (calling_file) {
11519
- if (fileName !== calling_file) {
11520
- return;
11521
- }
11522
- } else {
11523
- return;
11524
- }
11525
- }
11526
- }
11527
- };
11961
+ // Validate "rows" property
11962
+ const rows = def.rows;
11963
+ if (typeof rows !== 'function' || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
11964
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
11965
+ }
11528
11966
 
11529
- // run the 'prepareStackTrace' function above
11530
- Error.captureStackTrace(dummy);
11531
- dummy.stack;
11967
+ // Validate "columns" property
11968
+ let columns = def.columns;
11969
+ if (!Array.isArray(columns) || !isStringArray(columns = [...columns])) {
11970
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
11971
+ }
11972
+ if (columns.length !== new Set(columns).size) {
11973
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
11974
+ }
11975
+ if (!columns.length) {
11976
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
11977
+ }
11532
11978
 
11533
- // cleanup
11534
- Error.prepareStackTrace = origPST;
11535
- Error.stackTraceLimit = origSTL;
11979
+ // Validate "parameters" property
11980
+ let parameters;
11981
+ if (hasOwnProperty.call(def, 'parameters')) {
11982
+ parameters = def.parameters;
11983
+ if (!Array.isArray(parameters) || !isStringArray(parameters = [...parameters])) {
11984
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
11985
+ }
11986
+ } else {
11987
+ parameters = inferParameters(rows);
11988
+ }
11989
+ if (parameters.length !== new Set(parameters).size) {
11990
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
11991
+ }
11992
+ if (parameters.length > 32) {
11993
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
11994
+ }
11995
+ for (const parameter of parameters) {
11996
+ if (columns.includes(parameter)) {
11997
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
11998
+ }
11999
+ }
11536
12000
 
11537
- // handle filename that starts with "file://"
11538
- var fileSchema = 'file://';
11539
- if (fileName.indexOf(fileSchema) === 0) {
11540
- fileName = fileURLToPath(fileName);
12001
+ // Validate "safeIntegers" option
12002
+ let safeIntegers = 2;
12003
+ if (hasOwnProperty.call(def, 'safeIntegers')) {
12004
+ const bool = def.safeIntegers;
12005
+ if (typeof bool !== 'boolean') {
12006
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
11541
12007
  }
11542
- return fileName;
11543
- };
12008
+ safeIntegers = +bool;
12009
+ }
11544
12010
 
11545
- /**
11546
- * Gets the root directory of a module, given an arbitrary filename
11547
- * somewhere in the module tree. The "root directory" is the directory
11548
- * containing the `package.json` file.
11549
- *
11550
- * In: /home/nate/node-native-module/lib/index.js
11551
- * Out: /home/nate/node-native-module
11552
- */
12011
+ // Validate "directOnly" option
12012
+ let directOnly = false;
12013
+ if (hasOwnProperty.call(def, 'directOnly')) {
12014
+ directOnly = def.directOnly;
12015
+ if (typeof directOnly !== 'boolean') {
12016
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
12017
+ }
12018
+ }
11553
12019
 
11554
- exports.getRoot = function getRoot(file) {
11555
- var dir = dirname(file),
11556
- prev;
11557
- while (true) {
11558
- if (dir === '.') {
11559
- // Avoids an infinite loop in rare cases, like the REPL
11560
- dir = process.cwd();
11561
- }
11562
- if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
11563
- // Found the 'package.json' file or 'node_modules' dir; we're done
11564
- return dir;
11565
- }
11566
- if (prev === dir) {
11567
- // Got to the top
11568
- throw new Error('Could not find module root given file: "' + file + '". Do you have a `package.json` file? ');
12020
+ // Generate SQL for the virtual table definition
12021
+ const columnDefinitions = [...parameters.map(identifier).map(str => `${str} HIDDEN`), ...columns.map(identifier)];
12022
+ return [`CREATE TABLE x(${columnDefinitions.join(', ')});`, wrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName), parameters, safeIntegers, directOnly];
12023
+ }
12024
+ function wrapGenerator(generator, columnMap, moduleName) {
12025
+ return function* virtualTable(...args) {
12026
+ /*
12027
+ We must defensively clone any buffers in the arguments, because
12028
+ otherwise the generator could mutate one of them, which would cause
12029
+ us to return incorrect values for hidden columns, potentially
12030
+ corrupting the database.
12031
+ */
12032
+ const output = args.map(x => Buffer.isBuffer(x) ? Buffer.from(x) : x);
12033
+ for (let i = 0; i < columnMap.size; ++i) {
12034
+ output.push(null); // Fill with nulls to prevent gaps in array (v8 optimization)
12035
+ }
12036
+ for (const row of generator(...args)) {
12037
+ if (Array.isArray(row)) {
12038
+ extractRowArray(row, output, columnMap.size, moduleName);
12039
+ yield output;
12040
+ } else if (typeof row === 'object' && row !== null) {
12041
+ extractRowObject(row, output, columnMap, moduleName);
12042
+ yield output;
12043
+ } else {
12044
+ throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
11569
12045
  }
11570
- // Try the parent dir next
11571
- prev = dir;
11572
- dir = join(dir, '..');
11573
12046
  }
11574
12047
  };
11575
- })(bindings, bindings.exports);
11576
- return bindings.exports;
11577
- }
11578
-
11579
- var sqlite3Binding;
11580
- var hasRequiredSqlite3Binding;
11581
- function requireSqlite3Binding() {
11582
- if (hasRequiredSqlite3Binding) return sqlite3Binding;
11583
- hasRequiredSqlite3Binding = 1;
11584
- sqlite3Binding = requireBindings()('node_sqlite3.node');
11585
- return sqlite3Binding;
11586
- }
11587
-
11588
- var trace = {};
11589
-
11590
- var hasRequiredTrace;
11591
- function requireTrace() {
11592
- if (hasRequiredTrace) return trace;
11593
- hasRequiredTrace = 1;
11594
- // Inspired by https://github.com/tlrobinson/long-stack-traces
11595
- const util = require$$0$1;
11596
- function extendTrace(object, property, pos) {
11597
- const old = object[property];
11598
- object[property] = function () {
11599
- const error = new Error();
11600
- const name = object.constructor.name + '#' + property + '(' + Array.prototype.slice.call(arguments).map(function (el) {
11601
- return util.inspect(el, false, 0);
11602
- }).join(', ') + ')';
11603
- if (typeof pos === 'undefined') pos = -1;
11604
- if (pos < 0) pos += arguments.length;
11605
- const cb = arguments[pos];
11606
- if (typeof arguments[pos] === 'function') {
11607
- arguments[pos] = function replacement() {
11608
- const err = arguments[0];
11609
- if (err && err.stack && !err.__augmented) {
11610
- err.stack = filter(err).join('\n');
11611
- err.stack += '\n--> in ' + name;
11612
- err.stack += '\n' + filter(error).slice(1).join('\n');
11613
- err.__augmented = true;
11614
- }
11615
- return cb.apply(this, arguments);
11616
- };
12048
+ }
12049
+ function extractRowArray(row, output, columnCount, moduleName) {
12050
+ if (row.length !== columnCount) {
12051
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
12052
+ }
12053
+ const offset = output.length - columnCount;
12054
+ for (let i = 0; i < columnCount; ++i) {
12055
+ output[i + offset] = row[i];
12056
+ }
12057
+ }
12058
+ function extractRowObject(row, output, columnMap, moduleName) {
12059
+ let count = 0;
12060
+ for (const key of Object.keys(row)) {
12061
+ const index = columnMap.get(key);
12062
+ if (index === undefined) {
12063
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
11617
12064
  }
11618
- return old.apply(this, arguments);
11619
- };
12065
+ output[index] = row[key];
12066
+ count += 1;
12067
+ }
12068
+ if (count !== columnMap.size) {
12069
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
12070
+ }
11620
12071
  }
11621
- trace.extendTrace = extendTrace;
11622
- function filter(error) {
11623
- return error.stack.split('\n').filter(function (line) {
11624
- return line.indexOf(__filename) < 0;
11625
- });
12072
+ function inferParameters({
12073
+ length
12074
+ }) {
12075
+ if (!Number.isInteger(length) || length < 0) {
12076
+ throw new TypeError('Expected function.length to be a positive integer');
12077
+ }
12078
+ const params = [];
12079
+ for (let i = 0; i < length; ++i) {
12080
+ params.push(`$${i + 1}`);
12081
+ }
12082
+ return params;
11626
12083
  }
11627
- return trace;
12084
+ const {
12085
+ hasOwnProperty
12086
+ } = Object.prototype;
12087
+ const {
12088
+ apply
12089
+ } = Function.prototype;
12090
+ const GeneratorFunctionPrototype = Object.getPrototypeOf(function* () {});
12091
+ const identifier = str => `"${str.replace(/"/g, '""')}"`;
12092
+ const defer = x => () => x;
12093
+ const isStringArray = arr => {
12094
+ for (let i = 0; i < arr.length; ++i) {
12095
+ if (typeof arr[i] !== 'string') return false;
12096
+ }
12097
+ return true;
12098
+ };
12099
+ return table;
11628
12100
  }
11629
12101
 
11630
- var hasRequiredSqlite3;
11631
- function requireSqlite3() {
11632
- if (hasRequiredSqlite3) return sqlite3$1.exports;
11633
- hasRequiredSqlite3 = 1;
11634
- (function (module, exports) {
11635
- const path$1 = path;
11636
- const sqlite3 = requireSqlite3Binding();
11637
- const EventEmitter = require$$2.EventEmitter;
11638
- module.exports = sqlite3;
11639
- function normalizeMethod(fn) {
11640
- return function (sql) {
11641
- let errBack;
11642
- const args = Array.prototype.slice.call(arguments, 1);
11643
- if (typeof args[args.length - 1] === 'function') {
11644
- const callback = args[args.length - 1];
11645
- errBack = function (err) {
11646
- if (err) {
11647
- callback(err);
11648
- }
11649
- };
11650
- }
11651
- const statement = new Statement(this, sql, errBack);
11652
- return fn.call(this, statement, args);
11653
- };
12102
+ var inspect;
12103
+ var hasRequiredInspect;
12104
+ function requireInspect() {
12105
+ if (hasRequiredInspect) return inspect;
12106
+ hasRequiredInspect = 1;
12107
+ const DatabaseInspection = function Database() {};
12108
+ inspect = function inspect(depth, opts) {
12109
+ return Object.assign(new DatabaseInspection(), this);
12110
+ };
12111
+ return inspect;
12112
+ }
12113
+
12114
+ var database;
12115
+ var hasRequiredDatabase;
12116
+ function requireDatabase() {
12117
+ if (hasRequiredDatabase) return database;
12118
+ hasRequiredDatabase = 1;
12119
+ const fs = require$$0;
12120
+ const path$1 = path;
12121
+ const util = requireUtil();
12122
+ const SqliteError = requireSqliteError();
12123
+ database = function createDatabase(getAddon, allowNativeBinding) {
12124
+ function Database(filenameGiven, options) {
12125
+ if (new.target == null) {
12126
+ return new Database(filenameGiven, options);
12127
+ }
12128
+
12129
+ // Apply defaults
12130
+ let buffer;
12131
+ if (Buffer.isBuffer(filenameGiven)) {
12132
+ buffer = filenameGiven;
12133
+ filenameGiven = ':memory:';
12134
+ }
12135
+ if (filenameGiven == null) filenameGiven = '';
12136
+ if (options == null) options = {};
12137
+
12138
+ // Validate arguments
12139
+ if (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');
12140
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
12141
+ if ('readOnly' in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
12142
+ if ('memory' in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
12143
+
12144
+ // Interpret options
12145
+ const filename = filenameGiven.trim();
12146
+ const anonymous = filename === '' || filename === ':memory:';
12147
+ const readonly = util.getBooleanOption(options, 'readonly');
12148
+ const fileMustExist = util.getBooleanOption(options, 'fileMustExist');
12149
+ const timeout = 'timeout' in options ? options.timeout : 5000;
12150
+ const verbose = 'verbose' in options ? options.verbose : null;
12151
+ const nativeBinding = 'nativeBinding' in options ? options.nativeBinding : null;
12152
+
12153
+ // Validate interpreted options
12154
+ if (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');
12155
+ if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
12156
+ if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
12157
+ if (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the "verbose" option to be a function');
12158
+ if (!allowNativeBinding && 'nativeBinding' in options) throw new TypeError('The "nativeBinding" option is only supported by the default better-sqlite3 entrypoint');
12159
+ if (allowNativeBinding && nativeBinding != null && typeof nativeBinding !== 'string' && typeof nativeBinding !== 'object') throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
12160
+
12161
+ // Load the native addon
12162
+ const addon = getAddon(nativeBinding);
12163
+ if (!addon.isInitialized) {
12164
+ addon.initialize(SqliteError, arrayFactory, arrayAppender, rowFactory, recordFactory);
12165
+ addon.isInitialized = true;
12166
+ }
12167
+
12168
+ // Make sure the specified directory exists
12169
+ if (!anonymous && !filename.startsWith('file:') && !fs.existsSync(path$1.dirname(filename))) {
12170
+ throw new TypeError('Cannot open database because the directory does not exist');
12171
+ }
12172
+ Object.defineProperties(this, {
12173
+ [util.cppdb]: {
12174
+ value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null)
12175
+ },
12176
+ ...wrappers.getters
12177
+ });
11654
12178
  }
11655
- function inherits(target, source) {
11656
- for (const k in source.prototype) target.prototype[k] = source.prototype[k];
12179
+ const wrappers = requireWrappers();
12180
+ Database.prototype.prepare = wrappers.prepare;
12181
+ Database.prototype.transaction = requireTransaction();
12182
+ Database.prototype.pragma = requirePragma();
12183
+ Database.prototype.explain = requireExplain();
12184
+ Database.prototype.backup = requireBackup();
12185
+ Database.prototype.serialize = requireSerialize();
12186
+ Database.prototype.function = require_function();
12187
+ Database.prototype.aggregate = requireAggregate();
12188
+ Database.prototype.table = requireTable();
12189
+ Database.prototype.loadExtension = wrappers.loadExtension;
12190
+ Database.prototype.exec = wrappers.exec;
12191
+ Database.prototype.close = wrappers.close;
12192
+ Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
12193
+ Database.prototype.unsafeMode = wrappers.unsafeMode;
12194
+ Database.prototype[util.inspect] = requireInspect();
12195
+ return Database;
12196
+ };
12197
+ function arrayFactory(...values) {
12198
+ return values;
12199
+ }
12200
+ function arrayAppender(array, ...values) {
12201
+ const offset = array.length;
12202
+ for (let i = 0; i < values.length; ++i) {
12203
+ array[offset + i] = values[i];
11657
12204
  }
11658
- sqlite3.cached = {
11659
- Database: function (file, a, b) {
11660
- if (file === '' || file === ':memory:') {
11661
- // Don't cache special databases.
11662
- return new Database(file, a, b);
11663
- }
11664
- let db;
11665
- file = path$1.resolve(file);
11666
- if (!sqlite3.cached.objects[file]) {
11667
- db = sqlite3.cached.objects[file] = new Database(file, a, b);
11668
- } else {
11669
- // Make sure the callback is called.
11670
- db = sqlite3.cached.objects[file];
11671
- const callback = typeof a === 'number' ? b : a;
11672
- if (typeof callback === 'function') {
11673
- function cb() {
11674
- callback.call(db, null);
11675
- }
11676
- if (db.open) process.nextTick(cb);else db.once('open', cb);
11677
- }
11678
- }
11679
- return db;
11680
- },
11681
- objects: {}
12205
+ }
12206
+ function rowFactory(...keys) {
12207
+ if (!keys.includes('__proto__')) {
12208
+ const parameters = keys.map((_, index) => `v${index}`).join(',');
12209
+ const properties = keys.map((key, index) => `${JSON.stringify(key)}:v${index}`).join(',');
12210
+ return Function(`return (${parameters}) => ({${properties}})`)();
12211
+ }
12212
+ return (...values) => {
12213
+ const row = {};
12214
+ for (let i = 0; i < keys.length; ++i) row[keys[i]] = values[i];
12215
+ return row;
11682
12216
  };
11683
- const Database = sqlite3.Database;
11684
- const Statement = sqlite3.Statement;
11685
- const Backup = sqlite3.Backup;
11686
- inherits(Database, EventEmitter);
11687
- inherits(Statement, EventEmitter);
11688
- inherits(Backup, EventEmitter);
11689
-
11690
- // Database#prepare(sql, [bind1, bind2, ...], [callback])
11691
- Database.prototype.prepare = normalizeMethod(function (statement, params) {
11692
- return params.length ? statement.bind.apply(statement, params) : statement;
11693
- });
12217
+ }
12218
+ function recordFactory(value) {
12219
+ return {
12220
+ value,
12221
+ done: false
12222
+ };
12223
+ }
12224
+ return database;
12225
+ }
11694
12226
 
11695
- // Database#run(sql, [bind1, bind2, ...], [callback])
11696
- Database.prototype.run = normalizeMethod(function (statement, params) {
11697
- statement.run.apply(statement, params).finalize();
11698
- return this;
11699
- });
12227
+ function commonjsRequire(path) {
12228
+ throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
12229
+ }
11700
12230
 
11701
- // Database#get(sql, [bind1, bind2, ...], [callback])
11702
- Database.prototype.get = normalizeMethod(function (statement, params) {
11703
- statement.get.apply(statement, params).finalize();
11704
- return this;
11705
- });
12231
+ var binding = {exports: {}};
11706
12232
 
11707
- // Database#all(sql, [bind1, bind2, ...], [callback])
11708
- Database.prototype.all = normalizeMethod(function (statement, params) {
11709
- statement.all.apply(statement, params).finalize();
11710
- return this;
11711
- });
12233
+ var hasRequiredBinding;
12234
+ function requireBinding() {
12235
+ if (hasRequiredBinding) return binding.exports;
12236
+ hasRequiredBinding = 1;
12237
+ (function (module, exports) {
11712
12238
 
11713
- // Database#each(sql, [bind1, bind2, ...], [callback], [complete])
11714
- Database.prototype.each = normalizeMethod(function (statement, params) {
11715
- statement.each.apply(statement, params).finalize();
11716
- return this;
11717
- });
11718
- Database.prototype.map = normalizeMethod(function (statement, params) {
11719
- statement.map.apply(statement, params).finalize();
11720
- return this;
11721
- });
12239
+ const fs = require$$0;
12240
+ const path$1 = path;
12241
+ const PREBUILD_PLATFORMS = ['linux', 'darwin', 'win32'];
12242
+ const PREBUILD_ARCHS = ['x64', 'arm64'];
12243
+ let DEFAULT_ADDON;
12244
+ function getBinding(nativeBinding) {
12245
+ // If a path was provided, load the binding from the filesystem.
12246
+ if (typeof nativeBinding === 'string') {
12247
+ // See <https://webpack.js.org/api/module-variables/#__non_webpack_require__-webpack-specific>
12248
+ const requireFunc = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : commonjsRequire;
12249
+ return requireFunc(path$1.resolve(nativeBinding).replace(/(\.node)?$/, '.node'));
12250
+ }
11722
12251
 
11723
- // Database#backup(filename, [callback])
11724
- // Database#backup(filename, destName, sourceName, filenameIsDest, [callback])
11725
- Database.prototype.backup = function () {
11726
- let backup;
11727
- if (arguments.length <= 2) {
11728
- // By default, we write the main database out to the main database of the named file.
11729
- // This is the most likely use of the backup api.
11730
- backup = new Backup(this, arguments[0], 'main', 'main', true, arguments[1]);
11731
- } else {
11732
- // Otherwise, give the user full control over the sqlite3_backup_init arguments.
11733
- backup = new Backup(this, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
12252
+ // If an object was provided, use it as the binding directly.
12253
+ if (typeof nativeBinding === 'object' && nativeBinding !== null) {
12254
+ return nativeBinding;
11734
12255
  }
11735
- // Per the sqlite docs, exclude the following errors as non-fatal by default.
11736
- backup.retryErrors = [sqlite3.BUSY, sqlite3.LOCKED];
11737
- return backup;
11738
- };
11739
- Statement.prototype.map = function () {
11740
- const params = Array.prototype.slice.call(arguments);
11741
- const callback = params.pop();
11742
- params.push(function (err, rows) {
11743
- if (err) return callback(err);
11744
- const result = {};
11745
- if (rows.length) {
11746
- const keys = Object.keys(rows[0]);
11747
- const key = keys[0];
11748
- if (keys.length > 2) {
11749
- // Value is an object
11750
- for (let i = 0; i < rows.length; i++) {
11751
- result[rows[i][key]] = rows[i];
11752
- }
11753
- } else {
11754
- const value = keys[1];
11755
- // Value is a plain value
11756
- for (let i = 0; i < rows.length; i++) {
11757
- result[rows[i][key]] = rows[i][value];
11758
- }
11759
- }
11760
- }
11761
- callback(err, result);
11762
- });
11763
- return this.all.apply(this, params);
11764
- };
11765
- let isVerbose = false;
11766
- const supportedEvents = ['trace', 'profile', 'change'];
11767
- Database.prototype.addListener = Database.prototype.on = function (type) {
11768
- const val = EventEmitter.prototype.addListener.apply(this, arguments);
11769
- if (supportedEvents.indexOf(type) >= 0) {
11770
- this.configure(type, true);
11771
- }
11772
- return val;
11773
- };
11774
- Database.prototype.removeListener = function (type) {
11775
- const val = EventEmitter.prototype.removeListener.apply(this, arguments);
11776
- if (supportedEvents.indexOf(type) >= 0 && !this._events[type]) {
11777
- this.configure(type, false);
12256
+
12257
+ // If we're using the default binding and it already exists, just return it.
12258
+ if (DEFAULT_ADDON) {
12259
+ return DEFAULT_ADDON;
11778
12260
  }
11779
- return val;
11780
- };
11781
- Database.prototype.removeAllListeners = function (type) {
11782
- const val = EventEmitter.prototype.removeAllListeners.apply(this, arguments);
11783
- if (supportedEvents.indexOf(type) >= 0) {
11784
- this.configure(type, false);
12261
+
12262
+ // Otherwise, try to find the binding as a prebuilt binary.
12263
+ let filename = getPrebuildPath();
12264
+ if (filename) {
12265
+ return DEFAULT_ADDON = commonjsRequire(filename);
11785
12266
  }
11786
- return val;
11787
- };
11788
12267
 
11789
- // Save the stack trace over EIO callbacks.
11790
- sqlite3.verbose = function () {
11791
- if (!isVerbose) {
11792
- const trace = requireTrace();
11793
- ['prepare', 'get', 'run', 'all', 'each', 'map', 'close', 'exec'].forEach(function (name) {
11794
- trace.extendTrace(Database.prototype, name);
11795
- });
11796
- ['bind', 'get', 'run', 'all', 'each', 'map', 'reset', 'finalize'].forEach(function (name) {
11797
- trace.extendTrace(Statement.prototype, name);
11798
- });
11799
- isVerbose = true;
12268
+ // If no prebuilt binary was found, try the default node-gyp locations.
12269
+ filename = path$1.join(__dirname, '..', 'build', 'Debug', 'better_sqlite3.node');
12270
+ if (!fs.existsSync(filename)) {
12271
+ filename = path$1.join(__dirname, '..', 'build', 'Release', 'better_sqlite3.node');
11800
12272
  }
11801
- return sqlite3;
11802
- };
11803
- })(sqlite3$1);
11804
- return sqlite3$1.exports;
12273
+ return DEFAULT_ADDON = commonjsRequire(filename);
12274
+ }
12275
+ function getPrebuildPath() {
12276
+ if (PREBUILD_PLATFORMS.includes(process.platform) && PREBUILD_ARCHS.includes(process.arch)) {
12277
+ const target = `${isLinuxMusl() ? 'linuxmusl' : process.platform}-${process.arch}`;
12278
+ const filename = path$1.join(__dirname, '..', 'prebuilds', `${target}.node`);
12279
+ if (fs.existsSync(filename)) {
12280
+ return filename;
12281
+ }
12282
+ }
12283
+ return null;
12284
+ }
12285
+ function isLinuxMusl() {
12286
+ return process.platform === 'linux' && !process.report.getReport().header.glibcVersionRuntime;
12287
+ }
12288
+ exports.getBinding = getBinding;
12289
+ exports.getPrebuildPath = getPrebuildPath;
12290
+
12291
+ // This script is executed directly by binding.gyp to detect prebuilt binaries.
12292
+ if (require.main === module) {
12293
+ process.stdout.write(getPrebuildPath() ? '1' : '0');
12294
+ }
12295
+ })(binding, binding.exports);
12296
+ return binding.exports;
11805
12297
  }
11806
12298
 
11807
- var sqlite3Exports = requireSqlite3();
11808
- var sqlite3 = /*@__PURE__*/getDefaultExportFromCjs(sqlite3Exports);
12299
+ var hasRequiredLib;
12300
+ function requireLib() {
12301
+ if (hasRequiredLib) return lib.exports;
12302
+ hasRequiredLib = 1;
12303
+ lib.exports = requireDatabase()(requireBinding().getBinding, true);
12304
+ lib.exports.SqliteError = requireSqliteError();
12305
+ return lib.exports;
12306
+ }
11809
12307
 
11810
- function SQLiteResult(error, insertId, rowsAffected, rows) {
11811
- this.error = error;
11812
- this.insertId = insertId;
11813
- this.rowsAffected = rowsAffected;
11814
- this.rows = rows;
12308
+ var libExports = requireLib();
12309
+ var Database = /*@__PURE__*/getDefaultExportFromCjs(libExports);
12310
+
12311
+ /**
12312
+ *
12313
+ */
12314
+ class SQLiteResult {
12315
+ /**
12316
+ * @param {Error|null|undefined} error
12317
+ * @param {number|undefined} [insertId]
12318
+ * @param {number} [rowsAffected]
12319
+ * @param {object[]} [rows]
12320
+ */
12321
+ constructor(error, insertId, rowsAffected, rows) {
12322
+ this.error = error;
12323
+ this.insertId = insertId;
12324
+ this.rowsAffected = rowsAffected;
12325
+ this.rows = rows;
12326
+ }
11815
12327
  }
12328
+ const READ_ONLY_ERROR = new Error('could not prepare statement (23 not authorized)');
11816
12329
 
11817
- var READ_ONLY_ERROR = new Error('could not prepare statement (23 not authorized)');
11818
- function SQLiteDatabase(name, opts) {
11819
- opts = opts || {};
11820
- this._db = new sqlite3.Database(name);
12330
+ /**
12331
+ * @typedef {(sql: string, duration: number) => void} SQLProfileCallback
12332
+ */
12333
+
12334
+ /**
12335
+ * @typedef {((sql: string) => void)|undefined} SQLTraceCallback
12336
+ */
12337
+
12338
+ /**
12339
+ * @param {string} name
12340
+ * @param {{busyTimeout?: number, trace?: (sql: string) => void, profile?: SQLProfileCallback}} [opts]
12341
+ * @returns {void}
12342
+ */
12343
+ function SQLiteDatabase(name, opts = {}) {
12344
+ /** @type {import('better-sqlite3').Database} */
12345
+ const db = new Database(name);
12346
+
12347
+ /** @type {SQLTraceCallback} */
12348
+ // eslint-disable-next-line prefer-destructuring -- TS
12349
+ let trace = opts.trace;
12350
+ /** @type {SQLProfileCallback|undefined} */
12351
+ // eslint-disable-next-line prefer-destructuring -- TS
12352
+ let profile = opts.profile;
11821
12353
  if (opts.busyTimeout) {
11822
- this._db.configure('busyTimeout', opts.busyTimeout); // Default is 1000
11823
- }
11824
- if (opts.trace) {
11825
- this._db.configure('trace', opts.trace);
12354
+ db.pragma('busy_timeout = ' + Number(opts.busyTimeout));
11826
12355
  }
11827
- if (opts.profile) {
11828
- this._db.configure('profile', opts.profile);
11829
- }
11830
- }
11831
- function runSelect(db, sql, args, cb) {
11832
- db.all(sql, args, function (err, rows) {
11833
- if (err) {
11834
- return cb(new SQLiteResult(err));
12356
+
12357
+ // Kept untyped (rather than the better-sqlite3 `Database` type) since that
12358
+ // type is internal to `@types/better-sqlite3` and can't be named in this
12359
+ // file's emitted declaration.
12360
+ this._db = /** @type {any} */{
12361
+ _db: db,
12362
+ /**
12363
+ * Compatibility with node-sqlite3's configure API.
12364
+ * @param {'busyTimeout'|'trace'|'profile'} option
12365
+ * @param {number|((sql: string, duration?: number) => void)} value
12366
+ * @returns {void}
12367
+ */
12368
+ configure(option, value) {
12369
+ if (option === 'busyTimeout') {
12370
+ db.pragma('busy_timeout = ' + Number(/** @type {number} */value));
12371
+ return;
12372
+ }
12373
+ if (option === 'trace') {
12374
+ trace = /** @type {(sql: string) => void} */value;
12375
+ return;
12376
+ }
12377
+ if (option === 'profile') {
12378
+ profile = /** @type {SQLProfileCallback} */value;
12379
+ }
12380
+ },
12381
+ /**
12382
+ * Compatibility with callback-oriented close semantics.
12383
+ * @param {(err?: Error|null) => void} [cb]
12384
+ * @returns {void}
12385
+ */
12386
+ close(cb) {
12387
+ try {
12388
+ db.close();
12389
+ if (cb) {
12390
+ return cb(null);
12391
+ }
12392
+ } catch (err) {
12393
+ if (cb) {
12394
+ return cb(/** @type {Error} */err);
12395
+ }
12396
+ }
12397
+ return undefined;
12398
+ },
12399
+ getTrace() {
12400
+ return trace;
12401
+ },
12402
+ getProfile() {
12403
+ return profile;
11835
12404
  }
11836
- var insertId = void 0;
11837
- var rowsAffected = 0;
11838
- var resultSet = new SQLiteResult(null, insertId, rowsAffected, rows);
11839
- cb(resultSet);
11840
- });
12405
+ };
11841
12406
  }
11842
- function runNonSelect(db, sql, args, cb) {
11843
- db.run(sql, args, function (err) {
11844
- if (err) {
11845
- return cb(new SQLiteResult(err));
11846
- }
11847
- /* jshint validthis:true */
11848
- var executionResult = this;
11849
- var insertId = executionResult.lastID;
11850
- var rowsAffected = executionResult.changes;
11851
- var rows = [];
11852
- var resultSet = new SQLiteResult(null, insertId, rowsAffected, rows);
11853
- cb(resultSet);
11854
- });
12407
+
12408
+ /**
12409
+ * @param {import('better-sqlite3').Database} db
12410
+ * @param {string} sql
12411
+ * @param {unknown[]} args
12412
+ * @returns {object[]}
12413
+ */
12414
+ function runSelect(db, sql, args) {
12415
+ const stmt = db.prepare(sql);
12416
+ return stmt.reader ? (/** @type {object[]} */stmt.all(...args)) : [];
12417
+ }
12418
+
12419
+ /**
12420
+ * @param {import('better-sqlite3').Database} db
12421
+ * @param {string} sql
12422
+ * @param {unknown[]} args
12423
+ * @returns {import('better-sqlite3').RunResult}
12424
+ */
12425
+ function runNonSelect(db, sql, args) {
12426
+ const stmt = db.prepare(sql);
12427
+ return stmt.run(...args);
11855
12428
  }
12429
+
12430
+ /**
12431
+ * @param {{sql: string, args: unknown[]}[]} queries
12432
+ * @param {boolean} readOnly
12433
+ * @param {(err: Error|null, results?: SQLiteResult[]) => void} callback
12434
+ * @returns {void}
12435
+ */
11856
12436
  SQLiteDatabase.prototype.exec = function exec(queries, readOnly, callback) {
11857
- var db = this._db;
11858
- var len = queries.length;
11859
- var results = new Array(len);
11860
- var i = 0;
11861
- function checkDone() {
11862
- if (++i === len) {
11863
- callback(null, results);
11864
- } else {
11865
- doNext();
11866
- }
11867
- }
11868
- function onQueryComplete(i) {
11869
- return function (res) {
11870
- results[i] = res;
11871
- checkDone();
11872
- };
11873
- }
11874
- function doNext() {
11875
- var query = queries[i];
11876
- var sql = query.sql;
11877
- var args = query.args;
11878
-
11879
- // TODO: It seems like the node-sqlite3 API either allows:
11880
- // 1) all(), which returns results but not rowsAffected or lastID
11881
- // 2) run(), which doesn't return results, but returns rowsAffected and lastID
11882
- // So we try to sniff whether it's a SELECT query or not.
11883
- // This is inherently error-prone, although it will probably work in the 99%
11884
- // case.
11885
- var isSelect = /^\s*SELECT\b/i.test(sql);
12437
+ const db = this._db._db;
12438
+ const len = queries.length;
12439
+ const results = Array.from({
12440
+ length: len
12441
+ });
12442
+ for (let i = 0; i < len; i++) {
12443
+ const query = queries[i];
12444
+ const {
12445
+ sql,
12446
+ args
12447
+ } = query;
12448
+ const isSelect = /^\s*SELECT\b/iu.test(sql);
11886
12449
  if (readOnly && !isSelect) {
11887
- onQueryComplete(i)(new SQLiteResult(READ_ONLY_ERROR));
11888
- } else if (isSelect) {
11889
- runSelect(db, sql, args, onQueryComplete(i));
11890
- } else {
11891
- runNonSelect(db, sql, args, onQueryComplete(i));
12450
+ results[i] = new SQLiteResult(READ_ONLY_ERROR);
12451
+ continue;
12452
+ }
12453
+ const trace = this._db.getTrace();
12454
+ const profile = this._db.getProfile();
12455
+ // eslint-disable-next-line unicorn/prefer-bigint-literals -- `0n` needs ES2020+ target for tsc
12456
+ const start = profile ? process.hrtime.bigint() : BigInt(0);
12457
+ try {
12458
+ if (trace) {
12459
+ trace(sql);
12460
+ }
12461
+ if (isSelect) {
12462
+ const rows = runSelect(db, sql, args);
12463
+ results[i] = new SQLiteResult(null, undefined, 0, rows);
12464
+ } else {
12465
+ const executionResult = runNonSelect(db, sql, args);
12466
+ const insertId = Number(executionResult.lastInsertRowid);
12467
+ results[i] = new SQLiteResult(null, insertId, executionResult.changes, []);
12468
+ }
12469
+ } catch (err) {
12470
+ results[i] = new SQLiteResult(/** @type {Error} */err);
12471
+ } finally {
12472
+ if (profile) {
12473
+ profile(sql, Number(process.hrtime.bigint() - start));
12474
+ }
11892
12475
  }
11893
12476
  }
11894
- doNext();
12477
+ queueMicrotask(() => {
12478
+ callback(null, results);
12479
+ });
11895
12480
  };
11896
12481
 
11897
12482
  /**
@@ -11904,11 +12489,9 @@ function wrappedSQLiteDatabase(name) {
11904
12489
  db._db.configure('busyTimeout', /** @type {number} */CFG.sqlBusyTimeout); // Default is 1000
11905
12490
  }
11906
12491
  if (CFG.sqlTrace) {
11907
- // @ts-expect-error native API?
11908
12492
  db._db.configure('trace', CFG.sqlTrace);
11909
12493
  }
11910
12494
  if (CFG.sqlProfile) {
11911
- // @ts-expect-error native API?
11912
12495
  db._db.configure('profile', CFG.sqlProfile);
11913
12496
  }
11914
12497
  return db;
@@ -11939,6 +12522,7 @@ CFG.win = {
11939
12522
  const __setGlobalVars = function (idb, initialConfig = {}) {
11940
12523
  const obj = setGlobalVars(idb, {
11941
12524
  fs: fs$1,
12525
+ escapeNULForSQLiteStatements: false,
11942
12526
  ...initialConfig
11943
12527
  });
11944
12528
  /* istanbul ignore next -- TS guard */