dexie-cloud-addon 4.0.1-beta.35 → 4.0.1-beta.36

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.
@@ -210,6 +210,36 @@
210
210
  }
211
211
  }
212
212
 
213
+ const events = globalThis['lbc-events'] || (globalThis['lbc-events'] = new Map());
214
+ function addListener(name, listener) {
215
+ if (events.has(name)) {
216
+ events.get(name).push(listener);
217
+ }
218
+ else {
219
+ events.set(name, [listener]);
220
+ }
221
+ }
222
+ function removeListener(name, listener) {
223
+ const listeners = events.get(name);
224
+ if (listeners) {
225
+ const idx = listeners.indexOf(listener);
226
+ if (idx !== -1) {
227
+ listeners.splice(idx, 1);
228
+ }
229
+ }
230
+ }
231
+ function dispatch(ev) {
232
+ const listeners = events.get(ev.type);
233
+ if (listeners) {
234
+ listeners.forEach(listener => {
235
+ try {
236
+ listener(ev);
237
+ }
238
+ catch (_a) {
239
+ }
240
+ });
241
+ }
242
+ }
213
243
  class BroadcastedAndLocalEvent extends rxjs.Observable {
214
244
  constructor(name) {
215
245
  const bc = typeof BroadcastChannel === "undefined"
@@ -223,16 +253,24 @@
223
253
  subscriber.next(ev.data);
224
254
  }
225
255
  let unsubscribe;
226
- self.addEventListener(`lbc-${name}`, onCustomEvent);
227
- if (bc instanceof SWBroadcastChannel) {
228
- unsubscribe = bc.subscribe(message => subscriber.next(message));
256
+ //self.addEventListener(`lbc-${name}`, onCustomEvent); // Fails in service workers
257
+ addListener(`lbc-${name}`, onCustomEvent); // Works better in service worker
258
+ try {
259
+ if (bc instanceof SWBroadcastChannel) {
260
+ unsubscribe = bc.subscribe(message => subscriber.next(message));
261
+ }
262
+ else {
263
+ console.debug("BroadcastedAndLocalEvent: bc.addEventListener()", name, "bc is a", bc);
264
+ bc.addEventListener("message", onMessageEvent);
265
+ }
229
266
  }
230
- else {
231
- console.debug("BroadcastedAndLocalEvent: bc.addEventListener()", name, "bc is a", bc);
232
- bc.addEventListener("message", onMessageEvent);
267
+ catch (err) {
268
+ // Service workers might fail to subscribe outside its initial script.
269
+ console.warn('Failed to subscribe to broadcast channel', err);
233
270
  }
234
271
  return () => {
235
- self.removeEventListener(`lbc-${name}`, onCustomEvent);
272
+ //self.removeEventListener(`lbc-${name}`, onCustomEvent);
273
+ removeListener(`lbc-${name}`, onCustomEvent);
236
274
  if (bc instanceof SWBroadcastChannel) {
237
275
  unsubscribe();
238
276
  }
@@ -248,7 +286,8 @@
248
286
  console.debug("BroadcastedAndLocalEvent: bc.postMessage()", Object.assign({}, message), "bc is a", this.bc);
249
287
  this.bc.postMessage(message);
250
288
  const ev = new CustomEvent(`lbc-${this.name}`, { detail: message });
251
- self.dispatchEvent(ev);
289
+ //self.dispatchEvent(ev);
290
+ dispatch(ev);
252
291
  }
253
292
  }
254
293
 
@@ -3396,7 +3435,7 @@
3396
3435
  return _sync
3397
3436
  .apply(this, arguments)
3398
3437
  .then(() => {
3399
- if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
3438
+ if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) { // && syncOptions?.purpose !== 'push') {
3400
3439
  db.syncStateChangedEvent.next({
3401
3440
  phase: 'in-sync',
3402
3441
  });
@@ -3495,12 +3534,12 @@
3495
3534
  }
3496
3535
  return [clientChanges, syncState, baseRevs];
3497
3536
  }));
