@powersync/web 1.29.1 → 1.31.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 (60) hide show
  1. package/README.md +1 -1
  2. package/dist/0b19af1befc07ce338dd.wasm +0 -0
  3. package/dist/2632c3bda9473da74fd5.wasm +0 -0
  4. package/dist/64f5351ba3784bfe2f3e.wasm +0 -0
  5. package/dist/9318ca94aac4d0fe0135.wasm +0 -0
  6. package/dist/index.umd.js +7258 -1847
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/worker/SharedSyncImplementation.umd.js +548 -290
  9. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  10. package/dist/worker/WASQLiteDB.umd.js +192 -126
  11. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  12. package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js +3 -3
  13. package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js.map +1 -1
  14. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +22 -9
  15. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +1 -1
  16. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +22 -9
  17. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +1 -1
  18. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +22 -9
  19. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
  20. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +22 -9
  21. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -1
  22. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js +9 -9
  23. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js.map +1 -1
  24. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js +32 -35
  25. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +1 -1
  26. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js +27 -20
  27. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js.map +1 -1
  28. package/lib/package.json +5 -5
  29. package/lib/src/db/PowerSyncDatabase.d.ts +1 -1
  30. package/lib/src/db/PowerSyncDatabase.js +4 -4
  31. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +17 -0
  32. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +109 -19
  33. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +5 -1
  34. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +14 -7
  35. package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js +11 -2
  36. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +1 -1
  37. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +2 -2
  38. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +2 -5
  39. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +51 -35
  40. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +18 -8
  41. package/lib/src/worker/sync/SharedSyncImplementation.js +204 -108
  42. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +1 -1
  43. package/lib/src/worker/sync/WorkerClient.d.ts +4 -5
  44. package/lib/src/worker/sync/WorkerClient.js +7 -9
  45. package/lib/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +6 -6
  47. package/src/db/PowerSyncDatabase.ts +13 -15
  48. package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +126 -25
  49. package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +18 -6
  50. package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +11 -3
  51. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +3 -3
  52. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +65 -47
  53. package/src/worker/db/WASQLiteDB.worker.ts +0 -1
  54. package/src/worker/sync/SharedSyncImplementation.ts +234 -119
  55. package/src/worker/sync/SharedSyncImplementation.worker.ts +1 -1
  56. package/src/worker/sync/WorkerClient.ts +9 -13
  57. package/dist/10072fe45f0a8fab0a0e.wasm +0 -0
  58. package/dist/6e435e51534839845554.wasm +0 -0
  59. package/dist/a730f7ca717b02234beb.wasm +0 -0
  60. package/dist/aa2f408d64445fed090e.wasm +0 -0
@@ -3,11 +3,11 @@ var sdk_web;
3
3
  /******/ "use strict";
4
4
  /******/ var __webpack_modules__ = ({
5
5
 
6
- /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js":
6
+ /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js"
7
7
  /*!*******************************************************************!*\
8
8
  !*** ../../node_modules/@journeyapps/wa-sqlite/src/sqlite-api.js ***!
9
9
  \*******************************************************************/
10
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
10
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
11
11
 
12
12
  __webpack_require__.r(__webpack_exports__);
13
13
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -1147,8 +1147,11 @@ function Factory(Module) {
1147
1147
  // Wait for all pending retry operations to complete. This is
1148
1148
  // normally empty on the first loop iteration.
1149
1149
  if (Module.retryOps.length) {
1150
- await Promise.all(Module.retryOps);
1151
- Module.retryOps = [];
1150
+ try {
1151
+ await Promise.all(Module.retryOps);
1152
+ } finally {
1153
+ Module.retryOps = [];
1154
+ }
1152
1155
  }
1153
1156
 
1154
1157
  rc = await f();
@@ -1193,13 +1196,13 @@ function decl(s) {
1193
1196
  }
1194
1197
 
1195
1198
 
1196
- /***/ }),
1199
+ /***/ },
1197
1200
 
1198
- /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-constants.js":
1201
+ /***/ "../../node_modules/@journeyapps/wa-sqlite/src/sqlite-constants.js"
1199
1202
  /*!*************************************************************************!*\
1200
1203
  !*** ../../node_modules/@journeyapps/wa-sqlite/src/sqlite-constants.js ***!
1201
1204
  \*************************************************************************/
1202
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
1205
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
1203
1206
 
1204
1207
  __webpack_require__.r(__webpack_exports__);
1205
1208
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -1712,13 +1715,13 @@ const SQLITE_PREPARE_PERSISTENT = 0x01;
1712
1715
  const SQLITE_PREPARE_NORMALIZED = 0x02;
1713
1716
  const SQLITE_PREPARE_NO_VTAB = 0x04;
1714
1717
 
1715
- /***/ }),
1718
+ /***/ },
1716
1719
 
1717
- /***/ "../../node_modules/async-mutex/index.mjs":
1720
+ /***/ "../../node_modules/async-mutex/index.mjs"
1718
1721
  /*!************************************************!*\
1719
1722
  !*** ../../node_modules/async-mutex/index.mjs ***!
1720
1723
  \************************************************/
1721
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
1724
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
1722
1725
 
1723
1726
  __webpack_require__.r(__webpack_exports__);
1724
1727
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -2023,13 +2026,13 @@ function tryAcquire(sync, alreadyAcquiredError = E_ALREADY_LOCKED) {
2023
2026
 
2024
2027
 
2025
2028
 
2026
- /***/ }),
2029
+ /***/ },
2027
2030
 
2028
- /***/ "../../node_modules/comlink/dist/esm/comlink.mjs":
2031
+ /***/ "../../node_modules/comlink/dist/esm/comlink.mjs"
2029
2032
  /*!*******************************************************!*\
2030
2033
  !*** ../../node_modules/comlink/dist/esm/comlink.mjs ***!
2031
2034
  \*******************************************************/
2032
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
2035
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
2033
2036
 
2034
2037
  __webpack_require__.r(__webpack_exports__);
2035
2038
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -2404,13 +2407,13 @@ function generateUUID() {
2404
2407
  //# sourceMappingURL=comlink.mjs.map
2405
2408
 
2406
2409
 
2407
- /***/ }),
2410
+ /***/ },
2408
2411
 
2409
- /***/ "../common/dist/bundle.mjs":
2412
+ /***/ "../common/dist/bundle.mjs"
2410
2413
  /*!*********************************!*\
2411
2414
  !*** ../common/dist/bundle.mjs ***!
2412
2415
  \*********************************/
2413
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
2416
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
2414
2417
 
2415
2418
  __webpack_require__.r(__webpack_exports__);
2416
2419
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -2424,6 +2427,7 @@ __webpack_require__.r(__webpack_exports__);
2424
2427
  /* harmony export */ BaseObserver: () => (/* binding */ BaseObserver),
2425
2428
  /* harmony export */ Column: () => (/* binding */ Column),
2426
2429
  /* harmony export */ ColumnType: () => (/* binding */ ColumnType),
2430
+ /* harmony export */ ConnectionClosedError: () => (/* binding */ ConnectionClosedError),
2427
2431
  /* harmony export */ ConnectionManager: () => (/* binding */ ConnectionManager),
2428
2432
  /* harmony export */ ControlledExecutor: () => (/* binding */ ControlledExecutor),
2429
2433
  /* harmony export */ CrudBatch: () => (/* binding */ CrudBatch),
@@ -3228,12 +3232,30 @@ class SyncStatus {
3228
3232
  return {
3229
3233
  connected: this.connected,
3230
3234
  connecting: this.connecting,
3231
- dataFlow: this.dataFlowStatus,
3235
+ dataFlow: {
3236
+ ...this.dataFlowStatus,
3237
+ uploadError: this.serializeError(this.dataFlowStatus.uploadError),
3238
+ downloadError: this.serializeError(this.dataFlowStatus.downloadError)
3239
+ },
3232
3240
  lastSyncedAt: this.lastSyncedAt,
3233
3241
  hasSynced: this.hasSynced,
3234
3242
  priorityStatusEntries: this.priorityStatusEntries
3235
3243
  };
3236
3244
  }
3245
+ /**
3246
+ * Not all errors are serializable over a MessagePort. E.g. some `DomExceptions` fail to be passed across workers.
3247
+ * This explicitly serializes errors in the SyncStatus.
3248
+ */
3249
+ serializeError(error) {
3250
+ if (typeof error == 'undefined') {
3251
+ return undefined;
3252
+ }
3253
+ return {
3254
+ name: error.name,
3255
+ message: error.message,
3256
+ stack: error.stack
3257
+ };
3258
+ }
3237
3259
  static comparePriorities(a, b) {
3238
3260
  return b.priority - a.priority; // Reverse because higher priorities have lower numbers
3239
3261
  }
