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

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.37, 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));
@@ -3719,7 +3758,10 @@
3719
3758
  function cloneChange(change, rewriteValues) {
3720
3759
  // clone on demand:
3721
3760
  return Object.assign(Object.assign({}, change), { muts: rewriteValues
3722
- ? change.muts.map(function (m) { return (Object.assign(Object.assign({}, m), { keys: m.keys.slice(), values: m.values.slice() })); })
3761
+ ? change.muts.map(function (m) {
3762
+ return (m.type === 'insert' || m.type === 'upsert') && m.values
3763
+ ? Object.assign(Object.assign({}, m), { keys: m.keys.slice(), values: m.values.slice() }) : Object.assign(Object.assign({}, m), { keys: m.keys.slice() });
3764
+ })
3723
3765
  : change.muts.map(function (m) { return (Object.assign(Object.assign({}, m), { keys: m.keys.slice() })); }) });
3724
3766
  }
3725
3767
  //import {BisonWebStreamReader} from "dreambase-library/dist/typeson-simplified/BisonWebStreamReader";
@@ -4079,7 +4121,7 @@
4079
4121
  return _sync
4080
4122
  .apply(this, arguments)
4081
4123
  .then(function () {
4082
- if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
4124
+ if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) { // && syncOptions?.purpose !== 'push') {
4083
4125
  db.syncStateChangedEvent.next({
4084
4126
  phase: 'in-sync',
4085
4127
  });
@@ -4137,7 +4179,7 @@
4137
4179
  } : _k, isInitialSync = _l.isInitialSync, cancelToken = _l.cancelToken, justCheckIfNeeded = _l.justCheckIfNeeded, purpose = _l.purpose;
4138
4180
  var _a;
4139
4181
  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;
4182
+ var databaseUrl, currentUser, tablesToSync, mutationTables, persistedSyncState, readyForSyncification, tablesToSyncify, doSyncify, _k, clientChangeSet, syncState, baseRevs, pushSyncIsNeeded, latestRevisions, clientIdentity, res, done;
4141
4183
  var _this_1 = this;
4142
4184
  return __generator$1(this, function (_l) {
4143
4185
  switch (_l.label) {
@@ -4214,12 +4256,12 @@
4214
4256
  }); })];
4215
4257
  case 5:
4216
4258
  _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; }); });
4259
+ pushSyncIsNeeded = clientChangeSet.some(function (set) { return set.muts.some(function (mut) { return mut.keys.length > 0; }); });
4218
4260
  if (justCheckIfNeeded) {
4219
- console.debug('Sync is needed:', syncIsNeeded);
4220
- return [2 /*return*/, syncIsNeeded];
4261
+ console.debug('Sync is needed:', pushSyncIsNeeded);
4262
+ return [2 /*return*/, pushSyncIsNeeded];
4221
4263
  }
4222
- if (purpose === 'push' && !syncIsNeeded) {
4264
+ if (purpose === 'push' && !pushSyncIsNeeded) {
4223
4265
  // The purpose of this request was to push changes
4224
4266
  return [2 /*return*/, false];
4225
4267
  }
@@ -4394,6 +4436,7 @@
4394
4436
  case 8: return [2 /*return*/, _l.sent()];
4395
4437
  case 9:
4396
4438
  console.debug('SYNC DONE', { isInitialSync: isInitialSync });
4439
+ db.syncCompleteEvent.next();
4397
4440
  return [2 /*return*/, false]; // Not needed anymore
4398
4441
  }
4399
4442
  });
@@ -4787,6 +4830,7 @@
4787
4830
  if (!db) {
4788
4831
  var localSyncEvent = new rxjs.Subject();
4789
4832
  var syncStateChangedEvent_1 = new BroadcastedAndLocalEvent("syncstatechanged-".concat(dx.name));
4833
+ var syncCompleteEvent_1 = new BroadcastedAndLocalEvent("synccomplete-".concat(dx.name));
4790
4834
  localSyncEvent['id'] = ++static_counter;
4791
4835
  var initiallySynced_1 = false;
4792
4836
  db = {
@@ -4830,6 +4874,9 @@
4830
4874
  get syncStateChangedEvent() {
4831
4875
  return syncStateChangedEvent_1;
4832
4876
  },
4877
+ get syncCompleteEvent() {
4878
+ return syncCompleteEvent_1;
4879
+ },
4833
4880
  dx: dx,
4834
4881
  };
4835
4882
  var helperMethods = {
@@ -4862,6 +4909,7 @@
4862
4909
  },
4863
4910
  reconfigure: function () {
4864
4911
  syncStateChangedEvent_1 = new BroadcastedAndLocalEvent("syncstatechanged-".concat(dx.name));
4912
+ syncCompleteEvent_1 = new BroadcastedAndLocalEvent("synccomplete-".concat(dx.name));
4865
4913
  },
4866
4914
  };
4867
4915
  Object.assign(db, helperMethods);
