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.
Files changed (233) hide show
  1. package/@types/persisters/index.d.ts +82 -40
  2. package/@types/persisters/persister-automerge/index.d.ts +4 -4
  3. package/@types/persisters/persister-automerge/with-schemas/index.d.ts +4 -4
  4. package/@types/persisters/persister-browser/index.d.ts +4 -4
  5. package/@types/persisters/persister-browser/with-schemas/index.d.ts +4 -4
  6. package/@types/persisters/persister-cr-sqlite-wasm/index.d.ts +3 -3
  7. package/@types/persisters/persister-cr-sqlite-wasm/with-schemas/index.d.ts +3 -3
  8. package/@types/persisters/persister-electric-sql/index.d.ts +3 -3
  9. package/@types/persisters/persister-electric-sql/with-schemas/index.d.ts +3 -3
  10. package/@types/persisters/persister-expo-sqlite/index.d.ts +3 -3
  11. package/@types/persisters/persister-expo-sqlite/with-schemas/index.d.ts +3 -3
  12. package/@types/persisters/persister-file/index.d.ts +2 -2
  13. package/@types/persisters/persister-file/with-schemas/index.d.ts +2 -2
  14. package/@types/persisters/persister-indexed-db/index.d.ts +2 -2
  15. package/@types/persisters/persister-indexed-db/with-schemas/index.d.ts +2 -2
  16. package/@types/persisters/persister-libsql/index.d.ts +3 -3
  17. package/@types/persisters/persister-libsql/with-schemas/index.d.ts +3 -3
  18. package/@types/persisters/persister-partykit-client/index.d.ts +2 -2
  19. package/@types/persisters/persister-partykit-client/with-schemas/index.d.ts +2 -2
  20. package/@types/persisters/persister-pglite/index.d.ts +3 -3
  21. package/@types/persisters/persister-pglite/with-schemas/index.d.ts +3 -3
  22. package/@types/persisters/persister-postgres/index.d.ts +3 -3
  23. package/@types/persisters/persister-postgres/with-schemas/index.d.ts +3 -3
  24. package/@types/persisters/persister-powersync/index.d.ts +3 -3
  25. package/@types/persisters/persister-powersync/with-schemas/index.d.ts +3 -3
  26. package/@types/persisters/persister-remote/index.d.ts +2 -2
  27. package/@types/persisters/persister-remote/with-schemas/index.d.ts +2 -2
  28. package/@types/persisters/persister-sqlite-bun/index.d.ts +3 -3
  29. package/@types/persisters/persister-sqlite-bun/with-schemas/index.d.ts +3 -3
  30. package/@types/persisters/persister-sqlite-wasm/index.d.ts +3 -3
  31. package/@types/persisters/persister-sqlite-wasm/with-schemas/index.d.ts +3 -3
  32. package/@types/persisters/persister-sqlite3/index.d.ts +3 -3
  33. package/@types/persisters/persister-sqlite3/with-schemas/index.d.ts +3 -3
  34. package/@types/persisters/persister-yjs/index.d.ts +4 -4
  35. package/@types/persisters/persister-yjs/with-schemas/index.d.ts +4 -4
  36. package/@types/persisters/with-schemas/index.d.ts +86 -42
  37. package/@types/synchronizers/index.d.ts +18 -16
  38. package/@types/synchronizers/synchronizer-broadcast-channel/index.d.ts +3 -3
  39. package/@types/synchronizers/synchronizer-broadcast-channel/with-schemas/index.d.ts +3 -3
  40. package/@types/synchronizers/synchronizer-local/index.d.ts +2 -2
  41. package/@types/synchronizers/synchronizer-local/with-schemas/index.d.ts +2 -2
  42. package/@types/synchronizers/synchronizer-ws-client/index.d.ts +5 -5
  43. package/@types/synchronizers/synchronizer-ws-client/with-schemas/index.d.ts +5 -5
  44. package/@types/synchronizers/synchronizer-ws-server/index.d.ts +37 -37
  45. package/@types/synchronizers/synchronizer-ws-server/with-schemas/index.d.ts +37 -37
  46. package/@types/synchronizers/synchronizer-ws-server-simple/index.d.ts +7 -7
  47. package/@types/synchronizers/synchronizer-ws-server-simple/with-schemas/index.d.ts +7 -7
  48. package/@types/synchronizers/with-schemas/index.d.ts +18 -16
  49. package/@types/ui-react/index.d.ts +2 -2
  50. package/@types/ui-react/with-schemas/index.d.ts +2 -2
  51. package/index.js +23 -17
  52. package/mergeable-store/index.js +23 -17
  53. package/mergeable-store/with-schemas/index.js +23 -17
  54. package/min/index.js +1 -1
  55. package/min/index.js.gz +0 -0
  56. package/min/mergeable-store/index.js +1 -1
  57. package/min/mergeable-store/index.js.gz +0 -0
  58. package/min/mergeable-store/with-schemas/index.js +1 -1
  59. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  60. package/min/persisters/index.js +1 -1
  61. package/min/persisters/index.js.gz +0 -0
  62. package/min/persisters/persister-automerge/index.js +1 -1
  63. package/min/persisters/persister-automerge/index.js.gz +0 -0
  64. package/min/persisters/persister-automerge/with-schemas/index.js +1 -1
  65. package/min/persisters/persister-automerge/with-schemas/index.js.gz +0 -0
  66. package/min/persisters/persister-browser/index.js +1 -1
  67. package/min/persisters/persister-browser/index.js.gz +0 -0
  68. package/min/persisters/persister-browser/with-schemas/index.js +1 -1
  69. package/min/persisters/persister-browser/with-schemas/index.js.gz +0 -0
  70. package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
  71. package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
  72. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
  73. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
  74. package/min/persisters/persister-durable-object-storage/index.js +1 -1
  75. package/min/persisters/persister-durable-object-storage/index.js.gz +0 -0
  76. package/min/persisters/persister-durable-object-storage/with-schemas/index.js +1 -1
  77. package/min/persisters/persister-durable-object-storage/with-schemas/index.js.gz +0 -0
  78. package/min/persisters/persister-electric-sql/index.js +1 -1
  79. package/min/persisters/persister-electric-sql/index.js.gz +0 -0
  80. package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
  81. package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
  82. package/min/persisters/persister-expo-sqlite/index.js +1 -1
  83. package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
  84. package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
  85. package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
  86. package/min/persisters/persister-file/index.js +1 -1
  87. package/min/persisters/persister-file/index.js.gz +0 -0
  88. package/min/persisters/persister-file/with-schemas/index.js +1 -1
  89. package/min/persisters/persister-file/with-schemas/index.js.gz +0 -0
  90. package/min/persisters/persister-indexed-db/index.js +1 -1
  91. package/min/persisters/persister-indexed-db/index.js.gz +0 -0
  92. package/min/persisters/persister-indexed-db/with-schemas/index.js +1 -1
  93. package/min/persisters/persister-indexed-db/with-schemas/index.js.gz +0 -0
  94. package/min/persisters/persister-libsql/index.js +1 -1
  95. package/min/persisters/persister-libsql/index.js.gz +0 -0
  96. package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
  97. package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
  98. package/min/persisters/persister-partykit-client/index.js +1 -1
  99. package/min/persisters/persister-partykit-client/index.js.gz +0 -0
  100. package/min/persisters/persister-partykit-client/with-schemas/index.js +1 -1
  101. package/min/persisters/persister-partykit-client/with-schemas/index.js.gz +0 -0
  102. package/min/persisters/persister-pglite/index.js +1 -1
  103. package/min/persisters/persister-pglite/index.js.gz +0 -0
  104. package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
  105. package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
  106. package/min/persisters/persister-postgres/index.js +1 -1
  107. package/min/persisters/persister-postgres/index.js.gz +0 -0
  108. package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
  109. package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
  110. package/min/persisters/persister-powersync/index.js +1 -1
  111. package/min/persisters/persister-powersync/index.js.gz +0 -0
  112. package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
  113. package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
  114. package/min/persisters/persister-remote/index.js +1 -1
  115. package/min/persisters/persister-remote/index.js.gz +0 -0
  116. package/min/persisters/persister-remote/with-schemas/index.js +1 -1
  117. package/min/persisters/persister-remote/with-schemas/index.js.gz +0 -0
  118. package/min/persisters/persister-sqlite-bun/index.js +1 -1
  119. package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
  120. package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
  121. package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
  122. package/min/persisters/persister-sqlite-wasm/index.js +1 -1
  123. package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
  124. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
  125. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
  126. package/min/persisters/persister-sqlite3/index.js +1 -1
  127. package/min/persisters/persister-sqlite3/index.js.gz +0 -0
  128. package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
  129. package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
  130. package/min/persisters/persister-yjs/index.js +1 -1
  131. package/min/persisters/persister-yjs/index.js.gz +0 -0
  132. package/min/persisters/persister-yjs/with-schemas/index.js +1 -1
  133. package/min/persisters/persister-yjs/with-schemas/index.js.gz +0 -0
  134. package/min/persisters/with-schemas/index.js +1 -1
  135. package/min/persisters/with-schemas/index.js.gz +0 -0
  136. package/min/store/index.js +1 -1
  137. package/min/store/index.js.gz +0 -0
  138. package/min/store/with-schemas/index.js +1 -1
  139. package/min/store/with-schemas/index.js.gz +0 -0
  140. package/min/synchronizers/index.js +1 -1
  141. package/min/synchronizers/index.js.gz +0 -0
  142. package/min/synchronizers/synchronizer-broadcast-channel/index.js +1 -1
  143. package/min/synchronizers/synchronizer-broadcast-channel/index.js.gz +0 -0
  144. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +1 -1
  145. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js.gz +0 -0
  146. package/min/synchronizers/synchronizer-local/index.js +1 -1
  147. package/min/synchronizers/synchronizer-local/index.js.gz +0 -0
  148. package/min/synchronizers/synchronizer-local/with-schemas/index.js +1 -1
  149. package/min/synchronizers/synchronizer-local/with-schemas/index.js.gz +0 -0
  150. package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
  151. package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
  152. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
  153. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
  154. package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
  155. package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
  156. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
  157. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
  158. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
  159. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
  160. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
  161. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
  162. package/min/synchronizers/synchronizer-ws-server-simple/index.js +1 -1
  163. package/min/synchronizers/synchronizer-ws-server-simple/index.js.gz +0 -0
  164. package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +1 -1
  165. package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js.gz +0 -0
  166. package/min/synchronizers/with-schemas/index.js +1 -1
  167. package/min/synchronizers/with-schemas/index.js.gz +0 -0
  168. package/min/ui-react-inspector/index.js +1 -1
  169. package/min/ui-react-inspector/index.js.gz +0 -0
  170. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  171. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  172. package/min/with-schemas/index.js +1 -1
  173. package/min/with-schemas/index.js.gz +0 -0
  174. package/package.json +8 -4
  175. package/persisters/index.js +293 -161
  176. package/persisters/persister-automerge/index.js +55 -50
  177. package/persisters/persister-automerge/with-schemas/index.js +55 -50
  178. package/persisters/persister-browser/index.js +56 -55
  179. package/persisters/persister-browser/with-schemas/index.js +56 -55
  180. package/persisters/persister-cr-sqlite-wasm/index.js +181 -134
  181. package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +181 -134
  182. package/persisters/persister-durable-object-storage/index.js +58 -53
  183. package/persisters/persister-durable-object-storage/with-schemas/index.js +58 -53
  184. package/persisters/persister-electric-sql/index.js +181 -134
  185. package/persisters/persister-electric-sql/with-schemas/index.js +181 -134
  186. package/persisters/persister-expo-sqlite/index.js +181 -134
  187. package/persisters/persister-expo-sqlite/with-schemas/index.js +181 -134
  188. package/persisters/persister-file/index.js +55 -50
  189. package/persisters/persister-file/with-schemas/index.js +55 -50
  190. package/persisters/persister-indexed-db/index.js +82 -78
  191. package/persisters/persister-indexed-db/with-schemas/index.js +82 -78
  192. package/persisters/persister-libsql/index.js +182 -135
  193. package/persisters/persister-libsql/with-schemas/index.js +182 -135
  194. package/persisters/persister-partykit-client/index.js +56 -51
  195. package/persisters/persister-partykit-client/with-schemas/index.js +56 -51
  196. package/persisters/persister-pglite/index.js +299 -173
  197. package/persisters/persister-pglite/with-schemas/index.js +299 -173
  198. package/persisters/persister-postgres/index.js +296 -171
  199. package/persisters/persister-postgres/with-schemas/index.js +296 -171
  200. package/persisters/persister-powersync/index.js +189 -138
  201. package/persisters/persister-powersync/with-schemas/index.js +189 -138
  202. package/persisters/persister-remote/index.js +55 -50
  203. package/persisters/persister-remote/with-schemas/index.js +55 -50
  204. package/persisters/persister-sqlite-bun/index.js +182 -135
  205. package/persisters/persister-sqlite-bun/with-schemas/index.js +182 -135
  206. package/persisters/persister-sqlite-wasm/index.js +182 -135
  207. package/persisters/persister-sqlite-wasm/with-schemas/index.js +182 -135
  208. package/persisters/persister-sqlite3/index.js +181 -134
  209. package/persisters/persister-sqlite3/with-schemas/index.js +181 -134
  210. package/persisters/persister-yjs/index.js +55 -50
  211. package/persisters/persister-yjs/with-schemas/index.js +55 -50
  212. package/persisters/with-schemas/index.js +293 -161
  213. package/readme.md +2 -2
  214. package/releases.md +29 -1
  215. package/store/index.js +20 -15
  216. package/store/with-schemas/index.js +20 -15
  217. package/synchronizers/index.js +68 -63
  218. package/synchronizers/synchronizer-broadcast-channel/index.js +68 -63
  219. package/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +68 -63
  220. package/synchronizers/synchronizer-local/index.js +68 -63
  221. package/synchronizers/synchronizer-local/with-schemas/index.js +68 -63
  222. package/synchronizers/synchronizer-ws-client/index.js +68 -63
  223. package/synchronizers/synchronizer-ws-client/with-schemas/index.js +68 -63
  224. package/synchronizers/synchronizer-ws-server/index.js +79 -70
  225. package/synchronizers/synchronizer-ws-server/with-schemas/index.js +79 -70
  226. package/synchronizers/synchronizer-ws-server-durable-object/index.js +69 -51
  227. package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +69 -51
  228. package/synchronizers/synchronizer-ws-server-simple/index.js +1 -1
  229. package/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +1 -1
  230. package/synchronizers/with-schemas/index.js +68 -63
  231. package/ui-react-inspector/index.js +68 -60
  232. package/ui-react-inspector/with-schemas/index.js +68 -60
  233. package/with-schemas/index.js +23 -17
