tinybase 3.2.0-beta.0 → 4.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 (185) hide show
  1. package/lib/checkpoints.js +1 -1
  2. package/lib/checkpoints.js.gz +0 -0
  3. package/lib/cjs/checkpoints.cjs +1 -1
  4. package/lib/cjs/checkpoints.cjs.gz +0 -0
  5. package/lib/cjs/indexes.cjs +1 -1
  6. package/lib/cjs/indexes.cjs.gz +0 -0
  7. package/lib/cjs/metrics.cjs +1 -1
  8. package/lib/cjs/metrics.cjs.gz +0 -0
  9. package/lib/cjs/persister-browser.cjs +1 -0
  10. package/lib/cjs/persister-browser.cjs.gz +0 -0
  11. package/lib/cjs/persister-file.cjs +1 -0
  12. package/lib/cjs/persister-file.cjs.gz +0 -0
  13. package/lib/cjs/persister-remote.cjs +1 -0
  14. package/lib/cjs/persister-remote.cjs.gz +0 -0
  15. package/lib/cjs/persister-yjs.cjs +1 -0
  16. package/lib/cjs/persister-yjs.cjs.gz +0 -0
  17. package/lib/cjs/persisters.cjs +1 -1
  18. package/lib/cjs/persisters.cjs.gz +0 -0
  19. package/lib/cjs/relationships.cjs +1 -1
  20. package/lib/cjs/relationships.cjs.gz +0 -0
  21. package/lib/cjs/store.cjs +1 -1
  22. package/lib/cjs/store.cjs.gz +0 -0
  23. package/lib/cjs/tinybase.cjs +1 -1
  24. package/lib/cjs/tinybase.cjs.gz +0 -0
  25. package/lib/cjs/tools.cjs +1 -1
  26. package/lib/cjs/tools.cjs.gz +0 -0
  27. package/lib/cjs/ui-react.cjs +1 -1
  28. package/lib/cjs/ui-react.cjs.gz +0 -0
  29. package/lib/cjs-es6/checkpoints.cjs +1 -1
  30. package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
  31. package/lib/cjs-es6/indexes.cjs +1 -1
  32. package/lib/cjs-es6/indexes.cjs.gz +0 -0
  33. package/lib/cjs-es6/metrics.cjs +1 -1
  34. package/lib/cjs-es6/metrics.cjs.gz +0 -0
  35. package/lib/cjs-es6/persister-browser.cjs +1 -0
  36. package/lib/cjs-es6/persister-browser.cjs.gz +0 -0
  37. package/lib/cjs-es6/persister-file.cjs +1 -0
  38. package/lib/cjs-es6/persister-file.cjs.gz +0 -0
  39. package/lib/cjs-es6/persister-remote.cjs +1 -0
  40. package/lib/cjs-es6/persister-remote.cjs.gz +0 -0
  41. package/lib/cjs-es6/persister-yjs.cjs +1 -0
  42. package/lib/cjs-es6/persister-yjs.cjs.gz +0 -0
  43. package/lib/cjs-es6/persisters.cjs +1 -1
  44. package/lib/cjs-es6/persisters.cjs.gz +0 -0
  45. package/lib/cjs-es6/relationships.cjs +1 -1
  46. package/lib/cjs-es6/relationships.cjs.gz +0 -0
  47. package/lib/cjs-es6/store.cjs +1 -1
  48. package/lib/cjs-es6/store.cjs.gz +0 -0
  49. package/lib/cjs-es6/tinybase.cjs +1 -1
  50. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  51. package/lib/cjs-es6/tools.cjs +1 -1
  52. package/lib/cjs-es6/tools.cjs.gz +0 -0
  53. package/lib/cjs-es6/ui-react.cjs +1 -1
  54. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  55. package/lib/debug/checkpoints.js +2 -2
  56. package/lib/debug/indexes.js +2 -2
  57. package/lib/debug/metrics.js +2 -2
  58. package/lib/debug/persister-browser.js +148 -0
  59. package/lib/debug/persister-file.js +140 -0
  60. package/lib/debug/persister-remote.js +156 -0
  61. package/lib/debug/persister-yjs.js +119 -0
  62. package/lib/debug/persisters.js +31 -130
  63. package/lib/debug/relationships.js +2 -2
  64. package/lib/debug/store.js +43 -28
  65. package/lib/debug/tinybase.js +73 -155
  66. package/lib/debug/tools.js +5 -4
  67. package/lib/debug/ui-react.js +3 -2
  68. package/lib/es6/checkpoints.js +1 -1
  69. package/lib/es6/checkpoints.js.gz +0 -0
  70. package/lib/es6/indexes.js +1 -1
  71. package/lib/es6/indexes.js.gz +0 -0
  72. package/lib/es6/metrics.js +1 -1
  73. package/lib/es6/metrics.js.gz +0 -0
  74. package/lib/es6/persister-browser.js +1 -0
  75. package/lib/es6/persister-browser.js.gz +0 -0
  76. package/lib/es6/persister-file.js +1 -0
  77. package/lib/es6/persister-file.js.gz +0 -0
  78. package/lib/es6/persister-remote.js +1 -0
  79. package/lib/es6/persister-remote.js.gz +0 -0
  80. package/lib/es6/persister-yjs.js +1 -0
  81. package/lib/es6/persister-yjs.js.gz +0 -0
  82. package/lib/es6/persisters.js +1 -1
  83. package/lib/es6/persisters.js.gz +0 -0
  84. package/lib/es6/relationships.js +1 -1
  85. package/lib/es6/relationships.js.gz +0 -0
  86. package/lib/es6/store.js +1 -1
  87. package/lib/es6/store.js.gz +0 -0
  88. package/lib/es6/tinybase.js +1 -1
  89. package/lib/es6/tinybase.js.gz +0 -0
  90. package/lib/es6/tools.js +1 -1
  91. package/lib/es6/tools.js.gz +0 -0
  92. package/lib/es6/ui-react.js +1 -1
  93. package/lib/es6/ui-react.js.gz +0 -0
  94. package/lib/indexes.js +1 -1
  95. package/lib/indexes.js.gz +0 -0
  96. package/lib/metrics.js +1 -1
  97. package/lib/metrics.js.gz +0 -0
  98. package/lib/persister-browser.js +1 -0
  99. package/lib/persister-browser.js.gz +0 -0
  100. package/lib/persister-file.js +1 -0
  101. package/lib/persister-file.js.gz +0 -0
  102. package/lib/persister-remote.js +1 -0
  103. package/lib/persister-remote.js.gz +0 -0
  104. package/lib/persister-yjs.js +1 -0
  105. package/lib/persister-yjs.js.gz +0 -0
  106. package/lib/persisters.js +1 -1
  107. package/lib/persisters.js.gz +0 -0
  108. package/lib/relationships.js +1 -1
  109. package/lib/relationships.js.gz +0 -0
  110. package/lib/store.js +1 -1
  111. package/lib/store.js.gz +0 -0
  112. package/lib/tinybase.js +1 -1
  113. package/lib/tinybase.js.gz +0 -0
  114. package/lib/tools.js +1 -1
  115. package/lib/tools.js.gz +0 -0
  116. package/lib/types/persister-browser.d.ts +85 -0
  117. package/lib/types/persister-file.d.ts +41 -0
  118. package/lib/types/persister-remote.d.ts +60 -0
  119. package/lib/types/persister-yjs.d.ts +44 -0
  120. package/lib/types/persisters.d.ts +45 -176
  121. package/lib/types/store.d.ts +127 -12
  122. package/lib/types/ui-react.d.ts +11 -0
  123. package/lib/types/with-schemas/persister-browser.d.ts +103 -0
  124. package/lib/types/with-schemas/persister-file.d.ts +50 -0
  125. package/lib/types/with-schemas/persister-remote.d.ts +71 -0
  126. package/lib/types/with-schemas/persister-yjs.d.ts +53 -0
  127. package/lib/types/with-schemas/persisters.d.ts +58 -218
  128. package/lib/types/with-schemas/store.d.ts +147 -12
  129. package/lib/types/with-schemas/ui-react.d.ts +12 -0
  130. package/lib/ui-react.js +1 -1
  131. package/lib/ui-react.js.gz +0 -0
  132. package/lib/umd/checkpoints.js +1 -1
  133. package/lib/umd/checkpoints.js.gz +0 -0
  134. package/lib/umd/indexes.js +1 -1
  135. package/lib/umd/indexes.js.gz +0 -0
  136. package/lib/umd/metrics.js +1 -1
  137. package/lib/umd/metrics.js.gz +0 -0
  138. package/lib/umd/persister-browser.js +1 -0
  139. package/lib/umd/persister-browser.js.gz +0 -0
  140. package/lib/umd/persister-file.js +1 -0
  141. package/lib/umd/persister-file.js.gz +0 -0
  142. package/lib/umd/persister-remote.js +1 -0
  143. package/lib/umd/persister-remote.js.gz +0 -0
  144. package/lib/umd/persister-yjs.js +1 -0
  145. package/lib/umd/persister-yjs.js.gz +0 -0
  146. package/lib/umd/persisters.js +1 -1
  147. package/lib/umd/persisters.js.gz +0 -0
  148. package/lib/umd/relationships.js +1 -1
  149. package/lib/umd/relationships.js.gz +0 -0
  150. package/lib/umd/store.js +1 -1
  151. package/lib/umd/store.js.gz +0 -0
  152. package/lib/umd/tinybase.js +1 -1
  153. package/lib/umd/tinybase.js.gz +0 -0
  154. package/lib/umd/tools.js +1 -1
  155. package/lib/umd/tools.js.gz +0 -0
  156. package/lib/umd/ui-react.js +1 -1
  157. package/lib/umd/ui-react.js.gz +0 -0
  158. package/lib/umd-es6/checkpoints.js +1 -1
  159. package/lib/umd-es6/checkpoints.js.gz +0 -0
  160. package/lib/umd-es6/indexes.js +1 -1
  161. package/lib/umd-es6/indexes.js.gz +0 -0
  162. package/lib/umd-es6/metrics.js +1 -1
  163. package/lib/umd-es6/metrics.js.gz +0 -0
  164. package/lib/umd-es6/persister-browser.js +1 -0
  165. package/lib/umd-es6/persister-browser.js.gz +0 -0
  166. package/lib/umd-es6/persister-file.js +1 -0
  167. package/lib/umd-es6/persister-file.js.gz +0 -0
  168. package/lib/umd-es6/persister-remote.js +1 -0
  169. package/lib/umd-es6/persister-remote.js.gz +0 -0
  170. package/lib/umd-es6/persister-yjs.js +1 -0
  171. package/lib/umd-es6/persister-yjs.js.gz +0 -0
  172. package/lib/umd-es6/persisters.js +1 -1
  173. package/lib/umd-es6/persisters.js.gz +0 -0
  174. package/lib/umd-es6/relationships.js +1 -1
  175. package/lib/umd-es6/relationships.js.gz +0 -0
  176. package/lib/umd-es6/store.js +1 -1
  177. package/lib/umd-es6/store.js.gz +0 -0
  178. package/lib/umd-es6/tinybase.js +1 -1
  179. package/lib/umd-es6/tinybase.js.gz +0 -0
  180. package/lib/umd-es6/tools.js +1 -1
  181. package/lib/umd-es6/tools.js.gz +0 -0
  182. package/lib/umd-es6/ui-react.js +1 -1
  183. package/lib/umd-es6/ui-react.js.gz +0 -0
  184. package/package.json +15 -10
  185. package/readme.md +2 -2
