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) =>
@@ -84,10 +69,6 @@ const mapMatch = (map, obj, set, del = mapSet) => {
84
69
  return map;
85
70
  };
86
71
 
87
- const SINGLE_ROW_ID = '_';
88
- const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
89
- const escapeId = (str) => `"${str.replace(/"/g, '""')}"`;
90
-
91
72
  const setNew = (entryOrEntries) =>
92
73
  new Set(
93
74
  isArray(entryOrEntries) || isUndefined(entryOrEntries)
@@ -96,6 +77,10 @@ const setNew = (entryOrEntries) =>
96
77
  );
97
78
  const setAdd = (set, value) => set?.add(value);
98
79
 
80
+ const SINGLE_ROW_ID = '_';
81
+ const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
82
+ const escapeId = (str) => `"${str.replace(/"/g, '""')}"`;
83
+
99
84
  const SELECT_STAR_FROM = 'SELECT*FROM';
100
85
  const FROM_PRAGMA_TABLE = 'FROM pragma_table_';
101
86
  const WHERE = 'WHERE';
@@ -149,21 +134,6 @@ const getCommandFunctions = (cmd, managedTableNames) => {
149
134
  ),
150
135
  (_, name) => mapSet(schemaMap, name),
151
136
  );
152
- const loadSingleRow = async (tableName, rowIdColumnName) => {
153
- const rows = canSelect(tableName, rowIdColumnName)
154
- ? await cmd(
155
- SELECT_STAR_FROM +
156
- escapeId(tableName) +
157
- WHERE +
158
- escapeId(rowIdColumnName) +
159
- '=?',
160
- [SINGLE_ROW_ID],
161
- )
162
- : [];
163
- return arrayIsEmpty(rows) ? null : objDel(rows[0], rowIdColumnName);
164
- };
165
- const saveSingleRow = async (tableName, rowIdColumnName, rowId, row) =>
166
- await saveTable(tableName, rowIdColumnName, true, true, {[rowId]: row});
167
137
  const loadTable = async (tableName, rowIdColumnName) =>
168
138
  canSelect(tableName, rowIdColumnName)
