@basictech/react 0.1.1-beta.0 → 0.2.0-beta.1
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/changelog.md +15 -0
- package/dist/index.js +2066 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2065 -64
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/tsup.config.ts +1 -0
package/dist/index.mjs
CHANGED
|
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var require_dexie = __commonJS({
|
|
29
29
|
"../../node_modules/dexie/dist/dexie.js"(exports, module) {
|
|
30
30
|
"use strict";
|
|
31
|
-
(function(
|
|
32
|
-
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (
|
|
31
|
+
(function(global3, factory) {
|
|
32
|
+
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global3 = typeof globalThis !== "undefined" ? globalThis : global3 || self, global3.Dexie = factory());
|
|
33
33
|
})(exports, function() {
|
|
34
34
|
"use strict";
|
|
35
35
|
var extendStatics = function(d, b) {
|
|
@@ -125,7 +125,7 @@ var require_dexie = __commonJS({
|
|
|
125
125
|
function slice(args, start, end) {
|
|
126
126
|
return _slice.call(args, start, end);
|
|
127
127
|
}
|
|
128
|
-
function
|
|
128
|
+
function override3(origFunc, overridedFactory) {
|
|
129
129
|
return overridedFactory(origFunc);
|
|
130
130
|
}
|
|
131
131
|
function assert(b) {
|
|
@@ -460,7 +460,7 @@ var require_dexie = __commonJS({
|
|
|
460
460
|
fullNameExceptions.ModifyError = ModifyError;
|
|
461
461
|
fullNameExceptions.DexieError = DexieError;
|
|
462
462
|
fullNameExceptions.BulkError = BulkError;
|
|
463
|
-
function
|
|
463
|
+
function nop2() {
|
|
464
464
|
}
|
|
465
465
|
function mirror(val) {
|
|
466
466
|
return val;
|
|
@@ -479,7 +479,7 @@ var require_dexie = __commonJS({
|
|
|
479
479
|
};
|
|
480
480
|
}
|
|
481
481
|
function hookCreatingChain(f1, f2) {
|
|
482
|
-
if (f1 ===
|
|
482
|
+
if (f1 === nop2)
|
|
483
483
|
return f2;
|
|
484
484
|
return function() {
|
|
485
485
|
var res = f1.apply(this, arguments);
|
|
@@ -497,7 +497,7 @@ var require_dexie = __commonJS({
|
|
|
497
497
|
};
|
|
498
498
|
}
|
|
499
499
|
function hookDeletingChain(f1, f2) {
|
|
500
|
-
if (f1 ===
|
|
500
|
+
if (f1 === nop2)
|
|
501
501
|
return f2;
|
|
502
502
|
return function() {
|
|
503
503
|
f1.apply(this, arguments);
|
|
@@ -511,7 +511,7 @@ var require_dexie = __commonJS({
|
|
|
511
511
|
};
|
|
512
512
|
}
|
|
513
513
|
function hookUpdatingChain(f1, f2) {
|
|
514
|
-
if (f1 ===
|
|
514
|
+
if (f1 === nop2)
|
|
515
515
|
return f2;
|
|
516
516
|
return function(modifications) {
|
|
517
517
|
var res = f1.apply(this, arguments);
|
|
@@ -528,7 +528,7 @@ var require_dexie = __commonJS({
|
|
|
528
528
|
};
|
|
529
529
|
}
|
|
530
530
|
function reverseStoppableEventChain(f1, f2) {
|
|
531
|
-
if (f1 ===
|
|
531
|
+
if (f1 === nop2)
|
|
532
532
|
return f2;
|
|
533
533
|
return function() {
|
|
534
534
|
if (f2.apply(this, arguments) === false)
|
|
@@ -536,8 +536,8 @@ var require_dexie = __commonJS({
|
|
|
536
536
|
return f1.apply(this, arguments);
|
|
537
537
|
};
|
|
538
538
|
}
|
|
539
|
-
function
|
|
540
|
-
if (f1 ===
|
|
539
|
+
function promisableChain2(f1, f2) {
|
|
540
|
+
if (f1 === nop2)
|
|
541
541
|
return f2;
|
|
542
542
|
return function() {
|
|
543
543
|
var res = f1.apply(this, arguments);
|
|
@@ -586,10 +586,10 @@ var require_dexie = __commonJS({
|
|
|
586
586
|
global: true,
|
|
587
587
|
ref: 0,
|
|
588
588
|
unhandleds: [],
|
|
589
|
-
onunhandled:
|
|
589
|
+
onunhandled: nop2,
|
|
590
590
|
pgp: false,
|
|
591
591
|
env: {},
|
|
592
|
-
finalize:
|
|
592
|
+
finalize: nop2
|
|
593
593
|
};
|
|
594
594
|
var PSD = globalPSD;
|
|
595
595
|
var microtickQueue = [];
|
|
@@ -1027,7 +1027,7 @@ var require_dexie = __commonJS({
|
|
|
1027
1027
|
return true;
|
|
1028
1028
|
}
|
|
1029
1029
|
if (("" + nativePromiseThen).indexOf("[native code]") === -1) {
|
|
1030
|
-
incrementExpectedAwaits = decrementExpectedAwaits =
|
|
1030
|
+
incrementExpectedAwaits = decrementExpectedAwaits = nop2;
|
|
1031
1031
|
}
|
|
1032
1032
|
function onPossibleParallellAsync(possiblePromise) {
|
|
1033
1033
|
if (task.echoes && possiblePromise && possiblePromise.constructor === NativePromise) {
|
|
@@ -1138,7 +1138,7 @@ var require_dexie = __commonJS({
|
|
|
1138
1138
|
if (!db._state.isBeingOpened) {
|
|
1139
1139
|
if (!db._state.autoOpen)
|
|
1140
1140
|
return rejection(new exceptions.DatabaseClosed());
|
|
1141
|
-
db.open().catch(
|
|
1141
|
+
db.open().catch(nop2);
|
|
1142
1142
|
}
|
|
1143
1143
|
return db._state.dbReadyPromise.then(function() {
|
|
1144
1144
|
return tempTransaction(db, mode, storeNames, fn);
|
|
@@ -1685,7 +1685,7 @@ var require_dexie = __commonJS({
|
|
|
1685
1685
|
if (!chainFunction)
|
|
1686
1686
|
chainFunction = reverseStoppableEventChain;
|
|
1687
1687
|
if (!defaultFunction)
|
|
1688
|
-
defaultFunction =
|
|
1688
|
+
defaultFunction = nop2;
|
|
1689
1689
|
var context = {
|
|
1690
1690
|
subscribers: [],
|
|
1691
1691
|
fire: defaultFunction,
|
|
@@ -1737,10 +1737,10 @@ var require_dexie = __commonJS({
|
|
|
1737
1737
|
this.name = name;
|
|
1738
1738
|
this.schema = tableSchema;
|
|
1739
1739
|
this.hook = db._allTables[name] ? db._allTables[name].hook : Events(null, {
|
|
1740
|
-
"creating": [hookCreatingChain,
|
|
1740
|
+
"creating": [hookCreatingChain, nop2],
|
|
1741
1741
|
"reading": [pureFunctionChain, mirror],
|
|
1742
|
-
"updating": [hookUpdatingChain,
|
|
1743
|
-
"deleting": [hookDeletingChain,
|
|
1742
|
+
"updating": [hookUpdatingChain, nop2],
|
|
1743
|
+
"deleting": [hookDeletingChain, nop2]
|
|
1744
1744
|
});
|
|
1745
1745
|
});
|
|
1746
1746
|
}
|
|
@@ -1824,10 +1824,10 @@ var require_dexie = __commonJS({
|
|
|
1824
1824
|
return c = advancer;
|
|
1825
1825
|
}, function(val) {
|
|
1826
1826
|
cursor.stop(val);
|
|
1827
|
-
c =
|
|
1827
|
+
c = nop2;
|
|
1828
1828
|
}, function(e) {
|
|
1829
1829
|
cursor.fail(e);
|
|
1830
|
-
c =
|
|
1830
|
+
c = nop2;
|
|
1831
1831
|
}))
|
|
1832
1832
|
wrappedFn(cursor.value, cursor, function(advancer) {
|
|
1833
1833
|
return c = advancer;
|
|
@@ -3767,7 +3767,7 @@ var require_dexie = __commonJS({
|
|
|
3767
3767
|
return this;
|
|
3768
3768
|
};
|
|
3769
3769
|
Version2.prototype.upgrade = function(upgradeFunction) {
|
|
3770
|
-
this._cfg.contentUpgrade =
|
|
3770
|
+
this._cfg.contentUpgrade = promisableChain2(this._cfg.contentUpgrade || nop2, upgradeFunction);
|
|
3771
3771
|
return this;
|
|
3772
3772
|
};
|
|
3773
3773
|
return Version2;
|
|
@@ -3811,11 +3811,11 @@ var require_dexie = __commonJS({
|
|
|
3811
3811
|
}
|
|
3812
3812
|
function _onDatabaseCreated(_a2, name) {
|
|
3813
3813
|
var indexedDB2 = _a2.indexedDB, IDBKeyRange = _a2.IDBKeyRange;
|
|
3814
|
-
!hasDatabasesNative(indexedDB2) && name !== DBNAMES_DB && getDbNamesTable(indexedDB2, IDBKeyRange).put({ name }).catch(
|
|
3814
|
+
!hasDatabasesNative(indexedDB2) && name !== DBNAMES_DB && getDbNamesTable(indexedDB2, IDBKeyRange).put({ name }).catch(nop2);
|
|
3815
3815
|
}
|
|
3816
3816
|
function _onDatabaseDeleted(_a2, name) {
|
|
3817
3817
|
var indexedDB2 = _a2.indexedDB, IDBKeyRange = _a2.IDBKeyRange;
|
|
3818
|
-
!hasDatabasesNative(indexedDB2) && name !== DBNAMES_DB && getDbNamesTable(indexedDB2, IDBKeyRange).delete(name).catch(
|
|
3818
|
+
!hasDatabasesNative(indexedDB2) && name !== DBNAMES_DB && getDbNamesTable(indexedDB2, IDBKeyRange).delete(name).catch(nop2);
|
|
3819
3819
|
}
|
|
3820
3820
|
function vip(fn) {
|
|
3821
3821
|
return newScope(function() {
|
|
@@ -4187,7 +4187,7 @@ var require_dexie = __commonJS({
|
|
|
4187
4187
|
return db.on.ready.fire(db.vip);
|
|
4188
4188
|
})).then(function fireRemainders() {
|
|
4189
4189
|
if (state.onReadyBeingFired.length > 0) {
|
|
4190
|
-
var remainders_1 = state.onReadyBeingFired.reduce(
|
|
4190
|
+
var remainders_1 = state.onReadyBeingFired.reduce(promisableChain2, nop2);
|
|
4191
4191
|
state.onReadyBeingFired = [];
|
|
4192
4192
|
return DexiePromise.resolve(vip(function() {
|
|
4193
4193
|
return remainders_1(db.vip);
|
|
@@ -4467,25 +4467,25 @@ var require_dexie = __commonJS({
|
|
|
4467
4467
|
var _a2 = dxTrans.table(tableName).hook, deleting = _a2.deleting, creating = _a2.creating, updating = _a2.updating;
|
|
4468
4468
|
switch (req.type) {
|
|
4469
4469
|
case "add":
|
|
4470
|
-
if (creating.fire ===
|
|
4470
|
+
if (creating.fire === nop2)
|
|
4471
4471
|
break;
|
|
4472
4472
|
return dxTrans._promise("readwrite", function() {
|
|
4473
4473
|
return addPutOrDelete(req);
|
|
4474
4474
|
}, true);
|
|
4475
4475
|
case "put":
|
|
4476
|
-
if (creating.fire ===
|
|
4476
|
+
if (creating.fire === nop2 && updating.fire === nop2)
|
|
4477
4477
|
break;
|
|
4478
4478
|
return dxTrans._promise("readwrite", function() {
|
|
4479
4479
|
return addPutOrDelete(req);
|
|
4480
4480
|
}, true);
|
|
4481
4481
|
case "delete":
|
|
4482
|
-
if (deleting.fire ===
|
|
4482
|
+
if (deleting.fire === nop2)
|
|
4483
4483
|
break;
|
|
4484
4484
|
return dxTrans._promise("readwrite", function() {
|
|
4485
4485
|
return addPutOrDelete(req);
|
|
4486
4486
|
}, true);
|
|
4487
4487
|
case "deleteRange":
|
|
4488
|
-
if (deleting.fire ===
|
|
4488
|
+
if (deleting.fire === nop2)
|
|
4489
4489
|
break;
|
|
4490
4490
|
return dxTrans._promise("readwrite", function() {
|
|
4491
4491
|
return deleteRange(req);
|
|
@@ -5280,9 +5280,9 @@ var require_dexie = __commonJS({
|
|
|
5280
5280
|
isBeingOpened: false,
|
|
5281
5281
|
onReadyBeingFired: null,
|
|
5282
5282
|
openComplete: false,
|
|
5283
|
-
dbReadyResolve:
|
|
5283
|
+
dbReadyResolve: nop2,
|
|
5284
5284
|
dbReadyPromise: null,
|
|
5285
|
-
cancelOpen:
|
|
5285
|
+
cancelOpen: nop2,
|
|
5286
5286
|
openCanceller: null,
|
|
5287
5287
|
autoSchema: true,
|
|
5288
5288
|
PR1398_maxLoop: 3,
|
|
@@ -5296,8 +5296,8 @@ var require_dexie = __commonJS({
|
|
|
5296
5296
|
});
|
|
5297
5297
|
this._state = state;
|
|
5298
5298
|
this.name = name;
|
|
5299
|
-
this.on = Events(this, "populate", "blocked", "versionchange", "close", { ready: [
|
|
5300
|
-
this.on.ready.subscribe =
|
|
5299
|
+
this.on = Events(this, "populate", "blocked", "versionchange", "close", { ready: [promisableChain2, nop2] });
|
|
5300
|
+
this.on.ready.subscribe = override3(this.on.ready.subscribe, function(subscribe) {
|
|
5301
5301
|
return function(subscriber, bSticky) {
|
|
5302
5302
|
Dexie3.vip(function() {
|
|
5303
5303
|
var state2 = _this._state;
|
|
@@ -5416,7 +5416,7 @@ var require_dexie = __commonJS({
|
|
|
5416
5416
|
reject(new exceptions.DatabaseClosed());
|
|
5417
5417
|
return;
|
|
5418
5418
|
}
|
|
5419
|
-
_this.open().catch(
|
|
5419
|
+
_this.open().catch(nop2);
|
|
5420
5420
|
}
|
|
5421
5421
|
_this._state.dbReadyPromise.then(resolve, reject);
|
|
5422
5422
|
}).then(fn);
|
|
@@ -5606,17 +5606,17 @@ var require_dexie = __commonJS({
|
|
|
5606
5606
|
return Dexie3;
|
|
5607
5607
|
}();
|
|
5608
5608
|
var symbolObservable = typeof Symbol !== "undefined" && "observable" in Symbol ? Symbol.observable : "@@observable";
|
|
5609
|
-
var
|
|
5610
|
-
function
|
|
5609
|
+
var Observable3 = function() {
|
|
5610
|
+
function Observable4(subscribe) {
|
|
5611
5611
|
this._subscribe = subscribe;
|
|
5612
5612
|
}
|
|
5613
|
-
|
|
5613
|
+
Observable4.prototype.subscribe = function(x, error, complete) {
|
|
5614
5614
|
return this._subscribe(!x || typeof x === "function" ? { next: x, error, complete } : x);
|
|
5615
5615
|
};
|
|
5616
|
-
|
|
5616
|
+
Observable4.prototype[symbolObservable] = function() {
|
|
5617
5617
|
return this;
|
|
5618
5618
|
};
|
|
5619
|
-
return
|
|
5619
|
+
return Observable4;
|
|
5620
5620
|
}();
|
|
5621
5621
|
var domDeps;
|
|
5622
5622
|
try {
|
|
@@ -5630,7 +5630,7 @@ var require_dexie = __commonJS({
|
|
|
5630
5630
|
function liveQuery2(querier) {
|
|
5631
5631
|
var hasValue = false;
|
|
5632
5632
|
var currentValue;
|
|
5633
|
-
var observable = new
|
|
5633
|
+
var observable = new Observable3(function(observer) {
|
|
5634
5634
|
var scopeFuncIsAsync = isAsyncFunction(querier);
|
|
5635
5635
|
function execute(ctx) {
|
|
5636
5636
|
var wasRootExec = beginMicroTickScope();
|
|
@@ -5808,7 +5808,7 @@ var require_dexie = __commonJS({
|
|
|
5808
5808
|
derive,
|
|
5809
5809
|
extend,
|
|
5810
5810
|
props,
|
|
5811
|
-
override,
|
|
5811
|
+
override: override3,
|
|
5812
5812
|
Events,
|
|
5813
5813
|
on: globalEvents,
|
|
5814
5814
|
liveQuery: liveQuery2,
|
|
@@ -5942,7 +5942,2029 @@ var require_dexie = __commonJS({
|
|
|
5942
5942
|
// src/AuthContext.tsx
|
|
5943
5943
|
import { createContext, useContext, useEffect, useState, useRef } from "react";
|
|
5944
5944
|
import { jwtDecode } from "jwt-decode";
|
|
5945
|
-
|
|
5945
|
+
|
|
5946
|
+
// ../../node_modules/uuid/dist/esm-node/stringify.js
|
|
5947
|
+
var byteToHex = [];
|
|
5948
|
+
for (let i = 0; i < 256; ++i) {
|
|
5949
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
5950
|
+
}
|
|
5951
|
+
function unsafeStringify(arr, offset = 0) {
|
|
5952
|
+
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
5953
|
+
}
|
|
5954
|
+
|
|
5955
|
+
// ../../node_modules/uuid/dist/esm-node/rng.js
|
|
5956
|
+
import crypto2 from "crypto";
|
|
5957
|
+
var rnds8Pool = new Uint8Array(256);
|
|
5958
|
+
var poolPtr = rnds8Pool.length;
|
|
5959
|
+
function rng() {
|
|
5960
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
5961
|
+
crypto2.randomFillSync(rnds8Pool);
|
|
5962
|
+
poolPtr = 0;
|
|
5963
|
+
}
|
|
5964
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5967
|
+
// ../../node_modules/uuid/dist/esm-node/v7.js
|
|
5968
|
+
var _seqLow = null;
|
|
5969
|
+
var _seqHigh = null;
|
|
5970
|
+
var _msecs = 0;
|
|
5971
|
+
function v7(options, buf, offset) {
|
|
5972
|
+
options = options || {};
|
|
5973
|
+
let i = buf && offset || 0;
|
|
5974
|
+
const b = buf || new Uint8Array(16);
|
|
5975
|
+
const rnds = options.random || (options.rng || rng)();
|
|
5976
|
+
const msecs = options.msecs !== void 0 ? options.msecs : Date.now();
|
|
5977
|
+
let seq = options.seq !== void 0 ? options.seq : null;
|
|
5978
|
+
let seqHigh = _seqHigh;
|
|
5979
|
+
let seqLow = _seqLow;
|
|
5980
|
+
if (msecs > _msecs && options.msecs === void 0) {
|
|
5981
|
+
_msecs = msecs;
|
|
5982
|
+
if (seq !== null) {
|
|
5983
|
+
seqHigh = null;
|
|
5984
|
+
seqLow = null;
|
|
5985
|
+
}
|
|
5986
|
+
}
|
|
5987
|
+
if (seq !== null) {
|
|
5988
|
+
if (seq > 2147483647) {
|
|
5989
|
+
seq = 2147483647;
|
|
5990
|
+
}
|
|
5991
|
+
seqHigh = seq >>> 19 & 4095;
|
|
5992
|
+
seqLow = seq & 524287;
|
|
5993
|
+
}
|
|
5994
|
+
if (seqHigh === null || seqLow === null) {
|
|
5995
|
+
seqHigh = rnds[6] & 127;
|
|
5996
|
+
seqHigh = seqHigh << 8 | rnds[7];
|
|
5997
|
+
seqLow = rnds[8] & 63;
|
|
5998
|
+
seqLow = seqLow << 8 | rnds[9];
|
|
5999
|
+
seqLow = seqLow << 5 | rnds[10] >>> 3;
|
|
6000
|
+
}
|
|
6001
|
+
if (msecs + 1e4 > _msecs && seq === null) {
|
|
6002
|
+
if (++seqLow > 524287) {
|
|
6003
|
+
seqLow = 0;
|
|
6004
|
+
if (++seqHigh > 4095) {
|
|
6005
|
+
seqHigh = 0;
|
|
6006
|
+
_msecs++;
|
|
6007
|
+
}
|
|
6008
|
+
}
|
|
6009
|
+
} else {
|
|
6010
|
+
_msecs = msecs;
|
|
6011
|
+
}
|
|
6012
|
+
_seqHigh = seqHigh;
|
|
6013
|
+
_seqLow = seqLow;
|
|
6014
|
+
b[i++] = _msecs / 1099511627776 & 255;
|
|
6015
|
+
b[i++] = _msecs / 4294967296 & 255;
|
|
6016
|
+
b[i++] = _msecs / 16777216 & 255;
|
|
6017
|
+
b[i++] = _msecs / 65536 & 255;
|
|
6018
|
+
b[i++] = _msecs / 256 & 255;
|
|
6019
|
+
b[i++] = _msecs & 255;
|
|
6020
|
+
b[i++] = seqHigh >>> 4 & 15 | 112;
|
|
6021
|
+
b[i++] = seqHigh & 255;
|
|
6022
|
+
b[i++] = seqLow >>> 13 & 63 | 128;
|
|
6023
|
+
b[i++] = seqLow >>> 5 & 255;
|
|
6024
|
+
b[i++] = seqLow << 3 & 255 | rnds[10] & 7;
|
|
6025
|
+
b[i++] = rnds[11];
|
|
6026
|
+
b[i++] = rnds[12];
|
|
6027
|
+
b[i++] = rnds[13];
|
|
6028
|
+
b[i++] = rnds[14];
|
|
6029
|
+
b[i++] = rnds[15];
|
|
6030
|
+
return buf || unsafeStringify(b);
|
|
6031
|
+
}
|
|
6032
|
+
var v7_default = v7;
|
|
6033
|
+
|
|
6034
|
+
// ../../node_modules/dexie/import-wrapper.mjs
|
|
6035
|
+
var import_dexie = __toESM(require_dexie(), 1);
|
|
6036
|
+
var DexieSymbol = Symbol.for("Dexie");
|
|
6037
|
+
var Dexie = globalThis[DexieSymbol] || (globalThis[DexieSymbol] = import_dexie.default);
|
|
6038
|
+
if (import_dexie.default.semVer !== Dexie.semVer) {
|
|
6039
|
+
throw new Error(`Two different versions of Dexie loaded in the same app: ${import_dexie.default.semVer} and ${Dexie.semVer}`);
|
|
6040
|
+
}
|
|
6041
|
+
var {
|
|
6042
|
+
liveQuery,
|
|
6043
|
+
mergeRanges,
|
|
6044
|
+
rangesOverlap,
|
|
6045
|
+
RangeSet,
|
|
6046
|
+
cmp,
|
|
6047
|
+
Entity,
|
|
6048
|
+
PropModSymbol,
|
|
6049
|
+
PropModification,
|
|
6050
|
+
replacePrefix,
|
|
6051
|
+
add,
|
|
6052
|
+
remove
|
|
6053
|
+
} = Dexie;
|
|
6054
|
+
var import_wrapper_default = Dexie;
|
|
6055
|
+
|
|
6056
|
+
// ../../node_modules/dexie-observable/dist/dexie-observable.es.js
|
|
6057
|
+
function nop() {
|
|
6058
|
+
}
|
|
6059
|
+
function promisableChain(f1, f2) {
|
|
6060
|
+
if (f1 === nop)
|
|
6061
|
+
return f2;
|
|
6062
|
+
return function() {
|
|
6063
|
+
var res = f1.apply(this, arguments);
|
|
6064
|
+
if (res && typeof res.then === "function") {
|
|
6065
|
+
var thiz = this, args = arguments;
|
|
6066
|
+
return res.then(function() {
|
|
6067
|
+
return f2.apply(thiz, args);
|
|
6068
|
+
});
|
|
6069
|
+
}
|
|
6070
|
+
return f2.apply(this, arguments);
|
|
6071
|
+
};
|
|
6072
|
+
}
|
|
6073
|
+
function createUUID() {
|
|
6074
|
+
var d = Date.now();
|
|
6075
|
+
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
|
6076
|
+
var r = (d + Math.random() * 16) % 16 | 0;
|
|
6077
|
+
d = Math.floor(d / 16);
|
|
6078
|
+
return (c === "x" ? r : r & 7 | 8).toString(16);
|
|
6079
|
+
});
|
|
6080
|
+
return uuid;
|
|
6081
|
+
}
|
|
6082
|
+
function initOverrideCreateTransaction(db, wakeupObservers) {
|
|
6083
|
+
return function overrideCreateTransaction(origFunc) {
|
|
6084
|
+
return function(mode, storenames, dbschema, parent) {
|
|
6085
|
+
if (db.dynamicallyOpened())
|
|
6086
|
+
return origFunc.apply(this, arguments);
|
|
6087
|
+
var addChanges = false;
|
|
6088
|
+
if (mode === "readwrite" && storenames.some(function(storeName) {
|
|
6089
|
+
return dbschema[storeName] && dbschema[storeName].observable;
|
|
6090
|
+
})) {
|
|
6091
|
+
addChanges = true;
|
|
6092
|
+
storenames = storenames.slice(0);
|
|
6093
|
+
if (storenames.indexOf("_changes") === -1)
|
|
6094
|
+
storenames.push("_changes");
|
|
6095
|
+
}
|
|
6096
|
+
var trans = origFunc.call(this, mode, storenames, dbschema, parent);
|
|
6097
|
+
if (addChanges) {
|
|
6098
|
+
trans._lastWrittenRevision = 0;
|
|
6099
|
+
trans.on("complete", function() {
|
|
6100
|
+
if (trans._lastWrittenRevision) {
|
|
6101
|
+
if (!parent) {
|
|
6102
|
+
if (wakeupObservers.timeoutHandle)
|
|
6103
|
+
clearTimeout(wakeupObservers.timeoutHandle);
|
|
6104
|
+
wakeupObservers.timeoutHandle = setTimeout(function() {
|
|
6105
|
+
delete wakeupObservers.timeoutHandle;
|
|
6106
|
+
wakeupObservers(trans._lastWrittenRevision);
|
|
6107
|
+
}, 25);
|
|
6108
|
+
} else {
|
|
6109
|
+
var rootTransaction = function findRootTransaction(trans2) {
|
|
6110
|
+
return trans2.parent ? findRootTransaction(trans2.parent) : trans2;
|
|
6111
|
+
}(parent);
|
|
6112
|
+
rootTransaction._lastWrittenRevision = Math.max(trans._lastWrittenRevision, rootTransaction.lastWrittenRevision || 0);
|
|
6113
|
+
}
|
|
6114
|
+
}
|
|
6115
|
+
});
|
|
6116
|
+
if (trans.parent && trans.parent.source)
|
|
6117
|
+
trans.source = trans.parent.source;
|
|
6118
|
+
}
|
|
6119
|
+
return trans;
|
|
6120
|
+
};
|
|
6121
|
+
};
|
|
6122
|
+
}
|
|
6123
|
+
function initWakeupObservers(db, Observable3, localStorage) {
|
|
6124
|
+
return function wakeupObservers(lastWrittenRevision) {
|
|
6125
|
+
if (Observable3.latestRevision[db.name] < lastWrittenRevision) {
|
|
6126
|
+
Observable3.latestRevision[db.name] = lastWrittenRevision;
|
|
6127
|
+
import_wrapper_default.ignoreTransaction(function() {
|
|
6128
|
+
Observable3.on("latestRevisionIncremented").fire(db.name, lastWrittenRevision);
|
|
6129
|
+
});
|
|
6130
|
+
if (localStorage)
|
|
6131
|
+
localStorage.setItem("Dexie.Observable/latestRevision/" + db.name, lastWrittenRevision);
|
|
6132
|
+
}
|
|
6133
|
+
};
|
|
6134
|
+
}
|
|
6135
|
+
var CREATE = 1;
|
|
6136
|
+
var UPDATE = 2;
|
|
6137
|
+
var DELETE = 3;
|
|
6138
|
+
function initCreatingHook(db, table) {
|
|
6139
|
+
return function creatingHook(primKey, obj, trans) {
|
|
6140
|
+
var rv = void 0;
|
|
6141
|
+
if (primKey === void 0 && table.schema.primKey.uuid) {
|
|
6142
|
+
primKey = rv = import_wrapper_default.Observable.createUUID();
|
|
6143
|
+
if (table.schema.primKey.keyPath) {
|
|
6144
|
+
import_wrapper_default.setByKeyPath(obj, table.schema.primKey.keyPath, primKey);
|
|
6145
|
+
}
|
|
6146
|
+
}
|
|
6147
|
+
var change = {
|
|
6148
|
+
source: trans.source || null,
|
|
6149
|
+
table: table.name,
|
|
6150
|
+
key: primKey === void 0 ? null : primKey,
|
|
6151
|
+
type: CREATE,
|
|
6152
|
+
obj
|
|
6153
|
+
};
|
|
6154
|
+
var promise = db._changes.add(change).then(function(rev) {
|
|
6155
|
+
trans._lastWrittenRevision = Math.max(trans._lastWrittenRevision, rev);
|
|
6156
|
+
return rev;
|
|
6157
|
+
});
|
|
6158
|
+
this.onsuccess = function(resultKey) {
|
|
6159
|
+
if (primKey != resultKey)
|
|
6160
|
+
promise._then(function() {
|
|
6161
|
+
change.key = resultKey;
|
|
6162
|
+
db._changes.put(change);
|
|
6163
|
+
});
|
|
6164
|
+
};
|
|
6165
|
+
this.onerror = function() {
|
|
6166
|
+
promise._then(function(rev) {
|
|
6167
|
+
db._changes.delete(rev);
|
|
6168
|
+
});
|
|
6169
|
+
};
|
|
6170
|
+
return rv;
|
|
6171
|
+
};
|
|
6172
|
+
}
|
|
6173
|
+
function initUpdatingHook(db, tableName) {
|
|
6174
|
+
return function updatingHook(mods, primKey, oldObj, trans) {
|
|
6175
|
+
var modsWithoutUndefined = {};
|
|
6176
|
+
var anythingChanged = false;
|
|
6177
|
+
var newObj = import_wrapper_default.deepClone(oldObj);
|
|
6178
|
+
for (var propPath in mods) {
|
|
6179
|
+
var mod = mods[propPath];
|
|
6180
|
+
if (typeof mod === "undefined") {
|
|
6181
|
+
import_wrapper_default.delByKeyPath(newObj, propPath);
|
|
6182
|
+
modsWithoutUndefined[propPath] = null;
|
|
6183
|
+
anythingChanged = true;
|
|
6184
|
+
} else {
|
|
6185
|
+
var currentValue = import_wrapper_default.getByKeyPath(oldObj, propPath);
|
|
6186
|
+
if (mod !== currentValue && JSON.stringify(mod) !== JSON.stringify(currentValue)) {
|
|
6187
|
+
import_wrapper_default.setByKeyPath(newObj, propPath, mod);
|
|
6188
|
+
modsWithoutUndefined[propPath] = mod;
|
|
6189
|
+
anythingChanged = true;
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
}
|
|
6193
|
+
if (anythingChanged) {
|
|
6194
|
+
var change = {
|
|
6195
|
+
source: trans.source || null,
|
|
6196
|
+
table: tableName,
|
|
6197
|
+
key: primKey,
|
|
6198
|
+
type: UPDATE,
|
|
6199
|
+
mods: modsWithoutUndefined,
|
|
6200
|
+
oldObj,
|
|
6201
|
+
obj: newObj
|
|
6202
|
+
};
|
|
6203
|
+
var promise = db._changes.add(change);
|
|
6204
|
+
this.onsuccess = function() {
|
|
6205
|
+
promise._then(function(rev) {
|
|
6206
|
+
trans._lastWrittenRevision = Math.max(trans._lastWrittenRevision, rev);
|
|
6207
|
+
});
|
|
6208
|
+
};
|
|
6209
|
+
this.onerror = function() {
|
|
6210
|
+
promise._then(function(rev) {
|
|
6211
|
+
db._changes.delete(rev);
|
|
6212
|
+
});
|
|
6213
|
+
};
|
|
6214
|
+
}
|
|
6215
|
+
};
|
|
6216
|
+
}
|
|
6217
|
+
function initDeletingHook(db, tableName) {
|
|
6218
|
+
return function deletingHook(primKey, obj, trans) {
|
|
6219
|
+
var promise = db._changes.add({
|
|
6220
|
+
source: trans.source || null,
|
|
6221
|
+
table: tableName,
|
|
6222
|
+
key: primKey,
|
|
6223
|
+
type: DELETE,
|
|
6224
|
+
oldObj: obj
|
|
6225
|
+
}).then(function(rev) {
|
|
6226
|
+
trans._lastWrittenRevision = Math.max(trans._lastWrittenRevision, rev);
|
|
6227
|
+
return rev;
|
|
6228
|
+
}).catch(function(e) {
|
|
6229
|
+
console.log(obj);
|
|
6230
|
+
console.log(e.stack);
|
|
6231
|
+
});
|
|
6232
|
+
this.onerror = function() {
|
|
6233
|
+
promise._then(function(rev) {
|
|
6234
|
+
db._changes.delete(rev);
|
|
6235
|
+
});
|
|
6236
|
+
};
|
|
6237
|
+
};
|
|
6238
|
+
}
|
|
6239
|
+
function initCrudMonitor(db) {
|
|
6240
|
+
return function crudMonitor(table) {
|
|
6241
|
+
if (table.hook._observing)
|
|
6242
|
+
return;
|
|
6243
|
+
table.hook._observing = true;
|
|
6244
|
+
var tableName = table.name;
|
|
6245
|
+
table.hook("creating").subscribe(initCreatingHook(db, table));
|
|
6246
|
+
table.hook("updating").subscribe(initUpdatingHook(db, tableName));
|
|
6247
|
+
table.hook("deleting").subscribe(initDeletingHook(db, tableName));
|
|
6248
|
+
};
|
|
6249
|
+
}
|
|
6250
|
+
function initOnStorage(Observable3) {
|
|
6251
|
+
return function onStorage(event) {
|
|
6252
|
+
if (event.key && event.key.indexOf("Dexie.Observable/") === 0) {
|
|
6253
|
+
var parts = event.key.split("/");
|
|
6254
|
+
var prop = parts[1];
|
|
6255
|
+
var dbname = parts[2];
|
|
6256
|
+
if (prop === "latestRevision") {
|
|
6257
|
+
var rev = parseInt(event.newValue, 10);
|
|
6258
|
+
if (!isNaN(rev) && rev > Observable3.latestRevision[dbname]) {
|
|
6259
|
+
Observable3.latestRevision[dbname] = rev;
|
|
6260
|
+
import_wrapper_default.ignoreTransaction(function() {
|
|
6261
|
+
Observable3.on("latestRevisionIncremented").fire(dbname, rev);
|
|
6262
|
+
});
|
|
6263
|
+
}
|
|
6264
|
+
} else if (prop.indexOf("deadnode:") === 0) {
|
|
6265
|
+
var nodeID = parseInt(prop.split(":")[1], 10);
|
|
6266
|
+
if (event.newValue) {
|
|
6267
|
+
Observable3.on.suicideNurseCall.fire(dbname, nodeID);
|
|
6268
|
+
}
|
|
6269
|
+
} else if (prop === "intercomm") {
|
|
6270
|
+
if (event.newValue) {
|
|
6271
|
+
Observable3.on.intercomm.fire(dbname);
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
}
|
|
6275
|
+
};
|
|
6276
|
+
}
|
|
6277
|
+
function initOverrideOpen(db, SyncNode, crudMonitor) {
|
|
6278
|
+
return function overrideOpen(origOpen) {
|
|
6279
|
+
return function() {
|
|
6280
|
+
Object.keys(db._allTables).forEach(function(tableName) {
|
|
6281
|
+
var table = db._allTables[tableName];
|
|
6282
|
+
if (table.schema.observable) {
|
|
6283
|
+
crudMonitor(table);
|
|
6284
|
+
}
|
|
6285
|
+
if (table.name === "_syncNodes") {
|
|
6286
|
+
table.mapToClass(SyncNode);
|
|
6287
|
+
}
|
|
6288
|
+
});
|
|
6289
|
+
return origOpen.apply(this, arguments);
|
|
6290
|
+
};
|
|
6291
|
+
};
|
|
6292
|
+
}
|
|
6293
|
+
var Promise$2 = import_wrapper_default.Promise;
|
|
6294
|
+
function initIntercomm(db, Observable3, SyncNode, mySyncNode, localStorage) {
|
|
6295
|
+
var requestsWaitingForReply = {};
|
|
6296
|
+
db.observable.sendMessage = function(type, message, destinationNode, options) {
|
|
6297
|
+
options = options || {};
|
|
6298
|
+
if (!mySyncNode.node)
|
|
6299
|
+
return options.wantReply ? Promise$2.reject(new import_wrapper_default.DatabaseClosedError()) : Promise$2.resolve();
|
|
6300
|
+
var msg = { message, destinationNode, sender: mySyncNode.node.id, type };
|
|
6301
|
+
import_wrapper_default.extend(msg, options);
|
|
6302
|
+
return import_wrapper_default.ignoreTransaction(function() {
|
|
6303
|
+
var tables = ["_intercomm"];
|
|
6304
|
+
if (options.wantReply)
|
|
6305
|
+
tables.push("_syncNodes");
|
|
6306
|
+
var promise = db.transaction("rw", tables, function() {
|
|
6307
|
+
if (options.wantReply) {
|
|
6308
|
+
return db._syncNodes.where("id").equals(destinationNode).count(function(receiverAlive) {
|
|
6309
|
+
if (receiverAlive)
|
|
6310
|
+
return db._intercomm.add(msg);
|
|
6311
|
+
else
|
|
6312
|
+
return db._syncNodes.where("isMaster").above(0).first(function(masterNode) {
|
|
6313
|
+
msg.destinationNode = masterNode.id;
|
|
6314
|
+
return db._intercomm.add(msg);
|
|
6315
|
+
});
|
|
6316
|
+
});
|
|
6317
|
+
} else {
|
|
6318
|
+
return db._intercomm.add(msg);
|
|
6319
|
+
}
|
|
6320
|
+
}).then(function(messageId) {
|
|
6321
|
+
var rv = null;
|
|
6322
|
+
if (options.wantReply) {
|
|
6323
|
+
rv = new Promise$2(function(resolve, reject) {
|
|
6324
|
+
requestsWaitingForReply[messageId.toString()] = { resolve, reject };
|
|
6325
|
+
});
|
|
6326
|
+
}
|
|
6327
|
+
if (localStorage) {
|
|
6328
|
+
localStorage.setItem("Dexie.Observable/intercomm/" + db.name, messageId.toString());
|
|
6329
|
+
}
|
|
6330
|
+
Observable3.on.intercomm.fire(db.name);
|
|
6331
|
+
return rv;
|
|
6332
|
+
});
|
|
6333
|
+
if (!options.wantReply) {
|
|
6334
|
+
promise.catch(function() {
|
|
6335
|
+
});
|
|
6336
|
+
return;
|
|
6337
|
+
} else {
|
|
6338
|
+
return promise;
|
|
6339
|
+
}
|
|
6340
|
+
});
|
|
6341
|
+
};
|
|
6342
|
+
db.observable.broadcastMessage = function(type, message, bIncludeSelf) {
|
|
6343
|
+
if (!mySyncNode.node)
|
|
6344
|
+
return;
|
|
6345
|
+
var mySyncNodeId = mySyncNode.node.id;
|
|
6346
|
+
import_wrapper_default.ignoreTransaction(function() {
|
|
6347
|
+
db._syncNodes.toArray(function(nodes) {
|
|
6348
|
+
return Promise$2.all(nodes.filter(function(node) {
|
|
6349
|
+
return node.type === "local" && (bIncludeSelf || node.id !== mySyncNodeId);
|
|
6350
|
+
}).map(function(node) {
|
|
6351
|
+
return db.observable.sendMessage(type, message, node.id);
|
|
6352
|
+
}));
|
|
6353
|
+
}).catch(function() {
|
|
6354
|
+
});
|
|
6355
|
+
});
|
|
6356
|
+
};
|
|
6357
|
+
function consumeIntercommMessages() {
|
|
6358
|
+
if (!mySyncNode.node)
|
|
6359
|
+
return Promise$2.reject(new import_wrapper_default.DatabaseClosedError());
|
|
6360
|
+
return import_wrapper_default.ignoreTransaction(function() {
|
|
6361
|
+
return db.transaction("rw", "_intercomm", function() {
|
|
6362
|
+
return db._intercomm.where({ destinationNode: mySyncNode.node.id }).toArray(function(messages) {
|
|
6363
|
+
messages.forEach(function(msg) {
|
|
6364
|
+
return consumeMessage(msg);
|
|
6365
|
+
});
|
|
6366
|
+
return db._intercomm.where("id").anyOf(messages.map(function(msg) {
|
|
6367
|
+
return msg.id;
|
|
6368
|
+
})).delete();
|
|
6369
|
+
});
|
|
6370
|
+
});
|
|
6371
|
+
});
|
|
6372
|
+
}
|
|
6373
|
+
function consumeMessage(msg) {
|
|
6374
|
+
if (msg.type === "response") {
|
|
6375
|
+
var request = requestsWaitingForReply[msg.requestId.toString()];
|
|
6376
|
+
if (request) {
|
|
6377
|
+
if (msg.isFailure) {
|
|
6378
|
+
request.reject(msg.message.error);
|
|
6379
|
+
} else {
|
|
6380
|
+
request.resolve(msg.message.result);
|
|
6381
|
+
}
|
|
6382
|
+
delete requestsWaitingForReply[msg.requestId.toString()];
|
|
6383
|
+
}
|
|
6384
|
+
} else {
|
|
6385
|
+
msg.resolve = function(result) {
|
|
6386
|
+
db.observable.sendMessage("response", { result }, msg.sender, { requestId: msg.id });
|
|
6387
|
+
};
|
|
6388
|
+
msg.reject = function(error) {
|
|
6389
|
+
db.observable.sendMessage("response", { error: error.toString() }, msg.sender, { isFailure: true, requestId: msg.id });
|
|
6390
|
+
};
|
|
6391
|
+
db.on.message.fire(msg);
|
|
6392
|
+
}
|
|
6393
|
+
}
|
|
6394
|
+
function onIntercomm(dbname) {
|
|
6395
|
+
if (dbname === db.name) {
|
|
6396
|
+
consumeIntercommMessages().catch("DatabaseClosedError", function() {
|
|
6397
|
+
});
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
return {
|
|
6401
|
+
onIntercomm,
|
|
6402
|
+
consumeIntercommMessages
|
|
6403
|
+
};
|
|
6404
|
+
}
|
|
6405
|
+
function overrideParseStoresSpec(origFunc) {
|
|
6406
|
+
return function(stores, dbSchema) {
|
|
6407
|
+
stores["_changes"] = "++rev";
|
|
6408
|
+
stores["_syncNodes"] = "++id,myRevision,lastHeartBeat,&url,isMaster,type,status";
|
|
6409
|
+
stores["_intercomm"] = "++id,destinationNode";
|
|
6410
|
+
stores["_uncommittedChanges"] = "++id,node";
|
|
6411
|
+
origFunc.call(this, stores, dbSchema);
|
|
6412
|
+
Object.keys(dbSchema).forEach(function(tableName) {
|
|
6413
|
+
var schema = dbSchema[tableName];
|
|
6414
|
+
if (schema.primKey.name.indexOf("$$") === 0) {
|
|
6415
|
+
schema.primKey.uuid = true;
|
|
6416
|
+
schema.primKey.name = schema.primKey.name.substr(2);
|
|
6417
|
+
schema.primKey.keyPath = schema.primKey.keyPath.substr(2);
|
|
6418
|
+
}
|
|
6419
|
+
});
|
|
6420
|
+
Object.keys(dbSchema).forEach(function(tableName) {
|
|
6421
|
+
if (tableName.indexOf("_") !== 0 && tableName.indexOf("$") !== 0) {
|
|
6422
|
+
dbSchema[tableName].observable = true;
|
|
6423
|
+
}
|
|
6424
|
+
});
|
|
6425
|
+
};
|
|
6426
|
+
}
|
|
6427
|
+
function deleteOldChanges(db) {
|
|
6428
|
+
var CHUNK_SIZE = 100;
|
|
6429
|
+
import_wrapper_default.ignoreTransaction(function() {
|
|
6430
|
+
return db._syncNodes.orderBy("myRevision").first(function(oldestNode) {
|
|
6431
|
+
return db._changes.where("rev").below(oldestNode.myRevision).limit(CHUNK_SIZE).primaryKeys();
|
|
6432
|
+
}).then(function(keysToDelete) {
|
|
6433
|
+
if (keysToDelete.length === 0)
|
|
6434
|
+
return;
|
|
6435
|
+
return db._changes.bulkDelete(keysToDelete).then(function() {
|
|
6436
|
+
if (keysToDelete.length === CHUNK_SIZE) {
|
|
6437
|
+
setTimeout(function() {
|
|
6438
|
+
return db.isOpen() && deleteOldChanges(db);
|
|
6439
|
+
}, 500);
|
|
6440
|
+
}
|
|
6441
|
+
});
|
|
6442
|
+
});
|
|
6443
|
+
}).catch(function() {
|
|
6444
|
+
});
|
|
6445
|
+
}
|
|
6446
|
+
var global2 = self;
|
|
6447
|
+
var DatabaseChange = import_wrapper_default.defineClass({
|
|
6448
|
+
rev: Number,
|
|
6449
|
+
source: String,
|
|
6450
|
+
table: String,
|
|
6451
|
+
key: Object,
|
|
6452
|
+
type: Number,
|
|
6453
|
+
obj: Object,
|
|
6454
|
+
mods: Object,
|
|
6455
|
+
oldObj: Object
|
|
6456
|
+
// DELETE: oldObj contains the object deleted. UPDATE: oldObj contains the old object before updates applied.
|
|
6457
|
+
});
|
|
6458
|
+
var override = import_wrapper_default.override;
|
|
6459
|
+
var Promise$1 = import_wrapper_default.Promise;
|
|
6460
|
+
var browserIsShuttingDown = false;
|
|
6461
|
+
function Observable(db) {
|
|
6462
|
+
if (!/^(3|4)\./.test(import_wrapper_default.version))
|
|
6463
|
+
throw new Error("Missing dexie version 3.x or 4.x");
|
|
6464
|
+
if (db.observable) {
|
|
6465
|
+
if (db.observable.version !== "{version}")
|
|
6466
|
+
throw new Error("Mixed versions of dexie-observable");
|
|
6467
|
+
return;
|
|
6468
|
+
}
|
|
6469
|
+
var NODE_TIMEOUT = 2e4, HIBERNATE_GRACE_PERIOD = 2e4, LOCAL_POLL = 500, HEARTBEAT_INTERVAL = NODE_TIMEOUT - 5e3;
|
|
6470
|
+
var localStorage = Observable.localStorageImpl;
|
|
6471
|
+
var SyncNode = import_wrapper_default.defineClass({
|
|
6472
|
+
//id: Number,
|
|
6473
|
+
myRevision: Number,
|
|
6474
|
+
type: String,
|
|
6475
|
+
lastHeartBeat: Number,
|
|
6476
|
+
deleteTimeStamp: Number,
|
|
6477
|
+
url: String,
|
|
6478
|
+
isMaster: Number,
|
|
6479
|
+
// Below properties should be extended in Dexie.Syncable. Not here. They apply to remote nodes only (type == "remote"):
|
|
6480
|
+
syncProtocol: String,
|
|
6481
|
+
syncContext: null,
|
|
6482
|
+
syncOptions: Object,
|
|
6483
|
+
connected: false,
|
|
6484
|
+
status: Number,
|
|
6485
|
+
appliedRemoteRevision: null,
|
|
6486
|
+
remoteBaseRevisions: [{ local: Number, remote: null }],
|
|
6487
|
+
dbUploadState: {
|
|
6488
|
+
tablesToUpload: [String],
|
|
6489
|
+
currentTable: String,
|
|
6490
|
+
currentKey: null,
|
|
6491
|
+
localBaseRevision: Number
|
|
6492
|
+
}
|
|
6493
|
+
});
|
|
6494
|
+
db.observable = { version: "{version}" };
|
|
6495
|
+
db.observable.SyncNode = SyncNode;
|
|
6496
|
+
var wakeupObservers = initWakeupObservers(db, Observable, localStorage);
|
|
6497
|
+
var overrideCreateTransaction = initOverrideCreateTransaction(db, wakeupObservers);
|
|
6498
|
+
var crudMonitor = initCrudMonitor(db);
|
|
6499
|
+
var overrideOpen = initOverrideOpen(db, SyncNode, crudMonitor);
|
|
6500
|
+
var mySyncNode = { node: null };
|
|
6501
|
+
var intercomm = initIntercomm(db, Observable, SyncNode, mySyncNode, localStorage);
|
|
6502
|
+
var onIntercomm = intercomm.onIntercomm;
|
|
6503
|
+
var consumeIntercommMessages = intercomm.consumeIntercommMessages;
|
|
6504
|
+
Object.defineProperty(db, "_localSyncNode", {
|
|
6505
|
+
get: function() {
|
|
6506
|
+
return mySyncNode.node;
|
|
6507
|
+
}
|
|
6508
|
+
});
|
|
6509
|
+
var pollHandle = null, heartbeatHandle = null;
|
|
6510
|
+
if (import_wrapper_default.fake) {
|
|
6511
|
+
db.version(1).stores({
|
|
6512
|
+
_syncNodes: "++id,myRevision,lastHeartBeat",
|
|
6513
|
+
_changes: "++rev",
|
|
6514
|
+
_intercomm: "++id,destinationNode",
|
|
6515
|
+
_uncommittedChanges: "++id,node"
|
|
6516
|
+
});
|
|
6517
|
+
db._syncNodes.mapToClass(SyncNode);
|
|
6518
|
+
db._changes.mapToClass(DatabaseChange);
|
|
6519
|
+
mySyncNode.node = new SyncNode({
|
|
6520
|
+
myRevision: 0,
|
|
6521
|
+
type: "local",
|
|
6522
|
+
lastHeartBeat: Date.now(),
|
|
6523
|
+
deleteTimeStamp: null
|
|
6524
|
+
});
|
|
6525
|
+
}
|
|
6526
|
+
db.Version.prototype._parseStoresSpec = override(db.Version.prototype._parseStoresSpec, overrideParseStoresSpec);
|
|
6527
|
+
db.on.addEventType({
|
|
6528
|
+
changes: "asap",
|
|
6529
|
+
cleanup: [promisableChain, nop],
|
|
6530
|
+
message: "asap"
|
|
6531
|
+
});
|
|
6532
|
+
db._createTransaction = override(db._createTransaction, overrideCreateTransaction);
|
|
6533
|
+
Observable.latestRevision[db.name] = Observable.latestRevision[db.name] || 0;
|
|
6534
|
+
db.open = override(db.open, overrideOpen);
|
|
6535
|
+
db.close = override(db.close, function(origClose) {
|
|
6536
|
+
return function() {
|
|
6537
|
+
if (db.dynamicallyOpened())
|
|
6538
|
+
return origClose.apply(this, arguments);
|
|
6539
|
+
if (wakeupObservers.timeoutHandle) {
|
|
6540
|
+
clearTimeout(wakeupObservers.timeoutHandle);
|
|
6541
|
+
delete wakeupObservers.timeoutHandle;
|
|
6542
|
+
}
|
|
6543
|
+
Observable.on("latestRevisionIncremented").unsubscribe(onLatestRevisionIncremented);
|
|
6544
|
+
Observable.on("suicideNurseCall").unsubscribe(onSuicide);
|
|
6545
|
+
Observable.on("intercomm").unsubscribe(onIntercomm);
|
|
6546
|
+
Observable.on("beforeunload").unsubscribe(onBeforeUnload);
|
|
6547
|
+
if (mySyncNode.node && mySyncNode.node.id) {
|
|
6548
|
+
Observable.on.suicideNurseCall.fire(db.name, mySyncNode.node.id);
|
|
6549
|
+
if (localStorage) {
|
|
6550
|
+
localStorage.setItem("Dexie.Observable/deadnode:" + mySyncNode.node.id.toString() + "/" + db.name, "dead");
|
|
6551
|
+
}
|
|
6552
|
+
mySyncNode.node.deleteTimeStamp = 1;
|
|
6553
|
+
mySyncNode.node.lastHeartBeat = 0;
|
|
6554
|
+
db._syncNodes.put(mySyncNode.node);
|
|
6555
|
+
mySyncNode.node = null;
|
|
6556
|
+
}
|
|
6557
|
+
if (pollHandle)
|
|
6558
|
+
clearTimeout(pollHandle);
|
|
6559
|
+
pollHandle = null;
|
|
6560
|
+
if (heartbeatHandle)
|
|
6561
|
+
clearTimeout(heartbeatHandle);
|
|
6562
|
+
heartbeatHandle = null;
|
|
6563
|
+
return origClose.apply(this, arguments);
|
|
6564
|
+
};
|
|
6565
|
+
});
|
|
6566
|
+
db.delete = override(db.delete, function(origDelete) {
|
|
6567
|
+
return function() {
|
|
6568
|
+
return origDelete.apply(this, arguments).then(function(result) {
|
|
6569
|
+
Observable.latestRevision[db.name] = 0;
|
|
6570
|
+
return result;
|
|
6571
|
+
});
|
|
6572
|
+
};
|
|
6573
|
+
});
|
|
6574
|
+
db.on("ready", function startObserving() {
|
|
6575
|
+
if (db.dynamicallyOpened())
|
|
6576
|
+
return db;
|
|
6577
|
+
return db.table("_changes").orderBy("rev").last(function(lastChange) {
|
|
6578
|
+
var latestRevision = lastChange ? lastChange.rev : 0;
|
|
6579
|
+
mySyncNode.node = new SyncNode({
|
|
6580
|
+
myRevision: latestRevision,
|
|
6581
|
+
type: "local",
|
|
6582
|
+
lastHeartBeat: Date.now(),
|
|
6583
|
+
deleteTimeStamp: null,
|
|
6584
|
+
isMaster: 0
|
|
6585
|
+
});
|
|
6586
|
+
if (Observable.latestRevision[db.name] < latestRevision) {
|
|
6587
|
+
Observable.latestRevision[db.name] = latestRevision;
|
|
6588
|
+
import_wrapper_default.ignoreTransaction(function() {
|
|
6589
|
+
Observable.on.latestRevisionIncremented.fire(latestRevision);
|
|
6590
|
+
});
|
|
6591
|
+
}
|
|
6592
|
+
return db._syncNodes.put(mySyncNode.node).then(import_wrapper_default.ignoreTransaction(function() {
|
|
6593
|
+
var mySyncNodeShouldBecomeMaster = 1;
|
|
6594
|
+
return db._syncNodes.orderBy("isMaster").reverse().modify(function(existingNode) {
|
|
6595
|
+
if (existingNode.isMaster) {
|
|
6596
|
+
if (existingNode.lastHeartBeat < Date.now() - NODE_TIMEOUT) {
|
|
6597
|
+
existingNode.isMaster = 0;
|
|
6598
|
+
} else {
|
|
6599
|
+
mySyncNodeShouldBecomeMaster = 0;
|
|
6600
|
+
}
|
|
6601
|
+
}
|
|
6602
|
+
if (!mySyncNode.node)
|
|
6603
|
+
return;
|
|
6604
|
+
if (existingNode.id === mySyncNode.node.id) {
|
|
6605
|
+
existingNode.isMaster = mySyncNode.node.isMaster = mySyncNodeShouldBecomeMaster;
|
|
6606
|
+
}
|
|
6607
|
+
});
|
|
6608
|
+
})).then(function() {
|
|
6609
|
+
Observable.on("latestRevisionIncremented", onLatestRevisionIncremented);
|
|
6610
|
+
Observable.on("beforeunload", onBeforeUnload);
|
|
6611
|
+
Observable.on("suicideNurseCall", onSuicide);
|
|
6612
|
+
Observable.on("intercomm", onIntercomm);
|
|
6613
|
+
pollHandle = setTimeout(poll, LOCAL_POLL);
|
|
6614
|
+
heartbeatHandle = setTimeout(heartbeat, HEARTBEAT_INTERVAL);
|
|
6615
|
+
}).then(function() {
|
|
6616
|
+
cleanup();
|
|
6617
|
+
});
|
|
6618
|
+
});
|
|
6619
|
+
}, true);
|
|
6620
|
+
var handledRevision = 0;
|
|
6621
|
+
function onLatestRevisionIncremented(dbname, latestRevision) {
|
|
6622
|
+
if (dbname === db.name) {
|
|
6623
|
+
if (handledRevision >= latestRevision)
|
|
6624
|
+
return;
|
|
6625
|
+
handledRevision = latestRevision;
|
|
6626
|
+
import_wrapper_default.vip(function() {
|
|
6627
|
+
readChanges().catch("DatabaseClosedError", function() {
|
|
6628
|
+
});
|
|
6629
|
+
});
|
|
6630
|
+
}
|
|
6631
|
+
}
|
|
6632
|
+
function readChanges(latestRevision, recursion, wasPartial) {
|
|
6633
|
+
if (!recursion && readChanges.ongoingOperation) {
|
|
6634
|
+
return readChanges.ongoingOperation;
|
|
6635
|
+
}
|
|
6636
|
+
var partial = false;
|
|
6637
|
+
var ourSyncNode = mySyncNode.node;
|
|
6638
|
+
if (!ourSyncNode) {
|
|
6639
|
+
return Promise$1.reject(new import_wrapper_default.DatabaseClosedError());
|
|
6640
|
+
}
|
|
6641
|
+
var LIMIT = 1e3;
|
|
6642
|
+
var promise = db._changes.where("rev").above(ourSyncNode.myRevision).limit(LIMIT).toArray(function(changes) {
|
|
6643
|
+
if (changes.length > 0) {
|
|
6644
|
+
var lastChange = changes[changes.length - 1];
|
|
6645
|
+
partial = changes.length === LIMIT;
|
|
6646
|
+
db.on("changes").fire(changes, partial);
|
|
6647
|
+
ourSyncNode.myRevision = lastChange.rev;
|
|
6648
|
+
} else if (wasPartial) {
|
|
6649
|
+
db.on("changes").fire([], false);
|
|
6650
|
+
}
|
|
6651
|
+
var ourNodeStillExists = false;
|
|
6652
|
+
return db._syncNodes.where(":id").equals(ourSyncNode.id).modify(function(syncNode) {
|
|
6653
|
+
ourNodeStillExists = true;
|
|
6654
|
+
syncNode.lastHeartBeat = Date.now();
|
|
6655
|
+
syncNode.deleteTimeStamp = null;
|
|
6656
|
+
syncNode.myRevision = Math.max(syncNode.myRevision, ourSyncNode.myRevision);
|
|
6657
|
+
}).then(function() {
|
|
6658
|
+
return ourNodeStillExists;
|
|
6659
|
+
});
|
|
6660
|
+
}).then(function(ourNodeStillExists) {
|
|
6661
|
+
if (!ourNodeStillExists) {
|
|
6662
|
+
if (browserIsShuttingDown) {
|
|
6663
|
+
throw new Error("Browser is shutting down");
|
|
6664
|
+
} else {
|
|
6665
|
+
db.close();
|
|
6666
|
+
console.error("Out of sync");
|
|
6667
|
+
if (global2.location)
|
|
6668
|
+
global2.location.reload(true);
|
|
6669
|
+
throw new Error("Out of sync");
|
|
6670
|
+
}
|
|
6671
|
+
}
|
|
6672
|
+
if (partial || Observable.latestRevision[db.name] > ourSyncNode.myRevision) {
|
|
6673
|
+
return readChanges(Observable.latestRevision[db.name], (recursion || 0) + 1, partial);
|
|
6674
|
+
}
|
|
6675
|
+
}).finally(function() {
|
|
6676
|
+
delete readChanges.ongoingOperation;
|
|
6677
|
+
});
|
|
6678
|
+
if (!recursion) {
|
|
6679
|
+
readChanges.ongoingOperation = promise;
|
|
6680
|
+
}
|
|
6681
|
+
return promise;
|
|
6682
|
+
}
|
|
6683
|
+
function heartbeat() {
|
|
6684
|
+
heartbeatHandle = null;
|
|
6685
|
+
var currentInstance = mySyncNode.node && mySyncNode.node.id;
|
|
6686
|
+
if (!currentInstance)
|
|
6687
|
+
return;
|
|
6688
|
+
db.transaction("rw!", db._syncNodes, function() {
|
|
6689
|
+
db._syncNodes.where({ id: currentInstance }).first(function(ourSyncNode) {
|
|
6690
|
+
if (!ourSyncNode) {
|
|
6691
|
+
if (db.isOpen())
|
|
6692
|
+
db.close();
|
|
6693
|
+
return;
|
|
6694
|
+
}
|
|
6695
|
+
ourSyncNode.lastHeartBeat = Date.now();
|
|
6696
|
+
ourSyncNode.deleteTimeStamp = null;
|
|
6697
|
+
return db._syncNodes.put(ourSyncNode);
|
|
6698
|
+
});
|
|
6699
|
+
}).catch("DatabaseClosedError", function() {
|
|
6700
|
+
}).finally(function() {
|
|
6701
|
+
if (mySyncNode.node && mySyncNode.node.id === currentInstance && db.isOpen()) {
|
|
6702
|
+
heartbeatHandle = setTimeout(heartbeat, HEARTBEAT_INTERVAL);
|
|
6703
|
+
}
|
|
6704
|
+
});
|
|
6705
|
+
}
|
|
6706
|
+
function poll() {
|
|
6707
|
+
pollHandle = null;
|
|
6708
|
+
var currentInstance = mySyncNode.node && mySyncNode.node.id;
|
|
6709
|
+
if (!currentInstance)
|
|
6710
|
+
return;
|
|
6711
|
+
import_wrapper_default.vip(function() {
|
|
6712
|
+
readChanges(Observable.latestRevision[db.name]).then(cleanup).then(consumeIntercommMessages).catch("DatabaseClosedError", function() {
|
|
6713
|
+
}).finally(function() {
|
|
6714
|
+
if (mySyncNode.node && mySyncNode.node.id === currentInstance && db.isOpen()) {
|
|
6715
|
+
pollHandle = setTimeout(poll, LOCAL_POLL);
|
|
6716
|
+
}
|
|
6717
|
+
});
|
|
6718
|
+
});
|
|
6719
|
+
}
|
|
6720
|
+
function cleanup() {
|
|
6721
|
+
var ourSyncNode = mySyncNode.node;
|
|
6722
|
+
if (!ourSyncNode)
|
|
6723
|
+
return Promise$1.reject(new import_wrapper_default.DatabaseClosedError());
|
|
6724
|
+
return db.transaction("rw", "_syncNodes", "_changes", "_intercomm", function() {
|
|
6725
|
+
var weBecameMaster = false;
|
|
6726
|
+
db._syncNodes.where("lastHeartBeat").below(Date.now() - NODE_TIMEOUT).filter(function(node) {
|
|
6727
|
+
return node.type === "local";
|
|
6728
|
+
}).modify(function(node) {
|
|
6729
|
+
if (node.deleteTimeStamp && node.deleteTimeStamp < Date.now()) {
|
|
6730
|
+
delete this.value;
|
|
6731
|
+
if (localStorage) {
|
|
6732
|
+
localStorage.removeItem("Dexie.Observable/deadnode:" + node.id + "/" + db.name);
|
|
6733
|
+
}
|
|
6734
|
+
if (node.isMaster) {
|
|
6735
|
+
db._syncNodes.update(ourSyncNode, { isMaster: 1 });
|
|
6736
|
+
weBecameMaster = true;
|
|
6737
|
+
}
|
|
6738
|
+
db._intercomm.where({ destinationNode: node.id }).modify(function(msg) {
|
|
6739
|
+
if (msg.wantReply)
|
|
6740
|
+
msg.destinationNode = ourSyncNode.id;
|
|
6741
|
+
else
|
|
6742
|
+
delete this.value;
|
|
6743
|
+
});
|
|
6744
|
+
} else if (!node.deleteTimeStamp) {
|
|
6745
|
+
node.deleteTimeStamp = Date.now() + HIBERNATE_GRACE_PERIOD;
|
|
6746
|
+
}
|
|
6747
|
+
}).then(function() {
|
|
6748
|
+
Observable.deleteOldChanges(db);
|
|
6749
|
+
return db.on("cleanup").fire(weBecameMaster);
|
|
6750
|
+
});
|
|
6751
|
+
});
|
|
6752
|
+
}
|
|
6753
|
+
function onBeforeUnload() {
|
|
6754
|
+
if (!mySyncNode.node)
|
|
6755
|
+
return;
|
|
6756
|
+
browserIsShuttingDown = true;
|
|
6757
|
+
mySyncNode.node.deleteTimeStamp = 1;
|
|
6758
|
+
mySyncNode.node.lastHeartBeat = 0;
|
|
6759
|
+
db._syncNodes.put(mySyncNode.node);
|
|
6760
|
+
Observable.wereTheOneDying = true;
|
|
6761
|
+
if (localStorage) {
|
|
6762
|
+
localStorage.setItem("Dexie.Observable/deadnode:" + mySyncNode.node.id.toString() + "/" + db.name, "dead");
|
|
6763
|
+
}
|
|
6764
|
+
}
|
|
6765
|
+
function onSuicide(dbname, nodeID) {
|
|
6766
|
+
if (dbname === db.name && !Observable.wereTheOneDying) {
|
|
6767
|
+
import_wrapper_default.vip(function() {
|
|
6768
|
+
db._syncNodes.update(nodeID, { deleteTimeStamp: 1, lastHeartBeat: 0 }).then(cleanup);
|
|
6769
|
+
});
|
|
6770
|
+
}
|
|
6771
|
+
}
|
|
6772
|
+
}
|
|
6773
|
+
Observable.version = "{version}";
|
|
6774
|
+
Observable.latestRevision = {};
|
|
6775
|
+
Observable.on = import_wrapper_default.Events(null, "latestRevisionIncremented", "suicideNurseCall", "intercomm", "beforeunload");
|
|
6776
|
+
Observable.createUUID = createUUID;
|
|
6777
|
+
Observable.deleteOldChanges = deleteOldChanges;
|
|
6778
|
+
Observable._onStorage = initOnStorage(Observable);
|
|
6779
|
+
Observable._onBeforeUnload = function() {
|
|
6780
|
+
Observable.on.beforeunload.fire();
|
|
6781
|
+
};
|
|
6782
|
+
try {
|
|
6783
|
+
Observable.localStorageImpl = global2.localStorage;
|
|
6784
|
+
} catch (ex) {
|
|
6785
|
+
}
|
|
6786
|
+
if (global2 === null || global2 === void 0 ? void 0 : global2.addEventListener) {
|
|
6787
|
+
global2.addEventListener("storage", Observable._onStorage);
|
|
6788
|
+
global2.addEventListener("beforeunload", Observable._onBeforeUnload);
|
|
6789
|
+
}
|
|
6790
|
+
if (import_wrapper_default.Observable) {
|
|
6791
|
+
if (import_wrapper_default.Observable.version !== "{version}") {
|
|
6792
|
+
throw new Error("Mixed versions of dexie-observable");
|
|
6793
|
+
}
|
|
6794
|
+
} else {
|
|
6795
|
+
import_wrapper_default.Observable = Observable;
|
|
6796
|
+
import_wrapper_default.addons.push(Observable);
|
|
6797
|
+
}
|
|
6798
|
+
var Dexie_Observable = import_wrapper_default.Observable;
|
|
6799
|
+
|
|
6800
|
+
// ../../node_modules/dexie-syncable/dist/dexie-syncable.es.js
|
|
6801
|
+
var Promise$3 = import_wrapper_default.Promise;
|
|
6802
|
+
function initSyncableConnect(db, connect) {
|
|
6803
|
+
return function syncableConnect(protocolInstance, protocolName, url, options) {
|
|
6804
|
+
if (db.isOpen()) {
|
|
6805
|
+
if (!db._localSyncNode)
|
|
6806
|
+
throw new Error("Precondition failed: local sync node is missing. Make sure Dexie.Observable is active!");
|
|
6807
|
+
if (db._localSyncNode.isMaster) {
|
|
6808
|
+
return connect(protocolInstance, protocolName, url, options, db._localSyncNode.id);
|
|
6809
|
+
} else {
|
|
6810
|
+
return db.table("_syncNodes").where("isMaster").above(0).first(function(masterNode) {
|
|
6811
|
+
return db.observable.sendMessage("connect", {
|
|
6812
|
+
protocolName,
|
|
6813
|
+
url,
|
|
6814
|
+
options
|
|
6815
|
+
}, masterNode.id, { wantReply: true });
|
|
6816
|
+
});
|
|
6817
|
+
}
|
|
6818
|
+
} else if (db.hasBeenClosed()) {
|
|
6819
|
+
return Promise$3.reject(new import_wrapper_default.DatabaseClosedError());
|
|
6820
|
+
} else if (db.hasFailed()) {
|
|
6821
|
+
return Promise$3.reject(new import_wrapper_default.InvalidStateError("Dexie.Syncable: Cannot connect. Database has failed to open"));
|
|
6822
|
+
} else {
|
|
6823
|
+
var promise = new Promise$3(function(resolve, reject) {
|
|
6824
|
+
db.on("ready", function() {
|
|
6825
|
+
return db._syncNodes.get({ url }, function(node) {
|
|
6826
|
+
var connectPromise = db.syncable.connect(protocolName, url, options);
|
|
6827
|
+
connectPromise.then(resolve, reject);
|
|
6828
|
+
if (node && node.appliedRemoteRevision) {
|
|
6829
|
+
return;
|
|
6830
|
+
}
|
|
6831
|
+
return connectPromise;
|
|
6832
|
+
});
|
|
6833
|
+
});
|
|
6834
|
+
db.open().catch(function(ex) {
|
|
6835
|
+
reject(new import_wrapper_default.InvalidStateError("Dexie.Syncable: Couldn't connect. Database failed to open", ex));
|
|
6836
|
+
});
|
|
6837
|
+
});
|
|
6838
|
+
return promise;
|
|
6839
|
+
}
|
|
6840
|
+
};
|
|
6841
|
+
}
|
|
6842
|
+
function initPersistedContext(node) {
|
|
6843
|
+
return (
|
|
6844
|
+
/** @class */
|
|
6845
|
+
function() {
|
|
6846
|
+
function PersistedContext(nodeID, otherProps) {
|
|
6847
|
+
this.nodeID = nodeID;
|
|
6848
|
+
if (otherProps)
|
|
6849
|
+
import_wrapper_default.extend(this, otherProps);
|
|
6850
|
+
}
|
|
6851
|
+
PersistedContext.prototype.save = function() {
|
|
6852
|
+
return import_wrapper_default.vip(function() {
|
|
6853
|
+
return node.save();
|
|
6854
|
+
});
|
|
6855
|
+
};
|
|
6856
|
+
return PersistedContext;
|
|
6857
|
+
}()
|
|
6858
|
+
);
|
|
6859
|
+
}
|
|
6860
|
+
function initGetOrCreateSyncNode(db, protocolName, url) {
|
|
6861
|
+
return function getOrCreateSyncNode(options) {
|
|
6862
|
+
return db.transaction("rw", db._syncNodes, db._changes, function() {
|
|
6863
|
+
if (!url)
|
|
6864
|
+
throw new Error("Url cannot be empty");
|
|
6865
|
+
return db._syncNodes.where("url").equalsIgnoreCase(url).first(function(node) {
|
|
6866
|
+
if (node) {
|
|
6867
|
+
var PersistedContext = initPersistedContext(node);
|
|
6868
|
+
node.syncContext = new PersistedContext(node.id, node.syncContext);
|
|
6869
|
+
node.syncProtocol = protocolName;
|
|
6870
|
+
node.syncOptions = options;
|
|
6871
|
+
db._syncNodes.put(node);
|
|
6872
|
+
} else {
|
|
6873
|
+
node = new db.observable.SyncNode();
|
|
6874
|
+
node.myRevision = -1;
|
|
6875
|
+
node.appliedRemoteRevision = null;
|
|
6876
|
+
node.remoteBaseRevisions = [];
|
|
6877
|
+
node.type = "remote";
|
|
6878
|
+
node.syncProtocol = protocolName;
|
|
6879
|
+
node.url = url;
|
|
6880
|
+
node.syncOptions = options;
|
|
6881
|
+
node.lastHeartBeat = Date.now();
|
|
6882
|
+
node.dbUploadState = null;
|
|
6883
|
+
var PersistedContext_1 = initPersistedContext(node);
|
|
6884
|
+
import_wrapper_default.Promise.resolve(function() {
|
|
6885
|
+
if (options.initialUpload === false)
|
|
6886
|
+
return db._changes.toCollection().lastKey(function(currentRevision) {
|
|
6887
|
+
node.myRevision = currentRevision;
|
|
6888
|
+
});
|
|
6889
|
+
}()).then(function() {
|
|
6890
|
+
db._syncNodes.add(node).then(function(nodeID) {
|
|
6891
|
+
node.syncContext = new PersistedContext_1(nodeID);
|
|
6892
|
+
db._syncNodes.put(node);
|
|
6893
|
+
});
|
|
6894
|
+
});
|
|
6895
|
+
}
|
|
6896
|
+
return node;
|
|
6897
|
+
});
|
|
6898
|
+
});
|
|
6899
|
+
};
|
|
6900
|
+
}
|
|
6901
|
+
function initEnqueue(db) {
|
|
6902
|
+
return function enqueue(context, fn, instanceID) {
|
|
6903
|
+
function _enqueue() {
|
|
6904
|
+
if (!context.ongoingOperation) {
|
|
6905
|
+
context.ongoingOperation = import_wrapper_default.ignoreTransaction(function() {
|
|
6906
|
+
return import_wrapper_default.vip(function() {
|
|
6907
|
+
return fn();
|
|
6908
|
+
});
|
|
6909
|
+
}).finally(function() {
|
|
6910
|
+
delete context.ongoingOperation;
|
|
6911
|
+
});
|
|
6912
|
+
} else {
|
|
6913
|
+
context.ongoingOperation = context.ongoingOperation.then(function() {
|
|
6914
|
+
return enqueue(context, fn, instanceID);
|
|
6915
|
+
});
|
|
6916
|
+
}
|
|
6917
|
+
return context.ongoingOperation;
|
|
6918
|
+
}
|
|
6919
|
+
if (!instanceID) {
|
|
6920
|
+
if (db.isOpen()) {
|
|
6921
|
+
return _enqueue();
|
|
6922
|
+
} else {
|
|
6923
|
+
return import_wrapper_default.Promise.reject(new import_wrapper_default.DatabaseClosedError());
|
|
6924
|
+
}
|
|
6925
|
+
} else if (db._localSyncNode && instanceID === db._localSyncNode.id) {
|
|
6926
|
+
return _enqueue();
|
|
6927
|
+
} else {
|
|
6928
|
+
return import_wrapper_default.Promise.reject(new import_wrapper_default.DatabaseClosedError());
|
|
6929
|
+
}
|
|
6930
|
+
};
|
|
6931
|
+
}
|
|
6932
|
+
function initSaveToUncommittedChanges(db, node) {
|
|
6933
|
+
return function saveToUncommittedChanges(changes, remoteRevision) {
|
|
6934
|
+
return db.transaction("rw!", db._uncommittedChanges, function() {
|
|
6935
|
+
return db._uncommittedChanges.bulkAdd(changes.map(function(change) {
|
|
6936
|
+
var changeWithNodeId = {
|
|
6937
|
+
node: node.id,
|
|
6938
|
+
type: change.type,
|
|
6939
|
+
table: change.table,
|
|
6940
|
+
key: change.key
|
|
6941
|
+
};
|
|
6942
|
+
if (change.obj)
|
|
6943
|
+
changeWithNodeId.obj = change.obj;
|
|
6944
|
+
if (change.mods)
|
|
6945
|
+
changeWithNodeId.mods = change.mods;
|
|
6946
|
+
return changeWithNodeId;
|
|
6947
|
+
}));
|
|
6948
|
+
}).then(function() {
|
|
6949
|
+
node.appliedRemoteRevision = remoteRevision;
|
|
6950
|
+
return node.save();
|
|
6951
|
+
});
|
|
6952
|
+
};
|
|
6953
|
+
}
|
|
6954
|
+
var CREATE2 = 1;
|
|
6955
|
+
var UPDATE2 = 2;
|
|
6956
|
+
var DELETE2 = 3;
|
|
6957
|
+
function bulkUpdate(table, changes) {
|
|
6958
|
+
var keys = changes.map(function(c) {
|
|
6959
|
+
return c.key;
|
|
6960
|
+
});
|
|
6961
|
+
var map = {};
|
|
6962
|
+
return table.where(":id").anyOf(keys).raw().each(function(obj, cursor) {
|
|
6963
|
+
map[cursor.primaryKey + ""] = obj;
|
|
6964
|
+
}).then(function() {
|
|
6965
|
+
var updatesThatApply = changes.filter(function(c) {
|
|
6966
|
+
return map.hasOwnProperty(c.key + "");
|
|
6967
|
+
});
|
|
6968
|
+
var objsToPut = updatesThatApply.map(function(c) {
|
|
6969
|
+
var curr = map[c.key + ""];
|
|
6970
|
+
Object.keys(c.mods).forEach(function(keyPath) {
|
|
6971
|
+
import_wrapper_default.setByKeyPath(curr, keyPath, c.mods[keyPath]);
|
|
6972
|
+
});
|
|
6973
|
+
return curr;
|
|
6974
|
+
});
|
|
6975
|
+
return table.bulkPut(objsToPut);
|
|
6976
|
+
});
|
|
6977
|
+
}
|
|
6978
|
+
function initApplyChanges(db) {
|
|
6979
|
+
return function applyChanges(changes) {
|
|
6980
|
+
var collectedChanges = {};
|
|
6981
|
+
changes.forEach(function(change) {
|
|
6982
|
+
var _a;
|
|
6983
|
+
if (!collectedChanges.hasOwnProperty(change.table)) {
|
|
6984
|
+
collectedChanges[change.table] = (_a = {}, _a[CREATE2] = [], _a[DELETE2] = [], _a[UPDATE2] = [], _a);
|
|
6985
|
+
}
|
|
6986
|
+
collectedChanges[change.table][change.type].push(change);
|
|
6987
|
+
});
|
|
6988
|
+
var table_names = Object.keys(collectedChanges);
|
|
6989
|
+
var tables = table_names.map(function(table) {
|
|
6990
|
+
return db.table(table);
|
|
6991
|
+
});
|
|
6992
|
+
return db.transaction("rw", tables, function() {
|
|
6993
|
+
table_names.forEach(function(table_name) {
|
|
6994
|
+
var table = db.table(table_name);
|
|
6995
|
+
var specifyKeys = !table.schema.primKey.keyPath;
|
|
6996
|
+
var createChangesToApply = collectedChanges[table_name][CREATE2];
|
|
6997
|
+
var deleteChangesToApply = collectedChanges[table_name][DELETE2];
|
|
6998
|
+
var updateChangesToApply = collectedChanges[table_name][UPDATE2];
|
|
6999
|
+
if (createChangesToApply.length > 0)
|
|
7000
|
+
table.bulkPut(createChangesToApply.map(function(c) {
|
|
7001
|
+
return c.obj;
|
|
7002
|
+
}), specifyKeys ? createChangesToApply.map(function(c) {
|
|
7003
|
+
return c.key;
|
|
7004
|
+
}) : void 0);
|
|
7005
|
+
if (updateChangesToApply.length > 0)
|
|
7006
|
+
bulkUpdate(table, updateChangesToApply);
|
|
7007
|
+
if (deleteChangesToApply.length > 0)
|
|
7008
|
+
table.bulkDelete(deleteChangesToApply.map(function(c) {
|
|
7009
|
+
return c.key;
|
|
7010
|
+
}));
|
|
7011
|
+
});
|
|
7012
|
+
});
|
|
7013
|
+
};
|
|
7014
|
+
}
|
|
7015
|
+
function initFinallyCommitAllChanges(db, node) {
|
|
7016
|
+
var applyChanges = initApplyChanges(db);
|
|
7017
|
+
return function finallyCommitAllChanges(changes, remoteRevision) {
|
|
7018
|
+
var tablesToIncludeInTrans = db.tables.filter(function(table) {
|
|
7019
|
+
return table.name === "_changes" || table.name === "_uncommittedChanges" || table.schema.observable;
|
|
7020
|
+
});
|
|
7021
|
+
return db.transaction("rw!", tablesToIncludeInTrans, function() {
|
|
7022
|
+
var trans = import_wrapper_default.currentTransaction;
|
|
7023
|
+
var localRevisionBeforeChanges = 0;
|
|
7024
|
+
return db._changes.orderBy("rev").last(function(lastChange) {
|
|
7025
|
+
localRevisionBeforeChanges = lastChange && lastChange.rev || 0;
|
|
7026
|
+
}).then(function() {
|
|
7027
|
+
trans.source = node.id;
|
|
7028
|
+
return db._uncommittedChanges.where("node").equals(node.id).toArray();
|
|
7029
|
+
}).then(function(uncommittedChanges) {
|
|
7030
|
+
return applyChanges(uncommittedChanges);
|
|
7031
|
+
}).then(function() {
|
|
7032
|
+
return db._uncommittedChanges.where("node").equals(node.id).delete();
|
|
7033
|
+
}).then(function() {
|
|
7034
|
+
return applyChanges(changes);
|
|
7035
|
+
}).then(function() {
|
|
7036
|
+
return db._changes.orderBy("rev").last();
|
|
7037
|
+
}).then(function(lastChange) {
|
|
7038
|
+
var currentLocalRevision = lastChange && lastChange.rev || 0;
|
|
7039
|
+
node.appliedRemoteRevision = remoteRevision;
|
|
7040
|
+
node.remoteBaseRevisions.push({ remote: remoteRevision, local: currentLocalRevision });
|
|
7041
|
+
if (node.myRevision === localRevisionBeforeChanges) {
|
|
7042
|
+
node.myRevision = currentLocalRevision;
|
|
7043
|
+
}
|
|
7044
|
+
if (node.remoteBaseRevisions.length > 1) {
|
|
7045
|
+
for (var i = node.remoteBaseRevisions.length - 1; i > 0; --i) {
|
|
7046
|
+
if (node.myRevision >= node.remoteBaseRevisions[i].local) {
|
|
7047
|
+
node.remoteBaseRevisions.splice(0, i);
|
|
7048
|
+
break;
|
|
7049
|
+
}
|
|
7050
|
+
}
|
|
7051
|
+
}
|
|
7052
|
+
node.save().catch(function(err) {
|
|
7053
|
+
console.warn("Dexie.Syncable: Unable to save SyncNode after applying remote changes: " + (err.stack || err));
|
|
7054
|
+
});
|
|
7055
|
+
});
|
|
7056
|
+
});
|
|
7057
|
+
};
|
|
7058
|
+
}
|
|
7059
|
+
function getBaseRevisionAndMaxClientRevision(node) {
|
|
7060
|
+
if (node.remoteBaseRevisions.length === 0)
|
|
7061
|
+
return {
|
|
7062
|
+
// No remoteBaseRevisions have arrived yet. No limit on clientRevision and provide null as remoteBaseRevision:
|
|
7063
|
+
maxClientRevision: Infinity,
|
|
7064
|
+
remoteBaseRevision: null
|
|
7065
|
+
};
|
|
7066
|
+
for (var i = node.remoteBaseRevisions.length - 1; i >= 0; --i) {
|
|
7067
|
+
if (node.myRevision >= node.remoteBaseRevisions[i].local) {
|
|
7068
|
+
return {
|
|
7069
|
+
maxClientRevision: i === node.remoteBaseRevisions.length - 1 ? Infinity : node.remoteBaseRevisions[i + 1].local,
|
|
7070
|
+
remoteBaseRevision: node.remoteBaseRevisions[i].remote
|
|
7071
|
+
};
|
|
7072
|
+
}
|
|
7073
|
+
}
|
|
7074
|
+
return {
|
|
7075
|
+
maxClientRevision: node.remoteBaseRevisions[0].local,
|
|
7076
|
+
remoteBaseRevision: null
|
|
7077
|
+
};
|
|
7078
|
+
}
|
|
7079
|
+
function combineCreateAndUpdate(prevChange, nextChange) {
|
|
7080
|
+
var clonedChange = import_wrapper_default.deepClone(prevChange);
|
|
7081
|
+
Object.keys(nextChange.mods).forEach(function(keyPath) {
|
|
7082
|
+
import_wrapper_default.setByKeyPath(clonedChange.obj, keyPath, nextChange.mods[keyPath]);
|
|
7083
|
+
});
|
|
7084
|
+
return clonedChange;
|
|
7085
|
+
}
|
|
7086
|
+
function combineUpdateAndUpdate(prevChange, nextChange) {
|
|
7087
|
+
var clonedChange = import_wrapper_default.deepClone(prevChange);
|
|
7088
|
+
Object.keys(nextChange.mods).forEach(function(keyPath) {
|
|
7089
|
+
var hadParentPath = false;
|
|
7090
|
+
Object.keys(prevChange.mods).filter(function(parentPath) {
|
|
7091
|
+
return keyPath.indexOf(parentPath + ".") === 0;
|
|
7092
|
+
}).forEach(function(parentPath) {
|
|
7093
|
+
import_wrapper_default.setByKeyPath(clonedChange.mods[parentPath], keyPath.substr(parentPath.length + 1), nextChange.mods[keyPath]);
|
|
7094
|
+
hadParentPath = true;
|
|
7095
|
+
});
|
|
7096
|
+
if (!hadParentPath) {
|
|
7097
|
+
clonedChange.mods[keyPath] = nextChange.mods[keyPath];
|
|
7098
|
+
}
|
|
7099
|
+
Object.keys(prevChange.mods).filter(function(subPath) {
|
|
7100
|
+
return subPath.indexOf(keyPath + ".") === 0;
|
|
7101
|
+
}).forEach(function(subPath) {
|
|
7102
|
+
delete clonedChange.mods[subPath];
|
|
7103
|
+
});
|
|
7104
|
+
});
|
|
7105
|
+
return clonedChange;
|
|
7106
|
+
}
|
|
7107
|
+
function mergeChange(prevChange, nextChange) {
|
|
7108
|
+
switch (prevChange.type) {
|
|
7109
|
+
case CREATE2:
|
|
7110
|
+
switch (nextChange.type) {
|
|
7111
|
+
case CREATE2:
|
|
7112
|
+
return nextChange;
|
|
7113
|
+
case UPDATE2:
|
|
7114
|
+
return combineCreateAndUpdate(prevChange, nextChange);
|
|
7115
|
+
case DELETE2:
|
|
7116
|
+
return nextChange;
|
|
7117
|
+
}
|
|
7118
|
+
break;
|
|
7119
|
+
case UPDATE2:
|
|
7120
|
+
switch (nextChange.type) {
|
|
7121
|
+
case CREATE2:
|
|
7122
|
+
return nextChange;
|
|
7123
|
+
case UPDATE2:
|
|
7124
|
+
return combineUpdateAndUpdate(prevChange, nextChange);
|
|
7125
|
+
case DELETE2:
|
|
7126
|
+
return nextChange;
|
|
7127
|
+
}
|
|
7128
|
+
break;
|
|
7129
|
+
case DELETE2:
|
|
7130
|
+
switch (nextChange.type) {
|
|
7131
|
+
case CREATE2:
|
|
7132
|
+
return nextChange;
|
|
7133
|
+
case UPDATE2:
|
|
7134
|
+
return prevChange;
|
|
7135
|
+
case DELETE2:
|
|
7136
|
+
return prevChange;
|
|
7137
|
+
}
|
|
7138
|
+
break;
|
|
7139
|
+
}
|
|
7140
|
+
}
|
|
7141
|
+
function initGetChangesSinceRevision(db, node, hasMoreToGive) {
|
|
7142
|
+
return function getChangesSinceRevision(revision, maxChanges, maxRevision, cb) {
|
|
7143
|
+
var changeSet = {};
|
|
7144
|
+
var numChanges = 0;
|
|
7145
|
+
var partial = false;
|
|
7146
|
+
var ignoreSource = node.id;
|
|
7147
|
+
var nextRevision = revision;
|
|
7148
|
+
return db.transaction("r", db._changes, function() {
|
|
7149
|
+
var query = db._changes.where("rev").between(revision, maxRevision, false, true);
|
|
7150
|
+
return query.until(function() {
|
|
7151
|
+
if (numChanges === maxChanges) {
|
|
7152
|
+
partial = true;
|
|
7153
|
+
return true;
|
|
7154
|
+
}
|
|
7155
|
+
}).each(function(change) {
|
|
7156
|
+
nextRevision = change.rev;
|
|
7157
|
+
if (change.source === ignoreSource)
|
|
7158
|
+
return;
|
|
7159
|
+
var changeToSend = {
|
|
7160
|
+
type: change.type,
|
|
7161
|
+
table: change.table,
|
|
7162
|
+
key: change.key
|
|
7163
|
+
};
|
|
7164
|
+
if (change.type === CREATE2)
|
|
7165
|
+
changeToSend.obj = change.obj;
|
|
7166
|
+
else if (change.type === UPDATE2)
|
|
7167
|
+
changeToSend.mods = change.mods;
|
|
7168
|
+
var id = change.table + ":" + change.key;
|
|
7169
|
+
var prevChange = changeSet[id];
|
|
7170
|
+
if (!prevChange) {
|
|
7171
|
+
changeSet[id] = changeToSend;
|
|
7172
|
+
++numChanges;
|
|
7173
|
+
} else {
|
|
7174
|
+
var nextChange = changeToSend;
|
|
7175
|
+
var mergedChange = mergeChange(prevChange, nextChange);
|
|
7176
|
+
changeSet[id] = mergedChange;
|
|
7177
|
+
}
|
|
7178
|
+
});
|
|
7179
|
+
}).then(function() {
|
|
7180
|
+
var changes = Object.keys(changeSet).map(function(key) {
|
|
7181
|
+
return changeSet[key];
|
|
7182
|
+
});
|
|
7183
|
+
hasMoreToGive.hasMoreToGive = partial;
|
|
7184
|
+
return cb(changes, partial, { myRevision: nextRevision });
|
|
7185
|
+
});
|
|
7186
|
+
};
|
|
7187
|
+
}
|
|
7188
|
+
function initGetTableObjectsAsChanges(db, node, MAX_CHANGES_PER_CHUNK, getChangesSinceRevision, hasMoreToGive, cb) {
|
|
7189
|
+
return function getTableObjectsAsChanges(state, changes, collection) {
|
|
7190
|
+
var limitReached = false;
|
|
7191
|
+
return collection.until(function() {
|
|
7192
|
+
if (changes.length === MAX_CHANGES_PER_CHUNK) {
|
|
7193
|
+
limitReached = true;
|
|
7194
|
+
return true;
|
|
7195
|
+
}
|
|
7196
|
+
}).each(function(item, cursor) {
|
|
7197
|
+
changes.push({
|
|
7198
|
+
type: CREATE2,
|
|
7199
|
+
table: state.currentTable,
|
|
7200
|
+
key: cursor.key,
|
|
7201
|
+
obj: cursor.value
|
|
7202
|
+
});
|
|
7203
|
+
state.currentKey = cursor.key;
|
|
7204
|
+
}).then(function() {
|
|
7205
|
+
if (limitReached) {
|
|
7206
|
+
hasMoreToGive.hasMoreToGive = true;
|
|
7207
|
+
return cb(changes, null, true, { dbUploadState: state });
|
|
7208
|
+
} else {
|
|
7209
|
+
if (state.tablesToUpload.length === 0) {
|
|
7210
|
+
var brmcr = getBaseRevisionAndMaxClientRevision(node);
|
|
7211
|
+
return getChangesSinceRevision(state.localBaseRevision, MAX_CHANGES_PER_CHUNK - changes.length, brmcr.maxClientRevision, function(additionalChanges, partial, nodeModificationsOnAck) {
|
|
7212
|
+
changes = changes.concat(additionalChanges);
|
|
7213
|
+
nodeModificationsOnAck.dbUploadState = null;
|
|
7214
|
+
return cb(changes, brmcr.remoteBaseRevision, partial, nodeModificationsOnAck);
|
|
7215
|
+
});
|
|
7216
|
+
} else {
|
|
7217
|
+
state.currentTable = state.tablesToUpload.shift();
|
|
7218
|
+
return getTableObjectsAsChanges(state, changes, db.table(state.currentTable).orderBy(":id"));
|
|
7219
|
+
}
|
|
7220
|
+
}
|
|
7221
|
+
});
|
|
7222
|
+
};
|
|
7223
|
+
}
|
|
7224
|
+
function initGetLocalChangesForNode(db, hasMoreToGive, partialsThreshold) {
|
|
7225
|
+
var MAX_CHANGES_PER_CHUNK = partialsThreshold;
|
|
7226
|
+
return function getLocalChangesForNode(node, cb) {
|
|
7227
|
+
var getChangesSinceRevision = initGetChangesSinceRevision(db, node, hasMoreToGive);
|
|
7228
|
+
var getTableObjectsAsChanges = initGetTableObjectsAsChanges(db, node, MAX_CHANGES_PER_CHUNK, getChangesSinceRevision, hasMoreToGive, cb);
|
|
7229
|
+
if (node.myRevision >= 0) {
|
|
7230
|
+
var brmcr = getBaseRevisionAndMaxClientRevision(node);
|
|
7231
|
+
return getChangesSinceRevision(node.myRevision, MAX_CHANGES_PER_CHUNK, brmcr.maxClientRevision, function(changes, partial, nodeModificationsOnAck) {
|
|
7232
|
+
return cb(changes, brmcr.remoteBaseRevision, partial, nodeModificationsOnAck);
|
|
7233
|
+
});
|
|
7234
|
+
} else {
|
|
7235
|
+
if (node.dbUploadState === null) {
|
|
7236
|
+
var tablesToUpload = db.tables.filter(function(table) {
|
|
7237
|
+
return table.schema.observable;
|
|
7238
|
+
}).map(function(table) {
|
|
7239
|
+
return table.name;
|
|
7240
|
+
});
|
|
7241
|
+
if (tablesToUpload.length === 0)
|
|
7242
|
+
return import_wrapper_default.Promise.resolve(cb([], null, false, {}));
|
|
7243
|
+
var dbUploadState = {
|
|
7244
|
+
tablesToUpload,
|
|
7245
|
+
currentTable: tablesToUpload.shift(),
|
|
7246
|
+
currentKey: null
|
|
7247
|
+
};
|
|
7248
|
+
return db._changes.orderBy("rev").last(function(lastChange) {
|
|
7249
|
+
dbUploadState.localBaseRevision = lastChange && lastChange.rev || 0;
|
|
7250
|
+
var collection2 = db.table(dbUploadState.currentTable).orderBy(":id");
|
|
7251
|
+
return getTableObjectsAsChanges(dbUploadState, [], collection2);
|
|
7252
|
+
});
|
|
7253
|
+
} else if (node.dbUploadState.currentKey) {
|
|
7254
|
+
var collection = db.table(node.dbUploadState.currentTable).where(":id").above(node.dbUploadState.currentKey);
|
|
7255
|
+
return getTableObjectsAsChanges(import_wrapper_default.deepClone(node.dbUploadState), [], collection);
|
|
7256
|
+
} else {
|
|
7257
|
+
var collection = db.table(dbUploadState.currentTable).orderBy(":id");
|
|
7258
|
+
return getTableObjectsAsChanges(import_wrapper_default.deepClone(node.dbUploadState), [], collection);
|
|
7259
|
+
}
|
|
7260
|
+
}
|
|
7261
|
+
};
|
|
7262
|
+
}
|
|
7263
|
+
var Statuses = {
|
|
7264
|
+
ERROR: -1,
|
|
7265
|
+
OFFLINE: 0,
|
|
7266
|
+
CONNECTING: 1,
|
|
7267
|
+
ONLINE: 2,
|
|
7268
|
+
SYNCING: 3,
|
|
7269
|
+
ERROR_WILL_RETRY: 4
|
|
7270
|
+
// An error occurred such as net down but the sync provider will retry to connect.
|
|
7271
|
+
};
|
|
7272
|
+
var StatusTexts = {
|
|
7273
|
+
"-1": "ERROR",
|
|
7274
|
+
"0": "OFFLINE",
|
|
7275
|
+
"1": "CONNECTING",
|
|
7276
|
+
"2": "ONLINE",
|
|
7277
|
+
"3": "SYNCING",
|
|
7278
|
+
"4": "ERROR_WILL_RETRY"
|
|
7279
|
+
};
|
|
7280
|
+
var Promise$22 = import_wrapper_default.Promise;
|
|
7281
|
+
function initConnectProtocol(db, protocolInstance, dbAliveID, options, rejectConnectPromise) {
|
|
7282
|
+
var enqueue = initEnqueue(db);
|
|
7283
|
+
var hasMoreToGive = { hasMoreToGive: true };
|
|
7284
|
+
function stillAlive() {
|
|
7285
|
+
return db._localSyncNode && db._localSyncNode.id === dbAliveID;
|
|
7286
|
+
}
|
|
7287
|
+
return function connectProtocol(node, activePeer) {
|
|
7288
|
+
var getLocalChangesForNode = initGetLocalChangesForNode(db, hasMoreToGive, protocolInstance.partialsThreshold);
|
|
7289
|
+
var url = activePeer.url;
|
|
7290
|
+
function changeStatusTo(newStatus) {
|
|
7291
|
+
if (node.status !== newStatus) {
|
|
7292
|
+
node.status = newStatus;
|
|
7293
|
+
node.save().then(function() {
|
|
7294
|
+
db.syncable.on.statusChanged.fire(newStatus, url);
|
|
7295
|
+
db.observable.broadcastMessage("syncStatusChanged", { newStatus, url }, false);
|
|
7296
|
+
}).catch("DatabaseClosedError", function() {
|
|
7297
|
+
});
|
|
7298
|
+
}
|
|
7299
|
+
}
|
|
7300
|
+
activePeer.on("disconnect", function(newStatus) {
|
|
7301
|
+
if (!isNaN(newStatus))
|
|
7302
|
+
changeStatusTo(newStatus);
|
|
7303
|
+
});
|
|
7304
|
+
var connectedContinuation;
|
|
7305
|
+
changeStatusTo(Statuses.CONNECTING);
|
|
7306
|
+
return doSync();
|
|
7307
|
+
function doSync() {
|
|
7308
|
+
return enqueue(doSync, function() {
|
|
7309
|
+
return getLocalChangesForNode_autoAckIfEmpty(node, sendChangesToProvider);
|
|
7310
|
+
}, dbAliveID);
|
|
7311
|
+
}
|
|
7312
|
+
function sendChangesToProvider(changes, remoteBaseRevision, partial, nodeModificationsOnAck) {
|
|
7313
|
+
var finalSyncPromise = new Promise$22(function(resolve, reject) {
|
|
7314
|
+
rejectConnectPromise.p = function(err) {
|
|
7315
|
+
reject(err);
|
|
7316
|
+
};
|
|
7317
|
+
import_wrapper_default.asap(function() {
|
|
7318
|
+
try {
|
|
7319
|
+
protocolInstance.sync(node.syncContext, url, options, remoteBaseRevision, node.appliedRemoteRevision, changes, partial, applyRemoteChanges, onChangesAccepted, function(continuation) {
|
|
7320
|
+
resolve(continuation);
|
|
7321
|
+
}, onError);
|
|
7322
|
+
} catch (ex) {
|
|
7323
|
+
onError(ex, Infinity);
|
|
7324
|
+
}
|
|
7325
|
+
function onError(error, again) {
|
|
7326
|
+
reject(error);
|
|
7327
|
+
if (stillAlive()) {
|
|
7328
|
+
if (!isNaN(again) && again < Infinity) {
|
|
7329
|
+
setTimeout(function() {
|
|
7330
|
+
if (stillAlive()) {
|
|
7331
|
+
changeStatusTo(Statuses.SYNCING);
|
|
7332
|
+
doSync().catch("DatabaseClosedError", abortTheProvider);
|
|
7333
|
+
}
|
|
7334
|
+
}, again);
|
|
7335
|
+
changeStatusTo(Statuses.ERROR_WILL_RETRY);
|
|
7336
|
+
if (connectedContinuation && connectedContinuation.disconnect)
|
|
7337
|
+
connectedContinuation.disconnect();
|
|
7338
|
+
connectedContinuation = null;
|
|
7339
|
+
} else {
|
|
7340
|
+
abortTheProvider(error);
|
|
7341
|
+
}
|
|
7342
|
+
}
|
|
7343
|
+
}
|
|
7344
|
+
});
|
|
7345
|
+
});
|
|
7346
|
+
return finalSyncPromise.then(function() {
|
|
7347
|
+
return void 0;
|
|
7348
|
+
}).finally(function() {
|
|
7349
|
+
rejectConnectPromise.p = null;
|
|
7350
|
+
});
|
|
7351
|
+
function onChangesAccepted() {
|
|
7352
|
+
Object.keys(nodeModificationsOnAck).forEach(function(keyPath) {
|
|
7353
|
+
import_wrapper_default.setByKeyPath(node, keyPath, nodeModificationsOnAck[keyPath]);
|
|
7354
|
+
});
|
|
7355
|
+
finalSyncPromise.then(continueSendingChanges);
|
|
7356
|
+
return node.save();
|
|
7357
|
+
}
|
|
7358
|
+
}
|
|
7359
|
+
function abortTheProvider(error) {
|
|
7360
|
+
activePeer.disconnect(Statuses.ERROR, error);
|
|
7361
|
+
}
|
|
7362
|
+
function getLocalChangesForNode_autoAckIfEmpty(node2, cb) {
|
|
7363
|
+
return getLocalChangesForNode(node2, function autoAck(changes, remoteBaseRevision, partial, nodeModificationsOnAck) {
|
|
7364
|
+
if (changes.length === 0 && "myRevision" in nodeModificationsOnAck && nodeModificationsOnAck.myRevision !== node2.myRevision) {
|
|
7365
|
+
Object.keys(nodeModificationsOnAck).forEach(function(keyPath) {
|
|
7366
|
+
import_wrapper_default.setByKeyPath(node2, keyPath, nodeModificationsOnAck[keyPath]);
|
|
7367
|
+
});
|
|
7368
|
+
node2.save().catch("DatabaseClosedError", function() {
|
|
7369
|
+
});
|
|
7370
|
+
return getLocalChangesForNode(node2, autoAck);
|
|
7371
|
+
} else {
|
|
7372
|
+
return cb(changes, remoteBaseRevision, partial, nodeModificationsOnAck);
|
|
7373
|
+
}
|
|
7374
|
+
});
|
|
7375
|
+
}
|
|
7376
|
+
function applyRemoteChanges(remoteChanges, remoteRevision, partial) {
|
|
7377
|
+
var saveToUncommittedChanges = initSaveToUncommittedChanges(db, node);
|
|
7378
|
+
var finallyCommitAllChanges = initFinallyCommitAllChanges(db, node);
|
|
7379
|
+
return enqueue(applyRemoteChanges, function() {
|
|
7380
|
+
if (!stillAlive())
|
|
7381
|
+
return Promise$22.reject(new import_wrapper_default.DatabaseClosedError());
|
|
7382
|
+
return (partial ? saveToUncommittedChanges(remoteChanges, remoteRevision) : finallyCommitAllChanges(remoteChanges, remoteRevision)).catch(function(error) {
|
|
7383
|
+
abortTheProvider(error);
|
|
7384
|
+
return Promise$22.reject(error);
|
|
7385
|
+
});
|
|
7386
|
+
}, dbAliveID);
|
|
7387
|
+
}
|
|
7388
|
+
function continueSendingChanges(continuation) {
|
|
7389
|
+
if (!stillAlive()) {
|
|
7390
|
+
if (continuation.disconnect)
|
|
7391
|
+
continuation.disconnect();
|
|
7392
|
+
return;
|
|
7393
|
+
}
|
|
7394
|
+
connectedContinuation = continuation;
|
|
7395
|
+
activePeer.on("disconnect", function() {
|
|
7396
|
+
if (connectedContinuation) {
|
|
7397
|
+
if (connectedContinuation.react) {
|
|
7398
|
+
try {
|
|
7399
|
+
connectedContinuation.disconnect();
|
|
7400
|
+
} catch (e) {
|
|
7401
|
+
}
|
|
7402
|
+
}
|
|
7403
|
+
connectedContinuation = null;
|
|
7404
|
+
}
|
|
7405
|
+
});
|
|
7406
|
+
if (continuation.react) {
|
|
7407
|
+
continueUsingReactPattern(continuation);
|
|
7408
|
+
} else {
|
|
7409
|
+
continueUsingPollPattern();
|
|
7410
|
+
}
|
|
7411
|
+
}
|
|
7412
|
+
function continueUsingReactPattern(continuation) {
|
|
7413
|
+
var changesWaiting, isWaitingForServer;
|
|
7414
|
+
function onChanges() {
|
|
7415
|
+
if (connectedContinuation) {
|
|
7416
|
+
changeStatusTo(Statuses.SYNCING);
|
|
7417
|
+
if (isWaitingForServer)
|
|
7418
|
+
changesWaiting = true;
|
|
7419
|
+
else {
|
|
7420
|
+
reactToChanges();
|
|
7421
|
+
}
|
|
7422
|
+
}
|
|
7423
|
+
}
|
|
7424
|
+
db.on("changes", onChanges);
|
|
7425
|
+
activePeer.on("disconnect", function() {
|
|
7426
|
+
db.on.changes.unsubscribe(onChanges);
|
|
7427
|
+
});
|
|
7428
|
+
function reactToChanges() {
|
|
7429
|
+
if (!connectedContinuation)
|
|
7430
|
+
return;
|
|
7431
|
+
changesWaiting = false;
|
|
7432
|
+
isWaitingForServer = true;
|
|
7433
|
+
getLocalChangesForNode_autoAckIfEmpty(node, function(changes, remoteBaseRevision, partial, nodeModificationsOnAck) {
|
|
7434
|
+
if (!connectedContinuation)
|
|
7435
|
+
return;
|
|
7436
|
+
if (changes.length > 0) {
|
|
7437
|
+
continuation.react(changes, remoteBaseRevision, partial, function onChangesAccepted() {
|
|
7438
|
+
Object.keys(nodeModificationsOnAck).forEach(function(keyPath) {
|
|
7439
|
+
import_wrapper_default.setByKeyPath(node, keyPath, nodeModificationsOnAck[keyPath]);
|
|
7440
|
+
});
|
|
7441
|
+
node.save().catch("DatabaseClosedError", function() {
|
|
7442
|
+
});
|
|
7443
|
+
reactToChanges();
|
|
7444
|
+
});
|
|
7445
|
+
} else {
|
|
7446
|
+
isWaitingForServer = false;
|
|
7447
|
+
if (changesWaiting) {
|
|
7448
|
+
reactToChanges();
|
|
7449
|
+
} else {
|
|
7450
|
+
changeStatusTo(Statuses.ONLINE);
|
|
7451
|
+
}
|
|
7452
|
+
}
|
|
7453
|
+
}).catch(function(ex) {
|
|
7454
|
+
console.error("Got ".concat(ex.message, " caught by reactToChanges"));
|
|
7455
|
+
abortTheProvider(ex);
|
|
7456
|
+
});
|
|
7457
|
+
}
|
|
7458
|
+
reactToChanges();
|
|
7459
|
+
}
|
|
7460
|
+
function continueUsingPollPattern() {
|
|
7461
|
+
function syncAgain() {
|
|
7462
|
+
getLocalChangesForNode_autoAckIfEmpty(node, function(changes, remoteBaseRevision, partial, nodeModificationsOnAck) {
|
|
7463
|
+
protocolInstance.sync(node.syncContext, url, options, remoteBaseRevision, node.appliedRemoteRevision, changes, partial, applyRemoteChanges, onChangesAccepted, onSuccess, onError);
|
|
7464
|
+
function onChangesAccepted() {
|
|
7465
|
+
Object.keys(nodeModificationsOnAck).forEach(function(keyPath) {
|
|
7466
|
+
import_wrapper_default.setByKeyPath(node, keyPath, nodeModificationsOnAck[keyPath]);
|
|
7467
|
+
});
|
|
7468
|
+
node.save().catch("DatabaseClosedError", function() {
|
|
7469
|
+
});
|
|
7470
|
+
}
|
|
7471
|
+
function onSuccess(continuation) {
|
|
7472
|
+
if (!connectedContinuation) {
|
|
7473
|
+
return;
|
|
7474
|
+
}
|
|
7475
|
+
connectedContinuation = continuation;
|
|
7476
|
+
if (partial) {
|
|
7477
|
+
syncAgain();
|
|
7478
|
+
} else {
|
|
7479
|
+
if (!isNaN(continuation.again) && continuation.again < Infinity) {
|
|
7480
|
+
changeStatusTo(Statuses.ONLINE);
|
|
7481
|
+
setTimeout(function() {
|
|
7482
|
+
if (connectedContinuation) {
|
|
7483
|
+
changeStatusTo(Statuses.SYNCING);
|
|
7484
|
+
syncAgain();
|
|
7485
|
+
}
|
|
7486
|
+
}, continuation.again);
|
|
7487
|
+
} else {
|
|
7488
|
+
activePeer.disconnect(Statuses.OFFLINE);
|
|
7489
|
+
}
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
function onError(error, again) {
|
|
7493
|
+
if (!isNaN(again) && again < Infinity) {
|
|
7494
|
+
if (connectedContinuation) {
|
|
7495
|
+
setTimeout(function() {
|
|
7496
|
+
if (connectedContinuation) {
|
|
7497
|
+
changeStatusTo(Statuses.SYNCING);
|
|
7498
|
+
syncAgain();
|
|
7499
|
+
}
|
|
7500
|
+
}, again);
|
|
7501
|
+
changeStatusTo(Statuses.ERROR_WILL_RETRY);
|
|
7502
|
+
}
|
|
7503
|
+
} else {
|
|
7504
|
+
abortTheProvider(error);
|
|
7505
|
+
}
|
|
7506
|
+
}
|
|
7507
|
+
}).catch(abortTheProvider);
|
|
7508
|
+
}
|
|
7509
|
+
if (hasMoreToGive.hasMoreToGive) {
|
|
7510
|
+
syncAgain();
|
|
7511
|
+
} else if (connectedContinuation && !isNaN(connectedContinuation.again) && connectedContinuation.again < Infinity) {
|
|
7512
|
+
changeStatusTo(Statuses.ONLINE);
|
|
7513
|
+
setTimeout(function() {
|
|
7514
|
+
if (connectedContinuation) {
|
|
7515
|
+
changeStatusTo(Statuses.SYNCING);
|
|
7516
|
+
syncAgain();
|
|
7517
|
+
}
|
|
7518
|
+
}, connectedContinuation.again);
|
|
7519
|
+
} else {
|
|
7520
|
+
activePeer.disconnect(Statuses.OFFLINE);
|
|
7521
|
+
}
|
|
7522
|
+
}
|
|
7523
|
+
};
|
|
7524
|
+
}
|
|
7525
|
+
function initConnectFn(db, activePeers) {
|
|
7526
|
+
return function connect(protocolInstance, protocolName, url, options, dbAliveID) {
|
|
7527
|
+
var existingPeer = activePeers.filter(function(peer) {
|
|
7528
|
+
return peer.url === url;
|
|
7529
|
+
});
|
|
7530
|
+
if (existingPeer.length > 0) {
|
|
7531
|
+
var activePeer = existingPeer[0];
|
|
7532
|
+
var diffObject = {};
|
|
7533
|
+
import_wrapper_default.getObjectDiff(activePeer.syncOptions, options, diffObject);
|
|
7534
|
+
if (Object.keys(diffObject).length !== 0) {
|
|
7535
|
+
return db.syncable.disconnect(url).then(function() {
|
|
7536
|
+
return execConnect();
|
|
7537
|
+
});
|
|
7538
|
+
} else {
|
|
7539
|
+
return existingPeer[0].connectPromise;
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
function execConnect() {
|
|
7543
|
+
var rejectConnectPromise = { p: null };
|
|
7544
|
+
var connectProtocol = initConnectProtocol(db, protocolInstance, dbAliveID, options, rejectConnectPromise);
|
|
7545
|
+
var getOrCreateSyncNode = initGetOrCreateSyncNode(db, protocolName, url);
|
|
7546
|
+
var connectPromise = getOrCreateSyncNode(options).then(function(node) {
|
|
7547
|
+
return connectProtocol(node, activePeer2);
|
|
7548
|
+
});
|
|
7549
|
+
var disconnected = false;
|
|
7550
|
+
var activePeer2 = {
|
|
7551
|
+
url,
|
|
7552
|
+
status: Statuses.OFFLINE,
|
|
7553
|
+
connectPromise,
|
|
7554
|
+
syncOptions: options,
|
|
7555
|
+
on: import_wrapper_default.Events(null, "disconnect"),
|
|
7556
|
+
disconnect: function(newStatus, error) {
|
|
7557
|
+
var pos = activePeers.indexOf(activePeer2);
|
|
7558
|
+
if (pos >= 0)
|
|
7559
|
+
activePeers.splice(pos, 1);
|
|
7560
|
+
if (error && rejectConnectPromise.p)
|
|
7561
|
+
rejectConnectPromise.p(error);
|
|
7562
|
+
if (!disconnected) {
|
|
7563
|
+
activePeer2.on.disconnect.fire(newStatus, error);
|
|
7564
|
+
}
|
|
7565
|
+
disconnected = true;
|
|
7566
|
+
}
|
|
7567
|
+
};
|
|
7568
|
+
activePeers.push(activePeer2);
|
|
7569
|
+
return connectPromise;
|
|
7570
|
+
}
|
|
7571
|
+
return execConnect();
|
|
7572
|
+
};
|
|
7573
|
+
}
|
|
7574
|
+
var override2 = import_wrapper_default.override;
|
|
7575
|
+
var Promise$12 = import_wrapper_default.Promise;
|
|
7576
|
+
var Observable2 = import_wrapper_default.Observable;
|
|
7577
|
+
function Syncable(db) {
|
|
7578
|
+
if (!/^(3|4)\./.test(import_wrapper_default.version))
|
|
7579
|
+
throw new Error("Missing dexie version 3.x or 4.x");
|
|
7580
|
+
if (!db.observable || db.observable.version !== "{version}" && !/^(3|4)\./.test(db.observable.version))
|
|
7581
|
+
throw new Error("Missing dexie-observable version 3.x or 4.x");
|
|
7582
|
+
if (db.syncable) {
|
|
7583
|
+
if (db.syncable.version !== "{version}")
|
|
7584
|
+
throw new Error("Mixed versions of dexie-syncable");
|
|
7585
|
+
return;
|
|
7586
|
+
}
|
|
7587
|
+
var activePeers = [];
|
|
7588
|
+
var connectFn = initConnectFn(db, activePeers);
|
|
7589
|
+
var syncableConnect = initSyncableConnect(db, connectFn);
|
|
7590
|
+
db.on("message", function(msg) {
|
|
7591
|
+
import_wrapper_default.vip(function() {
|
|
7592
|
+
if (msg.type === "connect") {
|
|
7593
|
+
db.syncable.connect(msg.message.protocolName, msg.message.url, msg.message.options).then(msg.resolve, msg.reject);
|
|
7594
|
+
} else if (msg.type === "disconnect") {
|
|
7595
|
+
db.syncable.disconnect(msg.message.url).then(msg.resolve, msg.reject);
|
|
7596
|
+
} else if (msg.type === "syncStatusChanged") {
|
|
7597
|
+
db.syncable.on.statusChanged.fire(msg.message.newStatus, msg.message.url);
|
|
7598
|
+
}
|
|
7599
|
+
});
|
|
7600
|
+
});
|
|
7601
|
+
db.on("cleanup", function(weBecameMaster) {
|
|
7602
|
+
if (weBecameMaster) {
|
|
7603
|
+
import_wrapper_default.ignoreTransaction(function() {
|
|
7604
|
+
return import_wrapper_default.vip(function() {
|
|
7605
|
+
return db._syncNodes.where({ type: "remote" }).filter(function(node) {
|
|
7606
|
+
return node.status !== Statuses.OFFLINE;
|
|
7607
|
+
}).toArray(function(connectedRemoteNodes) {
|
|
7608
|
+
return Promise$12.all(connectedRemoteNodes.map(function(node) {
|
|
7609
|
+
return db.syncable.connect(node.syncProtocol, node.url, node.syncOptions).catch(function(e) {
|
|
7610
|
+
console.warn("Dexie.Syncable: Could not connect to ".concat(node.url, ". ").concat(e.stack || e));
|
|
7611
|
+
});
|
|
7612
|
+
}));
|
|
7613
|
+
});
|
|
7614
|
+
});
|
|
7615
|
+
}).catch("DatabaseClosedError", function() {
|
|
7616
|
+
});
|
|
7617
|
+
}
|
|
7618
|
+
});
|
|
7619
|
+
db.on("ready", function onReady() {
|
|
7620
|
+
if (db._localSyncNode && db._localSyncNode.isMaster) {
|
|
7621
|
+
db._syncNodes.where("type").equals("remote").and(function(node) {
|
|
7622
|
+
return node.status !== Statuses.OFFLINE;
|
|
7623
|
+
}).toArray(function(connectedRemoteNodes) {
|
|
7624
|
+
connectedRemoteNodes.forEach(
|
|
7625
|
+
function(node) {
|
|
7626
|
+
return db.syncable.connect(node.syncProtocol, node.url, node.syncOptions).catch(function() {
|
|
7627
|
+
});
|
|
7628
|
+
}
|
|
7629
|
+
// A failure will be triggered in on('statusChanged'). We can ignore.
|
|
7630
|
+
);
|
|
7631
|
+
}).catch("DatabaseClosedError", function() {
|
|
7632
|
+
});
|
|
7633
|
+
}
|
|
7634
|
+
}, true);
|
|
7635
|
+
db.syncable = {
|
|
7636
|
+
version: "{version}"
|
|
7637
|
+
};
|
|
7638
|
+
db.syncable.getStatus = function(url, cb) {
|
|
7639
|
+
if (db.isOpen()) {
|
|
7640
|
+
return import_wrapper_default.vip(function() {
|
|
7641
|
+
return db._syncNodes.where("url").equals(url).first(function(node) {
|
|
7642
|
+
return node ? node.status : Statuses.OFFLINE;
|
|
7643
|
+
});
|
|
7644
|
+
}).then(cb);
|
|
7645
|
+
} else {
|
|
7646
|
+
return Promise$12.resolve(Syncable.Statuses.OFFLINE).then(cb);
|
|
7647
|
+
}
|
|
7648
|
+
};
|
|
7649
|
+
db.syncable.getOptions = function(url, cb) {
|
|
7650
|
+
return db.transaction("r?", db._syncNodes, function() {
|
|
7651
|
+
return db._syncNodes.where("url").equals(url).first(function(node) {
|
|
7652
|
+
return node.syncOptions;
|
|
7653
|
+
}).then(cb);
|
|
7654
|
+
});
|
|
7655
|
+
};
|
|
7656
|
+
db.syncable.list = function() {
|
|
7657
|
+
return db.transaction("r?", db._syncNodes, function() {
|
|
7658
|
+
return db._syncNodes.where("type").equals("remote").toArray(function(a) {
|
|
7659
|
+
return a.map(function(node) {
|
|
7660
|
+
return node.url;
|
|
7661
|
+
});
|
|
7662
|
+
});
|
|
7663
|
+
});
|
|
7664
|
+
};
|
|
7665
|
+
db.syncable.on = import_wrapper_default.Events(db, { statusChanged: "asap" });
|
|
7666
|
+
db.syncable.disconnect = function(url) {
|
|
7667
|
+
return import_wrapper_default.ignoreTransaction(function() {
|
|
7668
|
+
return Promise$12.resolve().then(function() {
|
|
7669
|
+
if (db._localSyncNode && db._localSyncNode.isMaster) {
|
|
7670
|
+
return Promise$12.all(activePeers.filter(function(peer) {
|
|
7671
|
+
return peer.url === url;
|
|
7672
|
+
}).map(function(peer) {
|
|
7673
|
+
return peer.disconnect(Statuses.OFFLINE);
|
|
7674
|
+
}));
|
|
7675
|
+
} else {
|
|
7676
|
+
return db._syncNodes.where("isMaster").above(0).first(function(masterNode) {
|
|
7677
|
+
return db.observable.sendMessage("disconnect", { url }, masterNode.id, { wantReply: true });
|
|
7678
|
+
});
|
|
7679
|
+
}
|
|
7680
|
+
}).then(function() {
|
|
7681
|
+
return db._syncNodes.where("url").equals(url).modify(function(node) {
|
|
7682
|
+
node.status = Statuses.OFFLINE;
|
|
7683
|
+
});
|
|
7684
|
+
});
|
|
7685
|
+
});
|
|
7686
|
+
};
|
|
7687
|
+
db.syncable.connect = function(protocolName, url, options) {
|
|
7688
|
+
options = options || {};
|
|
7689
|
+
var protocolInstance = Syncable.registeredProtocols[protocolName];
|
|
7690
|
+
if (protocolInstance) {
|
|
7691
|
+
return syncableConnect(protocolInstance, protocolName, url, options);
|
|
7692
|
+
} else {
|
|
7693
|
+
return Promise$12.reject(new Error("ISyncProtocol '" + protocolName + "' is not registered in Dexie.Syncable.registerSyncProtocol()"));
|
|
7694
|
+
}
|
|
7695
|
+
};
|
|
7696
|
+
db.syncable.delete = function(url) {
|
|
7697
|
+
return db.syncable.disconnect(url).then(function() {
|
|
7698
|
+
return db.transaction("rw!", db._syncNodes, db._changes, db._uncommittedChanges, function() {
|
|
7699
|
+
var nodeIDsToDelete;
|
|
7700
|
+
return db._syncNodes.where("url").equals(url).toArray(function(nodes) {
|
|
7701
|
+
return nodes.map(function(node) {
|
|
7702
|
+
return node.id;
|
|
7703
|
+
});
|
|
7704
|
+
}).then(function(nodeIDs) {
|
|
7705
|
+
nodeIDsToDelete = nodeIDs;
|
|
7706
|
+
return db._syncNodes.where("id").anyOf(nodeIDs).delete();
|
|
7707
|
+
}).then(function() {
|
|
7708
|
+
return db._uncommittedChanges.where("node").anyOf(nodeIDsToDelete).delete();
|
|
7709
|
+
});
|
|
7710
|
+
}).then(function() {
|
|
7711
|
+
Observable2.deleteOldChanges(db);
|
|
7712
|
+
});
|
|
7713
|
+
});
|
|
7714
|
+
};
|
|
7715
|
+
db.syncable.unsyncedChanges = function(url) {
|
|
7716
|
+
return db._syncNodes.where("url").equals(url).first(function(node) {
|
|
7717
|
+
return db._changes.where("rev").above(node.myRevision).toArray();
|
|
7718
|
+
});
|
|
7719
|
+
};
|
|
7720
|
+
db.close = override2(db.close, function(origClose) {
|
|
7721
|
+
return function() {
|
|
7722
|
+
activePeers.forEach(function(peer) {
|
|
7723
|
+
peer.disconnect();
|
|
7724
|
+
});
|
|
7725
|
+
return origClose.apply(this, arguments);
|
|
7726
|
+
};
|
|
7727
|
+
});
|
|
7728
|
+
Object.defineProperty(db.observable.SyncNode.prototype, "save", {
|
|
7729
|
+
enumerable: false,
|
|
7730
|
+
configurable: true,
|
|
7731
|
+
writable: true,
|
|
7732
|
+
value: function() {
|
|
7733
|
+
var _this = this;
|
|
7734
|
+
return db.transaction("rw?", db._syncNodes, function() {
|
|
7735
|
+
return db._syncNodes.put(_this);
|
|
7736
|
+
});
|
|
7737
|
+
}
|
|
7738
|
+
});
|
|
7739
|
+
}
|
|
7740
|
+
Syncable.version = "{version}";
|
|
7741
|
+
Syncable.Statuses = Statuses;
|
|
7742
|
+
Syncable.StatusTexts = StatusTexts;
|
|
7743
|
+
Syncable.registeredProtocols = {};
|
|
7744
|
+
Syncable.registerSyncProtocol = function(name, protocolInstance) {
|
|
7745
|
+
var partialsThreshold = protocolInstance.partialsThreshold;
|
|
7746
|
+
if (typeof partialsThreshold === "number") {
|
|
7747
|
+
if (isNaN(partialsThreshold) || partialsThreshold < 0) {
|
|
7748
|
+
throw new Error("The given number for the threshold is not supported");
|
|
7749
|
+
}
|
|
7750
|
+
} else {
|
|
7751
|
+
protocolInstance.partialsThreshold = Infinity;
|
|
7752
|
+
}
|
|
7753
|
+
Syncable.registeredProtocols[name] = protocolInstance;
|
|
7754
|
+
};
|
|
7755
|
+
if (import_wrapper_default.Syncable) {
|
|
7756
|
+
if (import_wrapper_default.Syncable.version !== "{version}") {
|
|
7757
|
+
throw new Error("Mixed versions of dexie-syncable");
|
|
7758
|
+
}
|
|
7759
|
+
} else {
|
|
7760
|
+
import_wrapper_default.Syncable = Syncable;
|
|
7761
|
+
import_wrapper_default.addons.push(Syncable);
|
|
7762
|
+
}
|
|
7763
|
+
var Dexie_Syncable = import_wrapper_default.Syncable;
|
|
7764
|
+
|
|
7765
|
+
// ../sync/src/syncProtocol.js
|
|
7766
|
+
var syncProtocol = function() {
|
|
7767
|
+
console.log("Initializing syncProtocol");
|
|
7768
|
+
var RECONNECT_DELAY = 5e3;
|
|
7769
|
+
Dexie.Syncable.registerSyncProtocol("websocket", {
|
|
7770
|
+
sync: function(context, url, options, baseRevision, syncedRevision, changes, partial, applyRemoteChanges, onChangesAccepted, onSuccess, onError) {
|
|
7771
|
+
var requestId = 0;
|
|
7772
|
+
var acceptCallbacks = {};
|
|
7773
|
+
var ws = new WebSocket(url);
|
|
7774
|
+
function sendChanges(changes2, baseRevision2, partial2, onChangesAccepted2) {
|
|
7775
|
+
console.log("sendChanges", changes2.length, baseRevision2);
|
|
7776
|
+
++requestId;
|
|
7777
|
+
acceptCallbacks[requestId.toString()] = onChangesAccepted2;
|
|
7778
|
+
ws.send(
|
|
7779
|
+
JSON.stringify({
|
|
7780
|
+
type: "changes",
|
|
7781
|
+
changes: changes2,
|
|
7782
|
+
partial: partial2,
|
|
7783
|
+
baseRevision: baseRevision2,
|
|
7784
|
+
requestId
|
|
7785
|
+
})
|
|
7786
|
+
);
|
|
7787
|
+
}
|
|
7788
|
+
ws.onopen = function(event) {
|
|
7789
|
+
console.log("Opening socket - sending clientIdentity", context.clientIdentity);
|
|
7790
|
+
ws.send(
|
|
7791
|
+
JSON.stringify({
|
|
7792
|
+
type: "clientIdentity",
|
|
7793
|
+
clientIdentity: context.clientIdentity || null,
|
|
7794
|
+
authToken: options.authToken
|
|
7795
|
+
})
|
|
7796
|
+
);
|
|
7797
|
+
};
|
|
7798
|
+
ws.onerror = function(event) {
|
|
7799
|
+
ws.close();
|
|
7800
|
+
console.log("ws.onerror", event);
|
|
7801
|
+
onError(event?.message, RECONNECT_DELAY);
|
|
7802
|
+
};
|
|
7803
|
+
ws.onclose = function(event) {
|
|
7804
|
+
onError("Socket closed: " + event.reason, RECONNECT_DELAY);
|
|
7805
|
+
};
|
|
7806
|
+
var isFirstRound = true;
|
|
7807
|
+
ws.onmessage = function(event) {
|
|
7808
|
+
try {
|
|
7809
|
+
var requestFromServer = JSON.parse(event.data);
|
|
7810
|
+
console.log("requestFromServer", requestFromServer, { acceptCallback, isFirstRound });
|
|
7811
|
+
if (requestFromServer.type == "clientIdentity") {
|
|
7812
|
+
context.clientIdentity = requestFromServer.clientIdentity;
|
|
7813
|
+
context.save();
|
|
7814
|
+
sendChanges(changes, baseRevision, partial, onChangesAccepted);
|
|
7815
|
+
ws.send(
|
|
7816
|
+
JSON.stringify({
|
|
7817
|
+
type: "subscribe",
|
|
7818
|
+
syncedRevision
|
|
7819
|
+
})
|
|
7820
|
+
);
|
|
7821
|
+
} else if (requestFromServer.type == "error") {
|
|
7822
|
+
} else if (requestFromServer.type == "changes") {
|
|
7823
|
+
applyRemoteChanges(
|
|
7824
|
+
requestFromServer.changes,
|
|
7825
|
+
requestFromServer.currentRevision,
|
|
7826
|
+
requestFromServer.partial
|
|
7827
|
+
);
|
|
7828
|
+
if (isFirstRound && !requestFromServer.partial) {
|
|
7829
|
+
onSuccess({
|
|
7830
|
+
// Specify a react function that will react on additional client changes
|
|
7831
|
+
react: function(changes2, baseRevision2, partial2, onChangesAccepted2) {
|
|
7832
|
+
sendChanges(
|
|
7833
|
+
changes2,
|
|
7834
|
+
baseRevision2,
|
|
7835
|
+
partial2,
|
|
7836
|
+
onChangesAccepted2
|
|
7837
|
+
);
|
|
7838
|
+
},
|
|
7839
|
+
// Specify a disconnect function that will close our socket so that we dont continue to monitor changes.
|
|
7840
|
+
disconnect: function() {
|
|
7841
|
+
ws.close();
|
|
7842
|
+
}
|
|
7843
|
+
});
|
|
7844
|
+
isFirstRound = false;
|
|
7845
|
+
}
|
|
7846
|
+
} else if (requestFromServer.type == "ack") {
|
|
7847
|
+
var requestId2 = requestFromServer.requestId;
|
|
7848
|
+
var acceptCallback = acceptCallbacks[requestId2.toString()];
|
|
7849
|
+
acceptCallback();
|
|
7850
|
+
delete acceptCallbacks[requestId2.toString()];
|
|
7851
|
+
} else if (requestFromServer.type == "error") {
|
|
7852
|
+
var requestId2 = requestFromServer.requestId;
|
|
7853
|
+
ws.close();
|
|
7854
|
+
onError(requestFromServer.message, Infinity);
|
|
7855
|
+
} else {
|
|
7856
|
+
console.log("unknown message", requestFromServer);
|
|
7857
|
+
ws.close();
|
|
7858
|
+
onError("unknown message", Infinity);
|
|
7859
|
+
}
|
|
7860
|
+
} catch (e) {
|
|
7861
|
+
ws.close();
|
|
7862
|
+
onError(e, Infinity);
|
|
7863
|
+
}
|
|
7864
|
+
};
|
|
7865
|
+
}
|
|
7866
|
+
});
|
|
7867
|
+
};
|
|
7868
|
+
|
|
7869
|
+
// ../sync/src/index.ts
|
|
7870
|
+
syncProtocol();
|
|
7871
|
+
var BasicSync = class extends Dexie {
|
|
7872
|
+
basic_schema;
|
|
7873
|
+
constructor(name, options) {
|
|
7874
|
+
super(name, options);
|
|
7875
|
+
this.basic_schema = options.schema;
|
|
7876
|
+
this.version(1).stores(this._convertSchemaToDxSchema(this.basic_schema));
|
|
7877
|
+
this.version(2).stores({});
|
|
7878
|
+
this.Collection.prototype.get = this.Collection.prototype.toArray;
|
|
7879
|
+
}
|
|
7880
|
+
async connect({ access_token }) {
|
|
7881
|
+
const WS_URL = "ws://localhost:3003/ws";
|
|
7882
|
+
await this.updateSyncNodes();
|
|
7883
|
+
console.log("Starting connection...");
|
|
7884
|
+
return this.syncable.connect("websocket", WS_URL, { authToken: access_token });
|
|
7885
|
+
}
|
|
7886
|
+
async updateSyncNodes() {
|
|
7887
|
+
try {
|
|
7888
|
+
const syncNodes = await this.table("_syncNodes").toArray();
|
|
7889
|
+
const localSyncNodes = syncNodes.filter((node) => node.type === "local");
|
|
7890
|
+
console.log("Local sync nodes:", localSyncNodes);
|
|
7891
|
+
if (localSyncNodes.length > 1) {
|
|
7892
|
+
const largestNodeId = Math.max(...localSyncNodes.map((node) => node.id));
|
|
7893
|
+
const largestNode = localSyncNodes.find((node) => node.id === largestNodeId);
|
|
7894
|
+
if (largestNode && largestNode.isMaster === 1) {
|
|
7895
|
+
console.log("Largest node is already the master. No changes needed.");
|
|
7896
|
+
return;
|
|
7897
|
+
}
|
|
7898
|
+
console.log("Largest node id:", largestNodeId);
|
|
7899
|
+
console.error("HEISENBUG: More than one local sync node found.");
|
|
7900
|
+
for (const node of localSyncNodes) {
|
|
7901
|
+
console.log(`Local sync node keys:`, node.id, node.isMaster);
|
|
7902
|
+
await this.table("_syncNodes").update(node.id, { isMaster: node.id === largestNodeId ? 1 : 0 });
|
|
7903
|
+
console.log(`HEISENBUG: Setting ${node.id} to ${node.id === largestNodeId ? "master" : "0"}`);
|
|
7904
|
+
}
|
|
7905
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
7906
|
+
}
|
|
7907
|
+
console.log("Sync nodes updated");
|
|
7908
|
+
} catch (error) {
|
|
7909
|
+
console.error("Error updating _syncNodes table:", error);
|
|
7910
|
+
}
|
|
7911
|
+
}
|
|
7912
|
+
handleStatusChange(fn) {
|
|
7913
|
+
this.syncable.on("statusChanged", fn);
|
|
7914
|
+
}
|
|
7915
|
+
_convertSchemaToDxSchema(schema) {
|
|
7916
|
+
const stores = Object.entries(schema.tables).map(([key, table]) => {
|
|
7917
|
+
const indexedFields = Object.entries(table.fields).filter(([key2, field]) => field.indexed).map(([key2, field]) => `,${key2}`).join("");
|
|
7918
|
+
return {
|
|
7919
|
+
[key]: "id" + indexedFields
|
|
7920
|
+
};
|
|
7921
|
+
});
|
|
7922
|
+
return Object.assign({}, ...stores);
|
|
7923
|
+
}
|
|
7924
|
+
debugeroo() {
|
|
7925
|
+
return this.syncable;
|
|
7926
|
+
}
|
|
7927
|
+
collection(name) {
|
|
7928
|
+
return {
|
|
7929
|
+
/**
|
|
7930
|
+
* Returns the underlying Dexie table
|
|
7931
|
+
* @type {Dexie.Table}
|
|
7932
|
+
*/
|
|
7933
|
+
ref: this.table(name),
|
|
7934
|
+
// --- WRITE ---- //
|
|
7935
|
+
add: (data) => {
|
|
7936
|
+
console.log("Adding data to", name, data);
|
|
7937
|
+
return this.table(name).add({
|
|
7938
|
+
id: v7_default(),
|
|
7939
|
+
...data
|
|
7940
|
+
});
|
|
7941
|
+
},
|
|
7942
|
+
put: (data) => {
|
|
7943
|
+
return this.table(name).put({
|
|
7944
|
+
id: v7_default(),
|
|
7945
|
+
...data
|
|
7946
|
+
});
|
|
7947
|
+
},
|
|
7948
|
+
update: (id, data) => {
|
|
7949
|
+
return this.table(name).update(id, data);
|
|
7950
|
+
},
|
|
7951
|
+
delete: (id) => {
|
|
7952
|
+
return this.table(name).delete(id);
|
|
7953
|
+
},
|
|
7954
|
+
// --- READ ---- //
|
|
7955
|
+
get: (id) => {
|
|
7956
|
+
return this.table(name).get(id);
|
|
7957
|
+
},
|
|
7958
|
+
getAll: () => {
|
|
7959
|
+
return this.table(name).toArray();
|
|
7960
|
+
},
|
|
7961
|
+
// --- QUERY ---- //
|
|
7962
|
+
// TODO: lots to do here. simplifing creating querie, filtering/ordering/limit, and execute
|
|
7963
|
+
query: () => this.table(name),
|
|
7964
|
+
filter: (fn) => this.table(name).filter(fn).toArray()
|
|
7965
|
+
};
|
|
7966
|
+
}
|
|
7967
|
+
};
|
|
5946
7968
|
|
|
5947
7969
|
// src/db.ts
|
|
5948
7970
|
var baseUrl = "https://api.basic.tech";
|
|
@@ -5955,7 +7977,7 @@ async function get({ projectId, accountId, tableName, token }) {
|
|
|
5955
7977
|
});
|
|
5956
7978
|
return response.json();
|
|
5957
7979
|
}
|
|
5958
|
-
async function
|
|
7980
|
+
async function add2({ projectId, accountId, tableName, value, token }) {
|
|
5959
7981
|
const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;
|
|
5960
7982
|
const response = await fetch(url, {
|
|
5961
7983
|
method: "POST",
|
|
@@ -6196,7 +8218,7 @@ function BasicProvider({ children, project_id, schema }) {
|
|
|
6196
8218
|
add: async (value) => {
|
|
6197
8219
|
checkSignIn();
|
|
6198
8220
|
const tok = await getToken();
|
|
6199
|
-
return
|
|
8221
|
+
return add2({ projectId: project_id, accountId: user.id, tableName, value, token: tok });
|
|
6200
8222
|
},
|
|
6201
8223
|
update: async (id, value) => {
|
|
6202
8224
|
checkSignIn();
|
|
@@ -6227,27 +8249,6 @@ function useBasic() {
|
|
|
6227
8249
|
return useContext(BasicContext);
|
|
6228
8250
|
}
|
|
6229
8251
|
|
|
6230
|
-
// ../../node_modules/dexie/import-wrapper.mjs
|
|
6231
|
-
var import_dexie = __toESM(require_dexie(), 1);
|
|
6232
|
-
var DexieSymbol = Symbol.for("Dexie");
|
|
6233
|
-
var Dexie = globalThis[DexieSymbol] || (globalThis[DexieSymbol] = import_dexie.default);
|
|
6234
|
-
if (import_dexie.default.semVer !== Dexie.semVer) {
|
|
6235
|
-
throw new Error(`Two different versions of Dexie loaded in the same app: ${import_dexie.default.semVer} and ${Dexie.semVer}`);
|
|
6236
|
-
}
|
|
6237
|
-
var {
|
|
6238
|
-
liveQuery,
|
|
6239
|
-
mergeRanges,
|
|
6240
|
-
rangesOverlap,
|
|
6241
|
-
RangeSet,
|
|
6242
|
-
cmp,
|
|
6243
|
-
Entity,
|
|
6244
|
-
PropModSymbol,
|
|
6245
|
-
PropModification,
|
|
6246
|
-
replacePrefix,
|
|
6247
|
-
add: add2,
|
|
6248
|
-
remove
|
|
6249
|
-
} = Dexie;
|
|
6250
|
-
|
|
6251
8252
|
// ../../node_modules/dexie-react-hooks/dist/dexie-react-hooks.mjs
|
|
6252
8253
|
import React2 from "react";
|
|
6253
8254
|
function useObservable(observableFactory, arg2, arg3) {
|