tinybase 7.3.5 → 8.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/@types/index.d.ts +1 -0
  2. package/@types/middleware/index.d.ts +1064 -0
  3. package/@types/middleware/with-schemas/index.d.ts +1355 -0
  4. package/@types/omni/index.d.ts +1 -0
  5. package/@types/omni/with-schemas/index.d.ts +1 -0
  6. package/@types/store/index.d.ts +0 -1
  7. package/@types/with-schemas/index.d.ts +1 -0
  8. package/agents.md +33 -11
  9. package/checkpoints/index.js +8 -9
  10. package/checkpoints/with-schemas/index.js +8 -9
  11. package/index.js +484 -153
  12. package/mergeable-store/index.js +371 -135
  13. package/mergeable-store/with-schemas/index.js +371 -135
  14. package/middleware/index.js +130 -0
  15. package/middleware/with-schemas/index.js +130 -0
  16. package/min/checkpoints/index.js +1 -1
  17. package/min/checkpoints/index.js.gz +0 -0
  18. package/min/checkpoints/with-schemas/index.js +1 -1
  19. package/min/checkpoints/with-schemas/index.js.gz +0 -0
  20. package/min/index.js +1 -1
  21. package/min/index.js.gz +0 -0
  22. package/min/mergeable-store/index.js +1 -1
  23. package/min/mergeable-store/index.js.gz +0 -0
  24. package/min/mergeable-store/with-schemas/index.js +1 -1
  25. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  26. package/min/middleware/index.js +1 -0
  27. package/min/middleware/index.js.gz +0 -0
  28. package/min/middleware/with-schemas/index.js +1 -0
  29. package/min/middleware/with-schemas/index.js.gz +0 -0
  30. package/min/omni/index.js +1 -1
  31. package/min/omni/index.js.gz +0 -0
  32. package/min/omni/with-schemas/index.js +1 -1
  33. package/min/omni/with-schemas/index.js.gz +0 -0
  34. package/min/queries/index.js +1 -1
  35. package/min/queries/index.js.gz +0 -0
  36. package/min/queries/with-schemas/index.js +1 -1
  37. package/min/queries/with-schemas/index.js.gz +0 -0
  38. package/min/store/index.js +1 -1
  39. package/min/store/index.js.gz +0 -0
  40. package/min/store/with-schemas/index.js +1 -1
  41. package/min/store/with-schemas/index.js.gz +0 -0
  42. package/min/ui-react-inspector/index.js +1 -1
  43. package/min/ui-react-inspector/index.js.gz +0 -0
  44. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  45. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  46. package/min/with-schemas/index.js +1 -1
  47. package/min/with-schemas/index.js.gz +0 -0
  48. package/omni/index.js +492 -161
  49. package/omni/with-schemas/index.js +492 -161
  50. package/package.json +37 -1
  51. package/queries/index.js +1 -6
  52. package/queries/with-schemas/index.js +1 -6
  53. package/readme.md +14 -14
  54. package/releases.md +41 -41
  55. package/store/index.js +370 -134
  56. package/store/with-schemas/index.js +370 -134
  57. package/ui-react-inspector/index.js +349 -134
  58. package/ui-react-inspector/with-schemas/index.js +349 -134
  59. package/with-schemas/index.js +484 -153
@@ -101,6 +101,7 @@ const size = (arrayOrString) => arrayOrString.length;
101
101
  const test = (regex, subject) => regex.test(subject);
102
102
  const getUndefined = () => void 0;
103
103
  const getArg = (value) => value;
104
+ const structuredClone = GLOBAL.structuredClone;
104
105
  const errorNew = (message) => {
105
106
  throw new Error(message);
106
107
  };
@@ -703,12 +704,6 @@ const getCellOrValueType = (cellOrValue) => {
703
704
  ? type
704
705
  : void 0;
705
706
  };
706
- const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
707
- isUndefined(cell)
708
- ? store.delCell(tableId, rowId, cellId, true)
709
- : store.setCell(tableId, rowId, cellId, cell);
710
- const setOrDelValue = (store, valueId, value) =>
711
- isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
712
707
  const getTypeCase = (type, stringCase, numberCase, booleanCase) =>
713
708
  type == STRING
714
709
  ? stringCase
@@ -733,12 +728,15 @@ const idsChanged = (changedIds, id2, addedOrRemoved) =>
733
728
  id2,
734
729
  mapGet(changedIds, id2) == -addedOrRemoved ? void 0 : addedOrRemoved,
735
730
  );
731
+ const contentOrChangesIsEqual = ([tables1, values1], [tables2, values2]) =>
732
+ objIsEqual(tables1, tables2) && objIsEqual(values1, values2);
736
733
  const createStore = () => {
737
734
  let hasTablesSchema;
738
735
  let hasValuesSchema;
739
736
  let hadTables = false;
740
737
  let hadValues = false;
741
738
  let transactions = 0;
739
+ let middleware = [];
742
740
  let internalListeners = [];
743
741
  let mutating = 0;
744
742
  const changedTableIds = mapNew();
@@ -786,6 +784,19 @@ const createStore = () => {
786
784
  const finishTransactionListeners = pairNewMap();
787
785
  const [addListener, callListeners, delListenerImpl, callListenerImpl] =
788
786
  getListenerFunctions(() => store);
787
+ const whileMutating = (action) => {
788
+ const wasMutating = mutating;
789
+ mutating = 1;
790
+ const result = action();
791
+ mutating = wasMutating;
792
+ return result;
793
+ };
794
+ const ifTransformed = (snapshot, getResult, then, isEqual = Object.is) =>
795
+ ifNotUndefined(getResult(), (result) =>
796
+ snapshot === result || isEqual(snapshot, result)
797
+ ? then(result)
798
+ : whileMutating(() => then(result)),
799
+ );
789
800
  const validateTablesSchema = (tableSchema) =>
790
801
  objValidate(tableSchema, (tableSchema2) =>
791
802
  objValidate(tableSchema2, validateCellOrValueSchema),
@@ -973,82 +984,194 @@ const createStore = () => {
973
984
  );
974
985
  const setOrDelTables = (tables) =>
975
986
  objIsEmpty(tables) ? delTables() : setTables(tables);
976
- const setValidContent = ([tables, values]) => {
977
- (objIsEmpty(tables) ? delTables : setTables)(tables);
978
- (objIsEmpty(values) ? delValues : setValues)(values);
979
- };
980
- const setValidTables = (tables) =>
981
- mapMatch(
982
- tablesMap,
987
+ const setOrDelCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
988
+ isUndefined(cell)
989
+ ? delCell(tableId, rowId, cellId, true, skipMiddleware)
990
+ : setCell(tableId, rowId, cellId, cell, skipMiddleware);
991
+ const setOrDelValues = (values) =>
992
+ objIsEmpty(values) ? delValues() : setValues(values);
993
+ const setOrDelValue = (valueId, value, skipMiddleware) =>
994
+ isUndefined(value)
995
+ ? delValue(valueId, skipMiddleware)
996
+ : setValue(valueId, value, skipMiddleware);
997
+ const setValidContent = (content) =>
998
+ ifTransformed(
999
+ content,
1000
+ () =>
1001
+ ifNotUndefined(
1002
+ middleware[0],
1003
+ (willSetContent) =>
1004
+ whileMutating(() => willSetContent(structuredClone(content))),
1005
+ () => content,
1006
+ ),
1007
+ ([tables, values]) => {
1008
+ (objIsEmpty(tables) ? delTables : setTables)(tables);
1009
+ (objIsEmpty(values) ? delValues : setValues)(values);
1010
+ },
1011
+ contentOrChangesIsEqual,
1012
+ );
1013
+ const setValidTables = (tables, forceDel) =>
1014
+ ifTransformed(
983
1015
  tables,
984
- (_tables, tableId, table) => setValidTable(tableId, table),
985
- (_tables, tableId) => delValidTable(tableId),
1016
+ () =>
1017
+ forceDel
1018
+ ? tables
1019
+ : ifNotUndefined(
1020
+ middleware[1],
1021
+ (willSetTables) =>
1022
+ whileMutating(() => willSetTables(structuredClone(tables))),
1023
+ () => tables,
1024
+ ),
1025
+ (validTables) =>
1026
+ mapMatch(
1027
+ tablesMap,
1028
+ validTables,
1029
+ (_tables, tableId, table) => setValidTable(tableId, table),
1030
+ (_tables, tableId) => delValidTable(tableId),
1031
+ ),
1032
+ objIsEqual,
986
1033
  );
987
- const setValidTable = (tableId, table) =>
988
- mapMatch(
989
- mapEnsure(tablesMap, tableId, () => {
990
- tableIdsChanged(tableId, 1);
991
- mapSet(tablePoolFunctions, tableId, getPoolFunctions());
992
- mapSet(tableCellIds, tableId, mapNew());
993
- return mapNew();
994
- }),
1034
+ const setValidTable = (tableId, table, forceDel) =>
1035
+ ifTransformed(
995
1036
  table,
996
- (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
997
- (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
1037
+ () =>
1038
+ forceDel
1039
+ ? table
1040
+ : ifNotUndefined(
1041
+ middleware[2],
1042
+ (willSetTable) =>
1043
+ whileMutating(() =>
1044
+ willSetTable(tableId, structuredClone(table)),
1045
+ ),
1046
+ () => table,
1047
+ ),
1048
+ (validTable) =>
1049
+ mapMatch(
1050
+ mapEnsure(tablesMap, tableId, () => {
1051
+ tableIdsChanged(tableId, 1);
1052
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
1053
+ mapSet(tableCellIds, tableId, mapNew());
1054
+ return mapNew();
1055
+ }),
1056
+ validTable,
1057
+ (tableMap, rowId, row) => setValidRow(tableId, tableMap, rowId, row),
1058
+ (tableMap, rowId) => delValidRow(tableId, tableMap, rowId),
1059
+ ),
1060
+ objIsEqual,
998
1061
  );
999
1062
  const setValidRow = (tableId, tableMap, rowId, row, forceDel) =>
1000
- mapMatch(
1001
- mapEnsure(tableMap, rowId, () => {
1002
- rowIdsChanged(tableId, rowId, 1);
1003
- return mapNew();
1004
- }),
1063
+ ifTransformed(
1005
1064
  row,
1006
- (rowMap, cellId, cell) =>
1007
- setValidCell(tableId, rowId, rowMap, cellId, cell),
1008
- (rowMap, cellId) =>
1009
- delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
1065
+ () =>
1066
+ forceDel
1067
+ ? row
1068
+ : ifNotUndefined(
1069
+ middleware[3],
1070
+ (willSetRow) =>
1071
+ whileMutating(() =>
1072
+ willSetRow(tableId, rowId, structuredClone(row)),
1073
+ ),
1074
+ () => row,
1075
+ ),
1076
+ (validRow) =>
1077
+ mapMatch(
1078
+ mapEnsure(tableMap, rowId, () => {
1079
+ rowIdsChanged(tableId, rowId, 1);
1080
+ return mapNew();
1081
+ }),
1082
+ validRow,
1083
+ (rowMap, cellId, cell) =>
1084
+ setValidCell(tableId, rowId, rowMap, cellId, cell),
1085
+ (rowMap, cellId) =>
1086
+ delValidCell(tableId, tableMap, rowId, rowMap, cellId, forceDel),
1087
+ ),
1088
+ objIsEqual,
1010
1089
  );
1011
- const setValidCell = (tableId, rowId, rowMap, cellId, cell) => {
1012
- if (!collHas(rowMap, cellId)) {
1013
- cellIdsChanged(tableId, rowId, cellId, 1);
1014
- }
1015
- const oldCell = mapGet(rowMap, cellId);
1016
- if (cell !== oldCell) {
1017
- cellChanged(tableId, rowId, cellId, oldCell, cell);
1018
- mapSet(rowMap, cellId, cell);
1019
- }
1020
- };
1021
- const setCellIntoDefaultRow = (tableId, tableMap, rowId, cellId, validCell) =>
1090
+ const setValidCell = (tableId, rowId, rowMap, cellId, cell, skipMiddleware) =>
1091
+ ifTransformed(
1092
+ cell,
1093
+ () =>
1094
+ ifNotUndefined(
1095
+ skipMiddleware ? void 0 : middleware[4],
1096
+ (willSetCell) =>
1097
+ whileMutating(() => willSetCell(tableId, rowId, cellId, cell)),
1098
+ () => cell,
1099
+ ),
1100
+ (cell2) => {
1101
+ if (!collHas(rowMap, cellId)) {
1102
+ cellIdsChanged(tableId, rowId, cellId, 1);
1103
+ }
1104
+ const oldCell = mapGet(rowMap, cellId);
1105
+ if (cell2 !== oldCell) {
1106
+ cellChanged(tableId, rowId, cellId, oldCell, cell2);
1107
+ mapSet(rowMap, cellId, cell2);
1108
+ }
1109
+ },
1110
+ );
1111
+ const setCellIntoNewRow = (
1112
+ tableId,
1113
+ tableMap,
1114
+ rowId,
1115
+ cellId,
1116
+ validCell,
1117
+ skipMiddleware,
1118
+ ) =>
1022
1119
  ifNotUndefined(
1023
1120
  mapGet(tableMap, rowId),
1024
- (rowMap) => setValidCell(tableId, rowId, rowMap, cellId, validCell),
1025
- () =>
1026
- setValidRow(
1027
- tableId,
1028
- tableMap,
1029
- rowId,
1121
+ (rowMap) =>
1122
+ setValidCell(tableId, rowId, rowMap, cellId, validCell, skipMiddleware),
1123
+ () => {
1124
+ const rowMap = mapNew();
1125
+ mapSet(tableMap, rowId, rowMap);
1126
+ rowIdsChanged(tableId, rowId, 1);
1127
+ objMap(
1030
1128
  addDefaultsToRow({[cellId]: validCell}, tableId, rowId),
1031
- ),
1129
+ (cell, cellId2) =>
1130
+ setValidCell(tableId, rowId, rowMap, cellId2, cell, skipMiddleware),
1131
+ );
1132
+ },
1032
1133
  );
1033
- const setOrDelValues = (values) =>
1034
- objIsEmpty(values) ? delValues() : setValues(values);
1035
- const setValidValues = (values) =>
1036
- mapMatch(
1037
- valuesMap,
1134
+ const setValidValues = (values, forceDel) =>
1135
+ ifTransformed(
1038
1136
  values,
1039
- (_valuesMap, valueId, value) => setValidValue(valueId, value),
1040
- (_valuesMap, valueId) => delValidValue(valueId),
1137
+ () =>
1138
+ forceDel
1139
+ ? values
1140
+ : ifNotUndefined(
1141
+ middleware[5],
1142
+ (willSetValues) =>
1143
+ whileMutating(() => willSetValues(structuredClone(values))),
1144
+ () => values,
1145
+ ),
1146
+ (validValues) =>
1147
+ mapMatch(
1148
+ valuesMap,
1149
+ validValues,
1150
+ (_valuesMap, valueId, value) => setValidValue(valueId, value),
1151
+ (_valuesMap, valueId) => delValidValue(valueId),
1152
+ ),
1153
+ objIsEqual,
1154
+ );
1155
+ const setValidValue = (valueId, value, skipMiddleware) =>
1156
+ ifTransformed(
1157
+ value,
1158
+ () =>
1159
+ ifNotUndefined(
1160
+ skipMiddleware ? void 0 : middleware[6],
1161
+ (willSetValue) => whileMutating(() => willSetValue(valueId, value)),
1162
+ () => value,
1163
+ ),
1164
+ (value2) => {
1165
+ if (!collHas(valuesMap, valueId)) {
1166
+ valueIdsChanged(valueId, 1);
1167
+ }
1168
+ const oldValue = mapGet(valuesMap, valueId);
1169
+ if (value2 !== oldValue) {
1170
+ valueChanged(valueId, oldValue, value2);
1171
+ mapSet(valuesMap, valueId, value2);
1172
+ }
1173
+ },
1041
1174
  );
1042
- const setValidValue = (valueId, value) => {
1043
- if (!collHas(valuesMap, valueId)) {
1044
- valueIdsChanged(valueId, 1);
1045
- }
1046
- const oldValue = mapGet(valuesMap, valueId);
1047
- if (value !== oldValue) {
1048
- valueChanged(valueId, oldValue, value);
1049
- mapSet(valuesMap, valueId, value);
1050
- }
1051
- };
1052
1175
  const getNewRowId = (tableId, reuse) => {
1053
1176
  const [getId] = mapGet(tablePoolFunctions, tableId);
1054
1177
  let rowId;
@@ -1058,14 +1181,34 @@ const createStore = () => {
1058
1181
  return rowId;
1059
1182
  };
1060
1183
  const getOrCreateTable = (tableId) =>
1061
- mapGet(tablesMap, tableId) ?? setValidTable(tableId, {});
1062
- const delValidTable = (tableId) => setValidTable(tableId, {});
1184
+ mapEnsure(tablesMap, tableId, () => {
1185
+ tableIdsChanged(tableId, 1);
1186
+ mapSet(tablePoolFunctions, tableId, getPoolFunctions());
1187
+ mapSet(tableCellIds, tableId, mapNew());
1188
+ return mapNew();
1189
+ });
1190
+ const delValidTable = (tableId) => {
1191
+ if (whileMutating(() => middleware[8]?.(tableId)) ?? true) {
1192
+ return setValidTable(tableId, {}, true);
1193
+ }
1194
+ return mapGet(tablesMap, tableId);
1195
+ };
1063
1196
  const delValidRow = (tableId, tableMap, rowId) => {
1064
- const [, releaseId] = mapGet(tablePoolFunctions, tableId);
1065
- releaseId(rowId);
1066
- setValidRow(tableId, tableMap, rowId, {}, true);
1197
+ if (whileMutating(() => middleware[9]?.(tableId, rowId)) ?? true) {
1198
+ const [, releaseId] = mapGet(tablePoolFunctions, tableId);
1199
+ releaseId(rowId);
1200
+ setValidRow(tableId, tableMap, rowId, {}, true);
1201
+ }
1067
1202
  };
1068
- const delValidCell = (tableId, table, rowId, row, cellId, forceDel) => {
1203
+ const delValidCell = (
1204
+ tableId,
1205
+ table,
1206
+ rowId,
1207
+ row,
1208
+ cellId,
1209
+ forceDel,
1210
+ skipMiddleware,
1211
+ ) => {
1069
1212
  const defaultCell = mapGet(
1070
1213
  mapGet(tablesSchemaRowCache, tableId)?.[0],
1071
1214
  cellId,
@@ -1073,34 +1216,44 @@ const createStore = () => {
1073
1216
  if (!isUndefined(defaultCell) && !forceDel) {
1074
1217
  return setValidCell(tableId, rowId, row, cellId, defaultCell);
1075
1218
  }
1076
- const delCell2 = (cellId2) => {
1077
- cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
1078
- cellIdsChanged(tableId, rowId, cellId2, -1);
1079
- mapSet(row, cellId2);
1080
- };
1081
- if (isUndefined(defaultCell)) {
1082
- delCell2(cellId);
1083
- } else {
1084
- mapForEach(row, delCell2);
1085
- }
1086
- if (collIsEmpty(row)) {
1087
- rowIdsChanged(tableId, rowId, -1);
1088
- if (collIsEmpty(mapSet(table, rowId))) {
1089
- tableIdsChanged(tableId, -1);
1090
- mapSet(tablesMap, tableId);
1091
- mapSet(tablePoolFunctions, tableId);
1092
- mapSet(tableCellIds, tableId);
1219
+ if (
1220
+ skipMiddleware ||
1221
+ (whileMutating(() => middleware[10]?.(tableId, rowId, cellId)) ?? true)
1222
+ ) {
1223
+ const delCell2 = (cellId2) => {
1224
+ cellChanged(tableId, rowId, cellId2, mapGet(row, cellId2));
1225
+ cellIdsChanged(tableId, rowId, cellId2, -1);
1226
+ mapSet(row, cellId2);
1227
+ };
1228
+ if (isUndefined(defaultCell)) {
1229
+ delCell2(cellId);
1230
+ } else {
1231
+ mapForEach(row, delCell2);
1232
+ }
1233
+ if (collIsEmpty(row)) {
1234
+ rowIdsChanged(tableId, rowId, -1);
1235
+ if (collIsEmpty(mapSet(table, rowId))) {
1236
+ tableIdsChanged(tableId, -1);
1237
+ mapSet(tablesMap, tableId);
1238
+ mapSet(tablePoolFunctions, tableId);
1239
+ mapSet(tableCellIds, tableId);
1240
+ }
1093
1241
  }
1094
1242
  }
1095
1243
  };
1096
- const delValidValue = (valueId) => {
1244
+ const delValidValue = (valueId, skipMiddleware) => {
1097
1245
  const defaultValue = mapGet(valuesDefaulted, valueId);
1098
1246
  if (!isUndefined(defaultValue)) {
1099
1247
  return setValidValue(valueId, defaultValue);
1100
1248
  }
1101
- valueChanged(valueId, mapGet(valuesMap, valueId));
1102
- valueIdsChanged(valueId, -1);
1103
- mapSet(valuesMap, valueId);
1249
+ if (
1250
+ skipMiddleware ||
1251
+ (whileMutating(() => middleware[12]?.(valueId)) ?? true)
1252
+ ) {
1253
+ valueChanged(valueId, mapGet(valuesMap, valueId));
1254
+ valueIdsChanged(valueId, -1);
1255
+ mapSet(valuesMap, valueId);
1256
+ }
1104
1257
  };
1105
1258
  const tableIdsChanged = (tableId, addedOrRemoved) =>
1106
1259
  idsChanged(changedTableIds, tableId, addedOrRemoved);
@@ -1559,14 +1712,14 @@ const createStore = () => {
1559
1712
  if (validateRow(tableId2, rowId2, partialRow, 1)) {
1560
1713
  const table = getOrCreateTable(tableId2);
1561
1714
  objMap(partialRow, (cell, cellId) =>
1562
- setCellIntoDefaultRow(tableId2, table, rowId2, cellId, cell),
1715
+ setCellIntoNewRow(tableId2, table, rowId2, cellId, cell),
1563
1716
  );
1564
1717
  }
1565
1718
  },
1566
1719
  tableId,
1567
1720
  rowId,
1568
1721
  );
1569
- const setCell = (tableId, rowId, cellId, cell) =>
1722
+ const setCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
1570
1723
  fluentTransaction(
1571
1724
  (tableId2, rowId2, cellId2) =>
1572
1725
  ifNotUndefined(
@@ -1577,12 +1730,13 @@ const createStore = () => {
1577
1730
  isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
1578
1731
  ),
1579
1732
  (validCell) =>
1580
- setCellIntoDefaultRow(
1733
+ setCellIntoNewRow(
1581
1734
  tableId2,
1582
1735
  getOrCreateTable(tableId2),
1583
1736
  rowId2,
1584
1737
  cellId2,
1585
1738
  validCell,
1739
+ skipMiddleware,
1586
1740
  ),
1587
1741
  ),
1588
1742
  tableId,
@@ -1601,7 +1755,7 @@ const createStore = () => {
1601
1755
  )
1602
1756
  : 0,
1603
1757
  );
1604
- const setValue = (valueId, value) =>
1758
+ const setValue = (valueId, value, skipMiddleware) =>
1605
1759
  fluentTransaction(
1606
1760
  (valueId2) =>
1607
1761
  ifNotUndefined(
@@ -1609,27 +1763,40 @@ const createStore = () => {
1609
1763
  valueId2,
1610
1764
  isFunction(value) ? value(getValue(valueId2)) : value,
1611
1765
  ),
1612
- (validValue) => setValidValue(valueId2, validValue),
1766
+ (validValue) => setValidValue(valueId2, validValue, skipMiddleware),
1613
1767
  ),
1614
1768
  valueId,
1615
1769
  );
1616
1770
  const applyChanges = (changes) =>
1617
- fluentTransaction(() => {
1618
- objMap(changes[0], (table, tableId) =>
1619
- isUndefined(table)
1620
- ? delTable(tableId)
1621
- : objMap(table, (row, rowId) =>
1622
- isUndefined(row)
1623
- ? delRow(tableId, rowId)
1624
- : objMap(row, (cell, cellId) =>
1625
- setOrDelCell(store, tableId, rowId, cellId, cell),
1626
- ),
1627
- ),
1628
- );
1629
- objMap(changes[1], (value, valueId) =>
1630
- setOrDelValue(store, valueId, value),
1631
- );
1632
- });
1771
+ fluentTransaction(() =>
1772
+ ifTransformed(
1773
+ changes,
1774
+ () =>
1775
+ ifNotUndefined(
1776
+ middleware[13],
1777
+ (willApplyChanges) =>
1778
+ whileMutating(() => willApplyChanges(structuredClone(changes))),
1779
+ () => changes,
1780
+ ),
1781
+ (changes2) => {
1782
+ objMap(changes2[0], (table, tableId) =>
1783
+ isUndefined(table)
1784
+ ? delTable(tableId)
1785
+ : objMap(table, (row, rowId) =>
1786
+ isUndefined(row)
1787
+ ? delRow(tableId, rowId)
1788
+ : objMap(row, (cell, cellId) =>
1789
+ setOrDelCell(tableId, rowId, cellId, cell),
1790
+ ),
1791
+ ),
1792
+ );
1793
+ objMap(changes2[1], (value, valueId) =>
1794
+ setOrDelValue(valueId, value),
1795
+ );
1796
+ },
1797
+ contentOrChangesIsEqual,
1798
+ ),
1799
+ );
1633
1800
  const setTablesJson = (tablesJson) => {
1634
1801
  tryCatch(() => setOrDelTables(jsonParse(tablesJson)));
1635
1802
  return store;
@@ -1676,7 +1843,12 @@ const createStore = () => {
1676
1843
  setTablesSchema(tablesSchema);
1677
1844
  setValuesSchema(valuesSchema);
1678
1845
  });
1679
- const delTables = () => fluentTransaction(() => setValidTables({}));
1846
+ const delTables = () =>
1847
+ fluentTransaction(() =>
1848
+ (whileMutating(() => middleware[7]?.()) ?? true)
1849
+ ? setValidTables({}, true)
1850
+ : 0,
1851
+ );
1680
1852
  const delTable = (tableId) =>
1681
1853
  fluentTransaction(
1682
1854
  (tableId2) =>
@@ -1694,7 +1866,7 @@ const createStore = () => {
1694
1866
  tableId,
1695
1867
  rowId,
1696
1868
  );
1697
- const delCell = (tableId, rowId, cellId, forceDel) =>
1869
+ const delCell = (tableId, rowId, cellId, forceDel, skipMiddleware) =>
1698
1870
  fluentTransaction(
1699
1871
  (tableId2, rowId2, cellId2) =>
1700
1872
  ifNotUndefined(mapGet(tablesMap, tableId2), (tableMap) =>
@@ -1707,6 +1879,7 @@ const createStore = () => {
1707
1879
  rowMap,
1708
1880
  cellId2,
1709
1881
  forceDel,
1882
+ skipMiddleware,
1710
1883
  )
1711
1884
  : 0,
1712
1885
  ),
@@ -1715,11 +1888,18 @@ const createStore = () => {
1715
1888
  rowId,
1716
1889
  cellId,
1717
1890
  );
1718
- const delValues = () => fluentTransaction(() => setValidValues({}));
1719
- const delValue = (valueId) =>
1891
+ const delValues = () =>
1892
+ fluentTransaction(() =>
1893
+ (whileMutating(() => middleware[11]?.()) ?? true)
1894
+ ? setValidValues({}, true)
1895
+ : 0,
1896
+ );
1897
+ const delValue = (valueId, skipMiddleware) =>
1720
1898
  fluentTransaction(
1721
1899
  (valueId2) =>
1722
- collHas(valuesMap, valueId2) ? delValidValue(valueId2) : 0,
1900
+ collHas(valuesMap, valueId2)
1901
+ ? delValidValue(valueId2, skipMiddleware)
1902
+ : 0,
1723
1903
  valueId,
1724
1904
  );
1725
1905
  const delTablesSchema = () =>
@@ -1801,27 +1981,27 @@ const createStore = () => {
1801
1981
  transactions--;
1802
1982
  if (transactions == 0) {
1803
1983
  transactions = 1;
1804
- mutating = 1;
1805
- callInvalidCellListeners(1);
1806
- if (!collIsEmpty(changedCells)) {
1807
- callTabularListenersForChanges(1);
1808
- }
1809
- callInvalidValueListeners(1);
1810
- if (!collIsEmpty(changedValues)) {
1811
- callValuesListenersForChanges(1);
1812
- }
1813
- mutating = 0;
1984
+ whileMutating(() => {
1985
+ callInvalidCellListeners(1);
1986
+ if (!collIsEmpty(changedCells)) {
1987
+ callTabularListenersForChanges(1);
1988
+ }
1989
+ callInvalidValueListeners(1);
1990
+ if (!collIsEmpty(changedValues)) {
1991
+ callValuesListenersForChanges(1);
1992
+ }
1993
+ });
1814
1994
  if (doRollback?.(store)) {
1815
1995
  collForEach(changedCells, (table, tableId) =>
1816
1996
  collForEach(table, (row, rowId) =>
1817
1997
  collForEach(row, ([oldCell], cellId) =>
1818
- setOrDelCell(store, tableId, rowId, cellId, oldCell),
1998
+ setOrDelCell(tableId, rowId, cellId, oldCell, true),
1819
1999
  ),
1820
2000
  ),
1821
2001
  );
1822
2002
  collClear(changedCells);
1823
2003
  collForEach(changedValues, ([oldValue], valueId) =>
1824
- setOrDelValue(store, valueId, oldValue),
2004
+ setOrDelValue(valueId, oldValue, true),
1825
2005
  );
1826
2006
  collClear(changedValues);
1827
2007
  }
@@ -1948,6 +2128,38 @@ const createStore = () => {
1948
2128
  collSize2(startTransactionListeners) +
1949
2129
  pairCollSize2(finishTransactionListeners),
1950
2130
  });
2131
+ const setMiddleware = (
2132
+ willSetContent,
2133
+ willSetTables,
2134
+ willSetTable,
2135
+ willSetRow,
2136
+ willSetCell,
2137
+ willSetValues,
2138
+ willSetValue,
2139
+ willDelTables,
2140
+ willDelTable,
2141
+ willDelRow,
2142
+ willDelCell,
2143
+ willDelValues,
2144
+ willDelValue,
2145
+ willApplyChanges,
2146
+ ) =>
2147
+ (middleware = [
2148
+ willSetContent,
2149
+ willSetTables,
2150
+ willSetTable,
2151
+ willSetRow,
2152
+ willSetCell,
2153
+ willSetValues,
2154
+ willSetValue,
2155
+ willDelTables,
2156
+ willDelTable,
2157
+ willDelRow,
2158
+ willDelCell,
2159
+ willDelValues,
2160
+ willDelValue,
2161
+ willApplyChanges,
2162
+ ]);
1951
2163
  const setInternalListeners = (
1952
2164
  preStartTransaction,
1953
2165
  preFinishTransaction,
@@ -2041,6 +2253,9 @@ const createStore = () => {
2041
2253
  addListener,
2042
2254
  callListeners,
2043
2255
  setInternalListeners,
2256
+ setMiddleware,
2257
+ setOrDelCell,
2258
+ setOrDelValue,
2044
2259
  };
2045
2260
  objMap(
2046
2261
  {