169
139
  ? objNew(
@@ -182,30 +152,32 @@ const getCommandFunctions = (cmd, managedTableNames) => {
182
152
  const saveTable = async (
183
153
  tableName,
184
154
  rowIdColumnName,
155
+ table,
185
156
  deleteEmptyColumns,
186
157
  deleteEmptyTable,
187
- table,
158
+ partial = false,
188
159
  ) => {
189
- const cellIds = setNew();
160
+ const tableCellIds = setNew();
190
161
  objMap(table ?? {}, (row) =>
191
- arrayMap(objIds(row), (cellId) => setAdd(cellIds, cellId)),
162
+ arrayMap(objIds(row ?? {}), (cellId) => setAdd(tableCellIds, cellId)),
192
163
  );
193
- const columnNames = collValues(cellIds);
164
+ const tableColumnNames = collValues(tableCellIds);
194
165
  if (
195
- arrayIsEmpty(columnNames) &&
196
- collHas(schemaMap, tableName) &&
197
- deleteEmptyTable
166
+ !partial &&
167
+ deleteEmptyTable &&
168
+ arrayIsEmpty(tableColumnNames) &&
169
+ collHas(schemaMap, tableName)
198
170
  ) {
199
171
  await cmd('DROP TABLE' + escapeId(tableName));
200
172
  mapSet(schemaMap, tableName);
201
173
  return;
202
174
  }
203
- if (!arrayIsEmpty(columnNames) && !collHas(schemaMap, tableName)) {
175
+ if (!arrayIsEmpty(tableColumnNames) && !collHas(schemaMap, tableName)) {
204
176
  await cmd(
205
177
  `CREATE TABLE${escapeId(tableName)}(${escapeId(
206
178
  rowIdColumnName,
207
179
  )} PRIMARY KEY ON CONFLICT REPLACE${arrayJoin(
208
- arrayMap(columnNames, (cellId) => COMMA + escapeId(cellId)),
180
+ arrayMap(tableColumnNames, (cellId) => COMMA + escapeId(cellId)),
209
181
  )});`,
210
182
  );
211
183
  mapSet(
@@ -213,14 +185,17 @@ const getCommandFunctions = (cmd, managedTableNames) => {
213
185
  tableName,
214
186
  mapNew([
215
187
  [rowIdColumnName, EMPTY_STRING],
216
- ...arrayMap(columnNames, (columnName) => [columnName, EMPTY_STRING]),
188
+ ...arrayMap(tableColumnNames, (columnName) => [
189
+ columnName,
190
+ EMPTY_STRING,
191
+ ]),
217
192
  ]),
218
193
  );
219
194
  } else {
220
195
  const tableSchemaMap = mapGet(schemaMap, tableName);
221
196
  const columnNamesAccountedFor = setNew(mapKeys(tableSchemaMap));
222
197
  await promiseAll([
223
- ...arrayMap(columnNames, async (columnName) => {
198
+ ...arrayMap(tableColumnNames, async (columnName) => {
224
199
  if (!collDel(columnNamesAccountedFor, columnName)) {
225
200
  await cmd(
226
201
  `ALTER TABLE${escapeId(tableName)}ADD${escapeId(columnName)}`,
@@ -228,7 +203,7 @@ const getCommandFunctions = (cmd, managedTableNames) => {
228
203
  mapSet(tableSchemaMap, columnName, EMPTY_STRING);
229
204
  }
230
205
  }),
231
- ...(deleteEmptyColumns
206
+ ...(!partial && deleteEmptyColumns
232
207
  ? arrayMap(
233
208
  collValues(columnNamesAccountedFor),
234
209
  async (columnName) => {
@@ -245,74 +220,118 @@ const getCommandFunctions = (cmd, managedTableNames) => {
245
220
  : []),
246
221
  ]);
247
222
  }
248
- if (!arrayIsEmpty(columnNames)) {
249
- const insertSlots = [];
250
- const insertBinds = [];
251
- const deleteRowIds = [];
252
- const allColumnNames = arrayFilter(
253
- mapKeys(mapGet(schemaMap, tableName)),
254
- (columnName) => columnName != rowIdColumnName,
255
- );
256
- objMap(table, (row, rowId) => {
257
- arrayPush(
258
- insertSlots,
259
- `(?${strRepeat(',?', arrayLength(allColumnNames))})`,
223
+ if (partial) {
224
+ if (isUndefined(table)) {
225
+ await cmd('DELETE FROM' + escapeId(tableName) + 'WHERE 1');
226
+ } else {
227
+ await promiseAll(
228
+ objMap(table, async (row, rowId) => {
229
+ if (isUndefined(row)) {
230
+ await cmd(
231
+ 'DELETE FROM' +
232
+ escapeId(tableName) +
233
+ WHERE +
234
+ escapeId(rowIdColumnName) +
235
+ '=?',
236
+ [rowId],
237
+ );
238
+ } else if (!arrayIsEmpty(tableColumnNames)) {
239
+ await upsert(cmd, tableName, rowIdColumnName, objIds(row), [
240
+ rowId,
241
+ ...objValues(row),
242
+ ]);
243
+ }
244
+ }),
260
245
  );
261
- arrayPush(
262
- insertBinds,
263
- rowId,
264
- ...arrayMap(allColumnNames, (cellId) => row[cellId]),
246
+ }
247
+ } else {
248
+ if (!arrayIsEmpty(tableColumnNames)) {
249
+ const changingColumnNames = arrayFilter(
250
+ mapKeys(mapGet(schemaMap, tableName)),
251
+ (columnName) => columnName != rowIdColumnName,
265
252
  );
266
- arrayPush(deleteRowIds, rowId);
267
- });
268
- await cmd(
269
- 'INSERT INTO' +
270
- escapeId(tableName) +
271
- '(' +
272
- escapeId(rowIdColumnName) +
273
- arrayJoin(
274
- arrayMap(
275
- allColumnNames,
276
- (columnName) => COMMA + escapeId(columnName),
277
- ),
278
- ) +
279
- ')VALUES' +
280
- arrayJoin(insertSlots, COMMA) +
281
- 'ON CONFLICT(' +
282
- escapeId(rowIdColumnName) +
283
- ')DO UPDATE SET' +
284
- arrayJoin(
285
- arrayMap(
286
- allColumnNames,
287
- (columnName) =>
288
- escapeId(columnName) + '=excluded.' + escapeId(columnName),
289
- ),
290
- COMMA,
291
- ),
292
- insertBinds,
293
- );
294
- await cmd(
295
- 'DELETE FROM' +
296
- escapeId(tableName) +
297
- WHERE +
298
- escapeId(rowIdColumnName) +
299
- 'NOT IN(' +
300
- getPlaceholders(deleteRowIds) +
301
- ')',
302
- deleteRowIds,
303
- );
304
- } else if (collHas(schemaMap, tableName)) {
305
- await cmd('DELETE FROM' + escapeId(tableName));
253
+ const args = [];
254
+ const deleteRowIds = [];
255
+ objMap(table ?? {}, (row, rowId) => {
256
+ arrayPush(
257
+ args,
258
+ rowId,
259
+ ...arrayMap(changingColumnNames, (cellId) => row?.[cellId]),
260
+ );
261
+ arrayPush(deleteRowIds, rowId);
262
+ });
263
+ await upsert(
264
+ cmd,
265
+ tableName,
266
+ rowIdColumnName,
267
+ changingColumnNames,
268
+ args,
269
+ );
270
+ await cmd(
271
+ 'DELETE FROM' +
272
+ escapeId(tableName) +
273
+ WHERE +
274
+ escapeId(rowIdColumnName) +
275
+ 'NOT IN(' +
276
+ getPlaceholders(deleteRowIds) +
277
+ ')',
278
+ deleteRowIds,
279
+ );
280
+ } else if (collHas(schemaMap, tableName)) {
281
+ await cmd('DELETE FROM' + escapeId(tableName) + 'WHERE 1');
282
+ }
306
283
  }
307
284
  };
308
- return [refreshSchema, loadSingleRow, saveSingleRow, loadTable, saveTable];
285
+ return [refreshSchema, loadTable, saveTable];
309
286
  };
287
+ const upsert = async (
288
+ cmd,
289
+ tableName,
290
+ rowIdColumnName,
291
+ changingColumnNames,
292
+ args,
293
+ ) =>
294
+ await cmd(
295
+ 'INSERT INTO' +
296
+ escapeId(tableName) +
297
+ '(' +
298
+ escapeId(rowIdColumnName) +
299
+ arrayJoin(
300
+ arrayMap(
301
+ changingColumnNames,
302
+ (columnName) => COMMA + escapeId(columnName),
303
+ ),
304
+ ) +
305
+ ')VALUES' +
306
+ strRepeat(
307
+ `,(?${strRepeat(',?', arrayLength(changingColumnNames))})`,
308
+ arrayLength(args) / (arrayLength(changingColumnNames) + 1),
309
+ ).substring(1) +
310
+ 'ON CONFLICT(' +
311
+ escapeId(rowIdColumnName) +
312
+ ')DO UPDATE SET' +
313
+ arrayJoin(
314
+ arrayMap(
315
+ changingColumnNames,
316
+ (columnName) =>
317
+ escapeId(columnName) + '=excluded.' + escapeId(columnName),
318
+ ),
319
+ COMMA,
320
+ ),
321
+ args,
322
+ );
310
323
  const getPlaceholders = (array) =>
311
324
  arrayJoin(
312
325
  arrayMap(array, () => '?'),
313
326
  COMMA,
314
327
  );
315
328
 
329
+ const jsonString = (obj) =>
330
+ JSON.stringify(obj, (_key, value) =>
331
+ isInstanceOf(value, Map) ? object.fromEntries([...value]) : value,
332
+ );
333
+ const jsonParse = JSON.parse;
334
+
316
335
  const createCustomPersister = (
317
336
  store,
318
337
  getPersisted,
@@ -443,25 +462,28 @@ const createJsonSqlitePersister = (
443
462
  [storeTableName],
444
463
  managedTableNames,
445
464
  ) => {
446
- const [refreshSchema, loadSingleRow, saveSingleRow] = getCommandFunctions(
465
+ const [refreshSchema, loadTable, saveTable] = getCommandFunctions(
447
466
  cmd,
448
467
  managedTableNames,
449
468
  );
450
469
  const getPersisted = async () => {
451
470
  await refreshSchema();
452
471
  return jsonParse(
453
- ((await loadSingleRow(storeTableName, DEFAULT_ROW_ID_COLUMN_NAME)) ?? {})[
454
- STORE_COLUMN
455
- ],
472
+ (await loadTable(storeTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
473
+ SINGLE_ROW_ID
474
+ ]?.[STORE_COLUMN],
456
475
  );
457
476
  };
458
477
  const setPersisted = async (getContent) =>
459
478
  persister.schedule(refreshSchema, async () => {
460
- await saveSingleRow(
479
+ await saveTable(
461
480
  storeTableName,
462
481
  DEFAULT_ROW_ID_COLUMN_NAME,
463
- SINGLE_ROW_ID,
464
- {[STORE_COLUMN]: jsonString(getContent())},
482
+ {
483
+ [SINGLE_ROW_ID]: {[STORE_COLUMN]: jsonString(getContent())},
484
+ },
485
+ true,
486
+ true,
465
487
  );
466
488
  });
467
489
  const persister = createCustomPersister(
@@ -486,32 +508,41 @@ const createTabularSqlitePersister = (
486
508
  ],
487
509
  managedTableNames,
488
510
  ) => {
489
- const [refreshSchema, loadSingleRow, saveSingleRow, loadTable, saveTable] =
490
- getCommandFunctions(cmd, managedTableNames);
491
- const saveTables = async (tables) =>
511
+ const [refreshSchema, loadTable, saveTable] = getCommandFunctions(
512
+ cmd,
513
+ managedTableNames,
514
+ );
515
+ const saveTables = async (tables, partial) =>
492
516
  await promiseAll(
493
517
  mapMap(
494
518
  tablesSaveConfig,
495
519
  async (
496
520
  [tableName, rowIdColumnName, deleteEmptyColumns, deleteEmptyTable],
497
521
  tableId,
498
- ) =>
499
- await saveTable(
500
- tableName,
501
- rowIdColumnName,
502
- deleteEmptyColumns,
503
- deleteEmptyTable,
504
- tables[tableId],
505
- ),
522
+ ) => {
523
+ const table = tables[tableId];
524
+ if (!partial || table !== void 0) {
525
+ await saveTable(
526
+ tableName,
527
+ rowIdColumnName,
528
+ table,
529
+ deleteEmptyColumns,
530
+ deleteEmptyTable,
531
+ partial,
532
+ );
533
+ }
534
+ },
506
535
  ),
507
536
  );
508
- const saveValues = async (values) =>
537
+ const saveValues = async (values, partial) =>
509
538
  valuesSave
510
- ? await saveSingleRow(
539
+ ? await saveTable(
511
540
  valuesTableName,
512
541
  DEFAULT_ROW_ID_COLUMN_NAME,
513
- SINGLE_ROW_ID,
514
- values,
542
+ {[SINGLE_ROW_ID]: values},
543
+ true,
544
+ true,
545
+ partial,
515
546
  )
516
547
  : null;
517
548
  const loadTables = async () =>
@@ -531,7 +562,9 @@ const createTabularSqlitePersister = (
531
562
  );
532
563
  const loadValues = async () =>
533
564
  valuesLoad
534
- ? await loadSingleRow(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME)
565
+ ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
566
+ SINGLE_ROW_ID
567
+ ]
535
568
  : {};
536
569
  const getPersisted = async () => {
537
570
  await refreshSchema();
@@ -541,11 +574,17 @@ const createTabularSqlitePersister = (
541
574
  ? [tables, values]
542
575
  : void 0;
543
576
  };
544
- const setPersisted = async (getContent) => {
545
- const [tables, values] = getContent();
577
+ const setPersisted = async (getContent, getTransactionChanges) => {
546
578
  await refreshSchema();
547
- await saveTables(tables);
548
- await saveValues(values);
579
+ if (!isUndefined(getTransactionChanges)) {
580
+ const [tableChanges, valueChanges] = getTransactionChanges();
581
+ await saveTables(tableChanges, true);
582
+ await saveValues(valueChanges, true);
583
+ } else {
584
+ const [tables, values] = getContent();
585
+ await saveTables(tables);
586
+ await saveValues(values);
587
+ }
549
588
  };
550
589
  const persister = createCustomPersister(
551
590
  store,
@@ -659,6 +698,7 @@ const createSqlitePersister = (
659
698
  cmd,
660
699
  addUpdateListener,
661
700
  delUpdateListener,
701
+ logSql,
662
702
  ) => {
663
703
  let dataVersion;
664
704
  let schemaVersion;
@@ -698,7 +738,12 @@ const createSqlitePersister = (
698
738
  };
699
739
  return (isJson ? createJsonSqlitePersister : createTabularSqlitePersister)(
700
740
  store,
701
- cmd,
741
+ logSql
742
+ ? async (sql, args) => {
743
+ logSql(sql, args);
744
+ return await cmd(sql, args);
745
+ }
746
+ : cmd,
702
747
  addPersisterListener,
703
748
  delPersisterListener,
704
749
  defaultedConfig,
@@ -707,7 +752,7 @@ const createSqlitePersister = (
707
752
  };
708
753
 
709
754
  const CHANGE = 'change';
710
- const createSqlite3Persister = (store, db, configOrStoreTableName) =>
755
+ const createSqlite3Persister = (store, db, configOrStoreTableName, logSql) =>
711
756
  createSqlitePersister(
712
757
  store,
713
758
  configOrStoreTableName,
@@ -723,6 +768,7 @@ const createSqlite3Persister = (store, db, configOrStoreTableName) =>
723
768
  return observer;
724
769
  },
725
770
  (observer) => db.off(CHANGE, observer),
771
+ logSql,
726
772
  );
727
773
 
728
774
  export {createSqlite3Persister};
@@ -1,12 +1,12 @@
1
- const arrayLength = (array) => array.length;
2
- const arrayPush = (array, ...values) => array.push(...values);
3
- const arrayShift = (array) => array.shift();
4
-
5
1
  const isInstanceOf = (thing, cls) => thing instanceof cls;
6
2
  const isUndefined = (thing) => thing == void 0;
7
3
  const ifNotUndefined = (value, then, otherwise) =>
8
4
  isUndefined(value) ? otherwise?.() : then(value);
9
5
 
6
+ const arrayLength = (array) => array.length;
7
+ const arrayPush = (array, ...values) => array.push(...values);
8
+ const arrayShift = (array) => array.shift();
9
+
10
10
  const object = Object;
11
11
  const objIds = object.keys;
12
12
  const objFreeze = object.freeze;
@@ -2,6 +2,13 @@ const getTypeOf = (thing) => typeof thing;
2
2
  const EMPTY_STRING = '';
3
3
  const STRING = getTypeOf(EMPTY_STRING);
4
4
 
5
+ const isUndefined = (thing) => thing == void 0;
6
+ const ifNotUndefined = (value, then, otherwise) =>
7
+ isUndefined(value) ? otherwise?.() : then(value);
8
+ const isString = (thing) => getTypeOf(thing) == STRING;
9
+ const isArray = (thing) => Array.isArray(thing);
10
+ const test = (regex, subject) => regex.test(subject);
11
+
5
12
  const arrayEvery = (array, cb) => array.every(cb);
6
13
  const arrayIsEqual = (array1, array2) =>
7
14
  arrayLength(array1) === arrayLength(array2) &&
@@ -13,13 +20,6 @@ const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
13
20
  const arrayPush = (array, ...values) => array.push(...values);
14
21
  const arrayShift = (array) => array.shift();
15
22
 
16
- const isUndefined = (thing) => thing == void 0;
17
- const ifNotUndefined = (value, then, otherwise) =>
18
- isUndefined(value) ? otherwise?.() : then(value);
19
- const isString = (thing) => getTypeOf(thing) == STRING;
20
- const isArray = (thing) => Array.isArray(thing);
21
- const test = (regex, subject) => regex.test(subject);
22
-
23
23
  const object = Object;
24
24
  const objFreeze = object.freeze;
25
25
 
@@ -21,6 +21,16 @@ const VALUES = VALUE + 's';
21
21
  const VALUE_IDS = VALUE + IDS;
22
22
  const id = (key) => EMPTY_STRING + key;
23
23
 
24
+ const isFiniteNumber = isFinite;
25
+ const isInstanceOf = (thing, cls) => thing instanceof cls;
26
+ const isUndefined = (thing) => thing == void 0;
27
+ const ifNotUndefined = (value, then, otherwise) =>
28
+ isUndefined(value) ? otherwise?.() : then(value);
29
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
30
+ const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
31
+ const isArray = (thing) => Array.isArray(thing);
32
+ const test = (regex, subject) => regex.test(subject);
33
+
24
34
  const arrayHas = (array, value) => array.includes(value);
25
35
  const arrayEvery = (array, cb) => array.every(cb);
26
36
  const arrayIsEqual = (array1, array2) =>
@@ -35,30 +45,6 @@ const arraySlice = (array, start, end) => array.slice(start, end);
35
45
  const arrayPush = (array, ...values) => array.push(...values);
36
46
  const arrayShift = (array) => array.shift();
37
47
 
38
- const jsonString = (obj) =>
39
- JSON.stringify(obj, (_key, value) =>
40
- isInstanceOf(value, Map)
41
- ? arrayReduce(
42
- [...value],
43
- (obj2, [key, value2]) => {
44
- obj2[key] = value2;
45
- return obj2;
46
- },
47
- {},
48
- )
49
- : value,
50
- );
51
- const jsonParse = JSON.parse;
52
- const isFiniteNumber = isFinite;
53
- const isInstanceOf = (thing, cls) => thing instanceof cls;
54
- const isUndefined = (thing) => thing == void 0;
55
- const ifNotUndefined = (value, then, otherwise) =>
56
- isUndefined(value) ? otherwise?.() : then(value);
57
- const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
58
- const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
59
- const isArray = (thing) => Array.isArray(thing);
60
- const test = (regex, subject) => regex.test(subject);
61
-
62
48
  const object = Object;
63
49
  const objIds = object.keys;
64
50
  const objFrozen = object.isFrozen;
@@ -269,6 +255,12 @@ const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
269
255
  const setOrDelValue = (store, valueId, value) =>
270
256
  isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
271
257
 
258
+ const jsonString = (obj) =>
259
+ JSON.stringify(obj, (_key, value) =>
260
+ isInstanceOf(value, Map) ? object.fromEntries([...value]) : value,
261
+ );
262
+ const jsonParse = JSON.parse;
263
+
272
264
  const defaultSorter = (sortKey1, sortKey2) => (sortKey1 < sortKey2 ? -1 : 1);
273
265
 
274
266
  const validate = (obj, validateChild, onInvalidObj) => {
@@ -28,6 +28,20 @@ const VALUES = VALUE + 's';
28
28
  const VALUE_IDS = VALUE + IDS;
29
29
  const id = (key) => EMPTY_STRING + key;
30
30
 
31
+ const mathMax = Math.max;
32
+ const mathMin = Math.min;
33
+ const isFiniteNumber = isFinite;
34
+ const isInstanceOf = (thing, cls) => thing instanceof cls;
35
+ const isUndefined = (thing) => thing == void 0;
36
+ const ifNotUndefined = (value, then, otherwise) =>
37
+ isUndefined(value) ? otherwise?.() : then(value);
38
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
39
+ const isString = (thing) => getTypeOf(thing) == STRING;
40
+ const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
41
+ const isArray = (thing) => Array.isArray(thing);
42
+ const test = (regex, subject) => regex.test(subject);
43
+ const getUndefined = () => void 0;
44
+
31
45
  const arrayHas = (array, value) => array.includes(value);
32
46
  const arrayEvery = (array, cb) => array.every(cb);
33
47
  const arrayIsEqual = (array1, array2) =>
@@ -52,34 +66,6 @@ const arrayPop = (array) => array.pop();
52
66
  const arrayUnshift = (array, ...values) => array.unshift(...values);
53
67
  const arrayShift = (array) => array.shift();
54
68
 
55
- const jsonString = (obj) =>
56
- JSON.stringify(obj, (_key, value) =>
57
- isInstanceOf(value, Map)
58
- ? arrayReduce(
59
- [...value],
60
- (obj2, [key, value2]) => {
61
- obj2[key] = value2;
62
- return obj2;
63
- },
64
- {},
65
- )
66
- : value,
67
- );
68
- const jsonParse = JSON.parse;
69
- const mathMax = Math.max;
70
- const mathMin = Math.min;
71
- const isFiniteNumber = isFinite;
72
- const isInstanceOf = (thing, cls) => thing instanceof cls;
73
- const isUndefined = (thing) => thing == void 0;
74
- const ifNotUndefined = (value, then, otherwise) =>
75
- isUndefined(value) ? otherwise?.() : then(value);
76
- const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
77
- const isString = (thing) => getTypeOf(thing) == STRING;
78
- const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
79
- const isArray = (thing) => Array.isArray(thing);
80
- const test = (regex, subject) => regex.test(subject);
81
- const getUndefined = () => void 0;
82
-
83
69
  const object = Object;
84
70
  const objIds = object.keys;
85
71
  const objFrozen = object.isFrozen;
@@ -1780,6 +1766,12 @@ const pairNewMap = () => [mapNew(), mapNew()];
1780
1766
  const pairClone = (array) => [...array];
1781
1767
  const pairIsEqual = ([entry1, entry2]) => entry1 === entry2;
1782
1768
 
1769
+ const jsonString = (obj) =>
1770
+ JSON.stringify(obj, (_key, value) =>
1771
+ isInstanceOf(value, Map) ? object.fromEntries([...value]) : value,
1772
+ );
1773
+ const jsonParse = JSON.parse;
1774
+
1783
1775
  const validate = (obj, validateChild, onInvalidObj) => {
1784
1776
  if (isUndefined(obj) || !isObject(obj) || objIsEmpty(obj) || objFrozen(obj)) {
1785
1777
  onInvalidObj?.();