tinybase 3.2.0-beta.0 → 3.3.0

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 (139) 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/persisters.cjs +1 -1
  11. package/lib/cjs/persisters.cjs.gz +0 -0
  12. package/lib/cjs/queries.cjs +1 -1
  13. package/lib/cjs/queries.cjs.gz +0 -0
  14. package/lib/cjs/relationships.cjs +1 -1
  15. package/lib/cjs/relationships.cjs.gz +0 -0
  16. package/lib/cjs/store.cjs +1 -1
  17. package/lib/cjs/store.cjs.gz +0 -0
  18. package/lib/cjs/tinybase.cjs +1 -1
  19. package/lib/cjs/tinybase.cjs.gz +0 -0
  20. package/lib/cjs/tools.cjs +1 -1
  21. package/lib/cjs/tools.cjs.gz +0 -0
  22. package/lib/cjs/ui-react.cjs +1 -1
  23. package/lib/cjs/ui-react.cjs.gz +0 -0
  24. package/lib/cjs-es6/checkpoints.cjs +1 -1
  25. package/lib/cjs-es6/checkpoints.cjs.gz +0 -0
  26. package/lib/cjs-es6/indexes.cjs +1 -1
  27. package/lib/cjs-es6/indexes.cjs.gz +0 -0
  28. package/lib/cjs-es6/metrics.cjs +1 -1
  29. package/lib/cjs-es6/metrics.cjs.gz +0 -0
  30. package/lib/cjs-es6/persisters.cjs +1 -1
  31. package/lib/cjs-es6/persisters.cjs.gz +0 -0
  32. package/lib/cjs-es6/queries.cjs +1 -1
  33. package/lib/cjs-es6/queries.cjs.gz +0 -0
  34. package/lib/cjs-es6/relationships.cjs +1 -1
  35. package/lib/cjs-es6/relationships.cjs.gz +0 -0
  36. package/lib/cjs-es6/store.cjs +1 -1
  37. package/lib/cjs-es6/store.cjs.gz +0 -0
  38. package/lib/cjs-es6/tinybase.cjs +1 -1
  39. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  40. package/lib/cjs-es6/tools.cjs +1 -1
  41. package/lib/cjs-es6/tools.cjs.gz +0 -0
  42. package/lib/cjs-es6/ui-react.cjs +1 -1
  43. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  44. package/lib/debug/checkpoints.js +2 -2
  45. package/lib/debug/indexes.js +2 -2
  46. package/lib/debug/metrics.js +2 -2
  47. package/lib/debug/persisters.js +2 -2
  48. package/lib/debug/queries.js +1 -1
  49. package/lib/debug/relationships.js +2 -2
  50. package/lib/debug/store.js +89 -48
  51. package/lib/debug/tinybase.js +92 -51
  52. package/lib/debug/tools.js +106 -5
  53. package/lib/debug/ui-react.js +27 -2
  54. package/lib/es6/checkpoints.js +1 -1
  55. package/lib/es6/checkpoints.js.gz +0 -0
  56. package/lib/es6/indexes.js +1 -1
  57. package/lib/es6/indexes.js.gz +0 -0
  58. package/lib/es6/metrics.js +1 -1
  59. package/lib/es6/metrics.js.gz +0 -0
  60. package/lib/es6/persisters.js +1 -1
  61. package/lib/es6/persisters.js.gz +0 -0
  62. package/lib/es6/queries.js +1 -1
  63. package/lib/es6/queries.js.gz +0 -0
  64. package/lib/es6/relationships.js +1 -1
  65. package/lib/es6/relationships.js.gz +0 -0
  66. package/lib/es6/store.js +1 -1
  67. package/lib/es6/store.js.gz +0 -0
  68. package/lib/es6/tinybase.js +1 -1
  69. package/lib/es6/tinybase.js.gz +0 -0
  70. package/lib/es6/tools.js +1 -1
  71. package/lib/es6/tools.js.gz +0 -0
  72. package/lib/es6/ui-react.js +1 -1
  73. package/lib/es6/ui-react.js.gz +0 -0
  74. package/lib/indexes.js +1 -1
  75. package/lib/indexes.js.gz +0 -0
  76. package/lib/metrics.js +1 -1
  77. package/lib/metrics.js.gz +0 -0
  78. package/lib/persisters.js +1 -1
  79. package/lib/persisters.js.gz +0 -0
  80. package/lib/queries.js +1 -1
  81. package/lib/queries.js.gz +0 -0
  82. package/lib/relationships.js +1 -1
  83. package/lib/relationships.js.gz +0 -0
  84. package/lib/store.js +1 -1
  85. package/lib/store.js.gz +0 -0
  86. package/lib/tinybase.js +1 -1
  87. package/lib/tinybase.js.gz +0 -0
  88. package/lib/tools.js +1 -1
  89. package/lib/tools.js.gz +0 -0
  90. package/lib/types/store.d.ts +386 -30
  91. package/lib/types/tools.d.ts +2 -2
  92. package/lib/types/ui-react.d.ts +167 -0
  93. package/lib/types/with-schemas/store.d.ts +496 -37
  94. package/lib/types/with-schemas/tools.d.ts +2 -2
  95. package/lib/types/with-schemas/ui-react.d.ts +193 -5
  96. package/lib/ui-react.js +1 -1
  97. package/lib/ui-react.js.gz +0 -0
  98. package/lib/umd/checkpoints.js +1 -1
  99. package/lib/umd/checkpoints.js.gz +0 -0
  100. package/lib/umd/indexes.js +1 -1
  101. package/lib/umd/indexes.js.gz +0 -0
  102. package/lib/umd/metrics.js +1 -1
  103. package/lib/umd/metrics.js.gz +0 -0
  104. package/lib/umd/persisters.js +1 -1
  105. package/lib/umd/persisters.js.gz +0 -0
  106. package/lib/umd/queries.js +1 -1
  107. package/lib/umd/queries.js.gz +0 -0
  108. package/lib/umd/relationships.js +1 -1
  109. package/lib/umd/relationships.js.gz +0 -0
  110. package/lib/umd/store.js +1 -1
  111. package/lib/umd/store.js.gz +0 -0
  112. package/lib/umd/tinybase.js +1 -1
  113. package/lib/umd/tinybase.js.gz +0 -0
  114. package/lib/umd/tools.js +1 -1
  115. package/lib/umd/tools.js.gz +0 -0
  116. package/lib/umd/ui-react.js +1 -1
  117. package/lib/umd/ui-react.js.gz +0 -0
  118. package/lib/umd-es6/checkpoints.js +1 -1
  119. package/lib/umd-es6/checkpoints.js.gz +0 -0
  120. package/lib/umd-es6/indexes.js +1 -1
  121. package/lib/umd-es6/indexes.js.gz +0 -0
  122. package/lib/umd-es6/metrics.js +1 -1
  123. package/lib/umd-es6/metrics.js.gz +0 -0
  124. package/lib/umd-es6/persisters.js +1 -1
  125. package/lib/umd-es6/persisters.js.gz +0 -0
  126. package/lib/umd-es6/queries.js +1 -1
  127. package/lib/umd-es6/queries.js.gz +0 -0
  128. package/lib/umd-es6/relationships.js +1 -1
  129. package/lib/umd-es6/relationships.js.gz +0 -0
  130. package/lib/umd-es6/store.js +1 -1
  131. package/lib/umd-es6/store.js.gz +0 -0
  132. package/lib/umd-es6/tinybase.js +1 -1
  133. package/lib/umd-es6/tinybase.js.gz +0 -0
  134. package/lib/umd-es6/tools.js +1 -1
  135. package/lib/umd-es6/tools.js.gz +0 -0
  136. package/lib/umd-es6/ui-react.js +1 -1
  137. package/lib/umd-es6/ui-react.js.gz +0 -0
  138. package/package.json +52 -28
  139. package/readme.md +14 -14
@@ -48,7 +48,6 @@ const arraySum = (array) => arrayReduce(array, (i, j) => i + j, 0);
48
48
  const arrayLength = (array) => array.length;
49
49
  const arrayIsEmpty = (array) => arrayLength(array) == 0;
50
50
  const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
51
- const arrayFilter = (array, cb) => array.filter(cb);
52
51
  const arraySlice = (array, start, end) => array.slice(start, end);
53
52
  const arrayClear = (array, to) => array.splice(0, to);
54
53
  const arrayPush = (array, ...values) => array.push(...values);
@@ -335,7 +334,7 @@ const getPoolFunctions = () => {
335
334
  const pool = [];
336
335
  let nextId = 0;
337
336
  return [
338
- () => arrayShift(pool) ?? EMPTY_STRING + nextId++,
337
+ (reuse) => (reuse ? arrayShift(pool) : null) ?? EMPTY_STRING + nextId++,
339
338
  (id) => {
340
339
  if (test(INTEGER, id) && arrayLength(pool) < 1e3) {
341
340
  arrayPush(pool, id);
@@ -367,7 +366,7 @@ const getListenerFunctions = (getThing) => {
367
366
  extraArgsGetter = () => [],
368
367
  ) => {
369
368
  thing ??= getThing();
370
- const id = getId();
369
+ const id = getId(1);
371
370
  mapSet(allListeners, id, [
372
371
  listener,
373
372
  idSetNode,
@@ -1025,7 +1024,7 @@ const createCustomPersister = (
1025
1024
  let loads = 0;
1026
1025
  let saves = 0;
1027
1026
  const persister = {
1028
- load: async (initialTables, initialValues) => {
1027
+ load: async (initialTables = {}, initialValues = {}) => {
1029
1028
  /* istanbul ignore else */
1030
1029
  if (loadSave != 2) {
1031
1030
  loadSave = 1;
@@ -1044,7 +1043,7 @@ const createCustomPersister = (
1044
1043
  }
1045
1044
  return persister;
1046
1045
  },
1047
- startAutoLoad: async (initialTables, initialValues) => {
1046
+ startAutoLoad: async (initialTables = {}, initialValues = {}) => {
1048
1047
  persister.stopAutoLoad();
1049
1048
  await persister.load(initialTables, initialValues);
1050
1049
  startListeningToPersisted(persister.load);
@@ -1239,7 +1238,7 @@ const createQueries = getCreateFunction((store) => {
1239
1238
  addPreStoreListener(
1240
1239
  fromStore,
1241
1240
  queryId,
1242
- fromStore.addWillFinishTransactionListener(toStore.startTransaction),
1241
+ fromStore.addStartTransactionListener(toStore.startTransaction),
1243
1242
  fromStore.addDidFinishTransactionListener(() =>
1244
1243
  toStore.finishTransaction(),
1245
1244
  ),
@@ -1820,15 +1819,9 @@ const pairNew = (value) => [value, value];
1820
1819
  const pairCollSize2 = (pair, func = collSize2) => func(pair[0]) + func(pair[1]);
1821
1820
  const pairNewMap = () => [mapNew(), mapNew()];
1822
1821
 
1823
- const transformMap = (map, toBeLikeObject, setId, delId = mapSet) => {
1824
- const idsToDelete = arrayFilter(
1825
- mapKeys(map),
1826
- (id2) => !objHas(toBeLikeObject, id2),
1827
- );
1828
- arrayForEach(objIds(toBeLikeObject), (id2) =>
1829
- setId(map, id2, toBeLikeObject[id2]),
1830
- );
1831
- arrayForEach(idsToDelete, (id2) => delId(map, id2));
1822
+ const mapMatch = (map, obj, set, del = mapSet) => {
1823
+ objMap(obj, (value, id2) => set(map, id2, value));
1824
+ mapForEach(map, (id2) => (objHas(obj, id2) ? 0 : del(map, id2)));
1832
1825
  return map;
1833
1826
  };
1834
1827
  const validate = (obj, validateChild, onInvalidObj) => {
@@ -1852,6 +1845,7 @@ const createStore = () => {
1852
1845
  let valuesTouched;
1853
1846
  let transactions = 0;
1854
1847
  const changedTableIds = mapNew();
1848
+ const changedTableCellIds = mapNew();
1855
1849
  const changedRowIds = mapNew();
1856
1850
  const changedCellIds = mapNew();
1857
1851
  const changedCells = mapNew();
@@ -1865,11 +1859,13 @@ const createStore = () => {
1865
1859
  const valuesDefaulted = mapNew();
1866
1860
  const valuesNonDefaulted = setNew();
1867
1861
  const tablePoolFunctions = mapNew();
1862
+ const tableCellIds = mapNew();
1868
1863
  const tablesMap = mapNew();
1869
1864
  const valuesMap = mapNew();
1870
1865
  const tablesListeners = pairNewMap();
1871
1866
  const tableIdsListeners = pairNewMap();
1872
1867
  const tableListeners = pairNewMap();
1868
+ const tableCellIdsListeners = pairNewMap();
1873
1869
  const rowIdsListeners = pairNewMap();
1874
1870
  const sortedRowIdsListeners = pairNewMap();
1875
1871
  const rowListeners = pairNewMap();
@@ -1880,6 +1876,7 @@ const createStore = () => {
1880
1876
  const valuesListeners = pairNewMap();
1881
1877
  const valueIdsListeners = pairNewMap();
1882
1878
  const valueListeners = pairNewMap();
1879
+ const startTransactionListeners = mapNew();
1883
1880
  const finishTransactionListeners = pairNewMap();
1884
1881
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
1885
1882
  getListenerFunctions(() => store);
@@ -2001,13 +1998,13 @@ const createStore = () => {
2001
1998
  return values;
2002
1999
  };
2003
2000
  const setValidTablesSchema = (tablesSchema) =>
2004
- transformMap(
2001
+ mapMatch(
2005
2002
  tablesSchemaMap,
2006
2003
  tablesSchema,
2007
2004
  (_tablesSchema, tableId, tableSchema) => {
2008
2005
  const rowDefaulted = mapNew();
2009
2006
  const rowNonDefaulted = setNew();
2010
- transformMap(
2007
+ mapMatch(
2011
2008
  mapEnsure(tablesSchemaMap, tableId, mapNew),
2012
2009
  tableSchema,
2013
2010
  (tableSchemaMap, cellId, cellSchema) => {
@@ -2027,7 +2024,7 @@ const createStore = () => {
2027
2024
  },
2028
2025
  );
2029
2026
  const setValidValuesSchema = (valuesSchema) =>
2030
- transformMap(
2027
+ mapMatch(
2031
2028
  valuesSchemaMap,
2032
2029
  valuesSchema,
2033
2030
  (_valuesSchema, valueId, valueSchema) => {
@@ -2047,16 +2044,18 @@ const createStore = () => {
2047
2044
  const setOrDelTables = (tables) =>
2048
2045
  objIsEmpty(tables) ? delTables() : setTables(tables);
2049
2046
  const setValidTables = (tables) =>
2050
- transformMap(
2047
+ mapMatch(
2051
2048
  tablesMap,
2052
2049
  tables,
2053
2050
  (_tables, tableId, table) => setValidTable(tableId, table),
2054
2051
  (_tables, tableId) => delValidTable(tableId),
2055
2052
  );
2056
2053
  const setValidTable = (tableId, table) =>
2057
- transformMap(
2054
+ mapMatch(
2058
2055
  mapEnsure(tablesMap, tableId, () => {
2059
2056
  tableIdsChanged(tableId, 1);
2057
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
2058
+ mapSet(tableCellIds, tableId, mapNew());
2060
2059
  return mapNew();
2061
2060
  }),
2062
2061
  table,
@@ -2064,7 +2063,7 @@ const createStore = () => {
2064
2063
  (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
2065
2064
  );
2066
2065
  const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
2067
- transformMap(
2066
+ mapMatch(
2068
2067
  mapEnsure(tableMap, rowId, () => {
2069
2068
  rowIdsChanged(tableId, rowId, 1);
2070
2069
  return mapNew();
@@ -2100,7 +2099,7 @@ const createStore = () => {
2100
2099
  const setOrDelValues = (values) =>
2101
2100
  objIsEmpty(values) ? delValues() : setValues(values);
2102
2101
  const setValidValues = (values) =>
2103
- transformMap(
2102
+ mapMatch(
2104
2103
  valuesMap,
2105
2104
  values,
2106
2105
  (_valuesMap, valueId, value) => setValidValue(valueId, value),
@@ -2116,23 +2115,19 @@ const createStore = () => {
2116
2115
  mapSet(valuesMap, valueId, value);
2117
2116
  }
2118
2117
  };
2119
- const getNewRowId = (tableId) => {
2120
- const [getId] = mapEnsure(tablePoolFunctions, tableId, getPoolFunctions);
2121
- const rowId = getId();
2118
+ const getNewRowId = (tableId, reuse) => {
2119
+ const [getId] = mapGet(tablePoolFunctions, tableId);
2120
+ const rowId = getId(reuse);
2122
2121
  if (!collHas(mapGet(tablesMap, tableId), rowId)) {
2123
2122
  return rowId;
2124
2123
  }
2125
- return getNewRowId(tableId);
2124
+ return getNewRowId(tableId, reuse);
2126
2125
  };
2127
2126
  const getOrCreateTable = (tableId) =>
2128
2127
  mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
2129
2128
  const delValidTable = (tableId) => setValidTable(tableId, {});
2130
2129
  const delValidRow = (tableId, tableMap, rowId) => {
2131
- const [, releaseId] = mapEnsure(
2132
- tablePoolFunctions,
2133
- tableId,
2134
- getPoolFunctions,
2135
- );
2130
+ const [, releaseId] = mapGet(tablePoolFunctions, tableId);
2136
2131
  releaseId(rowId);
2137
2132
  setValidRow(tableId, tableMap, rowId, {}, true);
2138
2133
  };
@@ -2156,6 +2151,7 @@ const createStore = () => {
2156
2151
  tableIdsChanged(tableId, -1);
2157
2152
  mapSet(tablesMap, tableId);
2158
2153
  mapSet(tablePoolFunctions, tableId);
2154
+ mapSet(tableCellIds, tableId);
2159
2155
  }
2160
2156
  }
2161
2157
  };
@@ -2172,12 +2168,23 @@ const createStore = () => {
2172
2168
  idsChanged(changedTableIds, tableId, added);
2173
2169
  const rowIdsChanged = (tableId, rowId, added) =>
2174
2170
  idsChanged(mapEnsure(changedRowIds, tableId, mapNew), rowId, added);
2175
- const cellIdsChanged = (tableId, rowId, cellId, added) =>
2171
+ const cellIdsChanged = (tableId, rowId, cellId, added) => {
2172
+ const cellIds = mapGet(tableCellIds, tableId);
2173
+ const count = mapGet(cellIds, cellId) ?? 0;
2174
+ if ((count == 0 && added == 1) || (count == 1 && added == -1)) {
2175
+ idsChanged(
2176
+ mapEnsure(changedTableCellIds, tableId, mapNew),
2177
+ cellId,
2178
+ added,
2179
+ );
2180
+ }
2181
+ mapSet(cellIds, cellId, count != -added ? count + added : null);
2176
2182
  idsChanged(
2177
2183
  mapEnsure(mapEnsure(changedCellIds, tableId, mapNew), rowId, mapNew),
2178
2184
  cellId,
2179
2185
  added,
2180
2186
  );
2187
+ };
2181
2188
  const cellChanged = (tableId, rowId, cellId, oldCell, newCell) =>
2182
2189
  (mapEnsure(
2183
2190
  mapEnsure(mapEnsure(changedCells, tableId, mapNew), rowId, mapNew),
@@ -2248,7 +2255,7 @@ const createStore = () => {
2248
2255
  : 0;
2249
2256
  const callIdsListenersIfChanged = (listeners, changedIds, ids) => {
2250
2257
  if (!collIsEmpty(changedIds)) {
2251
- callListeners(listeners, ids);
2258
+ callListeners(listeners, ids, () => mapToObj(changedIds));
2252
2259
  return 1;
2253
2260
  }
2254
2261
  };
@@ -2258,6 +2265,7 @@ const createStore = () => {
2258
2265
  );
2259
2266
  const emptyIdListeners =
2260
2267
  collIsEmpty(cellIdsListeners[mutator]) &&
2268
+ collIsEmpty(tableCellIdsListeners[mutator]) &&
2261
2269
  collIsEmpty(rowIdsListeners[mutator]) &&
2262
2270
  emptySortedRowIdListeners &&
2263
2271
  collIsEmpty(tableIdsListeners[mutator]);
@@ -2270,13 +2278,27 @@ const createStore = () => {
2270
2278
  const changes = mutator
2271
2279
  ? [
2272
2280
  mapClone(changedTableIds),
2281
+ mapClone2(changedTableCellIds),
2273
2282
  mapClone2(changedRowIds),
2274
2283
  mapClone(changedCellIds, mapClone2),
2275
2284
  mapClone(changedCells, mapClone2),
2276
2285
  ]
2277
- : [changedTableIds, changedRowIds, changedCellIds, changedCells];
2286
+ : [
2287
+ changedTableIds,
2288
+ changedTableCellIds,
2289
+ changedRowIds,
2290
+ changedCellIds,
2291
+ changedCells,
2292
+ ];
2278
2293
  if (!emptyIdListeners) {
2279
- collForEach(changes[2], (rowCellIds, tableId) =>
2294
+ collForEach(changes[1], (changedIds, tableId) =>
2295
+ callIdsListenersIfChanged(
2296
+ tableCellIdsListeners[mutator],
2297
+ changedIds,
2298
+ [tableId],
2299
+ ),
2300
+ );
2301
+ collForEach(changes[3], (rowCellIds, tableId) =>
2280
2302
  collForEach(rowCellIds, (changedIds, rowId) =>
2281
2303
  callIdsListenersIfChanged(cellIdsListeners[mutator], changedIds, [
2282
2304
  tableId,
@@ -2285,7 +2307,7 @@ const createStore = () => {
2285
2307
  ),
2286
2308
  );
2287
2309
  const calledSortableTableIds = setNew();
2288
- collForEach(changes[1], (changedIds, tableId) => {
2310
+ collForEach(changes[2], (changedIds, tableId) => {
2289
2311
  if (
2290
2312
  callIdsListenersIfChanged(rowIdsListeners[mutator], changedIds, [
2291
2313
  tableId,
@@ -2297,7 +2319,7 @@ const createStore = () => {
2297
2319
  }
2298
2320
  });
2299
2321
  if (!emptySortedRowIdListeners) {
2300
- collForEach(changes[3], (rows, tableId) => {
2322
+ collForEach(changes[4], (rows, tableId) => {
2301
2323
  if (!collHas(calledSortableTableIds, tableId)) {
2302
2324
  const sortableCellIds = setNew();
2303
2325
  collForEach(rows, (cells) =>
@@ -2320,7 +2342,7 @@ const createStore = () => {
2320
2342
  }
2321
2343
  if (!emptyOtherListeners) {
2322
2344
  let tablesChanged;
2323
- collForEach(changes[3], (rows, tableId) => {
2345
+ collForEach(changes[4], (rows, tableId) => {
2324
2346
  let tableChanged;
2325
2347
  collForEach(rows, (cells, rowId) => {
2326
2348
  let rowChanged;
@@ -2395,6 +2417,8 @@ const createStore = () => {
2395
2417
  const getTableIds = () => mapKeys(tablesMap);
2396
2418
  const getTable = (tableId) =>
2397
2419
  mapToObj(mapGet(tablesMap, id(tableId)), mapToObj);
2420
+ const getTableCellIds = (tableId) =>
2421
+ mapKeys(mapGet(tableCellIds, id(tableId)));
2398
2422
  const getRowIds = (tableId) => mapKeys(mapGet(tablesMap, id(tableId)));
2399
2423
  const getSortedRowIds = (tableId, cellId, descending, offset = 0, limit) =>
2400
2424
  arrayMap(
@@ -2423,6 +2447,8 @@ const createStore = () => {
2423
2447
  const getValue = (valueId) => mapGet(valuesMap, id(valueId));
2424
2448
  const hasTables = () => !collIsEmpty(tablesMap);
2425
2449
  const hasTable = (tableId) => collHas(tablesMap, id(tableId));
2450
+ const hasTableCell = (tableId, cellId) =>
2451
+ collHas(mapGet(tableCellIds, id(tableId)), id(cellId));
2426
2452
  const hasRow = (tableId, rowId) =>
2427
2453
  collHas(mapGet(tablesMap, id(tableId)), id(rowId));
2428
2454
  const hasCell = (tableId, rowId, cellId) =>
@@ -2454,7 +2480,7 @@ const createStore = () => {
2454
2480
  tableId,
2455
2481
  rowId,
2456
2482
  );
2457
- const addRow = (tableId, row) =>
2483
+ const addRow = (tableId, row, reuseRowIds = true) =>
2458
2484
  transaction(() => {
2459
2485
  let rowId = void 0;
2460
2486
  if (validateRow(tableId, rowId, row)) {
@@ -2462,7 +2488,7 @@ const createStore = () => {
2462
2488
  setValidRow(
2463
2489
  tableId,
2464
2490
  getOrCreateTable(tableId),
2465
- (rowId = getNewRowId(tableId)),
2491
+ (rowId = getNewRowId(tableId, reuseRowIds ? 1 : 0)),
2466
2492
  row,
2467
2493
  );
2468
2494
  }
@@ -2639,16 +2665,20 @@ const createStore = () => {
2639
2665
  delValuesSchema();
2640
2666
  });
2641
2667
  const transaction = (actions, doRollback) => {
2642
- if (transactions == -1) {
2643
- return;
2668
+ if (transactions != -1) {
2669
+ startTransaction();
2670
+ const result = actions();
2671
+ finishTransaction(doRollback);
2672
+ return result;
2644
2673
  }
2645
- startTransaction();
2646
- const result = actions();
2647
- finishTransaction(doRollback);
2648
- return result;
2649
2674
  };
2650
2675
  const startTransaction = () => {
2651
- transactions++;
2676
+ if (transactions != -1) {
2677
+ transactions++;
2678
+ }
2679
+ if (transactions == 1) {
2680
+ callListeners(startTransactionListeners, void 0, false, false);
2681
+ }
2652
2682
  return store;
2653
2683
  };
2654
2684
  const finishTransaction = (doRollback) => {
@@ -2666,7 +2696,6 @@ const createStore = () => {
2666
2696
  if (valuesTouched) {
2667
2697
  callKeyedValuesListenersForChanges(1);
2668
2698
  }
2669
- transactions = -1;
2670
2699
  if (
2671
2700
  doRollback?.(
2672
2701
  mapToObj(
@@ -2693,7 +2722,6 @@ const createStore = () => {
2693
2722
  mapToObj(invalidValues),
2694
2723
  )
2695
2724
  ) {
2696
- transactions = 1;
2697
2725
  collForEach(changedCells, (table, tableId) =>
2698
2726
  collForEach(table, (row, rowId) =>
2699
2727
  collForEach(row, ([oldCell], cellId) =>
@@ -2704,7 +2732,6 @@ const createStore = () => {
2704
2732
  collForEach(changedValues, ([oldValue], valueId) =>
2705
2733
  setOrDelValue(store, valueId, oldValue),
2706
2734
  );
2707
- transactions = -1;
2708
2735
  cellsTouched = valuesTouched = false;
2709
2736
  }
2710
2737
  callListeners(
@@ -2713,6 +2740,7 @@ const createStore = () => {
2713
2740
  cellsTouched,
2714
2741
  valuesTouched,
2715
2742
  );
2743
+ transactions = -1;
2716
2744
  callInvalidCellListeners(0);
2717
2745
  if (cellsTouched) {
2718
2746
  callTabularListenersForChanges(0);
@@ -2731,6 +2759,7 @@ const createStore = () => {
2731
2759
  arrayForEach(
2732
2760
  [
2733
2761
  changedTableIds,
2762
+ changedTableCellIds,
2734
2763
  changedRowIds,
2735
2764
  changedCellIds,
2736
2765
  changedCells,
@@ -2755,6 +2784,8 @@ const createStore = () => {
2755
2784
  ),
2756
2785
  ),
2757
2786
  );
2787
+ const forEachTableCell = (tableId, tableCellCallback) =>
2788
+ mapForEach(mapGet(tableCellIds, id(tableId)), tableCellCallback);
2758
2789
  const forEachRow = (tableId, rowCallback) =>
2759
2790
  collForEach(mapGet(tablesMap, id(tableId)), (rowMap, rowId) =>
2760
2791
  rowCallback(rowId, (cellCallback) => mapForEach(rowMap, cellCallback)),
@@ -2805,6 +2836,8 @@ const createStore = () => {
2805
2836
  [getTableIds],
2806
2837
  );
2807
2838
  };
2839
+ const addStartTransactionListener = (listener) =>
2840
+ addListener(listener, startTransactionListeners);
2808
2841
  const addWillFinishTransactionListener = (listener) =>
2809
2842
  addListener(listener, finishTransactionListeners[0]);
2810
2843
  const addDidFinishTransactionListener = (listener) =>
@@ -2820,6 +2853,7 @@ const createStore = () => {
2820
2853
  const getListenerStats = () => ({
2821
2854
  tables: pairCollSize2(tablesListeners),
2822
2855
  tableIds: pairCollSize2(tableIdsListeners),
2856
+ tableCellIds: pairCollSize2(tableCellIdsListeners),
2823
2857
  table: pairCollSize2(tableListeners),
2824
2858
  rowIds: pairCollSize2(rowIdsListeners),
2825
2859
  sortedRowIds: pairCollSize2(sortedRowIdsListeners),
@@ -2831,12 +2865,15 @@ const createStore = () => {
2831
2865
  valueIds: pairCollSize2(valueIdsListeners),
2832
2866
  value: pairCollSize2(valueListeners),
2833
2867
  invalidValue: pairCollSize2(invalidValueListeners),
2834
- transaction: pairCollSize2(finishTransactionListeners),
2868
+ transaction:
2869
+ collSize2(startTransactionListeners) +
2870
+ pairCollSize2(finishTransactionListeners),
2835
2871
  });
2836
2872
  const store = {
2837
2873
  getTables,
2838
2874
  getTableIds,
2839
2875
  getTable,
2876
+ getTableCellIds,
2840
2877
  getRowIds,
2841
2878
  getSortedRowIds,
2842
2879
  getRow,
@@ -2847,6 +2884,7 @@ const createStore = () => {
2847
2884
  getValue,
2848
2885
  hasTables,
2849
2886
  hasTable,
2887
+ hasTableCell,
2850
2888
  hasRow,
2851
2889
  hasCell,
2852
2890
  hasValues,
@@ -2885,10 +2923,12 @@ const createStore = () => {
2885
2923
  startTransaction,
2886
2924
  finishTransaction,
2887
2925
  forEachTable,
2926
+ forEachTableCell,
2888
2927
  forEachRow,
2889
2928
  forEachCell,
2890
2929
  forEachValue,
2891
2930
  addSortedRowIdsListener,
2931
+ addStartTransactionListener,
2892
2932
  addWillFinishTransactionListener,
2893
2933
  addDidFinishTransactionListener,
2894
2934
  callListener,
@@ -2901,6 +2941,7 @@ const createStore = () => {
2901
2941
  [TABLES]: [0, tablesListeners],
2902
2942
  [TABLE_IDS]: [0, tableIdsListeners],
2903
2943
  [TABLE]: [1, tableListeners, [getTableIds]],
2944
+ [TABLE + CELL_IDS]: [1, tableCellIdsListeners, [getTableIds]],
2904
2945
  [ROW_IDS]: [1, rowIdsListeners, [getTableIds]],
2905
2946
  [ROW]: [2, rowListeners, [getTableIds, getRowIds]],
2906
2947
  [CELL_IDS]: [2, cellIdsListeners, [getTableIds, getRowIds]],