tinybase 5.0.0-beta.3 → 5.0.0-beta.4

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 (242) hide show
  1. package/lib/cjs/mergeable-store.cjs +1 -1
  2. package/lib/cjs/mergeable-store.cjs.gz +0 -0
  3. package/lib/cjs/persisters/persister-automerge.cjs +1 -1
  4. package/lib/cjs/persisters/persister-automerge.cjs.gz +0 -0
  5. package/lib/cjs/persisters/persister-browser.cjs +1 -1
  6. package/lib/cjs/persisters/persister-browser.cjs.gz +0 -0
  7. package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs +1 -1
  8. package/lib/cjs/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
  9. package/lib/cjs/persisters/persister-electric-sql.cjs +1 -1
  10. package/lib/cjs/persisters/persister-electric-sql.cjs.gz +0 -0
  11. package/lib/cjs/persisters/persister-expo-sqlite-next.cjs +1 -1
  12. package/lib/cjs/persisters/persister-expo-sqlite-next.cjs.gz +0 -0
  13. package/lib/cjs/persisters/persister-expo-sqlite.cjs +1 -1
  14. package/lib/cjs/persisters/persister-expo-sqlite.cjs.gz +0 -0
  15. package/lib/cjs/persisters/persister-file.cjs +1 -1
  16. package/lib/cjs/persisters/persister-file.cjs.gz +0 -0
  17. package/lib/cjs/persisters/persister-indexed-db.cjs +1 -1
  18. package/lib/cjs/persisters/persister-indexed-db.cjs.gz +0 -0
  19. package/lib/cjs/persisters/persister-partykit-client.cjs +1 -1
  20. package/lib/cjs/persisters/persister-partykit-client.cjs.gz +0 -0
  21. package/lib/cjs/persisters/persister-remote.cjs +1 -1
  22. package/lib/cjs/persisters/persister-remote.cjs.gz +0 -0
  23. package/lib/cjs/persisters/persister-sqlite-wasm.cjs +1 -1
  24. package/lib/cjs/persisters/persister-sqlite-wasm.cjs.gz +0 -0
  25. package/lib/cjs/persisters/persister-sqlite3.cjs +1 -1
  26. package/lib/cjs/persisters/persister-sqlite3.cjs.gz +0 -0
  27. package/lib/cjs/persisters/persister-yjs.cjs +1 -1
  28. package/lib/cjs/persisters/persister-yjs.cjs.gz +0 -0
  29. package/lib/cjs/persisters.cjs +1 -1
  30. package/lib/cjs/persisters.cjs.gz +0 -0
  31. package/lib/cjs/store.cjs +1 -1
  32. package/lib/cjs/store.cjs.gz +0 -0
  33. package/lib/cjs/tinybase.cjs +1 -1
  34. package/lib/cjs/tinybase.cjs.gz +0 -0
  35. package/lib/cjs/ui-react-dom-debug.cjs +1 -1
  36. package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
  37. package/lib/cjs-es6/mergeable-store.cjs +1 -1
  38. package/lib/cjs-es6/mergeable-store.cjs.gz +0 -0
  39. package/lib/cjs-es6/persisters/persister-automerge.cjs +1 -1
  40. package/lib/cjs-es6/persisters/persister-automerge.cjs.gz +0 -0
  41. package/lib/cjs-es6/persisters/persister-browser.cjs +1 -1
  42. package/lib/cjs-es6/persisters/persister-browser.cjs.gz +0 -0
  43. package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs +1 -1
  44. package/lib/cjs-es6/persisters/persister-cr-sqlite-wasm.cjs.gz +0 -0
  45. package/lib/cjs-es6/persisters/persister-electric-sql.cjs +1 -1
  46. package/lib/cjs-es6/persisters/persister-electric-sql.cjs.gz +0 -0
  47. package/lib/cjs-es6/persisters/persister-expo-sqlite-next.cjs +1 -1
  48. package/lib/cjs-es6/persisters/persister-expo-sqlite-next.cjs.gz +0 -0
  49. package/lib/cjs-es6/persisters/persister-expo-sqlite.cjs +1 -1
  50. package/lib/cjs-es6/persisters/persister-expo-sqlite.cjs.gz +0 -0
  51. package/lib/cjs-es6/persisters/persister-file.cjs +1 -1
  52. package/lib/cjs-es6/persisters/persister-file.cjs.gz +0 -0
  53. package/lib/cjs-es6/persisters/persister-indexed-db.cjs +1 -1
  54. package/lib/cjs-es6/persisters/persister-indexed-db.cjs.gz +0 -0
  55. package/lib/cjs-es6/persisters/persister-partykit-client.cjs +1 -1
  56. package/lib/cjs-es6/persisters/persister-partykit-client.cjs.gz +0 -0
  57. package/lib/cjs-es6/persisters/persister-remote.cjs +1 -1
  58. package/lib/cjs-es6/persisters/persister-remote.cjs.gz +0 -0
  59. package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs +1 -1
  60. package/lib/cjs-es6/persisters/persister-sqlite-wasm.cjs.gz +0 -0
  61. package/lib/cjs-es6/persisters/persister-sqlite3.cjs +1 -1
  62. package/lib/cjs-es6/persisters/persister-sqlite3.cjs.gz +0 -0
  63. package/lib/cjs-es6/persisters/persister-yjs.cjs +1 -1
  64. package/lib/cjs-es6/persisters/persister-yjs.cjs.gz +0 -0
  65. package/lib/cjs-es6/persisters.cjs +1 -1
  66. package/lib/cjs-es6/persisters.cjs.gz +0 -0
  67. package/lib/cjs-es6/store.cjs +1 -1
  68. package/lib/cjs-es6/store.cjs.gz +0 -0
  69. package/lib/cjs-es6/tinybase.cjs +1 -1
  70. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  71. package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -1
  72. package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
  73. package/lib/debug/mergeable-store.js +93 -52
  74. package/lib/debug/persisters/persister-automerge.js +33 -11
  75. package/lib/debug/persisters/persister-browser.js +34 -12
  76. package/lib/debug/persisters/persister-cr-sqlite-wasm.js +33 -11
  77. package/lib/debug/persisters/persister-electric-sql.js +33 -11
  78. package/lib/debug/persisters/persister-expo-sqlite-next.js +33 -11
  79. package/lib/debug/persisters/persister-expo-sqlite.js +33 -11
  80. package/lib/debug/persisters/persister-file.js +34 -12
  81. package/lib/debug/persisters/persister-indexed-db.js +33 -11
  82. package/lib/debug/persisters/persister-partykit-client.js +33 -11
  83. package/lib/debug/persisters/persister-remote.js +33 -11
  84. package/lib/debug/persisters/persister-sqlite-wasm.js +33 -11
  85. package/lib/debug/persisters/persister-sqlite3.js +33 -11
  86. package/lib/debug/persisters/persister-yjs.js +33 -11
  87. package/lib/debug/persisters.js +33 -11
  88. package/lib/debug/store.js +14 -18
  89. package/lib/debug/tinybase.js +125 -63
  90. package/lib/debug/ui-react-dom.js +48 -30
  91. package/lib/es6/mergeable-store.js +1 -1
  92. package/lib/es6/mergeable-store.js.gz +0 -0
  93. package/lib/es6/persisters/persister-automerge.js +1 -1
  94. package/lib/es6/persisters/persister-automerge.js.gz +0 -0
  95. package/lib/es6/persisters/persister-browser.js +1 -1
  96. package/lib/es6/persisters/persister-browser.js.gz +0 -0
  97. package/lib/es6/persisters/persister-cr-sqlite-wasm.js +1 -1
  98. package/lib/es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  99. package/lib/es6/persisters/persister-electric-sql.js +1 -1
  100. package/lib/es6/persisters/persister-electric-sql.js.gz +0 -0
  101. package/lib/es6/persisters/persister-expo-sqlite-next.js +1 -1
  102. package/lib/es6/persisters/persister-expo-sqlite-next.js.gz +0 -0
  103. package/lib/es6/persisters/persister-expo-sqlite.js +1 -1
  104. package/lib/es6/persisters/persister-expo-sqlite.js.gz +0 -0
  105. package/lib/es6/persisters/persister-file.js +1 -1
  106. package/lib/es6/persisters/persister-file.js.gz +0 -0
  107. package/lib/es6/persisters/persister-indexed-db.js +1 -1
  108. package/lib/es6/persisters/persister-indexed-db.js.gz +0 -0
  109. package/lib/es6/persisters/persister-partykit-client.js +1 -1
  110. package/lib/es6/persisters/persister-partykit-client.js.gz +0 -0
  111. package/lib/es6/persisters/persister-remote.js +1 -1
  112. package/lib/es6/persisters/persister-remote.js.gz +0 -0
  113. package/lib/es6/persisters/persister-sqlite-wasm.js +1 -1
  114. package/lib/es6/persisters/persister-sqlite-wasm.js.gz +0 -0
  115. package/lib/es6/persisters/persister-sqlite3.js +1 -1
  116. package/lib/es6/persisters/persister-sqlite3.js.gz +0 -0
  117. package/lib/es6/persisters/persister-yjs.js +1 -1
  118. package/lib/es6/persisters/persister-yjs.js.gz +0 -0
  119. package/lib/es6/persisters.js +1 -1
  120. package/lib/es6/persisters.js.gz +0 -0
  121. package/lib/es6/store.js +1 -1
  122. package/lib/es6/store.js.gz +0 -0
  123. package/lib/es6/tinybase.js +1 -1
  124. package/lib/es6/tinybase.js.gz +0 -0
  125. package/lib/es6/ui-react-dom-debug.js +1 -1
  126. package/lib/es6/ui-react-dom-debug.js.gz +0 -0
  127. package/lib/mergeable-store.js +1 -1
  128. package/lib/mergeable-store.js.gz +0 -0
  129. package/lib/persisters/persister-automerge.js +1 -1
  130. package/lib/persisters/persister-automerge.js.gz +0 -0
  131. package/lib/persisters/persister-browser.js +1 -1
  132. package/lib/persisters/persister-browser.js.gz +0 -0
  133. package/lib/persisters/persister-cr-sqlite-wasm.js +1 -1
  134. package/lib/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  135. package/lib/persisters/persister-electric-sql.js +1 -1
  136. package/lib/persisters/persister-electric-sql.js.gz +0 -0
  137. package/lib/persisters/persister-expo-sqlite-next.js +1 -1
  138. package/lib/persisters/persister-expo-sqlite-next.js.gz +0 -0
  139. package/lib/persisters/persister-expo-sqlite.js +1 -1
  140. package/lib/persisters/persister-expo-sqlite.js.gz +0 -0
  141. package/lib/persisters/persister-file.js +1 -1
  142. package/lib/persisters/persister-file.js.gz +0 -0
  143. package/lib/persisters/persister-indexed-db.js +1 -1
  144. package/lib/persisters/persister-indexed-db.js.gz +0 -0
  145. package/lib/persisters/persister-partykit-client.js +1 -1
  146. package/lib/persisters/persister-partykit-client.js.gz +0 -0
  147. package/lib/persisters/persister-remote.js +1 -1
  148. package/lib/persisters/persister-remote.js.gz +0 -0
  149. package/lib/persisters/persister-sqlite-wasm.js +1 -1
  150. package/lib/persisters/persister-sqlite-wasm.js.gz +0 -0
  151. package/lib/persisters/persister-sqlite3.js +1 -1
  152. package/lib/persisters/persister-sqlite3.js.gz +0 -0
  153. package/lib/persisters/persister-yjs.js +1 -1
  154. package/lib/persisters/persister-yjs.js.gz +0 -0
  155. package/lib/persisters.js +1 -1
  156. package/lib/persisters.js.gz +0 -0
  157. package/lib/store.js +1 -1
  158. package/lib/store.js.gz +0 -0
  159. package/lib/tinybase.js +1 -1
  160. package/lib/tinybase.js.gz +0 -0
  161. package/lib/types/mergeable-store.d.ts +6 -0
  162. package/lib/types/persisters/persister-browser.d.ts +2 -2
  163. package/lib/types/persisters/persister-file.d.ts +1 -1
  164. package/lib/types/persisters.d.ts +18 -7
  165. package/lib/types/with-schemas/mergeable-store.d.ts +6 -0
  166. package/lib/types/with-schemas/persisters/persister-browser.d.ts +2 -2
  167. package/lib/types/with-schemas/persisters/persister-file.d.ts +1 -1
  168. package/lib/types/with-schemas/persisters.d.ts +13 -6
  169. package/lib/umd/mergeable-store.js +1 -1
  170. package/lib/umd/mergeable-store.js.gz +0 -0
  171. package/lib/umd/persisters/persister-automerge.js +1 -1
  172. package/lib/umd/persisters/persister-automerge.js.gz +0 -0
  173. package/lib/umd/persisters/persister-browser.js +1 -1
  174. package/lib/umd/persisters/persister-browser.js.gz +0 -0
  175. package/lib/umd/persisters/persister-cr-sqlite-wasm.js +1 -1
  176. package/lib/umd/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  177. package/lib/umd/persisters/persister-electric-sql.js +1 -1
  178. package/lib/umd/persisters/persister-electric-sql.js.gz +0 -0
  179. package/lib/umd/persisters/persister-expo-sqlite-next.js +1 -1
  180. package/lib/umd/persisters/persister-expo-sqlite-next.js.gz +0 -0
  181. package/lib/umd/persisters/persister-expo-sqlite.js +1 -1
  182. package/lib/umd/persisters/persister-expo-sqlite.js.gz +0 -0
  183. package/lib/umd/persisters/persister-file.js +1 -1
  184. package/lib/umd/persisters/persister-file.js.gz +0 -0
  185. package/lib/umd/persisters/persister-indexed-db.js +1 -1
  186. package/lib/umd/persisters/persister-indexed-db.js.gz +0 -0
  187. package/lib/umd/persisters/persister-partykit-client.js +1 -1
  188. package/lib/umd/persisters/persister-partykit-client.js.gz +0 -0
  189. package/lib/umd/persisters/persister-remote.js +1 -1
  190. package/lib/umd/persisters/persister-remote.js.gz +0 -0
  191. package/lib/umd/persisters/persister-sqlite-wasm.js +1 -1
  192. package/lib/umd/persisters/persister-sqlite-wasm.js.gz +0 -0
  193. package/lib/umd/persisters/persister-sqlite3.js +1 -1
  194. package/lib/umd/persisters/persister-sqlite3.js.gz +0 -0
  195. package/lib/umd/persisters/persister-yjs.js +1 -1
  196. package/lib/umd/persisters/persister-yjs.js.gz +0 -0
  197. package/lib/umd/persisters.js +1 -1
  198. package/lib/umd/persisters.js.gz +0 -0
  199. package/lib/umd/store.js +1 -1
  200. package/lib/umd/store.js.gz +0 -0
  201. package/lib/umd/tinybase.js +1 -1
  202. package/lib/umd/tinybase.js.gz +0 -0
  203. package/lib/umd/ui-react-dom-debug.js +1 -1
  204. package/lib/umd/ui-react-dom-debug.js.gz +0 -0
  205. package/lib/umd-es6/mergeable-store.js +1 -1
  206. package/lib/umd-es6/mergeable-store.js.gz +0 -0
  207. package/lib/umd-es6/persisters/persister-automerge.js +1 -1
  208. package/lib/umd-es6/persisters/persister-automerge.js.gz +0 -0
  209. package/lib/umd-es6/persisters/persister-browser.js +1 -1
  210. package/lib/umd-es6/persisters/persister-browser.js.gz +0 -0
  211. package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js +1 -1
  212. package/lib/umd-es6/persisters/persister-cr-sqlite-wasm.js.gz +0 -0
  213. package/lib/umd-es6/persisters/persister-electric-sql.js +1 -1
  214. package/lib/umd-es6/persisters/persister-electric-sql.js.gz +0 -0
  215. package/lib/umd-es6/persisters/persister-expo-sqlite-next.js +1 -1
  216. package/lib/umd-es6/persisters/persister-expo-sqlite-next.js.gz +0 -0
  217. package/lib/umd-es6/persisters/persister-expo-sqlite.js +1 -1
  218. package/lib/umd-es6/persisters/persister-expo-sqlite.js.gz +0 -0
  219. package/lib/umd-es6/persisters/persister-file.js +1 -1
  220. package/lib/umd-es6/persisters/persister-file.js.gz +0 -0
  221. package/lib/umd-es6/persisters/persister-indexed-db.js +1 -1
  222. package/lib/umd-es6/persisters/persister-indexed-db.js.gz +0 -0
  223. package/lib/umd-es6/persisters/persister-partykit-client.js +1 -1
  224. package/lib/umd-es6/persisters/persister-partykit-client.js.gz +0 -0
  225. package/lib/umd-es6/persisters/persister-remote.js +1 -1
  226. package/lib/umd-es6/persisters/persister-remote.js.gz +0 -0
  227. package/lib/umd-es6/persisters/persister-sqlite-wasm.js +1 -1
  228. package/lib/umd-es6/persisters/persister-sqlite-wasm.js.gz +0 -0
  229. package/lib/umd-es6/persisters/persister-sqlite3.js +1 -1
  230. package/lib/umd-es6/persisters/persister-sqlite3.js.gz +0 -0
  231. package/lib/umd-es6/persisters/persister-yjs.js +1 -1
  232. package/lib/umd-es6/persisters/persister-yjs.js.gz +0 -0
  233. package/lib/umd-es6/persisters.js +1 -1
  234. package/lib/umd-es6/persisters.js.gz +0 -0
  235. package/lib/umd-es6/store.js +1 -1
  236. package/lib/umd-es6/store.js.gz +0 -0
  237. package/lib/umd-es6/tinybase.js +1 -1
  238. package/lib/umd-es6/tinybase.js.gz +0 -0
  239. package/lib/umd-es6/ui-react-dom-debug.js +1 -1
  240. package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
  241. package/package.json +14 -14
  242. package/readme.md +2 -2
@@ -66,6 +66,23 @@ const mapEnsure = (map, key, getDefaultValue) => {
66
66
 
67
67
  const scheduleRunning = mapNew();
68
68
  const scheduleActions = mapNew();
69
+ const isMergeable = (contentOrChanges) => isString(contentOrChanges?.[0]);
70
+ const getStoreFunctions = (supportsMergeableStore, store) =>
71
+ !supportsMergeableStore || isUndefined(store.getMergeableContent)
72
+ ? [
73
+ 0,
74
+ store.getContent,
75
+ store.getTransactionChanges,
76
+ ([changedTables, changedValues]) =>
77
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
78
+ ]
79
+ : [
80
+ 1,
81
+ store.getMergeableContent,
82
+ store.getTransactionMergeableChanges,
83
+ ([, [[, changedTables], [, changedValues]]]) =>
84
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
85
+ ];
69
86
  const createCustomPersister = (
70
87
  store,
71
88
  getPersisted,
@@ -86,10 +103,8 @@ const createCustomPersister = (
86
103
  let listeningHandle;
87
104
  mapEnsure(scheduleRunning, scheduleId, () => 0);
88
105
  mapEnsure(scheduleActions, scheduleId, () => []);
89
- const getContent =
90
- (supportsMergeableStore ? store.getMergeableContent : null) ??
91
- store.getContent;
92
- const getChanges = store.getTransactionChanges;
106
+ const [isMergeableStore, getContent, getChanges, hasChanges] =
107
+ getStoreFunctions(supportsMergeableStore, store);
93
108
  const run = async () => {
94
109
  /* istanbul ignore else */
95
110
  if (!mapGet(scheduleRunning, scheduleId)) {
@@ -126,8 +141,8 @@ const createCustomPersister = (
126
141
  await loadLock(async () => {
127
142
  try {
128
143
  const content = await getPersisted();
129
- (supportsMergeableStore && isString(content[0])
130
- ? store.applyMergeableChanges
144
+ (isMergeableStore && isMergeable(content)
145
+ ? store.setMergeableContent
131
146
  : store.setContent)(content);
132
147
  } catch {
133
148
  store.setContent([initialTables, initialValues]);
@@ -141,11 +156,18 @@ const createCustomPersister = (
141
156
  async (getContent2, getChanges2) => {
142
157
  if (getChanges2) {
143
158
  const changes = getChanges2();
144
- await loadLock(async () => store.applyChanges(changes));
159
+ await loadLock(async () =>
160
+ (isMergeableStore && isMergeable(changes)
161
+ ? store.applyMergeableChanges
162
+ : store.applyChanges)(changes),
163
+ );
145
164
  } else {
146
165
  await loadLock(async () => {
147
166
  try {
148
- store.setContent(getContent2?.() ?? (await getPersisted()));
167
+ const content = getContent2?.() ?? (await getPersisted());
168
+ (isMergeableStore && isMergeable(content)
169
+ ? store.setMergeableContent
170
+ : store.setContent)(content);
149
171
  } catch (error) {
150
172
  onIgnoredError?.(error);
151
173
  }
@@ -185,9 +207,9 @@ const createCustomPersister = (
185
207
  startAutoSave: async () => {
186
208
  await persister.stopAutoSave().save();
187
209
  listenerId = store.addDidFinishTransactionListener(() => {
188
- const [tableChanges, valueChanges] = getChanges();
189
- if (!objIsEmpty(tableChanges) || !objIsEmpty(valueChanges)) {
190
- persister.save(() => [tableChanges, valueChanges]);
210
+ const changes = getChanges();
211
+ if (hasChanges(changes)) {
212
+ persister.save(() => changes);
191
213
  }
192
214
  });
193
215
  return persister;
@@ -44,6 +44,23 @@ const mapEnsure = (map, key, getDefaultValue) => {
44
44
 
45
45
  const scheduleRunning = mapNew();
46
46
  const scheduleActions = mapNew();
47
+ const isMergeable = (contentOrChanges) => isString(contentOrChanges?.[0]);
48
+ const getStoreFunctions = (supportsMergeableStore, store) =>
49
+ !supportsMergeableStore || isUndefined(store.getMergeableContent)
50
+ ? [
51
+ 0,
52
+ store.getContent,
53
+ store.getTransactionChanges,
54
+ ([changedTables, changedValues]) =>
55
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
56
+ ]
57
+ : [
58
+ 1,
59
+ store.getMergeableContent,
60
+ store.getTransactionMergeableChanges,
61
+ ([, [[, changedTables], [, changedValues]]]) =>
62
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
63
+ ];
47
64
  const createCustomPersister = (
48
65
  store,
49
66
  getPersisted,
@@ -64,10 +81,8 @@ const createCustomPersister = (
64
81
  let listeningHandle;
65
82
  mapEnsure(scheduleRunning, scheduleId, () => 0);
66
83
  mapEnsure(scheduleActions, scheduleId, () => []);
67
- const getContent =
68
- (supportsMergeableStore ? store.getMergeableContent : null) ??
69
- store.getContent;
70
- const getChanges = store.getTransactionChanges;
84
+ const [isMergeableStore, getContent, getChanges, hasChanges] =
85
+ getStoreFunctions(supportsMergeableStore, store);
71
86
  const run = async () => {
72
87
  /* istanbul ignore else */
73
88
  if (!mapGet(scheduleRunning, scheduleId)) {
@@ -104,8 +119,8 @@ const createCustomPersister = (
104
119
  await loadLock(async () => {
105
120
  try {
106
121
  const content = await getPersisted();
107
- (supportsMergeableStore && isString(content[0])
108
- ? store.applyMergeableChanges
122
+ (isMergeableStore && isMergeable(content)
123
+ ? store.setMergeableContent
109
124
  : store.setContent)(content);
110
125
  } catch {
111
126
  store.setContent([initialTables, initialValues]);
@@ -119,11 +134,18 @@ const createCustomPersister = (
119
134
  async (getContent2, getChanges2) => {
120
135
  if (getChanges2) {
121
136
  const changes = getChanges2();
122
- await loadLock(async () => store.applyChanges(changes));
137
+ await loadLock(async () =>
138
+ (isMergeableStore && isMergeable(changes)
139
+ ? store.applyMergeableChanges
140
+ : store.applyChanges)(changes),
141
+ );
123
142
  } else {
124
143
  await loadLock(async () => {
125
144
  try {
126
- store.setContent(getContent2?.() ?? (await getPersisted()));
145
+ const content = getContent2?.() ?? (await getPersisted());
146
+ (isMergeableStore && isMergeable(content)
147
+ ? store.setMergeableContent
148
+ : store.setContent)(content);
127
149
  } catch (error) {
128
150
  onIgnoredError?.(error);
129
151
  }
@@ -163,9 +185,9 @@ const createCustomPersister = (
163
185
  startAutoSave: async () => {
164
186
  await persister.stopAutoSave().save();
165
187
  listenerId = store.addDidFinishTransactionListener(() => {
166
- const [tableChanges, valueChanges] = getChanges();
167
- if (!objIsEmpty(tableChanges) || !objIsEmpty(valueChanges)) {
168
- persister.save(() => [tableChanges, valueChanges]);
188
+ const changes = getChanges();
189
+ if (hasChanges(changes)) {
190
+ persister.save(() => changes);
169
191
  }
170
192
  });
171
193
  return persister;
@@ -296,12 +296,10 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
296
296
  const createStore = () => {
297
297
  let hasTablesSchema;
298
298
  let hasValuesSchema;
299
- let cellsTouched = false;
300
- let valuesTouched = false;
301
299
  let hadTables = false;
302
300
  let hadValues = false;
303
301
  let transactions = 0;
304
- let postTransactionListener;
302
+ let internalListeners = [];
305
303
  const changedTableIds = mapNew();
306
304
  const changedTableCellIds = mapNew();
307
305
  const changedRowCount = mapNew();
@@ -1261,8 +1259,8 @@ const createStore = () => {
1261
1259
  ),
1262
1260
  ];
1263
1261
  const getTransactionLog = () => [
1264
- cellsTouched,
1265
- valuesTouched,
1262
+ !collIsEmpty(changedCells),
1263
+ !collIsEmpty(changedValues),
1266
1264
  mapToObj3(changedCells, pairClone, pairIsEqual),
1267
1265
  mapToObj3(invalidCells),
1268
1266
  mapToObj(changedValues, pairClone, pairIsEqual),
@@ -1276,15 +1274,13 @@ const createStore = () => {
1276
1274
  if (transactions > 0) {
1277
1275
  transactions--;
1278
1276
  if (transactions == 0) {
1279
- cellsTouched = !collIsEmpty(changedCells);
1280
- valuesTouched = !collIsEmpty(changedValues);
1281
1277
  transactions = 1;
1282
1278
  callInvalidCellListeners(1);
1283
- if (cellsTouched) {
1279
+ if (!collIsEmpty(changedCells)) {
1284
1280
  callTabularListenersForChanges(1);
1285
1281
  }
1286
1282
  callInvalidValueListeners(1);
1287
- if (valuesTouched) {
1283
+ if (!collIsEmpty(changedValues)) {
1288
1284
  callValuesListenersForChanges(1);
1289
1285
  }
1290
1286
  if (doRollback?.(store)) {
@@ -1295,25 +1291,26 @@ const createStore = () => {
1295
1291
  ),
1296
1292
  ),
1297
1293
  );
1294
+ collClear(changedCells);
1298
1295
  collForEach(changedValues, ([oldValue], valueId) =>
1299
1296
  setOrDelValue(store, valueId, oldValue),
1300
1297
  );
1301
- cellsTouched = valuesTouched = false;
1298
+ collClear(changedValues);
1302
1299
  }
1303
1300
  callListeners(finishTransactionListeners[0], void 0);
1304
1301
  transactions = -1;
1305
1302
  callInvalidCellListeners(0);
1306
- if (cellsTouched) {
1303
+ if (!collIsEmpty(changedCells)) {
1307
1304
  callTabularListenersForChanges(0);
1308
1305
  }
1309
1306
  callInvalidValueListeners(0);
1310
- if (valuesTouched) {
1307
+ if (!collIsEmpty(changedValues)) {
1311
1308
  callValuesListenersForChanges(0);
1312
1309
  }
1313
- postTransactionListener?.(store);
1310
+ internalListeners[0]?.(store);
1314
1311
  callListeners(finishTransactionListeners[1], void 0);
1312
+ internalListeners[1]?.(store);
1315
1313
  transactions = 0;
1316
- cellsTouched = valuesTouched = false;
1317
1314
  hadTables = hasTables();
1318
1315
  hadValues = hasValues();
1319
1316
  arrayForEach(
@@ -1438,9 +1435,8 @@ const createStore = () => {
1438
1435
  collSize2(startTransactionListeners) +
1439
1436
  pairCollSize2(finishTransactionListeners),
1440
1437
  });
1441
- const addPostTransactionListener = (listener) => {
1442
- postTransactionListener = listener;
1443
- };
1438
+ const setInternalListeners = (preFinishTransaction, postFinishTransaction) =>
1439
+ (internalListeners = [preFinishTransaction, postFinishTransaction]);
1444
1440
  const store = {
1445
1441
  getContent,
1446
1442
  getTables,
@@ -1518,7 +1514,7 @@ const createStore = () => {
1518
1514
  createStore,
1519
1515
  addListener,
1520
1516
  callListeners,
1521
- addPostTransactionListener,
1517
+ setInternalListeners,
1522
1518
  };
1523
1519
  objToArray(
1524
1520
  {
@@ -1085,6 +1085,23 @@ const createMetrics = getCreateFunction((store) => {
1085
1085
 
1086
1086
  const scheduleRunning = mapNew();
1087
1087
  const scheduleActions = mapNew();
1088
+ const isMergeable = (contentOrChanges) => isString(contentOrChanges?.[0]);
1089
+ const getStoreFunctions = (supportsMergeableStore, store) =>
1090
+ !supportsMergeableStore || isUndefined(store.getMergeableContent)
1091
+ ? [
1092
+ 0,
1093
+ store.getContent,
1094
+ store.getTransactionChanges,
1095
+ ([changedTables, changedValues]) =>
1096
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
1097
+ ]
1098
+ : [
1099
+ 1,
1100
+ store.getMergeableContent,
1101
+ store.getTransactionMergeableChanges,
1102
+ ([, [[, changedTables], [, changedValues]]]) =>
1103
+ !objIsEmpty(changedTables) || !objIsEmpty(changedValues),
1104
+ ];
1088
1105
  const createCustomPersister = (
1089
1106
  store,
1090
1107
  getPersisted,
@@ -1105,10 +1122,8 @@ const createCustomPersister = (
1105
1122
  let listeningHandle;
1106
1123
  mapEnsure(scheduleRunning, scheduleId, () => 0);
1107
1124
  mapEnsure(scheduleActions, scheduleId, () => []);
1108
- const getContent =
1109
- (supportsMergeableStore ? store.getMergeableContent : null) ??
1110
- store.getContent;
1111
- const getChanges = store.getTransactionChanges;
1125
+ const [isMergeableStore, getContent, getChanges, hasChanges] =
1126
+ getStoreFunctions(supportsMergeableStore, store);
1112
1127
  const run = async () => {
1113
1128
  /* istanbul ignore else */
1114
1129
  if (!mapGet(scheduleRunning, scheduleId)) {
@@ -1145,8 +1160,8 @@ const createCustomPersister = (
1145
1160
  await loadLock(async () => {
1146
1161
  try {
1147
1162
  const content = await getPersisted();
1148
- (supportsMergeableStore && isString(content[0])
1149
- ? store.applyMergeableChanges
1163
+ (isMergeableStore && isMergeable(content)
1164
+ ? store.setMergeableContent
1150
1165
  : store.setContent)(content);
1151
1166
  } catch {
1152
1167
  store.setContent([initialTables, initialValues]);
@@ -1160,11 +1175,18 @@ const createCustomPersister = (
1160
1175
  async (getContent2, getChanges2) => {
1161
1176
  if (getChanges2) {
1162
1177
  const changes = getChanges2();
1163
- await loadLock(async () => store.applyChanges(changes));
1178
+ await loadLock(async () =>
1179
+ (isMergeableStore && isMergeable(changes)
1180
+ ? store.applyMergeableChanges
1181
+ : store.applyChanges)(changes),
1182
+ );
1164
1183
  } else {
1165
1184
  await loadLock(async () => {
1166
1185
  try {
1167
- store.setContent(getContent2?.() ?? (await getPersisted()));
1186
+ const content = getContent2?.() ?? (await getPersisted());
1187
+ (isMergeableStore && isMergeable(content)
1188
+ ? store.setMergeableContent
1189
+ : store.setContent)(content);
1168
1190
  } catch (error) {
1169
1191
  onIgnoredError?.(error);
1170
1192
  }
@@ -1204,9 +1226,9 @@ const createCustomPersister = (
1204
1226
  startAutoSave: async () => {
1205
1227
  await persister.stopAutoSave().save();
1206
1228
  listenerId = store.addDidFinishTransactionListener(() => {
1207
- const [tableChanges, valueChanges] = getChanges();
1208
- if (!objIsEmpty(tableChanges) || !objIsEmpty(valueChanges)) {
1209
- persister.save(() => [tableChanges, valueChanges]);
1229
+ const changes = getChanges();
1230
+ if (hasChanges(changes)) {
1231
+ persister.save(() => changes);
1210
1232
  }
1211
1233
  });
1212
1234
  return persister;
@@ -1879,9 +1901,11 @@ const createRelationships = getCreateFunction((store) => {
1879
1901
  return objFreeze(relationships);
1880
1902
  });
1881
1903
 
1882
- const stampNew = () => [EMPTY_STRING, void 0];
1883
- const stampNewMap = () => [EMPTY_STRING, mapNew()];
1884
- const mapStamp = ([stamp, value], mapper) => [stamp, mapper(value, stamp)];
1904
+ const stampNew = (time = EMPTY_STRING, thing) => [time, thing];
1905
+ const stampNewMap = (time = EMPTY_STRING) => stampNew(time, mapNew());
1906
+ const stampNewObj = (time) => stampNew(time, objNew());
1907
+ const mapStamp = ([time, value], mapper) => [time, mapper(value, time)];
1908
+ const cloneStamp = ([time, value]) => [time, value];
1885
1909
  const mapStampMapToObj = (stampedMap, mapper) =>
1886
1910
  mapStamp(stampedMap, (map) => mapToObj(map, mapper));
1887
1911
  const mergeStamps = (newThingStamps, thingStamps, changes, merge) =>
@@ -1941,12 +1965,10 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
1941
1965
  const createStore = () => {
1942
1966
  let hasTablesSchema;
1943
1967
  let hasValuesSchema;
1944
- let cellsTouched = false;
1945
- let valuesTouched = false;
1946
1968
  let hadTables = false;
1947
1969
  let hadValues = false;
1948
1970
  let transactions = 0;
1949
- let postTransactionListener;
1971
+ let internalListeners = [];
1950
1972
  const changedTableIds = mapNew();
1951
1973
  const changedTableCellIds = mapNew();
1952
1974
  const changedRowCount = mapNew();
@@ -2906,8 +2928,8 @@ const createStore = () => {
2906
2928
  ),
2907
2929
  ];
2908
2930
  const getTransactionLog = () => [
2909
- cellsTouched,
2910
- valuesTouched,
2931
+ !collIsEmpty(changedCells),
2932
+ !collIsEmpty(changedValues),
2911
2933
  mapToObj3(changedCells, pairClone, pairIsEqual),
2912
2934
  mapToObj3(invalidCells),
2913
2935
  mapToObj(changedValues, pairClone, pairIsEqual),
@@ -2921,15 +2943,13 @@ const createStore = () => {
2921
2943
  if (transactions > 0) {
2922
2944
  transactions--;
2923
2945
  if (transactions == 0) {
2924
- cellsTouched = !collIsEmpty(changedCells);
2925
- valuesTouched = !collIsEmpty(changedValues);
2926
2946
  transactions = 1;
2927
2947
  callInvalidCellListeners(1);
2928
- if (cellsTouched) {
2948
+ if (!collIsEmpty(changedCells)) {
2929
2949
  callTabularListenersForChanges(1);
2930
2950
  }
2931
2951
  callInvalidValueListeners(1);
2932
- if (valuesTouched) {
2952
+ if (!collIsEmpty(changedValues)) {
2933
2953
  callValuesListenersForChanges(1);
2934
2954
  }
2935
2955
  if (doRollback?.(store)) {
@@ -2940,25 +2960,26 @@ const createStore = () => {
2940
2960
  ),
2941
2961
  ),
2942
2962
  );
2963
+ collClear(changedCells);
2943
2964
  collForEach(changedValues, ([oldValue], valueId) =>
2944
2965
  setOrDelValue(store, valueId, oldValue),
2945
2966
  );
2946
- cellsTouched = valuesTouched = false;
2967
+ collClear(changedValues);
2947
2968
  }
2948
2969
  callListeners(finishTransactionListeners[0], void 0);
2949
2970
  transactions = -1;
2950
2971
  callInvalidCellListeners(0);
2951
- if (cellsTouched) {
2972
+ if (!collIsEmpty(changedCells)) {
2952
2973
  callTabularListenersForChanges(0);
2953
2974
  }
2954
2975
  callInvalidValueListeners(0);
2955
- if (valuesTouched) {
2976
+ if (!collIsEmpty(changedValues)) {
2956
2977
  callValuesListenersForChanges(0);
2957
2978
  }
2958
- postTransactionListener?.(store);
2979
+ internalListeners[0]?.(store);
2959
2980
  callListeners(finishTransactionListeners[1], void 0);
2981
+ internalListeners[1]?.(store);
2960
2982
  transactions = 0;
2961
- cellsTouched = valuesTouched = false;
2962
2983
  hadTables = hasTables();
2963
2984
  hadValues = hasValues();
2964
2985
  arrayForEach(
@@ -3083,9 +3104,8 @@ const createStore = () => {
3083
3104
  collSize2(startTransactionListeners) +
3084
3105
  pairCollSize2(finishTransactionListeners),
3085
3106
  });
3086
- const addPostTransactionListener = (listener) => {
3087
- postTransactionListener = listener;
3088
- };
3107
+ const setInternalListeners = (preFinishTransaction, postFinishTransaction) =>
3108
+ (internalListeners = [preFinishTransaction, postFinishTransaction]);
3089
3109
  const store = {
3090
3110
  getContent,
3091
3111
  getTables,
@@ -3163,7 +3183,7 @@ const createStore = () => {
3163
3183
  createStore,
3164
3184
  addListener,
3165
3185
  callListeners,
3166
- addPostTransactionListener,
3186
+ setInternalListeners,
3167
3187
  };
3168
3188
  objToArray(
3169
3189
  {
@@ -3290,23 +3310,23 @@ const decodeHlc = (hlc16) => [
3290
3310
  ];
3291
3311
  const getHlcFunctions = (uniqueId) => {
3292
3312
  let logicalTime = 0;
3293
- let counter = 0;
3313
+ let lastCounter = -1;
3294
3314
  const uniqueIdHash = hash(uniqueId);
3295
3315
  const getHlc = () => {
3296
3316
  seenHlc();
3297
- return encodeHlc(logicalTime, ++counter, uniqueIdHash);
3317
+ return encodeHlc(logicalTime, ++lastCounter, uniqueIdHash);
3298
3318
  };
3299
3319
  const seenHlc = (hlc) => {
3300
3320
  const previousLogicalTime = logicalTime;
3301
3321
  const [remoteLogicalTime, remoteCounter] = isUndefined(hlc)
3302
3322
  ? [0, 0]
3303
3323
  : decodeHlc(hlc);
3304
- logicalTime = Math.max(previousLogicalTime, remoteLogicalTime, Date.now());
3305
- counter =
3324
+ logicalTime = mathMax(previousLogicalTime, remoteLogicalTime, Date.now());
3325
+ lastCounter =
3306
3326
  logicalTime == previousLogicalTime
3307
3327
  ? logicalTime == remoteLogicalTime
3308
- ? Math.max(counter, remoteCounter)
3309
- : counter
3328
+ ? mathMax(lastCounter, remoteCounter)
3329
+ : lastCounter
3310
3330
  : logicalTime == remoteLogicalTime
3311
3331
  ? remoteCounter
3312
3332
  : -1;
@@ -3332,10 +3352,15 @@ const LISTENER_ARGS = {
3332
3352
  InvalidCell: 3,
3333
3353
  InvalidValue: 1,
3334
3354
  };
3335
- const newContentStamp = () => [EMPTY_STRING, [stampNewMap(), stampNewMap()]];
3355
+ const newContentStamp = (time = EMPTY_STRING) => [
3356
+ time,
3357
+ [stampNewMap(time), stampNewMap(time)],
3358
+ ];
3336
3359
  const createMergeableStore = (id) => {
3337
3360
  let listening = 1;
3338
3361
  let contentStamp = newContentStamp();
3362
+ let transactionTime;
3363
+ let finishTransactionMergeableChanges;
3339
3364
  const [getHlc, seenHlc] = getHlcFunctions(id);
3340
3365
  const store = createStore();
3341
3366
  const disableListening = (actions) => {
@@ -3344,37 +3369,41 @@ const createMergeableStore = (id) => {
3344
3369
  actions();
3345
3370
  listening = wasListening;
3346
3371
  };
3347
- const postTransactionListener = () => {
3372
+ const preFinishTransaction = () => {
3348
3373
  if (listening) {
3349
- const stamp = getHlc();
3350
- const [cellsTouched, valuesTouched, changedCells, , changedValues] =
3351
- store.getTransactionLog();
3352
- const [tablesStamp, valuesStamp] = contentStamp[1];
3353
- contentStamp[0] = stamp;
3374
+ finishTransactionMergeableChanges = getTransactionMergeableChanges();
3375
+ const [time, [changedTablesStamp, changedValuesStamp]] =
3376
+ finishTransactionMergeableChanges;
3377
+ const cellsTouched = !objIsEmpty(changedTablesStamp[1]);
3378
+ const valuesTouched = !objIsEmpty(changedValuesStamp[1]);
3379
+ const [, [tablesStamp, valuesStamp]] = contentStamp;
3380
+ if (cellsTouched || valuesTouched) {
3381
+ contentStamp[0] = time;
3382
+ }
3354
3383
  if (cellsTouched) {
3355
- tablesStamp[0] = stamp;
3356
- objToArray(changedCells, (changedTable, tableId) => {
3357
- const tableStamp = mapEnsure(tablesStamp[1], tableId, stampNew);
3358
- const rowsStamp = (tableStamp[1] ??= mapNew());
3359
- tableStamp[0] = stamp;
3360
- objToArray(changedTable, (changedRow, rowId) => {
3361
- const rowStamp = mapEnsure(rowsStamp, rowId, stampNew);
3362
- const cellsStamp = (rowStamp[1] ??= mapNew());
3363
- rowStamp[0] = stamp;
3364
- objToArray(changedRow, ([, newCell], cellId) =>
3365
- mapSet(cellsStamp, cellId, [stamp, newCell]),
3384
+ tablesStamp[0] = time;
3385
+ objToArray(changedTablesStamp[1], ([, changedRowStamps], tableId) => {
3386
+ const tableStamp = mapEnsure(tablesStamp[1], tableId, stampNewMap);
3387
+ tableStamp[0] = time;
3388
+ objToArray(changedRowStamps, ([, changedCellStamps], rowId) => {
3389
+ const rowStamp = mapEnsure(tableStamp[1], rowId, stampNewMap);
3390
+ rowStamp[0] = time;
3391
+ objToArray(changedCellStamps, ([, newCell], cellId) =>
3392
+ mapSet(rowStamp[1], cellId, stampNew(time, newCell)),
3366
3393
  );
3367
3394
  });
3368
3395
  });
3369
3396
  }
3370
3397
  if (valuesTouched) {
3371
- valuesStamp[0] = stamp;
3372
- objToArray(changedValues, ([, newValue], valueId) => {
3373
- mapSet(valuesStamp[1], valueId, [stamp, newValue]);
3374
- });
3398
+ valuesStamp[0] = time;
3399
+ objToArray(changedValuesStamp[1], ([, newValue], valueId) =>
3400
+ mapSet(valuesStamp[1], valueId, stampNew(time, newValue)),
3401
+ );
3375
3402
  }
3376
3403
  }
3377
3404
  };
3405
+ const postFinishTransaction = () =>
3406
+ (transactionTime = finishTransactionMergeableChanges = void 0);
3378
3407
  const merge = (mergeableStore2) => {
3379
3408
  const mergeableContent = mergeableStore.getMergeableContent();
3380
3409
  const mergeableContent2 = mergeableStore2.getMergeableContent();
@@ -3385,10 +3414,10 @@ const createMergeableStore = (id) => {
3385
3414
  mapStamp(contentStamp, ([tablesStamp, valuesStamp]) => [
3386
3415
  mapStampMapToObj(tablesStamp, (rowsStamp) =>
3387
3416
  mapStampMapToObj(rowsStamp, (cellsStamp) =>
3388
- mapStampMapToObj(cellsStamp, pairClone),
3417
+ mapStampMapToObj(cellsStamp, cloneStamp),
3389
3418
  ),
3390
3419
  ),
3391
- mapStampMapToObj(valuesStamp, pairClone),
3420
+ mapStampMapToObj(valuesStamp, cloneStamp),
3392
3421
  ]);
3393
3422
  const setMergeableContent = (mergeableContent) => {
3394
3423
  disableListening(() =>
@@ -3400,6 +3429,38 @@ const createMergeableStore = (id) => {
3400
3429
  applyMergeableChanges(mergeableContent);
3401
3430
  return mergeableStore;
3402
3431
  };
3432
+ const getTransactionMergeableChanges = () => {
3433
+ if (isUndefined(finishTransactionMergeableChanges)) {
3434
+ const [, , changedCells, , changedValues] = store.getTransactionLog();
3435
+ const time =
3436
+ !objIsEmpty(changedCells) || !objIsEmpty(changedValues)
3437
+ ? transactionTime ?? (transactionTime = getHlc())
3438
+ : EMPTY_STRING;
3439
+ const mergeableChanges = stampNew(time, [
3440
+ stampNewObj(objIsEmpty(changedCells) ? EMPTY_STRING : time),
3441
+ stampNewObj(objIsEmpty(changedValues) ? EMPTY_STRING : time),
3442
+ ]);
3443
+ const [[, tableStamps], [, valuesStamp]] = mergeableChanges[1];
3444
+ objToArray(changedCells, (changedTable, tableId) => {
3445
+ const [, rowStamps] = (tableStamps[tableId] = stampNewObj(time));
3446
+ objToArray(changedTable, (changedRow, rowId) => {
3447
+ const [, cellStamps] = (rowStamps[rowId] = stampNewObj(time));
3448
+ objToArray(
3449
+ changedRow,
3450
+ ([, newCell], cellId) =>
3451
+ (cellStamps[cellId] = stampNew(time, newCell)),
3452
+ );
3453
+ });
3454
+ });
3455
+ objToArray(
3456
+ changedValues,
3457
+ ([, newValue], valueId) =>
3458
+ (valuesStamp[valueId] = stampNew(time, newValue)),
3459
+ );
3460
+ return mergeableChanges;
3461
+ }
3462
+ return finishTransactionMergeableChanges;
3463
+ };
3403
3464
  const applyMergeableChanges = (newContentStamp2) => {
3404
3465
  const changes = [{}, {}];
3405
3466
  seenHlc(newContentStamp2[0]);
@@ -3439,10 +3500,11 @@ const createMergeableStore = (id) => {
3439
3500
  const mergeableStore = {
3440
3501
  getMergeableContent,
3441
3502
  setMergeableContent,
3503
+ getTransactionMergeableChanges,
3442
3504
  applyMergeableChanges,
3443
3505
  merge,
3444
3506
  };
3445
- store.addPostTransactionListener(postTransactionListener);
3507
+ store.setInternalListeners(preFinishTransaction, postFinishTransaction);
3446
3508
  objToArray(
3447
3509
  store,
3448
3510
  (method, name) =>