tinybase 8.6.0-beta.0 → 9.0.0-beta.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 (151) hide show
  1. package/@types/_internal/queries/with-schemas/index.d.ts +1 -2
  2. package/@types/_internal/ui/with-schemas/index.d.ts +8 -16
  3. package/@types/persisters/index.d.ts +32 -12
  4. package/@types/persisters/persister-durable-object-sql-storage/index.d.ts +9 -8
  5. package/@types/persisters/persister-durable-object-sql-storage/with-schemas/index.d.ts +10 -10
  6. package/@types/persisters/with-schemas/index.d.ts +56 -20
  7. package/@types/queries/index.d.ts +1 -7
  8. package/@types/queries/with-schemas/index.d.ts +5 -15
  9. package/@types/store/index.d.ts +1 -2
  10. package/@types/store/with-schemas/index.d.ts +19 -29
  11. package/@types/synchronizers/synchronizer-ws-client/index.d.ts +9 -3
  12. package/@types/synchronizers/synchronizer-ws-client/with-schemas/index.d.ts +10 -3
  13. package/@types/synchronizers/synchronizer-ws-server/index.d.ts +15 -2
  14. package/@types/synchronizers/synchronizer-ws-server/with-schemas/index.d.ts +17 -2
  15. package/@types/synchronizers/synchronizer-ws-server-durable-object/index.d.ts +51 -0
  16. package/@types/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.d.ts +51 -0
  17. package/@types/ui-react/with-schemas/index.d.ts +3 -6
  18. package/@types/ui-react-dom/with-schemas/index.d.ts +6 -12
  19. package/@types/ui-react-dom-charts/with-schemas/index.d.ts +3 -4
  20. package/@types/ui-solid/with-schemas/index.d.ts +4 -8
  21. package/@types/ui-solid-dom/with-schemas/index.d.ts +6 -12
  22. package/@types/ui-svelte-dom/with-schemas/index.d.ts +6 -12
  23. package/index.js +21 -19
  24. package/indexes/index.js +6 -8
  25. package/indexes/with-schemas/index.js +6 -8
  26. package/metrics/index.js +6 -8
  27. package/metrics/with-schemas/index.js +6 -8
  28. package/min/index.js +1 -1
  29. package/min/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/persisters/index.js +1 -1
  35. package/min/persisters/index.js.gz +0 -0
  36. package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
  37. package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
  38. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
  39. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
  40. package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
  41. package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
  42. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
  43. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
  44. package/min/persisters/persister-electric-sql/index.js +1 -1
  45. package/min/persisters/persister-electric-sql/index.js.gz +0 -0
  46. package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
  47. package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
  48. package/min/persisters/persister-expo-sqlite/index.js +1 -1
  49. package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
  50. package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
  51. package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
  52. package/min/persisters/persister-libsql/index.js +1 -1
  53. package/min/persisters/persister-libsql/index.js.gz +0 -0
  54. package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
  55. package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
  56. package/min/persisters/persister-pglite/index.js +1 -1
  57. package/min/persisters/persister-pglite/index.js.gz +0 -0
  58. package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
  59. package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
  60. package/min/persisters/persister-postgres/index.js +1 -1
  61. package/min/persisters/persister-postgres/index.js.gz +0 -0
  62. package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
  63. package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
  64. package/min/persisters/persister-powersync/index.js +1 -1
  65. package/min/persisters/persister-powersync/index.js.gz +0 -0
  66. package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
  67. package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
  68. package/min/persisters/persister-react-native-sqlite/index.js +1 -1
  69. package/min/persisters/persister-react-native-sqlite/index.js.gz +0 -0
  70. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js +1 -1
  71. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js.gz +0 -0
  72. package/min/persisters/persister-sqlite-bun/index.js +1 -1
  73. package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
  74. package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
  75. package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
  76. package/min/persisters/persister-sqlite-wasm/index.js +1 -1
  77. package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
  78. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
  79. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
  80. package/min/persisters/persister-sqlite3/index.js +1 -1
  81. package/min/persisters/persister-sqlite3/index.js.gz +0 -0
  82. package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
  83. package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
  84. package/min/persisters/with-schemas/index.js +1 -1
  85. package/min/persisters/with-schemas/index.js.gz +0 -0
  86. package/min/queries/index.js +1 -1
  87. package/min/queries/index.js.gz +0 -0
  88. package/min/queries/with-schemas/index.js +1 -1
  89. package/min/queries/with-schemas/index.js.gz +0 -0
  90. package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
  91. package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
  92. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
  93. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
  94. package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
  95. package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
  96. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
  97. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
  98. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
  99. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
  100. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
  101. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
  102. package/min/with-schemas/index.js +1 -1
  103. package/min/with-schemas/index.js.gz +0 -0
  104. package/omni/index.js +311 -141
  105. package/omni/with-schemas/index.js +311 -141
  106. package/package.json +7 -7
  107. package/persisters/index.js +129 -37
  108. package/persisters/persister-cr-sqlite-wasm/index.js +129 -37
  109. package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +129 -37
  110. package/persisters/persister-durable-object-sql-storage/index.js +271 -110
  111. package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +271 -110
  112. package/persisters/persister-electric-sql/index.js +129 -37
  113. package/persisters/persister-electric-sql/with-schemas/index.js +129 -37
  114. package/persisters/persister-expo-sqlite/index.js +129 -37
  115. package/persisters/persister-expo-sqlite/with-schemas/index.js +129 -37
  116. package/persisters/persister-libsql/index.js +129 -37
  117. package/persisters/persister-libsql/with-schemas/index.js +129 -37
  118. package/persisters/persister-pglite/index.js +130 -37
  119. package/persisters/persister-pglite/with-schemas/index.js +130 -37
  120. package/persisters/persister-postgres/index.js +130 -37
  121. package/persisters/persister-postgres/with-schemas/index.js +130 -37
  122. package/persisters/persister-powersync/index.js +182 -117
  123. package/persisters/persister-powersync/with-schemas/index.js +182 -117
  124. package/persisters/persister-react-native-sqlite/index.js +129 -37
  125. package/persisters/persister-react-native-sqlite/with-schemas/index.js +129 -37
  126. package/persisters/persister-sqlite-bun/index.js +129 -37
  127. package/persisters/persister-sqlite-bun/with-schemas/index.js +129 -37
  128. package/persisters/persister-sqlite-wasm/index.js +129 -37
  129. package/persisters/persister-sqlite-wasm/with-schemas/index.js +129 -37
  130. package/persisters/persister-sqlite3/index.js +129 -37
  131. package/persisters/persister-sqlite3/with-schemas/index.js +129 -37
  132. package/persisters/with-schemas/index.js +129 -37
  133. package/queries/index.js +21 -19
  134. package/queries/with-schemas/index.js +21 -19
  135. package/readme.md +14 -14
  136. package/relationships/index.js +6 -8
  137. package/relationships/with-schemas/index.js +6 -8
  138. package/releases.md +57 -57
  139. package/synchronizers/synchronizer-ws-client/index.js +116 -42
  140. package/synchronizers/synchronizer-ws-client/with-schemas/index.js +116 -42
  141. package/synchronizers/synchronizer-ws-server/index.js +109 -28
  142. package/synchronizers/synchronizer-ws-server/with-schemas/index.js +109 -28
  143. package/synchronizers/synchronizer-ws-server-durable-object/index.js +122 -38
  144. package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +122 -38
  145. package/ui-svelte/index.js +1 -1
  146. package/ui-svelte/with-schemas/index.js +1 -1
  147. package/ui-svelte-dom/index.js +2 -2
  148. package/ui-svelte-dom/with-schemas/index.js +2 -2
  149. package/ui-svelte-inspector/index.js +2 -2
  150. package/ui-svelte-inspector/with-schemas/index.js +2 -2
  151. package/with-schemas/index.js +21 -19
