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
@@ -27,6 +27,7 @@ const id = (key) => EMPTY_STRING + key;
27
27
 
28
28
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
29
29
  predicate(value) ? otherwise?.() : then(value);
30
+ const GLOBAL = globalThis;
30
31
  const isFiniteNumber = isFinite;
31
32
  const isInstanceOf = (thing, cls) => thing instanceof cls;
32
33
  const isNullish = (thing) => thing == null;
@@ -40,6 +41,7 @@ const isArray = (thing) => Array.isArray(thing);
40
41
  const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
41
42
  const size = (arrayOrString) => arrayOrString.length;
42
43
  const test = (regex, subject) => regex.test(subject);
44
+ const structuredClone = GLOBAL.structuredClone;
43
45
  const tryCatch = async (action, then1, then2) => {
44
46
  try {
45
47
  return await action();
@@ -71,12 +73,6 @@ const getCellOrValueType = (cellOrValue) => {
71
73
  ? type
72
74
  : void 0;
73
75
  };
74
- const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
75
- isUndefined(cell)
76
- ? store.delCell(tableId, rowId, cellId, true)
77
- : store.setCell(tableId, rowId, cellId, cell);
78
- const setOrDelValue = (store, valueId, value) =>
79
- isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
80
76
 
81
77
  const collSizeN = (collSizer) => (coll) =>
82
78
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
@@ -122,6 +118,26 @@ const objMap = (obj, cb) =>
122
118
  objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
123
119
  const objSize = (obj) => size(objIds(obj));
124
120
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
121
+
122
+ /* istanbul ignore next */
123
+ const objIsEqual = (
124
+ obj1,
125
+ obj2,
126
+ isEqual = (value1, value2) => value1 === value2,
127
+ ) => {
128
+ const entries1 = objEntries(obj1);
129
+ return (
130
+ size(entries1) === objSize(obj2) &&
131
+ arrayEvery(entries1, ([index, value1]) =>
132
+ isObject(value1)
133
+ ? /* istanbul ignore next */
134
+ isObject(obj2[index])
135
+ ? objIsEqual(obj2[index], value1)
136
+ : false
137
+ : isEqual(value1, obj2[index]),
138
+ )
139
+ );
140
+ };
125
141
  const objValidate = (obj, validateChild, onInvalidObj, emptyIsValid = 0) => {
126
142
  if (
127
143
  isNullish(obj) ||
@@ -140,31 +156,32 @@ const objValidate = (obj, validateChild, onInvalidObj, emptyIsValid = 0) => {
140
156
  return emptyIsValid ? true : !objIsEmpty(obj);
141
157
  };
142
158
 
143
- const mapNew = (entries) => new Map(entries);
144
- const mapKeys = (map) => [...(map?.keys() ?? [])];
145
- const mapGet = (map, key) => map?.get(key);
146
- const mapForEach = (map, cb) =>
147
- collForEach(map, (value, key) => cb(key, value));
159
+ const map = Map;
160
+ const mapNew = (entries) => new map(entries);
161
+ const mapKeys = (map2) => [...(map2?.keys() ?? [])];
162
+ const mapGet = (map2, key) => map2?.get(key);
163
+ const mapForEach = (map2, cb) =>
164
+ collForEach(map2, (value, key) => cb(key, value));
148
165
  const mapMap = (coll, cb) =>
149
166
  arrayMap([...(coll?.entries() ?? [])], ([key, value]) => cb(value, key));
150
- const mapSet = (map, key, value) =>
151
- isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
152
- const mapEnsure = (map, key, getDefaultValue, hadExistingValue) => {
153
- if (!collHas(map, key)) {
154
- mapSet(map, key, getDefaultValue());
167
+ const mapSet = (map2, key, value) =>
168
+ isUndefined(value) ? (collDel(map2, key), map2) : map2?.set(key, value);
169
+ const mapEnsure = (map2, key, getDefaultValue, hadExistingValue) => {
170
+ if (!collHas(map2, key)) {
171
+ mapSet(map2, key, getDefaultValue());
155
172
  } else {
156
- hadExistingValue?.(mapGet(map, key));
173
+ hadExistingValue?.(mapGet(map2, key));
157
174
  }
158
- return mapGet(map, key);
175
+ return mapGet(map2, key);
159
176
  };
160
- const mapMatch = (map, obj, set, del = mapSet) => {
161
- objMap(obj, (value, id) => set(map, id, value));
162
- mapForEach(map, (id) => (objHas(obj, id) ? 0 : del(map, id)));
163
- return map;
177
+ const mapMatch = (map2, obj, set, del = mapSet) => {
178
+ objMap(obj, (value, id) => set(map2, id, value));
179
+ mapForEach(map2, (id) => (objHas(obj, id) ? 0 : del(map2, id)));
180
+ return map2;
164
181
  };
165
- const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
182
+ const mapToObj = (map2, valueMapper, excludeMapValue, excludeObjValue) => {
166
183
  const obj = {};
167
- collForEach(map, (mapValue, id) => {
184
+ collForEach(map2, (mapValue, id) => {
168
185
  if (!excludeMapValue?.(mapValue, id)) {
169
186
  const objValue = valueMapper ? valueMapper(mapValue, id) : mapValue;
170
187
  if (!excludeObjValue?.(objValue)) {
@@ -174,27 +191,27 @@ const mapToObj = (map, valueMapper, excludeMapValue, excludeObjValue) => {
174
191
  });
175
192
  return obj;
176
193
  };
177
- const mapToObj2 = (map, valueMapper, excludeMapValue) =>
194
+ const mapToObj2 = (map2, valueMapper, excludeMapValue) =>
178
195
  mapToObj(
179
- map,
196
+ map2,
180
197
  (childMap) => mapToObj(childMap, valueMapper, excludeMapValue),
181
198
  collIsEmpty,
182
199
  objIsEmpty,
183
200
  );
184
- const mapToObj3 = (map, valueMapper, excludeMapValue) =>
201
+ const mapToObj3 = (map2, valueMapper, excludeMapValue) =>
185
202
  mapToObj(
186
- map,
203
+ map2,
187
204
  (childMap) => mapToObj2(childMap, valueMapper, excludeMapValue),
188
205
  collIsEmpty,
189
206
  objIsEmpty,
190
207
  );
191
- const mapClone = (map, mapValue) => {
192
- const map2 = mapNew();
193
- collForEach(map, (value, key) => map2.set(key, mapValue?.(value) ?? value));
194
- return map2;
208
+ const mapClone = (map2, mapValue) => {
209
+ const map22 = mapNew();
210
+ collForEach(map2, (value, key) => map22.set(key, mapValue?.(value) ?? value));
211
+ return map22;
195
212
  };
196
- const mapClone2 = (map) => mapClone(map, mapClone);
197
- const mapClone3 = (map) => mapClone(map, mapClone2);
213
+ const mapClone2 = (map2) => mapClone(map2, mapClone);
214
+ const mapClone3 = (map2) => mapClone(map2, mapClone2);
198
215
  const visitTree = (node, path, ensureLeaf, pruneLeaf, p = 0) =>
199
216
  ifNotUndefined(
200
217
  (ensureLeaf ? mapEnsure : mapGet)(
@@ -333,13 +350,17 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
333
350
  id2,
334
351
  mapGet(changedIds, id2) == -addedOrRemoved ? void 0 : addedOrRemoved,
335
352
  );
353
+ const contentOrChangesIsEqual = ([tables1, values1], [tables2, values2]) =>
354
+ objIsEqual(tables1, tables2) && objIsEqual(values1, values2);
336
355
  const createStore = () => {
337
356
  let hasTablesSchema;
338
357
  let hasValuesSchema;
339
358
  let hadTables = false;
340
359
  let hadValues = false;
341
360
  let transactions = 0;
361
+ let middleware = [];
342
362
  let internalListeners = [];
363
+ let mutating = 0;
343
364
  const changedTableIds = mapNew();
344
365
  const changedTableCellIds = mapNew();
345
366
  const changedRowCount = mapNew();
@@ -385,6 +406,19 @@ const createStore = () => {
385
406
  const finishTransactionListeners = pairNewMap();
386
407
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
387
408
  getListenerFunctions(() => store);
409
+ const whileMutating = (action) => {
410
+ const wasMutating = mutating;
411
+ mutating = 1;
412
+ const result = action();
413
+ mutating = wasMutating;
414
+ return result;
415
+ };
416
+ const ifTransformed = (snapshot, getResult, then, isEqual = Object.is) =>
417
+ ifNotUndefined(getResult(), (result) =>
418
+ snapshot === result || isEqual(snapshot, result)
419
+ ? then(result)
420
+ : whileMutating(() => then(result)),
421
+ );
388
422
  const validateTablesSchema = (tableSchema) =>
389
423
  objValidate(tableSchema, (tableSchema2) =>
390
424
  objValidate(tableSchema2, validateCellOrValueSchema),
@@ -572,82 +606,194 @@ const createStore = () => {
572
606
  );
573
607
  const setOrDelTables = (tables) =>
574
608
  objIsEmpty(tables) ? delTables() : setTables(tables);
575
- const setValidContent = ([tables, values]) => {
576
- (objIsEmpty(tables) ? delTables : setTables)(tables);
577
- (objIsEmpty(values) ? delValues : setValues)(values);
578
- };
579
- const setValidTables = (tables) =>
580
- mapMatch(
581
- tablesMap,
609
+ const setOrDelCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
610
+ isUndefined(cell)
611
+ ? delCell(tableId, rowId, cellId, true, skipMiddleware)
612
+ : setCell(tableId, rowId, cellId, cell, skipMiddleware);
613
+ const setOrDelValues = (values) =>
614
+ objIsEmpty(values) ? delValues() : setValues(values);
615
+ const setOrDelValue = (valueId, value, skipMiddleware) =>
616
+ isUndefined(value)
617
+ ? delValue(valueId, skipMiddleware)
618
+ : setValue(valueId, value, skipMiddleware);
619
+ const setValidContent = (content) =>
620
+ ifTransformed(
621
+ content,
622
+ () =>
623
+ ifNotUndefined(
624
+ middleware[0],
625
+ (willSetContent) =>
626
+ whileMutating(() => willSetContent(structuredClone(content))),
627
+ () => content,
628
+ ),
629
+ ([tables, values]) => {
630
+ (objIsEmpty(tables) ? delTables : setTables)(tables);
631
+ (objIsEmpty(values) ? delValues : setValues)(values);
632
+ },
633
+ contentOrChangesIsEqual,
634
+ );
635
+ const setValidTables = (tables, forceDel) =>
636
+ ifTransformed(
582
637
  tables,
583
- (_tables, tableId, table) => setValidTable(tableId, table),
584
- (_tables, tableId) => delValidTable(tableId),
638
+ () =>
639
+ forceDel
640
+ ? tables
641
+ : ifNotUndefined(
642
+ middleware[1],
643
+ (willSetTables) =>
644
+ whileMutating(() => willSetTables(structuredClone(tables))),
645
+ () => tables,
646
+ ),
647
+ (validTables) =>
648
+ mapMatch(
649
+ tablesMap,
650
+ validTables,
651
+ (_tables, tableId, table) => setValidTable(tableId, table),
652
+ (_tables, tableId) => delValidTable(tableId),
653
+ ),
654
+ objIsEqual,
585
655
  );
586
- const setValidTable = (tableId, table) =>
587
- mapMatch(
588
- mapEnsure(tablesMap, tableId, () => {
589
- tableIdsChanged(tableId, 1);
590
- mapSet(tablePoolFunctions, tableId, getPoolFunctions());
591
- mapSet(tableCellIds, tableId, mapNew());
592
- return mapNew();
593
- }),
656
+ const setValidTable = (tableId, table, forceDel) =>
657
+ ifTransformed(
594
658
  table,
595
- (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
596
- (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
659
+ () =>
660
+ forceDel
661
+ ? table
662
+ : ifNotUndefined(
663
+ middleware[2],
664
+ (willSetTable) =>
665
+ whileMutating(() =>
666
+ willSetTable(tableId, structuredClone(table)),
667
+ ),
668
+ () => table,
669
+ ),
670
+ (validTable) =>
671
+ mapMatch(
672
+ mapEnsure(tablesMap, tableId, () => {
673
+ tableIdsChanged(tableId, 1);
674
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
675
+ mapSet(tableCellIds, tableId, mapNew());
676
+ return mapNew();
677
+ }),
678
+ validTable,
679
+ (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
680
+ (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
681
+ ),
682
+ objIsEqual,
597
683
  );
598
684
  const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
599
- mapMatch(
600
- mapEnsure(tableMap, rowId, () => {
601
- rowIdsChanged(tableId, rowId, 1);
602
- return mapNew();
603
- }),
685
+ ifTransformed(
604
686
  row,
605
- (rowMap, cellId, cell) =>
606
- setValidCell(tableId, rowId, rowMap, cellId, cell),
607
- (rowMap, cellId) =>
608
- delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
687
+ () =>
688
+ forceDel
689
+ ? row
690
+ : ifNotUndefined(
691
+ middleware[3],
692
+ (willSetRow) =>
693
+ whileMutating(() =>
694
+ willSetRow(tableId, rowId, structuredClone(row)),
695
+ ),
696
+ () => row,
697
+ ),
698
+ (validRow) =>
699
+ mapMatch(
700
+ mapEnsure(tableMap, rowId, () => {
701
+ rowIdsChanged(tableId, rowId, 1);
702
+ return mapNew();
703
+ }),
704
+ validRow,
705
+ (rowMap, cellId, cell) =>
706
+ setValidCell(tableId, rowId, rowMap, cellId, cell),
707
+ (rowMap, cellId) =>
708
+ delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
709
+ ),
710
+ objIsEqual,
609
711
  );
610
- const setValidCell = (tableId, rowId, rowMap, cellId, cell) => {
611
- if (!collHas(rowMap, cellId)) {
612
- cellIdsChanged(tableId, rowId, cellId, 1);
613
- }
614
- const oldCell = mapGet(rowMap, cellId);
615
- if (cell !== oldCell) {
616
- cellChanged(tableId, rowId, cellId, oldCell, cell);
617
- mapSet(rowMap, cellId, cell);
618
- }
619
- };
620
- const setCellIntoDefaultRow = (tableId, tableMap, rowId, cellId, validCell) =>
712
+ const setValidCell = (tableId, rowId, rowMap, cellId, cell, skipMiddleware) =>
713
+ ifTransformed(
714
+ cell,
715
+ () =>
716
+ ifNotUndefined(
717
+ skipMiddleware ? void 0 : middleware[4],
718
+ (willSetCell) =>
719
+ whileMutating(() => willSetCell(tableId, rowId, cellId, cell)),
720
+ () => cell,
721
+ ),
722
+ (cell2) => {
723
+ if (!collHas(rowMap, cellId)) {
724
+ cellIdsChanged(tableId, rowId, cellId, 1);
725
+ }
726
+ const oldCell = mapGet(rowMap, cellId);
727
+ if (cell2 !== oldCell) {
728
+ cellChanged(tableId, rowId, cellId, oldCell, cell2);
729
+ mapSet(rowMap, cellId, cell2);
730
+ }
731
+ },
732
+ );
733
+ const setCellIntoNewRow = (
734
+ tableId,
735
+ tableMap,
736
+ rowId,
737
+ cellId,
738
+ validCell,
739
+ skipMiddleware,
740
+ ) =>
621
741
  ifNotUndefined(
622
742
  mapGet(tableMap, rowId),
623
- (rowMap) => setValidCell(tableId, rowId, rowMap, cellId, validCell),
624
- () =>
625
- setValidRow(
626
- tableId,
627
- tableMap,
628
- rowId,
743
+ (rowMap) =>
744
+ setValidCell(tableId, rowId, rowMap, cellId, validCell, skipMiddleware),
745
+ () => {
746
+ const rowMap = mapNew();
747
+ mapSet(tableMap, rowId, rowMap);
748
+ rowIdsChanged(tableId, rowId, 1);
749
+ objMap(
629
750
  addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
630
- ),
751
+ (cell, cellId2) =>
752
+ setValidCell(tableId, rowId, rowMap, cellId2, cell, skipMiddleware),
753
+ );
754
+ },
631
755
  );
632
- const setOrDelValues = (values) =>
633
- objIsEmpty(values) ? delValues() : setValues(values);
634
- const setValidValues = (values) =>
635
- mapMatch(
636
- valuesMap,
756
+ const setValidValues = (values, forceDel) =>
757
+ ifTransformed(
637
758
  values,
638
- (_valuesMap, valueId, value) => setValidValue(valueId, value),
639
- (_valuesMap, valueId) => delValidValue(valueId),
759
+ () =>
760
+ forceDel
761
+ ? values
762
+ : ifNotUndefined(
763
+ middleware[5],
764
+ (willSetValues) =>
765
+ whileMutating(() => willSetValues(structuredClone(values))),
766
+ () => values,
767
+ ),
768
+ (validValues) =>
769
+ mapMatch(
770
+ valuesMap,
771
+ validValues,
772
+ (_valuesMap, valueId, value) => setValidValue(valueId, value),
773
+ (_valuesMap, valueId) => delValidValue(valueId),
774
+ ),
775
+ objIsEqual,
776
+ );
777
+ const setValidValue = (valueId, value, skipMiddleware) =>
778
+ ifTransformed(
779
+ value,
780
+ () =>
781
+ ifNotUndefined(
782
+ skipMiddleware ? void 0 : middleware[6],
783
+ (willSetValue) => whileMutating(() => willSetValue(valueId, value)),
784
+ () => value,
785
+ ),
786
+ (value2) => {
787
+ if (!collHas(valuesMap, valueId)) {
788
+ valueIdsChanged(valueId, 1);
789
+ }
790
+ const oldValue = mapGet(valuesMap, valueId);
791
+ if (value2 !== oldValue) {
792
+ valueChanged(valueId, oldValue, value2);
793
+ mapSet(valuesMap, valueId, value2);
794
+ }
795
+ },
640
796
  );
641
- const setValidValue = (valueId, value) => {
642
- if (!collHas(valuesMap, valueId)) {
643
- valueIdsChanged(valueId, 1);
644
- }
645
- const oldValue = mapGet(valuesMap, valueId);
646
- if (value !== oldValue) {
647
- valueChanged(valueId, oldValue, value);
648
- mapSet(valuesMap, valueId, value);
649
- }
650
- };
651
797
  const getNewRowId = (tableId, reuse) => {
652
798
  const [getId] = mapGet(tablePoolFunctions, tableId);
653
799
  let rowId;
@@ -657,14 +803,34 @@ const createStore = () => {
657
803
  return rowId;
658
804
  };
659
805
  const getOrCreateTable = (tableId) =>
660
- mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
661
- const delValidTable = (tableId) => setValidTable(tableId, {});
806
+ mapEnsure(tablesMap, tableId, () => {
807
+ tableIdsChanged(tableId, 1);
808
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
809
+ mapSet(tableCellIds, tableId, mapNew());
810
+ return mapNew();
811
+ });
812
+ const delValidTable = (tableId) => {
813
+ if (whileMutating(() => middleware[8]?.(tableId)) ?? true) {
814
+ return setValidTable(tableId, {}, true);
815
+ }
816
+ return mapGet(tablesMap, tableId);
817
+ };
662
818
  const delValidRow = (tableId, tableMap, rowId) => {
663
- const [, releaseId] = mapGet(tablePoolFunctions, tableId);
664
- releaseId(rowId);
665
- setValidRow(tableId, tableMap, rowId, {}, true);
819
+ if (whileMutating(() => middleware[9]?.(tableId, rowId)) ?? true) {
820
+ const [, releaseId] = mapGet(tablePoolFunctions, tableId);
821
+ releaseId(rowId);
822
+ setValidRow(tableId, tableMap, rowId, {}, true);
823
+ }
666
824
  };
667
- const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
825
+ const delValidCell = (
826
+ tableId,
827
+ table,
828
+ rowId,
829
+ row,
830
+ cellId,
831
+ forceDel,
832
+ skipMiddleware,
833
+ ) => {
668
834
  const defaultCell = mapGet(
669
835
  mapGet(tablesSchemaRowCache, tableId)?.[0],
670
836
  cellId,
@@ -672,34 +838,44 @@ const createStore = () => {
672
838
  if (!isUndefined(defaultCell) && !forceDel) {
673
839
  return setValidCell(tableId, rowId, row, cellId, defaultCell);
674
840
  }
675
- const delCell2 = (cellId2) => {
676
- cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
677
- cellIdsChanged(tableId, rowId, cellId2, -1);
678
- mapSet(row, cellId2);
679
- };
680
- if (isUndefined(defaultCell)) {
681
- delCell2(cellId);
682
- } else {
683
- mapForEach(row, delCell2);
684
- }
685
- if (collIsEmpty(row)) {
686
- rowIdsChanged(tableId, rowId, -1);
687
- if (collIsEmpty(mapSet(table, rowId))) {
688
- tableIdsChanged(tableId, -1);
689
- mapSet(tablesMap, tableId);
690
- mapSet(tablePoolFunctions, tableId);
691
- mapSet(tableCellIds, tableId);
841
+ if (
842
+ skipMiddleware ||
843
+ (whileMutating(() => middleware[10]?.(tableId, rowId, cellId)) ?? true)
844
+ ) {
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);
862
+ }
692
863
  }
693
864
  }
694
865
  };
695
- const delValidValue = (valueId) => {
866
+ const delValidValue = (valueId, skipMiddleware) => {
696
867
  const defaultValue = mapGet(valuesDefaulted, valueId);
697
868
  if (!isUndefined(defaultValue)) {
698
869
  return setValidValue(valueId, defaultValue);
699
870
  }
700
- valueChanged(valueId, mapGet(valuesMap, valueId));
701
- valueIdsChanged(valueId, -1);
702
- mapSet(valuesMap, valueId);
871
+ if (
872
+ skipMiddleware ||
873
+ (whileMutating(() => middleware[12]?.(valueId)) ?? true)
874
+ ) {
875
+ valueChanged(valueId, mapGet(valuesMap, valueId));
876
+ valueIdsChanged(valueId, -1);
877
+ mapSet(valuesMap, valueId);
878
+ }
703
879
  };
704
880
  const tableIdsChanged = (tableId, addedOrRemoved) =>
705
881
  idsChanged(changedTableIds, tableId, addedOrRemoved);
@@ -744,13 +920,13 @@ const createStore = () => {
744
920
  cellId,
745
921
  () => [oldCell, 0],
746
922
  )[1] = newCell;
747
- internalListeners[3]?.(tableId, rowId, cellId, newCell);
923
+ internalListeners[3]?.(tableId, rowId, cellId, newCell, mutating);
748
924
  };
749
925
  const valueIdsChanged = (valueId, addedOrRemoved) =>
750
926
  idsChanged(changedValueIds, valueId, addedOrRemoved);
751
927
  const valueChanged = (valueId, oldValue, newValue) => {
752
928
  mapEnsure(changedValues, valueId, () => [oldValue, 0])[1] = newValue;
753
- internalListeners[4]?.(valueId, newValue);
929
+ internalListeners[4]?.(valueId, newValue, mutating);
754
930
  };
755
931
  const cellInvalid = (tableId, rowId, cellId, invalidCell, defaultedCell) => {
756
932
  arrayPush(
@@ -825,14 +1001,11 @@ const createStore = () => {
825
1001
  }
826
1002
  };
827
1003
  const callTabularListenersForChanges = (mutator) => {
828
- const hasTablesNow = hasTables();
829
- if (hasTablesNow != hadTables) {
830
- callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
831
- }
832
- const emptySortedRowIdListeners = collIsEmpty(
1004
+ const hasHasTablesListeners = !collIsEmpty(hasTablesListeners[mutator]);
1005
+ const hasSortedRowIdListeners = !collIsEmpty(
833
1006
  sortedRowIdsListeners[mutator],
834
1007
  );
835
- const emptyIdAndHasListeners =
1008
+ const hasIdOrHasListeners = !(
836
1009
  collIsEmpty(cellIdsListeners[mutator]) &&
837
1010
  collIsEmpty(hasCellListeners[mutator]) &&
838
1011
  collIsEmpty(rowIdsListeners[mutator]) &&
@@ -840,15 +1013,17 @@ const createStore = () => {
840
1013
  collIsEmpty(tableCellIdsListeners[mutator]) &&
841
1014
  collIsEmpty(hasTableCellListeners[mutator]) &&
842
1015
  collIsEmpty(rowCountListeners[mutator]) &&
843
- emptySortedRowIdListeners &&
1016
+ !hasSortedRowIdListeners &&
844
1017
  collIsEmpty(tableIdsListeners[mutator]) &&
845
- collIsEmpty(hasTableListeners[mutator]);
846
- const emptyOtherListeners =
1018
+ collIsEmpty(hasTableListeners[mutator])
1019
+ );
1020
+ const hasOtherListeners = !(
847
1021
  collIsEmpty(cellListeners[mutator]) &&
848
1022
  collIsEmpty(rowListeners[mutator]) &&
849
1023
  collIsEmpty(tableListeners[mutator]) &&
850
- collIsEmpty(tablesListeners[mutator]);
851
- if (!emptyIdAndHasListeners || !emptyOtherListeners) {
1024
+ collIsEmpty(tablesListeners[mutator])
1025
+ );
1026
+ if (hasHasTablesListeners || hasIdOrHasListeners || hasOtherListeners) {
852
1027
  const changes = mutator
853
1028
  ? [
854
1029
  mapClone(changedTableIds),
@@ -856,7 +1031,9 @@ const createStore = () => {
856
1031
  mapClone(changedRowCount),
857
1032
  mapClone2(changedRowIds),
858
1033
  mapClone3(changedCellIds),
859
- mapClone3(changedCells),
1034
+ mapClone(changedCells, (map) =>
1035
+ mapClone(map, (map2) => mapClone(map2, pairClone)),
1036
+ ),
860
1037
  ]
861
1038
  : [
862
1039
  changedTableIds,
@@ -866,7 +1043,13 @@ const createStore = () => {
866
1043
  changedCellIds,
867
1044
  changedCells,
868
1045
  ];
869
- if (!emptyIdAndHasListeners) {
1046
+ if (hasHasTablesListeners) {
1047
+ const hasTablesNow = hasTables();
1048
+ if (hasTablesNow != hadTables) {
1049
+ callListeners(hasTablesListeners[mutator], void 0, hasTablesNow);
1050
+ }
1051
+ }
1052
+ if (hasIdOrHasListeners) {
870
1053
  callIdsAndHasListenersIfChanged(
871
1054
  changes[0],
872
1055
  tableIdsListeners[mutator],
@@ -898,13 +1081,13 @@ const createStore = () => {
898
1081
  hasRowListeners[mutator],
899
1082
  [tableId],
900
1083
  ) &&
901
- !emptySortedRowIdListeners
1084
+ hasSortedRowIdListeners
902
1085
  ) {
903
1086
  callListeners(sortedRowIdsListeners[mutator], [tableId, null]);
904
1087
  setAdd(calledSortableTableIds, tableId);
905
1088
  }
906
1089
  });
907
- if (!emptySortedRowIdListeners) {
1090
+ if (hasSortedRowIdListeners) {
908
1091
  collForEach(changes[5], (rows, tableId) => {
909
1092
  if (!collHas(calledSortableTableIds, tableId)) {
910
1093
  const sortableCellIds = setNew();
@@ -935,7 +1118,7 @@ const createStore = () => {
935
1118
  ),
936
1119
  );
937
1120
  }
938
- if (!emptyOtherListeners) {
1121
+ if (hasOtherListeners) {
939
1122
  let tablesChanged;
940
1123
  collForEach(changes[5], (rows, tableId) => {
941
1124
  let tableChanged;
@@ -972,28 +1155,31 @@ const createStore = () => {
972
1155
  }
973
1156
  };
974
1157
  const callValuesListenersForChanges = (mutator) => {
975
- const hasValuesNow = hasValues();
976
- if (hasValuesNow != hadValues) {
977
- callListeners(hasValuesListeners[mutator], void 0, hasValuesNow);
978
- }
979
- const emptyIdAndHasListeners =
980
- collIsEmpty(valueIdsListeners[mutator]) &&
981
- collIsEmpty(hasValueListeners[mutator]);
982
- const emptyOtherListeners =
983
- collIsEmpty(valueListeners[mutator]) &&
984
- collIsEmpty(valuesListeners[mutator]);
985
- if (!emptyIdAndHasListeners || !emptyOtherListeners) {
1158
+ const hasHasValuesListeners = !collIsEmpty(hasValuesListeners[mutator]);
1159
+ const hasIdOrHasListeners =
1160
+ !collIsEmpty(valueIdsListeners[mutator]) ||
1161
+ !collIsEmpty(hasValueListeners[mutator]);
1162
+ const hasOtherListeners =
1163
+ !collIsEmpty(valueListeners[mutator]) ||
1164
+ !collIsEmpty(valuesListeners[mutator]);
1165
+ if (hasHasValuesListeners || hasIdOrHasListeners || hasOtherListeners) {
986
1166
  const changes = mutator
987
- ? [mapClone(changedValueIds), mapClone(changedValues)]
1167
+ ? [mapClone(changedValueIds), mapClone(changedValues, pairClone)]
988
1168
  : [changedValueIds, changedValues];
989
- if (!emptyIdAndHasListeners) {
1169
+ if (hasHasValuesListeners) {
1170
+ const hasValuesNow = hasValues();
1171
+ if (hasValuesNow != hadValues) {
1172
+ callListeners(hasValuesListeners[mutator], void 0, hasValuesNow);
1173
+ }
1174
+ }
1175
+ if (hasIdOrHasListeners) {
990
1176
  callIdsAndHasListenersIfChanged(
991
1177
  changes[0],
992
1178
  valueIdsListeners[mutator],
993
1179
  hasValueListeners[mutator],
994
1180
  );
995
1181
  }
996
- if (!emptyOtherListeners) {
1182
+ if (hasOtherListeners) {
997
1183
  let valuesChanged;
998
1184
  collForEach(changes[1], ([oldValue, newValue], valueId) => {
999
1185
  if (newValue !== oldValue) {
@@ -1148,14 +1334,14 @@ const createStore = () => {
1148
1334
  if (validateRow(tableId2, rowId2, partialRow, 1)) {
1149
1335
  const table = getOrCreateTable(tableId2);
1150
1336
  objMap(partialRow, (cell, cellId) =>
1151
- setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
1337
+ setCellIntoNewRow(tableId2, table, rowId2, cellId, cell),
1152
1338
  );
1153
1339
  }
1154
1340
  },
1155
1341
  tableId,
1156
1342
  rowId,
1157
1343
  );
1158
- const setCell = (tableId, rowId, cellId, cell) =>
1344
+ const setCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
1159
1345
  fluentTransaction(
1160
1346
  (tableId2, rowId2, cellId2) =>
1161
1347
  ifNotUndefined(
@@ -1166,12 +1352,13 @@ const createStore = () => {
1166
1352
  isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
1167
1353
  ),
1168
1354
  (validCell) =>
1169
- setCellIntoDefaultRow(
1355
+ setCellIntoNewRow(
1170
1356
  tableId2,
1171
1357
  getOrCreateTable(tableId2),
1172
1358
  rowId2,
1173
1359
  cellId2,
1174
1360
  validCell,
1361
+ skipMiddleware,
1175
1362
  ),
1176
1363
  ),
1177
1364
  tableId,
@@ -1190,7 +1377,7 @@ const createStore = () => {
1190
1377
  )
1191
1378
  : 0,
1192
1379
  );
1193
- const setValue = (valueId, value) =>
1380
+ const setValue = (valueId, value, skipMiddleware) =>
1194
1381
  fluentTransaction(
1195
1382
  (valueId2) =>
1196
1383
  ifNotUndefined(
@@ -1198,27 +1385,40 @@ const createStore = () => {
1198
1385
  valueId2,
1199
1386
  isFunction(value) ? value(getValue(valueId2)) : value,
1200
1387
  ),
1201
- (validValue) => setValidValue(valueId2, validValue),
1388
+ (validValue) => setValidValue(valueId2, validValue, skipMiddleware),
1202
1389
  ),
1203
1390
  valueId,
1204
1391
  );
1205
1392
  const applyChanges = (changes) =>
1206
- fluentTransaction(() => {
1207
- objMap(changes[0], (table, tableId) =>
1208
- isUndefined(table)
1209
- ? delTable(tableId)
1210
- : objMap(table, (row, rowId) =>
1211
- isUndefined(row)
1212
- ? delRow(tableId, rowId)
1213
- : objMap(row, (cell, cellId) =>
1214
- setOrDelCell(store, tableId, rowId, cellId, cell),
1215
- ),
1216
- ),
1217
- );
1218
- objMap(changes[1], (value, valueId) =>
1219
- setOrDelValue(store, valueId, value),
1220
- );
1221
- });
1393
+ fluentTransaction(() =>
1394
+ ifTransformed(
1395
+ changes,
1396
+ () =>
1397
+ ifNotUndefined(
1398
+ middleware[13],
1399
+ (willApplyChanges) =>
1400
+ whileMutating(() => willApplyChanges(structuredClone(changes))),
1401
+ () => changes,
1402
+ ),
1403
+ (changes2) => {
1404
+ objMap(changes2[0], (table, tableId) =>
1405
+ isUndefined(table)
1406
+ ? delTable(tableId)
1407
+ : objMap(table, (row, rowId) =>
1408
+ isUndefined(row)
1409
+ ? delRow(tableId, rowId)
1410
+ : objMap(row, (cell, cellId) =>
1411
+ setOrDelCell(tableId, rowId, cellId, cell),
1412
+ ),
1413
+ ),
1414
+ );
1415
+ objMap(changes2[1], (value, valueId) =>
1416
+ setOrDelValue(valueId, value),
1417
+ );
1418
+ },
1419
+ contentOrChangesIsEqual,
1420
+ ),
1421
+ );
1222
1422
  const setTablesJson = (tablesJson) => {
1223
1423
  tryCatch(() => setOrDelTables(jsonParse(tablesJson)));
1224
1424
  return store;
@@ -1265,7 +1465,12 @@ const createStore = () => {
1265
1465
  setTablesSchema(tablesSchema);
1266
1466
  setValuesSchema(valuesSchema);
1267
1467
  });
1268
- const delTables = () => fluentTransaction(() => setValidTables({}));
1468
+ const delTables = () =>
1469
+ fluentTransaction(() =>
1470
+ (whileMutating(() => middleware[7]?.()) ?? true)
1471
+ ? setValidTables({}, true)
1472
+ : 0,
1473
+ );
1269
1474
  const delTable = (tableId) =>
1270
1475
  fluentTransaction(
1271
1476
  (tableId2) =>
@@ -1283,7 +1488,7 @@ const createStore = () => {
1283
1488
  tableId,
1284
1489
  rowId,
1285
1490
  );
1286
- const delCell = (tableId, rowId, cellId, forceDel) =>
1491
+ const delCell = (tableId, rowId, cellId, forceDel, skipMiddleware) =>
1287
1492
  fluentTransaction(
1288
1493
  (tableId2, rowId2, cellId2) =>
1289
1494
  ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
@@ -1296,6 +1501,7 @@ const createStore = () => {
1296
1501
  rowMap,
1297
1502
  cellId2,
1298
1503
  forceDel,
1504
+ skipMiddleware,
1299
1505
  )
1300
1506
  : 0,
1301
1507
  ),
@@ -1304,11 +1510,18 @@ const createStore = () => {
1304
1510
  rowId,
1305
1511
  cellId,
1306
1512
  );
1307
- const delValues = () => fluentTransaction(() => setValidValues({}));
1308
- const delValue = (valueId) =>
1513
+ const delValues = () =>
1514
+ fluentTransaction(() =>
1515
+ (whileMutating(() => middleware[11]?.()) ?? true)
1516
+ ? setValidValues({}, true)
1517
+ : 0,
1518
+ );
1519
+ const delValue = (valueId, skipMiddleware) =>
1309
1520
  fluentTransaction(
1310
1521
  (valueId2) =>
1311
- collHas(valuesMap, valueId2) ? delValidValue(valueId2) : 0,
1522
+ collHas(valuesMap, valueId2)
1523
+ ? delValidValue(valueId2, skipMiddleware)
1524
+ : 0,
1312
1525
  valueId,
1313
1526
  );
1314
1527
  const delTablesSchema = () =>
@@ -1390,25 +1603,27 @@ const createStore = () => {
1390
1603
  transactions--;
1391
1604
  if (transactions == 0) {
1392
1605
  transactions = 1;
1393
- callInvalidCellListeners(1);
1394
- if (!collIsEmpty(changedCells)) {
1395
- callTabularListenersForChanges(1);
1396
- }
1397
- callInvalidValueListeners(1);
1398
- if (!collIsEmpty(changedValues)) {
1399
- callValuesListenersForChanges(1);
1400
- }
1606
+ whileMutating(() => {
1607
+ callInvalidCellListeners(1);
1608
+ if (!collIsEmpty(changedCells)) {
1609
+ callTabularListenersForChanges(1);
1610
+ }
1611
+ callInvalidValueListeners(1);
1612
+ if (!collIsEmpty(changedValues)) {
1613
+ callValuesListenersForChanges(1);
1614
+ }
1615
+ });
1401
1616
  if (doRollback?.(store)) {
1402
1617
  collForEach(changedCells, (table, tableId) =>
1403
1618
  collForEach(table, (row, rowId) =>
1404
1619
  collForEach(row, ([oldCell], cellId) =>
1405
- setOrDelCell(store, tableId, rowId, cellId, oldCell),
1620
+ setOrDelCell(tableId, rowId, cellId, oldCell, true),
1406
1621
  ),
1407
1622
  ),
1408
1623
  );
1409
1624
  collClear(changedCells);
1410
1625
  collForEach(changedValues, ([oldValue], valueId) =>
1411
- setOrDelValue(store, valueId, oldValue),
1626
+ setOrDelValue(valueId, oldValue, true),
1412
1627
  );
1413
1628
  collClear(changedValues);
1414
1629
  }
@@ -1535,6 +1750,38 @@ const createStore = () => {
1535
1750
  collSize2(startTransactionListeners) +
1536
1751
  pairCollSize2(finishTransactionListeners),
1537
1752
  });
1753
+ const setMiddleware = (
1754
+ willSetContent,
1755
+ willSetTables,
1756
+ willSetTable,
1757
+ willSetRow,
1758
+ willSetCell,
1759
+ willSetValues,
1760
+ willSetValue,
1761
+ willDelTables,
1762
+ willDelTable,
1763
+ willDelRow,
1764
+ willDelCell,
1765
+ willDelValues,
1766
+ willDelValue,
1767
+ willApplyChanges,
1768
+ ) =>
1769
+ (middleware = [
1770
+ willSetContent,
1771
+ willSetTables,
1772
+ willSetTable,
1773
+ willSetRow,
1774
+ willSetCell,
1775
+ willSetValues,
1776
+ willSetValue,
1777
+ willDelTables,
1778
+ willDelTable,
1779
+ willDelRow,
1780
+ willDelCell,
1781
+ willDelValues,
1782
+ willDelValue,
1783
+ willApplyChanges,
1784
+ ]);
1538
1785
  const setInternalListeners = (
1539
1786
  preStartTransaction,
1540
1787
  preFinishTransaction,
@@ -1628,6 +1875,9 @@ const createStore = () => {
1628
1875
  addListener,
1629
1876
  callListeners,
1630
1877
  setInternalListeners,
1878
+ setMiddleware,
1879
+ setOrDelCell,
1880
+ setOrDelValue,
1631
1881
  };
1632
1882
  objMap(
1633
1883
  {