tinybase 8.0.0-beta.0 → 8.0.0-beta.2

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 +1181 -0
  4. package/@types/middleware/with-schemas/index.d.ts +1495 -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 +632 -215
  15. package/indexes/index.js +13 -12
  16. package/indexes/with-schemas/index.js +13 -12
  17. package/mergeable-store/index.js +498 -197
  18. package/mergeable-store/with-schemas/index.js +498 -197
  19. package/metrics/index.js +13 -12
  20. package/metrics/with-schemas/index.js +13 -12
  21. package/middleware/index.js +169 -0
  22. package/middleware/with-schemas/index.js +169 -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 +667 -232
  192. package/omni/with-schemas/index.js +667 -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 +59 -43
  246. package/store/index.js +479 -192
  247. package/store/with-schemas/index.js +479 -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 +475 -193
  263. package/ui-react-inspector/with-schemas/index.js +475 -193
  264. package/with-schemas/index.js +632 -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);
@@ -124,6 +119,7 @@ const isObject = (obj) =>
124
119
  const objIds = object.keys;
125
120
  const objFreeze = object.freeze;
126
121
  const objNew = (entries = []) => object.fromEntries(entries);
122
+ const objMerge = (...objs) => object.assign({}, ...objs);
127
123
  const objHas = (obj, id) => id in obj;
128
124
  const objDel = (obj, id) => {
129
125
  delete obj[id];
@@ -137,6 +133,26 @@ const objMap = (obj, cb) =>
137
133
  objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
138
134
  const objSize = (obj) => size(objIds(obj));
139
135
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
136
+
137
+ /* istanbul ignore next */
138
+ const objIsEqual = (
139
+ obj1,
140
+ obj2,
141
+ isEqual = (value1, value2) => value1 === value2,
142
+ ) => {
143
+ const entries1 = objEntries(obj1);
144
+ return (
145
+ size(entries1) === objSize(obj2) &&
146
+ arrayEvery(entries1, ([index, value1]) =>
147
+ isObject(value1)
148
+ ? /* istanbul ignore next */
149
+ isObject(obj2[index])
150
+ ? objIsEqual(obj2[index], value1)
151
+ : false
152
+ : isEqual(value1, obj2[index]),
153
+ )
154
+ );
155
+ };
140
156
  const objEnsure = (obj, id, getDefaultValue) => {
141
157
  if (!objHas(obj, id)) {
142
158
  obj[id] = getDefaultValue();
@@ -184,31 +200,32 @@ const getValueInValuesHash = (valueId, valueHash) =>
184
200
  const getValueHash = (value, valueHlc) =>
185
201
  getHash(jsonStringWithMap(value ?? null) + ':' + valueHlc);
186
202
 
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));
203
+ const map = Map;
204
+ const mapNew = (entries) => new map(entries);
205
+ const mapKeys = (map2) => [...(map2?.keys() ?? [])];
206
+ const mapGet = (map2, key) => map2?.get(key);
207
+ const mapForEach = (map2, cb) =>
208
+ collForEach(map2, (value, key) => cb(key, value));
192
209
  const mapMap = (coll, cb) =>
193
210
  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());
211
+ const mapSet = (map2, key, value) =>
212
+ isUndefined(value) ? (collDel(map2, key), map2) : map2?.set(key, value);
213
+ const mapEnsure = (map2, key, getDefaultValue, hadExistingValue) => {
214
+ if (!collHas(map2, key)) {
215
+ mapSet(map2, key, getDefaultValue());
199
216
  } else {
200
- hadExistingValue?.(mapGet(map, key));
217
+ hadExistingValue?.(mapGet(map2, key));
201
218
  }
202
- return mapGet(map, key);
219
+ return mapGet(map2, key);
203
220
  };
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;
221
+ const mapMatch = (map2, obj, set, del = mapSet) => {
222
+ objMap(obj, (value, id) => set(map2, id, value));
223
+ mapForEach(map2, (id) => (objHas(obj, id) ? 0 : del(map2, id)));
224
+ return map2;
208
225
  };
