tinybase 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/bin/cli.js +1 -1
  2. package/lib/checkpoints.js +1 -1
  3. package/lib/checkpoints.js.gz +0 -0
  4. package/lib/cjs/checkpoints.cjs +1 -1
  5. package/lib/cjs/checkpoints.cjs.gz +0 -0
  6. package/lib/cjs/indexes.cjs +1 -1
  7. package/lib/cjs/indexes.cjs.gz +0 -0
  8. package/lib/cjs/metrics.cjs +1 -1
  9. package/lib/cjs/metrics.cjs.gz +0 -0
  10. package/lib/cjs/persisters/persister-browser.cjs +1 -1
  11. package/lib/cjs/persisters/persister-browser.cjs.gz +0 -0
  12. package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs +1 -1
  13. package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
  14. package/lib/cjs/persisters/persister-file.cjs +1 -1
  15. package/lib/cjs/persisters/persister-file.cjs.gz +0 -0
  16. package/lib/cjs/persisters/persister-remote.cjs +1 -1
  17. package/lib/cjs/persisters/persister-remote.cjs.gz +0 -0
  18. package/lib/cjs/persisters/persister-sqlite-wasm.cjs +1 -1
  19. package/lib/cjs/persisters/persister-sqlite-wasm.cjs.gz +0 -0
  20. package/lib/cjs/persisters/persister-sqlite3.cjs +1 -1
  21. package/lib/cjs/persisters/persister-sqlite3.cjs.gz +0 -0
  22. package/lib/cjs/relationships.cjs +1 -1
  23. package/lib/cjs/relationships.cjs.gz +0 -0
  24. package/lib/cjs/store.cjs +1 -1
  25. package/lib/cjs/store.cjs.gz +0 -0
  26. package/lib/cjs/tinybase.cjs +1 -1
  27. package/lib/cjs/tinybase.cjs.gz +0 -0
  28. package/lib/cjs/tools.cjs +1 -1
  29. package/lib/cjs/tools.cjs.gz +0 -0
  30. package/lib/cjs/ui-react.cjs +1 -1
  31. package/lib/cjs/ui-react.cjs.gz +0 -0
  32. package/lib/cjs-es6/checkpoints.cjs +1 -1
  33. package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
  34. package/lib/cjs-es6/indexes.cjs +1 -1
  35. package/lib/cjs-es6/indexes.cjs.gz +0 -0
  36. package/lib/cjs-es6/metrics.cjs +1 -1
  37. package/lib/cjs-es6/metrics.cjs.gz +0 -0
  38. package/lib/cjs-es6/persisters/persister-browser.cjs +1 -1
  39. package/lib/cjs-es6/persisters/persister-browser.cjs.gz +0 -0
  40. package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs +1 -1
  41. package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
  42. package/lib/cjs-es6/persisters/persister-file.cjs +1 -1
  43. package/lib/cjs-es6/persisters/persister-file.cjs.gz +0 -0
  44. package/lib/cjs-es6/persisters/persister-remote.cjs +1 -1
  45. package/lib/cjs-es6/persisters/persister-remote.cjs.gz +0 -0
  46. package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs +1 -1
  47. package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs.gz +0 -0
  48. package/lib/cjs-es6/persisters/persister-sqlite3.cjs +1 -1
  49. package/lib/cjs-es6/persisters/persister-sqlite3.cjs.gz +0 -0
  50. package/lib/cjs-es6/relationships.cjs +1 -1
  51. package/lib/cjs-es6/relationships.cjs.gz +0 -0
  52. package/lib/cjs-es6/store.cjs +1 -1
  53. package/lib/cjs-es6/store.cjs.gz +0 -0
  54. package/lib/cjs-es6/tinybase.cjs +1 -1
  55. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  56. package/lib/cjs-es6/tools.cjs +1 -1
  57. package/lib/cjs-es6/tools.cjs.gz +0 -0
  58. package/lib/cjs-es6/ui-react.cjs +1 -1
  59. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  60. package/lib/debug/checkpoints.js +6 -6
  61. package/lib/debug/indexes.js +7 -7
  62. package/lib/debug/metrics.js +12 -12
  63. package/lib/debug/persisters/persister-browser.js +10 -19
  64. package/lib/debug/persisters/persister-cr-sqlite-wasm.js +183 -132
  65. package/lib/debug/persisters/persister-file.js +10 -19
  66. package/lib/debug/persisters/persister-remote.js +10 -19
  67. package/lib/debug/persisters/persister-sqlite-wasm.js +178 -131
  68. package/lib/debug/persisters/persister-sqlite3.js +178 -132
  69. package/lib/debug/persisters.js +4 -4
  70. package/lib/debug/relationships.js +7 -7
  71. package/lib/debug/store.js +16 -24
  72. package/lib/debug/tinybase.js +20 -28
  73. package/lib/debug/tools.js +14 -13
  74. package/lib/debug/ui-react.js +4 -4
  75. package/lib/es6/checkpoints.js +1 -1
  76. package/lib/es6/checkpoints.js.gz +0 -0
  77. package/lib/es6/indexes.js +1 -1
  78. package/lib/es6/indexes.js.gz +0 -0
  79. package/lib/es6/metrics.js +1 -1
  80. package/lib/es6/metrics.js.gz +0 -0
  81. package/lib/es6/persisters/persister-browser.js +1 -1
  82. package/lib/es6/persisters/persister-browser.js.gz +0 -0
  83. package/lib/es6/persisters/persister-cr-sqlite-wasm.js +1 -1
  84. package/lib/es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  85. package/lib/es6/persisters/persister-file.js +1 -1
  86. package/lib/es6/persisters/persister-file.js.gz +0 -0
  87. package/lib/es6/persisters/persister-remote.js +1 -1
  88. package/lib/es6/persisters/persister-remote.js.gz +0 -0
  89. package/lib/es6/persisters/persister-sqlite-wasm.js +1 -1
  90. package/lib/es6/persisters/persister-sqlite-wasm.js.gz +0 -0
  91. package/lib/es6/persisters/persister-sqlite3.js +1 -1
  92. package/lib/es6/persisters/persister-sqlite3.js.gz +0 -0
  93. package/lib/es6/relationships.js +1 -1
  94. package/lib/es6/relationships.js.gz +0 -0
  95. package/lib/es6/store.js +1 -1
  96. package/lib/es6/store.js.gz +0 -0
  97. package/lib/es6/tinybase.js +1 -1
  98. package/lib/es6/tinybase.js.gz +0 -0
  99. package/lib/es6/tools.js +1 -1
  100. package/lib/es6/tools.js.gz +0 -0
  101. package/lib/es6/ui-react.js +1 -1
  102. package/lib/es6/ui-react.js.gz +0 -0
  103. package/lib/indexes.js +1 -1
  104. package/lib/indexes.js.gz +0 -0
  105. package/lib/metrics.js +1 -1
  106. package/lib/metrics.js.gz +0 -0
  107. package/lib/persisters/persister-browser.js +1 -1
  108. package/lib/persisters/persister-browser.js.gz +0 -0
  109. package/lib/persisters/persister-cr-sqlite-wasm.js +1 -1
  110. package/lib/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  111. package/lib/persisters/persister-file.js +1 -1
  112. package/lib/persisters/persister-file.js.gz +0 -0
  113. package/lib/persisters/persister-remote.js +1 -1
  114. package/lib/persisters/persister-remote.js.gz +0 -0
  115. package/lib/persisters/persister-sqlite-wasm.js +1 -1
  116. package/lib/persisters/persister-sqlite-wasm.js.gz +0 -0
  117. package/lib/persisters/persister-sqlite3.js +1 -1
  118. package/lib/persisters/persister-sqlite3.js.gz +0 -0
  119. package/lib/relationships.js +1 -1
  120. package/lib/relationships.js.gz +0 -0
  121. package/lib/store.js +1 -1
  122. package/lib/store.js.gz +0 -0
  123. package/lib/tinybase.js +1 -1
  124. package/lib/tinybase.js.gz +0 -0
  125. package/lib/tools.js +1 -1
  126. package/lib/tools.js.gz +0 -0
  127. package/lib/types/persisters.d.ts +7 -0
  128. package/lib/types/with-schemas/persisters.d.ts +7 -0
  129. package/lib/ui-react.js +1 -1
  130. package/lib/ui-react.js.gz +0 -0
  131. package/lib/umd/checkpoints.js +1 -1
  132. package/lib/umd/checkpoints.js.gz +0 -0
  133. package/lib/umd/indexes.js +1 -1
  134. package/lib/umd/indexes.js.gz +0 -0
  135. package/lib/umd/metrics.js +1 -1
  136. package/lib/umd/metrics.js.gz +0 -0
  137. package/lib/umd/persisters/persister-browser.js +1 -1
  138. package/lib/umd/persisters/persister-browser.js.gz +0 -0
  139. package/lib/umd/persisters/persister-cr-sqlite-wasm.js +1 -1
  140. package/lib/umd/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  141. package/lib/umd/persisters/persister-file.js +1 -1
  142. package/lib/umd/persisters/persister-file.js.gz +0 -0
  143. package/lib/umd/persisters/persister-remote.js +1 -1
  144. package/lib/umd/persisters/persister-remote.js.gz +0 -0
  145. package/lib/umd/persisters/persister-sqlite-wasm.js +1 -1
  146. package/lib/umd/persisters/persister-sqlite-wasm.js.gz +0 -0
  147. package/lib/umd/persisters/persister-sqlite3.js +1 -1
  148. package/lib/umd/persisters/persister-sqlite3.js.gz +0 -0
  149. package/lib/umd/relationships.js +1 -1
  150. package/lib/umd/relationships.js.gz +0 -0
  151. package/lib/umd/store.js +1 -1
  152. package/lib/umd/store.js.gz +0 -0
  153. package/lib/umd/tinybase.js +1 -1
  154. package/lib/umd/tinybase.js.gz +0 -0
  155. package/lib/umd/tools.js +1 -1
  156. package/lib/umd/tools.js.gz +0 -0
  157. package/lib/umd/ui-react.js +1 -1
  158. package/lib/umd/ui-react.js.gz +0 -0
  159. package/lib/umd-es6/checkpoints.js +1 -1
  160. package/lib/umd-es6/checkpoints.js.gz +0 -0
  161. package/lib/umd-es6/indexes.js +1 -1
  162. package/lib/umd-es6/indexes.js.gz +0 -0
  163. package/lib/umd-es6/metrics.js +1 -1
  164. package/lib/umd-es6/metrics.js.gz +0 -0
  165. package/lib/umd-es6/persisters/persister-browser.js +1 -1
  166. package/lib/umd-es6/persisters/persister-browser.js.gz +0 -0
  167. package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js +1 -1
  168. package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  169. package/lib/umd-es6/persisters/persister-file.js +1 -1
  170. package/lib/umd-es6/persisters/persister-file.js.gz +0 -0
  171. package/lib/umd-es6/persisters/persister-remote.js +1 -1
  172. package/lib/umd-es6/persisters/persister-remote.js.gz +0 -0
  173. package/lib/umd-es6/persisters/persister-sqlite-wasm.js +1 -1
  174. package/lib/umd-es6/persisters/persister-sqlite-wasm.js.gz +0 -0
  175. package/lib/umd-es6/persisters/persister-sqlite3.js +1 -1
  176. package/lib/umd-es6/persisters/persister-sqlite3.js.gz +0 -0
  177. package/lib/umd-es6/relationships.js +1 -1
  178. package/lib/umd-es6/relationships.js.gz +0 -0
  179. package/lib/umd-es6/store.js +1 -1
  180. package/lib/umd-es6/store.js.gz +0 -0
  181. package/lib/umd-es6/tinybase.js +1 -1
  182. package/lib/umd-es6/tinybase.js.gz +0 -0
  183. package/lib/umd-es6/tools.js +1 -1
  184. package/lib/umd-es6/tools.js.gz +0 -0
  185. package/lib/umd-es6/ui-react.js +1 -1
  186. package/lib/umd-es6/ui-react.js.gz +0 -0
  187. package/package.json +33 -33
  188. package/readme.md +5 -5
