dexie-cloud-addon 4.4.4 → 4.4.6

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.
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * ==========================================================================
10
10
  *
11
- * Version 4.4.4, Wed Mar 25 2026
11
+ * Version 4.4.6, Thu Mar 26 2026
12
12
  *
13
13
  * https://dexie.org
14
14
  *
@@ -4190,6 +4190,16 @@
4190
4190
  }
4191
4191
  break;
4192
4192
  case 'update':
4193
+ if (!primaryKey.outbound && primaryKey.keyPath) {
4194
+ // The primary key should never be part of an updateSpec — it cannot change
4195
+ // and is already communicated via the operation's keys array.
4196
+ // For private singleton IDs (e.g. "#key:userId" on server, "#key" on client),
4197
+ // the encoded server-side key may leak into the changeSpec via getObjectDiff().
4198
+ // Strip it here unconditionally as a defensive measure.
4199
+ for (const changeSpec of mut.changeSpecs) {
4200
+ Dexie.delByKeyPath(changeSpec, primaryKey.keyPath);
4201
+ }
4202
+ }
4193
4203
  yield bulkUpdate(table, keys, mut.changeSpecs);
4194
4204
  break;
4195
4205
  case 'delete':
@@ -13588,7 +13598,7 @@
13588
13598
  *
13589
13599
  * ==========================================================================
13590
13600
  *
13591
- * Version 4.4.0, Wed Mar 25 2026
13601
+ * Version 4.4.0, Thu Mar 26 2026
13592
13602
  *
13593
13603
  * https://dexie.org
13594
13604
  *
@@ -18003,14 +18013,13 @@
18003
18013
  throw new Error(`No database URL to connect WebSocket to`);
18004
18014
  }
18005
18015
  const readyForChangesMessage = db.messageConsumer.readyToServe.pipe(operators.filter((isReady) => isReady), // When consumer is ready for new messages, produce such a message to inform server about it
18006
- operators.switchMap(() => db.getPersistedSyncState()), // We need the info on which server revision we are at:
18007
- operators.filter((syncState) => syncState && syncState.serverRevision), // We wont send anything to server before inital sync has taken place
18016
+ operators.switchMap(() => db.cloud.persistedSyncState.pipe(operators.filter((syncState) => !!(syncState && syncState.serverRevision)), operators.take(1))), // Wait reactively for syncState with serverRevision (avoids race with logout/re-sync)
18008
18017
  operators.switchMap((syncState) => __awaiter(this, void 0, void 0, function* () {
18009
18018
  return ({
18010
18019
  // Produce the message to trigger server to send us new messages to consume:
18011
18020
  type: 'ready',
18012
18021
  rev: syncState.serverRevision,
18013
- realmSetHash: yield computeRealmSetHash(syncState)
18022
+ realmSetHash: yield computeRealmSetHash(syncState),
18014
18023
  });
18015
18024
  })));
18016
18025
  const messageProducer = rxjs.merge(readyForChangesMessage, db.messageProducer);
@@ -18023,7 +18032,8 @@
18023
18032
  }*/
18024
18033
  return userIsReallyActive.pipe(operators.map((isActive) => [isActive ? userLogin : null, syncState]));
18025
18034
  }), operators.switchMap(([userLogin, syncState]) => {
18026
- if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
18035
+ if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) &&
18036
+ !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
18027
18037
  // We're in an in-between state when user is logged in but the user's realms are not yet synced.
18028
18038
  // Don't make this change reconnect the websocket just yet. Wait till syncState is updated
18029
18039
  // to iclude the user's realm.
@@ -18058,7 +18068,7 @@
18058
18068
  accessTokenExpiration: refreshedLogin.accessTokenExpiration,
18059
18069
  claims: refreshedLogin.claims,
18060
18070
  license: refreshedLogin.license,
18061
- data: refreshedLogin.data
18071
+ data: refreshedLogin.data,
18062
18072
  });
18063
18073
  })), operators.switchMap(() => createObservable()));
18064
18074
  }
@@ -18066,7 +18076,7 @@
18066
18076
  return rxjs.throwError(() => error);
18067
18077
  }
18068
18078
  }), operators.catchError((error) => {
18069
- db.cloud.webSocketStatus.next("error");
18079
+ db.cloud.webSocketStatus.next('error');
18070
18080
  if (error instanceof InvalidLicenseError) {
18071
18081
  // Don't retry. Just throw and don't try connect again.
18072
18082
  return rxjs.throwError(() => error);
@@ -18178,27 +18188,30 @@
18178
18188
  // break free from possible active transaction:
18179
18189
  setTimeout(() => {
18180
18190
  const purpose = pullSignalled ? 'pull' : 'push';
18191
+ pullSignalled = false;
18192
+ pushSignalled = false;
18181
18193
  syncStartTime = Date.now();
18182
18194
  syncIfPossible(db, cloudOptions, cloudSchema, {
18183
18195
  cancelToken,
18184
18196
  retryImmediatelyOnFetchError: true, // workaround for "net::ERR_NETWORK_CHANGED" in chrome.
18185
18197
  purpose,
18186
- }).then(() => {
18198
+ })
18199
+ .then(() => {
18187
18200
  if (cancelToken.cancelled) {
18188
18201
  stop();
18189
18202
  }
18190
18203
  else {
18191
18204
  if (pullSignalled || pushSignalled) {
18192
18205
  // If we have signalled for more sync, do it now.
18193
- pullSignalled = false;
18194
- pushSignalled = false;
18206
+ // Note: don't reset flags here - syncAndRetry reads them in setTimeout
18195
18207
  return syncAndRetry();
18196
18208
  }
18197
18209
  }
18198
18210
  ongoingSync = false;
18199
18211
  nextRetryTime = 0;
18200
18212
  syncStartTime = 0;
18201
- }).catch((error) => {
18213
+ })
18214
+ .catch((error) => {
18202
18215
  console.error('error in syncIfPossible()', error);
18203
18216
  if (cancelToken.cancelled) {
18204
18217
  stop();
@@ -18241,7 +18254,8 @@
18241
18254
  if (nextRetryTime) {
18242
18255
  console.debug(`Sync is paused until ${new Date(nextRetryTime).toISOString()} due to error in last sync attempt`);
18243
18256
  }
18244
- else if (syncStartTime > 0 && Date.now() - syncStartTime > 20 * SECONDS) {
18257
+ else if (syncStartTime > 0 &&
18258
+ Date.now() - syncStartTime > 20 * SECONDS) {
18245
18259
  console.debug(`An existing sync operation is taking more than 20 seconds. Will resync when done.`);
18246
18260
  }
18247
18261
  return;
@@ -19432,7 +19446,7 @@
19432
19446
  const downloading$ = createDownloadingState();
19433
19447
  dexie.cloud = {
19434
19448
  // @ts-ignore
19435
- version: "4.4.4",
19449
+ version: "4.4.6",
19436
19450
  options: Object.assign({}, DEFAULT_OPTIONS),
19437
19451
  schema: null,
19438
19452
  get currentUserId() {
@@ -19859,7 +19873,7 @@
19859
19873
  }
19860
19874
  }
19861
19875
  // @ts-ignore
19862
- dexieCloud.version = "4.4.4";
19876
+ dexieCloud.version = "4.4.6";
19863
19877
  Dexie.Cloud = dexieCloud;
19864
19878
 
19865
19879
  // In case the SW lives for a while, let it reuse already opened connections: