tinybase 8.0.0-beta.0 → 8.0.0-beta.1

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 (264) hide show
  1. package/@types/index.d.ts +1 -0
  2. package/@types/mergeable-store/with-schemas/index.d.ts +1 -1
  3. package/@types/middleware/index.d.ts +1064 -0
  4. package/@types/middleware/with-schemas/index.d.ts +1355 -0
  5. package/@types/omni/index.d.ts +1 -0
  6. package/@types/omni/with-schemas/index.d.ts +1 -0
  7. package/@types/store/index.d.ts +0 -1
  8. package/@types/with-schemas/index.d.ts +1 -0
  9. package/agents.md +33 -11
  10. package/checkpoints/index.js +20 -20
  11. package/checkpoints/with-schemas/index.js +20 -20
  12. package/common/index.js +3 -2
  13. package/common/with-schemas/index.js +3 -2
  14. package/index.js +574 -215
  15. package/indexes/index.js +13 -12
  16. package/indexes/with-schemas/index.js +13 -12
  17. package/mergeable-store/index.js +461 -197
  18. package/mergeable-store/with-schemas/index.js +461 -197
  19. package/metrics/index.js +13 -12
  20. package/metrics/with-schemas/index.js +13 -12
  21. package/middleware/index.js +130 -0
  22. package/middleware/with-schemas/index.js +130 -0
  23. package/min/checkpoints/index.js +1 -1
  24. package/min/checkpoints/index.js.gz +0 -0
  25. package/min/checkpoints/with-schemas/index.js +1 -1
  26. package/min/checkpoints/with-schemas/index.js.gz +0 -0
  27. package/min/common/index.js +1 -1
  28. package/min/common/index.js.gz +0 -0
  29. package/min/common/with-schemas/index.js +1 -1
  30. package/min/common/with-schemas/index.js.gz +0 -0
  31. package/min/index.js +1 -1
  32. package/min/index.js.gz +0 -0
  33. package/min/indexes/index.js +1 -1
  34. package/min/indexes/index.js.gz +0 -0
  35. package/min/indexes/with-schemas/index.js +1 -1
  36. package/min/indexes/with-schemas/index.js.gz +0 -0
  37. package/min/mergeable-store/index.js +1 -1
  38. package/min/mergeable-store/index.js.gz +0 -0
  39. package/min/mergeable-store/with-schemas/index.js +1 -1
  40. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  41. package/min/metrics/index.js +1 -1
  42. package/min/metrics/index.js.gz +0 -0
  43. package/min/metrics/with-schemas/index.js +1 -1
  44. package/min/metrics/with-schemas/index.js.gz +0 -0
  45. package/min/middleware/index.js +1 -0
  46. package/min/middleware/index.js.gz +0 -0
  47. package/min/middleware/with-schemas/index.js +1 -0
  48. package/min/middleware/with-schemas/index.js.gz +0 -0
  49. package/min/omni/index.js +1 -1
  50. package/min/omni/index.js.gz +0 -0
  51. package/min/omni/with-schemas/index.js +1 -1
  52. package/min/omni/with-schemas/index.js.gz +0 -0
  53. package/min/persisters/index.js +1 -1
  54. package/min/persisters/index.js.gz +0 -0
  55. package/min/persisters/persister-automerge/index.js +1 -1
  56. package/min/persisters/persister-automerge/index.js.gz +0 -0
  57. package/min/persisters/persister-automerge/with-schemas/index.js +1 -1
  58. package/min/persisters/persister-automerge/with-schemas/index.js.gz +0 -0
  59. package/min/persisters/persister-browser/index.js +1 -1
  60. package/min/persisters/persister-browser/index.js.gz +0 -0
  61. package/min/persisters/persister-browser/with-schemas/index.js +1 -1
  62. package/min/persisters/persister-browser/with-schemas/index.js.gz +0 -0
  63. package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
  64. package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
  65. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
  66. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
  67. package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
  68. package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
  69. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
  70. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
  71. package/min/persisters/persister-durable-object-storage/index.js +1 -1
  72. package/min/persisters/persister-durable-object-storage/index.js.gz +0 -0
  73. package/min/persisters/persister-durable-object-storage/with-schemas/index.js +1 -1
  74. package/min/persisters/persister-durable-object-storage/with-schemas/index.js.gz +0 -0
  75. package/min/persisters/persister-electric-sql/index.js +1 -1
  76. package/min/persisters/persister-electric-sql/index.js.gz +0 -0
  77. package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
  78. package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
  79. package/min/persisters/persister-expo-sqlite/index.js +1 -1
  80. package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
  81. package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
  82. package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
  83. package/min/persisters/persister-file/index.js +1 -1
  84. package/min/persisters/persister-file/index.js.gz +0 -0
  85. package/min/persisters/persister-file/with-schemas/index.js +1 -1
  86. package/min/persisters/persister-file/with-schemas/index.js.gz +0 -0
  87. package/min/persisters/persister-indexed-db/index.js +1 -1
  88. package/min/persisters/persister-indexed-db/index.js.gz +0 -0
  89. package/min/persisters/persister-indexed-db/with-schemas/index.js +1 -1
  90. package/min/persisters/persister-indexed-db/with-schemas/index.js.gz +0 -0
  91. package/min/persisters/persister-libsql/index.js +1 -1
  92. package/min/persisters/persister-libsql/index.js.gz +0 -0
  93. package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
  94. package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
  95. package/min/persisters/persister-partykit-client/index.js +1 -1
  96. package/min/persisters/persister-partykit-client/index.js.gz +0 -0
  97. package/min/persisters/persister-partykit-client/with-schemas/index.js +1 -1
  98. package/min/persisters/persister-partykit-client/with-schemas/index.js.gz +0 -0
  99. package/min/persisters/persister-partykit-server/index.js +1 -1
  100. package/min/persisters/persister-partykit-server/index.js.gz +0 -0
  101. package/min/persisters/persister-partykit-server/with-schemas/index.js +1 -1
  102. package/min/persisters/persister-partykit-server/with-schemas/index.js.gz +0 -0
  103. package/min/persisters/persister-pglite/index.js +1 -1
  104. package/min/persisters/persister-pglite/index.js.gz +0 -0
  105. package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
  106. package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
  107. package/min/persisters/persister-postgres/index.js +1 -1
  108. package/min/persisters/persister-postgres/index.js.gz +0 -0
  109. package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
  110. package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
  111. package/min/persisters/persister-powersync/index.js +1 -1
  112. package/min/persisters/persister-powersync/index.js.gz +0 -0
  113. package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
  114. package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
  115. package/min/persisters/persister-react-native-mmkv/index.js +1 -1
  116. package/min/persisters/persister-react-native-mmkv/index.js.gz +0 -0
  117. package/min/persisters/persister-react-native-mmkv/with-schemas/index.js +1 -1
  118. package/min/persisters/persister-react-native-mmkv/with-schemas/index.js.gz +0 -0
  119. package/min/persisters/persister-react-native-sqlite/index.js +1 -1
  120. package/min/persisters/persister-react-native-sqlite/index.js.gz +0 -0
  121. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js +1 -1
  122. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js.gz +0 -0
  123. package/min/persisters/persister-remote/index.js +1 -1
  124. package/min/persisters/persister-remote/index.js.gz +0 -0
  125. package/min/persisters/persister-remote/with-schemas/index.js +1 -1
  126. package/min/persisters/persister-remote/with-schemas/index.js.gz +0 -0
  127. package/min/persisters/persister-sqlite-bun/index.js +1 -1
  128. package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
  129. package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
  130. package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
  131. package/min/persisters/persister-sqlite-wasm/index.js +1 -1
  132. package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
  133. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
  134. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
  135. package/min/persisters/persister-sqlite3/index.js +1 -1
  136. package/min/persisters/persister-sqlite3/index.js.gz +0 -0
  137. package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
  138. package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
  139. package/min/persisters/persister-yjs/index.js +1 -1
  140. package/min/persisters/persister-yjs/index.js.gz +0 -0
  141. package/min/persisters/persister-yjs/with-schemas/index.js +1 -1
  142. package/min/persisters/persister-yjs/with-schemas/index.js.gz +0 -0
  143. package/min/persisters/with-schemas/index.js +1 -1
  144. package/min/persisters/with-schemas/index.js.gz +0 -0
  145. package/min/queries/index.js +1 -1
  146. package/min/queries/index.js.gz +0 -0
  147. package/min/queries/with-schemas/index.js +1 -1
  148. package/min/queries/with-schemas/index.js.gz +0 -0
  149. package/min/relationships/index.js +1 -1
  150. package/min/relationships/index.js.gz +0 -0
  151. package/min/relationships/with-schemas/index.js +1 -1
  152. package/min/relationships/with-schemas/index.js.gz +0 -0
  153. package/min/store/index.js +1 -1
  154. package/min/store/index.js.gz +0 -0
  155. package/min/store/with-schemas/index.js +1 -1
  156. package/min/store/with-schemas/index.js.gz +0 -0
  157. package/min/synchronizers/index.js +1 -1
  158. package/min/synchronizers/index.js.gz +0 -0
  159. package/min/synchronizers/synchronizer-broadcast-channel/index.js +1 -1
  160. package/min/synchronizers/synchronizer-broadcast-channel/index.js.gz +0 -0
  161. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +1 -1
  162. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js.gz +0 -0
  163. package/min/synchronizers/synchronizer-local/index.js +1 -1
  164. package/min/synchronizers/synchronizer-local/index.js.gz +0 -0
  165. package/min/synchronizers/synchronizer-local/with-schemas/index.js +1 -1
  166. package/min/synchronizers/synchronizer-local/with-schemas/index.js.gz +0 -0
  167. package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
  168. package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
  169. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
  170. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
  171. package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
  172. package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
  173. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
  174. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
  175. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
  176. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
  177. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
  178. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
  179. package/min/synchronizers/synchronizer-ws-server-simple/index.js +1 -1
  180. package/min/synchronizers/synchronizer-ws-server-simple/index.js.gz +0 -0
  181. package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +1 -1
  182. package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js.gz +0 -0
  183. package/min/synchronizers/with-schemas/index.js +1 -1
  184. package/min/synchronizers/with-schemas/index.js.gz +0 -0
  185. package/min/ui-react-inspector/index.js +1 -1
  186. package/min/ui-react-inspector/index.js.gz +0 -0
  187. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  188. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  189. package/min/with-schemas/index.js +1 -1
  190. package/min/with-schemas/index.js.gz +0 -0
  191. package/omni/index.js +610 -232
  192. package/omni/with-schemas/index.js +610 -232
  193. package/package.json +55 -19
  194. package/persisters/index.js +29 -12
  195. package/persisters/persister-automerge/index.js +17 -9
  196. package/persisters/persister-automerge/with-schemas/index.js +17 -9
  197. package/persisters/persister-browser/index.js +34 -10
  198. package/persisters/persister-browser/with-schemas/index.js +34 -10
  199. package/persisters/persister-cr-sqlite-wasm/index.js +29 -12
  200. package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +29 -12
  201. package/persisters/persister-durable-object-sql-storage/index.js +29 -12
  202. package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +29 -12
  203. package/persisters/persister-durable-object-storage/index.js +24 -17
  204. package/persisters/persister-durable-object-storage/with-schemas/index.js +24 -17
  205. package/persisters/persister-electric-sql/index.js +29 -12
  206. package/persisters/persister-electric-sql/with-schemas/index.js +29 -12
  207. package/persisters/persister-expo-sqlite/index.js +29 -12
  208. package/persisters/persister-expo-sqlite/with-schemas/index.js +29 -12
  209. package/persisters/persister-file/index.js +34 -10
  210. package/persisters/persister-file/with-schemas/index.js +34 -10
  211. package/persisters/persister-indexed-db/index.js +17 -9
  212. package/persisters/persister-indexed-db/with-schemas/index.js +17 -9
  213. package/persisters/persister-libsql/index.js +29 -12
  214. package/persisters/persister-libsql/with-schemas/index.js +29 -12
  215. package/persisters/persister-partykit-client/index.js +44 -11
  216. package/persisters/persister-partykit-client/with-schemas/index.js +44 -11
  217. package/persisters/persister-partykit-server/index.js +39 -4
  218. package/persisters/persister-partykit-server/with-schemas/index.js +39 -4
  219. package/persisters/persister-pglite/index.js +29 -12
  220. package/persisters/persister-pglite/with-schemas/index.js +29 -12
  221. package/persisters/persister-postgres/index.js +29 -12
  222. package/persisters/persister-postgres/with-schemas/index.js +29 -12
  223. package/persisters/persister-powersync/index.js +29 -12
  224. package/persisters/persister-powersync/with-schemas/index.js +29 -12
  225. package/persisters/persister-react-native-mmkv/index.js +17 -9
  226. package/persisters/persister-react-native-mmkv/with-schemas/index.js +17 -9
  227. package/persisters/persister-react-native-sqlite/index.js +29 -12
  228. package/persisters/persister-react-native-sqlite/with-schemas/index.js +29 -12
  229. package/persisters/persister-remote/index.js +17 -9
  230. package/persisters/persister-remote/with-schemas/index.js +17 -9
  231. package/persisters/persister-sqlite-bun/index.js +29 -12
  232. package/persisters/persister-sqlite-bun/with-schemas/index.js +29 -12
  233. package/persisters/persister-sqlite-wasm/index.js +29 -12
  234. package/persisters/persister-sqlite-wasm/with-schemas/index.js +29 -12
  235. package/persisters/persister-sqlite3/index.js +29 -12
  236. package/persisters/persister-sqlite3/with-schemas/index.js +29 -12
  237. package/persisters/persister-yjs/index.js +19 -11
  238. package/persisters/persister-yjs/with-schemas/index.js +19 -11
  239. package/persisters/with-schemas/index.js +29 -12
  240. package/queries/index.js +16 -20
  241. package/queries/with-schemas/index.js +16 -20
  242. package/readme.md +21 -13
  243. package/relationships/index.js +13 -12
  244. package/relationships/with-schemas/index.js +13 -12
  245. package/releases.md +41 -41
  246. package/store/index.js +442 -192
  247. package/store/with-schemas/index.js +442 -192
  248. package/synchronizers/index.js +17 -9
  249. package/synchronizers/synchronizer-broadcast-channel/index.js +17 -9
  250. package/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +17 -9
  251. package/synchronizers/synchronizer-local/index.js +19 -11
  252. package/synchronizers/synchronizer-local/with-schemas/index.js +19 -11
  253. package/synchronizers/synchronizer-ws-client/index.js +31 -10
  254. package/synchronizers/synchronizer-ws-client/with-schemas/index.js +31 -10
  255. package/synchronizers/synchronizer-ws-server/index.js +34 -13
  256. package/synchronizers/synchronizer-ws-server/with-schemas/index.js +34 -13
  257. package/synchronizers/synchronizer-ws-server-durable-object/index.js +31 -10
  258. package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +31 -10
  259. package/synchronizers/synchronizer-ws-server-simple/index.js +11 -10
  260. package/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +11 -10
  261. package/synchronizers/with-schemas/index.js +17 -9
  262. package/ui-react-inspector/index.js +438 -193
  263. package/ui-react-inspector/with-schemas/index.js +438 -193
  264. package/with-schemas/index.js +574 -215
