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