tinybase 6.1.0-beta.3 → 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 +83 -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 +159 -0
  29. package/@types/persisters/persister-sqlite-bun/with-schemas/index.d.ts +178 -0
  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 +87 -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 -0
  119. package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
  120. package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -0
  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 +46 -6
  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 +1171 -0
  205. package/persisters/persister-sqlite-bun/with-schemas/index.js +1171 -0
  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
@@ -0,0 +1,1171 @@
1
+ const getTypeOf = (thing) => typeof thing;
2
+ const TINYBASE = 'tinybase';
3
+ const EMPTY_STRING = '';
4
+ const COMMA = ',';
5
+ const STRING = getTypeOf(EMPTY_STRING);
6
+ const TRUE = 'true';
7
+ const UNDEFINED = '\uFFFC';
8
+ const strReplace = (str, searchValue, replaceValue) =>
9
+ str.replace(searchValue, replaceValue);
10
+
11
+ const promise = Promise;
12
+ const THOUSAND = 1e3;
13
+ const startInterval = (callback, sec, immediate) => {
14
+ return setInterval(callback, sec * THOUSAND);
15
+ };
16
+ const stopInterval = clearInterval;
17
+ const isUndefined = (thing) => thing == void 0;
18
+ const ifNotUndefined = (value, then, otherwise) =>
19
+ isUndefined(value) ? otherwise?.() : then(value);
20
+ const isString = (thing) => getTypeOf(thing) == STRING;
21
+ const isArray = (thing) => Array.isArray(thing);
22
+ const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
23
+ const size = (arrayOrString) => arrayOrString.length;
24
+ const test = (regex, subject) => regex.test(subject);
25
+ const noop = () => {};
26
+ const promiseAll = async (promises) => promise.all(promises);
27
+ const errorNew = (message) => {
28
+ throw new Error(message);
29
+ };
30
+ const tryCatch = async (action, then1, then2) => {
31
+ try {
32
+ return await action();
33
+ } catch (error) {
34
+ /* istanbul ignore next */
35
+ then1?.(error);
36
+ }
37
+ };
38
+
39
+ const arrayForEach = (array, cb) => array.forEach(cb);
40
+ const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
41
+ const arrayMap = (array, cb) => array.map(cb);
42
+ const arrayIsEmpty = (array) => size(array) == 0;
43
+ const arrayFilter = (array, cb) => array.filter(cb);
44
+ const arrayClear = (array, to) => array.splice(0, to);
45
+ const arrayPush = (array, ...values) => array.push(...values);
46
+ const arrayShift = (array) => array.shift();
47
+
48
+ const collSize = (coll) => coll?.size ?? 0;
49
+ const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
50
+ const collIsEmpty = (coll) => isUndefined(coll) || collSize(coll) == 0;
51
+ const collValues = (coll) => [...(coll?.values() ?? [])];
52
+ const collClear = (coll) => coll.clear();
53
+ const collForEach = (coll, cb) => coll?.forEach(cb);
54
+ const collDel = (coll, keyOrValue) => coll?.delete(keyOrValue);
55
+
56
+ const SINGLE_ROW_ID = '_';
57
+ const DEFAULT_ROW_ID_COLUMN_NAME = '_id';
58
+ const SELECT = 'SELECT';
59
+ const WHERE = 'WHERE';
60
+ const TABLE = 'TABLE';
61
+ const INSERT = 'INSERT';
62
+ const DELETE = 'DELETE';
63
+ const UPDATE = 'UPDATE';
64
+ const ALTER_TABLE = 'ALTER ' + TABLE;
65
+ const FROM = 'FROM';
66
+ const DELETE_FROM = DELETE + ' ' + FROM;
67
+ const SELECT_STAR_FROM = SELECT + '*' + FROM;
68
+ const PRAGMA = 'pragma_';
69
+ const DATA_VERSION = 'data_version';
70
+ const SCHEMA_VERSION = 'schema_version';
71
+ const PRAGMA_TABLE = 'pragma_table_';
72
+ const CREATE = 'CREATE ';
73
+ const CREATE_TABLE = CREATE + TABLE;
74
+ const TABLE_NAME_PLACEHOLDER = '$tableName';
75
+ const getWrappedCommand = (executeCommand, onSqlCommand) =>
76
+ onSqlCommand
77
+ ? async (sql, params) => {
78
+ onSqlCommand(sql, params);
79
+ return await executeCommand(sql, params);
80
+ }
81
+ : executeCommand;
82
+ const escapeId = (str) => `"${strReplace(str, /"/g, '""')}"`;
83
+ const escapeColumnNames = (...columnNames) =>
84
+ arrayJoin(arrayMap(columnNames, escapeId), COMMA);
85
+ const getPlaceholders = (array, offset = [1]) =>
86
+ arrayJoin(
87
+ arrayMap(array, () => '$' + offset[0]++),
88
+ COMMA,
89
+ );
90
+ const getWhereCondition = (tableName, condition = TRUE) =>
91
+ WHERE +
92
+ `(${strReplace(condition, TABLE_NAME_PLACEHOLDER, escapeId(tableName))})`;
93
+
94
+ const object = Object;
95
+ const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
96
+ const objEntries = object.entries;
97
+ const isObject = (obj) =>
98
+ !isUndefined(obj) &&
99
+ ifNotUndefined(
100
+ getPrototypeOf(obj),
101
+ (objPrototype) =>
102
+ objPrototype == object.prototype ||
103
+ isUndefined(getPrototypeOf(objPrototype)),
104
+
105
+ /* istanbul ignore next */
106
+ () => true,
107
+ );
108
+ const objIds = object.keys;
109
+ const objFreeze = object.freeze;
110
+ const objNew = (entries = []) => object.fromEntries(entries);
111
+ const objMerge = (...objs) => object.assign({}, ...objs);
112
+ const objHas = (obj, id) => id in obj;
113
+ const objDel = (obj, id) => {
114
+ delete obj[id];
115
+ return obj;
116
+ };
117
+ const objToArray = (obj, cb) =>
118
+ arrayMap(objEntries(obj), ([id, value]) => cb(value, id));
119
+ const objMap = (obj, cb) =>
120
+ objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
121
+ const objValues = (obj) => object.values(obj);
122
+ const objSize = (obj) => size(objIds(obj));
123
+ const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
124
+
125
+ const mapNew = (entries) => new Map(entries);
126
+ const mapGet = (map, key) => map?.get(key);
127
+ const mapForEach = (map, cb) =>
128
+ collForEach(map, (value, key) => cb(key, value));
129
+ const mapMap = (coll, cb) =>
130
+ arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
131
+ const mapSet = (map, key, value) =>
132
+ isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
133
+ const mapEnsure = (map, key, getDefaultValue, hadExistingValue) => {
134
+ if (!collHas(map, key)) {
135
+ mapSet(map, key, getDefaultValue());
136
+ } else {
137
+ hadExistingValue?.(mapGet(map, key));
138
+ }
139
+ return mapGet(map, key);
140
+ };
141
+ const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
142
+ ifNotUndefined(
143
+ (ensureLeaf ? mapEnsure : mapGet)(
144
+ node,
145
+ path[p],
146
+ p > size(path) - 2 ? ensureLeaf : mapNew,
147
+ ),
148
+ (nodeOrLeaf) => {
149
+ if (p > size(path) - 2) {
150
+ if (pruneLeaf?.(nodeOrLeaf)) {
151
+ mapSet(node, path[p]);
152
+ }
153
+ return nodeOrLeaf;
154
+ }
155
+ const leaf = visitTree(nodeOrLeaf, path, ensureLeaf, pruneLeaf, p + 1);
156
+ if (collIsEmpty(nodeOrLeaf)) {
157
+ mapSet(node, path[p]);
158
+ }
159
+ return leaf;
160
+ },
161
+ );
162
+
163
+ const setNew = (entryOrEntries) =>
164
+ new Set(
165
+ isArray(entryOrEntries) || isUndefined(entryOrEntries)
166
+ ? entryOrEntries
167
+ : [entryOrEntries],
168
+ );
169
+ const setAdd = (set, value) => set?.add(value);
170
+
171
+ const COLUMN_NAME = 'ColumnName';
172
+ const STORE = 'store';
173
+ const JSON$1 = 'json';
174
+ const STORE_TABLE_NAME = STORE + 'TableName';
175
+ const STORE_ID_COLUMN_NAME = STORE + 'Id' + COLUMN_NAME;
176
+ const STORE_COLUMN_NAME = STORE + COLUMN_NAME;
177
+ const AUTO_LOAD_INTERVAL_SECONDS = 'autoLoadIntervalSeconds';
178
+ const ROW_ID_COLUMN_NAME = 'rowId' + COLUMN_NAME;
179
+ const TABLE_ID = 'tableId';
180
+ const TABLE_NAME = 'tableName';
181
+ const DELETE_EMPTY_COLUMNS = 'deleteEmptyColumns';
182
+ const DELETE_EMPTY_TABLE = 'deleteEmptyTable';
183
+ const CONDITION = 'condition';
184
+ const DEFAULT_CONFIG = {
185
+ mode: JSON$1,
186
+ [AUTO_LOAD_INTERVAL_SECONDS]: 1,
187
+ };
188
+ const DEFAULT_TABULAR_VALUES_CONFIG = {
189
+ load: 0,
190
+ save: 0,
191
+ [TABLE_NAME]: TINYBASE + '_values',
192
+ };
193
+ const getDefaultedConfig = (configOrStoreTableName) =>
194
+ objMerge(
195
+ DEFAULT_CONFIG,
196
+ isString(configOrStoreTableName)
197
+ ? {[STORE_TABLE_NAME]: configOrStoreTableName}
198
+ : (configOrStoreTableName ?? {}),
199
+ );
200
+ const getDefaultedTabularConfigMap = (
201
+ configsObj,
202
+ defaultObj,
203
+ tableField,
204
+ exclude,
205
+ then,
206
+ ) => {
207
+ const configMap = mapNew();
208
+ objMap(configsObj, (configObj, id) => {
209
+ const defaultedConfig = slice(
210
+ objValues(
211
+ objMerge(
212
+ defaultObj,
213
+ isString(configObj) ? {[tableField]: configObj} : configObj,
214
+ ),
215
+ ),
216
+ 0,
217
+ objSize(defaultObj),
218
+ );
219
+ if (!isUndefined(defaultedConfig[0]) && !exclude(id, defaultedConfig[0])) {
220
+ then(id, defaultedConfig[0]);
221
+ mapSet(configMap, id, defaultedConfig);
222
+ }
223
+ });
224
+ return configMap;
225
+ };
226
+ const getConfigStructures = (configOrStoreTableName) => {
227
+ const config = getDefaultedConfig(configOrStoreTableName);
228
+ const autoLoadIntervalSeconds = config[AUTO_LOAD_INTERVAL_SECONDS];
229
+ if (config.mode == JSON$1) {
230
+ const storeTableName = config[STORE_TABLE_NAME] ?? TINYBASE;
231
+ return [
232
+ 1,
233
+ autoLoadIntervalSeconds,
234
+ [
235
+ storeTableName,
236
+ config[STORE_ID_COLUMN_NAME] ?? DEFAULT_ROW_ID_COLUMN_NAME,
237
+ config[STORE_COLUMN_NAME] ?? STORE,
238
+ ],
239
+ setNew(storeTableName),
240
+ ];
241
+ }
242
+ const {tables: {load = {}, save = {}} = {}, values = {}} = config;
243
+ const valuesConfig = slice(
244
+ objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
245
+ 0,
246
+ objSize(DEFAULT_TABULAR_VALUES_CONFIG),
247
+ );
248
+ const valuesTable = valuesConfig[2];
249
+ const managedTableNames = setNew(valuesTable);
250
+ const excludedTableNames = setNew(valuesTable);
251
+ const tablesLoadConfig = getDefaultedTabularConfigMap(
252
+ load,
253
+ {
254
+ [TABLE_ID]: null,
255
+ [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
256
+ [CONDITION]: TRUE,
257
+ },
258
+ TABLE_ID,
259
+ (tableName) => collHas(excludedTableNames, tableName),
260
+ (tableName) => setAdd(managedTableNames, tableName),
261
+ );
262
+ const tablesSaveConfig = getDefaultedTabularConfigMap(
263
+ save,
264
+ {
265
+ [TABLE_NAME]: null,
266
+ [ROW_ID_COLUMN_NAME]: DEFAULT_ROW_ID_COLUMN_NAME,
267
+ [DELETE_EMPTY_COLUMNS]: 0,
268
+ [DELETE_EMPTY_TABLE]: 0,
269
+ [CONDITION]: null,
270
+ },
271
+ TABLE_NAME,
272
+ (_, tableName) => collHas(excludedTableNames, tableName),
273
+ (_, tableName) => setAdd(managedTableNames, tableName),
274
+ );
275
+ mapForEach(
276
+ tablesSaveConfig,
277
+ (_, tableSaveConfig) =>
278
+ (tableSaveConfig[4] ??=
279
+ mapGet(tablesLoadConfig, tableSaveConfig[0])?.[2] ?? TRUE),
280
+ );
281
+ return [
282
+ 0,
283
+ autoLoadIntervalSeconds,
284
+ [tablesLoadConfig, tablesSaveConfig, valuesConfig],
285
+ managedTableNames,
286
+ ];
287
+ };
288
+
289
+ const jsonString = JSON.stringify;
290
+ const jsonParse = JSON.parse;
291
+ const jsonStringWithUndefined = (obj) =>
292
+ jsonString(obj, (_key, value) => (value === void 0 ? UNDEFINED : value));
293
+ const jsonParseWithUndefined = (str) =>
294
+ jsonParse(str, (_key, value) => (value === UNDEFINED ? void 0 : value));
295
+
296
+ const INTEGER = /^\d+$/;
297
+ const getPoolFunctions = () => {
298
+ const pool = [];
299
+ let nextId = 0;
300
+ return [
301
+ (reuse) => (reuse ? arrayShift(pool) : null) ?? EMPTY_STRING + nextId++,
302
+ (id) => {
303
+ if (test(INTEGER, id) && size(pool) < 1e3) {
304
+ arrayPush(pool, id);
305
+ }
306
+ },
307
+ ];
308
+ };
309
+
310
+ const getWildcardedLeaves = (deepIdSet, path = [EMPTY_STRING]) => {
311
+ const leaves = [];
312
+ const deep = (node, p) =>
313
+ p == size(path)
314
+ ? arrayPush(leaves, node)
315
+ : path[p] === null
316
+ ? collForEach(node, (node2) => deep(node2, p + 1))
317
+ : arrayForEach([path[p], null], (id) => deep(mapGet(node, id), p + 1));
318
+ deep(deepIdSet, 0);
319
+ return leaves;
320
+ };
321
+ const getListenerFunctions = (getThing) => {
322
+ let thing;
323
+ const [getId, releaseId] = getPoolFunctions();
324
+ const allListeners = mapNew();
325
+ const addListener = (
326
+ listener,
327
+ idSetNode,
328
+ path,
329
+ pathGetters = [],
330
+ extraArgsGetter = () => [],
331
+ ) => {
332
+ thing ??= getThing();
333
+ const id = getId(1);
334
+ mapSet(allListeners, id, [
335
+ listener,
336
+ idSetNode,
337
+ path,
338
+ pathGetters,
339
+ extraArgsGetter,
340
+ ]);
341
+ setAdd(visitTree(idSetNode, path ?? [EMPTY_STRING], setNew), id);
342
+ return id;
343
+ };
344
+ const callListeners = (idSetNode, ids, ...extraArgs) =>
345
+ arrayForEach(getWildcardedLeaves(idSetNode, ids), (set) =>
346
+ collForEach(set, (id) =>
347
+ mapGet(allListeners, id)[0](thing, ...(ids ?? []), ...extraArgs),
348
+ ),
349
+ );
350
+ const delListener = (id) =>
351
+ ifNotUndefined(mapGet(allListeners, id), ([, idSetNode, idOrNulls]) => {
352
+ visitTree(idSetNode, idOrNulls ?? [EMPTY_STRING], void 0, (idSet) => {
353
+ collDel(idSet, id);
354
+ return collIsEmpty(idSet) ? 1 : 0;
355
+ });
356
+ mapSet(allListeners, id);
357
+ releaseId(id);
358
+ return idOrNulls;
359
+ });
360
+ const callListener = (id) =>
361
+ ifNotUndefined(
362
+ mapGet(allListeners, id),
363
+ ([listener, , path = [], pathGetters, extraArgsGetter]) => {
364
+ const callWithIds = (...ids) => {
365
+ const index = size(ids);
366
+ if (index == size(path)) {
367
+ listener(thing, ...ids, ...extraArgsGetter(ids));
368
+ } else if (isUndefined(path[index])) {
369
+ arrayForEach(pathGetters[index]?.(...ids) ?? [], (id2) =>
370
+ callWithIds(...ids, id2),
371
+ );
372
+ } else {
373
+ callWithIds(...ids, path[index]);
374
+ }
375
+ };
376
+ callWithIds();
377
+ },
378
+ );
379
+ return [addListener, callListeners, delListener, callListener];
380
+ };
381
+
382
+ const scheduleRunning = mapNew();
383
+ const scheduleActions = mapNew();
384
+ const getStoreFunctions = (
385
+ persist = 1 /* StoreOnly */,
386
+ store,
387
+ isSynchronizer,
388
+ ) =>
389
+ persist != 1 /* StoreOnly */ && store.isMergeable()
390
+ ? [
391
+ 1,
392
+ store.getMergeableContent,
393
+ () => store.getTransactionMergeableChanges(!isSynchronizer),
394
+ ([[changedTables], [changedValues]]) =>
395
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
396
+ store.setDefaultContent,
397
+ ]
398
+ : persist != 2 /* MergeableStoreOnly */
399
+ ? [
400
+ 0,
401
+ store.getContent,
402
+ store.getTransactionChanges,
403
+ ([changedTables, changedValues]) =>
404
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
405
+ store.setContent,
406
+ ]
407
+ : errorNew('Store type not supported by this Persister');
408
+ const createCustomPersister = (
409
+ store,
410
+ getPersisted,
411
+ setPersisted,
412
+ addPersisterListener,
413
+ delPersisterListener,
414
+ onIgnoredError,
415
+ persist,
416
+ extra = {},
417
+ isSynchronizer = 0,
418
+ scheduleId = [],
419
+ ) => {
420
+ let status = 0; /* Idle */
421
+ let loads = 0;
422
+ let saves = 0;
423
+ let action;
424
+ let autoLoadHandle;
425
+ let autoSaveListenerId;
426
+ mapEnsure(scheduleRunning, scheduleId, () => 0);
427
+ mapEnsure(scheduleActions, scheduleId, () => []);
428
+ const statusListeners = mapNew();
429
+ const [
430
+ isMergeableStore,
431
+ getContent,
432
+ getChanges,
433
+ hasChanges,
434
+ setDefaultContent,
435
+ ] = getStoreFunctions(persist, store, isSynchronizer);
436
+ const [addListener, callListeners, delListenerImpl] = getListenerFunctions(
437
+ () => persister,
438
+ );
439
+ const setStatus = (newStatus) => {
440
+ if (newStatus != status) {
441
+ status = newStatus;
442
+ callListeners(statusListeners, void 0, status);
443
+ }
444
+ };
445
+ const run = async () => {
446
+ /* istanbul ignore else */
447
+ if (!mapGet(scheduleRunning, scheduleId)) {
448
+ mapSet(scheduleRunning, scheduleId, 1);
449
+ while (
450
+ !isUndefined((action = arrayShift(mapGet(scheduleActions, scheduleId))))
451
+ ) {
452
+ await tryCatch(action, onIgnoredError);
453
+ }
454
+ mapSet(scheduleRunning, scheduleId, 0);
455
+ }
456
+ };
457
+ const setContentOrChanges = (contentOrChanges) => {
458
+ (isMergeableStore && isArray(contentOrChanges?.[0])
459
+ ? contentOrChanges?.[2] === 1
460
+ ? store.applyMergeableChanges
461
+ : store.setMergeableContent
462
+ : contentOrChanges?.[2] === 1
463
+ ? store.applyChanges
464
+ : store.setContent)(contentOrChanges);
465
+ };
466
+ const load = async (initialContent) => {
467
+ /* istanbul ignore else */
468
+ if (status != 2 /* Saving */) {
469
+ setStatus(1 /* Loading */);
470
+ loads++;
471
+ await schedule(async () => {
472
+ await tryCatch(
473
+ async () => {
474
+ const content = await getPersisted();
475
+ if (isArray(content)) {
476
+ setContentOrChanges(content);
477
+ } else if (initialContent) {
478
+ setDefaultContent(initialContent);
479
+ } else {
480
+ errorNew(`Content is not an array: ${content}`);
481
+ }
482
+ },
483
+ () => {
484
+ if (initialContent) {
485
+ setDefaultContent(initialContent);
486
+ }
487
+ },
488
+ );
489
+ setStatus(0 /* Idle */);
490
+ });
491
+ }
492
+ return persister;
493
+ };
494
+ const startAutoLoad = async (initialContent) => {
495
+ stopAutoLoad();
496
+ await load(initialContent);
497
+ await tryCatch(
498
+ async () =>
499
+ (autoLoadHandle = await addPersisterListener(
500
+ async (content, changes) => {
501
+ if (changes || content) {
502
+ /* istanbul ignore else */
503
+ if (status != 2 /* Saving */) {
504
+ setStatus(1 /* Loading */);
505
+ loads++;
506
+ setContentOrChanges(changes ?? content);
507
+ setStatus(0 /* Idle */);
508
+ }
509
+ } else {
510
+ await load();
511
+ }
512
+ },
513
+ )),
514
+ onIgnoredError,
515
+ );
516
+ return persister;
517
+ };
518
+ const stopAutoLoad = async () => {
519
+ if (autoLoadHandle) {
520
+ await tryCatch(
521
+ () => delPersisterListener(autoLoadHandle),
522
+ onIgnoredError,
523
+ );
524
+ autoLoadHandle = void 0;
525
+ }
526
+ return persister;
527
+ };
528
+ const isAutoLoading = () => !isUndefined(autoLoadHandle);
529
+ const save = async (changes) => {
530
+ /* istanbul ignore else */
531
+ if (status != 1 /* Loading */) {
532
+ setStatus(2 /* Saving */);
533
+ saves++;
534
+ await schedule(async () => {
535
+ await tryCatch(() => setPersisted(getContent, changes), onIgnoredError);
536
+ setStatus(0 /* Idle */);
537
+ });
538
+ }
539
+ return persister;
540
+ };
541
+ const startAutoSave = async () => {
542
+ stopAutoSave();
543
+ await save();
544
+ autoSaveListenerId = store.addDidFinishTransactionListener(() => {
545
+ const changes = getChanges();
546
+ if (hasChanges(changes)) {
547
+ save(changes);
548
+ }
549
+ });
550
+ return persister;
551
+ };
552
+ const stopAutoSave = async () => {
553
+ if (autoSaveListenerId) {
554
+ store.delListener(autoSaveListenerId);
555
+ autoSaveListenerId = void 0;
556
+ }
557
+ return persister;
558
+ };
559
+ const isAutoSaving = () => !isUndefined(autoSaveListenerId);
560
+ const getStatus = () => status;
561
+ const addStatusListener = (listener) =>
562
+ addListener(listener, statusListeners);
563
+ const delListener = (listenerId) => {
564
+ delListenerImpl(listenerId);
565
+ return store;
566
+ };
567
+ const schedule = async (...actions) => {
568
+ arrayPush(mapGet(scheduleActions, scheduleId), ...actions);
569
+ await run();
570
+ return persister;
571
+ };
572
+ const getStore = () => store;
573
+ const destroy = async () => {
574
+ arrayClear(mapGet(scheduleActions, scheduleId));
575
+ await persister.stopAutoLoad();
576
+ return await persister.stopAutoSave();
577
+ };
578
+ const getStats = () => ({loads, saves});
579
+ const persister = {
580
+ load,
581
+ startAutoLoad,
582
+ stopAutoLoad,
583
+ isAutoLoading,
584
+ save,
585
+ startAutoSave,
586
+ stopAutoSave,
587
+ isAutoSaving,
588
+ getStatus,
589
+ addStatusListener,
590
+ delListener,
591
+ schedule,
592
+ getStore,
593
+ destroy,
594
+ getStats,
595
+ ...extra,
596
+ };
597
+ return objFreeze(persister);
598
+ };
599
+
600
+ const getCommandFunctions = (
601
+ databaseExecuteCommand,
602
+ managedTableNames,
603
+ querySchema,
604
+ onIgnoredError,
605
+ columnType,
606
+ upsert = defaultUpsert,
607
+ encode,
608
+ decode,
609
+ ) => {
610
+ const schemaMap = mapNew();
611
+ const canSelect = (tableName, rowIdColumnName) =>
612
+ collHas(mapGet(schemaMap, tableName), rowIdColumnName);
613
+ const refreshSchema = async () => {
614
+ collClear(schemaMap);
615
+ arrayMap(
616
+ await querySchema(databaseExecuteCommand, managedTableNames),
617
+ ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
618
+ );
619
+ };
620
+ const loadTable = async (tableName, rowIdColumnName, condition) =>
621
+ canSelect(tableName, rowIdColumnName)
622
+ ? objNew(
623
+ arrayFilter(
624
+ arrayMap(
625
+ await databaseExecuteCommand(
626
+ SELECT_STAR_FROM +
627
+ escapeId(tableName) +
628
+ getWhereCondition(tableName, condition),
629
+ ),
630
+ (row) => [
631
+ row[rowIdColumnName],
632
+ decode
633
+ ? objMap(objDel(row, rowIdColumnName), decode)
634
+ : objDel(row, rowIdColumnName),
635
+ ],
636
+ ),
637
+ ([rowId, row]) => !isUndefined(rowId) && !objIsEmpty(row),
638
+ ),
639
+ )
640
+ : {};
641
+ const saveTable = async (
642
+ tableName,
643
+ rowIdColumnName,
644
+ content,
645
+ deleteEmptyColumns,
646
+ deleteEmptyTable,
647
+ partial = false,
648
+ condition = TRUE,
649
+ ) => {
650
+ const settingColumnNameSet = setNew();
651
+ objMap(content ?? {}, (contentRow) =>
652
+ arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
653
+ setAdd(settingColumnNameSet, cellOrValueId),
654
+ ),
655
+ );
656
+ const settingColumnNames = collValues(settingColumnNameSet);
657
+ if (
658
+ !partial &&
659
+ deleteEmptyTable &&
660
+ condition == TRUE &&
661
+ arrayIsEmpty(settingColumnNames) &&
662
+ collHas(schemaMap, tableName)
663
+ ) {
664
+ await databaseExecuteCommand('DROP ' + TABLE + escapeId(tableName));
665
+ mapSet(schemaMap, tableName);
666
+ return;
667
+ }
668
+ const currentColumnNames = mapGet(schemaMap, tableName);
669
+ const unaccountedColumnNames = setNew(collValues(currentColumnNames));
670
+ if (!arrayIsEmpty(settingColumnNames)) {
671
+ if (!collHas(schemaMap, tableName)) {
672
+ await databaseExecuteCommand(
673
+ CREATE_TABLE +
674
+ escapeId(tableName) +
675
+ `(${escapeId(rowIdColumnName)}${columnType} PRIMARY KEY${arrayJoin(
676
+ arrayMap(
677
+ settingColumnNames,
678
+ (settingColumnName) =>
679
+ COMMA + escapeId(settingColumnName) + columnType,
680
+ ),
681
+ )});`,
682
+ );
683
+ mapSet(
684
+ schemaMap,
685
+ tableName,
686
+ setNew([rowIdColumnName, ...settingColumnNames]),
687
+ );
688
+ } else {
689
+ await promiseAll(
690
+ arrayMap(
691
+ [rowIdColumnName, ...settingColumnNames],
692
+ async (settingColumnName, index) => {
693
+ if (!collDel(unaccountedColumnNames, settingColumnName)) {
694
+ await databaseExecuteCommand(
695
+ ALTER_TABLE +
696
+ escapeId(tableName) +
697
+ 'ADD' +
698
+ escapeId(settingColumnName) +
699
+ columnType,
700
+ );
701
+ if (index == 0) {
702
+ await databaseExecuteCommand(
703
+ 'CREATE UNIQUE INDEX pk ON ' +
704
+ escapeId(tableName) +
705
+ `(${escapeId(rowIdColumnName)})`,
706
+ );
707
+ }
708
+ setAdd(currentColumnNames, settingColumnName);
709
+ }
710
+ },
711
+ ),
712
+ );
713
+ }
714
+ }
715
+ await promiseAll([
716
+ ...(!partial && deleteEmptyColumns
717
+ ? arrayMap(
718
+ collValues(unaccountedColumnNames),
719
+ async (unaccountedColumnName) => {
720
+ if (unaccountedColumnName != rowIdColumnName) {
721
+ await databaseExecuteCommand(
722
+ ALTER_TABLE +
723
+ escapeId(tableName) +
724
+ 'DROP' +
725
+ escapeId(unaccountedColumnName),
726
+ );
727
+ collDel(currentColumnNames, unaccountedColumnName);
728
+ }
729
+ },
730
+ )
731
+ : []),
732
+ ]);
733
+ if (partial) {
734
+ if (isUndefined(content)) {
735
+ await databaseExecuteCommand(
736
+ DELETE_FROM +
737
+ escapeId(tableName) +
738
+ getWhereCondition(tableName, condition),
739
+ );
740
+ } else {
741
+ await promiseAll(
742
+ objToArray(content, async (row, rowId) => {
743
+ if (isUndefined(row)) {
744
+ await databaseExecuteCommand(
745
+ DELETE_FROM +
746
+ escapeId(tableName) +
747
+ getWhereCondition(tableName, condition) +
748
+ `AND(${escapeId(rowIdColumnName)}=$1)`,
749
+ [rowId],
750
+ );
751
+ } else if (!arrayIsEmpty(settingColumnNames)) {
752
+ await upsert(
753
+ databaseExecuteCommand,
754
+ tableName,
755
+ rowIdColumnName,
756
+ objIds(row),
757
+ {
758
+ [rowId]: encode
759
+ ? arrayMap(objValues(row), encode)
760
+ : objValues(row),
761
+ },
762
+ currentColumnNames,
763
+ );
764
+ }
765
+ }),
766
+ );
767
+ }
768
+ } else {
769
+ if (!arrayIsEmpty(settingColumnNames)) {
770
+ const changingColumnNames = arrayFilter(
771
+ collValues(mapGet(schemaMap, tableName)),
772
+ (changingColumnName) => changingColumnName != rowIdColumnName,
773
+ );
774
+ const rows = {};
775
+ const deleteRowIds = [];
776
+ objMap(content ?? {}, (row, rowId) => {
777
+ rows[rowId] = arrayMap(changingColumnNames, (cellId) =>
778
+ encode ? encode(row?.[cellId]) : row?.[cellId],
779
+ );
780
+ arrayPush(deleteRowIds, rowId);
781
+ });
782
+ await upsert(
783
+ databaseExecuteCommand,
784
+ tableName,
785
+ rowIdColumnName,
786
+ changingColumnNames,
787
+ rows,
788
+ );
789
+ await databaseExecuteCommand(
790
+ DELETE_FROM +
791
+ escapeId(tableName) +
792
+ getWhereCondition(tableName, condition) + // eslint-disable-next-line max-len
793
+ `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
794
+ deleteRowIds,
795
+ );
796
+ } else if (collHas(schemaMap, tableName)) {
797
+ await databaseExecuteCommand(
798
+ DELETE_FROM +
799
+ escapeId(tableName) +
800
+ getWhereCondition(tableName, condition),
801
+ );
802
+ }
803
+ }
804
+ };
805
+ const transaction = async (actions) => {
806
+ let result;
807
+ await databaseExecuteCommand('BEGIN');
808
+ await tryCatch(async () => (result = await actions()), onIgnoredError);
809
+ await databaseExecuteCommand('END');
810
+ return result;
811
+ };
812
+ return [refreshSchema, loadTable, saveTable, transaction];
813
+ };
814
+ const defaultUpsert = async (
815
+ executeCommand,
816
+ tableName,
817
+ rowIdColumnName,
818
+ changingColumnNames,
819
+ rows,
820
+ ) => {
821
+ const offset = [1];
822
+ await executeCommand(
823
+ INSERT +
824
+ ' INTO' +
825
+ escapeId(tableName) +
826
+ '(' +
827
+ escapeColumnNames(rowIdColumnName, ...changingColumnNames) +
828
+ ')VALUES' +
829
+ arrayJoin(
830
+ objToArray(
831
+ rows,
832
+ (row) =>
833
+ '($' + offset[0]++ + ',' + getPlaceholders(row, offset) + ')',
834
+ ),
835
+ COMMA,
836
+ ) +
837
+ 'ON CONFLICT(' +
838
+ escapeId(rowIdColumnName) +
839
+ `)DO ${UPDATE} SET` +
840
+ arrayJoin(
841
+ arrayMap(
842
+ changingColumnNames,
843
+ (columnName) =>
844
+ escapeId(columnName) + '=excluded.' + escapeId(columnName),
845
+ ),
846
+ COMMA,
847
+ ),
848
+ objToArray(rows, (row, id) => [
849
+ id,
850
+ ...arrayMap(row, (value) => value ?? null),
851
+ ]).flat(),
852
+ );
853
+ };
854
+
855
+ const createJsonPersister = (
856
+ store,
857
+ executeCommand,
858
+ addPersisterListener,
859
+ delPersisterListener,
860
+ onIgnoredError,
861
+ extraDestroy,
862
+ persist,
863
+ [storeTableName, storeIdColumnName, storeColumnName],
864
+ managedTableNames,
865
+ querySchema,
866
+ thing,
867
+ getThing,
868
+ columnType,
869
+ upsert,
870
+ ) => {
871
+ const [refreshSchema, loadTable, saveTable, transaction] =
872
+ getCommandFunctions(
873
+ executeCommand,
874
+ managedTableNames,
875
+ querySchema,
876
+ onIgnoredError,
877
+ columnType,
878
+ upsert,
879
+ );
880
+ const getPersisted = () =>
881
+ transaction(async () => {
882
+ await refreshSchema();
883
+ return jsonParseWithUndefined(
884
+ (await loadTable(storeTableName, storeIdColumnName))[SINGLE_ROW_ID]?.[
885
+ storeColumnName
886
+ ] ?? 'null',
887
+ );
888
+ });
889
+ const setPersisted = (getContent) =>
890
+ transaction(async () => {
891
+ await refreshSchema();
892
+ await saveTable(
893
+ storeTableName,
894
+ storeIdColumnName,
895
+ {
896
+ [SINGLE_ROW_ID]: {
897
+ [storeColumnName]: jsonStringWithUndefined(getContent() ?? null),
898
+ },
899
+ },
900
+ true,
901
+ true,
902
+ );
903
+ });
904
+ const destroy = async () => {
905
+ await persister.stopAutoLoad();
906
+ await persister.stopAutoSave();
907
+ extraDestroy();
908
+ return persister;
909
+ };
910
+ const persister = createCustomPersister(
911
+ store,
912
+ getPersisted,
913
+ setPersisted,
914
+ addPersisterListener,
915
+ delPersisterListener,
916
+ onIgnoredError,
917
+ persist,
918
+ {[getThing]: () => thing, destroy},
919
+ 0,
920
+ thing,
921
+ );
922
+ return persister;
923
+ };
924
+
925
+ const createTabularPersister = (
926
+ store,
927
+ executeCommand,
928
+ addPersisterListener,
929
+ delPersisterListener,
930
+ onIgnoredError,
931
+ extraDestroy,
932
+ persist,
933
+ [
934
+ tablesLoadConfig,
935
+ tablesSaveConfig,
936
+ [valuesLoad, valuesSave, valuesTableName],
937
+ ],
938
+ managedTableNames,
939
+ querySchema,
940
+ thing,
941
+ getThing,
942
+ columnType,
943
+ upsert,
944
+ encode,
945
+ decode,
946
+ ) => {
947
+ const [refreshSchema, loadTable, saveTable, transaction] =
948
+ getCommandFunctions(
949
+ executeCommand,
950
+ managedTableNames,
951
+ querySchema,
952
+ onIgnoredError,
953
+ columnType,
954
+ upsert,
955
+ encode,
956
+ decode,
957
+ );
958
+ const saveTables = (tables, partial) =>
959
+ promiseAll(
960
+ mapMap(
961
+ tablesSaveConfig,
962
+ async (
963
+ [
964
+ tableName,
965
+ rowIdColumnName,
966
+ deleteEmptyColumns,
967
+ deleteEmptyTable,
968
+ condition,
969
+ ],
970
+ tableId,
971
+ ) => {
972
+ if (!partial || objHas(tables, tableId)) {
973
+ await saveTable(
974
+ tableName,
975
+ rowIdColumnName,
976
+ tables[tableId],
977
+ deleteEmptyColumns,
978
+ deleteEmptyTable,
979
+ partial,
980
+ condition,
981
+ );
982
+ }
983
+ },
984
+ ),
985
+ );
986
+ const saveValues = async (values, partial) =>
987
+ valuesSave
988
+ ? await saveTable(
989
+ valuesTableName,
990
+ DEFAULT_ROW_ID_COLUMN_NAME,
991
+ {[SINGLE_ROW_ID]: values},
992
+ true,
993
+ true,
994
+ partial,
995
+ )
996
+ : null;
997
+ const loadTables = async () =>
998
+ objNew(
999
+ arrayFilter(
1000
+ await promiseAll(
1001
+ mapMap(
1002
+ tablesLoadConfig,
1003
+ async ([tableId, rowIdColumnName, condition], tableName) => [
1004
+ tableId,
1005
+ await loadTable(tableName, rowIdColumnName, condition),
1006
+ ],
1007
+ ),
1008
+ ),
1009
+ (pair) => !objIsEmpty(pair[1]),
1010
+ ),
1011
+ );
1012
+ const loadValues = async () =>
1013
+ valuesLoad
1014
+ ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1015
+ SINGLE_ROW_ID
1016
+ ]
1017
+ : {};
1018
+ const getPersisted = () =>
1019
+ transaction(async () => {
1020
+ await refreshSchema();
1021
+ const tables = await loadTables();
1022
+ const values = await loadValues();
1023
+ return !objIsEmpty(tables) || !isUndefined(values)
1024
+ ? [tables, values]
1025
+ : void 0;
1026
+ });
1027
+ const setPersisted = (getContent, changes) =>
1028
+ transaction(async () => {
1029
+ await refreshSchema();
1030
+ if (!isUndefined(changes)) {
1031
+ await saveTables(changes[0], true);
1032
+ await saveValues(changes[1], true);
1033
+ } else {
1034
+ const [tables, values] = getContent();
1035
+ await saveTables(tables);
1036
+ await saveValues(values);
1037
+ }
1038
+ });
1039
+ const destroy = async () => {
1040
+ await persister.stopAutoLoad();
1041
+ await persister.stopAutoSave();
1042
+ extraDestroy();
1043
+ return persister;
1044
+ };
1045
+ const persister = createCustomPersister(
1046
+ store,
1047
+ getPersisted,
1048
+ setPersisted,
1049
+ addPersisterListener,
1050
+ delPersisterListener,
1051
+ onIgnoredError,
1052
+ persist,
1053
+ {[getThing]: () => thing, destroy},
1054
+ 0,
1055
+ thing,
1056
+ );
1057
+ return persister;
1058
+ };
1059
+
1060
+ const createCustomSqlitePersister = (
1061
+ store,
1062
+ configOrStoreTableName,
1063
+ rawExecuteCommand,
1064
+ addChangeListener,
1065
+ delChangeListener,
1066
+ onSqlCommand,
1067
+ onIgnoredError,
1068
+ destroy,
1069
+ persist,
1070
+ thing,
1071
+ getThing = 'getDb',
1072
+ upsert,
1073
+ ) => {
1074
+ let dataVersion;
1075
+ let schemaVersion;
1076
+ let totalChanges;
1077
+ const executeCommand = getWrappedCommand(rawExecuteCommand, onSqlCommand);
1078
+ const [
1079
+ isJson,
1080
+ autoLoadIntervalSeconds,
1081
+ defaultedConfig,
1082
+ managedTableNamesSet,
1083
+ ] = getConfigStructures(configOrStoreTableName);
1084
+ const addPersisterListener = (listener) => {
1085
+ let interval;
1086
+ const startPolling = () =>
1087
+ (interval = startInterval(
1088
+ () =>
1089
+ tryCatch(async () => {
1090
+ const [{d, s, c}] = await executeCommand(
1091
+ SELECT + // eslint-disable-next-line max-len
1092
+ ` ${DATA_VERSION} d,${SCHEMA_VERSION} s,TOTAL_CHANGES() c FROM ${PRAGMA}${DATA_VERSION} JOIN ${PRAGMA}${SCHEMA_VERSION}`,
1093
+ );
1094
+ if (d != dataVersion || s != schemaVersion || c != totalChanges) {
1095
+ if (dataVersion != null) {
1096
+ listener();
1097
+ }
1098
+ dataVersion = d;
1099
+ schemaVersion = s;
1100
+ totalChanges = c;
1101
+ }
1102
+ }),
1103
+ autoLoadIntervalSeconds,
1104
+ ));
1105
+ const stopPolling = () => {
1106
+ dataVersion = schemaVersion = totalChanges = null;
1107
+ stopInterval(interval);
1108
+ };
1109
+ const listeningHandle = addChangeListener((tableName) => {
1110
+ if (managedTableNamesSet.has(tableName)) {
1111
+ stopPolling();
1112
+ listener();
1113
+ startPolling();
1114
+ }
1115
+ });
1116
+ startPolling();
1117
+ return () => {
1118
+ stopPolling();
1119
+ delChangeListener(listeningHandle);
1120
+ };
1121
+ };
1122
+ const delPersisterListener = (stopPollingAndDelUpdateListener) =>
1123
+ stopPollingAndDelUpdateListener();
1124
+ return (isJson ? createJsonPersister : createTabularPersister)(
1125
+ store,
1126
+ executeCommand,
1127
+ addPersisterListener,
1128
+ delPersisterListener,
1129
+ onIgnoredError,
1130
+ destroy,
1131
+ persist,
1132
+ defaultedConfig,
1133
+ collValues(managedTableNamesSet),
1134
+ async (executeCommand2, managedTableNames) =>
1135
+ await executeCommand2(
1136
+ SELECT + // eslint-disable-next-line max-len
1137
+ ` 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`,
1138
+ managedTableNames,
1139
+ ),
1140
+ thing,
1141
+ getThing,
1142
+ EMPTY_STRING,
1143
+ upsert,
1144
+ (cellOrValue) =>
1145
+ cellOrValue === true ? 1 : cellOrValue === false ? 0 : cellOrValue,
1146
+ void 0,
1147
+ );
1148
+ };
1149
+
1150
+ const createSqliteBunPersister = (
1151
+ store,
1152
+ db,
1153
+ configOrStoreTableName,
1154
+ onSqlCommand,
1155
+ onIgnoredError,
1156
+ ) =>
1157
+ createCustomSqlitePersister(
1158
+ store,
1159
+ configOrStoreTableName,
1160
+ async (sql, params = []) => db.query(sql).all(...params),
1161
+ () => noop,
1162
+ (unsubscribeFunction) => unsubscribeFunction(),
1163
+ onSqlCommand,
1164
+ onIgnoredError,
1165
+ noop,
1166
+ 3,
1167
+ // StoreOrMergeableStore,
1168
+ db,
1169
+ );
1170
+
1171
+ export {createSqliteBunPersister};