@powersync/web 1.38.7 → 1.39.1

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 (44) hide show
  1. package/dist/index.umd.js +344 -83
  2. package/dist/index.umd.js.map +1 -1
  3. package/dist/worker/SharedSyncImplementation.umd.js +18 -9
  4. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  5. package/dist/worker/WASQLiteDB.umd.js +94 -60
  6. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  7. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-833585.umd.js +1400 -0
  8. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-833585.umd.js.map +1 -0
  9. package/lib/package.json +2 -2
  10. package/lib/src/db/adapters/AsyncWebAdapter.js +1 -1
  11. package/lib/src/db/adapters/AsyncWebAdapter.js.map +1 -1
  12. package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.d.ts +8 -1
  13. package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js +13 -9
  14. package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js.map +1 -1
  15. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +8 -2
  16. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js.map +1 -1
  17. package/lib/src/db/adapters/wa-sqlite/vfs.d.ts +20 -30
  18. package/lib/src/db/adapters/wa-sqlite/vfs.js +57 -39
  19. package/lib/src/db/adapters/wa-sqlite/vfs.js.map +1 -1
  20. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +1 -0
  21. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +10 -5
  22. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js.map +1 -1
  23. package/lib/src/worker/db/MultiDatabaseServer.js +5 -3
  24. package/lib/src/worker/db/MultiDatabaseServer.js.map +1 -1
  25. package/lib/src/worker/db/open-worker-database.d.ts +3 -2
  26. package/lib/src/worker/db/open-worker-database.js +30 -22
  27. package/lib/src/worker/db/open-worker-database.js.map +1 -1
  28. package/lib/src/worker/errors.d.ts +2 -0
  29. package/lib/src/worker/errors.js +7 -0
  30. package/lib/src/worker/errors.js.map +1 -0
  31. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +1 -0
  32. package/lib/src/worker/sync/SharedSyncImplementation.js +2 -1
  33. package/lib/src/worker/sync/SharedSyncImplementation.js.map +1 -1
  34. package/lib/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +3 -3
  36. package/src/db/adapters/AsyncWebAdapter.ts +1 -1
  37. package/src/db/adapters/wa-sqlite/RawSqliteConnection.ts +15 -11
  38. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +24 -9
  39. package/src/db/adapters/wa-sqlite/vfs.ts +67 -54
  40. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +17 -11
  41. package/src/worker/db/MultiDatabaseServer.ts +5 -3
  42. package/src/worker/db/open-worker-database.ts +34 -22
  43. package/src/worker/errors.ts +9 -0
  44. package/src/worker/sync/SharedSyncImplementation.ts +3 -1
package/dist/index.umd.js CHANGED
@@ -1564,6 +1564,198 @@ class Lock {
1564
1564
  }
1565
1565
 
1566
1566
 