@@ -9,27 +9,12 @@ const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
9
9
  const arrayMap = (array, cb) => array.map(cb);
10
10
  const arrayLength = (array) => array.length;
11
11
  const arrayIsEmpty = (array) => arrayLength(array) == 0;
12
- const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
13
12
  const arrayFilter = (array, cb) => array.filter(cb);
14
13
  const arraySlice = (array, start, end) => array.slice(start, end);
15
14
  const arrayPush = (array, ...values) => array.push(...values);
16
15
  const arrayShift = (array) => array.shift();
17
16
 
18
17
  const promise = Promise;
19
- const jsonString = (obj) =>
20
- JSON.stringify(obj, (_key, value) =>
21
- isInstanceOf(value, Map)
22
- ? arrayReduce(
23
- [...value],
24
- (obj2, [key, value2]) => {
25
- obj2[key] = value2;
26
- return obj2;
27
- },
28
- {},
29
- )
30
- : value,
31
- );
32
- const jsonParse = JSON.parse;
33
18
  const isInstanceOf = (thing, cls) => thing instanceof cls;
34
19
  const isUndefined = (thing) => thing == void 0;
35
20
  const ifNotUndefined = (value, then, otherwise) =>
@@ -83,10 +68,6 @@ const mapMatch = (map, obj, set, del = mapSet) => {
83
68
  return map;
84
69
  };
