dexie-cloud-addon 4.0.1-beta.34 → 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.
@@ -1,7 +1,7 @@
1
1
  import Dexie, { liveQuery, cmp } from 'dexie';
2
2
  import { BehaviorSubject, fromEvent, of, merge, from as from$1, Observable as Observable$1, Subscription as Subscription$1, Subject, combineLatest, map as map$1, share, timer as timer$1, throwError } from 'rxjs';
3
3
 
4
- /*! *****************************************************************************
4
+ /******************************************************************************
5
5
  Copyright (c) Microsoft Corporation.
6
6
 
7
7
  Permission to use, copy, modify, and/or distribute this software for any
@@ -88,7 +88,7 @@ function __spreadArray$1(to, from, pack) {
88
88
  ar[i] = from[i];
89
89
  }
90
90
  }
91
- return to.concat(ar || from);
91
+ return to.concat(ar || Array.prototype.slice.call(from));
92
92
  }
93
93
 
94
94
  /* ==========================================================================
@@ -101,14 +101,14 @@ function __spreadArray$1(to, from, pack) {
101
101
  *
102
102
  * ==========================================================================
103
103
  *
104
- * Version 4.0.1-beta.34, Mon Mar 27 2023
104
+ * Version 4.0.1-beta.36, Mon Apr 17 2023
105
105
  *
106
106
  * https://dexie.org
107
107
  *
108
108
  * Apache License Version 2.0, January 2004, http://www.apache.org/licenses/
109
109
  *
110
110
  */
111
- /*! *****************************************************************************
111
+ /******************************************************************************
112
112
  Copyright (c) Microsoft Corporation.
113
113
 
114
114
  Permission to use, copy, modify, and/or distribute this software for any
@@ -273,7 +273,7 @@ function __spreadArray(to, from, pack) {
273
273
  ar[i] = from[i];
274
274
  }
275
275
  }
276
- return to.concat(ar || from);
276
+ return to.concat(ar || Array.prototype.slice.call(from));
277
277
  }
278
278
  function __await(v) {
279
279
  return this instanceof __await ? (this.v = v, this) : new __await(v);
@@ -1400,7 +1400,6 @@ var AsyncAction = (function (_super) {
1400
1400
  return _this;
1401
1401
  }
1402
1402
  AsyncAction.prototype.schedule = function (state, delay) {
1403
- var _a;
1404
1403
  if (delay === void 0) {
1405
1404
  delay = 0;
1406
1405
  }
@@ -1415,7 +1414,7 @@ var AsyncAction = (function (_super) {
1415
1414
  }
1416
1415
  this.pending = true;
1417
1416
  this.delay = delay;
1418
- this.id = (_a = this.id) !== null && _a !== void 0 ? _a : this.requestAsyncId(scheduler, this.id, delay);
1417
+ this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);
1419
1418
  return this;
1420
1419
  };
1421
1420
  AsyncAction.prototype.requestAsyncId = function (scheduler, _id, delay) {
@@ -1431,9 +1430,7 @@ var AsyncAction = (function (_super) {
1431
1430
  if (delay != null && this.delay === delay && this.pending === false) {
1432
1431
  return id;
1433
1432
  }
1434
- if (id != null) {
1435
- intervalProvider.clearInterval(id);
1436
- }
1433
+ intervalProvider.clearInterval(id);
1437
1434
  return undefined;
1438
1435
  };
1439
1436
  AsyncAction.prototype.execute = function (state, delay) {
@@ -1512,6 +1509,7 @@ var AsyncScheduler = (function (_super) {
1512
1509
  var _this = _super.call(this, SchedulerAction, now) || this;
1513
1510
  _this.actions = [];
1514
1511
  _this._active = false;
1512
+ _this._scheduled = undefined;
1515
1513
  return _this;
1516
1514
  }
1517
1515
  AsyncScheduler.prototype.flush = function (action) {
@@ -1910,7 +1908,7 @@ function delayWhen(delayDurationSelector, subscriptionDelay) {
1910
1908
  return concat$1(subscriptionDelay.pipe(take(1), ignoreElements()), source.pipe(delayWhen(delayDurationSelector)));
1911
1909
  };
1912
1910
  }
1913
- return mergeMap(function (value, index) { return innerFrom(delayDurationSelector(value, index)).pipe(take(1), mapTo(value)); });
1911
+ return mergeMap(function (value, index) { return delayDurationSelector(value, index).pipe(take(1), mapTo(value)); });
1914
1912
  }
1915
1913
  function delay(due, scheduler) {
1916
1914
  if (scheduler === void 0) {
@@ -2396,13 +2394,22 @@ function userAuthenticate(context, fetchToken, userInteraction, hints) {
2396
2394
  var _k, privateKey, publicKey, publicKeySPKI, publicKeyPEM, response2, error_1;
2397
2395
  return __generator$1(this, function (_l) {
2398
2396
  switch (_l.label) {
2399
- case 0: return [4 /*yield*/, crypto.subtle.generateKey({
2400
- name: 'RSASSA-PKCS1-v1_5',
2401
- modulusLength: 2048,
2402
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
2403
- hash: { name: 'SHA-256' },
2404
- }, false, // Non-exportable...
2405
- ['sign', 'verify'])];
2397
+ case 0:
2398
+ if (!crypto.subtle) {
2399
+ if (typeof location !== 'undefined' && location.protocol === 'http:') {
2400
+ throw new Error("Dexie Cloud Addon needs to use WebCrypto, but your browser has disabled it due to being served from an insecure location. Please serve it from https or http://localhost:<port> (See https://stackoverflow.com/questions/46670556/how-to-enable-crypto-subtle-for-unsecure-origins-in-chrome/46671627#46671627)");
2401
+ }
2402
+ else {
2403
+ throw new Error("This browser does not support WebCrypto.");
2404
+ }
2405
+ }
2406
+ return [4 /*yield*/, crypto.subtle.generateKey({
2407
+ name: 'RSASSA-PKCS1-v1_5',
2408
+ modulusLength: 2048,
2409
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
2410
+ hash: { name: 'SHA-256' },
2411
+ }, false, // Non-exportable...
2412
+ ['sign', 'verify'])];
2406
2413
  case 1:
2407
2414
  _k = _l.sent(), privateKey = _k.privateKey, publicKey = _k.publicKey;
2408
2415
  if (!privateKey || !publicKey)
@@ -2451,7 +2458,7 @@ function userAuthenticate(context, fetchToken, userInteraction, hints) {
2451
2458
  type: 'error',
2452
2459
  messageCode: 'GENERIC_ERROR',
2453
2460
  message: "We're having a problem authenticating right now.",
2454
- messageParams: {}
2461
+ messageParams: {},
2455
2462
  }).catch(function () { })];
2456
2463
  case 8:
2457
2464
  _l.sent();
@@ -2717,7 +2724,7 @@ function setCurrentUser(db, user) {
2717
2724
  }
2718
2725
  function login(db, hints) {
2719
2726
  return __awaiter(this, void 0, void 0, function () {
2720
- var currentUser, context;
2727
+ var currentUser, context, e_6;
2721
2728
  return __generator$1(this, function (_k) {
2722
2729
  switch (_k.label) {
2723
2730
  case 0: return [4 /*yield*/, db.getCurrentUser()];
@@ -2733,7 +2740,7 @@ function login(db, hints) {
2733
2740
  }
2734
2741
  }
2735
2742
  // Already authenticated according to given hints.
2736
- return [2 /*return*/];
2743
+ return [2 /*return*/, false];
2737
2744
  }
2738
2745
  context = new AuthPersistedContext(db, {
2739
2746
  claims: {},
@@ -2742,16 +2749,31 @@ function login(db, hints) {
2742
2749
  return [4 /*yield*/, authenticate(db.cloud.options.databaseUrl, context, db.cloud.options.fetchTokens || otpFetchTokenCallback(db), db.cloud.userInteraction, hints)];
2743
2750
  case 2:
2744
2751
  _k.sent();
2745
- return [4 /*yield*/, context.save()];
2752
+ _k.label = 3;
2746
2753
  case 3:
2747
- _k.sent();
2748
- return [4 /*yield*/, setCurrentUser(db, context)];
2754
+ _k.trys.push([3, 5, , 6]);
2755
+ return [4 /*yield*/, context.save()];
2749
2756
  case 4:
2757
+ _k.sent();
2758
+ return [3 /*break*/, 6];
2759
+ case 5:
2760
+ e_6 = _k.sent();
2761
+ try {
2762
+ if (e_6.name === 'DataCloneError') {
2763
+ console.debug("Login context property names:", Object.keys(context));
2764
+ console.debug("Login context:", context);
2765
+ console.debug("Login context JSON:", JSON.stringify(context));
2766
+ }
2767
+ }
2768
+ catch (_a) { }
2769
+ throw e_6;
2770
+ case 6: return [4 /*yield*/, setCurrentUser(db, context)];
2771
+ case 7:
2750
2772
  _k.sent();
2751
2773
  // Make sure to resync as the new login will be authorized
2752
2774
  // for new realms.
2753
2775
  triggerSync(db, "pull");
2754
- return [2 /*return*/];
2776
+ return [2 /*return*/, true];
2755
2777
  }
2756
2778
  });
2757
2779
  });
@@ -2827,6 +2849,36 @@ var SWBroadcastChannel = /** @class */ (function () {
2827
2849
  };
2828
2850
  return SWBroadcastChannel;
2829
2851
  }());
2852
+ var events = globalThis['lbc-events'] || (globalThis['lbc-events'] = new Map());
2853
+ function addListener(name, listener) {
2854
+ if (events.has(name)) {
2855
+ events.get(name).push(listener);
2856
+ }
2857
+ else {
2858
+ events.set(name, [listener]);
2859
+ }
2860
+ }
2861
+ function removeListener(name, listener) {
2862
+ var listeners = events.get(name);
2863
+ if (listeners) {
2864
+ var idx = listeners.indexOf(listener);
2865
+ if (idx !== -1) {
2866
+ listeners.splice(idx, 1);
2867
+ }
2868
+ }
2869
+ }
2870
+ function dispatch(ev) {
2871
+ var listeners = events.get(ev.type);
2872
+ if (listeners) {
2873
+ listeners.forEach(function (listener) {
2874
+ try {
2875
+ listener(ev);
2876
+ }
2877
+ catch (_a) {
2878
+ }
2879
+ });
2880
+ }
2881
+ }
2830
2882
  var BroadcastedAndLocalEvent = /** @class */ (function (_super_1) {
2831
2883
  __extends$1(BroadcastedAndLocalEvent, _super_1);
2832
2884
  function BroadcastedAndLocalEvent(name) {
@@ -2842,16 +2894,24 @@ var BroadcastedAndLocalEvent = /** @class */ (function (_super_1) {
2842
2894
  subscriber.next(ev.data);
2843
2895
  }
2844
2896
  var unsubscribe;
2845
- self.addEventListener("lbc-".concat(name), onCustomEvent);
2846
- if (bc instanceof SWBroadcastChannel) {
2847
- unsubscribe = bc.subscribe(function (message) { return subscriber.next(message); });
2897
+ //self.addEventListener(`lbc-${name}`, onCustomEvent); // Fails in service workers
2898
+ addListener("lbc-".concat(name), onCustomEvent); // Works better in service worker
2899
+ try {
2900
+ if (bc instanceof SWBroadcastChannel) {
2901
+ unsubscribe = bc.subscribe(function (message) { return subscriber.next(message); });
2902
+ }
2903
+ else {
2904
+ console.debug("BroadcastedAndLocalEvent: bc.addEventListener()", name, "bc is a", bc);
2905
+ bc.addEventListener("message", onMessageEvent);
2906
+ }
2848
2907
  }
2849
- else {
2850
- console.debug("BroadcastedAndLocalEvent: bc.addEventListener()", name, "bc is a", bc);
2851
- bc.addEventListener("message", onMessageEvent);
2908
+ catch (err) {
2909
+ // Service workers might fail to subscribe outside its initial script.
2910
+ console.warn('Failed to subscribe to broadcast channel', err);
2852
2911
  }
2853
2912
  return function () {
2854
- self.removeEventListener("lbc-".concat(name), onCustomEvent);
2913
+ //self.removeEventListener(`lbc-${name}`, onCustomEvent);
2914
+ removeListener("lbc-".concat(name), onCustomEvent);
2855
2915
  if (bc instanceof SWBroadcastChannel) {
2856
2916
  unsubscribe();
2857
2917
  }
@@ -2868,7 +2928,8 @@ var BroadcastedAndLocalEvent = /** @class */ (function (_super_1) {
2868
2928
  console.debug("BroadcastedAndLocalEvent: bc.postMessage()", Object.assign({}, message), "bc is a", this.bc);
2869
2929
  this.bc.postMessage(message);
2870
2930
  var ev = new CustomEvent("lbc-".concat(this.name), { detail: message });
2871
- self.dispatchEvent(ev);
2931
+ //self.dispatchEvent(ev);
2932
+ dispatch(ev);
2872
2933
  };
2873
2934
  return BroadcastedAndLocalEvent;
2874
2935
  }(Observable$1));
@@ -4050,7 +4111,7 @@ function sync(db, options, schema, syncOptions) {
4050
4111
  return _sync
4051
4112
  .apply(this, arguments)
4052
4113
  .then(function () {
4053
- if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
4114
+ if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) { // && syncOptions?.purpose !== 'push') {
4054
4115
  db.syncStateChangedEvent.next({
4055
4116
  phase: 'in-sync',
4056
4117
  });
@@ -4108,7 +4169,7 @@ function _sync(db, options, schema, _k) {
4108
4169
  } : _k, isInitialSync = _l.isInitialSync, cancelToken = _l.cancelToken, justCheckIfNeeded = _l.justCheckIfNeeded, purpose = _l.purpose;
4109
4170
  var _a;
4110
4171
  return __awaiter(this, void 0, void 0, function () {
4111
- var databaseUrl, currentUser, tablesToSync, mutationTables, persistedSyncState, readyForSyncification, tablesToSyncify, doSyncify, _k, clientChangeSet, syncState, baseRevs, syncIsNeeded, latestRevisions, clientIdentity, res, done;
4172
+ var databaseUrl, currentUser, tablesToSync, mutationTables, persistedSyncState, readyForSyncification, tablesToSyncify, doSyncify, _k, clientChangeSet, syncState, baseRevs, pushSyncIsNeeded, latestRevisions, clientIdentity, res, done;
4112
4173
  var _this_1 = this;
4113
4174
  return __generator$1(this, function (_l) {
4114
4175
  switch (_l.label) {
@@ -4185,12 +4246,12 @@ function _sync(db, options, schema, _k) {
4185
4246
  }); })];
4186
4247
  case 5:
4187
4248
  _k = _l.sent(), clientChangeSet = _k[0], syncState = _k[1], baseRevs = _k[2];
4188
- syncIsNeeded = clientChangeSet.some(function (set) { return set.muts.some(function (mut) { return mut.keys.length > 0; }); });
4249
+ pushSyncIsNeeded = clientChangeSet.some(function (set) { return set.muts.some(function (mut) { return mut.keys.length > 0; }); });
4189
4250
  if (justCheckIfNeeded) {
4190
- console.debug('Sync is needed:', syncIsNeeded);
4191
- return [2 /*return*/, syncIsNeeded];
4251
+ console.debug('Sync is needed:', pushSyncIsNeeded);
4252
+ return [2 /*return*/, pushSyncIsNeeded];
4192
4253
  }
4193
- if (purpose === 'push' && !syncIsNeeded) {
4254
+ if (purpose === 'push' && !pushSyncIsNeeded) {
4194
4255
  // The purpose of this request was to push changes
4195
4256
  return [2 /*return*/, false];
4196
4257
  }
@@ -4365,6 +4426,7 @@ function _sync(db, options, schema, _k) {
4365
4426
  case 8: return [2 /*return*/, _l.sent()];
4366
4427
  case 9:
4367
4428
  console.debug('SYNC DONE', { isInitialSync: isInitialSync });
4429
+ db.syncCompleteEvent.next();
4368
4430
  return [2 /*return*/, false]; // Not needed anymore
4369
4431
  }
4370
4432
  });
@@ -4758,6 +4820,7 @@ function DexieCloudDB(dx) {
4758
4820
  if (!db) {
4759
4821
  var localSyncEvent = new Subject();
4760
4822
  var syncStateChangedEvent_1 = new BroadcastedAndLocalEvent("syncstatechanged-".concat(dx.name));
4823
+ var syncCompleteEvent_1 = new BroadcastedAndLocalEvent("synccomplete-".concat(dx.name));
4761
4824
  localSyncEvent['id'] = ++static_counter;
4762
4825
  var initiallySynced_1 = false;
4763
4826
  db = {
@@ -4801,6 +4864,9 @@ function DexieCloudDB(dx) {
4801
4864
  get syncStateChangedEvent() {
4802
4865
  return syncStateChangedEvent_1;
4803
4866
  },
4867
+ get syncCompleteEvent() {
4868
+ return syncCompleteEvent_1;
4869
+ },
4804
4870
  dx: dx,
4805
4871
  };
4806
4872
  var helperMethods = {
@@ -4833,6 +4899,7 @@ function DexieCloudDB(dx) {
4833
4899
  },
4834
4900
  reconfigure: function () {
4835
4901
  syncStateChangedEvent_1 = new BroadcastedAndLocalEvent("syncstatechanged-".concat(dx.name));
4902
+ syncCompleteEvent_1 = new BroadcastedAndLocalEvent("synccomplete-".concat(dx.name));
4836
4903
  },
4837
4904
  };
4838
4905
  Object.assign(db, helperMethods);
@@ -5766,6 +5833,15 @@ function connectWebSocket(db) {
5766
5833
  switchMap(function (syncState) { return db.cloud.currentUser.pipe(map(function (userLogin) { return [userLogin, syncState]; })); }), switchMap(function (_k) {
5767
5834
  var userLogin = _k[0], syncState = _k[1];
5768
5835
  return userIsReallyActive.pipe(map(function (isActive) { return [isActive ? userLogin : null, syncState]; }));
5836
+ }), switchMap(function (_k) {
5837
+ var userLogin = _k[0], syncState = _k[1];
5838
+ if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
5839
+ // We're in an in-between state when user is logged in but the user's realms are not yet synced.
5840
+ // Don't make this change reconnect the websocket just yet. Wait till syncState is updated
5841
+ // to iclude the user's realm.
5842
+ 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]; }));
5843
+ }
5844
+ return new BehaviorSubject([userLogin, syncState]);
5769
5845
  }), switchMap(function (_k) {
5770
5846
  var userLogin = _k[0], syncState = _k[1];
5771
5847
  return __awaiter(_this_1, void 0, void 0, function () { var _k; return __generator$1(this, function (_l) {
@@ -6961,8 +7037,9 @@ function dexieCloud(dexie) {
6961
7037
  localSyncWorker = null;
6962
7038
  currentUserEmitter.next(UNAUTHORIZED_USER);
6963
7039
  });
7040
+ var syncComplete = new Subject();
6964
7041
  dexie.cloud = {
6965
- version: '4.0.1-beta.34',
7042
+ version: '4.0.1-beta.36',
6966
7043
  options: Object.assign({}, DEFAULT_OPTIONS),
6967
7044
  schema: null,
6968
7045
  get currentUserId() {
@@ -6973,6 +7050,9 @@ function dexieCloud(dexie) {
6973
7050
  phase: 'initial',
6974
7051
  status: 'not-started',
6975
7052
  }),
7053
+ events: {
7054
+ syncComplete: syncComplete,
7055
+ },
6976
7056
  persistedSyncState: new BehaviorSubject(undefined),
6977
7057
  userInteraction: new BehaviorSubject(undefined),
6978
7058
  webSocketStatus: new BehaviorSubject('not-started'),
@@ -7090,7 +7170,7 @@ function dexieCloud(dexie) {
7090
7170
  function onDbReady(dexie) {
7091
7171
  var _a, _b, _c, _d, _e, _f, _g;
7092
7172
  return __awaiter(this, void 0, void 0, function () {
7093
- var db, swRegistrations, _k, initiallySynced;
7173
+ var db, swRegistrations, _k, initiallySynced, changedUser;
7094
7174
  var _this_1 = this;
7095
7175
  return __generator$1(this, function (_l) {
7096
7176
  switch (_l.label) {
@@ -7106,6 +7186,8 @@ function dexieCloud(dexie) {
7106
7186
  if (!db.cloud.isServiceWorkerDB) {
7107
7187
  subscriptions.push(computeSyncState(db).subscribe(dexie.cloud.syncState));
7108
7188
  }
7189
+ // Forward db.syncCompleteEvent to be publicly consumable via db.cloud.events.syncComplete:
7190
+ subscriptions.push(db.syncCompleteEvent.subscribe(syncComplete));
7109
7191
  //verifyConfig(db.cloud.options); Not needed (yet at least!)
7110
7192
  // Verify the user has allowed version increment.
7111
7193
  if (!db.tables.every(function (table) { return table.core; })) {
@@ -7245,10 +7327,11 @@ function dexieCloud(dexie) {
7245
7327
  _l.sent();
7246
7328
  _l.label = 8;
7247
7329
  case 8:
7330
+ changedUser = false;
7248
7331
  if (!((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.requireAuth)) return [3 /*break*/, 10];
7249
7332
  return [4 /*yield*/, login(db)];
7250
7333
  case 9:
7251
- _l.sent();
7334
+ changedUser = _l.sent();
7252
7335
  _l.label = 10;
7253
7336
  case 10:
7254
7337
  if (localSyncWorker)
@@ -7256,7 +7339,7 @@ function dexieCloud(dexie) {
7256
7339
  localSyncWorker = null;
7257
7340
  throwIfClosed();
7258
7341
  if (db.cloud.usingServiceWorker && ((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl)) {
7259
- registerSyncEvent(db, 'push').catch(function () { });
7342
+ registerSyncEvent(db, changedUser ? 'pull' : 'push').catch(function () { });
7260
7343
  registerPeriodicSyncEvent(db).catch(function () { });
7261
7344
  }
7262
7345
  else if (((_e = db.cloud.options) === null || _e === void 0 ? void 0 : _e.databaseUrl) &&
@@ -7265,7 +7348,7 @@ function dexieCloud(dexie) {
7265
7348
  // There's no SW. Start SyncWorker instead.
7266
7349
  localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema);
7267
7350
  localSyncWorker.start();
7268
- triggerSync(db, 'push');
7351
+ triggerSync(db, changedUser ? 'pull' : 'push');
7269
7352
  }
7270
7353
  // Listen to online event and do sync.
7271
7354
  throwIfClosed();
@@ -7295,7 +7378,7 @@ function dexieCloud(dexie) {
7295
7378
  });
7296
7379
  }
7297
7380
  }
7298
- dexieCloud.version = '4.0.1-beta.34';
7381
+ dexieCloud.version = '4.0.1-beta.36';
7299
7382
  Dexie.Cloud = dexieCloud;
7300
7383
 
7301
7384
  export { dexieCloud as default, dexieCloud, getTiedObjectId, getTiedRealmId };