1567
+ /***/ },
1568
+
1569
+ /***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/MemoryVFS.js"
1570
+ /*!***************************************************************************************************************************!*\
1571
+ !*** ../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/MemoryVFS.js ***!
1572
+ \***************************************************************************************************************************/
1573
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
1574
+
1575
+ __webpack_require__.r(__webpack_exports__);
1576
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1577
+ /* harmony export */ MemoryVFS: () => (/* binding */ MemoryVFS)
1578
+ /* harmony export */ });
1579
+ /* harmony import */ var _FacadeVFS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../FacadeVFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/FacadeVFS.js");
1580
+ /* harmony import */ var _VFS_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../VFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/VFS.js");
1581
+ // Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
1582
+
1583
+
1584
+
1585
+ // Sample in-memory filesystem.
1586
+ class MemoryVFS extends _FacadeVFS_js__WEBPACK_IMPORTED_MODULE_0__.FacadeVFS {
1587
+ // Map of existing files, keyed by filename.
1588
+ mapNameToFile = new Map();
1589
+
1590
+ // Map of open files, keyed by id (sqlite3_file pointer).
1591
+ mapIdToFile = new Map();
1592
+
1593
+ static async create(name, module) {
1594
+ const vfs = new MemoryVFS(name, module);
1595
+ await vfs.isReady();
1596
+ return vfs;
1597
+ }
1598
+
1599
+ constructor(name, module) {
1600
+ super(name, module);
1601
+ }
1602
+
1603
+ close() {
1604
+ for (const fileId of this.mapIdToFile.keys()) {
1605
+ this.jClose(fileId);
1606
+ }
1607
+ }
1608
+
1609
+ /**
1610
+ * @param {string?} filename
1611
+ * @param {number} fileId
1612
+ * @param {number} flags
1613
+ * @param {DataView} pOutFlags
1614
+ * @returns {number|Promise<number>}
1615
+ */
1616
+ jOpen(filename, fileId, flags, pOutFlags) {
1617
+ const url = new URL(filename || Math.random().toString(36).slice(2), 'file://');
1618
+ const pathname = url.pathname;
1619
+
1620
+ let file = this.mapNameToFile.get(pathname);
1621
+ if (!file) {
1622
+ if (flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_CREATE) {
1623
+ // Create a new file object.
1624
+ file = {
1625
+ pathname,
1626
+ flags,
1627
+ size: 0,
1628
+ data: new ArrayBuffer(0)
1629
+ };
1630
+ this.mapNameToFile.set(pathname, file);
1631
+ } else {
1632
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_CANTOPEN;
1633
+ }
1634
+ }
1635
+
1636
+ // Put the file in the opened files map.
1637
+ this.mapIdToFile.set(fileId, file);
1638
+ pOutFlags.setInt32(0, flags, true);
1639
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1640
+ }
1641
+
1642
+ /**
1643
+ * @param {number} fileId
1644
+ * @returns {number|Promise<number>}
1645
+ */
1646
+ jClose(fileId) {
1647
+ const file = this.mapIdToFile.get(fileId);
1648
+ this.mapIdToFile.delete(fileId);
1649
+
1650
+ if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_DELETEONCLOSE) {
1651
+ this.mapNameToFile.delete(file.pathname);
1652
+ }
1653
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1654
+ }
1655
+
1656
+ /**
1657
+ * @param {number} fileId
1658
+ * @param {Uint8Array} pData
1659
+ * @param {number} iOffset
1660
+ * @returns {number|Promise<number>}
1661
+ */
1662
+ jRead(fileId, pData, iOffset) {
1663
+ const file = this.mapIdToFile.get(fileId);
1664
+
1665
+ // Clip the requested read to the file boundary.
1666
+ const bgn = Math.min(iOffset, file.size);
1667
+ const end = Math.min(iOffset + pData.byteLength, file.size);
1668
+ const nBytes = end - bgn;
1669
+
1670
+ if (nBytes) {
1671
+ pData.set(new Uint8Array(file.data, bgn, nBytes));
1672
+ }
1673
+
1674
+ if (nBytes < pData.byteLength) {
1675
+ // Zero unused area of read buffer.
1676
+ pData.fill(0, nBytes);
1677
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_SHORT_READ;
1678
+ }
1679
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1680
+ }
1681
+
1682
+ /**
1683
+ * @param {number} fileId
1684
+ * @param {Uint8Array} pData
1685
+ * @param {number} iOffset
1686
+ * @returns {number|Promise<number>}
1687
+ */
1688
+ jWrite(fileId, pData, iOffset) {
1689
+ const file = this.mapIdToFile.get(fileId);
1690
+ if (iOffset + pData.byteLength > file.data.byteLength) {
1691
+ // Resize the ArrayBuffer to hold more data.
1692
+ const newSize = Math.max(iOffset + pData.byteLength, 2 * file.data.byteLength);
1693
+ const data = new ArrayBuffer(newSize);
1694
+ new Uint8Array(data).set(new Uint8Array(file.data, 0, file.size));
1695
+ file.data = data;
1696
+ }
1697
+
1698
+ // Copy data.
1699
+ new Uint8Array(file.data, iOffset, pData.byteLength).set(pData.subarray());
1700
+ file.size = Math.max(file.size, iOffset + pData.byteLength);
1701
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1702
+ }
1703
+
1704
+ /**
1705
+ * @param {number} fileId
1706
+ * @param {number} iSize
1707
+ * @returns {number|Promise<number>}
1708
+ */
1709
+ jTruncate(fileId, iSize) {
1710
+ const file = this.mapIdToFile.get(fileId);
1711
+
1712
+ // For simplicity we don't make the ArrayBuffer smaller.
1713
+ file.size = Math.min(file.size, iSize);
1714
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1715
+ }
1716
+
1717
+ /**
1718
+ * @param {number} fileId
1719
+ * @param {DataView} pSize64
1720
+ * @returns {number|Promise<number>}
1721
+ */
1722
+ jFileSize(fileId, pSize64) {
1723
+ const file = this.mapIdToFile.get(fileId);
1724
+
1725
+ pSize64.setBigInt64(0, BigInt(file.size), true);
1726
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1727
+ }
1728
+
1729
+ /**
1730
+ * @param {string} name
1731
+ * @param {number} syncDir
1732
+ * @returns {number|Promise<number>}
1733
+ */
1734
+ jDelete(name, syncDir) {
1735
+ const url = new URL(name, 'file://');
1736
+ const pathname = url.pathname;
1737
+
1738
+ this.mapNameToFile.delete(pathname);
1739
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1740
+ }
1741
+
1742
+ /**
1743
+ * @param {string} name
1744
+ * @param {number} flags
1745
+ * @param {DataView} pResOut
1746
+ * @returns {number|Promise<number>}
1747
+ */
1748
+ jAccess(name, flags, pResOut) {
1749
+ const url = new URL(name, 'file://');
1750
+ const pathname = url.pathname;
1751
+
1752
+ const file = this.mapNameToFile.get(pathname);
1753
+ pResOut.setInt32(0, file ? 1 : 0, true);
1754
+ return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
1755
+ }
1756
+ }
1757
+
1758
+
1567
1759
  /***/ },