@@ -1,7 +1,4 @@
1
- import {promises, watch} from 'fs';
2
-
3
1
  const EMPTY_STRING = '';
4
- const UTF8 = 'utf8';
5
2
 
6
3
  const isUndefined = (thing) => thing == void 0;
7
4
  const ifNotUndefined = (value, then, otherwise) =>
@@ -14,14 +11,15 @@ const createCustomPersister = (
14
11
  store,
15
12
  getPersisted,
16
13
  setPersisted,
17
- startListeningToPersisted,
18
- stopListeningToPersisted,
14
+ addPersisterListener,
15
+ delPersisterListener,
19
16
  ) => {
20
- let tablesListenerId;
21
- let valuesListenerId;
17
+ let listenerId;
22
18
  let loadSave = 0;
23
19
  let loads = 0;
24
20
  let saves = 0;
21
+ let listening = false;
22
+ let listeningHandle;
25
23
  const persister = {
26
24
  load: async (initialTables, initialValues) => {
27
25
  /* istanbul ignore else */
@@ -34,9 +32,7 @@ const createCustomPersister = (
34
32
  if (!isUndefined(body) && body != EMPTY_STRING) {
35
33
  store.setJson(body);
36
34
  } else {
37
- store.transaction(() =>
38
- store.setTables(initialTables).setValues(initialValues),
39
- );
35
+ store.setContent([initialTables, initialValues]);
40
36
  }
41
37
  loadSave = 0;
42
38
  }
@@ -45,11 +41,30 @@ const createCustomPersister = (
45
41
  startAutoLoad: async (initialTables, initialValues) => {
46
42
  persister.stopAutoLoad();
47
43
  await persister.load(initialTables, initialValues);
48
- startListeningToPersisted(persister.load);
44
+ 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++;
54
+ }
55
+ store.setContent(content);
56
+ loadSave = 0;
57
+ }
58
+ }
59
+ });
49
60
  return persister;
