dexie-cloud-addon 4.1.0-alpha.9 → 4.1.0-beta.25
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/DexieCloudOptions.d.ts +3 -0
- package/dist/modern/TSON.d.ts +1 -1
- package/dist/modern/db/entities/PersistedSyncState.d.ts +1 -0
- package/dist/modern/define-ydoc-trigger.d.ts +2 -0
- package/dist/modern/dexie-cloud-addon.d.ts +1 -0
- package/dist/modern/dexie-cloud-addon.js +623 -260
- 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/getInvitesObservable.d.ts +11 -11
- package/dist/modern/service-worker.js +465 -258
- 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/modern/yjs/YDexieCloudSyncState.d.ts +0 -1
- package/dist/modern/yjs/applyYMessages.d.ts +5 -1
- package/dist/modern/yjs/reopenDocSignal.d.ts +10 -0
- package/dist/modern/yjs/updateYSyncStates.d.ts +1 -1
- package/dist/umd/DexieCloudOptions.d.ts +3 -0
- package/dist/umd/TSON.d.ts +1 -1
- package/dist/umd/db/entities/PersistedSyncState.d.ts +1 -0
- package/dist/umd/define-ydoc-trigger.d.ts +2 -0
- package/dist/umd/dexie-cloud-addon.d.ts +1 -0
- package/dist/umd/dexie-cloud-addon.js +621 -257
- 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/getInvitesObservable.d.ts +11 -11
- package/dist/umd/service-worker.js +463 -256
- 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/yjs/YDexieCloudSyncState.d.ts +0 -1
- package/dist/umd/yjs/applyYMessages.d.ts +5 -1
- package/dist/umd/yjs/reopenDocSignal.d.ts +10 -0
- package/dist/umd/yjs/updateYSyncStates.d.ts +1 -1
- package/package.json +6 -5
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.1.0-
|
|
11
|
+
* Version 4.1.0-beta.25, Wed Dec 04 2024
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -1768,8 +1768,8 @@
|
|
|
1768
1768
|
});
|
|
1769
1769
|
}
|
|
1770
1770
|
function registerPeriodicSyncEvent(db) {
|
|
1771
|
-
var _a;
|
|
1772
1771
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1772
|
+
var _a;
|
|
1773
1773
|
try {
|
|
1774
1774
|
// Register periodicSync event to SW:
|
|
1775
1775
|
// @ts-ignore
|
|
@@ -1834,8 +1834,8 @@
|
|
|
1834
1834
|
return btoa(strs.join(""));
|
|
1835
1835
|
};
|
|
1836
1836
|
|
|
1837
|
-
function computeRealmSetHash(
|
|
1838
|
-
return __awaiter(this,
|
|
1837
|
+
function computeRealmSetHash(_a) {
|
|
1838
|
+
return __awaiter(this, arguments, void 0, function* ({ realms, inviteRealms, }) {
|
|
1839
1839
|
const data = JSON.stringify([
|
|
1840
1840
|
...realms.map((realmId) => ({ realmId, accepted: true })),
|
|
1841
1841
|
...inviteRealms.map((realmId) => ({ realmId, accepted: false })),
|
|
@@ -1871,8 +1871,8 @@
|
|
|
1871
1871
|
return concat.apply([], a);
|
|
1872
1872
|
}
|
|
1873
1873
|
|
|
1874
|
-
function listClientChanges(
|
|
1875
|
-
return __awaiter(this,
|
|
1874
|
+
function listClientChanges(mutationTables_1, db_1) {
|
|
1875
|
+
return __awaiter(this, arguments, void 0, function* (mutationTables, db, { since = {}, limit = Infinity } = {}) {
|
|
1876
1876
|
const allMutsOnTables = yield Promise.all(mutationTables.map((mutationTable) => __awaiter(this, void 0, void 0, function* () {
|
|
1877
1877
|
const tableName = getTableFromMutationTable(mutationTable.name);
|
|
1878
1878
|
const lastRevision = since[tableName];
|
|
@@ -2757,13 +2757,20 @@
|
|
|
2757
2757
|
function encodeYMessage(msg) {
|
|
2758
2758
|
const encoder = new Encoder();
|
|
2759
2759
|
writeVarString(encoder, msg.type);
|
|
2760
|
-
|
|
2761
|
-
|
|
2760
|
+
if ('table' in msg)
|
|
2761
|
+
writeVarString(encoder, msg.table);
|
|
2762
|
+
if ('prop' in msg)
|
|
2763
|
+
writeVarString(encoder, msg.prop);
|
|
2762
2764
|
switch (msg.type) {
|
|
2763
2765
|
case 'u-ack':
|
|
2764
2766
|
case 'u-reject':
|
|
2765
2767
|
writeBigUint64(encoder, BigInt(msg.i));
|
|
2766
2768
|
break;
|
|
2769
|
+
case 'outdated-server-rev':
|
|
2770
|
+
break;
|
|
2771
|
+
case 'y-complete-sync-done':
|
|
2772
|
+
writeVarString(encoder, msg.yServerRev);
|
|
2773
|
+
break;
|
|
2767
2774
|
default:
|
|
2768
2775
|
writeAny(encoder, msg.k);
|
|
2769
2776
|
switch (msg.type) {
|
|
@@ -3107,6 +3114,12 @@
|
|
|
3107
3114
|
function decodeYMessage(a) {
|
|
3108
3115
|
const decoder = new Decoder(a);
|
|
3109
3116
|
const type = readVarString(decoder);
|
|
3117
|
+
if (type === 'outdated-server-rev') {
|
|
3118
|
+
return { type };
|
|
3119
|
+
}
|
|
3120
|
+
if (type === 'y-complete-sync-done') {
|
|
3121
|
+
return { type, yServerRev: readVarString(decoder) };
|
|
3122
|
+
}
|
|
3110
3123
|
const table = readVarString(decoder);
|
|
3111
3124
|
const prop = readVarString(decoder);
|
|
3112
3125
|
switch (type) {
|
|
@@ -3519,8 +3532,8 @@
|
|
|
3519
3532
|
}
|
|
3520
3533
|
|
|
3521
3534
|
function loadAccessToken(db) {
|
|
3522
|
-
var _a, _b, _c;
|
|
3523
3535
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3536
|
+
var _a, _b, _c;
|
|
3524
3537
|
const currentUser = yield db.getCurrentUser();
|
|
3525
3538
|
const { accessToken, accessTokenExpiration, refreshToken, refreshTokenExpiration, claims, } = currentUser;
|
|
3526
3539
|
if (!accessToken)
|
|
@@ -4350,8 +4363,8 @@
|
|
|
4350
4363
|
// seconds (given that there is a Ratelimit-Reset header).
|
|
4351
4364
|
let syncRatelimitDelays = new WeakMap();
|
|
4352
4365
|
function checkSyncRateLimitDelay(db) {
|
|
4353
|
-
var _a, _b;
|
|
4354
4366
|
return __awaiter(this, void 0, void 0, function* () {
|
|
4367
|
+
var _a, _b;
|
|
4355
4368
|
const delatMilliseconds = ((_b = (_a = syncRatelimitDelays.get(db)) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0) - Date.now();
|
|
4356
4369
|
if (delatMilliseconds > 0) {
|
|
4357
4370
|
console.debug(`Stalling sync request ${delatMilliseconds} ms to spare ratelimits`);
|
|
@@ -4412,6 +4425,7 @@
|
|
|
4412
4425
|
lastPull: syncState
|
|
4413
4426
|
? {
|
|
4414
4427
|
serverRevision: syncState.serverRevision,
|
|
4428
|
+
yServerRevision: syncState.yServerRevision,
|
|
4415
4429
|
realms: syncState.realms,
|
|
4416
4430
|
inviteRealms: syncState.inviteRealms,
|
|
4417
4431
|
}
|
|
@@ -4756,12 +4770,15 @@
|
|
|
4756
4770
|
|
|
4757
4771
|
function applyYServerMessages(yMessages, db) {
|
|
4758
4772
|
return __awaiter(this, void 0, void 0, function* () {
|
|
4759
|
-
|
|
4773
|
+
var _a;
|
|
4774
|
+
const receivedUntils = {};
|
|
4775
|
+
let resyncNeeded = false;
|
|
4776
|
+
let yServerRevision;
|
|
4760
4777
|
for (const m of yMessages) {
|
|
4761
4778
|
switch (m.type) {
|
|
4762
4779
|
case 'u-s': {
|
|
4763
4780
|
const utbl = getUpdatesTable(db, m.table, m.prop);
|
|
4764
|
-
|
|
4781
|
+
receivedUntils[utbl.name] = yield utbl.add({
|
|
4765
4782
|
k: m.k,
|
|
4766
4783
|
u: m.u,
|
|
4767
4784
|
});
|
|
@@ -4786,7 +4803,24 @@
|
|
|
4786
4803
|
// See my question in https://discuss.yjs.dev/t/generate-an-inverse-update/2765
|
|
4787
4804
|
console.debug(`Y update rejected. Deleting it.`);
|
|
4788
4805
|
const utbl = getUpdatesTable(db, m.table, m.prop);
|
|
4789
|
-
|
|
4806
|
+
// Delete the rejected update and all local updates since (avoid holes in the CRDT)
|
|
4807
|
+
// and destroy it's open document if there is one.
|
|
4808
|
+
const primaryKey = (_a = (yield utbl.get(m.i))) === null || _a === void 0 ? void 0 : _a.k;
|
|
4809
|
+
if (primaryKey != null) {
|
|
4810
|
+
yield db.transaction('rw', utbl, (tx) => {
|
|
4811
|
+
// @ts-ignore
|
|
4812
|
+
tx.idbtrans._rejecting_y_ypdate = true; // Inform ydoc triggers that we delete because of a rejection and not GC
|
|
4813
|
+
return utbl
|
|
4814
|
+
.where('i')
|
|
4815
|
+
.aboveOrEqual(m.i)
|
|
4816
|
+
.filter((u) => Dexie.cmp(u.k, primaryKey) === 0 && ((u.f || 0) & 1) === 1)
|
|
4817
|
+
.delete();
|
|
4818
|
+
});
|
|
4819
|
+
// Destroy active doc
|
|
4820
|
+
const activeDoc = Dexie.DexieYProvider.getDocCache(db.dx).find(m.table, primaryKey, m.prop);
|
|
4821
|
+
if (activeDoc)
|
|
4822
|
+
activeDoc.destroy(); // Destroy the document so that editors don't continue to work on it
|
|
4823
|
+
}
|
|
4790
4824
|
break;
|
|
4791
4825
|
}
|
|
4792
4826
|
case 'in-sync': {
|
|
@@ -4796,15 +4830,26 @@
|
|
|
4796
4830
|
}
|
|
4797
4831
|
break;
|
|
4798
4832
|
}
|
|
4833
|
+
case 'y-complete-sync-done': {
|
|
4834
|
+
yServerRevision = m.yServerRev;
|
|
4835
|
+
break;
|
|
4836
|
+
}
|
|
4837
|
+
case 'outdated-server-rev':
|
|
4838
|
+
resyncNeeded = true;
|
|
4839
|
+
break;
|
|
4799
4840
|
}
|
|
4800
4841
|
}
|
|
4801
|
-
return
|
|
4842
|
+
return {
|
|
4843
|
+
receivedUntils,
|
|
4844
|
+
resyncNeeded,
|
|
4845
|
+
yServerRevision
|
|
4846
|
+
};
|
|
4802
4847
|
});
|
|
4803
4848
|
}
|
|
4804
4849
|
|
|
4805
|
-
function updateYSyncStates(lastUpdateIdsBeforeSync, receivedUntilsAfterSync, db
|
|
4806
|
-
var _a, _b, _c, _d, _e;
|
|
4850
|
+
function updateYSyncStates(lastUpdateIdsBeforeSync, receivedUntilsAfterSync, db) {
|
|
4807
4851
|
return __awaiter(this, void 0, void 0, function* () {
|
|
4852
|
+
var _a, _b, _c, _d, _e;
|
|
4808
4853
|
// We want to update unsentFrom for each yTable to the value specified in first argument
|
|
4809
4854
|
// because we got those values before we synced with server and here we are back from server
|
|
4810
4855
|
// that has successfully received all those messages - no matter if the last update was a client or server update,
|
|
@@ -4851,14 +4896,12 @@
|
|
|
4851
4896
|
yield db.table(yTable).add({
|
|
4852
4897
|
i: DEXIE_CLOUD_SYNCER_ID,
|
|
4853
4898
|
unsentFrom,
|
|
4854
|
-
receivedUntil
|
|
4855
|
-
serverRev: serverRevision,
|
|
4899
|
+
receivedUntil
|
|
4856
4900
|
});
|
|
4857
4901
|
}
|
|
4858
4902
|
else {
|
|
4859
4903
|
state.unsentFrom = Math.max(unsentFrom, state.unsentFrom || 1);
|
|
4860
4904
|
state.receivedUntil = Math.max(receivedUntil, state.receivedUntil || 0);
|
|
4861
|
-
state.serverRev = serverRevision;
|
|
4862
4905
|
yield db.table(yTable).put(state);
|
|
4863
4906
|
}
|
|
4864
4907
|
}));
|
|
@@ -4869,8 +4912,8 @@
|
|
|
4869
4912
|
const BINSTREAM_TYPE_REALMID = 1;
|
|
4870
4913
|
const BINSTREAM_TYPE_TABLE_AND_PROP = 2;
|
|
4871
4914
|
const BINSTREAM_TYPE_DOCUMENT = 3;
|
|
4872
|
-
function downloadYDocsFromServer(
|
|
4873
|
-
return __awaiter(this,
|
|
4915
|
+
function downloadYDocsFromServer(db_1, databaseUrl_1, _a) {
|
|
4916
|
+
return __awaiter(this, arguments, void 0, function* (db, databaseUrl, { yDownloadedRealms, realms }) {
|
|
4874
4917
|
if (yDownloadedRealms &&
|
|
4875
4918
|
realms &&
|
|
4876
4919
|
realms.every((realmId) => yDownloadedRealms[realmId] === '*')) {
|
|
@@ -4985,8 +5028,7 @@
|
|
|
4985
5028
|
|
|
4986
5029
|
const CURRENT_SYNC_WORKER = 'currentSyncWorker';
|
|
4987
5030
|
function sync(db, options, schema, syncOptions) {
|
|
4988
|
-
return _sync
|
|
4989
|
-
.apply(this, arguments)
|
|
5031
|
+
return _sync(db, options, schema, syncOptions)
|
|
4990
5032
|
.then((result) => {
|
|
4991
5033
|
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) { // && syncOptions?.purpose !== 'push') {
|
|
4992
5034
|
db.syncStateChangedEvent.next({
|
|
@@ -5028,11 +5070,11 @@
|
|
|
5028
5070
|
return Promise.reject(error);
|
|
5029
5071
|
}));
|
|
5030
5072
|
}
|
|
5031
|
-
function _sync(
|
|
5032
|
-
isInitialSync
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5073
|
+
function _sync(db_1, options_1, schema_1) {
|
|
5074
|
+
return __awaiter(this, arguments, void 0, function* (db, options, schema, { isInitialSync, cancelToken, justCheckIfNeeded, purpose } = {
|
|
5075
|
+
isInitialSync: false,
|
|
5076
|
+
}) {
|
|
5077
|
+
var _a;
|
|
5036
5078
|
if (!justCheckIfNeeded) {
|
|
5037
5079
|
console.debug('SYNC STARTED', { isInitialSync, purpose });
|
|
5038
5080
|
}
|
|
@@ -5049,7 +5091,7 @@
|
|
|
5049
5091
|
// Prepare for syncification by modifying locally unauthorized objects:
|
|
5050
5092
|
//
|
|
5051
5093
|
const persistedSyncState = yield db.getPersistedSyncState();
|
|
5052
|
-
const readyForSyncification =
|
|
5094
|
+
const readyForSyncification = currentUser.isLoggedIn;
|
|
5053
5095
|
const tablesToSyncify = readyForSyncification
|
|
5054
5096
|
? getTablesToSyncify(db, persistedSyncState)
|
|
5055
5097
|
: [];
|
|
@@ -5074,7 +5116,7 @@
|
|
|
5074
5116
|
const [clientChangeSet, syncState, baseRevs, { yMessages, lastUpdateIds }] = yield db.transaction('r', db.tables, () => __awaiter(this, void 0, void 0, function* () {
|
|
5075
5117
|
const syncState = yield db.getPersistedSyncState();
|
|
5076
5118
|
const baseRevs = yield db.$baseRevs.toArray();
|
|
5077
|
-
let clientChanges = yield listClientChanges(mutationTables);
|
|
5119
|
+
let clientChanges = yield listClientChanges(mutationTables, db);
|
|
5078
5120
|
const yResults = yield listYClientMessagesAndStateVector(db, tablesToSync);
|
|
5079
5121
|
throwIfCancelled(cancelToken);
|
|
5080
5122
|
if (doSyncify) {
|
|
@@ -5194,6 +5236,7 @@
|
|
|
5194
5236
|
newSyncState.realms = res.realms;
|
|
5195
5237
|
newSyncState.inviteRealms = res.inviteRealms;
|
|
5196
5238
|
newSyncState.serverRevision = res.serverRevision;
|
|
5239
|
+
newSyncState.yServerRevision = res.serverRevision;
|
|
5197
5240
|
newSyncState.timestamp = new Date();
|
|
5198
5241
|
delete newSyncState.error;
|
|
5199
5242
|
const filteredChanges = filterServerChangesThroughAddedClientChanges(res.changes, addedClientChanges);
|
|
@@ -5205,11 +5248,17 @@
|
|
|
5205
5248
|
//
|
|
5206
5249
|
// apply yMessages
|
|
5207
5250
|
//
|
|
5208
|
-
const receivedUntils = yield applyYServerMessages(res.yMessages, db);
|
|
5251
|
+
const { receivedUntils, resyncNeeded, yServerRevision } = yield applyYServerMessages(res.yMessages, db);
|
|
5252
|
+
if (yServerRevision) {
|
|
5253
|
+
newSyncState.yServerRevision = yServerRevision;
|
|
5254
|
+
}
|
|
5209
5255
|
//
|
|
5210
5256
|
// update Y SyncStates
|
|
5211
5257
|
//
|
|
5212
|
-
yield updateYSyncStates(lastUpdateIds, receivedUntils, db
|
|
5258
|
+
yield updateYSyncStates(lastUpdateIds, receivedUntils, db);
|
|
5259
|
+
if (resyncNeeded) {
|
|
5260
|
+
newSyncState.yDownloadedRealms = {}; // Will trigger a full download of Y-documents below...
|
|
5261
|
+
}
|
|
5213
5262
|
}
|
|
5214
5263
|
//
|
|
5215
5264
|
// Update regular syncState
|
|
@@ -5343,8 +5392,8 @@
|
|
|
5343
5392
|
event.next(null);
|
|
5344
5393
|
}
|
|
5345
5394
|
function consumeQueue() {
|
|
5346
|
-
var _a, _b, _c, _d, _e, _f;
|
|
5347
5395
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5396
|
+
var _a, _b, _c, _d, _e, _f;
|
|
5348
5397
|
while (queue.length > 0) {
|
|
5349
5398
|
const msg = queue.shift();
|
|
5350
5399
|
try {
|
|
@@ -5502,7 +5551,7 @@
|
|
|
5502
5551
|
};
|
|
5503
5552
|
}
|
|
5504
5553
|
|
|
5505
|
-
const wm$
|
|
5554
|
+
const wm$2 = new WeakMap();
|
|
5506
5555
|
const DEXIE_CLOUD_SCHEMA = {
|
|
5507
5556
|
members: '@id, [userId+realmId], [email+realmId], realmId',
|
|
5508
5557
|
roles: '[realmId+name]',
|
|
@@ -5516,7 +5565,7 @@
|
|
|
5516
5565
|
function DexieCloudDB(dx) {
|
|
5517
5566
|
if ('vip' in dx)
|
|
5518
5567
|
dx = dx['vip']; // Avoid race condition. Always map to a vipped dexie that don't block during db.on.ready().
|
|
5519
|
-
let db = wm$
|
|
5568
|
+
let db = wm$2.get(dx.cloud);
|
|
5520
5569
|
if (!db) {
|
|
5521
5570
|
const localSyncEvent = new rxjs.Subject();
|
|
5522
5571
|
let syncStateChangedEvent = new BroadcastedAndLocalEvent(`syncstatechanged-${dx.name}`);
|
|
@@ -5604,7 +5653,7 @@
|
|
|
5604
5653
|
Object.assign(db, helperMethods);
|
|
5605
5654
|
db.messageConsumer = MessagesFromServerConsumer(db);
|
|
5606
5655
|
db.messageProducer = new rxjs.Subject();
|
|
5607
|
-
wm$
|
|
5656
|
+
wm$2.set(dx.cloud, db);
|
|
5608
5657
|
}
|
|
5609
5658
|
return db;
|
|
5610
5659
|
}
|
|
@@ -5615,10 +5664,10 @@
|
|
|
5615
5664
|
}
|
|
5616
5665
|
|
|
5617
5666
|
// Emulate true-private property db. Why? So it's not stored in DB.
|
|
5618
|
-
const wm = new WeakMap();
|
|
5667
|
+
const wm$1 = new WeakMap();
|
|
5619
5668
|
class AuthPersistedContext {
|
|
5620
5669
|
constructor(db, userLogin) {
|
|
5621
|
-
wm.set(this, db);
|
|
5670
|
+
wm$1.set(this, db);
|
|
5622
5671
|
Object.assign(this, userLogin);
|
|
5623
5672
|
}
|
|
5624
5673
|
static load(db, userId) {
|
|
@@ -5635,7 +5684,7 @@
|
|
|
5635
5684
|
}
|
|
5636
5685
|
save() {
|
|
5637
5686
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5638
|
-
const db = wm.get(this);
|
|
5687
|
+
const db = wm$1.get(this);
|
|
5639
5688
|
db.table("$logins").put(this);
|
|
5640
5689
|
});
|
|
5641
5690
|
}
|
|
@@ -5659,8 +5708,8 @@
|
|
|
5659
5708
|
}
|
|
5660
5709
|
});
|
|
5661
5710
|
}
|
|
5662
|
-
function _logout(
|
|
5663
|
-
return __awaiter(this,
|
|
5711
|
+
function _logout(db_1) {
|
|
5712
|
+
return __awaiter(this, arguments, void 0, function* (db, { deleteUnsyncedData = false } = {}) {
|
|
5664
5713
|
// Clear the database without emptying configuration options.
|
|
5665
5714
|
const [numUnsynced, loggedOut] = yield db.dx.transaction('rw', db.dx.tables, (tx) => __awaiter(this, void 0, void 0, function* () {
|
|
5666
5715
|
// @ts-ignore
|
|
@@ -5698,11 +5747,11 @@
|
|
|
5698
5747
|
|
|
5699
5748
|
function otpFetchTokenCallback(db) {
|
|
5700
5749
|
const { userInteraction } = db.cloud;
|
|
5701
|
-
return function otpAuthenticate(
|
|
5702
|
-
|
|
5703
|
-
|
|
5750
|
+
return function otpAuthenticate(_a) {
|
|
5751
|
+
return __awaiter(this, arguments, void 0, function* ({ public_key, hints }) {
|
|
5752
|
+
var _b;
|
|
5704
5753
|
let tokenRequest;
|
|
5705
|
-
const url = (
|
|
5754
|
+
const url = (_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.databaseUrl;
|
|
5706
5755
|
if (!url)
|
|
5707
5756
|
throw new Error(`No database URL given.`);
|
|
5708
5757
|
if ((hints === null || hints === void 0 ? void 0 : hints.grant_type) === 'demo') {
|
|
@@ -5868,8 +5917,8 @@
|
|
|
5868
5917
|
}
|
|
5869
5918
|
|
|
5870
5919
|
function login(db, hints) {
|
|
5871
|
-
var _a;
|
|
5872
5920
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5921
|
+
var _a;
|
|
5873
5922
|
const currentUser = yield db.getCurrentUser();
|
|
5874
5923
|
const origUserId = currentUser.userId;
|
|
5875
5924
|
if (currentUser.isLoggedIn && (!hints || (!hints.email && !hints.userId))) {
|
|
@@ -6306,8 +6355,7 @@
|
|
|
6306
6355
|
outstandingTransactions.next(outstandingTransactions.value);
|
|
6307
6356
|
};
|
|
6308
6357
|
const txComplete = () => {
|
|
6309
|
-
if (tx.mutationsAdded &&
|
|
6310
|
-
!isEagerSyncDisabled(db)) {
|
|
6358
|
+
if (tx.mutationsAdded && !isEagerSyncDisabled(db)) {
|
|
6311
6359
|
triggerSync(db, 'push');
|
|
6312
6360
|
}
|
|
6313
6361
|
removeTransaction();
|
|
@@ -6389,26 +6437,107 @@
|
|
|
6389
6437
|
: mutateAndLog(req);
|
|
6390
6438
|
} }));
|
|
6391
6439
|
function mutateAndLog(req) {
|
|
6440
|
+
var _a, _b;
|
|
6392
6441
|
const trans = req.trans;
|
|
6393
|
-
|
|
6442
|
+
const unsyncedProps = (_b = (_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.unsyncedProperties) === null || _b === void 0 ? void 0 : _b[tableName];
|
|
6394
6443
|
const { txid, currentUser: { userId }, } = trans;
|
|
6395
6444
|
const { type } = req;
|
|
6396
6445
|
const opNo = ++trans.opCount;
|
|
6446
|
+
function stripChangeSpec(changeSpec) {
|
|
6447
|
+
if (!unsyncedProps)
|
|
6448
|
+
return changeSpec;
|
|
6449
|
+
let rv = changeSpec;
|
|
6450
|
+
for (const keyPath of Object.keys(changeSpec)) {
|
|
6451
|
+
if (unsyncedProps.some((p) => keyPath === p || keyPath.startsWith(p + '.'))) {
|
|
6452
|
+
if (rv === changeSpec)
|
|
6453
|
+
rv = Object.assign({}, changeSpec); // clone on demand
|
|
6454
|
+
delete rv[keyPath];
|
|
6455
|
+
}
|
|
6456
|
+
}
|
|
6457
|
+
return rv;
|
|
6458
|
+
}
|
|
6397
6459
|
return table.mutate(req).then((res) => {
|
|
6460
|
+
var _a;
|
|
6398
6461
|
const { numFailures: hasFailures, failures } = res;
|
|
6399
6462
|
let keys = type === 'delete' ? req.keys : res.results;
|
|
6400
6463
|
let values = 'values' in req ? req.values : [];
|
|
6401
|
-
let
|
|
6464
|
+
let changeSpec = 'changeSpec' in req ? req.changeSpec : undefined;
|
|
6465
|
+
let updates = 'updates' in req ? req.updates : undefined;
|
|
6402
6466
|
if (hasFailures) {
|
|
6403
6467
|
keys = keys.filter((_, idx) => !failures[idx]);
|
|
6404
6468
|
values = values.filter((_, idx) => !failures[idx]);
|
|
6405
6469
|
}
|
|
6470
|
+
if (unsyncedProps) {
|
|
6471
|
+
// Filter out unsynced properties
|
|
6472
|
+
values = values.map((value) => {
|
|
6473
|
+
const newValue = Object.assign({}, value);
|
|
6474
|
+
for (const prop of unsyncedProps) {
|
|
6475
|
+
delete newValue[prop];
|
|
6476
|
+
}
|
|
6477
|
+
return newValue;
|
|
6478
|
+
});
|
|
6479
|
+
if (changeSpec) {
|
|
6480
|
+
// modify operation with criteria and changeSpec.
|
|
6481
|
+
// We must strip out unsynced properties from changeSpec.
|
|
6482
|
+
// We deal with criteria later.
|
|
6483
|
+
changeSpec = stripChangeSpec(changeSpec);
|
|
6484
|
+
if (Object.keys(changeSpec).length === 0) {
|
|
6485
|
+
// Nothing to change on server
|
|
6486
|
+
return res;
|
|
6487
|
+
}
|
|
6488
|
+
}
|
|
6489
|
+
if (updates) {
|
|
6490
|
+
let strippedChangeSpecs = updates.changeSpecs.map(stripChangeSpec);
|
|
6491
|
+
let newUpdates = {
|
|
6492
|
+
keys: [],
|
|
6493
|
+
changeSpecs: [],
|
|
6494
|
+
};
|
|
6495
|
+
const validKeys = new Dexie.RangeSet();
|
|
6496
|
+
let anyChangeSpecBecameEmpty = false;
|
|
6497
|
+
for (let i = 0, l = strippedChangeSpecs.length; i < l; ++i) {
|
|
6498
|
+
if (Object.keys(strippedChangeSpecs[i]).length > 0) {
|
|
6499
|
+
newUpdates.keys.push(updates.keys[i]);
|
|
6500
|
+
newUpdates.changeSpecs.push(strippedChangeSpecs[i]);
|
|
6501
|
+
validKeys.addKey(updates.keys[i]);
|
|
6502
|
+
}
|
|
6503
|
+
else {
|
|
6504
|
+
anyChangeSpecBecameEmpty = true;
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
updates = newUpdates;
|
|
6508
|
+
if (anyChangeSpecBecameEmpty) {
|
|
6509
|
+
// Some keys were stripped. We must also strip them from keys and values
|
|
6510
|
+
let newKeys = [];
|
|
6511
|
+
let newValues = [];
|
|
6512
|
+
for (let i = 0, l = keys.length; i < l; ++i) {
|
|
6513
|
+
if (validKeys.hasKey(keys[i])) {
|
|
6514
|
+
newKeys.push(keys[i]);
|
|
6515
|
+
newValues.push(values[i]);
|
|
6516
|
+
}
|
|
6517
|
+
}
|
|
6518
|
+
keys = newKeys;
|
|
6519
|
+
values = newValues;
|
|
6520
|
+
}
|
|
6521
|
+
}
|
|
6522
|
+
}
|
|
6406
6523
|
const ts = Date.now();
|
|
6407
6524
|
// Canonicalize req.criteria.index to null if it's on the primary key.
|
|
6408
|
-
|
|
6525
|
+
let criteria = 'criteria' in req && req.criteria
|
|
6409
6526
|
? Object.assign(Object.assign({}, req.criteria), { index: req.criteria.index === schema.primaryKey.keyPath // Use null to inform server that criteria is on primary key
|
|
6410
6527
|
? null // This will disable the server from trying to log consistent operations where it shouldnt.
|
|
6411
6528
|
: req.criteria.index }) : undefined;
|
|
6529
|
+
if (unsyncedProps && (criteria === null || criteria === void 0 ? void 0 : criteria.index)) {
|
|
6530
|
+
const keyPaths = (_a = schema.indexes.find((idx) => idx.name === criteria.index)) === null || _a === void 0 ? void 0 : _a.keyPath;
|
|
6531
|
+
const involvedProps = keyPaths
|
|
6532
|
+
? typeof keyPaths === 'string'
|
|
6533
|
+
? [keyPaths]
|
|
6534
|
+
: keyPaths
|
|
6535
|
+
: [];
|
|
6536
|
+
if (involvedProps.some((p) => unsyncedProps === null || unsyncedProps === void 0 ? void 0 : unsyncedProps.includes(p))) {
|
|
6537
|
+
// Don't log criteria on unsynced properties as the server could not test them.
|
|
6538
|
+
criteria = undefined;
|
|
6539
|
+
}
|
|
6540
|
+
}
|
|
6412
6541
|
const mut = req.type === 'delete'
|
|
6413
6542
|
? {
|
|
6414
6543
|
type: 'delete',
|
|
@@ -6429,7 +6558,7 @@
|
|
|
6429
6558
|
userId,
|
|
6430
6559
|
values,
|
|
6431
6560
|
}
|
|
6432
|
-
: criteria &&
|
|
6561
|
+
: criteria && changeSpec
|
|
6433
6562
|
? {
|
|
6434
6563
|
// Common changeSpec for all keys
|
|
6435
6564
|
type: 'modify',
|
|
@@ -6437,37 +6566,51 @@
|
|
|
6437
6566
|
opNo,
|
|
6438
6567
|
keys,
|
|
6439
6568
|
criteria,
|
|
6440
|
-
changeSpec
|
|
6569
|
+
changeSpec,
|
|
6441
6570
|
txid,
|
|
6442
6571
|
userId,
|
|
6443
6572
|
}
|
|
6444
|
-
:
|
|
6573
|
+
: changeSpec
|
|
6445
6574
|
? {
|
|
6446
|
-
//
|
|
6575
|
+
// In case criteria involved an unsynced property, we go for keys instead.
|
|
6447
6576
|
type: 'update',
|
|
6448
6577
|
ts,
|
|
6449
6578
|
opNo,
|
|
6450
|
-
keys: updates.keys,
|
|
6451
|
-
changeSpecs: updates.changeSpecs,
|
|
6452
|
-
txid,
|
|
6453
|
-
userId,
|
|
6454
|
-
}
|
|
6455
|
-
: {
|
|
6456
|
-
type: 'upsert',
|
|
6457
|
-
ts,
|
|
6458
|
-
opNo,
|
|
6459
6579
|
keys,
|
|
6460
|
-
|
|
6580
|
+
changeSpecs: keys.map(() => changeSpec),
|
|
6461
6581
|
txid,
|
|
6462
6582
|
userId,
|
|
6463
|
-
}
|
|
6583
|
+
}
|
|
6584
|
+
: updates
|
|
6585
|
+
? {
|
|
6586
|
+
// One changeSpec per key
|
|
6587
|
+
type: 'update',
|
|
6588
|
+
ts,
|
|
6589
|
+
opNo,
|
|
6590
|
+
keys: updates.keys,
|
|
6591
|
+
changeSpecs: updates.changeSpecs,
|
|
6592
|
+
txid,
|
|
6593
|
+
userId,
|
|
6594
|
+
}
|
|
6595
|
+
: {
|
|
6596
|
+
type: 'upsert',
|
|
6597
|
+
ts,
|
|
6598
|
+
opNo,
|
|
6599
|
+
keys,
|
|
6600
|
+
values,
|
|
6601
|
+
txid,
|
|
6602
|
+
userId,
|
|
6603
|
+
};
|
|
6464
6604
|
if ('isAdditionalChunk' in req && req.isAdditionalChunk) {
|
|
6465
6605
|
mut.isAdditionalChunk = true;
|
|
6466
6606
|
}
|
|
6467
6607
|
return keys.length > 0 || criteria
|
|
6468
6608
|
? mutsTable
|
|
6469
6609
|
.mutate({ type: 'add', trans, values: [mut] }) // Log entry
|
|
6470
|
-
.then(() =>
|
|
6610
|
+
.then(() => {
|
|
6611
|
+
trans.mutationsAdded = true; // Mark transaction as having added mutations to trigger eager sync
|
|
6612
|
+
return res; // Return original response
|
|
6613
|
+
})
|
|
6471
6614
|
: res;
|
|
6472
6615
|
});
|
|
6473
6616
|
}
|
|
@@ -6551,10 +6694,18 @@
|
|
|
6551
6694
|
};
|
|
6552
6695
|
}
|
|
6553
6696
|
|
|
6697
|
+
function performGuardedJob(db, jobName, job) {
|
|
6698
|
+
if (typeof navigator === 'undefined' || !navigator.locks) {
|
|
6699
|
+
// No support for guarding jobs. IE11, node.js, etc.
|
|
6700
|
+
return job();
|
|
6701
|
+
}
|
|
6702
|
+
return navigator.locks.request(db.name + '|' + jobName, () => job());
|
|
6703
|
+
}
|
|
6704
|
+
|
|
6554
6705
|
function performInitialSync(db, cloudOptions, cloudSchema) {
|
|
6555
6706
|
return __awaiter(this, void 0, void 0, function* () {
|
|
6556
6707
|
console.debug('Performing initial sync');
|
|
6557
|
-
yield sync(db, cloudOptions, cloudSchema, { isInitialSync: true });
|
|
6708
|
+
yield performGuardedJob(db, CURRENT_SYNC_WORKER, () => sync(db, cloudOptions, cloudSchema, { isInitialSync: true }));
|
|
6558
6709
|
console.debug('Done initial sync');
|
|
6559
6710
|
});
|
|
6560
6711
|
}
|
|
@@ -6641,38 +6792,42 @@
|
|
|
6641
6792
|
updatesTable: p.updatesTable,
|
|
6642
6793
|
}))));
|
|
6643
6794
|
return rxjs.merge(...yTableRecords.map(({ table, ydocProp, updatesTable }) => {
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6795
|
+
// Per updates table (table+prop combo), we first read syncer.unsentFrom,
|
|
6796
|
+
// and then start listening for updates since that number.
|
|
6797
|
+
const yTbl = db.table(updatesTable);
|
|
6798
|
+
return rxjs.from(yTbl.get(DEXIE_CLOUD_SYNCER_ID)).pipe(rxjs.switchMap((syncer) => {
|
|
6799
|
+
let currentUnsentFrom = (syncer === null || syncer === void 0 ? void 0 : syncer.unsentFrom) || 1;
|
|
6800
|
+
return rxjs.from(Dexie.liveQuery(() => __awaiter(this, void 0, void 0, function* () {
|
|
6801
|
+
const addedUpdates = yield listUpdatesSince(yTbl, currentUnsentFrom);
|
|
6802
|
+
return addedUpdates
|
|
6803
|
+
.filter((update) => update.f && update.f & 1) // Only include local updates
|
|
6804
|
+
.map((update) => {
|
|
6805
|
+
return {
|
|
6806
|
+
type: 'u-c',
|
|
6807
|
+
table,
|
|
6808
|
+
prop: ydocProp,
|
|
6809
|
+
k: update.k,
|
|
6810
|
+
u: update.u,
|
|
6811
|
+
i: update.i,
|
|
6812
|
+
};
|
|
6813
|
+
});
|
|
6814
|
+
}))).pipe(rxjs.tap((addedUpdates) => {
|
|
6815
|
+
// Update currentUnsentFrom to only listen for updates that will be newer than the ones we emitted.
|
|
6816
|
+
// (Before, we did this within the liveQuery, but that caused a bug because
|
|
6817
|
+
// a cancelled emittion of a liveQuery would update the currentUnsentFrom without
|
|
6818
|
+
// emitting anything, leading to that we jumped over some updates. Here we update it
|
|
6819
|
+
// after the liveQuery has emitted its updates)
|
|
6820
|
+
if (addedUpdates.length > 0) {
|
|
6821
|
+
currentUnsentFrom = addedUpdates.at(-1).i + 1;
|
|
6822
|
+
}
|
|
6823
|
+
}));
|
|
6667
6824
|
}));
|
|
6668
6825
|
})).pipe(
|
|
6669
6826
|
// Flatten the array of messages.
|
|
6670
6827
|
// If messageProducer emits empty array, nothing is emitted
|
|
6671
6828
|
// but if messageProducer emits array of messages, they are
|
|
6672
6829
|
// emitted one by one.
|
|
6673
|
-
rxjs.mergeMap((messages) => messages)
|
|
6674
|
-
console.debug('dexie-cloud emitting y-c', message);
|
|
6675
|
-
}));
|
|
6830
|
+
rxjs.mergeMap((messages) => messages));
|
|
6676
6831
|
}
|
|
6677
6832
|
|
|
6678
6833
|
function getAwarenessLibrary(db) {
|
|
@@ -6685,6 +6840,23 @@
|
|
|
6685
6840
|
const awarenessWeakMap = new WeakMap();
|
|
6686
6841
|
const getDocAwareness = (doc) => awarenessWeakMap.get(doc);
|
|
6687
6842
|
|
|
6843
|
+
const wm = new WeakMap();
|
|
6844
|
+
/** A property (package-private) on Y.Doc that is used
|
|
6845
|
+
* to signal that the server wants us to send a 'doc-open' message
|
|
6846
|
+
* to the server for this document.
|
|
6847
|
+
*
|
|
6848
|
+
* @param doc
|
|
6849
|
+
* @returns
|
|
6850
|
+
*/
|
|
6851
|
+
function getOpenDocSignal(doc) {
|
|
6852
|
+
let signal = wm.get(doc);
|
|
6853
|
+
if (!signal) {
|
|
6854
|
+
signal = new rxjs.Subject();
|
|
6855
|
+
wm.set(doc, signal);
|
|
6856
|
+
}
|
|
6857
|
+
return signal;
|
|
6858
|
+
}
|
|
6859
|
+
|
|
6688
6860
|
const SERVER_PING_TIMEOUT = 20000;
|
|
6689
6861
|
const CLIENT_PING_INTERVAL = 30000;
|
|
6690
6862
|
const FAIL_RETRY_WAIT_TIME = 60000;
|
|
@@ -6847,9 +7019,6 @@
|
|
|
6847
7019
|
if (msg.type === 'error') {
|
|
6848
7020
|
throw new Error(`Error message from dexie-cloud: ${msg.error}`);
|
|
6849
7021
|
}
|
|
6850
|
-
else if (msg.type === 'rev') {
|
|
6851
|
-
this.rev = msg.rev; // No meaning but seems reasonable.
|
|
6852
|
-
}
|
|
6853
7022
|
else if (msg.type === 'aware') {
|
|
6854
7023
|
const docCache = Dexie.DexieYProvider.getDocCache(this.db.dx);
|
|
6855
7024
|
const doc = docCache.find(msg.table, msg.k, msg.prop);
|
|
@@ -6864,7 +7033,19 @@
|
|
|
6864
7033
|
else if (msg.type === 'u-ack' || msg.type === 'u-reject' || msg.type === 'u-s' || msg.type === 'in-sync') {
|
|
6865
7034
|
applyYServerMessages([msg], this.db);
|
|
6866
7035
|
}
|
|
7036
|
+
else if (msg.type === 'doc-open') {
|
|
7037
|
+
const docCache = Dexie.DexieYProvider.getDocCache(this.db.dx);
|
|
7038
|
+
const doc = docCache.find(msg.table, msg.k, msg.prop);
|
|
7039
|
+
if (doc) {
|
|
7040
|
+
getOpenDocSignal(doc).next(); // Make yHandler reopen the document on server.
|
|
7041
|
+
}
|
|
7042
|
+
}
|
|
7043
|
+
else if (msg.type === 'outdated-server-rev' || msg.type === 'y-complete-sync-done') {
|
|
7044
|
+
// Won't happen but need this for typing.
|
|
7045
|
+
throw new Error('Outdated server revision or y-complete-sync-done not expected over WebSocket - only in sync using fetch()');
|
|
7046
|
+
}
|
|
6867
7047
|
else if (msg.type !== 'pong') {
|
|
7048
|
+
// Forward the request to our subscriber, wich is in messageFromServerQueue.ts (via connectWebSocket's subscribe() at the end!)
|
|
6868
7049
|
this.subscriber.next(msg);
|
|
6869
7050
|
}
|
|
6870
7051
|
}
|
|
@@ -6901,6 +7082,10 @@
|
|
|
6901
7082
|
}
|
|
6902
7083
|
console.debug('dexie-cloud WebSocket send', msg.type, msg);
|
|
6903
7084
|
if (msg.type === 'ready') {
|
|
7085
|
+
// Ok, we are certain to have stored everything up until revision msg.rev.
|
|
7086
|
+
// Update this.rev in case of reconnect - remember where we were and don't just start over!
|
|
7087
|
+
this.rev = msg.rev;
|
|
7088
|
+
// ... and then send along the request to the server so it would also be updated!
|
|
6904
7089
|
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.send(TSON.stringify(msg));
|
|
6905
7090
|
}
|
|
6906
7091
|
else {
|
|
@@ -6982,7 +7167,7 @@
|
|
|
6982
7167
|
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]));
|
|
6983
7168
|
}
|
|
6984
7169
|
return new rxjs.BehaviorSubject([userLogin, syncState]);
|
|
6985
|
-
}), switchMap((
|
|
7170
|
+
}), switchMap((_a) => __awaiter(this, [_a], void 0, function* ([userLogin, syncState]) { return [userLogin, yield computeRealmSetHash(syncState)]; })), distinctUntilChanged(([prevUser, prevHash], [currUser, currHash]) => prevUser === currUser && prevHash === currHash), switchMap(([userLogin, realmSetHash]) => {
|
|
6986
7171
|
var _a;
|
|
6987
7172
|
if (!((_a = db.cloud.persistedSyncState) === null || _a === void 0 ? void 0 : _a.value)) {
|
|
6988
7173
|
// Restart the flow if persistedSyncState is not yet available.
|
|
@@ -7043,22 +7228,14 @@
|
|
|
7043
7228
|
}
|
|
7044
7229
|
|
|
7045
7230
|
function isSyncNeeded(db) {
|
|
7046
|
-
var _a;
|
|
7047
7231
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7232
|
+
var _a;
|
|
7048
7233
|
return ((_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.databaseUrl) && db.cloud.schema
|
|
7049
7234
|
? yield sync(db, db.cloud.options, db.cloud.schema, { justCheckIfNeeded: true })
|
|
7050
7235
|
: false;
|
|
7051
7236
|
});
|
|
7052
7237
|
}
|
|
7053
7238
|
|
|
7054
|
-
function performGuardedJob(db, jobName, job) {
|
|
7055
|
-
if (typeof navigator === 'undefined' || !navigator.locks) {
|
|
7056
|
-
// No support for guarding jobs. IE11, node.js, etc.
|
|
7057
|
-
return job();
|
|
7058
|
-
}
|
|
7059
|
-
return navigator.locks.request(db.name + '|' + jobName, () => job());
|
|
7060
|
-
}
|
|
7061
|
-
|
|
7062
7239
|
const ongoingSyncs = new WeakMap();
|
|
7063
7240
|
function syncIfPossible(db, cloudOptions, cloudSchema, options) {
|
|
7064
7241
|
const ongoing = ongoingSyncs.get(db);
|
|
@@ -7112,20 +7289,7 @@
|
|
|
7112
7289
|
try {
|
|
7113
7290
|
// Check if should delay sync due to ratelimit:
|
|
7114
7291
|
yield checkSyncRateLimitDelay(db);
|
|
7115
|
-
|
|
7116
|
-
if (db.cloud.isServiceWorkerDB) {
|
|
7117
|
-
// We are the dedicated sync SW:
|
|
7118
|
-
yield sync(db, cloudOptions, cloudSchema, options);
|
|
7119
|
-
}
|
|
7120
|
-
else if (!db.cloud.usingServiceWorker) {
|
|
7121
|
-
// We use a flow that is better suited for the case when multiple workers want to
|
|
7122
|
-
// do the same thing.
|
|
7123
|
-
yield performGuardedJob(db, CURRENT_SYNC_WORKER, () => sync(db, cloudOptions, cloudSchema, options));
|
|
7124
|
-
}
|
|
7125
|
-
else {
|
|
7126
|
-
assert(false);
|
|
7127
|
-
throw new Error('Internal _syncIfPossible() - invalid precondition - should not have been called.');
|
|
7128
|
-
}
|
|
7292
|
+
yield performGuardedJob(db, CURRENT_SYNC_WORKER, () => sync(db, cloudOptions, cloudSchema, options));
|
|
7129
7293
|
ongoingSyncs.delete(db);
|
|
7130
7294
|
console.debug('Done sync');
|
|
7131
7295
|
}
|
|
@@ -7728,6 +7892,7 @@
|
|
|
7728
7892
|
// If user can update any prop in any table in this realm, return true unless
|
|
7729
7893
|
// it regards to ownership change:
|
|
7730
7894
|
if (this.permissions.update === '*') {
|
|
7895
|
+
// @ts-ignore
|
|
7731
7896
|
return props.every((prop) => prop !== 'owner');
|
|
7732
7897
|
}
|
|
7733
7898
|
const tablePermissions = (_b = this.permissions.update) === null || _b === void 0 ? void 0 : _b[this.tableName];
|
|
@@ -7801,125 +7966,151 @@
|
|
|
7801
7966
|
function createYHandler(db) {
|
|
7802
7967
|
return (provider) => {
|
|
7803
7968
|
var _a;
|
|
7804
|
-
const awap = getAwarenessLibrary(db);
|
|
7805
7969
|
const doc = provider.doc;
|
|
7806
|
-
const { parentTable
|
|
7970
|
+
const { parentTable } = doc.meta || {};
|
|
7807
7971
|
if (!((_a = db.cloud.schema) === null || _a === void 0 ? void 0 : _a[parentTable].markedForSync)) {
|
|
7808
7972
|
return; // The table that holds the doc is not marked for sync - leave it to dexie. No syncing, no awareness.
|
|
7809
7973
|
}
|
|
7810
|
-
let awareness
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7974
|
+
let awareness;
|
|
7975
|
+
Object.defineProperty(provider, 'awareness', {
|
|
7976
|
+
get() {
|
|
7977
|
+
if (awareness)
|
|
7978
|
+
return awareness;
|
|
7979
|
+
awareness = createAwareness(db, doc, provider);
|
|
7980
|
+
awarenessWeakMap.set(doc, awareness);
|
|
7981
|
+
return awareness;
|
|
7982
|
+
},
|
|
7983
|
+
});
|
|
7984
|
+
};
|
|
7985
|
+
}
|
|
7986
|
+
function createAwareness(db, doc, provider) {
|
|
7987
|
+
const { parentTable, parentId, parentProp, updatesTable } = doc.meta;
|
|
7988
|
+
const awap = getAwarenessLibrary(db);
|
|
7989
|
+
const awareness = new awap.Awareness(doc);
|
|
7990
|
+
const reopenDocSignal = getOpenDocSignal(doc);
|
|
7991
|
+
awareness.on('update', ({ added, updated, removed }, origin) => {
|
|
7992
|
+
// Send the update
|
|
7993
|
+
const changedClients = added.concat(updated).concat(removed);
|
|
7994
|
+
const user = db.cloud.currentUser.value;
|
|
7995
|
+
if (origin !== 'server' && user.isLoggedIn && !isEagerSyncDisabled(db)) {
|
|
7996
|
+
const update = awap.encodeAwarenessUpdate(awareness, changedClients);
|
|
7997
|
+
db.messageProducer.next({
|
|
7998
|
+
type: 'aware',
|
|
7999
|
+
table: parentTable,
|
|
8000
|
+
prop: parentProp,
|
|
8001
|
+
k: doc.meta.parentId,
|
|
8002
|
+
u: update,
|
|
8003
|
+
});
|
|
8004
|
+
if (provider.destroyed) {
|
|
8005
|
+
// We're called from awareness.on('destroy') that did
|
|
8006
|
+
// removeAwarenessStates.
|
|
8007
|
+
// It's time to also send the doc-close message that dexie-cloud understands
|
|
8008
|
+
// and uses to stop subscribing for updates and awareness updates and brings
|
|
8009
|
+
// down the cached information in memory on the WS connection for this.
|
|
7819
8010
|
db.messageProducer.next({
|
|
7820
|
-
type: '
|
|
8011
|
+
type: 'doc-close',
|
|
7821
8012
|
table: parentTable,
|
|
7822
8013
|
prop: parentProp,
|
|
7823
8014
|
k: doc.meta.parentId,
|
|
7824
|
-
u: update,
|
|
7825
8015
|
});
|
|
7826
|
-
if (provider.destroyed) {
|
|
7827
|
-
// We're called from awareness.on('destroy') that did
|
|
7828
|
-
// removeAwarenessStates.
|
|
7829
|
-
// It's time to also send the doc-close message that dexie-cloud understands
|
|
7830
|
-
// and uses to stop subscribing for updates and awareness updates and brings
|
|
7831
|
-
// down the cached information in memory on the WS connection for this.
|
|
7832
|
-
db.messageProducer.next({
|
|
7833
|
-
type: 'doc-close',
|
|
7834
|
-
table: parentTable,
|
|
7835
|
-
prop: parentProp,
|
|
7836
|
-
k: doc.meta.parentId
|
|
7837
|
-
});
|
|
7838
|
-
}
|
|
7839
8016
|
}
|
|
7840
|
-
}
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
8017
|
+
}
|
|
8018
|
+
});
|
|
8019
|
+
awareness.on('destroy', () => {
|
|
8020
|
+
// Signal to server that this provider is destroyed (the update event will be triggered, which
|
|
8021
|
+
// in turn will trigger db.messageProducer that will send the message to the server if WS is connected)
|
|
8022
|
+
awap.removeAwarenessStates(awareness, [doc.clientID], 'provider destroyed');
|
|
8023
|
+
});
|
|
8024
|
+
// Open the document on the server
|
|
8025
|
+
(() => __awaiter(this, void 0, void 0, function* () {
|
|
8026
|
+
if (provider.destroyed)
|
|
8027
|
+
return;
|
|
8028
|
+
let connected = false;
|
|
8029
|
+
let currentFlowId = 1;
|
|
8030
|
+
const subscription = rxjs.combineLatest([
|
|
8031
|
+
db.cloud.webSocketStatus, // Wake up when webSocket status changes
|
|
8032
|
+
reopenDocSignal.pipe(rxjs.startWith(null)), // Wake up when reopenDocSignal emits
|
|
8033
|
+
]).subscribe(([wsStatus]) => {
|
|
7848
8034
|
if (provider.destroyed)
|
|
7849
8035
|
return;
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
8036
|
+
// Keep "connected" state in a variable so we can check it after async operations
|
|
8037
|
+
connected = wsStatus === 'connected';
|
|
8038
|
+
// We are or got connected. Open the document on the server.
|
|
8039
|
+
const user = db.cloud.currentUser.value;
|
|
8040
|
+
if (wsStatus === 'connected' &&
|
|
8041
|
+
user.isLoggedIn &&
|
|
8042
|
+
!isEagerSyncDisabled(db)) {
|
|
8043
|
+
++currentFlowId;
|
|
8044
|
+
openDocumentOnServer().catch((error) => {
|
|
8045
|
+
console.warn(`Error catched in createYHandler.ts: ${error}`);
|
|
8046
|
+
});
|
|
8047
|
+
}
|
|
8048
|
+
});
|
|
8049
|
+
// Wait until WebSocket is connected
|
|
8050
|
+
provider.addCleanupHandler(subscription);
|
|
8051
|
+
/** Sends an 'doc-open' message to server whenever websocket becomes
|
|
8052
|
+
* connected, or if it is already connected.
|
|
8053
|
+
* The flow is aborted in case websocket is disconnected while querying
|
|
8054
|
+
* information required to compute the state vector. Flow is also
|
|
8055
|
+
* aborted in case document or provider has been destroyed during
|
|
8056
|
+
* the async parts of the task.
|
|
8057
|
+
*
|
|
8058
|
+
* The state vector is only computed from the updates that have occured
|
|
8059
|
+
* after the last full sync - which could very often be zero - in which
|
|
8060
|
+
* case no state vector is sent (then the server already knows us by
|
|
8061
|
+
* revision)
|
|
8062
|
+
*
|
|
8063
|
+
* When server gets the doc-open message, it will authorize us for
|
|
8064
|
+
* whether we are allowed to read / write to this document, and then
|
|
8065
|
+
* keep the cached information in memory on the WS connection for this
|
|
8066
|
+
* particular document, as well as subscribe to updates and awareness updates
|
|
8067
|
+
* from other clients on the document.
|
|
8068
|
+
*/
|
|
8069
|
+
function openDocumentOnServer() {
|
|
8070
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8071
|
+
const myFlow = currentFlowId; // So we can abort when a new flow is started
|
|
8072
|
+
const yTbl = db.table(updatesTable);
|
|
8073
|
+
const syncStateTbl = db.$syncState;
|
|
8074
|
+
const [receivedUntil, yServerRev] = yield db.transaction('r', syncStateTbl, yTbl, () => __awaiter(this, void 0, void 0, function* () {
|
|
8075
|
+
const syncState = yield yTbl.get(DEXIE_CLOUD_SYNCER_ID);
|
|
8076
|
+
const persistedSyncState = yield syncStateTbl.get('syncState');
|
|
8077
|
+
return [
|
|
8078
|
+
(syncState === null || syncState === void 0 ? void 0 : syncState.receivedUntil) || 0,
|
|
8079
|
+
(persistedSyncState === null || persistedSyncState === void 0 ? void 0 : persistedSyncState.yServerRevision) ||
|
|
8080
|
+
(persistedSyncState === null || persistedSyncState === void 0 ? void 0 : persistedSyncState.serverRevision),
|
|
8081
|
+
];
|
|
8082
|
+
}));
|
|
8083
|
+
// After every await, check if we still should be working on this task.
|
|
8084
|
+
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7854
8085
|
return;
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
8086
|
+
const docOpenMsg = {
|
|
8087
|
+
type: 'doc-open',
|
|
8088
|
+
table: parentTable,
|
|
8089
|
+
prop: parentProp,
|
|
8090
|
+
k: parentId,
|
|
8091
|
+
serverRev: yServerRev,
|
|
8092
|
+
};
|
|
8093
|
+
const serverUpdatesSinceLastSync = yield yTbl
|
|
8094
|
+
.where('i')
|
|
8095
|
+
.between(receivedUntil, Infinity, false)
|
|
8096
|
+
.filter((update) => Dexie.cmp(update.k, parentId) === 0 && // Only updates for this document
|
|
8097
|
+
((update.f || 0) & 1) === 0 // Don't include local changes
|
|
8098
|
+
)
|
|
8099
|
+
.toArray();
|
|
8100
|
+
// After every await, check if we still should be working on this task.
|
|
8101
|
+
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
8102
|
+
return;
|
|
8103
|
+
if (serverUpdatesSinceLastSync.length > 0) {
|
|
8104
|
+
const Y = $Y(db); // Get the Yjs library from Dexie constructor options
|
|
8105
|
+
const mergedUpdate = Y.mergeUpdatesV2(serverUpdatesSinceLastSync.map((update) => update.u));
|
|
8106
|
+
const stateVector = Y.encodeStateVectorFromUpdateV2(mergedUpdate);
|
|
8107
|
+
docOpenMsg.sv = stateVector;
|
|
7864
8108
|
}
|
|
8109
|
+
db.messageProducer.next(docOpenMsg);
|
|
7865
8110
|
});
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
* connected, or if it is already connected.
|
|
7870
|
-
* The flow is aborted in case websocket is disconnected while querying
|
|
7871
|
-
* information required to compute the state vector. Flow is also
|
|
7872
|
-
* aborted in case document or provider has been destroyed during
|
|
7873
|
-
* the async parts of the task.
|
|
7874
|
-
*
|
|
7875
|
-
* The state vector is only computed from the updates that have occured
|
|
7876
|
-
* after the last full sync - which could very often be zero - in which
|
|
7877
|
-
* case no state vector is sent (then the server already knows us by
|
|
7878
|
-
* revision)
|
|
7879
|
-
*
|
|
7880
|
-
* When server gets the doc-open message, it will authorized us for
|
|
7881
|
-
* whether we are allowed to read / write to this document, and then
|
|
7882
|
-
* keep the cached information in memory on the WS connection for this
|
|
7883
|
-
* particular document, as well as subscribe to updates and awareness updates
|
|
7884
|
-
* from other clients on the document.
|
|
7885
|
-
*/
|
|
7886
|
-
function openDocumentOnServer(wsStatus) {
|
|
7887
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
7888
|
-
const myFlow = currentFlowId; // So we can abort when a new flow is started
|
|
7889
|
-
const yTbl = db.table(updatesTable);
|
|
7890
|
-
const syncState = yield yTbl.get(DEXIE_CLOUD_SYNCER_ID);
|
|
7891
|
-
// After every await, check if we still should be working on this task.
|
|
7892
|
-
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7893
|
-
return;
|
|
7894
|
-
const receivedUntil = (syncState === null || syncState === void 0 ? void 0 : syncState.receivedUntil) || 0;
|
|
7895
|
-
const docOpenMsg = {
|
|
7896
|
-
type: 'doc-open',
|
|
7897
|
-
table: parentTable,
|
|
7898
|
-
prop: parentProp,
|
|
7899
|
-
k: parentId,
|
|
7900
|
-
serverRev: syncState === null || syncState === void 0 ? void 0 : syncState.serverRev,
|
|
7901
|
-
};
|
|
7902
|
-
const serverUpdatesSinceLastSync = yield yTbl
|
|
7903
|
-
.where('i')
|
|
7904
|
-
.between(receivedUntil, Infinity, false)
|
|
7905
|
-
.filter((update) => Dexie.cmp(update.k, parentId) === 0 && // Only updates for this document
|
|
7906
|
-
((update.f || 0) & 1) === 0 // Don't include local changes
|
|
7907
|
-
)
|
|
7908
|
-
.toArray();
|
|
7909
|
-
// After every await, check if we still should be working on this task.
|
|
7910
|
-
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7911
|
-
return;
|
|
7912
|
-
if (serverUpdatesSinceLastSync.length > 0) {
|
|
7913
|
-
const Y = $Y(db); // Get the Yjs library from Dexie constructor options
|
|
7914
|
-
const mergedUpdate = Y.mergeUpdatesV2(serverUpdatesSinceLastSync.map((update) => update.u));
|
|
7915
|
-
const stateVector = Y.encodeStateVectorFromUpdateV2(mergedUpdate);
|
|
7916
|
-
docOpenMsg.sv = stateVector;
|
|
7917
|
-
}
|
|
7918
|
-
db.messageProducer.next(docOpenMsg);
|
|
7919
|
-
});
|
|
7920
|
-
}
|
|
7921
|
-
}));
|
|
7922
|
-
};
|
|
8111
|
+
}
|
|
8112
|
+
}))();
|
|
8113
|
+
return awareness;
|
|
7923
8114
|
}
|
|
7924
8115
|
|
|
7925
8116
|
const DEFAULT_OPTIONS = {
|
|
@@ -7962,7 +8153,7 @@
|
|
|
7962
8153
|
const syncComplete = new rxjs.Subject();
|
|
7963
8154
|
dexie.cloud = {
|
|
7964
8155
|
// @ts-ignore
|
|
7965
|
-
version: "4.1.0-
|
|
8156
|
+
version: "4.1.0-beta.25",
|
|
7966
8157
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
7967
8158
|
schema: null,
|
|
7968
8159
|
get currentUserId() {
|
|
@@ -7998,16 +8189,16 @@
|
|
|
7998
8189
|
}
|
|
7999
8190
|
updateSchemaFromOptions(dexie.cloud.schema, dexie.cloud.options);
|
|
8000
8191
|
},
|
|
8001
|
-
logout(
|
|
8002
|
-
return __awaiter(this,
|
|
8192
|
+
logout() {
|
|
8193
|
+
return __awaiter(this, arguments, void 0, function* ({ force } = {}) {
|
|
8003
8194
|
force
|
|
8004
8195
|
? yield _logout(DexieCloudDB(dexie), { deleteUnsyncedData: true })
|
|
8005
8196
|
: yield logout(DexieCloudDB(dexie));
|
|
8006
8197
|
});
|
|
8007
8198
|
},
|
|
8008
|
-
sync(
|
|
8009
|
-
|
|
8010
|
-
|
|
8199
|
+
sync() {
|
|
8200
|
+
return __awaiter(this, arguments, void 0, function* ({ wait, purpose } = { wait: true, purpose: 'push' }) {
|
|
8201
|
+
var _a;
|
|
8011
8202
|
if (wait === undefined)
|
|
8012
8203
|
wait = true;
|
|
8013
8204
|
const db = DexieCloudDB(dexie);
|
|
@@ -8065,8 +8256,8 @@
|
|
|
8065
8256
|
dexie.use(createImplicitPropSetterMiddleware(DexieCloudDB(dexie)));
|
|
8066
8257
|
dexie.use(createIdGenerationMiddleware(DexieCloudDB(dexie)));
|
|
8067
8258
|
function onDbReady(dexie) {
|
|
8068
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
8069
8259
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8260
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
8070
8261
|
closed = false; // As Dexie calls us, we are not closed anymore. Maybe reopened? Remember db.ready event is registered with sticky flag!
|
|
8071
8262
|
const db = DexieCloudDB(dexie);
|
|
8072
8263
|
// Setup default GUI:
|
|
@@ -8089,7 +8280,7 @@
|
|
|
8089
8280
|
? yield navigator.serviceWorker.getRegistrations()
|
|
8090
8281
|
: [];
|
|
8091
8282
|
const [initiallySynced, lastSyncedRealms] = yield db.transaction('rw', db.$syncState, () => __awaiter(this, void 0, void 0, function* () {
|
|
8092
|
-
var
|
|
8283
|
+
var _a, _b;
|
|
8093
8284
|
const { options, schema } = db.cloud;
|
|
8094
8285
|
const [persistedOptions, persistedSchema, persistedSyncState] = yield Promise.all([
|
|
8095
8286
|
db.getOptions(),
|
|
@@ -8111,7 +8302,7 @@
|
|
|
8111
8302
|
delete newPersistedOptions.awarenessProtocol;
|
|
8112
8303
|
yield db.$syncState.put(newPersistedOptions, 'options');
|
|
8113
8304
|
}
|
|
8114
|
-
if (((
|
|
8305
|
+
if (((_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.tryUseServiceWorker) &&
|
|
8115
8306
|
'serviceWorker' in navigator &&
|
|
8116
8307
|
swRegistrations.length > 0 &&
|
|
8117
8308
|
!DISABLE_SERVICEWORKER_STRATEGY) {
|
|
@@ -8125,7 +8316,7 @@
|
|
|
8125
8316
|
// Not configured for using service worker or no service worker
|
|
8126
8317
|
// registration exists. Don't rely on service worker to do any job.
|
|
8127
8318
|
// Use LocalSyncWorker instead.
|
|
8128
|
-
if (((
|
|
8319
|
+
if (((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.tryUseServiceWorker) &&
|
|
8129
8320
|
!db.cloud.isServiceWorkerDB) {
|
|
8130
8321
|
console.debug('dexie-cloud-addon: Not using service worker.', swRegistrations.length === 0
|
|
8131
8322
|
? 'No SW registrations found.'
|
|
@@ -8168,10 +8359,6 @@
|
|
|
8168
8359
|
db.setInitiallySynced(true);
|
|
8169
8360
|
}
|
|
8170
8361
|
verifySchema(db);
|
|
8171
|
-
if (((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.databaseUrl) && !initiallySynced) {
|
|
8172
|
-
yield performInitialSync(db, db.cloud.options, db.cloud.schema);
|
|
8173
|
-
db.setInitiallySynced(true);
|
|
8174
|
-
}
|
|
8175
8362
|
// Manage CurrentUser observable:
|
|
8176
8363
|
throwIfClosed();
|
|
8177
8364
|
if (!db.cloud.isServiceWorkerDB) {
|
|
@@ -8196,20 +8383,29 @@
|
|
|
8196
8383
|
// HERE: If requireAuth, do athentication now.
|
|
8197
8384
|
let changedUser = false;
|
|
8198
8385
|
const user = yield db.getCurrentUser();
|
|
8199
|
-
const requireAuth = (
|
|
8386
|
+
const requireAuth = (_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.requireAuth;
|
|
8200
8387
|
if (requireAuth) {
|
|
8201
|
-
if (
|
|
8202
|
-
//
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
changedUser = yield login(db, requireAuth);
|
|
8208
|
-
}
|
|
8388
|
+
if (db.cloud.isServiceWorkerDB) {
|
|
8389
|
+
// If this is a service worker DB, we can't do authentication here,
|
|
8390
|
+
// we just wait until the application has done it.
|
|
8391
|
+
console.debug('Dexie Cloud Service worker. Waiting for application to authenticate.');
|
|
8392
|
+
yield rxjs.firstValueFrom(currentUserEmitter.pipe(filter((user) => !!user.isLoggedIn), take(1)));
|
|
8393
|
+
console.debug('Dexie Cloud Service worker. Application has authenticated.');
|
|
8209
8394
|
}
|
|
8210
|
-
else
|
|
8211
|
-
|
|
8212
|
-
|
|
8395
|
+
else {
|
|
8396
|
+
if (typeof requireAuth === 'object') {
|
|
8397
|
+
// requireAuth contains login hints. Check if we already fulfil it:
|
|
8398
|
+
if (!user.isLoggedIn ||
|
|
8399
|
+
(requireAuth.userId && user.userId !== requireAuth.userId) ||
|
|
8400
|
+
(requireAuth.email && user.email !== requireAuth.email)) {
|
|
8401
|
+
// If not, login the configured user:
|
|
8402
|
+
changedUser = yield login(db, requireAuth);
|
|
8403
|
+
}
|
|
8404
|
+
}
|
|
8405
|
+
else if (!user.isLoggedIn) {
|
|
8406
|
+
// requireAuth is true and user is not logged in
|
|
8407
|
+
changedUser = yield login(db);
|
|
8408
|
+
}
|
|
8213
8409
|
}
|
|
8214
8410
|
}
|
|
8215
8411
|
if (user.isLoggedIn && (!lastSyncedRealms || !lastSyncedRealms.includes(user.userId))) {
|
|
@@ -8224,8 +8420,17 @@
|
|
|
8224
8420
|
localSyncWorker.stop();
|
|
8225
8421
|
localSyncWorker = null;
|
|
8226
8422
|
throwIfClosed();
|
|
8423
|
+
const doInitialSync = ((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.databaseUrl) && (!initiallySynced || changedUser);
|
|
8424
|
+
if (doInitialSync) {
|
|
8425
|
+
// Do the initial sync directly in the browser thread no matter if we are using service worker or not.
|
|
8426
|
+
yield performInitialSync(db, db.cloud.options, db.cloud.schema);
|
|
8427
|
+
db.setInitiallySynced(true);
|
|
8428
|
+
}
|
|
8429
|
+
throwIfClosed();
|
|
8227
8430
|
if (db.cloud.usingServiceWorker && ((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl)) {
|
|
8228
|
-
|
|
8431
|
+
if (!doInitialSync) {
|
|
8432
|
+
registerSyncEvent(db, 'push').catch(() => { });
|
|
8433
|
+
}
|
|
8229
8434
|
registerPeriodicSyncEvent(db).catch(() => { });
|
|
8230
8435
|
}
|
|
8231
8436
|
else if (((_e = db.cloud.options) === null || _e === void 0 ? void 0 : _e.databaseUrl) &&
|
|
@@ -8234,7 +8439,9 @@
|
|
|
8234
8439
|
// There's no SW. Start SyncWorker instead.
|
|
8235
8440
|
localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema);
|
|
8236
8441
|
localSyncWorker.start();
|
|
8237
|
-
|
|
8442
|
+
if (!doInitialSync) {
|
|
8443
|
+
triggerSync(db, 'push');
|
|
8444
|
+
}
|
|
8238
8445
|
}
|
|
8239
8446
|
// Listen to online event and do sync.
|
|
8240
8447
|
throwIfClosed();
|
|
@@ -8254,7 +8461,7 @@
|
|
|
8254
8461
|
});
|
|
8255
8462
|
}));
|
|
8256
8463
|
}
|
|
8257
|
-
// Connect WebSocket unless we
|
|
8464
|
+
// Connect WebSocket unless we are in a service worker or websocket is disabled.
|
|
8258
8465
|
if (((_f = db.cloud.options) === null || _f === void 0 ? void 0 : _f.databaseUrl) &&
|
|
8259
8466
|
!((_g = db.cloud.options) === null || _g === void 0 ? void 0 : _g.disableWebSocket) &&
|
|
8260
8467
|
!IS_SERVICE_WORKER) {
|
|
@@ -8264,7 +8471,7 @@
|
|
|
8264
8471
|
}
|
|
8265
8472
|
}
|
|
8266
8473
|
// @ts-ignore
|
|
8267
|
-
dexieCloud.version = "4.1.0-
|
|
8474
|
+
dexieCloud.version = "4.1.0-beta.25";
|
|
8268
8475
|
Dexie.Cloud = dexieCloud;
|
|
8269
8476
|
|
|
8270
8477
|
// In case the SW lives for a while, let it reuse already opened connections:
|
|
@@ -8294,8 +8501,8 @@
|
|
|
8294
8501
|
}
|
|
8295
8502
|
return promise;
|
|
8296
8503
|
function _syncDB(dbName, purpose) {
|
|
8297
|
-
var _a;
|
|
8298
8504
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8505
|
+
var _a;
|
|
8299
8506
|
let db = managedDBs.get(dbName);
|
|
8300
8507
|
if (!db) {
|
|
8301
8508
|
console.debug('Dexie Cloud SW: Creating new Dexie instance for', dbName);
|