1568
1760
 
1569
1761
  /***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js"
@@ -4731,7 +4923,7 @@ function readWritePoolState(writer, readers) {
4731
4923
  let timeout = null;
4732
4924
  let release;
4733
4925
  if (options?.timeoutMs) {
4734
- timeout = setTimeout(() => abortController.abort, options.timeoutMs);
4926
+ timeout = setTimeout(() => abortController.abort('requesting database timed out'), options.timeoutMs);
4735
4927
  }
4736
4928
  try {
4737
4929
  if (allowReadOnly) {
@@ -5450,12 +5642,21 @@ class DatabaseServer {
5450
5642
 
5451
5643
  __webpack_require__.r(__webpack_exports__);
5452
5644
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
5453
- /* harmony export */ RawSqliteConnection: () => (/* binding */ RawSqliteConnection)
5645
+ /* harmony export */ RawSqliteConnection: () => (/* binding */ RawSqliteConnection),
5646
+ /* harmony export */ maxPathNameLength: () => (/* binding */ maxPathNameLength)
5454
5647
  /* harmony export */ });
5455
5648
  /* harmony import */ var _journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @journeyapps/wa-sqlite */ "@journeyapps/wa-sqlite");
5456
5649
  /* harmony import */ var _vfs_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./vfs.js */ "./lib/src/db/adapters/wa-sqlite/vfs.js");
5457
5650
 
5458
5651
 
5652
+ /**
5653
+ * The maximum length of a db filename we support.
5654
+ *
5655
+ * We configure the same on WA-SQLite (which otherwise defaults to a maximum length of 64). We don't want to support
5656
+ * very long path names as Safari maps OPFS files directly to OS files, and APFS has a 255-byte filename limit. Since
5657
+ * some VFS append additional characters for pooled file access handles, we want to stay well below that.
5658
+ */
5659
+ const maxPathNameLength = 128;
5459
5660
  /**
5460
5661
  * A small wrapper around WA-sqlite to help with opening databases and running statements by preparing them internally.
5461
5662
  *
@@ -5469,10 +5670,8 @@ class RawSqliteConnection {
5469
5670
  * The `sqlite3*` connection pointer.
5470
5671
  */
5471
5672
  db = 0;
5472
- _moduleFactory;
5473
5673
  constructor(options) {
5474
5674
  this.options = options;
5475
- this._moduleFactory = _vfs_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_MODULE_FACTORIES[this.options.vfs];
5476
5675
  }
5477
5676
  get isOpen() {
5478
5677
  return this.db != 0;
@@ -5482,17 +5681,15 @@ class RawSqliteConnection {
5482
5681
  this.db = await api.open_v2(this.options.dbFilename, this.options.isReadOnly ? 1 /* SQLITE_OPEN_READONLY */ : 6 /* SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE */);
5483
5682
  await this.executeRaw(`PRAGMA temp_store = ${this.options.temporaryStorage};`);
5484
5683
  if (this.options.encryptionKey) {
5485
- const escapedKey = this.options.encryptionKey.replace("'", "''");
5486
- await this.executeRaw(`PRAGMA key = '${escapedKey}'`);
5684
+ const escapedKey = this.options.encryptionKey.replaceAll("'", "''");
5685
+ await this.executeRaw(`PRAGMA key = '${escapedKey}';`);
5487
5686
  }
5488
5687
  await this.executeRaw(`PRAGMA cache_size = -${this.options.cacheSizeKb};`);
5489
5688
  await this.executeRaw(`SELECT powersync_update_hooks('install');`);
5490
5689
  }
5491
5690
  async openSQLiteAPI() {
5492
- const { module, vfs } = await this._moduleFactory({
5493
- dbFileName: this.options.dbFilename,
5494
- encryptionKey: this.options.encryptionKey
5495
- });
5691
+ const { module, vfs } = await (0,_vfs_js__WEBPACK_IMPORTED_MODULE_1__.loadModuleAndVfs)(this.options);
5692
+ vfs.mxPathname = maxPathNameLength;
5496
5693
  const sqlite3 = (0,_journeyapps_wa_sqlite__WEBPACK_IMPORTED_MODULE_0__.Factory)(module);
5497
5694
  sqlite3.vfs_register(vfs, true);
5498
5695
  /**
@@ -5625,6 +5822,8 @@ __webpack_require__.r(__webpack_exports__);
5625
5822
  /* harmony import */ var _DatabaseClient_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./DatabaseClient.js */ "./lib/src/db/adapters/wa-sqlite/DatabaseClient.js");
5626
5823
  /* harmony import */ var _shared_tab_close_signal_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../shared/tab_close_signal.js */ "./lib/src/shared/tab_close_signal.js");