@@ -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 isUndefined = (thing) => thing == void 0;
11
15
  const ifNotUndefined = (value, then, otherwise) =>
12
16
  isUndefined(value) ? otherwise?.() : then(value);
@@ -19,6 +23,14 @@ const promiseAll = async (promises) => promise.all(promises);
19
23
  const errorNew = (message) => {
20
24
  throw new Error(message);
21
25
  };
26
+ const tryCatch = async (action, then1, then2) => {
27
+ try {
28
+ return await action();
29
+ } catch (error) {
30
+ /* istanbul ignore next */
31
+ then1?.(error);
32
+ }
33
+ };
22
34
 
23
35
  const arrayForEach = (array, cb) => array.forEach(cb);
24
36
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
@@ -37,6 +49,17 @@ const collClear = (coll) => coll.clear();
37
49
  const collForEach = (coll, cb) => coll?.forEach(cb);
38
50
  const collDel = (coll, keyOrValue) => coll?.delete(keyOrValue);
39
51
 
52
+ const textEncoder = /* @__PURE__ */ new GLOBAL.TextEncoder();
53
+ const getHash = (value) => {
54
+ let hash = 2166136261;
55
+ arrayForEach(textEncoder.encode(value), (char) => {
56
+ hash ^= char;
57
+ hash +=
58
+ (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
59
+ });
60
+ return hash >>> 0;
61
+ };
62
+
40
63
  const object = Object;
41
64
  const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
42
65
  const objEntries = object.entries;
@@ -75,32 +98,10 @@ const jsonStringWithUndefined = (obj) =>
75
98
  const jsonParseWithUndefined = (str) =>
76
99
  jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
77
100
 
78
- const SINGLE_ROW_ID = '_';
79
- const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
80
- const SELECT = 'SELECT';
81
- const WHERE = 'WHERE';
82
- const TABLE = 'TABLE';
83
- const ALTER_TABLE = 'ALTER ' + TABLE;
84
- const DELETE_FROM = 'DELETE FROM';
85
- const SELECT_STAR_FROM = SELECT + '*FROM';
86
- const getWrappedCommand = (executeCommand, onSqlCommand) =>
87
- onSqlCommand
88
- ? async (sql, params) => {
89
- onSqlCommand(sql, params);
90
- return await executeCommand(sql, params);
91
- }
92
- : executeCommand;
93
- const escapeId = (str) => `"${str.replace(/"/g, '""')}"`;
94
- const escapeColumnNames = (...columnNames) =>
95
- arrayJoin(arrayMap(columnNames, escapeId), COMMA);
96
- const getPlaceholders = (array, offset = [1]) =>
97
- arrayJoin(
98
- arrayMap(array, () => '$' + offset[0]++),
99
- COMMA,
100
- );
101
-
102
101
  const mapNew = (entries) => new Map(entries);
103
102
  const mapGet = (map, key) => map?.get(key);
103
+ const mapForEach = (map, cb) =>
104
+ collForEach(map, (value, key) => cb(key, value));
104
105
  const mapMap = (coll, cb) =>
105
106
  arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
106
107
  const mapSet = (map, key, value) =>
@@ -135,6 +136,43 @@ const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
135
136
  },
136
137
  );
137
138
 
139
+ const SINGLE_ROW_ID = '_';
140
+ const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
141
+ const SELECT = 'SELECT';
142
+ const WHERE = 'WHERE';
143
+ const TABLE = 'TABLE';
144
+ const INSERT = 'INSERT';
145
+ const DELETE = 'DELETE';
146
+ const UPDATE = 'UPDATE';
147
+ const ALTER_TABLE = 'ALTER ' + TABLE;
148
+ const FROM = 'FROM';
149
+ const DELETE_FROM = DELETE + ' ' + FROM;
150
+ const SELECT_STAR_FROM = SELECT + '*' + FROM;
151
+ const CREATE = 'CREATE ';
152
+ const CREATE_TABLE = CREATE + TABLE;
153
+ const OR_REPLACE = 'OR REPLACE ';
154
+ const FUNCTION = 'FUNCTION';
155
+ const TABLE_NAME_PLACEHOLDER = '$tableName';
156
+ const getWrappedCommand = (executeCommand, onSqlCommand) =>
157
+ onSqlCommand
158
+ ? async (sql, params) => {
159
+ onSqlCommand(sql, params);
160
+ return await executeCommand(sql, params);
161
+ }
162
+ : executeCommand;
163
+ const escapeId = (str) => `"${strReplace(str, /"/g, '""')}"`;
164
+ const escapeIds = (...ids) => escapeId(arrayJoin(ids, '_'));
165
+ const escapeColumnNames = (...columnNames) =>
166
+ arrayJoin(arrayMap(columnNames, escapeId), COMMA);
167
+ const getPlaceholders = (array, offset = [1]) =>
168
+ arrayJoin(
169
+ arrayMap(array, () => '$' + offset[0]++),
170
+ COMMA,
171
+ );
172
+ const getWhereCondition = (tableName, condition = TRUE) =>
173
+ WHERE +
174
+ `(${strReplace(condition, TABLE_NAME_PLACEHOLDER, escapeId(tableName))})`;
175
+
138
176
  const setNew = (entryOrEntries) =>
