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
  *
@@ -3759,6 +3759,16 @@ function applyServerChanges(changes, db) {
3759
3759
  }
3760
3760
  break;
3761
3761
  case 'update':
3762
+ if (!primaryKey.outbound && primaryKey.keyPath) {
3763
+ // The primary key should never be part of an updateSpec — it cannot change
3764
+ // and is already communicated via the operation's keys array.
3765
+ // For private singleton IDs (e.g. "#key:userId" on server, "#key" on client),
3766
+ // the encoded server-side key may leak into the changeSpec via getObjectDiff().
3767
+ // Strip it here unconditionally as a defensive measure.
3768
+ for (const changeSpec of mut.changeSpecs) {
3769
+ Dexie.delByKeyPath(changeSpec, primaryKey.keyPath);
3770
+ }
3771
+ }
3762
3772
  yield bulkUpdate(table, keys, mut.changeSpecs);
3763
3773
  break;
3764
3774
  case 'delete':
@@ -6773,14 +6783,13 @@ function connectWebSocket(db) {
6773
6783
  throw new Error(`No database URL to connect WebSocket to`);
6774
6784
  }
6775
6785
  const readyForChangesMessage = db.messageConsumer.readyToServe.pipe(filter$1((isReady) => isReady), // When consumer is ready for new messages, produce such a message to inform server about it
6776
- switchMap(() => db.getPersistedSyncState()), // We need the info on which server revision we are at:
6777
- filter$1((syncState) => syncState && syncState.serverRevision), // We wont send anything to server before inital sync has taken place
6786
+ switchMap(() => db.cloud.persistedSyncState.pipe(filter$1((syncState) => !!(syncState && syncState.serverRevision)), take(1))), // Wait reactively for syncState with serverRevision (avoids race with logout/re-sync)
6778
6787
  switchMap((syncState) => __awaiter(this, void 0, void 0, function* () {
6779
6788
  return ({
6780
6789
  // Produce the message to trigger server to send us new messages to consume:
6781
6790
  type: 'ready',
6782
6791
  rev: syncState.serverRevision,
6783
- realmSetHash: yield computeRealmSetHash(syncState)
6792
+ realmSetHash: yield computeRealmSetHash(syncState),
6784
6793
  });
6785
6794
  })));
6786
6795
  const messageProducer = merge(readyForChangesMessage, db.messageProducer);
@@ -6793,7 +6802,8 @@ function connectWebSocket(db) {
6793
6802
  }*/
6794
6803
  return userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]));
6795
6804
  }), switchMap(([userLogin, syncState]) => {
6796
- if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
6805
+ if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) &&
6806
+ !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
6797
6807
  // We're in an in-between state when user is logged in but the user's realms are not yet synced.
6798
6808
  // Don't make this change reconnect the websocket just yet. Wait till syncState is updated
6799
6809
  // to iclude the user's realm.
@@ -6828,7 +6838,7 @@ function connectWebSocket(db) {
6828
6838
  accessTokenExpiration: refreshedLogin.accessTokenExpiration,
6829
6839
  claims: refreshedLogin.claims,
6830
6840
  license: refreshedLogin.license,
6831
- data: refreshedLogin.data
6841
+ data: refreshedLogin.data,
6832
6842
  });
6833
6843
  })), switchMap(() => createObservable()));
6834
6844
  }
@@ -6836,7 +6846,7 @@ function connectWebSocket(db) {
6836
6846
  return throwError(() => error);
6837
6847
  }
6838
6848
  }), catchError((error) => {
6839
- db.cloud.webSocketStatus.next("error");
6849
+ db.cloud.webSocketStatus.next('error');
6840
6850
  if (error instanceof InvalidLicenseError) {
6841
6851
  // Don't retry. Just throw and don't try connect again.
6842
6852
  return throwError(() => error);
@@ -6948,27 +6958,30 @@ function LocalSyncWorker(db, cloudOptions, cloudSchema) {
6948
6958
  // break free from possible active transaction:
6949
6959
  setTimeout(() => {
6950
6960
  const purpose = pullSignalled ? 'pull' : 'push';
6961
+ pullSignalled = false;
6962
+ pushSignalled = false;
6951
6963
  syncStartTime = Date.now();
6952
6964
  syncIfPossible(db, cloudOptions, cloudSchema, {
6953
6965
  cancelToken,
6954
6966
  retryImmediatelyOnFetchError: true, // workaround for "net::ERR_NETWORK_CHANGED" in chrome.
6955
6967
  purpose,
6956
- }).then(() => {
6968
+ })
6969
+ .then(() => {
6957
6970
  if (cancelToken.cancelled) {
6958
6971
  stop();
6959
6972
  }
6960
6973
  else {
6961
6974
  if (pullSignalled || pushSignalled) {
6962
6975
  // If we have signalled for more sync, do it now.
6963
- pullSignalled = false;
6964
- pushSignalled = false;
6976
+ // Note: don't reset flags here - syncAndRetry reads them in setTimeout
6965
6977
  return syncAndRetry();
6966
6978
  }
6967
6979
  }
6968
6980
  ongoingSync = false;
6969
6981
  nextRetryTime = 0;
6970
6982
  syncStartTime = 0;
6971
- }).catch((error) => {
6983
+ })
6984
+ .catch((error) => {
6972
6985
  console.error('error in syncIfPossible()', error);
6973
6986
  if (cancelToken.cancelled) {
6974
6987
  stop();
@@ -7011,7 +7024,8 @@ function LocalSyncWorker(db, cloudOptions, cloudSchema) {
7011
7024
  if (nextRetryTime) {
7012
7025
  console.debug(`Sync is paused until ${new Date(nextRetryTime).toISOString()} due to error in last sync attempt`);
7013
7026
  }
7014
- else if (syncStartTime > 0 && Date.now() - syncStartTime > 20 * SECONDS) {
7027
+ else if (syncStartTime > 0 &&
7028
+ Date.now() - syncStartTime > 20 * SECONDS) {
7015
7029
  console.debug(`An existing sync operation is taking more than 20 seconds. Will resync when done.`);
7016
7030
  }
7017
7031
  return;
@@ -8373,7 +8387,7 @@ function dexieCloud(dexie) {
8373
8387
  const downloading$ = createDownloadingState();
8374
8388
  dexie.cloud = {
8375
8389
  // @ts-ignore
8376
- version: "4.4.4",
8390
+ version: "4.4.6",
8377
8391
  options: Object.assign({}, DEFAULT_OPTIONS),
8378
8392
  schema: null,
8379
8393
  get currentUserId() {
@@ -8800,7 +8814,7 @@ function dexieCloud(dexie) {
8800
8814
  }
8801
8815
  }
8802
8816
  // @ts-ignore
8803
- dexieCloud.version = "4.4.4";
8817
+ dexieCloud.version = "4.4.6";
8804
8818
  Dexie.Cloud = dexieCloud;
8805
8819
 
8806
8820
  export { dexieCloud as default, defineYDocTrigger, dexieCloud, getTiedObjectId, getTiedRealmId, resolveText };