@@ -50,6 +50,7 @@ const tryCatch = async (action, then1, then2) => {
50
50
  }
51
51
  };
52
52
 
53
+ const arrayHas = (array, value) => array.includes(value);
53
54
  const arrayForEach = (array, cb) => array.forEach(cb);
54
55
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
55
56
  const arrayMap = (array, cb) => array.map(cb);
@@ -209,6 +210,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
209
210
  save: 0,
210
211
  [TABLE_NAME]: TINYBASE + '_values',
211
212
  };
213
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
214
+ const hasValues = (config) => isTrue(config) || isArray(config);
212
215
  const getDefaultedConfig = (configOrStoreTableName) =>
213
216
  objMerge(
214
217
  DEFAULT_CONFIG,
@@ -259,11 +262,15 @@ const getConfigStructures = (configOrStoreTableName) => {
259
262
  ];
260
263
  }
261
264
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
262
- const valuesConfig = slice(
263
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
264
- 0,
265
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
266
- );
265
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
266
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
267
+ const valuesConfig = [
268
+ hasValues(valuesLoad),
269
+ hasValues(valuesSave),
270
+ valuesConfigObj[TABLE_NAME],
271
+ getValuesIn(valuesLoad),
272
+ getValuesIn(valuesSave),
273
+ ];
267
274
  const valuesTable = valuesConfig[2];
