tinybase 4.0.0-beta.0 → 4.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/persister-browser.cjs +1 -0
- package/lib/cjs/persister-browser.cjs.gz +0 -0
- package/lib/cjs/persister-file.cjs +1 -0
- package/lib/cjs/persister-file.cjs.gz +0 -0
- package/lib/cjs/persister-remote.cjs +1 -0
- 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/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-es6/persister-browser.cjs +1 -0
- package/lib/cjs-es6/persister-browser.cjs.gz +0 -0
- package/lib/cjs-es6/persister-file.cjs +1 -0
- package/lib/cjs-es6/persister-file.cjs.gz +0 -0
- package/lib/cjs-es6/persister-remote.cjs +1 -0
- 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/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/debug/persister-browser.js +148 -0
- package/lib/debug/persister-file.js +140 -0
- package/lib/debug/persister-remote.js +156 -0
- package/lib/debug/persister-yjs.js +30 -21
- package/lib/debug/persisters.js +24 -117
- package/lib/debug/store.js +36 -21
- package/lib/debug/tinybase.js +59 -135
- package/lib/es6/persister-browser.js +1 -0
- package/lib/es6/persister-browser.js.gz +0 -0
- package/lib/es6/persister-file.js +1 -0
- package/lib/es6/persister-file.js.gz +0 -0
- package/lib/es6/persister-remote.js +1 -0
- 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/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/persister-browser.js +1 -0
- package/lib/persister-browser.js.gz +0 -0
- package/lib/persister-file.js +1 -0
- package/lib/persister-file.js.gz +0 -0
- package/lib/persister-remote.js +1 -0
- 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/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/types/persister-browser.d.ts +85 -0
- package/lib/types/persister-file.d.ts +41 -0
- package/lib/types/persister-remote.d.ts +60 -0
- package/lib/types/persisters.d.ts +40 -173
- package/lib/types/store.d.ts +117 -11
- package/lib/types/with-schemas/persister-browser.d.ts +103 -0
- package/lib/types/with-schemas/persister-file.d.ts +50 -0
- package/lib/types/with-schemas/persister-remote.d.ts +71 -0
- package/lib/types/with-schemas/persisters.d.ts +49 -214
- package/lib/types/with-schemas/store.d.ts +136 -11
- package/lib/umd/persister-browser.js +1 -0
- package/lib/umd/persister-browser.js.gz +0 -0
- package/lib/umd/persister-file.js +1 -0
- package/lib/umd/persister-file.js.gz +0 -0
- package/lib/umd/persister-remote.js +1 -0
- 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/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-es6/persister-browser.js +1 -0
- package/lib/umd-es6/persister-browser.js.gz +0 -0
- package/lib/umd-es6/persister-file.js +1 -0
- package/lib/umd-es6/persister-file.js.gz +0 -0
- package/lib/umd-es6/persister-remote.js +1 -0
- 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/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/package.json +9 -9
- package/readme.md +2 -2
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
const EMPTY_STRING = '';
|
|
2
|
+
|
|
3
|
+
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
4
|
+
|
|
5
|
+
const jsonString = (obj) =>
|
|
6
|
+
JSON.stringify(obj, (_key, value) =>
|
|
7
|
+
isInstanceOf(value, Map)
|
|
8
|
+
? arrayReduce(
|
|
9
|
+
[...value],
|
|
10
|
+
(obj2, [key, value2]) => {
|
|
11
|
+
obj2[key] = value2;
|
|
12
|
+
return obj2;
|
|
13
|
+
},
|
|
14
|
+
{},
|
|
15
|
+
)
|
|
16
|
+
: value,
|
|
17
|
+
);
|
|
18
|
+
const isInstanceOf = (thing, cls) => thing instanceof cls;
|
|
19
|
+
const isUndefined = (thing) => thing == void 0;
|
|
20
|
+
const ifNotUndefined = (value, then, otherwise) =>
|
|
21
|
+
isUndefined(value) ? otherwise?.() : then(value);
|
|
22
|
+
|
|
23
|
+
const object = Object;
|
|
24
|
+
const objFreeze = object.freeze;
|
|
25
|
+
|
|
26
|
+
const createCustomPersister = (
|
|
27
|
+
store,
|
|
28
|
+
getPersisted,
|
|
29
|
+
setPersisted,
|
|
30
|
+
addPersisterListener,
|
|
31
|
+
delPersisterListener,
|
|
32
|
+
) => {
|
|
33
|
+
let listenerId;
|
|
34
|
+
let loadSave = 0;
|
|
35
|
+
let loads = 0;
|
|
36
|
+
let saves = 0;
|
|
37
|
+
let listening = false;
|
|
38
|
+
let listeningHandle;
|
|
39
|
+
const persister = {
|
|
40
|
+
load: async (initialTables, initialValues) => {
|
|
41
|
+
/* istanbul ignore else */
|
|
42
|
+
if (loadSave != 2) {
|
|
43
|
+
loadSave = 1;
|
|
44
|
+
{
|
|
45
|
+
loads++;
|
|
46
|
+
}
|
|
47
|
+
const body = await getPersisted();
|
|
48
|
+
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
49
|
+
store.setJson(body);
|
|
50
|
+
} else {
|
|
51
|
+
store.setContent([initialTables, initialValues]);
|
|
52
|
+
}
|
|
53
|
+
loadSave = 0;
|
|
54
|
+
}
|
|
55
|
+
return persister;
|
|
56
|
+
},
|
|
57
|
+
startAutoLoad: async (initialTables, initialValues) => {
|
|
58
|
+
persister.stopAutoLoad();
|
|
59
|
+
await persister.load(initialTables, initialValues);
|
|
60
|
+
listening = true;
|
|
61
|
+
listeningHandle = addPersisterListener(async (content) => {
|
|
62
|
+
if (isUndefined(content)) {
|
|
63
|
+
await persister.load();
|
|
64
|
+
} else {
|
|
65
|
+
/* istanbul ignore else */
|
|
66
|
+
if (loadSave != 2) {
|
|
67
|
+
loadSave = 1;
|
|
68
|
+
{
|
|
69
|
+
loads++;
|
|
70
|
+
}
|
|
71
|
+
store.setContent(content);
|
|
72
|
+
loadSave = 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return persister;
|
|
77
|
+
},
|
|
78
|
+
stopAutoLoad: () => {
|
|
79
|
+
if (listening) {
|
|
80
|
+
delPersisterListener(listeningHandle);
|
|
81
|
+
listeningHandle = void 0;
|
|
82
|
+
listening = false;
|
|
83
|
+
}
|
|
84
|
+
return persister;
|
|
85
|
+
},
|
|
86
|
+
save: async () => {
|
|
87
|
+
/* istanbul ignore else */
|
|
88
|
+
if (loadSave != 1) {
|
|
89
|
+
loadSave = 2;
|
|
90
|
+
{
|
|
91
|
+
saves++;
|
|
92
|
+
}
|
|
93
|
+
await setPersisted(store.getContent);
|
|
94
|
+
loadSave = 0;
|
|
95
|
+
}
|
|
96
|
+
return persister;
|
|
97
|
+
},
|
|
98
|
+
startAutoSave: async () => {
|
|
99
|
+
await persister.stopAutoSave().save();
|
|
100
|
+
listenerId = store.addDidFinishTransactionListener(persister.save);
|
|
101
|
+
return persister;
|
|
102
|
+
},
|
|
103
|
+
stopAutoSave: () => {
|
|
104
|
+
ifNotUndefined(listenerId, store.delListener);
|
|
105
|
+
return persister;
|
|
106
|
+
},
|
|
107
|
+
getStore: () => store,
|
|
108
|
+
destroy: () => persister.stopAutoLoad().stopAutoSave(),
|
|
109
|
+
getStats: () => ({loads, saves}),
|
|
110
|
+
};
|
|
111
|
+
return objFreeze(persister);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const STORAGE = 'storage';
|
|
115
|
+
const WINDOW = globalThis.window;
|
|
116
|
+
const getStoragePersister = (store, storageName, storage) => {
|
|
117
|
+
const getPersisted = async () => storage.getItem(storageName);
|
|
118
|
+
const setPersisted = async (getContent) =>
|
|
119
|
+
storage.setItem(storageName, jsonString(getContent()));
|
|
120
|
+
const addPersisterListener = (listener) => {
|
|
121
|
+
const storeListener = (event) => {
|
|
122
|
+
if (event.storageArea === storage && event.key === storageName) {
|
|
123
|
+
let newValue;
|
|
124
|
+
try {
|
|
125
|
+
newValue = JSON.parse(event.newValue);
|
|
126
|
+
} catch {}
|
|
127
|
+
listener(newValue);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
WINDOW.addEventListener(STORAGE, storeListener);
|
|
131
|
+
return storeListener;
|
|
132
|
+
};
|
|
133
|
+
const delPersisterListener = (storeListener) =>
|
|
134
|
+
WINDOW.removeEventListener(STORAGE, storeListener);
|
|
135
|
+
return createCustomPersister(
|
|
136
|
+
store,
|
|
137
|
+
getPersisted,
|
|
138
|
+
setPersisted,
|
|
139
|
+
addPersisterListener,
|
|
140
|
+
delPersisterListener,
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
const createLocalPersister = (store, storageName) =>
|
|
144
|
+
getStoragePersister(store, storageName, localStorage);
|
|
145
|
+
const createSessionPersister = (store, storageName) =>
|
|
146
|
+
getStoragePersister(store, storageName, sessionStorage);
|
|
147
|
+
|
|
148
|
+
export {createLocalPersister, createSessionPersister};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {readFile, writeFile} from 'fs/promises';
|
|
2
|
+
import {watch} from 'fs';
|
|
3
|
+
|
|
4
|
+
const EMPTY_STRING = '';
|
|
5
|
+
const UTF8 = 'utf8';
|
|
6
|
+
|
|
7
|
+
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
8
|
+
|
|
9
|
+
const jsonString = (obj) =>
|
|
10
|
+
JSON.stringify(obj, (_key, value) =>
|
|
11
|
+
isInstanceOf(value, Map)
|
|
12
|
+
? arrayReduce(
|
|
13
|
+
[...value],
|
|
14
|
+
(obj2, [key, value2]) => {
|
|
15
|
+
obj2[key] = value2;
|
|
16
|
+
return obj2;
|
|
17
|
+
},
|
|
18
|
+
{},
|
|
19
|
+
)
|
|
20
|
+
: value,
|
|
21
|
+
);
|
|
22
|
+
const isInstanceOf = (thing, cls) => thing instanceof cls;
|
|
23
|
+
const isUndefined = (thing) => thing == void 0;
|
|
24
|
+
const ifNotUndefined = (value, then, otherwise) =>
|
|
25
|
+
isUndefined(value) ? otherwise?.() : then(value);
|
|
26
|
+
|
|
27
|
+
const object = Object;
|
|
28
|
+
const objFreeze = object.freeze;
|
|
29
|
+
|
|
30
|
+
const createCustomPersister = (
|
|
31
|
+
store,
|
|
32
|
+
getPersisted,
|
|
33
|
+
setPersisted,
|
|
34
|
+
addPersisterListener,
|
|
35
|
+
delPersisterListener,
|
|
36
|
+
) => {
|
|
37
|
+
let listenerId;
|
|
38
|
+
let loadSave = 0;
|
|
39
|
+
let loads = 0;
|
|
40
|
+
let saves = 0;
|
|
41
|
+
let listening = false;
|
|
42
|
+
let listeningHandle;
|
|
43
|
+
const persister = {
|
|
44
|
+
load: async (initialTables, initialValues) => {
|
|
45
|
+
/* istanbul ignore else */
|
|
46
|
+
if (loadSave != 2) {
|
|
47
|
+
loadSave = 1;
|
|
48
|
+
{
|
|
49
|
+
loads++;
|
|
50
|
+
}
|
|
51
|
+
const body = await getPersisted();
|
|
52
|
+
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
53
|
+
store.setJson(body);
|
|
54
|
+
} else {
|
|
55
|
+
store.setContent([initialTables, initialValues]);
|
|
56
|
+
}
|
|
57
|
+
loadSave = 0;
|
|
58
|
+
}
|
|
59
|
+
return persister;
|
|
60
|
+
},
|
|
61
|
+
startAutoLoad: async (initialTables, initialValues) => {
|
|
62
|
+
persister.stopAutoLoad();
|
|
63
|
+
await persister.load(initialTables, initialValues);
|
|
64
|
+
listening = true;
|
|
65
|
+
listeningHandle = addPersisterListener(async (content) => {
|
|
66
|
+
if (isUndefined(content)) {
|
|
67
|
+
await persister.load();
|
|
68
|
+
} else {
|
|
69
|
+
/* istanbul ignore else */
|
|
70
|
+
if (loadSave != 2) {
|
|
71
|
+
loadSave = 1;
|
|
72
|
+
{
|
|
73
|
+
loads++;
|
|
74
|
+
}
|
|
75
|
+
store.setContent(content);
|
|
76
|
+
loadSave = 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return persister;
|
|
81
|
+
},
|
|
82
|
+
stopAutoLoad: () => {
|
|
83
|
+
if (listening) {
|
|
84
|
+
delPersisterListener(listeningHandle);
|
|
85
|
+
listeningHandle = void 0;
|
|
86
|
+
listening = false;
|
|
87
|
+
}
|
|
88
|
+
return persister;
|
|
89
|
+
},
|
|
90
|
+
save: async () => {
|
|
91
|
+
/* istanbul ignore else */
|
|
92
|
+
if (loadSave != 1) {
|
|
93
|
+
loadSave = 2;
|
|
94
|
+
{
|
|
95
|
+
saves++;
|
|
96
|
+
}
|
|
97
|
+
await setPersisted(store.getContent);
|
|
98
|
+
loadSave = 0;
|
|
99
|
+
}
|
|
100
|
+
return persister;
|
|
101
|
+
},
|
|
102
|
+
startAutoSave: async () => {
|
|
103
|
+
await persister.stopAutoSave().save();
|
|
104
|
+
listenerId = store.addDidFinishTransactionListener(persister.save);
|
|
105
|
+
return persister;
|
|
106
|
+
},
|
|
107
|
+
stopAutoSave: () => {
|
|
108
|
+
ifNotUndefined(listenerId, store.delListener);
|
|
109
|
+
return persister;
|
|
110
|
+
},
|
|
111
|
+
getStore: () => store,
|
|
112
|
+
destroy: () => persister.stopAutoLoad().stopAutoSave(),
|
|
113
|
+
getStats: () => ({loads, saves}),
|
|
114
|
+
};
|
|
115
|
+
return objFreeze(persister);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const createFilePersister = (store, filePath) => {
|
|
119
|
+
const getPersisted = async () => {
|
|
120
|
+
try {
|
|
121
|
+
return await readFile(filePath, UTF8);
|
|
122
|
+
} catch {}
|
|
123
|
+
};
|
|
124
|
+
const setPersisted = async (getContent) => {
|
|
125
|
+
try {
|
|
126
|
+
await writeFile(filePath, jsonString(getContent()), UTF8);
|
|
127
|
+
} catch {}
|
|
128
|
+
};
|
|
129
|
+
const addPersisterListener = (listener) => watch(filePath, () => listener());
|
|
130
|
+
const delPersisterListener = (watcher) => watcher?.close();
|
|
131
|
+
return createCustomPersister(
|
|
132
|
+
store,
|
|
133
|
+
getPersisted,
|
|
134
|
+
setPersisted,
|
|
135
|
+
addPersisterListener,
|
|
136
|
+
delPersisterListener,
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export {createFilePersister};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const EMPTY_STRING = '';
|
|
2
|
+
|
|
3
|
+
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
|
|
4
|
+
|
|
5
|
+
const jsonString = (obj) =>
|
|
6
|
+
JSON.stringify(obj, (_key, value) =>
|
|
7
|
+
isInstanceOf(value, Map)
|
|
8
|
+
? arrayReduce(
|
|
9
|
+
[...value],
|
|
10
|
+
(obj2, [key, value2]) => {
|
|
11
|
+
obj2[key] = value2;
|
|
12
|
+
return obj2;
|
|
13
|
+
},
|
|
14
|
+
{},
|
|
15
|
+
)
|
|
16
|
+
: value,
|
|
17
|
+
);
|
|
18
|
+
const isInstanceOf = (thing, cls) => thing instanceof cls;
|
|
19
|
+
const isUndefined = (thing) => thing == void 0;
|
|
20
|
+
const ifNotUndefined = (value, then, otherwise) =>
|
|
21
|
+
isUndefined(value) ? otherwise?.() : then(value);
|
|
22
|
+
|
|
23
|
+
const object = Object;
|
|
24
|
+
const objFreeze = object.freeze;
|
|
25
|
+
|
|
26
|
+
const createCustomPersister = (
|
|
27
|
+
store,
|
|
28
|
+
getPersisted,
|
|
29
|
+
setPersisted,
|
|
30
|
+
addPersisterListener,
|
|
31
|
+
delPersisterListener,
|
|
32
|
+
) => {
|
|
33
|
+
let listenerId;
|
|
34
|
+
let loadSave = 0;
|
|
35
|
+
let loads = 0;
|
|
36
|
+
let saves = 0;
|
|
37
|
+
let listening = false;
|
|
38
|
+
let listeningHandle;
|
|
39
|
+
const persister = {
|
|
40
|
+
load: async (initialTables, initialValues) => {
|
|
41
|
+
/* istanbul ignore else */
|
|
42
|
+
if (loadSave != 2) {
|
|
43
|
+
loadSave = 1;
|
|
44
|
+
{
|
|
45
|
+
loads++;
|
|
46
|
+
}
|
|
47
|
+
const body = await getPersisted();
|
|
48
|
+
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
49
|
+
store.setJson(body);
|
|
50
|
+
} else {
|
|
51
|
+
store.setContent([initialTables, initialValues]);
|
|
52
|
+
}
|
|
53
|
+
loadSave = 0;
|
|
54
|
+
}
|
|
55
|
+
return persister;
|
|
56
|
+
},
|
|
57
|
+
startAutoLoad: async (initialTables, initialValues) => {
|
|
58
|
+
persister.stopAutoLoad();
|
|
59
|
+
await persister.load(initialTables, initialValues);
|
|
60
|
+
listening = true;
|
|
61
|
+
listeningHandle = addPersisterListener(async (content) => {
|
|
62
|
+
if (isUndefined(content)) {
|
|
63
|
+
await persister.load();
|
|
64
|
+
} else {
|
|
65
|
+
/* istanbul ignore else */
|
|
66
|
+
if (loadSave != 2) {
|
|
67
|
+
loadSave = 1;
|
|
68
|
+
{
|
|
69
|
+
loads++;
|
|
70
|
+
}
|
|
71
|
+
store.setContent(content);
|
|
72
|
+
loadSave = 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return persister;
|
|
77
|
+
},
|
|
78
|
+
stopAutoLoad: () => {
|
|
79
|
+
if (listening) {
|
|
80
|
+
delPersisterListener(listeningHandle);
|
|
81
|
+
listeningHandle = void 0;
|
|
82
|
+
listening = false;
|
|
83
|
+
}
|
|
84
|
+
return persister;
|
|
85
|
+
},
|
|
86
|
+
save: async () => {
|
|
87
|
+
/* istanbul ignore else */
|
|
88
|
+
if (loadSave != 1) {
|
|
89
|
+
loadSave = 2;
|
|
90
|
+
{
|
|
91
|
+
saves++;
|
|
92
|
+
}
|
|
93
|
+
await setPersisted(store.getContent);
|
|
94
|
+
loadSave = 0;
|
|
95
|
+
}
|
|
96
|
+
return persister;
|
|
97
|
+
},
|
|
98
|
+
startAutoSave: async () => {
|
|
99
|
+
await persister.stopAutoSave().save();
|
|
100
|
+
listenerId = store.addDidFinishTransactionListener(persister.save);
|
|
101
|
+
return persister;
|
|
102
|
+
},
|
|
103
|
+
stopAutoSave: () => {
|
|
104
|
+
ifNotUndefined(listenerId, store.delListener);
|
|
105
|
+
return persister;
|
|
106
|
+
},
|
|
107
|
+
getStore: () => store,
|
|
108
|
+
destroy: () => persister.stopAutoLoad().stopAutoSave(),
|
|
109
|
+
getStats: () => ({loads, saves}),
|
|
110
|
+
};
|
|
111
|
+
return objFreeze(persister);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const getETag = (response) => response.headers.get('ETag');
|
|
115
|
+
const createRemotePersister = (
|
|
116
|
+
store,
|
|
117
|
+
loadUrl,
|
|
118
|
+
saveUrl,
|
|
119
|
+
autoLoadIntervalSeconds,
|
|
120
|
+
) => {
|
|
121
|
+
let lastEtag;
|
|
122
|
+
const getPersisted = async () => {
|
|
123
|
+
const response = await fetch(loadUrl);
|
|
124
|
+
lastEtag = getETag(response);
|
|
125
|
+
return response.text();
|
|
126
|
+
};
|
|
127
|
+
const setPersisted = async (getContent) =>
|
|
128
|
+
await fetch(saveUrl, {
|
|
129
|
+
method: 'POST',
|
|
130
|
+
headers: {'Content-Type': 'application/json'},
|
|
131
|
+
body: jsonString(getContent()),
|
|
132
|
+
});
|
|
133
|
+
const addPersisterListener = (listener) =>
|
|
134
|
+
setInterval(async () => {
|
|
135
|
+
const response = await fetch(loadUrl, {method: 'HEAD'});
|
|
136
|
+
const currentEtag = getETag(response);
|
|
137
|
+
if (
|
|
138
|
+
!isUndefined(lastEtag) &&
|
|
139
|
+
!isUndefined(currentEtag) &&
|
|
140
|
+
currentEtag != lastEtag
|
|
141
|
+
) {
|
|
142
|
+
lastEtag = currentEtag;
|
|
143
|
+
listener();
|
|
144
|
+
}
|
|
145
|
+
}, autoLoadIntervalSeconds * 1e3);
|
|
146
|
+
const delPersisterListener = (interval) => clearInterval(interval);
|
|
147
|
+
return createCustomPersister(
|
|
148
|
+
store,
|
|
149
|
+
getPersisted,
|
|
150
|
+
setPersisted,
|
|
151
|
+
addPersisterListener,
|
|
152
|
+
delPersisterListener,
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export {createRemotePersister};
|
|
@@ -11,11 +11,10 @@ const createCustomPersister = (
|
|
|
11
11
|
store,
|
|
12
12
|
getPersisted,
|
|
13
13
|
setPersisted,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
addPersisterListener,
|
|
15
|
+
delPersisterListener,
|
|
16
16
|
) => {
|
|
17
|
-
let
|
|
18
|
-
let valuesListenerId;
|
|
17
|
+
let listenerId;
|
|
19
18
|
let loadSave = 0;
|
|
20
19
|
let loads = 0;
|
|
21
20
|
let saves = 0;
|
|
@@ -33,9 +32,7 @@ const createCustomPersister = (
|
|
|
33
32
|
if (!isUndefined(body) && body != EMPTY_STRING) {
|
|
34
33
|
store.setJson(body);
|
|
35
34
|
} else {
|
|
36
|
-
store.
|
|
37
|
-
store.setTables(initialTables).setValues(initialValues),
|
|
38
|
-
);
|
|
35
|
+
store.setContent([initialTables, initialValues]);
|
|
39
36
|
}
|
|
40
37
|
loadSave = 0;
|
|
41
38
|
}
|
|
@@ -45,12 +42,26 @@ const createCustomPersister = (
|
|
|
45
42
|
persister.stopAutoLoad();
|
|
46
43
|
await persister.load(initialTables, initialValues);
|
|
47
44
|
listening = true;
|
|
48
|
-
listeningHandle =
|
|
45
|
+
listeningHandle = addPersisterListener(async (content) => {
|
|
46
|
+
if (isUndefined(content)) {
|
|
47
|
+
await persister.load();
|
|
48
|
+
} else {
|
|
49
|
+
/* istanbul ignore else */
|
|
50
|
+
if (loadSave != 2) {
|
|
51
|
+
loadSave = 1;
|
|
52
|
+
{
|
|
53
|
+
loads++;
|
|
54
|
+
}
|
|
55
|
+
store.setContent(content);
|
|
56
|
+
loadSave = 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
49
60
|
return persister;
|
|
50
61
|
},
|
|
51
62
|
stopAutoLoad: () => {
|
|
52
63
|
if (listening) {
|
|
53
|
-
|
|
64
|
+
delPersisterListener(listeningHandle);
|
|
54
65
|
listeningHandle = void 0;
|
|
55
66
|
listening = false;
|
|
56
67
|
}
|
|
@@ -63,20 +74,18 @@ const createCustomPersister = (
|
|
|
63
74
|
{
|
|
64
75
|
saves++;
|
|
65
76
|
}
|
|
66
|
-
await setPersisted(store.
|
|
77
|
+
await setPersisted(store.getContent);
|
|
67
78
|
loadSave = 0;
|
|
68
79
|
}
|
|
69
80
|
return persister;
|
|
70
81
|
},
|
|
71
82
|
startAutoSave: async () => {
|
|
72
83
|
await persister.stopAutoSave().save();
|
|
73
|
-
|
|
74
|
-
valuesListenerId = store.addValuesListener(persister.save);
|
|
84
|
+
listenerId = store.addDidFinishTransactionListener(persister.save);
|
|
75
85
|
return persister;
|
|
76
86
|
},
|
|
77
87
|
stopAutoSave: () => {
|
|
78
|
-
ifNotUndefined(
|
|
79
|
-
ifNotUndefined(valuesListenerId, store.delListener);
|
|
88
|
+
ifNotUndefined(listenerId, store.delListener);
|
|
80
89
|
return persister;
|
|
81
90
|
},
|
|
82
91
|
getStore: () => store,
|
|
@@ -89,21 +98,21 @@ const createCustomPersister = (
|
|
|
89
98
|
const createYjsPersister = (store, yDoc) => {
|
|
90
99
|
const map = yDoc.getMap('tinybase/store');
|
|
91
100
|
const getPersisted = async () => map.get('json');
|
|
92
|
-
const setPersisted = async (
|
|
93
|
-
map.set('json',
|
|
101
|
+
const setPersisted = async (getContent) => {
|
|
102
|
+
map.set('json', JSON.stringify(getContent()));
|
|
94
103
|
};
|
|
95
|
-
const
|
|
96
|
-
const observer = () =>
|
|
104
|
+
const addPersisterListener = (listener) => {
|
|
105
|
+
const observer = () => listener();
|
|
97
106
|
map.observe(observer);
|
|
98
107
|
return observer;
|
|
99
108
|
};
|
|
100
|
-
const
|
|
109
|
+
const delPersisterListener = (observer) => map.unobserve(observer);
|
|
101
110
|
return createCustomPersister(
|
|
102
111
|
store,
|
|
103
112
|
getPersisted,
|
|
104
113
|
setPersisted,
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
addPersisterListener,
|
|
115
|
+
delPersisterListener,
|
|
107
116
|
);
|
|
108
117
|
};
|
|
109
118
|
|