@instantdb/core 0.22.57 → 0.22.58
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/__tests__/src/Reactor.test.js +97 -21
- package/__tests__/src/utils/PersistedObject.test.ts +383 -0
- package/dist/commonjs/InMemoryStorage.d.ts +11 -0
- package/dist/commonjs/InMemoryStorage.d.ts.map +1 -0
- package/dist/commonjs/InMemoryStorage.js +48 -0
- package/dist/commonjs/InMemoryStorage.js.map +1 -0
- package/dist/commonjs/IndexedDBStorage.d.ts +10 -3
- package/dist/commonjs/IndexedDBStorage.d.ts.map +1 -1
- package/dist/commonjs/IndexedDBStorage.js +254 -8
- package/dist/commonjs/IndexedDBStorage.js.map +1 -1
- package/dist/commonjs/Reactor.d.ts +7 -16
- package/dist/commonjs/Reactor.d.ts.map +1 -1
- package/dist/commonjs/Reactor.js +199 -149
- package/dist/commonjs/Reactor.js.map +1 -1
- package/dist/commonjs/SyncTable.d.ts +3 -1
- package/dist/commonjs/SyncTable.d.ts.map +1 -1
- package/dist/commonjs/SyncTable.js +194 -168
- package/dist/commonjs/SyncTable.js.map +1 -1
- package/dist/commonjs/index.d.ts +2 -1
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +3 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/utils/PersistedObject.d.ts +73 -29
- package/dist/commonjs/utils/PersistedObject.d.ts.map +1 -1
- package/dist/commonjs/utils/PersistedObject.js +366 -77
- package/dist/commonjs/utils/PersistedObject.js.map +1 -1
- package/dist/esm/InMemoryStorage.d.ts +11 -0
- package/dist/esm/InMemoryStorage.d.ts.map +1 -0
- package/dist/esm/InMemoryStorage.js +45 -0
- package/dist/esm/InMemoryStorage.js.map +1 -0
- package/dist/esm/IndexedDBStorage.d.ts +10 -3
- package/dist/esm/IndexedDBStorage.d.ts.map +1 -1
- package/dist/esm/IndexedDBStorage.js +254 -8
- package/dist/esm/IndexedDBStorage.js.map +1 -1
- package/dist/esm/Reactor.d.ts +7 -16
- package/dist/esm/Reactor.d.ts.map +1 -1
- package/dist/esm/Reactor.js +199 -149
- package/dist/esm/Reactor.js.map +1 -1
- package/dist/esm/SyncTable.d.ts +3 -1
- package/dist/esm/SyncTable.d.ts.map +1 -1
- package/dist/esm/SyncTable.js +194 -168
- package/dist/esm/SyncTable.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/PersistedObject.d.ts +73 -29
- package/dist/esm/utils/PersistedObject.d.ts.map +1 -1
- package/dist/esm/utils/PersistedObject.js +364 -76
- package/dist/esm/utils/PersistedObject.js.map +1 -1
- package/dist/standalone/index.js +1978 -1567
- package/dist/standalone/index.umd.cjs +3 -3
- package/package.json +2 -2
- package/src/InMemoryStorage.ts +34 -0
- package/src/IndexedDBStorage.ts +281 -9
- package/src/Reactor.js +212 -184
- package/src/SyncTable.ts +220 -191
- package/src/index.ts +8 -0
- package/src/utils/PersistedObject.ts +480 -109
- package/src/InMemoryStorage.js +0 -14
package/dist/esm/SyncTable.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Logger } from './Reactor.js';
|
|
2
2
|
import { InstaQLResponse, ValidQuery } from './queryTypes.ts';
|
|
3
3
|
import { EntitiesDef, IContainEntitiesAndLinks } from './schemaTypes.ts';
|
|
4
|
+
import { StorageInterface } from './index.ts';
|
|
4
5
|
type StartMsg = {
|
|
5
6
|
op: 'start-sync';
|
|
6
7
|
q: string;
|
|
@@ -8,6 +9,7 @@ type StartMsg = {
|
|
|
8
9
|
type EndMsg = {
|
|
9
10
|
op: 'remove-sync';
|
|
10
11
|
'subscription-id': string;
|
|
12
|
+
'keep-subscription': boolean;
|
|
11
13
|
};
|
|
12
14
|
type ResyncMsg = {
|
|
13
15
|
op: 'resync-table';
|
|
@@ -103,7 +105,7 @@ export declare class SyncTable {
|
|
|
103
105
|
private idToHash;
|
|
104
106
|
private log;
|
|
105
107
|
private createStore;
|
|
106
|
-
constructor(trySend: TrySend,
|
|
108
|
+
constructor(trySend: TrySend, storage: StorageInterface, config: Config, log: Logger, createStore: (triples: Triple[]) => any);
|
|
107
109
|
beforeUnload(): void;
|
|
108
110
|
subscribe(q: any, cb: SyncTableCallback<any, any, any>): (opts?: {
|
|
109
111
|
keepSubscription?: boolean | null | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SyncTable.d.ts","sourceRoot":"","sources":["../../src/SyncTable.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"SyncTable.d.ts","sourceRoot":"","sources":["../../src/SyncTable.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA2B9C,KAAK,QAAQ,GAAG;IACd,EAAE,EAAE,YAAY,CAAC;IACjB,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,KAAK,MAAM,GAAG;IACZ,EAAE,EAAE,aAAa,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,cAAc,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,KAAK,cAAc,GAAG;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AAE5C,KAAK,gBAAgB,GAAG;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;CAC9B,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAC5D,EAAE,CAAC;CACL,CAAC;AAEF,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;AAEvD,KAAK,MAAM,GAAG;IAAE,cAAc,EAAE,OAAO,CAAA;CAAE,CAAC;AAsL1C,oBAAY,iBAAiB;IAC3B,gBAAgB,qBAAqB;IACrC,mBAAmB,wBAAwB;IAC3C,eAAe,oBAAoB;IACnC,eAAe,oBAAoB;IACnC,KAAK,UAAU;CAChB;AAED,KAAK,aAAa,CAChB,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,IACtB,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,eAAe,CAC5D,MAAM,EACN,CAAC,EACD,QAAQ,CACT,CAAC,CAAC;AAEH,KAAK,WAAW,CACd,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,IACtB,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAEvE,KAAK,aAAa,CAAC,MAAM,IAAI;KAC1B,CAAC,IAAI,MAAM,MAAM,CAAC,CAAC,EAAE;QACpB,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;KACrB;CACF,CAAC;AAEF,MAAM,WAAW,iBAAiB,CAChC,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO;IAExB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,gBAAgB,CAC/B,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,CACxB,SAAQ,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC;IAC9C,IAAI,EAAE,iBAAiB,CAAC,gBAAgB,CAAC;IACzC,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,mBAAmB,CAClC,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,CACxB,SAAQ,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC;IAC9C,IAAI,EAAE,iBAAiB,CAAC,mBAAmB,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe,CAC9B,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,CACxB,SAAQ,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC;IAC9C,IAAI,EAAE,iBAAiB,CAAC,eAAe,CAAC;IACxC,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC5C,OAAO,EAAE;QACP,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC5C,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC5C,aAAa,EAAE,aAAa,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;KAChE,EAAE,CAAC;CACL;AAED,MAAM,WAAW,eAAe,CAC9B,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,CACxB,SAAQ,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC;IAC9C,IAAI,EAAE,iBAAiB,CAAC,eAAe,CAAC;CACzC;AAED,MAAM,WAAW,UAAU,CACzB,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,CACxB,SAAQ,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC;IAC9C,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC;IAC9B,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAED,MAAM,MAAM,aAAa,CACvB,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,IAEtB,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,GACrC,mBAAmB,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,GACxC,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,GACpC,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,GACpC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;AAEpC,MAAM,MAAM,iBAAiB,CAC3B,MAAM,SAAS,wBAAwB,CAAC,WAAW,EAAE,GAAG,CAAC,EACzD,CAAC,SAAS,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAC/B,QAAQ,SAAS,OAAO,IACtB,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC;AAExD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,IAAI,CAA6C;IAEzD,OAAO,CAAC,SAAS,CACZ;IACL,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAA4C;IAC5D,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,WAAW,CAA6B;gBAG9C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAG;IAuBlC,YAAY;IAIZ,SAAS,CACd,CAAC,EAAE,GAAG,EACN,EAAE,EAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GACnC,CACD,IAAI,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,KACxE,IAAI;IAYT,OAAO,CAAC,WAAW;IAsBnB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,UAAU;YAQJ,gBAAgB;IAqDjB,YAAY;IAYlB,aAAa,CAAC,GAAG,EAAE,cAAc;IA4BxC,OAAO,CAAC,SAAS;IAMV,eAAe,CAAC,GAAG,EAAE,gBAAgB;IAmDrC,gBAAgB,CAAC,GAAG,EAAE,iBAAiB;IAgCvC,mBAAmB,CAAC,GAAG,EAAE,oBAAoB;IA2HpD,OAAO,CAAC,qBAAqB;IAwBtB,gBAAgB,CAAC,GAAG,EAAE;QAC3B,EAAE,EAAE,OAAO,CAAC;QACZ,gBAAgB,EAAE,QAAQ,CAAC;QAC3B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,CAAC;KACZ;IAiBM,aAAa,CAAC,GAAG,EAAE;QACxB,EAAE,EAAE,OAAO,CAAC;QACZ,gBAAgB,EAAE,SAAS,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd;CAUF"}
|
package/dist/esm/SyncTable.js
CHANGED
|
@@ -13,44 +13,44 @@ import weakHash from "./utils/weakHash.js";
|
|
|
13
13
|
import uuid from "./utils/uuid.js";
|
|
14
14
|
import instaql, { compareOrder } from './instaql.js';
|
|
15
15
|
// Modifies the data in place because it comes directly from storage
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
for (const e of
|
|
16
|
+
function syncSubFromStorage(sub, useDateObjects) {
|
|
17
|
+
const values = sub.values;
|
|
18
|
+
if (values) {
|
|
19
|
+
for (const e of values.entities || []) {
|
|
20
20
|
e.store.useDateObjects = useDateObjects;
|
|
21
|
+
e.store.attrs = values.attrs;
|
|
21
22
|
e.store = s.fromJSON(e.store);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
|
-
return
|
|
25
|
+
return sub;
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
jsonSubs[key] = sub;
|
|
27
|
+
function syncSubToStorage(_k, sub) {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
if ((_a = sub.values) === null || _a === void 0 ? void 0 : _a.entities) {
|
|
30
|
+
const entities = [];
|
|
31
|
+
for (const e of (_b = sub.values) === null || _b === void 0 ? void 0 : _b.entities) {
|
|
32
|
+
const store = s.toJSON(e.store);
|
|
33
|
+
// We'll store the attrs once on values, and put the
|
|
34
|
+
// attrs back into the store on hydration
|
|
35
|
+
delete store['attrs'];
|
|
36
|
+
entities.push(Object.assign(Object.assign({}, e), { store }));
|
|
39
37
|
}
|
|
38
|
+
return Object.assign(Object.assign({}, sub), { values: Object.assign(Object.assign({}, sub.values), { entities }) });
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return sub;
|
|
40
42
|
}
|
|
41
|
-
return jsonSubs;
|
|
42
43
|
}
|
|
43
|
-
function
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
function onMergeSub(_key, storageSub, inMemorySub) {
|
|
45
|
+
const storageTxId = storageSub === null || storageSub === void 0 ? void 0 : storageSub.state.txId;
|
|
46
|
+
const memoryTxId = inMemorySub === null || inMemorySub === void 0 ? void 0 : inMemorySub.state.txId;
|
|
47
|
+
if (storageTxId && (!memoryTxId || storageTxId > memoryTxId)) {
|
|
48
|
+
return storageSub;
|
|
47
49
|
}
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
subs[k] = v;
|
|
51
|
-
}
|
|
50
|
+
if (memoryTxId && (!storageTxId || memoryTxId > storageTxId)) {
|
|
51
|
+
return inMemorySub;
|
|
52
52
|
}
|
|
53
|
-
return
|
|
53
|
+
return storageSub || inMemorySub;
|
|
54
54
|
}
|
|
55
55
|
function queryEntity(sub, store) {
|
|
56
56
|
const res = instaql({ store, pageInfo: null, aggregate: null }, sub.query);
|
|
@@ -141,7 +141,7 @@ export var CallbackEventType;
|
|
|
141
141
|
CallbackEventType["Error"] = "Error";
|
|
142
142
|
})(CallbackEventType || (CallbackEventType = {}));
|
|
143
143
|
export class SyncTable {
|
|
144
|
-
constructor(trySend,
|
|
144
|
+
constructor(trySend, storage, config, log, createStore) {
|
|
145
145
|
// Using any for the SyncCallback because we'd need Reactor to be typed
|
|
146
146
|
this.callbacks = {};
|
|
147
147
|
this.idToHash = {};
|
|
@@ -149,7 +149,20 @@ export class SyncTable {
|
|
|
149
149
|
this.config = config;
|
|
150
150
|
this.log = log;
|
|
151
151
|
this.createStore = createStore;
|
|
152
|
-
this.subs = new PersistedObject(
|
|
152
|
+
this.subs = new PersistedObject({
|
|
153
|
+
persister: storage,
|
|
154
|
+
merge: onMergeSub,
|
|
155
|
+
serialize: syncSubToStorage,
|
|
156
|
+
parse: (_key, x) => syncSubFromStorage(x, this.config.useDateObjects),
|
|
157
|
+
objectSize: (sub) => { var _a; return ((_a = sub.values) === null || _a === void 0 ? void 0 : _a.entities.length) || 0; },
|
|
158
|
+
logger: log,
|
|
159
|
+
gc: {
|
|
160
|
+
maxAgeMs: 1000 * 60 * 60 * 24 * 7 * 52, // 1 year
|
|
161
|
+
maxEntries: 1000,
|
|
162
|
+
// Size of each sub is the number of entity
|
|
163
|
+
maxSize: 1000000, // 1 million entities
|
|
164
|
+
},
|
|
165
|
+
});
|
|
153
166
|
}
|
|
154
167
|
beforeUnload() {
|
|
155
168
|
this.subs.flush();
|
|
@@ -168,17 +181,15 @@ export class SyncTable {
|
|
|
168
181
|
this.callbacks[hash] = cbs;
|
|
169
182
|
if (!cbs.length) {
|
|
170
183
|
delete this.callbacks[hash];
|
|
171
|
-
if (keepSubscription) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
184
|
const sub = this.subs.currentValue[hash];
|
|
175
185
|
if (sub === null || sub === void 0 ? void 0 : sub.state) {
|
|
176
|
-
this.clearSubscriptionData(sub.state.subscriptionId);
|
|
186
|
+
this.clearSubscriptionData(sub.state.subscriptionId, keepSubscription);
|
|
187
|
+
}
|
|
188
|
+
if (!keepSubscription) {
|
|
189
|
+
this.subs.updateInPlace((prev) => {
|
|
190
|
+
delete prev[hash];
|
|
191
|
+
});
|
|
177
192
|
}
|
|
178
|
-
this.subs.set((prev) => {
|
|
179
|
-
delete prev[hash];
|
|
180
|
-
return prev;
|
|
181
|
-
});
|
|
182
193
|
}
|
|
183
194
|
}
|
|
184
195
|
sendStart(query) {
|
|
@@ -197,36 +208,37 @@ export class SyncTable {
|
|
|
197
208
|
token: state.token,
|
|
198
209
|
});
|
|
199
210
|
}
|
|
200
|
-
sendRemove(state) {
|
|
211
|
+
sendRemove(state, keepSubscription) {
|
|
201
212
|
this.trySend(uuid(), {
|
|
202
213
|
op: 'remove-sync',
|
|
203
214
|
'subscription-id': state.subscriptionId,
|
|
215
|
+
'keep-subscription': keepSubscription,
|
|
204
216
|
});
|
|
205
217
|
}
|
|
206
218
|
initSubscription(query, hash, cb) {
|
|
207
219
|
return __awaiter(this, void 0, void 0, function* () {
|
|
208
|
-
var _a, _b, _c;
|
|
220
|
+
var _a, _b, _c, _d, _e;
|
|
209
221
|
// Wait for storage to load so that we know if we already have an existing subscription
|
|
210
|
-
yield this.subs.
|
|
222
|
+
yield this.subs.waitForKeyToLoad(hash);
|
|
211
223
|
const existingSub = this.subs.currentValue[hash];
|
|
212
224
|
if (existingSub && existingSub.state && existingSub.state.txId) {
|
|
213
225
|
this.sendResync(existingSub, existingSub.state);
|
|
214
|
-
if (existingSub.entities && cb) {
|
|
226
|
+
if (((_a = existingSub.values) === null || _a === void 0 ? void 0 : _a.entities) && cb) {
|
|
215
227
|
const k = Object.keys(query)[0];
|
|
216
228
|
cb({
|
|
217
229
|
type: CallbackEventType.LoadFromStorage,
|
|
218
|
-
data: subData(existingSub, existingSub.entities),
|
|
230
|
+
data: subData(existingSub, (_b = existingSub.values) === null || _b === void 0 ? void 0 : _b.entities),
|
|
219
231
|
});
|
|
220
232
|
}
|
|
221
233
|
return;
|
|
222
234
|
}
|
|
223
235
|
const table = Object.keys(query)[0];
|
|
224
|
-
const orderBy = ((
|
|
236
|
+
const orderBy = ((_d = (_c = query[table]) === null || _c === void 0 ? void 0 : _c.$) === null || _d === void 0 ? void 0 : _d.order) || { serverCreatedAt: 'asc' };
|
|
225
237
|
const [orderField, orderDirection] = Object.entries(orderBy)[0];
|
|
226
238
|
const orderFieldType = orderField === 'serverCreatedAt'
|
|
227
239
|
? 'number'
|
|
228
|
-
: (
|
|
229
|
-
this.subs.
|
|
240
|
+
: (_e = s.getAttrByFwdIdentName(this.createStore([]), table, orderField)) === null || _e === void 0 ? void 0 : _e['checked-data-type'];
|
|
241
|
+
this.subs.updateInPlace((prev) => {
|
|
230
242
|
prev[hash] = {
|
|
231
243
|
query,
|
|
232
244
|
hash: hash,
|
|
@@ -237,15 +249,14 @@ export class SyncTable {
|
|
|
237
249
|
createdAt: Date.now(),
|
|
238
250
|
updatedAt: Date.now(),
|
|
239
251
|
};
|
|
240
|
-
return prev;
|
|
241
252
|
});
|
|
242
253
|
this.sendStart(query);
|
|
243
254
|
});
|
|
244
255
|
}
|
|
245
256
|
flushPending() {
|
|
246
257
|
return __awaiter(this, void 0, void 0, function* () {
|
|
247
|
-
yield this.subs.waitForLoaded();
|
|
248
258
|
for (const hash of Object.keys(this.callbacks)) {
|
|
259
|
+
yield this.subs.waitForKeyToLoad(hash);
|
|
249
260
|
const sub = this.subs.currentValue[hash];
|
|
250
261
|
if (sub) {
|
|
251
262
|
yield this.initSubscription(sub.query, sub.hash);
|
|
@@ -261,7 +272,7 @@ export class SyncTable {
|
|
|
261
272
|
const q = msg.q;
|
|
262
273
|
const hash = weakHash(q);
|
|
263
274
|
this.idToHash[subscriptionId] = hash;
|
|
264
|
-
this.subs.
|
|
275
|
+
this.subs.updateInPlace((prev) => {
|
|
265
276
|
const sub = prev[hash];
|
|
266
277
|
if (!sub) {
|
|
267
278
|
this.log.error('Missing sub for hash', hash, 'subscription-id', subscriptionId, 'query', q);
|
|
@@ -271,7 +282,6 @@ export class SyncTable {
|
|
|
271
282
|
subscriptionId: subscriptionId,
|
|
272
283
|
token: msg.token,
|
|
273
284
|
};
|
|
274
|
-
return prev;
|
|
275
285
|
});
|
|
276
286
|
}
|
|
277
287
|
notifyCbs(hash, event) {
|
|
@@ -280,6 +290,7 @@ export class SyncTable {
|
|
|
280
290
|
}
|
|
281
291
|
}
|
|
282
292
|
onSyncLoadBatch(msg) {
|
|
293
|
+
var _a;
|
|
283
294
|
const subscriptionId = msg['subscription-id'];
|
|
284
295
|
const joinRows = msg['join-rows'];
|
|
285
296
|
const hash = this.idToHash[subscriptionId];
|
|
@@ -288,49 +299,55 @@ export class SyncTable {
|
|
|
288
299
|
return;
|
|
289
300
|
}
|
|
290
301
|
const batch = [];
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
302
|
+
const sub = this.subs.currentValue[hash];
|
|
303
|
+
if (!sub) {
|
|
304
|
+
this.log.error('Missing sub for hash', hash, msg);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const values = (_a = sub.values) !== null && _a !== void 0 ? _a : {
|
|
308
|
+
entities: [],
|
|
309
|
+
attrs: this.createStore([]).attrs,
|
|
310
|
+
};
|
|
311
|
+
sub.values = values;
|
|
312
|
+
const entities = values.entities;
|
|
313
|
+
for (const entRows of joinRows) {
|
|
314
|
+
const store = this.createStore(entRows);
|
|
315
|
+
values.attrs = store.attrs;
|
|
316
|
+
const entity = queryEntity(sub, store);
|
|
317
|
+
entities.push({
|
|
318
|
+
store,
|
|
319
|
+
entity,
|
|
320
|
+
serverCreatedAt: getServerCreatedAt(sub, store, entity.id),
|
|
321
|
+
});
|
|
322
|
+
batch.push(entity);
|
|
323
|
+
}
|
|
324
|
+
this.subs.updateInPlace((prev) => {
|
|
325
|
+
prev[hash] = sub;
|
|
326
|
+
// Make sure we write a field or mutative won't
|
|
327
|
+
// see the change because sub === prev[hash]
|
|
328
|
+
prev[hash].updatedAt = Date.now();
|
|
312
329
|
});
|
|
313
|
-
|
|
314
|
-
if (sub.entities) {
|
|
330
|
+
if (sub.values) {
|
|
315
331
|
this.notifyCbs(hash, {
|
|
316
332
|
type: CallbackEventType.InitialSyncBatch,
|
|
317
|
-
data: subData(sub, sub.entities),
|
|
333
|
+
data: subData(sub, sub.values.entities),
|
|
318
334
|
batch,
|
|
319
335
|
});
|
|
320
336
|
}
|
|
321
337
|
}
|
|
322
338
|
onSyncInitFinish(msg) {
|
|
339
|
+
var _a;
|
|
323
340
|
const subscriptionId = msg['subscription-id'];
|
|
324
341
|
const hash = this.idToHash[subscriptionId];
|
|
325
342
|
if (!hash) {
|
|
326
343
|
this.log.error('Missing hash for subscription', msg);
|
|
327
344
|
return;
|
|
328
345
|
}
|
|
329
|
-
this.subs.
|
|
346
|
+
this.subs.updateInPlace((prev) => {
|
|
330
347
|
const sub = prev[hash];
|
|
331
348
|
if (!sub) {
|
|
332
349
|
this.log.error('Missing sub for hash', hash, msg);
|
|
333
|
-
return
|
|
350
|
+
return;
|
|
334
351
|
}
|
|
335
352
|
const state = sub.state;
|
|
336
353
|
if (!state) {
|
|
@@ -339,131 +356,140 @@ export class SyncTable {
|
|
|
339
356
|
}
|
|
340
357
|
state.txId = msg['tx-id'];
|
|
341
358
|
sub.updatedAt = Date.now();
|
|
342
|
-
return prev;
|
|
343
359
|
});
|
|
344
360
|
const sub = this.subs.currentValue[hash];
|
|
345
361
|
if (sub) {
|
|
346
362
|
this.notifyCbs(hash, {
|
|
347
363
|
type: CallbackEventType.InitialSyncComplete,
|
|
348
|
-
data: subData(sub, sub.entities || []),
|
|
364
|
+
data: subData(sub, ((_a = sub.values) === null || _a === void 0 ? void 0 : _a.entities) || []),
|
|
349
365
|
});
|
|
350
366
|
}
|
|
351
367
|
}
|
|
352
368
|
onSyncUpdateTriples(msg) {
|
|
369
|
+
var _a, _b, _c;
|
|
353
370
|
const subscriptionId = msg['subscription-id'];
|
|
354
371
|
const hash = this.idToHash[subscriptionId];
|
|
355
372
|
if (!hash) {
|
|
356
373
|
this.log.error('Missing hash for subscription', msg);
|
|
357
374
|
return;
|
|
358
375
|
}
|
|
359
|
-
this.subs.
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
376
|
+
const sub = this.subs.currentValue[hash];
|
|
377
|
+
if (!sub) {
|
|
378
|
+
this.log.error('Missing sub for hash', hash, msg);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const state = sub.state;
|
|
382
|
+
if (!state) {
|
|
383
|
+
this.log.error('Missing state for sub', sub, msg);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
for (const tx of msg.txes) {
|
|
387
|
+
if (state.txId >= tx['tx-id']) {
|
|
388
|
+
continue;
|
|
365
389
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
390
|
+
state.txId = tx['tx-id'];
|
|
391
|
+
const idxesToDelete = [];
|
|
392
|
+
// Note: this won't work as well when links are involved
|
|
393
|
+
const byEid = {};
|
|
394
|
+
for (const change of tx.changes) {
|
|
395
|
+
const eidChanges = (_a = byEid[change.triple[0]]) !== null && _a !== void 0 ? _a : [];
|
|
396
|
+
byEid[change.triple[0]] = eidChanges;
|
|
397
|
+
eidChanges.push(change);
|
|
370
398
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
eidLoop: for (const [eid, changes] of Object.entries(byEid)) {
|
|
389
|
-
for (const [entIdx, ent] of Object.entries(entities)) {
|
|
390
|
-
if (s.hasEntity(ent.store, eid)) {
|
|
391
|
-
applyChangesToStore(ent.store, changes);
|
|
392
|
-
const entity = queryEntity(sub, ent.store);
|
|
393
|
-
const changedFields = changedFieldsOfChanges(ent.store, changes)[eid];
|
|
394
|
-
for (const [k, { oldValue, newValue }] of Object.entries(changedFields || {})) {
|
|
395
|
-
if (oldValue === newValue) {
|
|
396
|
-
delete changedFields[k];
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
if (entity) {
|
|
400
|
-
updated.push({
|
|
401
|
-
oldEntity: ent.entity,
|
|
402
|
-
newEntity: entity,
|
|
403
|
-
changedFields: changedFields || {},
|
|
404
|
-
});
|
|
405
|
-
ent.entity = entity;
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
idxesToDelete.push(entIdx);
|
|
399
|
+
const values = (_b = sub.values) !== null && _b !== void 0 ? _b : {
|
|
400
|
+
entities: [],
|
|
401
|
+
attrs: this.createStore([]).attrs,
|
|
402
|
+
};
|
|
403
|
+
const entities = values.entities;
|
|
404
|
+
sub.values = values;
|
|
405
|
+
const updated = [];
|
|
406
|
+
// Update the existing stores, if we already know about this entity
|
|
407
|
+
eidLoop: for (const [eid, changes] of Object.entries(byEid)) {
|
|
408
|
+
for (const [entIdx, ent] of Object.entries(entities)) {
|
|
409
|
+
if (s.hasEntity(ent.store, eid)) {
|
|
410
|
+
applyChangesToStore(ent.store, changes);
|
|
411
|
+
const entity = queryEntity(sub, ent.store);
|
|
412
|
+
const changedFields = changedFieldsOfChanges(ent.store, changes)[eid];
|
|
413
|
+
for (const [k, { oldValue, newValue }] of Object.entries(changedFields || {})) {
|
|
414
|
+
if (oldValue === newValue) {
|
|
415
|
+
delete changedFields[k];
|
|
409
416
|
}
|
|
410
|
-
delete byEid[eid];
|
|
411
|
-
continue eidLoop;
|
|
412
417
|
}
|
|
418
|
+
if (entity) {
|
|
419
|
+
updated.push({
|
|
420
|
+
oldEntity: ent.entity,
|
|
421
|
+
newEntity: entity,
|
|
422
|
+
changedFields: changedFields || {},
|
|
423
|
+
});
|
|
424
|
+
ent.entity = entity;
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
idxesToDelete.push(entIdx);
|
|
428
|
+
}
|
|
429
|
+
delete byEid[eid];
|
|
430
|
+
continue eidLoop;
|
|
413
431
|
}
|
|
414
432
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
1;
|
|
428
|
-
continue;
|
|
429
|
-
}
|
|
430
|
-
entities.push({
|
|
433
|
+
}
|
|
434
|
+
const added = [];
|
|
435
|
+
// If we have anything left in byEid, then this must be a new entity we don't know about
|
|
436
|
+
for (const [_eid, changes] of Object.entries(byEid)) {
|
|
437
|
+
const store = this.createStore([]);
|
|
438
|
+
values.attrs = store.attrs;
|
|
439
|
+
applyChangesToStore(store, changes);
|
|
440
|
+
const entity = queryEntity(sub, store);
|
|
441
|
+
if (!entity) {
|
|
442
|
+
this.log.error('No entity found after applying change', {
|
|
443
|
+
sub,
|
|
444
|
+
changes,
|
|
431
445
|
store,
|
|
432
|
-
entity,
|
|
433
|
-
serverCreatedAt: getServerCreatedAt(sub, store, entity.id),
|
|
434
446
|
});
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
const removed = [];
|
|
438
|
-
for (const idx of idxesToDelete.sort().reverse()) {
|
|
439
|
-
removed.push(entities[idx].entity);
|
|
440
|
-
entities.splice(idx, 1);
|
|
447
|
+
continue;
|
|
441
448
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
added,
|
|
447
|
-
removed,
|
|
448
|
-
updated,
|
|
449
|
+
entities.push({
|
|
450
|
+
store,
|
|
451
|
+
entity,
|
|
452
|
+
serverCreatedAt: getServerCreatedAt(sub, store, entity.id),
|
|
449
453
|
});
|
|
450
|
-
|
|
454
|
+
added.push(entity);
|
|
455
|
+
}
|
|
456
|
+
const removed = [];
|
|
457
|
+
for (const idx of idxesToDelete.sort().reverse()) {
|
|
458
|
+
removed.push(entities[idx].entity);
|
|
459
|
+
entities.splice(idx, 1);
|
|
451
460
|
}
|
|
452
|
-
|
|
461
|
+
sortEntitiesInPlace(sub, entities);
|
|
462
|
+
this.notifyCbs(hash, {
|
|
463
|
+
type: CallbackEventType.SyncTransaction,
|
|
464
|
+
data: subData(sub, (_c = sub.values) === null || _c === void 0 ? void 0 : _c.entities),
|
|
465
|
+
added,
|
|
466
|
+
removed,
|
|
467
|
+
updated,
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
this.subs.updateInPlace((prev) => {
|
|
471
|
+
prev[hash] = sub;
|
|
472
|
+
// Make sure we write a field or mutative won't
|
|
473
|
+
// see the change because sub === prev[hash]
|
|
474
|
+
prev[hash].updatedAt = Date.now();
|
|
453
475
|
});
|
|
454
476
|
}
|
|
455
|
-
clearSubscriptionData(subscriptionId) {
|
|
477
|
+
clearSubscriptionData(subscriptionId, keepSubscription) {
|
|
456
478
|
const hash = this.idToHash[subscriptionId];
|
|
457
479
|
if (hash) {
|
|
458
480
|
delete this.idToHash[subscriptionId];
|
|
459
481
|
const sub = this.subs.currentValue[hash];
|
|
460
482
|
if (sub.state) {
|
|
461
|
-
this.sendRemove(sub.state);
|
|
483
|
+
this.sendRemove(sub.state, keepSubscription);
|
|
484
|
+
}
|
|
485
|
+
if (keepSubscription) {
|
|
486
|
+
this.subs.unloadKey(hash);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
this.subs.updateInPlace((prev) => {
|
|
490
|
+
delete prev[hash];
|
|
491
|
+
});
|
|
462
492
|
}
|
|
463
|
-
this.subs.set((prev) => {
|
|
464
|
-
delete prev[hash];
|
|
465
|
-
return prev;
|
|
466
|
-
});
|
|
467
493
|
if (sub) {
|
|
468
494
|
return sub;
|
|
469
495
|
}
|
|
@@ -489,7 +515,7 @@ export class SyncTable {
|
|
|
489
515
|
// This can happen if the auth changed and we need to refetch with the
|
|
490
516
|
// new auth or if the subscription is too far behind.
|
|
491
517
|
const subscriptionId = msg['original-event']['subscription-id'];
|
|
492
|
-
const removedSub = this.clearSubscriptionData(subscriptionId);
|
|
518
|
+
const removedSub = this.clearSubscriptionData(subscriptionId, false);
|
|
493
519
|
if (removedSub) {
|
|
494
520
|
this.initSubscription(removedSub.query, removedSub.hash);
|
|
495
521
|
}
|