tinybase 4.0.0-beta.1 → 4.0.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/bin/cli.js +1 -1
- package/lib/checkpoints.js +1 -1
- package/lib/checkpoints.js.gz +0 -0
- package/lib/cjs/checkpoints.cjs +1 -1
- package/lib/cjs/checkpoints.cjs.gz +0 -0
- package/lib/cjs/indexes.cjs +1 -1
- package/lib/cjs/indexes.cjs.gz +0 -0
- package/lib/cjs/metrics.cjs +1 -1
- package/lib/cjs/metrics.cjs.gz +0 -0
- package/lib/cjs/persister-browser.cjs +1 -1
- package/lib/cjs/persister-browser.cjs.gz +0 -0
- package/lib/cjs/persister-file.cjs +1 -1
- package/lib/cjs/persister-file.cjs.gz +0 -0
- package/lib/cjs/persister-remote.cjs +1 -1
- package/lib/cjs/persister-remote.cjs.gz +0 -0
- package/lib/cjs/persister-yjs.cjs +1 -1
- package/lib/cjs/persister-yjs.cjs.gz +0 -0
- package/lib/cjs/persisters.cjs +1 -1
- package/lib/cjs/persisters.cjs.gz +0 -0
- package/lib/cjs/queries.cjs +1 -1
- package/lib/cjs/queries.cjs.gz +0 -0
- package/lib/cjs/relationships.cjs +1 -1
- package/lib/cjs/relationships.cjs.gz +0 -0
- package/lib/cjs/store.cjs +1 -1
- package/lib/cjs/store.cjs.gz +0 -0
- package/lib/cjs/tinybase.cjs +1 -1
- package/lib/cjs/tinybase.cjs.gz +0 -0
- package/lib/cjs/tools.cjs +1 -1
- package/lib/cjs/tools.cjs.gz +0 -0
- package/lib/cjs/ui-react.cjs +1 -1
- package/lib/cjs/ui-react.cjs.gz +0 -0
- package/lib/cjs-es6/checkpoints.cjs +1 -1
- package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
- package/lib/cjs-es6/indexes.cjs +1 -1
- package/lib/cjs-es6/indexes.cjs.gz +0 -0
- package/lib/cjs-es6/metrics.cjs +1 -1
- package/lib/cjs-es6/metrics.cjs.gz +0 -0
- package/lib/cjs-es6/persister-browser.cjs +1 -1
- package/lib/cjs-es6/persister-browser.cjs.gz +0 -0
- package/lib/cjs-es6/persister-file.cjs +1 -1
- package/lib/cjs-es6/persister-file.cjs.gz +0 -0
- package/lib/cjs-es6/persister-remote.cjs +1 -1
- package/lib/cjs-es6/persister-remote.cjs.gz +0 -0
- package/lib/cjs-es6/persister-yjs.cjs +1 -1
- package/lib/cjs-es6/persister-yjs.cjs.gz +0 -0
- package/lib/cjs-es6/persisters.cjs +1 -1
- package/lib/cjs-es6/persisters.cjs.gz +0 -0
- package/lib/cjs-es6/queries.cjs +1 -1
- package/lib/cjs-es6/queries.cjs.gz +0 -0
- package/lib/cjs-es6/relationships.cjs +1 -1
- package/lib/cjs-es6/relationships.cjs.gz +0 -0
- package/lib/cjs-es6/store.cjs +1 -1
- package/lib/cjs-es6/store.cjs.gz +0 -0
- package/lib/cjs-es6/tinybase.cjs +1 -1
- package/lib/cjs-es6/tinybase.cjs.gz +0 -0
- package/lib/cjs-es6/tools.cjs +1 -1
- package/lib/cjs-es6/tools.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react.cjs +1 -1
- package/lib/cjs-es6/ui-react.cjs.gz +0 -0
- package/lib/debug/checkpoints.js +3 -3
- package/lib/debug/indexes.js +3 -3
- package/lib/debug/metrics.js +3 -3
- package/lib/debug/persister-browser.js +38 -39
- package/lib/debug/persister-file.js +37 -37
- package/lib/debug/persister-remote.js +37 -34
- package/lib/debug/persister-yjs.js +225 -40
- package/lib/debug/persisters.js +36 -33
- package/lib/debug/queries.js +5 -5
- package/lib/debug/relationships.js +3 -3
- package/lib/debug/store.js +129 -94
- package/lib/debug/tinybase.js +165 -125
- package/lib/debug/tools.js +9 -9
- package/lib/es6/checkpoints.js +1 -1
- package/lib/es6/checkpoints.js.gz +0 -0
- package/lib/es6/indexes.js +1 -1
- package/lib/es6/indexes.js.gz +0 -0
- package/lib/es6/metrics.js +1 -1
- package/lib/es6/metrics.js.gz +0 -0
- package/lib/es6/persister-browser.js +1 -1
- package/lib/es6/persister-browser.js.gz +0 -0
- package/lib/es6/persister-file.js +1 -1
- package/lib/es6/persister-file.js.gz +0 -0
- package/lib/es6/persister-remote.js +1 -1
- package/lib/es6/persister-remote.js.gz +0 -0
- package/lib/es6/persister-yjs.js +1 -1
- package/lib/es6/persister-yjs.js.gz +0 -0
- package/lib/es6/persisters.js +1 -1
- package/lib/es6/persisters.js.gz +0 -0
- package/lib/es6/queries.js +1 -1
- package/lib/es6/queries.js.gz +0 -0
- package/lib/es6/relationships.js +1 -1
- package/lib/es6/relationships.js.gz +0 -0
- package/lib/es6/store.js +1 -1
- package/lib/es6/store.js.gz +0 -0
- package/lib/es6/tinybase.js +1 -1
- package/lib/es6/tinybase.js.gz +0 -0
- package/lib/es6/tools.js +1 -1
- package/lib/es6/tools.js.gz +0 -0
- package/lib/es6/ui-react.js +1 -1
- package/lib/es6/ui-react.js.gz +0 -0
- package/lib/indexes.js +1 -1
- package/lib/indexes.js.gz +0 -0
- package/lib/metrics.js +1 -1
- package/lib/metrics.js.gz +0 -0
- package/lib/persister-browser.js +1 -1
- package/lib/persister-browser.js.gz +0 -0
- package/lib/persister-file.js +1 -1
- package/lib/persister-file.js.gz +0 -0
- package/lib/persister-remote.js +1 -1
- package/lib/persister-remote.js.gz +0 -0
- package/lib/persister-yjs.js +1 -1
- package/lib/persister-yjs.js.gz +0 -0
- package/lib/persisters.js +1 -1
- package/lib/persisters.js.gz +0 -0
- package/lib/queries.js +1 -1
- package/lib/queries.js.gz +0 -0
- package/lib/relationships.js +1 -1
- package/lib/relationships.js.gz +0 -0
- package/lib/store.js +1 -1
- package/lib/store.js.gz +0 -0
- package/lib/tinybase.js +1 -1
- package/lib/tinybase.js.gz +0 -0
- package/lib/tools.js +1 -1
- package/lib/tools.js.gz +0 -0
- package/lib/types/persister-yjs.d.ts +70 -8
- package/lib/types/persisters.d.ts +42 -17
- package/lib/types/queries.d.ts +52 -52
- package/lib/types/store.d.ts +399 -145
- package/lib/types/tools.d.ts +16 -16
- package/lib/types/ui-react.d.ts +56 -47
- package/lib/types/with-schemas/internal/ui-react.d.ts +2 -2
- package/lib/types/with-schemas/persister-yjs.d.ts +72 -9
- package/lib/types/with-schemas/persisters.d.ts +59 -18
- package/lib/types/with-schemas/queries.d.ts +52 -52
- package/lib/types/with-schemas/store.d.ts +480 -163
- package/lib/types/with-schemas/tools.d.ts +16 -16
- package/lib/types/with-schemas/ui-react.d.ts +54 -45
- package/lib/ui-react.js +1 -1
- package/lib/ui-react.js.gz +0 -0
- package/lib/umd/checkpoints.js +1 -1
- package/lib/umd/checkpoints.js.gz +0 -0
- package/lib/umd/indexes.js +1 -1
- package/lib/umd/indexes.js.gz +0 -0
- package/lib/umd/metrics.js +1 -1
- package/lib/umd/metrics.js.gz +0 -0
- package/lib/umd/persister-browser.js +1 -1
- package/lib/umd/persister-browser.js.gz +0 -0
- package/lib/umd/persister-file.js +1 -1
- package/lib/umd/persister-file.js.gz +0 -0
- package/lib/umd/persister-remote.js +1 -1
- package/lib/umd/persister-remote.js.gz +0 -0
- package/lib/umd/persister-yjs.js +1 -1
- package/lib/umd/persister-yjs.js.gz +0 -0
- package/lib/umd/persisters.js +1 -1
- package/lib/umd/persisters.js.gz +0 -0
- package/lib/umd/queries.js +1 -1
- package/lib/umd/queries.js.gz +0 -0
- package/lib/umd/relationships.js +1 -1
- package/lib/umd/relationships.js.gz +0 -0
- package/lib/umd/store.js +1 -1
- package/lib/umd/store.js.gz +0 -0
- package/lib/umd/tinybase.js +1 -1
- package/lib/umd/tinybase.js.gz +0 -0
- package/lib/umd/tools.js +1 -1
- package/lib/umd/tools.js.gz +0 -0
- package/lib/umd/ui-react.js +1 -1
- package/lib/umd/ui-react.js.gz +0 -0
- package/lib/umd-es6/checkpoints.js +1 -1
- package/lib/umd-es6/checkpoints.js.gz +0 -0
- package/lib/umd-es6/indexes.js +1 -1
- package/lib/umd-es6/indexes.js.gz +0 -0
- package/lib/umd-es6/metrics.js +1 -1
- package/lib/umd-es6/metrics.js.gz +0 -0
- package/lib/umd-es6/persister-browser.js +1 -1
- package/lib/umd-es6/persister-browser.js.gz +0 -0
- package/lib/umd-es6/persister-file.js +1 -1
- package/lib/umd-es6/persister-file.js.gz +0 -0
- package/lib/umd-es6/persister-remote.js +1 -1
- package/lib/umd-es6/persister-remote.js.gz +0 -0
- package/lib/umd-es6/persister-yjs.js +1 -1
- package/lib/umd-es6/persister-yjs.js.gz +0 -0
- package/lib/umd-es6/persisters.js +1 -1
- package/lib/umd-es6/persisters.js.gz +0 -0
- package/lib/umd-es6/queries.js +1 -1
- package/lib/umd-es6/queries.js.gz +0 -0
- package/lib/umd-es6/relationships.js +1 -1
- package/lib/umd-es6/relationships.js.gz +0 -0
- package/lib/umd-es6/store.js +1 -1
- package/lib/umd-es6/store.js.gz +0 -0
- package/lib/umd-es6/tinybase.js +1 -1
- package/lib/umd-es6/tinybase.js.gz +0 -0
- package/lib/umd-es6/tools.js +1 -1
- package/lib/umd-es6/tools.js.gz +0 -0
- package/lib/umd-es6/ui-react.js +1 -1
- package/lib/umd-es6/ui-react.js.gz +0 -0
- package/package.json +13 -13
- package/readme.md +2 -2
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {readFile, writeFile} from 'fs/promises';
|
|
2
2
|
import {watch} from 'fs';
|
|
3
3
|
|
|
4
|
-
const EMPTY_STRING = '';
|
|
5
4
|
const UTF8 = 'utf8';
|
|
6
5
|
|
|
7
6
|
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
@@ -40,43 +39,45 @@ const createCustomPersister = (
|
|
|
40
39
|
let saves = 0;
|
|
41
40
|
let listening = false;
|
|
42
41
|
let listeningHandle;
|
|
42
|
+
const loadLock = async (actions) => {
|
|
43
|
+
/* istanbul ignore else */
|
|
44
|
+
if (loadSave != 2) {
|
|
45
|
+
loadSave = 1;
|
|
46
|
+
{
|
|
47
|
+
loads++;
|
|
48
|
+
}
|
|
49
|
+
await actions();
|
|
50
|
+
loadSave = 0;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
43
53
|
const persister = {
|
|
44
54
|
load: async (initialTables, initialValues) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
53
|
-
store.setJson(body);
|
|
54
|
-
} else {
|
|
55
|
-
store.setContent([initialTables, initialValues]);
|
|
56
|
-
}
|
|
57
|
-
loadSave = 0;
|
|
58
|
-
}
|
|
55
|
+
await loadLock(async () => {
|
|
56
|
+
let content;
|
|
57
|
+
try {
|
|
58
|
+
content = await getPersisted();
|
|
59
|
+
} catch {}
|
|
60
|
+
store.setContent(content ?? [initialTables, initialValues]);
|
|
61
|
+
});
|
|
59
62
|
return persister;
|
|
60
63
|
},
|
|
61
64
|
startAutoLoad: async (initialTables, initialValues) => {
|
|
62
65
|
persister.stopAutoLoad();
|
|
63
66
|
await persister.load(initialTables, initialValues);
|
|
64
67
|
listening = true;
|
|
65
|
-
listeningHandle = addPersisterListener(
|
|
66
|
-
|
|
67
|
-
await
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
listeningHandle = addPersisterListener(
|
|
69
|
+
async (getContent, getTransactionChanges) => {
|
|
70
|
+
await loadLock(async () => {
|
|
71
|
+
if (getTransactionChanges) {
|
|
72
|
+
store.setTransactionChanges(getTransactionChanges());
|
|
73
|
+
} else {
|
|
74
|
+
try {
|
|
75
|
+
store.setContent(getContent?.() ?? (await getPersisted()));
|
|
76
|
+
} catch {}
|
|
74
77
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
});
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
);
|
|
80
81
|
return persister;
|
|
81
82
|
},
|
|
82
83
|
stopAutoLoad: () => {
|
|
@@ -87,21 +88,24 @@ const createCustomPersister = (
|
|
|
87
88
|
}
|
|
88
89
|
return persister;
|
|
89
90
|
},
|
|
90
|
-
save: async () => {
|
|
91
|
+
save: async (getTransactionChanges) => {
|
|
91
92
|
/* istanbul ignore else */
|
|
92
93
|
if (loadSave != 1) {
|
|
93
94
|
loadSave = 2;
|
|
94
95
|
{
|
|
95
96
|
saves++;
|
|
96
97
|
}
|
|
97
|
-
await setPersisted(store.getContent);
|
|
98
|
+
await setPersisted(store.getContent, getTransactionChanges);
|
|
98
99
|
loadSave = 0;
|
|
99
100
|
}
|
|
100
101
|
return persister;
|
|
101
102
|
},
|
|
102
103
|
startAutoSave: async () => {
|
|
103
104
|
await persister.stopAutoSave().save();
|
|
104
|
-
listenerId = store.addDidFinishTransactionListener(
|
|
105
|
+
listenerId = store.addDidFinishTransactionListener(
|
|
106
|
+
(_store, getTransactionChanges) =>
|
|
107
|
+
persister.save(getTransactionChanges),
|
|
108
|
+
);
|
|
105
109
|
return persister;
|
|
106
110
|
},
|
|
107
111
|
stopAutoSave: () => {
|
|
@@ -116,11 +120,7 @@ const createCustomPersister = (
|
|
|
116
120
|
};
|
|
117
121
|
|
|
118
122
|
const createFilePersister = (store, filePath) => {
|
|
119
|
-
const getPersisted = async () =>
|
|
120
|
-
try {
|
|
121
|
-
return await readFile(filePath, UTF8);
|
|
122
|
-
} catch {}
|
|
123
|
-
};
|
|
123
|
+
const getPersisted = async () => JSON.parse(await readFile(filePath, UTF8));
|
|
124
124
|
const setPersisted = async (getContent) => {
|
|
125
125
|
try {
|
|
126
126
|
await writeFile(filePath, jsonString(getContent()), UTF8);
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const EMPTY_STRING = '';
|
|
2
|
-
|
|
3
1
|
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
4
2
|
|
|
5
3
|
const jsonString = (obj) =>
|
|
@@ -36,43 +34,45 @@ const createCustomPersister = (
|
|
|
36
34
|
let saves = 0;
|
|
37
35
|
let listening = false;
|
|
38
36
|
let listeningHandle;
|
|
37
|
+
const loadLock = async (actions) => {
|
|
38
|
+
/* istanbul ignore else */
|
|
39
|
+
if (loadSave != 2) {
|
|
40
|
+
loadSave = 1;
|
|
41
|
+
{
|
|
42
|
+
loads++;
|
|
43
|
+
}
|
|
44
|
+
await actions();
|
|
45
|
+
loadSave = 0;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
39
48
|
const persister = {
|
|
40
49
|
load: async (initialTables, initialValues) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
49
|
-
store.setJson(body);
|
|
50
|
-
} else {
|
|
51
|
-
store.setContent([initialTables, initialValues]);
|
|
52
|
-
}
|
|
53
|
-
loadSave = 0;
|
|
54
|
-
}
|
|
50
|
+
await loadLock(async () => {
|
|
51
|
+
let content;
|
|
52
|
+
try {
|
|
53
|
+
content = await getPersisted();
|
|
54
|
+
} catch {}
|
|
55
|
+
store.setContent(content ?? [initialTables, initialValues]);
|
|
56
|
+
});
|
|
55
57
|
return persister;
|
|
56
58
|
},
|
|
57
59
|
startAutoLoad: async (initialTables, initialValues) => {
|
|
58
60
|
persister.stopAutoLoad();
|
|
59
61
|
await persister.load(initialTables, initialValues);
|
|
60
62
|
listening = true;
|
|
61
|
-
listeningHandle = addPersisterListener(
|
|
62
|
-
|
|
63
|
-
await
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
listeningHandle = addPersisterListener(
|
|
64
|
+
async (getContent, getTransactionChanges) => {
|
|
65
|
+
await loadLock(async () => {
|
|
66
|
+
if (getTransactionChanges) {
|
|
67
|
+
store.setTransactionChanges(getTransactionChanges());
|
|
68
|
+
} else {
|
|
69
|
+
try {
|
|
70
|
+
store.setContent(getContent?.() ?? (await getPersisted()));
|
|
71
|
+
} catch {}
|
|
70
72
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
});
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
76
|
return persister;
|
|
77
77
|
},
|
|
78
78
|
stopAutoLoad: () => {
|
|
@@ -83,21 +83,24 @@ const createCustomPersister = (
|
|
|
83
83
|
}
|
|
84
84
|
return persister;
|
|
85
85
|
},
|
|
86
|
-
save: async () => {
|
|
86
|
+
save: async (getTransactionChanges) => {
|
|
87
87
|
/* istanbul ignore else */
|
|
88
88
|
if (loadSave != 1) {
|
|
89
89
|
loadSave = 2;
|
|
90
90
|
{
|
|
91
91
|
saves++;
|
|
92
92
|
}
|
|
93
|
-
await setPersisted(store.getContent);
|
|
93
|
+
await setPersisted(store.getContent, getTransactionChanges);
|
|
94
94
|
loadSave = 0;
|
|
95
95
|
}
|
|
96
96
|
return persister;
|
|
97
97
|
},
|
|
98
98
|
startAutoSave: async () => {
|
|
99
99
|
await persister.stopAutoSave().save();
|
|
100
|
-
listenerId = store.addDidFinishTransactionListener(
|
|
100
|
+
listenerId = store.addDidFinishTransactionListener(
|
|
101
|
+
(_store, getTransactionChanges) =>
|
|
102
|
+
persister.save(getTransactionChanges),
|
|
103
|
+
);
|
|
101
104
|
return persister;
|
|
102
105
|
},
|
|
103
106
|
stopAutoSave: () => {
|
|
@@ -122,7 +125,7 @@ const createRemotePersister = (
|
|
|
122
125
|
const getPersisted = async () => {
|
|
123
126
|
const response = await fetch(loadUrl);
|
|
124
127
|
lastEtag = getETag(response);
|
|
125
|
-
return response.text();
|
|
128
|
+
return JSON.parse(await response.text());
|
|
126
129
|
};
|
|
127
130
|
const setPersisted = async (getContent) =>
|
|
128
131
|
await fetch(saveUrl, {
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import {Map} from 'yjs';
|
|
2
|
+
|
|
3
|
+
const arrayForEach = (array, cb) => array.forEach(cb);
|
|
4
|
+
const arrayMap = (array, cb) => array.map(cb);
|
|
5
|
+
const arrayLength = (array) => array.length;
|
|
6
|
+
const arrayIsEmpty = (array) => arrayLength(array) == 0;
|
|
7
|
+
const arrayShift = (array) => array.shift();
|
|
2
8
|
|
|
3
9
|
const isUndefined = (thing) => thing == void 0;
|
|
4
10
|
const ifNotUndefined = (value, then, otherwise) =>
|
|
@@ -6,6 +12,17 @@ const ifNotUndefined = (value, then, otherwise) =>
|
|
|
6
12
|
|
|
7
13
|
const object = Object;
|
|
8
14
|
const objFreeze = object.freeze;
|
|
15
|
+
const objNew = () => ({});
|
|
16
|
+
const objGet = (obj, id) => ifNotUndefined(obj, (obj2) => obj2[id]);
|
|
17
|
+
const objHas = (obj, id) => !isUndefined(objGet(obj, id));
|
|
18
|
+
const objMap = (obj, cb) =>
|
|
19
|
+
arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
|
|
20
|
+
const objEnsure = (obj, id, getDefaultValue) => {
|
|
21
|
+
if (!objHas(obj, id)) {
|
|
22
|
+
obj[id] = getDefaultValue();
|
|
23
|
+
}
|
|
24
|
+
return obj[id];
|
|
25
|
+
};
|
|
9
26
|
|
|
10
27
|
const createCustomPersister = (
|
|
11
28
|
store,
|
|
@@ -20,43 +37,45 @@ const createCustomPersister = (
|
|
|
20
37
|
let saves = 0;
|
|
21
38
|
let listening = false;
|
|
22
39
|
let listeningHandle;
|
|
40
|
+
const loadLock = async (actions) => {
|
|
41
|
+
/* istanbul ignore else */
|
|
42
|
+
if (loadSave != 2) {
|
|
43
|
+
loadSave = 1;
|
|
44
|
+
{
|
|
45
|
+
loads++;
|
|
46
|
+
}
|
|
47
|
+
await actions();
|
|
48
|
+
loadSave = 0;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
23
51
|
const persister = {
|
|
24
52
|
load: async (initialTables, initialValues) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
33
|
-
store.setJson(body);
|
|
34
|
-
} else {
|
|
35
|
-
store.setContent([initialTables, initialValues]);
|
|
36
|
-
}
|
|
37
|
-
loadSave = 0;
|
|
38
|
-
}
|
|
53
|
+
await loadLock(async () => {
|
|
54
|
+
let content;
|
|
55
|
+
try {
|
|
56
|
+
content = await getPersisted();
|
|
57
|
+
} catch {}
|
|
58
|
+
store.setContent(content ?? [initialTables, initialValues]);
|
|
59
|
+
});
|
|
39
60
|
return persister;
|
|
40
61
|
},
|
|
41
62
|
startAutoLoad: async (initialTables, initialValues) => {
|
|
42
63
|
persister.stopAutoLoad();
|
|
43
64
|
await persister.load(initialTables, initialValues);
|
|
44
65
|
listening = true;
|
|
45
|
-
listeningHandle = addPersisterListener(
|
|
46
|
-
|
|
47
|
-
await
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
66
|
+
listeningHandle = addPersisterListener(
|
|
67
|
+
async (getContent, getTransactionChanges) => {
|
|
68
|
+
await loadLock(async () => {
|
|
69
|
+
if (getTransactionChanges) {
|
|
70
|
+
store.setTransactionChanges(getTransactionChanges());
|
|
71
|
+
} else {
|
|
72
|
+
try {
|
|
73
|
+
store.setContent(getContent?.() ?? (await getPersisted()));
|
|
74
|
+
} catch {}
|
|
54
75
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
});
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
);
|
|
60
79
|
return persister;
|
|
61
80
|
},
|
|
62
81
|
stopAutoLoad: () => {
|
|
@@ -67,21 +86,24 @@ const createCustomPersister = (
|
|
|
67
86
|
}
|
|
68
87
|
return persister;
|
|
69
88
|
},
|
|
70
|
-
save: async () => {
|
|
89
|
+
save: async (getTransactionChanges) => {
|
|
71
90
|
/* istanbul ignore else */
|
|
72
91
|
if (loadSave != 1) {
|
|
73
92
|
loadSave = 2;
|
|
74
93
|
{
|
|
75
94
|
saves++;
|
|
76
95
|
}
|
|
77
|
-
await setPersisted(store.getContent);
|
|
96
|
+
await setPersisted(store.getContent, getTransactionChanges);
|
|
78
97
|
loadSave = 0;
|
|
79
98
|
}
|
|
80
99
|
return persister;
|
|
81
100
|
},
|
|
82
101
|
startAutoSave: async () => {
|
|
83
102
|
await persister.stopAutoSave().save();
|
|
84
|
-
listenerId = store.addDidFinishTransactionListener(
|
|
103
|
+
listenerId = store.addDidFinishTransactionListener(
|
|
104
|
+
(_store, getTransactionChanges) =>
|
|
105
|
+
persister.save(getTransactionChanges),
|
|
106
|
+
);
|
|
85
107
|
return persister;
|
|
86
108
|
},
|
|
87
109
|
stopAutoSave: () => {
|
|
@@ -95,18 +117,181 @@ const createCustomPersister = (
|
|
|
95
117
|
return objFreeze(persister);
|
|
96
118
|
};
|
|
97
119
|
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
120
|
+
const collForEach = (coll, cb) => coll?.forEach(cb);
|
|
121
|
+
|
|
122
|
+
const mapForEach = (map, cb) =>
|
|
123
|
+
collForEach(map, (value, key) => cb(key, value));
|
|
124
|
+
|
|
125
|
+
const tablesKey = 't';
|
|
126
|
+
const valuesKey = 'v';
|
|
127
|
+
const DELETE = 'delete';
|
|
128
|
+
const ensureYContent = (yContent) => {
|
|
129
|
+
if (!yContent.size) {
|
|
130
|
+
yContent.set(tablesKey, new Map());
|
|
131
|
+
yContent.set(valuesKey, new Map());
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const getYContent = (yContent) => [
|
|
135
|
+
yContent.get(tablesKey),
|
|
136
|
+
yContent.get(valuesKey),
|
|
137
|
+
];
|
|
138
|
+
const getTransactionChangesFromYDoc = (yContent, events) => {
|
|
139
|
+
if (arrayLength(events) == 1 && arrayIsEmpty(events[0].path)) {
|
|
140
|
+
return [yContent.get('t').toJSON(), yContent.get('v').toJSON()];
|
|
141
|
+
}
|
|
142
|
+
const [yTables, yValues] = getYContent(yContent);
|
|
143
|
+
const tables = {};
|
|
144
|
+
const values = {};
|
|
145
|
+
arrayForEach(events, ({path, changes: {keys}}) =>
|
|
146
|
+
arrayShift(path) == tablesKey
|
|
147
|
+
? ifNotUndefined(
|
|
148
|
+
arrayShift(path),
|
|
149
|
+
(yTableId) => {
|
|
150
|
+
const table = objEnsure(tables, yTableId, objNew);
|
|
151
|
+
const yTable = yTables.get(yTableId);
|
|
152
|
+
ifNotUndefined(
|
|
153
|
+
arrayShift(path),
|
|
154
|
+
(yRowId) => {
|
|
155
|
+
const row = objEnsure(table, yRowId, objNew);
|
|
156
|
+
const yRow = yTable.get(yRowId);
|
|
157
|
+
mapForEach(
|
|
158
|
+
keys,
|
|
159
|
+
(cellId, {action}) =>
|
|
160
|
+
(row[cellId] = action == DELETE ? null : yRow.get(cellId)),
|
|
161
|
+
);
|
|
162
|
+
},
|
|
163
|
+
() =>
|
|
164
|
+
mapForEach(
|
|
165
|
+
keys,
|
|
166
|
+
(rowId, {action}) =>
|
|
167
|
+
(table[rowId] =
|
|
168
|
+
action == DELETE ? null : yTable.get(rowId)?.toJSON()),
|
|
169
|
+
),
|
|
170
|
+
);
|
|
171
|
+
},
|
|
172
|
+
() =>
|
|
173
|
+
mapForEach(
|
|
174
|
+
keys,
|
|
175
|
+
(tableId, {action}) =>
|
|
176
|
+
(tables[tableId] =
|
|
177
|
+
action == DELETE ? null : yTables.get(tableId)?.toJSON()),
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
: mapForEach(
|
|
181
|
+
keys,
|
|
182
|
+
(valueId, {action}) =>
|
|
183
|
+
(values[valueId] = action == DELETE ? null : yValues.get(valueId)),
|
|
184
|
+
),
|
|
185
|
+
);
|
|
186
|
+
return [tables, values];
|
|
187
|
+
};
|
|
188
|
+
const setTransactionChangesToYDoc = (
|
|
189
|
+
yContent,
|
|
190
|
+
getContent,
|
|
191
|
+
getTransactionChanges,
|
|
192
|
+
) => {
|
|
193
|
+
ensureYContent(yContent);
|
|
194
|
+
const [yTables, yValues] = getYContent(yContent);
|
|
195
|
+
const transactionChangesDidFail = () => {
|
|
196
|
+
transactionChangesFailed = 1;
|
|
103
197
|
};
|
|
198
|
+
let transactionChangesFailed = 1;
|
|
199
|
+
ifNotUndefined(getTransactionChanges?.(), ([cellChanges, valueChanges]) => {
|
|
200
|
+
transactionChangesFailed = 0;
|
|
201
|
+
objMap(cellChanges, (table, tableId) =>
|
|
202
|
+
transactionChangesFailed
|
|
203
|
+
? 0
|
|
204
|
+
: isUndefined(table)
|
|
205
|
+
? yTables.delete(tableId)
|
|
206
|
+
: ifNotUndefined(
|
|
207
|
+
yTables.get(tableId),
|
|
208
|
+
(yTable) =>
|
|
209
|
+
objMap(table, (row, rowId) =>
|
|
210
|
+
transactionChangesFailed
|
|
211
|
+
? 0
|
|
212
|
+
: isUndefined(row)
|
|
213
|
+
? yTable.delete(rowId)
|
|
214
|
+
: ifNotUndefined(
|
|
215
|
+
yTable.get(rowId),
|
|
216
|
+
(yRow) =>
|
|
217
|
+
objMap(row, (cell, cellId) =>
|
|
218
|
+
isUndefined(cell)
|
|
219
|
+
? yRow.delete(cellId)
|
|
220
|
+
: yRow.set(cellId, cell),
|
|
221
|
+
),
|
|
222
|
+
transactionChangesDidFail,
|
|
223
|
+
),
|
|
224
|
+
),
|
|
225
|
+
transactionChangesDidFail,
|
|
226
|
+
),
|
|
227
|
+
);
|
|
228
|
+
objMap(valueChanges, (value, valueId) =>
|
|
229
|
+
transactionChangesFailed
|
|
230
|
+
? 0
|
|
231
|
+
: isUndefined(value)
|
|
232
|
+
? yValues.delete(valueId)
|
|
233
|
+
: yValues.set(valueId, value),
|
|
234
|
+
);
|
|
235
|
+
});
|
|
236
|
+
if (transactionChangesFailed) {
|
|
237
|
+
const [tables, values] = getContent();
|
|
238
|
+
yMapMatch(yTables, void 0, tables, (_, tableId, table) =>
|
|
239
|
+
yMapMatch(yTables, tableId, table, (yTable, rowId, row) =>
|
|
240
|
+
yMapMatch(yTable, rowId, row, (yRow, cellId, cell) => {
|
|
241
|
+
if (yRow.get(cellId) !== cell) {
|
|
242
|
+
yRow.set(cellId, cell);
|
|
243
|
+
return 1;
|
|
244
|
+
}
|
|
245
|
+
}),
|
|
246
|
+
),
|
|
247
|
+
);
|
|
248
|
+
yMapMatch(yValues, void 0, values, (_, valueId, value) => {
|
|
249
|
+
if (yValues.get(valueId) !== value) {
|
|
250
|
+
yValues.set(valueId, value);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const yMapMatch = (yMapOrParent, idInParent, obj, set) => {
|
|
256
|
+
const yMap = isUndefined(idInParent)
|
|
257
|
+
? yMapOrParent
|
|
258
|
+
: yMapOrParent.get(idInParent) ?? yMapOrParent.set(idInParent, new Map());
|
|
259
|
+
let changed;
|
|
260
|
+
objMap(obj, (value, id) => {
|
|
261
|
+
if (set(yMap, id, value)) {
|
|
262
|
+
changed = 1;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
yMap.forEach((_, id) => {
|
|
266
|
+
if (!objHas(obj, id)) {
|
|
267
|
+
yMap.delete(id);
|
|
268
|
+
changed = 1;
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
if (!isUndefined(idInParent) && !yMap.size) {
|
|
272
|
+
yMapOrParent.delete(idInParent);
|
|
273
|
+
}
|
|
274
|
+
return changed;
|
|
275
|
+
};
|
|
276
|
+
const createYjsPersister = (store, yDoc, yMapName = 'tinybase') => {
|
|
277
|
+
const yContent = yDoc.getMap(yMapName);
|
|
278
|
+
const getPersisted = async () =>
|
|
279
|
+
yContent.size
|
|
280
|
+
? [yContent.get('t').toJSON(), yContent.get('v').toJSON()]
|
|
281
|
+
: void 0;
|
|
282
|
+
const setPersisted = async (getContent, getTransactionChanges) =>
|
|
283
|
+
yDoc.transact(() =>
|
|
284
|
+
setTransactionChangesToYDoc(yContent, getContent, getTransactionChanges),
|
|
285
|
+
);
|
|
104
286
|
const addPersisterListener = (listener) => {
|
|
105
|
-
const observer = () =>
|
|
106
|
-
|
|
287
|
+
const observer = (events) =>
|
|
288
|
+
listener(void 0, () => getTransactionChangesFromYDoc(yContent, events));
|
|
289
|
+
yContent.observeDeep(observer);
|
|
107
290
|
return observer;
|
|
108
291
|
};
|
|
109
|
-
const delPersisterListener = (observer) =>
|
|
292
|
+
const delPersisterListener = (observer) => {
|
|
293
|
+
yContent.unobserveDeep(observer);
|
|
294
|
+
};
|
|
110
295
|
return createCustomPersister(
|
|
111
296
|
store,
|
|
112
297
|
getPersisted,
|
package/lib/debug/persisters.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const EMPTY_STRING = '';
|
|
2
|
-
|
|
3
1
|
const isUndefined = (thing) => thing == void 0;
|
|
4
2
|
const ifNotUndefined = (value, then, otherwise) =>
|
|
5
3
|
isUndefined(value) ? otherwise?.() : then(value);
|
|
@@ -20,43 +18,45 @@ const createCustomPersister = (
|
|
|
20
18
|
let saves = 0;
|
|
21
19
|
let listening = false;
|
|
22
20
|
let listeningHandle;
|
|
21
|
+
const loadLock = async (actions) => {
|
|
22
|
+
/* istanbul ignore else */
|
|
23
|
+
if (loadSave != 2) {
|
|
24
|
+
loadSave = 1;
|
|
25
|
+
{
|
|
26
|
+
loads++;
|
|
27
|
+
}
|
|
28
|
+
await actions();
|
|
29
|
+
loadSave = 0;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
23
32
|
const persister = {
|
|
24
33
|
load: async (initialTables, initialValues) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
33
|
-
store.setJson(body);
|
|
34
|
-
} else {
|
|
35
|
-
store.setContent([initialTables, initialValues]);
|
|
36
|
-
}
|
|
37
|
-
loadSave = 0;
|
|
38
|
-
}
|
|
34
|
+
await loadLock(async () => {
|
|
35
|
+
let content;
|
|
36
|
+
try {
|
|
37
|
+
content = await getPersisted();
|
|
38
|
+
} catch {}
|
|
39
|
+
store.setContent(content ?? [initialTables, initialValues]);
|
|
40
|
+
});
|
|
39
41
|
return persister;
|
|
40
42
|
},
|
|
41
43
|
startAutoLoad: async (initialTables, initialValues) => {
|
|
42
44
|
persister.stopAutoLoad();
|
|
43
45
|
await persister.load(initialTables, initialValues);
|
|
44
46
|
listening = true;
|
|
45
|
-
listeningHandle = addPersisterListener(
|
|
46
|
-
|
|
47
|
-
await
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
listeningHandle = addPersisterListener(
|
|
48
|
+
async (getContent, getTransactionChanges) => {
|
|
49
|
+
await loadLock(async () => {
|
|
50
|
+
if (getTransactionChanges) {
|
|
51
|
+
store.setTransactionChanges(getTransactionChanges());
|
|
52
|
+
} else {
|
|
53
|
+
try {
|
|
54
|
+
store.setContent(getContent?.() ?? (await getPersisted()));
|
|
55
|
+
} catch {}
|
|
54
56
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
});
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
60
|
return persister;
|
|
61
61
|
},
|
|
62
62
|
stopAutoLoad: () => {
|
|
@@ -67,21 +67,24 @@ const createCustomPersister = (
|
|
|
67
67
|
}
|
|
68
68
|
return persister;
|
|
69
69
|
},
|
|
70
|
-
save: async () => {
|
|
70
|
+
save: async (getTransactionChanges) => {
|
|
71
71
|
/* istanbul ignore else */
|
|
72
72
|
if (loadSave != 1) {
|
|
73
73
|
loadSave = 2;
|
|
74
74
|
{
|
|
75
75
|
saves++;
|
|
76
76
|
}
|
|
77
|
-
await setPersisted(store.getContent);
|
|
77
|
+
await setPersisted(store.getContent, getTransactionChanges);
|
|
78
78
|
loadSave = 0;
|
|
79
79
|
}
|
|
80
80
|
return persister;
|
|
81
81
|
},
|
|
82
82
|
startAutoSave: async () => {
|
|
83
83
|
await persister.stopAutoSave().save();
|
|
84
|
-
listenerId = store.addDidFinishTransactionListener(
|
|
84
|
+
listenerId = store.addDidFinishTransactionListener(
|
|
85
|
+
(_store, getTransactionChanges) =>
|
|
86
|
+
persister.save(getTransactionChanges),
|
|
87
|
+
);
|
|
85
88
|
return persister;
|
|
86
89
|
},
|
|
87
90
|
stopAutoSave: () => {
|
package/lib/debug/queries.js
CHANGED
|
@@ -44,6 +44,11 @@ const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
|
|
|
44
44
|
const isArray = (thing) => Array.isArray(thing);
|
|
45
45
|
const getUndefined = () => void 0;
|
|
46
46
|
|
|
47
|
+
const object = Object;
|
|
48
|
+
const objFreeze = object.freeze;
|
|
49
|
+
const objMap = (obj, cb) =>
|
|
50
|
+
arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
|
|
51
|
+
|
|
47
52
|
const collSize = (coll) => coll.size;
|
|
48
53
|
const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
|
|
49
54
|
const collIsEmpty = (coll) => isUndefined(coll) || collSize(coll) == 0;
|
|
@@ -329,11 +334,6 @@ const getCreateFunction = (getFunction) => {
|
|
|
329
334
|
};
|
|
330
335
|
};
|
|
331
336
|
|
|
332
|
-
const object = Object;
|
|
333
|
-
const objFreeze = object.freeze;
|
|
334
|
-
const objMap = (obj, cb) =>
|
|
335
|
-
arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
|
|
336
|
-
|
|
337
337
|
const createQueries = getCreateFunction((store) => {
|
|
338
338
|
const createStore = store.createStore;
|
|
339
339
|
const [
|