268
275
  const managedTableNames = setNew(valuesTable);
269
276
  const excludedTableNames = setNew(valuesTable);
@@ -672,8 +679,18 @@ const getCommandFunctions = (
672
679
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
673
680
  );
674
681
  };
675
- const loadTable = async (tableName, rowIdColumnName, condition) =>
676
- canSelect(tableName, rowIdColumnName)
682
+ const loadTable = async (
683
+ tableName,
684
+ rowIdColumnName,
685
+ condition,
686
+ contentSubIds,
687
+ ) => {
688
+ const contentSubIdSet = isUndefined(contentSubIds)
689
+ ? void 0
690
+ : setNew(contentSubIds);
691
+ const includeContentSubId = (contentSubId) =>
692
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
693
+ return canSelect(tableName, rowIdColumnName)
677
694
  ? objNew(
678
695
  arrayFilter(
679
696
  arrayMap(
@@ -682,17 +699,35 @@ const getCommandFunctions = (
682
699
  escapeId(tableName) +
683
700
  getWhereCondition(tableName, condition),
684
701
  ),
685
- (row) => [
686
- row[rowIdColumnName],
687
- decode
702
+ (row) => {
703
+ const rowId = row[rowIdColumnName];
704
+ const rowContent = decode
688
705
  ? objMap(objDel(row, rowIdColumnName), decode)
689
- : objDel(row, rowIdColumnName),
690
- ],
706
+ : objDel(row, rowIdColumnName);
707
+ return [
708
+ rowId,
709
+ isUndefined(contentSubIdSet)
710
+ ? rowContent
711
+ : objNew(
712
+ arrayFilter(
713
+ objToArray(
714
+ rowContent,
715
+ (cellOrValue, contentSubId) => [
716
+ contentSubId,
717
+ cellOrValue,
718
+ ],
719
+ ),
720
+ ([contentSubId]) => includeContentSubId(contentSubId),
721
+ ),
722
+ ),
723
+ ];
724
+ },
691
725
  ),
692
726
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
693
727
  ),
694
728
  )
695
729
  : {};
730
+ };
696
731
  const saveTable = async (
697
732
  tableName,
698
733
  rowIdColumnName,
@@ -701,15 +736,23 @@ const getCommandFunctions = (
701
736
  deleteEmptyTable,
702
737
  partial = false,
703
738
  condition = TRUE,
739
+ contentSubIds,
704
740
  ) => {
741
+ const contentSubIdSet = isUndefined(contentSubIds)
742
+ ? void 0
743
+ : setNew(contentSubIds);
744
+ const includeContentSubId = (contentSubId) =>
745
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
705
746
  const settingColumnNameSet = setNew();
706
747
  objMap(content ?? {}, (contentRow) =>
707
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
708
- setAdd(settingColumnNameSet, cellOrValueId),
748
+ arrayMap(
749
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
750
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
709
751
  ),
710
752
  );
711
753
  const settingColumnNames = collValues(settingColumnNameSet);
712
754
  if (
755
+ isUndefined(contentSubIdSet) &&
713
756
  !partial &&
714
757
  deleteEmptyTable &&
715
758
  condition == TRUE &&
@@ -721,7 +764,13 @@ const getCommandFunctions = (
721
764
  return;
722
765
  }
723
766
  const currentColumnNames = mapGet(schemaMap, tableName);
724
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
767
+ const unaccountedColumnNames = setNew(
768
+ arrayFilter(
769
+ collValues(currentColumnNames),
770
+ (columnName) =>
771
+ columnName == rowIdColumnName || includeContentSubId(columnName),
772
+ ),
773
+ );
725
774
  if (!arrayIsEmpty(settingColumnNames)) {
726
775
  if (!collHas(schemaMap, tableName)) {
727
776
  await databaseExecuteCommand(
@@ -787,11 +836,13 @@ const getCommandFunctions = (
787
836
  ]);
788
837
  if (partial) {
789
838
  if (isUndefined(content)) {
790
- await databaseExecuteCommand(
791
- DELETE_FROM +
792
- escapeId(tableName) +
793
- getWhereCondition(tableName, condition),
794
- );
839
+ if (isUndefined(contentSubIdSet)) {
840
+ await databaseExecuteCommand(
841
+ DELETE_FROM +
842
+ escapeId(tableName) +
843
+ getWhereCondition(tableName, condition),
844
+ );
845
+ }
795
846
  } else {
796
847
  await promiseAll(
797
848
  objToArray(content, async (row, rowId) => {
@@ -804,18 +855,24 @@ const getCommandFunctions = (
804
855
  [rowId],
805
856
  );
806
857
  } else if (!arrayIsEmpty(settingColumnNames)) {
807
- await upsert(
808
- databaseExecuteCommand,
809
- tableName,
810
- rowIdColumnName,
858
+ const changingColumnNames = arrayFilter(
811
859
  objIds(row),
812
- {
813
- [rowId]: encode
814
- ? arrayMap(objValues(row), encode)
815
- : objValues(row),
816
- },
817
- currentColumnNames,
860
+ includeContentSubId,
818
861
  );
862
+ if (!arrayIsEmpty(changingColumnNames)) {
863
+ await upsert(
864
+ databaseExecuteCommand,
865
+ tableName,
866
+ rowIdColumnName,
867
+ changingColumnNames,
868
+ {
869
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
870
+ encode ? encode(row[cellId]) : row[cellId],
871
+ ),
872
+ },
873
+ currentColumnNames,
874
+ );
875
+ }
819
876
  }
820
877
  }),
821
878
  );
@@ -824,7 +881,9 @@ const getCommandFunctions = (
824
881
  if (!arrayIsEmpty(settingColumnNames)) {
825
882
  const changingColumnNames = arrayFilter(
826
883
  collValues(mapGet(schemaMap, tableName)),
827
- (changingColumnName) => changingColumnName != rowIdColumnName,
884
+ (changingColumnName) =>
885
+ changingColumnName != rowIdColumnName &&
886
+ includeContentSubId(changingColumnName),
828
887
  );
829
888
  const rows = {};
830
889
  const deleteRowIds = [];
@@ -840,6 +899,7 @@ const getCommandFunctions = (
840
899
  rowIdColumnName,
841
900
  changingColumnNames,
842
901
  rows,
902
+ currentColumnNames,
843
903
  );
844
904
  await databaseExecuteCommand(
845
905
  DELETE_FROM +
@@ -848,7 +908,10 @@ const getCommandFunctions = (
848
908
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
849
909
  deleteRowIds,
850
910
  );
851
- } else if (collHas(schemaMap, tableName)) {
911
+ } else if (
912
+ isUndefined(contentSubIdSet) &&
913
+ collHas(schemaMap, tableName)
914
+ ) {
852
915
  await databaseExecuteCommand(
853
916
  DELETE_FROM +
854
917
  escapeId(tableName) +
@@ -987,7 +1050,13 @@ const createTabularPersister = (
987
1050
  [
988
1051
  tablesLoadConfig,
989
1052
  tablesSaveConfig,
990
- [valuesLoad, valuesSave, valuesTableName],
1053
+ [
1054
+ valuesLoad,
1055
+ valuesSave,
1056
+ valuesTableName,
1057
+ valuesLoadValueIds,
1058
+ valuesSaveValueIds,
1059
+ ],
991
1060
  ],
992
1061
  managedTableNames,
993
1062
  querySchema,
@@ -1037,15 +1106,33 @@ const createTabularPersister = (
1037
1106
  },
1038
1107
  ),
1039
1108
  );
1109
+ const getValuesSubset = (values, valueIds, partial) =>
1110
+ objNew(
1111
+ partial == true
1112
+ ? arrayFilter(
1113
+ objToArray(values, (value, valueId) => [valueId, value]),
1114
+ ([valueId]) => arrayHas(valueIds, valueId),
1115
+ )
1116
+ : arrayFilter(
1117
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1118
+ ([, value]) => !isUndefined(value),
1119
+ ),
1120
+ );
1040
1121
  const saveValues = async (values, partial) =>
1041
1122
  valuesSave
1042
1123
  ? await saveTable(
1043
1124
  valuesTableName,
1044
1125
  DEFAULT_ROW_ID_COLUMN_NAME,
1045
- {[SINGLE_ROW_ID]: values},
1126
+ {
1127
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1128
+ ? values
1129
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1130
+ },
1046
1131
  true,
1047
1132
  true,
1048
1133
  partial,
1134
+ void 0,
1135
+ valuesSaveValueIds,
1049
1136
  )
1050
1137
  : null;
1051
1138
  const loadTables = async () =>
@@ -1065,9 +1152,14 @@ const createTabularPersister = (
1065
1152
  );
1066
1153
  const loadValues = async () =>
1067
1154
  valuesLoad
1068
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1069
- SINGLE_ROW_ID
1070
- ]
1155
+ ? (
1156
+ await loadTable(
1157
+ valuesTableName,
1158
+ DEFAULT_ROW_ID_COLUMN_NAME,
1159
+ void 0,
1160
+ valuesLoadValueIds,
1161
+ )
1162
+ )[SINGLE_ROW_ID]
1071
1163
  : {};
1072
1164
  const getPersisted = () =>
1073
1165
  transaction(async () => {
@@ -50,6 +50,7 @@ const tryCatch = async (action, then1, then2) => {
50
50
  }
51
51
  };
52
52
 
53
+ const arrayHas = (array, value) => array.includes(value);
53
54
  const arrayForEach = (array, cb) => array.forEach(cb);
54
55
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
55
56
  const arrayMap = (array, cb) => array.map(cb);
@@ -209,6 +210,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
209
210
  save: 0,
210
211
  [TABLE_NAME]: TINYBASE + '_values',
211
212
  };
213
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
214
+ const hasValues = (config) => isTrue(config) || isArray(config);
212
215
  const getDefaultedConfig = (configOrStoreTableName) =>
213
216
  objMerge(
214
217
  DEFAULT_CONFIG,
@@ -259,11 +262,15 @@ const getConfigStructures = (configOrStoreTableName) => {
259
262
  ];
260
263
  }
261
264
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
262
- const valuesConfig = slice(
263
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
264
- 0,
265
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
266
- );
265
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
266
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
267
+ const valuesConfig = [
268
+ hasValues(valuesLoad),
269
+ hasValues(valuesSave),
270
+ valuesConfigObj[TABLE_NAME],
271
+ getValuesIn(valuesLoad),
272
+ getValuesIn(valuesSave),
273
+ ];
267
274
  const valuesTable = valuesConfig[2];
268
275
  const managedTableNames = setNew(valuesTable);
269
276
  const excludedTableNames = setNew(valuesTable);
@@ -672,8 +679,18 @@ const getCommandFunctions = (
672
679
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
673
680
  );
674
681
  };
675
- const loadTable = async (tableName, rowIdColumnName, condition) =>
676
- canSelect(tableName, rowIdColumnName)
682
+ const loadTable = async (
683
+ tableName,
684
+ rowIdColumnName,
685
+ condition,
686
+ contentSubIds,
687
+ ) => {
688
+ const contentSubIdSet = isUndefined(contentSubIds)
689
+ ? void 0
690
+ : setNew(contentSubIds);
691
+ const includeContentSubId = (contentSubId) =>
692
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
693
+ return canSelect(tableName, rowIdColumnName)
677
694
  ? objNew(
678
695
  arrayFilter(
679
696
  arrayMap(
@@ -682,17 +699,35 @@ const getCommandFunctions = (
682
699
  escapeId(tableName) +
683
700
  getWhereCondition(tableName, condition),
684
701
  ),
685
- (row) => [
686
- row[rowIdColumnName],
687
- decode
702
+ (row) => {
703
+ const rowId = row[rowIdColumnName];
704
+ const rowContent = decode
688
705
  ? objMap(objDel(row, rowIdColumnName), decode)
689
- : objDel(row, rowIdColumnName),
690
- ],
706
+ : objDel(row, rowIdColumnName);
707
+ return [
708
+ rowId,
709
+ isUndefined(contentSubIdSet)
710
+ ? rowContent
711
+ : objNew(
712
+ arrayFilter(
713
+ objToArray(
714
+ rowContent,
715
+ (cellOrValue, contentSubId) => [
716
+ contentSubId,
717
+ cellOrValue,
718
+ ],
719
+ ),
720
+ ([contentSubId]) => includeContentSubId(contentSubId),
721
+ ),
722
+ ),
723
+ ];
724
+ },
691
725
  ),
692
726
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
693
727
  ),
694
728
  )
695
729
  : {};
730
+ };
696
731
  const saveTable = async (
697
732
  tableName,
698
733
  rowIdColumnName,
@@ -701,15 +736,23 @@ const getCommandFunctions = (
701
736
  deleteEmptyTable,
702
737
  partial = false,
703
738
  condition = TRUE,
739
+ contentSubIds,
704
740
  ) => {
741
+ const contentSubIdSet = isUndefined(contentSubIds)
742
+ ? void 0
743
+ : setNew(contentSubIds);
744
+ const includeContentSubId = (contentSubId) =>
745
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
705
746
  const settingColumnNameSet = setNew();
706
747
  objMap(content ?? {}, (contentRow) =>
707
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
708
- setAdd(settingColumnNameSet, cellOrValueId),
748
+ arrayMap(
749
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
750
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
709
751
  ),
710
752
  );
711
753
  const settingColumnNames = collValues(settingColumnNameSet);
712
754
  if (
755
+ isUndefined(contentSubIdSet) &&
713
756
  !partial &&
714
757
  deleteEmptyTable &&
715
758
  condition == TRUE &&
@@ -721,7 +764,13 @@ const getCommandFunctions = (
721
764
  return;
722
765
  }
723
766
  const currentColumnNames = mapGet(schemaMap, tableName);
724
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
767
+ const unaccountedColumnNames = setNew(
768
+ arrayFilter(
769
+ collValues(currentColumnNames),
770
+ (columnName) =>
771
+ columnName == rowIdColumnName || includeContentSubId(columnName),
772
+ ),
773
+ );
725
774
  if (!arrayIsEmpty(settingColumnNames)) {
726
775
  if (!collHas(schemaMap, tableName)) {
727
776
  await databaseExecuteCommand(
@@ -787,11 +836,13 @@ const getCommandFunctions = (
787
836
  ]);
788
837
  if (partial) {
789
838
  if (isUndefined(content)) {
790
- await databaseExecuteCommand(
791
- DELETE_FROM +
792
- escapeId(tableName) +
793
- getWhereCondition(tableName, condition),
794
- );
839
+ if (isUndefined(contentSubIdSet)) {
840
+ await databaseExecuteCommand(
841
+ DELETE_FROM +
842
+ escapeId(tableName) +
843
+ getWhereCondition(tableName, condition),
844
+ );
845
+ }
795
846
  } else {
796
847
  await promiseAll(
797
848
  objToArray(content, async (row, rowId) => {
@@ -804,18 +855,24 @@ const getCommandFunctions = (
804
855
  [rowId],
805
856
  );
806
857
  } else if (!arrayIsEmpty(settingColumnNames)) {
807
- await upsert(
808
- databaseExecuteCommand,
809
- tableName,
810
- rowIdColumnName,
858
+ const changingColumnNames = arrayFilter(
811
859
  objIds(row),
812
- {
813
- [rowId]: encode
814
- ? arrayMap(objValues(row), encode)
815
- : objValues(row),
816
- },
817
- currentColumnNames,
860
+ includeContentSubId,
818
861
  );
862
+ if (!arrayIsEmpty(changingColumnNames)) {
863
+ await upsert(
864
+ databaseExecuteCommand,
865
+ tableName,
866
+ rowIdColumnName,
867
+ changingColumnNames,
868
+ {
869
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
870
+ encode ? encode(row[cellId]) : row[cellId],
871
+ ),
872
+ },
873
+ currentColumnNames,
874
+ );
875
+ }
819
876
  }
820
877
  }),
821
878
  );
@@ -824,7 +881,9 @@ const getCommandFunctions = (
824
881
  if (!arrayIsEmpty(settingColumnNames)) {
825
882
  const changingColumnNames = arrayFilter(
826
883
  collValues(mapGet(schemaMap, tableName)),
827
- (changingColumnName) => changingColumnName != rowIdColumnName,
884
+ (changingColumnName) =>
885
+ changingColumnName != rowIdColumnName &&
886
+ includeContentSubId(changingColumnName),
828
887
  );
829
888
  const rows = {};
830
889
  const deleteRowIds = [];
@@ -840,6 +899,7 @@ const getCommandFunctions = (
840
899
  rowIdColumnName,
841
900
  changingColumnNames,
842
901
  rows,
902
+ currentColumnNames,
843
903
  );
844
904
  await databaseExecuteCommand(
845
905
  DELETE_FROM +
@@ -848,7 +908,10 @@ const getCommandFunctions = (
848
908
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
849
909
  deleteRowIds,
850
910
  );
851
- } else if (collHas(schemaMap, tableName)) {
911
+ } else if (
912
+ isUndefined(contentSubIdSet) &&
913
+ collHas(schemaMap, tableName)
914
+ ) {
852
915
  await databaseExecuteCommand(
853
916
  DELETE_FROM +
854
917
  escapeId(tableName) +
@@ -987,7 +1050,13 @@ const createTabularPersister = (
987
1050
  [
988
1051
  tablesLoadConfig,
989
1052
  tablesSaveConfig,
990
- [valuesLoad, valuesSave, valuesTableName],
1053
+ [
1054
+ valuesLoad,
1055
+ valuesSave,
1056
+ valuesTableName,
1057
+ valuesLoadValueIds,
1058
+ valuesSaveValueIds,
1059
+ ],
991
1060
  ],
992
1061
  managedTableNames,
993
1062
  querySchema,
@@ -1037,15 +1106,33 @@ const createTabularPersister = (
1037
1106
  },
1038
1107
  ),
1039
1108
  );
1109
+ const getValuesSubset = (values, valueIds, partial) =>
1110
+ objNew(
1111
+ partial == true
1112
+ ? arrayFilter(
1113
+ objToArray(values, (value, valueId) => [valueId, value]),
1114
+ ([valueId]) => arrayHas(valueIds, valueId),
1115
+ )
1116
+ : arrayFilter(
1117
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1118
+ ([, value]) => !isUndefined(value),
1119
+ ),
1120
+ );
1040
1121
  const saveValues = async (values, partial) =>
1041
1122
  valuesSave
1042
1123
  ? await saveTable(
1043
1124
  valuesTableName,
1044
1125
  DEFAULT_ROW_ID_COLUMN_NAME,
1045
- {[SINGLE_ROW_ID]: values},
1126
+ {
1127
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1128
+ ? values
1129
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1130
+ },
1046
1131
  true,
1047
1132
  true,
1048
1133
  partial,
1134
+ void 0,
1135
+ valuesSaveValueIds,
1049
1136
  )
1050
1137
  : null;
1051
1138
  const loadTables = async () =>
@@ -1065,9 +1152,14 @@ const createTabularPersister = (
1065
1152
  );
1066
1153
  const loadValues = async () =>
1067
1154
  valuesLoad
1068
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1069
- SINGLE_ROW_ID
1070
- ]
1155
+ ? (
1156
+ await loadTable(
1157
+ valuesTableName,
1158
+ DEFAULT_ROW_ID_COLUMN_NAME,
1159
+ void 0,
1160
+ valuesLoadValueIds,
1161
+ )
1162
+ )[SINGLE_ROW_ID]
1071
1163
  : {};
1072
1164
  const getPersisted = () =>
1073
1165
  transaction(async () => {