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.
@@ -20,6 +20,9 @@ export interface DexieCloudAPI {
20
20
  webSocketStatus: Rx.BehaviorSubject<DXCWebSocketStatus>;
21
21
  syncState: Rx.BehaviorSubject<SyncState>;
22
22
  persistedSyncState: Rx.BehaviorSubject<PersistedSyncState | undefined>;
23
+ events: {
24
+ syncComplete: Rx.Observable<void>;
25
+ };
23
26
  userInteraction: Rx.BehaviorSubject<DXCUserInteraction | undefined>;
24
27
  invites: Rx.Observable<Invite[]>;
25
28
  roles: Rx.Observable<{
@@ -3,4 +3,4 @@ export declare function login(db: DexieCloudDB, hints?: {
3
3
  email?: string;
4
4
  userId?: string;
5
5
  grant_type?: string;
6
- }): Promise<void>;
6
+ }): Promise<boolean>;
@@ -3,7 +3,7 @@ import { GuardedJob } from './entities/GuardedJob';
3
3
  import { UserLogin } from './entities/UserLogin';
4
4
  import { PersistedSyncState } from './entities/PersistedSyncState';
5
5
  import { DexieCloudOptions } from '../DexieCloudOptions';
6
- import { BehaviorSubject } from 'rxjs';
6
+ import { Subject } from 'rxjs';
7
7
  import { BaseRevisionMapEntry } from './entities/BaseRevisionMapEntry';
8
8
  import { DBRealm, DBRealmMember, DBRealmRole, DexieCloudSchema } from 'dexie-cloud-common';
9
9
  import { BroadcastedAndLocalEvent } from '../helpers/BroadcastedAndLocalEvent';
@@ -29,10 +29,11 @@ export interface DexieCloudDBBase {
29
29
  readonly realms: Table<DBRealm, string>;
30
30
  readonly members: Table<DBRealmMember, string>;
31
31
  readonly roles: Table<DBRealmRole, [string, string]>;
32
- readonly localSyncEvent: BehaviorSubject<{
32
+ readonly localSyncEvent: Subject<{
33
33
  purpose?: 'pull' | 'push';
34
34
  }>;
35
35
  readonly syncStateChangedEvent: BroadcastedAndLocalEvent<SyncStateChangedEventData>;
36
+ readonly syncCompleteEvent: BroadcastedAndLocalEvent<void>;
36
37
  readonly dx: Dexie;
37
38
  readonly initiallySynced: boolean;
38
39
  }
@@ -108,7 +108,7 @@
108
108
  *
109
109
  * ==========================================================================
110
110
  *
111
- * Version 4.0.1-beta.35, Tue Apr 11 2023
111
+ * Version 4.0.1-beta.36, Mon Apr 17 2023
112
112
  *
113
113
  * https://dexie.org
114
114
  *
@@ -2747,7 +2747,7 @@
2747
2747
  }
2748
2748
  }
2749
2749
  // Already authenticated according to given hints.
2750
- return [2 /*return*/];
2750
+ return [2 /*return*/, false];
2751
2751
  }
2752
2752
  context = new AuthPersistedContext(db, {
2753
2753
  claims: {},
@@ -2780,7 +2780,7 @@
2780
2780
  // Make sure to resync as the new login will be authorized
2781
2781
  // for new realms.
2782
2782
  triggerSync(db, "pull");
2783
- return [2 /*return*/];
2783
+ return [2 /*return*/, true];
2784
2784
  }
2785
2785
  });
2786
2786
  });
@@ -2856,6 +2856,36 @@
2856
2856
  };
2857
2857
  return SWBroadcastChannel;
2858
2858
  }());