@@ -4846,7 +4868,7 @@ var hasRequiredBuffer$1;
4846
4868
  function requireBuffer$1 () {
4847
4869
  if (hasRequiredBuffer$1) return buffer$1;
4848
4870
  hasRequiredBuffer$1 = 1;
4849
- (function (exports) {
4871
+ (function (exports$1) {
4850
4872
 
4851
4873
  const base64 = requireBase64Js();
4852
4874
  const ieee754 = requireIeee754();
@@ -4855,12 +4877,12 @@ function requireBuffer$1 () {
4855
4877
  ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation
4856
4878
  : null;
4857
4879
 
4858
- exports.Buffer = Buffer;
4859
- exports.SlowBuffer = SlowBuffer;
4860
- exports.INSPECT_MAX_BYTES = 50;
4880
+ exports$1.Buffer = Buffer;
4881
+ exports$1.SlowBuffer = SlowBuffer;
4882
+ exports$1.INSPECT_MAX_BYTES = 50;
4861
4883
 
4862
4884
  const K_MAX_LENGTH = 0x7fffffff;
4863
- exports.kMaxLength = K_MAX_LENGTH;
4885
+ exports$1.kMaxLength = K_MAX_LENGTH;
4864
4886
 
4865
4887
  /**
4866
4888
  * If `Buffer.TYPED_ARRAY_SUPPORT`:
@@ -5456,7 +5478,7 @@ function requireBuffer$1 () {
5456
5478
 
5457
5479
  Buffer.prototype.inspect = function inspect () {
5458
5480
  let str = '';
5459
- const max = exports.INSPECT_MAX_BYTES;
5481
+ const max = exports$1.INSPECT_MAX_BYTES;
5460
5482
  str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim();
5461
5483
  if (this.length > max) str += ' ... ';
5462
5484
  return '<Buffer ' + str + '>'
@@ -6964,7 +6986,7 @@ var hasRequiredBuffer;
6964
6986
  function requireBuffer () {
6965
6987
  if (hasRequiredBuffer) return buffer;
6966
6988
  hasRequiredBuffer = 1;
6967
- (function (exports) {
6989
+ (function (exports$1) {
6968
6990
 
6969
6991
  var base64 = requireBase64Js();
6970
6992
  var ieee754 = requireIeee754();
@@ -6973,12 +6995,12 @@ function requireBuffer () {
6973
6995
  ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation
6974
6996
  : null;
6975
6997
 
6976
- exports.Buffer = Buffer;
6977
- exports.SlowBuffer = SlowBuffer;
6978
- exports.INSPECT_MAX_BYTES = 50;
6998
+ exports$1.Buffer = Buffer;
6999
+ exports$1.SlowBuffer = SlowBuffer;
7000
+ exports$1.INSPECT_MAX_BYTES = 50;
6979
7001
 
6980
7002
  var K_MAX_LENGTH = 0x7fffffff;
6981
- exports.kMaxLength = K_MAX_LENGTH;
7003
+ exports$1.kMaxLength = K_MAX_LENGTH;
6982
7004
 
6983
7005
  /**
6984
7006
  * If `Buffer.TYPED_ARRAY_SUPPORT`:
@@ -7575,7 +7597,7 @@ function requireBuffer () {
7575
7597
 
7576
7598
  Buffer.prototype.inspect = function inspect () {
7577
7599
  var str = '';
7578
- var max = exports.INSPECT_MAX_BYTES;
7600
+ var max = exports$1.INSPECT_MAX_BYTES;
7579
7601
  str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim();
7580
7602
  if (this.length > max) str += ' ... ';
7581
7603
  return '<Buffer ' + str + '>'
@@ -8788,7 +8810,7 @@ var hasRequiredFrames;
8788
8810
  function requireFrames () {
8789
8811
  if (hasRequiredFrames) return Frames;
8790
8812
  hasRequiredFrames = 1;
8791
- (function (exports) {
8813
+ (function (exports$1) {
8792
8814
  /*
8793
8815
  * Copyright 2021-2022 the original author or authors.
8794
8816
  *
@@ -8804,8 +8826,8 @@ function requireFrames () {
8804
8826
  * See the License for the specific language governing permissions and
8805
8827
  * limitations under the License.
8806
8828
  */
8807
- Object.defineProperty(exports, "__esModule", { value: true });
8808
- exports.Frame = exports.Lengths = exports.Flags = exports.FrameTypes = void 0;
8829
+ Object.defineProperty(exports$1, "__esModule", { value: true });
8830
+ exports$1.Frame = exports$1.Lengths = exports$1.Flags = exports$1.FrameTypes = void 0;
8809
8831
  var FrameTypes;
8810
8832
  (function (FrameTypes) {
8811
8833
  FrameTypes[FrameTypes["RESERVED"] = 0] = "RESERVED";
@@ -8824,7 +8846,7 @@ function requireFrames () {
8824
8846
  FrameTypes[FrameTypes["RESUME"] = 13] = "RESUME";
8825
8847
  FrameTypes[FrameTypes["RESUME_OK"] = 14] = "RESUME_OK";
8826
8848
  FrameTypes[FrameTypes["EXT"] = 63] = "EXT";
8827
- })(FrameTypes = exports.FrameTypes || (exports.FrameTypes = {}));
8849
+ })(FrameTypes = exports$1.FrameTypes || (exports$1.FrameTypes = {}));
8828
8850
  (function (Flags) {
8829
8851
  Flags[Flags["NONE"] = 0] = "NONE";
8830
8852
  Flags[Flags["COMPLETE"] = 64] = "COMPLETE";
@@ -8835,7 +8857,7 @@ function requireFrames () {
8835
8857
  Flags[Flags["NEXT"] = 32] = "NEXT";
8836
8858
  Flags[Flags["RESPOND"] = 128] = "RESPOND";
8837
8859
  Flags[Flags["RESUME_ENABLE"] = 128] = "RESUME_ENABLE";
8838
- })(exports.Flags || (exports.Flags = {}));
8860
+ })(exports$1.Flags || (exports$1.Flags = {}));
8839
8861
  (function (Flags) {
8840
8862
  function hasMetadata(flags) {
8841
8863
  return (flags & Flags.METADATA) === Flags.METADATA;
@@ -8869,13 +8891,13 @@ function requireFrames () {
8869
8891
  return (flags & Flags.RESUME_ENABLE) === Flags.RESUME_ENABLE;
8870
8892
  }
8871
8893
  Flags.hasResume = hasResume;
8872
- })(exports.Flags || (exports.Flags = {}));
8894
+ })(exports$1.Flags || (exports$1.Flags = {}));
8873
8895
  (function (Lengths) {
8874
8896
  Lengths[Lengths["FRAME"] = 3] = "FRAME";
8875
8897
  Lengths[Lengths["HEADER"] = 6] = "HEADER";
8876
8898
  Lengths[Lengths["METADATA"] = 3] = "METADATA";
8877
8899
  Lengths[Lengths["REQUEST"] = 3] = "REQUEST";
8878
- })(exports.Lengths || (exports.Lengths = {}));
8900
+ })(exports$1.Lengths || (exports$1.Lengths = {}));
8879
8901
  (function (Frame) {
8880
8902
  function isConnection(frame) {
8881
8903
  return frame.streamId === 0;
@@ -8886,7 +8908,7 @@ function requireFrames () {
8886
8908
  frame.type <= FrameTypes.REQUEST_CHANNEL);
8887
8909
  }
8888
8910
  Frame.isRequest = isRequest;
8889
- })(exports.Frame || (exports.Frame = {}));
8911
+ })(exports$1.Frame || (exports$1.Frame = {}));
8890
8912
 
8891
8913
  } (Frames));
8892
8914
  return Frames;
@@ -8897,7 +8919,7 @@ var hasRequiredCodecs;
8897
8919
  function requireCodecs () {
8898
8920
  if (hasRequiredCodecs) return Codecs;
8899
8921
  hasRequiredCodecs = 1;
8900
- (function (exports) {
8922
+ (function (exports$1) {
8901
8923
  var __generator = (Codecs && Codecs.__generator) || function (thisArg, body) {
8902
8924
  var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
8903
8925
  return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
@@ -8925,22 +8947,22 @@ function requireCodecs () {
8925
8947
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
8926
8948
  }
8927
8949
  };
8928
- Object.defineProperty(exports, "__esModule", { value: true });
8929
- exports.Deserializer = exports.sizeOfFrame = exports.serializeFrame = exports.deserializeFrame = exports.serializeFrameWithLength = exports.deserializeFrames = exports.deserializeFrameWithLength = exports.writeUInt64BE = exports.readUInt64BE = exports.writeUInt24BE = exports.readUInt24BE = exports.MAX_VERSION = exports.MAX_TTL = exports.MAX_STREAM_ID = exports.MAX_RESUME_LENGTH = exports.MAX_REQUEST_N = exports.MAX_REQUEST_COUNT = exports.MAX_MIME_LENGTH = exports.MAX_METADATA_LENGTH = exports.MAX_LIFETIME = exports.MAX_KEEPALIVE = exports.MAX_CODE = exports.FRAME_TYPE_OFFFSET = exports.FLAGS_MASK = void 0;
8950
+ Object.defineProperty(exports$1, "__esModule", { value: true });
8951
+ exports$1.Deserializer = exports$1.sizeOfFrame = exports$1.serializeFrame = exports$1.deserializeFrame = exports$1.serializeFrameWithLength = exports$1.deserializeFrames = exports$1.deserializeFrameWithLength = exports$1.writeUInt64BE = exports$1.readUInt64BE = exports$1.writeUInt24BE = exports$1.readUInt24BE = exports$1.MAX_VERSION = exports$1.MAX_TTL = exports$1.MAX_STREAM_ID = exports$1.MAX_RESUME_LENGTH = exports$1.MAX_REQUEST_N = exports$1.MAX_REQUEST_COUNT = exports$1.MAX_MIME_LENGTH = exports$1.MAX_METADATA_LENGTH = exports$1.MAX_LIFETIME = exports$1.MAX_KEEPALIVE = exports$1.MAX_CODE = exports$1.FRAME_TYPE_OFFFSET = exports$1.FLAGS_MASK = void 0;
8930
8952
  var Frames_1 = requireFrames();
8931
- exports.FLAGS_MASK = 0x3ff; // low 10 bits
8932
- exports.FRAME_TYPE_OFFFSET = 10; // frame type is offset 10 bytes within the uint16 containing type + flags
8933
- exports.MAX_CODE = 0x7fffffff; // uint31
8934
- exports.MAX_KEEPALIVE = 0x7fffffff; // uint31
8935
- exports.MAX_LIFETIME = 0x7fffffff; // uint31
8936
- exports.MAX_METADATA_LENGTH = 0xffffff; // uint24
8937
- exports.MAX_MIME_LENGTH = 0xff; // int8
8938
- exports.MAX_REQUEST_COUNT = 0x7fffffff; // uint31
8939
- exports.MAX_REQUEST_N = 0x7fffffff; // uint31
8940
- exports.MAX_RESUME_LENGTH = 0xffff; // uint16
8941
- exports.MAX_STREAM_ID = 0x7fffffff; // uint31
8942
- exports.MAX_TTL = 0x7fffffff; // uint31
8943
- exports.MAX_VERSION = 0xffff; // uint16
8953
+ exports$1.FLAGS_MASK = 0x3ff; // low 10 bits
8954
+ exports$1.FRAME_TYPE_OFFFSET = 10; // frame type is offset 10 bytes within the uint16 containing type + flags
8955
+ exports$1.MAX_CODE = 0x7fffffff; // uint31
8956
+ exports$1.MAX_KEEPALIVE = 0x7fffffff; // uint31
8957
+ exports$1.MAX_LIFETIME = 0x7fffffff; // uint31
8958
+ exports$1.MAX_METADATA_LENGTH = 0xffffff; // uint24
8959
+ exports$1.MAX_MIME_LENGTH = 0xff; // int8
8960
+ exports$1.MAX_REQUEST_COUNT = 0x7fffffff; // uint31
8961
+ exports$1.MAX_REQUEST_N = 0x7fffffff; // uint31
8962
+ exports$1.MAX_RESUME_LENGTH = 0xffff; // uint16
8963
+ exports$1.MAX_STREAM_ID = 0x7fffffff; // uint31
8964
+ exports$1.MAX_TTL = 0x7fffffff; // uint31
8965
+ exports$1.MAX_VERSION = 0xffff; // uint16
8944
8966
  /**
8945
8967
  * Mimimum value that would overflow bitwise operators (2^32).
8946
8968
  */
@@ -8954,7 +8976,7 @@ function requireCodecs () {
8954
8976
  var val3 = buffer.readUInt8(offset + 2);
8955
8977
  return val1 | val2 | val3;
8956
8978
  }
8957
- exports.readUInt24BE = readUInt24BE;
8979
+ exports$1.readUInt24BE = readUInt24BE;
8958
8980
  /**
8959
8981
  * Writes a uint24 to a buffer starting at the given offset, returning the
8960
8982
  * offset of the next byte.
@@ -8964,7 +8986,7 @@ function requireCodecs () {
8964
8986
  offset = buffer.writeUInt8((value >>> 8) & 0xff, offset); // 2nd byte
8965
8987
  return buffer.writeUInt8(value & 0xff, offset); // 1st byte
8966
8988
  }
8967
- exports.writeUInt24BE = writeUInt24BE;
8989
+ exports$1.writeUInt24BE = writeUInt24BE;
8968
8990
  /**
8969
8991
  * Read a uint64 (technically supports up to 53 bits per JS number
8970
8992
  * representation).
@@ -8974,7 +8996,7 @@ function requireCodecs () {
8974
8996
  var low = buffer.readUInt32BE(offset + 4);
8975
8997
  return high * BITWISE_OVERFLOW + low;
8976
8998
  }
8977
- exports.readUInt64BE = readUInt64BE;
8999
+ exports$1.readUInt64BE = readUInt64BE;
8978
9000
  /**
8979
9001
  * Write a uint64 (technically supports up to 53 bits per JS number
8980
9002
  * representation).
@@ -8985,7 +9007,7 @@ function requireCodecs () {
8985
9007
  offset = buffer.writeUInt32BE(high, offset); // first half of uint64
8986
9008
  return buffer.writeUInt32BE(low, offset); // second half of uint64
8987
9009
  }
8988
- exports.writeUInt64BE = writeUInt64BE;
9010
+ exports$1.writeUInt64BE = writeUInt64BE;
8989
9011
  /**
8990
9012
  * Frame header is:
8991
9013
  * - stream id (uint32 = 4)
@@ -9003,7 +9025,7 @@ function requireCodecs () {
9003
9025
  var frameLength = readUInt24BE(buffer, 0);
9004
9026
  return deserializeFrame(buffer.slice(UINT24_SIZE, UINT24_SIZE + frameLength));
9005
9027
  }
9006
- exports.deserializeFrameWithLength = deserializeFrameWithLength;
9028
+ exports$1.deserializeFrameWithLength = deserializeFrameWithLength;
9007
9029
  /**
9008
9030
  * Given a buffer that may contain zero or more length-prefixed frames followed
9009
9031
  * by zero or more bytes of a (partial) subsequent frame, returns an array of
@@ -9036,7 +9058,7 @@ function requireCodecs () {
9036
9058
  }
9037
9059
  });
9038
9060
  }
9039
- exports.deserializeFrames = deserializeFrames;
9061
+ exports$1.deserializeFrames = deserializeFrames;
9040
9062
  /**
9041
9063
  * Writes a frame to a buffer with a length prefix.
9042
9064
  */
@@ -9047,7 +9069,7 @@ function requireCodecs () {
9047
9069
  buffer.copy(lengthPrefixed, UINT24_SIZE);
9048
9070
  return lengthPrefixed;
9049
9071
  }
9050
- exports.serializeFrameWithLength = serializeFrameWithLength;
9072
+ exports$1.serializeFrameWithLength = serializeFrameWithLength;
9051
9073
  /**
9052
9074
  * Read a frame from the buffer.
9053
9075
  */
@@ -9062,8 +9084,8 @@ function requireCodecs () {
9062
9084
  // );
9063
9085
  var typeAndFlags = buffer.readUInt16BE(offset);
9064
9086
  offset += 2;
9065
- var type = typeAndFlags >>> exports.FRAME_TYPE_OFFFSET; // keep highest 6 bits
9066
- var flags = typeAndFlags & exports.FLAGS_MASK; // keep lowest 10 bits
9087
+ var type = typeAndFlags >>> exports$1.FRAME_TYPE_OFFFSET; // keep highest 6 bits
9088
+ var flags = typeAndFlags & exports$1.FLAGS_MASK; // keep lowest 10 bits
9067
9089
  switch (type) {
9068
9090
  case Frames_1.FrameTypes.SETUP:
9069
9091
  return deserializeSetupFrame(buffer, streamId, flags);
@@ -9100,7 +9122,7 @@ function requireCodecs () {
9100
9122
  // );
9101
9123
  }
9102
9124
  }
9103
- exports.deserializeFrame = deserializeFrame;
9125
+ exports$1.deserializeFrame = deserializeFrame;
9104
9126
  /**
9105
9127
  * Convert the frame to a (binary) buffer.
9106
9128
  */
@@ -9139,7 +9161,7 @@ function requireCodecs () {
9139
9161
  // );
9140
9162
  }
9141
9163
  }
9142
- exports.serializeFrame = serializeFrame;
9164
+ exports$1.serializeFrame = serializeFrame;
9143
9165
  /**
9144
9166
  * Byte size of frame without size prefix
9145
9167
  */
@@ -9178,7 +9200,7 @@ function requireCodecs () {
9178
9200
  // );
9179
9201
  }
9180
9202
  }
9181
- exports.sizeOfFrame = sizeOfFrame;
9203
+ exports$1.sizeOfFrame = sizeOfFrame;
9182
9204
  /**
9183
9205
  * Writes a SETUP frame into a new buffer and returns it.
9184
9206
  *
@@ -9813,7 +9835,7 @@ function requireCodecs () {
9813
9835
  function writeHeader(frame, buffer) {
9814
9836
  var offset = buffer.writeInt32BE(frame.streamId, 0);
9815
9837
  // shift frame to high 6 bits, extract lowest 10 bits from flags
9816
- return buffer.writeUInt16BE((frame.type << exports.FRAME_TYPE_OFFFSET) | (frame.flags & exports.FLAGS_MASK), offset);
9838
+ return buffer.writeUInt16BE((frame.type << exports$1.FRAME_TYPE_OFFFSET) | (frame.flags & exports$1.FLAGS_MASK), offset);
9817
9839
  }
9818
9840
  /**
9819
9841
  * Determine the length of the payload section of a frame. Only applies to
@@ -9894,7 +9916,7 @@ function requireCodecs () {
9894
9916
  };
9895
9917
  return Deserializer;
9896
9918
  }());
9897
- exports.Deserializer = Deserializer;
9919
+ exports$1.Deserializer = Deserializer;
9898
9920
 
9899
9921
  } (Codecs));
9900
9922
  return Codecs;
@@ -10040,7 +10062,7 @@ var hasRequiredErrors;
10040
10062
  function requireErrors () {
10041
10063
  if (hasRequiredErrors) return Errors;
10042
10064
  hasRequiredErrors = 1;
10043
- (function (exports) {
10065
+ (function (exports$1) {
10044
10066
  /*
10045
10067
  * Copyright 2021-2022 the original author or authors.
10046
10068
  *
@@ -10071,8 +10093,8 @@ function requireErrors () {
10071
10093
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10072
10094
  };
10073
10095
  })();
10074
- Object.defineProperty(exports, "__esModule", { value: true });
10075
- exports.ErrorCodes = exports.RSocketError = void 0;
10096
+ Object.defineProperty(exports$1, "__esModule", { value: true });
10097
+ exports$1.ErrorCodes = exports$1.RSocketError = void 0;
10076
10098
  var RSocketError = /** @class */ (function (_super) {
10077
10099
  __extends(RSocketError, _super);
10078
10100
  function RSocketError(code, message) {
@@ -10082,7 +10104,7 @@ function requireErrors () {
10082
10104
  }
10083
10105
  return RSocketError;
10084
10106
  }(Error));
10085
- exports.RSocketError = RSocketError;
10107
+ exports$1.RSocketError = RSocketError;
10086
10108
  (function (ErrorCodes) {
10087
10109
  ErrorCodes[ErrorCodes["RESERVED"] = 0] = "RESERVED";
10088
10110
  ErrorCodes[ErrorCodes["INVALID_SETUP"] = 1] = "INVALID_SETUP";
@@ -10096,7 +10118,7 @@ function requireErrors () {
10096
10118
  ErrorCodes[ErrorCodes["CANCELED"] = 515] = "CANCELED";
10097
10119
  ErrorCodes[ErrorCodes["INVALID"] = 516] = "INVALID";
10098
10120
  ErrorCodes[ErrorCodes["RESERVED_EXTENSION"] = 4294967295] = "RESERVED_EXTENSION";
10099
- })(exports.ErrorCodes || (exports.ErrorCodes = {}));
10121
+ })(exports$1.ErrorCodes || (exports$1.ErrorCodes = {}));
10100
10122
 
10101
10123
  } (Errors));
10102
10124
  return Errors;
@@ -10138,7 +10160,7 @@ var hasRequiredClientServerMultiplexerDemultiplexer;
10138
10160
  function requireClientServerMultiplexerDemultiplexer () {
10139
10161
  if (hasRequiredClientServerMultiplexerDemultiplexer) return ClientServerMultiplexerDemultiplexer;
10140
10162
  hasRequiredClientServerMultiplexerDemultiplexer = 1;
10141
- (function (exports) {
10163
+ (function (exports$1) {
10142
10164
  /*
10143
10165
  * Copyright 2021-2022 the original author or authors.
10144
10166
  *
@@ -10205,8 +10227,8 @@ function requireClientServerMultiplexerDemultiplexer () {
10205
10227
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
10206
10228
  }
10207
10229
  };
10208
- Object.defineProperty(exports, "__esModule", { value: true });
10209
- exports.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = exports.ResumableClientServerInputMultiplexerDemultiplexer = exports.ClientServerInputMultiplexerDemultiplexer = exports.StreamIdGenerator = void 0;
10230
+ Object.defineProperty(exports$1, "__esModule", { value: true });
10231
+ exports$1.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = exports$1.ResumableClientServerInputMultiplexerDemultiplexer = exports$1.ClientServerInputMultiplexerDemultiplexer = exports$1.StreamIdGenerator = void 0;
10210
10232
  var _1 = requireDist();
10211
10233
  var Deferred_1 = requireDeferred();
10212
10234
  var Errors_1 = requireErrors();
@@ -10229,7 +10251,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10229
10251
  };
10230
10252
  return StreamIdGeneratorImpl;
10231
10253
  }());
10232
- })(exports.StreamIdGenerator || (exports.StreamIdGenerator = {}));
10254
+ })(exports$1.StreamIdGenerator || (exports$1.StreamIdGenerator = {}));
10233
10255
  var ClientServerInputMultiplexerDemultiplexer = /** @class */ (function (_super) {
10234
10256
  __extends(ClientServerInputMultiplexerDemultiplexer, _super);
10235
10257
  function ClientServerInputMultiplexerDemultiplexer(streamIdSupplier, outbound, closeable) {
@@ -10318,7 +10340,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10318
10340
  };
10319
10341
  return ClientServerInputMultiplexerDemultiplexer;
10320
10342
  }(Deferred_1.Deferred));
10321
- exports.ClientServerInputMultiplexerDemultiplexer = ClientServerInputMultiplexerDemultiplexer;
10343
+ exports$1.ClientServerInputMultiplexerDemultiplexer = ClientServerInputMultiplexerDemultiplexer;
10322
10344
  var ResumableClientServerInputMultiplexerDemultiplexer = /** @class */ (function (_super) {
10323
10345
  __extends(ResumableClientServerInputMultiplexerDemultiplexer, _super);
10324
10346
  function ResumableClientServerInputMultiplexerDemultiplexer(streamIdSupplier, outbound, closeable, frameStore, token, sessionStoreOrReconnector, sessionTimeout) {
@@ -10475,7 +10497,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10475
10497
  };
10476
10498
  return ResumableClientServerInputMultiplexerDemultiplexer;
10477
10499
  }(ClientServerInputMultiplexerDemultiplexer));
10478
- exports.ResumableClientServerInputMultiplexerDemultiplexer = ResumableClientServerInputMultiplexerDemultiplexer;
10500
+ exports$1.ResumableClientServerInputMultiplexerDemultiplexer = ResumableClientServerInputMultiplexerDemultiplexer;
10479
10501
  var ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = /** @class */ (function () {
10480
10502
  function ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer(outbound, closeable, delegate) {
10481
10503
  this.outbound = outbound;
@@ -10532,7 +10554,7 @@ function requireClientServerMultiplexerDemultiplexer () {
10532
10554
  };
10533
10555
  return ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer;
10534
10556
  }());
10535
- exports.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer;
10557
+ exports$1.ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer = ResumeOkAwaitingResumableClientServerInputMultiplexerDemultiplexer;
10536
10558
 
10537
10559
  } (ClientServerMultiplexerDemultiplexer));
10538
10560
  return ClientServerMultiplexerDemultiplexer;
@@ -13518,7 +13540,7 @@ var hasRequiredDist;
13518
13540
  function requireDist () {
13519
13541
  if (hasRequiredDist) return dist;
13520
13542
  hasRequiredDist = 1;
13521
- (function (exports) {
13543
+ (function (exports$1) {
13522
13544
  /*
13523
13545
  * Copyright 2021-2022 the original author or authors.
13524
13546
  *
@@ -13541,19 +13563,19 @@ function requireDist () {
13541
13563
  if (k2 === undefined) k2 = k;
13542
13564
  o[k2] = m[k];
13543
13565
  }));
13544
- var __exportStar = (dist && dist.__exportStar) || function(m, exports) {
13545
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
13566
+ var __exportStar = (dist && dist.__exportStar) || function(m, exports$1) {
13567
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p);
13546
13568
  };
13547
- Object.defineProperty(exports, "__esModule", { value: true });
13548
- __exportStar(requireCodecs(), exports);
13549
- __exportStar(requireCommon(), exports);
13550
- __exportStar(requireDeferred(), exports);
13551
- __exportStar(requireErrors(), exports);
13552
- __exportStar(requireFrames(), exports);
13553
- __exportStar(requireRSocket(), exports);
13554
- __exportStar(requireRSocketConnector(), exports);
13555
- __exportStar(requireRSocketServer(), exports);
13556
- __exportStar(requireTransport(), exports);
13569
+ Object.defineProperty(exports$1, "__esModule", { value: true });
13570
+ __exportStar(requireCodecs(), exports$1);
13571
+ __exportStar(requireCommon(), exports$1);
13572
+ __exportStar(requireDeferred(), exports$1);
13573
+ __exportStar(requireErrors(), exports$1);
13574
+ __exportStar(requireFrames(), exports$1);
13575
+ __exportStar(requireRSocket(), exports$1);
13576
+ __exportStar(requireRSocketConnector(), exports$1);
13577
+ __exportStar(requireRSocketServer(), exports$1);
13578
+ __exportStar(requireTransport(), exports$1);
13557
13579
 
13558
13580
  } (dist));
13559
13581
  return dist;
@@ -13561,7 +13583,7 @@ function requireDist () {
13561
13583
 
13562
13584
  var distExports = requireDist();
13563
13585
 
13564
- var version = "1.43.1";
13586
+ var version = "1.45.0";
13565
13587
  var PACKAGE = {
13566
13588
  version: version};
13567
13589
 
@@ -14488,6 +14510,7 @@ const DEFAULT_STREAMING_SYNC_OPTIONS = {
14488
14510
  crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
14489
14511
  };
14490
14512
  const DEFAULT_STREAM_CONNECTION_OPTIONS = {
14513
+ appMetadata: {},
14491
14514
  connectionMethod: SyncStreamConnectionMethod.WEB_SOCKET,
14492
14515
  clientImplementation: DEFAULT_SYNC_CLIENT_IMPLEMENTATION,
14493
14516
  fetchStrategy: FetchStrategy.Buffered,
@@ -14866,6 +14889,11 @@ The next upload iteration will be delayed.`);
14866
14889
  ...DEFAULT_STREAM_CONNECTION_OPTIONS,
14867
14890
  ...(options ?? {})
14868
14891
  };
14892
+ // Validate app metadata
14893
+ const invalidMetadata = Object.entries(resolvedOptions.appMetadata).filter(([_, value]) => typeof value != 'string');
14894
+ if (invalidMetadata.length > 0) {
14895
+ throw new Error(`Invalid appMetadata provided. Only string values are allowed. Invalid values: ${invalidMetadata.map(([key, value]) => `${key}: ${value}`).join(', ')}`);
14896
+ }
14869
14897
  const clientImplementation = resolvedOptions.clientImplementation;
14870
14898
  this.updateSyncStatus({ clientImplementation });
14871
14899
  if (clientImplementation == SyncClientImplementation.JAVASCRIPT) {
@@ -14901,6 +14929,7 @@ The next upload iteration will be delayed.`);
14901
14929
  include_checksum: true,
14902
14930
  raw_data: true,
14903
14931
  parameters: resolvedOptions.params,
14932
+ app_metadata: resolvedOptions.appMetadata,
14904
14933
  client_id: clientId
14905
14934
  }
14906
14935
  };
@@ -15260,6 +15289,7 @@ The next upload iteration will be delayed.`);
15260
15289
  try {
15261
15290
  const options = {
15262
15291
  parameters: resolvedOptions.params,
15292
+ app_metadata: resolvedOptions.appMetadata,
15263
15293
  active_streams: this.activeStreams,
15264
15294
  include_defaults: resolvedOptions.includeDefaultStreams
15265
15295
  };
@@ -15918,11 +15948,11 @@ class AbstractPowerSyncDatabase extends BaseObserver {
15918
15948
  .map((n) => parseInt(n));
15919
15949
  }
15920
15950
  catch (e) {
15921
- throw new Error(`Unsupported powersync extension version. Need >=0.4.5 <1.0.0, got: ${this.sdkVersion}. Details: ${e.message}`);
15951
+ throw new Error(`Unsupported powersync extension version. Need >=0.4.10 <1.0.0, got: ${this.sdkVersion}. Details: ${e.message}`);
15922
15952
  }
15923
- // Validate >=0.4.5 <1.0.0
15924
- if (versionInts[0] != 0 || versionInts[1] < 4 || (versionInts[1] == 4 && versionInts[2] < 5)) {
15925
- throw new Error(`Unsupported powersync extension version. Need >=0.4.5 <1.0.0, got: ${this.sdkVersion}`);
15953
+ // Validate >=0.4.10 <1.0.0
15954
+ if (versionInts[0] != 0 || versionInts[1] < 4 || (versionInts[1] == 4 && versionInts[2] < 10)) {
15955
+ throw new Error(`Unsupported powersync extension version. Need >=0.4.10 <1.0.0, got: ${this.sdkVersion}`);
15926
15956
  }
15927
15957
  }
15928
15958
  async resolveOfflineSyncStatus() {
@@ -17042,6 +17072,27 @@ class SyncDataBatch {
17042
17072
  }
17043
17073
  }
17044
17074
 
17075
+ /**
17076
+ * Thrown when an underlying database connection is closed.
17077
+ * This is particularly relevant when worker connections are marked as closed while
17078
+ * operations are still in progress.
17079
+ */
17080
+ class ConnectionClosedError extends Error {
17081
+ static NAME = 'ConnectionClosedError';
17082
+ static MATCHES(input) {
17083
+ /**
17084
+ * If there are weird package issues which cause multiple versions of classes to be present, the instanceof
17085
+ * check might fail. This also performs a failsafe check.
17086
+ * This might also happen if the Error is serialized and parsed over a bridging channel like a MessagePort.
17087
+ */
17088
+ return (input instanceof ConnectionClosedError || (input instanceof Error && input.name == ConnectionClosedError.NAME));
17089
+ }
17090
+ constructor(message) {
17091
+ super(message);
17092
+ this.name = ConnectionClosedError.NAME;
17093
+ }
17094
+ }
17095
+
17045
17096
  // https://www.sqlite.org/lang_expr.html#castexpr
17046
17097
  var ColumnType;
17047
17098
  (function (ColumnType) {
@@ -17600,20 +17651,20 @@ const parseQuery = (query, parameters) => {
17600
17651
  //# sourceMappingURL=bundle.mjs.map
17601
17652
 
17602
17653
 
17603
- /***/ }),
17654
+ /***/ },
17604
17655
 
17605
- /***/ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js":
17656
+ /***/ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js"
17606
17657
  /*!***********************************************************!*\
17607
17658
  !*** ./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js ***!
17608
17659
  \***********************************************************/
17609
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
17660
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
17610
17661
 
17611
17662
  __webpack_require__.r(__webpack_exports__);
17612
17663
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17613
17664
  /* harmony export */ LockedAsyncDatabaseAdapter: () => (/* binding */ LockedAsyncDatabaseAdapter)
17614
17665
  /* harmony export */ });
17615
17666
  /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
17616
- /* harmony import */ var _shared_navigator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../..//shared/navigator */ "./lib/src/shared/navigator.js");
17667
+ /* harmony import */ var _shared_navigator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/navigator */ "./lib/src/shared/navigator.js");
17617
17668
  /* harmony import */ var _WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./WorkerWrappedAsyncDatabaseConnection */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
17618
17669
  /* harmony import */ var _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./wa-sqlite/WASQLiteConnection */ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js");
17619
17670
 
@@ -17637,6 +17688,7 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17637
17688
  _config = null;
17638
17689
  pendingAbortControllers;
17639
17690
  requiresHolds;
17691
+ databaseOpenPromise = null;
17640
17692
  closing;
17641
17693
  closed;
17642
17694
  constructor(options) {
@@ -17686,16 +17738,69 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17686
17738
  async init() {
17687
17739
  return this.initPromise;
17688
17740
  }
17741
+ async openInternalDB() {
17742
+ /**
17743
+ * Execute opening of the db in a lock in order not to interfere with other operations.
17744
+ */
17745
+ return this._acquireLock(async () => {
17746
+ // Dispose any previous table change listener.
17747
+ this._disposeTableChangeListener?.();
17748
+ this._disposeTableChangeListener = null;
17749
+ this._db?.close().catch((ex) => this.logger.warn(`Error closing database before opening new instance`, ex));
17750
+ const isReOpen = !!this._db;
17751
+ this._db = null;
17752
+ this._db = await this.options.openConnection();
17753
+ await this._db.init();
17754
+ this._config = await this._db.getConfig();
17755
+ await this.registerOnChangeListener(this._db);
17756
+ if (isReOpen) {
17757
+ this.iterateListeners((cb) => cb.databaseReOpened?.());
17758
+ }
17759
+ /**
17760
+ * This is only required for the long-lived shared IndexedDB connections.
17761
+ */
17762
+ this.requiresHolds = this._config.vfs == _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_3__.WASQLiteVFS.IDBBatchAtomicVFS;
17763
+ });
17764
+ }
17765
+ _reOpen() {
17766
+ this.databaseOpenPromise = this.openInternalDB().finally(() => {
17767
+ this.databaseOpenPromise = null;
17768
+ });
17769
+ return this.databaseOpenPromise;
17770
+ }
17771
+ /**
17772
+ * Re-opens the underlying database.
17773
+ * Returns a pending operation if one is already in progress.
17774
+ */
17775
+ async reOpenInternalDB() {
17776
+ if (!this.options.reOpenOnConnectionClosed) {
17777
+ throw new Error(`Cannot re-open underlying database, reOpenOnConnectionClosed is not enabled`);
17778
+ }
17779
+ if (this.databaseOpenPromise) {
17780
+ return this.databaseOpenPromise;
17781
+ }
17782
+ return this._reOpen();
17783
+ }
17689
17784
  async _init() {
17690
- this._db = await this.options.openConnection();
17691
- await this._db.init();
17692
- this._config = await this._db.getConfig();
17693
- await this.registerOnChangeListener(this._db);
17694
- this.iterateListeners((cb) => cb.initialized?.());
17695
17785
  /**
17696
- * This is only required for the long-lived shared IndexedDB connections.
17786
+ * For OPFS, we can see this open call sometimes fail due to NoModificationAllowedError.
17787
+ * We should be able to recover from this by re-opening the database.
17697
17788
  */
17698
- this.requiresHolds = this._config.vfs == _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_3__.WASQLiteVFS.IDBBatchAtomicVFS;
17789
+ const maxAttempts = 3;
17790
+ for (let count = 0; count < maxAttempts; count++) {
17791
+ try {
17792
+ await this.openInternalDB();
17793
+ break;
17794
+ }
17795
+ catch (ex) {
17796
+ if (count == maxAttempts - 1) {
17797
+ throw ex;
17798
+ }
17799
+ this.logger.warn(`Attempt ${count + 1} of ${maxAttempts} to open database failed, retrying in 1 second...`, ex);
17800
+ await new Promise((resolve) => setTimeout(resolve, 1000));
17801
+ }
17802
+ }
17803
+ this.iterateListeners((cb) => cb.initialized?.());
17699
17804
  }
17700
17805
  getConfiguration() {
17701
17806
  if (!this._config) {
@@ -17742,7 +17847,14 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17742
17847
  */
17743
17848
  async close() {
17744
17849
  this.closing = true;
17745
- this._disposeTableChangeListener?.();
17850
+ /**
17851
+ * Note that we obtain a reference to the callback to avoid calling the callback with `this` as the context.
17852
+ * This is to avoid Comlink attempting to clone `this` when calling the method.
17853
+ */
17854
+ const dispose = this._disposeTableChangeListener;
17855
+ if (dispose) {
17856
+ dispose();
17857
+ }
17746
17858
  this.pendingAbortControllers.forEach((controller) => controller.abort('Closed'));
17747
17859
  await this.baseDB?.close?.();
17748
17860
  this.closed = true;
@@ -17762,24 +17874,23 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17762
17874
  async readLock(fn, options) {
17763
17875
  await this.waitForInitialized();
17764
17876
  return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
17765
- timeoutMs: options?.timeoutMs
17877
+ timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
17766
17878
  });
17767
17879
  }
17768
17880
  async writeLock(fn, options) {
17769
17881
  await this.waitForInitialized();
17770
17882
  return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
17771
- timeoutMs: options?.timeoutMs
17883
+ timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
17772
17884
  });
17773
17885
  }
17774
- async acquireLock(callback, options) {
17775
- await this.waitForInitialized();
17886
+ async _acquireLock(callback, options) {
17776
17887
  if (this.closing) {
17777
17888
  throw new Error(`Cannot acquire lock, the database is closing`);
17778
17889
  }
17779
17890
  const abortController = new AbortController();
17780
17891
  this.pendingAbortControllers.add(abortController);
17781
17892
  const { timeoutMs } = options ?? {};
17782
- const timoutId = timeoutMs
17893
+ const timeoutId = timeoutMs
17783
17894
  ? setTimeout(() => {
17784
17895
  abortController.abort(`Timeout after ${timeoutMs}ms`);
17785
17896
  this.pendingAbortControllers.delete(abortController);
@@ -17787,19 +17898,49 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17787
17898
  : null;
17788
17899
  return (0,_shared_navigator__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(`db-lock-${this._dbIdentifier}`, { signal: abortController.signal }, async () => {
17789
17900
  this.pendingAbortControllers.delete(abortController);
17790
- if (timoutId) {
17791
- clearTimeout(timoutId);
17901
+ if (timeoutId) {
17902
+ clearTimeout(timeoutId);
17792
17903
  }
17793
- const holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
17904
+ return await callback();
17905
+ });
17906
+ }
17907
+ async acquireLock(callback, options) {
17908
+ await this.waitForInitialized();
17909
+ // The database is being opened in the background. Wait for it here.
17910
+ if (this.databaseOpenPromise) {
17911
+ await this.databaseOpenPromise;
17912
+ }
17913
+ return this._acquireLock(async () => {
17914
+ let holdId = null;
17794
17915
  try {
17916
+ /**
17917
+ * We can't await this since it uses the same lock as we're in now.
17918
+ * If there is a pending open, this call will throw.
17919
+ * If there is no pending open, but there is also no database - the open
17920
+ * might have failed. We need to re-open the database.
17921
+ */
17922
+ if (this.databaseOpenPromise || !this._db) {
17923
+ throw new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Connection is busy re-opening');
17924
+ }
17925
+ holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
17795
17926
  return await callback();
17796
17927
  }
17928
+ catch (ex) {
17929
+ if (_powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError.MATCHES(ex)) {
17930
+ if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
17931
+ // Immediately re-open the database. We need to miss as little table updates as possible.
17932
+ // Note, don't await this since it uses the same lock as we're in now.
17933
+ this.reOpenInternalDB();
17934
+ }
17935
+ }
17936
+ throw ex;
17937
+ }
17797
17938
  finally {
17798
17939
  if (holdId) {
17799
17940
  await this.baseDB.releaseHold(holdId);
17800
17941
  }
17801
17942
  }
17802
- });
17943
+ }, options);
17803
17944
  }
17804
17945
  async readTransaction(fn, options) {
17805
17946
  return this.readLock(this.wrapTransaction(fn));
@@ -17914,29 +18055,32 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
17914
18055
  }
17915
18056
 
17916
18057
 
17917
- /***/ }),
18058
+ /***/ },
17918
18059
 
17919
- /***/ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js":
18060
+ /***/ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js"
17920
18061
  /*!*********************************************************************!*\
17921
18062
  !*** ./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js ***!
17922
18063
  \*********************************************************************/
17923
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18064
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
17924
18065
 
17925
18066
  __webpack_require__.r(__webpack_exports__);
17926
18067
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17927
18068
  /* harmony export */ WorkerWrappedAsyncDatabaseConnection: () => (/* binding */ WorkerWrappedAsyncDatabaseConnection)
17928
18069
  /* harmony export */ });
17929
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18070
+ /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
18071
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18072
+
17930
18073
 
17931
18074
  /**
17932
18075
  * Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
17933
18076
  * functions for worker listeners.
17934
18077
  */
17935
- class WorkerWrappedAsyncDatabaseConnection {
18078
+ class WorkerWrappedAsyncDatabaseConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.BaseObserver {
17936
18079
  options;
17937
18080
  lockAbortController = new AbortController();
17938
18081
  notifyRemoteClosed;
17939
18082
  constructor(options) {
18083
+ super();
17940
18084
  this.options = options;
17941
18085
  if (options.remoteCanCloseUnexpectedly) {
17942
18086
  this.notifyRemoteClosed = new AbortController();
@@ -17969,17 +18113,20 @@ class WorkerWrappedAsyncDatabaseConnection {
17969
18113
  isAutoCommit() {
17970
18114
  return this.withRemote(() => this.baseConnection.isAutoCommit());
17971
18115
  }
17972
- withRemote(workerPromise) {
18116
+ withRemote(workerPromise, fireActionOnAbort = false) {
17973
18117
  const controller = this.notifyRemoteClosed;
17974
18118
  if (controller) {
17975
18119
  return new Promise((resolve, reject) => {
17976
18120
  if (controller.signal.aborted) {
17977
- reject(new Error('Called operation on closed remote'));
17978
- // Don't run the operation if we're going to reject
17979
- return;
18121
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Called operation on closed remote'));
18122
+ if (!fireActionOnAbort) {
18123
+ // Don't run the operation if we're going to reject
18124
+ // We might want to fire-and-forget the operation in some cases (like a close operation)
18125
+ return;
18126
+ }
17980
18127
  }
17981
18128
  function handleAbort() {
17982
- reject(new Error('Remote peer closed with request in flight'));
18129
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionClosedError('Remote peer closed with request in flight'));
17983
18130
  }
17984
18131
  function completePromise(action) {
17985
18132
  controller.signal.removeEventListener('abort', handleAbort);
@@ -18033,7 +18180,7 @@ class WorkerWrappedAsyncDatabaseConnection {
18033
18180
  reject(ex);
18034
18181
  }
18035
18182
  }));
18036
- const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_0__.createEndpoint]();
18183
+ const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_1__.createEndpoint]();
18037
18184
  return { port: newPort, identifier };
18038
18185
  }
18039
18186
  /**
@@ -18041,17 +18188,19 @@ class WorkerWrappedAsyncDatabaseConnection {
18041
18188
  * This can be extended by custom implementations in order to handle proxy events.
18042
18189
  */
18043
18190
  async registerOnTableChange(callback) {
18044
- return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_0__.proxy(callback));
18191
+ return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_1__.proxy(callback));
18045
18192
  }
18046
18193
  async close() {
18047
18194
  // Abort any pending lock requests.
18048
18195
  this.lockAbortController.abort();
18049
18196
  try {
18050
- await this.withRemote(() => this.baseConnection.close());
18197
+ // fire and forget the close operation
18198
+ await this.withRemote(() => this.baseConnection.close(), true);
18051
18199
  }
18052
18200
  finally {
18053
- this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_0__.releaseProxy]();
18201
+ this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_1__.releaseProxy]();
18054
18202
  this.options.onClose?.();
18203
+ this.iterateListeners((l) => l.closing?.());
18055
18204
  }
18056
18205
  }
18057
18206
  execute(sql, params) {
@@ -18069,13 +18218,13 @@ class WorkerWrappedAsyncDatabaseConnection {
18069
18218
  }
18070
18219
 
18071
18220
 
18072
- /***/ }),
18221
+ /***/ },
18073
18222
 
18074
- /***/ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js":
18223
+ /***/ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js"
18075
18224
  /*!*************************************************************!*\
18076
18225
  !*** ./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js ***!
18077
18226
  \*************************************************************/
18078
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18227
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18079
18228
 
18080
18229
  __webpack_require__.r(__webpack_exports__);
18081
18230
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18174,9 +18323,10 @@ const DEFAULT_MODULE_FACTORIES = {
18174
18323
  }
18175
18324
  // @ts-expect-error The types for this static method are missing upstream
18176
18325
  const { OPFSCoopSyncVFS } = await __webpack_require__.e(/*! import() */ "node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js").then(__webpack_require__.bind(__webpack_require__, /*! @journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js */ "../../node_modules/@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js"));
18326
+ const vfs = await OPFSCoopSyncVFS.create(options.dbFileName, module);
18177
18327
  return {
18178
18328
  module,
18179
- vfs: await OPFSCoopSyncVFS.create(options.dbFileName, module)
18329
+ vfs
18180
18330
  };
18181
18331
  }
18182
18332
  };
@@ -18402,7 +18552,15 @@ class WASqliteConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_1__.
18402
18552
  }
18403
18553
  async close() {
18404
18554
  this.broadcastChannel?.close();
18405
- await this.sqliteAPI.close(this.dbP);
18555
+ await this.acquireExecuteLock(async () => {
18556
+ /**
18557
+ * Running the close operation inside the same execute mutex prevents errors like:
18558
+ * ```
18559
+ * unable to close due to unfinalized statements or unfinished backups
18560
+ * ```
18561
+ */
18562
+ await this.sqliteAPI.close(this.dbP);
18563
+ });
18406
18564
  }
18407
18565
  async registerOnTableChange(callback) {
18408
18566
  return this.registerListener({
@@ -18484,13 +18642,13 @@ class WASqliteConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_1__.
18484
18642
  }
18485
18643
 
18486
18644
 
18487
- /***/ }),
18645
+ /***/ },
18488
18646
 
18489
- /***/ "./lib/src/db/sync/WebRemote.js":
18647
+ /***/ "./lib/src/db/sync/WebRemote.js"
18490
18648
  /*!**************************************!*\
18491
18649
  !*** ./lib/src/db/sync/WebRemote.js ***!
18492
18650
  \**************************************/
18493
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18651
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18494
18652
 
18495
18653
  __webpack_require__.r(__webpack_exports__);
18496
18654
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18544,13 +18702,13 @@ class WebRemote extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbstractR
18544
18702
  }
18545
18703
 
18546
18704
 
18547
- /***/ }),
18705
+ /***/ },
18548
18706
 
18549
- /***/ "./lib/src/db/sync/WebStreamingSyncImplementation.js":
18707
+ /***/ "./lib/src/db/sync/WebStreamingSyncImplementation.js"
18550
18708
  /*!***********************************************************!*\
18551
18709
  !*** ./lib/src/db/sync/WebStreamingSyncImplementation.js ***!
18552
18710
  \***********************************************************/
18553
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18711
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18554
18712
 
18555
18713
  __webpack_require__.r(__webpack_exports__);
18556
18714
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18578,13 +18736,13 @@ class WebStreamingSyncImplementation extends _powersync_common__WEBPACK_IMPORTED
18578
18736
  }
18579
18737
 
18580
18738
 
18581
- /***/ }),
18739
+ /***/ },
18582
18740
 
18583
- /***/ "./lib/src/db/sync/userAgent.js":
18741
+ /***/ "./lib/src/db/sync/userAgent.js"
18584
18742
  /*!**************************************!*\
18585
18743
  !*** ./lib/src/db/sync/userAgent.js ***!
18586
18744
  \**************************************/
18587
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18745
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18588
18746
 
18589
18747
  __webpack_require__.r(__webpack_exports__);
18590
18748
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18656,13 +18814,13 @@ function getOsInfo(nav) {
18656
18814
  }
18657
18815
 
18658
18816
 
18659
- /***/ }),
18817
+ /***/ },
18660
18818
 
18661
- /***/ "./lib/src/shared/navigator.js":
18819
+ /***/ "./lib/src/shared/navigator.js"
18662
18820
  /*!*************************************!*\
18663
18821
  !*** ./lib/src/shared/navigator.js ***!
18664
18822
  \*************************************/
18665
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18823
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18666
18824
 
18667
18825
  __webpack_require__.r(__webpack_exports__);
18668
18826
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18676,13 +18834,13 @@ const getNavigatorLocks = () => {
18676
18834
  };
18677
18835
 
18678
18836
 
18679
- /***/ }),
18837
+ /***/ },
18680
18838
 
18681
- /***/ "./lib/src/worker/sync/BroadcastLogger.js":
18839
+ /***/ "./lib/src/worker/sync/BroadcastLogger.js"
18682
18840
  /*!************************************************!*\
18683
18841
  !*** ./lib/src/worker/sync/BroadcastLogger.js ***!
18684
18842
  \************************************************/
18685
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18843
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18686
18844
 
18687
18845
  __webpack_require__.r(__webpack_exports__);
18688
18846
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18819,13 +18977,13 @@ class BroadcastLogger {
18819
18977
  }
18820
18978
 
18821
18979
 
18822
- /***/ }),
18980
+ /***/ },
18823
18981
 
18824
- /***/ "./lib/src/worker/sync/SharedSyncImplementation.js":
18982
+ /***/ "./lib/src/worker/sync/SharedSyncImplementation.js"
18825
18983
  /*!*********************************************************!*\
18826
18984
  !*** ./lib/src/worker/sync/SharedSyncImplementation.js ***!
18827
18985
  \*********************************************************/
18828
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
18986
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
18829
18987
 
18830
18988
  __webpack_require__.r(__webpack_exports__);
18831
18989
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
@@ -18834,12 +18992,12 @@ __webpack_require__.r(__webpack_exports__);
18834
18992
  /* harmony export */ });
18835
18993
  /* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
18836
18994
  /* harmony import */ var async_mutex__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! async-mutex */ "../../node_modules/async-mutex/index.mjs");
18837
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18838
- /* harmony import */ var _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../db/sync/WebRemote */ "./lib/src/db/sync/WebRemote.js");
18839
- /* harmony import */ var _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../db/sync/WebStreamingSyncImplementation */ "./lib/src/db/sync/WebStreamingSyncImplementation.js");
18840
- /* harmony import */ var _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../db/adapters/LockedAsyncDatabaseAdapter */ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js");
18841
- /* harmony import */ var _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../db/adapters/WorkerWrappedAsyncDatabaseConnection */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
18842
- /* harmony import */ var _BroadcastLogger__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./BroadcastLogger */ "./lib/src/worker/sync/BroadcastLogger.js");
18995
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
18996
+ /* harmony import */ var _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../db/sync/WebRemote */ "./lib/src/db/sync/WebRemote.js");
18997
+ /* harmony import */ var _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../db/sync/WebStreamingSyncImplementation */ "./lib/src/db/sync/WebStreamingSyncImplementation.js");
18998
+ /* harmony import */ var _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../db/adapters/LockedAsyncDatabaseAdapter */ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js");
18999
+ /* harmony import */ var _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../db/adapters/WorkerWrappedAsyncDatabaseConnection */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
19000
+ /* harmony import */ var _BroadcastLogger__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BroadcastLogger */ "./lib/src/worker/sync/BroadcastLogger.js");
18843
19001
 
18844
19002
 
18845
19003
 
@@ -18877,7 +19035,6 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18877
19035
  statusListener;
18878
19036
  fetchCredentialsController;
18879
19037
  uploadDataController;
18880
- dbAdapter;
18881
19038
  syncParams;
18882
19039
  logger;
18883
19040
  lastConnectOptions;
@@ -18886,10 +19043,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18886
19043
  connectionManager;
18887
19044
  syncStatus;
18888
19045
  broadCastLogger;
19046
+ distributedDB;
18889
19047
  constructor() {
18890
19048
  super();
18891
19049
  this.ports = [];
18892
- this.dbAdapter = null;
18893
19050
  this.syncParams = null;
18894
19051
  this.logger = (0,_powersync_common__WEBPACK_IMPORTED_MODULE_0__.createLogger)('shared-sync');
18895
19052
  this.lastConnectOptions = undefined;
@@ -18902,26 +19059,23 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18902
19059
  }
18903
19060
  });
18904
19061
  });
19062
+ // Should be configured once we get params
19063
+ this.distributedDB = null;
18905
19064
  this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus({});
18906
- this.broadCastLogger = new _BroadcastLogger__WEBPACK_IMPORTED_MODULE_6__.BroadcastLogger(this.ports);
19065
+ this.broadCastLogger = new _BroadcastLogger__WEBPACK_IMPORTED_MODULE_7__.BroadcastLogger(this.ports);
18907
19066
  this.connectionManager = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionManager({
18908
19067
  createSyncImplementation: async () => {
18909
- return this.portMutex.runExclusive(async () => {
18910
- await this.waitForReady();
18911
- if (!this.dbAdapter) {
18912
- await this.openInternalDB();
19068
+ await this.waitForReady();
19069
+ const sync = this.generateStreamingImplementation();
19070
+ const onDispose = sync.registerListener({
19071
+ statusChanged: (status) => {
19072
+ this.updateAllStatuses(status.toJSON());
18913
19073
  }
18914
- const sync = this.generateStreamingImplementation();
18915
- const onDispose = sync.registerListener({
18916
- statusChanged: (status) => {
18917
- this.updateAllStatuses(status.toJSON());
18918
- }
18919
- });
18920
- return {
18921
- sync,
18922
- onDispose
18923
- };
18924
19074
  });
19075
+ return {
19076
+ sync,
19077
+ onDispose
19078
+ };
18925
19079
  },
18926
19080
  logger: this.logger
18927
19081
  });
@@ -18932,6 +19086,30 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18932
19086
  get isConnected() {
18933
19087
  return this.connectionManager.syncStreamImplementation?.isConnected ?? false;
18934
19088
  }
19089
+ /**
19090
+ * Gets the last client port which we know is safe from unexpected closes.
19091
+ */
19092
+ async getLastWrappedPort() {
19093
+ // Find the last port which is not closing
19094
+ return await this.portMutex.runExclusive(() => {
19095
+ for (let i = this.ports.length - 1; i >= 0; i--) {
19096
+ if (!this.ports[i].isClosing) {
19097
+ return this.ports[i];
19098
+ }
19099
+ }
19100
+ return;
19101
+ });
19102
+ }
19103
+ /**
19104
+ * In some very rare cases a specific tab might not respond to requests.
19105
+ * This returns a random port which is not closing.
19106
+ */
19107
+ async getRandomWrappedPort() {
19108
+ return await this.portMutex.runExclusive(() => {
19109
+ const nonClosingPorts = this.ports.filter((p) => !p.isClosing);
19110
+ return nonClosingPorts[Math.floor(Math.random() * nonClosingPorts.length)];
19111
+ });
19112
+ }
18935
19113
  async waitForStatus(status) {
18936
19114
  return this.withSyncImplementation(async (sync) => {
18937
19115
  return sync.waitForStatus(status);
@@ -18972,28 +19150,53 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
18972
19150
  async setParams(params) {
18973
19151
  await this.portMutex.runExclusive(async () => {
18974
19152
  this.collectActiveSubscriptions();
18975
- if (this.syncParams) {
18976
- // Cannot modify already existing sync implementation params
18977
- // But we can ask for a DB adapter, if required, at this point.
18978
- if (!this.dbAdapter) {
18979
- await this.openInternalDB();
18980
- }
18981
- return;
18982
- }
18983
- // First time setting params
18984
- this.syncParams = params;
18985
- if (params.streamOptions?.flags?.broadcastLogs) {
18986
- this.logger = this.broadCastLogger;
18987
- }
18988
- self.onerror = (event) => {
18989
- // Share any uncaught events on the broadcast logger
18990
- this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
18991
- };
18992
- if (!this.dbAdapter) {
18993
- await this.openInternalDB();
19153
+ });
19154
+ if (this.syncParams) {
19155
+ // Cannot modify already existing sync implementation params
19156
+ return;
19157
+ }
19158
+ // First time setting params
19159
+ this.syncParams = params;
19160
+ if (params.streamOptions?.flags?.broadcastLogs) {
19161
+ this.logger = this.broadCastLogger;
19162
+ }
19163
+ const lockedAdapter = new _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_5__.LockedAsyncDatabaseAdapter({
19164
+ name: params.dbParams.dbFilename,
19165
+ openConnection: async () => {
19166
+ // Gets a connection from the clients when a new connection is requested.
19167
+ const db = await this.openInternalDB();
19168
+ db.registerListener({
19169
+ closing: () => {
19170
+ lockedAdapter.reOpenInternalDB();
19171
+ }
19172
+ });
19173
+ return db;
19174
+ },
19175
+ logger: this.logger,
19176
+ reOpenOnConnectionClosed: true
19177
+ });
19178
+ this.distributedDB = lockedAdapter;
19179
+ await lockedAdapter.init();
19180
+ lockedAdapter.registerListener({
19181
+ databaseReOpened: () => {
19182
+ // We may have missed some table updates while the database was closed.
19183
+ // We can poke the crud in case we missed any updates.
19184
+ this.connectionManager.syncStreamImplementation?.triggerCrudUpload();
19185
+ /**
19186
+ * FIXME or IMPROVE ME
19187
+ * The Rust client implementation stores sync state on the connection level.
19188
+ * Reopening the database causes a state machine error which should cause the
19189
+ * StreamingSyncImplementation to reconnect. It would be nicer if we could trigger
19190
+ * this reconnect earlier.
19191
+ * This reconnect is not required for IndexedDB.
19192
+ */
18994
19193
  }
18995
- this.iterateListeners((l) => l.initialized?.());
18996
19194
  });
19195
+ self.onerror = (event) => {
19196
+ // Share any uncaught events on the broadcast logger
19197
+ this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
19198
+ };
19199
+ this.iterateListeners((l) => l.initialized?.());
18997
19200
  }
18998
19201
  async dispose() {
18999
19202
  await this.waitForReady();
@@ -19020,9 +19223,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19020
19223
  return await this.portMutex.runExclusive(() => {
19021
19224
  const portProvider = {
19022
19225
  port,
19023
- clientProvider: comlink__WEBPACK_IMPORTED_MODULE_7__.wrap(port),
19226
+ clientProvider: comlink__WEBPACK_IMPORTED_MODULE_2__.wrap(port),
19024
19227
  currentSubscriptions: [],
19025
- closeListeners: []
19228
+ closeListeners: [],
19229
+ isClosing: false
19026
19230
  };
19027
19231
  this.ports.push(portProvider);
19028
19232
  // Give the newly connected client the latest status
@@ -19038,14 +19242,16 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19038
19242
  * clients.
19039
19243
  */
19040
19244
  async removePort(port) {
19245
+ // Ports might be removed faster than we can process them.
19246
+ port.isClosing = true;
19041
19247
  // Remove the port within a mutex context.
19042
19248
  // Warns if the port is not found. This should not happen in practice.
19043
19249
  // We return early if the port is not found.
19044
- const { trackedPort, shouldReconnect } = await this.portMutex.runExclusive(async () => {
19250
+ return await this.portMutex.runExclusive(async () => {
19045
19251
  const index = this.ports.findIndex((p) => p == port);
19046
19252
  if (index < 0) {
19047
19253
  this.logger.warn(`Could not remove port ${port} since it is not present in active ports.`);
19048
- return {};
19254
+ return () => { };
19049
19255
  }
19050
19256
  const trackedPort = this.ports[index];
19051
19257
  // Remove from the list of active ports
@@ -19059,35 +19265,13 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19059
19265
  abortController.controller.abort(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Closing pending requests after client port is removed'));
19060
19266
  }
19061
19267
  });
19062
- const shouldReconnect = !!this.connectionManager.syncStreamImplementation && this.ports.length > 0;
19063
- return {
19064
- shouldReconnect,
19065
- trackedPort
19066
- };
19067
- });
19068
- if (!trackedPort) {
19069
- // We could not find the port to remove
19070
- return () => { };
19071
- }
19072
- for (const closeListener of trackedPort.closeListeners) {
19073
- await closeListener();
19074
- }
19075
- if (this.dbAdapter && this.dbAdapter == trackedPort.db) {
19076
- // Unconditionally close the connection because the database it's writing to has just been closed.
19077
- // The connection has been closed previously, this might throw. We should be able to ignore it.
19078
- await this.connectionManager
19079
- .disconnect()
19080
- .catch((ex) => this.logger.warn('Error while disconnecting. Will attempt to reconnect.', ex));
19081
- // Clearing the adapter will result in a new one being opened in connect
19082
- this.dbAdapter = null;
19083
- if (shouldReconnect) {
19084
- await this.connectionManager.connect(CONNECTOR_PLACEHOLDER, this.lastConnectOptions ?? {});
19268
+ // Close the worker wrapped database connection, we can't accurately rely on this connection
19269
+ for (const closeListener of trackedPort.closeListeners) {
19270
+ await closeListener();
19085
19271
  }
19086
- }
19087
- // Re-index subscriptions, the subscriptions of the removed port would no longer be considered.
19088
- this.collectActiveSubscriptions();
19089
- // Release proxy
19090
- return () => trackedPort.clientProvider[comlink__WEBPACK_IMPORTED_MODULE_7__.releaseProxy]();
19272
+ this.collectActiveSubscriptions();
19273
+ return () => trackedPort.clientProvider[comlink__WEBPACK_IMPORTED_MODULE_2__.releaseProxy]();
19274
+ });
19091
19275
  }
19092
19276
  triggerCrudUpload() {
19093
19277
  this.withSyncImplementation(async (sync) => {
@@ -19123,11 +19307,14 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19123
19307
  // This should only be called after initialization has completed
19124
19308
  const syncParams = this.syncParams;
19125
19309
  // Create a new StreamingSyncImplementation for each connect call. This is usually done is all SDKs.
19126
- return new _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_3__.WebStreamingSyncImplementation({
19127
- adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.dbAdapter, this.logger),
19128
- remote: new _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_2__.WebRemote({
19310
+ return new _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_4__.WebStreamingSyncImplementation({
19311
+ adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.distributedDB, this.logger),
19312
+ remote: new _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_3__.WebRemote({
19129
19313
  invalidateCredentials: async () => {
19130
- const lastPort = this.ports[this.ports.length - 1];
19314
+ const lastPort = await this.getLastWrappedPort();
19315
+ if (!lastPort) {
19316
+ throw new Error('No client port found to invalidate credentials');
19317
+ }
19131
19318
  try {
19132
19319
  this.logger.log('calling the last port client provider to invalidate credentials');
19133
19320
  lastPort.clientProvider.invalidateCredentials();
@@ -19137,7 +19324,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19137
19324
  }
19138
19325
  },
19139
19326
  fetchCredentials: async () => {
19140
- const lastPort = this.ports[this.ports.length - 1];
19327
+ const lastPort = await this.getLastWrappedPort();
19328
+ if (!lastPort) {
19329
+ throw new Error('No client port found to fetch credentials');
19330
+ }
19141
19331
  return new Promise(async (resolve, reject) => {
19142
19332
  const abortController = new AbortController();
19143
19333
  this.fetchCredentialsController = {
@@ -19159,7 +19349,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19159
19349
  }
19160
19350
  }, this.logger),
19161
19351
  uploadCrud: async () => {
19162
- const lastPort = this.ports[this.ports.length - 1];
19352
+ const lastPort = await this.getLastWrappedPort();
19353
+ if (!lastPort) {
19354
+ throw new Error('No client port found to upload crud');
19355
+ }
19163
19356
  return new Promise(async (resolve, reject) => {
19164
19357
  const abortController = new AbortController();
19165
19358
  this.uploadDataController = {
@@ -19185,38 +19378,81 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19185
19378
  logger: this.logger
19186
19379
  });
19187
19380
  }
19381
+ /**
19382
+ * Opens a worker wrapped database connection. Using the last connected client port.
19383
+ */
19188
19384
  async openInternalDB() {
19189
- const lastClient = this.ports[this.ports.length - 1];
19190
- if (!lastClient) {
19385
+ const client = await this.getRandomWrappedPort();
19386
+ if (!client) {
19191
19387
  // Should not really happen in practice
19192
19388
  throw new Error(`Could not open DB connection since no client is connected.`);
19193
19389
  }
19194
- const workerPort = await lastClient.clientProvider.getDBWorkerPort();
19195
- const remote = comlink__WEBPACK_IMPORTED_MODULE_7__.wrap(workerPort);
19390
+ // Fail-safe timeout for opening a database connection.
19391
+ const timeout = setTimeout(() => {
19392
+ abortController.abort();
19393
+ }, 10_000);
19394
+ /**
19395
+ * Handle cases where the client might close while opening a connection.
19396
+ */
19397
+ const abortController = new AbortController();
19398
+ const closeListener = () => {
19399
+ abortController.abort();
19400
+ };
19401
+ const removeCloseListener = () => {
19402
+ const index = client.closeListeners.indexOf(closeListener);
19403
+ if (index >= 0) {
19404
+ client.closeListeners.splice(index, 1);
19405
+ }
19406
+ };
19407
+ client.closeListeners.push(closeListener);
19408
+ const workerPort = await withAbort({
19409
+ action: () => client.clientProvider.getDBWorkerPort(),
19410
+ signal: abortController.signal,
19411
+ cleanupOnAbort: (port) => {
19412
+ port.close();
19413
+ }
19414
+ }).catch((ex) => {
19415
+ removeCloseListener();
19416
+ throw ex;
19417
+ });
19418
+ const remote = comlink__WEBPACK_IMPORTED_MODULE_2__.wrap(workerPort);
19196
19419
  const identifier = this.syncParams.dbParams.dbFilename;
19197
- const db = await remote(this.syncParams.dbParams);
19198
- const locked = new _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_4__.LockedAsyncDatabaseAdapter({
19199
- name: identifier,
19200
- openConnection: async () => {
19201
- const wrapped = new _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_5__.WorkerWrappedAsyncDatabaseConnection({
19202
- remote,
19203
- baseConnection: db,
19204
- identifier,
19205
- // It's possible for this worker to outlive the client hosting the database for us. We need to be prepared for
19206
- // that and ensure pending requests are aborted when the tab is closed.
19207
- remoteCanCloseUnexpectedly: true
19208
- });
19209
- lastClient.closeListeners.push(async () => {
19210
- this.logger.info('Aborting open connection because associated tab closed.');
19211
- await wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
19212
- wrapped.markRemoteClosed();
19213
- });
19214
- return wrapped;
19215
- },
19216
- logger: this.logger
19420
+ /**
19421
+ * The open could fail if the tab is closed while we're busy opening the database.
19422
+ * This operation is typically executed inside an exclusive portMutex lock.
19423
+ * We typically execute the closeListeners using the portMutex in a different context.
19424
+ * We can't rely on the closeListeners to abort the operation if the tab is closed.
19425
+ */
19426
+ const db = await withAbort({
19427
+ action: () => remote(this.syncParams.dbParams),
19428
+ signal: abortController.signal,
19429
+ cleanupOnAbort: (db) => {
19430
+ db.close();
19431
+ }
19432
+ }).finally(() => {
19433
+ // We can remove the close listener here since we no longer need it past this point.
19434
+ removeCloseListener();
19435
+ });
19436
+ clearTimeout(timeout);
19437
+ const wrapped = new _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_6__.WorkerWrappedAsyncDatabaseConnection({
19438
+ remote,
19439
+ baseConnection: db,
19440
+ identifier,
19441
+ // It's possible for this worker to outlive the client hosting the database for us. We need to be prepared for
19442
+ // that and ensure pending requests are aborted when the tab is closed.
19443
+ remoteCanCloseUnexpectedly: true
19444
+ });
19445
+ client.closeListeners.push(async () => {
19446
+ this.logger.info('Aborting open connection because associated tab closed.');
19447
+ /**
19448
+ * Don't await this close operation. It might never resolve if the tab is closed.
19449
+ * We mark the remote as closed first, this will reject any pending requests.
19450
+ * We then call close. The close operation is configured to fire-and-forget, the main promise will reject immediately.
19451
+ */
19452
+ wrapped.markRemoteClosed();
19453
+ wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
19217
19454
  });
19218
- await locked.init();
19219
- this.dbAdapter = lastClient.db = locked;
19455
+ return wrapped;
19220
19456
  }
19221
19457
  /**
19222
19458
  * A method to update the all shared statuses for each
@@ -19226,36 +19462,54 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
19226
19462
  this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
19227
19463
  this.ports.forEach((p) => p.clientProvider.statusChanged(status));
19228
19464
  }
19229
- /**
19230
- * A function only used for unit tests which updates the internal
19231
- * sync stream client and all tab client's sync status
19232
- */
19233
- async _testUpdateAllStatuses(status) {
19234
- if (!this.connectionManager.syncStreamImplementation) {
19235
- throw new Error('Cannot update status without a sync stream implementation');
19465
+ }
19466
+ /**
19467
+ * Runs the action with an abort controller.
19468
+ */
19469
+ function withAbort(options) {
19470
+ const { action, signal, cleanupOnAbort } = options;
19471
+ return new Promise((resolve, reject) => {
19472
+ if (signal.aborted) {
19473
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
19474
+ return;
19236
19475
  }
19237
- // Only assigning, don't call listeners for this test
19238
- this.connectionManager.syncStreamImplementation.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
19239
- this.updateAllStatuses(status);
19240
- }
19476
+ function handleAbort() {
19477
+ signal.removeEventListener('abort', handleAbort);
19478
+ reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
19479
+ }
19480
+ signal.addEventListener('abort', handleAbort, { once: true });
19481
+ function completePromise(action) {
19482
+ signal.removeEventListener('abort', handleAbort);
19483
+ action();
19484
+ }
19485
+ action()
19486
+ .then((data) => {
19487
+ // We already rejected due to the abort, allow for cleanup
19488
+ if (signal.aborted) {
19489
+ return completePromise(() => cleanupOnAbort?.(data));
19490
+ }
19491
+ completePromise(() => resolve(data));
19492
+ })
19493
+ .catch((e) => completePromise(() => reject(e)));
19494
+ });
19241
19495
  }
19242
19496
 
19243
19497
 
19244
- /***/ }),
19498
+ /***/ },
19245
19499
 
19246
- /***/ "./lib/src/worker/sync/WorkerClient.js":
19500
+ /***/ "./lib/src/worker/sync/WorkerClient.js"
19247
19501
  /*!*********************************************!*\
19248
19502
  !*** ./lib/src/worker/sync/WorkerClient.js ***!
19249
19503
  \*********************************************/
19250
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19504
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
19251
19505
 
19252
19506
  __webpack_require__.r(__webpack_exports__);
19253
19507
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
19254
19508
  /* harmony export */ WorkerClient: () => (/* binding */ WorkerClient)
19255
19509
  /* harmony export */ });
19256
- /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
19257
- /* harmony import */ var _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SharedSyncImplementation */ "./lib/src/worker/sync/SharedSyncImplementation.js");
19510
+ /* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
19258
19511
  /* harmony import */ var _shared_navigator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/navigator */ "./lib/src/shared/navigator.js");
19512
+ /* harmony import */ var _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SharedSyncImplementation */ "./lib/src/worker/sync/SharedSyncImplementation.js");
19259
19513
 
19260
19514
 
19261
19515
 
@@ -19269,23 +19523,21 @@ class WorkerClient {
19269
19523
  sync;
19270
19524
  port;
19271
19525
  resolvedPort = null;
19526
+ resolvedPortPromise = null;
19272
19527
  constructor(sync, port) {
19273
19528
  this.sync = sync;
19274
19529
  this.port = port;
19275
- }
19276
- async initialize() {
19530
+ comlink__WEBPACK_IMPORTED_MODULE_0__.expose(this, this.port);
19277
19531
  /**
19278
19532
  * Adds an extra listener which can remove this port
19279
19533
  * from the list of monitored ports.
19280
19534
  */
19281
19535
  this.port.addEventListener('message', async (event) => {
19282
19536
  const payload = event.data;
19283
- if (payload?.event == _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_0__.SharedSyncClientEvent.CLOSE_CLIENT) {
19537
+ if (payload?.event == _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_2__.SharedSyncClientEvent.CLOSE_CLIENT) {
19284
19538
  await this.removePort();
19285
19539
  }
19286
19540
  });
19287
- this.resolvedPort = await this.sync.addPort(this.port);
19288
- comlink__WEBPACK_IMPORTED_MODULE_2__.expose(this, this.port);
19289
19541
  }
19290
19542
  async removePort() {
19291
19543
  if (this.resolvedPort) {
@@ -19294,7 +19546,7 @@ class WorkerClient {
19294
19546
  const release = await this.sync.removePort(resolved);
19295
19547
  this.resolvedPort = null;
19296
19548
  this.port.postMessage({
19297
- event: _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_0__.SharedSyncClientEvent.CLOSE_ACK,
19549
+ event: _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_2__.SharedSyncClientEvent.CLOSE_ACK,
19298
19550
  data: {}
19299
19551
  });
19300
19552
  release?.();
@@ -19306,7 +19558,10 @@ class WorkerClient {
19306
19558
  * When the client tab is closed, its lock will be returned. So when the shared worker attempts to acquire the lock,
19307
19559
  * it can consider the connection to be closed.
19308
19560
  */
19309
- addLockBasedCloseSignal(name) {
19561
+ async addLockBasedCloseSignal(name) {
19562
+ // Only add the port once the lock has been obtained on the client.
19563
+ this.resolvedPort = await this.sync.addPort(this.port);
19564
+ // Don't await this lock request
19310
19565
  (0,_shared_navigator__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(name, async () => {
19311
19566
  await this.removePort();
19312
19567
  });
@@ -19338,13 +19593,10 @@ class WorkerClient {
19338
19593
  disconnect() {
19339
19594
  return this.sync.disconnect();
19340
19595
  }
19341
- async _testUpdateAllStatuses(status) {
19342
- return this.sync._testUpdateAllStatuses(status);
19343
- }
19344
19596
  }
19345
19597
 
19346
19598
 
19347
- /***/ })
19599
+ /***/ }
19348
19600
 
19349
19601
  /******/ });
19350
19602
  /************************************************************************/
@@ -19358,6 +19610,12 @@ class WorkerClient {
19358
19610
  /******/ if (cachedModule !== undefined) {
19359
19611
  /******/ return cachedModule.exports;
19360
19612
  /******/ }
19613
+ /******/ // Check if module exists (development only)
19614
+ /******/ if (__webpack_modules__[moduleId] === undefined) {
19615
+ /******/ var e = new Error("Cannot find module '" + moduleId + "'");
19616
+ /******/ e.code = 'MODULE_NOT_FOUND';
19617
+ /******/ throw e;
19618
+ /******/ }
19361
19619
  /******/ // Create a new module (and put it into the cache)
19362
19620
  /******/ var module = __webpack_module_cache__[moduleId] = {
19363
19621
  /******/ // no module.id needed
@@ -19522,7 +19780,7 @@ logger.useDefaults();
19522
19780
  const sharedSyncImplementation = new _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_1__.SharedSyncImplementation();
19523
19781
  _self.onconnect = async function (event) {
19524
19782
  const port = event.ports[0];
19525
- await new _WorkerClient__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port).initialize();
19783
+ new _WorkerClient__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port);
19526
19784
  };
19527
19785
 
19528
19786
  })();