85
70
 
86
- const SINGLE_ROW_ID = '_';
87
- const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
88
- const escapeId = (str) => `"${str.replace(/"/g, '""')}"`;
89
-
90
71
  const setNew = (entryOrEntries) =>
91
72
  new Set(
92
73
  isArray(entryOrEntries) || isUndefined(entryOrEntries)
@@ -95,6 +76,10 @@ const setNew = (entryOrEntries) =>
95
76
  );
96
77
  const setAdd = (set, value) => set?.add(value);
97
78
 
79
+ const SINGLE_ROW_ID = '_';
80
+ const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
81
+ const escapeId = (str) => `"${str.replace(/"/g, '""')}"`;
82
+
98
83
  const SELECT_STAR_FROM = 'SELECT*FROM';
99
84
  const FROM_PRAGMA_TABLE = 'FROM pragma_table_';
100
85
  const WHERE = 'WHERE';
@@ -148,21 +133,6 @@ const getCommandFunctions = (cmd, managedTableNames) => {
148
133
  ),
149
134
  (_, name) => mapSet(schemaMap, name),
150
135
  );
151
- const loadSingleRow = async (tableName, rowIdColumnName) => {
152
- const rows = canSelect(tableName, rowIdColumnName)
153
- ? await cmd(
154
- SELECT_STAR_FROM +
155
- escapeId(tableName) +
156
- WHERE +
157
- escapeId(rowIdColumnName) +
158
- '=?',
159
- [SINGLE_ROW_ID],
160
- )
161
- : [];
162
- return arrayIsEmpty(rows) ? null : objDel(rows[0], rowIdColumnName);
163
- };
164
- const saveSingleRow = async (tableName, rowIdColumnName, rowId, row) =>
165
- await saveTable(tableName, rowIdColumnName, true, true, {[rowId]: row});
166
136
  const loadTable = async (tableName, rowIdColumnName) =>