5627
5824
  /* harmony import */ var _AsyncWebAdapter_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../AsyncWebAdapter.js */ "./lib/src/db/adapters/AsyncWebAdapter.js");
5825
+ /* harmony import */ var _RawSqliteConnection_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./RawSqliteConnection.js */ "./lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js");
5826
+
5628
5827
 
5629
5828
 
5630
5829
 
@@ -5701,8 +5900,8 @@ class WASQLiteOpenFactory {
5701
5900
  cacheSizeKb,
5702
5901
  flags: this.resolvedFlags,
5703
5902
  encryptionKey
5704
- }))
5705
- : (0,_worker_db_open_worker_database_js__WEBPACK_IMPORTED_MODULE_2__.openWorkerDatabasePort)(this.options.dbFilename, enableMultiTabs, optionsDbWorker, this.waOptions.vfs);
5903
+ }), this.logger)
5904
+ : (0,_worker_db_open_worker_database_js__WEBPACK_IMPORTED_MODULE_2__.openWorkerDatabasePort)(this.options.dbFilename, enableMultiTabs, optionsDbWorker, this.waOptions.vfs, this.logger);
5706
5905
  const source = comlink__WEBPACK_IMPORTED_MODULE_1__.wrap(workerPort);
5707
5906
  const closeSignal = new AbortController();
5708
5907
  const connection = await source.connect({
@@ -5769,6 +5968,11 @@ function assertValidWASQLiteOpenFactoryOptions(options) {
5769
5968
  throw new Error(`Invalid configuration: The 'useWebWorker' flag must be true when using an OPFS-based VFS (${vfs}).`);
5770
5969
  }
5771
5970
  }
5971
+ // Account for the fact that SQLite might append -journal suffixes
5972
+ const maxLength = _RawSqliteConnection_js__WEBPACK_IMPORTED_MODULE_10__.maxPathNameLength - 16;
5973
+ if (options.dbFilename.length > maxLength) {
5974
+ throw new Error(`dbFilename too long (max length is ${maxLength})`);
5975
+ }
5772
5976
  }
5773
5977
 
5774
5978
 
@@ -5820,8 +6024,8 @@ class WASQLitePowerSyncDatabaseOpenFactory extends _AbstractWebPowerSyncDatabase
5820
6024
 
5821
6025
  __webpack_require__.r(__webpack_exports__);
5822
6026
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
5823
- /* harmony export */ DEFAULT_MODULE_FACTORIES: () => (/* binding */ DEFAULT_MODULE_FACTORIES),
5824
6027
  /* harmony export */ WASQLiteVFS: () => (/* binding */ WASQLiteVFS),
6028
+ /* harmony export */ loadModuleAndVfs: () => (/* binding */ loadModuleAndVfs),
5825
6029
  /* harmony export */ vfsRequiresDedicatedWorkers: () => (/* binding */ vfsRequiresDedicatedWorkers)
5826
6030
  /* harmony export */ });
5827
6031
  /**
@@ -5833,9 +6037,26 @@ var WASQLiteVFS;
5833
6037
  WASQLiteVFS["OPFSCoopSyncVFS"] = "OPFSCoopSyncVFS";
5834
6038
  WASQLiteVFS["AccessHandlePoolVFS"] = "AccessHandlePoolVFS";
5835
6039
  WASQLiteVFS["OPFSWriteAheadVFS"] = "OPFSWriteAheadVFS";
6040
+ /**
6041
+ * A virtual file system storing data in-memory only, without persistence.
6042
+ *
6043
+ * This file system can be used in three configurations:
6044
+ *
6045
+ * 1. In shared workers (the default when available): All tabs share the same in-memory database, which is cleared
6046
+ * once the last tab is closed.
6047
+ * 2. In dedicated workers (used when `enableMultiTabs` is disabled). Each tab has its own in-memory database cleared
6048
+ * when the tab is closed. Queries are offloaded to a dedicated worker.
6049
+ * 3. In the context of the tab itself (used when both `enableMultiTabs` and `useWebWorker` are disabled). The per-tab
6050
+ * database is hosted in the tab itself, and queries run synchronously. This is _a lot_ faster than any other
6051
+ * single-threadedVFS, but can block JavaScript for computationally-intensive queries.
6052
+ *
6053
+ * This VFS primarily intended for development, but it also useful for online-first deployments not syncing large
6054
+ * amounts of data, as it is quicker to start up.
6055
+ */
6056
+ WASQLiteVFS["InMemoryVfs"] = "InMemoryVFS";
5836
6057
  })(WASQLiteVFS || (WASQLiteVFS = {}));
