tinybase 6.1.0-beta.4 → 6.1.0-beta.5
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/@types/persisters/index.d.ts +82 -40
- package/@types/persisters/persister-automerge/index.d.ts +4 -4
- package/@types/persisters/persister-automerge/with-schemas/index.d.ts +4 -4
- package/@types/persisters/persister-browser/index.d.ts +4 -4
- package/@types/persisters/persister-browser/with-schemas/index.d.ts +4 -4
- package/@types/persisters/persister-cr-sqlite-wasm/index.d.ts +3 -3
- package/@types/persisters/persister-cr-sqlite-wasm/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-electric-sql/index.d.ts +3 -3
- package/@types/persisters/persister-electric-sql/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-expo-sqlite/index.d.ts +3 -3
- package/@types/persisters/persister-expo-sqlite/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-file/index.d.ts +2 -2
- package/@types/persisters/persister-file/with-schemas/index.d.ts +2 -2
- package/@types/persisters/persister-indexed-db/index.d.ts +2 -2
- package/@types/persisters/persister-indexed-db/with-schemas/index.d.ts +2 -2
- package/@types/persisters/persister-libsql/index.d.ts +3 -3
- package/@types/persisters/persister-libsql/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-partykit-client/index.d.ts +2 -2
- package/@types/persisters/persister-partykit-client/with-schemas/index.d.ts +2 -2
- package/@types/persisters/persister-pglite/index.d.ts +3 -3
- package/@types/persisters/persister-pglite/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-postgres/index.d.ts +3 -3
- package/@types/persisters/persister-postgres/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-powersync/index.d.ts +3 -3
- package/@types/persisters/persister-powersync/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-remote/index.d.ts +2 -2
- package/@types/persisters/persister-remote/with-schemas/index.d.ts +2 -2
- package/@types/persisters/persister-sqlite-bun/index.d.ts +3 -3
- package/@types/persisters/persister-sqlite-bun/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-sqlite-wasm/index.d.ts +3 -3
- package/@types/persisters/persister-sqlite-wasm/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-sqlite3/index.d.ts +3 -3
- package/@types/persisters/persister-sqlite3/with-schemas/index.d.ts +3 -3
- package/@types/persisters/persister-yjs/index.d.ts +4 -4
- package/@types/persisters/persister-yjs/with-schemas/index.d.ts +4 -4
- package/@types/persisters/with-schemas/index.d.ts +86 -42
- package/@types/synchronizers/index.d.ts +18 -16
- package/@types/synchronizers/synchronizer-broadcast-channel/index.d.ts +3 -3
- package/@types/synchronizers/synchronizer-broadcast-channel/with-schemas/index.d.ts +3 -3
- package/@types/synchronizers/synchronizer-local/index.d.ts +2 -2
- package/@types/synchronizers/synchronizer-local/with-schemas/index.d.ts +2 -2
- package/@types/synchronizers/synchronizer-ws-client/index.d.ts +5 -5
- package/@types/synchronizers/synchronizer-ws-client/with-schemas/index.d.ts +5 -5
- package/@types/synchronizers/synchronizer-ws-server/index.d.ts +37 -37
- package/@types/synchronizers/synchronizer-ws-server/with-schemas/index.d.ts +37 -37
- package/@types/synchronizers/synchronizer-ws-server-simple/index.d.ts +7 -7
- package/@types/synchronizers/synchronizer-ws-server-simple/with-schemas/index.d.ts +7 -7
- package/@types/synchronizers/with-schemas/index.d.ts +18 -16
- package/@types/ui-react/index.d.ts +2 -2
- package/@types/ui-react/with-schemas/index.d.ts +2 -2
- package/index.js +23 -17
- package/mergeable-store/index.js +23 -17
- package/mergeable-store/with-schemas/index.js +23 -17
- package/min/index.js +1 -1
- package/min/index.js.gz +0 -0
- package/min/mergeable-store/index.js +1 -1
- package/min/mergeable-store/index.js.gz +0 -0
- package/min/mergeable-store/with-schemas/index.js +1 -1
- package/min/mergeable-store/with-schemas/index.js.gz +0 -0
- package/min/persisters/index.js +1 -1
- package/min/persisters/index.js.gz +0 -0
- package/min/persisters/persister-automerge/index.js +1 -1
- package/min/persisters/persister-automerge/index.js.gz +0 -0
- package/min/persisters/persister-automerge/with-schemas/index.js +1 -1
- package/min/persisters/persister-automerge/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-browser/index.js +1 -1
- package/min/persisters/persister-browser/index.js.gz +0 -0
- package/min/persisters/persister-browser/with-schemas/index.js +1 -1
- package/min/persisters/persister-browser/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
- package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
- package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
- package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-storage/index.js +1 -1
- package/min/persisters/persister-durable-object-storage/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-storage/with-schemas/index.js +1 -1
- package/min/persisters/persister-durable-object-storage/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-electric-sql/index.js +1 -1
- package/min/persisters/persister-electric-sql/index.js.gz +0 -0
- package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
- package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-expo-sqlite/index.js +1 -1
- package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
- package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
- package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-file/index.js +1 -1
- package/min/persisters/persister-file/index.js.gz +0 -0
- package/min/persisters/persister-file/with-schemas/index.js +1 -1
- package/min/persisters/persister-file/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-indexed-db/index.js +1 -1
- package/min/persisters/persister-indexed-db/index.js.gz +0 -0
- package/min/persisters/persister-indexed-db/with-schemas/index.js +1 -1
- package/min/persisters/persister-indexed-db/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-libsql/index.js +1 -1
- package/min/persisters/persister-libsql/index.js.gz +0 -0
- package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
- package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-partykit-client/index.js +1 -1
- package/min/persisters/persister-partykit-client/index.js.gz +0 -0
- package/min/persisters/persister-partykit-client/with-schemas/index.js +1 -1
- package/min/persisters/persister-partykit-client/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-pglite/index.js +1 -1
- package/min/persisters/persister-pglite/index.js.gz +0 -0
- package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
- package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-postgres/index.js +1 -1
- package/min/persisters/persister-postgres/index.js.gz +0 -0
- package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
- package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-powersync/index.js +1 -1
- package/min/persisters/persister-powersync/index.js.gz +0 -0
- package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
- package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-remote/index.js +1 -1
- package/min/persisters/persister-remote/index.js.gz +0 -0
- package/min/persisters/persister-remote/with-schemas/index.js +1 -1
- package/min/persisters/persister-remote/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-bun/index.js +1 -1
- package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-wasm/index.js +1 -1
- package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite3/index.js +1 -1
- package/min/persisters/persister-sqlite3/index.js.gz +0 -0
- package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-yjs/index.js +1 -1
- package/min/persisters/persister-yjs/index.js.gz +0 -0
- package/min/persisters/persister-yjs/with-schemas/index.js +1 -1
- package/min/persisters/persister-yjs/with-schemas/index.js.gz +0 -0
- package/min/persisters/with-schemas/index.js +1 -1
- package/min/persisters/with-schemas/index.js.gz +0 -0
- package/min/store/index.js +1 -1
- package/min/store/index.js.gz +0 -0
- package/min/store/with-schemas/index.js +1 -1
- package/min/store/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/index.js +1 -1
- package/min/synchronizers/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-broadcast-channel/index.js +1 -1
- package/min/synchronizers/synchronizer-broadcast-channel/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-local/index.js +1 -1
- package/min/synchronizers/synchronizer-local/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-local/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-local/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-simple/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-simple/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/with-schemas/index.js +1 -1
- package/min/synchronizers/with-schemas/index.js.gz +0 -0
- package/min/ui-react-inspector/index.js +1 -1
- package/min/ui-react-inspector/index.js.gz +0 -0
- package/min/ui-react-inspector/with-schemas/index.js +1 -1
- package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
- package/min/with-schemas/index.js +1 -1
- package/min/with-schemas/index.js.gz +0 -0
- package/package.json +8 -4
- package/persisters/index.js +293 -161
- package/persisters/persister-automerge/index.js +55 -50
- package/persisters/persister-automerge/with-schemas/index.js +55 -50
- package/persisters/persister-browser/index.js +56 -55
- package/persisters/persister-browser/with-schemas/index.js +56 -55
- package/persisters/persister-cr-sqlite-wasm/index.js +181 -134
- package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +181 -134
- package/persisters/persister-durable-object-storage/index.js +58 -53
- package/persisters/persister-durable-object-storage/with-schemas/index.js +58 -53
- package/persisters/persister-electric-sql/index.js +181 -134
- package/persisters/persister-electric-sql/with-schemas/index.js +181 -134
- package/persisters/persister-expo-sqlite/index.js +181 -134
- package/persisters/persister-expo-sqlite/with-schemas/index.js +181 -134
- package/persisters/persister-file/index.js +55 -50
- package/persisters/persister-file/with-schemas/index.js +55 -50
- package/persisters/persister-indexed-db/index.js +82 -78
- package/persisters/persister-indexed-db/with-schemas/index.js +82 -78
- package/persisters/persister-libsql/index.js +182 -135
- package/persisters/persister-libsql/with-schemas/index.js +182 -135
- package/persisters/persister-partykit-client/index.js +56 -51
- package/persisters/persister-partykit-client/with-schemas/index.js +56 -51
- package/persisters/persister-pglite/index.js +299 -173
- package/persisters/persister-pglite/with-schemas/index.js +299 -173
- package/persisters/persister-postgres/index.js +296 -171
- package/persisters/persister-postgres/with-schemas/index.js +296 -171
- package/persisters/persister-powersync/index.js +189 -138
- package/persisters/persister-powersync/with-schemas/index.js +189 -138
- package/persisters/persister-remote/index.js +55 -50
- package/persisters/persister-remote/with-schemas/index.js +55 -50
- package/persisters/persister-sqlite-bun/index.js +182 -135
- package/persisters/persister-sqlite-bun/with-schemas/index.js +182 -135
- package/persisters/persister-sqlite-wasm/index.js +182 -135
- package/persisters/persister-sqlite-wasm/with-schemas/index.js +182 -135
- package/persisters/persister-sqlite3/index.js +181 -134
- package/persisters/persister-sqlite3/with-schemas/index.js +181 -134
- package/persisters/persister-yjs/index.js +55 -50
- package/persisters/persister-yjs/with-schemas/index.js +55 -50
- package/persisters/with-schemas/index.js +293 -161
- package/readme.md +2 -2
- package/releases.md +29 -1
- package/store/index.js +20 -15
- package/store/with-schemas/index.js +20 -15
- package/synchronizers/index.js +68 -63
- package/synchronizers/synchronizer-broadcast-channel/index.js +68 -63
- package/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +68 -63
- package/synchronizers/synchronizer-local/index.js +68 -63
- package/synchronizers/synchronizer-local/with-schemas/index.js +68 -63
- package/synchronizers/synchronizer-ws-client/index.js +68 -63
- package/synchronizers/synchronizer-ws-client/with-schemas/index.js +68 -63
- package/synchronizers/synchronizer-ws-server/index.js +79 -70
- package/synchronizers/synchronizer-ws-server/with-schemas/index.js +79 -70
- package/synchronizers/synchronizer-ws-server-durable-object/index.js +69 -51
- package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +69 -51
- package/synchronizers/synchronizer-ws-server-simple/index.js +1 -1
- package/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +1 -1
- package/synchronizers/with-schemas/index.js +68 -63
- package/ui-react-inspector/index.js +68 -60
- package/ui-react-inspector/with-schemas/index.js +68 -60
- package/with-schemas/index.js +23 -17
package/persisters/index.js
CHANGED
|
@@ -3,10 +3,14 @@ const TINYBASE = 'tinybase';
|
|
|
3
3
|
const EMPTY_STRING = '';
|
|
4
4
|
const COMMA = ',';
|
|
5
5
|
const STRING = getTypeOf(EMPTY_STRING);
|
|
6
|
+
const TRUE = 'true';
|
|
6
7
|
const UNDEFINED = '\uFFFC';
|
|
7
8
|
const strMatch = (str, regex) => str?.match(regex);
|
|
9
|
+
const strReplace = (str, searchValue, replaceValue) =>
|
|
10
|
+
str.replace(searchValue, replaceValue);
|
|
8
11
|
|
|
9
12
|
const promise = Promise;
|
|
13
|
+
const GLOBAL = globalThis;
|
|
10
14
|
const THOUSAND = 1e3;
|
|
11
15
|
const startInterval = (callback, sec, immediate) => {
|
|
12
16
|
return setInterval(callback, sec * THOUSAND);
|
|
@@ -24,6 +28,14 @@ const promiseAll = async (promises) => promise.all(promises);
|
|
|
24
28
|
const errorNew = (message) => {
|
|
25
29
|
throw new Error(message);
|
|
26
30
|
};
|
|
31
|
+
const tryCatch = async (action, then1, then2) => {
|
|
32
|
+
try {
|
|
33
|
+
return await action();
|
|
34
|
+
} catch (error) {
|
|
35
|
+
/* istanbul ignore next */
|
|
36
|
+
then1?.(error);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
27
39
|
|
|
28
40
|
const arrayForEach = (array, cb) => array.forEach(cb);
|
|
29
41
|
const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
|
|
@@ -75,6 +87,8 @@ const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
|
|
|
75
87
|
|
|
76
88
|
const mapNew = (entries) => new Map(entries);
|
|
77
89
|
const mapGet = (map, key) => map?.get(key);
|
|
90
|
+
const mapForEach = (map, cb) =>
|
|
91
|
+
collForEach(map, (value, key) => cb(key, value));
|
|
78
92
|
const mapMap = (coll, cb) =>
|
|
79
93
|
arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
|
|
80
94
|
const mapSet = (map, key, value) =>
|
|
@@ -283,12 +297,7 @@ const createCustomPersister = (
|
|
|
283
297
|
while (
|
|
284
298
|
!isUndefined((action = arrayShift(mapGet(scheduleActions, scheduleId))))
|
|
285
299
|
) {
|
|
286
|
-
|
|
287
|
-
await action();
|
|
288
|
-
} catch (error) {
|
|
289
|
-
/* istanbul ignore next */
|
|
290
|
-
onIgnoredError?.(error);
|
|
291
|
-
}
|
|
300
|
+
await tryCatch(action, onIgnoredError);
|
|
292
301
|
}
|
|
293
302
|
mapSet(scheduleRunning, scheduleId, 0);
|
|
294
303
|
}
|
|
@@ -308,21 +317,23 @@ const createCustomPersister = (
|
|
|
308
317
|
setStatus(1 /* Loading */);
|
|
309
318
|
loads++;
|
|
310
319
|
await schedule(async () => {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
320
|
+
await tryCatch(
|
|
321
|
+
async () => {
|
|
322
|
+
const content = await getPersisted();
|
|
323
|
+
if (isArray(content)) {
|
|
324
|
+
setContentOrChanges(content);
|
|
325
|
+
} else if (initialContent) {
|
|
326
|
+
setDefaultContent(initialContent);
|
|
327
|
+
} else {
|
|
328
|
+
errorNew(`Content is not an array: ${content}`);
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
() => {
|
|
332
|
+
if (initialContent) {
|
|
333
|
+
setDefaultContent(initialContent);
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
);
|
|
326
337
|
setStatus(0 /* Idle */);
|
|
327
338
|
});
|
|
328
339
|
}
|
|
@@ -331,29 +342,33 @@ const createCustomPersister = (
|
|
|
331
342
|
const startAutoLoad = async (initialContent) => {
|
|
332
343
|
stopAutoLoad();
|
|
333
344
|
await load(initialContent);
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
345
|
+
await tryCatch(
|
|
346
|
+
async () =>
|
|
347
|
+
(autoLoadHandle = await addPersisterListener(
|
|
348
|
+
async (content, changes) => {
|
|
349
|
+
if (changes || content) {
|
|
350
|
+
/* istanbul ignore else */
|
|
351
|
+
if (status != 2 /* Saving */) {
|
|
352
|
+
setStatus(1 /* Loading */);
|
|
353
|
+
loads++;
|
|
354
|
+
setContentOrChanges(changes ?? content);
|
|
355
|
+
setStatus(0 /* Idle */);
|
|
356
|
+
}
|
|
357
|
+
} else {
|
|
358
|
+
await load();
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
)),
|
|
362
|
+
onIgnoredError,
|
|
363
|
+
);
|
|
352
364
|
return persister;
|
|
353
365
|
};
|
|
354
|
-
const stopAutoLoad = () => {
|
|
366
|
+
const stopAutoLoad = async () => {
|
|
355
367
|
if (autoLoadHandle) {
|
|
356
|
-
|
|
368
|
+
await tryCatch(
|
|
369
|
+
() => delPersisterListener(autoLoadHandle),
|
|
370
|
+
onIgnoredError,
|
|
371
|
+
);
|
|
357
372
|
autoLoadHandle = void 0;
|
|
358
373
|
}
|
|
359
374
|
return persister;
|
|
@@ -365,12 +380,7 @@ const createCustomPersister = (
|
|
|
365
380
|
setStatus(2 /* Saving */);
|
|
366
381
|
saves++;
|
|
367
382
|
await schedule(async () => {
|
|
368
|
-
|
|
369
|
-
await setPersisted(getContent, changes);
|
|
370
|
-
} catch (error) {
|
|
371
|
-
/* istanbul ignore next */
|
|
372
|
-
onIgnoredError?.(error);
|
|
373
|
-
}
|
|
383
|
+
await tryCatch(() => setPersisted(getContent, changes), onIgnoredError);
|
|
374
384
|
setStatus(0 /* Idle */);
|
|
375
385
|
});
|
|
376
386
|
}
|
|
@@ -387,7 +397,7 @@ const createCustomPersister = (
|
|
|
387
397
|
});
|
|
388
398
|
return persister;
|
|
389
399
|
};
|
|
390
|
-
const stopAutoSave = () => {
|
|
400
|
+
const stopAutoSave = async () => {
|
|
391
401
|
if (autoSaveListenerId) {
|
|
392
402
|
store.delListener(autoSaveListenerId);
|
|
393
403
|
autoSaveListenerId = void 0;
|
|
@@ -408,9 +418,10 @@ const createCustomPersister = (
|
|
|
408
418
|
return persister;
|
|
409
419
|
};
|
|
410
420
|
const getStore = () => store;
|
|
411
|
-
const destroy = () => {
|
|
421
|
+
const destroy = async () => {
|
|
412
422
|
arrayClear(mapGet(scheduleActions, scheduleId));
|
|
413
|
-
|
|
423
|
+
await persister.stopAutoLoad();
|
|
424
|
+
return await persister.stopAutoSave();
|
|
414
425
|
};
|
|
415
426
|
const getStats = () => ({loads, saves});
|
|
416
427
|
const persister = {
|
|
@@ -434,6 +445,17 @@ const createCustomPersister = (
|
|
|
434
445
|
return objFreeze(persister);
|
|
435
446
|
};
|
|
436
447
|
|
|
448
|
+
const textEncoder = /* @__PURE__ */ new GLOBAL.TextEncoder();
|
|
449
|
+
const getHash = (value) => {
|
|
450
|
+
let hash = 2166136261;
|
|
451
|
+
arrayForEach(textEncoder.encode(value), (char) => {
|
|
452
|
+
hash ^= char;
|
|
453
|
+
hash +=
|
|
454
|
+
(hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
455
|
+
});
|
|
456
|
+
return hash >>> 0;
|
|
457
|
+
};
|
|
458
|
+
|
|
437
459
|
const jsonString = JSON.stringify;
|
|
438
460
|
const jsonParse = JSON.parse;
|
|
439
461
|
const jsonStringWithUndefined = (obj) =>
|
|
@@ -446,14 +468,22 @@ const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
|
|
|
446
468
|
const SELECT = 'SELECT';
|
|
447
469
|
const WHERE = 'WHERE';
|
|
448
470
|
const TABLE = 'TABLE';
|
|
471
|
+
const INSERT = 'INSERT';
|
|
472
|
+
const DELETE = 'DELETE';
|
|
473
|
+
const UPDATE = 'UPDATE';
|
|
449
474
|
const ALTER_TABLE = 'ALTER ' + TABLE;
|
|
450
|
-
const
|
|
451
|
-
const
|
|
475
|
+
const FROM = 'FROM';
|
|
476
|
+
const DELETE_FROM = DELETE + ' ' + FROM;
|
|
477
|
+
const SELECT_STAR_FROM = SELECT + '*' + FROM;
|
|
452
478
|
const PRAGMA = 'pragma_';
|
|
453
479
|
const DATA_VERSION = 'data_version';
|
|
454
480
|
const SCHEMA_VERSION = 'schema_version';
|
|
455
|
-
const FROM = 'FROM ';
|
|
456
481
|
const PRAGMA_TABLE = 'pragma_table_';
|
|
482
|
+
const CREATE = 'CREATE ';
|
|
483
|
+
const CREATE_TABLE = CREATE + TABLE;
|
|
484
|
+
const OR_REPLACE = 'OR REPLACE ';
|
|
485
|
+
const FUNCTION = 'FUNCTION';
|
|
486
|
+
const TABLE_NAME_PLACEHOLDER = '$tableName';
|
|
457
487
|
const getWrappedCommand = (executeCommand, onSqlCommand) =>
|
|
458
488
|
onSqlCommand
|
|
459
489
|
? async (sql, params) => {
|
|
@@ -461,7 +491,8 @@ const getWrappedCommand = (executeCommand, onSqlCommand) =>
|
|
|
461
491
|
return await executeCommand(sql, params);
|
|
462
492
|
}
|
|
463
493
|
: executeCommand;
|
|
464
|
-
const escapeId = (str) => `"${str
|
|
494
|
+
const escapeId = (str) => `"${strReplace(str, /"/g, '""')}"`;
|
|
495
|
+
const escapeIds = (...ids) => escapeId(arrayJoin(ids, '_'));
|
|
465
496
|
const escapeColumnNames = (...columnNames) =>
|
|
466
497
|
arrayJoin(arrayMap(columnNames, escapeId), COMMA);
|
|
467
498
|
const getPlaceholders = (array, offset = [1]) =>
|
|
@@ -469,6 +500,9 @@ const getPlaceholders = (array, offset = [1]) =>
|
|
|
469
500
|
arrayMap(array, () => '$' + offset[0]++),
|
|
470
501
|
COMMA,
|
|
471
502
|
);
|
|
503
|
+
const getWhereCondition = (tableName, condition = TRUE) =>
|
|
504
|
+
WHERE +
|
|
505
|
+
`(${strReplace(condition, TABLE_NAME_PLACEHOLDER, escapeId(tableName))})`;
|
|
472
506
|
|
|
473
507
|
const COLUMN_NAME = 'ColumnName';
|
|
474
508
|
const STORE = 'store';
|
|
@@ -482,6 +516,7 @@ const TABLE_ID = 'tableId';
|
|
|
482
516
|
const TABLE_NAME = 'tableName';
|
|
483
517
|
const DELETE_EMPTY_COLUMNS = 'deleteEmptyColumns';
|
|
484
518
|
const DELETE_EMPTY_TABLE = 'deleteEmptyTable';
|
|
519
|
+
const CONDITION = 'condition';
|
|
485
520
|
const DEFAULT_CONFIG = {
|
|
486
521
|
mode: JSON$1,
|
|
487
522
|
[AUTO_LOAD_INTERVAL_SECONDS]: 1,
|
|
@@ -549,29 +584,42 @@ const getConfigStructures = (configOrStoreTableName) => {
|
|
|
549
584
|
const valuesTable = valuesConfig[2];
|
|
550
585
|
const managedTableNames = setNew(valuesTable);
|
|
551
586
|
const excludedTableNames = setNew(valuesTable);
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
587
|
+
const tablesLoadConfig = getDefaultedTabularConfigMap(
|
|
588
|
+
load,
|
|
589
|
+
{
|
|
590
|
+
[TABLE_ID]: null,
|
|
591
|
+
[ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
|
|
592
|
+
[CONDITION]: TRUE,
|
|
593
|
+
},
|
|
594
|
+
TABLE_ID,
|
|
595
|
+
(tableName) => collHas(excludedTableNames, tableName),
|
|
596
|
+
(tableName) => setAdd(managedTableNames, tableName),
|
|
597
|
+
);
|
|
598
|
+
const tablesSaveConfig = getDefaultedTabularConfigMap(
|
|
599
|
+
save,
|
|
600
|
+
{
|
|
601
|
+
[TABLE_NAME]: null,
|
|
602
|
+
[ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
|
|
603
|
+
[DELETE_EMPTY_COLUMNS]: 0,
|
|
604
|
+
[DELETE_EMPTY_TABLE]: 0,
|
|
605
|
+
[CONDITION]: null,
|
|
606
|
+
},
|
|
607
|
+
TABLE_NAME,
|
|
608
|
+
(_, tableName) => collHas(excludedTableNames, tableName),
|
|
609
|
+
(_, tableName) => setAdd(managedTableNames, tableName),
|
|
610
|
+
);
|
|
611
|
+
mapForEach(
|
|
612
|
+
tablesSaveConfig,
|
|
613
|
+
(_, tableSaveConfig) =>
|
|
614
|
+
(tableSaveConfig[4] ??=
|
|
615
|
+
mapGet(tablesLoadConfig, tableSaveConfig[0])?.[2] ?? TRUE),
|
|
616
|
+
);
|
|
617
|
+
return [
|
|
618
|
+
0,
|
|
619
|
+
autoLoadIntervalSeconds,
|
|
620
|
+
[tablesLoadConfig, tablesSaveConfig, valuesConfig],
|
|
621
|
+
managedTableNames,
|
|
573
622
|
];
|
|
574
|
-
return [0, autoLoadIntervalSeconds, tabularConfig, managedTableNames];
|
|
575
623
|
};
|
|
576
624
|
|
|
577
625
|
const getCommandFunctions = (
|
|
@@ -594,13 +642,15 @@ const getCommandFunctions = (
|
|
|
594
642
|
({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
|
|
595
643
|
);
|
|
596
644
|
};
|
|
597
|
-
const loadTable = async (tableName, rowIdColumnName) =>
|
|
645
|
+
const loadTable = async (tableName, rowIdColumnName, condition) =>
|
|
598
646
|
canSelect(tableName, rowIdColumnName)
|
|
599
647
|
? objNew(
|
|
600
648
|
arrayFilter(
|
|
601
649
|
arrayMap(
|
|
602
650
|
await databaseExecuteCommand(
|
|
603
|
-
SELECT_STAR_FROM +
|
|
651
|
+
SELECT_STAR_FROM +
|
|
652
|
+
escapeId(tableName) +
|
|
653
|
+
getWhereCondition(tableName, condition),
|
|
604
654
|
),
|
|
605
655
|
(row) => [
|
|
606
656
|
row[rowIdColumnName],
|
|
@@ -620,6 +670,7 @@ const getCommandFunctions = (
|
|
|
620
670
|
deleteEmptyColumns,
|
|
621
671
|
deleteEmptyTable,
|
|
622
672
|
partial = false,
|
|
673
|
+
condition = TRUE,
|
|
623
674
|
) => {
|
|
624
675
|
const settingColumnNameSet = setNew();
|
|
625
676
|
objMap(content ?? {}, (contentRow) =>
|
|
@@ -631,6 +682,7 @@ const getCommandFunctions = (
|
|
|
631
682
|
if (
|
|
632
683
|
!partial &&
|
|
633
684
|
deleteEmptyTable &&
|
|
685
|
+
condition == TRUE &&
|
|
634
686
|
arrayIsEmpty(settingColumnNames) &&
|
|
635
687
|
collHas(schemaMap, tableName)
|
|
636
688
|
) {
|
|
@@ -643,8 +695,7 @@ const getCommandFunctions = (
|
|
|
643
695
|
if (!arrayIsEmpty(settingColumnNames)) {
|
|
644
696
|
if (!collHas(schemaMap, tableName)) {
|
|
645
697
|
await databaseExecuteCommand(
|
|
646
|
-
|
|
647
|
-
TABLE +
|
|
698
|
+
CREATE_TABLE +
|
|
648
699
|
escapeId(tableName) +
|
|
649
700
|
`(${escapeId(rowIdColumnName)}${columnType} PRIMARY KEY${arrayJoin(
|
|
650
701
|
arrayMap(
|
|
@@ -707,7 +758,9 @@ const getCommandFunctions = (
|
|
|
707
758
|
if (partial) {
|
|
708
759
|
if (isUndefined(content)) {
|
|
709
760
|
await databaseExecuteCommand(
|
|
710
|
-
DELETE_FROM +
|
|
761
|
+
DELETE_FROM +
|
|
762
|
+
escapeId(tableName) +
|
|
763
|
+
getWhereCondition(tableName, condition),
|
|
711
764
|
);
|
|
712
765
|
} else {
|
|
713
766
|
await promiseAll(
|
|
@@ -716,9 +769,8 @@ const getCommandFunctions = (
|
|
|
716
769
|
await databaseExecuteCommand(
|
|
717
770
|
DELETE_FROM +
|
|
718
771
|
escapeId(tableName) +
|
|
719
|
-
|
|
720
|
-
escapeId(rowIdColumnName)
|
|
721
|
-
'=$1',
|
|
772
|
+
getWhereCondition(tableName, condition) +
|
|
773
|
+
`AND(${escapeId(rowIdColumnName)}=$1)`,
|
|
722
774
|
[rowId],
|
|
723
775
|
);
|
|
724
776
|
} else if (!arrayIsEmpty(settingColumnNames)) {
|
|
@@ -762,14 +814,15 @@ const getCommandFunctions = (
|
|
|
762
814
|
await databaseExecuteCommand(
|
|
763
815
|
DELETE_FROM +
|
|
764
816
|
escapeId(tableName) +
|
|
765
|
-
|
|
766
|
-
escapeId(rowIdColumnName)
|
|
767
|
-
`NOT IN(${getPlaceholders(deleteRowIds)})`,
|
|
817
|
+
getWhereCondition(tableName, condition) + // eslint-disable-next-line max-len
|
|
818
|
+
`AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
|
|
768
819
|
deleteRowIds,
|
|
769
820
|
);
|
|
770
821
|
} else if (collHas(schemaMap, tableName)) {
|
|
771
822
|
await databaseExecuteCommand(
|
|
772
|
-
DELETE_FROM +
|
|
823
|
+
DELETE_FROM +
|
|
824
|
+
escapeId(tableName) +
|
|
825
|
+
getWhereCondition(tableName, condition),
|
|
773
826
|
);
|
|
774
827
|
}
|
|
775
828
|
}
|
|
@@ -777,11 +830,7 @@ const getCommandFunctions = (
|
|
|
777
830
|
const transaction = async (actions) => {
|
|
778
831
|
let result;
|
|
779
832
|
await databaseExecuteCommand('BEGIN');
|
|
780
|
-
|
|
781
|
-
result = await actions();
|
|
782
|
-
} catch (error) {
|
|
783
|
-
onIgnoredError?.(error);
|
|
784
|
-
}
|
|
833
|
+
await tryCatch(async () => (result = await actions()), onIgnoredError);
|
|
785
834
|
await databaseExecuteCommand('END');
|
|
786
835
|
return result;
|
|
787
836
|
};
|
|
@@ -796,7 +845,8 @@ const defaultUpsert = async (
|
|
|
796
845
|
) => {
|
|
797
846
|
const offset = [1];
|
|
798
847
|
await executeCommand(
|
|
799
|
-
|
|
848
|
+
INSERT +
|
|
849
|
+
' INTO' +
|
|
800
850
|
escapeId(tableName) +
|
|
801
851
|
'(' +
|
|
802
852
|
escapeColumnNames(rowIdColumnName, ...changingColumnNames) +
|
|
@@ -811,7 +861,7 @@ const defaultUpsert = async (
|
|
|
811
861
|
) +
|
|
812
862
|
'ON CONFLICT(' +
|
|
813
863
|
escapeId(rowIdColumnName) +
|
|
814
|
-
|
|
864
|
+
`)DO ${UPDATE} SET` +
|
|
815
865
|
arrayJoin(
|
|
816
866
|
arrayMap(
|
|
817
867
|
changingColumnNames,
|
|
@@ -833,7 +883,7 @@ const createJsonPersister = (
|
|
|
833
883
|
addPersisterListener,
|
|
834
884
|
delPersisterListener,
|
|
835
885
|
onIgnoredError,
|
|
836
|
-
|
|
886
|
+
extraDestroy,
|
|
837
887
|
persist,
|
|
838
888
|
[storeTableName, storeIdColumnName, storeColumnName],
|
|
839
889
|
managedTableNames,
|
|
@@ -852,8 +902,8 @@ const createJsonPersister = (
|
|
|
852
902
|
columnType,
|
|
853
903
|
upsert,
|
|
854
904
|
);
|
|
855
|
-
const getPersisted =
|
|
856
|
-
|
|
905
|
+
const getPersisted = () =>
|
|
906
|
+
transaction(async () => {
|
|
857
907
|
await refreshSchema();
|
|
858
908
|
return jsonParseWithUndefined(
|
|
859
909
|
(await loadTable(storeTableName, storeIdColumnName))[SINGLE_ROW_ID]?.[
|
|
@@ -861,8 +911,8 @@ const createJsonPersister = (
|
|
|
861
911
|
] ?? 'null',
|
|
862
912
|
);
|
|
863
913
|
});
|
|
864
|
-
const setPersisted =
|
|
865
|
-
|
|
914
|
+
const setPersisted = (getContent) =>
|
|
915
|
+
transaction(async () => {
|
|
866
916
|
await refreshSchema();
|
|
867
917
|
await saveTable(
|
|
868
918
|
storeTableName,
|
|
@@ -876,9 +926,10 @@ const createJsonPersister = (
|
|
|
876
926
|
true,
|
|
877
927
|
);
|
|
878
928
|
});
|
|
879
|
-
const destroy = () => {
|
|
880
|
-
persister.stopAutoLoad()
|
|
881
|
-
|
|
929
|
+
const destroy = async () => {
|
|
930
|
+
await persister.stopAutoLoad();
|
|
931
|
+
await persister.stopAutoSave();
|
|
932
|
+
extraDestroy();
|
|
882
933
|
return persister;
|
|
883
934
|
};
|
|
884
935
|
const persister = createCustomPersister(
|
|
@@ -902,7 +953,7 @@ const createTabularPersister = (
|
|
|
902
953
|
addPersisterListener,
|
|
903
954
|
delPersisterListener,
|
|
904
955
|
onIgnoredError,
|
|
905
|
-
|
|
956
|
+
extraDestroy,
|
|
906
957
|
persist,
|
|
907
958
|
[
|
|
908
959
|
tablesLoadConfig,
|
|
@@ -929,12 +980,18 @@ const createTabularPersister = (
|
|
|
929
980
|
encode,
|
|
930
981
|
decode,
|
|
931
982
|
);
|
|
932
|
-
const saveTables =
|
|
933
|
-
|
|
983
|
+
const saveTables = (tables, partial) =>
|
|
984
|
+
promiseAll(
|
|
934
985
|
mapMap(
|
|
935
986
|
tablesSaveConfig,
|
|
936
987
|
async (
|
|
937
|
-
[
|
|
988
|
+
[
|
|
989
|
+
tableName,
|
|
990
|
+
rowIdColumnName,
|
|
991
|
+
deleteEmptyColumns,
|
|
992
|
+
deleteEmptyTable,
|
|
993
|
+
condition,
|
|
994
|
+
],
|
|
938
995
|
tableId,
|
|
939
996
|
) => {
|
|
940
997
|
if (!partial || objHas(tables, tableId)) {
|
|
@@ -945,6 +1002,7 @@ const createTabularPersister = (
|
|
|
945
1002
|
deleteEmptyColumns,
|
|
946
1003
|
deleteEmptyTable,
|
|
947
1004
|
partial,
|
|
1005
|
+
condition,
|
|
948
1006
|
);
|
|
949
1007
|
}
|
|
950
1008
|
},
|
|
@@ -967,9 +1025,9 @@ const createTabularPersister = (
|
|
|
967
1025
|
await promiseAll(
|
|
968
1026
|
mapMap(
|
|
969
1027
|
tablesLoadConfig,
|
|
970
|
-
async ([tableId, rowIdColumnName], tableName) => [
|
|
1028
|
+
async ([tableId, rowIdColumnName, condition], tableName) => [
|
|
971
1029
|
tableId,
|
|
972
|
-
await loadTable(tableName, rowIdColumnName),
|
|
1030
|
+
await loadTable(tableName, rowIdColumnName, condition),
|
|
973
1031
|
],
|
|
974
1032
|
),
|
|
975
1033
|
),
|
|
@@ -982,8 +1040,8 @@ const createTabularPersister = (
|
|
|
982
1040
|
SINGLE_ROW_ID
|
|
983
1041
|
]
|
|
984
1042
|
: {};
|
|
985
|
-
const getPersisted =
|
|
986
|
-
|
|
1043
|
+
const getPersisted = () =>
|
|
1044
|
+
transaction(async () => {
|
|
987
1045
|
await refreshSchema();
|
|
988
1046
|
const tables = await loadTables();
|
|
989
1047
|
const values = await loadValues();
|
|
@@ -991,8 +1049,8 @@ const createTabularPersister = (
|
|
|
991
1049
|
? [tables, values]
|
|
992
1050
|
: void 0;
|
|
993
1051
|
});
|
|
994
|
-
const setPersisted =
|
|
995
|
-
|
|
1052
|
+
const setPersisted = (getContent, changes) =>
|
|
1053
|
+
transaction(async () => {
|
|
996
1054
|
await refreshSchema();
|
|
997
1055
|
if (!isUndefined(changes)) {
|
|
998
1056
|
await saveTables(changes[0], true);
|
|
@@ -1003,9 +1061,10 @@ const createTabularPersister = (
|
|
|
1003
1061
|
await saveValues(values);
|
|
1004
1062
|
}
|
|
1005
1063
|
});
|
|
1006
|
-
const destroy = () => {
|
|
1007
|
-
persister.stopAutoLoad()
|
|
1008
|
-
|
|
1064
|
+
const destroy = async () => {
|
|
1065
|
+
await persister.stopAutoLoad();
|
|
1066
|
+
await persister.stopAutoSave();
|
|
1067
|
+
extraDestroy();
|
|
1009
1068
|
return persister;
|
|
1010
1069
|
};
|
|
1011
1070
|
const persister = createCustomPersister(
|
|
@@ -1023,10 +1082,9 @@ const createTabularPersister = (
|
|
|
1023
1082
|
return persister;
|
|
1024
1083
|
};
|
|
1025
1084
|
|
|
1026
|
-
const
|
|
1085
|
+
const TABLE_CREATED = 'c';
|
|
1086
|
+
const DATA_CHANGED = 'd';
|
|
1027
1087
|
const EVENT_REGEX = /^([cd]:)(.+)/;
|
|
1028
|
-
const CHANGE_DATA_TRIGGER = TINYBASE + '_data';
|
|
1029
|
-
const CREATE_TABLE_TRIGGER = TINYBASE + '_table';
|
|
1030
1088
|
const createCustomPostgreSqlPersister = (
|
|
1031
1089
|
store,
|
|
1032
1090
|
configOrStoreTableName,
|
|
@@ -1044,53 +1102,125 @@ const createCustomPostgreSqlPersister = (
|
|
|
1044
1102
|
const [isJson, , defaultedConfig, managedTableNamesSet] = getConfigStructures(
|
|
1045
1103
|
configOrStoreTableName,
|
|
1046
1104
|
);
|
|
1047
|
-
const
|
|
1105
|
+
const configHash =
|
|
1106
|
+
EMPTY_STRING + getHash(jsonStringWithUndefined(defaultedConfig));
|
|
1107
|
+
const channel = TINYBASE + '_' + configHash;
|
|
1108
|
+
const createFunction = async (
|
|
1109
|
+
name,
|
|
1110
|
+
body,
|
|
1111
|
+
returnPrefix = '',
|
|
1112
|
+
declarations = '',
|
|
1113
|
+
) => {
|
|
1114
|
+
const escapedFunctionName = escapeIds(TINYBASE, name, configHash);
|
|
1048
1115
|
await executeCommand(
|
|
1049
|
-
|
|
1050
|
-
|
|
1116
|
+
CREATE +
|
|
1117
|
+
OR_REPLACE +
|
|
1118
|
+
FUNCTION +
|
|
1119
|
+
escapedFunctionName +
|
|
1120
|
+
`()RETURNS ${returnPrefix}trigger AS $$ ${declarations}BEGIN ${body}END;$$ LANGUAGE plpgsql;`,
|
|
1051
1121
|
);
|
|
1122
|
+
return escapedFunctionName;
|
|
1052
1123
|
};
|
|
1053
|
-
const
|
|
1124
|
+
const createTrigger = async (
|
|
1125
|
+
prefix,
|
|
1126
|
+
escapedTriggerName,
|
|
1127
|
+
body,
|
|
1128
|
+
escapedFunctionName,
|
|
1129
|
+
) => {
|
|
1054
1130
|
await executeCommand(
|
|
1055
|
-
|
|
1056
|
-
|
|
1131
|
+
CREATE +
|
|
1132
|
+
prefix +
|
|
1133
|
+
'TRIGGER' +
|
|
1134
|
+
escapedTriggerName +
|
|
1135
|
+
body +
|
|
1136
|
+
'EXECUTE ' +
|
|
1137
|
+
FUNCTION +
|
|
1138
|
+
escapedFunctionName +
|
|
1139
|
+
`()`,
|
|
1057
1140
|
);
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1141
|
+
return escapedTriggerName;
|
|
1142
|
+
};
|
|
1143
|
+
const notify = (message) => `PERFORM pg_notify('${channel}',${message});`;
|
|
1144
|
+
const when = (tableName, newOrOldOrBoth) =>
|
|
1145
|
+
isJson
|
|
1146
|
+
? TRUE
|
|
1147
|
+
: newOrOldOrBoth === 2
|
|
1148
|
+
? when(tableName, 0) + ' OR ' + when(tableName, 1)
|
|
1149
|
+
: strReplace(
|
|
1150
|
+
mapGet(defaultedConfig[0], tableName)?.[2] ?? TRUE,
|
|
1151
|
+
TABLE_NAME_PLACEHOLDER,
|
|
1152
|
+
newOrOldOrBoth == 0 ? 'NEW' : 'OLD',
|
|
1153
|
+
);
|
|
1154
|
+
const addDataChangedTriggers = (tableName, dataChangedFunction) =>
|
|
1155
|
+
promiseAll(
|
|
1156
|
+
arrayMap([INSERT, DELETE, UPDATE], (action, newOrOldOrBoth) =>
|
|
1157
|
+
createTrigger(
|
|
1158
|
+
OR_REPLACE,
|
|
1159
|
+
escapeIds(TINYBASE, DATA_CHANGED, configHash, tableName, action),
|
|
1160
|
+
`AFTER ${action} ON${escapeId(tableName)}FOR EACH ROW WHEN(${when(
|
|
1161
|
+
tableName,
|
|
1162
|
+
newOrOldOrBoth,
|
|
1163
|
+
)})`,
|
|
1164
|
+
dataChangedFunction,
|
|
1165
|
+
),
|
|
1166
|
+
),
|
|
1167
|
+
);
|
|
1168
|
+
const addPersisterListener = async (listener) => {
|
|
1169
|
+
const tableCreatedFunctionName = await createFunction(
|
|
1170
|
+
TABLE_CREATED,
|
|
1065
1171
|
// eslint-disable-next-line max-len
|
|
1066
|
-
`
|
|
1172
|
+
`FOR row IN SELECT object_identity FROM pg_event_trigger_ddl_commands()${WHERE} command_tag='${CREATE_TABLE}' LOOP ${notify(`'c:'||SPLIT_PART(row.object_identity,'.',2)`)}END LOOP;`,
|
|
1173
|
+
'event_',
|
|
1174
|
+
'DECLARE row record;',
|
|
1175
|
+
);
|
|
1176
|
+
await createTrigger(
|
|
1177
|
+
'EVENT ',
|
|
1178
|
+
escapeIds(TINYBASE, TABLE_CREATED, configHash),
|
|
1179
|
+
`ON ddl_command_end WHEN TAG IN('${CREATE_TABLE}')`,
|
|
1180
|
+
tableCreatedFunctionName,
|
|
1181
|
+
);
|
|
1182
|
+
const dataChangedFunctionName = await createFunction(
|
|
1183
|
+
DATA_CHANGED,
|
|
1184
|
+
notify(`'d:'||TG_TABLE_NAME`) + `RETURN NULL;`,
|
|
1067
1185
|
);
|
|
1068
1186
|
await promiseAll(
|
|
1069
1187
|
arrayMap(collValues(managedTableNamesSet), async (tableName) => {
|
|
1070
1188
|
await executeCommand(
|
|
1071
|
-
|
|
1072
|
-
|
|
1189
|
+
CREATE_TABLE +
|
|
1190
|
+
` IF NOT EXISTS${escapeId(tableName)}("_id"text PRIMARY KEY)`,
|
|
1073
1191
|
);
|
|
1074
|
-
await
|
|
1192
|
+
return await addDataChangedTriggers(tableName, dataChangedFunctionName);
|
|
1075
1193
|
}),
|
|
1076
1194
|
);
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1195
|
+
const listenerHandle = await addChangeListener(
|
|
1196
|
+
channel,
|
|
1197
|
+
(prefixAndTableName) =>
|
|
1198
|
+
ifNotUndefined(
|
|
1081
1199
|
strMatch(prefixAndTableName, EVENT_REGEX),
|
|
1082
1200
|
async ([, eventType, tableName]) => {
|
|
1083
1201
|
if (collHas(managedTableNamesSet, tableName)) {
|
|
1084
1202
|
if (eventType == 'c:') {
|
|
1085
|
-
await
|
|
1203
|
+
await addDataChangedTriggers(
|
|
1204
|
+
tableName,
|
|
1205
|
+
dataChangedFunctionName,
|
|
1206
|
+
);
|
|
1086
1207
|
}
|
|
1087
1208
|
listener();
|
|
1088
1209
|
}
|
|
1089
1210
|
},
|
|
1090
1211
|
),
|
|
1091
1212
|
);
|
|
1213
|
+
return [
|
|
1214
|
+
listenerHandle,
|
|
1215
|
+
[tableCreatedFunctionName, dataChangedFunctionName],
|
|
1216
|
+
];
|
|
1217
|
+
};
|
|
1218
|
+
const delPersisterListener = async ([listenerHandle, functionNames]) => {
|
|
1219
|
+
delChangeListener(listenerHandle);
|
|
1220
|
+
await executeCommand(
|
|
1221
|
+
`DROP FUNCTION IF EXISTS${arrayJoin(functionNames, ',')}CASCADE`,
|
|
1222
|
+
);
|
|
1092
1223
|
};
|
|
1093
|
-
const delPersisterListener = delChangeListener;
|
|
1094
1224
|
return (isJson ? createJsonPersister : createTabularPersister)(
|
|
1095
1225
|
store,
|
|
1096
1226
|
executeCommand,
|
|
@@ -1103,8 +1233,8 @@ const createCustomPostgreSqlPersister = (
|
|
|
1103
1233
|
collValues(managedTableNamesSet),
|
|
1104
1234
|
async (executeCommand2, managedTableNames) =>
|
|
1105
1235
|
await executeCommand2(
|
|
1106
|
-
// eslint-disable-next-line max-len
|
|
1107
|
-
|
|
1236
|
+
SELECT + // eslint-disable-next-line max-len
|
|
1237
|
+
` table_name tn,column_name cn FROM information_schema.columns ${WHERE} table_schema='public'AND table_name IN(${getPlaceholders(managedTableNames)})`,
|
|
1108
1238
|
managedTableNames,
|
|
1109
1239
|
),
|
|
1110
1240
|
thing,
|
|
@@ -1143,22 +1273,24 @@ const createCustomSqlitePersister = (
|
|
|
1143
1273
|
const addPersisterListener = (listener) => {
|
|
1144
1274
|
let interval;
|
|
1145
1275
|
const startPolling = () =>
|
|
1146
|
-
(interval = startInterval(
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
if (dataVersion !=
|
|
1154
|
-
|
|
1276
|
+
(interval = startInterval(
|
|
1277
|
+
() =>
|
|
1278
|
+
tryCatch(async () => {
|
|
1279
|
+
const [{d, s, c}] = await executeCommand(
|
|
1280
|
+
SELECT + // eslint-disable-next-line max-len
|
|
1281
|
+
` ${DATA_VERSION} d,${SCHEMA_VERSION} s,TOTAL_CHANGES() c FROM ${PRAGMA}${DATA_VERSION} JOIN ${PRAGMA}${SCHEMA_VERSION}`,
|
|
1282
|
+
);
|
|
1283
|
+
if (d != dataVersion || s != schemaVersion || c != totalChanges) {
|
|
1284
|
+
if (dataVersion != null) {
|
|
1285
|
+
listener();
|
|
1286
|
+
}
|
|
1287
|
+
dataVersion = d;
|
|
1288
|
+
schemaVersion = s;
|
|
1289
|
+
totalChanges = c;
|
|
1155
1290
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
}
|
|
1160
|
-
} catch {}
|
|
1161
|
-
}, autoLoadIntervalSeconds));
|
|
1291
|
+
}),
|
|
1292
|
+
autoLoadIntervalSeconds,
|
|
1293
|
+
));
|
|
1162
1294
|
const stopPolling = () => {
|
|
1163
1295
|
dataVersion = schemaVersion = totalChanges = null;
|
|
1164
1296
|
stopInterval(interval);
|
|
@@ -1190,8 +1322,8 @@ const createCustomSqlitePersister = (
|
|
|
1190
1322
|
collValues(managedTableNamesSet),
|
|
1191
1323
|
async (executeCommand2, managedTableNames) =>
|
|
1192
1324
|
await executeCommand2(
|
|
1193
|
-
// eslint-disable-next-line max-len
|
|
1194
|
-
|
|
1325
|
+
SELECT + // eslint-disable-next-line max-len
|
|
1326
|
+
` t.name tn,c.name cn FROM ${PRAGMA_TABLE}list()t,${PRAGMA_TABLE}info(t.name)c ${WHERE} t.schema='main'AND t.type IN('table','view')AND t.name IN(${getPlaceholders(managedTableNames)})ORDER BY t.name,c.name`,
|
|
1195
1327
|
managedTableNames,
|
|
1196
1328
|
),
|
|
1197
1329
|
thing,
|