indexeddbshim 17.0.0 → 17.2.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 (58) 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/DOMException.d.ts.map +1 -1
  7. package/dist/IDBCursor.d.ts +25 -18
  8. package/dist/IDBCursor.d.ts.map +1 -1
  9. package/dist/IDBFactory.d.ts +19 -19
  10. package/dist/IDBFactory.d.ts.map +1 -1
  11. package/dist/IDBIndex.d.ts.map +1 -1
  12. package/dist/IDBKeyRange.d.ts +5 -5
  13. package/dist/IDBKeyRange.d.ts.map +1 -1
  14. package/dist/IDBTransaction.d.ts +24 -3
  15. package/dist/IDBTransaction.d.ts.map +1 -1
  16. package/dist/Key.d.ts +41 -41
  17. package/dist/Key.d.ts.map +1 -1
  18. package/dist/indexeddbshim-Key.js +88 -69
  19. package/dist/indexeddbshim-Key.js.map +1 -1
  20. package/dist/indexeddbshim-Key.min.js +2 -2
  21. package/dist/indexeddbshim-Key.min.js.map +1 -1
  22. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +1682 -1056
  23. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
  24. package/dist/indexeddbshim-UnicodeIdentifiers.js +886 -663
  25. package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
  26. package/dist/indexeddbshim-UnicodeIdentifiers.min.js +4 -4
  27. package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
  28. package/dist/indexeddbshim-node.cjs +1682 -1056
  29. package/dist/indexeddbshim-node.cjs.map +1 -1
  30. package/dist/indexeddbshim-noninvasive.js +886 -663
  31. package/dist/indexeddbshim-noninvasive.js.map +1 -1
  32. package/dist/indexeddbshim-noninvasive.min.js +4 -4
  33. package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
  34. package/dist/indexeddbshim.js +890 -660
  35. package/dist/indexeddbshim.js.map +1 -1
  36. package/dist/indexeddbshim.min.js +4 -4
  37. package/dist/indexeddbshim.min.js.map +1 -1
  38. package/dist/node-UnicodeIdentifiers.d.ts.map +1 -1
  39. package/dist/node.d.ts.map +1 -1
  40. package/dist/nodeSQLiteDatabase.d.ts +65 -0
  41. package/dist/nodeSQLiteDatabase.d.ts.map +1 -0
  42. package/dist/nodeWebSQL.d.ts.map +1 -1
  43. package/dist/util.d.ts +5 -0
  44. package/dist/util.d.ts.map +1 -1
  45. package/package.json +22 -18
  46. package/src/CFG.js +3 -0
  47. package/src/DOMException.js +10 -10
  48. package/src/IDBCursor.js +152 -102
  49. package/src/IDBFactory.js +30 -26
  50. package/src/IDBIndex.js +1 -2
  51. package/src/IDBKeyRange.js +5 -5
  52. package/src/IDBTransaction.js +35 -5
  53. package/src/Key.js +63 -55
  54. package/src/node-UnicodeIdentifiers.js +5 -1
  55. package/src/node.js +5 -1
  56. package/src/nodeSQLiteDatabase.js +174 -0
  57. package/src/nodeWebSQL.js +1 -3
  58. package/src/util.js +62 -3
@@ -1,12 +1,11 @@
1
- /*! indexeddbshim - v17.0.0 - 7/28/2026 */
1
+ /*! indexeddbshim - v17.2.0 - 8/18/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
  */
@@ -2100,11 +2155,11 @@ const createDOMException = useNativeDOMException
2100
2155
  // eslint-disable-next-line @stylistic/operator-linebreak -- Need JSDoc
2101
2156
  ?
2102
2157
  /**
2103
- * @param {string} name
2104
- * @param {string} message
2105
- * @param {ErrorLike} [error]
2106
- * @returns {DOMException}
2107
- */
2158
+ * @param {string} name
2159
+ * @param {string} message
2160
+ * @param {ErrorLike} [error]
2161
+ * @returns {DOMException}
2162
+ */
2108
2163
  function (name, message, error) {
2109
2164
  logError(name, message, error);
2110
2165
  return createNativeDOMException(name, message);
@@ -2112,11 +2167,11 @@ function (name, message, error) {
2112
2167
  // eslint-disable-next-line @stylistic/operator-linebreak -- Need JSDoc
2113
2168
  :
2114
2169
  /**
2115
- * @param {string} name
2116
- * @param {string} message
2117
- * @param {ErrorLike} [error]
2118
- * @returns {Error}
2119
- */
2170
+ * @param {string} name
2171
+ * @param {string} message
2172
+ * @param {ErrorLike} [error]
2173
+ * @returns {Error}
2174
+ */
2120
2175
  function (name, message, error) {
2121
2176
  logError(name, message, error);
2122
2177
  return createNonNativeDOMException(name, message);
@@ -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.
@@ -2650,14 +2714,14 @@ function cmp(first, second) {
2650
2714
  */
2651
2715
 
2652
2716
  /**
2653
- * @typedef {object} KeyValueObject
2654
- * @property {KeyType|"NaN"|"null"|"undefined"|"boolean"|"object"|"symbol"|
2655
- * "function"|"bigint"} type If not `KeyType`, indicates invalid value
2656
- * @property {Value} [value]
2657
- * @property {boolean} [invalid]
2658
- * @property {string} [message]
2659
- * @todo Specify acceptable `value` more precisely
2660
- */
2717
+ * @typedef {object} KeyValueObject
2718
+ * @property {KeyType|"NaN"|"null"|"undefined"|"boolean"|"object"|"symbol"|
2719
+ * "function"|"bigint"} type If not `KeyType`, indicates invalid value
2720
+ * @property {Value} [value]
2721
+ * @property {boolean} [invalid]
2722
+ * @property {string} [message]
2723
+ * @todo Specify acceptable `value` more precisely
2724
+ */
2661
2725
 
2662
2726
  /**
2663
2727
  * @typedef {number|string|Date|ArrayBuffer} ValueTypePrimitive
@@ -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];
@@ -3066,10 +3138,10 @@ function convertValueToKey(input, seen) {
3066
3138
  }
3067
3139
 
3068
3140
  /**
3069
- * Currently not in use.
3070
- * @param {Value} input
3071
- * @returns {KeyValueObject}
3072
- */
3141
+ * Currently not in use.
3142
+ * @param {Value} input
3143
+ * @returns {KeyValueObject}
3144
+ */
3073
3145
  function convertValueToMultiEntryKey(input) {
3074
3146
  return convertValueToKeyValueDecoded(input, null, true, true);
3075
3147
  }
@@ -3104,17 +3176,17 @@ function getCopyBytesHeldByBufferSource(O) {
3104
3176
  }
3105
3177
 
3106
3178
  /**
3107
- * Shortcut utility to avoid returning full keys from `convertValueToKey`
3108
- * and subsequent need to process in calling code unless `fullKeys` is
3109
- * set; may throw.
3110
- * @param {Value} input
3111
- * @param {Value[]|null} [seen]
3112
- * @param {boolean} [multiEntry]
3113
- * @param {boolean} [fullKeys]
3114
- * @throws {TypeError} See `getCopyBytesHeldByBufferSource`
3115
- * @todo Document other allowable `input`
3116
- * @returns {KeyValueObject}
3117
- */
3179
+ * Shortcut utility to avoid returning full keys from `convertValueToKey`
3180
+ * and subsequent need to process in calling code unless `fullKeys` is
3181
+ * set; may throw.
3182
+ * @param {Value} input
3183
+ * @param {Value[]|null} [seen]
3184
+ * @param {boolean} [multiEntry]
3185
+ * @param {boolean} [fullKeys]
3186
+ * @throws {TypeError} See `getCopyBytesHeldByBufferSource`
3187
+ * @todo Document other allowable `input`
3188
+ * @returns {KeyValueObject}
3189
+ */
3118
3190
  function convertValueToKeyValueDecoded(input, seen, multiEntry, fullKeys) {
3119
3191
  seen ||= [];
3120
3192
  if (seen.includes(input)) {
@@ -3256,12 +3328,12 @@ function convertValueToMultiEntryKeyDecoded(key, fullKeys) {
3256
3328
  }
3257
3329
 
3258
3330
  /**
3259
- * An internal utility.
3260
- * @param {Value} input
3261
- * @param {Value[]|null|undefined} [seen]
3262
- * @throws {DOMException} `DataError`
3263
- * @returns {KeyValueObject}
3264
- */
3331
+ * An internal utility.
3332
+ * @param {Value} input
3333
+ * @param {Value[]|null|undefined} [seen]
3334
+ * @throws {DOMException} `DataError`
3335
+ * @returns {KeyValueObject}
3336
+ */
3265
3337
  function convertValueToKeyRethrowingAndIfInvalid(input, seen) {
3266
3338
  const key = convertValueToKey(input, seen);
3267
3339
  if (key.invalid) {
@@ -3282,26 +3354,26 @@ function extractKeyFromValueUsingKeyPath(value, keyPath, multiEntry) {
3282
3354
  return extractKeyValueDecodedFromValueUsingKeyPath(value, keyPath, multiEntry, true);
3283
3355
  }
3284
3356
  /**
3285
- * Not currently in use.
3286
- * @param {Value} value
3287
- * @param {KeyPath} keyPath
3288
- * @param {boolean} multiEntry
3289
- * @returns {KeyPathEvaluateValue}
3290
- */
3357
+ * Not currently in use.
3358
+ * @param {Value} value
3359
+ * @param {KeyPath} keyPath
3360
+ * @param {boolean} multiEntry
3361
+ * @returns {KeyPathEvaluateValue}
3362
+ */
3291
3363
  function evaluateKeyPathOnValue(value, keyPath, multiEntry) {
3292
3364
  return evaluateKeyPathOnValueToDecodedValue(value, keyPath);
3293
3365
  }
3294
3366
 
3295
3367
  /**
3296
- * May throw, return `{failure: true}` (e.g., non-object on keyPath resolution)
3297
- * or `{invalid: true}` (e.g., `NaN`).
3298
- * @param {Value} value
3299
- * @param {KeyPath} keyPath
3300
- * @param {boolean} [multiEntry]
3301
- * @param {boolean} [fullKeys]
3302
- * @returns {KeyValueObject|KeyPathEvaluateValue}
3303
- * @todo Document other possible return?
3304
- */
3368
+ * May throw, return `{failure: true}` (e.g., non-object on keyPath resolution)
3369
+ * or `{invalid: true}` (e.g., `NaN`).
3370
+ * @param {Value} value
3371
+ * @param {KeyPath} keyPath
3372
+ * @param {boolean} [multiEntry]
3373
+ * @param {boolean} [fullKeys]
3374
+ * @returns {KeyValueObject|KeyPathEvaluateValue}
3375
+ * @todo Document other possible return?
3376
+ */
3305
3377
  function extractKeyValueDecodedFromValueUsingKeyPath(value, keyPath, multiEntry, fullKeys) {
3306
3378
  const r = evaluateKeyPathOnValueToDecodedValue(value, keyPath);
3307
3379
  if (r.failure) {
@@ -3513,11 +3585,11 @@ function findMultiEntryMatches(keyEntry, range) {
3513
3585
  }
3514
3586
 
3515
3587
  /**
3516
- * Not currently in use but keeping for spec parity.
3517
- * @param {Key} key
3518
- * @throws {Error} Upon a "bad key"
3519
- * @returns {ValueType}
3520
- */
3588
+ * Not currently in use but keeping for spec parity.
3589
+ * @param {Key} key
3590
+ * @throws {Error} Upon a "bad key"
3591
+ * @returns {ValueType}
3592
+ */
3521
3593
  function convertKeyToValue(key) {
3522
3594
  const {
3523
3595
  type,
@@ -3611,10 +3683,10 @@ const MAX_ALLOWED_CURRENT_NUMBER = 9007199254740992; // 2 ^ 53 (Also equal to `N
3611
3683
  */
3612
3684
 
3613
3685
  /**
3614
- * @callback SQLFailureCallback
3615
- * @param {DOMException|Error} exception
3616
- * @returns {void}
3617
- */
3686
+ * @callback SQLFailureCallback
3687
+ * @param {DOMException|Error} exception
3688
+ * @returns {void}
3689
+ */
3618
3690
 
3619
3691
  /**
3620
3692
  *
@@ -3783,11 +3855,11 @@ const readonlyProperties$4 = /** @type {const} */['lower', 'upper', 'lowerOpen',
3783
3855
 
3784
3856
  /**
3785
3857
  * @typedef {globalThis.IDBKeyRange & {
3786
- * __lowerCached: string|null|false,
3787
- * __upperCached: string|null|false,
3788
- * __lowerOpen: boolean,
3789
- * }} IDBKeyRangeFull
3790
- */
3858
+ * __lowerCached: string|null|false,
3859
+ * __upperCached: string|null|false,
3860
+ * __lowerOpen: boolean,
3861
+ * }} IDBKeyRangeFull
3862
+ */
3791
3863
 
3792
3864
  /**
3793
3865
  * The IndexedDB KeyRange object.
@@ -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) {
@@ -5015,10 +5117,10 @@ IDBTransaction.__assertActive = function (tx) {
5015
5117
  };
5016
5118
 
5017
5119
  /**
5018
- * Used by our `EventTarget.prototype` library to implement bubbling/capturing.
5120
+ * Used by our `EventTarget.prototype` library to implement bubbling/capturing.
5019
5121
  * @this {IDBTransactionFull}
5020
- * @returns {import('./IDBDatabase.js').IDBDatabaseFull}
5021
- */
5122
+ * @returns {import('./IDBDatabase.js').IDBDatabaseFull}
5123
+ */
5022
5124
  IDBTransaction.prototype.__getParent = function () {
5023
5125
  return this.db;
5024
5126
  };
@@ -5052,7 +5154,7 @@ TypesonPromise.__typeson__type__ = "TypesonPromise", "undefined" != typeof Symbo
5052
5154
  }).then(r, n);
5053
5155
  });
5054
5156
  }, TypesonPromise.prototype.catch = function (e) {
5055
- return this.then(() => {}, e);
5157
+ return this.then(void 0, e);
5056
5158
  }, TypesonPromise.resolve = function (e) {
5057
5159
  return new TypesonPromise(t => {
5058
5160
  t(e);
@@ -5108,26 +5210,31 @@ function escapeKeyPathComponent(e) {
5108
5210
  function unescapeKeyPathComponent(e) {
5109
5211
  return e.replaceAll("~1", ".").replaceAll("~0", "~").replace(/^''$/u, "").replaceAll("''''", "''");
5110
5212
  }
5111
- function getByKeyPath(e, t) {
5112
- if ("" === t) return e;
5113
- if (null === e || "object" != typeof e) throw new TypeError("Unexpected non-object type");
5114
- const r = t.indexOf(".");
5115
- if (-1 !== r) {
5116
- const n = e[unescapeKeyPathComponent(t.slice(0, r))];
5117
- return void 0 === n ? void 0 : getByKeyPath(n, t.slice(r + 1));
5213
+ function getByKeyPath(t, r, n) {
5214
+ if ("" === r) return t;
5215
+ if (null === t || "object" != typeof t) throw new TypeError("Unexpected non-object type");
5216
+ const o = r.indexOf("."),
5217
+ s = unescapeKeyPathComponent(-1 === o ? r : r.slice(0, o));
5218
+ if (e(t, s)) {
5219
+ if (-1 !== o) {
5220
+ const e = t[s];
5221
+ return void 0 === e ? void 0 : getByKeyPath(e, r.slice(o + 1));
5222
+ }
5223
+ return t[s];
5118
5224
  }
5119
- return e[unescapeKeyPathComponent(t)];
5120
5225
  }
5121
- function setAtKeyPath(e, t, r) {
5122
- if ("" === t) return r;
5123
- let n = e,
5124
- o = t;
5226
+ function setAtKeyPath(t, r, n, o) {
5227
+ if ("" === r) return n;
5228
+ let s = t,
5229
+ a = r;
5125
5230
  for (;;) {
5126
- if (!n || "object" != typeof n) throw new TypeError("Unexpected non-object type");
5127
- if ("__proto__" === o) throw new TypeError("Invalid property");
5128
- const t = o.indexOf(".");
5129
- if (-1 === t) return n[unescapeKeyPathComponent(o)] = r, e;
5130
- n = n[unescapeKeyPathComponent(o.slice(0, t))], o = o.slice(t + 1);
5231
+ if (!s || "object" != typeof s) throw new TypeError("Unexpected non-object type");
5232
+ const r = a.indexOf("."),
5233
+ i = unescapeKeyPathComponent(-1 === r ? a : a.slice(0, r));
5234
+ if ("__proto__" === i) throw new TypeError("Invalid property");
5235
+ if (-1 === r) return s[i] = n, t;
5236
+ if (!e(s, i)) throw new TypeError("Invalid property");
5237
+ s = s[i], a = a.slice(r + 1);
5131
5238
  }
5132
5239
  }
5133
5240
  function getJSONType(e) {
@@ -5137,7 +5244,7 @@ function getJSONType(e) {
5137
5244
  * @file Typeson - JSON with types.
5138
5245
  * @license The MIT License (MIT)
5139
5246
  * @copyright (c) 2016-2018 David Fahlander, Brett Zamir
5140
- */
5247
+ */
5141
5248
  const {
5142
5249
  keys: r,
5143
5250
  hasOwn: n
@@ -5146,6 +5253,14 @@ const {
5146
5253
  isArray: o
5147
5254
  } = Array,
5148
5255
  s = ["type", "replaced", "iterateIn", "iterateUnsetNumeric", "addLength"];
5256
+ function setOwnEnumerable(e, t, r) {
5257
+ Object.defineProperty(e, t, {
5258
+ configurable: true,
5259
+ enumerable: true,
5260
+ value: r,
5261
+ writable: true
5262
+ });
5263
+ }
5149
5264
  function nestedPathsFirst(e, t) {
5150
5265
  if ("" === e.keypath) return -1;
5151
5266
  let r = e.keypath.match(/\./gu) ?? 0,
@@ -5201,10 +5316,16 @@ class Typeson {
5201
5316
  });
5202
5317
  }
5203
5318
  specialTypeNames(e, t, r = {}) {
5204
- return r.returnTypeNames = true, this.encapsulate(e, t, r);
5319
+ return this.encapsulate(e, t, {
5320
+ ...r,
5321
+ returnTypeNames: true
5322
+ });
5205
5323
  }
5206
5324
  rootTypeName(e, t, r = {}) {
5207
- return r.iterateNone = true, this.encapsulate(e, t, r);
5325
+ return this.encapsulate(e, t, {
5326
+ ...r,
5327
+ iterateNone: true
5328
+ });
5208
5329
  }
5209
5330
  encapsulate(e, t, a) {
5210
5331
  const i = {
@@ -5216,12 +5337,13 @@ class Typeson {
5216
5337
  sync: c
5217
5338
  } = i,
5218
5339
  y = {},
5219
- l = [],
5220
5340
  u = [],
5341
+ l = [],
5221
5342
  p = [],
5222
5343
  f = !("cyclic" in i) || i.cyclic,
5223
5344
  {
5224
- encapsulateObserver: d
5345
+ encapsulateObserver: d,
5346
+ encapsulateError: m
5225
5347
  } = i,
5226
5348
  finish = e => {
5227
5349
  const t = Object.values(y);
@@ -5245,14 +5367,10 @@ class Typeson {
5245
5367
  return await Promise.all(r.map(async function (r) {
5246
5368
  const n = [],
5247
5369
  [o] = t.splice(0, 1),
5248
- [s,, a, i, c, y, l] = o,
5249
- u = _encapsulate(s, r, a, i, n, true, l),
5250
- p = hasConstructorOf(u, TypesonPromise);
5251
- if (s && p) {
5252
- const t = await u.p;
5253
- return c[y] = t, checkPromises(e, n);
5254
- }
5255
- return s ? c[y] = u : e = p ? u.p : u, checkPromises(e, n);
5370
+ [s,, a, i, c, y, u] = o,
5371
+ l = _encapsulate(s, r, a, i, n, true, u),
5372
+ p = hasConstructorOf(l, TypesonPromise);
5373
+ return s && p ? (setOwnEnumerable(c, y, await l.p), checkPromises(e, n)) : (s ? setOwnEnumerable(c, y, l) : e = p ? l.p : l, checkPromises(e, n));
5256
5374
  })), e;
5257
5375
  },
5258
5376
  _adaptBuiltinStateObjectProperties = (e, t, r) => {
@@ -5266,45 +5384,70 @@ class Typeson {
5266
5384
  });
5267
5385
  },
5268
5386
  _encapsulate = (e, t, s, a, c, p, f) => {
5269
- let m,
5270
- h = {};
5271
- const g = d ? function (r) {
5272
- const n = f ?? a.type ?? getJSONType(t);
5273
- d(Object.assign(r ?? h, {
5274
- keypath: e,
5275
- value: t,
5276
- cyclic: s,
5277
- stateObj: a,
5278
- promisesData: c,
5279
- resolvingTypesonPromise: p,
5280
- awaitingTypesonPromise: hasConstructorOf(t, TypesonPromise)
5281
- }, {
5282
- type: n
5283
- }));
5284
- } : null;
5285
- if (["string", "boolean", "number", "undefined"].includes(typeof t)) return void 0 === t || t === 1 / 0 || 0 === t || t === -1 / 0 || Number.isNaN(t) ? (m = a.replaced ? t : replace(e, t, a, c, false, p, g), m !== t && (h = {
5286
- replaced: m
5287
- })) : m = t, g && g(), m;
5288
- if (null === t) return g && g(), t;
5387
+ let h,
5388
+ g = {};
5389
+ const b = d ? function (r) {
5390
+ const n = f ?? a.type ?? getJSONType(t);
5391
+ d(Object.assign(r ?? g, {
5392
+ keypath: e,
5393
+ value: t,
5394
+ cyclic: s,
5395
+ stateObj: a,
5396
+ promisesData: c,
5397
+ resolvingTypesonPromise: p,
5398
+ awaitingTypesonPromise: hasConstructorOf(t, TypesonPromise)
5399
+ }, {
5400
+ type: n
5401
+ }));
5402
+ } : null,
5403
+ getEncapsulatedValue = (e, t, r) => {
5404
+ try {
5405
+ return {
5406
+ value: _encapsulate(e, t[r], Boolean(s), a, c, p)
5407
+ };
5408
+ } catch (n) {
5409
+ if (!m) throw n;
5410
+ const o = f ?? a.type ?? getJSONType(t),
5411
+ s = m({
5412
+ keypath: e,
5413
+ error: n,
5414
+ parent: t,
5415
+ key: r,
5416
+ stateObj: a,
5417
+ type: o
5418
+ });
5419
+ if (!s) throw n;
5420
+ if ("substitute" in s) return {
5421
+ value: s.substitute,
5422
+ substitute: true
5423
+ };
5424
+ if (s.ignore) return;
5425
+ throw n;
5426
+ }
5427
+ };
5428
+ if (["string", "boolean", "number", "undefined"].includes(typeof t)) return void 0 === t || t === 1 / 0 || 0 === t || t === -1 / 0 || Number.isNaN(t) ? (h = a.replaced ? t : replace(e, t, a, c, false, p, b), h !== t && (g = {
5429
+ replaced: h
5430
+ })) : h = t, b && b(), h;
5431
+ if (null === t) return b && b(), t;
5289
5432
  if (s && t && "object" == typeof t && !a.iterateIn && !a.iterateUnsetNumeric) {
5290
- const r = l.indexOf(t);
5291
- if (-1 !== r) return y[e] = "#", g && g({
5292
- cyclicKeypath: u[r]
5293
- }), "#" + u[r];
5294
- true === s && (l.push(t), u.push(e));
5433
+ const r = u.indexOf(t);
5434
+ if (-1 !== r) return y[e] = "#", b && b({
5435
+ cyclicKeypath: l[r]
5436
+ }), "#" + l[r];
5437
+ true === s && (u.push(t), l.push(e));
5295
5438
  }
5296
- const b = isPlainObject(t),
5297
- v = o(t),
5298
- O = (b || v) && (!this.plainObjectReplacers.length || a.replaced) || a.iterateIn ? t : replace(e, t, a, c, b || v, null, g);
5299
- let w;
5300
- if (O !== t ? (m = O, h = {
5301
- replaced: O
5302
- }) : "" === e && hasConstructorOf(t, TypesonPromise) ? (c.push([e, t, s, a, void 0, void 0, a.type]), m = t) : v && "object" !== a.iterateIn || "array" === a.iterateIn ? (w = new Array(t.length), h = {
5303
- clone: w
5304
- }) : !b && (["function", "symbol"].includes(typeof t) || "toJSON" in t || hasConstructorOf(t, TypesonPromise) || hasConstructorOf(t, Promise) || hasConstructorOf(t, ArrayBuffer)) && "object" !== a.iterateIn ? m = t : (w = {}, a.addLength && (w.length = t.length), h = {
5305
- clone: w
5306
- }), g && g(), i.iterateNone) return w ?? m;
5307
- if (!w) return m;
5439
+ const v = isPlainObject(t),
5440
+ O = o(t),
5441
+ w = (v || O) && (!this.plainObjectReplacers.length || a.replaced) || a.iterateIn ? t : replace(e, t, a, c, v || O, null, b);
5442
+ let T;
5443
+ if (w !== t ? (h = w, g = {
5444
+ replaced: w
5445
+ }) : "" === e && hasConstructorOf(t, TypesonPromise) ? (c.push([e, t, s, a, void 0, void 0, a.type]), h = t) : O && "object" !== a.iterateIn || "array" === a.iterateIn ? (T = new Array(t.length), g = {
5446
+ clone: T
5447
+ }) : !v && ("object" != typeof t || "toJSON" in t || hasConstructorOf(t, TypesonPromise) || hasConstructorOf(t, Promise) || hasConstructorOf(t, ArrayBuffer)) && "object" !== a.iterateIn ? h = t : (T = {}, a.addLength && (T.length = t.length), g = {
5448
+ clone: T
5449
+ }), b && b(), i.iterateNone) return T ?? h;
5450
+ if (!T) return h;
5308
5451
  if (a.iterateIn) {
5309
5452
  for (const r in t) {
5310
5453
  const o = {
@@ -5312,11 +5455,12 @@ class Typeson {
5312
5455
  };
5313
5456
  _adaptBuiltinStateObjectProperties(a, o, () => {
5314
5457
  const n = e + (e ? "." : "") + escapeKeyPathComponent(r),
5315
- o = _encapsulate(n, t[r], Boolean(s), a, c, p);
5316
- hasConstructorOf(o, TypesonPromise) ? c.push([n, o, Boolean(s), a, w, r, a.type]) : void 0 !== o && (w[r] = o);
5458
+ o = getEncapsulatedValue(n, t, r),
5459
+ i = o && o.value;
5460
+ hasConstructorOf(i, TypesonPromise) ? c.push([n, i, Boolean(s), a, T, r, a.type]) : o && (void 0 !== i || "substitute" in o) && setOwnEnumerable(T, r, i);
5317
5461
  });
5318
5462
  }
5319
- g && g({
5463
+ b && b({
5320
5464
  endIterateIn: true,
5321
5465
  end: true
5322
5466
  });
@@ -5325,10 +5469,11 @@ class Typeson {
5325
5469
  _adaptBuiltinStateObjectProperties(a, {
5326
5470
  ownKeys: true
5327
5471
  }, () => {
5328
- const e = _encapsulate(n, t[r], Boolean(s), a, c, p);
5329
- hasConstructorOf(e, TypesonPromise) ? c.push([n, e, Boolean(s), a, w, r, a.type]) : void 0 !== e && (w[r] = e);
5472
+ const e = getEncapsulatedValue(n, t, r),
5473
+ o = e && e.value;
5474
+ hasConstructorOf(o, TypesonPromise) ? c.push([n, o, Boolean(s), a, T, r, a.type]) : e && (void 0 !== o || "substitute" in e) && setOwnEnumerable(T, r, o);
5330
5475
  });
5331
- }), g && g({
5476
+ }), b && b({
5332
5477
  endIterateOwn: true,
5333
5478
  end: true
5334
5479
  });
@@ -5341,21 +5486,21 @@ class Typeson {
5341
5486
  ownKeys: false
5342
5487
  }, () => {
5343
5488
  const e = _encapsulate(r, void 0, Boolean(s), a, c, p);
5344
- hasConstructorOf(e, TypesonPromise) ? c.push([r, e, Boolean(s), a, w, n, a.type]) : void 0 !== e && (w[n] = e);
5489
+ hasConstructorOf(e, TypesonPromise) ? c.push([r, e, Boolean(s), a, T, n, a.type]) : void 0 !== e && setOwnEnumerable(T, n, e);
5345
5490
  });
5346
5491
  }
5347
- g && g({
5492
+ b && b({
5348
5493
  endIterateUnsetNumeric: true,
5349
5494
  end: true
5350
5495
  });
5351
5496
  }
5352
- return w;
5497
+ return T;
5353
5498
  },
5354
5499
  replace = (e, t, r, n, o, s, a) => {
5355
5500
  const i = o ? this.plainObjectReplacers : this.nonplainObjectReplacers;
5356
- let l = i.length;
5357
- for (; l--;) {
5358
- const o = i[l];
5501
+ let u = i.length;
5502
+ for (; u--;) {
5503
+ const o = i[u];
5359
5504
  if (o.test(t, r)) {
5360
5505
  const {
5361
5506
  type: i
@@ -5370,24 +5515,24 @@ class Typeson {
5370
5515
  }), (c || !o.replaceAsync) && !o.replace) return a && a({
5371
5516
  typeDetected: true
5372
5517
  }), _encapsulate(e, t, f && "readonly", r, n, s, i);
5373
- let l;
5518
+ let u;
5374
5519
  if (a && a({
5375
5520
  replacing: true
5376
5521
  }), c || !o.replaceAsync) {
5377
5522
  if (void 0 === o.replace) throw new TypeError("Missing replacer");
5378
- l = o.replace(t, r);
5379
- } else l = o.replaceAsync(t, r);
5380
- return _encapsulate(e, l, f && "readonly", r, n, s, i);
5523
+ u = o.replace(t, r);
5524
+ } else u = o.replaceAsync(t, r);
5525
+ return _encapsulate(e, u, f && "readonly", r, n, s, i);
5381
5526
  }
5382
5527
  }
5383
5528
  return t;
5384
5529
  },
5385
- m = _encapsulate("", e, f, t ?? {}, p);
5530
+ h = _encapsulate("", e, f, t ?? {}, p);
5386
5531
  if (p.length) return c && i.throwOnBadSyncType ? (() => {
5387
5532
  throw new TypeError("Sync method requested but async result obtained");
5388
- })() : Promise.resolve(checkPromises(m, p)).then(finish);
5533
+ })() : Promise.resolve(checkPromises(h, p)).then(finish);
5389
5534
  if (!c && i.throwOnBadSyncType) throw new TypeError("Async method requested but sync result obtained");
5390
- return c && i.stringification ? [finish(m)] : c ? finish(m) : Promise.resolve(finish(m));
5535
+ return c && i.stringification ? [finish(h)] : c ? finish(h) : Promise.resolve(finish(h));
5391
5536
  }
5392
5537
  encapsulateSync(e, t, r) {
5393
5538
  return this.encapsulate(e, t, {
@@ -5423,15 +5568,15 @@ class Typeson {
5423
5568
  if (!i || "object" != typeof i || Array.isArray(i)) return finishRevival(e);
5424
5569
  const c = [],
5425
5570
  y = Object.create(null),
5426
- l = {};
5427
- let u = true;
5428
- i.$ && isPlainObject(i.$) && (e = e.$, i = i.$, u = false);
5571
+ u = {};
5572
+ let l = true;
5573
+ i.$ && isPlainObject(i.$) && (e = e.$, i = i.$, l = false);
5429
5574
  const executeReviver = (e, t) => {
5430
5575
  const [r] = this.revivers[e] ?? [];
5431
5576
  if (!r) throw new Error("Unregistered type: " + e);
5432
5577
  if (a && !("revive" in r)) return t;
5433
- if (!a && r.reviveAsync) return r.reviveAsync(t, l);
5434
- if (r.revive) return r.revive(t, l);
5578
+ if (!a && r.reviveAsync) return r.reviveAsync(t, u);
5579
+ if (r.revive) return r.revive(t, u);
5435
5580
  throw new Error("Missing reviver");
5436
5581
  },
5437
5582
  p = [];
@@ -5469,23 +5614,23 @@ class Typeson {
5469
5614
  }, void 0);
5470
5615
  })();
5471
5616
  let d;
5472
- return hasConstructorOf(f, TypesonPromise) ? d = f.then(() => e) : (d = function _revive(e, t, s, l, f) {
5473
- if (u && "$types" === e) return;
5617
+ return hasConstructorOf(f, TypesonPromise) ? d = f.then(() => e) : (d = function _revive(e, t, s, u, f) {
5618
+ if (l && "$types" === e) return;
5474
5619
  const d = p.length,
5475
- m = i[e],
5620
+ m = n(i, e) ? i[e] : void 0,
5476
5621
  h = o(t);
5477
5622
  if (h || isPlainObject(t)) {
5478
5623
  const o = h ? new Array(t.length) : {};
5479
5624
  for (r(t).forEach(r => {
5480
5625
  const n = _revive(e + (e ? "." : "") + escapeKeyPathComponent(r), t[r], s ?? o, o, r),
5481
- set = e => (hasConstructorOf(e, Undefined) ? o[r] = void 0 : void 0 !== e && (o[r] = e), e);
5626
+ set = e => (hasConstructorOf(e, Undefined) ? setOwnEnumerable(o, r, void 0) : void 0 !== e && setOwnEnumerable(o, r, e), e);
5482
5627
  hasConstructorOf(n, TypesonPromise) ? p.push(n.then(e => set(e))) : set(n);
5483
5628
  }), t = o; c.length;) {
5484
5629
  const [[e, t, r, o]] = c,
5485
5630
  s = n(y, t),
5486
5631
  a = s ? y[t] : getByKeyPath(e, t);
5487
5632
  if (!s && void 0 === a) break;
5488
- r[o] = a, c.shift();
5633
+ setOwnEnumerable(r, o, a), c.shift();
5489
5634
  }
5490
5635
  }
5491
5636
  if (!m) return y[e] = t, t;
@@ -5493,7 +5638,7 @@ class Typeson {
5493
5638
  const e = t.slice(1),
5494
5639
  r = n(y, e),
5495
5640
  o = r ? y[e] : getByKeyPath(s, e);
5496
- return r || void 0 !== o || c.push([s, e, l, f]), o;
5641
+ return r || void 0 !== o || c.push([s, e, u, f]), o;
5497
5642
  }
5498
5643
  const applyType = t => {
5499
5644
  const r = [].concat(m).reduce(function reducer(e, t) {
@@ -5533,11 +5678,10 @@ class Typeson {
5533
5678
  if ("#" === t) throw new TypeError("# cannot be used as a type name as it is reserved for cyclic objects");
5534
5679
  if (a.includes(t)) throw new TypeError("Plain JSON object types are reserved as type names");
5535
5680
  let r = e[t];
5536
- const s = r && "function" != typeof r && !Array.isArray(r) && r.testPlainObjects ? this.plainObjectReplacers : this.nonplainObjectReplacers,
5537
- i = s.filter(function (e) {
5538
- return e.type === t;
5539
- });
5540
- if (i.length && (s.splice(s.indexOf(i[0]), 1), delete this.revivers[t], delete this.types[t]), "function" == typeof r) {
5681
+ if ([this.plainObjectReplacers, this.nonplainObjectReplacers].forEach(e => {
5682
+ const r = e.findIndex(e => e.type === t);
5683
+ -1 !== r && e.splice(r, 1);
5684
+ }), delete this.revivers[t], delete this.types[t], "function" == typeof r) {
5541
5685
  const e = r;
5542
5686
  r = {
5543
5687
  test: t => t && t.constructor === e,
@@ -5555,13 +5699,13 @@ class Typeson {
5555
5699
  };
5556
5700
  }
5557
5701
  if (!r?.test) return;
5558
- const c = {
5702
+ const s = {
5559
5703
  type: t,
5560
5704
  test: r.test.bind(r)
5561
5705
  };
5562
- r.replace && (c.replace = r.replace.bind(r)), r.replaceAsync && (c.replaceAsync = r.replaceAsync.bind(r));
5563
- const y = "number" == typeof n.fallback ? n.fallback : n.fallback ? 0 : 1 / 0;
5564
- if (r.testPlainObjects ? this.plainObjectReplacers.splice(y, 0, c) : this.nonplainObjectReplacers.splice(y, 0, c), r.revive || r.reviveAsync) {
5706
+ r.replace && (s.replace = r.replace.bind(r)), r.replaceAsync && (s.replaceAsync = r.replaceAsync.bind(r));
5707
+ const i = "number" == typeof n.fallback ? n.fallback : n.fallback ? 0 : 1 / 0;
5708
+ if (r.testPlainObjects ? this.plainObjectReplacers.splice(i, 0, s) : this.nonplainObjectReplacers.splice(i, 0, s), r.revive || r.reviveAsync) {
5565
5709
  const e = {};
5566
5710
  r.revive && (e.revive = r.revive.bind(r)), r.reviveAsync && (e.reviveAsync = r.reviveAsync.bind(r)), this.revivers[t] = [e, {
5567
5711
  plain: r.testPlainObjects
@@ -5579,12 +5723,12 @@ class Undefined {}
5579
5723
  Undefined.__typeson__type__ = "TypesonUndefined";
5580
5724
  const a = ["null", "boolean", "number", "string", "array", "object"];
5581
5725
  for (var i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", c = new Uint8Array(256), y = 0; y < 64; y++) c[i.codePointAt(y)] = y;
5582
- var l = function encode(e, t, r) {
5726
+ var u = function encode(e, t, r) {
5583
5727
  null == r && (r = e.byteLength);
5584
5728
  for (var n = new Uint8Array(e, 0, r), o = n.length, s = "", a = 0; a < o; a += 3) s += i[n[a] >> 2], s += i[(3 & n[a]) << 4 | n[a + 1] >> 4], s += i[(15 & n[a + 1]) << 2 | n[a + 2] >> 6], s += i[63 & n[a + 2]];
5585
5729
  return o % 3 == 2 ? s = s.slice(0, -1) + "=" : o % 3 == 1 && (s = s.slice(0, -2) + "=="), s;
5586
5730
  },
5587
- u = function decode(e, t) {
5731
+ l = function decode(e, t) {
5588
5732
  var r = e.length;
5589
5733
  if (r % 4) throw new Error("Bad base64 length: not divisible by four");
5590
5734
  var n,
@@ -5594,8 +5738,8 @@ var l = function encode(e, t, r) {
5594
5738
  i = .75 * e.length,
5595
5739
  y = 0;
5596
5740
  "=" === e[e.length - 1] && (i--, "=" === e[e.length - 2] && i--);
5597
- for (var l = new ArrayBuffer(i, t), u = new Uint8Array(l), p = 0; p < r; p += 4) n = c[e.codePointAt(p)], o = c[e.codePointAt(p + 1)], s = c[e.codePointAt(p + 2)], a = c[e.codePointAt(p + 3)], u[y++] = n << 2 | o >> 4, u[y++] = (15 & o) << 4 | s >> 2, u[y++] = (3 & s) << 6 | 63 & a;
5598
- return l;
5741
+ for (var u = new ArrayBuffer(i, t), l = new Uint8Array(u), p = 0; p < r; p += 4) n = c[e.codePointAt(p)], o = c[e.codePointAt(p + 1)], s = c[e.codePointAt(p + 2)], a = c[e.codePointAt(p + 3)], l[y++] = n << 2 | o >> 4, l[y++] = (15 & o) << 4 | s >> 2, l[y++] = (3 & s) << 6 | 63 & a;
5742
+ return u;
5599
5743
  };
5600
5744
  const p = {
5601
5745
  arraybuffer: {
@@ -5606,14 +5750,14 @@ const p = {
5606
5750
  return -1 !== r ? {
5607
5751
  index: r
5608
5752
  } : (t.buffers.push(e), {
5609
- s: l(e),
5753
+ s: u(e),
5610
5754
  maxByteLength: e.maxByteLength,
5611
5755
  resizable: e.resizable
5612
5756
  });
5613
5757
  },
5614
5758
  revive(e, t) {
5615
5759
  if (t.buffers || (t.buffers = []), Object.hasOwn(e, "index")) return t.buffers[e.index];
5616
- const r = u(e.s, e.resizable ? {
5760
+ const r = l(e.s, e.resizable ? {
5617
5761
  maxByteLength: e.maxByteLength
5618
5762
  } : void 0);
5619
5763
  return t.buffers.push(r), r;
@@ -5716,7 +5860,7 @@ const b = {
5716
5860
  byteOffset: t,
5717
5861
  byteLength: r
5718
5862
  } : (n.buffers.push(e), {
5719
- encoded: l(e),
5863
+ encoded: u(e),
5720
5864
  maxByteLength: e.maxByteLength,
5721
5865
  resizable: e.resizable,
5722
5866
  byteOffset: t,
@@ -5734,7 +5878,7 @@ const b = {
5734
5878
  resizable: i
5735
5879
  } = e;
5736
5880
  let c;
5737
- return "index" in e ? c = t.buffers[s] : (c = u(o, i ? {
5881
+ return "index" in e ? c = t.buffers[s] : (c = l(o, i ? {
5738
5882
  maxByteLength: a
5739
5883
  } : a), t.buffers.push(c)), new DataView(c, r, n);
5740
5884
  }
@@ -5907,7 +6051,7 @@ function create$2(e) {
5907
6051
  };
5908
6052
  }
5909
6053
  [TypeError, RangeError, SyntaxError, ReferenceError, EvalError, URIError].forEach(e => create$2(e)), "undefined" != typeof AggregateError && create$2(AggregateError), "function" == typeof InternalError && create$2(InternalError);
5910
- const N = {
6054
+ const E = {
5911
6055
  file: {
5912
6056
  test: e => "File" === toStringTag(e),
5913
6057
  replace(e) {
@@ -5944,8 +6088,8 @@ const N = {
5944
6088
  })
5945
6089
  }
5946
6090
  },
5947
- _ = {
5948
- file: N.file,
6091
+ N = {
6092
+ file: E.file,
5949
6093
  filelist: {
5950
6094
  test: e => "FileList" === toStringTag(e),
5951
6095
  replace(e) {
@@ -5969,7 +6113,7 @@ const N = {
5969
6113
  }
5970
6114
  }
5971
6115
  },
5972
- B = {
6116
+ _ = {
5973
6117
  imagebitmap: {
5974
6118
  test: e => "ImageBitmap" === toStringTag(e) || e && e.dataset && "ImageBitmap" === e.dataset.toStringTag,
5975
6119
  replace(e) {
@@ -6004,7 +6148,7 @@ const N = {
6004
6148
  }
6005
6149
  }
6006
6150
  },
6007
- E = {
6151
+ B = {
6008
6152
  imagedata: {
6009
6153
  test: e => "ImageData" === toStringTag(e),
6010
6154
  replace: e => ({
@@ -6015,7 +6159,7 @@ const N = {
6015
6159
  revive: e => new ImageData(new Uint8ClampedArray(e.array), e.width, e.height)
6016
6160
  }
6017
6161
  },
6018
- C = {
6162
+ I = {
6019
6163
  infinity: {
6020
6164
  test: e => e === 1 / 0,
6021
6165
  replace: () => "Infinity",
@@ -6050,7 +6194,7 @@ const N = {
6050
6194
  revive: () => -0
6051
6195
  }
6052
6196
  },
6053
- k = {
6197
+ R = {
6054
6198
  StringObject: {
6055
6199
  test: e => "String" === toStringTag(e) && "object" == typeof e,
6056
6200
  replace: String,
@@ -6067,7 +6211,7 @@ const N = {
6067
6211
  revive: e => new Number(e)
6068
6212
  }
6069
6213
  },
6070
- $ = {
6214
+ K = {
6071
6215
  regexp: {
6072
6216
  test: e => "RegExp" === toStringTag(e),
6073
6217
  replace: e => ({
@@ -6080,7 +6224,7 @@ const N = {
6080
6224
  }) => new RegExp(e, t)
6081
6225
  }
6082
6226
  },
6083
- J = {
6227
+ z = {
6084
6228
  set: {
6085
6229
  test: e => "Set" === toStringTag(e),
6086
6230
  replace: e => e.values().toArray(),
@@ -6115,7 +6259,7 @@ const W = {};
6115
6259
  } : (n.buffers.push(e), {
6116
6260
  maxByteLength: e.maxByteLength,
6117
6261
  resizable: e.resizable,
6118
- encoded: l(e),
6262
+ encoded: u(e),
6119
6263
  byteOffset: t,
6120
6264
  length: r
6121
6265
  });
@@ -6131,7 +6275,7 @@ const W = {};
6131
6275
  resizable: c
6132
6276
  } = t;
6133
6277
  let y;
6134
- return "index" in t ? y = r.buffers[a] : (y = u(s, c ? {
6278
+ return "index" in t ? y = r.buffers[a] : (y = l(s, c ? {
6135
6279
  maxByteLength: i
6136
6280
  } : void 0), r.buffers.push(y)), new e(y, n, o);
6137
6281
  }
@@ -6173,8 +6317,8 @@ const Q = {
6173
6317
  revive() {}
6174
6318
  }
6175
6319
  }],
6176
- X = [M, C, L, D],
6177
- re = [G, Q, H, k, X, O, $, E, B, N, _, m, x, j].concat("function" == typeof Map ? U : [], "function" == typeof Set ? J : [], "function" == typeof ArrayBuffer ? p : [], "function" == typeof Uint8Array ? W : [], "function" == typeof DataView ? v : [], "undefined" != typeof crypto ? b : [], "undefined" != typeof BigInt ? [d, f] : [], "undefined" != typeof DOMException ? w : [], "undefined" != typeof DOMRect ? S : [], "undefined" != typeof DOMPoint ? A : [], "undefined" != typeof DOMQuad ? P : [], "undefined" != typeof DOMMatrix ? T : []),
6320
+ X = [M, I, L, D],
6321
+ re = [G, Q, H, R, X, O, K, B, _, E, N, m, x, j].concat("function" == typeof Map ? U : [], "function" == typeof Set ? z : [], "function" == typeof ArrayBuffer ? p : [], "function" == typeof Uint8Array ? W : [], "function" == typeof DataView ? v : [], "undefined" != typeof crypto ? b : [], "undefined" != typeof BigInt ? [d, f] : [], "undefined" != typeof DOMException ? w : [], "undefined" != typeof DOMRect ? S : [], "undefined" != typeof DOMPoint ? A : [], "undefined" != typeof DOMQuad ? P : [], "undefined" != typeof DOMMatrix ? T : []),
6178
6322
  ne = re.concat({
6179
6323
  checkDataCloneException: {
6180
6324
  test(e) {
@@ -6925,7 +7069,7 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
6925
7069
  reject(err);
6926
7070
  });
6927
7071
  }));
6928
- SyncPromise.all(indexCreations).then(finish, /** @type {(reason: any) => PromiseLike<never>} */
7072
+ SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: any) => PromiseLike<never>} */
6929
7073
  error).catch(err => {
6930
7074
  console.log('Index rename error');
6931
7075
  throw err;
@@ -8879,7 +9023,7 @@ function IDBFactory() {
8879
9023
  * __connections: {
8880
9024
  * [key: string]: import('./IDBDatabase.js').IDBDatabaseFull[]
8881
9025
  * }
8882
- * }} IDBFactoryFull
9026
+ * }} IDBFactoryFull
8883
9027
  */
8884
9028
 
8885
9029
  const IDBFactoryAlias = IDBFactory;
@@ -9070,7 +9214,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
9070
9214
  /** @type {import('./IDBDatabase.js').IDBDatabaseFull} */
9071
9215
  req.__result.__versionTransaction = null;
9072
9216
  sysdbFinishedCb(systx, false, function () {
9073
- req.transaction.__transFinishedCb(false, function () {
9217
+ req.transaction.__callTransFinishedCb(false, function () {
9074
9218
  ev.complete();
9075
9219
  req.__transaction = null;
9076
9220
  });
@@ -9181,6 +9325,13 @@ IDBFactory.prototype.open = function (name /* , version */) {
9181
9325
  function openDB(oldVersion) {
9182
9326
  /** @type {DatabaseFull} */
9183
9327
  let db;
9328
+ if (version === undefined) {
9329
+ // Resolve before use as a cache key below, or a `open(name)` call
9330
+ // (no explicit version) would cache/look up under `undefined`
9331
+ // instead of the actual version, causing a second, separate
9332
+ // connection to be opened for the same database on reopen.
9333
+ version = oldVersion || 1;
9334
+ }
9184
9335
  if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
9185
9336
  db = websqlDBCache[name][version];
9186
9337
  } else {
@@ -9192,9 +9343,6 @@ IDBFactory.prototype.open = function (name /* , version */) {
9192
9343
  websqlDBCache[name][version] = db;
9193
9344
  }
9194
9345
  }
9195
- if (version === undefined) {
9196
- version = oldVersion || 1;
9197
- }
9198
9346
  if (oldVersion > version) {
9199
9347
  const err = createDOMException('VersionError', 'An attempt was made to open a database using a lower version than the existing version.', version);
9200
9348
  if (useDatabaseCache) {
@@ -9363,7 +9511,6 @@ IDBFactory.prototype.deleteDatabase = function (name) {
9363
9511
  } = data.rows.item(0));
9364
9512
  const openConnections = me.__connections[name] || [];
9365
9513
  triggerAnyVersionChangeAndBlockedEvents(openConnections, req, version, null).then(function () {
9366
- // eslint-disable-line promise/catch-or-return -- Sync promise
9367
9514
  // Since we need two databases which can't be in a single transaction, we
9368
9515
  // do this deleting from `dbVersions` first since the `__sys__` deleting
9369
9516
  // only impacts file memory whereas this one is critical for avoiding it
@@ -9392,7 +9539,7 @@ IDBFactory.prototype.deleteDatabase = function (name) {
9392
9539
  });
9393
9540
  return undefined;
9394
9541
  // @ts-expect-error It's ok
9395
- }, dbError);
9542
+ }).catch(dbError);
9396
9543
  return undefined;
9397
9544
  }, dbError);
9398
9545
  });
@@ -9423,14 +9570,14 @@ IDBFactory.prototype.cmp = function (key1, key2) {
9423
9570
  };
9424
9571
 
9425
9572
  /**
9426
- * May return outdated information if a database has since been deleted.
9427
- * @see https://github.com/w3c/IndexedDB/pull/240/files
9428
- * @this {IDBFactoryFull}
9429
- * @returns {Promise<{
9430
- * name: string,
9431
- * version: Integer
9432
- * }[]>}
9433
- */
9573
+ * May return outdated information if a database has since been deleted.
9574
+ * @see https://github.com/w3c/IndexedDB/pull/240/files
9575
+ * @this {IDBFactoryFull}
9576
+ * @returns {Promise<{
9577
+ * name: string,
9578
+ * version: Integer
9579
+ * }[]>}
9580
+ */
9434
9581
  IDBFactory.prototype.databases = function () {
9435
9582
  const me = this;
9436
9583
  let calledDbCreateError = false;
@@ -9479,20 +9626,20 @@ IDBFactory.prototype.databases = function () {
9479
9626
  };
9480
9627
 
9481
9628
  /**
9482
- * @todo forceClose: Test
9483
- * This is provided to facilitate unit-testing of the
9484
- * closing of a database connection with a forced flag:
9485
- * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>
9486
- * @param {string} dbName
9487
- * @param {Integer} connIdx
9488
- * @param {string} msg
9489
- * @throws {TypeError}
9490
- * @this {IDBFactoryFull}
9491
- * @returns {void}
9492
- */
9493
- IDBFactory.prototype.__forceClose = function (dbName, connIdx, msg) {
9494
- const me = this;
9495
- /**
9629
+ * @todo forceClose: Test
9630
+ * This is provided to facilitate unit-testing of the
9631
+ * closing of a database connection with a forced flag:
9632
+ * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>
9633
+ * @param {string} dbName
9634
+ * @param {Integer} connIdx
9635
+ * @param {string} msg
9636
+ * @throws {TypeError}
9637
+ * @this {IDBFactoryFull}
9638
+ * @returns {void}
9639
+ */
9640
+ IDBFactory.prototype.__forceClose = function (dbName, connIdx, msg) {
9641
+ const me = this;
9642
+ /**
9496
9643
  *
9497
9644
  * @param {import('./IDBDatabase.js').IDBDatabaseFull} conn
9498
9645
  * @returns {void}
@@ -9574,6 +9721,9 @@ const shimIndexedDB = IDBFactory.__createInstance();
9574
9721
  * __unique: boolean,
9575
9722
  * __sqlDirection: "DESC"|"ASC",
9576
9723
  * __matchedKeys: {[key: string]: true},
9724
+ * __continuationKey: import('./Key.js').Key|undefined,
9725
+ * __continuationPrimaryKey: import('./Key.js').Key|undefined,
9726
+ * __multiEntryExhausted: boolean,
9577
9727
  * __invalidateCache: () => void
9578
9728
  * }} IDBCursorFull
9579
9729
  */
@@ -9647,6 +9797,9 @@ IDBCursor.__super = function IDBCursor(query, direction, store, source, keyColum
9647
9797
  this.__valueDecoder = this.__keyOnly ? Key : Sca;
9648
9798
  this.__count = count;
9649
9799
  this.__prefetchedIndex = -1;
9800
+ this.__continuationKey = undefined;
9801
+ this.__continuationPrimaryKey = undefined;
9802
+ this.__multiEntryExhausted = false;
9650
9803
  this.__multiEntryIndex = this.__indexSource ? 'multiEntry' in source && source.multiEntry : false;
9651
9804
  this.__unique = this.direction.includes('unique');
9652
9805
  this.__sqlDirection = ['prev', 'prevunique'].includes(this.direction) ? 'DESC' : 'ASC';
@@ -9799,73 +9952,96 @@ const leftBracketRegex = /\[/gu;
9799
9952
  * @param {SQLTransaction} tx
9800
9953
  * @param {KeySuccess} success
9801
9954
  * @param {FindError} error
9802
- * @param {Integer|undefined} recordsToLoad
9955
+ * @param {Integer} [recordsToLoad]
9803
9956
  * @this {IDBCursorFull}
9804
9957
  * @returns {void}
9805
9958
  */
9806
- IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error, recordsToLoad) {
9959
+ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error, recordsToLoad = 1) {
9807
9960
  const me = this;
9808
- if (me.__prefetchedData && me.__prefetchedData.length === me.__prefetchedIndex) {
9961
+ if (me.__multiEntryExhausted) {
9809
9962
  if (CFG.DEBUG) {
9810
- console.log('Reached end of multiEntry cursor');
9963
+ console.log('[multiEntry] Reached end of multiEntry cursor (already exhausted)');
9811
9964
  }
9812
9965
  success(undefined, undefined, undefined);
9813
9966
  return;
9814
9967
  }
9815
9968
  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
- }
9969
+ const quotedKey = sqlQuote('key');
9826
9970
 
9827
9971
  // Determine the ORDER BY direction based on the cursor.
9828
9972
  const direction = me.__sqlDirection;
9829
9973
  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
9974
 
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);
9975
+ /**
9976
+ * Runs (and, if a batch of underlying rows produces no matching
9977
+ * multi-entry values, repeatedly re-runs) the query for the next batch
9978
+ * of underlying rows, advancing `me.__continuationKey`/
9979
+ * `me.__continuationPrimaryKey` (tracking the last *physical* row
9980
+ * scanned) each time, until either some matches are found or the
9981
+ * underlying table is exhausted.
9982
+ * @returns {void}
9983
+ */
9984
+ function runQuery() {
9985
+ const sql = ['SELECT * FROM', escapeStoreNameForSQL(me.__store.__currentName)];
9986
+ /** @type {string[]} */
9987
+ const sqlValues = [];
9988
+ sql.push('WHERE', quotedKeyColumnName, 'NOT NULL');
9989
+ if (me.__range && me.__range.lower !== undefined && Array.isArray(me.__range.upper)) {
9990
+ if (me.__range.upper.indexOf(me.__range.lower) === 0) {
9991
+ sql.push('AND', quotedKeyColumnName, "LIKE ? ESCAPE '^'");
9992
+ sqlValues.push('%' + sqlLIKEEscape(/** @type {string} */me.__range.__lowerCached.slice(0, -1)) + '%');
9993
+ }
9994
+ }
9995
+ if (primaryKey !== undefined) {
9996
+ sql.push('AND', quotedKey, op + '= ?');
9997
+ // Key.convertValueToKey(primaryKey); // Already checked by `continuePrimaryKey`
9998
+ sqlValues.push(/** @type {string} */encode$1(primaryKey));
9853
9999
  }
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);
10000
+ if (key !== undefined) {
10001
+ sql.push('AND', quotedKeyColumnName, op + '= ?');
10002
+ // Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
10003
+ sqlValues.push(/** @type {string} */encode$1(key));
10004
+ } else if (me.__continuationKey !== undefined) {
10005
+ // Resume from the last underlying (physical) row we scanned, not
10006
+ // from the last *matching* multi-entry value (which lives in a
10007
+ // different key-space than the raw index column and cannot be
10008
+ // reliably compared against it, e.g. for array index keys).
10009
+ sql.push('AND (', quotedKeyColumnName, op, '?', 'OR (', quotedKeyColumnName, '= ?', 'AND', quotedKey, op, '?))');
10010
+ const encodedContinuationKey = /** @type {string} */
10011
+ encode$1(me.__continuationKey, true);
10012
+ sqlValues.push(encodedContinuationKey, encodedContinuationKey, /** @type {string} */encode$1(me.__continuationPrimaryKey));
10013
+ }
10014
+ if (!me.__count) {
10015
+ // 1. Sort by key
10016
+ sql.push('ORDER BY', quotedKeyColumnName, direction);
10017
+
10018
+ // 2. Sort by primaryKey (if defined and not unique)
10019
+ if (!me.__unique && me.__keyColumnName !== 'key') {
10020
+ // Avoid adding 'key' twice
10021
+ sql.push(',', sqlQuote('key'), direction);
10022
+ }
10023
+
10024
+ // 3. Sort by position (if defined)
10025
+
10026
+ if (!me.__unique && me.__indexSource) {
10027
+ // 4. Sort by object store position (if defined and not unique)
10028
+ sql.push(',', sqlQuote(me.__valueColumnName), direction);
10029
+ }
10030
+ sql.push('LIMIT', String(recordsToLoad));
10031
+ }
10032
+ const sqlStr = sql.join(' ');
10033
+ if (CFG.DEBUG) {
10034
+ console.log('[multiEntry] query', sqlStr, sqlValues);
9860
10035
  }
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) {
10036
+ tx.executeSql(sqlStr, sqlValues, function (tx, data) {
10037
+ if (data.rows.length === 0) {
10038
+ me.__multiEntryExhausted = true;
10039
+ if (CFG.DEBUG) {
10040
+ console.log('[multiEntry] Reached end of multiEntry cursor (no more rows)');
10041
+ }
10042
+ success(undefined, undefined, undefined);
10043
+ return;
10044
+ }
9869
10045
  if (me.__count) {
9870
10046
  // Avoid caching and other processing below
9871
10047
  let ct = 0;
@@ -9878,6 +10054,16 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
9878
10054
  success(undefined, ct, undefined);
9879
10055
  return;
9880
10056
  }
10057
+
10058
+ // Track how far we've physically scanned, regardless of whether
10059
+ // this batch produced any matches, so the next batch (if any)
10060
+ // resumes after this one instead of re-scanning or stopping early.
10061
+ const lastRawRow = data.rows.item(data.rows.length - 1);
10062
+ me.__continuationKey = decode$1(lastRawRow[me.__keyColumnName], true);
10063
+ me.__continuationPrimaryKey = decode$1(lastRawRow.key);
10064
+ if (data.rows.length < recordsToLoad) {
10065
+ me.__multiEntryExhausted = true;
10066
+ }
9881
10067
  const rows = [];
9882
10068
  for (let i = 0; i < data.rows.length; i++) {
9883
10069
  const rowItem = data.rows.item(i);
@@ -9897,6 +10083,20 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
9897
10083
  rows.push(clone);
9898
10084
  }
9899
10085
  }
10086
+ if (rows.length === 0) {
10087
+ if (me.__multiEntryExhausted) {
10088
+ if (CFG.DEBUG) {
10089
+ console.log('[multiEntry] Reached end of multiEntry cursor (last batch had no matches)');
10090
+ }
10091
+ success(undefined, undefined, undefined);
10092
+ return;
10093
+ }
10094
+ if (CFG.DEBUG) {
10095
+ console.log('[multiEntry] batch had no matches; fetching next batch');
10096
+ }
10097
+ runQuery();
10098
+ return;
10099
+ }
9900
10100
  const reverse = me.direction.indexOf('prev') === 0;
9901
10101
  rows.sort(function (a, b) {
9902
10102
  if (a.matchingKey.replaceAll(leftBracketRegex, 'z') < b.matchingKey.replaceAll(leftBracketRegex, 'z')) {
@@ -9913,47 +10113,31 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
9913
10113
  }
9914
10114
  return 0;
9915
10115
  });
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');
10116
+ me.__prefetchedIndex = 0;
10117
+ me.__prefetchedData = {
10118
+ data: rows,
10119
+ length: rows.length,
10120
+ /**
10121
+ * @param {Integer} index
10122
+ * @returns {RowItemNonNull}
10123
+ */
10124
+ item(index) {
10125
+ return this.data[index];
9941
10126
  }
9942
- success(undefined, undefined, undefined);
10127
+ };
10128
+ if (CFG.DEBUG) {
10129
+ console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
9943
10130
  }
9944
- } else {
10131
+ me.__decode(rows[0], success);
10132
+ }, function (tx, err) {
9945
10133
  if (CFG.DEBUG) {
9946
- console.log('Reached end of multiEntry cursor');
10134
+ console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
9947
10135
  }
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
- });
10136
+ error(err);
10137
+ return false;
10138
+ });
10139
+ }
10140
+ runQuery();
9957
10141
  };
9958
10142
 
9959
10143
  /**
@@ -9965,19 +10149,19 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
9965
10149
  */
9966
10150
 
9967
10151
  /**
9968
- * @callback SuccessArg
9969
- * @param {StructuredCloneValue} value
9970
- * @param {import('./IDBRequest.js').IDBRequestFull} req
9971
- * @returns {void}
9972
- */
10152
+ * @callback SuccessArg
10153
+ * @param {StructuredCloneValue} value
10154
+ * @param {import('./IDBRequest.js').IDBRequestFull} req
10155
+ * @returns {void}
10156
+ */
9973
10157
 
9974
10158
  /**
9975
- * @callback SuccessCallback
9976
- * @param {IndexedDBKey} key
9977
- * @param {StructuredCloneValue} value
9978
- * @param {IndexedDBKey} primaryKey
9979
- * @returns {void}
9980
- */
10159
+ * @callback SuccessCallback
10160
+ * @param {IndexedDBKey} key
10161
+ * @param {StructuredCloneValue} value
10162
+ * @param {IndexedDBKey} primaryKey
10163
+ * @returns {void}
10164
+ */
9981
10165
 
9982
10166
  /**
9983
10167
  * Creates an "onsuccess" callback.
@@ -10005,11 +10189,11 @@ IDBCursor.prototype.__onsuccess = function (success) {
10005
10189
 
10006
10190
  /**
10007
10191
  * @typedef {{
10008
- * matchingKey: string,
10009
- * key: string,
10010
- * [k: string]: string
10011
- * }} RowItemNonNull
10012
- */
10192
+ * matchingKey: string,
10193
+ * key: string,
10194
+ * [k: string]: string
10195
+ * }} RowItemNonNull
10196
+ */
10013
10197
 
10014
10198
  /**
10015
10199
  *
@@ -10062,6 +10246,7 @@ IDBCursor.prototype.__sourceOrEffectiveObjStoreDeleted = function () {
10062
10246
  IDBCursor.prototype.__invalidateCache = function () {
10063
10247
  // @ts-expect-error Why is this not being found?
10064
10248
  this.__prefetchedData = null;
10249
+ this.__multiEntryExhausted = false;
10065
10250
  };
10066
10251
 
10067
10252
  /**
@@ -10117,8 +10302,8 @@ IDBCursor.prototype.__continueFinish = function (key, primaryKey, advanceState)
10117
10302
  me.__advanceCount--;
10118
10303
  me.__key = k;
10119
10304
  me.__continue(undefined, true);
10120
- /** @type {() => void} */
10121
- executeNextRequest(); // We don't call success yet but do need to advance the transaction queue
10305
+ // We don't call success yet but do need to advance the transaction queue
10306
+ runContinuationSafely(/** @type {() => void} */executeNextRequest);
10122
10307
  return;
10123
10308
  }
10124
10309
  me.__advanceCount = undefined;
@@ -10140,11 +10325,11 @@ IDBCursor.prototype.__continueFinish = function (key, primaryKey, advanceState)
10140
10325
  return;
10141
10326
  }
10142
10327
  // @ts-expect-error Todo: Our bug to fix
10143
- cursorContinue(tx, args, success, error);
10328
+ runContinuationSafely(() => cursorContinue(tx, args, success, error));
10144
10329
  }
10145
10330
  if (me.__unique && !me.__multiEntryIndex && encKey === encode$1(me.key, me.__multiEntryIndex)) {
10146
10331
  // @ts-expect-error Todo: Our bug to fix
10147
- cursorContinue(tx, args, success, error);
10332
+ runContinuationSafely(() => cursorContinue(tx, args, success, error));
10148
10333
  return;
10149
10334
  }
10150
10335
  checkKey();
@@ -10747,21 +10932,21 @@ function requireNextTick() {
10747
10932
  return nextTick;
10748
10933
  }
10749
10934
 
10750
- var queueMicrotask = {};
10935
+ var queueMicrotask$1 = {};
10751
10936
 
10752
10937
  var hasRequiredQueueMicrotask;
10753
10938
  function requireQueueMicrotask() {
10754
- if (hasRequiredQueueMicrotask) return queueMicrotask;
10939
+ if (hasRequiredQueueMicrotask) return queueMicrotask$1;
10755
10940
  hasRequiredQueueMicrotask = 1;
10756
- queueMicrotask.test = function () {
10941
+ queueMicrotask$1.test = function () {
10757
10942
  return typeof commonjsGlobal.queueMicrotask === 'function';
10758
10943
  };
10759
- queueMicrotask.install = function (func) {
10944
+ queueMicrotask$1.install = function (func) {
10760
10945
  return function () {
10761
10946
  commonjsGlobal.queueMicrotask(func);
10762
10947
  };
10763
10948
  };
10764
- return queueMicrotask;
10949
+ return queueMicrotask$1;
10765
10950
  }
10766
10951
 
10767
10952
  var mutation = {};
@@ -10860,11 +11045,11 @@ function requireTimeout() {
10860
11045
  return timeout;
10861
11046
  }
10862
11047
 
10863
- var lib;
10864
- var hasRequiredLib;
10865
- function requireLib() {
10866
- if (hasRequiredLib) return lib;
10867
- hasRequiredLib = 1;
11048
+ var lib$1;
11049
+ var hasRequiredLib$1;
11050
+ function requireLib$1() {
11051
+ if (hasRequiredLib$1) return lib$1;
11052
+ hasRequiredLib$1 = 1;
10868
11053
  var types = [requireNextTick(), requireQueueMicrotask(), requireMutation(), requireMessageChannel(), requireStateChange(), requireTimeout()];
10869
11054
  var draining;
10870
11055
  var currentQueue;
@@ -10939,7 +11124,7 @@ function requireLib() {
10939
11124
  return fun.apply(null, array);
10940
11125
  }
10941
11126
  };
10942
- lib = immediate;
11127
+ lib$1 = immediate;
10943
11128
  function immediate(task) {
10944
11129
  var args = new Array(arguments.length - 1);
10945
11130
  if (arguments.length > 1) {
@@ -10953,11 +11138,11 @@ function requireLib() {
10953
11138
  scheduleDrain();
10954
11139
  }
10955
11140
  }
10956
- return lib;
11141
+ return lib$1;
10957
11142
  }
10958
11143
 
10959
- var libExports = requireLib();
10960
- var immediate = /*@__PURE__*/getDefaultExportFromCjs(libExports);
11144
+ var libExports$1 = requireLib$1();
11145
+ var immediate = /*@__PURE__*/getDefaultExportFromCjs(libExports$1);
10961
11146
 
10962
11147
  var tinyQueue;
10963
11148
  var hasRequiredTinyQueue;
@@ -11314,584 +11499,1026 @@ function customOpenDatabase(SQLiteDatabase, opts) {
11314
11499
  return (...args) => openDatabase(args);
11315
11500
  }
11316
11501
 
11317
- var sqlite3$1 = {exports: {}};
11502
+ var lib = {exports: {}};
11318
11503
 
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.');
11504
+ var util = {};
11505
+
11506
+ var hasRequiredUtil;
11507
+ function requireUtil() {
11508
+ if (hasRequiredUtil) return util;
11509
+ hasRequiredUtil = 1;
11510
+ util.getBooleanOption = (options, key) => {
11511
+ let value = false;
11512
+ if (key in options && typeof (value = options[key]) !== 'boolean') {
11513
+ throw new TypeError(`Expected the "${key}" option to be a boolean`);
11514
+ }
11515
+ return value;
11516
+ };
11517
+ util.cppdb = Symbol();
11518
+ util.inspect = Symbol.for('nodejs.util.inspect.custom');
11519
+ return util;
11321
11520
  }
11322
11521
 
11323
- var bindings = {exports: {}};
11522
+ var sqliteError;
11523
+ var hasRequiredSqliteError;
11524
+ function requireSqliteError() {
11525
+ if (hasRequiredSqliteError) return sqliteError;
11526
+ hasRequiredSqliteError = 1;
11527
+ class SqliteError extends Error {
11528
+ constructor(message, code) {
11529
+ if (typeof code !== 'string') {
11530
+ throw new TypeError('Expected second argument to be a string');
11531
+ }
11532
+ super('' + message);
11533
+ this.code = code;
11534
+ if (typeof Error.captureStackTrace === 'function') {
11535
+ Error.captureStackTrace(this, SqliteError);
11536
+ }
11537
+ }
11538
+ }
11539
+ Object.defineProperty(SqliteError.prototype, 'name', {
11540
+ value: 'SqliteError',
11541
+ writable: true,
11542
+ enumerable: false,
11543
+ configurable: true
11544
+ });
11545
+ sqliteError = SqliteError;
11546
+ return sqliteError;
11547
+ }
11324
11548
 
11325
- var fileUriToPath_1;
11326
- var hasRequiredFileUriToPath;
11327
- function requireFileUriToPath() {
11328
- if (hasRequiredFileUriToPath) return fileUriToPath_1;
11329
- hasRequiredFileUriToPath = 1;
11330
- /**
11331
- * Module dependencies.
11332
- */
11549
+ var wrappers = {};
11333
11550
 
11334
- var sep = path.sep || '/';
11551
+ var hasRequiredWrappers;
11552
+ function requireWrappers() {
11553
+ if (hasRequiredWrappers) return wrappers;
11554
+ hasRequiredWrappers = 1;
11555
+ const {
11556
+ cppdb
11557
+ } = requireUtil();
11558
+ wrappers.prepare = function prepare(sql) {
11559
+ return this[cppdb].prepare(sql, this, false, false);
11560
+ };
11561
+ wrappers.exec = function exec(sql) {
11562
+ this[cppdb].exec(sql);
11563
+ return this;
11564
+ };
11565
+ wrappers.close = function close() {
11566
+ this[cppdb].close();
11567
+ return this;
11568
+ };
11569
+ wrappers.loadExtension = function loadExtension(...args) {
11570
+ this[cppdb].loadExtension(...args);
11571
+ return this;
11572
+ };
11573
+ wrappers.defaultSafeIntegers = function defaultSafeIntegers(...args) {
11574
+ this[cppdb].defaultSafeIntegers(...args);
11575
+ return this;
11576
+ };
11577
+ wrappers.unsafeMode = function unsafeMode(...args) {
11578
+ this[cppdb].unsafeMode(...args);
11579
+ return this;
11580
+ };
11581
+ wrappers.getters = {
11582
+ name: {
11583
+ get: function name() {
11584
+ return this[cppdb].name;
11585
+ },
11586
+ enumerable: true
11587
+ },
11588
+ open: {
11589
+ get: function open() {
11590
+ return this[cppdb].open;
11591
+ },
11592
+ enumerable: true
11593
+ },
11594
+ inTransaction: {
11595
+ get: function inTransaction() {
11596
+ return this[cppdb].inTransaction;
11597
+ },
11598
+ enumerable: true
11599
+ },
11600
+ readonly: {
11601
+ get: function readonly() {
11602
+ return this[cppdb].readonly;
11603
+ },
11604
+ enumerable: true
11605
+ },
11606
+ memory: {
11607
+ get: function memory() {
11608
+ return this[cppdb].memory;
11609
+ },
11610
+ enumerable: true
11611
+ }
11612
+ };
11613
+ return wrappers;
11614
+ }
11335
11615
 
11336
- /**
11337
- * Module exports.
11338
- */
11616
+ var transaction;
11617
+ var hasRequiredTransaction;
11618
+ function requireTransaction() {
11619
+ if (hasRequiredTransaction) return transaction;
11620
+ hasRequiredTransaction = 1;
11621
+ const {
11622
+ cppdb
11623
+ } = requireUtil();
11624
+ const controllers = new WeakMap();
11625
+ transaction = function transaction(fn) {
11626
+ if (typeof fn !== 'function') throw new TypeError('Expected first argument to be a function');
11627
+ const db = this[cppdb];
11628
+ const controller = getController(db, this);
11629
+ const {
11630
+ apply
11631
+ } = Function.prototype;
11339
11632
 
11340
- fileUriToPath_1 = fileUriToPath;
11633
+ // Each version of the transaction function has these same properties
11634
+ const properties = {
11635
+ default: {
11636
+ value: wrapTransaction(apply, fn, db, controller.default)
11637
+ },
11638
+ deferred: {
11639
+ value: wrapTransaction(apply, fn, db, controller.deferred)
11640
+ },
11641
+ immediate: {
11642
+ value: wrapTransaction(apply, fn, db, controller.immediate)
11643
+ },
11644
+ exclusive: {
11645
+ value: wrapTransaction(apply, fn, db, controller.exclusive)
11646
+ },
11647
+ database: {
11648
+ value: this,
11649
+ enumerable: true
11650
+ }
11651
+ };
11652
+ Object.defineProperties(properties.default.value, properties);
11653
+ Object.defineProperties(properties.deferred.value, properties);
11654
+ Object.defineProperties(properties.immediate.value, properties);
11655
+ Object.defineProperties(properties.exclusive.value, properties);
11341
11656
 
11342
- /**
11343
- * File URI to Path function.
11344
- *
11345
- * @param {String} uri
11346
- * @return {String} path
11347
- * @api public
11348
- */
11657
+ // Return the default version of the transaction function
11658
+ return properties.default.value;
11659
+ };
11349
11660
 
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');
11661
+ // Return the database's cached transaction controller, or create a new one
11662
+ const getController = (db, self) => {
11663
+ let controller = controllers.get(db);
11664
+ if (!controller) {
11665
+ const shared = {
11666
+ commit: db.prepare('COMMIT', self, false, false),
11667
+ rollback: db.prepare('ROLLBACK', self, false, false),
11668
+ savepoint: db.prepare('SAVEPOINT `\t_bs3.\t`', self, false, false),
11669
+ release: db.prepare('RELEASE `\t_bs3.\t`', self, false, false),
11670
+ rollbackTo: db.prepare('ROLLBACK TO `\t_bs3.\t`', self, false, false)
11671
+ };
11672
+ controllers.set(db, controller = {
11673
+ default: Object.assign({
11674
+ begin: db.prepare('BEGIN', self, false, false)
11675
+ }, shared),
11676
+ deferred: Object.assign({
11677
+ begin: db.prepare('BEGIN DEFERRED', self, false, false)
11678
+ }, shared),
11679
+ immediate: Object.assign({
11680
+ begin: db.prepare('BEGIN IMMEDIATE', self, false, false)
11681
+ }, shared),
11682
+ exclusive: Object.assign({
11683
+ begin: db.prepare('BEGIN EXCLUSIVE', self, false, false)
11684
+ }, shared)
11685
+ });
11353
11686
  }
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);
11687
+ return controller;
11688
+ };
11358
11689
 
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;
11690
+ // Return a new transaction function by wrapping the given function
11691
+ const wrapTransaction = (apply, fn, db, {
11692
+ begin,
11693
+ commit,
11694
+ rollback,
11695
+ savepoint,
11696
+ release,
11697
+ rollbackTo
11698
+ }) => function sqliteTransaction() {
11699
+ let before, after, undo;
11700
+ if (db.inTransaction) {
11701
+ before = savepoint;
11702
+ after = release;
11703
+ undo = rollbackTo;
11704
+ } else {
11705
+ before = begin;
11706
+ after = commit;
11707
+ undo = rollback;
11366
11708
  }
11709
+ before.run();
11710
+ try {
11711
+ const result = apply.call(fn, this, arguments);
11712
+ if (result && typeof result.then === 'function') {
11713
+ throw new TypeError('Transaction function cannot return a promise');
11714
+ }
11715
+ after.run();
11716
+ return result;
11717
+ } catch (ex) {
11718
+ if (db.inTransaction) {
11719
+ undo.run();
11720
+ if (undo !== rollback) after.run();
11721
+ }
11722
+ throw ex;
11723
+ }
11724
+ };
11725
+ return transaction;
11726
+ }
11367
11727
 
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:');
11728
+ var pragma;
11729
+ var hasRequiredPragma;
11730
+ function requirePragma() {
11731
+ if (hasRequiredPragma) return pragma;
11732
+ hasRequiredPragma = 1;
11733
+ const {
11734
+ getBooleanOption,
11735
+ cppdb
11736
+ } = requireUtil();
11737
+ pragma = function pragma(source, options) {
11738
+ if (options == null) options = {};
11739
+ if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
11740
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
11741
+ const simple = getBooleanOption(options, 'simple');
11742
+ const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true, false);
11743
+ return simple ? stmt.pluck().get() : stmt.all();
11744
+ };
11745
+ return pragma;
11746
+ }
11376
11747
 
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;
11748
+ var explain;
11749
+ var hasRequiredExplain;
11750
+ function requireExplain() {
11751
+ if (hasRequiredExplain) return explain;
11752
+ hasRequiredExplain = 1;
11753
+ const {
11754
+ cppdb
11755
+ } = requireUtil();
11756
+ explain = function explain(source) {
11757
+ if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
11758
+ const stmt = this[cppdb].prepare(`EXPLAIN ${source}`, this, false, true);
11759
+ return stmt.all();
11760
+ };
11761
+ return explain;
11388
11762
  }
11389
11763
 
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) {
11764
+ var backup;
11765
+ var hasRequiredBackup;
11766
+ function requireBackup() {
11767
+ if (hasRequiredBackup) return backup;
11768
+ hasRequiredBackup = 1;
11769
+ const fs = require$$0;
11770
+ const path$1 = path;
11771
+ const {
11772
+ promisify
11773
+ } = require$$2;
11774
+ const {
11775
+ cppdb
11776
+ } = requireUtil();
11777
+ const fsAccess = promisify(fs.access);
11778
+ backup = async function backup(filename, options) {
11779
+ if (options == null) options = {};
11780
+
11781
+ // Validate arguments
11782
+ if (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');
11783
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
11784
+
11785
+ // Interpret options
11786
+ filename = filename.trim();
11787
+ const attachedName = 'attached' in options ? options.attached : 'main';
11788
+ const handler = 'progress' in options ? options.progress : null;
11789
+
11790
+ // Validate interpreted options
11791
+ if (!filename) throw new TypeError('Backup filename cannot be an empty string');
11792
+ if (filename === ':memory:') throw new TypeError('Invalid backup filename ":memory:"');
11793
+ if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
11794
+ if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
11795
+ if (handler != null && typeof handler !== 'function') throw new TypeError('Expected the "progress" option to be a function');
11796
+
11797
+ // Make sure the specified directory exists
11798
+ await fsAccess(path$1.dirname(filename)).catch(() => {
11799
+ throw new TypeError('Cannot save backup because the directory does not exist');
11800
+ });
11801
+ const isNewFile = await fsAccess(filename).then(() => false, () => true);
11802
+ return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
11803
+ };
11804
+ const runBackup = (backup, handler) => {
11805
+ let rate = 0;
11806
+ let useDefault = true;
11807
+ return new Promise((resolve, reject) => {
11808
+ setImmediate(function step() {
11404
11809
  try {
11405
- fs.accessSync(path);
11406
- } catch (e) {
11407
- return false;
11810
+ const progress = backup.transfer(rate);
11811
+ if (!progress.remainingPages) {
11812
+ backup.close();
11813
+ resolve(progress);
11814
+ return;
11815
+ }
11816
+ if (useDefault) {
11817
+ useDefault = false;
11818
+ rate = 100;
11819
+ }
11820
+ if (handler) {
11821
+ const ret = handler(progress);
11822
+ if (ret !== undefined) {
11823
+ 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');
11824
+ }
11825
+ }
11826
+ setImmediate(step);
11827
+ } catch (err) {
11828
+ backup.close();
11829
+ reject(err);
11408
11830
  }
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
- */
11831
+ });
11832
+ });
11833
+ };
11834
+ return backup;
11835
+ }
11443
11836
 
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
- }
11837
+ var serialize;
11838
+ var hasRequiredSerialize;
11839
+ function requireSerialize() {
11840
+ if (hasRequiredSerialize) return serialize;
11841
+ hasRequiredSerialize = 1;
11842
+ const {
11843
+ cppdb
11844
+ } = requireUtil();
11845
+ serialize = function serialize(options) {
11846
+ if (options == null) options = {};
11847
+
11848
+ // Validate arguments
11849
+ if (typeof options !== 'object') throw new TypeError('Expected first argument to be an options object');
11850
+
11851
+ // Interpret and validate options
11852
+ const attachedName = 'attached' in options ? options.attached : 'main';
11853
+ if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
11854
+ if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
11855
+ return this[cppdb].serialize(attachedName);
11856
+ };
11857
+ return serialize;
11858
+ }
11453
11859
 
11454
- // maps `defaults` onto `opts` object
11455
- Object.keys(defaults).map(function (i) {
11456
- if (!(i in opts)) opts[i] = defaults[i];
11457
- });
11860
+ var _function;
11861
+ var hasRequired_function;
11862
+ function require_function() {
11863
+ if (hasRequired_function) return _function;
11864
+ hasRequired_function = 1;
11865
+ const {
11866
+ getBooleanOption,
11867
+ cppdb
11868
+ } = requireUtil();
11869
+ _function = function defineFunction(name, options, fn) {
11870
+ // Apply defaults
11871
+ if (options == null) options = {};
11872
+ if (typeof options === 'function') {
11873
+ fn = options;
11874
+ options = {};
11875
+ }
11876
+
11877
+ // Validate arguments
11878
+ if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
11879
+ if (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');
11880
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
11881
+ if (!name) throw new TypeError('User-defined function name cannot be an empty string');
11882
+
11883
+ // Interpret options
11884
+ const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
11885
+ const deterministic = getBooleanOption(options, 'deterministic');
11886
+ const directOnly = getBooleanOption(options, 'directOnly');
11887
+ const varargs = getBooleanOption(options, 'varargs');
11888
+ let argCount = -1;
11889
+
11890
+ // Determine argument count
11891
+ if (!varargs) {
11892
+ argCount = fn.length;
11893
+ if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');
11894
+ if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
11895
+ }
11896
+ this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
11897
+ return this;
11898
+ };
11899
+ return _function;
11900
+ }
11458
11901
 
11459
- // Get the module root
11460
- if (!opts.module_root) {
11461
- opts.module_root = exports.getRoot(exports.getFileName());
11462
- }
11902
+ var aggregate;
11903
+ var hasRequiredAggregate;
11904
+ function requireAggregate() {
11905
+ if (hasRequiredAggregate) return aggregate;
11906
+ hasRequiredAggregate = 1;
11907
+ const {
11908
+ getBooleanOption,
11909
+ cppdb
11910
+ } = requireUtil();
11911
+ aggregate = function defineAggregate(name, options) {
11912
+ // Validate arguments
11913
+ if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
11914
+ if (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');
11915
+ if (!name) throw new TypeError('User-defined function name cannot be an empty string');
11916
+
11917
+ // Interpret options
11918
+ const start = 'start' in options ? options.start : null;
11919
+ const step = getFunctionOption(options, 'step', true);
11920
+ const inverse = getFunctionOption(options, 'inverse', false);
11921
+ const result = getFunctionOption(options, 'result', false);
11922
+ const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
11923
+ const deterministic = getBooleanOption(options, 'deterministic');
11924
+ const directOnly = getBooleanOption(options, 'directOnly');
11925
+ const varargs = getBooleanOption(options, 'varargs');
11926
+ let argCount = -1;
11927
+
11928
+ // Determine argument count
11929
+ if (!varargs) {
11930
+ argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
11931
+ if (argCount > 0) argCount -= 1;
11932
+ if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
11933
+ }
11934
+ this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
11935
+ return this;
11936
+ };
11937
+ const getFunctionOption = (options, key, required) => {
11938
+ const value = key in options ? options[key] : null;
11939
+ if (typeof value === 'function') return value;
11940
+ if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
11941
+ if (required) throw new TypeError(`Missing required option "${key}"`);
11942
+ return null;
11943
+ };
11944
+ const getLength = ({
11945
+ length
11946
+ }) => {
11947
+ if (Number.isInteger(length) && length >= 0) return length;
11948
+ throw new TypeError('Expected function.length to be a positive integer');
11949
+ };
11950
+ return aggregate;
11951
+ }
11463
11952
 
11464
- // Ensure the given bindings name ends with .node
11465
- if (path$1.extname(opts.bindings) != '.node') {
11466
- opts.bindings += '.node';
11467
- }
11953
+ var table;
11954
+ var hasRequiredTable;
11955
+ function requireTable() {
11956
+ if (hasRequiredTable) return table;
11957
+ hasRequiredTable = 1;
11958
+ const {
11959
+ cppdb
11960
+ } = requireUtil();
11961
+ table = function defineTable(name, factory) {
11962
+ // Validate arguments
11963
+ if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
11964
+ if (!name) throw new TypeError('Virtual table module name cannot be an empty string');
11965
+
11966
+ // Determine whether the module is eponymous-only or not
11967
+ let eponymous = false;
11968
+ if (typeof factory === 'object' && factory !== null) {
11969
+ eponymous = true;
11970
+ factory = defer(parseTableDefinition(factory, 'used', name));
11971
+ } else {
11972
+ if (typeof factory !== 'function') throw new TypeError('Expected second argument to be a function or a table definition object');
11973
+ factory = wrapFactory(factory);
11974
+ }
11975
+ this[cppdb].table(factory, name, eponymous);
11976
+ return this;
11977
+ };
11978
+ function wrapFactory(factory) {
11979
+ return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
11980
+ const thisObject = {
11981
+ module: moduleName,
11982
+ database: databaseName,
11983
+ table: tableName
11984
+ };
11468
11985
 
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
- }
11986
+ // Generate a new table definition by invoking the factory
11987
+ const def = apply.call(factory, thisObject, args);
11988
+ if (typeof def !== 'object' || def === null) {
11989
+ throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
11493
11990
  }
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;
11991
+ return parseTableDefinition(def, 'returned', moduleName);
11992
+ };
11993
+ }
11994
+ function parseTableDefinition(def, verb, moduleName) {
11995
+ // Validate required properties
11996
+ if (!hasOwnProperty.call(def, 'rows')) {
11997
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
11998
+ }
11999
+ if (!hasOwnProperty.call(def, 'columns')) {
12000
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
11499
12001
  }
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
12002
 
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
- };
12003
+ // Validate "rows" property
12004
+ const rows = def.rows;
12005
+ if (typeof rows !== 'function' || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
12006
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
12007
+ }
11528
12008
 
11529
- // run the 'prepareStackTrace' function above
11530
- Error.captureStackTrace(dummy);
11531
- dummy.stack;
12009
+ // Validate "columns" property
12010
+ let columns = def.columns;
12011
+ if (!Array.isArray(columns) || !isStringArray(columns = [...columns])) {
12012
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
12013
+ }
12014
+ if (columns.length !== new Set(columns).size) {
12015
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
12016
+ }
12017
+ if (!columns.length) {
12018
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
12019
+ }
11532
12020
 
11533
- // cleanup
11534
- Error.prepareStackTrace = origPST;
11535
- Error.stackTraceLimit = origSTL;
12021
+ // Validate "parameters" property
12022
+ let parameters;
12023
+ if (hasOwnProperty.call(def, 'parameters')) {
12024
+ parameters = def.parameters;
12025
+ if (!Array.isArray(parameters) || !isStringArray(parameters = [...parameters])) {
12026
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
12027
+ }
12028
+ } else {
12029
+ parameters = inferParameters(rows);
12030
+ }
12031
+ if (parameters.length !== new Set(parameters).size) {
12032
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
12033
+ }
12034
+ if (parameters.length > 32) {
12035
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
12036
+ }
12037
+ for (const parameter of parameters) {
12038
+ if (columns.includes(parameter)) {
12039
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
12040
+ }
12041
+ }
11536
12042
 
11537
- // handle filename that starts with "file://"
11538
- var fileSchema = 'file://';
11539
- if (fileName.indexOf(fileSchema) === 0) {
11540
- fileName = fileURLToPath(fileName);
12043
+ // Validate "safeIntegers" option
12044
+ let safeIntegers = 2;
12045
+ if (hasOwnProperty.call(def, 'safeIntegers')) {
12046
+ const bool = def.safeIntegers;
12047
+ if (typeof bool !== 'boolean') {
12048
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
11541
12049
  }
11542
- return fileName;
11543
- };
12050
+ safeIntegers = +bool;
12051
+ }
11544
12052
 
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
- */
12053
+ // Validate "directOnly" option
12054
+ let directOnly = false;
12055
+ if (hasOwnProperty.call(def, 'directOnly')) {
12056
+ directOnly = def.directOnly;
12057
+ if (typeof directOnly !== 'boolean') {
12058
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
12059
+ }
12060
+ }
11553
12061
 
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? ');
12062
+ // Generate SQL for the virtual table definition
12063
+ const columnDefinitions = [...parameters.map(identifier).map(str => `${str} HIDDEN`), ...columns.map(identifier)];
12064
+ return [`CREATE TABLE x(${columnDefinitions.join(', ')});`, wrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName), parameters, safeIntegers, directOnly];
12065
+ }
12066
+ function wrapGenerator(generator, columnMap, moduleName) {
12067
+ return function* virtualTable(...args) {
12068
+ /*
12069
+ We must defensively clone any buffers in the arguments, because
12070
+ otherwise the generator could mutate one of them, which would cause
12071
+ us to return incorrect values for hidden columns, potentially
12072
+ corrupting the database.
12073
+ */
12074
+ const output = args.map(x => Buffer.isBuffer(x) ? Buffer.from(x) : x);
12075
+ for (let i = 0; i < columnMap.size; ++i) {
12076
+ output.push(null); // Fill with nulls to prevent gaps in array (v8 optimization)
12077
+ }
12078
+ for (const row of generator(...args)) {
12079
+ if (Array.isArray(row)) {
12080
+ extractRowArray(row, output, columnMap.size, moduleName);
12081
+ yield output;
12082
+ } else if (typeof row === 'object' && row !== null) {
12083
+ extractRowObject(row, output, columnMap, moduleName);
12084
+ yield output;
12085
+ } else {
12086
+ throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
11569
12087
  }
11570
- // Try the parent dir next
11571
- prev = dir;
11572
- dir = join(dir, '..');
11573
12088
  }
11574
12089
  };
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
- };
12090
+ }
12091
+ function extractRowArray(row, output, columnCount, moduleName) {
12092
+ if (row.length !== columnCount) {
12093
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
12094
+ }
12095
+ const offset = output.length - columnCount;
12096
+ for (let i = 0; i < columnCount; ++i) {
12097
+ output[i + offset] = row[i];
12098
+ }
12099
+ }
12100
+ function extractRowObject(row, output, columnMap, moduleName) {
12101
+ let count = 0;
12102
+ for (const key of Object.keys(row)) {
12103
+ const index = columnMap.get(key);
12104
+ if (index === undefined) {
12105
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
11617
12106
  }
11618
- return old.apply(this, arguments);
11619
- };
12107
+ output[index] = row[key];
12108
+ count += 1;
12109
+ }
12110
+ if (count !== columnMap.size) {
12111
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
12112
+ }
11620
12113
  }
11621
- trace.extendTrace = extendTrace;
11622
- function filter(error) {
11623
- return error.stack.split('\n').filter(function (line) {
11624
- return line.indexOf(__filename) < 0;
11625
- });
12114
+ function inferParameters({
12115
+ length
12116
+ }) {
12117
+ if (!Number.isInteger(length) || length < 0) {
12118
+ throw new TypeError('Expected function.length to be a positive integer');
12119
+ }
12120
+ const params = [];
12121
+ for (let i = 0; i < length; ++i) {
12122
+ params.push(`$${i + 1}`);
12123
+ }
12124
+ return params;
11626
12125
  }
11627
- return trace;
12126
+ const {
12127
+ hasOwnProperty
12128
+ } = Object.prototype;
12129
+ const {
12130
+ apply
12131
+ } = Function.prototype;
12132
+ const GeneratorFunctionPrototype = Object.getPrototypeOf(function* () {});
12133
+ const identifier = str => `"${str.replace(/"/g, '""')}"`;
12134
+ const defer = x => () => x;
12135
+ const isStringArray = arr => {
12136
+ for (let i = 0; i < arr.length; ++i) {
12137
+ if (typeof arr[i] !== 'string') return false;
12138
+ }
12139
+ return true;
12140
+ };
12141
+ return table;
11628
12142
  }
11629
12143
 
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
- };
12144
+ var inspect;
12145
+ var hasRequiredInspect;
12146
+ function requireInspect() {
12147
+ if (hasRequiredInspect) return inspect;
12148
+ hasRequiredInspect = 1;
12149
+ const DatabaseInspection = function Database() {};
12150
+ inspect = function inspect(depth, opts) {
12151
+ return Object.assign(new DatabaseInspection(), this);
12152
+ };
12153
+ return inspect;
12154
+ }
12155
+
12156
+ var database;
12157
+ var hasRequiredDatabase;
12158
+ function requireDatabase() {
12159
+ if (hasRequiredDatabase) return database;
12160
+ hasRequiredDatabase = 1;
12161
+ const fs = require$$0;
12162
+ const path$1 = path;
12163
+ const util = requireUtil();
12164
+ const SqliteError = requireSqliteError();
12165
+ database = function createDatabase(getAddon, allowNativeBinding) {
12166
+ function Database(filenameGiven, options) {
12167
+ if (new.target == null) {
12168
+ return new Database(filenameGiven, options);
12169
+ }
12170
+
12171
+ // Apply defaults
12172
+ let buffer;
12173
+ if (Buffer.isBuffer(filenameGiven)) {
12174
+ buffer = filenameGiven;
12175
+ filenameGiven = ':memory:';
12176
+ }
12177
+ if (filenameGiven == null) filenameGiven = '';
12178
+ if (options == null) options = {};
12179
+
12180
+ // Validate arguments
12181
+ if (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');
12182
+ if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
12183
+ if ('readOnly' in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
12184
+ if ('memory' in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
12185
+
12186
+ // Interpret options
12187
+ const filename = filenameGiven.trim();
12188
+ const anonymous = filename === '' || filename === ':memory:';
12189
+ const readonly = util.getBooleanOption(options, 'readonly');
12190
+ const fileMustExist = util.getBooleanOption(options, 'fileMustExist');
12191
+ const timeout = 'timeout' in options ? options.timeout : 5000;
12192
+ const verbose = 'verbose' in options ? options.verbose : null;
12193
+ const nativeBinding = 'nativeBinding' in options ? options.nativeBinding : null;
12194
+
12195
+ // Validate interpreted options
12196
+ if (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');
12197
+ if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
12198
+ if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
12199
+ if (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the "verbose" option to be a function');
12200
+ if (!allowNativeBinding && 'nativeBinding' in options) throw new TypeError('The "nativeBinding" option is only supported by the default better-sqlite3 entrypoint');
12201
+ if (allowNativeBinding && nativeBinding != null && typeof nativeBinding !== 'string' && typeof nativeBinding !== 'object') throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
12202
+
12203
+ // Load the native addon
12204
+ const addon = getAddon(nativeBinding);
12205
+ if (!addon.isInitialized) {
12206
+ addon.initialize(SqliteError, arrayFactory, arrayAppender, rowFactory, recordFactory);
12207
+ addon.isInitialized = true;
12208
+ }
12209
+
12210
+ // Make sure the specified directory exists
12211
+ if (!anonymous && !filename.startsWith('file:') && !fs.existsSync(path$1.dirname(filename))) {
12212
+ throw new TypeError('Cannot open database because the directory does not exist');
12213
+ }
12214
+ Object.defineProperties(this, {
12215
+ [util.cppdb]: {
12216
+ value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null)
12217
+ },
12218
+ ...wrappers.getters
12219
+ });
11654
12220
  }
11655
- function inherits(target, source) {
11656
- for (const k in source.prototype) target.prototype[k] = source.prototype[k];
12221
+ const wrappers = requireWrappers();
12222
+ Database.prototype.prepare = wrappers.prepare;
12223
+ Database.prototype.transaction = requireTransaction();
12224
+ Database.prototype.pragma = requirePragma();
12225
+ Database.prototype.explain = requireExplain();
12226
+ Database.prototype.backup = requireBackup();
12227
+ Database.prototype.serialize = requireSerialize();
12228
+ Database.prototype.function = require_function();
12229
+ Database.prototype.aggregate = requireAggregate();
12230
+ Database.prototype.table = requireTable();
12231
+ Database.prototype.loadExtension = wrappers.loadExtension;
12232
+ Database.prototype.exec = wrappers.exec;
12233
+ Database.prototype.close = wrappers.close;
12234
+ Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
12235
+ Database.prototype.unsafeMode = wrappers.unsafeMode;
12236
+ Database.prototype[util.inspect] = requireInspect();
12237
+ return Database;
12238
+ };
12239
+ function arrayFactory(...values) {
12240
+ return values;
12241
+ }
12242
+ function arrayAppender(array, ...values) {
12243
+ const offset = array.length;
12244
+ for (let i = 0; i < values.length; ++i) {
12245
+ array[offset + i] = values[i];
11657
12246
  }
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: {}
12247
+ }
12248
+ function rowFactory(...keys) {
12249
+ if (!keys.includes('__proto__')) {
12250
+ const parameters = keys.map((_, index) => `v${index}`).join(',');
12251
+ const properties = keys.map((key, index) => `${JSON.stringify(key)}:v${index}`).join(',');
12252
+ return Function(`return (${parameters}) => ({${properties}})`)();
12253
+ }
12254
+ return (...values) => {
12255
+ const row = {};
12256
+ for (let i = 0; i < keys.length; ++i) row[keys[i]] = values[i];
12257
+ return row;
11682
12258
  };
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
- });
12259
+ }
12260
+ function recordFactory(value) {
12261
+ return {
12262
+ value,
12263
+ done: false
12264
+ };
12265
+ }
12266
+ return database;
12267
+ }
11694
12268
 
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
- });
12269
+ function commonjsRequire(path) {
12270
+ 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.');
12271
+ }
11700
12272
 
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
- });
12273
+ var binding = {exports: {}};
11706
12274
 
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
- });
12275
+ var hasRequiredBinding;
12276
+ function requireBinding() {
12277
+ if (hasRequiredBinding) return binding.exports;
12278
+ hasRequiredBinding = 1;
12279
+ (function (module, exports) {
11712
12280
 
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
- });
12281
+ const fs = require$$0;
12282
+ const path$1 = path;
12283
+ const PREBUILD_PLATFORMS = ['linux', 'darwin', 'win32'];
12284
+ const PREBUILD_ARCHS = ['x64', 'arm64'];
12285
+ let DEFAULT_ADDON;
12286
+ function getBinding(nativeBinding) {
12287
+ // If a path was provided, load the binding from the filesystem.
12288
+ if (typeof nativeBinding === 'string') {
12289
+ // See <https://webpack.js.org/api/module-variables/#__non_webpack_require__-webpack-specific>
12290
+ const requireFunc = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : commonjsRequire;
12291
+ return requireFunc(path$1.resolve(nativeBinding).replace(/(\.node)?$/, '.node'));
12292
+ }
11722
12293
 
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]);
12294
+ // If an object was provided, use it as the binding directly.
12295
+ if (typeof nativeBinding === 'object' && nativeBinding !== null) {
12296
+ return nativeBinding;
11734
12297
  }
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);
12298
+
12299
+ // If we're using the default binding and it already exists, just return it.
12300
+ if (DEFAULT_ADDON) {
12301
+ return DEFAULT_ADDON;
11778
12302
  }
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);
12303
+
12304
+ // Otherwise, try to find the binding as a prebuilt binary.
12305
+ let filename = getPrebuildPath();
12306
+ if (filename) {
12307
+ return DEFAULT_ADDON = commonjsRequire(filename);
11785
12308
  }
11786
- return val;
11787
- };
11788
12309
 
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;
12310
+ // If no prebuilt binary was found, try the default node-gyp locations.
12311
+ filename = path$1.join(__dirname, '..', 'build', 'Debug', 'better_sqlite3.node');
12312
+ if (!fs.existsSync(filename)) {
12313
+ filename = path$1.join(__dirname, '..', 'build', 'Release', 'better_sqlite3.node');
11800
12314
  }
11801
- return sqlite3;
11802
- };
11803
- })(sqlite3$1);
11804
- return sqlite3$1.exports;
12315
+ return DEFAULT_ADDON = commonjsRequire(filename);
12316
+ }
12317
+ function getPrebuildPath() {
12318
+ if (PREBUILD_PLATFORMS.includes(process.platform) && PREBUILD_ARCHS.includes(process.arch)) {
12319
+ const target = `${isLinuxMusl() ? 'linuxmusl' : process.platform}-${process.arch}`;
12320
+ const filename = path$1.join(__dirname, '..', 'prebuilds', `${target}.node`);
12321
+ if (fs.existsSync(filename)) {
12322
+ return filename;
12323
+ }
12324
+ }
12325
+ return null;
12326
+ }
12327
+ function isLinuxMusl() {
12328
+ return process.platform === 'linux' && !process.report.getReport().header.glibcVersionRuntime;
12329
+ }
12330
+ exports.getBinding = getBinding;
12331
+ exports.getPrebuildPath = getPrebuildPath;
12332
+
12333
+ // This script is executed directly by binding.gyp to detect prebuilt binaries.
12334
+ if (require.main === module) {
12335
+ process.stdout.write(getPrebuildPath() ? '1' : '0');
12336
+ }
12337
+ })(binding, binding.exports);
12338
+ return binding.exports;
12339
+ }
12340
+
12341
+ var hasRequiredLib;
12342
+ function requireLib() {
12343
+ if (hasRequiredLib) return lib.exports;
12344
+ hasRequiredLib = 1;
12345
+ lib.exports = requireDatabase()(requireBinding().getBinding, true);
12346
+ lib.exports.SqliteError = requireSqliteError();
12347
+ return lib.exports;
11805
12348
  }
11806
12349
 
11807
- var sqlite3Exports = requireSqlite3();
11808
- var sqlite3 = /*@__PURE__*/getDefaultExportFromCjs(sqlite3Exports);
12350
+ var libExports = requireLib();
12351
+ var Database = /*@__PURE__*/getDefaultExportFromCjs(libExports);
11809
12352
 
11810
- function SQLiteResult(error, insertId, rowsAffected, rows) {
11811
- this.error = error;
11812
- this.insertId = insertId;
11813
- this.rowsAffected = rowsAffected;
11814
- this.rows = rows;
12353
+ /**
12354
+ *
12355
+ */
12356
+ class SQLiteResult {
12357
+ /**
12358
+ * @param {Error|null|undefined} error
12359
+ * @param {number|undefined} [insertId]
12360
+ * @param {number} [rowsAffected]
12361
+ * @param {object[]} [rows]
12362
+ */
12363
+ constructor(error, insertId, rowsAffected, rows) {
12364
+ this.error = error;
12365
+ this.insertId = insertId;
12366
+ this.rowsAffected = rowsAffected;
12367
+ this.rows = rows;
12368
+ }
11815
12369
  }
12370
+ const READ_ONLY_ERROR = new Error('could not prepare statement (23 not authorized)');
11816
12371
 
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);
12372
+ /**
12373
+ * @typedef {(sql: string, duration: number) => void} SQLProfileCallback
12374
+ */
12375
+
12376
+ /**
12377
+ * @typedef {((sql: string) => void)|undefined} SQLTraceCallback
12378
+ */
12379
+
12380
+ /**
12381
+ * @param {string} name
12382
+ * @param {{busyTimeout?: number, trace?: (sql: string) => void, profile?: SQLProfileCallback}} [opts]
12383
+ * @returns {void}
12384
+ */
12385
+ function SQLiteDatabase(name, opts = {}) {
12386
+ /** @type {import('better-sqlite3').Database} */
12387
+ const db = new Database(name);
12388
+
12389
+ /** @type {SQLTraceCallback} */
12390
+ // eslint-disable-next-line prefer-destructuring -- TS
12391
+ let trace = opts.trace;
12392
+ /** @type {SQLProfileCallback|undefined} */
12393
+ // eslint-disable-next-line prefer-destructuring -- TS
12394
+ let profile = opts.profile;
11821
12395
  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);
11826
- }
11827
- if (opts.profile) {
11828
- this._db.configure('profile', opts.profile);
12396
+ db.pragma('busy_timeout = ' + Number(opts.busyTimeout));
11829
12397
  }
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));
12398
+
12399
+ // Kept untyped (rather than the better-sqlite3 `Database` type) since that
12400
+ // type is internal to `@types/better-sqlite3` and can't be named in this
12401
+ // file's emitted declaration.
12402
+ this._db = /** @type {any} */{
12403
+ _db: db,
12404
+ /**
12405
+ * Compatibility with node-sqlite3's configure API.
12406
+ * @param {'busyTimeout'|'trace'|'profile'} option
12407
+ * @param {number|((sql: string, duration?: number) => void)} value
12408
+ * @returns {void}
12409
+ */
12410
+ configure(option, value) {
12411
+ if (option === 'busyTimeout') {
12412
+ db.pragma('busy_timeout = ' + Number(/** @type {number} */value));
12413
+ return;
12414
+ }
12415
+ if (option === 'trace') {
12416
+ trace = /** @type {(sql: string) => void} */value;
12417
+ return;
12418
+ }
12419
+ if (option === 'profile') {
12420
+ profile = /** @type {SQLProfileCallback} */value;
12421
+ }
12422
+ },
12423
+ /**
12424
+ * Compatibility with callback-oriented close semantics.
12425
+ * @param {(err?: Error|null) => void} [cb]
12426
+ * @returns {void}
12427
+ */
12428
+ close(cb) {
12429
+ try {
12430
+ db.close();
12431
+ if (cb) {
12432
+ return cb(null);
12433
+ }
12434
+ } catch (err) {
12435
+ if (cb) {
12436
+ return cb(/** @type {Error} */err);
12437
+ }
12438
+ }
12439
+ return undefined;
12440
+ },
12441
+ getTrace() {
12442
+ return trace;
12443
+ },
12444
+ getProfile() {
12445
+ return profile;
11835
12446
  }
11836
- var insertId = void 0;
11837
- var rowsAffected = 0;
11838
- var resultSet = new SQLiteResult(null, insertId, rowsAffected, rows);
11839
- cb(resultSet);
11840
- });
12447
+ };
11841
12448
  }
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
- });
12449
+
12450
+ /**
12451
+ * @param {import('better-sqlite3').Database} db
12452
+ * @param {string} sql
12453
+ * @param {unknown[]} args
12454
+ * @returns {object[]}
12455
+ */
12456
+ function runSelect(db, sql, args) {
12457
+ const stmt = db.prepare(sql);
12458
+ return stmt.reader ? (/** @type {object[]} */stmt.all(...args)) : [];
11855
12459
  }
12460
+
12461
+ /**
12462
+ * @param {import('better-sqlite3').Database} db
12463
+ * @param {string} sql
12464
+ * @param {unknown[]} args
12465
+ * @returns {import('better-sqlite3').RunResult}
12466
+ */
12467
+ function runNonSelect(db, sql, args) {
12468
+ const stmt = db.prepare(sql);
12469
+ return stmt.run(...args);
12470
+ }
12471
+
12472
+ /**
12473
+ * @param {{sql: string, args: unknown[]}[]} queries
12474
+ * @param {boolean} readOnly
12475
+ * @param {(err: Error|null, results?: SQLiteResult[]) => void} callback
12476
+ * @returns {void}
12477
+ */
11856
12478
  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);
12479
+ const db = this._db._db;
12480
+ const len = queries.length;
12481
+ const results = Array.from({
12482
+ length: len
12483
+ });
12484
+ for (let i = 0; i < len; i++) {
12485
+ const query = queries[i];
12486
+ const {
12487
+ sql,
12488
+ args
12489
+ } = query;
12490
+ const isSelect = /^\s*SELECT\b/iu.test(sql);
11886
12491
  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));
12492
+ results[i] = new SQLiteResult(READ_ONLY_ERROR);
12493
+ continue;
12494
+ }
12495
+ const trace = this._db.getTrace();
12496
+ const profile = this._db.getProfile();
12497
+ // eslint-disable-next-line unicorn/prefer-bigint-literals -- `0n` needs ES2020+ target for tsc
12498
+ const start = profile ? process.hrtime.bigint() : BigInt(0);
12499
+ try {
12500
+ if (trace) {
12501
+ trace(sql);
12502
+ }
12503
+ if (isSelect) {
12504
+ const rows = runSelect(db, sql, args);
12505
+ results[i] = new SQLiteResult(null, undefined, 0, rows);
12506
+ } else {
12507
+ const executionResult = runNonSelect(db, sql, args);
12508
+ const insertId = Number(executionResult.lastInsertRowid);
12509
+ results[i] = new SQLiteResult(null, insertId, executionResult.changes, []);
12510
+ }
12511
+ } catch (err) {
12512
+ results[i] = new SQLiteResult(/** @type {Error} */err);
12513
+ } finally {
12514
+ if (profile) {
12515
+ profile(sql, Number(process.hrtime.bigint() - start));
12516
+ }
11892
12517
  }
11893
12518
  }
11894
- doNext();
12519
+ queueMicrotask(() => {
12520
+ callback(null, results);
12521
+ });
11895
12522
  };
11896
12523
 
11897
12524
  /**
@@ -11904,11 +12531,9 @@ function wrappedSQLiteDatabase(name) {
11904
12531
  db._db.configure('busyTimeout', /** @type {number} */CFG.sqlBusyTimeout); // Default is 1000
11905
12532
  }
11906
12533
  if (CFG.sqlTrace) {
11907
- // @ts-expect-error native API?
11908
12534
  db._db.configure('trace', CFG.sqlTrace);
11909
12535
  }
11910
12536
  if (CFG.sqlProfile) {
11911
- // @ts-expect-error native API?
11912
12537
  db._db.configure('profile', CFG.sqlProfile);
11913
12538
  }
11914
12539
  return db;
@@ -11939,6 +12564,7 @@ CFG.win = {
11939
12564
  const __setGlobalVars = function (idb, initialConfig = {}) {
11940
12565
  const obj = setGlobalVars(idb, {
11941
12566
  fs: fs$1,
12567
+ escapeNULForSQLiteStatements: false,
11942
12568
  ...initialConfig
11943
12569
  });
11944
12570
  /* istanbul ignore next -- TS guard */