5837
6058
  function vfsRequiresDedicatedWorkers(vfs) {
5838
- return vfs != WASQLiteVFS.IDBBatchAtomicVFS;
6059
+ return vfs != WASQLiteVFS.IDBBatchAtomicVFS && vfs != WASQLiteVFS.InMemoryVfs;
5839
6060
  }
5840
6061
  async function asyncModuleFactory(encryptionKey) {
5841
6062
  if (encryptionKey) {
@@ -5860,46 +6081,47 @@ async function syncModuleFactory(encryptionKey) {
5860
6081
  /**
5861
6082
  * @internal
5862
6083
  */
5863
- const DEFAULT_MODULE_FACTORIES = {
5864
- [WASQLiteVFS.IDBBatchAtomicVFS]: async (options) => {
5865
- const module = await asyncModuleFactory(options.encryptionKey);
5866
- const { IDBBatchAtomicVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js */ "@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js", 19));
5867
- return {
5868
- module,
6084
+ async function loadModuleAndVfs({ vfs, dbFilename, encryptionKey }) {
6085
+ let moduleFactory = syncModuleFactory;
6086
+ let resolveVfs;
6087
+ switch (vfs) {
6088
+ case WASQLiteVFS.IDBBatchAtomicVFS: {
6089
+ moduleFactory = asyncModuleFactory;
6090
+ const { IDBBatchAtomicVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js */ "@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js", 19));
6091
+ resolveVfs = (module) => {
6092
+ // @ts-expect-error The types for this static method are missing upstream
6093
+ return IDBBatchAtomicVFS.create(dbFilename, module, { lockPolicy: 'exclusive' });
6094
+ };
6095
+ break;
6096
+ }
6097
+ case WASQLiteVFS.AccessHandlePoolVFS: {
6098
+ // @ts-expect-error The types for this import are missing upstream
6099
+ const { AccessHandlePoolVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js */ "@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js", 19));
6100
+ resolveVfs = (module) => AccessHandlePoolVFS.create(dbFilename, module);
6101
+ break;
6102
+ }
6103
+ case WASQLiteVFS.OPFSCoopSyncVFS: {
6104
+ // @ts-expect-error The types for this import are missing upstream
6105
+ const { OPFSCoopSyncVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js */ "@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js", 19));
6106
+ resolveVfs = (module) => OPFSCoopSyncVFS.create(dbFilename, module);
6107
+ break;
6108
+ }
6109
+ case WASQLiteVFS.OPFSWriteAheadVFS: {
6110
+ // @ts-expect-error The types for this import are missing upstream
6111
+ const { OPFSWriteAheadVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js"));
6112
+ resolveVfs = (module) => OPFSWriteAheadVFS.create(dbFilename, module, {});
6113
+ break;
6114
+ }
6115
+ case WASQLiteVFS.InMemoryVfs: {
6116
+ const { MemoryVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/MemoryVFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/MemoryVFS.js"));
5869
6117
  // @ts-expect-error The types for this static method are missing upstream
5870
- vfs: await IDBBatchAtomicVFS.create(options.dbFileName, module, { lockPolicy: 'exclusive' })
5871
- };
5872
- },
5873
- [WASQLiteVFS.AccessHandlePoolVFS]: async (options) => {
5874
- const module = await syncModuleFactory(options.encryptionKey);
5875
- // @ts-expect-error The types for this static method are missing upstream
5876
- const { AccessHandlePoolVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js */ "@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js", 19));
5877
- return {
5878
- module,
5879
- vfs: await AccessHandlePoolVFS.create(options.dbFileName, module)
5880
- };
5881
- },
5882
- [WASQLiteVFS.OPFSCoopSyncVFS]: async (options) => {
5883
- const module = await syncModuleFactory(options.encryptionKey);
5884
- // @ts-expect-error The types for this static method are missing upstream
5885
- const { OPFSCoopSyncVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js */ "@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js", 19));
5886
- const vfs = await OPFSCoopSyncVFS.create(options.dbFileName, module);
5887
- return {
5888
- module,
5889
- vfs
5890
- };
5891
- },
5892
- [WASQLiteVFS.OPFSWriteAheadVFS]: async (options) => {
5893
- const module = await syncModuleFactory(options.encryptionKey);
5894
- // @ts-expect-error The types for this static method are missing upstream
5895
- const { OPFSWriteAheadVFS } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js"));
5896
- const vfs = await OPFSWriteAheadVFS.create(options.dbFileName, module, {});
5897
- return {
5898
- module,
5899
- vfs
5900
- };
6118
+ resolveVfs = (module) => MemoryVFS.create(dbFilename, module);
6119
+ break;
6120
+ }
5901
6121
  }
5902
- };
6122
+ const module = await moduleFactory(encryptionKey);
6123
+ return { module, vfs: await resolveVfs(module) };
6124
+ }
5903
6125
 
