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.
- package/dist/modern/dexie-cloud-addon.js +111 -31
- package/dist/modern/dexie-cloud-addon.js.map +1 -1
- package/dist/modern/dexie-cloud-addon.min.js +1 -1
- package/dist/modern/dexie-cloud-addon.min.js.map +1 -1
- package/dist/modern/service-worker.js +110 -30
- package/dist/modern/service-worker.js.map +1 -1
- package/dist/modern/service-worker.min.js +1 -1
- package/dist/modern/service-worker.min.js.map +1 -1
- package/dist/module-es5/dexie-cloud-addon.js +128 -45
- package/dist/module-es5/dexie-cloud-addon.js.map +1 -1
- package/dist/module-es5/dexie-cloud-addon.min.js +1 -1
- package/dist/module-es5/dexie-cloud-addon.min.js.map +1 -1
- package/dist/types/DexieCloudAPI.d.ts +3 -0
- package/dist/types/authentication/login.d.ts +1 -1
- package/dist/types/db/DexieCloudDB.d.ts +3 -2
- package/dist/types/sync/getTablesToSyncify.d.ts +1 -1
- package/dist/umd/dexie-cloud-addon.js +128 -45
- package/dist/umd/dexie-cloud-addon.js.map +1 -1
- package/dist/umd/dexie-cloud-addon.min.js +1 -1
- package/dist/umd/dexie-cloud-addon.min.js.map +1 -1
- package/dist/umd/service-worker.js +110 -30
- package/dist/umd/service-worker.js.map +1 -1
- package/dist/umd/service-worker.min.js +1 -1
- package/dist/umd/service-worker.min.js.map +1 -1
- package/dist/umd-modern/dexie-cloud-addon.js +108 -28
- package/dist/umd-modern/dexie-cloud-addon.js.map +1 -1
- package/dist/umd-modern/dexie-cloud-addon.min.js +1 -1
- package/dist/umd-modern/dexie-cloud-addon.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Dexie, { cmp, liveQuery } from 'dexie';
|
|
2
2
|
import { Observable as Observable$1, BehaviorSubject, Subject, fromEvent, of, merge, Subscription as Subscription$1, from as from$1, throwError, combineLatest, map as map$1, share, timer as timer$1 } 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
|
|
@@ -106,7 +106,7 @@ function __spreadArray(to, from, pack) {
|
|
|
106
106
|
ar[i] = from[i];
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
return to.concat(ar || from);
|
|
109
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
function __await(v) {
|
|
@@ -203,6 +203,36 @@ class SWBroadcastChannel {
|
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
const events = globalThis['lbc-events'] || (globalThis['lbc-events'] = new Map());
|
|
207
|
+
function addListener(name, listener) {
|
|
208
|
+
if (events.has(name)) {
|
|
209
|
+
events.get(name).push(listener);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
events.set(name, [listener]);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function removeListener(name, listener) {
|
|
216
|
+
const listeners = events.get(name);
|
|
217
|
+
if (listeners) {
|
|
218
|
+
const idx = listeners.indexOf(listener);
|
|
219
|
+
if (idx !== -1) {
|
|
220
|
+
listeners.splice(idx, 1);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function dispatch(ev) {
|
|
225
|
+
const listeners = events.get(ev.type);
|
|
226
|
+
if (listeners) {
|
|
227
|
+
listeners.forEach(listener => {
|
|
228
|
+
try {
|
|
229
|
+
listener(ev);
|
|
230
|
+
}
|
|
231
|
+
catch (_a) {
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
206
236
|
class BroadcastedAndLocalEvent extends Observable$1 {
|
|
207
237
|
constructor(name) {
|
|
208
238
|
const bc = typeof BroadcastChannel === "undefined"
|
|
@@ -216,16 +246,24 @@ class BroadcastedAndLocalEvent extends Observable$1 {
|
|
|
216
246
|
subscriber.next(ev.data);
|
|
217
247
|
}
|
|
218
248
|
let unsubscribe;
|
|
219
|
-
self.addEventListener(`lbc-${name}`, onCustomEvent);
|
|
220
|
-
|
|
221
|
-
|
|
249
|
+
//self.addEventListener(`lbc-${name}`, onCustomEvent); // Fails in service workers
|
|
250
|
+
addListener(`lbc-${name}`, onCustomEvent); // Works better in service worker
|
|
251
|
+
try {
|
|
252
|
+
if (bc instanceof SWBroadcastChannel) {
|
|
253
|
+
unsubscribe = bc.subscribe(message => subscriber.next(message));
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
console.debug("BroadcastedAndLocalEvent: bc.addEventListener()", name, "bc is a", bc);
|
|
257
|
+
bc.addEventListener("message", onMessageEvent);
|
|
258
|
+
}
|
|
222
259
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
260
|
+
catch (err) {
|
|
261
|
+
// Service workers might fail to subscribe outside its initial script.
|
|
262
|
+
console.warn('Failed to subscribe to broadcast channel', err);
|
|
226
263
|
}
|
|
227
264
|
return () => {
|
|
228
|
-
self.removeEventListener(`lbc-${name}`, onCustomEvent);
|
|
265
|
+
//self.removeEventListener(`lbc-${name}`, onCustomEvent);
|
|
266
|
+
removeListener(`lbc-${name}`, onCustomEvent);
|
|
229
267
|
if (bc instanceof SWBroadcastChannel) {
|
|
230
268
|
unsubscribe();
|
|
231
269
|
}
|
|
@@ -241,7 +279,8 @@ class BroadcastedAndLocalEvent extends Observable$1 {
|
|
|
241
279
|
console.debug("BroadcastedAndLocalEvent: bc.postMessage()", Object.assign({}, message), "bc is a", this.bc);
|
|
242
280
|
this.bc.postMessage(message);
|
|
243
281
|
const ev = new CustomEvent(`lbc-${this.name}`, { detail: message });
|
|
244
|
-
self.dispatchEvent(ev);
|
|
282
|
+
//self.dispatchEvent(ev);
|
|
283
|
+
dispatch(ev);
|
|
245
284
|
}
|
|
246
285
|
}
|
|
247
286
|
|
|
@@ -1089,7 +1128,6 @@ var AsyncAction = (function (_super) {
|
|
|
1089
1128
|
return _this;
|
|
1090
1129
|
}
|
|
1091
1130
|
AsyncAction.prototype.schedule = function (state, delay) {
|
|
1092
|
-
var _a;
|
|
1093
1131
|
if (delay === void 0) { delay = 0; }
|
|
1094
1132
|
if (this.closed) {
|
|
1095
1133
|
return this;
|
|
@@ -1102,7 +1140,7 @@ var AsyncAction = (function (_super) {
|
|
|
1102
1140
|
}
|
|
1103
1141
|
this.pending = true;
|
|
1104
1142
|
this.delay = delay;
|
|
1105
|
-
this.id =
|
|
1143
|
+
this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);
|
|
1106
1144
|
return this;
|
|
1107
1145
|
};
|
|
1108
1146
|
AsyncAction.prototype.requestAsyncId = function (scheduler, _id, delay) {
|
|
@@ -1114,9 +1152,7 @@ var AsyncAction = (function (_super) {
|
|
|
1114
1152
|
if (delay != null && this.delay === delay && this.pending === false) {
|
|
1115
1153
|
return id;
|
|
1116
1154
|
}
|
|
1117
|
-
|
|
1118
|
-
intervalProvider.clearInterval(id);
|
|
1119
|
-
}
|
|
1155
|
+
intervalProvider.clearInterval(id);
|
|
1120
1156
|
return undefined;
|
|
1121
1157
|
};
|
|
1122
1158
|
AsyncAction.prototype.execute = function (state, delay) {
|
|
@@ -1192,6 +1228,7 @@ var AsyncScheduler = (function (_super) {
|
|
|
1192
1228
|
var _this = _super.call(this, SchedulerAction, now) || this;
|
|
1193
1229
|
_this.actions = [];
|
|
1194
1230
|
_this._active = false;
|
|
1231
|
+
_this._scheduled = undefined;
|
|
1195
1232
|
return _this;
|
|
1196
1233
|
}
|
|
1197
1234
|
AsyncScheduler.prototype.flush = function (action) {
|
|
@@ -1601,7 +1638,7 @@ function delayWhen(delayDurationSelector, subscriptionDelay) {
|
|
|
1601
1638
|
return concat$1(subscriptionDelay.pipe(take(1), ignoreElements()), source.pipe(delayWhen(delayDurationSelector)));
|
|
1602
1639
|
};
|
|
1603
1640
|
}
|
|
1604
|
-
return mergeMap(function (value, index) { return
|
|
1641
|
+
return mergeMap(function (value, index) { return delayDurationSelector(value, index).pipe(take(1), mapTo(value)); });
|
|
1605
1642
|
}
|
|
1606
1643
|
|
|
1607
1644
|
function delay(due, scheduler) {
|
|
@@ -2485,6 +2522,14 @@ function refreshAccessToken(url, login) {
|
|
|
2485
2522
|
}
|
|
2486
2523
|
function userAuthenticate(context, fetchToken, userInteraction, hints) {
|
|
2487
2524
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2525
|
+
if (!crypto.subtle) {
|
|
2526
|
+
if (typeof location !== 'undefined' && location.protocol === 'http:') {
|
|
2527
|
+
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)`);
|
|
2528
|
+
}
|
|
2529
|
+
else {
|
|
2530
|
+
throw new Error(`This browser does not support WebCrypto.`);
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2488
2533
|
const { privateKey, publicKey } = yield crypto.subtle.generateKey({
|
|
2489
2534
|
name: 'RSASSA-PKCS1-v1_5',
|
|
2490
2535
|
modulusLength: 2048,
|
|
@@ -2530,7 +2575,7 @@ function userAuthenticate(context, fetchToken, userInteraction, hints) {
|
|
|
2530
2575
|
type: 'error',
|
|
2531
2576
|
messageCode: 'GENERIC_ERROR',
|
|
2532
2577
|
message: `We're having a problem authenticating right now.`,
|
|
2533
|
-
messageParams: {}
|
|
2578
|
+
messageParams: {},
|
|
2534
2579
|
}).catch(() => { });
|
|
2535
2580
|
throw error;
|
|
2536
2581
|
}
|
|
@@ -3383,7 +3428,7 @@ function sync(db, options, schema, syncOptions) {
|
|
|
3383
3428
|
return _sync
|
|
3384
3429
|
.apply(this, arguments)
|
|
3385
3430
|
.then(() => {
|
|
3386
|
-
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
|
|
3431
|
+
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) { // && syncOptions?.purpose !== 'push') {
|
|
3387
3432
|
db.syncStateChangedEvent.next({
|
|
3388
3433
|
phase: 'in-sync',
|
|
3389
3434
|
});
|
|
@@ -3482,12 +3527,12 @@ function _sync(db, options, schema, { isInitialSync, cancelToken, justCheckIfNee
|
|
|
3482
3527
|
}
|
|
3483
3528
|
return [clientChanges, syncState, baseRevs];
|
|
3484
3529
|
}));
|
|
3485
|
-
const
|
|
3530
|
+
const pushSyncIsNeeded = clientChangeSet.some((set) => set.muts.some((mut) => mut.keys.length > 0));
|
|
3486
3531
|
if (justCheckIfNeeded) {
|
|
3487
|
-
console.debug('Sync is needed:',
|
|
3488
|
-
return
|
|
3532
|
+
console.debug('Sync is needed:', pushSyncIsNeeded);
|
|
3533
|
+
return pushSyncIsNeeded;
|
|
3489
3534
|
}
|
|
3490
|
-
if (purpose === 'push' && !
|
|
3535
|
+
if (purpose === 'push' && !pushSyncIsNeeded) {
|
|
3491
3536
|
// The purpose of this request was to push changes
|
|
3492
3537
|
return false;
|
|
3493
3538
|
}
|
|
@@ -3605,6 +3650,7 @@ function _sync(db, options, schema, { isInitialSync, cancelToken, justCheckIfNee
|
|
|
3605
3650
|
return yield _sync(db, options, schema, { isInitialSync, cancelToken });
|
|
3606
3651
|
}
|
|
3607
3652
|
console.debug('SYNC DONE', { isInitialSync });
|
|
3653
|
+
db.syncCompleteEvent.next();
|
|
3608
3654
|
return false; // Not needed anymore
|
|
3609
3655
|
});
|
|
3610
3656
|
}
|
|
@@ -3884,6 +3930,7 @@ function DexieCloudDB(dx) {
|
|
|
3884
3930
|
if (!db) {
|
|
3885
3931
|
const localSyncEvent = new Subject();
|
|
3886
3932
|
let syncStateChangedEvent = new BroadcastedAndLocalEvent(`syncstatechanged-${dx.name}`);
|
|
3933
|
+
let syncCompleteEvent = new BroadcastedAndLocalEvent(`synccomplete-${dx.name}`);
|
|
3887
3934
|
localSyncEvent['id'] = ++static_counter;
|
|
3888
3935
|
let initiallySynced = false;
|
|
3889
3936
|
db = {
|
|
@@ -3927,6 +3974,9 @@ function DexieCloudDB(dx) {
|
|
|
3927
3974
|
get syncStateChangedEvent() {
|
|
3928
3975
|
return syncStateChangedEvent;
|
|
3929
3976
|
},
|
|
3977
|
+
get syncCompleteEvent() {
|
|
3978
|
+
return syncCompleteEvent;
|
|
3979
|
+
},
|
|
3930
3980
|
dx,
|
|
3931
3981
|
};
|
|
3932
3982
|
const helperMethods = {
|
|
@@ -3958,6 +4008,7 @@ function DexieCloudDB(dx) {
|
|
|
3958
4008
|
},
|
|
3959
4009
|
reconfigure() {
|
|
3960
4010
|
syncStateChangedEvent = new BroadcastedAndLocalEvent(`syncstatechanged-${dx.name}`);
|
|
4011
|
+
syncCompleteEvent = new BroadcastedAndLocalEvent(`synccomplete-${dx.name}`);
|
|
3961
4012
|
},
|
|
3962
4013
|
};
|
|
3963
4014
|
Object.assign(db, helperMethods);
|
|
@@ -4172,18 +4223,32 @@ function login(db, hints) {
|
|
|
4172
4223
|
}
|
|
4173
4224
|
}
|
|
4174
4225
|
// Already authenticated according to given hints.
|
|
4175
|
-
return;
|
|
4226
|
+
return false;
|
|
4176
4227
|
}
|
|
4177
4228
|
const context = new AuthPersistedContext(db, {
|
|
4178
4229
|
claims: {},
|
|
4179
4230
|
lastLogin: new Date(0),
|
|
4180
4231
|
});
|
|
4181
4232
|
yield authenticate(db.cloud.options.databaseUrl, context, db.cloud.options.fetchTokens || otpFetchTokenCallback(db), db.cloud.userInteraction, hints);
|
|
4182
|
-
|
|
4233
|
+
try {
|
|
4234
|
+
yield context.save();
|
|
4235
|
+
}
|
|
4236
|
+
catch (e) {
|
|
4237
|
+
try {
|
|
4238
|
+
if (e.name === 'DataCloneError') {
|
|
4239
|
+
console.debug(`Login context property names:`, Object.keys(context));
|
|
4240
|
+
console.debug(`Login context:`, context);
|
|
4241
|
+
console.debug(`Login context JSON:`, JSON.stringify(context));
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
catch (_a) { }
|
|
4245
|
+
throw e;
|
|
4246
|
+
}
|
|
4183
4247
|
yield setCurrentUser(db, context);
|
|
4184
4248
|
// Make sure to resync as the new login will be authorized
|
|
4185
4249
|
// for new realms.
|
|
4186
4250
|
triggerSync(db, "pull");
|
|
4251
|
+
return true;
|
|
4187
4252
|
});
|
|
4188
4253
|
}
|
|
4189
4254
|
|
|
@@ -5076,7 +5141,15 @@ function connectWebSocket(db) {
|
|
|
5076
5141
|
function createObservable() {
|
|
5077
5142
|
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.
|
|
5078
5143
|
take(1), // Don't continue waking up whenever syncState change
|
|
5079
|
-
switchMap((syncState) => db.cloud.currentUser.pipe(map((userLogin) => [userLogin, syncState]))), switchMap(([userLogin, syncState]) => userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]))), switchMap(([userLogin, syncState]) =>
|
|
5144
|
+
switchMap((syncState) => db.cloud.currentUser.pipe(map((userLogin) => [userLogin, syncState]))), switchMap(([userLogin, syncState]) => userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]))), switchMap(([userLogin, syncState]) => {
|
|
5145
|
+
if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
|
|
5146
|
+
// We're in an in-between state when user is logged in but the user's realms are not yet synced.
|
|
5147
|
+
// Don't make this change reconnect the websocket just yet. Wait till syncState is updated
|
|
5148
|
+
// to iclude the user's realm.
|
|
5149
|
+
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]));
|
|
5150
|
+
}
|
|
5151
|
+
return new BehaviorSubject([userLogin, syncState]);
|
|
5152
|
+
}), switchMap(([userLogin, syncState]) => __awaiter(this, void 0, void 0, function* () { return [userLogin, yield computeRealmSetHash(syncState)]; })), switchMap(([userLogin, realmSetHash]) =>
|
|
5080
5153
|
// Let server end query changes from last entry of same client-ID and forward.
|
|
5081
5154
|
// If no new entries, server won't bother the client. If new entries, server sends only those
|
|
5082
5155
|
// and the baseRev of the last from same client-ID.
|
|
@@ -5938,8 +6011,9 @@ function dexieCloud(dexie) {
|
|
|
5938
6011
|
localSyncWorker = null;
|
|
5939
6012
|
currentUserEmitter.next(UNAUTHORIZED_USER);
|
|
5940
6013
|
});
|
|
6014
|
+
const syncComplete = new Subject();
|
|
5941
6015
|
dexie.cloud = {
|
|
5942
|
-
version: '4.0.1-beta.
|
|
6016
|
+
version: '4.0.1-beta.36',
|
|
5943
6017
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
5944
6018
|
schema: null,
|
|
5945
6019
|
get currentUserId() {
|
|
@@ -5950,6 +6024,9 @@ function dexieCloud(dexie) {
|
|
|
5950
6024
|
phase: 'initial',
|
|
5951
6025
|
status: 'not-started',
|
|
5952
6026
|
}),
|
|
6027
|
+
events: {
|
|
6028
|
+
syncComplete,
|
|
6029
|
+
},
|
|
5953
6030
|
persistedSyncState: new BehaviorSubject(undefined),
|
|
5954
6031
|
userInteraction: new BehaviorSubject(undefined),
|
|
5955
6032
|
webSocketStatus: new BehaviorSubject('not-started'),
|
|
@@ -6043,6 +6120,8 @@ function dexieCloud(dexie) {
|
|
|
6043
6120
|
if (!db.cloud.isServiceWorkerDB) {
|
|
6044
6121
|
subscriptions.push(computeSyncState(db).subscribe(dexie.cloud.syncState));
|
|
6045
6122
|
}
|
|
6123
|
+
// Forward db.syncCompleteEvent to be publicly consumable via db.cloud.events.syncComplete:
|
|
6124
|
+
subscriptions.push(db.syncCompleteEvent.subscribe(syncComplete));
|
|
6046
6125
|
//verifyConfig(db.cloud.options); Not needed (yet at least!)
|
|
6047
6126
|
// Verify the user has allowed version increment.
|
|
6048
6127
|
if (!db.tables.every((table) => table.core)) {
|
|
@@ -6150,15 +6229,16 @@ function dexieCloud(dexie) {
|
|
|
6150
6229
|
]).toPromise();
|
|
6151
6230
|
}
|
|
6152
6231
|
// HERE: If requireAuth, do athentication now.
|
|
6232
|
+
let changedUser = false;
|
|
6153
6233
|
if ((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.requireAuth) {
|
|
6154
|
-
yield login(db);
|
|
6234
|
+
changedUser = yield login(db);
|
|
6155
6235
|
}
|
|
6156
6236
|
if (localSyncWorker)
|
|
6157
6237
|
localSyncWorker.stop();
|
|
6158
6238
|
localSyncWorker = null;
|
|
6159
6239
|
throwIfClosed();
|
|
6160
6240
|
if (db.cloud.usingServiceWorker && ((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl)) {
|
|
6161
|
-
registerSyncEvent(db, 'push').catch(() => { });
|
|
6241
|
+
registerSyncEvent(db, changedUser ? 'pull' : 'push').catch(() => { });
|
|
6162
6242
|
registerPeriodicSyncEvent(db).catch(() => { });
|
|
6163
6243
|
}
|
|
6164
6244
|
else if (((_e = db.cloud.options) === null || _e === void 0 ? void 0 : _e.databaseUrl) &&
|
|
@@ -6167,7 +6247,7 @@ function dexieCloud(dexie) {
|
|
|
6167
6247
|
// There's no SW. Start SyncWorker instead.
|
|
6168
6248
|
localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema);
|
|
6169
6249
|
localSyncWorker.start();
|
|
6170
|
-
triggerSync(db, 'push');
|
|
6250
|
+
triggerSync(db, changedUser ? 'pull' : 'push');
|
|
6171
6251
|
}
|
|
6172
6252
|
// Listen to online event and do sync.
|
|
6173
6253
|
throwIfClosed();
|
|
@@ -6194,7 +6274,7 @@ function dexieCloud(dexie) {
|
|
|
6194
6274
|
});
|
|
6195
6275
|
}
|
|
6196
6276
|
}
|
|
6197
|
-
dexieCloud.version = '4.0.1-beta.
|
|
6277
|
+
dexieCloud.version = '4.0.1-beta.36';
|
|
6198
6278
|
Dexie.Cloud = dexieCloud;
|
|
6199
6279
|
|
|
6200
6280
|
// In case the SW lives for a while, let it reuse already opened connections:
|