@@ -5795,6 +5843,15 @@
5795
5843
  switchMap(function (syncState) { return db.cloud.currentUser.pipe(map(function (userLogin) { return [userLogin, syncState]; })); }), switchMap(function (_k) {
5796
5844
  var userLogin = _k[0], syncState = _k[1];
5797
5845
  return userIsReallyActive.pipe(map(function (isActive) { return [isActive ? userLogin : null, syncState]; }));
5846
+ }), switchMap(function (_k) {
5847
+ var userLogin = _k[0], syncState = _k[1];
5848
+ if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
5849
+ // We're in an in-between state when user is logged in but the user's realms are not yet synced.
5850
+ // Don't make this change reconnect the websocket just yet. Wait till syncState is updated
5851
+ // to iclude the user's realm.
5852
+ 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]; }));
5853
+ }
5854
+ return new rxjs.BehaviorSubject([userLogin, syncState]);
5798
5855
  }), switchMap(function (_k) {
5799
5856
  var userLogin = _k[0], syncState = _k[1];
5800
5857
  return __awaiter(_this_1, void 0, void 0, function () { var _k; return __generator$1(this, function (_l) {
@@ -6990,8 +7047,9 @@
6990
7047
  localSyncWorker = null;
6991
7048
  currentUserEmitter.next(UNAUTHORIZED_USER);
6992
7049
  });
7050
+ var syncComplete = new rxjs.Subject();
6993
7051
  dexie.cloud = {
6994
- version: '4.0.1-beta.35',
7052
+ version: '4.0.1-beta.37',
6995
7053
  options: Object.assign({}, DEFAULT_OPTIONS),
6996
7054
  schema: null,
6997
7055
  get currentUserId() {
@@ -7002,6 +7060,9 @@
7002
7060
  phase: 'initial',
7003
7061
  status: 'not-started',
7004
7062
  }),
7063
+ events: {
7064
+ syncComplete: syncComplete,
7065
+ },
7005
7066
  persistedSyncState: new rxjs.BehaviorSubject(undefined),
7006
7067
  userInteraction: new rxjs.BehaviorSubject(undefined),
7007
7068
  webSocketStatus: new rxjs.BehaviorSubject('not-started'),
@@ -7119,7 +7180,7 @@
7119
7180
  function onDbReady(dexie) {
7120
7181
  var _a, _b, _c, _d, _e, _f, _g;
7121
7182
  return __awaiter(this, void 0, void 0, function () {
7122
- var db, swRegistrations, _k, initiallySynced;
7183
+ var db, swRegistrations, _k, initiallySynced, changedUser;
7123
7184
  var _this_1 = this;
7124
7185
  return __generator$1(this, function (_l) {
7125
7186
  switch (_l.label) {
@@ -7135,6 +7196,8 @@
7135
7196
  if (!db.cloud.isServiceWorkerDB) {
7136
7197
  subscriptions.push(computeSyncState(db).subscribe(dexie.cloud.syncState));
7137
7198
  }
7199
+ // Forward db.syncCompleteEvent to be publicly consumable via db.cloud.events.syncComplete:
7200
+ subscriptions.push(db.syncCompleteEvent.subscribe(syncComplete));
7138
7201
  //verifyConfig(db.cloud.options); Not needed (yet at least!)
7139
7202
  // Verify the user has allowed version increment.
7140
7203
  if (!db.tables.every(function (table) { return table.core; })) {
@@ -7274,10 +7337,11 @@
7274
7337
  _l.sent();
7275
7338
  _l.label = 8;
7276
7339
  case 8:
7340
+ changedUser = false;
7277
7341
  if (!((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.requireAuth)) return [3 /*break*/, 10];
7278
7342
  return [4 /*yield*/, login(db)];
7279
7343
  case 9:
7280
- _l.sent();
7344
+ changedUser = _l.sent();
7281
7345
  _l.label = 10;
7282
7346
  case 10:
7283
7347
  if (localSyncWorker)
@@ -7285,7 +7349,7 @@
7285
7349
  localSyncWorker = null;
7286
7350
  throwIfClosed();
7287
7351
  if (db.cloud.usingServiceWorker && ((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl)) {
7288
- registerSyncEvent(db, 'push').catch(function () { });
7352
+ registerSyncEvent(db, changedUser ? 'pull' : 'push').catch(function () { });
7289
7353
  registerPeriodicSyncEvent(db).catch(function () { });
7290
7354
  }
7291
7355
  else if (((_e = db.cloud.options) === null || _e === void 0 ? void 0 : _e.databaseUrl) &&
@@ -7294,7 +7358,7 @@
7294
7358
  // There's no SW. Start SyncWorker instead.
7295
7359
  localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema);
7296
7360
  localSyncWorker.start();
7297
- triggerSync(db, 'push');
7361
+ triggerSync(db, changedUser ? 'pull' : 'push');
7298
7362
  }
7299
7363
  // Listen to online event and do sync.
7300
7364
  throwIfClosed();
@@ -7324,7 +7388,7 @@
7324
7388
  });
7325
7389
  }
7326
7390
  }
7327
- dexieCloud.version = '4.0.1-beta.35';
7391
+ dexieCloud.version = '4.0.1-beta.37';
7328
7392
  Dexie__default["default"].Cloud = dexieCloud;
7329
7393
 
7330
7394
  exports["default"] = dexieCloud;