5904
6126
 
5905
6127
  /***/ },
@@ -6057,6 +6279,8 @@ __webpack_require__.r(__webpack_exports__);
6057
6279
  /* harmony import */ var _adapters_web_sql_flags_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../adapters/web-sql-flags.js */ "./lib/src/db/adapters/web-sql-flags.js");
6058
6280
  /* harmony import */ var _WebStreamingSyncImplementation_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./WebStreamingSyncImplementation.js */ "./lib/src/db/sync/WebStreamingSyncImplementation.js");
6059
6281
  /* harmony import */ var _shared_tab_close_signal_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../shared/tab_close_signal.js */ "./lib/src/shared/tab_close_signal.js");
6282
+ /* harmony import */ var _worker_errors_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../worker/errors.js */ "./lib/src/worker/errors.js");
6283
+
6060
6284
 
6061
6285
 
6062
6286
 
@@ -6162,21 +6386,21 @@ class SharedWebStreamingSyncImplementation extends _WebStreamingSyncImplementati
6162
6386
  const syncWorker = options.sync?.worker;
6163
6387
  if (syncWorker) {
6164
6388
  if (typeof syncWorker === 'function') {
6165
- this.messagePort = syncWorker(resolvedWorkerOptions).port;
6389
+ this.messagePort = this.workerPort(syncWorker(resolvedWorkerOptions));
6166
6390
  }
6167
6391
  else {
6168
- this.messagePort = new SharedWorker(`${syncWorker}`, {
6392
+ this.messagePort = this.workerPort(new SharedWorker(`${syncWorker}`, {
6169
6393
  /* @vite-ignore */
6170
6394
  name: `shared-sync-${this.webOptions.identifier}`
6171
- }).port;
6395
+ }));
6172
6396
  }
6173
6397
  }
6174
6398
  else {
6175
- this.messagePort = new SharedWorker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("lib_src_worker_sync_SharedSyncImplementation_worker_js"), __webpack_require__.b), {
6399
+ this.messagePort = this.workerPort(new SharedWorker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("lib_src_worker_sync_SharedSyncImplementation_worker_js"), __webpack_require__.b), {
6176
6400
  /* @vite-ignore */
6177
6401
  name: `shared-sync-${this.webOptions.identifier}`,
6178
6402
  type: undefined
6179
- }).port;
6403
+ }));
6180
6404
  }
6181
6405
  /**
6182
6406
  * Pass along any sync status updates to this listener
@@ -6201,6 +6425,10 @@ class SharedWebStreamingSyncImplementation extends _WebStreamingSyncImplementati
6201
6425
  */
6202
6426
  this.isInitialized = this._init();
6203
6427
  }
6428
+ workerPort(worker) {
6429
+ (0,_worker_errors_js__WEBPACK_IMPORTED_MODULE_6__.logWorkerErrors)(worker, this.logger);
6430
+ return worker.port;
6431
+ }
6204
6432
  async _init() {
6205
6433
  /**
6206
6434
  * The general flow of initialization is:
@@ -6517,6 +6745,8 @@ __webpack_require__.r(__webpack_exports__);
6517
6745
  /* harmony import */ var _shared_navigator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../shared/navigator.js */ "./lib/src/shared/navigator.js");
6518
6746
  /* harmony import */ var _db_adapters_wa_sqlite_RawSqliteConnection_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../db/adapters/wa-sqlite/RawSqliteConnection.js */ "./lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js");
6519
6747
  /* harmony import */ var _db_adapters_wa_sqlite_ConcurrentConnection_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../db/adapters/wa-sqlite/ConcurrentConnection.js */ "./lib/src/db/adapters/wa-sqlite/ConcurrentConnection.js");