@@ -64,6 +64,7 @@ const size = (arrayOrString) => arrayOrString.length;
64
64
  const test = (regex, subject) => regex.test(subject);
65
65
  const getUndefined = () => void 0;
66
66
  const noop = () => {};
67
+ const structuredClone = GLOBAL.structuredClone;
67
68
  const tryCatch = async (action, then1, then2) => {
68
69
  try {
69
70
  return await action();
@@ -99,25 +100,6 @@ const arrayPop = (array) => array.pop();
99
100
  const arrayUnshift = (array, ...values) => array.unshift(...values);
100
101
  const arrayShift = (array) => array.shift();
101
102
 
102
- const getCellOrValueType = (cellOrValue) => {
103
- if (isNull(cellOrValue)) {
104
- return NULL;
105
- }
106
- const type = getTypeOf(cellOrValue);
107
- return isTypeStringOrBoolean(type) ||
108
- (type == NUMBER && isFiniteNumber(cellOrValue))
109
- ? type
110
- : void 0;
111
- };
112
- const isCellOrValueOrUndefined = (cellOrValue) =>
113
- isUndefined(cellOrValue) || !isUndefined(getCellOrValueType(cellOrValue));
114
- const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
115
- isUndefined(cell)
116
- ? store.delCell(tableId, rowId, cellId, true)
117
- : store.setCell(tableId, rowId, cellId, cell);
118
- const setOrDelValue = (store, valueId, value) =>
119
- isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
120
-
121
103
  const collSizeN = (collSizer) => (coll) =>
122
104
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
123
105
  const collSize = (coll) => coll?.size ?? 0;
@@ -208,31 +190,32 @@ const objValidate = (obj, validateChild, onInvalidObj, emptyIsValid = 0) => {
208
190
  return emptyIsValid ? true : !objIsEmpty(obj);
209
191
  };
210
192
 
211
- const mapNew = (entries) => new Map(entries);
212
- const mapKeys = (map) => [...(map?.keys() ?? [])];
213
- const mapGet = (map, key) => map?.get(key);
214
- const mapForEach = (map, cb) =>
215
- collForEach(map, (value, key) => cb(key, value));
193
+ const map = Map;
194
+ const mapNew = (entries) => new map(entries);
195
+ const mapKeys = (map2) => [...(map2?.keys() ?? [])];
196
+ const mapGet = (map2, key) => map2?.get(key);
197
+ const mapForEach = (map2, cb) =>
198
+ collForEach(map2, (value, key) => cb(key, value));
216
199
  const mapMap = (coll, cb) =>
217
200
  arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
218
- const mapSet = (map, key, value) =>
219
- isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
220
- const mapEnsure = (map, key, getDefaultValue, hadExistingValue) => {
221
- if (!collHas(map, key)) {
222
- mapSet(map, key, getDefaultValue());
201
+ const mapSet = (map2, key, value) =>
202
+ isUndefined(value) ? (collDel(map2, key), map2) : map2?.set(key, value);
203
+ const mapEnsure = (map2, key, getDefaultValue, hadExistingValue) => {
204
+ if (!collHas(map2, key)) {
205
+ mapSet(map2, key, getDefaultValue());
223
206
  } else {
224
- hadExistingValue?.(mapGet(map, key));
207
+ hadExistingValue?.(mapGet(map2, key));
225
208
  }
226
- return mapGet(map, key);
209
+ return mapGet(map2, key);
227
210
  };
228
- const mapMatch = (map, obj, set, del = mapSet) => {
229
- objMap(obj, (value, id) => set(map, id, value));
230
- mapForEach(map, (id) => (objHas(obj, id) ? 0 : del(map, id)));
231
- return map;
211
+ const mapMatch = (map2, obj, set, del = mapSet) => {
212
+ objMap(obj, (value, id) => set(map2, id, value));
213
+ mapForEach(map2, (id) => (objHas(obj, id) ? 0 : del(map2, id)));
214
+ return map2;
232
215
  };
233
- const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
216
+ const mapToObj = (map2, valueMapper, excludeMapValue, excludeObjValue) => {
234
217
  const obj = {};
235
- collForEach(map, (mapValue, id) => {
218
+ collForEach(map2, (mapValue, id) => {
236
219
  if (!excludeMapValue?.(mapValue, id)) {
237
220
  const objValue = valueMapper ? valueMapper(mapValue, id) : mapValue;
238
221
  if (!excludeObjValue?.(objValue)) {
@@ -242,27 +225,27 @@ const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
242
225
  });
243
226
  return obj;
244
227
  };
245
- const mapToObj2 = (map, valueMapper, excludeMapValue) =>
228
+ const mapToObj2 = (map2, valueMapper, excludeMapValue) =>
246
229
  mapToObj(
247
- map,
230
+ map2,
248
231
  (childMap) => mapToObj(childMap, valueMapper, excludeMapValue),
249
232
  collIsEmpty,
250
233
  objIsEmpty,
251
234
  );
252
- const mapToObj3 = (map, valueMapper, excludeMapValue) =>
235
+ const mapToObj3 = (map2, valueMapper, excludeMapValue) =>
253
236
  mapToObj(
254
- map,
237
+ map2,
255
238
  (childMap) => mapToObj2(childMap, valueMapper, excludeMapValue),
256
239
  collIsEmpty,
257
240
  objIsEmpty,
258
241
  );
259
- const mapClone = (map, mapValue) => {
260
- const map2 = mapNew();
261
- collForEach(map, (value, key) => map2.set(key, mapValue?.(value) ?? value));
262
- return map2;
242
+ const mapClone = (map2, mapValue) => {
243
+ const map22 = mapNew();
244
+ collForEach(map2, (value, key) => map22.set(key, mapValue?.(value) ?? value));
245
+ return map22;
263
246
  };
264
- const mapClone2 = (map) => mapClone(map, mapClone);
265
- const mapClone3 = (map) => mapClone(map, mapClone2);
247
+ const mapClone2 = (map2) => mapClone(map2, mapClone);
248
+ const mapClone3 = (map2) => mapClone(map2, mapClone2);
266
249
  const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
267
250
  ifNotUndefined(
268
251
  (ensureLeaf ? mapEnsure : mapGet)(
@@ -576,12 +559,18 @@ const createCheckpoints = getCreateFunction(
576
559
  collForEach(cellsDelta2, (table, tableId) =>
577
560
  collForEach(table, (row, rowId) =>
578
561
  collForEach(row, (oldNew, cellId) =>
579
- setOrDelCell(store, tableId, rowId, cellId, oldNew[oldOrNew]),
562
+ store.setOrDelCell(
563
+ tableId,
564
+ rowId,
565
+ cellId,
566
+ oldNew[oldOrNew],
567
+ true,
568
+ ),
580
569
  ),
581
570
  ),
582
571
  );
583
572
  collForEach(valuesDelta2, (oldNew, valueId) =>
584
- setOrDelValue(store, valueId, oldNew[oldOrNew]),
573
+ store.setOrDelValue(valueId, oldNew[oldOrNew], true),
585
574
  );
586
575
  });
587
576
  listening = 1;
@@ -1167,6 +1156,19 @@ const createIndexes = getCreateFunction((store) => {
1167
1156
  return objFreeze(indexes);
1168
1157
  });
1169
1158
 
1159
+ const getCellOrValueType = (cellOrValue) => {
1160
+ if (isNull(cellOrValue)) {
1161
+ return NULL;
1162
+ }
1163
+ const type = getTypeOf(cellOrValue);
1164
+ return isTypeStringOrBoolean(type) ||
1165
+ (type == NUMBER && isFiniteNumber(cellOrValue))
1166
+ ? type
1167
+ : void 0;
1168
+ };
1169
+ const isCellOrValueOrUndefined = (cellOrValue) =>
1170
+ isUndefined(cellOrValue) || !isUndefined(getCellOrValueType(cellOrValue));
1171
+
1170
1172
  const stampClone = ([value, hlc]) => stampNew(value, hlc);
1171
1173
  const stampCloneWithHash = ([value, hlc, hash]) => [value, hlc, hash];
1172
1174
  const stampNew = (value, hlc) => (hlc ? [value, hlc] : [value]);
@@ -1211,13 +1213,17 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
1211
1213
  id2,
1212
1214
  mapGet(changedIds, id2) == -addedOrRemoved ? void 0 : addedOrRemoved,
1213
1215
  );
1216
+ const contentOrChangesIsEqual = ([tables1, values1], [tables2, values2]) =>
1217
+ objIsEqual(tables1, tables2) && objIsEqual(values1, values2);
1214
1218
  const createStore = () => {
1215
1219
  let hasTablesSchema;
1216
1220
  let hasValuesSchema;
1217
1221
  let hadTables = false;
1218
1222
  let hadValues = false;
1219
1223
  let transactions = 0;
1224
+ let middleware = [];
1220
1225
  let internalListeners = [];
1226
+ let mutating = 0;
1221
1227
  const changedTableIds = mapNew();
1222
1228
  const changedTableCellIds = mapNew();
1223
1229
  const changedRowCount = mapNew();
@@ -1263,6 +1269,19 @@ const createStore = () => {
1263
1269
  const finishTransactionListeners = pairNewMap();
1264
1270
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
1265
1271
  getListenerFunctions(() => store);
1272
+ const whileMutating = (action) => {
1273
+ const wasMutating = mutating;
1274
+ mutating = 1;
1275
+ const result = action();
1276
+ mutating = wasMutating;
1277
+ return result;
1278
+ };
1279
+ const ifTransformed = (snapshot, getResult, then, isEqual = Object.is) =>
1280
+ ifNotUndefined(getResult(), (result) =>
1281
+ snapshot === result || isEqual(snapshot, result)
1282
+ ? then(result)
1283
+ : whileMutating(() => then(result)),
1284
+ );
1266
1285
  const validateTablesSchema = (tableSchema) =>
1267
1286
  objValidate(tableSchema, (tableSchema2) =>
1268
1287
  objValidate(tableSchema2, validateCellOrValueSchema),
@@ -1450,82 +1469,194 @@ const createStore = () => {
1450
1469
  );
1451
1470
  const setOrDelTables = (tables) =>
1452
1471
  objIsEmpty(tables) ? delTables() : setTables(tables);
1453
- const setValidContent = ([tables, values]) => {
1454
- (objIsEmpty(tables) ? delTables : setTables)(tables);
1455
- (objIsEmpty(values) ? delValues : setValues)(values);
1456
- };
1457
- const setValidTables = (tables) =>
1458
- mapMatch(
1459
- tablesMap,
1472
+ const setOrDelCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
1473
+ isUndefined(cell)
1474
+ ? delCell(tableId, rowId, cellId, true, skipMiddleware)
1475
+ : setCell(tableId, rowId, cellId, cell, skipMiddleware);
1476
+ const setOrDelValues = (values) =>
1477
+ objIsEmpty(values) ? delValues() : setValues(values);
1478
+ const setOrDelValue = (valueId, value, skipMiddleware) =>
1479
+ isUndefined(value)
1480
+ ? delValue(valueId, skipMiddleware)
1481
+ : setValue(valueId, value, skipMiddleware);
1482
+ const setValidContent = (content) =>
1483
+ ifTransformed(
1484
+ content,
1485
+ () =>
1486
+ ifNotUndefined(
1487
+ middleware[0],
1488
+ (willSetContent) =>
1489
+ whileMutating(() => willSetContent(structuredClone(content))),
1490
+ () => content,
1491
+ ),
1492
+ ([tables, values]) => {
1493
+ (objIsEmpty(tables) ? delTables : setTables)(tables);
1494
+ (objIsEmpty(values) ? delValues : setValues)(values);
1495
+ },
1496
+ contentOrChangesIsEqual,
1497
+ );
1498
+ const setValidTables = (tables, forceDel) =>
1499
+ ifTransformed(
1460
1500
  tables,
1461
- (_tables, tableId, table) => setValidTable(tableId, table),
1462
- (_tables, tableId) => delValidTable(tableId),
1501
+ () =>
1502
+ forceDel
1503
+ ? tables
1504
+ : ifNotUndefined(
1505
+ middleware[1],
1506
+ (willSetTables) =>
1507
+ whileMutating(() => willSetTables(structuredClone(tables))),
1508
+ () => tables,
1509
+ ),
1510
+ (validTables) =>
1511
+ mapMatch(
1512
+ tablesMap,
1513
+ validTables,
1514
+ (_tables, tableId, table) => setValidTable(tableId, table),
1515
+ (_tables, tableId) => delValidTable(tableId),
1516
+ ),
1517
+ objIsEqual,
1463
1518
  );
1464
- const setValidTable = (tableId, table) =>
1465
- mapMatch(
1466
- mapEnsure(tablesMap, tableId, () => {
1467
- tableIdsChanged(tableId, 1);
1468
- mapSet(tablePoolFunctions, tableId, getPoolFunctions());
1469
- mapSet(tableCellIds, tableId, mapNew());
1470
- return mapNew();
1471
- }),
1519
+ const setValidTable = (tableId, table, forceDel) =>
1520
+ ifTransformed(
1472
1521
  table,
1473
- (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
1474
- (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
1522
+ () =>
1523
+ forceDel
1524
+ ? table
1525
+ : ifNotUndefined(
1526
+ middleware[2],
1527
+ (willSetTable) =>
1528
+ whileMutating(() =>
1529
+ willSetTable(tableId, structuredClone(table)),
1530
+ ),
1531
+ () => table,
1532
+ ),
1533
+ (validTable) =>
1534
+ mapMatch(
1535
+ mapEnsure(tablesMap, tableId, () => {
1536
+ tableIdsChanged(tableId, 1);
1537
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
1538
+ mapSet(tableCellIds, tableId, mapNew());
1539
+ return mapNew();
1540
+ }),
1541
+ validTable,
1542
+ (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
1543
+ (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
1544
+ ),
1545
+ objIsEqual,
1475
1546
  );
1476
1547
  const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
1477
- mapMatch(
1478
- mapEnsure(tableMap, rowId, () => {
1479
- rowIdsChanged(tableId, rowId, 1);
1480
- return mapNew();
1481
- }),
1548
+ ifTransformed(
1482
1549
  row,
1483
- (rowMap, cellId, cell) =>
1484
- setValidCell(tableId, rowId, rowMap, cellId, cell),
1485
- (rowMap, cellId) =>
1486
- delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
1487
- );
1488
- const setValidCell = (tableId, rowId, rowMap, cellId, cell) => {
1489
- if (!collHas(rowMap, cellId)) {
1490
- cellIdsChanged(tableId, rowId, cellId, 1);
1491
- }
1492
- const oldCell = mapGet(rowMap, cellId);
1493
- if (cell !== oldCell) {
1494
- cellChanged(tableId, rowId, cellId, oldCell, cell);
1495
- mapSet(rowMap, cellId, cell);
1496
- }
1497
- };
1498
- const setCellIntoDefaultRow = (tableId, tableMap, rowId, cellId, validCell) =>
1550
+ () =>
1551
+ forceDel
1552
+ ? row
1553
+ : ifNotUndefined(
1554
+ middleware[3],
1555
+ (willSetRow) =>
1556
+ whileMutating(() =>
1557
+ willSetRow(tableId, rowId, structuredClone(row)),
1558
+ ),
1559
+ () => row,
1560
+ ),
1561
+ (validRow) =>
1562
+ mapMatch(
1563
+ mapEnsure(tableMap, rowId, () => {
1564
+ rowIdsChanged(tableId, rowId, 1);
1565
+ return mapNew();
1566
+ }),
1567
+ validRow,
1568
+ (rowMap, cellId, cell) =>
1569
+ setValidCell(tableId, rowId, rowMap, cellId, cell),
1570
+ (rowMap, cellId) =>
1571
+ delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
1572
+ ),
1573
+ objIsEqual,
1574
+ );
1575
+ const setValidCell = (tableId, rowId, rowMap, cellId, cell, skipMiddleware) =>
1576
+ ifTransformed(
1577
+ cell,
1578
+ () =>
1579
+ ifNotUndefined(
1580
+ skipMiddleware ? void 0 : middleware[4],
1581
+ (willSetCell) =>
1582
+ whileMutating(() => willSetCell(tableId, rowId, cellId, cell)),
1583
+ () => cell,
1584
+ ),
1585
+ (cell2) => {
1586
+ if (!collHas(rowMap, cellId)) {
1587
+ cellIdsChanged(tableId, rowId, cellId, 1);
1588
+ }
1589
+ const oldCell = mapGet(rowMap, cellId);
1590
+ if (cell2 !== oldCell) {
1591
+ cellChanged(tableId, rowId, cellId, oldCell, cell2);
1592
+ mapSet(rowMap, cellId, cell2);
1593
+ }
1594
+ },
1595
+ );
1596
+ const setCellIntoNewRow = (
1597
+ tableId,
1598
+ tableMap,
1599
+ rowId,
1600
+ cellId,
1601
+ validCell,
1602
+ skipMiddleware,
1603
+ ) =>
1499
1604
  ifNotUndefined(
1500
1605
  mapGet(tableMap, rowId),
1501
- (rowMap) => setValidCell(tableId, rowId, rowMap, cellId, validCell),
1502
- () =>
1503
- setValidRow(
1504
- tableId,
1505
- tableMap,
1506
- rowId,
1606
+ (rowMap) =>
1607
+ setValidCell(tableId, rowId, rowMap, cellId, validCell, skipMiddleware),
1608
+ () => {
1609
+ const rowMap = mapNew();
1610
+ mapSet(tableMap, rowId, rowMap);
1611
+ rowIdsChanged(tableId, rowId, 1);
1612
+ objMap(
1507
1613
  addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
1508
- ),
1614
+ (cell, cellId2) =>
1615
+ setValidCell(tableId, rowId, rowMap, cellId2, cell, skipMiddleware),
1616
+ );
1617
+ },
1509
1618
  );
1510
- const setOrDelValues = (values) =>
1511
- objIsEmpty(values) ? delValues() : setValues(values);
1512
- const setValidValues = (values) =>
1513
- mapMatch(
1514
- valuesMap,
1619
+ const setValidValues = (values, forceDel) =>
1620
+ ifTransformed(
1515
1621
  values,
1516
- (_valuesMap, valueId, value) => setValidValue(valueId, value),
1517
- (_valuesMap, valueId) => delValidValue(valueId),
1622
+ () =>
1623
+ forceDel
1624
+ ? values
1625
+ : ifNotUndefined(
1626
+ middleware[5],
1627
+ (willSetValues) =>
1628
+ whileMutating(() => willSetValues(structuredClone(values))),
1629
+ () => values,
1630
+ ),
1631
+ (validValues) =>
1632
+ mapMatch(
1633
+ valuesMap,
1634
+ validValues,
1635
+ (_valuesMap, valueId, value) => setValidValue(valueId, value),
1636
+ (_valuesMap, valueId) => delValidValue(valueId),
1637
+ ),
1638
+ objIsEqual,
1639
+ );
1640
+ const setValidValue = (valueId, value, skipMiddleware) =>
1641
+ ifTransformed(
1642
+ value,
1643
+ () =>
1644
+ ifNotUndefined(
1645
+ skipMiddleware ? void 0 : middleware[6],
1646
+ (willSetValue) => whileMutating(() => willSetValue(valueId, value)),
1647
+ () => value,
1648
+ ),
1649
+ (value2) => {
1650
+ if (!collHas(valuesMap, valueId)) {
1651
+ valueIdsChanged(valueId, 1);
1652
+ }
1653
+ const oldValue = mapGet(valuesMap, valueId);
1654
+ if (value2 !== oldValue) {
1655
+ valueChanged(valueId, oldValue, value2);
1656
+ mapSet(valuesMap, valueId, value2);
1657
+ }
1658
+ },
1518
1659
  );
1519
- const setValidValue = (valueId, value) => {
1520
- if (!collHas(valuesMap, valueId)) {
1521
- valueIdsChanged(valueId, 1);
1522
- }
1523
- const oldValue = mapGet(valuesMap, valueId);
1524
- if (value !== oldValue) {
1525
- valueChanged(valueId, oldValue, value);
1526
- mapSet(valuesMap, valueId, value);
1527
- }
1528
- };
1529
1660
  const getNewRowId = (tableId, reuse) => {
1530
1661
  const [getId] = mapGet(tablePoolFunctions, tableId);
1531
1662
  let rowId;
@@ -1535,14 +1666,34 @@ const createStore = () => {
1535
1666
  return rowId;
1536
1667
  };
1537
1668
  const getOrCreateTable = (tableId) =>
1538
- mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
1539
- const delValidTable = (tableId) => setValidTable(tableId, {});
1669
+ mapEnsure(tablesMap, tableId, () => {
1670
+ tableIdsChanged(tableId, 1);
1671
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
1672
+ mapSet(tableCellIds, tableId, mapNew());
1673
+ return mapNew();
1674
+ });
1675
+ const delValidTable = (tableId) => {
1676
+ if (whileMutating(() => middleware[8]?.(tableId)) ?? true) {
1677
+ return setValidTable(tableId, {}, true);
1678
+ }
1679
+ return mapGet(tablesMap, tableId);
1680
+ };
1540
1681
  const delValidRow = (tableId, tableMap, rowId) => {
1541
- const [, releaseId] = mapGet(tablePoolFunctions, tableId);
1542
- releaseId(rowId);
1543
- setValidRow(tableId, tableMap, rowId, {}, true);
1682
+ if (whileMutating(() => middleware[9]?.(tableId, rowId)) ?? true) {
1683
+ const [, releaseId] = mapGet(tablePoolFunctions, tableId);
1684
+ releaseId(rowId);
1685
+ setValidRow(tableId, tableMap, rowId, {}, true);
1686
+ }
1544
1687
  };
1545
- const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
1688
+ const delValidCell = (
1689
+ tableId,
1690
+ table,
1691
+ rowId,
1692
+ row,
1693
+ cellId,
1694
+ forceDel,
1695
+ skipMiddleware,
1696
+ ) => {
1546
1697
  const defaultCell = mapGet(
1547
1698
  mapGet(tablesSchemaRowCache, tableId)?.[0],
1548
1699
  cellId,
@@ -1550,34 +1701,44 @@ const createStore = () => {
1550
1701
  if (!isUndefined(defaultCell) && !forceDel) {
1551
1702
  return setValidCell(tableId, rowId, row, cellId, defaultCell);
1552
1703
  }
1553
- const delCell2 = (cellId2) => {
1554
- cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
1555
- cellIdsChanged(tableId, rowId, cellId2, -1);
1556
- mapSet(row, cellId2);
1557
- };
1558
- if (isUndefined(defaultCell)) {
1559
- delCell2(cellId);
1560
- } else {
1561
- mapForEach(row, delCell2);
1562
- }
1563
- if (collIsEmpty(row)) {
1564
- rowIdsChanged(tableId, rowId, -1);
1565
- if (collIsEmpty(mapSet(table, rowId))) {
1566
- tableIdsChanged(tableId, -1);
1567
- mapSet(tablesMap, tableId);
1568
- mapSet(tablePoolFunctions, tableId);
1569
- mapSet(tableCellIds, tableId);
1704
+ if (
1705
+ skipMiddleware ||
1706
+ (whileMutating(() => middleware[10]?.(tableId, rowId, cellId)) ?? true)
1707
+ ) {
1708
+ const delCell2 = (cellId2) => {
1709
+ cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
1710
+ cellIdsChanged(tableId, rowId, cellId2, -1);
1711
+ mapSet(row, cellId2);
1712
+ };
1713
+ if (isUndefined(defaultCell)) {
1714
+ delCell2(cellId);
1715
+ } else {
1716
+ mapForEach(row, delCell2);
1717
+ }
1718
+ if (collIsEmpty(row)) {
1719
+ rowIdsChanged(tableId, rowId, -1);
1720
+ if (collIsEmpty(mapSet(table, rowId))) {
1721
+ tableIdsChanged(tableId, -1);
1722
+ mapSet(tablesMap, tableId);
1723
+ mapSet(tablePoolFunctions, tableId);
1724
+ mapSet(tableCellIds, tableId);
1725
+ }
1570
1726
  }
1571
1727
  }
1572
1728
  };
1573
- const delValidValue = (valueId) => {
1729
+ const delValidValue = (valueId, skipMiddleware) => {
1574
1730
  const defaultValue = mapGet(valuesDefaulted, valueId);
1575
1731
  if (!isUndefined(defaultValue)) {
1576
1732
  return setValidValue(valueId, defaultValue);
1577
1733
  }
1578
- valueChanged(valueId, mapGet(valuesMap, valueId));
1579
- valueIdsChanged(valueId, -1);
1580
- mapSet(valuesMap, valueId);
1734
+ if (
1735
+ skipMiddleware ||
1736
+ (whileMutating(() => middleware[12]?.(valueId)) ?? true)
1737
+ ) {
1738
+ valueChanged(valueId, mapGet(valuesMap, valueId));
1739
+ valueIdsChanged(valueId, -1);
1740
+ mapSet(valuesMap, valueId);
1741
+ }
1581
1742
  };
1582
1743
  const tableIdsChanged = (tableId, addedOrRemoved) =>
1583
1744
  idsChanged(changedTableIds, tableId, addedOrRemoved);
@@ -1622,13 +1783,13 @@ const createStore = () => {
1622
1783
  cellId,
1623
1784
  () => [oldCell, 0],
1624
1785
  )[1] = newCell;
1625
- internalListeners[3]?.(tableId, rowId, cellId, newCell);
1786
+ internalListeners[3]?.(tableId, rowId, cellId, newCell, mutating);
1626
1787
  };
1627
1788
  const valueIdsChanged = (valueId, addedOrRemoved) =>
1628
1789
  idsChanged(changedValueIds, valueId, addedOrRemoved);
1629
1790
  const valueChanged = (valueId, oldValue, newValue) => {
1630
1791
  mapEnsure(changedValues, valueId, () => [oldValue, 0])[1] = newValue;
1631
- internalListeners[4]?.(valueId, newValue);
1792
+ internalListeners[4]?.(valueId, newValue, mutating);
1632
1793
  };
1633
1794
  const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
1634
1795
  arrayPush(
@@ -1703,14 +1864,11 @@ const createStore = () => {
1703
1864
  }
1704
1865
  };
1705
1866
  const callTabularListenersForChanges = (mutator) => {
1706
- const hasTablesNow = hasTables();
1707
- if (hasTablesNow != hadTables) {
1708
- callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
1709
- }
1710
- const emptySortedRowIdListeners = collIsEmpty(
1867
+ const hasHasTablesListeners = !collIsEmpty(hasTablesListeners[mutator]);
1868
+ const hasSortedRowIdListeners = !collIsEmpty(
1711
1869
  sortedRowIdsListeners[mutator],
1712
1870
  );
1713
- const emptyIdAndHasListeners =
1871
+ const hasIdOrHasListeners = !(
1714
1872
  collIsEmpty(cellIdsListeners[mutator]) &&
1715
1873
  collIsEmpty(hasCellListeners[mutator]) &&
1716
1874
  collIsEmpty(rowIdsListeners[mutator]) &&
@@ -1718,15 +1876,17 @@ const createStore = () => {
1718
1876
  collIsEmpty(tableCellIdsListeners[mutator]) &&
1719
1877
  collIsEmpty(hasTableCellListeners[mutator]) &&
1720
1878
  collIsEmpty(rowCountListeners[mutator]) &&
1721
- emptySortedRowIdListeners &&
1879
+ !hasSortedRowIdListeners &&
1722
1880
  collIsEmpty(tableIdsListeners[mutator]) &&
1723
- collIsEmpty(hasTableListeners[mutator]);
1724
- const emptyOtherListeners =
1881
+ collIsEmpty(hasTableListeners[mutator])
1882
+ );
1883
+ const hasOtherListeners = !(
1725
1884
  collIsEmpty(cellListeners[mutator]) &&
1726
1885
  collIsEmpty(rowListeners[mutator]) &&
1727
1886
  collIsEmpty(tableListeners[mutator]) &&
1728
- collIsEmpty(tablesListeners[mutator]);
1729
- if (!emptyIdAndHasListeners || !emptyOtherListeners) {
1887
+ collIsEmpty(tablesListeners[mutator])
1888
+ );
1889
+ if (hasHasTablesListeners || hasIdOrHasListeners || hasOtherListeners) {
1730
1890
  const changes = mutator
1731
1891
  ? [
1732
1892
  mapClone(changedTableIds),
@@ -1734,7 +1894,9 @@ const createStore = () => {
1734
1894
  mapClone(changedRowCount),
1735
1895
  mapClone2(changedRowIds),
1736
1896
  mapClone3(changedCellIds),
1737
- mapClone3(changedCells),
1897
+ mapClone(changedCells, (map) =>
1898
+ mapClone(map, (map2) => mapClone(map2, pairClone)),
1899
+ ),
1738
1900
  ]
1739
1901
  : [
1740
1902
  changedTableIds,
@@ -1744,7 +1906,13 @@ const createStore = () => {
1744
1906
  changedCellIds,
1745
1907
  changedCells,
1746
1908
  ];
1747
- if (!emptyIdAndHasListeners) {
1909
+ if (hasHasTablesListeners) {
1910
+ const hasTablesNow = hasTables();
1911
+ if (hasTablesNow != hadTables) {
1912
+ callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
1913
+ }
1914
+ }
1915
+ if (hasIdOrHasListeners) {
1748
1916
  callIdsAndHasListenersIfChanged(
1749
1917
  changes[0],
1750
1918
  tableIdsListeners[mutator],
@@ -1776,13 +1944,13 @@ const createStore = () => {
1776
1944
  hasRowListeners[mutator],
1777
1945
  [tableId],
1778
1946
  ) &&
1779
- !emptySortedRowIdListeners
1947
+ hasSortedRowIdListeners
1780
1948
  ) {
1781
1949
  callListeners(sortedRowIdsListeners[mutator], [tableId, null]);
1782
1950
  setAdd(calledSortableTableIds, tableId);
1783
1951
  }
1784
1952
  });
1785
- if (!emptySortedRowIdListeners) {
1953
+ if (hasSortedRowIdListeners) {
1786
1954
  collForEach(changes[5], (rows, tableId) => {
1787
1955
  if (!collHas(calledSortableTableIds, tableId)) {
1788
1956
  const sortableCellIds = setNew();
@@ -1813,7 +1981,7 @@ const createStore = () => {
1813
1981
  ),
1814
1982
  );
1815
1983
  }
1816
- if (!emptyOtherListeners) {
1984
+ if (hasOtherListeners) {
1817
1985
  let tablesChanged;
1818
1986
  collForEach(changes[5], (rows, tableId) => {
1819
1987
  let tableChanged;
@@ -1850,28 +2018,31 @@ const createStore = () => {
1850
2018
  }
1851
2019
  };
1852
2020
  const callValuesListenersForChanges = (mutator) => {
1853
- const hasValuesNow = hasValues();
1854
- if (hasValuesNow != hadValues) {
1855
- callListeners(hasValuesListeners[mutator], void 0, hasValuesNow);
1856
- }
1857
- const emptyIdAndHasListeners =
1858
- collIsEmpty(valueIdsListeners[mutator]) &&
1859
- collIsEmpty(hasValueListeners[mutator]);
1860
- const emptyOtherListeners =
1861
- collIsEmpty(valueListeners[mutator]) &&
1862
- collIsEmpty(valuesListeners[mutator]);
1863
- if (!emptyIdAndHasListeners || !emptyOtherListeners) {
2021
+ const hasHasValuesListeners = !collIsEmpty(hasValuesListeners[mutator]);
2022
+ const hasIdOrHasListeners =
2023
+ !collIsEmpty(valueIdsListeners[mutator]) ||
2024
+ !collIsEmpty(hasValueListeners[mutator]);
2025
+ const hasOtherListeners =
2026
+ !collIsEmpty(valueListeners[mutator]) ||
2027
+ !collIsEmpty(valuesListeners[mutator]);
2028
+ if (hasHasValuesListeners || hasIdOrHasListeners || hasOtherListeners) {
1864
2029
  const changes = mutator
1865
- ? [mapClone(changedValueIds), mapClone(changedValues)]
2030
+ ? [mapClone(changedValueIds), mapClone(changedValues, pairClone)]
1866
2031
  : [changedValueIds, changedValues];
1867
- if (!emptyIdAndHasListeners) {
2032
+ if (hasHasValuesListeners) {
2033
+ const hasValuesNow = hasValues();
2034
+ if (hasValuesNow != hadValues) {
2035
+ callListeners(hasValuesListeners[mutator], void 0, hasValuesNow);
2036
+ }
2037
+ }
2038
+ if (hasIdOrHasListeners) {
1868
2039
  callIdsAndHasListenersIfChanged(
1869
2040
  changes[0],
1870
2041
  valueIdsListeners[mutator],
1871
2042
  hasValueListeners[mutator],
1872
2043
  );
1873
2044
  }
1874
- if (!emptyOtherListeners) {
2045
+ if (hasOtherListeners) {
1875
2046
  let valuesChanged;
1876
2047
  collForEach(changes[1], ([oldValue, newValue], valueId) => {
1877
2048
  if (newValue !== oldValue) {
@@ -2026,14 +2197,14 @@ const createStore = () => {
2026
2197
  if (validateRow(tableId2, rowId2, partialRow, 1)) {
2027
2198
  const table = getOrCreateTable(tableId2);
2028
2199
  objMap(partialRow, (cell, cellId) =>
2029
- setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
2200
+ setCellIntoNewRow(tableId2, table, rowId2, cellId, cell),
2030
2201
  );
2031
2202
  }
2032
2203
  },
2033
2204
  tableId,
2034
2205
  rowId,
2035
2206
  );
2036
- const setCell = (tableId, rowId, cellId, cell) =>
2207
+ const setCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
2037
2208
  fluentTransaction(
2038
2209
  (tableId2, rowId2, cellId2) =>
2039
2210
  ifNotUndefined(
@@ -2044,12 +2215,13 @@ const createStore = () => {
2044
2215
  isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
2045
2216
  ),
2046
2217
  (validCell) =>
2047
- setCellIntoDefaultRow(
2218
+ setCellIntoNewRow(
2048
2219
  tableId2,
2049
2220
  getOrCreateTable(tableId2),
2050
2221
  rowId2,
2051
2222
  cellId2,
2052
2223
  validCell,
2224
+ skipMiddleware,
2053
2225
  ),
2054
2226
  ),
2055
2227
  tableId,
@@ -2068,7 +2240,7 @@ const createStore = () => {
2068
2240
  )
2069
2241
  : 0,
2070
2242
  );
2071
- const setValue = (valueId, value) =>
2243
+ const setValue = (valueId, value, skipMiddleware) =>
2072
2244
  fluentTransaction(
2073
2245
  (valueId2) =>
2074
2246
  ifNotUndefined(
@@ -2076,27 +2248,40 @@ const createStore = () => {
2076
2248
  valueId2,
2077
2249
  isFunction(value) ? value(getValue(valueId2)) : value,
2078
2250
  ),
2079
- (validValue) => setValidValue(valueId2, validValue),
2251
+ (validValue) => setValidValue(valueId2, validValue, skipMiddleware),
2080
2252
  ),
2081
2253
  valueId,
2082
2254
  );
2083
2255
  const applyChanges = (changes) =>
2084
- fluentTransaction(() => {
2085
- objMap(changes[0], (table, tableId) =>
2086
- isUndefined(table)
2087
- ? delTable(tableId)
2088
- : objMap(table, (row, rowId) =>
2089
- isUndefined(row)
2090
- ? delRow(tableId, rowId)
2091
- : objMap(row, (cell, cellId) =>
2092
- setOrDelCell(store, tableId, rowId, cellId, cell),
2093
- ),
2094
- ),
2095
- );
2096
- objMap(changes[1], (value, valueId) =>
2097
- setOrDelValue(store, valueId, value),
2098
- );
2099
- });
2256
+ fluentTransaction(() =>
2257
+ ifTransformed(
2258
+ changes,
2259
+ () =>
2260
+ ifNotUndefined(
2261
+ middleware[13],
2262
+ (willApplyChanges) =>
2263
+ whileMutating(() => willApplyChanges(structuredClone(changes))),
2264
+ () => changes,
2265
+ ),
2266
+ (changes2) => {
2267
+ objMap(changes2[0], (table, tableId) =>
2268
+ isUndefined(table)
2269
+ ? delTable(tableId)
2270
+ : objMap(table, (row, rowId) =>
2271
+ isUndefined(row)
2272
+ ? delRow(tableId, rowId)
2273
+ : objMap(row, (cell, cellId) =>
2274
+ setOrDelCell(tableId, rowId, cellId, cell),
2275
+ ),
2276
+ ),
2277
+ );
2278
+ objMap(changes2[1], (value, valueId) =>
2279
+ setOrDelValue(valueId, value),
2280
+ );
2281
+ },
2282
+ contentOrChangesIsEqual,
2283
+ ),
2284
+ );
2100
2285
  const setTablesJson = (tablesJson) => {
2101
2286
  tryCatch(() => setOrDelTables(jsonParse(tablesJson)));
2102
2287
  return store;
@@ -2143,7 +2328,12 @@ const createStore = () => {
2143
2328
  setTablesSchema(tablesSchema);
2144
2329
  setValuesSchema(valuesSchema);
2145
2330
  });
2146
- const delTables = () => fluentTransaction(() => setValidTables({}));
2331
+ const delTables = () =>
2332
+ fluentTransaction(() =>
2333
+ (whileMutating(() => middleware[7]?.()) ?? true)
2334
+ ? setValidTables({}, true)
2335
+ : 0,
2336
+ );
2147
2337
  const delTable = (tableId) =>
2148
2338
  fluentTransaction(
2149
2339
  (tableId2) =>
@@ -2161,7 +2351,7 @@ const createStore = () => {
2161
2351
  tableId,
2162
2352
  rowId,
2163
2353
  );
2164
- const delCell = (tableId, rowId, cellId, forceDel) =>
2354
+ const delCell = (tableId, rowId, cellId, forceDel, skipMiddleware) =>
2165
2355
  fluentTransaction(
2166
2356
  (tableId2, rowId2, cellId2) =>
2167
2357
  ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
@@ -2174,6 +2364,7 @@ const createStore = () => {
2174
2364
  rowMap,
2175
2365
  cellId2,
2176
2366
  forceDel,
2367
+ skipMiddleware,
2177
2368
  )
2178
2369
  : 0,
2179
2370
  ),
@@ -2182,11 +2373,18 @@ const createStore = () => {
2182
2373
  rowId,
2183
2374
  cellId,
2184
2375
  );
2185
- const delValues = () => fluentTransaction(() => setValidValues({}));
2186
- const delValue = (valueId) =>
2376
+ const delValues = () =>
2377
+ fluentTransaction(() =>
2378
+ (whileMutating(() => middleware[11]?.()) ?? true)
2379
+ ? setValidValues({}, true)
2380
+ : 0,
2381
+ );
2382
+ const delValue = (valueId, skipMiddleware) =>
2187
2383
  fluentTransaction(
2188
2384
  (valueId2) =>
2189
- collHas(valuesMap, valueId2) ? delValidValue(valueId2) : 0,
2385
+ collHas(valuesMap, valueId2)
2386
+ ? delValidValue(valueId2, skipMiddleware)
2387
+ : 0,
2190
2388
  valueId,
2191
2389
  );
2192
2390
  const delTablesSchema = () =>
@@ -2268,25 +2466,27 @@ const createStore = () => {
2268
2466
  transactions--;
2269
2467
  if (transactions == 0) {
2270
2468
  transactions = 1;
2271
- callInvalidCellListeners(1);
2272
- if (!collIsEmpty(changedCells)) {
2273
- callTabularListenersForChanges(1);
2274
- }
2275
- callInvalidValueListeners(1);
2276
- if (!collIsEmpty(changedValues)) {
2277
- callValuesListenersForChanges(1);
2278
- }
2469
+ whileMutating(() => {
2470
+ callInvalidCellListeners(1);
2471
+ if (!collIsEmpty(changedCells)) {
2472
+ callTabularListenersForChanges(1);
2473
+ }
2474
+ callInvalidValueListeners(1);
2475
+ if (!collIsEmpty(changedValues)) {
2476
+ callValuesListenersForChanges(1);
2477
+ }
2478
+ });
2279
2479
  if (doRollback?.(store)) {
2280
2480
  collForEach(changedCells, (table, tableId) =>
2281
2481
  collForEach(table, (row, rowId) =>
2282
2482
  collForEach(row, ([oldCell], cellId) =>
2283
- setOrDelCell(store, tableId, rowId, cellId, oldCell),
2483
+ setOrDelCell(tableId, rowId, cellId, oldCell, true),
2284
2484
  ),
2285
2485
  ),
2286
2486
  );
2287
2487
  collClear(changedCells);
2288
2488
  collForEach(changedValues, ([oldValue], valueId) =>
2289
- setOrDelValue(store, valueId, oldValue),
2489
+ setOrDelValue(valueId, oldValue, true),
2290
2490
  );
2291
2491
  collClear(changedValues);
2292
2492
  }
@@ -2413,6 +2613,38 @@ const createStore = () => {
2413
2613
  collSize2(startTransactionListeners) +
2414
2614
  pairCollSize2(finishTransactionListeners),
2415
2615
  });
2616
+ const setMiddleware = (
2617
+ willSetContent,
2618
+ willSetTables,
2619
+ willSetTable,
2620
+ willSetRow,
2621
+ willSetCell,
2622
+ willSetValues,
2623
+ willSetValue,
2624
+ willDelTables,
2625
+ willDelTable,
2626
+ willDelRow,
2627
+ willDelCell,
2628
+ willDelValues,
2629
+ willDelValue,
2630
+ willApplyChanges,
2631
+ ) =>
2632
+ (middleware = [
2633
+ willSetContent,
2634
+ willSetTables,
2635
+ willSetTable,
2636
+ willSetRow,
2637
+ willSetCell,
2638
+ willSetValues,
2639
+ willSetValue,
2640
+ willDelTables,
2641
+ willDelTable,
2642
+ willDelRow,
2643
+ willDelCell,
2644
+ willDelValues,
2645
+ willDelValue,
2646
+ willApplyChanges,
2647
+ ]);
2416
2648
  const setInternalListeners = (
2417
2649
  preStartTransaction,
2418
2650
  preFinishTransaction,
@@ -2506,6 +2738,9 @@ const createStore = () => {
2506
2738
  addListener,
2507
2739
  callListeners,
2508
2740
  setInternalListeners,
2741
+ setMiddleware,
2742
+ setOrDelCell,
2743
+ setOrDelValue,
2509
2744
  };
2510
2745
  objMap(
2511
2746
  {
@@ -2642,6 +2877,7 @@ const createMergeableStore = (uniqueId, getNow) => {
2642
2877
  let listeningToRawStoreChanges = 1;
2643
2878
  let contentStampMap = newContentStampMap();
2644
2879
  let defaultingContent = 0;
2880
+ let mutated = 0;
2645
2881
  const touchedCells = mapNew();
2646
2882
  const touchedValues = setNew();
2647
2883
  const [getNextHlc, seenHlc] = getHlcFunctions(uniqueId, getNow);
@@ -2768,12 +3004,15 @@ const createMergeableStore = (uniqueId, getNow) => {
2768
3004
  collClear(touchedCells);
2769
3005
  collClear(touchedValues);
2770
3006
  };
2771
- const cellChanged = (tableId, rowId, cellId, newCell) => {
3007
+ const cellChanged = (tableId, rowId, cellId, newCell, mutating) => {
2772
3008
  setAdd(
2773
3009
  mapEnsure(mapEnsure(touchedCells, tableId, mapNew), rowId, setNew),
2774
3010
  cellId,
2775
3011
  );
2776
- if (listeningToRawStoreChanges) {
3012
+ if (listeningToRawStoreChanges || mutating) {
3013
+ if (mutating) {
3014
+ mutated = 1;
3015
+ }
2777
3016
  mergeContentOrChanges([
2778
3017
  [
2779
3018
  {
@@ -2796,9 +3035,12 @@ const createMergeableStore = (uniqueId, getNow) => {
2796
3035
  ]);
2797
3036
  }
2798
3037
  };
2799
- const valueChanged = (valueId, newValue) => {
3038
+ const valueChanged = (valueId, newValue, mutating) => {
2800
3039
  setAdd(touchedValues, valueId);
2801
- if (listeningToRawStoreChanges) {
3040
+ if (listeningToRawStoreChanges || mutating) {
3041
+ if (mutating) {
3042
+ mutated = 1;
3043
+ }
2802
3044
  mergeContentOrChanges([
2803
3045
  [{}],
2804
3046
  [
@@ -3016,6 +3258,11 @@ const createMergeableStore = (uniqueId, getNow) => {
3016
3258
  mergeableStore2.applyMergeableChanges(mergeableChanges);
3017
3259
  return applyMergeableChanges(mergeableChanges2);
3018
3260
  };
3261
+ const hadMutated = () => {
3262
+ const result = mutated;
3263
+ mutated = 0;
3264
+ return result;
3265
+ };
3019
3266
  const mergeableStore = {
3020
3267
  getMergeableContent,
3021
3268
  getMergeableContentHashes,
@@ -3032,6 +3279,8 @@ const createMergeableStore = (uniqueId, getNow) => {
3032
3279
  getTransactionMergeableChanges,
3033
3280
  applyMergeableChanges,
3034
3281
  merge,
3282
+ // only used internally by other modules
3283
+ hadMutated,
3035
3284
  };
3036
3285
  store.setInternalListeners(
3037
3286
  preStartTransaction,
@@ -3048,7 +3297,8 @@ const createMergeableStore = (uniqueId, getNow) => {
3048
3297
  strStartsWith(name, DEL) ||
3049
3298
  strStartsWith(name, 'apply') ||
3050
3299
  strEndsWith(name, TRANSACTION) ||
3051
- name == 'call' + LISTENER
3300
+ name == 'call' + LISTENER ||
3301
+ name == 'use'
3052
3302
  ? (...args) => {
3053
3303
  method(...args);
3054
3304
  return mergeableStore;
@@ -3241,6 +3491,115 @@ const createMetrics = getCreateFunction((store) => {
3241
3491
  return objFreeze(metrics);
3242
3492
  });
3243
3493
 
3494
+ const reduceCallbacks = (callbacks, thing, ...ids) =>
3495
+ arrayReduce(
3496
+ callbacks,
3497
+ (current, callback) =>
3498
+ isUndefined(current) ? current : callback(...ids, current),
3499
+ thing,
3500
+ );
3501
+ const everyCallback = (callbacks, ...ids) =>
3502
+ arrayEvery(callbacks, (callback) => callback(...ids));
3503
+ const createMiddleware = getCreateFunction((store) => {
3504
+ const fluent = (actions) => {
3505
+ actions();
3506
+ return middleware;
3507
+ };
3508
+ const addCallback = (callbacks) => (callback) =>
3509
+ fluent(() => arrayPush(callbacks, callback));
3510
+ const willSetContentCallbacks = [];
3511
+ const willSetTablesCallbacks = [];
3512
+ const willSetTableCallbacks = [];
3513
+ const willSetRowCallbacks = [];
3514
+ const willSetCellCallbacks = [];
3515
+ const willSetValuesCallbacks = [];
3516
+ const willSetValueCallbacks = [];
3517
+ const willDelTablesCallbacks = [];
3518
+ const willDelTableCallbacks = [];
3519
+ const willDelRowCallbacks = [];
3520
+ const willDelCellCallbacks = [];
3521
+ const willDelValuesCallbacks = [];
3522
+ const willDelValueCallbacks = [];
3523
+ const willApplyChangesCallbacks = [];
3524
+ const willSetContent = (content) =>
3525
+ reduceCallbacks(willSetContentCallbacks, content);
3526
+ const willSetTables = (tables) =>
3527
+ reduceCallbacks(willSetTablesCallbacks, tables);
3528
+ const willSetTable = (tableId, table) =>
3529
+ reduceCallbacks(willSetTableCallbacks, table, tableId);
3530
+ const willSetRow = (tableId, rowId, row) =>
3531
+ reduceCallbacks(willSetRowCallbacks, row, tableId, rowId);
3532
+ const willSetCell = (tableId, rowId, cellId, cell) =>
3533
+ reduceCallbacks(willSetCellCallbacks, cell, tableId, rowId, cellId);
3534
+ const willSetValues = (values) =>
3535
+ reduceCallbacks(willSetValuesCallbacks, values);
3536
+ const willSetValue = (valueId, value) =>
3537
+ reduceCallbacks(willSetValueCallbacks, value, valueId);
3538
+ const willDelTables = () => everyCallback(willDelTablesCallbacks);
3539
+ const willDelTable = (tableId) =>
3540
+ everyCallback(willDelTableCallbacks, tableId);
3541
+ const willDelRow = (tableId, rowId) =>
3542
+ everyCallback(willDelRowCallbacks, tableId, rowId);
3543
+ const willDelCell = (tableId, rowId, cellId) =>
3544
+ everyCallback(willDelCellCallbacks, tableId, rowId, cellId);
3545
+ const willDelValues = () => everyCallback(willDelValuesCallbacks);
3546
+ const willDelValue = (valueId) =>
3547
+ everyCallback(willDelValueCallbacks, valueId);
3548
+ const willApplyChanges = (changes) =>
3549
+ reduceCallbacks(willApplyChangesCallbacks, changes);
3550
+ const getStore = () => store;
3551
+ const addWillSetContentCallback = addCallback(willSetContentCallbacks);
3552
+ const addWillSetTablesCallback = addCallback(willSetTablesCallbacks);
3553
+ const addWillSetTableCallback = addCallback(willSetTableCallbacks);
3554
+ const addWillSetRowCallback = addCallback(willSetRowCallbacks);
3555
+ const addWillSetCellCallback = addCallback(willSetCellCallbacks);
3556
+ const addWillSetValuesCallback = addCallback(willSetValuesCallbacks);
3557
+ const addWillSetValueCallback = addCallback(willSetValueCallbacks);
3558
+ const addWillDelTablesCallback = addCallback(willDelTablesCallbacks);
3559
+ const addWillDelTableCallback = addCallback(willDelTableCallbacks);
3560
+ const addWillDelRowCallback = addCallback(willDelRowCallbacks);
3561
+ const addWillDelCellCallback = addCallback(willDelCellCallbacks);
3562
+ const addWillDelValuesCallback = addCallback(willDelValuesCallbacks);
3563
+ const addWillDelValueCallback = addCallback(willDelValueCallbacks);
3564
+ const addWillApplyChangesCallback = addCallback(willApplyChangesCallbacks);
3565
+ const destroy = () => {};
3566
+ const middleware = objFreeze({
3567
+ getStore,
3568
+ addWillSetContentCallback,
3569
+ addWillSetTablesCallback,
3570
+ addWillSetTableCallback,
3571
+ addWillSetRowCallback,
3572
+ addWillSetCellCallback,
3573
+ addWillSetValuesCallback,
3574
+ addWillSetValueCallback,
3575
+ addWillDelTablesCallback,
3576
+ addWillDelTableCallback,
3577
+ addWillDelRowCallback,
3578
+ addWillDelCellCallback,
3579
+ addWillDelValuesCallback,
3580
+ addWillDelValueCallback,
3581
+ addWillApplyChangesCallback,
3582
+ destroy,
3583
+ });
3584
+ store.setMiddleware(
3585
+ willSetContent,
3586
+ willSetTables,
3587
+ willSetTable,
3588
+ willSetRow,
3589
+ willSetCell,
3590
+ willSetValues,
3591
+ willSetValue,
3592
+ willDelTables,
3593
+ willDelTable,
3594
+ willDelRow,
3595
+ willDelCell,
3596
+ willDelValues,
3597
+ willDelValue,
3598
+ willApplyChanges,
3599
+ );
3600
+ return middleware;
3601
+ });
3602
+
3244
3603
  const createQueries = getCreateFunction((store) => {
3245
3604
  const createStore = store.createStore;
3246
3605
  const preStore = createStore();
@@ -3569,8 +3928,7 @@ const createQueries = getCreateFunction((store) => {
3569
3928
  selectJoinWhereStore.transaction(() =>
3570
3929
  arrayEvery(wheres, (where2) => where2(getTableCell))
3571
3930
  ? mapForEach(selects, (asCellId, tableCellGetter) =>
3572
- setOrDelCell(
3573
- selectJoinWhereStore,
3931
+ selectJoinWhereStore.setOrDelCell(
3574
3932
  queryId,
3575
3933
  rootRowId,
3576
3934
  asCellId,
@@ -3975,6 +4333,7 @@ export {
3975
4333
  createIndexes,
3976
4334
  createMergeableStore,
3977
4335
  createMetrics,
4336
+ createMiddleware,
3978
4337
  createQueries,
3979
4338
  createRelationships,
3980
4339
  createStore,