dexie-cloud-addon 4.1.0-alpha.8 → 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 +622 -257
- 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 +464 -255
- 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 +620 -254
- 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 +462 -253
- 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,29 +6792,35 @@
|
|
|
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.
|
|
@@ -6683,6 +6840,23 @@
|
|
|
6683
6840
|
const awarenessWeakMap = new WeakMap();
|
|
6684
6841
|
const getDocAwareness = (doc) => awarenessWeakMap.get(doc);
|
|
6685
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
|
+
|
|
6686
6860
|
const SERVER_PING_TIMEOUT = 20000;
|
|
6687
6861
|
const CLIENT_PING_INTERVAL = 30000;
|
|
6688
6862
|
const FAIL_RETRY_WAIT_TIME = 60000;
|
|
@@ -6845,9 +7019,6 @@
|
|
|
6845
7019
|
if (msg.type === 'error') {
|
|
6846
7020
|
throw new Error(`Error message from dexie-cloud: ${msg.error}`);
|
|
6847
7021
|
}
|
|
6848
|
-
else if (msg.type === 'rev') {
|
|
6849
|
-
this.rev = msg.rev; // No meaning but seems reasonable.
|
|
6850
|
-
}
|
|
6851
7022
|
else if (msg.type === 'aware') {
|
|
6852
7023
|
const docCache = Dexie.DexieYProvider.getDocCache(this.db.dx);
|
|
6853
7024
|
const doc = docCache.find(msg.table, msg.k, msg.prop);
|
|
@@ -6862,7 +7033,19 @@
|
|
|
6862
7033
|
else if (msg.type === 'u-ack' || msg.type === 'u-reject' || msg.type === 'u-s' || msg.type === 'in-sync') {
|
|
6863
7034
|
applyYServerMessages([msg], this.db);
|
|
6864
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
|
+
}
|
|
6865
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!)
|
|
6866
7049
|
this.subscriber.next(msg);
|
|
6867
7050
|
}
|
|
6868
7051
|
}
|
|
@@ -6899,6 +7082,10 @@
|
|
|
6899
7082
|
}
|
|
6900
7083
|
console.debug('dexie-cloud WebSocket send', msg.type, msg);
|
|
6901
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!
|
|
6902
7089
|
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.send(TSON.stringify(msg));
|
|
6903
7090
|
}
|
|
6904
7091
|
else {
|
|
@@ -6980,7 +7167,7 @@
|
|
|
6980
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]));
|
|
6981
7168
|
}
|
|
6982
7169
|
return new rxjs.BehaviorSubject([userLogin, syncState]);
|
|
6983
|
-
}), 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]) => {
|
|
6984
7171
|
var _a;
|
|
6985
7172
|
if (!((_a = db.cloud.persistedSyncState) === null || _a === void 0 ? void 0 : _a.value)) {
|
|
6986
7173
|
// Restart the flow if persistedSyncState is not yet available.
|
|
@@ -7041,22 +7228,14 @@
|
|
|
7041
7228
|
}
|
|
7042
7229
|
|
|
7043
7230
|
function isSyncNeeded(db) {
|
|
7044
|
-
var _a;
|
|
7045
7231
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7232
|
+
var _a;
|
|
7046
7233
|
return ((_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.databaseUrl) && db.cloud.schema
|
|
7047
7234
|
? yield sync(db, db.cloud.options, db.cloud.schema, { justCheckIfNeeded: true })
|
|
7048
7235
|
: false;
|
|
7049
7236
|
});
|
|
7050
7237
|
}
|
|
7051
7238
|
|
|
7052
|
-
function performGuardedJob(db, jobName, job) {
|
|
7053
|
-
if (typeof navigator === 'undefined' || !navigator.locks) {
|
|
7054
|
-
// No support for guarding jobs. IE11, node.js, etc.
|
|
7055
|
-
return job();
|
|
7056
|
-
}
|
|
7057
|
-
return navigator.locks.request(db.name + '|' + jobName, () => job());
|
|
7058
|
-
}
|
|
7059
|
-
|
|
7060
7239
|
const ongoingSyncs = new WeakMap();
|
|
7061
7240
|
function syncIfPossible(db, cloudOptions, cloudSchema, options) {
|
|
7062
7241
|
const ongoing = ongoingSyncs.get(db);
|
|
@@ -7110,20 +7289,7 @@
|
|
|
7110
7289
|
try {
|
|
7111
7290
|
// Check if should delay sync due to ratelimit:
|
|
7112
7291
|
yield checkSyncRateLimitDelay(db);
|
|
7113
|
-
|
|
7114
|
-
if (db.cloud.isServiceWorkerDB) {
|
|
7115
|
-
// We are the dedicated sync SW:
|
|
7116
|
-
yield sync(db, cloudOptions, cloudSchema, options);
|
|
7117
|
-
}
|
|
7118
|
-
else if (!db.cloud.usingServiceWorker) {
|
|
7119
|
-
// We use a flow that is better suited for the case when multiple workers want to
|
|
7120
|
-
// do the same thing.
|
|
7121
|
-
yield performGuardedJob(db, CURRENT_SYNC_WORKER, () => sync(db, cloudOptions, cloudSchema, options));
|
|
7122
|
-
}
|
|
7123
|
-
else {
|
|
7124
|
-
assert(false);
|
|
7125
|
-
throw new Error('Internal _syncIfPossible() - invalid precondition - should not have been called.');
|
|
7126
|
-
}
|
|
7292
|
+
yield performGuardedJob(db, CURRENT_SYNC_WORKER, () => sync(db, cloudOptions, cloudSchema, options));
|
|
7127
7293
|
ongoingSyncs.delete(db);
|
|
7128
7294
|
console.debug('Done sync');
|
|
7129
7295
|
}
|
|
@@ -7726,6 +7892,7 @@
|
|
|
7726
7892
|
// If user can update any prop in any table in this realm, return true unless
|
|
7727
7893
|
// it regards to ownership change:
|
|
7728
7894
|
if (this.permissions.update === '*') {
|
|
7895
|
+
// @ts-ignore
|
|
7729
7896
|
return props.every((prop) => prop !== 'owner');
|
|
7730
7897
|
}
|
|
7731
7898
|
const tablePermissions = (_b = this.permissions.update) === null || _b === void 0 ? void 0 : _b[this.tableName];
|
|
@@ -7799,125 +7966,151 @@
|
|
|
7799
7966
|
function createYHandler(db) {
|
|
7800
7967
|
return (provider) => {
|
|
7801
7968
|
var _a;
|
|
7802
|
-
const awap = getAwarenessLibrary(db);
|
|
7803
7969
|
const doc = provider.doc;
|
|
7804
|
-
const { parentTable
|
|
7970
|
+
const { parentTable } = doc.meta || {};
|
|
7805
7971
|
if (!((_a = db.cloud.schema) === null || _a === void 0 ? void 0 : _a[parentTable].markedForSync)) {
|
|
7806
7972
|
return; // The table that holds the doc is not marked for sync - leave it to dexie. No syncing, no awareness.
|
|
7807
7973
|
}
|
|
7808
|
-
let awareness
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
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.
|
|
7817
8010
|
db.messageProducer.next({
|
|
7818
|
-
type: '
|
|
8011
|
+
type: 'doc-close',
|
|
7819
8012
|
table: parentTable,
|
|
7820
8013
|
prop: parentProp,
|
|
7821
8014
|
k: doc.meta.parentId,
|
|
7822
|
-
u: update,
|
|
7823
8015
|
});
|
|
7824
|
-
if (provider.destroyed) {
|
|
7825
|
-
// We're called from awareness.on('destroy') that did
|
|
7826
|
-
// removeAwarenessStates.
|
|
7827
|
-
// It's time to also send the doc-close message that dexie-cloud understands
|
|
7828
|
-
// and uses to stop subscribing for updates and awareness updates and brings
|
|
7829
|
-
// down the cached information in memory on the WS connection for this.
|
|
7830
|
-
db.messageProducer.next({
|
|
7831
|
-
type: 'doc-close',
|
|
7832
|
-
table: parentTable,
|
|
7833
|
-
prop: parentProp,
|
|
7834
|
-
k: doc.meta.parentId
|
|
7835
|
-
});
|
|
7836
|
-
}
|
|
7837
8016
|
}
|
|
7838
|
-
}
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
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]) => {
|
|
7846
8034
|
if (provider.destroyed)
|
|
7847
8035
|
return;
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
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)
|
|
7852
8085
|
return;
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
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;
|
|
7862
8108
|
}
|
|
8109
|
+
db.messageProducer.next(docOpenMsg);
|
|
7863
8110
|
});
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
* connected, or if it is already connected.
|
|
7868
|
-
* The flow is aborted in case websocket is disconnected while querying
|
|
7869
|
-
* information required to compute the state vector. Flow is also
|
|
7870
|
-
* aborted in case document or provider has been destroyed during
|
|
7871
|
-
* the async parts of the task.
|
|
7872
|
-
*
|
|
7873
|
-
* The state vector is only computed from the updates that have occured
|
|
7874
|
-
* after the last full sync - which could very often be zero - in which
|
|
7875
|
-
* case no state vector is sent (then the server already knows us by
|
|
7876
|
-
* revision)
|
|
7877
|
-
*
|
|
7878
|
-
* When server gets the doc-open message, it will authorized us for
|
|
7879
|
-
* whether we are allowed to read / write to this document, and then
|
|
7880
|
-
* keep the cached information in memory on the WS connection for this
|
|
7881
|
-
* particular document, as well as subscribe to updates and awareness updates
|
|
7882
|
-
* from other clients on the document.
|
|
7883
|
-
*/
|
|
7884
|
-
function openDocumentOnServer(wsStatus) {
|
|
7885
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
7886
|
-
const myFlow = currentFlowId; // So we can abort when a new flow is started
|
|
7887
|
-
const yTbl = db.table(updatesTable);
|
|
7888
|
-
const syncState = yield yTbl.get(DEXIE_CLOUD_SYNCER_ID);
|
|
7889
|
-
// After every await, check if we still should be working on this task.
|
|
7890
|
-
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7891
|
-
return;
|
|
7892
|
-
const receivedUntil = (syncState === null || syncState === void 0 ? void 0 : syncState.receivedUntil) || 0;
|
|
7893
|
-
const docOpenMsg = {
|
|
7894
|
-
type: 'doc-open',
|
|
7895
|
-
table: parentTable,
|
|
7896
|
-
prop: parentProp,
|
|
7897
|
-
k: parentId,
|
|
7898
|
-
serverRev: syncState === null || syncState === void 0 ? void 0 : syncState.serverRev,
|
|
7899
|
-
};
|
|
7900
|
-
const serverUpdatesSinceLastSync = yield yTbl
|
|
7901
|
-
.where('i')
|
|
7902
|
-
.between(receivedUntil, Infinity, false)
|
|
7903
|
-
.filter((update) => Dexie.cmp(update.k, parentId) === 0 && // Only updates for this document
|
|
7904
|
-
((update.f || 0) & 1) === 0 // Don't include local changes
|
|
7905
|
-
)
|
|
7906
|
-
.toArray();
|
|
7907
|
-
// After every await, check if we still should be working on this task.
|
|
7908
|
-
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7909
|
-
return;
|
|
7910
|
-
if (serverUpdatesSinceLastSync.length > 0) {
|
|
7911
|
-
const Y = $Y(db); // Get the Yjs library from Dexie constructor options
|
|
7912
|
-
const mergedUpdate = Y.mergeUpdatesV2(serverUpdatesSinceLastSync.map((update) => update.u));
|
|
7913
|
-
const stateVector = Y.encodeStateVectorFromUpdateV2(mergedUpdate);
|
|
7914
|
-
docOpenMsg.sv = stateVector;
|
|
7915
|
-
}
|
|
7916
|
-
db.messageProducer.next(docOpenMsg);
|
|
7917
|
-
});
|
|
7918
|
-
}
|
|
7919
|
-
}));
|
|
7920
|
-
};
|
|
8111
|
+
}
|
|
8112
|
+
}))();
|
|
8113
|
+
return awareness;
|
|
7921
8114
|
}
|
|
7922
8115
|
|
|
7923
8116
|
const DEFAULT_OPTIONS = {
|
|
@@ -7960,7 +8153,7 @@
|
|
|
7960
8153
|
const syncComplete = new rxjs.Subject();
|
|
7961
8154
|
dexie.cloud = {
|
|
7962
8155
|
// @ts-ignore
|
|
7963
|
-
version: "4.1.0-
|
|
8156
|
+
version: "4.1.0-beta.25",
|
|
7964
8157
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
7965
8158
|
schema: null,
|
|
7966
8159
|
get currentUserId() {
|
|
@@ -7996,16 +8189,16 @@
|
|
|
7996
8189
|
}
|
|
7997
8190
|
updateSchemaFromOptions(dexie.cloud.schema, dexie.cloud.options);
|
|
7998
8191
|
},
|
|
7999
|
-
logout(
|
|
8000
|
-
return __awaiter(this,
|
|
8192
|
+
logout() {
|
|
8193
|
+
return __awaiter(this, arguments, void 0, function* ({ force } = {}) {
|
|
8001
8194
|
force
|
|
8002
8195
|
? yield _logout(DexieCloudDB(dexie), { deleteUnsyncedData: true })
|
|
8003
8196
|
: yield logout(DexieCloudDB(dexie));
|
|
8004
8197
|
});
|
|
8005
8198
|
},
|
|
8006
|
-
sync(
|
|
8007
|
-
|
|
8008
|
-
|
|
8199
|
+
sync() {
|
|
8200
|
+
return __awaiter(this, arguments, void 0, function* ({ wait, purpose } = { wait: true, purpose: 'push' }) {
|
|
8201
|
+
var _a;
|
|
8009
8202
|
if (wait === undefined)
|
|
8010
8203
|
wait = true;
|
|
8011
8204
|
const db = DexieCloudDB(dexie);
|
|
@@ -8063,8 +8256,8 @@
|
|
|
8063
8256
|
dexie.use(createImplicitPropSetterMiddleware(DexieCloudDB(dexie)));
|
|
8064
8257
|
dexie.use(createIdGenerationMiddleware(DexieCloudDB(dexie)));
|
|
8065
8258
|
function onDbReady(dexie) {
|
|
8066
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
8067
8259
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8260
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
8068
8261
|
closed = false; // As Dexie calls us, we are not closed anymore. Maybe reopened? Remember db.ready event is registered with sticky flag!
|
|
8069
8262
|
const db = DexieCloudDB(dexie);
|
|
8070
8263
|
// Setup default GUI:
|
|
@@ -8087,7 +8280,7 @@
|
|
|
8087
8280
|
? yield navigator.serviceWorker.getRegistrations()
|
|
8088
8281
|
: [];
|
|
8089
8282
|
const [initiallySynced, lastSyncedRealms] = yield db.transaction('rw', db.$syncState, () => __awaiter(this, void 0, void 0, function* () {
|
|
8090
|
-
var
|
|
8283
|
+
var _a, _b;
|
|
8091
8284
|
const { options, schema } = db.cloud;
|
|
8092
8285
|
const [persistedOptions, persistedSchema, persistedSyncState] = yield Promise.all([
|
|
8093
8286
|
db.getOptions(),
|
|
@@ -8109,7 +8302,7 @@
|
|
|
8109
8302
|
delete newPersistedOptions.awarenessProtocol;
|
|
8110
8303
|
yield db.$syncState.put(newPersistedOptions, 'options');
|
|
8111
8304
|
}
|
|
8112
|
-
if (((
|
|
8305
|
+
if (((_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.tryUseServiceWorker) &&
|
|
8113
8306
|
'serviceWorker' in navigator &&
|
|
8114
8307
|
swRegistrations.length > 0 &&
|
|
8115
8308
|
!DISABLE_SERVICEWORKER_STRATEGY) {
|
|
@@ -8123,7 +8316,7 @@
|
|
|
8123
8316
|
// Not configured for using service worker or no service worker
|
|
8124
8317
|
// registration exists. Don't rely on service worker to do any job.
|
|
8125
8318
|
// Use LocalSyncWorker instead.
|
|
8126
|
-
if (((
|
|
8319
|
+
if (((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.tryUseServiceWorker) &&
|
|
8127
8320
|
!db.cloud.isServiceWorkerDB) {
|
|
8128
8321
|
console.debug('dexie-cloud-addon: Not using service worker.', swRegistrations.length === 0
|
|
8129
8322
|
? 'No SW registrations found.'
|
|
@@ -8166,10 +8359,6 @@
|
|
|
8166
8359
|
db.setInitiallySynced(true);
|
|
8167
8360
|
}
|
|
8168
8361
|
verifySchema(db);
|
|
8169
|
-
if (((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.databaseUrl) && !initiallySynced) {
|
|
8170
|
-
yield performInitialSync(db, db.cloud.options, db.cloud.schema);
|
|
8171
|
-
db.setInitiallySynced(true);
|
|
8172
|
-
}
|
|
8173
8362
|
// Manage CurrentUser observable:
|
|
8174
8363
|
throwIfClosed();
|
|
8175
8364
|
if (!db.cloud.isServiceWorkerDB) {
|
|
@@ -8194,20 +8383,29 @@
|
|
|
8194
8383
|
// HERE: If requireAuth, do athentication now.
|
|
8195
8384
|
let changedUser = false;
|
|
8196
8385
|
const user = yield db.getCurrentUser();
|
|
8197
|
-
const requireAuth = (
|
|
8386
|
+
const requireAuth = (_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.requireAuth;
|
|
8198
8387
|
if (requireAuth) {
|
|
8199
|
-
if (
|
|
8200
|
-
//
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
changedUser = yield login(db, requireAuth);
|
|
8206
|
-
}
|
|
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.');
|
|
8207
8394
|
}
|
|
8208
|
-
else
|
|
8209
|
-
|
|
8210
|
-
|
|
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
|
+
}
|
|
8211
8409
|
}
|
|
8212
8410
|
}
|
|
8213
8411
|
if (user.isLoggedIn && (!lastSyncedRealms || !lastSyncedRealms.includes(user.userId))) {
|
|
@@ -8222,8 +8420,17 @@
|
|
|
8222
8420
|
localSyncWorker.stop();
|
|
8223
8421
|
localSyncWorker = null;
|
|
8224
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();
|
|
8225
8430
|
if (db.cloud.usingServiceWorker && ((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl)) {
|
|
8226
|
-
|
|
8431
|
+
if (!doInitialSync) {
|
|
8432
|
+
registerSyncEvent(db, 'push').catch(() => { });
|
|
8433
|
+
}
|
|
8227
8434
|
registerPeriodicSyncEvent(db).catch(() => { });
|
|
8228
8435
|
}
|
|
8229
8436
|
else if (((_e = db.cloud.options) === null || _e === void 0 ? void 0 : _e.databaseUrl) &&
|
|
@@ -8232,7 +8439,9 @@
|
|
|
8232
8439
|
// There's no SW. Start SyncWorker instead.
|
|
8233
8440
|
localSyncWorker = LocalSyncWorker(db, db.cloud.options, db.cloud.schema);
|
|
8234
8441
|
localSyncWorker.start();
|
|
8235
|
-
|
|
8442
|
+
if (!doInitialSync) {
|
|
8443
|
+
triggerSync(db, 'push');
|
|
8444
|
+
}
|
|
8236
8445
|
}
|
|
8237
8446
|
// Listen to online event and do sync.
|
|
8238
8447
|
throwIfClosed();
|
|
@@ -8252,7 +8461,7 @@
|
|
|
8252
8461
|
});
|
|
8253
8462
|
}));
|
|
8254
8463
|
}
|
|
8255
|
-
// Connect WebSocket unless we
|
|
8464
|
+
// Connect WebSocket unless we are in a service worker or websocket is disabled.
|
|
8256
8465
|
if (((_f = db.cloud.options) === null || _f === void 0 ? void 0 : _f.databaseUrl) &&
|
|
8257
8466
|
!((_g = db.cloud.options) === null || _g === void 0 ? void 0 : _g.disableWebSocket) &&
|
|
8258
8467
|
!IS_SERVICE_WORKER) {
|
|
@@ -8262,7 +8471,7 @@
|
|
|
8262
8471
|
}
|
|
8263
8472
|
}
|
|
8264
8473
|
// @ts-ignore
|
|
8265
|
-
dexieCloud.version = "4.1.0-
|
|
8474
|
+
dexieCloud.version = "4.1.0-beta.25";
|
|
8266
8475
|
Dexie.Cloud = dexieCloud;
|
|
8267
8476
|
|
|
8268
8477
|
// In case the SW lives for a while, let it reuse already opened connections:
|
|
@@ -8292,8 +8501,8 @@
|
|
|
8292
8501
|
}
|
|
8293
8502
|
return promise;
|
|
8294
8503
|
function _syncDB(dbName, purpose) {
|
|
8295
|
-
var _a;
|
|
8296
8504
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8505
|
+
var _a;
|
|
8297
8506
|
let db = managedDBs.get(dbName);
|
|
8298
8507
|
if (!db) {
|
|
8299
8508
|
console.debug('Dexie Cloud SW: Creating new Dexie instance for', dbName);
|