3498
- const syncIsNeeded = clientChangeSet.some((set) => set.muts.some((mut) => mut.keys.length > 0));
3537
+ const pushSyncIsNeeded = clientChangeSet.some((set) => set.muts.some((mut) => mut.keys.length > 0));
3499
3538
  if (justCheckIfNeeded) {
3500
- console.debug('Sync is needed:', syncIsNeeded);
3501
- return syncIsNeeded;
3539
+ console.debug('Sync is needed:', pushSyncIsNeeded);
3540
+ return pushSyncIsNeeded;
3502
3541
  }
3503
- if (purpose === 'push' && !syncIsNeeded) {
3542
+ if (purpose === 'push' && !pushSyncIsNeeded) {
3504
3543
  // The purpose of this request was to push changes
3505
3544
  return false;
3506
3545
  }
@@ -3618,6 +3657,7 @@
3618
3657
  return yield _sync(db, options, schema, { isInitialSync, cancelToken });
3619
3658
  }
3620
3659
  console.debug('SYNC DONE', { isInitialSync });
3660
+ db.syncCompleteEvent.next();
3621
3661
  return false; // Not needed anymore
3622
3662
  });
3623
3663
  }
@@ -3897,6 +3937,7 @@
3897
3937
  if (!db) {
3898
3938
  const localSyncEvent = new rxjs.Subject();
3899
3939
  let syncStateChangedEvent = new BroadcastedAndLocalEvent(`syncstatechanged-${dx.name}`);
3940
+ let syncCompleteEvent = new BroadcastedAndLocalEvent(`synccomplete-${dx.name}`);
3900
3941
  localSyncEvent['id'] = ++static_counter;
3901
3942
  let initiallySynced = false;
3902
3943
  db = {
@@ -3940,6 +3981,9 @@
3940
3981
  get syncStateChangedEvent() {
3941
3982
  return syncStateChangedEvent;
3942
3983
  },
3984
+ get syncCompleteEvent() {
3985
+ return syncCompleteEvent;
3986
+ },
3943
3987
  dx,
3944
3988
  };
3945
3989
  const helperMethods = {
@@ -3971,6 +4015,7 @@
3971
4015
  },
3972
4016
  reconfigure() {
3973
4017
  syncStateChangedEvent = new BroadcastedAndLocalEvent(`syncstatechanged-${dx.name}`);
4018
+ syncCompleteEvent = new BroadcastedAndLocalEvent(`synccomplete-${dx.name}`);
3974
4019
  },
3975
4020
  };
3976
4021
  Object.assign(db, helperMethods);
@@ -4185,7 +4230,7 @@
4185
4230
  }
4186
4231
  }
4187
4232
  // Already authenticated according to given hints.
4188
- return;
4233
+ return false;
4189
4234
  }
4190
4235
  const context = new AuthPersistedContext(db, {
4191
4236
  claims: {},
@@ -4210,6 +4255,7 @@
4210
4255
  // Make sure to resync as the new login will be authorized
4211
4256
  // for new realms.
4212
4257
  triggerSync(db, "pull");
4258
+ return true;
4213
4259
  });
4214
4260
  }
4215
4261
 
@@ -5102,7 +5148,15 @@
5102
5148
  function createObservable() {
5103
5149
  return db.cloud.persistedSyncState.pipe(filter((syncState) => syncState === null || syncState === void 0 ? void 0 : syncState.serverRevision), // Don't connect before there's no initial sync performed.
5104
5150
  take(1), // Don't continue waking up whenever syncState change
5105
- switchMap((syncState) => db.cloud.currentUser.pipe(map((userLogin) => [userLogin, syncState]))), switchMap(([userLogin, syncState]) => userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]))), switchMap(([userLogin, syncState]) => __awaiter(this, void 0, void 0, function* () { return [userLogin, yield computeRealmSetHash(syncState)]; })), switchMap(([userLogin, realmSetHash]) =>
5151
+ switchMap((syncState) => db.cloud.currentUser.pipe(map((userLogin) => [userLogin, syncState]))), switchMap(([userLogin, syncState]) => userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]))), switchMap(([userLogin, syncState]) => {
5152
+ if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
5153
+ // We're in an in-between state when user is logged in but the user's realms are not yet synced.
5154
+ // Don't make this change reconnect the websocket just yet. Wait till syncState is updated
5155
+ // to iclude the user's realm.
5156
+ return db.cloud.persistedSyncState.pipe(filter((syncState) => (syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId)) || false), take(1), map((syncState) => [userLogin, syncState]));
5157
+ }
5158
+ return new rxjs.BehaviorSubject([userLogin, syncState]);
5159
+ }), switchMap(([userLogin, syncState]) => __awaiter(this, void 0, void 0, function* () { return [userLogin, yield computeRealmSetHash(syncState)]; })), switchMap(([userLogin, realmSetHash]) =>
5106
5160
  // Let server end query changes from last entry of same client-ID and forward.
5107
5161
  // If no new entries, server won't bother the client. If new entries, server sends only those
5108
5162
  // and the baseRev of the last from same client-ID.
@@ -5964,8 +6018,9 @@
5964
6018
  localSyncWorker = null;
5965
6019
  currentUserEmitter.next(UNAUTHORIZED_USER);
5966
6020
  });
