tinybase 4.0.0-beta.5.2 → 4.0.0

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 (138) hide show
  1. package/lib/cjs/persisters/persister-automerge.cjs +1 -1
  2. package/lib/cjs/persisters/persister-automerge.cjs.gz +0 -0
  3. package/lib/cjs/persisters/persister-browser.cjs +1 -1
  4. package/lib/cjs/persisters/persister-browser.cjs.gz +0 -0
  5. package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs +1 -1
  6. package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
  7. package/lib/cjs/persisters/persister-file.cjs +1 -1
  8. package/lib/cjs/persisters/persister-file.cjs.gz +0 -0
  9. package/lib/cjs/persisters/persister-remote.cjs +1 -1
  10. package/lib/cjs/persisters/persister-remote.cjs.gz +0 -0
  11. package/lib/cjs/persisters/persister-sqlite-wasm.cjs +1 -1
  12. package/lib/cjs/persisters/persister-sqlite-wasm.cjs.gz +0 -0
  13. package/lib/cjs/persisters/persister-sqlite3.cjs +1 -1
  14. package/lib/cjs/persisters/persister-sqlite3.cjs.gz +0 -0
  15. package/lib/cjs/persisters/persister-yjs.cjs +1 -1
  16. package/lib/cjs/persisters/persister-yjs.cjs.gz +0 -0
  17. package/lib/cjs/persisters.cjs +1 -1
  18. package/lib/cjs/persisters.cjs.gz +0 -0
  19. package/lib/cjs/tinybase.cjs +1 -1
  20. package/lib/cjs/tinybase.cjs.gz +0 -0
  21. package/lib/cjs-es6/persisters/persister-automerge.cjs +1 -1
  22. package/lib/cjs-es6/persisters/persister-automerge.cjs.gz +0 -0
  23. package/lib/cjs-es6/persisters/persister-browser.cjs +1 -1
  24. package/lib/cjs-es6/persisters/persister-browser.cjs.gz +0 -0
  25. package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs +1 -1
  26. package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
  27. package/lib/cjs-es6/persisters/persister-file.cjs +1 -1
  28. package/lib/cjs-es6/persisters/persister-file.cjs.gz +0 -0
  29. package/lib/cjs-es6/persisters/persister-remote.cjs +1 -1
  30. package/lib/cjs-es6/persisters/persister-remote.cjs.gz +0 -0
  31. package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs +1 -1
  32. package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs.gz +0 -0
  33. package/lib/cjs-es6/persisters/persister-sqlite3.cjs +1 -1
  34. package/lib/cjs-es6/persisters/persister-sqlite3.cjs.gz +0 -0
  35. package/lib/cjs-es6/persisters/persister-yjs.cjs +1 -1
  36. package/lib/cjs-es6/persisters/persister-yjs.cjs.gz +0 -0
  37. package/lib/cjs-es6/persisters.cjs +1 -1
  38. package/lib/cjs-es6/persisters.cjs.gz +0 -0
  39. package/lib/cjs-es6/tinybase.cjs +1 -1
  40. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  41. package/lib/debug/persisters/persister-automerge.js +22 -20
  42. package/lib/debug/persisters/persister-browser.js +28 -20
  43. package/lib/debug/persisters/persister-cr-sqlite-wasm.js +199 -150
  44. package/lib/debug/persisters/persister-file.js +28 -20
  45. package/lib/debug/persisters/persister-remote.js +28 -20
  46. package/lib/debug/persisters/persister-sqlite-wasm.js +204 -150
  47. package/lib/debug/persisters/persister-sqlite3.js +199 -150
  48. package/lib/debug/persisters/persister-yjs.js +28 -20
  49. package/lib/debug/persisters.js +29 -20
  50. package/lib/debug/tinybase.js +22 -20
  51. package/lib/es6/persisters/persister-automerge.js +1 -1
  52. package/lib/es6/persisters/persister-automerge.js.gz +0 -0
  53. package/lib/es6/persisters/persister-browser.js +1 -1
  54. package/lib/es6/persisters/persister-browser.js.gz +0 -0
  55. package/lib/es6/persisters/persister-cr-sqlite-wasm.js +1 -1
  56. package/lib/es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  57. package/lib/es6/persisters/persister-file.js +1 -1
  58. package/lib/es6/persisters/persister-file.js.gz +0 -0
  59. package/lib/es6/persisters/persister-remote.js +1 -1
  60. package/lib/es6/persisters/persister-remote.js.gz +0 -0
  61. package/lib/es6/persisters/persister-sqlite-wasm.js +1 -1
  62. package/lib/es6/persisters/persister-sqlite-wasm.js.gz +0 -0
  63. package/lib/es6/persisters/persister-sqlite3.js +1 -1
  64. package/lib/es6/persisters/persister-sqlite3.js.gz +0 -0
  65. package/lib/es6/persisters/persister-yjs.js +1 -1
  66. package/lib/es6/persisters/persister-yjs.js.gz +0 -0
  67. package/lib/es6/persisters.js +1 -1
  68. package/lib/es6/persisters.js.gz +0 -0
  69. package/lib/es6/tinybase.js +1 -1
  70. package/lib/es6/tinybase.js.gz +0 -0
  71. package/lib/persisters/persister-automerge.js +1 -1
  72. package/lib/persisters/persister-automerge.js.gz +0 -0
  73. package/lib/persisters/persister-browser.js +1 -1
  74. package/lib/persisters/persister-browser.js.gz +0 -0
  75. package/lib/persisters/persister-cr-sqlite-wasm.js +1 -1
  76. package/lib/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  77. package/lib/persisters/persister-file.js +1 -1
  78. package/lib/persisters/persister-file.js.gz +0 -0
  79. package/lib/persisters/persister-remote.js +1 -1
  80. package/lib/persisters/persister-remote.js.gz +0 -0
  81. package/lib/persisters/persister-sqlite-wasm.js +1 -1
  82. package/lib/persisters/persister-sqlite-wasm.js.gz +0 -0
  83. package/lib/persisters/persister-sqlite3.js +1 -1
  84. package/lib/persisters/persister-sqlite3.js.gz +0 -0
  85. package/lib/persisters/persister-yjs.js +1 -1
  86. package/lib/persisters/persister-yjs.js.gz +0 -0
  87. package/lib/persisters.js +1 -1
  88. package/lib/persisters.js.gz +0 -0
  89. package/lib/tinybase.js +1 -1
  90. package/lib/tinybase.js.gz +0 -0
  91. package/lib/types/persisters/persister-cr-sqlite-wasm.d.ts +2 -0
  92. package/lib/types/persisters/persister-sqlite-wasm.d.ts +2 -0
  93. package/lib/types/persisters/persister-sqlite3.d.ts +2 -0
  94. package/lib/types/with-schemas/persisters/persister-cr-sqlite-wasm.d.ts +2 -0
  95. package/lib/types/with-schemas/persisters/persister-sqlite-wasm.d.ts +2 -0
  96. package/lib/types/with-schemas/persisters/persister-sqlite3.d.ts +2 -0
  97. package/lib/umd/persisters/persister-automerge.js +1 -1
  98. package/lib/umd/persisters/persister-automerge.js.gz +0 -0
  99. package/lib/umd/persisters/persister-browser.js +1 -1
  100. package/lib/umd/persisters/persister-browser.js.gz +0 -0
  101. package/lib/umd/persisters/persister-cr-sqlite-wasm.js +1 -1
  102. package/lib/umd/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  103. package/lib/umd/persisters/persister-file.js +1 -1
  104. package/lib/umd/persisters/persister-file.js.gz +0 -0
  105. package/lib/umd/persisters/persister-remote.js +1 -1
  106. package/lib/umd/persisters/persister-remote.js.gz +0 -0
  107. package/lib/umd/persisters/persister-sqlite-wasm.js +1 -1
  108. package/lib/umd/persisters/persister-sqlite-wasm.js.gz +0 -0
  109. package/lib/umd/persisters/persister-sqlite3.js +1 -1
  110. package/lib/umd/persisters/persister-sqlite3.js.gz +0 -0
  111. package/lib/umd/persisters/persister-yjs.js +1 -1
  112. package/lib/umd/persisters/persister-yjs.js.gz +0 -0
  113. package/lib/umd/persisters.js +1 -1
  114. package/lib/umd/persisters.js.gz +0 -0
  115. package/lib/umd/tinybase.js +1 -1
  116. package/lib/umd/tinybase.js.gz +0 -0
  117. package/lib/umd-es6/persisters/persister-automerge.js +1 -1
  118. package/lib/umd-es6/persisters/persister-automerge.js.gz +0 -0
  119. package/lib/umd-es6/persisters/persister-browser.js +1 -1
  120. package/lib/umd-es6/persisters/persister-browser.js.gz +0 -0
  121. package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js +1 -1
  122. package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  123. package/lib/umd-es6/persisters/persister-file.js +1 -1
  124. package/lib/umd-es6/persisters/persister-file.js.gz +0 -0
  125. package/lib/umd-es6/persisters/persister-remote.js +1 -1
  126. package/lib/umd-es6/persisters/persister-remote.js.gz +0 -0
  127. package/lib/umd-es6/persisters/persister-sqlite-wasm.js +1 -1
  128. package/lib/umd-es6/persisters/persister-sqlite-wasm.js.gz +0 -0
  129. package/lib/umd-es6/persisters/persister-sqlite3.js +1 -1
  130. package/lib/umd-es6/persisters/persister-sqlite3.js.gz +0 -0
  131. package/lib/umd-es6/persisters/persister-yjs.js +1 -1
  132. package/lib/umd-es6/persisters/persister-yjs.js.gz +0 -0
  133. package/lib/umd-es6/persisters.js +1 -1
  134. package/lib/umd-es6/persisters.js.gz +0 -0
  135. package/lib/umd-es6/tinybase.js +1 -1
  136. package/lib/umd-es6/tinybase.js.gz +0 -0
  137. package/package.json +16 -16
  138. package/readme.md +14 -14
@@ -1,3 +1,4 @@
1
+ const arrayLength = (array) => array.length;
1
2
  const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
2
3
  const arrayPush = (array, ...values) => array.push(...values);
3
4
  const arrayShift = (array) => array.shift();
@@ -22,7 +23,12 @@ const ifNotUndefined = (value, then, otherwise) =>
22
23
  isUndefined(value) ? otherwise?.() : then(value);
23
24
 
24
25
  const object = Object;
26
+ const objIds = object.keys;
25
27
  const objFreeze = object.freeze;
28
+ const isObject = (obj) =>
29
+ isInstanceOf(obj, object) && obj.constructor == object;
30
+ const objSize = (obj) => arrayLength(objIds(obj));
31
+ const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
26
32
 
27
33
  const createCustomPersister = (
28
34
  store,
@@ -59,27 +65,28 @@ const createCustomPersister = (
59
65
  {
60
66
  loads++;
61
67
  }
62
- await actions();
63
- loadSave = 0;
68
+ await persister.schedule(async () => {
69
+ await actions();
70
+ loadSave = 0;
71
+ });
64
72
  }
73
+ return persister;
65
74
  };
66
75
  const persister = {
67
- load: async (initialTables, initialValues) => {
76
+ load: async (initialTables, initialValues) =>
68
77
  await loadLock(async () => {
69
78
  try {
70
79
  store.setContent(await getPersisted());
71
80
  } catch {
72
81
  store.setContent([initialTables, initialValues]);
73
82
  }
74
- });
75
- return persister;
76
- },
83
+ }),
77
84
  startAutoLoad: async (initialTables = {}, initialValues = {}) => {
78
85
  persister.stopAutoLoad();
79
86
  await persister.load(initialTables, initialValues);
80
87
  listening = 1;
81
88
  listeningHandle = addPersisterListener(
82
- async (getContent, getTransactionChanges) => {
89
+ async (getContent, getTransactionChanges) =>
83
90
  await loadLock(async () => {
84
91
  if (getTransactionChanges) {
85
92
  store.setTransactionChanges(getTransactionChanges());
@@ -88,8 +95,7 @@ const createCustomPersister = (
88
95
  store.setContent(getContent?.() ?? (await getPersisted()));
89
96
  } catch {}
90
97
  }
91
- });
92
- },
98
+ }),
93
99
  );
94
100
  return persister;
95
101
  },
@@ -102,27 +108,29 @@ const createCustomPersister = (
102
108
  return persister;
103
109
  },
104
110
  save: async (getTransactionChanges) => {
105
- await persister.schedule(async () => {
106
- /* istanbul ignore else */
107
- if (loadSave != 1) {
108
- loadSave = 2;
109
- {
110
- saves++;
111
- }
111
+ /* istanbul ignore else */
112
+ if (loadSave != 1) {
113
+ loadSave = 2;
114
+ {
115
+ saves++;
116
+ }
117
+ await persister.schedule(async () => {
112
118
  try {
113
119
  await setPersisted(store.getContent, getTransactionChanges);
114
120
  } catch {}
115
121
  loadSave = 0;
116
- }
117
- });
122
+ });
123
+ }
118
124
  return persister;
119
125
  },
120
126
  startAutoSave: async () => {
121
127
  await persister.stopAutoSave().save();
122
128
  listenerId = store.addDidFinishTransactionListener(
123
129
  (_store, getTransactionChanges) => {
124
- const transactionChanges = getTransactionChanges();
125
- persister.save(() => transactionChanges);
130
+ const [tableChanges, valueChanges] = getTransactionChanges();
131
+ if (!objIsEmpty(tableChanges) || !objIsEmpty(valueChanges)) {
132
+ persister.save(() => [tableChanges, valueChanges]);
133
+ }
126
134
  },
127
135
  );
128
136
  return persister;
@@ -38,6 +38,11 @@ const isString = (thing) => getTypeOf(thing) == STRING;
38
38
  const isArray = (thing) => Array.isArray(thing);
39
39
  const promiseAll = async (promises) => promise.all(promises);
40
40
 
41
+ const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
42
+ const collValues = (coll) => [...(coll?.values() ?? [])];
43
+ const collForEach = (coll, cb) => coll?.forEach(cb);
44
+ const collDel = (coll, keyOrValue) => coll?.delete(keyOrValue);
45
+
41
46
  const object = Object;
42
47
  const objIds = object.keys;
43
48
  const objFreeze = object.freeze;
@@ -57,11 +62,6 @@ const objValues = (obj) => object.values(obj);
57
62
  const objSize = (obj) => arrayLength(objIds(obj));
58
63
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
59
64
 
60
- const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
61
- const collValues = (coll) => [...(coll?.values() ?? [])];
62
- const collForEach = (coll, cb) => coll?.forEach(cb);
63
- const collDel = (coll, keyOrValue) => coll?.delete(keyOrValue);
64
-
65
65
  const mapNew = (entries) => new Map(entries);
66
66
  const mapKeys = (map) => [...(map?.keys() ?? [])];
67
67
  const mapGet = (map, key) => map?.get(key);
@@ -98,9 +98,7 @@ const setAdd = (set, value) => set?.add(value);
98
98
  const SELECT_STAR_FROM = 'SELECT*FROM';
99
99
  const FROM_PRAGMA_TABLE = 'FROM pragma_table_';
100
100
  const WHERE = 'WHERE';
101
- const WHERE_MAIN_TABLE =
102
- WHERE + ` schema='main'AND type='table'AND name!='sqlite_schema'`;
103
- const getCommandFunctions = (cmd) => {
101
+ const getCommandFunctions = (cmd, managedTableNames) => {
104
102
  const schemaMap = mapNew();
105
103
  const canSelect = (tableName, rowIdColumnName) =>
106
104
  !isUndefined(mapGet(mapGet(schemaMap, tableName), rowIdColumnName));
@@ -111,7 +109,12 @@ const getCommandFunctions = (cmd) => {
111
109
  await promiseAll(
112
110
  arrayMap(
113
111
  await cmd(
114
- 'SELECT name ' + FROM_PRAGMA_TABLE + 'list ' + WHERE_MAIN_TABLE,
112
+ 'SELECT name ' +
113
+ FROM_PRAGMA_TABLE +
114
+ `list WHERE schema='main'AND type='table'AND name IN(` +
115
+ getPlaceholders(managedTableNames) +
116
+ `)`,
117
+ managedTableNames,
115
118
  ),
116
119
  async ({name: tableName}) => [
117
120
  tableName,
@@ -245,15 +248,19 @@ const getCommandFunctions = (cmd) => {
245
248
  const insertSlots = [];
246
249
  const insertBinds = [];
247
250
  const deleteRowIds = [];
251
+ const allColumnNames = arrayFilter(
252
+ mapKeys(mapGet(schemaMap, tableName)),
253
+ (columnName) => columnName != rowIdColumnName,
254
+ );
248
255
  objMap(table, (row, rowId) => {
249
256
  arrayPush(
250
257
  insertSlots,
251
- `(?${strRepeat(',?', arrayLength(columnNames))})`,
258
+ `(?${strRepeat(',?', arrayLength(allColumnNames))})`,
252
259
  );
253
260
  arrayPush(
254
261
  insertBinds,
255
262
  rowId,
256
- ...arrayMap(columnNames, (cellId) => row[cellId]),
263
+ ...arrayMap(allColumnNames, (cellId) => row[cellId]),
257
264
  );
258
265
  arrayPush(deleteRowIds, rowId);
259
266
  });
@@ -263,10 +270,24 @@ const getCommandFunctions = (cmd) => {
263
270
  '(' +
264
271
  escapeId(rowIdColumnName) +
265
272
  arrayJoin(
266
- arrayMap(columnNames, (columnName) => COMMA + escapeId(columnName)),
273
+ arrayMap(
274
+ allColumnNames,
275
+ (columnName) => COMMA + escapeId(columnName),
276
+ ),
267
277
  ) +
268
278
  ')VALUES' +
269
- arrayJoin(insertSlots, COMMA),
279
+ arrayJoin(insertSlots, COMMA) +
280
+ 'ON CONFLICT(' +
281
+ escapeId(rowIdColumnName) +
282
+ ')DO UPDATE SET' +
283
+ arrayJoin(
284
+ arrayMap(
285
+ allColumnNames,
286
+ (columnName) =>
287
+ escapeId(columnName) + '=excluded.' + escapeId(columnName),
288
+ ),
289
+ COMMA,
290
+ ),
270
291
  insertBinds,
271
292
  );
272
293
  await cmd(
@@ -275,19 +296,21 @@ const getCommandFunctions = (cmd) => {
275
296
  WHERE +
276
297
  escapeId(rowIdColumnName) +
277
298
  'NOT IN(' +
278
- arrayJoin(
279
- arrayMap(deleteRowIds, () => '?'),
280
- COMMA,
281
- ) +
299
+ getPlaceholders(deleteRowIds) +
282
300
  ')',
283
301
  deleteRowIds,
284
302
  );
285
- } else {
303
+ } else if (collHas(schemaMap, tableName)) {
286
304
  await cmd('DELETE FROM' + escapeId(tableName));
287
305
  }
288
306
  };
289
307
  return [refreshSchema, loadSingleRow, saveSingleRow, loadTable, saveTable];
290
308
  };
309
+ const getPlaceholders = (array) =>
310
+ arrayJoin(
311
+ arrayMap(array, () => '?'),
312
+ COMMA,
313
+ );
291
314
 
292
315
  const createCustomPersister = (
293
316
  store,
@@ -324,27 +347,28 @@ const createCustomPersister = (
324
347
  {
325
348
  loads++;
326
349
  }
327
- await actions();
328
- loadSave = 0;
350
+ await persister.schedule(async () => {
351
+ await actions();
352
+ loadSave = 0;
353
+ });
329
354
  }
355
+ return persister;
330
356
  };
331
357
  const persister = {
332
- load: async (initialTables, initialValues) => {
358
+ load: async (initialTables, initialValues) =>
333
359
  await loadLock(async () => {
334
360
  try {
335
361
  store.setContent(await getPersisted());
336
362
  } catch {
337
363
  store.setContent([initialTables, initialValues]);
338
364
  }
339
- });
340
- return persister;
341
- },
365
+ }),
342
366
  startAutoLoad: async (initialTables = {}, initialValues = {}) => {
343
367
  persister.stopAutoLoad();
344
368
  await persister.load(initialTables, initialValues);
345
369
  listening = 1;
346
370
  listeningHandle = addPersisterListener(
347
- async (getContent, getTransactionChanges) => {
371
+ async (getContent, getTransactionChanges) =>
348
372
  await loadLock(async () => {
349
373
  if (getTransactionChanges) {
350
374
  store.setTransactionChanges(getTransactionChanges());
@@ -353,8 +377,7 @@ const createCustomPersister = (
353
377
  store.setContent(getContent?.() ?? (await getPersisted()));
354
378
  } catch {}
355
379
  }
356
- });
357
- },
380
+ }),
358
381
  );
359
382
  return persister;
360
383
  },
@@ -367,27 +390,29 @@ const createCustomPersister = (
367
390
  return persister;
368
391
  },
369
392
  save: async (getTransactionChanges) => {
370
- await persister.schedule(async () => {
371
- /* istanbul ignore else */
372
- if (loadSave != 1) {
373
- loadSave = 2;
374
- {
375
- saves++;
376
- }
393
+ /* istanbul ignore else */
394
+ if (loadSave != 1) {
395
+ loadSave = 2;
396
+ {
397
+ saves++;
398
+ }
399
+ await persister.schedule(async () => {
377
400
  try {
378
401
  await setPersisted(store.getContent, getTransactionChanges);
379
402
  } catch {}
380
403
  loadSave = 0;
381
- }
382
- });
404
+ });
405
+ }
383
406
  return persister;
384
407
  },
385
408
  startAutoSave: async () => {
386
409
  await persister.stopAutoSave().save();
387
410
  listenerId = store.addDidFinishTransactionListener(
388
411
  (_store, getTransactionChanges) => {
389
- const transactionChanges = getTransactionChanges();
390
- persister.save(() => transactionChanges);
412
+ const [tableChanges, valueChanges] = getTransactionChanges();
413
+ if (!objIsEmpty(tableChanges) || !objIsEmpty(valueChanges)) {
414
+ persister.save(() => [tableChanges, valueChanges]);
415
+ }
391
416
  },
392
417
  );
393
418
  return persister;
@@ -414,10 +439,13 @@ const createJsonSqlitePersister = (
414
439
  cmd,
415
440
  addPersisterListener,
416
441
  delPersisterListener,
417
- {storeTableName = TINYBASE},
442
+ [storeTableName],
443
+ managedTableNames,
418
444
  ) => {
419
- const [refreshSchema, loadSingleRow, saveSingleRow] =
420
- getCommandFunctions(cmd);
445
+ const [refreshSchema, loadSingleRow, saveSingleRow] = getCommandFunctions(
446
+ cmd,
447
+ managedTableNames,
448
+ );
421
449
  const getPersisted = async () => {
422
450
  await refreshSchema();
423
451
  return jsonParse(
@@ -445,97 +473,28 @@ const createJsonSqlitePersister = (
445
473
  return persister;
446
474
  };
447
475
 
448
- const ROW_ID_COLUMN_NAME = 'rowIdColumnName';
449
- const TABLE_ID = 'tableId';
450
- const TABLE_NAME = 'tableName';
451
- const DELETE_EMPTY_COLUMNS = 'deleteEmptyColumns';
452
- const DELETE_EMPTY_TABLE = 'deleteEmptyTable';
453
- const DEFAULTED_VALUES_CONFIG = {
454
- load: 0,
455
- save: 0,
456
- [TABLE_NAME]: TINYBASE + '_values',
457
- };
458
- const getDefaultedTableConfigMap = (
459
- configsObj,
460
- defaultObj,
461
- tableField,
462
- filter,
463
- ) => {
464
- const configMap = mapNew();
465
- objMap(configsObj, (configObj, id) => {
466
- const defaultedConfig = arraySlice(
467
- objValues(
468
- objMerge(
469
- defaultObj,
470
- isString(configObj) ? {[tableField]: configObj} : configObj,
471
- ),
472
- ),
473
- 0,
474
- objSize(defaultObj),
475
- );
476
- if (!isUndefined(defaultedConfig[0]) && !filter(id, defaultedConfig[0])) {
477
- mapSet(configMap, id, defaultedConfig);
478
- }
479
- });
480
- return configMap;
481
- };
482
- const getDefaultedConfig = ({
483
- tables: {load = {}, save = {}} = {},
484
- values = {},
485
- }) => {
486
- const valuesConfig = arraySlice(
487
- objValues(objMerge(DEFAULTED_VALUES_CONFIG, values)),
488
- 0,
489
- objSize(DEFAULTED_VALUES_CONFIG),
490
- );
491
- const valuesTable = valuesConfig[2];
492
- return [
493
- getDefaultedTableConfigMap(
494
- load,
495
- {
496
- [TABLE_ID]: null,
497
- [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
498
- },
499
- TABLE_ID,
500
- (tableName) => tableName == valuesTable,
501
- ),
502
- getDefaultedTableConfigMap(
503
- save,
504
- {
505
- [TABLE_NAME]: null,
506
- [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
507
- [DELETE_EMPTY_COLUMNS]: 0,
508
- [DELETE_EMPTY_TABLE]: 0,
509
- },
510
- TABLE_NAME,
511
- (_, tableName) => tableName == valuesTable,
512
- ),
513
- valuesConfig,
514
- ];
515
- };
516
-
517
476
  const createTabularSqlitePersister = (
518
477
  store,
519
478
  cmd,
520
479
  addPersisterListener,
521
480
  delPersisterListener,
522
- config,
523
- ) => {
524
- const [
481
+ [
525
482
  tablesLoadConfig,
526
483
  tablesSaveConfig,
527
484
  [valuesLoad, valuesSave, valuesTableName],
528
- ] = getDefaultedConfig(config);
485
+ ],
486
+ managedTableNames,
487
+ ) => {
529
488
  const [refreshSchema, loadSingleRow, saveSingleRow, loadTable, saveTable] =
530
- getCommandFunctions(cmd);
531
- const getSaveTablesActions = (tables) =>
532
- mapMap(
533
- tablesSaveConfig,
534
- (
489
+ getCommandFunctions(cmd, managedTableNames);
490
+ const saveTables = async (tables) =>
491
+ await promiseAll(
492
+ mapMap(
493
+ tablesSaveConfig,
494
+ async (
535
495
  [tableName, rowIdColumnName, deleteEmptyColumns, deleteEmptyTable],
536
496
  tableId,
537
497
  ) =>
538
- async () =>
539
498
  await saveTable(
540
499
  tableName,
541
500
  rowIdColumnName,
@@ -543,16 +502,16 @@ const createTabularSqlitePersister = (
543
502
  deleteEmptyTable,
544
503
  tables[tableId],
545
504
  ),
505
+ ),
546
506
  );
547
- const getSaveValuesAction = (values) =>
507
+ const saveValues = async (values) =>
548
508
  valuesSave
549
- ? async () =>
550
- await saveSingleRow(
551
- valuesTableName,
552
- DEFAULT_ROW_ID_COLUMN_NAME,
553
- SINGLE_ROW_ID,
554
- values,
555
- )
509
+ ? await saveSingleRow(
510
+ valuesTableName,
511
+ DEFAULT_ROW_ID_COLUMN_NAME,
512
+ SINGLE_ROW_ID,
513
+ values,
514
+ )
556
515
  : null;
557
516
  const loadTables = async () =>
558
517
  objNew(
@@ -583,11 +542,9 @@ const createTabularSqlitePersister = (
583
542
  };
584
543
  const setPersisted = async (getContent) => {
585
544
  const [tables, values] = getContent();
586
- persister.schedule(
587
- refreshSchema,
588
- ...getSaveTablesActions(tables),
589
- getSaveValuesAction(values),
590
- );
545
+ await refreshSchema();
546
+ await saveTables(tables);
547
+ await saveValues(values);
591
548
  };
592
549
  const persister = createCustomPersister(
593
550
  store,
@@ -601,10 +558,97 @@ const createTabularSqlitePersister = (
601
558
 
602
559
  const JSON$1 = 'json';
603
560
  const AUTO_LOAD_INTERVAL_SECONDS = 'autoLoadIntervalSeconds';
561
+ const STORE_TABLE_NAME = 'storeTableName';
562
+ const ROW_ID_COLUMN_NAME = 'rowIdColumnName';
563
+ const TABLE_ID = 'tableId';
564
+ const TABLE_NAME = 'tableName';
565
+ const DELETE_EMPTY_COLUMNS = 'deleteEmptyColumns';
566
+ const DELETE_EMPTY_TABLE = 'deleteEmptyTable';
604
567
  const DEFAULT_CONFIG = {
605
568
  mode: JSON$1,
606
569
  [AUTO_LOAD_INTERVAL_SECONDS]: 1,
607
570
  };
571
+ const DEFAULT_TABULAR_VALUES_CONFIG = {
572
+ load: 0,
573
+ save: 0,
574
+ [TABLE_NAME]: TINYBASE + '_values',
575
+ };
576
+ const getDefaultedConfig = (configOrStoreTableName) =>
577
+ objMerge(
578
+ DEFAULT_CONFIG,
579
+ isString(configOrStoreTableName)
580
+ ? {[STORE_TABLE_NAME]: configOrStoreTableName}
581
+ : configOrStoreTableName ?? {},
582
+ );
583
+ const getDefaultedTabularConfigMap = (
584
+ configsObj,
585
+ defaultObj,
586
+ tableField,
587
+ filter,
588
+ ) => {
589
+ const configMap = mapNew();
590
+ objMap(configsObj, (configObj, id) => {
591
+ const defaultedConfig = arraySlice(
592
+ objValues(
593
+ objMerge(
594
+ defaultObj,
595
+ isString(configObj) ? {[tableField]: configObj} : configObj,
596
+ ),
597
+ ),
598
+ 0,
599
+ objSize(defaultObj),
600
+ );
601
+ if (!isUndefined(defaultedConfig[0]) && !filter(id, defaultedConfig[0])) {
602
+ mapSet(configMap, id, defaultedConfig);
603
+ }
604
+ });
605
+ return configMap;
606
+ };
607
+ const getConfigStructures = (configOrStoreTableName) => {
608
+ const config = getDefaultedConfig(configOrStoreTableName);
609
+ const autoLoadIntervalSeconds = config[AUTO_LOAD_INTERVAL_SECONDS];
610
+ if (config.mode == JSON$1) {
611
+ const {storeTableName = TINYBASE} = config;
612
+ return [
613
+ 1,
614
+ autoLoadIntervalSeconds,
615
+ [storeTableName],
616
+ setNew(storeTableName),
617
+ ];
618
+ }
619
+ const {tables: {load = {}, save = {}} = {}, values = {}} = config;
620
+ const valuesConfig = arraySlice(
621
+ objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
622
+ 0,
623
+ objSize(DEFAULT_TABULAR_VALUES_CONFIG),
624
+ );
625
+ const valuesTable = valuesConfig[2];
626
+ const managedTableNames = setNew(valuesTable);
627
+ const tabularConfig = [
628
+ getDefaultedTabularConfigMap(
629
+ load,
630
+ {[TABLE_ID]: null, [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME},
631
+ TABLE_ID,
632
+ (tableName) =>
633
+ setAdd(managedTableNames, tableName) && tableName == valuesTable,
634
+ ),
635
+ getDefaultedTabularConfigMap(
636
+ save,
637
+ {
638
+ [TABLE_NAME]: null,
639
+ [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
640
+ [DELETE_EMPTY_COLUMNS]: 0,
641
+ [DELETE_EMPTY_TABLE]: 0,
642
+ },
643
+ TABLE_NAME,
644
+ (_, tableName) =>
645
+ setAdd(managedTableNames, tableName) && tableName == valuesTable,
646
+ ),
647
+ valuesConfig,
648
+ ];
649
+ return [0, autoLoadIntervalSeconds, tabularConfig, managedTableNames];
650
+ };
651
+
608
652
  const PRAGMA = 'pragma ';
609
653
  const DATA_VERSION = 'data_version';
610
654
  const SCHEMA_VERSION = 'schema_version';
@@ -612,17 +656,17 @@ const createSqlitePersister = (
612
656
  store,
613
657
  configOrStoreTableName,
614
658
  cmd,
615
- addPersisterLocalListener,
616
- delPersisterLocalListener,
659
+ addUpdateListener,
660
+ delUpdateListener,
617
661
  ) => {
618
- const config = objMerge(
619
- DEFAULT_CONFIG,
620
- isString(configOrStoreTableName)
621
- ? {storeTableName: configOrStoreTableName}
622
- : configOrStoreTableName ?? {},
623
- );
624
662
  let dataVersion;
625
663
  let schemaVersion;
664
+ const [
665
+ isJson,
666
+ autoLoadIntervalSeconds,
667
+ defaultedConfig,
668
+ managedTableNamesSet,
669
+ ] = getConfigStructures(configOrStoreTableName);
626
670
  const addPersisterListener = (listener) => [
627
671
  setInterval(async () => {
628
672
  try {
@@ -641,19 +685,24 @@ const createSqlitePersister = (
641
685
  schemaVersion = newSchemaVersion;
642
686
  }
643
687
  } catch {}
644
- }, config[AUTO_LOAD_INTERVAL_SECONDS] * 1e3),
645
- addPersisterLocalListener(listener),
688
+ }, autoLoadIntervalSeconds * 1e3),
689
+ addUpdateListener((tableName) =>
690
+ managedTableNamesSet.has(tableName) ? listener() : 0,
691
+ ),
646
692
  ];
647
693
  const delPersisterListener = ([interval, listeningHandle]) => {
648
694
  clearInterval(interval);
649
695
  dataVersion = schemaVersion = null;
650
- delPersisterLocalListener(listeningHandle);
696
+ delUpdateListener(listeningHandle);
651
697
  };
652
- return (
653
- config.mode == JSON$1
654
- ? createJsonSqlitePersister
655
- : createTabularSqlitePersister
656
- )(store, cmd, addPersisterListener, delPersisterListener, config);
698
+ return (isJson ? createJsonSqlitePersister : createTabularSqlitePersister)(
699
+ store,
700
+ cmd,
701
+ addPersisterListener,
702
+ delPersisterListener,
703
+ defaultedConfig,
704
+ collValues(managedTableNamesSet),
705
+ );
657
706
  };
658
707
 
659
708
  const createSqliteWasmPersister = (
@@ -669,7 +718,12 @@ const createSqliteWasmPersister = (
669
718
  db
670
719
  .exec(sql, {bind: args, rowMode: 'object', returnValue: 'resultRows'})
671
720
  .map((row) => ({...row})),
672
- (listener) => sqlite3.capi.sqlite3_update_hook(db, () => listener(), 0),
721
+ (listener) =>
722
+ sqlite3.capi.sqlite3_update_hook(
723
+ db,
724
+ (_, _2, _3, tableName) => listener(tableName),
725
+ 0,
726
+ ),
673
727
  () => sqlite3.capi.sqlite3_update_hook(db, () => 0, 0),
674
728
  );
675
729