139
177
  new Set(
140
178
  isArray(entryOrEntries) || isUndefined(entryOrEntries)
@@ -155,6 +193,7 @@ const TABLE_ID = 'tableId';
155
193
  const TABLE_NAME = 'tableName';
156
194
  const DELETE_EMPTY_COLUMNS = 'deleteEmptyColumns';
157
195
  const DELETE_EMPTY_TABLE = 'deleteEmptyTable';
196
+ const CONDITION = 'condition';
158
197
  const DEFAULT_CONFIG = {
159
198
  mode: JSON$1,
160
199
  [AUTO_LOAD_INTERVAL_SECONDS]: 1,
@@ -222,29 +261,42 @@ const getConfigStructures = (configOrStoreTableName) => {
222
261
  const valuesTable = valuesConfig[2];
223
262
  const managedTableNames = setNew(valuesTable);
224
263
  const excludedTableNames = setNew(valuesTable);
225
- const tabularConfig = [
226
- getDefaultedTabularConfigMap(
227
- load,
228
- {[TABLE_ID]: null, [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME},
229
- TABLE_ID,
230
- (tableName) => collHas(excludedTableNames, tableName),
231
- (tableName) => setAdd(managedTableNames, tableName),
232
- ),
233
- getDefaultedTabularConfigMap(
234
- save,
235
- {
236
- [TABLE_NAME]: null,
237
- [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
238
- [DELETE_EMPTY_COLUMNS]: 0,
239
- [DELETE_EMPTY_TABLE]: 0,
240
- },
241
- TABLE_NAME,
242
- (_, tableName) => collHas(excludedTableNames, tableName),
243
- (_, tableName) => setAdd(managedTableNames, tableName),
244
- ),
245
- valuesConfig,
264
+ const tablesLoadConfig = getDefaultedTabularConfigMap(
265
+ load,
266
+ {
267
+ [TABLE_ID]: null,
268
+ [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
269
+ [CONDITION]: TRUE,
270
+ },
271
+ TABLE_ID,
272
+ (tableName) => collHas(excludedTableNames, tableName),
273
+ (tableName) => setAdd(managedTableNames, tableName),
274
+ );
275
+ const tablesSaveConfig = getDefaultedTabularConfigMap(
276
+ save,
277
+ {
278
+ [TABLE_NAME]: null,
279
+ [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
280
+ [DELETE_EMPTY_COLUMNS]: 0,
281
+ [DELETE_EMPTY_TABLE]: 0,
282
+ [CONDITION]: null,
283
+ },
284
+ TABLE_NAME,
285
+ (_, tableName) => collHas(excludedTableNames, tableName),
286
+ (_, tableName) => setAdd(managedTableNames, tableName),
287
+ );
288
+ mapForEach(
289
+ tablesSaveConfig,
290
+ (_, tableSaveConfig) =>
291
+ (tableSaveConfig[4] ??=
292
+ mapGet(tablesLoadConfig, tableSaveConfig[0])?.[2] ?? TRUE),
293
+ );
294
+ return [
295
+ 0,
296
+ autoLoadIntervalSeconds,
297
+ [tablesLoadConfig, tablesSaveConfig, valuesConfig],
298
+ managedTableNames,
246
299
  ];
247
- return [0, autoLoadIntervalSeconds, tabularConfig, managedTableNames];
248
300
  };
249
301
 
250
302
  const INTEGER = /^\d+$/;
@@ -403,12 +455,7 @@ const createCustomPersister = (
403
455
  while (
404
456
  !isUndefined((action = arrayShift(mapGet(scheduleActions, scheduleId))))
405
457
  ) {
406
- try {
407
- await action();
408
- } catch (error) {
409
- /* istanbul ignore next */
410
- onIgnoredError?.(error);
411
- }
458
+ await tryCatch(action, onIgnoredError);
412
459
  }
413
460
  mapSet(scheduleRunning, scheduleId, 0);
414
461
  }
@@ -428,21 +475,23 @@ const createCustomPersister = (
428
475
  setStatus(1 /* Loading */);
429
476
  loads++;
430
477
  await schedule(async () => {
431
- try {
432
- const content = await getPersisted();
433
- if (isArray(content)) {
434
- setContentOrChanges(content);
435
- } else if (initialContent) {
436
- setDefaultContent(initialContent);
437
- } else {
438
- errorNew(`Content is not an array: ${content}`);
439
- }
440
- } catch (error) {
441
- onIgnoredError?.(error);
442
- if (initialContent) {
443
- setDefaultContent(initialContent);
444
- }
445
- }
478
+ await tryCatch(
479
+ async () => {
480
+ const content = await getPersisted();
481
+ if (isArray(content)) {
482
+ setContentOrChanges(content);
483
+ } else if (initialContent) {
484
+ setDefaultContent(initialContent);
485
+ } else {
486
+ errorNew(`Content is not an array: ${content}`);
487
+ }
488
+ },
489
+ () => {
490
+ if (initialContent) {
491
+ setDefaultContent(initialContent);
492
+ }
493
+ },
494
+ );
446
495
  setStatus(0 /* Idle */);
447
496
  });
448
497
  }
@@ -451,29 +500,33 @@ const createCustomPersister = (
451
500
  const startAutoLoad = async (initialContent) => {
452
501
  stopAutoLoad();
453
502
  await load(initialContent);
454
- try {
455
- autoLoadHandle = await addPersisterListener(async (content, changes) => {
456
- if (changes || content) {
457
- /* istanbul ignore else */
458
- if (status != 2 /* Saving */) {
459
- setStatus(1 /* Loading */);
460
- loads++;
461
- setContentOrChanges(changes ?? content);
462
- setStatus(0 /* Idle */);
463
- }
464
- } else {
465
- await load();
466
- }
467
- });
468
- } catch (error) {
469
- /* istanbul ignore next */
470
- onIgnoredError?.(error);
471
- }
503
+ await tryCatch(
504
+ async () =>
505
+ (autoLoadHandle = await addPersisterListener(
506
+ async (content, changes) => {
507
+ if (changes || content) {
508
+ /* istanbul ignore else */
509
+ if (status != 2 /* Saving */) {
510
+ setStatus(1 /* Loading */);
511
+ loads++;
512
+ setContentOrChanges(changes ?? content);
513
+ setStatus(0 /* Idle */);
514
+ }
515
+ } else {
516
+ await load();
517
+ }
518
+ },
519
+ )),
520
+ onIgnoredError,
521
+ );
472
522
  return persister;
473
523
  };
474
- const stopAutoLoad = () => {
524
+ const stopAutoLoad = async () => {
475
525
  if (autoLoadHandle) {
476
- delPersisterListener(autoLoadHandle);
526
+ await tryCatch(
527
+ () => delPersisterListener(autoLoadHandle),
528
+ onIgnoredError,
529
+ );
477
530
  autoLoadHandle = void 0;
478
531
  }
479
532
  return persister;
@@ -485,12 +538,7 @@ const createCustomPersister = (
485
538
  setStatus(2 /* Saving */);
486
539
  saves++;
487
540
  await schedule(async () => {
488
- try {
489
- await setPersisted(getContent, changes);
490
- } catch (error) {
491
- /* istanbul ignore next */
492
- onIgnoredError?.(error);
493
- }
541
+ await tryCatch(() => setPersisted(getContent, changes), onIgnoredError);
494
542
  setStatus(0 /* Idle */);
495
543
  });
496
544
  }
@@ -507,7 +555,7 @@ const createCustomPersister = (
507
555
  });
508
556
  return persister;
509
557
  };
510
- const stopAutoSave = () => {
558
+ const stopAutoSave = async () => {
511
559
  if (autoSaveListenerId) {
512
560
  store.delListener(autoSaveListenerId);
513
561
  autoSaveListenerId = void 0;
@@ -528,9 +576,10 @@ const createCustomPersister = (
528
576
  return persister;
529
577
  };
530
578
  const getStore = () => store;
531
- const destroy = () => {
579
+ const destroy = async () => {
532
580
  arrayClear(mapGet(scheduleActions, scheduleId));
533
- return stopAutoLoad().stopAutoSave();
581
+ await persister.stopAutoLoad();
582
+ return await persister.stopAutoSave();
534
583
  };
535
584
  const getStats = () => ({loads, saves});
536
585
  const persister = {
@@ -574,13 +623,15 @@ const getCommandFunctions = (
574
623
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
575
624
  );
576
625
  };
577
- const loadTable = async (tableName, rowIdColumnName) =>
626
+ const loadTable = async (tableName, rowIdColumnName, condition) =>
578
627
  canSelect(tableName, rowIdColumnName)
579
628
  ? objNew(
580
629
  arrayFilter(
581
630
  arrayMap(
582
631
  await databaseExecuteCommand(
583
- SELECT_STAR_FROM + escapeId(tableName),
632
+ SELECT_STAR_FROM +
633
+ escapeId(tableName) +
634
+ getWhereCondition(tableName, condition),
584
635
  ),
585
636
  (row) => [
586
637
  row[rowIdColumnName],
@@ -600,6 +651,7 @@ const getCommandFunctions = (
600
651
  deleteEmptyColumns,
601
652
  deleteEmptyTable,
602
653
  partial = false,
654
+ condition = TRUE,
603
655
  ) => {
604
656
  const settingColumnNameSet = setNew();
605
657
  objMap(content ?? {}, (contentRow) =>
@@ -611,6 +663,7 @@ const getCommandFunctions = (
611
663
  if (
612
664
  !partial &&
613
665
  deleteEmptyTable &&
666
+ condition == TRUE &&
614
667
  arrayIsEmpty(settingColumnNames) &&
615
668
  collHas(schemaMap, tableName)
616
669
  ) {
@@ -623,8 +676,7 @@ const getCommandFunctions = (
623
676
  if (!arrayIsEmpty(settingColumnNames)) {
624
677
  if (!collHas(schemaMap, tableName)) {
625
678
  await databaseExecuteCommand(
626
- 'CREATE ' +
627
- TABLE +
679
+ CREATE_TABLE +
628
680
  escapeId(tableName) +
629
681
  `(${escapeId(rowIdColumnName)}${columnType} PRIMARY KEY${arrayJoin(
630
682
  arrayMap(
@@ -687,7 +739,9 @@ const getCommandFunctions = (
687
739
  if (partial) {
688
740
  if (isUndefined(content)) {
689
741
  await databaseExecuteCommand(
690
- DELETE_FROM + escapeId(tableName) + WHERE + ' true',
742
+ DELETE_FROM +
743
+ escapeId(tableName) +
744
+ getWhereCondition(tableName, condition),
691
745
  );
692
746
  } else {
693
747
  await promiseAll(
@@ -696,9 +750,8 @@ const getCommandFunctions = (
696
750
  await databaseExecuteCommand(
697
751
  DELETE_FROM +
698
752
  escapeId(tableName) +
699
- WHERE +
700
- escapeId(rowIdColumnName) +
701
- '=$1',
753
+ getWhereCondition(tableName, condition) +
754
+ `AND(${escapeId(rowIdColumnName)}=$1)`,
702
755
  [rowId],
703
756
  );
704
757
  } else if (!arrayIsEmpty(settingColumnNames)) {
@@ -742,14 +795,15 @@ const getCommandFunctions = (
742
795
  await databaseExecuteCommand(
743
796
  DELETE_FROM +
744
797
  escapeId(tableName) +
745
- WHERE +
746
- escapeId(rowIdColumnName) +
747
- `NOT IN(${getPlaceholders(deleteRowIds)})`,
798
+ getWhereCondition(tableName, condition) + // eslint-disable-next-line max-len
799
+ `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
748
800
  deleteRowIds,
749
801
  );
750
802
  } else if (collHas(schemaMap, tableName)) {
751
803
  await databaseExecuteCommand(
752
- DELETE_FROM + escapeId(tableName) + WHERE + ' true',
804
+ DELETE_FROM +
805
+ escapeId(tableName) +
806
+ getWhereCondition(tableName, condition),
753
807
  );
754
808
  }
755
809
  }
@@ -757,11 +811,7 @@ const getCommandFunctions = (
757
811
  const transaction = async (actions) => {
758
812
  let result;
759
813
  await databaseExecuteCommand('BEGIN');
760
- try {
761
- result = await actions();
762
- } catch (error) {
763
- onIgnoredError?.(error);
764
- }
814
+ await tryCatch(async () => (result = await actions()), onIgnoredError);
765
815
  await databaseExecuteCommand('END');
766
816
  return result;
767
817
  };
@@ -776,7 +826,8 @@ const defaultUpsert = async (
776
826
  ) => {
777
827
  const offset = [1];
778
828
  await executeCommand(
779
- 'INSERT INTO' +
829
+ INSERT +
830
+ ' INTO' +
780
831
  escapeId(tableName) +
781
832
  '(' +
782
833
  escapeColumnNames(rowIdColumnName, ...changingColumnNames) +
@@ -791,7 +842,7 @@ const defaultUpsert = async (
791
842
  ) +
792
843
  'ON CONFLICT(' +
793
844
  escapeId(rowIdColumnName) +
794
- ')DO UPDATE SET' +
845
+ `)DO ${UPDATE} SET` +
795
846
  arrayJoin(
796
847
  arrayMap(
797
848
  changingColumnNames,
@@ -813,7 +864,7 @@ const createJsonPersister = (
813
864
  addPersisterListener,
814
865
  delPersisterListener,
815
866
  onIgnoredError,
816
- destroyImpl,
867
+ extraDestroy,
817
868
  persist,
818
869
  [storeTableName, storeIdColumnName, storeColumnName],
819
870
  managedTableNames,
@@ -832,8 +883,8 @@ const createJsonPersister = (
832
883
  columnType,
833
884
  upsert,
834
885
  );
835
- const getPersisted = async () =>
836
- await transaction(async () => {
886
+ const getPersisted = () =>
887
+ transaction(async () => {
837
888
  await refreshSchema();
838
889
  return jsonParseWithUndefined(
839
890
  (await loadTable(storeTableName, storeIdColumnName))[SINGLE_ROW_ID]?.[
@@ -841,8 +892,8 @@ const createJsonPersister = (
841
892
  ] ?? 'null',
842
893
  );
843
894
  });
844
- const setPersisted = async (getContent) =>
845
- await transaction(async () => {
895
+ const setPersisted = (getContent) =>
896
+ transaction(async () => {
846
897
  await refreshSchema();
847
898
  await saveTable(
848
899
  storeTableName,
@@ -856,9 +907,10 @@ const createJsonPersister = (
856
907
  true,
857
908
  );
858
909
  });
859
- const destroy = () => {
860
- persister.stopAutoLoad().stopAutoSave();
861
- destroyImpl();
910
+ const destroy = async () => {
911
+ await persister.stopAutoLoad();
912
+ await persister.stopAutoSave();
913
+ extraDestroy();
862
914
  return persister;
863
915
  };
864
916
  const persister = createCustomPersister(
@@ -882,7 +934,7 @@ const createTabularPersister = (
882
934
  addPersisterListener,
883
935
  delPersisterListener,
884
936
  onIgnoredError,
885
- destroyImpl,
937
+ extraDestroy,
886
938
  persist,
887
939
  [
888
940
  tablesLoadConfig,
@@ -909,12 +961,18 @@ const createTabularPersister = (
909
961
  encode,
910
962
  decode,
911
963
  );
912
- const saveTables = async (tables, partial) =>
913
- await promiseAll(
964
+ const saveTables = (tables, partial) =>
965
+ promiseAll(
914
966
  mapMap(
915
967
  tablesSaveConfig,
916
968
  async (
917
- [tableName, rowIdColumnName, deleteEmptyColumns, deleteEmptyTable],
969
+ [
970
+ tableName,
971
+ rowIdColumnName,
972
+ deleteEmptyColumns,
973
+ deleteEmptyTable,
974
+ condition,
975
+ ],
918
976
  tableId,
919
977
  ) => {
920
978
  if (!partial || objHas(tables, tableId)) {
@@ -925,6 +983,7 @@ const createTabularPersister = (
925
983
  deleteEmptyColumns,
926
984
  deleteEmptyTable,
927
985
  partial,
986
+ condition,
928
987
  );
929
988
  }
930
989
  },
@@ -947,9 +1006,9 @@ const createTabularPersister = (
947
1006
  await promiseAll(
948
1007
  mapMap(
949
1008
  tablesLoadConfig,
950
- async ([tableId, rowIdColumnName], tableName) => [
1009
+ async ([tableId, rowIdColumnName, condition], tableName) => [
951
1010
  tableId,
952
- await loadTable(tableName, rowIdColumnName),
1011
+ await loadTable(tableName, rowIdColumnName, condition),
953
1012
  ],
954
1013
  ),
955
1014
  ),
@@ -962,8 +1021,8 @@ const createTabularPersister = (
962
1021
  SINGLE_ROW_ID
963
1022
  ]
964
1023
  : {};
965
- const getPersisted = async () =>
966
- await transaction(async () => {
1024
+ const getPersisted = () =>
1025
+ transaction(async () => {
967
1026
  await refreshSchema();
968
1027
  const tables = await loadTables();
969
1028
  const values = await loadValues();
@@ -971,8 +1030,8 @@ const createTabularPersister = (
971
1030
  ? [tables, values]
972
1031
  : void 0;
973
1032
  });
974
- const setPersisted = async (getContent, changes) =>
975
- await transaction(async () => {
1033
+ const setPersisted = (getContent, changes) =>
1034
+ transaction(async () => {
976
1035
  await refreshSchema();
977
1036
  if (!isUndefined(changes)) {
978
1037
  await saveTables(changes[0], true);
@@ -983,9 +1042,10 @@ const createTabularPersister = (
983
1042
  await saveValues(values);
984
1043
  }
985
1044
  });
986
- const destroy = () => {
987
- persister.stopAutoLoad().stopAutoSave();
988
- destroyImpl();
1045
+ const destroy = async () => {
1046
+ await persister.stopAutoLoad();
1047
+ await persister.stopAutoSave();
1048
+ extraDestroy();
989
1049
  return persister;
990
1050
  };
991
1051
  const persister = createCustomPersister(
@@ -1003,10 +1063,9 @@ const createTabularPersister = (
1003
1063
  return persister;
1004
1064
  };
1005
1065
 
1006
- const EVENT_CHANNEL = TINYBASE;
1066
+ const TABLE_CREATED = 'c';
1067
+ const DATA_CHANGED = 'd';
1007
1068
  const EVENT_REGEX = /^([cd]:)(.+)/;
1008
- const CHANGE_DATA_TRIGGER = TINYBASE + '_data';
1009
- const CREATE_TABLE_TRIGGER = TINYBASE + '_table';
1010
1069
  const createCustomPostgreSqlPersister = (
1011
1070
  store,
1012
1071
  configOrStoreTableName,
@@ -1024,53 +1083,125 @@ const createCustomPostgreSqlPersister = (
1024
1083
  const [isJson, , defaultedConfig, managedTableNamesSet] = getConfigStructures(
1025
1084
  configOrStoreTableName,
1026
1085
  );
1027
- const addDataTrigger = async (tableName) => {
1086
+ const configHash =
1087
+ EMPTY_STRING + getHash(jsonStringWithUndefined(defaultedConfig));
1088
+ const channel = TINYBASE + '_' + configHash;
1089
+ const createFunction = async (
1090
+ name,
1091
+ body,
1092
+ returnPrefix = '',
1093
+ declarations = '',
1094
+ ) => {
1095
+ const escapedFunctionName = escapeIds(TINYBASE, name, configHash);
1028
1096
  await executeCommand(
1029
- // eslint-disable-next-line max-len
1030
- `CREATE OR REPLACE TRIGGER ${escapeId(CHANGE_DATA_TRIGGER + '_' + tableName)} AFTER INSERT OR UPDATE OR DELETE ON ${escapeId(tableName)} EXECUTE FUNCTION ${CHANGE_DATA_TRIGGER}()`,
1097
+ CREATE +
1098
+ OR_REPLACE +
1099
+ FUNCTION +
1100
+ escapedFunctionName +
1101
+ `()RETURNS ${returnPrefix}trigger AS $$ ${declarations}BEGIN ${body}END;$$ LANGUAGE plpgsql;`,
1031
1102
  );
1103
+ return escapedFunctionName;
1032
1104
  };
1033
- const addPersisterListener = async (listener) => {
1105
+ const createTrigger = async (
1106
+ prefix,
1107
+ escapedTriggerName,
1108
+ body,
1109
+ escapedFunctionName,
1110
+ ) => {
1034
1111
  await executeCommand(
1035
- // eslint-disable-next-line max-len
1036
- `CREATE OR REPLACE FUNCTION ${CREATE_TABLE_TRIGGER}()RETURNS event_trigger AS $t2$ DECLARE row record; BEGIN FOR row IN SELECT object_identity FROM pg_event_trigger_ddl_commands()WHERE command_tag='CREATE TABLE' LOOP PERFORM pg_notify('${EVENT_CHANNEL}','c:'||SPLIT_PART(row.object_identity,'.',2));END LOOP;END;$t2$ LANGUAGE plpgsql;`,
1112
+ CREATE +
1113
+ prefix +
1114
+ 'TRIGGER' +
1115
+ escapedTriggerName +
1116
+ body +
1117
+ 'EXECUTE ' +
1118
+ FUNCTION +
1119
+ escapedFunctionName +
1120
+ `()`,
1037
1121
  );
1038
- try {
1039
- await executeCommand(
1040
- // eslint-disable-next-line max-len
1041
- `CREATE EVENT TRIGGER ${CREATE_TABLE_TRIGGER} ON ddl_command_end WHEN TAG IN('CREATE TABLE')EXECUTE FUNCTION ${CREATE_TABLE_TRIGGER}();`,
1042
- );
1043
- } catch {}
1044
- await executeCommand(
1122
+ return escapedTriggerName;
1123
+ };
1124
+ const notify = (message) => `PERFORM pg_notify('${channel}',${message});`;
1125
+ const when = (tableName, newOrOldOrBoth) =>
1126
+ isJson
1127
+ ? TRUE
1128
+ : newOrOldOrBoth === 2
1129
+ ? when(tableName, 0) + ' OR ' + when(tableName, 1)
1130
+ : strReplace(
1131
+ mapGet(defaultedConfig[0], tableName)?.[2] ?? TRUE,
1132
+ TABLE_NAME_PLACEHOLDER,
1133
+ newOrOldOrBoth == 0 ? 'NEW' : 'OLD',
1134
+ );
1135
+ const addDataChangedTriggers = (tableName, dataChangedFunction) =>
1136
+ promiseAll(
1137
+ arrayMap([INSERT, DELETE, UPDATE], (action, newOrOldOrBoth) =>
1138
+ createTrigger(
1139
+ OR_REPLACE,
1140
+ escapeIds(TINYBASE, DATA_CHANGED, configHash, tableName, action),
1141
+ `AFTER ${action} ON${escapeId(tableName)}FOR EACH ROW WHEN(${when(
1142
+ tableName,
1143
+ newOrOldOrBoth,
1144
+ )})`,
1145
+ dataChangedFunction,
1146
+ ),
1147
+ ),
1148
+ );
1149
+ const addPersisterListener = async (listener) => {
1150
+ const tableCreatedFunctionName = await createFunction(
1151
+ TABLE_CREATED,
1045
1152
  // eslint-disable-next-line max-len
1046
- `CREATE OR REPLACE FUNCTION ${CHANGE_DATA_TRIGGER}()RETURNS trigger AS $t1$ BEGIN PERFORM pg_notify('${EVENT_CHANNEL}','d:'||TG_TABLE_NAME);RETURN NULL;END;$t1$ LANGUAGE plpgsql;`,
1153
+ `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;`,
1154
+ 'event_',
1155
+ 'DECLARE row record;',
1156
+ );
1157
+ await createTrigger(
1158
+ 'EVENT ',
1159
+ escapeIds(TINYBASE, TABLE_CREATED, configHash),
1160
+ `ON ddl_command_end WHEN TAG IN('${CREATE_TABLE}')`,
1161
+ tableCreatedFunctionName,
1162
+ );
1163
+ const dataChangedFunctionName = await createFunction(
1164
+ DATA_CHANGED,
1165
+ notify(`'d:'||TG_TABLE_NAME`) + `RETURN NULL;`,
1047
1166
  );
1048
1167
  await promiseAll(
1049
1168
  arrayMap(collValues(managedTableNamesSet), async (tableName) => {
1050
1169
  await executeCommand(
1051
- // eslint-disable-next-line max-len
1052
- `CREATE TABLE IF NOT EXISTS ${escapeId(tableName)}("_id"text PRIMARY KEY)`,
1170
+ CREATE_TABLE +
1171
+ ` IF NOT EXISTS${escapeId(tableName)}("_id"text PRIMARY KEY)`,
1053
1172
  );
1054
- await addDataTrigger(tableName);
1173
+ return await addDataChangedTriggers(tableName, dataChangedFunctionName);
1055
1174
  }),
1056
1175
  );
1057
- return await addChangeListener(
1058
- EVENT_CHANNEL,
1059
- async (prefixAndTableName) =>
1060
- await ifNotUndefined(
1176
+ const listenerHandle = await addChangeListener(
1177
+ channel,
1178
+ (prefixAndTableName) =>
1179
+ ifNotUndefined(
1061
1180
  strMatch(prefixAndTableName, EVENT_REGEX),
1062
1181
  async ([, eventType, tableName]) => {
1063
1182
  if (collHas(managedTableNamesSet, tableName)) {
1064
1183
  if (eventType == 'c:') {
1065
- await addDataTrigger(tableName);
1184
+ await addDataChangedTriggers(
1185
+ tableName,
1186
+ dataChangedFunctionName,
1187
+ );
1066
1188
  }
1067
1189
  listener();
1068
1190
  }
1069
1191
  },
1070
1192
  ),
1071
1193
  );
1194
+ return [
1195
+ listenerHandle,
1196
+ [tableCreatedFunctionName, dataChangedFunctionName],
1197
+ ];
1198
+ };
1199
+ const delPersisterListener = async ([listenerHandle, functionNames]) => {
1200
+ delChangeListener(listenerHandle);
1201
+ await executeCommand(
1202
+ `DROP FUNCTION IF EXISTS${arrayJoin(functionNames, ',')}CASCADE`,
1203
+ );
1072
1204
  };
1073
- const delPersisterListener = delChangeListener;
1074
1205
  return (isJson ? createJsonPersister : createTabularPersister)(
1075
1206
  store,
1076
1207
  executeCommand,
@@ -1083,8 +1214,8 @@ const createCustomPostgreSqlPersister = (
1083
1214
  collValues(managedTableNamesSet),
1084
1215
  async (executeCommand2, managedTableNames) =>
1085
1216
  await executeCommand2(
1086
- // eslint-disable-next-line max-len
1087
- `${SELECT} table_name tn,column_name cn FROM information_schema.columns ${WHERE} table_schema='public'AND table_name IN(${getPlaceholders(managedTableNames)})`,
1217
+ SELECT + // eslint-disable-next-line max-len
1218
+ ` table_name tn,column_name cn FROM information_schema.columns ${WHERE} table_schema='public'AND table_name IN(${getPlaceholders(managedTableNames)})`,
1088
1219
  managedTableNames,
1089
1220
  ),
1090
1221
  thing,
@@ -1109,13 +1240,7 @@ const createPostgresPersister = async (
1109
1240
  configOrStoreTableName,
1110
1241
  commandSql?.unsafe,
1111
1242
  async (channel, listener) => sql.listen(channel, listener),
1112
- async (notifyListener) => {
1113
- try {
1114
- await notifyListener.unlisten();
1115
- } catch (e) {
1116
- onIgnoredError?.(e);
1117
- }
1118
- },
1243
+ (notifyListener) => tryCatch(notifyListener.unlisten, onIgnoredError),
1119
1244
  onSqlCommand,
1120
1245
  onIgnoredError,
1121
1246
  () => commandSql?.release?.(),