tinybase 4.0.0-beta.1 → 4.0.0-beta.3

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 (212) hide show
  1. package/bin/cli.js +1 -1
  2. package/lib/checkpoints.js +1 -1
  3. package/lib/checkpoints.js.gz +0 -0
  4. package/lib/cjs/checkpoints.cjs +1 -1
  5. package/lib/cjs/checkpoints.cjs.gz +0 -0
  6. package/lib/cjs/indexes.cjs +1 -1
  7. package/lib/cjs/indexes.cjs.gz +0 -0
  8. package/lib/cjs/metrics.cjs +1 -1
  9. package/lib/cjs/metrics.cjs.gz +0 -0
  10. package/lib/cjs/persister-automerge.cjs +1 -0
  11. package/lib/cjs/persister-automerge.cjs.gz +0 -0
  12. package/lib/cjs/persister-browser.cjs +1 -1
  13. package/lib/cjs/persister-browser.cjs.gz +0 -0
  14. package/lib/cjs/persister-file.cjs +1 -1
  15. package/lib/cjs/persister-file.cjs.gz +0 -0
  16. package/lib/cjs/persister-remote.cjs +1 -1
  17. package/lib/cjs/persister-remote.cjs.gz +0 -0
  18. package/lib/cjs/persister-yjs.cjs +1 -1
  19. package/lib/cjs/persister-yjs.cjs.gz +0 -0
  20. package/lib/cjs/persisters.cjs +1 -1
  21. package/lib/cjs/persisters.cjs.gz +0 -0
  22. package/lib/cjs/queries.cjs +1 -1
  23. package/lib/cjs/queries.cjs.gz +0 -0
  24. package/lib/cjs/relationships.cjs +1 -1
  25. package/lib/cjs/relationships.cjs.gz +0 -0
  26. package/lib/cjs/store.cjs +1 -1
  27. package/lib/cjs/store.cjs.gz +0 -0
  28. package/lib/cjs/tinybase.cjs +1 -1
  29. package/lib/cjs/tinybase.cjs.gz +0 -0
  30. package/lib/cjs/tools.cjs +1 -1
  31. package/lib/cjs/tools.cjs.gz +0 -0
  32. package/lib/cjs/ui-react.cjs +1 -1
  33. package/lib/cjs/ui-react.cjs.gz +0 -0
  34. package/lib/cjs-es6/checkpoints.cjs +1 -1
  35. package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
  36. package/lib/cjs-es6/indexes.cjs +1 -1
  37. package/lib/cjs-es6/indexes.cjs.gz +0 -0
  38. package/lib/cjs-es6/metrics.cjs +1 -1
  39. package/lib/cjs-es6/metrics.cjs.gz +0 -0
  40. package/lib/cjs-es6/persister-automerge.cjs +1 -0
  41. package/lib/cjs-es6/persister-automerge.cjs.gz +0 -0
  42. package/lib/cjs-es6/persister-browser.cjs +1 -1
  43. package/lib/cjs-es6/persister-browser.cjs.gz +0 -0
  44. package/lib/cjs-es6/persister-file.cjs +1 -1
  45. package/lib/cjs-es6/persister-file.cjs.gz +0 -0
  46. package/lib/cjs-es6/persister-remote.cjs +1 -1
  47. package/lib/cjs-es6/persister-remote.cjs.gz +0 -0
  48. package/lib/cjs-es6/persister-yjs.cjs +1 -1
  49. package/lib/cjs-es6/persister-yjs.cjs.gz +0 -0
  50. package/lib/cjs-es6/persisters.cjs +1 -1
  51. package/lib/cjs-es6/persisters.cjs.gz +0 -0
  52. package/lib/cjs-es6/queries.cjs +1 -1
  53. package/lib/cjs-es6/queries.cjs.gz +0 -0
  54. package/lib/cjs-es6/relationships.cjs +1 -1
  55. package/lib/cjs-es6/relationships.cjs.gz +0 -0
  56. package/lib/cjs-es6/store.cjs +1 -1
  57. package/lib/cjs-es6/store.cjs.gz +0 -0
  58. package/lib/cjs-es6/tinybase.cjs +1 -1
  59. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  60. package/lib/cjs-es6/tools.cjs +1 -1
  61. package/lib/cjs-es6/tools.cjs.gz +0 -0
  62. package/lib/cjs-es6/ui-react.cjs +1 -1
  63. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  64. package/lib/debug/checkpoints.js +3 -3
  65. package/lib/debug/indexes.js +3 -3
  66. package/lib/debug/metrics.js +3 -3
  67. package/lib/debug/persister-automerge.js +257 -0
  68. package/lib/debug/persister-browser.js +40 -41
  69. package/lib/debug/persister-file.js +39 -39
  70. package/lib/debug/persister-remote.js +39 -36
  71. package/lib/debug/persister-yjs.js +227 -42
  72. package/lib/debug/persisters.js +38 -35
  73. package/lib/debug/queries.js +5 -5
  74. package/lib/debug/relationships.js +3 -3
  75. package/lib/debug/store.js +129 -94
  76. package/lib/debug/tinybase.js +167 -127
  77. package/lib/debug/tools.js +51 -11
  78. package/lib/es6/checkpoints.js +1 -1
  79. package/lib/es6/checkpoints.js.gz +0 -0
  80. package/lib/es6/indexes.js +1 -1
  81. package/lib/es6/indexes.js.gz +0 -0
  82. package/lib/es6/metrics.js +1 -1
  83. package/lib/es6/metrics.js.gz +0 -0
  84. package/lib/es6/persister-automerge.js +1 -0
  85. package/lib/es6/persister-automerge.js.gz +0 -0
  86. package/lib/es6/persister-browser.js +1 -1
  87. package/lib/es6/persister-browser.js.gz +0 -0
  88. package/lib/es6/persister-file.js +1 -1
  89. package/lib/es6/persister-file.js.gz +0 -0
  90. package/lib/es6/persister-remote.js +1 -1
  91. package/lib/es6/persister-remote.js.gz +0 -0
  92. package/lib/es6/persister-yjs.js +1 -1
  93. package/lib/es6/persister-yjs.js.gz +0 -0
  94. package/lib/es6/persisters.js +1 -1
  95. package/lib/es6/persisters.js.gz +0 -0
  96. package/lib/es6/queries.js +1 -1
  97. package/lib/es6/queries.js.gz +0 -0
  98. package/lib/es6/relationships.js +1 -1
  99. package/lib/es6/relationships.js.gz +0 -0
  100. package/lib/es6/store.js +1 -1
  101. package/lib/es6/store.js.gz +0 -0
  102. package/lib/es6/tinybase.js +1 -1
  103. package/lib/es6/tinybase.js.gz +0 -0
  104. package/lib/es6/tools.js +1 -1
  105. package/lib/es6/tools.js.gz +0 -0
  106. package/lib/es6/ui-react.js +1 -1
  107. package/lib/es6/ui-react.js.gz +0 -0
  108. package/lib/indexes.js +1 -1
  109. package/lib/indexes.js.gz +0 -0
  110. package/lib/metrics.js +1 -1
  111. package/lib/metrics.js.gz +0 -0
  112. package/lib/persister-automerge.js +1 -0
  113. package/lib/persister-automerge.js.gz +0 -0
  114. package/lib/persister-browser.js +1 -1
  115. package/lib/persister-browser.js.gz +0 -0
  116. package/lib/persister-file.js +1 -1
  117. package/lib/persister-file.js.gz +0 -0
  118. package/lib/persister-remote.js +1 -1
  119. package/lib/persister-remote.js.gz +0 -0
  120. package/lib/persister-yjs.js +1 -1
  121. package/lib/persister-yjs.js.gz +0 -0
  122. package/lib/persisters.js +1 -1
  123. package/lib/persisters.js.gz +0 -0
  124. package/lib/queries.js +1 -1
  125. package/lib/queries.js.gz +0 -0
  126. package/lib/relationships.js +1 -1
  127. package/lib/relationships.js.gz +0 -0
  128. package/lib/store.js +1 -1
  129. package/lib/store.js.gz +0 -0
  130. package/lib/tinybase.js +1 -1
  131. package/lib/tinybase.js.gz +0 -0
  132. package/lib/tools.js +1 -1
  133. package/lib/tools.js.gz +0 -0
  134. package/lib/types/persister-automerge.d.ts +110 -0
  135. package/lib/types/persister-yjs.d.ts +71 -8
  136. package/lib/types/persisters.d.ts +45 -20
  137. package/lib/types/queries.d.ts +52 -52
  138. package/lib/types/store.d.ts +399 -145
  139. package/lib/types/tools.d.ts +20 -20
  140. package/lib/types/ui-react.d.ts +56 -47
  141. package/lib/types/with-schemas/internal/ui-react.d.ts +2 -2
  142. package/lib/types/with-schemas/persister-automerge.d.ts +120 -0
  143. package/lib/types/with-schemas/persister-yjs.d.ts +73 -9
  144. package/lib/types/with-schemas/persisters.d.ts +62 -21
  145. package/lib/types/with-schemas/queries.d.ts +52 -52
  146. package/lib/types/with-schemas/store.d.ts +480 -163
  147. package/lib/types/with-schemas/tools.d.ts +20 -20
  148. package/lib/types/with-schemas/ui-react.d.ts +54 -45
  149. package/lib/ui-react.js +1 -1
  150. package/lib/ui-react.js.gz +0 -0
  151. package/lib/umd/checkpoints.js +1 -1
  152. package/lib/umd/checkpoints.js.gz +0 -0
  153. package/lib/umd/indexes.js +1 -1
  154. package/lib/umd/indexes.js.gz +0 -0
  155. package/lib/umd/metrics.js +1 -1
  156. package/lib/umd/metrics.js.gz +0 -0
  157. package/lib/umd/persister-automerge.js +1 -0
  158. package/lib/umd/persister-automerge.js.gz +0 -0
  159. package/lib/umd/persister-browser.js +1 -1
  160. package/lib/umd/persister-browser.js.gz +0 -0
  161. package/lib/umd/persister-file.js +1 -1
  162. package/lib/umd/persister-file.js.gz +0 -0
  163. package/lib/umd/persister-remote.js +1 -1
  164. package/lib/umd/persister-remote.js.gz +0 -0
  165. package/lib/umd/persister-yjs.js +1 -1
  166. package/lib/umd/persister-yjs.js.gz +0 -0
  167. package/lib/umd/persisters.js +1 -1
  168. package/lib/umd/persisters.js.gz +0 -0
  169. package/lib/umd/queries.js +1 -1
  170. package/lib/umd/queries.js.gz +0 -0
  171. package/lib/umd/relationships.js +1 -1
  172. package/lib/umd/relationships.js.gz +0 -0
  173. package/lib/umd/store.js +1 -1
  174. package/lib/umd/store.js.gz +0 -0
  175. package/lib/umd/tinybase.js +1 -1
  176. package/lib/umd/tinybase.js.gz +0 -0
  177. package/lib/umd/tools.js +1 -1
  178. package/lib/umd/tools.js.gz +0 -0
  179. package/lib/umd/ui-react.js +1 -1
  180. package/lib/umd/ui-react.js.gz +0 -0
  181. package/lib/umd-es6/checkpoints.js +1 -1
  182. package/lib/umd-es6/checkpoints.js.gz +0 -0
  183. package/lib/umd-es6/indexes.js +1 -1
  184. package/lib/umd-es6/indexes.js.gz +0 -0
  185. package/lib/umd-es6/metrics.js +1 -1
  186. package/lib/umd-es6/metrics.js.gz +0 -0
  187. package/lib/umd-es6/persister-automerge.js +1 -0
  188. package/lib/umd-es6/persister-automerge.js.gz +0 -0
  189. package/lib/umd-es6/persister-browser.js +1 -1
  190. package/lib/umd-es6/persister-browser.js.gz +0 -0
  191. package/lib/umd-es6/persister-file.js +1 -1
  192. package/lib/umd-es6/persister-file.js.gz +0 -0
  193. package/lib/umd-es6/persister-remote.js +1 -1
  194. package/lib/umd-es6/persister-remote.js.gz +0 -0
  195. package/lib/umd-es6/persister-yjs.js +1 -1
  196. package/lib/umd-es6/persister-yjs.js.gz +0 -0
  197. package/lib/umd-es6/persisters.js +1 -1
  198. package/lib/umd-es6/persisters.js.gz +0 -0
  199. package/lib/umd-es6/queries.js +1 -1
  200. package/lib/umd-es6/queries.js.gz +0 -0
  201. package/lib/umd-es6/relationships.js +1 -1
  202. package/lib/umd-es6/relationships.js.gz +0 -0
  203. package/lib/umd-es6/store.js +1 -1
  204. package/lib/umd-es6/store.js.gz +0 -0
  205. package/lib/umd-es6/tinybase.js +1 -1
  206. package/lib/umd-es6/tinybase.js.gz +0 -0
  207. package/lib/umd-es6/tools.js +1 -1
  208. package/lib/umd-es6/tools.js.gz +0 -0
  209. package/lib/umd-es6/ui-react.js +1 -1
  210. package/lib/umd-es6/ui-react.js.gz +0 -0
  211. package/package.json +59 -29
  212. package/readme.md +3 -3
