tinybase 6.1.0-beta.1 → 6.1.0-beta.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.
Files changed (108) hide show
  1. package/@types/common/index.d.ts +4 -4
  2. package/@types/common/with-schemas/index.d.ts +4 -4
  3. package/@types/mergeable-store/index.d.ts +45 -20
  4. package/@types/mergeable-store/with-schemas/index.d.ts +49 -21
  5. package/@types/persisters/index.d.ts +1 -1
  6. package/@types/persisters/with-schemas/index.d.ts +1 -1
  7. package/index.js +19 -11
  8. package/indexes/index.js +15 -3
  9. package/indexes/with-schemas/index.js +15 -3
  10. package/mergeable-store/index.js +4 -8
  11. package/mergeable-store/with-schemas/index.js +4 -8
  12. package/min/index.js +1 -1
  13. package/min/index.js.gz +0 -0
  14. package/min/indexes/index.js +1 -1
  15. package/min/indexes/index.js.gz +0 -0
  16. package/min/indexes/with-schemas/index.js +1 -1
  17. package/min/indexes/with-schemas/index.js.gz +0 -0
  18. package/min/mergeable-store/index.js +1 -1
  19. package/min/mergeable-store/index.js.gz +0 -0
  20. package/min/mergeable-store/with-schemas/index.js +1 -1
  21. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  22. package/min/with-schemas/index.js +1 -1
  23. package/min/with-schemas/index.js.gz +0 -0
  24. package/package.json +9 -9
  25. package/readme.md +2 -2
  26. package/with-schemas/index.js +19 -11
  27. package/@types/_internal/queries/index.d.cts +0 -0
  28. package/@types/_internal/queries/with-schemas/index.d.cts +0 -22
  29. package/@types/_internal/store/index.d.cts +0 -3
  30. package/@types/_internal/store/with-schemas/index.d.cts +0 -106
  31. package/@types/_internal/ui-react/index.d.cts +0 -0
  32. package/@types/_internal/ui-react/with-schemas/index.d.cts +0 -1130
  33. package/@types/checkpoints/index.d.cts +0 -1059
  34. package/@types/checkpoints/with-schemas/index.d.cts +0 -1151
  35. package/@types/common/index.d.cts +0 -158
  36. package/@types/common/with-schemas/index.d.cts +0 -158
  37. package/@types/index.d.cts +0 -17
  38. package/@types/indexes/index.d.cts +0 -1064
  39. package/@types/indexes/with-schemas/index.d.cts +0 -1210
  40. package/@types/mergeable-store/index.d.cts +0 -1139
  41. package/@types/mergeable-store/with-schemas/index.d.cts +0 -1628
  42. package/@types/metrics/index.d.cts +0 -917
  43. package/@types/metrics/with-schemas/index.d.cts +0 -1004
  44. package/@types/persisters/index.d.cts +0 -1877
  45. package/@types/persisters/persister-automerge/index.d.cts +0 -165
  46. package/@types/persisters/persister-automerge/with-schemas/index.d.cts +0 -180
  47. package/@types/persisters/persister-browser/index.d.cts +0 -185
  48. package/@types/persisters/persister-browser/with-schemas/index.d.cts +0 -208
  49. package/@types/persisters/persister-cr-sqlite-wasm/index.d.cts +0 -159
  50. package/@types/persisters/persister-cr-sqlite-wasm/with-schemas/index.d.cts +0 -178
  51. package/@types/persisters/persister-durable-object-storage/index.d.cts +0 -122
  52. package/@types/persisters/persister-durable-object-storage/with-schemas/index.d.cts +0 -136
  53. package/@types/persisters/persister-electric-sql/index.d.cts +0 -185
  54. package/@types/persisters/persister-electric-sql/with-schemas/index.d.cts +0 -204
  55. package/@types/persisters/persister-expo-sqlite/index.d.cts +0 -186
  56. package/@types/persisters/persister-expo-sqlite/with-schemas/index.d.cts +0 -205
  57. package/@types/persisters/persister-file/index.d.cts +0 -94
  58. package/@types/persisters/persister-file/with-schemas/index.d.cts +0 -107
  59. package/@types/persisters/persister-indexed-db/index.d.cts +0 -120
  60. package/@types/persisters/persister-indexed-db/with-schemas/index.d.cts +0 -135
  61. package/@types/persisters/persister-libsql/index.d.cts +0 -158
  62. package/@types/persisters/persister-libsql/with-schemas/index.d.cts +0 -177
  63. package/@types/persisters/persister-partykit-client/index.d.cts +0 -195
  64. package/@types/persisters/persister-partykit-client/with-schemas/index.d.cts +0 -210
  65. package/@types/persisters/persister-partykit-server/index.d.cts +0 -650
  66. package/@types/persisters/persister-partykit-server/with-schemas/index.d.cts +0 -695
  67. package/@types/persisters/persister-pglite/index.d.cts +0 -177
  68. package/@types/persisters/persister-pglite/with-schemas/index.d.cts +0 -196
  69. package/@types/persisters/persister-postgres/index.d.cts +0 -166
  70. package/@types/persisters/persister-postgres/with-schemas/index.d.cts +0 -185
  71. package/@types/persisters/persister-powersync/index.d.cts +0 -174
  72. package/@types/persisters/persister-powersync/with-schemas/index.d.cts +0 -193
  73. package/@types/persisters/persister-remote/index.d.cts +0 -117
  74. package/@types/persisters/persister-remote/with-schemas/index.d.cts +0 -133
  75. package/@types/persisters/persister-sqlite-wasm/index.d.cts +0 -175
  76. package/@types/persisters/persister-sqlite-wasm/with-schemas/index.d.cts +0 -195
  77. package/@types/persisters/persister-sqlite3/index.d.cts +0 -176
  78. package/@types/persisters/persister-sqlite3/with-schemas/index.d.cts +0 -195
  79. package/@types/persisters/persister-yjs/index.d.cts +0 -161
  80. package/@types/persisters/persister-yjs/with-schemas/index.d.cts +0 -176
  81. package/@types/persisters/with-schemas/index.d.cts +0 -2054
  82. package/@types/queries/index.d.cts +0 -3695
  83. package/@types/queries/with-schemas/index.d.cts +0 -4016
  84. package/@types/relationships/index.d.cts +0 -1320
  85. package/@types/relationships/with-schemas/index.d.cts +0 -1474
  86. package/@types/store/index.d.cts +0 -7598
  87. package/@types/store/with-schemas/index.d.cts +0 -9278
  88. package/@types/synchronizers/index.d.cts +0 -485
  89. package/@types/synchronizers/synchronizer-broadcast-channel/index.d.cts +0 -121
  90. package/@types/synchronizers/synchronizer-broadcast-channel/with-schemas/index.d.cts +0 -137
  91. package/@types/synchronizers/synchronizer-local/index.d.cts +0 -95
  92. package/@types/synchronizers/synchronizer-local/with-schemas/index.d.cts +0 -114
  93. package/@types/synchronizers/synchronizer-ws-client/index.d.cts +0 -160
  94. package/@types/synchronizers/synchronizer-ws-client/with-schemas/index.d.cts +0 -179
  95. package/@types/synchronizers/synchronizer-ws-server/index.d.cts +0 -736
  96. package/@types/synchronizers/synchronizer-ws-server/with-schemas/index.d.cts +0 -765
  97. package/@types/synchronizers/synchronizer-ws-server-durable-object/index.d.cts +0 -311
  98. package/@types/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.d.cts +0 -349
  99. package/@types/synchronizers/synchronizer-ws-server-simple/index.d.cts +0 -144
  100. package/@types/synchronizers/synchronizer-ws-server-simple/with-schemas/index.d.cts +0 -144
  101. package/@types/synchronizers/with-schemas/index.d.cts +0 -503
  102. package/@types/ui-react/index.d.cts +0 -16640
  103. package/@types/ui-react/with-schemas/index.d.cts +0 -17281
  104. package/@types/ui-react-dom/index.d.cts +0 -1862
  105. package/@types/ui-react-dom/with-schemas/index.d.cts +0 -1994
  106. package/@types/ui-react-inspector/index.d.cts +0 -79
  107. package/@types/ui-react-inspector/with-schemas/index.d.cts +0 -1985
  108. package/@types/with-schemas/index.d.cts +0 -17
@@ -1,2054 +0,0 @@
1
- /**
2
- * The persisters module of the TinyBase project provides a simple framework for
3
- * saving and loading Store and MergeableStore data, to and from different
4
- * destinations, or underlying storage types.
5
- *
6
- * Many entry points are provided (in separately installed modules), each of
7
- * which returns different types of Persister that can load and save a Store.
8
- * Between them, these allow you to store your TinyBase data locally, remotely,
9
- * to SQLite and PostgreSQL databases, and across synchronization boundaries
10
- * with CRDT frameworks.
11
- *
12
- * |Persister|Storage|Store|MergeableStore
13
- * |-|-|-|-|
14
- * |SessionPersister|Browser session storage|Yes|Yes
15
- * |LocalPersister|Browser local storage|Yes|Yes
16
- * |FilePersister|Local file (where possible)|Yes|Yes
17
- * |IndexedDbPersister|Browser IndexedDB|Yes|No
18
- * |RemotePersister|Remote server|Yes|No
19
- * |Sqlite3Persister|SQLite in Node, via [sqlite3](https://github.com/TryGhost/node-sqlite3)|Yes|Yes*
20
- * |SqliteWasmPersister|SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm)|Yes|Yes*
21
- * |ExpoSqlitePersister|SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite)|Yes|Yes*
22
- * |PostgresPersister|PostgreSQL, via [postgres](https://github.com/porsager/postgres)|Yes|Yes*
23
- * |PglitePersister|PostgreSQL, via [PGlite](https://github.com/electric-sql/pglite)|Yes|Yes*
24
- * |CrSqliteWasmPersister|SQLite CRDTs, via [cr-sqlite-wasm](https://github.com/vlcn-io/cr-sqlite)|Yes|No
25
- * |ElectricSqlPersister|Electric SQL, via [electric-sql](https://github.com/electric-sql/electric)|Yes|No
26
- * |LibSqlPersister|LibSQL for Turso, via [libsql-client](https://github.com/tursodatabase/libsql-client-ts)|Yes|No
27
- * |PowerSyncPersister|PowerSync, via [powersync-sdk](https://github.com/powersync-ja/powersync-js)|Yes|No
28
- * |YjsPersister|Yjs CRDTs, via [yjs](https://github.com/yjs/yjs)|Yes|No
29
- * |AutomergePersister|Automerge CRDTs, via [automerge-repo](https://github.com/automerge/automerge-repo)|Yes|No
30
- * |PartyKitPersister|[PartyKit](https://www.partykit.io/), via the persister-partykit-server module|Yes|No|
31
- *
32
- * (*) Note that SQLite- and PostgreSQL-based Persisters can currently only
33
- * persist MergeableStore data when used with the JSON-based DpcJson mode, and
34
- * not when using the DpcTabular mode.
35
- *
36
- * Since persistence requirements can be different for every app, the
37
- * createCustomPersister function in this module can also be used to easily
38
- * create a fully customized way to save and load Store data.
39
- *
40
- * Similarly, the createCustomSqlitePersister function and
41
- * createCustomPostgreSqlPersister function can be used to build Persister objects
42
- * against SQLite and PostgreSQL SDKs (or forks) that are not already included
43
- * with TinyBase.
44
- * @see Persistence guides
45
- * @see Countries demo
46
- * @see Todo App demos
47
- * @see Drawing demo
48
- * @packageDocumentation
49
- * @module persisters
50
- * @since v1.0.0
51
- */
52
- import type {TableIdFromSchema} from '../../_internal/store/with-schemas/index.d.cts';
53
- import type {
54
- MergeableChanges,
55
- MergeableContent,
56
- MergeableStore,
57
- } from '../../mergeable-store/with-schemas/index.d.cts';
58
- import type {
59
- Changes,
60
- Content,
61
- OptionalSchemas,
62
- OptionalTablesSchema,
63
- Store,
64
- } from '../../store/with-schemas/index.d.cts';
65
- import type {Id} from '../../with-schemas/index.d.cts';
66
-
67
- /**
68
- * The Status enum is used to indicate whether a Persister is idle, or loading or
69
- * saving data.
70
- *
71
- * The enum is intended to be used to understand the status of the Persister in
72
- * conjunction with the getStatus and addStatusListener methods.
73
- *
74
- * Note that a Persister cannot be loading and saving data at the same time.
75
- * @category Lifecycle
76
- * @since v5.3.0
77
- */
78
- export const enum Status {
79
- /**
80
- * Indicates that the Persister is neither loading or saving data.
81
- * @category Enum
82
- * @since v5.3.0
83
- */
84
- Idle = 0,
85
- /**
86
- * Indicates that the Persister is loading data.
87
- * @category Enum
88
- * @since v5.3.0
89
- */
90
- Loading = 1,
91
- /**
92
- * Indicates that the Persister is saving data.
93
- * @category Enum
94
- * @since v5.3.0
95
- */
96
- Saving = 2,
97
- }
98
-
99
- /**
100
- * The Persists enum is used to indicate whether a Persister can support a
101
- * regular Store, a MergeableStore, or both.
102
- *
103
- * The enum is intended to be used by the author of a Persister to indicate
104
- * which types of store can be persisted. If you discover type errors when
105
- * trying to instantiate a Persister, it is most likely that you are passing in
106
- * an unsupported type of store.
107
- *
108
- * See the createCustomPersister method for an example of this enum being used.
109
- * @category Mergeable
110
- * @since v5.0.0
111
- */
112
- export const enum Persists {
113
- /**
114
- * Indicates that only a regular Store can be supported by a Persister.
115
- * @category Enum
116
- * @since v5.0.0
117
- */
118
- StoreOnly = 1,
119
- /**
120
- * Indicates that only a MergeableStore can be supported by a Persister.
121
- * @category Enum
122
- * @since v5.0.0
123
- */
124
- MergeableStoreOnly = 2,
125
- /**
126
- * Indicates that either a regular Store or a MergeableStore can be supported
127
- * by a Persister.
128
- * @category Enum
129
- * @since v5.0.0
130
- */
131
- StoreOrMergeableStore = 3,
132
- }
133
-
134
- /**
135
- * The PersistedStore type is a generic representation of the type of store
136
- * being handled by a Persister.
137
- *
138
- * This has schema-based typing. The following is a simplified representation:
139
- *
140
- * ```ts override
141
- * export type PersistedStore<Persist extends Persists = Persists.StoreOnly> =
142
- * Persist extends Persists.StoreOrMergeableStore
143
- * ? Store | MergeableStore
144
- * : Persist extends Persists.MergeableStoreOnly
145
- * ? MergeableStore
146
- * : Store;
147
- * ```
148
- *
149
- * Using the values of the Persists enum, the generic parameter indicates
150
- * whether the Persister is handling a regular Store, a MergeableStore, or
151
- * either.
152
- *
153
- * If the generic parameter is unspecified, the StoreOnly enum value is used,
154
- * meaning that PersistedStore is equivalent to a regular Store.
155
- * @category Mergeable
156
- * @since v5.0.0
157
- */
158
- export type PersistedStore<
159
- Schemas extends OptionalSchemas,
160
- Persist extends Persists = Persists.StoreOnly,
161
- > = Persist extends Persists.StoreOrMergeableStore
162
- ? Store<Schemas> | MergeableStore<Schemas>
163
- : Persist extends Persists.MergeableStoreOnly
164
- ? MergeableStore<Schemas>
165
- : Store<Schemas>;
166
-
167
- /**
168
- * The PersistedContent type is a generic representation of the content in the
169
- * type of store being handled by a Persister.
170
- *
171
- * This has schema-based typing. The following is a simplified representation:
172
- *
173
- * ```ts override
174
- * export type PersistedContent<Persist extends Persists = Persists.StoreOnly> =
175
- * Persist extends Persists.StoreOrMergeableStore
176
- * ? Content | MergeableContent
177
- * : Persist extends Persists.MergeableStoreOnly
178
- * ? MergeableContent
179
- * : Content;
180
- * ```
181
- *
182
- * Using the values of the Persists enum, the generic parameter indicates
183
- * whether the Persister is handling content from a regular Store (the Content
184
- * type), a MergeableStore (the MergeableContent type), or either (the union of
185
- * the two).
186
- *
187
- * If the generic parameter is unspecified, the StoreOnly enum value is used,
188
- * meaning that PersistedContent is equivalent to the Content type.
189
- * @category Mergeable
190
- * @since v5.0.0
191
- */
192
- export type PersistedContent<
193
- Schemas extends OptionalSchemas,
194
- Persist extends Persists = Persists.StoreOnly,
195
- > = Persist extends Persists.StoreOrMergeableStore
196
- ? Content<Schemas> | MergeableContent<Schemas>
197
- : Persist extends Persists.MergeableStoreOnly
198
- ? MergeableContent<Schemas>
199
- : Content<Schemas>;
200
-
201
- /**
202
- * The PersistedChanges type is a generic representation of changes made to the
203
- * type of store being handled by a Persister.
204
- *
205
- * This has schema-based typing. The following is a simplified representation:
206
- *
207
- * ```ts override
208
- * export type PersistedChanges<
209
- * Persist extends Persists = Persists.StoreOnly,
210
- * Hashed extends boolean = false,
211
- * > = Persist extends Persists.StoreOrMergeableStore
212
- * ? Changes | MergeableChanges<Hashed>
213
- * : Persist extends Persists.MergeableStoreOnly
214
- * ? MergeableChanges<Hashed>
215
- * : Changes;
216
- * ```
217
- *
218
- * Using the values of the Persists enum, the generic parameter indicates
219
- * whether the Persister is handling changes for a regular Store (the Changes
220
- * type), a MergeableStore (the MergeableChanges type), or either (the union of
221
- * the two).
222
- * @category Mergeable
223
- * @since v5.0.0
224
- */
225
- export type PersistedChanges<
226
- Schemas extends OptionalSchemas,
227
- Persist extends Persists = Persists.StoreOnly,
228
- > = Persist extends Persists.StoreOrMergeableStore
229
- ? Changes<Schemas> | MergeableChanges<Schemas>
230
- : Persist extends Persists.MergeableStoreOnly
231
- ? MergeableChanges<Schemas>
232
- : Changes<Schemas>;
233
-
234
- /**
235
- * A PersisterListener is a generic representation of the callback that lets a
236
- * Persister inform the store that a change has happened to the underlying data.
237
- *
238
- * This has schema-based typing. The following is a simplified representation:
239
- *
240
- * ```ts override
241
- * export type PersisterListener<Persist extends Persists = Persists.StoreOnly> = (
242
- * content?: PersistedContent<Persist>,
243
- * changes?: PersistedChanges<Persist>,
244
- * ) => void;
245
- * ```
246
- *
247
- * Using the values of the Persists enum, the generic parameter indicates
248
- * whether the Persister is handling content and changes from a regular Store, a
249
- * MergeableStore, or either.
250
- *
251
- * If the listener is called with the `changes` parameter, it will be used to
252
- * make an incremental change to the Store. If not, but the `content` parameter
253
- * is available, that will be used to make a wholesale change to the Store. If
254
- * neither are present, the content will be loaded using the Persister's load
255
- * method. Prior to v5.0, these parameters were callbacks and the overall type
256
- * was non-generic.
257
- * @param content If provided, this is a Content object from the the Persister
258
- * that will be used to immediately wholesale update the Store.
259
- * @param changes If provided, this is a Changes object from the the Persister
260
- * that will be used to immediately incrementally update the Store. This takes
261
- * priority over the content argument above if present.
262
- * @category Creation
263
- * @since v4.0.0
264
- */
265
- export type PersisterListener<
266
- Schemas extends OptionalSchemas,
267
- Persist extends Persists = Persists.StoreOnly,
268
- > = (
269
- content?: PersistedContent<Schemas, Persist>,
270
- changes?: PersistedChanges<Schemas, Persist>,
271
- ) => void;
272
-
273
- /**
274
- * The StatusListener type describes a function that is used to listen to
275
- * changes to the loading and saving status of the Persister.
276
- *
277
- * This has schema-based typing. The following is a simplified representation:
278
- *
279
- * ```ts override
280
- * export type StatusListener<Persist extends Persists = Persists.StoreOnly> = (
281
- * persister: Persister<Persist>,
282
- * status: Status,
283
- * ) => void;
284
- * ```
285
- *
286
- * A StatusListener is provided when using the addStatusListener method. See
287
- * that method for specific examples.
288
- *
289
- * When called, a StatusListener is given a reference to the Persister and the
290
- * new Status: 0 means now idle, 1 means now loading, and 2 means now saving.
291
- * @param persister A reference to the Persister that changed.
292
- * @param status The new loading or saving Status.
293
- * @category Listener
294
- * @since v5.3.0
295
- */
296
- export type StatusListener<
297
- Schemas extends OptionalSchemas,
298
- Persist extends Persists = Persists.StoreOnly,
299
- > = (persister: Persister<Schemas, Persist>, status: Status) => void;
300
-
301
- /**
302
- * The PersisterStats type describes the number of times a Persister object has
303
- * loaded or saved data.
304
- *
305
- * A PersisterStats object is returned from the getStats method.
306
- * @category Development
307
- * @since v1.0.0
308
- */
309
- export type PersisterStats = {
310
- /**
311
- * The number of times data has been loaded.
312
- * @category Stat
313
- * @since v1.0.0
314
- */
315
- loads: number;
316
- /**
317
- * The number of times data has been saved.
318
- * @category Stat
319
- * @since v1.0.0
320
- */
321
- saves: number;
322
- };
323
-
324
- /**
325
- * The DatabasePersisterConfig type describes the configuration of a
326
- * database-oriented Persister, such as those for SQLite and PostgreSQL.
327
- *
328
- * This has schema-based typing. The following is a simplified representation:
329
- *
330
- * ```ts override
331
- * DpcJson | DpcTabular;
332
- * ```
333
- *
334
- * There are two modes for persisting a Store with a database:
335
- *
336
- * - A JSON serialization of the whole Store, which is stored in a single row of
337
- * a table (normally called `tinybase`) within the database. This is
338
- * configured by providing a DpcJson object.
339
- * - A tabular mapping of Table Ids to database table names (and vice-versa).
340
- * Values are stored in a separate special table (normally called
341
- * `tinybase_values`). This is configured by providing a DpcTabular object.
342
- *
343
- * Please see the DpcJson and DpcTabular type documentation for more detail on
344
- * each. If not specified otherwise, JSON serialization will be used for
345
- * persistence.
346
- *
347
- * Changes made to the database (outside of this Persister) are picked up
348
- * immediately if they are made via the same connection or library that it is
349
- * using. If the database is being changed by another client, the Persister
350
- * needs to poll for changes. Hence both configuration types also contain an
351
- * `autoLoadIntervalSeconds` property which indicates how often it should do
352
- * that. This defaults to 1 second.
353
- *
354
- * Note that all the nested types within this type have a 'Dpc' prefix, short
355
- * for 'DatabasePersisterConfig'.
356
- * @example
357
- * When applied to a database Persister, this DatabasePersisterConfig will load
358
- * and save a JSON serialization from and to a table called `my_tinybase`,
359
- * polling the database every 2 seconds. See DpcJson for more details on these
360
- * settings.
361
- *
362
- * ```js
363
- * import type {DatabasePersisterConfig} from 'tinybase';
364
- *
365
- * export const databasePersisterConfig: DatabasePersisterConfig = {
366
- * mode: 'json',
367
- * storeTableName: 'my_tinybase',
368
- * autoLoadIntervalSeconds: 2,
369
- * };
370
- * ```
371
- * @example
372
- * When applied to a database Persister, this DatabasePersisterConfig will load
373
- * and save tabular data from and to tables specified in the `load` and `save`
374
- * mappings. See DpcTabular for more details on these settings.
375
- *
376
- * ```js
377
- * import type {DatabasePersisterConfig} from 'tinybase';
378
- *
379
- * export const databasePersisterConfig: DatabasePersisterConfig = {
380
- * mode: 'tabular',
381
- * tables: {
382
- * load: {petsInDb: 'pets', speciesInDb: 'species'},
383
- * save: {pets: 'petsInDb', species: 'speciesInDb'},
384
- * },
385
- * };
386
- * ```
387
- * @category Configuration
388
- * @since v4.0.0
389
- */
390
- export type DatabasePersisterConfig<Schemas extends OptionalSchemas> =
391
- | DpcJson
392
- | DpcTabular<Schemas[0]>;
393
-
394
- /**
395
- * The DpcJson type describes the configuration of a database-oriented Persister
396
- * operating in serialized JSON mode.
397
- *
398
- * One setting is the `storeTableName` property, which indicates the name of a
399
- * table in the database which will be used to serialize the Store content into.
400
- * It defaults to `tinybase`.
401
- *
402
- * That table in the database will be given two columns: a primary key column
403
- * called `_id`, and one called `store`. (These column names can be changed
404
- * using the `rowIdColumnName` and `storeColumnName` settings). The Persister
405
- * will place a single row in this table with `_` in the `_id` column, and the
406
- * JSON serialization in the `store` column, something like the following.
407
- *
408
- * ```
409
- * > SELECT * FROM tinybase;
410
- * +-----+-----------------------------------------------------+
411
- * | _id | store |
412
- * +-----+-----------------------------------------------------+
413
- * | _ | [{"pets":{"fido":{"species":"dog"}}},{"open":true}] |
414
- * +-----+-----------------------------------------------------+
415
- * ```
416
- *
417
- * The 'Dpc' prefix indicates that this type is used within the
418
- * DatabasePersisterConfig type.
419
- * @example
420
- * When applied to a database Persister, this DatabasePersisterConfig will load
421
- * and save a JSON serialization from and to a table called `tinybase_json`.
422
- *
423
- * ```js
424
- * import type {DatabasePersisterConfig} from 'tinybase';
425
- *
426
- * export const databasePersisterConfig: DatabasePersisterConfig = {
427
- * mode: 'json',
428
- * storeTableName: 'tinybase_json',
429
- * };
430
- * ```
431
- * @category Configuration
432
- * @since v4.0.0
433
- */
434
- export type DpcJson = {
435
- /**
436
- * The mode to be used for persisting the Store to the database, in this case
437
- * JSON serialization. See the DpcTabular type for the alternative tabular
438
- * mapping mode.
439
- * @category Configuration
440
- * @since v4.0.0
441
- */
442
- mode: 'json';
443
- /**
444
- * An optional string which indicates the name of a table in the database
445
- * which will be used to serialize the Store content into. It defaults to
446
- * `tinybase`.
447
- * @category Configuration
448
- * @since v4.0.0
449
- */
450
- storeTableName?: string;
451
- /**
452
- * The optional name of the column in the database table that will be used as
453
- * the Id for the Store, defaulting to '_id', since v5.0.
454
- * @category Configuration
455
- * @since v4.0.0
456
- */
457
- storeIdColumnName?: string;
458
- /**
459
- * The optional name of the column in the database table that will be used for
460
- * the JSON of the Store, defaulting to 'store', since v5.0.
461
- * @category Configuration
462
- * @since v4.0.0
463
- */
464
- storeColumnName?: string;
465
- /**
466
- * How often the Persister should poll the database for any changes made to it
467
- * by other clients, defaulting to 1 second.
468
- * @category Configuration
469
- * @since v4.0.0
470
- */
471
- autoLoadIntervalSeconds?: number;
472
- };
473
-
474
- /**
475
- * The DpcTabular type describes the configuration of a database-oriented
476
- * Persister that is operating in tabular mapping mode.
477
- *
478
- * This configuration can only be used when the Persister is persisting a
479
- * regular Store. For those database-oriented Persister types that support
480
- * MergeableStore data, you will need to use JSON-serialization, es described in
481
- * the DpcJson section.
482
- *
483
- * It is important to note that both the tabular mapping in ('save') and out
484
- * ('load') of an underlying database are disabled by default. This is to ensure
485
- * that if you pass in an existing populated database you don't run the
486
- * immediate risk of corrupting or losing all your data.
487
- *
488
- * This configuration therefore takes a `tables` property object (with child
489
- * `load` and `save` property objects) and a `values` property object. These
490
- * indicate how you want to load and save Tables and Values respectively. At
491
- * least one of these two properties are required for the Persister to do
492
- * anything!
493
- *
494
- * Note that if you are planning to both load from and save to a database, it is
495
- * important to make sure that the load and save table mappings are symmetrical.
496
- * For example, consider the following.
497
- *
498
- * ```js
499
- * import type {DatabasePersisterConfig} from 'tinybase';
500
- *
501
- * export const databasePersisterConfig: DatabasePersisterConfig = {
502
- * mode: 'tabular',
503
- * tables: {
504
- * load: {petsInDb: 'pets', speciesInDb: 'species'},
505
- * save: {pets: 'petsInDb', species: 'speciesInDb'},
506
- * },
507
- * };
508
- * ```
509
- *
510
- * See the documentation for the DpcTabularLoad, DpcTabularSave, and
511
- * DpcTabularValues types for more details on how to configure the tabular
512
- * mapping mode.
513
- *
514
- * Columns in SQLite database have no type, and so in this mode, the table can
515
- * contain strings and numbers for Cells and Values, just as TinyBase does.
516
- * Booleans, unfortunately, are stored as 0 or 1 in SQLite, and cannot be
517
- * distinguished from numbers.
518
- *
519
- * In PostgreSQL databases, all Cell and Value columns are expected to be typed
520
- * as `text`, and the strings, booleans, and numbers are all JSON-encoded by the
521
- * Persister.
522
- *
523
- * The 'Dpc' prefix indicates that this type is used within the
524
- * DatabasePersisterConfig type.
525
- * @example
526
- * When applied to a database Persister, this DatabasePersisterConfig will load
527
- * and save Tables data from and to tables specified in the `load` and `save`
528
- * mappings, and Values data from and to a table called `my_tinybase_values`.
529
- *
530
- * ```js
531
- * import type {DatabasePersisterConfig} from 'tinybase';
532
- *
533
- * export const databasePersisterConfig: DatabasePersisterConfig = {
534
- * mode: 'tabular',
535
- * tables: {
536
- * load: {petsInDb: 'pets', speciesInDb: 'species'},
537
- * save: {pets: 'petsInDb', species: 'speciesInDb'},
538
- * },
539
- * values: {
540
- * load: true,
541
- * save: true,
542
- * tableName: 'my_tinybase_values',
543
- * },
544
- * };
545
- * ```
546
- * @category Configuration
547
- * @since v4.0.0
548
- */
549
- export type DpcTabular<Schema extends OptionalTablesSchema> = {
550
- /**
551
- * The mode to be used for persisting the Store to the database, in this case
552
- * tabular mapping. See the DpcJson type for the alternative JSON
553
- * serialization mode.
554
- * @category Configuration
555
- * @since v4.0.0
556
- */
557
- mode: 'tabular';
558
- /**
559
- * The settings for how the Store Tables are mapped to and from the database.
560
- * @category Configuration
561
- * @since v4.0.0
562
- */
563
- tables?: {
564
- /**
565
- * The settings for how the database tables are mapped into the Store Tables
566
- * when loading.
567
- * @category Configuration
568
- * @since v4.0.0
569
- */
570
- load?: DpcTabularLoad<Schema>;
571
- /**
572
- * The settings for how the Store Tables are mapped out to the database
573
- * tables when saving.
574
- * @category Configuration
575
- * @since v4.0.0
576
- */
577
- save?: DpcTabularSave<Schema>;
578
- };
579
- /**
580
- * The settings for how the Store Values are mapped to and from the database.
581
- * @category Configuration
582
- * @since v4.0.0
583
- */
584
- values?: DpcTabularValues;
585
- /**
586
- * How often the Persister should poll the database for any changes made to it
587
- * by other clients, defaulting to 1 second.
588
- * @category Configuration
589
- * @since v4.0.0
590
- */
591
- autoLoadIntervalSeconds?: number;
592
- };
593
-
594
- /**
595
- * The DpcTabularLoad type describes the configuration for loading Tables in a
596
- * database-oriented Persister that is operating in tabular mode.
597
- *
598
- * It is an object where each key is a name of a database table, and the value
599
- * is a child configuration object for how that table should be loaded into the
600
- * Store. The properties of the child configuration object are:
601
- *
602
- * ||Type|Description|
603
- * |-|-|-|
604
- * |`tableId`|Id|The Id of the Store Table into which data from this database table should be loaded.|
605
- * |`rowIdColumnName?`|string|The optional name of the column in the database table that will be used as the Row Ids in the Store Table, defaulting to '_id'.|
606
- *
607
- * As a shortcut, if you do not need to specify a custom `rowIdColumnName`, you
608
- * can simply provide the Id of the Store Table instead of the whole object.
609
- *
610
- * The 'Dpc' prefix indicates that this type is used within the
611
- * DatabasePersisterConfig type.
612
- * @example
613
- * When applied to a database Persister, this DatabasePersisterConfig will load
614
- * the data of two database tables (called 'petsInDb' and 'speciesInDb') into
615
- * two Store Tables (called 'pets' and 'species'). One has a column for the Row
616
- * Id called 'id' and the other defaults it to '_id'.
617
- *
618
- * ```js
619
- * import type {DatabasePersisterConfig} from 'tinybase';
620
- *
621
- * export const databasePersisterConfig: DatabasePersisterConfig = {
622
- * mode: 'tabular',
623
- * tables: {
624
- * load: {
625
- * petsInDb: {tableId: 'pets', rowIdColumnName: 'id'},
626
- * speciesInDb: 'species',
627
- * },
628
- * },
629
- * };
630
- * ```
631
- *
632
- * Imagine database tables that look like this:
633
- *
634
- * ```
635
- * > SELECT * FROM petsInDb;
636
- * +-------+---------+-------+
637
- * | id | species | color |
638
- * +-------+---------+-------+
639
- * | fido | dog | brown |
640
- * | felix | cat | black |
641
- * +-------+---------+-------+
642
- *
643
- * > SELECT * FROM speciesInDb;
644
- * +------+-------+
645
- * | _id | price |
646
- * +------+-------+
647
- * | dog | 5 |
648
- * | cat | 4 |
649
- * +------+-------+
650
- * ```
651
- *
652
- * With the configuration above, this will load into a Store with Tables that
653
- * look like this:
654
- *
655
- * ```json
656
- * {
657
- * "pets": {
658
- * "fido": {"species": "dog", "color": "brown"},
659
- * "felix": {"species": "cat", "color": "black"},
660
- * },
661
- * "species": {
662
- * "dog": {"price": 5},
663
- * "cat": {"price": 4},
664
- * },
665
- * }
666
- * ```
667
- *
668
- * The example above represents what happens with a SQLite Persister. In
669
- * PostgreSQL databases, all Cell and Value columns are expected to be
670
- * typed as `text`, and the strings, booleans, and numbers would be JSON-encoded
671
- * if you queried them.
672
- * @category Configuration
673
- * @since v4.0.0
674
- */
675
- export type DpcTabularLoad<Schema extends OptionalTablesSchema> = {
676
- [tableName: string]:
677
- | {
678
- /**
679
- * The Id of the Store Table into which data from this database table
680
- * should be loaded.
681
- * @category Configuration
682
- * @since v4.0.0
683
- */
684
- tableId: TableIdFromSchema<Schema>;
685
- /**
686
- * The optional name of the column in the database table that will be
687
- * used as the Row Ids in the Store Table, defaulting to '_id'.
688
- * @category Configuration
689
- * @since v4.0.0
690
- */
691
- rowIdColumnName?: string;
692
- }
693
- | TableIdFromSchema<Schema>;
694
- };
695
-
696
- /**
697
- * The DpcTabularSave type describes the configuration for saving Tables in a
698
- * database-oriented Persister that is operating in tabular mode.
699
- *
700
- * It is an object where each key is an Id of a Store Table, and the value is a
701
- * child configuration object for how that Table should be saved out to the
702
- * database. The properties of the child configuration object are:
703
- *
704
- * ||Type|Description|
705
- * |-|-|-|
706
- * |`tableName`|string|The name of the database table out to which the Store Table should be saved.|
707
- * |`rowIdColumnName?`|string|The optional name of the column in the database table that will be used to save the Row Ids from the Store Table, defaulting to '_id'.|
708
- * |`deleteEmptyColumns?`|boolean|Whether columns in the database table will be removed if they are empty in the Store Table, defaulting to false.|
709
- * |`deleteEmptyTable?`|boolean|Whether tables in the database will be removed if the Store Table is empty, defaulting to false.|
710
- *
711
- * As a shortcut, if you do not need to specify a custom `rowIdColumnName`, or
712
- * enable the `deleteEmptyColumns` or `deleteEmptyTable` settings, you can
713
- * simply provide the name of the database table instead of the whole object.
714
- *
715
- * `deleteEmptyColumns` and `deleteEmptyTable` only have a guaranteed effect
716
- * when an explicit call is made to the Persister's save method. Columns and
717
- * tables will not necessarily be removed when the Persister is incrementally
718
- * 'autoSaving', due to performance reasons. If you want to be sure that your
719
- * database table matches a TinyBase Table without any extraneous columns,
720
- * simply call the save method at an idle moment.
721
- *
722
- * The 'Dpc' prefix indicates that this type is used within the
723
- * DatabasePersisterConfig type.
724
- * @example
725
- * When applied to a database Persister, this DatabasePersisterConfig will save
726
- * the data of two Store Tables (called 'pets' and 'species') into two database
727
- * tables (called 'petsInDb' and 'speciesInDb'). One has a column for the Row
728
- * Id called 'id' and will delete columns and the whole table if empty, the
729
- * other defaults to '_id' and will not delete columns or the whole table if
730
- * empty.
731
- *
732
- * ```js
733
- * import type {DatabasePersisterConfig} from 'tinybase';
734
- *
735
- * export const databasePersisterConfig: DatabasePersisterConfig = {
736
- * mode: 'tabular',
737
- * tables: {
738
- * save: {
739
- * pets: {
740
- * tableName: 'petsInDb',
741
- * deleteEmptyColumns: true,
742
- * deleteEmptyTable: true,
743
- * },
744
- * species: 'speciesInDb',
745
- * },
746
- * },
747
- * };
748
- * ```
749
- *
750
- * Imagine a Store with Tables that look like this:
751
- *
752
- * ```json
753
- * {
754
- * "pets": {
755
- * "fido": {"species": "dog", "color": "brown"},
756
- * "felix": {"species": "cat", "color": "black"},
757
- * },
758
- * "species": {
759
- * "dog": {"price": 5},
760
- * "cat": {"price": 4},
761
- * },
762
- * }
763
- * ```
764
- *
765
- * With the configuration above, this will save out to a database with tables
766
- * that look like this:
767
- *
768
- * ```
769
- * > SELECT * FROM petsInDb;
770
- * +-------+---------+-------+
771
- * | id | species | color |
772
- * +-------+---------+-------+
773
- * | fido | dog | brown |
774
- * | felix | cat | black |
775
- * +-------+---------+-------+
776
- *
777
- * > SELECT * FROM speciesInDb;
778
- * +------+-------+
779
- * | _id | price |
780
- * +------+-------+
781
- * | dog | 5 |
782
- * | cat | 4 |
783
- * +------+-------+
784
- * ```
785
- * The example above represents what happens with a SQLite Persister. In
786
- * PostgreSQL databases, all Cell and Value columns are expected to be
787
- * typed as `text`, and the strings, booleans, and numbers would be JSON-encoded
788
- * if you queried them.
789
- * @category Configuration
790
- * @since v4.0.0
791
- */
792
- export type DpcTabularSave<Schema extends OptionalTablesSchema> = {
793
- [TableId in TableIdFromSchema<Schema>]:
794
- | {
795
- /**
796
- * The name of the database table out to which the Store Table should be
797
- * saved.
798
- * @category Configuration
799
- * @since v4.0.0
800
- */
801
- tableName: string;
802
- /**
803
- * The optional name of the column in the database table that will be
804
- * used to save the Row Ids from the Store Table, defaulting to '_id'.
805
- * @category Configuration
806
- * @since v4.0.0
807
- */
808
- rowIdColumnName?: string;
809
- /**
810
- * Whether columns in the database table will be removed if they are
811
- * empty in the Store Table, defaulting to false.
812
- * @category Configuration
813
- * @since v4.0.0
814
- */
815
- deleteEmptyColumns?: boolean;
816
- /**
817
- * Whether tables in the database will be removed if the Store Table is
818
- * empty, defaulting to false.
819
- * @category Configuration
820
- * @since v4.0.0
821
- */
822
- deleteEmptyTable?: boolean;
823
- }
824
- | string;
825
- };
826
-
827
- /**
828
- * The DpcTabularValues type describes the configuration for handling Values in
829
- * a database-oriented Persister that is operating in tabular mode.
830
- *
831
- * Note that both loading and saving of Values from and to the database are
832
- * disabled by default.
833
- *
834
- * The 'Dpc' prefix indicates that this type is used within the
835
- * DatabasePersisterConfig type.
836
- * @example
837
- * When applied to a database Persister, this DatabasePersisterConfig will load
838
- * and save the data of a Store's Values into a database
839
- * table called 'my_tinybase_values'.
840
- *
841
- * ```js
842
- * import type {DatabasePersisterConfig} from 'tinybase';
843
- *
844
- * export const databasePersisterConfig: DatabasePersisterConfig = {
845
- * mode: 'tabular',
846
- * values: {
847
- * load: true,
848
- * save: true,
849
- * tableName: 'my_tinybase_values',
850
- * },
851
- * };
852
- * ```
853
- * @category Configuration
854
- * @since v4.0.0
855
- */
856
- export type DpcTabularValues = {
857
- /**
858
- * Whether Store Values will be loaded from a database table.
859
- * @category Configuration
860
- * @since v4.0.0
861
- */
862
- load?: boolean;
863
- /**
864
- * Whether Store Values will be saved to a database table.
865
- * @category Configuration
866
- * @since v4.0.0
867
- */
868
- save?: boolean;
869
- /**
870
- * The optional name of the database table from and to which the Store Values
871
- * should be loaded or saved, defaulting to `tinybase_values`.
872
- * @category Configuration
873
- * @since v4.0.0
874
- */
875
- tableName?: string;
876
- };
877
-
878
- /**
879
- * A Persister object lets you save and load Store data to and from different
880
- * locations, or underlying storage types.
881
- *
882
- * This is useful for preserving Store or MergeableStore data between browser
883
- * sessions or reloads, saving or loading browser state to or from a server, or
884
- * saving Store data to disk in a environment with filesystem access.
885
- *
886
- * Creating a Persister depends on the choice of underlying storage where the
887
- * data is to be stored. Options include the createSessionPersister function,
888
- * the createLocalPersister function, the createRemotePersister function, and
889
- * the createFilePersister function, as just simple examples. The
890
- * createCustomPersister function can also be used to easily create a fully
891
- * customized way to save and load Store data.
892
- *
893
- * Using the values of the Persists enum, the generic parameter to the Persister
894
- * indicates whether it can handle a regular Store, a MergeableStore, or either.
895
- * Consult the table in the overall persisters module documentation to see
896
- * current support for each. The different levels of support are also described
897
- * for each of the types of Persister themselves.
898
- *
899
- * A Persister lets you explicit save or load data, with the save method and the
900
- * load method respectively. These methods are both asynchronous (since the
901
- * underlying data storage may also be) and return promises. As a result you
902
- * should use the `await` keyword to call them in a way that guarantees
903
- * subsequent execution order.
904
- *
905
- * When you don't want to deal with explicit persistence operations, a Persister
906
- * object also provides automatic saving and loading. Automatic saving listens
907
- * for changes to the Store and persists the data immediately. Automatic loading
908
- * listens (or polls) for changes to the persisted data and reflects those
909
- * changes in the Store.
910
- *
911
- * You can start automatic saving or loading with the startAutoSave method and
912
- * startAutoLoad method. Both are asynchronous since they will do an immediate
913
- * save and load before starting to listen for subsequent changes. You can stop
914
- * the behavior with the stopAutoSave method and stopAutoLoad method (which are
915
- * synchronous).
916
- *
917
- * You may often want to have both automatic saving and loading of a Store so
918
- * that changes are constantly synchronized (allowing basic state preservation
919
- * between browser tabs, for example). The framework has some basic provisions
920
- * to prevent race conditions - for example it will not attempt to save data if
921
- * it is currently loading it and vice-versa - and will sequentially schedule
922
- * methods that could cause race conditions.
923
- *
924
- * That said, be aware that you should always comprehensively test your
925
- * persistence strategy to understand the opportunity for data loss (in the case
926
- * of trying to save data to a server under poor network conditions, for
927
- * example).
928
- *
929
- * To help debug such issues, since v4.0.4, the create methods for all Persister
930
- * objects take an optional `onIgnoredError` argument. This is a handler for the
931
- * errors that the Persister would otherwise ignore when trying to save or load
932
- * data (such as when handling corrupted stored data). It's recommended you use
933
- * this for debugging persistence issues, but only in a development environment.
934
- * Database-based Persister objects also take an optional `onSqlCommand`
935
- * argument for logging commands and queries made to the underlying database.
936
- * @example
937
- * This example creates a Store, persists it to the browser's session storage as
938
- * a JSON string, changes the persisted data, updates the Store from it, and
939
- * finally destroys the Persister again.
940
- *
941
- * ```js
942
- * import {createStore} from 'tinybase';
943
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
944
- *
945
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
946
- * const persister = createSessionPersister(store, 'pets');
947
- *
948
- * await persister.save();
949
- * console.log(sessionStorage.getItem('pets'));
950
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
951
- *
952
- * sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
953
- * await persister.load();
954
- * console.log(store.getTables());
955
- * // -> {pets: {toto: {species: 'dog'}}}
956
- *
957
- * persister.destroy();
958
- * sessionStorage.clear();
959
- * ```
960
- * @example
961
- * This example creates a Store, and automatically saves and loads it to the
962
- * browser's session storage as a JSON string. Changes to the Store data, or the
963
- * persisted data (implicitly firing a StorageEvent), are reflected accordingly.
964
- *
965
- * ```js
966
- * import {createStore} from 'tinybase';
967
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
968
- *
969
- * const store = createStore();
970
- * const persister = createSessionPersister(store, 'pets');
971
- *
972
- * await persister.startAutoLoad([{pets: {fido: {species: 'dog'}}}, {}]);
973
- * await persister.startAutoSave();
974
- *
975
- * store.setTables({pets: {felix: {species: 'cat'}}});
976
- * // ...
977
- * console.log(sessionStorage.getItem('pets'));
978
- * // -> '[{"pets":{"felix":{"species":"cat"}}},{}]'
979
- *
980
- * // In another browser tab:
981
- * sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
982
- * // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
983
- *
984
- * // ...
985
- * console.log(store.getTables());
986
- * // -> {pets: {toto: {species: 'dog'}}}
987
- *
988
- * persister.destroy();
989
- * sessionStorage.clear();
990
- * ```
991
- * @category Persister
992
- * @since v1.0.0
993
- */
994
- export interface Persister<
995
- in out Schemas extends OptionalSchemas,
996
- Persist extends Persists = Persists.StoreOnly,
997
- > {
998
- /**
999
- * The load method gets persisted data from storage, and loads it into the
1000
- * Store with which the Persister is associated, once.
1001
- *
1002
- * This has schema-based typing. The following is a simplified representation:
1003
- *
1004
- * ```ts override
1005
- * load(initialContent?: Content | (() => Content)): Promise<this>;
1006
- * ```
1007
- *
1008
- * The optional parameter allows you to specify what the initial content for
1009
- * the Store will be if there is nothing currently persisted or if the load
1010
- * fails (for example when the Persister is remote and the environment is
1011
- * offline). This allows you to fallback or instantiate a Store whether it's
1012
- * loading from previously persisted storage or being run for the first time.
1013
- * Since v5.4.2, this parameter can also be a function that returns the
1014
- * content.
1015
- *
1016
- * This method is asynchronous because the persisted data may be on a remote
1017
- * machine or a filesystem. Even for those storage types that are synchronous
1018
- * (like browser storage) it is still recommended that you `await` calls to
1019
- * this method or handle the return type natively as a Promise.
1020
- * @param initialContent An optional Content object used when the underlying
1021
- * storage has not previously been populated.
1022
- * @returns A Promise containing a reference to the Persister object.
1023
- * @example
1024
- * This example creates an empty Store, and loads data into it from the
1025
- * browser's session storage, which for the purposes of this example has been
1026
- * previously populated.
1027
- *
1028
- * ```js
1029
- * import {createStore} from 'tinybase';
1030
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1031
- *
1032
- * sessionStorage.setItem('pets', '[{"pets":{"fido":{"species":"dog"}}},{}]');
1033
- *
1034
- * const store = createStore();
1035
- * const persister = createSessionPersister(store, 'pets');
1036
- *
1037
- * await persister.load();
1038
- * console.log(store.getTables());
1039
- * // -> {pets: {fido: {species: 'dog'}}}
1040
- *
1041
- * sessionStorage.clear();
1042
- * ```
1043
- * @example
1044
- * This example creates an empty Store, and loads data into it from the
1045
- * browser's session storage, which is at first empty, so the optional
1046
- * parameter is used. The second time the load method is called, data has
1047
- * previously been persisted and instead, that is loaded.
1048
- *
1049
- * ```js
1050
- * import {createStore} from 'tinybase';
1051
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1052
- *
1053
- * const store = createStore();
1054
- * const persister = createSessionPersister(store, 'pets');
1055
- *
1056
- * await persister.load([{pets: {fido: {species: 'dog'}}}, {}]);
1057
- * console.log(store.getTables());
1058
- * // -> {pets: {fido: {species: 'dog'}}}
1059
- *
1060
- * sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
1061
- * await persister.load({pets: {fido: {species: 'dog'}}});
1062
- * console.log(store.getTables());
1063
- * // -> {pets: {toto: {species: 'dog'}}}
1064
- *
1065
- * sessionStorage.clear();
1066
- * ```
1067
- * @category Load
1068
- * @since v1.0.0
1069
- */
1070
- load(
1071
- initialContent?: Content<Schemas, true> | (() => Content<Schemas, true>),
1072
- ): Promise<this>;
1073
-
1074
- /**
1075
- * The startAutoLoad method gets persisted data from storage, and loads it
1076
- * into the Store with which the Persister is associated, once, and then
1077
- * continuously.
1078
- *
1079
- * This has schema-based typing. The following is a simplified representation:
1080
- *
1081
- * ```ts override
1082
- * startAutoLoad(initialContent?: Content | (() => Content)): Promise<this>;
1083
- * ```
1084
- *
1085
- * The optional parameter allows you to specify what the initial content for
1086
- * the Store will be if there is nothing currently persisted or if the load
1087
- * fails (for example when the Persister is remote and the environment is
1088
- * offline). This allows you to fallback or instantiate a Store whether it's
1089
- * loading from previously persisted storage or being run for the first time.
1090
- * Since v5.4.2, this parameter can also be a function that returns the
1091
- * content.
1092
- *
1093
- * This method first runs a single call to the load method to ensure the data
1094
- * is in sync with the persisted storage. It then continues to watch for
1095
- * changes to the underlying data (either through events or polling, depending
1096
- * on the storage type), automatically loading the data into the Store.
1097
- *
1098
- * This method is asynchronous because it starts by making a single call to
1099
- * the asynchronous load method. Even for those storage types that are
1100
- * synchronous (like browser storage) it is still recommended that you `await`
1101
- * calls to this method or handle the return type natively as a Promise.
1102
- * @param initialContent An optional Content object used when the underlying
1103
- * storage has not previously been populated.
1104
- * @returns A Promise containing a reference to the Persister object.
1105
- * @example
1106
- * This example creates an empty Store, and loads data into it from the
1107
- * browser's session storage, which at first is empty (so the `initialTables`
1108
- * parameter is used). Subsequent changes to the underlying storage are then
1109
- * reflected in the Store (in this case through detection of StorageEvents
1110
- * from session storage changes made in another browser tab).
1111
- *
1112
- * ```js
1113
- * import {createStore} from 'tinybase';
1114
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1115
- *
1116
- * const store = createStore();
1117
- * const persister = createSessionPersister(store, 'pets');
1118
- *
1119
- * await persister.startAutoLoad([{pets: {fido: {species: 'dog'}}}, {}]);
1120
- * console.log(store.getTables());
1121
- * // -> {pets: {fido: {species: 'dog'}}}
1122
- *
1123
- * // In another browser tab:
1124
- * sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
1125
- * // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
1126
- *
1127
- * // ...
1128
- * console.log(store.getTables());
1129
- * // -> {pets: {toto: {species: 'dog'}}}
1130
- *
1131
- * persister.destroy();
1132
- * sessionStorage.clear();
1133
- * ```
1134
- * @category Load
1135
- * @since v1.0.0
1136
- */
1137
- startAutoLoad(
1138
- initialContent?: Content<Schemas, true> | (() => Content<Schemas, true>),
1139
- ): Promise<this>;
1140
-
1141
- /**
1142
- * The stopAutoLoad method stops the automatic loading of data from storage
1143
- * previously started with the startAutoLoad method.
1144
- *
1145
- * If the Persister is not currently set to automatically load, this method
1146
- * has no effect.
1147
- * @returns A reference to the Persister object.
1148
- * @example
1149
- * This example creates an empty Store, and starts automatically loading data
1150
- * into it from the browser's session storage. Once the automatic loading is
1151
- * stopped, subsequent changes are not reflected in the Store.
1152
- *
1153
- * ```js
1154
- * import {createStore} from 'tinybase';
1155
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1156
- *
1157
- * const store = createStore();
1158
- * const persister = createSessionPersister(store, 'pets');
1159
- * await persister.startAutoLoad();
1160
- *
1161
- * // In another browser tab:
1162
- * sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
1163
- * // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
1164
- * // ...
1165
- * console.log(store.getTables());
1166
- * // -> {pets: {toto: {species: 'dog'}}}
1167
- *
1168
- * persister.stopAutoLoad();
1169
- *
1170
- * // In another browser tab:
1171
- * sessionStorage.setItem(
1172
- * 'pets',
1173
- * '[{"pets":{"felix":{"species":"cat"}}},{}]',
1174
- * );
1175
- * // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
1176
- * // ...
1177
- * console.log(store.getTables());
1178
- * // -> {pets: {toto: {species: 'dog'}}}
1179
- * // Storage change has not been automatically loaded.
1180
- *
1181
- * persister.destroy();
1182
- * sessionStorage.clear();
1183
- * ```
1184
- * @category Load
1185
- * @since v1.0.0
1186
- */
1187
- stopAutoLoad(): this;
1188
-
1189
- /**
1190
- * The isAutoLoading method lets you find out if the Persister is currently
1191
- * automatically loading its content.
1192
- * @returns A boolean indicating whether the Persister is currently
1193
- * autoLoading.
1194
- * @example
1195
- * This example creates a Persister and queries whether it is autoLoading.
1196
- *
1197
- * ```js
1198
- * import {createStore} from 'tinybase';
1199
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1200
- *
1201
- * const persister = createSessionPersister(createStore(), 'pets');
1202
- *
1203
- * console.log(persister.isAutoLoading());
1204
- * // -> false
1205
- *
1206
- * await persister.startAutoLoad();
1207
- * console.log(persister.isAutoLoading());
1208
- * // -> true
1209
- *
1210
- * await persister.stopAutoLoad();
1211
- * console.log(persister.isAutoLoading());
1212
- * // -> false
1213
- * ```
1214
- * @category Load
1215
- * @since v5.0.0
1216
- */
1217
- isAutoLoading(): boolean;
1218
-
1219
- /**
1220
- * The save method takes data from the Store with which the Persister is
1221
- * associated and persists it into storage, once.
1222
- *
1223
- * This method is asynchronous because the persisted data may be on a remote
1224
- * machine or a filesystem. Even for those storage types that are synchronous
1225
- * (like browser storage) it is still recommended that you `await` calls to
1226
- * this method or handle the return type natively as a Promise.
1227
- * @returns A Promise containing a reference to the Persister object.
1228
- * @example
1229
- * This example creates a Store with some data, and saves into the browser's
1230
- * session storage.
1231
- *
1232
- * ```js
1233
- * import {createStore} from 'tinybase';
1234
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1235
- *
1236
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
1237
- * const persister = createSessionPersister(store, 'pets');
1238
- *
1239
- * await persister.save();
1240
- * console.log(sessionStorage.getItem('pets'));
1241
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
1242
- *
1243
- * persister.destroy();
1244
- * sessionStorage.clear();
1245
- * ```
1246
- * @category Save
1247
- * @since v1.0.0
1248
- */
1249
- save(): Promise<this>;
1250
-
1251
- /**
1252
- * The save method takes data from the Store with which the Persister is
1253
- * associated and persists it into storage, once, and then continuously.
1254
- *
1255
- * This method first runs a single call to the save method to ensure the data
1256
- * is in sync with the persisted storage. It then continues to watch for
1257
- * changes to the Store, automatically saving the data to storage.
1258
- *
1259
- * This method is asynchronous because it starts by making a single call to
1260
- * the asynchronous save method. Even for those storage types that are
1261
- * synchronous (like browser storage) it is still recommended that you `await`
1262
- * calls to this method or handle the return type natively as a Promise.
1263
- * @returns A Promise containing a reference to the Persister object.
1264
- * @example
1265
- * This example creates a Store with some data, and saves into the browser's
1266
- * session storage. Subsequent changes to the Store are then automatically
1267
- * saved to the underlying storage.
1268
- *
1269
- * ```js
1270
- * import {createStore} from 'tinybase';
1271
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1272
- *
1273
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
1274
- * const persister = createSessionPersister(store, 'pets');
1275
- *
1276
- * await persister.startAutoSave();
1277
- * console.log(sessionStorage.getItem('pets'));
1278
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
1279
- *
1280
- * store.setTables({pets: {toto: {species: 'dog'}}});
1281
- * // ...
1282
- * console.log(sessionStorage.getItem('pets'));
1283
- * // -> '[{"pets":{"toto":{"species":"dog"}}},{}]'
1284
- *
1285
- * sessionStorage.clear();
1286
- * ```
1287
- * @category Save
1288
- * @since v1.0.0
1289
- */
1290
- startAutoSave(): Promise<this>;
1291
-
1292
- /**
1293
- * The stopAutoSave method stops the automatic save of data to storage
1294
- * previously started with the startAutoSave method.
1295
- *
1296
- * If the Persister is not currently set to automatically save, this method
1297
- * has no effect.
1298
- * @returns A reference to the Persister object.
1299
- * @example
1300
- * This example creates a Store with some data, and saves into the browser's
1301
- * session storage. Subsequent changes to the Store are then automatically
1302
- * saved to the underlying storage. Once the automatic saving is
1303
- * stopped, subsequent changes are not reflected.
1304
- *
1305
- * ```js
1306
- * import {createStore} from 'tinybase';
1307
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1308
- *
1309
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
1310
- * const persister = createSessionPersister(store, 'pets');
1311
- * await persister.startAutoSave();
1312
- *
1313
- * store.setTables({pets: {toto: {species: 'dog'}}});
1314
- * // ...
1315
- * console.log(sessionStorage.getItem('pets'));
1316
- * // -> '[{"pets":{"toto":{"species":"dog"}}},{}]'
1317
- *
1318
- * persister.stopAutoSave();
1319
- *
1320
- * store.setTables({pets: {felix: {species: 'cat'}}});
1321
- * // ...
1322
- * console.log(sessionStorage.getItem('pets'));
1323
- * // -> '[{"pets":{"toto":{"species":"dog"}}},{}]'
1324
- * // Store change has not been automatically saved.
1325
- *
1326
- * sessionStorage.clear();
1327
- * ```
1328
- * @category Save
1329
- * @since v1.0.0
1330
- */
1331
- stopAutoSave(): this;
1332
-
1333
- /**
1334
- * The isAutoSaving method lets you find out if the Persister is currently
1335
- * automatically saving its content.
1336
- * @returns A boolean indicating whether the Persister is currently
1337
- * autoSaving.
1338
- * @example
1339
- * This example creates a Persister and queries whether it is autoSaving.
1340
- *
1341
- * ```js
1342
- * import {createStore} from 'tinybase';
1343
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1344
- *
1345
- * const persister = createSessionPersister(createStore(), 'pets');
1346
- *
1347
- * console.log(persister.isAutoSaving());
1348
- * // -> false
1349
- *
1350
- * await persister.startAutoSave();
1351
- * console.log(persister.isAutoSaving());
1352
- * // -> true
1353
- *
1354
- * await persister.stopAutoSave();
1355
- * console.log(persister.isAutoSaving());
1356
- * // -> false
1357
- * ```
1358
- * @category Save
1359
- * @since v5.0.0
1360
- */
1361
- isAutoSaving(): boolean;
1362
-
1363
- /**
1364
- * The getStatus method lets you find out if the Persister is currently in the
1365
- * process of loading or saving content.
1366
- *
1367
- * It can only be doing one or the other (or neither) at any given time. The
1368
- * Status enum is returned, where 0 means idle, 1 means loading, and 2 means
1369
- * saving.
1370
- *
1371
- * This method is only likely to be useful for Persister implementations that
1372
- * have asynchronous load or save operations. The status for synchronous
1373
- * persister media (such as browser local or session storage) will switch back
1374
- * to idle before you are able to query it.
1375
- * @returns A value of type Status indicating whether the Persister is idle,
1376
- * loading, or saving.
1377
- * @example
1378
- * This example creates a Persister and queries its status.
1379
- *
1380
- * ```js
1381
- * import {createStore} from 'tinybase';
1382
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1383
- *
1384
- * const persister = createSessionPersister(createStore(), 'pets');
1385
- *
1386
- * console.log(persister.getStatus());
1387
- * // -> 0
1388
- * ```
1389
- * @category Lifecycle
1390
- * @since v5.3.0
1391
- */
1392
- getStatus(): Status;
1393
-
1394
- /**
1395
- * The addStatusListener method registers a listener function with the
1396
- * Persister that will be called whenever it starts or stops loading or
1397
- * saving.
1398
- *
1399
- * This has schema-based typing. The following is a simplified representation:
1400
- *
1401
- * ```ts override
1402
- * addStatusListener(listener: StatusListener<Persist>): Id;
1403
- * ```
1404
- *
1405
- * The provided listener is a StatusListener function, and will be called with
1406
- * a reference to the Persister and the new Status: 0 means now idle, 1 means
1407
- * now loading, and 2 means now saving.
1408
- * @param listener The function that will be called whenever the Persister
1409
- * starts or stops loading or saving.
1410
- * @returns A unique Id for the listener that can later be used to remove it.
1411
- * @example
1412
- * This example registers a listener that responds to changes in the state of
1413
- * the Persister.
1414
- *
1415
- * ```js
1416
- * import {createStore} from 'tinybase';
1417
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1418
- *
1419
- * const persister = createSessionPersister(createStore(), 'pets');
1420
- *
1421
- * const listenerId = persister.addStatusListener((persister, status) => {
1422
- * console.log(
1423
- * `${persister.getStorageName()} persister status changed to ${status}`,
1424
- * );
1425
- * });
1426
- *
1427
- * await persister.load();
1428
- * // -> 'pets persister status changed to 1'
1429
- * // -> 'pets persister status changed to 0'
1430
- * await persister.save();
1431
- * // -> 'pets persister status changed to 2'
1432
- * // -> 'pets persister status changed to 0'
1433
- *
1434
- * persister.delListener(listenerId);
1435
- * ```
1436
- * @category Listener
1437
- * @since v5.3.0
1438
- */
1439
- addStatusListener(listener: StatusListener<Schemas, Persist>): Id;
1440
-
1441
- /**
1442
- * The delListener method removes a listener that was previously added to the
1443
- * Persister.
1444
- *
1445
- * Use the Id returned by whichever method was used to add the listener. Note
1446
- * that the Persister may re-use this Id for future listeners added to it.
1447
- * @param listenerId The Id of the listener to remove.
1448
- * @returns A reference to the Persister.
1449
- * @example
1450
- * This example registers a listener and then removes it.
1451
- *
1452
- * ```js
1453
- * import {createStore} from 'tinybase';
1454
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1455
- *
1456
- * const persister = createSessionPersister(createStore(), 'pets');
1457
- *
1458
- * const listenerId = persister.addStatusListener((_persister, status) => {
1459
- * console.log(`Status changed to ${status}`);
1460
- * });
1461
- *
1462
- * await persister.load();
1463
- * // -> `Status changed to 1`
1464
- * // -> `Status changed to 0`
1465
- *
1466
- * persister.delListener(listenerId);
1467
- *
1468
- * await persister.load();
1469
- * // -> undefined
1470
- * // The listener is not called.
1471
- * ```
1472
- * @category Listener
1473
- * @since v5.3.0
1474
- */
1475
- delListener(listenerId: Id): this;
1476
-
1477
- /**
1478
- * The schedule method allows you to queue up a series of asynchronous actions
1479
- * that must run in sequence during persistence.
1480
- *
1481
- * For example, a database Persister may need to ensure that multiple
1482
- * asynchronous tasks to check and update the database schema are completed
1483
- * before data is written to it. Therefore it's most likely you will be using
1484
- * this method inside your `setPersisted` implementation.
1485
- *
1486
- * Call this method to add a single asynchronous action, or a sequence of them
1487
- * in one call. This will also start to run the first task in the queue (which
1488
- * once complete will then run the next, and so on), and so this method itself
1489
- * is also asynchronous and returns a promise of the Persister.
1490
- * @param actions One or many functions which will be scheduled, and which can
1491
- * be asynchronous.
1492
- * @returns A reference to the Persister object.
1493
- * @example
1494
- * This example creates a custom Persister object against a newly-created
1495
- * Store and then sequences two tasks in order to update its data on a
1496
- * hypothetical remote system.
1497
- *
1498
- * ```js yolo
1499
- * import {
1500
- * checkRemoteSystemIsReady,
1501
- * getDataFromRemoteSystem,
1502
- * sendDataToRemoteSystem,
1503
- * } from 'custom-remote-handlers';
1504
- * import {createStore} from 'tinybase';
1505
- * import {createCustomPersister} from 'tinybase/persisters';
1506
- *
1507
- * const store = createStore();
1508
- * const persister = createCustomPersister(
1509
- * store,
1510
- * async () => {
1511
- * // getPersisted
1512
- * return await getDataFromRemoteSystem();
1513
- * },
1514
- * async (getContent) => {
1515
- * // setPersisted
1516
- * await persister.schedule(
1517
- * async () => await checkRemoteSystemIsReady(),
1518
- * async () => await sendDataToRemoteSystem(getContent()),
1519
- * );
1520
- * },
1521
- * (listener) => setInterval(listener, 1000),
1522
- * (interval) => clearInterval(interval),
1523
- * );
1524
- * ```
1525
- * @category Lifecycle
1526
- * @since v4.0.0
1527
- */
1528
- schedule(...actions: (() => Promise<any>)[]): Promise<this>;
1529
-
1530
- /**
1531
- * The getStore method returns a reference to the underlying Store or
1532
- * MergeableStore that is backing this Persister object.
1533
- * @returns A reference to the Store or MergeableStore.
1534
- * @example
1535
- * This example creates a Persister object against a newly-created Store and
1536
- * then gets its reference in order to update its data.
1537
- *
1538
- * This has schema-based typing. The following is a simplified representation:
1539
- *
1540
- * ```ts override
1541
- * getStore(): PersistedStore<Persist>;
1542
- * ```
1543
- *
1544
- * ```js
1545
- * import {createStore} from 'tinybase';
1546
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1547
- *
1548
- * const persister = createSessionPersister(createStore(), 'pets');
1549
- * await persister.startAutoSave();
1550
- *
1551
- * persister.getStore().setTables({pets: {fido: {species: 'dog'}}});
1552
- * // ...
1553
- * console.log(sessionStorage.getItem('pets'));
1554
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
1555
- *
1556
- * sessionStorage.clear();
1557
- * ```
1558
- * @category Getter
1559
- * @since v1.0.0
1560
- */
1561
- getStore(): PersistedStore<Schemas, Persist>;
1562
-
1563
- /**
1564
- * The destroy method should be called when this Persister object is no longer
1565
- * used.
1566
- *
1567
- * This guarantees that all of the listeners that the object registered with
1568
- * the underlying Store and storage are removed and it can be correctly
1569
- * garbage collected. It is equivalent to running the stopAutoLoad method and
1570
- * the stopAutoSave method in succession.
1571
- * @returns A reference to the Persister object.
1572
- * @example
1573
- * This example creates a Store, associates a Persister object with it (that
1574
- * registers a TablesListener with the underlying Store), and then destroys it
1575
- * again, removing the listener.
1576
- *
1577
- * ```js
1578
- * import {createStore} from 'tinybase';
1579
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1580
- *
1581
- * const store = createStore();
1582
- * const persister = createSessionPersister(store, 'pets');
1583
- * await persister.startAutoSave();
1584
- *
1585
- * console.log(store.getListenerStats().transaction);
1586
- * // -> 1
1587
- *
1588
- * persister.destroy();
1589
- *
1590
- * console.log(store.getListenerStats().transaction);
1591
- * // -> 0
1592
- * ```
1593
- * @category Lifecycle
1594
- * @since v1.0.0
1595
- */
1596
- destroy(): this;
1597
-
1598
- /**
1599
- * The getStats method provides a set of statistics about the Persister, and
1600
- * is used for debugging purposes.
1601
- *
1602
- * The PersisterStats object contains a count of the number of times the
1603
- * Persister has loaded and saved data.
1604
- *
1605
- * The method is intended to be used during development to ensure your
1606
- * persistence layer is acting as expected, for example.
1607
- * @returns A PersisterStats object containing Persister load and save
1608
- * statistics.
1609
- * @example
1610
- * This example gets the load and save statistics of a Persister object.
1611
- * Remember that the startAutoLoad method invokes an explicit load when it
1612
- * starts, and the startAutoSave method invokes an explicit save when it
1613
- * starts - so those numbers are included in addition to the loads and saves
1614
- * invoked by changes to the Store and to the underlying storage.
1615
- *
1616
- * ```js
1617
- * import {createStore} from 'tinybase';
1618
- * import {createSessionPersister} from 'tinybase/persisters/persister-browser';
1619
- *
1620
- * const store = createStore();
1621
- * const persister = createSessionPersister(store, 'pets');
1622
- *
1623
- * await persister.startAutoLoad({pets: {fido: {species: 'dog'}}});
1624
- * await persister.startAutoSave();
1625
- *
1626
- * store.setTables({pets: {felix: {species: 'cat'}}});
1627
- * // ...
1628
- *
1629
- * sessionStorage.setItem('pets', '[{"pets":{"toto":{"species":"dog"}}},{}]');
1630
- * // -> StorageEvent('storage', {storageArea: sessionStorage, key: 'pets'})
1631
- * // ...
1632
- *
1633
- * console.log(persister.getStats());
1634
- * // -> {loads: 2, saves: 2}
1635
- *
1636
- * persister.destroy();
1637
- * sessionStorage.clear();
1638
- * ```
1639
- * @category Development
1640
- * @since v1.0.0
1641
- */
1642
- getStats(): PersisterStats;
1643
- }
1644
-
1645
- /**
1646
- * The AnyPersister type is a convenient alias for any type of Persister that
1647
- * can persist Store or MergeableStore objects.
1648
- * @category Mergeable
1649
- * @since v5.3.0
1650
- */
1651
- export type AnyPersister<Schemas extends OptionalSchemas> = Persister<
1652
- Schemas,
1653
- Persists
1654
- >;
1655
-
1656
- /**
1657
- * The DatabaseExecuteCommand type describes a function that is used to execute
1658
- * commands against a database.
1659
- *
1660
- * This is only used when developing custom database-oriented Persisters, and
1661
- * most TinyBase users will not need to be particularly aware of it.
1662
- *
1663
- * It is modelled around the common pattern of database SDKs being able to
1664
- * execute commands with parameters, and have those (probably asynchronous)
1665
- * command executions return an array of objects, where each object represents a
1666
- * row.
1667
- * @param sql The SQL string to execute, which may include positional parameter
1668
- * placeholders.
1669
- * @param params An array of parameters to pass to the SQL command.
1670
- * @returns An promise of an array of objects, where each object represents a
1671
- * database result row (if the command was a query).
1672
- * @category Creation
1673
- * @since v5.2.0
1674
- */
1675
- export type DatabaseExecuteCommand = (
1676
- sql: string,
1677
- params?: any[],
1678
- ) => Promise<{[field: string]: any}[]>;
1679
-
1680
- /**
1681
- * The DatabaseChangeListener type describes a function that is used to listen
1682
- * for changes to the data in a database.
1683
- *
1684
- * This is only used when developing custom database-oriented Persisters, and
1685
- * most TinyBase users will not need to be particularly aware of it.
1686
- *
1687
- * This function should be called with the name of a relevant table that has
1688
- * changed, possible through the use of events, triggers, or notifications,
1689
- * dependent on the specific database implementation.
1690
- * @param tableName The name of the table that has changed.
1691
- * @category Creation
1692
- * @since v5.2.0
1693
- */
1694
- export type DatabaseChangeListener = (tableName: string) => void;
1695
-
1696
- /**
1697
- * The createCustomPersister function creates a Persister object that you can
1698
- * configure to persist the Store in any way you wish.
1699
- *
1700
- * This has schema-based typing. The following is a simplified representation:
1701
- *
1702
- * ```ts override
1703
- * createCustomPersister<
1704
- * ListenerHandle,
1705
- * Persist extends Persists = Persists.StoreOnly,
1706
- * >(
1707
- * store: PersistedStore<Persist>,
1708
- * getPersisted: () => Promise<PersistedContent<Persist> | undefined>,
1709
- * setPersisted: (
1710
- * getContent: () => PersistedContent<Persist>,
1711
- * changes?: PersistedChanges<Persist>,
1712
- * ) => Promise<void>,
1713
- * addPersisterListener: (
1714
- * listener: PersisterListener<Persist>,
1715
- * ) => ListenerHandle | Promise<ListenerHandle>,
1716
- * delPersisterListener: (listenerHandle: ListenerHandle) => void,
1717
- * onIgnoredError?: (error: any) => void,
1718
- * persist?: Persist,
1719
- * ): Persister<Persist>;
1720
- * ```
1721
- *
1722
- * This is only used when developing custom Persisters, and most TinyBase users
1723
- * will not need to be particularly aware of it.
1724
- *
1725
- * As well as providing a reference to the Store to persist, you must provide
1726
- * functions that handle how to fetch, write, and listen to, the persistence
1727
- * layer.
1728
- *
1729
- * The other creation functions (such as the createSessionPersister function and
1730
- * createFilePersister function, for example) all use this function under the
1731
- * covers. See those implementations for ideas on how to implement your own
1732
- * Persister types.
1733
- *
1734
- * This API changed in v4.0. Any custom persisters created on previous versions
1735
- * should be upgraded. Most notably, the `setPersisted` function parameter is
1736
- * provided with a `getContent` function to get the content from the Store
1737
- * itself, rather than being passed pre-serialized JSON. It also receives
1738
- * information about the changes made during a transaction. The `getPersisted`
1739
- * function must return the content (or nothing) rather than JSON.
1740
- * `startListeningToPersisted` has been renamed `addPersisterListener`, and
1741
- * `stopListeningToPersisted` has been renamed `delPersisterListener`.
1742
- * @param store The Store to persist.
1743
- * @param getPersisted An asynchronous function which will fetch content from
1744
- * the persistence layer (or `undefined` if not present).
1745
- * @param setPersisted An asynchronous function which will send content to the
1746
- * persistence layer. Since v4.0, it receives functions for getting the Store
1747
- * content and information about the changes made during a transaction. Since
1748
- * v5.0, the changes are received directly by reference, rather than an
1749
- * accessor.
1750
- * @param addPersisterListener A function that will register a `listener`
1751
- * listener on underlying changes to the persistence layer. You can return a
1752
- * listening handle that will be provided again when `delPersisterListener` is
1753
- * called. This function can be asynchronous.
1754
- * @param delPersisterListener A function that will unregister the listener from
1755
- * the underlying changes to the persistence layer. It receives whatever was
1756
- * returned from your `addPersisterListener` implementation.
1757
- * @param onIgnoredError An optional handler for the errors that the Persister
1758
- * would otherwise ignore when trying to save or load data. This is suitable for
1759
- * debugging persistence issues in a development environment, since v4.0.4.
1760
- * @param persist Since v5.0, an optional integer from the Persists enum to
1761
- * indicate which types of Store are supported by this Persister: `1` indicates
1762
- * only a regular Store is supported, `2` indicates only a MergeableStore is
1763
- * supported, and `3` indicates that both Store and MergeableStore are
1764
- * supported.
1765
- * @returns A reference to the new Persister object.
1766
- * @example
1767
- * This example creates a custom Persister object and persists a Store to a
1768
- * local string called `persistedJson` and which would automatically load by
1769
- * polling for changes every second. It implicitly supports only a regular
1770
- * Store.
1771
- *
1772
- * ```js
1773
- * import {createStore} from 'tinybase';
1774
- * import {createCustomPersister} from 'tinybase/persisters';
1775
- *
1776
- * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
1777
- * let persistedJson;
1778
- *
1779
- * const persister = createCustomPersister(
1780
- * store,
1781
- * async () => {
1782
- * // getPersisted
1783
- * return JSON.parse(persistedJson);
1784
- * },
1785
- * async (getContent) => {
1786
- * // setPersisted
1787
- * persistedJson = JSON.stringify(getContent());
1788
- * },
1789
- * (listener) => setInterval(listener, 1000),
1790
- * (interval) => clearInterval(interval),
1791
- * );
1792
- *
1793
- * await persister.save();
1794
- * console.log(persistedJson);
1795
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
1796
- *
1797
- * persistedJson = '[{"pets":{"fido":{"species":"dog","color":"brown"}}},{}]';
1798
- * await persister.load();
1799
- *
1800
- * console.log(store.getTables());
1801
- * // -> {pets: {fido: {species: 'dog', color: 'brown'}}}
1802
- *
1803
- * persister.destroy();
1804
- * ```
1805
- * @example
1806
- * This example demonstrates a Persister creation function which returns a
1807
- * Persister. This can persists a store to a local string called `persistedJson`
1808
- * and which would automatically load by polling for changes every second.
1809
- * It emits warnings to the console and explicitly supports either a Store or a
1810
- * MergeableStore.
1811
- *
1812
- * ```js
1813
- * import {createMergeableStore, createStore} from 'tinybase';
1814
- * import {Persists, createCustomPersister} from 'tinybase/persisters';
1815
- *
1816
- * let persistedJson;
1817
- * const createJsonPersister = (storeOrMergeableStore) =>
1818
- * createCustomPersister(
1819
- * storeOrMergeableStore,
1820
- * async () => {
1821
- * // getPersisted
1822
- * return JSON.parse(persistedJson);
1823
- * },
1824
- * async (getContent) => {
1825
- * // setPersisted
1826
- * persistedJson = JSON.stringify(getContent());
1827
- * },
1828
- * (listener) => setInterval(listener, 1000),
1829
- * (interval) => clearInterval(interval),
1830
- * console.warn,
1831
- * Persists.StoreOrMergeableStore,
1832
- * );
1833
- *
1834
- * const store = createStore();
1835
- * store.setTables({pets: {fido: {species: 'dog'}}});
1836
- * const storePersister = createJsonPersister(store);
1837
- * await storePersister.save();
1838
- * console.log(persistedJson);
1839
- * // -> '[{"pets":{"fido":{"species":"dog"}}},{}]'
1840
- * storePersister.destroy();
1841
- *
1842
- * const mergeableStore = createMergeableStore('mergeableStore1'); // !resetHlc
1843
- * mergeableStore.setTables({pets: {fido: {species: 'dog'}}});
1844
- * const mergeableStorePersister = createJsonPersister(mergeableStore);
1845
- * await mergeableStorePersister.save();
1846
- * console.log(JSON.parse(persistedJson));
1847
- * // ->
1848
- * [
1849
- * [
1850
- * {
1851
- * pets: [
1852
- * {
1853
- * fido: [
1854
- * {species: ['dog', 'Nn1JUF-----Zjl0M', 4176151067]},
1855
- * '',
1856
- * 2722999044,
1857
- * ],
1858
- * },
1859
- * '',
1860
- * 3367164653,
1861
- * ],
1862
- * },
1863
- * '',
1864
- * 30627183,
1865
- * ],
1866
- * [{}, '', 0],
1867
- * ];
1868
- * mergeableStorePersister.destroy();
1869
- * ```
1870
- * @category Creation
1871
- * @since v1.0.0
1872
- */
1873
- export function createCustomPersister<
1874
- Schemas extends OptionalSchemas,
1875
- ListenerHandle,
1876
- Persist extends Persists = Persists.StoreOnly,
1877
- >(
1878
- store: PersistedStore<Schemas, Persist>,
1879
- getPersisted: () => Promise<PersistedContent<Schemas, Persist> | undefined>,
1880
- setPersisted: (
1881
- getContent: () => PersistedContent<Schemas, Persist>,
1882
- changes?: PersistedChanges<Schemas, Persist>,
1883
- ) => Promise<void>,
1884
- addPersisterListener: (
1885
- listener: PersisterListener<Schemas, Persist>,
1886
- ) => ListenerHandle | Promise<ListenerHandle>,
1887
- delPersisterListener: (listenerHandle: ListenerHandle) => void,
1888
- onIgnoredError?: (error: any) => void,
1889
- persist?: Persist,
1890
- ): Persister<Schemas, Persist>;
1891
-
1892
- /**
1893
- * The createCustomSqlitePersister function creates a Persister object that you
1894
- * can configure to persist the Store to a SQLite database.
1895
- *
1896
- * This has schema-based typing. The following is a simplified representation:
1897
- *
1898
- * ```ts override
1899
- * createCustomSqlitePersister<
1900
- * ListenerHandle,
1901
- * Persist extends Persists = Persists.StoreOnly,
1902
- * >(
1903
- * store: PersistedStore<Persist>,
1904
- * configOrStoreTableName: DatabasePersisterConfig | string | undefined,
1905
- * executeCommand: DatabaseExecuteCommand,
1906
- * addChangeListener: (listener: DatabaseChangeListener) => ListenerHandle,
1907
- * delChangeListener: (listenerHandle: ListenerHandle) => void,
1908
- * onSqlCommand: ((sql: string, params?: any[]) => void) | undefined,
1909
- * onIgnoredError: ((error: any) => void) | undefined,
1910
- * destroy: () => void,
1911
- * persist: Persist,
1912
- * thing: any,
1913
- * getThing?: string,
1914
- * ): Persister<Persist>;
1915
- * ```
1916
- *
1917
- * This is only used when developing custom database-oriented Persisters, and
1918
- * most TinyBase users will not need to be particularly aware of it.
1919
- *
1920
- * All of the TinyBase SQLite-oriented Persister functions use this function
1921
- * under the covers, and so you may wish to look at those implementations for
1922
- * ideas on how to build your own Persister type, and as functional examples.
1923
- * Examine the implementation of the createSqlite3Persister function as a good
1924
- * starting point, for example.
1925
- * @param store The Store to persist.
1926
- * @param configOrStoreTableName A DatabasePersisterConfig object, or a string
1927
- * that will be used as the name of the Store's table in the database.
1928
- * @param executeCommand A function that will execute a command against the
1929
- * database.
1930
- * @param addChangeListener A function that will register a listener for changes
1931
- * to the database.
1932
- * @param delChangeListener A function that will unregister the listener for
1933
- * changes to the database.
1934
- * @param onSqlCommand A function that will be called for each SQL command
1935
- * executed against the database.
1936
- * @param onIgnoredError An optional handler for the errors that the Persister
1937
- * would otherwise ignore when trying to save or load data. This is suitable for
1938
- * debugging persistence issues in a development environment.
1939
- * @param destroy A function that will be called to perform any extra clean up
1940
- * on the Persister.
1941
- * @param persist An integer from the Persists enum to indicate which types of
1942
- * Store are supported by this Persister: `1` indicates only a regular Store is
1943
- * supported, `2` indicates only a MergeableStore is supported, and `3`
1944
- * indicates that both Store and MergeableStore are supported.
1945
- * @param thing A reference to the database or connection that can be returned
1946
- * with a method, by default called `getDb`.
1947
- * @param getThing An optional string that will be used to get the reference to
1948
- * the database or connection from the Persister, defaulting to `getDb`.
1949
- * @returns A reference to the new SQLite-oriented Persister object.
1950
- * @category Creation
1951
- * @since v5.2.0
1952
- */
1953
- export function createCustomSqlitePersister<
1954
- Schemas extends OptionalSchemas,
1955
- ListenerHandle,
1956
- Persist extends Persists = Persists.StoreOnly,
1957
- >(
1958
- store: PersistedStore<Schemas, Persist>,
1959
- configOrStoreTableName: DatabasePersisterConfig<Schemas> | string | undefined,
1960
- executeCommand: DatabaseExecuteCommand,
1961
- addChangeListener: (listener: DatabaseChangeListener) => ListenerHandle,
1962
- delChangeListener: (listenerHandle: ListenerHandle) => void,
1963
- onSqlCommand: ((sql: string, params?: any[]) => void) | undefined,
1964
- onIgnoredError: ((error: any) => void) | undefined,
1965
- destroy: () => void,
1966
- persist: Persist,
1967
- thing: any,
1968
- getThing?: string,
1969
- ): Persister<Schemas, Persist>;
1970
-
1971
- /**
1972
- * The createCustomSqlitePersister function creates a Persister object that you
1973
- * can configure to persist the Store to a PostgreSQL database.
1974
- *
1975
- * This has schema-based typing. The following is a simplified representation:
1976
- *
1977
- * ```ts override
1978
- * createCustomPostgreSqlPersister<
1979
- * ListenerHandle,
1980
- * Persist extends Persists = Persists.StoreOnly,
1981
- * >(
1982
- * store: PersistedStore<Persist>,
1983
- * configOrStoreTableName: DatabasePersisterConfig | string | undefined,
1984
- * executeCommand: DatabaseExecuteCommand,
1985
- * addChangeListener: (
1986
- * channel: string,
1987
- * listener: DatabaseChangeListener,
1988
- * ) => Promise<ListenerHandle>,
1989
- * delChangeListener: (listenerHandle: ListenerHandle) => void,
1990
- * onSqlCommand: ((sql: string, params?: any[]) => void) | undefined,
1991
- * onIgnoredError: ((error: any) => void) | undefined,
1992
- * destroy: () => void,
1993
- * persist: Persist,
1994
- * thing: any,
1995
- * getThing?: string,
1996
- * ): Persister<Persist>;
1997
- * ```
1998
- *
1999
- * This is only used when developing custom database-oriented Persisters, and
2000
- * most TinyBase users will not need to be particularly aware of it.
2001
- *
2002
- * All of the TinyBase PostgreSQL-oriented Persister functions use this function
2003
- * under the covers, and so you may wish to look at those implementations for
2004
- * ideas on how to build your own Persister type, and as functional
2005
- * examples. Examine the implementation of the createPostgresPersister function
2006
- * as a good starting point, for example.
2007
- * @param store The Store to persist.
2008
- * @param configOrStoreTableName A DatabasePersisterConfig object, or a string
2009
- * that will be used as the name of the Store's table in the database.
2010
- * @param executeCommand A function that will execute a command against the
2011
- * database.
2012
- * @param addChangeListener A function that will register a listener for changes
2013
- * to the database.
2014
- * @param delChangeListener A function that will unregister the listener for
2015
- * changes to the database.
2016
- * @param onSqlCommand A function that will be called for each SQL command
2017
- * executed against the database.
2018
- * @param onIgnoredError An optional handler for the errors that the Persister
2019
- * would otherwise ignore when trying to save or load data. This is suitable for
2020
- * debugging persistence issues in a development environment.
2021
- * @param destroy A function that will be called to perform any extra clean up
2022
- * on the Persister.
2023
- * @param persist An integer from the Persists enum to indicate which types of
2024
- * Store are supported by this Persister: `1` indicates only a regular Store is
2025
- * supported, `2` indicates only a MergeableStore is supported, and `3`
2026
- * indicates that both Store and MergeableStore are supported.
2027
- * @param thing A reference to the database or connection that can be returned
2028
- * with a method, by default called `getDb`.
2029
- * @param getThing An optional string that will be used to get the reference to
2030
- * the database or connection from the Persister, defaulting to `getDb`.
2031
- * @returns A reference to the new Persister object.
2032
- * @category Creation
2033
- * @since v5.2.0
2034
- */
2035
- export function createCustomPostgreSqlPersister<
2036
- Schemas extends OptionalSchemas,
2037
- ListenerHandle,
2038
- Persist extends Persists = Persists.StoreOnly,
2039
- >(
2040
- store: PersistedStore<Schemas, Persist>,
2041
- configOrStoreTableName: DatabasePersisterConfig<Schemas> | string | undefined,
2042
- executeCommand: DatabaseExecuteCommand,
2043
- addChangeListener: (
2044
- channel: string,
2045
- listener: DatabaseChangeListener,
2046
- ) => Promise<ListenerHandle>,
2047
- delChangeListener: (listenerHandle: ListenerHandle) => void,
2048
- onSqlCommand: ((sql: string, params?: any[]) => void) | undefined,
2049
- onIgnoredError: ((error: any) => void) | undefined,
2050
- destroy: () => void,
2051
- persist: Persist,
2052
- thing: any,
2053
- getThing?: string,
2054
- ): Persister<Schemas, Persist>;