6748
+ /* harmony import */ var _db_adapters_wa_sqlite_vfs_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../db/adapters/wa-sqlite/vfs.js */ "./lib/src/db/adapters/wa-sqlite/vfs.js");
6749
+
6520
6750
 
6521
6751
 
6522
6752
 
@@ -6565,13 +6795,14 @@ class MultiDatabaseServer {
6565
6795
  }
6566
6796
  async databaseOpenAttempt(options) {
6567
6797
  return (0,_shared_navigator_js__WEBPACK_IMPORTED_MODULE_2__.getNavigatorLocks)().request(OPEN_DB_LOCK, async () => {
6568
- const { dbFilename } = options;
6798
+ const { dbFilename, isReadOnly, vfs } = options;
6569
6799
  let server = this.activeDatabases.get(dbFilename);
6570
6800
  if (server == null) {
6571
6801
  // We don't need navigator locks for shared workers because all queries run in this shared worker exclusively.
6572
6802
  // For read-only connections, we use a VFS that supports concurrent reads (so a single lock on the connection is
6573
- // fine).
6574
- const needsNavigatorLocks = !(isSharedWorker || options.isReadOnly);
6803
+ // fine). In-memory databases either run in a shared worker or aren't shared across tabs at all, so the internal
6804
+ // lock is enough.
6805
+ const needsNavigatorLocks = !(isSharedWorker || isReadOnly || vfs == _db_adapters_wa_sqlite_vfs_js__WEBPACK_IMPORTED_MODULE_5__.WASQLiteVFS.InMemoryVfs);
6575
6806
  const connection = new _db_adapters_wa_sqlite_RawSqliteConnection_js__WEBPACK_IMPORTED_MODULE_3__.RawSqliteConnection(options);
6576
6807
  const withSafeConcurrency = new _db_adapters_wa_sqlite_ConcurrentConnection_js__WEBPACK_IMPORTED_MODULE_4__.ConcurrentSqliteConnection(connection, needsNavigatorLocks);
6577
6808
  // Initializing the RawSqliteConnection will run some pragmas that might write to the database file, so we want
@@ -6625,23 +6856,27 @@ __webpack_require__.r(__webpack_exports__);
6625
6856
  /* harmony export */ });
6626
6857
  /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! comlink */ "comlink");
6627
6858
  /* harmony import */ var _db_adapters_wa_sqlite_vfs_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../db/adapters/wa-sqlite/vfs.js */ "./lib/src/db/adapters/wa-sqlite/vfs.js");
6859
+ /* harmony import */ var _errors_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../errors.js */ "./lib/src/worker/errors.js");
6860
+
6628
6861
 
6629
6862
 
6630
6863
  /**
6631
6864
  * Opens a shared or dedicated worker which exposes opening of database connections
6632
6865
  */
6633
- function openWorkerDatabasePort(workerIdentifier, multipleTabs = true, worker = '', vfs) {
6866
+ function openWorkerDatabasePort(workerIdentifier, multipleTabs = true, worker = '', vfs, logger) {
6634
6867
  const needsDedicated = vfs && (0,_db_adapters_wa_sqlite_vfs_js__WEBPACK_IMPORTED_MODULE_1__.vfsRequiresDedicatedWorkers)(vfs);
6868
+ let resolvedWorker;
6635
6869
  if (worker) {
6636
- return !needsDedicated && multipleTabs
6637
- ? new SharedWorker(`${worker}`, {
6638
- /* @vite-ignore */
6639
- name: `shared-DB-worker-${workerIdentifier}`
6640
- }).port
6641
- : new Worker(`${worker}`, {
6642
- /* @vite-ignore */
6643
- name: `DB-worker-${workerIdentifier}`
6644
- });
6870
+ resolvedWorker =
6871
+ !needsDedicated && multipleTabs
6872
+ ? new SharedWorker(`${worker}`, {
6873
+ /* @vite-ignore */
6874
+ name: `shared-DB-worker-${workerIdentifier}`
6875
+ })
6876
+ : new Worker(`${worker}`, {
6877
+ /* @vite-ignore */
6878
+ name: `DB-worker-${workerIdentifier}`
6879
+ });
6645
6880
  }
6646
6881
  else {
6647
6882
  /**
@@ -6650,18 +6885,20 @@ function openWorkerDatabasePort(workerIdentifier, multipleTabs = true, worker =
6650
6885
  * This enables multi tab support by default, but falls back if SharedWorker is not available
6651
6886
  * (in the case of Android)
6652
6887
  */
6653
- return !needsDedicated && multipleTabs
6654
- ? new SharedWorker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("lib_src_worker_db_WASQLiteDB_worker_js"), __webpack_require__.b), {
6655
- /* @vite-ignore */
6656
- name: `shared-DB-worker-${workerIdentifier}`,
6657
- type: undefined
6658
- }).port
6659
- : new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("lib_src_worker_db_WASQLiteDB_worker_js"), __webpack_require__.b), {
6660
- /* @vite-ignore */
6661
- name: `DB-worker-${workerIdentifier}`,
6662
- type: undefined
6663
- });
6888
+ resolvedWorker =
6889
+ !needsDedicated && multipleTabs
6890
+ ? new SharedWorker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("lib_src_worker_db_WASQLiteDB_worker_js"), __webpack_require__.b), {
6891
+ /* @vite-ignore */
6892
+ name: `shared-DB-worker-${workerIdentifier}`,
6893
+ type: undefined
6894
+ })
6895
+ : new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("lib_src_worker_db_WASQLiteDB_worker_js"), __webpack_require__.b), {
6896
+ /* @vite-ignore */
6897
+ name: `DB-worker-${workerIdentifier}`,
6898
+ type: undefined
6899
+ });
6664
6900
  }