50
61
  },
51
62
  stopAutoLoad: () => {
52
- stopListeningToPersisted();
63
+ if (listening) {
64
+ delPersisterListener(listeningHandle);
65
+ listeningHandle = void 0;
66
+ listening = false;
67
+ }
53
68
  return persister;
54
69
  },
55
70
  save: async () => {
@@ -59,20 +74,18 @@ const createCustomPersister = (
59
74
  {
60
75
  saves++;
61
76
  }
62
- await setPersisted(store.getJson());
77
+ await setPersisted(store.getContent);
63
78
  loadSave = 0;
64
79
  }
65
80
  return persister;
66
81
  },
67
82
  startAutoSave: async () => {
68
83
  await persister.stopAutoSave().save();
69
- tablesListenerId = store.addTablesListener(persister.save);
70
- valuesListenerId = store.addValuesListener(persister.save);
84
+ listenerId = store.addDidFinishTransactionListener(persister.save);
71
85
  return persister;
72
86
  },
73
87
  stopAutoSave: () => {
74
- ifNotUndefined(tablesListenerId, store.delListener);
75
- ifNotUndefined(valuesListenerId, store.delListener);
88
+ ifNotUndefined(listenerId, store.delListener);
76
89
  return persister;
77
90
  },
78
91
  getStore: () => store,