167
137
  canSelect(tableName, rowIdColumnName)
168
138
  ? objNew(
@@ -181,30 +151,32 @@ const getCommandFunctions = (cmd, managedTableNames) => {
181
151
  const saveTable = async (
182
152
  tableName,
183
153
  rowIdColumnName,
154
+ table,
184
155
  deleteEmptyColumns,
185
156
  deleteEmptyTable,
186
- table,
157
+ partial = false,
187
158
  ) => {
188
- const cellIds = setNew();
159
+ const tableCellIds = setNew();
189
160
  objMap(table ?? {}, (row) =>
190
- arrayMap(objIds(row), (cellId) => setAdd(cellIds, cellId)),
161
+ arrayMap(objIds(row ?? {}), (cellId) => setAdd(tableCellIds, cellId)),
191
162
  );
192
- const columnNames = collValues(cellIds);
163
+ const tableColumnNames = collValues(tableCellIds);
193
164
  if (
194
- arrayIsEmpty(columnNames) &&
195
- collHas(schemaMap, tableName) &&
196
- deleteEmptyTable
165
+ !partial &&
166
+ deleteEmptyTable &&
167
+ arrayIsEmpty(tableColumnNames) &&
168
+ collHas(schemaMap, tableName)
197
169
  ) {
198
170
  await cmd('DROP TABLE' + escapeId(tableName));
199
171
  mapSet(schemaMap, tableName);
200
172
  return;
201
173
  }
202
- if (!arrayIsEmpty(columnNames) && !collHas(schemaMap, tableName)) {
174
+ if (!arrayIsEmpty(tableColumnNames) && !collHas(schemaMap, tableName)) {
203
175
  await cmd(
204
176
  `CREATE TABLE${escapeId(tableName)}(${escapeId(
205
177
  rowIdColumnName,
206
178
  )} PRIMARY KEY ON CONFLICT REPLACE${arrayJoin(
207
- arrayMap(columnNames, (cellId) => COMMA + escapeId(cellId)),
179
+ arrayMap(tableColumnNames, (cellId) => COMMA + escapeId(cellId)),
208
180
  )});`,
209
181
  );
210
182
  mapSet(
@@ -212,14 +184,17 @@ const getCommandFunctions = (cmd, managedTableNames) => {
212
184
  tableName,
213
185
  mapNew([
214
186
  [rowIdColumnName, EMPTY_STRING],
215
- ...arrayMap(columnNames, (columnName) => [columnName, EMPTY_STRING]),
187
+ ...arrayMap(tableColumnNames, (columnName) => [
188
+ columnName,
189
+ EMPTY_STRING,
190
+ ]),
216
191
  ]),
217
192
  );
218
193
  } else {
219
194
  const tableSchemaMap = mapGet(schemaMap, tableName);
220
195
  const columnNamesAccountedFor = setNew(mapKeys(tableSchemaMap));
221
196
  await promiseAll([
222
- ...arrayMap(columnNames, async (columnName) => {
197
+ ...arrayMap(tableColumnNames, async (columnName) => {
223
198
  if (!collDel(columnNamesAccountedFor, columnName)) {
224
199
  await cmd(
225
200
  `ALTER TABLE${escapeId(tableName)}ADD${escapeId(columnName)}`,
@@ -227,7 +202,7 @@ const getCommandFunctions = (cmd, managedTableNames) => {
227
202
  mapSet(tableSchemaMap, columnName, EMPTY_STRING);
228
203
  }
229
204
  }),
230
- ...(deleteEmptyColumns
205
+ ...(!partial && deleteEmptyColumns
231
206
  ? arrayMap(
232
207
  collValues(columnNamesAccountedFor),
233
208
  async (columnName) => {
@@ -244,74 +219,118 @@ const getCommandFunctions = (cmd, managedTableNames) => {
244
219
  : []),
245
220
  ]);
246
221
  }
247
- if (!arrayIsEmpty(columnNames)) {
248
- const insertSlots = [];
249
- const insertBinds = [];
250
- const deleteRowIds = [];
251
- const allColumnNames = arrayFilter(
252
- mapKeys(mapGet(schemaMap, tableName)),
253
- (columnName) => columnName != rowIdColumnName,
254
- );
255
- objMap(table, (row, rowId) => {
256
- arrayPush(
257
- insertSlots,
258
- `(?${strRepeat(',?', arrayLength(allColumnNames))})`,
222
+ if (partial) {
223
+ if (isUndefined(table)) {
224
+ await cmd('DELETE FROM' + escapeId(tableName) + 'WHERE 1');
225
+ } else {
226
+ await promiseAll(
227
+ objMap(table, async (row, rowId) => {
228
+ if (isUndefined(row)) {
229
+ await cmd(
230
+ 'DELETE FROM' +
231
+ escapeId(tableName) +
232
+ WHERE +
233
+ escapeId(rowIdColumnName) +
234
+ '=?',
235
+ [rowId],
236
+ );
237
+ } else if (!arrayIsEmpty(tableColumnNames)) {
238
+ await upsert(cmd, tableName, rowIdColumnName, objIds(row), [
239
+ rowId,
240
+ ...objValues(row),
241
+ ]);
242
+ }
243
+ }),
259
244
  );
260
- arrayPush(
261
- insertBinds,
262
- rowId,
263
- ...arrayMap(allColumnNames, (cellId) => row[cellId]),
245
+ }
246
+ } else {
247
+ if (!arrayIsEmpty(tableColumnNames)) {
248
+ const changingColumnNames = arrayFilter(
249
+ mapKeys(mapGet(schemaMap, tableName)),
250
+ (columnName) => columnName != rowIdColumnName,
264
251
  );
265
- arrayPush(deleteRowIds, rowId);
266
- });
267
- await cmd(
268
- 'INSERT INTO' +
269
- escapeId(tableName) +
270
- '(' +
271
- escapeId(rowIdColumnName) +
272
- arrayJoin(
273
- arrayMap(
274
- allColumnNames,
275
- (columnName) => COMMA + escapeId(columnName),
276
- ),
277
- ) +
278
- ')VALUES' +
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
- ),
291
- insertBinds,
292
- );
293
- await cmd(
294
- 'DELETE FROM' +
295
- escapeId(tableName) +
296
- WHERE +
297
- escapeId(rowIdColumnName) +
298
- 'NOT IN(' +
299
- getPlaceholders(deleteRowIds) +
300
- ')',
301
- deleteRowIds,
302
- );
303
- } else if (collHas(schemaMap, tableName)) {
304
- await cmd('DELETE FROM' + escapeId(tableName));
252
+ const args = [];
253
+ const deleteRowIds = [];
254
+ objMap(table ?? {}, (row, rowId) => {
255
+ arrayPush(
256
+ args,
257
+ rowId,
258
+ ...arrayMap(changingColumnNames, (cellId) => row?.[cellId]),
259
+ );
260
+ arrayPush(deleteRowIds, rowId);
261
+ });
262
+ await upsert(
263
+ cmd,
264
+ tableName,
265
+ rowIdColumnName,
266
+ changingColumnNames,
267
+ args,
268
+ );
269
+ await cmd(
270
+ 'DELETE FROM' +
271
+ escapeId(tableName) +
272
+ WHERE +
273
+ escapeId(rowIdColumnName) +
274
+ 'NOT IN(' +
275
+ getPlaceholders(deleteRowIds) +
276
+ ')',
277
+ deleteRowIds,
278
+ );
279
+ } else if (collHas(schemaMap, tableName)) {
280
+ await cmd('DELETE FROM' + escapeId(tableName) + 'WHERE 1');
281
+ }
305
282
  }
306
283
  };
307
- return [refreshSchema, loadSingleRow, saveSingleRow, loadTable, saveTable];
284
+ return [refreshSchema, loadTable, saveTable];
308
285
  };
286
+ const upsert = async (
287
+ cmd,
288
+ tableName,
289
+ rowIdColumnName,
290
+ changingColumnNames,
291
+ args,
292
+ ) =>
293
+ await cmd(
294
+ 'INSERT INTO' +
295
+ escapeId(tableName) +
296
+ '(' +
297
+ escapeId(rowIdColumnName) +
298
+ arrayJoin(
299
+ arrayMap(
300
+ changingColumnNames,
301
+ (columnName) => COMMA + escapeId(columnName),
302
+ ),
303
+ ) +
304
+ ')VALUES' +
305
+ strRepeat(
306
+ `,(?${strRepeat(',?', arrayLength(changingColumnNames))})`,
307
+ arrayLength(args) / (arrayLength(changingColumnNames) + 1),
308
+ ).substring(1) +
309
+ 'ON CONFLICT(' +
310
+ escapeId(rowIdColumnName) +
311
+ ')DO UPDATE SET' +
312
+ arrayJoin(
313
+ arrayMap(
314
+ changingColumnNames,
315
+ (columnName) =>
316
+ escapeId(columnName) + '=excluded.' + escapeId(columnName),
317
+ ),
318
+ COMMA,
319
+ ),
320
+ args,
321
+ );
309
322
  const getPlaceholders = (array) =>
310
323
  arrayJoin(
311
324
  arrayMap(array, () => '?'),
312
325
  COMMA,
313
326
  );
314
327
 
328
+ const jsonString = (obj) =>
329
+ JSON.stringify(obj, (_key, value) =>
330
+ isInstanceOf(value, Map) ? object.fromEntries([...value]) : value,
331
+ );
332
+ const jsonParse = JSON.parse;
333
+
315
334
  const createCustomPersister = (
316
335
  store,
317
336
  getPersisted,
@@ -442,25 +461,28 @@ const createJsonSqlitePersister = (
442
461
  [storeTableName],
443
462
  managedTableNames,
444
463
  ) => {
445
- const [refreshSchema, loadSingleRow, saveSingleRow] = getCommandFunctions(
464
+ const [refreshSchema, loadTable, saveTable] = getCommandFunctions(
446
465
  cmd,
447
466
  managedTableNames,
448
467
  );
449
468
  const getPersisted = async () => {
450
469
  await refreshSchema();
451
470
  return jsonParse(
452
- ((await loadSingleRow(storeTableName, DEFAULT_ROW_ID_COLUMN_NAME)) ?? {})[
453
- STORE_COLUMN
454
- ],
471
+ (await loadTable(storeTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
472
+ SINGLE_ROW_ID
473
+ ]?.[STORE_COLUMN],
455
474
  );
456
475
  };
457
476
  const setPersisted = async (getContent) =>
458
477
  persister.schedule(refreshSchema, async () => {
459
- await saveSingleRow(
478
+ await saveTable(
460
479
  storeTableName,
461
480
  DEFAULT_ROW_ID_COLUMN_NAME,
462
- SINGLE_ROW_ID,
463
- {[STORE_COLUMN]: jsonString(getContent())},
481
+ {
482
+ [SINGLE_ROW_ID]: {[STORE_COLUMN]: jsonString(getContent())},
483
+ },
484
+ true,
485
+ true,
464
486
  );
465
487
  });
466
488
  const persister = createCustomPersister(
@@ -485,32 +507,41 @@ const createTabularSqlitePersister = (
485
507
  ],
486
508
  managedTableNames,
487
509
  ) => {
488
- const [refreshSchema, loadSingleRow, saveSingleRow, loadTable, saveTable] =
489
- getCommandFunctions(cmd, managedTableNames);
490
- const saveTables = async (tables) =>
510
+ const [refreshSchema, loadTable, saveTable] = getCommandFunctions(
511
+ cmd,
512
+ managedTableNames,
513
+ );
514
+ const saveTables = async (tables, partial) =>
491
515
  await promiseAll(
492
516
  mapMap(
493
517
  tablesSaveConfig,
494
518
  async (
495
519
  [tableName, rowIdColumnName, deleteEmptyColumns, deleteEmptyTable],
496
520
  tableId,
497
- ) =>
498
- await saveTable(
499
- tableName,
500
- rowIdColumnName,
501
- deleteEmptyColumns,
502
- deleteEmptyTable,
503
- tables[tableId],
504
- ),
521
+ ) => {
522
+ const table = tables[tableId];
523
+ if (!partial || table !== void 0) {
524
+ await saveTable(
525
+ tableName,
526
+ rowIdColumnName,
527
+ table,
528
+ deleteEmptyColumns,
529
+ deleteEmptyTable,
530
+ partial,
531
+ );
532
+ }
533
+ },
505
534
  ),
506
535
  );
507
- const saveValues = async (values) =>
536
+ const saveValues = async (values, partial) =>
508
537
  valuesSave
509
- ? await saveSingleRow(
538
+ ? await saveTable(
510
539
  valuesTableName,
511
540
  DEFAULT_ROW_ID_COLUMN_NAME,
512
- SINGLE_ROW_ID,
513
- values,
541
+ {[SINGLE_ROW_ID]: values},
542
+ true,
543
+ true,
544
+ partial,
514
545
  )
515
546
  : null;
516
547
  const loadTables = async () =>
@@ -530,7 +561,9 @@ const createTabularSqlitePersister = (
530
561
  );
531
562
  const loadValues = async () =>
532
563
  valuesLoad
533
- ? await loadSingleRow(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME)
564
+ ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
565
+ SINGLE_ROW_ID
566
+ ]
534
567
  : {};
535
568
  const getPersisted = async () => {
536
569
  await refreshSchema();
@@ -540,11 +573,17 @@ const createTabularSqlitePersister = (
540
573
  ? [tables, values]
541
574
  : void 0;
542
575
  };
543
- const setPersisted = async (getContent) => {
544
- const [tables, values] = getContent();
576
+ const setPersisted = async (getContent, getTransactionChanges) => {
545
577
  await refreshSchema();
546
- await saveTables(tables);
547
- await saveValues(values);
578
+ if (!isUndefined(getTransactionChanges)) {
579
+ const [tableChanges, valueChanges] = getTransactionChanges();
580
+ await saveTables(tableChanges, true);
581
+ await saveValues(valueChanges, true);
582
+ } else {
583
+ const [tables, values] = getContent();
584
+ await saveTables(tables);
585
+ await saveValues(values);
586
+ }
548
587
  };
549
588
  const persister = createCustomPersister(
550
589
  store,
@@ -658,6 +697,7 @@ const createSqlitePersister = (
658
697
  cmd,
659
698
  addUpdateListener,
660
699
  delUpdateListener,
700
+ logSql,
661
701
  ) => {
662
702
  let dataVersion;
663
703
  let schemaVersion;
@@ -697,7 +737,12 @@ const createSqlitePersister = (
697
737
  };
698
738
  return (isJson ? createJsonSqlitePersister : createTabularSqlitePersister)(
699
739
  store,
700
- cmd,
740
+ logSql
741
+ ? async (sql, args) => {
742
+ logSql(sql, args);
743
+ return await cmd(sql, args);
744
+ }
745
+ : cmd,
701
746
  addPersisterListener,
702
747
  delPersisterListener,
703
748
  defaultedConfig,
@@ -710,6 +755,7 @@ const createSqliteWasmPersister = (
710
755
  sqlite3,
711
756
  db,
712
757
  configOrStoreTableName,
758
+ logSql,
713
759
  ) =>
714
760
  createSqlitePersister(
715
761
  store,
@@ -725,6 +771,7 @@ const createSqliteWasmPersister = (
725
771
  0,
726
772
  ),
727
773
  () => sqlite3.capi.sqlite3_update_hook(db, () => 0, 0),
774
+ logSql,
728
775
  );
729
776
 
730
777
  export {createSqliteWasmPersister};