6901
+ return resolveWorkerDatabasePortFactory(() => resolvedWorker, logger);
6665
6902
  }
6666
6903
  /**
6667
6904
  * @returns A function which allows for opening database connections inside
@@ -6670,8 +6907,11 @@ function openWorkerDatabasePort(workerIdentifier, multipleTabs = true, worker =
6670
6907
  function getWorkerDatabaseOpener(workerIdentifier, multipleTabs = true, worker = '') {
6671
6908
  return comlink__WEBPACK_IMPORTED_MODULE_0__.wrap(openWorkerDatabasePort(workerIdentifier, multipleTabs, worker));
6672
6909
  }
6673
- function resolveWorkerDatabasePortFactory(worker) {
6910
+ function resolveWorkerDatabasePortFactory(worker, logger) {
6674
6911
  const workerInstance = worker();
6912
+ if (logger) {
6913
+ (0,_errors_js__WEBPACK_IMPORTED_MODULE_2__.logWorkerErrors)(workerInstance, logger);
6914
+ }
6675
6915
  return isSharedWorker(workerInstance) ? workerInstance.port : workerInstance;
6676
6916
  }
6677
6917
  function isSharedWorker(worker) {
@@ -6679,6 +6919,26 @@ function isSharedWorker(worker) {
6679
6919
  }
6680
6920
 
6681
6921
 
6922
+ /***/ },
6923
+
6924
+ /***/ "./lib/src/worker/errors.js"
6925
+ /*!**********************************!*\
6926
+ !*** ./lib/src/worker/errors.js ***!
6927
+ \**********************************/
6928
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
6929
+
6930
+ __webpack_require__.r(__webpack_exports__);
6931
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
6932
+ /* harmony export */ logWorkerErrors: () => (/* binding */ logWorkerErrors)
6933
+ /* harmony export */ });
6934
+ function logWorkerErrors(worker, logger) {
6935
+ function logError(event) {
6936
+ logger.error('Error in database or sync worker, this likely disrupts PowerSync.', event.error);
6937
+ }
6938
+ worker.addEventListener('error', logError);
6939
+ }
6940
+
6941
+
6682
6942
  /***/ },
6683
6943
 
6684
6944
  /***/ "./lib/src/worker/sync/AbstractSharedSyncClientProvider.js"
@@ -6906,6 +7166,7 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
6906
7166
  syncStatus;
6907
7167
  broadCastLogger;
6908
7168
  database = this.generateReconnectableDatabase();
7169
+ sharedCloseSignal = (0,_shared_tab_close_signal_js__WEBPACK_IMPORTED_MODULE_6__.generateTabCloseSignal)();
6909
7170
  constructor() {
6910
7171
  super();
6911
7172
  this.ports = [];
@@ -7239,7 +7500,7 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
7239
7500
  });
7240
7501
  const remote = comlink__WEBPACK_IMPORTED_MODULE_1__.wrap(workerPort);
7241
7502
  const identifier = this.syncParams.dbParams.dbFilename;
7242
- const clientLockName = await (0,_shared_tab_close_signal_js__WEBPACK_IMPORTED_MODULE_6__.generateTabCloseSignal)();
7503
+ const clientLockName = await this.sharedCloseSignal;
7243
7504
  /**
7244
7505
  * The open could fail if the tab is closed while we're busy opening the database.
7245
7506
  * This operation is typically executed inside an exclusive portMutex lock.