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
@@ -53,6 +53,7 @@ const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
53
53
  const size = (arrayOrString) => arrayOrString.length;
54
54
  const test = (regex, subject) => regex.test(subject);
55
55
  const noop = () => {};
56
+ const structuredClone = GLOBAL.structuredClone;
56
57
  const tryCatch = async (action, then1, then2) => {
57
58
  try {
58
59
  return await action();
@@ -74,12 +75,6 @@ const getCellOrValueType = (cellOrValue) => {
74
75
  };
75
76
  const isCellOrValueOrUndefined = (cellOrValue) =>
76
77
  isUndefined(cellOrValue) || !isUndefined(getCellOrValueType(cellOrValue));
77
- const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
78
- isUndefined(cell)
79
- ? store.delCell(tableId, rowId, cellId, true)
80
- : store.setCell(tableId, rowId, cellId, cell);
81
- const setOrDelValue = (store, valueId, value) =>
82
- isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
83
78
 
84
79
  const arrayHas = (array, value) => array.includes(value);
85
80
  const arrayEvery = (array, cb) => array.every(cb);
@@ -137,6 +132,26 @@ const objMap = (obj, cb) =>
137
132
  objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
138
133
  const objSize = (obj) => size(objIds(obj));
139
134
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
135
+
136
+ /* istanbul ignore next */
137
+ const objIsEqual = (
138
+ obj1,
139
+ obj2,
140
+ isEqual = (value1, value2) => value1 === value2,
141
+ ) => {
142
+ const entries1 = objEntries(obj1);
143
+ return (
144
+ size(entries1) === objSize(obj2) &&
145
+ arrayEvery(entries1, ([index, value1]) =>
146
+ isObject(value1)
147
+ ? /* istanbul ignore next */
148
+ isObject(obj2[index])
149
+ ? objIsEqual(obj2[index], value1)
150
+ : false
151
+ : isEqual(value1, obj2[index]),
152
+ )
153
+ );
154
+ };
140
155
  const objEnsure = (obj, id, getDefaultValue) => {
141
156
  if (!objHas(obj, id)) {
142
157
  obj[id] = getDefaultValue();
@@ -184,31 +199,32 @@ const getValueInValuesHash = (valueId, valueHash) =>
184
199
  const getValueHash = (value, valueHlc) =>
185
200
  getHash(jsonStringWithMap(value ?? null) + ':' + valueHlc);
186
201
 
187
- const mapNew = (entries) => new Map(entries);
188
- const mapKeys = (map) => [...(map?.keys() ?? [])];
189
- const mapGet = (map, key) => map?.get(key);
190
- const mapForEach = (map, cb) =>
191
- collForEach(map, (value, key) => cb(key, value));
202
+ const map = Map;
203
+ const mapNew = (entries) => new map(entries);
204
+ const mapKeys = (map2) => [...(map2?.keys() ?? [])];
205
+ const mapGet = (map2, key) => map2?.get(key);
206
+ const mapForEach = (map2, cb) =>
207
+ collForEach(map2, (value, key) => cb(key, value));
192
208
  const mapMap = (coll, cb) =>
193
209
  arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
194
- const mapSet = (map, key, value) =>
195
- isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
196
- const mapEnsure = (map, key, getDefaultValue, hadExistingValue) => {
197
- if (!collHas(map, key)) {
198
- mapSet(map, key, getDefaultValue());
210
+ const mapSet = (map2, key, value) =>
211
+ isUndefined(value) ? (collDel(map2, key), map2) : map2?.set(key, value);
212
+ const mapEnsure = (map2, key, getDefaultValue, hadExistingValue) => {
213
+ if (!collHas(map2, key)) {
214
+ mapSet(map2, key, getDefaultValue());
199
215
  } else {
200
- hadExistingValue?.(mapGet(map, key));
216
+ hadExistingValue?.(mapGet(map2, key));
201
217
  }
202
- return mapGet(map, key);
218
+ return mapGet(map2, key);
203
219
  };
204
- const mapMatch = (map, obj, set, del = mapSet) => {
205
- objMap(obj, (value, id) => set(map, id, value));
206
- mapForEach(map, (id) => (objHas(obj, id) ? 0 : del(map, id)));
207
- return map;
220
+ const mapMatch = (map2, obj, set, del = mapSet) => {
221
+ objMap(obj, (value, id) => set(map2, id, value));
222
+ mapForEach(map2, (id) => (objHas(obj, id) ? 0 : del(map2, id)));
223
+ return map2;
208
224
  };
209
- const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
225
+ const mapToObj = (map2, valueMapper, excludeMapValue, excludeObjValue) => {
210
226
  const obj = {};
211
- collForEach(map, (mapValue, id) => {
227
+ collForEach(map2, (mapValue, id) => {
212
228
  if (!excludeMapValue?.(mapValue, id)) {
213
229
  const objValue = valueMapper ? valueMapper(mapValue, id) : mapValue;
214
230
  if (!excludeObjValue?.(objValue)) {
@@ -218,27 +234,27 @@ const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
218
234
  });
219
235
  return obj;
220
236
  };
221
- const mapToObj2 = (map, valueMapper, excludeMapValue) =>
237
+ const mapToObj2 = (map2, valueMapper, excludeMapValue) =>
222
238
  mapToObj(
223
- map,
239
+ map2,
224
240
  (childMap) => mapToObj(childMap, valueMapper, excludeMapValue),
225
241
  collIsEmpty,
226
242
  objIsEmpty,
227
243
  );
228
- const mapToObj3 = (map, valueMapper, excludeMapValue) =>
244
+ const mapToObj3 = (map2, valueMapper, excludeMapValue) =>
229
245
  mapToObj(
230
- map,
246
+ map2,
231
247
  (childMap) => mapToObj2(childMap, valueMapper, excludeMapValue),
232
248
  collIsEmpty,
233
249
  objIsEmpty,
234
250
  );
235
- const mapClone = (map, mapValue) => {
236
- const map2 = mapNew();
237
- collForEach(map, (value, key) => map2.set(key, mapValue?.(value) ?? value));
238
- return map2;
251
+ const mapClone = (map2, mapValue) => {
252
+ const map22 = mapNew();
253
+ collForEach(map2, (value, key) => map22.set(key, mapValue?.(value) ?? value));
254
+ return map22;
239
255
  };
240
- const mapClone2 = (map) => mapClone(map, mapClone);
241
- const mapClone3 = (map) => mapClone(map, mapClone2);
256
+ const mapClone2 = (map2) => mapClone(map2, mapClone);
257
+ const mapClone3 = (map2) => mapClone(map2, mapClone2);
242
258
  const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
243
259
  ifNotUndefined(
244
260
  (ensureLeaf ? mapEnsure : mapGet)(
@@ -503,13 +519,17 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
503
519
  id2,
504
520
  mapGet(changedIds, id2) == -addedOrRemoved ? void 0 : addedOrRemoved,
505
521
  );
522
+ const contentOrChangesIsEqual = ([tables1, values1], [tables2, values2]) =>
523
+ objIsEqual(tables1, tables2) && objIsEqual(values1, values2);
506
524
  const createStore = () => {
507
525
  let hasTablesSchema;
508
526
  let hasValuesSchema;
509
527
  let hadTables = false;
510
528
  let hadValues = false;
511
529
  let transactions = 0;
530
+ let middleware = [];
512
531
  let internalListeners = [];
532
+ let mutating = 0;
513
533
  const changedTableIds = mapNew();
514
534
  const changedTableCellIds = mapNew();
515
535
  const changedRowCount = mapNew();
@@ -555,6 +575,19 @@ const createStore = () => {
555
575
  const finishTransactionListeners = pairNewMap();
556
576
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
557
577
  getListenerFunctions(() => store);
578
+ const whileMutating = (action) => {
579
+ const wasMutating = mutating;
580
+ mutating = 1;
581
+ const result = action();
582
+ mutating = wasMutating;
583
+ return result;
584
+ };
585
+ const ifTransformed = (snapshot, getResult, then, isEqual = Object.is) =>
586
+ ifNotUndefined(getResult(), (result) =>
587
+ snapshot === result || isEqual(snapshot, result)
588
+ ? then(result)
589
+ : whileMutating(() => then(result)),
590
+ );
558
591
  const validateTablesSchema = (tableSchema) =>
559
592
  objValidate(tableSchema, (tableSchema2) =>
560
593
  objValidate(tableSchema2, validateCellOrValueSchema),
@@ -742,82 +775,194 @@ const createStore = () => {
742
775
  );
743
776
  const setOrDelTables = (tables) =>
744
777
  objIsEmpty(tables) ? delTables() : setTables(tables);
745
- const setValidContent = ([tables, values]) => {
746
- (objIsEmpty(tables) ? delTables : setTables)(tables);
747
- (objIsEmpty(values) ? delValues : setValues)(values);
748
- };
749
- const setValidTables = (tables) =>
750
- mapMatch(
751
- tablesMap,
778
+ const setOrDelCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
779
+ isUndefined(cell)
780
+ ? delCell(tableId, rowId, cellId, true, skipMiddleware)
781
+ : setCell(tableId, rowId, cellId, cell, skipMiddleware);
782
+ const setOrDelValues = (values) =>
783
+ objIsEmpty(values) ? delValues() : setValues(values);
784
+ const setOrDelValue = (valueId, value, skipMiddleware) =>
785
+ isUndefined(value)
786
+ ? delValue(valueId, skipMiddleware)
787
+ : setValue(valueId, value, skipMiddleware);
788
+ const setValidContent = (content) =>
789
+ ifTransformed(
790
+ content,
791
+ () =>
792
+ ifNotUndefined(
793
+ middleware[0],
794
+ (willSetContent) =>
795
+ whileMutating(() => willSetContent(structuredClone(content))),
796
+ () => content,
797
+ ),
798
+ ([tables, values]) => {
799
+ (objIsEmpty(tables) ? delTables : setTables)(tables);
800
+ (objIsEmpty(values) ? delValues : setValues)(values);
801
+ },
802
+ contentOrChangesIsEqual,
803
+ );
804
+ const setValidTables = (tables, forceDel) =>
805
+ ifTransformed(
752
806
  tables,
753
- (_tables, tableId, table) => setValidTable(tableId, table),
754
- (_tables, tableId) => delValidTable(tableId),
807
+ () =>
808
+ forceDel
809
+ ? tables
810
+ : ifNotUndefined(
811
+ middleware[1],
812
+ (willSetTables) =>
813
+ whileMutating(() => willSetTables(structuredClone(tables))),
814
+ () => tables,
815
+ ),
816
+ (validTables) =>
817
+ mapMatch(
818
+ tablesMap,
819
+ validTables,
820
+ (_tables, tableId, table) => setValidTable(tableId, table),
821
+ (_tables, tableId) => delValidTable(tableId),
822
+ ),
823
+ objIsEqual,
755
824
  );
756
- const setValidTable = (tableId, table) =>
757
- mapMatch(
758
- mapEnsure(tablesMap, tableId, () => {
759
- tableIdsChanged(tableId, 1);
760
- mapSet(tablePoolFunctions, tableId, getPoolFunctions());
761
- mapSet(tableCellIds, tableId, mapNew());
762
- return mapNew();
763
- }),
825
+ const setValidTable = (tableId, table, forceDel) =>
826
+ ifTransformed(
764
827
  table,
765
- (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
766
- (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
828
+ () =>
829
+ forceDel
830
+ ? table
831
+ : ifNotUndefined(
832
+ middleware[2],
833
+ (willSetTable) =>
834
+ whileMutating(() =>
835
+ willSetTable(tableId, structuredClone(table)),
836
+ ),
837
+ () => table,
838
+ ),
839
+ (validTable) =>
840
+ mapMatch(
841
+ mapEnsure(tablesMap, tableId, () => {
842
+ tableIdsChanged(tableId, 1);
843
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
844
+ mapSet(tableCellIds, tableId, mapNew());
845
+ return mapNew();
846
+ }),
847
+ validTable,
848
+ (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
849
+ (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
850
+ ),
851
+ objIsEqual,
767
852
  );
768
853
  const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
769
- mapMatch(
770
- mapEnsure(tableMap, rowId, () => {
771
- rowIdsChanged(tableId, rowId, 1);
772
- return mapNew();
773
- }),
854
+ ifTransformed(
774
855
  row,
775
- (rowMap, cellId, cell) =>
776
- setValidCell(tableId, rowId, rowMap, cellId, cell),
777
- (rowMap, cellId) =>
778
- delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
856
+ () =>
857
+ forceDel
858
+ ? row
859
+ : ifNotUndefined(
860
+ middleware[3],
861
+ (willSetRow) =>
862
+ whileMutating(() =>
863
+ willSetRow(tableId, rowId, structuredClone(row)),
864
+ ),
865
+ () => row,
866
+ ),
867
+ (validRow) =>
868
+ mapMatch(
869
+ mapEnsure(tableMap, rowId, () => {
870
+ rowIdsChanged(tableId, rowId, 1);
871
+ return mapNew();
872
+ }),
873
+ validRow,
874
+ (rowMap, cellId, cell) =>
875
+ setValidCell(tableId, rowId, rowMap, cellId, cell),
876
+ (rowMap, cellId) =>
877
+ delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
878
+ ),
879
+ objIsEqual,
779
880
  );
780
- const setValidCell = (tableId, rowId, rowMap, cellId, cell) => {
781
- if (!collHas(rowMap, cellId)) {
782
- cellIdsChanged(tableId, rowId, cellId, 1);
783
- }
784
- const oldCell = mapGet(rowMap, cellId);
785
- if (cell !== oldCell) {
786
- cellChanged(tableId, rowId, cellId, oldCell, cell);
787
- mapSet(rowMap, cellId, cell);
788
- }
789
- };
790
- const setCellIntoDefaultRow = (tableId, tableMap, rowId, cellId, validCell) =>
881
+ const setValidCell = (tableId, rowId, rowMap, cellId, cell, skipMiddleware) =>
882
+ ifTransformed(
883
+ cell,
884
+ () =>
885
+ ifNotUndefined(
886
+ skipMiddleware ? void 0 : middleware[4],
887
+ (willSetCell) =>
888
+ whileMutating(() => willSetCell(tableId, rowId, cellId, cell)),
889
+ () => cell,
890
+ ),
891
+ (cell2) => {
892
+ if (!collHas(rowMap, cellId)) {
893
+ cellIdsChanged(tableId, rowId, cellId, 1);
894
+ }
895
+ const oldCell = mapGet(rowMap, cellId);
896
+ if (cell2 !== oldCell) {
897
+ cellChanged(tableId, rowId, cellId, oldCell, cell2);
898
+ mapSet(rowMap, cellId, cell2);
899
+ }
900
+ },
901
+ );
902
+ const setCellIntoNewRow = (
903
+ tableId,
904
+ tableMap,
905
+ rowId,
906
+ cellId,
907
+ validCell,
908
+ skipMiddleware,
909
+ ) =>
791
910
  ifNotUndefined(
792
911
  mapGet(tableMap, rowId),
793
- (rowMap) => setValidCell(tableId, rowId, rowMap, cellId, validCell),
794
- () =>
795
- setValidRow(
796
- tableId,
797
- tableMap,
798
- rowId,
912
+ (rowMap) =>
913
+ setValidCell(tableId, rowId, rowMap, cellId, validCell, skipMiddleware),
914
+ () => {
915
+ const rowMap = mapNew();
916
+ mapSet(tableMap, rowId, rowMap);
917
+ rowIdsChanged(tableId, rowId, 1);
918
+ objMap(
799
919
  addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
800
- ),
920
+ (cell, cellId2) =>
921
+ setValidCell(tableId, rowId, rowMap, cellId2, cell, skipMiddleware),
922
+ );
923
+ },
801
924
  );
802
- const setOrDelValues = (values) =>
803
- objIsEmpty(values) ? delValues() : setValues(values);
804
- const setValidValues = (values) =>
805
- mapMatch(
806
- valuesMap,
925
+ const setValidValues = (values, forceDel) =>
926
+ ifTransformed(
807
927
  values,
808
- (_valuesMap, valueId, value) => setValidValue(valueId, value),
809
- (_valuesMap, valueId) => delValidValue(valueId),
928
+ () =>
929
+ forceDel
930
+ ? values
931
+ : ifNotUndefined(
932
+ middleware[5],
933
+ (willSetValues) =>
934
+ whileMutating(() => willSetValues(structuredClone(values))),
935
+ () => values,
936
+ ),
937
+ (validValues) =>
938
+ mapMatch(
939
+ valuesMap,
940
+ validValues,
941
+ (_valuesMap, valueId, value) => setValidValue(valueId, value),
942
+ (_valuesMap, valueId) => delValidValue(valueId),
943
+ ),
944
+ objIsEqual,
945
+ );
946
+ const setValidValue = (valueId, value, skipMiddleware) =>
947
+ ifTransformed(
948
+ value,
949
+ () =>
950
+ ifNotUndefined(
951
+ skipMiddleware ? void 0 : middleware[6],
952
+ (willSetValue) => whileMutating(() => willSetValue(valueId, value)),
953
+ () => value,
954
+ ),
955
+ (value2) => {
956
+ if (!collHas(valuesMap, valueId)) {
957
+ valueIdsChanged(valueId, 1);
958
+ }
959
+ const oldValue = mapGet(valuesMap, valueId);
960
+ if (value2 !== oldValue) {
961
+ valueChanged(valueId, oldValue, value2);
962
+ mapSet(valuesMap, valueId, value2);
963
+ }
964
+ },
810
965
  );
811
- const setValidValue = (valueId, value) => {
812
- if (!collHas(valuesMap, valueId)) {
813
- valueIdsChanged(valueId, 1);
814
- }
815
- const oldValue = mapGet(valuesMap, valueId);
816
- if (value !== oldValue) {
817
- valueChanged(valueId, oldValue, value);
818
- mapSet(valuesMap, valueId, value);
819
- }
820
- };
821
966
  const getNewRowId = (tableId, reuse) => {
822
967
  const [getId] = mapGet(tablePoolFunctions, tableId);
823
968
  let rowId;
@@ -827,14 +972,34 @@ const createStore = () => {
827
972
  return rowId;
828
973
  };
829
974
  const getOrCreateTable = (tableId) =>
830
- mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
831
- const delValidTable = (tableId) => setValidTable(tableId, {});
975
+ mapEnsure(tablesMap, tableId, () => {
976
+ tableIdsChanged(tableId, 1);
977
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
978
+ mapSet(tableCellIds, tableId, mapNew());
979
+ return mapNew();
980
+ });
981
+ const delValidTable = (tableId) => {
982
+ if (whileMutating(() => middleware[8]?.(tableId)) ?? true) {
983
+ return setValidTable(tableId, {}, true);
984
+ }
985
+ return mapGet(tablesMap, tableId);
986
+ };
832
987
  const delValidRow = (tableId, tableMap, rowId) => {
833
- const [, releaseId] = mapGet(tablePoolFunctions, tableId);
834
- releaseId(rowId);
835
- setValidRow(tableId, tableMap, rowId, {}, true);
988
+ if (whileMutating(() => middleware[9]?.(tableId, rowId)) ?? true) {
989
+ const [, releaseId] = mapGet(tablePoolFunctions, tableId);
990
+ releaseId(rowId);
991
+ setValidRow(tableId, tableMap, rowId, {}, true);
992
+ }
836
993
  };
837
- const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
994
+ const delValidCell = (
995
+ tableId,
996
+ table,
997
+ rowId,
998
+ row,
999
+ cellId,
1000
+ forceDel,
1001
+ skipMiddleware,
1002
+ ) => {
838
1003
  const defaultCell = mapGet(
839
1004
  mapGet(tablesSchemaRowCache, tableId)?.[0],
840
1005
  cellId,
@@ -842,34 +1007,44 @@ const createStore = () => {
842
1007
  if (!isUndefined(defaultCell) && !forceDel) {
843
1008
  return setValidCell(tableId, rowId, row, cellId, defaultCell);
844
1009
  }
845
- const delCell2 = (cellId2) => {
846
- cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
847
- cellIdsChanged(tableId, rowId, cellId2, -1);
848
- mapSet(row, cellId2);
849
- };
850
- if (isUndefined(defaultCell)) {
851
- delCell2(cellId);
852
- } else {
853
- mapForEach(row, delCell2);
854
- }
855
- if (collIsEmpty(row)) {
856
- rowIdsChanged(tableId, rowId, -1);
857
- if (collIsEmpty(mapSet(table, rowId))) {
858
- tableIdsChanged(tableId, -1);
859
- mapSet(tablesMap, tableId);
860
- mapSet(tablePoolFunctions, tableId);
861
- mapSet(tableCellIds, tableId);
1010
+ if (
1011
+ skipMiddleware ||
1012
+ (whileMutating(() => middleware[10]?.(tableId, rowId, cellId)) ?? true)
1013
+ ) {
1014
+ const delCell2 = (cellId2) => {
1015
+ cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
1016
+ cellIdsChanged(tableId, rowId, cellId2, -1);
1017
+ mapSet(row, cellId2);
1018
+ };
1019
+ if (isUndefined(defaultCell)) {
1020
+ delCell2(cellId);
1021
+ } else {
1022
+ mapForEach(row, delCell2);
1023
+ }
1024
+ if (collIsEmpty(row)) {
1025
+ rowIdsChanged(tableId, rowId, -1);
1026
+ if (collIsEmpty(mapSet(table, rowId))) {
1027
+ tableIdsChanged(tableId, -1);
1028
+ mapSet(tablesMap, tableId);
1029
+ mapSet(tablePoolFunctions, tableId);
1030
+ mapSet(tableCellIds, tableId);
1031
+ }
862
1032
  }
863
1033
  }
864
1034
  };
865
- const delValidValue = (valueId) => {
1035
+ const delValidValue = (valueId, skipMiddleware) => {
866
1036
  const defaultValue = mapGet(valuesDefaulted, valueId);
867
1037
  if (!isUndefined(defaultValue)) {
868
1038
  return setValidValue(valueId, defaultValue);
869
1039
  }
870
- valueChanged(valueId, mapGet(valuesMap, valueId));
871
- valueIdsChanged(valueId, -1);
872
- mapSet(valuesMap, valueId);
1040
+ if (
1041
+ skipMiddleware ||
1042
+ (whileMutating(() => middleware[12]?.(valueId)) ?? true)
1043
+ ) {
1044
+ valueChanged(valueId, mapGet(valuesMap, valueId));
1045
+ valueIdsChanged(valueId, -1);
1046
+ mapSet(valuesMap, valueId);
1047
+ }
873
1048
  };
874
1049
  const tableIdsChanged = (tableId, addedOrRemoved) =>
875
1050
  idsChanged(changedTableIds, tableId, addedOrRemoved);
@@ -914,13 +1089,13 @@ const createStore = () => {
914
1089
  cellId,
915
1090
  () => [oldCell, 0],
916
1091
  )[1] = newCell;
917
- internalListeners[3]?.(tableId, rowId, cellId, newCell);
1092
+ internalListeners[3]?.(tableId, rowId, cellId, newCell, mutating);
918
1093
  };
919
1094
  const valueIdsChanged = (valueId, addedOrRemoved) =>
920
1095
  idsChanged(changedValueIds, valueId, addedOrRemoved);
921
1096
  const valueChanged = (valueId, oldValue, newValue) => {
922
1097
  mapEnsure(changedValues, valueId, () => [oldValue, 0])[1] = newValue;
923
- internalListeners[4]?.(valueId, newValue);
1098
+ internalListeners[4]?.(valueId, newValue, mutating);
924
1099
  };
925
1100
  const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
926
1101
  arrayPush(
@@ -995,14 +1170,11 @@ const createStore = () => {
995
1170
  }
996
1171
  };
997
1172
  const callTabularListenersForChanges = (mutator) => {
998
- const hasTablesNow = hasTables();
999
- if (hasTablesNow != hadTables) {
1000
- callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
1001
- }
1002
- const emptySortedRowIdListeners = collIsEmpty(
1173
+ const hasHasTablesListeners = !collIsEmpty(hasTablesListeners[mutator]);
1174
+ const hasSortedRowIdListeners = !collIsEmpty(
1003
1175
  sortedRowIdsListeners[mutator],
1004
1176
  );
1005
- const emptyIdAndHasListeners =
1177
+ const hasIdOrHasListeners = !(
1006
1178
  collIsEmpty(cellIdsListeners[mutator]) &&
1007
1179
  collIsEmpty(hasCellListeners[mutator]) &&
1008
1180
  collIsEmpty(rowIdsListeners[mutator]) &&
@@ -1010,15 +1182,17 @@ const createStore = () => {
1010
1182
  collIsEmpty(tableCellIdsListeners[mutator]) &&
1011
1183
  collIsEmpty(hasTableCellListeners[mutator]) &&
1012
1184
  collIsEmpty(rowCountListeners[mutator]) &&
1013
- emptySortedRowIdListeners &&
1185
+ !hasSortedRowIdListeners &&
1014
1186
  collIsEmpty(tableIdsListeners[mutator]) &&
1015
- collIsEmpty(hasTableListeners[mutator]);
1016
- const emptyOtherListeners =
1187
+ collIsEmpty(hasTableListeners[mutator])
1188
+ );
1189
+ const hasOtherListeners = !(
1017
1190
  collIsEmpty(cellListeners[mutator]) &&
1018
1191
  collIsEmpty(rowListeners[mutator]) &&
1019
1192
  collIsEmpty(tableListeners[mutator]) &&
1020
- collIsEmpty(tablesListeners[mutator]);
1021
- if (!emptyIdAndHasListeners || !emptyOtherListeners) {
1193
+ collIsEmpty(tablesListeners[mutator])
1194
+ );
1195
+ if (hasHasTablesListeners || hasIdOrHasListeners || hasOtherListeners) {
1022
1196
  const changes = mutator
1023
1197
  ? [
1024
1198
  mapClone(changedTableIds),
@@ -1026,7 +1200,9 @@ const createStore = () => {
1026
1200
  mapClone(changedRowCount),
1027
1201
  mapClone2(changedRowIds),
1028
1202
  mapClone3(changedCellIds),
1029
- mapClone3(changedCells),
1203
+ mapClone(changedCells, (map) =>
1204
+ mapClone(map, (map2) => mapClone(map2, pairClone)),
1205
+ ),
1030
1206
  ]
1031
1207
  : [
1032
1208
  changedTableIds,
@@ -1036,7 +1212,13 @@ const createStore = () => {
1036
1212
  changedCellIds,
1037
1213
  changedCells,
1038
1214
  ];
1039
- if (!emptyIdAndHasListeners) {
1215
+ if (hasHasTablesListeners) {
1216
+ const hasTablesNow = hasTables();
1217
+ if (hasTablesNow != hadTables) {
1218
+ callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
1219
+ }
1220
+ }
1221
+ if (hasIdOrHasListeners) {
1040
1222
  callIdsAndHasListenersIfChanged(
1041
1223
  changes[0],
1042
1224
  tableIdsListeners[mutator],
@@ -1068,13 +1250,13 @@ const createStore = () => {
1068
1250
  hasRowListeners[mutator],
1069
1251
  [tableId],
1070
1252
  ) &&
1071
- !emptySortedRowIdListeners
1253
+ hasSortedRowIdListeners
1072
1254
  ) {
1073
1255
  callListeners(sortedRowIdsListeners[mutator], [tableId, null]);
1074
1256
  setAdd(calledSortableTableIds, tableId);
1075
1257
  }
1076
1258
  });
1077
- if (!emptySortedRowIdListeners) {
1259
+ if (hasSortedRowIdListeners) {
1078
1260
  collForEach(changes[5], (rows, tableId) => {
1079
1261
  if (!collHas(calledSortableTableIds, tableId)) {
1080
1262
  const sortableCellIds = setNew();
@@ -1105,7 +1287,7 @@ const createStore = () => {
1105
1287
  ),
1106
1288
  );
1107
1289
  }
1108
- if (!emptyOtherListeners) {
1290
+ if (hasOtherListeners) {
1109
1291
  let tablesChanged;
1110
1292
  collForEach(changes[5], (rows, tableId) => {
1111
1293
  let tableChanged;
@@ -1142,28 +1324,31 @@ const createStore = () => {
1142
1324
  }
1143
1325
  };
1144
1326
  const callValuesListenersForChanges = (mutator) => {
1145
- const hasValuesNow = hasValues();
1146
- if (hasValuesNow != hadValues) {
1147
- callListeners(hasValuesListeners[mutator], void 0, hasValuesNow);
1148
- }
1149
- const emptyIdAndHasListeners =
1150
- collIsEmpty(valueIdsListeners[mutator]) &&
1151
- collIsEmpty(hasValueListeners[mutator]);
1152
- const emptyOtherListeners =
1153
- collIsEmpty(valueListeners[mutator]) &&
1154
- collIsEmpty(valuesListeners[mutator]);
1155
- if (!emptyIdAndHasListeners || !emptyOtherListeners) {
1327
+ const hasHasValuesListeners = !collIsEmpty(hasValuesListeners[mutator]);
1328
+ const hasIdOrHasListeners =
1329
+ !collIsEmpty(valueIdsListeners[mutator]) ||
1330
+ !collIsEmpty(hasValueListeners[mutator]);
1331
+ const hasOtherListeners =
1332
+ !collIsEmpty(valueListeners[mutator]) ||
1333
+ !collIsEmpty(valuesListeners[mutator]);
1334
+ if (hasHasValuesListeners || hasIdOrHasListeners || hasOtherListeners) {
1156
1335
  const changes = mutator
1157
- ? [mapClone(changedValueIds), mapClone(changedValues)]
1336
+ ? [mapClone(changedValueIds), mapClone(changedValues, pairClone)]
1158
1337
  : [changedValueIds, changedValues];
1159
- if (!emptyIdAndHasListeners) {
1338
+ if (hasHasValuesListeners) {
1339
+ const hasValuesNow = hasValues();
1340
+ if (hasValuesNow != hadValues) {
1341
+ callListeners(hasValuesListeners[mutator], void 0, hasValuesNow);
1342
+ }
1343
+ }
1344
+ if (hasIdOrHasListeners) {
1160
1345
  callIdsAndHasListenersIfChanged(
1161
1346
  changes[0],
1162
1347
  valueIdsListeners[mutator],
1163
1348
  hasValueListeners[mutator],
1164
1349
  );
1165
1350
  }
1166
- if (!emptyOtherListeners) {
1351
+ if (hasOtherListeners) {
1167
1352
  let valuesChanged;
1168
1353
  collForEach(changes[1], ([oldValue, newValue], valueId) => {
1169
1354
  if (newValue !== oldValue) {
@@ -1318,14 +1503,14 @@ const createStore = () => {
1318
1503
  if (validateRow(tableId2, rowId2, partialRow, 1)) {
1319
1504
  const table = getOrCreateTable(tableId2);
1320
1505
  objMap(partialRow, (cell, cellId) =>
1321
- setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
1506
+ setCellIntoNewRow(tableId2, table, rowId2, cellId, cell),
1322
1507
  );
1323
1508
  }
1324
1509
  },
1325
1510
  tableId,
1326
1511
  rowId,
1327
1512
  );
1328
- const setCell = (tableId, rowId, cellId, cell) =>
1513
+ const setCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
1329
1514
  fluentTransaction(
1330
1515
  (tableId2, rowId2, cellId2) =>
1331
1516
  ifNotUndefined(
@@ -1336,12 +1521,13 @@ const createStore = () => {
1336
1521
  isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
1337
1522
  ),
1338
1523
  (validCell) =>
1339
- setCellIntoDefaultRow(
1524
+ setCellIntoNewRow(
1340
1525
  tableId2,
1341
1526
  getOrCreateTable(tableId2),
1342
1527
  rowId2,
1343
1528
  cellId2,
1344
1529
  validCell,
1530
+ skipMiddleware,
1345
1531
  ),
1346
1532
  ),
1347
1533
  tableId,
@@ -1360,7 +1546,7 @@ const createStore = () => {
1360
1546
  )
1361
1547
  : 0,
1362
1548
  );
1363
- const setValue = (valueId, value) =>
1549
+ const setValue = (valueId, value, skipMiddleware) =>
1364
1550
  fluentTransaction(
1365
1551
  (valueId2) =>
1366
1552
  ifNotUndefined(
@@ -1368,27 +1554,40 @@ const createStore = () => {
1368
1554
  valueId2,
1369
1555
  isFunction(value) ? value(getValue(valueId2)) : value,
1370
1556
  ),
1371
- (validValue) => setValidValue(valueId2, validValue),
1557
+ (validValue) => setValidValue(valueId2, validValue, skipMiddleware),
1372
1558
  ),
1373
1559
  valueId,
1374
1560
  );
1375
1561
  const applyChanges = (changes) =>
1376
- fluentTransaction(() => {
1377
- objMap(changes[0], (table, tableId) =>
1378
- isUndefined(table)
1379
- ? delTable(tableId)
1380
- : objMap(table, (row, rowId) =>
1381
- isUndefined(row)
1382
- ? delRow(tableId, rowId)
1383
- : objMap(row, (cell, cellId) =>
1384
- setOrDelCell(store, tableId, rowId, cellId, cell),
1385
- ),
1386
- ),
1387
- );
1388
- objMap(changes[1], (value, valueId) =>
1389
- setOrDelValue(store, valueId, value),
1390
- );
1391
- });
1562
+ fluentTransaction(() =>
1563
+ ifTransformed(
1564
+ changes,
1565
+ () =>
1566
+ ifNotUndefined(
1567
+ middleware[13],
1568
+ (willApplyChanges) =>
1569
+ whileMutating(() => willApplyChanges(structuredClone(changes))),
1570
+ () => changes,
1571
+ ),
1572
+ (changes2) => {
1573
+ objMap(changes2[0], (table, tableId) =>
1574
+ isUndefined(table)
1575
+ ? delTable(tableId)
1576
+ : objMap(table, (row, rowId) =>
1577
+ isUndefined(row)
1578
+ ? delRow(tableId, rowId)
1579
+ : objMap(row, (cell, cellId) =>
1580
+ setOrDelCell(tableId, rowId, cellId, cell),
1581
+ ),
1582
+ ),
1583
+ );
1584
+ objMap(changes2[1], (value, valueId) =>
1585
+ setOrDelValue(valueId, value),
1586
+ );
1587
+ },
1588
+ contentOrChangesIsEqual,
1589
+ ),
1590
+ );
1392
1591
  const setTablesJson = (tablesJson) => {
1393
1592
  tryCatch(() => setOrDelTables(jsonParse(tablesJson)));
1394
1593
  return store;
@@ -1435,7 +1634,12 @@ const createStore = () => {
1435
1634
  setTablesSchema(tablesSchema);
1436
1635
  setValuesSchema(valuesSchema);
1437
1636
  });
1438
- const delTables = () => fluentTransaction(() => setValidTables({}));
1637
+ const delTables = () =>
1638
+ fluentTransaction(() =>
1639
+ (whileMutating(() => middleware[7]?.()) ?? true)
1640
+ ? setValidTables({}, true)
1641
+ : 0,
1642
+ );
1439
1643
  const delTable = (tableId) =>
1440
1644
  fluentTransaction(
1441
1645
  (tableId2) =>
@@ -1453,7 +1657,7 @@ const createStore = () => {
1453
1657
  tableId,
1454
1658
  rowId,
1455
1659
  );
1456
- const delCell = (tableId, rowId, cellId, forceDel) =>
1660
+ const delCell = (tableId, rowId, cellId, forceDel, skipMiddleware) =>
1457
1661
  fluentTransaction(
1458
1662
  (tableId2, rowId2, cellId2) =>
1459
1663
  ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
@@ -1466,6 +1670,7 @@ const createStore = () => {
1466
1670
  rowMap,
1467
1671
  cellId2,
1468
1672
  forceDel,
1673
+ skipMiddleware,
1469
1674
  )
1470
1675
  : 0,
1471
1676
  ),
@@ -1474,11 +1679,18 @@ const createStore = () => {
1474
1679
  rowId,
1475
1680
  cellId,
1476
1681
  );
1477
- const delValues = () => fluentTransaction(() => setValidValues({}));
1478
- const delValue = (valueId) =>
1682
+ const delValues = () =>
1683
+ fluentTransaction(() =>
1684
+ (whileMutating(() => middleware[11]?.()) ?? true)
1685
+ ? setValidValues({}, true)
1686
+ : 0,
1687
+ );
1688
+ const delValue = (valueId, skipMiddleware) =>
1479
1689
  fluentTransaction(
1480
1690
  (valueId2) =>
1481
- collHas(valuesMap, valueId2) ? delValidValue(valueId2) : 0,
1691
+ collHas(valuesMap, valueId2)
1692
+ ? delValidValue(valueId2, skipMiddleware)
1693
+ : 0,
1482
1694
  valueId,
1483
1695
  );
1484
1696
  const delTablesSchema = () =>
@@ -1560,25 +1772,27 @@ const createStore = () => {
1560
1772
  transactions--;
1561
1773
  if (transactions == 0) {
1562
1774
  transactions = 1;
1563
- callInvalidCellListeners(1);
1564
- if (!collIsEmpty(changedCells)) {
1565
- callTabularListenersForChanges(1);
1566
- }
1567
- callInvalidValueListeners(1);
1568
- if (!collIsEmpty(changedValues)) {
1569
- callValuesListenersForChanges(1);
1570
- }
1775
+ whileMutating(() => {
1776
+ callInvalidCellListeners(1);
1777
+ if (!collIsEmpty(changedCells)) {
1778
+ callTabularListenersForChanges(1);
1779
+ }
1780
+ callInvalidValueListeners(1);
1781
+ if (!collIsEmpty(changedValues)) {
1782
+ callValuesListenersForChanges(1);
1783
+ }
1784
+ });
1571
1785
  if (doRollback?.(store)) {
1572
1786
  collForEach(changedCells, (table, tableId) =>
1573
1787
  collForEach(table, (row, rowId) =>
1574
1788
  collForEach(row, ([oldCell], cellId) =>
1575
- setOrDelCell(store, tableId, rowId, cellId, oldCell),
1789
+ setOrDelCell(tableId, rowId, cellId, oldCell, true),
1576
1790
  ),
1577
1791
  ),
1578
1792
  );
1579
1793
  collClear(changedCells);
1580
1794
  collForEach(changedValues, ([oldValue], valueId) =>
1581
- setOrDelValue(store, valueId, oldValue),
1795
+ setOrDelValue(valueId, oldValue, true),
1582
1796
  );
1583
1797
  collClear(changedValues);
1584
1798
  }
@@ -1705,6 +1919,38 @@ const createStore = () => {
1705
1919
  collSize2(startTransactionListeners) +
1706
1920
  pairCollSize2(finishTransactionListeners),
1707
1921
  });
1922
+ const setMiddleware = (
1923
+ willSetContent,
1924
+ willSetTables,
1925
+ willSetTable,
1926
+ willSetRow,
1927
+ willSetCell,
1928
+ willSetValues,
1929
+ willSetValue,
1930
+ willDelTables,
1931
+ willDelTable,
1932
+ willDelRow,
1933
+ willDelCell,
1934
+ willDelValues,
1935
+ willDelValue,
1936
+ willApplyChanges,
1937
+ ) =>
1938
+ (middleware = [
1939
+ willSetContent,
1940
+ willSetTables,
1941
+ willSetTable,
1942
+ willSetRow,
1943
+ willSetCell,
1944
+ willSetValues,
1945
+ willSetValue,
1946
+ willDelTables,
1947
+ willDelTable,
1948
+ willDelRow,
1949
+ willDelCell,
1950
+ willDelValues,
1951
+ willDelValue,
1952
+ willApplyChanges,
1953
+ ]);
1708
1954
  const setInternalListeners = (
1709
1955
  preStartTransaction,
1710
1956
  preFinishTransaction,
@@ -1798,6 +2044,9 @@ const createStore = () => {
1798
2044
  addListener,
1799
2045
  callListeners,
1800
2046
  setInternalListeners,
2047
+ setMiddleware,
2048
+ setOrDelCell,
2049
+ setOrDelValue,
1801
2050
  };
1802
2051
  objMap(
1803
2052
  {
@@ -1934,6 +2183,7 @@ const createMergeableStore = (uniqueId, getNow) => {
1934
2183
  let listeningToRawStoreChanges = 1;
1935
2184
  let contentStampMap = newContentStampMap();
1936
2185
  let defaultingContent = 0;
2186
+ let mutated = 0;
1937
2187
  const touchedCells = mapNew();
1938
2188
  const touchedValues = setNew();
1939
2189
  const [getNextHlc, seenHlc] = getHlcFunctions(uniqueId, getNow);
@@ -2060,12 +2310,15 @@ const createMergeableStore = (uniqueId, getNow) => {
2060
2310
  collClear(touchedCells);
2061
2311
  collClear(touchedValues);
2062
2312
  };
2063
- const cellChanged = (tableId, rowId, cellId, newCell) => {
2313
+ const cellChanged = (tableId, rowId, cellId, newCell, mutating) => {
2064
2314
  setAdd(
2065
2315
  mapEnsure(mapEnsure(touchedCells, tableId, mapNew), rowId, setNew),
2066
2316
  cellId,
2067
2317
  );
2068
- if (listeningToRawStoreChanges) {
2318
+ if (listeningToRawStoreChanges || mutating) {
2319
+ if (mutating) {
2320
+ mutated = 1;
2321
+ }
2069
2322
  mergeContentOrChanges([
2070
2323
  [
2071
2324
  {
@@ -2088,9 +2341,12 @@ const createMergeableStore = (uniqueId, getNow) => {
2088
2341
  ]);
2089
2342
  }
2090
2343
  };
2091
- const valueChanged = (valueId, newValue) => {
2344
+ const valueChanged = (valueId, newValue, mutating) => {
2092
2345
  setAdd(touchedValues, valueId);
2093
- if (listeningToRawStoreChanges) {
2346
+ if (listeningToRawStoreChanges || mutating) {
2347
+ if (mutating) {
2348
+ mutated = 1;
2349
+ }
2094
2350
  mergeContentOrChanges([
2095
2351
  [{}],
2096
2352
  [
@@ -2308,6 +2564,11 @@ const createMergeableStore = (uniqueId, getNow) => {
2308
2564
  mergeableStore2.applyMergeableChanges(mergeableChanges);
2309
2565
  return applyMergeableChanges(mergeableChanges2);
2310
2566
  };
2567
+ const hadMutated = () => {
2568
+ const result = mutated;
2569
+ mutated = 0;
2570
+ return result;
2571
+ };
2311
2572
  const mergeableStore = {
2312
2573
  getMergeableContent,
2313
2574
  getMergeableContentHashes,
@@ -2324,6 +2585,8 @@ const createMergeableStore = (uniqueId, getNow) => {
2324
2585
  getTransactionMergeableChanges,
2325
2586
  applyMergeableChanges,
2326
2587
  merge,
2588
+ // only used internally by other modules
2589
+ hadMutated,
2327
2590
  };
2328
2591
  store.setInternalListeners(
2329
2592
  preStartTransaction,
@@ -2340,7 +2603,8 @@ const createMergeableStore = (uniqueId, getNow) => {
2340
2603
  strStartsWith(name, DEL) ||
2341
2604
  strStartsWith(name, 'apply') ||
2342
2605
  strEndsWith(name, TRANSACTION) ||
2343
- name == 'call' + LISTENER
2606
+ name == 'call' + LISTENER ||
2607
+ name == 'use'
2344
2608
  ? (...args) => {
2345
2609
  method(...args);
2346
2610
  return mergeableStore;