@@ -82,116 +95,4 @@ const createCustomPersister = (
82
95
  return objFreeze(persister);
83
96
  };
84
97
 
85
- const STORAGE = 'storage';
86
- const WINDOW = globalThis.window;
87
- const getStoragePersister = (store, storageName, storage) => {
88
- let listener;
89
- const getPersisted = async () => storage.getItem(storageName);
90
- const setPersisted = async (json) => storage.setItem(storageName, json);
91
- const startListeningToPersisted = (didChange) => {
92
- listener = (event) => {
93
- if (event.storageArea === storage && event.key === storageName) {
94
- didChange();
95
- }
96
- };
97
- WINDOW.addEventListener(STORAGE, listener);
98
- };
99
- const stopListeningToPersisted = () => {
100
- WINDOW.removeEventListener(STORAGE, listener);
101
- listener = void 0;
102
- };
103
- return createCustomPersister(
104
- store,
105
- getPersisted,
106
- setPersisted,
107
- startListeningToPersisted,
108
- stopListeningToPersisted,
109
- );
110
- };
111
- const createLocalPersister = (store, storageName) =>
112
- getStoragePersister(store, storageName, localStorage);
113
- const createSessionPersister = (store, storageName) =>
114
- getStoragePersister(store, storageName, sessionStorage);
115
-
116
- const createFilePersister = (store, filePath) => {
117
- let watcher;
118
- const getPersisted = async () => {
119
- try {
120
- return await promises.readFile(filePath, UTF8);
121
- } catch {}
122
- };
123
- const setPersisted = async (json) => {
124
- try {
125
- await promises.writeFile(filePath, json, UTF8);
126
- } catch {}
127
- };
128
- const startListeningToPersisted = (didChange) => {
129
- watcher = watch(filePath, didChange);
130
- };
131
- const stopListeningToPersisted = () => {
132
- watcher?.close();
133
- watcher = void 0;
134
- };
135
- return createCustomPersister(
136
- store,
137
- getPersisted,
138
- setPersisted,
139
- startListeningToPersisted,
140
- stopListeningToPersisted,
141
- );
142
- };
143
-
144
- const getETag = (response) => response.headers.get('ETag');
145
- const createRemotePersister = (
146
- store,
147
- loadUrl,
148
- saveUrl,
149
- autoLoadIntervalSeconds,
150
- ) => {
151
- let interval;
152
- let lastEtag;
153
- const getPersisted = async () => {
154
- const response = await fetch(loadUrl);
155
- lastEtag = getETag(response);
156
- return response.text();
157
- };
158
- const setPersisted = async (json) =>
159
- await fetch(saveUrl, {
160
- method: 'POST',
161
- headers: {'Content-Type': 'application/json'},
162
- body: json,
163
- });
164
- const startListeningToPersisted = (didChange) => {
165
- interval = setInterval(async () => {
166
- const response = await fetch(loadUrl, {method: 'HEAD'});
167
- const currentEtag = getETag(response);
168
- if (
169
- !isUndefined(lastEtag) &&
170
- !isUndefined(currentEtag) &&
171
- currentEtag != lastEtag
172
- ) {
173
- lastEtag = currentEtag;
174
- didChange();
175
- }
176
- }, autoLoadIntervalSeconds * 1e3);
177
- };
178
- const stopListeningToPersisted = () => {
179
- ifNotUndefined(interval, clearInterval);
180
- interval = void 0;
181
- };
182
- return createCustomPersister(
183
- store,
184
- getPersisted,
185
- setPersisted,
186
- startListeningToPersisted,
187
- stopListeningToPersisted,
188
- );
189
- };
190
-
191
- export {
192
- createCustomPersister,
193
- createFilePersister,
194
- createLocalPersister,
195
- createRemotePersister,
196
- createSessionPersister,
197
- };
98
+ export {createCustomPersister};
@@ -238,7 +238,7 @@ const getPoolFunctions = () => {
238
238
  const pool = [];
239
239
  let nextId = 0;
240
240
  return [
241
- () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
241
+ (reuse) => (reuse ? arrayShift(pool) : null) ?? EMPTY_STRING + nextId++,
242
242
  (id) => {
243
243
  if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
244
244
  arrayPush(pool, id);
@@ -270,7 +270,7 @@ const getListenerFunctions = (getThing) => {
270
270
  extraArgsGetter = () => [],
271
271
  ) => {
272
272
  thing ??= getThing();
273
- const id = getId();
273
+ const id = getId(1);
274
274
  mapSet(allListeners, id, [
275
275
  listener,
276
276
  idSetNode,
@@ -141,7 +141,7 @@ const getPoolFunctions = () => {
141
141
  const pool = [];
142
142
  let nextId = 0;
143
143
  return [
144
- () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
144
+ (reuse) => (reuse ? arrayShift(pool) : null) ?? EMPTY_STRING + nextId++,
145
145
  (id) => {
146
146
  if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
147
147
  arrayPush(pool, id);
@@ -173,7 +173,7 @@ const getListenerFunctions = (getThing) => {
173
173
  extraArgsGetter = () => [],
174
174
  ) => {
175
175
  thing ??= getThing();
176
- const id = getId();
176
+ const id = getId(1);
177
177
  mapSet(allListeners, id, [
178
178
  listener,
179
179
  idSetNode,
@@ -548,13 +548,13 @@ const createStore = () => {
548
548
  mapSet(valuesMap, valueId, value);
549
549
  }
550
550
  };
551
- const getNewRowId = (tableId) => {
551
+ const getNewRowId = (tableId, reuse) => {
552
552
  const [getId] = mapEnsure(tablePoolFunctions, tableId, getPoolFunctions);
553
- const rowId = getId();
553
+ const rowId = getId(reuse);
554
554
  if (!collHas(mapGet(tablesMap, tableId), rowId)) {
555
555
  return rowId;
556
556
  }
557
- return getNewRowId(tableId);
557
+ return getNewRowId(tableId, reuse);
558
558
  };
559
559
  const getOrCreateTable = (tableId) =>
560
560
  mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
@@ -822,6 +822,7 @@ const createStore = () => {
822
822
  transaction(() => actions(...arrayMap(args, id)));
823
823
  return store;
824
824
  };
825
+ const getContent = () => [getTables(), getValues()];
825
826
  const getTables = () =>
826
827
  mapToObj(tablesMap, (table) => mapToObj(table, mapToObj));
827
828
  const getTableIds = () => mapKeys(tablesMap);
@@ -867,6 +868,11 @@ const createStore = () => {
867
868
  const getTablesSchemaJson = () => jsonString(tablesSchemaMap);
868
869
  const getValuesSchemaJson = () => jsonString(valuesSchemaMap);
869
870
  const getSchemaJson = () => jsonString([tablesSchemaMap, valuesSchemaMap]);
871
+ const setContent = ([tables, values]) =>
872
+ fluentTransaction(() => {
873
+ setTables(tables);
874
+ setValues(values);
875
+ });
870
876
  const setTables = (tables) =>
871
877
  fluentTransaction(() =>
872
878
  validateTables(tables) ? setValidTables(tables) : 0,
@@ -886,7 +892,7 @@ const createStore = () => {
886
892
  tableId,
887
893
  rowId,
888
894
  );
889
- const addRow = (tableId, row) =>
895
+ const addRow = (tableId, row, reuseRowIds = true) =>
890
896
  transaction(() => {
891
897
  let rowId = void 0;
892
898
  if (validateRow(tableId, rowId, row)) {
@@ -894,7 +900,7 @@ const createStore = () => {
894
900
  setValidRow(
895
901
  tableId,
896
902
  getOrCreateTable(tableId),
897
- (rowId = getNewRowId(tableId)),
903
+ (rowId = getNewRowId(tableId, reuseRowIds ? 1 : 0)),
898
904
  row,
899
905
  );
900
906
  }
@@ -1099,32 +1105,36 @@ const createStore = () => {
1099
1105
  callKeyedValuesListenersForChanges(1);
1100
1106
  }
1101
1107
  transactions = -1;
1102
- if (
1103
- doRollback?.(
1104
- mapToObj(
1105
- changedCells,
1106
- (table) =>
1108
+ let transactionChanges =
1109
+ doRollback ||
1110
+ !collIsEmpty(finishTransactionListeners[0]) ||
1111
+ !collIsEmpty(finishTransactionListeners[1])
1112
+ ? [
1107
1113
  mapToObj(
1108
- table,
1109
- (row) =>
1114
+ changedCells,
1115
+ (table) =>
1110
1116
  mapToObj(
1111
- row,
1112
- (cells) => [...cells],
1113
- ([oldCell, newCell]) => oldCell === newCell,
1117
+ table,
1118
+ (row) =>
1119
+ mapToObj(
1120
+ row,
1121
+ (cells) => [...cells],
1122
+ ([oldCell, newCell]) => oldCell === newCell,
1123
+ ),
1124
+ objIsEmpty,
1114
1125
  ),
1115
1126
  objIsEmpty,
1116
1127
  ),
1117
- objIsEmpty,
1118
- ),
1119
- mapToObj(invalidCells, (map) => mapToObj(map, mapToObj)),
1120
- mapToObj(
1121
- changedValues,
1122
- (values) => [...values],
1123
- ([oldValue, newValue]) => oldValue === newValue,
1124
- ),
1125
- mapToObj(invalidValues),
1126
- )
1127
- ) {
1128
+ mapToObj(invalidCells, (map) => mapToObj(map, mapToObj)),
1129
+ mapToObj(
1130
+ changedValues,
1131
+ (values) => [...values],
1132
+ ([oldValue, newValue]) => oldValue === newValue,
1133
+ ),
1134
+ mapToObj(invalidValues),
1135
+ ]
1136
+ : [{}, {}, {}, {}];
1137
+ if (doRollback?.(...transactionChanges)) {
1128
1138
  transactions = 1;
1129
1139
  collForEach(changedCells, (table, tableId) =>
1130
1140
  collForEach(table, (row, rowId) =>
@@ -1138,12 +1148,14 @@ const createStore = () => {
1138
1148
  );
1139
1149
  transactions = -1;
1140
1150
  cellsTouched = valuesTouched = false;
1151
+ transactionChanges = [{}, {}, {}, {}];
1141
1152
  }
1142
1153
  callListeners(
1143
1154
  finishTransactionListeners[0],
1144
1155
  void 0,
1145
1156
  cellsTouched,
1146
1157
  valuesTouched,
1158
+ ...transactionChanges,
1147
1159
  );
1148
1160
  callInvalidCellListeners(0);
1149
1161
  if (cellsTouched) {
@@ -1158,6 +1170,7 @@ const createStore = () => {
1158
1170
  void 0,
1159
1171
  cellsTouched,
1160
1172
  valuesTouched,
1173
+ ...transactionChanges,
1161
1174
  );
1162
1175
  transactions = 0;
1163
1176
  arrayForEach(
@@ -1266,6 +1279,7 @@ const createStore = () => {
1266
1279
  transaction: pairCollSize2(finishTransactionListeners),
1267
1280
  });
1268
1281
  const store = {
1282
+ getContent,
1269
1283
  getTables,
1270
1284
  getTableIds,
1271
1285
  getTable,
@@ -1289,6 +1303,7 @@ const createStore = () => {
1289
1303
  getTablesSchemaJson,
1290
1304
  getValuesSchemaJson,
1291
1305
  getSchemaJson,
1306
+ setContent,
1292
1307
  setTables,
1293
1308
  setTable,
1294
1309
  setRow,