209
- const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
226
+ const mapToObj = (map2, valueMapper, excludeMapValue, excludeObjValue) => {
210
227
  const obj = {};
211
- collForEach(map, (mapValue, id) => {
228
+ collForEach(map2, (mapValue, id) => {
212
229
  if (!excludeMapValue?.(mapValue, id)) {
213
230
  const objValue = valueMapper ? valueMapper(mapValue, id) : mapValue;
214
231
  if (!excludeObjValue?.(objValue)) {
@@ -218,27 +235,27 @@ const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
218
235
  });
219
236
  return obj;
220
237
  };
221
- const mapToObj2 = (map, valueMapper, excludeMapValue) =>
238
+ const mapToObj2 = (map2, valueMapper, excludeMapValue) =>
222
239
  mapToObj(
223
- map,
240
+ map2,
224
241
  (childMap) => mapToObj(childMap, valueMapper, excludeMapValue),
225
242
  collIsEmpty,
226
243
  objIsEmpty,
227
244
  );
228
- const mapToObj3 = (map, valueMapper, excludeMapValue) =>
245
+ const mapToObj3 = (map2, valueMapper, excludeMapValue) =>
229
246
  mapToObj(
230
- map,
247
+ map2,
231
248
  (childMap) => mapToObj2(childMap, valueMapper, excludeMapValue),
232
249
  collIsEmpty,
233
250
  objIsEmpty,
234
251
  );
235
- const mapClone = (map, mapValue) => {
236
- const map2 = mapNew();
237
- collForEach(map, (value, key) => map2.set(key, mapValue?.(value) ?? value));
238
- return map2;
252
+ const mapClone = (map2, mapValue) => {
253
+ const map22 = mapNew();
254
+ collForEach(map2, (value, key) => map22.set(key, mapValue?.(value) ?? value));
255
+ return map22;
239
256
  };
240
- const mapClone2 = (map) => mapClone(map, mapClone);
241
- const mapClone3 = (map) => mapClone(map, mapClone2);
257
+ const mapClone2 = (map2) => mapClone(map2, mapClone);
258
+ const mapClone3 = (map2) => mapClone(map2, mapClone2);
242
259
  const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
243
260
  ifNotUndefined(
244
261
  (ensureLeaf ? mapEnsure : mapGet)(
@@ -503,13 +520,17 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
503
520
  id2,
504
521
  mapGet(changedIds, id2) == -addedOrRemoved ? void 0 : addedOrRemoved,
505
522
  );
523
+ const contentOrChangesIsEqual = ([tables1, values1], [tables2, values2]) =>
524
+ objIsEqual(tables1, tables2) && objIsEqual(values1, values2);
506
525
  const createStore = () => {
507
526
  let hasTablesSchema;
508
527
  let hasValuesSchema;
509
528
  let hadTables = false;
510
529
  let hadValues = false;
511
530
  let transactions = 0;
531
+ let middleware = [];
512
532
  let internalListeners = [];
533
+ let mutating = 0;
513
534
  const changedTableIds = mapNew();
514
535
  const changedTableCellIds = mapNew();
515
536
  const changedRowCount = mapNew();
@@ -555,6 +576,19 @@ const createStore = () => {
555
576
  const finishTransactionListeners = pairNewMap();
556
577
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
557
578
  getListenerFunctions(() => store);
579
+ const whileMutating = (action) => {
580
+ const wasMutating = mutating;
581
+ mutating = 1;
582
+ const result = action();
583
+ mutating = wasMutating;
584
+ return result;
585
+ };
586
+ const ifTransformed = (snapshot, getResult, then, isEqual = Object.is) =>
587
+ ifNotUndefined(getResult(), (result) =>
588
+ snapshot === result || isEqual(snapshot, result)
589
+ ? then(result)
590
+ : whileMutating(() => then(result)),
591
+ );
558
592
  const validateTablesSchema = (tableSchema) =>
559
593
  objValidate(tableSchema, (tableSchema2) =>
560
594
  objValidate(tableSchema2, validateCellOrValueSchema),
@@ -742,82 +776,194 @@ const createStore = () => {
742
776
  );
743
777
  const setOrDelTables = (tables) =>
744
778
  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,
779
+ const setOrDelCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
780
+ isUndefined(cell)
781
+ ? delCell(tableId, rowId, cellId, true, skipMiddleware)
782
+ : setCell(tableId, rowId, cellId, cell, skipMiddleware);
783
+ const setOrDelValues = (values) =>
784
+ objIsEmpty(values) ? delValues() : setValues(values);
785
+ const setOrDelValue = (valueId, value, skipMiddleware) =>
786
+ isUndefined(value)
787
+ ? delValue(valueId, skipMiddleware)
788
+ : setValue(valueId, value, skipMiddleware);
789
+ const setValidContent = (content) =>
790
+ ifTransformed(
791
+ content,
792
+ () =>
793
+ ifNotUndefined(
794
+ middleware[0],
795
+ (willSetContent) =>
796
+ whileMutating(() => willSetContent(structuredClone(content))),
797
+ () => content,
798
+ ),
799
+ ([tables, values]) => {
800
+ (objIsEmpty(tables) ? delTables : setTables)(tables);
801
+ (objIsEmpty(values) ? delValues : setValues)(values);
802
+ },
803
+ contentOrChangesIsEqual,
804
+ );
805
+ const setValidTables = (tables, forceDel) =>
806
+ ifTransformed(
752
807
  tables,
753
- (_tables, tableId, table) => setValidTable(tableId, table),
754
- (_tables, tableId) => delValidTable(tableId),
808
+ () =>
809
+ forceDel
810
+ ? tables
811
+ : ifNotUndefined(
812
+ middleware[1],
813
+ (willSetTables) =>
814
+ whileMutating(() => willSetTables(structuredClone(tables))),
815
+ () => tables,
816
+ ),
817
+ (validTables) =>
818
+ mapMatch(
819
+ tablesMap,
820
+ validTables,
821
+ (_tables, tableId, table) => setValidTable(tableId, table),
822
+ (_tables, tableId) => delValidTable(tableId),
823
+ ),
824
+ objIsEqual,
755
825
  );
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
- }),
826
+ const setValidTable = (tableId, table, forceDel) =>
827
+ ifTransformed(
764
828
  table,
765
- (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
766
- (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
829
+ () =>
830
+ forceDel
831
+ ? table
832
+ : ifNotUndefined(
833
+ middleware[2],
834
+ (willSetTable) =>
835
+ whileMutating(() =>
836
+ willSetTable(tableId, structuredClone(table)),
837
+ ),
838
+ () => table,
839
+ ),
840
+ (validTable) =>
841
+ mapMatch(
842
+ mapEnsure(tablesMap, tableId, () => {
843
+ tableIdsChanged(tableId, 1);
844
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
845
+ mapSet(tableCellIds, tableId, mapNew());
846
+ return mapNew();
847
+ }),
848
+ validTable,
849
+ (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
850
+ (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
851
+ ),
852
+ objIsEqual,
767
853
  );
768
854
  const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
769
- mapMatch(
770
- mapEnsure(tableMap, rowId, () => {
771
- rowIdsChanged(tableId, rowId, 1);
772
- return mapNew();
773
- }),
855
+ ifTransformed(
774
856
  row,
775
- (rowMap, cellId, cell) =>
776
- setValidCell(tableId, rowId, rowMap, cellId, cell),
777
- (rowMap, cellId) =>
778
- delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
857
+ () =>
858
+ forceDel
859
+ ? row
860
+ : ifNotUndefined(
861
+ middleware[3],
862
+ (willSetRow) =>
863
+ whileMutating(() =>
864
+ willSetRow(tableId, rowId, structuredClone(row)),
865
+ ),
866
+ () => row,
867
+ ),
868
+ (validRow) =>
869
+ mapMatch(
870
+ mapEnsure(tableMap, rowId, () => {
871
+ rowIdsChanged(tableId, rowId, 1);
872
+ return mapNew();
873
+ }),
874
+ validRow,
875
+ (rowMap, cellId, cell) =>
876
+ setValidCell(tableId, rowId, rowMap, cellId, cell),
877
+ (rowMap, cellId) =>
878
+ delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
879
+ ),
880
+ objIsEqual,
779
881
  );
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) =>
882
+ const setValidCell = (tableId, rowId, rowMap, cellId, cell, skipMiddleware) =>
883
+ ifTransformed(
884
+ cell,
885
+ () =>
886
+ ifNotUndefined(
887
+ skipMiddleware ? void 0 : middleware[4],
888
+ (willSetCell) =>
889
+ whileMutating(() => willSetCell(tableId, rowId, cellId, cell)),
890
+ () => cell,
891
+ ),
892
+ (cell2) => {
893
+ if (!collHas(rowMap, cellId)) {
894
+ cellIdsChanged(tableId, rowId, cellId, 1);
895
+ }
896
+ const oldCell = mapGet(rowMap, cellId);
897
+ if (cell2 !== oldCell) {
898
+ cellChanged(tableId, rowId, cellId, oldCell, cell2);
899
+ mapSet(rowMap, cellId, cell2);
900
+ }
901
+ },
902
+ );
903
+ const setCellIntoNewRow = (
904
+ tableId,
905
+ tableMap,
906
+ rowId,
907
+ cellId,
908
+ validCell,
909
+ skipMiddleware,
910
+ ) =>
791
911
  ifNotUndefined(
792
912
  mapGet(tableMap, rowId),
793
- (rowMap) => setValidCell(tableId, rowId, rowMap, cellId, validCell),
794
- () =>
795
- setValidRow(
796
- tableId,
797
- tableMap,
798
- rowId,
913
+ (rowMap) =>
914
+ setValidCell(tableId, rowId, rowMap, cellId, validCell, skipMiddleware),
915
+ () => {
916
+ const rowMap = mapNew();
917
+ mapSet(tableMap, rowId, rowMap);
918
+ rowIdsChanged(tableId, rowId, 1);
919
+ objMap(
799
920
  addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
800
- ),
921
+ (cell, cellId2) =>
922
+ setValidCell(tableId, rowId, rowMap, cellId2, cell, skipMiddleware),
923
+ );
924
+ },
801
925
  );
802
- const setOrDelValues = (values) =>
803
- objIsEmpty(values) ? delValues() : setValues(values);
804
- const setValidValues = (values) =>
805
- mapMatch(
806
- valuesMap,
926
+ const setValidValues = (values, forceDel) =>
927
+ ifTransformed(
807
928
  values,
808
- (_valuesMap, valueId, value) => setValidValue(valueId, value),
809
- (_valuesMap, valueId) => delValidValue(valueId),
929
+ () =>
930
+ forceDel
931
+ ? values
932
+ : ifNotUndefined(
933
+ middleware[5],
934
+ (willSetValues) =>
935
+ whileMutating(() => willSetValues(structuredClone(values))),
936
+ () => values,
937
+ ),
938
+ (validValues) =>
939
+ mapMatch(
940
+ valuesMap,
941
+ validValues,
942
+ (_valuesMap, valueId, value) => setValidValue(valueId, value),
943
+ (_valuesMap, valueId) => delValidValue(valueId),
944
+ ),
945
+ objIsEqual,
946
+ );
947
+ const setValidValue = (valueId, value, skipMiddleware) =>
948
+ ifTransformed(
949
+ value,
950
+ () =>
951
+ ifNotUndefined(
952
+ skipMiddleware ? void 0 : middleware[6],
953
+ (willSetValue) => whileMutating(() => willSetValue(valueId, value)),
954
+ () => value,
955
+ ),
956
+ (value2) => {
957
+ if (!collHas(valuesMap, valueId)) {
958
+ valueIdsChanged(valueId, 1);
959
+ }
960
+ const oldValue = mapGet(valuesMap, valueId);
961
+ if (value2 !== oldValue) {
962
+ valueChanged(valueId, oldValue, value2);
963
+ mapSet(valuesMap, valueId, value2);
964
+ }
965
+ },
810
966
  );
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
967
  const getNewRowId = (tableId, reuse) => {
822
968
  const [getId] = mapGet(tablePoolFunctions, tableId);
823
969
  let rowId;
@@ -827,14 +973,34 @@ const createStore = () => {
827
973
  return rowId;
828
974
  };
829
975
  const getOrCreateTable = (tableId) =>
830
- mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
831
- const delValidTable = (tableId) => setValidTable(tableId, {});
976
+ mapEnsure(tablesMap, tableId, () => {
977
+ tableIdsChanged(tableId, 1);
978
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
979
+ mapSet(tableCellIds, tableId, mapNew());
980
+ return mapNew();
981
+ });
982
+ const delValidTable = (tableId) => {
983
+ if (whileMutating(() => middleware[8]?.(tableId)) ?? true) {
984
+ return setValidTable(tableId, {}, true);
985
+ }
986
+ return mapGet(tablesMap, tableId);
987
+ };
832
988
  const delValidRow = (tableId, tableMap, rowId) => {
833
- const [, releaseId] = mapGet(tablePoolFunctions, tableId);
834
- releaseId(rowId);
835
- setValidRow(tableId, tableMap, rowId, {}, true);
989
+ if (whileMutating(() => middleware[9]?.(tableId, rowId)) ?? true) {
990
+ const [, releaseId] = mapGet(tablePoolFunctions, tableId);
991
+ releaseId(rowId);
992
+ setValidRow(tableId, tableMap, rowId, {}, true);
993
+ }
836
994
  };
837
- const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
995
+ const delValidCell = (
996
+ tableId,
997
+ table,
998
+ rowId,
999
+ row,
1000
+ cellId,
1001
+ forceDel,
1002
+ skipMiddleware,
1003
+ ) => {
838
1004
  const defaultCell = mapGet(
839
1005
  mapGet(tablesSchemaRowCache, tableId)?.[0],
840
1006
  cellId,
@@ -842,34 +1008,44 @@ const createStore = () => {
842
1008
  if (!isUndefined(defaultCell) && !forceDel) {
843
1009
  return setValidCell(tableId, rowId, row, cellId, defaultCell);
844
1010
  }
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);
1011
+ if (
1012
+ skipMiddleware ||
1013
+ (whileMutating(() => middleware[10]?.(tableId, rowId, cellId)) ?? true)
1014
+ ) {
1015
+ const delCell2 = (cellId2) => {
1016
+ cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
1017
+ cellIdsChanged(tableId, rowId, cellId2, -1);
1018
+ mapSet(row, cellId2);
1019
+ };
1020
+ if (isUndefined(defaultCell)) {
1021
+ delCell2(cellId);
1022
+ } else {
1023
+ mapForEach(row, delCell2);
1024
+ }
1025
+ if (collIsEmpty(row)) {
1026
+ rowIdsChanged(tableId, rowId, -1);
1027
+ if (collIsEmpty(mapSet(table, rowId))) {
1028
+ tableIdsChanged(tableId, -1);
1029
+ mapSet(tablesMap, tableId);
1030
+ mapSet(tablePoolFunctions, tableId);
1031
+ mapSet(tableCellIds, tableId);
1032
+ }
862
1033
  }
863
1034
  }
864
1035
  };
865
- const delValidValue = (valueId) => {
1036
+ const delValidValue = (valueId, skipMiddleware) => {
866
1037
  const defaultValue = mapGet(valuesDefaulted, valueId);
867
1038
  if (!isUndefined(defaultValue)) {
868
1039
  return setValidValue(valueId, defaultValue);
869
1040
  }
870
- valueChanged(valueId, mapGet(valuesMap, valueId));
871
- valueIdsChanged(valueId, -1);
872
- mapSet(valuesMap, valueId);
1041
+ if (
1042
+ skipMiddleware ||
1043
+ (whileMutating(() => middleware[12]?.(valueId)) ?? true)
1044
+ ) {
1045
+ valueChanged(valueId, mapGet(valuesMap, valueId));
1046
+ valueIdsChanged(valueId, -1);
1047
+ mapSet(valuesMap, valueId);
1048
+ }
873
1049
  };
874
1050
  const tableIdsChanged = (tableId, addedOrRemoved) =>
875
1051
  idsChanged(changedTableIds, tableId, addedOrRemoved);
@@ -914,13 +1090,13 @@ const createStore = () => {
914
1090
  cellId,
915
1091
  () => [oldCell, 0],
916
1092
  )[1] = newCell;
917
- internalListeners[3]?.(tableId, rowId, cellId, newCell);
1093
+ internalListeners[3]?.(tableId, rowId, cellId, newCell, mutating);
918
1094
  };
919
1095
  const valueIdsChanged = (valueId, addedOrRemoved) =>
920
1096
  idsChanged(changedValueIds, valueId, addedOrRemoved);
921
1097
  const valueChanged = (valueId, oldValue, newValue) => {
922
1098
  mapEnsure(changedValues, valueId, () => [oldValue, 0])[1] = newValue;
923
- internalListeners[4]?.(valueId, newValue);
1099
+ internalListeners[4]?.(valueId, newValue, mutating);
924
1100
  };
925
1101
  const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
926
1102
  arrayPush(
@@ -994,15 +1170,16 @@ const createStore = () => {
994
1170
  return 1;
995
1171
  }
996
1172
  };
1173
+ const clonedChangedCells = (changedCells2) =>
1174
+ mapClone(changedCells2, (map) =>
1175
+ mapClone(map, (map2) => mapClone(map2, pairClone)),
1176
+ );
997
1177
  const callTabularListenersForChanges = (mutator) => {
998
- const hasTablesNow = hasTables();
999
- if (hasTablesNow != hadTables) {
1000
- callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
1001
- }
1002
- const emptySortedRowIdListeners = collIsEmpty(
1178
+ const hasHasTablesListeners = !collIsEmpty(hasTablesListeners[mutator]);
1179
+ const hasSortedRowIdListeners = !collIsEmpty(
1003
1180
  sortedRowIdsListeners[mutator],
1004
1181
  );
1005
- const emptyIdAndHasListeners =
1182
+ const hasIdOrHasListeners = !(
1006
1183
  collIsEmpty(cellIdsListeners[mutator]) &&
1007
1184
  collIsEmpty(hasCellListeners[mutator]) &&
1008
1185
  collIsEmpty(rowIdsListeners[mutator]) &&
@@ -1010,15 +1187,17 @@ const createStore = () => {
1010
1187
  collIsEmpty(tableCellIdsListeners[mutator]) &&
1011
1188
  collIsEmpty(hasTableCellListeners[mutator]) &&
1012
1189
  collIsEmpty(rowCountListeners[mutator]) &&
1013
- emptySortedRowIdListeners &&
1190
+ !hasSortedRowIdListeners &&
1014
1191
  collIsEmpty(tableIdsListeners[mutator]) &&
1015
- collIsEmpty(hasTableListeners[mutator]);
1016
- const emptyOtherListeners =
1192
+ collIsEmpty(hasTableListeners[mutator])
1193
+ );
1194
+ const hasOtherListeners = !(
1017
1195
  collIsEmpty(cellListeners[mutator]) &&
1018
1196
  collIsEmpty(rowListeners[mutator]) &&
1019
1197
  collIsEmpty(tableListeners[mutator]) &&
1020
- collIsEmpty(tablesListeners[mutator]);
1021
- if (!emptyIdAndHasListeners || !emptyOtherListeners) {
1198
+ collIsEmpty(tablesListeners[mutator])
1199
+ );
1200
+ if (hasHasTablesListeners || hasIdOrHasListeners || hasOtherListeners) {
1022
1201
  const changes = mutator
1023
1202
  ? [
1024
1203
  mapClone(changedTableIds),
@@ -1026,7 +1205,7 @@ const createStore = () => {
1026
1205
  mapClone(changedRowCount),
1027
1206
  mapClone2(changedRowIds),
1028
1207
  mapClone3(changedCellIds),
1029
- mapClone3(changedCells),
1208
+ clonedChangedCells(changedCells),
1030
1209
  ]
1031
1210
  : [
1032
1211
  changedTableIds,
@@ -1036,7 +1215,13 @@ const createStore = () => {
1036
1215
  changedCellIds,
1037
1216
  changedCells,
1038
1217
  ];
1039
- if (!emptyIdAndHasListeners) {
1218
+ if (hasHasTablesListeners) {
1219
+ const hasTablesNow = hasTables();
1220
+ if (hasTablesNow != hadTables) {
1221
+ callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
1222
+ }
1223
+ }
1224
+ if (hasIdOrHasListeners) {
1040
1225
  callIdsAndHasListenersIfChanged(
1041
1226
  changes[0],
1042
1227
  tableIdsListeners[mutator],
@@ -1068,13 +1253,13 @@ const createStore = () => {
1068
1253
  hasRowListeners[mutator],
1069
1254
  [tableId],
1070
1255
  ) &&
1071
- !emptySortedRowIdListeners
1256
+ hasSortedRowIdListeners
1072
1257
  ) {
1073
1258
  callListeners(sortedRowIdsListeners[mutator], [tableId, null]);
1074
1259
  setAdd(calledSortableTableIds, tableId);
1075
1260
  }
1076
1261
  });
1077
- if (!emptySortedRowIdListeners) {
1262
+ if (hasSortedRowIdListeners) {
1078
1263
  collForEach(changes[5], (rows, tableId) => {
1079
1264
  if (!collHas(calledSortableTableIds, tableId)) {
1080
1265
  const sortableCellIds = setNew();
@@ -1105,7 +1290,7 @@ const createStore = () => {
1105
1290
  ),
1106
1291
  );
1107
1292
  }
1108
- if (!emptyOtherListeners) {
1293
+ if (hasOtherListeners) {
1109
1294
  let tablesChanged;
1110
1295
  collForEach(changes[5], (rows, tableId) => {
1111
1296
  let tableChanged;
@@ -1142,28 +1327,31 @@ const createStore = () => {
1142
1327
  }
1143
1328
  };
1144
1329
  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) {
1330
+ const hasHasValuesListeners = !collIsEmpty(hasValuesListeners[mutator]);
1331
+ const hasIdOrHasListeners =
1332
+ !collIsEmpty(valueIdsListeners[mutator]) ||
1333
+ !collIsEmpty(hasValueListeners[mutator]);
1334
+ const hasOtherListeners =
1335
+ !collIsEmpty(valueListeners[mutator]) ||
1336
+ !collIsEmpty(valuesListeners[mutator]);
1337
+ if (hasHasValuesListeners || hasIdOrHasListeners || hasOtherListeners) {
1156
1338
  const changes = mutator
1157
- ? [mapClone(changedValueIds), mapClone(changedValues)]
1339
+ ? [mapClone(changedValueIds), mapClone(changedValues, pairClone)]
1158
1340
  : [changedValueIds, changedValues];
1159
- if (!emptyIdAndHasListeners) {
1341
+ if (hasHasValuesListeners) {
1342
+ const hasValuesNow = hasValues();
1343
+ if (hasValuesNow != hadValues) {
1344
+ callListeners(hasValuesListeners[mutator], void 0, hasValuesNow);
1345
+ }
1346
+ }
1347
+ if (hasIdOrHasListeners) {
1160
1348
  callIdsAndHasListenersIfChanged(
1161
1349
  changes[0],
1162
1350
  valueIdsListeners[mutator],
1163
1351
  hasValueListeners[mutator],
1164
1352
  );
1165
1353
  }
1166
- if (!emptyOtherListeners) {
1354
+ if (hasOtherListeners) {
1167
1355
  let valuesChanged;
1168
1356
  collForEach(changes[1], ([oldValue, newValue], valueId) => {
1169
1357
  if (newValue !== oldValue) {
@@ -1318,14 +1506,14 @@ const createStore = () => {
1318
1506
  if (validateRow(tableId2, rowId2, partialRow, 1)) {
1319
1507
  const table = getOrCreateTable(tableId2);
1320
1508
  objMap(partialRow, (cell, cellId) =>
1321
- setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
1509
+ setCellIntoNewRow(tableId2, table, rowId2, cellId, cell),
1322
1510
  );
1323
1511
  }
1324
1512
  },
1325
1513
  tableId,
1326
1514
  rowId,
1327
1515
  );
1328
- const setCell = (tableId, rowId, cellId, cell) =>
1516
+ const setCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
1329
1517
  fluentTransaction(
1330
1518
  (tableId2, rowId2, cellId2) =>
1331
1519
  ifNotUndefined(
@@ -1336,12 +1524,13 @@ const createStore = () => {
1336
1524
  isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
1337
1525
  ),
1338
1526
  (validCell) =>
1339
- setCellIntoDefaultRow(
1527
+ setCellIntoNewRow(
1340
1528
  tableId2,
1341
1529
  getOrCreateTable(tableId2),
1342
1530
  rowId2,
1343
1531
  cellId2,
1344
1532
  validCell,
1533
+ skipMiddleware,
1345
1534
  ),
1346
1535
  ),
1347
1536
  tableId,
@@ -1360,7 +1549,7 @@ const createStore = () => {
1360
1549
  )
1361
1550
  : 0,
1362
1551
  );
1363
- const setValue = (valueId, value) =>
1552
+ const setValue = (valueId, value, skipMiddleware) =>
1364
1553
  fluentTransaction(
1365
1554
  (valueId2) =>
1366
1555
  ifNotUndefined(
@@ -1368,27 +1557,40 @@ const createStore = () => {
1368
1557
  valueId2,
1369
1558
  isFunction(value) ? value(getValue(valueId2)) : value,
1370
1559
  ),
1371
- (validValue) => setValidValue(valueId2, validValue),
1560
+ (validValue) => setValidValue(valueId2, validValue, skipMiddleware),
1372
1561
  ),
1373
1562
  valueId,
1374
1563
  );
1375
1564
  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
- });
1565
+ fluentTransaction(() =>
1566
+ ifTransformed(
1567
+ changes,
1568
+ () =>
1569
+ ifNotUndefined(
1570
+ middleware[13],
1571
+ (willApplyChanges) =>
1572
+ whileMutating(() => willApplyChanges(structuredClone(changes))),
1573
+ () => changes,
1574
+ ),
1575
+ (changes2) => {
1576
+ objMap(changes2[0], (table, tableId) =>
1577
+ isUndefined(table)
1578
+ ? delTable(tableId)
1579
+ : objMap(table, (row, rowId) =>
1580
+ isUndefined(row)
1581
+ ? delRow(tableId, rowId)
1582
+ : objMap(row, (cell, cellId) =>
1583
+ setOrDelCell(tableId, rowId, cellId, cell),
1584
+ ),
1585
+ ),
1586
+ );
1587
+ objMap(changes2[1], (value, valueId) =>
1588
+ setOrDelValue(valueId, value),
1589
+ );
1590
+ },
1591
+ contentOrChangesIsEqual,
1592
+ ),
1593
+ );
1392
1594
  const setTablesJson = (tablesJson) => {
1393
1595
  tryCatch(() => setOrDelTables(jsonParse(tablesJson)));
1394
1596
  return store;
@@ -1435,7 +1637,12 @@ const createStore = () => {
1435
1637
  setTablesSchema(tablesSchema);
1436
1638
  setValuesSchema(valuesSchema);
1437
1639
  });
1438
- const delTables = () => fluentTransaction(() => setValidTables({}));
1640
+ const delTables = () =>
1641
+ fluentTransaction(() =>
1642
+ (whileMutating(() => middleware[7]?.()) ?? true)
1643
+ ? setValidTables({}, true)
1644
+ : 0,
1645
+ );
1439
1646
  const delTable = (tableId) =>
1440
1647
  fluentTransaction(
1441
1648
  (tableId2) =>
@@ -1453,7 +1660,7 @@ const createStore = () => {
1453
1660
  tableId,
1454
1661
  rowId,
1455
1662
  );
1456
- const delCell = (tableId, rowId, cellId, forceDel) =>
1663
+ const delCell = (tableId, rowId, cellId, forceDel, skipMiddleware) =>
1457
1664
  fluentTransaction(
1458
1665
  (tableId2, rowId2, cellId2) =>
1459
1666
  ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
@@ -1466,6 +1673,7 @@ const createStore = () => {
1466
1673
  rowMap,
1467
1674
  cellId2,
1468
1675
  forceDel,
1676
+ skipMiddleware,
1469
1677
  )
1470
1678
  : 0,
1471
1679
  ),
@@ -1474,11 +1682,18 @@ const createStore = () => {
1474
1682
  rowId,
1475
1683
  cellId,
1476
1684
  );
1477
- const delValues = () => fluentTransaction(() => setValidValues({}));
1478
- const delValue = (valueId) =>
1685
+ const delValues = () =>
1686
+ fluentTransaction(() =>
1687
+ (whileMutating(() => middleware[11]?.()) ?? true)
1688
+ ? setValidValues({}, true)
1689
+ : 0,
1690
+ );
1691
+ const delValue = (valueId, skipMiddleware) =>
1479
1692
  fluentTransaction(
1480
1693
  (valueId2) =>
1481
- collHas(valuesMap, valueId2) ? delValidValue(valueId2) : 0,
1694
+ collHas(valuesMap, valueId2)
1695
+ ? delValidValue(valueId2, skipMiddleware)
1696
+ : 0,
1482
1697
  valueId,
1483
1698
  );
1484
1699
  const delTablesSchema = () =>
@@ -1555,30 +1770,64 @@ const createStore = () => {
1555
1770
  mapToObj3(changedCellIds),
1556
1771
  mapToObj(changedValueIds),
1557
1772
  ];
1773
+ const doDidSetRows = () => {
1774
+ if (middleware[14]) {
1775
+ const changedCells2 = clonedChangedCells(changedCells);
1776
+ collForEach(changedCells2, (rows, tableId) =>
1777
+ collForEach(rows, (cells, rowId) => {
1778
+ if (
1779
+ !arrayEvery(
1780
+ collValues(cells),
1781
+ ([oldCell, newCell]) => oldCell === newCell,
1782
+ )
1783
+ ) {
1784
+ const newRow = getRow(tableId, rowId);
1785
+ const oldRow = objMerge(newRow);
1786
+ collForEach(cells, ([oldCell], cellId) =>
1787
+ isUndefined(oldCell)
1788
+ ? objDel(oldRow, cellId)
1789
+ : (oldRow[cellId] = oldCell),
1790
+ );
1791
+ const didSetRow = middleware[14](tableId, rowId, oldRow, newRow);
1792
+ if (!objIsEqual(didSetRow, newRow)) {
1793
+ const setOrDelRow = objMap(newRow, () => void 0);
1794
+ objMap(didSetRow, (cell, cellId) => (setOrDelRow[cellId] = cell));
1795
+ objMap(setOrDelRow, (cell, cellId) =>
1796
+ setOrDelCell(tableId, rowId, cellId, cell, true),
1797
+ );
1798
+ }
1799
+ }
1800
+ }),
1801
+ );
1802
+ }
1803
+ };
1558
1804
  const finishTransaction = (doRollback) => {
1559
1805
  if (transactions > 0) {
1560
1806
  transactions--;
1561
1807
  if (transactions == 0) {
1562
1808
  transactions = 1;
1563
- callInvalidCellListeners(1);
1564
- if (!collIsEmpty(changedCells)) {
1565
- callTabularListenersForChanges(1);
1566
- }
1567
- callInvalidValueListeners(1);
1568
- if (!collIsEmpty(changedValues)) {
1569
- callValuesListenersForChanges(1);
1570
- }
1809
+ whileMutating(() => {
1810
+ callInvalidCellListeners(1);
1811
+ if (!collIsEmpty(changedCells)) {
1812
+ callTabularListenersForChanges(1);
1813
+ doDidSetRows();
1814
+ }
1815
+ callInvalidValueListeners(1);
1816
+ if (!collIsEmpty(changedValues)) {
1817
+ callValuesListenersForChanges(1);
1818
+ }
1819
+ });
1571
1820
  if (doRollback?.(store)) {
1572
1821
  collForEach(changedCells, (table, tableId) =>
1573
1822
  collForEach(table, (row, rowId) =>
1574
1823
  collForEach(row, ([oldCell], cellId) =>
1575
- setOrDelCell(store, tableId, rowId, cellId, oldCell),
1824
+ setOrDelCell(tableId, rowId, cellId, oldCell, true),
1576
1825
  ),
1577
1826
  ),
1578
1827
  );
1579
1828
  collClear(changedCells);
1580
1829
  collForEach(changedValues, ([oldValue], valueId) =>
1581
- setOrDelValue(store, valueId, oldValue),
1830
+ setOrDelValue(valueId, oldValue, true),
1582
1831
  );
1583
1832
  collClear(changedValues);
1584
1833
  }
@@ -1705,6 +1954,40 @@ const createStore = () => {
1705
1954
  collSize2(startTransactionListeners) +
1706
1955
  pairCollSize2(finishTransactionListeners),
1707
1956
  });
1957
+ const setMiddleware = (
1958
+ willSetContent,
1959
+ willSetTables,
1960
+ willSetTable,
1961
+ willSetRow,
1962
+ willSetCell,
1963
+ willSetValues,
1964
+ willSetValue,
1965
+ willDelTables,
1966
+ willDelTable,
1967
+ willDelRow,
1968
+ willDelCell,
1969
+ willDelValues,
1970
+ willDelValue,
1971
+ willApplyChanges,
1972
+ didSetRow,
1973
+ ) =>
1974
+ (middleware = [
1975
+ willSetContent,
1976
+ willSetTables,
1977
+ willSetTable,
1978
+ willSetRow,
1979
+ willSetCell,
1980
+ willSetValues,
1981
+ willSetValue,
1982
+ willDelTables,
1983
+ willDelTable,
1984
+ willDelRow,
1985
+ willDelCell,
1986
+ willDelValues,
1987
+ willDelValue,
1988
+ willApplyChanges,
1989
+ didSetRow,
1990
+ ]);
1708
1991
  const setInternalListeners = (
1709
1992
  preStartTransaction,
1710
1993
  preFinishTransaction,
@@ -1798,6 +2081,9 @@ const createStore = () => {
1798
2081
  addListener,
1799
2082
  callListeners,
1800
2083
  setInternalListeners,
2084
+ setMiddleware,
2085
+ setOrDelCell,
2086
+ setOrDelValue,
1801
2087
  };
1802
2088
  objMap(
1803
2089
  {
@@ -1934,6 +2220,7 @@ const createMergeableStore = (uniqueId, getNow) => {
1934
2220
  let listeningToRawStoreChanges = 1;
1935
2221
  let contentStampMap = newContentStampMap();
1936
2222
  let defaultingContent = 0;
2223
+ let mutated = 0;
1937
2224
  const touchedCells = mapNew();
1938
2225
  const touchedValues = setNew();
1939
2226
  const [getNextHlc, seenHlc] = getHlcFunctions(uniqueId, getNow);
@@ -2060,12 +2347,15 @@ const createMergeableStore = (uniqueId, getNow) => {
2060
2347
  collClear(touchedCells);
2061
2348
  collClear(touchedValues);
2062
2349
  };
2063
- const cellChanged = (tableId, rowId, cellId, newCell) => {
2350
+ const cellChanged = (tableId, rowId, cellId, newCell, mutating) => {
2064
2351
  setAdd(
2065
2352
  mapEnsure(mapEnsure(touchedCells, tableId, mapNew), rowId, setNew),
2066
2353
  cellId,
2067
2354
  );
2068
- if (listeningToRawStoreChanges) {
2355
+ if (listeningToRawStoreChanges || mutating) {
2356
+ if (mutating) {
2357
+ mutated = 1;
2358
+ }
2069
2359
  mergeContentOrChanges([
2070
2360
  [
2071
2361
  {
@@ -2088,9 +2378,12 @@ const createMergeableStore = (uniqueId, getNow) => {
2088
2378
  ]);
2089
2379
  }
2090
2380
  };
2091
- const valueChanged = (valueId, newValue) => {
2381
+ const valueChanged = (valueId, newValue, mutating) => {
2092
2382
  setAdd(touchedValues, valueId);
2093
- if (listeningToRawStoreChanges) {
2383
+ if (listeningToRawStoreChanges || mutating) {
2384
+ if (mutating) {
2385
+ mutated = 1;
2386
+ }
2094
2387
  mergeContentOrChanges([
2095
2388
  [{}],
2096
2389
  [
@@ -2308,6 +2601,11 @@ const createMergeableStore = (uniqueId, getNow) => {
2308
2601
  mergeableStore2.applyMergeableChanges(mergeableChanges);
2309
2602
  return applyMergeableChanges(mergeableChanges2);
2310
2603
  };
2604
+ const hadMutated = () => {
2605
+ const result = mutated;
2606
+ mutated = 0;
2607
+ return result;
2608
+ };
2311
2609
  const mergeableStore = {
2312
2610
  getMergeableContent,
2313
2611
  getMergeableContentHashes,
@@ -2324,6 +2622,8 @@ const createMergeableStore = (uniqueId, getNow) => {
2324
2622
  getTransactionMergeableChanges,
2325
2623
  applyMergeableChanges,
2326
2624
  merge,
2625
+ // only used internally by other modules
2626
+ hadMutated,
2327
2627
  };
2328
2628
  store.setInternalListeners(
2329
2629
  preStartTransaction,
@@ -2340,7 +2640,8 @@ const createMergeableStore = (uniqueId, getNow) => {
2340
2640
  strStartsWith(name, DEL) ||
2341
2641
  strStartsWith(name, 'apply') ||
2342
2642
  strEndsWith(name, TRANSACTION) ||
2343
- name == 'call' + LISTENER
2643
+ name == 'call' + LISTENER ||
2644
+ name == 'use'
2344
2645
  ? (...args) => {
2345
2646
  method(...args);
2346
2647
  return mergeableStore;