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