2859
+ var events = globalThis['lbc-events'] || (globalThis['lbc-events'] = new Map());
2860
+ function addListener(name, listener) {
2861
+ if (events.has(name)) {
2862
+ events.get(name).push(listener);
2863
+ }
2864
+ else {
2865
+ events.set(name, [listener]);
2866
+ }
2867
+ }
2868
+ function removeListener(name, listener) {
2869
+ var listeners = events.get(name);
2870
+ if (listeners) {
2871
+ var idx = listeners.indexOf(listener);
2872
+ if (idx !== -1) {
2873
+ listeners.splice(idx, 1);
2874
+ }
2875
+ }
2876
+ }
2877
+ function dispatch(ev) {
2878
+ var listeners = events.get(ev.type);
2879
+ if (listeners) {
2880
+ listeners.forEach(function (listener) {
2881
+ try {
2882
+ listener(ev);
2883
+ }
2884
+ catch (_a) {
2885
+ }
2886
+ });
2887
+ }
2888
+ }
2859
2889
  var BroadcastedAndLocalEvent = /** @class */ (function (_super_1) {
2860
2890
  __extends$1(BroadcastedAndLocalEvent, _super_1);
2861
2891
  function BroadcastedAndLocalEvent(name) {
@@ -2871,16 +2901,24 @@
2871
2901
  subscriber.next(ev.data);
2872
2902
  }
2873
2903
  var unsubscribe;
2874
- self.addEventListener("lbc-".concat(name), onCustomEvent);
2875
- if (bc instanceof SWBroadcastChannel) {
2876
- unsubscribe = bc.subscribe(function (message) { return subscriber.next(message); });
2904
+ //self.addEventListener(`lbc-${name}`, onCustomEvent); // Fails in service workers
2905
+ addListener("lbc-".concat(name), onCustomEvent); // Works better in service worker
2906
+ try {
2907
+ if (bc instanceof SWBroadcastChannel) {
2908
+ unsubscribe = bc.subscribe(function (message) { return subscriber.next(message); });
2909
+ }
2910
+ else {
2911
+ console.debug("BroadcastedAndLocalEvent: bc.addEventListener()", name, "bc is a", bc);
2912
+ bc.addEventListener("message", onMessageEvent);
2913
+ }
2877
2914
  }
2878
- else {
2879
- console.debug("BroadcastedAndLocalEvent: bc.addEventListener()", name, "bc is a", bc);
2880
- bc.addEventListener("message", onMessageEvent);
2915
+ catch (err) {
2916
+ // Service workers might fail to subscribe outside its initial script.
2917
+ console.warn('Failed to subscribe to broadcast channel', err);
2881
2918
  }
2882
2919
  return function () {
2883
- self.removeEventListener("lbc-".concat(name), onCustomEvent);
2920
+ //self.removeEventListener(`lbc-${name}`, onCustomEvent);
2921
+ removeListener("lbc-".concat(name), onCustomEvent);
2884
2922
  if (bc instanceof SWBroadcastChannel) {
2885
2923
  unsubscribe();
2886
2924
  }
@@ -2897,7 +2935,8 @@
2897
2935
  console.debug("BroadcastedAndLocalEvent: bc.postMessage()", Object.assign({}, message), "bc is a", this.bc);
2898
2936
  this.bc.postMessage(message);
2899
2937
  var ev = new CustomEvent("lbc-".concat(this.name), { detail: message });
2900
- self.dispatchEvent(ev);
2938
+ //self.dispatchEvent(ev);
2939
+ dispatch(ev);
2901
2940
  };
2902
2941
  return BroadcastedAndLocalEvent;
2903
2942
  }(rxjs.Observable));
@@ -4079,7 +4118,7 @@
4079
4118
  return _sync
4080
4119
  .apply(this, arguments)
4081
4120
  .then(function () {
4082
- if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
4121
+ if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) { // && syncOptions?.purpose !== 'push') {
4083
4122
  db.syncStateChangedEvent.next({
4084
4123
  phase: 'in-sync',
4085
4124
  });
@@ -4137,7 +4176,7 @@
4137
4176
  } : _k, isInitialSync = _l.isInitialSync, cancelToken = _l.cancelToken, justCheckIfNeeded = _l.justCheckIfNeeded, purpose = _l.purpose;
4138
4177
  var _a;
4139
4178
  return __awaiter(this, void 0, void 0, function () {
4140
- var databaseUrl, currentUser, tablesToSync, mutationTables, persistedSyncState, readyForSyncification, tablesToSyncify, doSyncify, _k, clientChangeSet, syncState, baseRevs, syncIsNeeded, latestRevisions, clientIdentity, res, done;
4179
+ var databaseUrl, currentUser, tablesToSync, mutationTables, persistedSyncState, readyForSyncification, tablesToSyncify, doSyncify, _k, clientChangeSet, syncState, baseRevs, pushSyncIsNeeded, latestRevisions, clientIdentity, res, done;
4141
4180
  var _this_1 = this;
4142
4181
  return __generator$1(this, function (_l) {
4143
4182
  switch (_l.label) {
@@ -4214,12 +4253,12 @@
4214
4253
  }); })];
4215
4254
  case 5:
4216
4255
  _k = _l.sent(), clientChangeSet = _k[0], syncState = _k[1], baseRevs = _k[2];
4217
- syncIsNeeded = clientChangeSet.some(function (set) { return set.muts.some(function (mut) { return mut.keys.length > 0; }); });
4256
+ pushSyncIsNeeded = clientChangeSet.some(function (set) { return set.muts.some(function (mut) { return mut.keys.length > 0; }); });
4218
4257
  if (justCheckIfNeeded) {
4219
- console.debug('Sync is needed:', syncIsNeeded);
4220
- return [2 /*return*/, syncIsNeeded];
4258
+ console.debug('Sync is needed:', pushSyncIsNeeded);
4259
+ return [2 /*return*/, pushSyncIsNeeded];
4221
4260
  }
4222
- if (purpose === 'push' && !syncIsNeeded) {
4261
+ if (purpose === 'push' && !pushSyncIsNeeded) {
4223
4262
  // The purpose of this request was to push changes
4224
4263
  return [2 /*return*/, false];
4225
4264
  }
@@ -4394,6 +4433,7 @@
4394
4433
  case 8: return [2 /*return*/, _l.sent()];
4395
4434
  case 9:
4396
4435
  console.debug('SYNC DONE', { isInitialSync: isInitialSync });
4436
+ db.syncCompleteEvent.next();
4397
4437
  return [2 /*return*/, false]; // Not needed anymore
4398
4438
  }
4399
4439
  });
@@ -4787,6 +4827,7 @@
4787
4827
  if (!db) {
4788
4828
  var localSyncEvent = new rxjs.Subject();
4789
4829
  var syncStateChangedEvent_1 = new BroadcastedAndLocalEvent("syncstatechanged-".concat(dx.name));
4830
+ var syncCompleteEvent_1 = new BroadcastedAndLocalEvent("synccomplete-".concat(dx.name));
4790
4831
  localSyncEvent['id'] = ++static_counter;
4791
4832
  var initiallySynced_1 = false;
4792
4833
  db = {
@@ -4830,6 +4871,9 @@
4830
4871
  get syncStateChangedEvent() {
4831
4872
  return syncStateChangedEvent_1;
4832
4873
  },
4874
+ get syncCompleteEvent() {
4875
+ return syncCompleteEvent_1;
4876
+ },
4833
4877
  dx: dx,
4834
4878
  };
4835
4879
  var helperMethods = {
@@ -4862,6 +4906,7 @@
4862
4906
  },
4863
4907
  reconfigure: function () {
4864
4908
  syncStateChangedEvent_1 = new BroadcastedAndLocalEvent("syncstatechanged-".concat(dx.name));
4909
+ syncCompleteEvent_1 = new BroadcastedAndLocalEvent("synccomplete-".concat(dx.name));
4865
4910
  },
4866
4911
  };
4867
4912
  Object.assign(db, helperMethods);
@@ -5795,6 +5840,15 @@
5795
5840
  switchMap(function (syncState) { return db.cloud.currentUser.pipe(map(function (userLogin) { return [userLogin, syncState]; })); }), switchMap(function (_k) {
5796
5841
  var userLogin = _k[0], syncState = _k[1];
5797
5842
  return userIsReallyActive.pipe(map(function (isActive) { return [isActive ? userLogin : null, syncState]; }));
5843
+ }), switchMap(function (_k) {
5844
+ var userLogin = _k[0], syncState = _k[1];
5845
+ if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
5846
+ // We're in an in-between state when user is logged in but the user's realms are not yet synced.
5847
+ // Don't make this change reconnect the websocket just yet. Wait till syncState is updated
5848
+ // to iclude the user's realm.
5849
+ return db.cloud.persistedSyncState.pipe(filter(function (syncState) { return (syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId)) || false; }), take(1), map(function (syncState) { return [userLogin, syncState]; }));
5850
+ }
5851
+ return new rxjs.BehaviorSubject([userLogin, syncState]);
5798
5852
  }), switchMap(function (_k) {
5799
5853
  var userLogin = _k[0], syncState = _k[1];
5800
5854
  return __awaiter(_this_1, void 0, void 0, function () { var _k; return __generator$1(this, function (_l) {
@@ -6990,8 +7044,9 @@
6990
7044
  localSyncWorker = null;
6991
7045
  currentUserEmitter.next(UNAUTHORIZED_USER);
6992
7046
  });
7047
+ var syncComplete = new rxjs.Subject();
6993
7048
  dexie.cloud = {
6994
- version: '4.0.1-beta.35',
7049
+ version: '4.0.1-beta.36',
6995
7050
  options: Object.assign({}, DEFAULT_OPTIONS),
6996
7051
  schema: null,
6997
7052
  get currentUserId() {
@@ -7002,6 +7057,9 @@
7002
7057
  phase: 'initial',
7003
7058
  status: 'not-started',
7004
7059
  }),
7060
+ events: {
7061
+ syncComplete: syncComplete,
7062
+ },
7005
7063
  persistedSyncState: new rxjs.BehaviorSubject(undefined),
7006
7064
  userInteraction: new rxjs.BehaviorSubject(undefined),
7007
7065
  webSocketStatus: new rxjs.BehaviorSubject('not-started'),
@@ -7119,7 +7177,7 @@
7119
7177
  function onDbReady(dexie) {
7120
7178
  var _a, _b, _c, _d, _e, _f, _g;
7121
7179
  return __awaiter(this, void 0, void 0, function () {
7122
- var db, swRegistrations, _k, initiallySynced;
7180
+ var db, swRegistrations, _k, initiallySynced, changedUser;
7123
7181
  var _this_1 = this;
7124
7182
  return __generator$1(this, function (_l) {
7125
7183
  switch (_l.label) {
@@ -7135,6 +7193,8 @@
7135
7193
  if (!db.cloud.isServiceWorkerDB) {
7136
7194
  subscriptions.push(computeSyncState(db).subscribe(dexie.cloud.syncState));
7137
7195
  }
7196
+ // Forward db.syncCompleteEvent to be publicly consumable via db.cloud.events.syncComplete:
7197
+ subscriptions.push(db.syncCompleteEvent.subscribe(syncComplete));
7138
7198
  //verifyConfig(db.cloud.options); Not needed (yet at least!)
7139
7199
  // Verify the user has allowed version increment.
7140
7200
  if (!db.tables.every(function (table) { return table.core; })) {
@@ -7274,10 +7334,11 @@
7274
7334
  _l.sent();
7275
7335
  _l.label = 8;
7276
7336
  case 8:
7337
+ changedUser = false;
7277
7338
  if (!((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.requireAuth)) return [3 /*break*/, 10];
7278
7339
  return [4 /*yield*/, login(db)];
7279
7340
  case 9:
7280
- _l.sent();
7341
+ changedUser = _l.sent();
7281
7342
  _l.label = 10;
7282
7343
  case 10:
7283
7344
  if (localSyncWorker)
@@ -7285,7 +7346,7 @@
7285
7346
  localSyncWorker = null;
7286
7347
  throwIfClosed();
7287
7348
  if (db.cloud.usingServiceWorker && ((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl)) {
7288
- registerSyncEvent(db, 'push').catch(function () { });
7349
+ registerSyncEvent(db, changedUser ? 'pull' : 'push').catch(function () { });
7289
7350
  registerPeriodicSyncEvent(db).catch(function () { });
7290
7351
  }
7291
7352
  else if (((_e = db.cloud.options) === null || _e === void 0 ? void 0 : _e.databaseUrl) &&
@@ -7294,7 +7355,7 @@
7294
7355
  // There's no SW. Start SyncWorker instead.
7295
7356
  localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema);
7296
7357
  localSyncWorker.start();
7297
- triggerSync(db, 'push');
7358
+ triggerSync(db, changedUser ? 'pull' : 'push');
7298
7359
  }
7299
7360
  // Listen to online event and do sync.
7300
7361
  throwIfClosed();
@@ -7324,7 +7385,7 @@
7324
7385
  });
7325
7386
  }
7326
7387
  }
7327
- dexieCloud.version = '4.0.1-beta.35';
7388
+ dexieCloud.version = '4.0.1-beta.36';
7328
7389
  Dexie__default["default"].Cloud = dexieCloud;
7329
7390
 
7330
7391
  exports["default"] = dexieCloud;