6021
+ const syncComplete = new rxjs.Subject();
5967
6022
  dexie.cloud = {
5968
- version: '4.0.1-beta.35',
6023
+ version: '4.0.1-beta.36',
5969
6024
  options: Object.assign({}, DEFAULT_OPTIONS),
5970
6025
  schema: null,
5971
6026
  get currentUserId() {
@@ -5976,6 +6031,9 @@
5976
6031
  phase: 'initial',
5977
6032
  status: 'not-started',
5978
6033
  }),
6034
+ events: {
6035
+ syncComplete,
6036
+ },
5979
6037
  persistedSyncState: new rxjs.BehaviorSubject(undefined),
5980
6038
  userInteraction: new rxjs.BehaviorSubject(undefined),
5981
6039
  webSocketStatus: new rxjs.BehaviorSubject('not-started'),
@@ -6069,6 +6127,8 @@
6069
6127
  if (!db.cloud.isServiceWorkerDB) {
6070
6128
  subscriptions.push(computeSyncState(db).subscribe(dexie.cloud.syncState));
6071
6129
  }
6130
+ // Forward db.syncCompleteEvent to be publicly consumable via db.cloud.events.syncComplete:
6131
+ subscriptions.push(db.syncCompleteEvent.subscribe(syncComplete));
6072
6132
  //verifyConfig(db.cloud.options); Not needed (yet at least!)
6073
6133
  // Verify the user has allowed version increment.
6074
6134
  if (!db.tables.every((table) => table.core)) {
@@ -6176,15 +6236,16 @@
6176
6236
  ]).toPromise();
6177
6237
  }
6178
6238
  // HERE: If requireAuth, do athentication now.
6239
+ let changedUser = false;
6179
6240
  if ((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.requireAuth) {
6180
- yield login(db);
6241
+ changedUser = yield login(db);
6181
6242
  }
6182
6243
  if (localSyncWorker)
6183
6244
  localSyncWorker.stop();
6184
6245
  localSyncWorker = null;
6185
6246
  throwIfClosed();
6186
6247
  if (db.cloud.usingServiceWorker && ((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl)) {
6187
- registerSyncEvent(db, 'push').catch(() => { });
6248
+ registerSyncEvent(db, changedUser ? 'pull' : 'push').catch(() => { });
6188
6249
  registerPeriodicSyncEvent(db).catch(() => { });
6189
6250
  }
6190
6251
  else if (((_e = db.cloud.options) === null || _e === void 0 ? void 0 : _e.databaseUrl) &&
@@ -6193,7 +6254,7 @@
6193
6254
  // There's no SW. Start SyncWorker instead.
6194
6255
  localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema);
6195
6256
  localSyncWorker.start();
6196
- triggerSync(db, 'push');
6257
+ triggerSync(db, changedUser ? 'pull' : 'push');
6197
6258
  }
6198
6259
  // Listen to online event and do sync.
6199
6260
  throwIfClosed();
@@ -6220,7 +6281,7 @@
6220
6281
  });
6221
6282
  }
6222
6283
  }
6223
- dexieCloud.version = '4.0.1-beta.35';
6284
+ dexieCloud.version = '4.0.1-beta.36';
6224
6285
  Dexie__default["default"].Cloud = dexieCloud;
6225
6286
 
6226
6287
  // In case the SW lives for a while, let it reuse already opened connections: