tinybase 3.0.1 → 3.0.3
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/checkpoints.cjs +1 -0
- package/lib/cjs/checkpoints.cjs.gz +0 -0
- package/lib/cjs/checkpoints.d.ts +959 -0
- package/lib/cjs/common.cjs +1 -0
- package/lib/cjs/common.cjs.gz +0 -0
- package/lib/cjs/common.d.ts +115 -0
- package/lib/cjs/indexes.cjs +1 -0
- package/lib/cjs/indexes.cjs.gz +0 -0
- package/lib/cjs/indexes.d.ts +966 -0
- package/lib/cjs/metrics.cjs +1 -0
- package/lib/cjs/metrics.cjs.gz +0 -0
- package/lib/cjs/metrics.d.ts +827 -0
- package/lib/cjs/persisters.cjs +1 -0
- package/lib/cjs/persisters.cjs.gz +0 -0
- package/lib/cjs/persisters.d.ts +727 -0
- package/lib/cjs/queries.cjs +1 -0
- package/lib/cjs/queries.cjs.gz +0 -0
- package/lib/cjs/queries.d.ts +3024 -0
- package/lib/cjs/relationships.cjs +1 -0
- package/lib/cjs/relationships.cjs.gz +0 -0
- package/lib/cjs/relationships.d.ts +1201 -0
- package/lib/cjs/store.cjs +1 -0
- package/lib/cjs/store.cjs.gz +0 -0
- package/lib/cjs/store.d.ts +5244 -0
- package/lib/cjs/tinybase.cjs +1 -0
- package/lib/cjs/tinybase.cjs.gz +0 -0
- package/lib/cjs/tinybase.d.ts +14 -0
- package/lib/cjs/tools.cjs +1 -0
- package/lib/cjs/tools.cjs.gz +0 -0
- package/lib/cjs/tools.d.ts +512 -0
- package/lib/cjs/ui-react.cjs +1 -0
- package/lib/cjs/ui-react.cjs.gz +0 -0
- package/lib/cjs/ui-react.d.ts +10921 -0
- package/lib/cjs-es6/checkpoints.cjs +1 -0
- package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
- package/lib/cjs-es6/checkpoints.d.ts +959 -0
- package/lib/cjs-es6/common.cjs +1 -0
- package/lib/cjs-es6/common.cjs.gz +0 -0
- package/lib/cjs-es6/common.d.ts +115 -0
- package/lib/cjs-es6/indexes.cjs +1 -0
- package/lib/cjs-es6/indexes.cjs.gz +0 -0
- package/lib/cjs-es6/indexes.d.ts +966 -0
- package/lib/cjs-es6/metrics.cjs +1 -0
- package/lib/cjs-es6/metrics.cjs.gz +0 -0
- package/lib/cjs-es6/metrics.d.ts +827 -0
- package/lib/cjs-es6/persisters.cjs +1 -0
- package/lib/cjs-es6/persisters.cjs.gz +0 -0
- package/lib/cjs-es6/persisters.d.ts +727 -0
- package/lib/cjs-es6/queries.cjs +1 -0
- package/lib/cjs-es6/queries.cjs.gz +0 -0
- package/lib/cjs-es6/queries.d.ts +3024 -0
- package/lib/cjs-es6/relationships.cjs +1 -0
- package/lib/cjs-es6/relationships.cjs.gz +0 -0
- package/lib/cjs-es6/relationships.d.ts +1201 -0
- package/lib/cjs-es6/store.cjs +1 -0
- package/lib/cjs-es6/store.cjs.gz +0 -0
- package/lib/cjs-es6/store.d.ts +5244 -0
- package/lib/cjs-es6/tinybase.cjs +1 -0
- package/lib/cjs-es6/tinybase.cjs.gz +0 -0
- package/lib/cjs-es6/tinybase.d.ts +14 -0
- package/lib/cjs-es6/tools.cjs +1 -0
- package/lib/cjs-es6/tools.cjs.gz +0 -0
- package/lib/cjs-es6/tools.d.ts +512 -0
- package/lib/cjs-es6/ui-react.cjs +1 -0
- package/lib/cjs-es6/ui-react.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react.d.ts +10921 -0
- package/lib/debug/ui-react.js +22 -21
- package/lib/es6/ui-react.js +1 -1
- package/lib/es6/ui-react.js.gz +0 -0
- package/lib/ui-react.js +1 -1
- package/lib/ui-react.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/ui-react.js +1 -1
- package/lib/umd-es6/ui-react.js.gz +0 -0
- package/package.json +30 -22
- package/readme.md +1 -1
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The persisters module of the TinyBase project provides a simple framework for
|
|
3
|
+
* saving and loading Store data, to and from different destinations, or
|
|
4
|
+
* underlying storage types.
|
|
5
|
+
*
|
|
6
|
+
* Several entry points are provided, each of which returns a new Persister
|
|
7
|
+
* object that can load and save a Store:
|
|
8
|
+
*
|
|
9
|
+
* - The createSessionPersister function returns a Persister that uses the
|
|
10
|
+
* browser's session storage.
|
|
11
|
+
* - The createLocalPersister function returns a Persister that uses the
|
|
12
|
+
* browser's local storage.
|
|
13
|
+
* - The createRemotePersister function returns a Persister that uses a remote
|
|
14
|
+
* server.
|
|
15
|
+
* - The createFilePersister function returns a Persister that uses a local file
|
|
16
|
+
* (in an appropriate environment).
|
|
17
|
+
*
|
|
18
|
+
* Since persistence requirements can be different for every app, the
|
|
19
|
+
* createCustomPersister function can also be used to easily create a fully
|
|
20
|
+
* customized way to save and load Store data.
|
|
21
|
+
*
|
|
22
|
+
* @see Persisting Data guide
|
|
23
|
+
* @see Countries demo
|
|
24
|
+
* @see Todo App demos
|
|
25
|
+
* @see Drawing demo
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
* @module persisters
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import {Store, Tables, Values} from './store.d';
|
|
31
|
+
import {Callback} from './common.d';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The PersisterStats type describes the number of times a Persister object has
|
|
35
|
+
* loaded or saved data.
|
|
36
|
+
*
|
|
37
|
+
* A PersisterStats object is returned from the getStats method, and is only
|
|
38
|
+
* populated in a debug build.
|
|
39
|
+
*
|
|
40
|
+
* @category Development
|
|
41
|
+
*/
|
|
42
|
+
export type PersisterStats = {
|
|
43
|
+
/**
|
|
44
|
+
* The number of times data has been loaded.
|
|
45
|
+
*/
|
|
46
|
+
loads?: number;
|
|
47
|
+
/**
|
|
48
|
+
* The number of times data has been saved.
|
|
49
|
+
*/
|
|
50
|
+
saves?: number;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A Persister object lets you save and load Store data to and from different
|
|
55
|
+
* locations, or underlying storage types.
|
|
56
|
+
*
|
|
57
|
+
* This is useful for preserving Store data between browser sessions or reloads,
|
|
58
|
+
* saving or loading browser state to or from a server, or saving Store data to
|
|
59
|
+
* disk in a environment with filesystem access.
|
|
60
|
+
*
|
|
61
|
+
* Creating a Persister depends on the choice of underlying storage where the
|
|
62
|
+
* data is to be stored. Options include the createSessionPersister function,
|
|
63
|
+
* the createLocalPersister, the createRemotePersister function, and the
|
|
64
|
+
* createFilePersister function. The createCustomPersister function can also be
|
|
65
|
+
* used to easily create a fully customized way to save and load Store data.
|
|
66
|
+
*
|
|
67
|
+
* A Persister lets you explicit save or load data, with the save method and the
|
|
68
|
+
* load method respectively. These methods are both asynchronous (since the
|
|
69
|
+
* underlying data storage may also be) and return promises. As a result you
|
|
70
|
+
* should use the `await` keyword to call them in a way that guarantees
|
|
71
|
+
* subsequent execution order.
|
|
72
|
+
*
|
|
73
|
+
* When you don't want to deal with explicit persistence operations, a Persister
|
|
74
|
+
* object also provides automatic saving and loading. Automatic saving listens
|
|
75
|
+
* for changes to the Store and persists the data immediately. Automatic loading
|
|
76
|
+
* listens (or polls) for changes to the persisted data and reflects those
|
|
77
|
+
* changes in the Store.
|
|
78
|
+
*
|
|
79
|
+
* You can start automatic saving or loading with the startAutoSave method and
|
|
80
|
+
* startAutoLoad method. Both are asynchronous since they will do an immediate
|
|
81
|
+
* save and load before starting to listen for subsequent changes. You can stop
|
|
82
|
+
* the behavior with the stopAutoSave method and stopAutoLoad method (which are
|
|
83
|
+
* synchronous).
|
|
84
|
+
*
|
|
85
|
+
* You may often want to have both automatic saving and loading of a Store so
|
|
86
|
+
* that changes are constantly synchronized (allowing basic state preservation
|
|
87
|
+
* between browser tabs, for example). The framework has some basic provisions
|
|
88
|
+
* to prevent race conditions - for example it will not attempt to save data if
|
|
89
|
+
* it is currently loading it and vice-versa.
|
|
90
|
+
*
|
|
91
|
+
* Be aware, however, that the default implementations do not provide complex
|
|
92
|
+
* synchronization heuristics and you should comprehensively test your
|
|
93
|
+
* persistence strategy to understand the opportunity for data loss (in the case
|
|
94
|
+
* of trying to save data to a server under poor network conditions, for
|
|
95
|
+
* example).
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* This example creates a Store, persists it to the browser's session storage as
|
|
99
|
+
* a JSON string, changes the persisted data, updates the Store from it, and
|
|
100
|
+
* finally destroys the Persister again.
|
|
101
|
+
*
|
|
102
|
+
* ```js
|
|
103
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
104
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
105
|
+
*
|
|
106
|
+
* await persister.save();
|
|
107
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
108
|
+
* // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
|
|
109
|
+
*
|
|
110
|
+
* sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
|
|
111
|
+
* await persister.load();
|
|
112
|
+
* console.log(store.getTables());
|
|
113
|
+
* // -> {pets: {toto: {species: 'dog'}}}
|
|
114
|
+
*
|
|
115
|
+
* persister.destroy();
|
|
116
|
+
* sessionStorage.clear();
|
|
117
|
+
* ```
|
|
118
|
+
* @example
|
|
119
|
+
* This example creates a Store, and automatically saves and loads it to the
|
|
120
|
+
* browser's session storage as a JSON string. Changes to the Store data, or the
|
|
121
|
+
* persisted data (implicitly firing a StorageEvent), are reflected accordingly.
|
|
122
|
+
*
|
|
123
|
+
* ```js
|
|
124
|
+
* const store = createStore();
|
|
125
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
126
|
+
*
|
|
127
|
+
* await persister.startAutoLoad({pets: {fido: {species: 'dog'}}});
|
|
128
|
+
* await persister.startAutoSave();
|
|
129
|
+
*
|
|
130
|
+
* store.setTables({pets: {felix: {species: 'cat'}}});
|
|
131
|
+
* // ...
|
|
132
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
133
|
+
* // -> '[{"pets":{"felix":{"species":"cat"}}},{}]'
|
|
134
|
+
*
|
|
135
|
+
* // In another browser tab:
|
|
136
|
+
* sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
|
|
137
|
+
* // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
|
|
138
|
+
*
|
|
139
|
+
* // ...
|
|
140
|
+
* console.log(store.getTables());
|
|
141
|
+
* // -> {pets: {toto: {species: 'dog'}}}
|
|
142
|
+
*
|
|
143
|
+
* persister.destroy();
|
|
144
|
+
* sessionStorage.clear();
|
|
145
|
+
* ```
|
|
146
|
+
* @category Persister
|
|
147
|
+
*/
|
|
148
|
+
export interface Persister {
|
|
149
|
+
/**
|
|
150
|
+
* The load method gets persisted data from storage, and loads it into the
|
|
151
|
+
* Store with which the Persister is associated, once.
|
|
152
|
+
*
|
|
153
|
+
* The optional parameter allows you to specify what the initial Tables object
|
|
154
|
+
* for the Store will be if there is nothing currently persisted. Using this
|
|
155
|
+
* instead of the `initialTables` parameter in the regular createStore
|
|
156
|
+
* function allows you to easily instantiate a Store whether it's loading from
|
|
157
|
+
* previously persisted storage or being run for the first time.
|
|
158
|
+
*
|
|
159
|
+
* This method is asynchronous because the persisted data may be on a remote
|
|
160
|
+
* machine or a filesystem. Even for those storage types that are synchronous
|
|
161
|
+
* (like browser storage) it is still recommended that you `await` calls to
|
|
162
|
+
* this method or handle the return type natively as a Promise.
|
|
163
|
+
*
|
|
164
|
+
* @param initialTables An optional Tables object used when the underlying
|
|
165
|
+
* storage has not previously been populated.
|
|
166
|
+
* @param initialValues An optional Values object used when the underlying
|
|
167
|
+
* storage has not previously been populated, since v3.0.0.
|
|
168
|
+
* @returns A Promise containing a reference to the Persister object.
|
|
169
|
+
* @example
|
|
170
|
+
* This example creates an empty Store, and loads data into it from the
|
|
171
|
+
* browser's session storage, which for the purposes of this example has been
|
|
172
|
+
* previously populated.
|
|
173
|
+
*
|
|
174
|
+
* ```js
|
|
175
|
+
* sessionStorage.setItem('pets', '[{"pets":{"fido":{"species":"dog"}}},{}]');
|
|
176
|
+
*
|
|
177
|
+
* const store = createStore();
|
|
178
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
179
|
+
*
|
|
180
|
+
* await persister.load();
|
|
181
|
+
* console.log(store.getTables());
|
|
182
|
+
* // -> {pets: {fido: {species: 'dog'}}}
|
|
183
|
+
*
|
|
184
|
+
* sessionStorage.clear();
|
|
185
|
+
* ```
|
|
186
|
+
* @example
|
|
187
|
+
* This example creates an empty Store, and loads data into it from the
|
|
188
|
+
* browser's session storage, which is at first empty, so the optional
|
|
189
|
+
* parameter is used. The second time the load method is called, data has
|
|
190
|
+
* previously been persisted and instead, that is loaded.
|
|
191
|
+
*
|
|
192
|
+
* ```js
|
|
193
|
+
* const store = createStore();
|
|
194
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
195
|
+
*
|
|
196
|
+
* await persister.load({pets: {fido: {species: 'dog'}}});
|
|
197
|
+
* console.log(store.getTables());
|
|
198
|
+
* // -> {pets: {fido: {species: 'dog'}}}
|
|
199
|
+
*
|
|
200
|
+
* sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
|
|
201
|
+
* await persister.load({pets: {fido: {species: 'dog'}}});
|
|
202
|
+
* console.log(store.getTables());
|
|
203
|
+
* // -> {pets: {toto: {species: 'dog'}}}
|
|
204
|
+
*
|
|
205
|
+
* sessionStorage.clear();
|
|
206
|
+
* ```
|
|
207
|
+
* @category Load
|
|
208
|
+
*/
|
|
209
|
+
load(initialTables?: Tables, initialValues?: Values): Promise<Persister>;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* The startAutoLoad method gets persisted data from storage, and loads it
|
|
213
|
+
* into the Store with which the Persister is associated, once, and then
|
|
214
|
+
* continuously.
|
|
215
|
+
*
|
|
216
|
+
* The optional parameter allows you to specify what the initial Tables object
|
|
217
|
+
* for the Store will be if there is nothing at first persisted. Using this
|
|
218
|
+
* instead of the `initialTables` parameter in the regular createStore
|
|
219
|
+
* function allows you to easily instantiate a Store whether it's loading from
|
|
220
|
+
* previously persisted storage or being run for the first time.
|
|
221
|
+
*
|
|
222
|
+
* This method first runs a single call to the load method to ensure the data
|
|
223
|
+
* is in sync with the persisted storage. It then continues to watch for
|
|
224
|
+
* changes to the underlying data (either through events or polling, depending
|
|
225
|
+
* on the storage type), automatically loading the data into the Store.
|
|
226
|
+
*
|
|
227
|
+
* This method is asynchronous because it starts by making a single call to
|
|
228
|
+
* the asynchronous load method. Even for those storage types that are
|
|
229
|
+
* synchronous (like browser storage) it is still recommended that you `await`
|
|
230
|
+
* calls to this method or handle the return type natively as a Promise.
|
|
231
|
+
*
|
|
232
|
+
* @param initialTables An optional Tables object used when the underlying
|
|
233
|
+
* storage has not previously been populated.
|
|
234
|
+
* @param initialValues An optional Values object used when the underlying
|
|
235
|
+
* storage has not previously been populated, since v3.0.0.
|
|
236
|
+
* @returns A Promise containing a reference to the Persister object.
|
|
237
|
+
* @example
|
|
238
|
+
* This example creates an empty Store, and loads data into it from the
|
|
239
|
+
* browser's session storage, which at first is empty (so the `initialTables`
|
|
240
|
+
* parameter is used). Subsequent changes to the underlying storage are then
|
|
241
|
+
* reflected in the Store (in this case through detection of StorageEvents
|
|
242
|
+
* from session storage changes made in another browser tab).
|
|
243
|
+
*
|
|
244
|
+
* ```js
|
|
245
|
+
* const store = createStore();
|
|
246
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
247
|
+
*
|
|
248
|
+
* await persister.startAutoLoad({pets: {fido: {species: 'dog'}}});
|
|
249
|
+
* console.log(store.getTables());
|
|
250
|
+
* // -> {pets: {fido: {species: 'dog'}}}
|
|
251
|
+
*
|
|
252
|
+
* // In another browser tab:
|
|
253
|
+
* sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
|
|
254
|
+
* // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
|
|
255
|
+
*
|
|
256
|
+
* // ...
|
|
257
|
+
* console.log(store.getTables());
|
|
258
|
+
* // -> {pets: {toto: {species: 'dog'}}}
|
|
259
|
+
*
|
|
260
|
+
* persister.destroy();
|
|
261
|
+
* sessionStorage.clear();
|
|
262
|
+
* ```
|
|
263
|
+
* @category Load
|
|
264
|
+
*/
|
|
265
|
+
startAutoLoad(
|
|
266
|
+
initialTables?: Tables,
|
|
267
|
+
initialValues?: Values,
|
|
268
|
+
): Promise<Persister>;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* The stopAutoLoad method stops the automatic loading of data from storage
|
|
272
|
+
* previously started with the startAutoLoad method.
|
|
273
|
+
*
|
|
274
|
+
* If the Persister is not currently set to automatically load, this method
|
|
275
|
+
* has no effect.
|
|
276
|
+
*
|
|
277
|
+
* @returns A reference to the Persister object.
|
|
278
|
+
* @example
|
|
279
|
+
* This example creates an empty Store, and starts automatically loading data
|
|
280
|
+
* into it from the browser's session storage. Once the automatic loading is
|
|
281
|
+
* stopped, subsequent changes are not reflected in the Store.
|
|
282
|
+
*
|
|
283
|
+
* ```js
|
|
284
|
+
* const store = createStore();
|
|
285
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
286
|
+
* await persister.startAutoLoad();
|
|
287
|
+
*
|
|
288
|
+
* // In another browser tab:
|
|
289
|
+
* sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
|
|
290
|
+
* // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
|
|
291
|
+
* // ...
|
|
292
|
+
* console.log(store.getTables());
|
|
293
|
+
* // -> {pets: {toto: {species: 'dog'}}}
|
|
294
|
+
*
|
|
295
|
+
* persister.stopAutoLoad();
|
|
296
|
+
*
|
|
297
|
+
* // In another browser tab:
|
|
298
|
+
* sessionStorage.setItem(
|
|
299
|
+
* 'pets',
|
|
300
|
+
* '[{"pets":{"felix":{"species":"cat"}}},{}]',
|
|
301
|
+
* );
|
|
302
|
+
* // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
|
|
303
|
+
* // ...
|
|
304
|
+
* console.log(store.getTables());
|
|
305
|
+
* // -> {pets: {toto: {species: 'dog'}}}
|
|
306
|
+
* // Storage change has not been automatically loaded.
|
|
307
|
+
*
|
|
308
|
+
* persister.destroy();
|
|
309
|
+
* sessionStorage.clear();
|
|
310
|
+
* ```
|
|
311
|
+
* @category Load
|
|
312
|
+
*/
|
|
313
|
+
stopAutoLoad(): Persister;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* The save method takes data from the Store with which the Persister is
|
|
317
|
+
* associated and persists it into storage, once.
|
|
318
|
+
*
|
|
319
|
+
* This method is asynchronous because the persisted data may be on a remote
|
|
320
|
+
* machine or a filesystem. Even for those storage types that are synchronous
|
|
321
|
+
* (like browser storage) it is still recommended that you `await` calls to
|
|
322
|
+
* this method or handle the return type natively as a Promise.
|
|
323
|
+
*
|
|
324
|
+
* @returns A Promise containing a reference to the Persister object.
|
|
325
|
+
* @example
|
|
326
|
+
* This example creates a Store with some data, and saves into the browser's
|
|
327
|
+
* session storage.
|
|
328
|
+
*
|
|
329
|
+
* ```js
|
|
330
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
331
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
332
|
+
*
|
|
333
|
+
* await persister.save();
|
|
334
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
335
|
+
* // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
|
|
336
|
+
*
|
|
337
|
+
* persister.destroy();
|
|
338
|
+
* sessionStorage.clear();
|
|
339
|
+
* ```
|
|
340
|
+
* @category Save
|
|
341
|
+
*/
|
|
342
|
+
save(): Promise<Persister>;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* The save method takes data from the Store with which the Persister is
|
|
346
|
+
* associated and persists it into storage, once, and then continuously.
|
|
347
|
+
*
|
|
348
|
+
* This method first runs a single call to the save method to ensure the data
|
|
349
|
+
* is in sync with the persisted storage. It then continues to watch for
|
|
350
|
+
* changes to the Store, automatically saving the data to storage.
|
|
351
|
+
*
|
|
352
|
+
* This method is asynchronous because it starts by making a single call to
|
|
353
|
+
* the asynchronous save method. Even for those storage types that are
|
|
354
|
+
* synchronous (like browser storage) it is still recommended that you `await`
|
|
355
|
+
* calls to this method or handle the return type natively as a Promise.
|
|
356
|
+
*
|
|
357
|
+
* @returns A Promise containing a reference to the Persister object.
|
|
358
|
+
* @example
|
|
359
|
+
* This example creates a Store with some data, and saves into the browser's
|
|
360
|
+
* session storage. Subsequent changes to the Store are then automatically
|
|
361
|
+
* saved to the underlying storage.
|
|
362
|
+
*
|
|
363
|
+
* ```js
|
|
364
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
365
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
366
|
+
*
|
|
367
|
+
* await persister.startAutoSave();
|
|
368
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
369
|
+
* // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
|
|
370
|
+
*
|
|
371
|
+
* store.setTables({pets: {toto: {species: 'dog'}}});
|
|
372
|
+
* // ...
|
|
373
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
374
|
+
* // -> '[{"pets":{"toto":{"species":"dog"}}},{}]'
|
|
375
|
+
*
|
|
376
|
+
* sessionStorage.clear();
|
|
377
|
+
* ```
|
|
378
|
+
* @category Save
|
|
379
|
+
*/
|
|
380
|
+
startAutoSave(): Promise<Persister>;
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* The stopAutoSave method stops the automatic save of data to storage
|
|
384
|
+
* previously started with the startAutoSave method.
|
|
385
|
+
*
|
|
386
|
+
* If the Persister is not currently set to automatically save, this method
|
|
387
|
+
* has no effect.
|
|
388
|
+
*
|
|
389
|
+
* @returns A reference to the Persister object.
|
|
390
|
+
* @example
|
|
391
|
+
* This example creates a Store with some data, and saves into the browser's
|
|
392
|
+
* session storage. Subsequent changes to the Store are then automatically
|
|
393
|
+
* saved to the underlying storage. Once the automatic saving is
|
|
394
|
+
* stopped, subsequent changes are not reflected.
|
|
395
|
+
*
|
|
396
|
+
* ```js
|
|
397
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
398
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
399
|
+
* await persister.startAutoSave();
|
|
400
|
+
*
|
|
401
|
+
* store.setTables({pets: {toto: {species: 'dog'}}});
|
|
402
|
+
* // ...
|
|
403
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
404
|
+
* // -> '[{"pets":{"toto":{"species":"dog"}}},{}]'
|
|
405
|
+
*
|
|
406
|
+
* persister.stopAutoSave();
|
|
407
|
+
*
|
|
408
|
+
* store.setTables({pets: {felix: {species: 'cat'}}});
|
|
409
|
+
* // ...
|
|
410
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
411
|
+
* // -> '[{"pets":{"toto":{"species":"dog"}}},{}]'
|
|
412
|
+
* // Store change has not been automatically saved.
|
|
413
|
+
*
|
|
414
|
+
* sessionStorage.clear();
|
|
415
|
+
* ```
|
|
416
|
+
* @category Save
|
|
417
|
+
*/
|
|
418
|
+
stopAutoSave(): Persister;
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* The getStore method returns a reference to the underlying Store that is
|
|
422
|
+
* backing this Persister object.
|
|
423
|
+
*
|
|
424
|
+
* @returns A reference to the Store.
|
|
425
|
+
* @example
|
|
426
|
+
* This example creates a Persister object against a newly-created Store and
|
|
427
|
+
* then gets its reference in order to update its data.
|
|
428
|
+
*
|
|
429
|
+
* ```js
|
|
430
|
+
* const persister = createSessionPersister(createStore(), 'pets');
|
|
431
|
+
* await persister.startAutoSave();
|
|
432
|
+
*
|
|
433
|
+
* persister.getStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
434
|
+
* // ...
|
|
435
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
436
|
+
* // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
|
|
437
|
+
*
|
|
438
|
+
* sessionStorage.clear();
|
|
439
|
+
* ```
|
|
440
|
+
* @category Getter
|
|
441
|
+
*/
|
|
442
|
+
getStore(): Store;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* The destroy method should be called when this Persister object is no longer
|
|
446
|
+
* used.
|
|
447
|
+
*
|
|
448
|
+
* This guarantees that all of the listeners that the object registered with
|
|
449
|
+
* the underlying Store and storage are removed and it can be correctly
|
|
450
|
+
* garbage collected. It is equivalent to running the stopAutoLoad method and
|
|
451
|
+
* the stopAutoSave method in succession.
|
|
452
|
+
*
|
|
453
|
+
* @example
|
|
454
|
+
* This example creates a Store, associates a Persister object with it (that
|
|
455
|
+
* registers a TablesListener with the underlying Store), and then destroys it
|
|
456
|
+
* again, removing the listener.
|
|
457
|
+
*
|
|
458
|
+
* ```js
|
|
459
|
+
* const store = createStore();
|
|
460
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
461
|
+
* await persister.startAutoSave();
|
|
462
|
+
*
|
|
463
|
+
* console.log(store.getListenerStats().tables);
|
|
464
|
+
* // -> 1
|
|
465
|
+
*
|
|
466
|
+
* persister.destroy();
|
|
467
|
+
*
|
|
468
|
+
* console.log(store.getListenerStats().tables);
|
|
469
|
+
* // -> 0
|
|
470
|
+
* ```
|
|
471
|
+
* @category Lifecycle
|
|
472
|
+
*/
|
|
473
|
+
destroy(): Persister;
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* The getStats method provides a set of statistics about the Persister, and
|
|
477
|
+
* is used for debugging purposes.
|
|
478
|
+
*
|
|
479
|
+
* The PersisterStats object contains a count of the number of times the
|
|
480
|
+
* Persister has loaded and saved data.
|
|
481
|
+
*
|
|
482
|
+
* The statistics are only populated in a debug build: production builds
|
|
483
|
+
* return an empty object. The method is intended to be used during
|
|
484
|
+
* development to ensure your persistence layer is acting as expected, for
|
|
485
|
+
* example.
|
|
486
|
+
*
|
|
487
|
+
* @returns A PersisterStats object containing Persister load and save
|
|
488
|
+
* statistics.
|
|
489
|
+
* @example
|
|
490
|
+
* This example gets the load and save statistics of a Persister object.
|
|
491
|
+
* Remember that the startAutoLoad method invokes an explicit load when it
|
|
492
|
+
* starts, and the startAutoSave method invokes an explicit save when it
|
|
493
|
+
* starts - so those numbers are included in addition to the loads and saves
|
|
494
|
+
* invoked by changes to the Store and to the underlying storage.
|
|
495
|
+
*
|
|
496
|
+
* ```js
|
|
497
|
+
* const store = createStore();
|
|
498
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
499
|
+
*
|
|
500
|
+
* await persister.startAutoLoad({pets: {fido: {species: 'dog'}}});
|
|
501
|
+
* await persister.startAutoSave();
|
|
502
|
+
*
|
|
503
|
+
* store.setTables({pets: {felix: {species: 'cat'}}});
|
|
504
|
+
* // ...
|
|
505
|
+
*
|
|
506
|
+
* sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
|
|
507
|
+
* // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
|
|
508
|
+
* // ...
|
|
509
|
+
*
|
|
510
|
+
* console.log(persister.getStats());
|
|
511
|
+
* // -> {loads: 2, saves: 2}
|
|
512
|
+
*
|
|
513
|
+
* persister.destroy();
|
|
514
|
+
* sessionStorage.clear();
|
|
515
|
+
* ```
|
|
516
|
+
* @category Development
|
|
517
|
+
*/
|
|
518
|
+
getStats(): PersisterStats;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* The createSessionPersister function creates a Persister object that can
|
|
523
|
+
* persist the Store to the browser's session storage.
|
|
524
|
+
*
|
|
525
|
+
* As well as providing a reference to the Store to persist, you must provide a
|
|
526
|
+
* `storageName` parameter which is unique to your application. This is the key
|
|
527
|
+
* that the browser uses to identify the storage location.
|
|
528
|
+
*
|
|
529
|
+
* @param store The Store to persist.
|
|
530
|
+
* @param storageName The unique key to identify the storage location.
|
|
531
|
+
* @returns A reference to the new Persister object.
|
|
532
|
+
* @example
|
|
533
|
+
* This example creates a Persister object and persists the Store to the
|
|
534
|
+
* browser's session storage.
|
|
535
|
+
*
|
|
536
|
+
* ```js
|
|
537
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
538
|
+
* const persister = createSessionPersister(store, 'pets');
|
|
539
|
+
*
|
|
540
|
+
* await persister.save();
|
|
541
|
+
* console.log(sessionStorage.getItem('pets'));
|
|
542
|
+
* // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
|
|
543
|
+
*
|
|
544
|
+
* persister.destroy();
|
|
545
|
+
* sessionStorage.clear();
|
|
546
|
+
* ```
|
|
547
|
+
* @category Creation
|
|
548
|
+
*/
|
|
549
|
+
export function createSessionPersister(
|
|
550
|
+
store: Store,
|
|
551
|
+
storageName: string,
|
|
552
|
+
): Persister;
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* The createLocalPersister function creates a Persister object that can
|
|
556
|
+
* persist the Store to the browser's local storage.
|
|
557
|
+
*
|
|
558
|
+
* As well as providing a reference to the Store to persist, you must provide a
|
|
559
|
+
* `storageName` parameter which is unique to your application. This is the key
|
|
560
|
+
* that the browser uses to identify the storage location.
|
|
561
|
+
*
|
|
562
|
+
* @param store The Store to persist.
|
|
563
|
+
* @param storageName The unique key to identify the storage location.
|
|
564
|
+
* @returns A reference to the new Persister object.
|
|
565
|
+
* @example
|
|
566
|
+
* This example creates a Persister object and persists the Store to the
|
|
567
|
+
* browser's local storage.
|
|
568
|
+
*
|
|
569
|
+
* ```js
|
|
570
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
571
|
+
* const persister = createLocalPersister(store, 'pets');
|
|
572
|
+
*
|
|
573
|
+
* await persister.save();
|
|
574
|
+
* console.log(localStorage.getItem('pets'));
|
|
575
|
+
* // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
|
|
576
|
+
*
|
|
577
|
+
* persister.destroy();
|
|
578
|
+
* localStorage.clear();
|
|
579
|
+
* ```
|
|
580
|
+
* @category Creation
|
|
581
|
+
*/
|
|
582
|
+
export function createLocalPersister(
|
|
583
|
+
store: Store,
|
|
584
|
+
storageName: string,
|
|
585
|
+
): Persister;
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* The createRemotePersister function creates a Persister object that can
|
|
589
|
+
* persist the Store to a remote server.
|
|
590
|
+
*
|
|
591
|
+
* As well as providing a reference to the Store to persist, you must provide
|
|
592
|
+
* `loadUrl` and `saveUrl` parameters. These identify the endpoints of the
|
|
593
|
+
* server that support the `GET` method (to fetch the Store JSON to load) and
|
|
594
|
+
* the `POST` method (to send the Store JSON to save) respectively.
|
|
595
|
+
*
|
|
596
|
+
* For when you choose to enable automatic loading for the Persister (with the
|
|
597
|
+
* startAutoLoad method), it will poll the loadUrl for changes. The
|
|
598
|
+
* `autoLoadIntervalSeconds` method is used to indicate how often to do this.
|
|
599
|
+
*
|
|
600
|
+
* @param store The Store to persist.
|
|
601
|
+
* @param loadUrl The endpoint that supports a `GET` method to load JSON.
|
|
602
|
+
* @param saveUrl The endpoint that supports a `POST` method to save JSON.
|
|
603
|
+
* @param autoLoadIntervalSeconds How often to poll the `loadUrl` when
|
|
604
|
+
* automatically loading changes from the server.
|
|
605
|
+
* @returns A reference to the new Persister object.
|
|
606
|
+
* @example
|
|
607
|
+
* This example creates a Persister object and persists the Store to a remote
|
|
608
|
+
* server.
|
|
609
|
+
*
|
|
610
|
+
* ```js yolo
|
|
611
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
612
|
+
* const persister = createRemotePersister(
|
|
613
|
+
* store,
|
|
614
|
+
* 'https://example.com/load',
|
|
615
|
+
* 'https://example.com/save',
|
|
616
|
+
* 5,
|
|
617
|
+
* );
|
|
618
|
+
*
|
|
619
|
+
* await persister.save();
|
|
620
|
+
* // Store JSON will be sent to server in a POST request.
|
|
621
|
+
*
|
|
622
|
+
* await persister.load();
|
|
623
|
+
* // Store JSON will be fetched from server with a GET request.
|
|
624
|
+
*
|
|
625
|
+
* persister.destroy();
|
|
626
|
+
* ```
|
|
627
|
+
* @category Creation
|
|
628
|
+
*/
|
|
629
|
+
export function createRemotePersister(
|
|
630
|
+
store: Store,
|
|
631
|
+
loadUrl: string,
|
|
632
|
+
saveUrl: string,
|
|
633
|
+
autoLoadIntervalSeconds: number,
|
|
634
|
+
): Persister;
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* The createFilePersister function creates a Persister object that can persist
|
|
638
|
+
* the Store to a local file (in an appropriate environment).
|
|
639
|
+
*
|
|
640
|
+
* As well as providing a reference to the Store to persist, you must provide
|
|
641
|
+
* `filePath` parameter which identifies the file to persist it to.
|
|
642
|
+
*
|
|
643
|
+
* @param store The Store to persist.
|
|
644
|
+
* @param filePath The location of the local file to persist the Store to.
|
|
645
|
+
* @returns A reference to the new Persister object.
|
|
646
|
+
* @example
|
|
647
|
+
* This example creates a Persister object and persists the Store to a local
|
|
648
|
+
* file.
|
|
649
|
+
*
|
|
650
|
+
* ```js yolo
|
|
651
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
652
|
+
* const persister = createFilePersister(store, '/app/persisted.json');
|
|
653
|
+
*
|
|
654
|
+
* await persister.save();
|
|
655
|
+
* // Store JSON will be saved to the file.
|
|
656
|
+
*
|
|
657
|
+
* await persister.load();
|
|
658
|
+
* // Store JSON will be loaded from the file.
|
|
659
|
+
*
|
|
660
|
+
* persister.destroy();
|
|
661
|
+
* ```
|
|
662
|
+
* @category Creation
|
|
663
|
+
*/
|
|
664
|
+
export function createFilePersister(store: Store, filePath: string): Persister;
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* The createCustomPersister function creates a Persister object that you can
|
|
668
|
+
* configure to persist the Store in any way you wish.
|
|
669
|
+
*
|
|
670
|
+
* As well as providing a reference to the Store to persist, you must provide
|
|
671
|
+
* functions that handle how to fetch, write, and listen to, the persistence
|
|
672
|
+
* layer.
|
|
673
|
+
*
|
|
674
|
+
* The other creation functions (such as the createSessionPersister function and
|
|
675
|
+
* createFilePersister function, for example) all use this function under the
|
|
676
|
+
* covers. See those implementations for ideas on how to implement your own
|
|
677
|
+
* Persister types.
|
|
678
|
+
*
|
|
679
|
+
* @param store The Store to persist.
|
|
680
|
+
* @param getPersisted An asynchronous function which will fetch JSON from the
|
|
681
|
+
* persistence layer (or `null` or `undefined` if not present).
|
|
682
|
+
* @param setPersisted An asynchronous function which will send JSON to the
|
|
683
|
+
* persistence layer.
|
|
684
|
+
* @param startListeningToPersisted A function that will register a `didChange`
|
|
685
|
+
* listener on underlying changes to the persistence layer.
|
|
686
|
+
* @param stopListeningToPersisted A function that will unregister the listener
|
|
687
|
+
* from the underlying changes to the persistence layer.
|
|
688
|
+
* @returns A reference to the new Persister object.
|
|
689
|
+
* @example
|
|
690
|
+
* This example creates a custom Persister object and persists the Store to a
|
|
691
|
+
* local string called `storeJson` and which would automatically load by polling
|
|
692
|
+
* for changes every second.
|
|
693
|
+
*
|
|
694
|
+
* ```js
|
|
695
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
696
|
+
* let storeJson;
|
|
697
|
+
* let interval;
|
|
698
|
+
*
|
|
699
|
+
* const persister = createCustomPersister(
|
|
700
|
+
* store,
|
|
701
|
+
* async () => storeJson,
|
|
702
|
+
* async (json) => (storeJson = json),
|
|
703
|
+
* (didChange) => (interval = setInterval(didChange, 1000)),
|
|
704
|
+
* () => clearInterval(interval),
|
|
705
|
+
* );
|
|
706
|
+
*
|
|
707
|
+
* await persister.save();
|
|
708
|
+
* console.log(storeJson);
|
|
709
|
+
* // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
|
|
710
|
+
*
|
|
711
|
+
* storeJson = '[{"pets":{"fido":{"species":"dog","color":"brown"}}},{}]';
|
|
712
|
+
* await persister.load();
|
|
713
|
+
*
|
|
714
|
+
* console.log(store.getTables());
|
|
715
|
+
* // -> {pets: {fido: {species: 'dog', color: 'brown'}}}
|
|
716
|
+
*
|
|
717
|
+
* persister.destroy();
|
|
718
|
+
* ```
|
|
719
|
+
* @category Creation
|
|
720
|
+
*/
|
|
721
|
+
export function createCustomPersister(
|
|
722
|
+
store: Store,
|
|
723
|
+
getPersisted: () => Promise<string | null | undefined>,
|
|
724
|
+
setPersisted: (json: string) => Promise<void>,
|
|
725
|
+
startListeningToPersisted: (didChange: Callback) => void,
|
|
726
|
+
stopListeningToPersisted: Callback,
|
|
727
|
+
): Persister;
|