@@ -1,4 +1,10 @@
1
- const EMPTY_STRING = '';
1
+ import {Map} from 'yjs';
2
+
3
+ const arrayForEach = (array, cb) => array.forEach(cb);
4
+ const arrayMap = (array, cb) => array.map(cb);
5
+ const arrayLength = (array) => array.length;
6
+ const arrayIsEmpty = (array) => arrayLength(array) == 0;
7
+ const arrayShift = (array) => array.shift();
2
8
 
3
9
  const isUndefined = (thing) => thing == void 0;
4
10
  const ifNotUndefined = (value, then, otherwise) =>
@@ -6,6 +12,17 @@ const ifNotUndefined = (value, then, otherwise) =>
6
12
 
7
13
  const object = Object;
8
14
  const objFreeze = object.freeze;
15
+ const objNew = () => ({});
16
+ const objGet = (obj, id) => ifNotUndefined(obj, (obj2) => obj2[id]);
17
+ const objHas = (obj, id) => !isUndefined(objGet(obj, id));
18
+ const objMap = (obj, cb) =>
19
+ arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
20
+ const objEnsure = (obj, id, getDefaultValue) => {
21
+ if (!objHas(obj, id)) {
22
+ obj[id] = getDefaultValue();
23
+ }
24
+ return obj[id];
25
+ };
9
26
 
10
27
  const createCustomPersister = (
11
28
  store,
@@ -20,43 +37,45 @@ const createCustomPersister = (
20
37
  let saves = 0;
21
38
  let listening = false;
22
39
  let listeningHandle;
23
- const persister = {
24
- load: async (initialTables, initialValues) => {
25
- /* istanbul ignore else */
26
- if (loadSave != 2) {
27
- loadSave = 1;
28
- {
29
- loads++;
30
- }
31
- const body = await getPersisted();
32
- if (!isUndefined(body) && body != EMPTY_STRING) {
33
- store.setJson(body);
34
- } else {
35
- store.setContent([initialTables, initialValues]);
36
- }
37
- loadSave = 0;
40
+ const loadLock = async (actions) => {
41
+ /* istanbul ignore else */
42
+ if (loadSave != 2) {
43
+ loadSave = 1;
44
+ {
45
+ loads++;
38
46
  }
47
+ await actions();
48
+ loadSave = 0;
49
+ }
50
+ };
51
+ const persister = {
52
+ load: async (initialTables = {}, initialValues = {}) => {
53
+ await loadLock(async () => {
54
+ let content;
55
+ try {
56
+ content = await getPersisted();
57
+ } catch {}
58
+ store.setContent(content ?? [initialTables, initialValues]);
59
+ });
39
60
  return persister;
40
61
  },
41
- startAutoLoad: async (initialTables, initialValues) => {
62
+ startAutoLoad: async (initialTables = {}, initialValues = {}) => {
42
63
  persister.stopAutoLoad();
43
64
  await persister.load(initialTables, initialValues);
44
65
  listening = true;
45
- listeningHandle = addPersisterListener(async (content) => {
46
- if (isUndefined(content)) {
47
- await persister.load();
48
- } else {
49
- /* istanbul ignore else */
50
- if (loadSave != 2) {
51
- loadSave = 1;
52
- {
53
- loads++;
66
+ listeningHandle = addPersisterListener(
67
+ async (getContent, getTransactionChanges) => {
68
+ await loadLock(async () => {
69
+ if (getTransactionChanges) {
70
+ store.setTransactionChanges(getTransactionChanges());
71
+ } else {
72
+ try {
73
+ store.setContent(getContent?.() ?? (await getPersisted()));
74
+ } catch {}
54
75
  }
55
- store.setContent(content);
56
- loadSave = 0;
57
- }
58
- }
59
- });
76
+ });
77
+ },
78
+ );
60
79
  return persister;
61
80
  },
62
81
  stopAutoLoad: () => {
@@ -67,21 +86,24 @@ const createCustomPersister = (
67
86
  }
68
87
  return persister;
69
88
  },
70
- save: async () => {
89
+ save: async (getTransactionChanges) => {
71
90
  /* istanbul ignore else */
72
91
  if (loadSave != 1) {
73
92
  loadSave = 2;
74
93
  {
75
94
  saves++;
76
95
  }
77
- await setPersisted(store.getContent);
96
+ await setPersisted(store.getContent, getTransactionChanges);
78
97
  loadSave = 0;
79
98
  }
80
99
  return persister;
81
100
  },
82
101
  startAutoSave: async () => {
83
102
  await persister.stopAutoSave().save();
84
- listenerId = store.addDidFinishTransactionListener(persister.save);
103
+ listenerId = store.addDidFinishTransactionListener(
104
+ (_store, getTransactionChanges) =>
105
+ persister.save(getTransactionChanges),
106
+ );
85
107
  return persister;
86
108
  },
87
109
  stopAutoSave: () => {
@@ -95,18 +117,181 @@ const createCustomPersister = (
95
117
  return objFreeze(persister);
96
118
  };
97
119
 
98
- const createYjsPersister = (store, yDoc) => {
99
- const map = yDoc.getMap('tinybase/store');
100
- const getPersisted = async () => map.get('json');
101
- const setPersisted = async (getContent) => {
102
- map.set('json', JSON.stringify(getContent()));
120
+ const collForEach = (coll, cb) => coll?.forEach(cb);
121
+
122
+ const mapForEach = (map, cb) =>
123
+ collForEach(map, (value, key) => cb(key, value));
124
+
125
+ const tablesKey = 't';
126
+ const valuesKey = 'v';
127
+ const DELETE = 'delete';
128
+ const ensureYContent = (yContent) => {
129
+ if (!yContent.size) {
130
+ yContent.set(tablesKey, new Map());
131
+ yContent.set(valuesKey, new Map());
132
+ }
133
+ };
134
+ const getYContent = (yContent) => [
135
+ yContent.get(tablesKey),
136
+ yContent.get(valuesKey),
137
+ ];
138
+ const getTransactionChangesFromYDoc = (yContent, events) => {
139
+ if (arrayLength(events) == 1 && arrayIsEmpty(events[0].path)) {
140
+ return [yContent.get('t').toJSON(), yContent.get('v').toJSON()];
141
+ }
142
+ const [yTables, yValues] = getYContent(yContent);
143
+ const tables = {};
144
+ const values = {};
145
+ arrayForEach(events, ({path, changes: {keys}}) =>
146
+ arrayShift(path) == tablesKey
147
+ ? ifNotUndefined(
148
+ arrayShift(path),
149
+ (yTableId) => {
150
+ const table = objEnsure(tables, yTableId, objNew);
151
+ const yTable = yTables.get(yTableId);
152
+ ifNotUndefined(
153
+ arrayShift(path),
154
+ (yRowId) => {
155
+ const row = objEnsure(table, yRowId, objNew);
156
+ const yRow = yTable.get(yRowId);
157
+ mapForEach(
158
+ keys,
159
+ (cellId, {action}) =>
160
+ (row[cellId] = action == DELETE ? null : yRow.get(cellId)),
161
+ );
162
+ },
163
+ () =>
164
+ mapForEach(
165
+ keys,
166
+ (rowId, {action}) =>
167
+ (table[rowId] =
168
+ action == DELETE ? null : yTable.get(rowId)?.toJSON()),
169
+ ),
170
+ );
171
+ },
172
+ () =>
173
+ mapForEach(
174
+ keys,
175
+ (tableId, {action}) =>
176
+ (tables[tableId] =
177
+ action == DELETE ? null : yTables.get(tableId)?.toJSON()),
178
+ ),
179
+ )
180
+ : mapForEach(
181
+ keys,
182
+ (valueId, {action}) =>
183
+ (values[valueId] = action == DELETE ? null : yValues.get(valueId)),
184
+ ),
185
+ );
186
+ return [tables, values];
187
+ };
188
+ const setTransactionChangesToYDoc = (
189
+ yContent,
190
+ getContent,
191
+ getTransactionChanges,
192
+ ) => {
193
+ ensureYContent(yContent);
194
+ const [yTables, yValues] = getYContent(yContent);
195
+ const transactionChangesDidFail = () => {
196
+ transactionChangesFailed = 1;
103
197
  };
198
+ let transactionChangesFailed = 1;
199
+ ifNotUndefined(getTransactionChanges?.(), ([cellChanges, valueChanges]) => {
200
+ transactionChangesFailed = 0;
201
+ objMap(cellChanges, (table, tableId) =>
202
+ transactionChangesFailed
203
+ ? 0
204
+ : isUndefined(table)
205
+ ? yTables.delete(tableId)
206
+ : ifNotUndefined(
207
+ yTables.get(tableId),
208
+ (yTable) =>
209
+ objMap(table, (row, rowId) =>
210
+ transactionChangesFailed
211
+ ? 0
212
+ : isUndefined(row)
213
+ ? yTable.delete(rowId)
214
+ : ifNotUndefined(
215
+ yTable.get(rowId),
216
+ (yRow) =>
217
+ objMap(row, (cell, cellId) =>
218
+ isUndefined(cell)
219
+ ? yRow.delete(cellId)
220
+ : yRow.set(cellId, cell),
221
+ ),
222
+ transactionChangesDidFail,
223
+ ),
224
+ ),
225
+ transactionChangesDidFail,
226
+ ),
227
+ );
228
+ objMap(valueChanges, (value, valueId) =>
229
+ transactionChangesFailed
230
+ ? 0
231
+ : isUndefined(value)
232
+ ? yValues.delete(valueId)
233
+ : yValues.set(valueId, value),
234
+ );
235
+ });
236
+ if (transactionChangesFailed) {
237
+ const [tables, values] = getContent();
238
+ yMapMatch(yTables, void 0, tables, (_, tableId, table) =>
239
+ yMapMatch(yTables, tableId, table, (yTable, rowId, row) =>
240
+ yMapMatch(yTable, rowId, row, (yRow, cellId, cell) => {
241
+ if (yRow.get(cellId) !== cell) {
242
+ yRow.set(cellId, cell);
243
+ return 1;
244
+ }
245
+ }),
246
+ ),
247
+ );
248
+ yMapMatch(yValues, void 0, values, (_, valueId, value) => {
249
+ if (yValues.get(valueId) !== value) {
250
+ yValues.set(valueId, value);
251
+ }
252
+ });
253
+ }
254
+ };
255
+ const yMapMatch = (yMapOrParent, idInParent, obj, set) => {
256
+ const yMap = isUndefined(idInParent)
257
+ ? yMapOrParent
258
+ : yMapOrParent.get(idInParent) ?? yMapOrParent.set(idInParent, new Map());
259
+ let changed;
260
+ objMap(obj, (value, id) => {
261
+ if (set(yMap, id, value)) {
262
+ changed = 1;
263
+ }
264
+ });
265
+ yMap.forEach((_, id) => {
266
+ if (!objHas(obj, id)) {
267
+ yMap.delete(id);
268
+ changed = 1;
269
+ }
270
+ });
271
+ if (!isUndefined(idInParent) && !yMap.size) {
272
+ yMapOrParent.delete(idInParent);
273
+ }
274
+ return changed;
275
+ };
276
+ const createYjsPersister = (store, yDoc, yMapName = 'tinybase') => {
277
+ const yContent = yDoc.getMap(yMapName);
278
+ const getPersisted = async () =>
279
+ yContent.size
280
+ ? [yContent.get(tablesKey).toJSON(), yContent.get(valuesKey).toJSON()]
281
+ : void 0;
282
+ const setPersisted = async (getContent, getTransactionChanges) =>
283
+ yDoc.transact(() =>
284
+ setTransactionChangesToYDoc(yContent, getContent, getTransactionChanges),
285
+ );
104
286
  const addPersisterListener = (listener) => {
105
- const observer = () => listener();
106
- map.observe(observer);
287
+ const observer = (events) =>
288
+ listener(void 0, () => getTransactionChangesFromYDoc(yContent, events));
289
+ yContent.observeDeep(observer);
107
290
  return observer;
108
291
  };
109
- const delPersisterListener = (observer) => map.unobserve(observer);
292
+ const delPersisterListener = (observer) => {
293
+ yContent.unobserveDeep(observer);
294
+ };
110
295
  return createCustomPersister(
111
296
  store,
112
297
  getPersisted,
@@ -1,5 +1,3 @@
1
- const EMPTY_STRING = '';
2
-
3
1
  const isUndefined = (thing) => thing == void 0;
4
2
  const ifNotUndefined = (value, then, otherwise) =>
5
3
  isUndefined(value) ? otherwise?.() : then(value);
@@ -20,43 +18,45 @@ const createCustomPersister = (
20
18
  let saves = 0;
21
19
  let listening = false;
22
20
  let listeningHandle;
23
- const persister = {
24
- load: async (initialTables, initialValues) => {
25
- /* istanbul ignore else */
26
- if (loadSave != 2) {
27
- loadSave = 1;
28
- {
29
- loads++;
30
- }
31
- const body = await getPersisted();
32
- if (!isUndefined(body) && body != EMPTY_STRING) {
33
- store.setJson(body);
34
- } else {
35
- store.setContent([initialTables, initialValues]);
36
- }
37
- loadSave = 0;
21
+ const loadLock = async (actions) => {
22
+ /* istanbul ignore else */
23
+ if (loadSave != 2) {
24
+ loadSave = 1;
25
+ {
26
+ loads++;
38
27
  }
28
+ await actions();
29
+ loadSave = 0;
30
+ }
31
+ };
32
+ const persister = {
33
+ load: async (initialTables = {}, initialValues = {}) => {
34
+ await loadLock(async () => {
35
+ let content;
36
+ try {
37
+ content = await getPersisted();
38
+ } catch {}
39
+ store.setContent(content ?? [initialTables, initialValues]);
40
+ });
39
41
  return persister;
40
42
  },
41
- startAutoLoad: async (initialTables, initialValues) => {
43
+ startAutoLoad: async (initialTables = {}, initialValues = {}) => {
42
44
  persister.stopAutoLoad();
43
45
  await persister.load(initialTables, initialValues);
44
46
  listening = true;
45
- listeningHandle = addPersisterListener(async (content) => {
46
- if (isUndefined(content)) {
47
- await persister.load();
48
- } else {
49
- /* istanbul ignore else */
50
- if (loadSave != 2) {
51
- loadSave = 1;
52
- {
53
- loads++;
47
+ listeningHandle = addPersisterListener(
48
+ async (getContent, getTransactionChanges) => {
49
+ await loadLock(async () => {
50
+ if (getTransactionChanges) {
51
+ store.setTransactionChanges(getTransactionChanges());
52
+ } else {
53
+ try {
54
+ store.setContent(getContent?.() ?? (await getPersisted()));
55
+ } catch {}
54
56
  }
55
- store.setContent(content);
56
- loadSave = 0;
57
- }
58
- }
59
- });
57
+ });
58
+ },
59
+ );
60
60
  return persister;
61
61
  },
62
62
  stopAutoLoad: () => {
@@ -67,21 +67,24 @@ const createCustomPersister = (
67
67
  }
68
68
  return persister;
69
69
  },
70
- save: async () => {
70
+ save: async (getTransactionChanges) => {
71
71
  /* istanbul ignore else */
72
72
  if (loadSave != 1) {
73
73
  loadSave = 2;
74
74
  {
75
75
  saves++;
76
76
  }
77
- await setPersisted(store.getContent);
77
+ await setPersisted(store.getContent, getTransactionChanges);
78
78
  loadSave = 0;
79
79
  }
80
80
  return persister;
81
81
  },
82
82
  startAutoSave: async () => {
83
83
  await persister.stopAutoSave().save();
84
- listenerId = store.addDidFinishTransactionListener(persister.save);
84
+ listenerId = store.addDidFinishTransactionListener(
85
+ (_store, getTransactionChanges) =>
86
+ persister.save(getTransactionChanges),
87
+ );
85
88
  return persister;
86
89
  },
87
90
  stopAutoSave: () => {
@@ -44,6 +44,11 @@ const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
44
44
  const isArray = (thing) => Array.isArray(thing);
45
45
  const getUndefined = () => void 0;
46
46
 
47
+ const object = Object;
48
+ const objFreeze = object.freeze;
49
+ const objMap = (obj, cb) =>
50
+ arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
51
+
47
52
  const collSize = (coll) => coll.size;
48
53
  const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
49
54
  const collIsEmpty = (coll) => isUndefined(coll) || collSize(coll) == 0;
@@ -329,11 +334,6 @@ const getCreateFunction = (getFunction) => {
329
334
  };
330
335
  };
331
336
 
332
- const object = Object;
333
- const objFreeze = object.freeze;
334
- const objMap = (obj, cb) =>
335
- arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
336
-
337
337
  const createQueries = getCreateFunction((store) => {
338
338
  const createStore = store.createStore;
339
339
  const [
@@ -20,6 +20,9 @@ const isString = (thing) => getTypeOf(thing) == STRING;
20
20
  const isArray = (thing) => Array.isArray(thing);
21
21
  const test = (regex, subject) => regex.test(subject);
22
22
 
23
+ const object = Object;
24
+ const objFreeze = object.freeze;
25
+
23
26
  const collSizeN = (collSizer) => (coll) =>
24
27
  arrayReduce(collValues(coll), (total, coll2) => total + collSizer(coll2), 0);
25
28
  const collSize = (coll) => coll.size;
@@ -317,9 +320,6 @@ const getListenerFunctions = (getThing) => {
317
320
  return [addListener, callListeners, delListener, callListener];
318
321
  };
319
322
 
320
- const object = Object;
321
- const objFreeze = object.freeze;
322
-
323
323
  const createRelationships = getCreateFunction((store) => {
324
324
  const remoteTableIds = mapNew();
325
325
  const remoteRowIdListeners = mapNew();