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
@@ -49,6 +49,7 @@ const tryCatch = async (action, then1, then2) => {
49
49
  }
50
50
  };
51
51
 
52
+ const arrayHas = (array, value) => array.includes(value);
52
53
  const arrayForEach = (array, cb) => array.forEach(cb);
53
54
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
54
55
  const arrayMap = (array, cb) => array.map(cb);
@@ -208,6 +209,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
208
209
  save: 0,
209
210
  [TABLE_NAME]: TINYBASE + '_values',
210
211
  };
212
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
213
+ const hasValues = (config) => isTrue(config) || isArray(config);
211
214
  const getDefaultedConfig = (configOrStoreTableName) =>
212
215
  objMerge(
213
216
  DEFAULT_CONFIG,
@@ -258,11 +261,15 @@ const getConfigStructures = (configOrStoreTableName) => {
258
261
  ];
259
262
  }
260
263
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
261
- const valuesConfig = slice(
262
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
263
- 0,
264
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
265
- );
264
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
265
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
266
+ const valuesConfig = [
267
+ hasValues(valuesLoad),
268
+ hasValues(valuesSave),
269
+ valuesConfigObj[TABLE_NAME],
270
+ getValuesIn(valuesLoad),
271
+ getValuesIn(valuesSave),
272
+ ];
266
273
  const valuesTable = valuesConfig[2];
267
274
  const managedTableNames = setNew(valuesTable);
268
275
  const excludedTableNames = setNew(valuesTable);
@@ -671,8 +678,18 @@ const getCommandFunctions = (
671
678
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
672
679
  );
673
680
  };
674
- const loadTable = async (tableName, rowIdColumnName, condition) =>
675
- canSelect(tableName, rowIdColumnName)
681
+ const loadTable = async (
682
+ tableName,
683
+ rowIdColumnName,
684
+ condition,
685
+ contentSubIds,
686
+ ) => {
687
+ const contentSubIdSet = isUndefined(contentSubIds)
688
+ ? void 0
689
+ : setNew(contentSubIds);
690
+ const includeContentSubId = (contentSubId) =>
691
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
692
+ return canSelect(tableName, rowIdColumnName)
676
693
  ? objNew(
677
694
  arrayFilter(
678
695
  arrayMap(
@@ -681,17 +698,35 @@ const getCommandFunctions = (
681
698
  escapeId(tableName) +
682
699
  getWhereCondition(tableName, condition),
683
700
  ),
684
- (row) => [
685
- row[rowIdColumnName],
686
- decode
701
+ (row) => {
702
+ const rowId = row[rowIdColumnName];
703
+ const rowContent = decode
687
704
  ? objMap(objDel(row, rowIdColumnName), decode)
688
- : objDel(row, rowIdColumnName),
689
- ],
705
+ : objDel(row, rowIdColumnName);
706
+ return [
707
+ rowId,
708
+ isUndefined(contentSubIdSet)
709
+ ? rowContent
710
+ : objNew(
711
+ arrayFilter(
712
+ objToArray(
713
+ rowContent,
714
+ (cellOrValue, contentSubId) => [
715
+ contentSubId,
716
+ cellOrValue,
717
+ ],
718
+ ),
719
+ ([contentSubId]) => includeContentSubId(contentSubId),
720
+ ),
721
+ ),
722
+ ];
723
+ },
690
724
  ),
691
725
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
692
726
  ),
693
727
  )
694
728
  : {};
729
+ };
695
730
  const saveTable = async (
696
731
  tableName,
697
732
  rowIdColumnName,
@@ -700,15 +735,23 @@ const getCommandFunctions = (
700
735
  deleteEmptyTable,
701
736
  partial = false,
702
737
  condition = TRUE,
738
+ contentSubIds,
703
739
  ) => {
740
+ const contentSubIdSet = isUndefined(contentSubIds)
741
+ ? void 0
742
+ : setNew(contentSubIds);
743
+ const includeContentSubId = (contentSubId) =>
744
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
704
745
  const settingColumnNameSet = setNew();
705
746
  objMap(content ?? {}, (contentRow) =>
706
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
707
- setAdd(settingColumnNameSet, cellOrValueId),
747
+ arrayMap(
748
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
749
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
708
750
  ),
709
751
  );
710
752
  const settingColumnNames = collValues(settingColumnNameSet);
711
753
  if (
754
+ isUndefined(contentSubIdSet) &&
712
755
  !partial &&
713
756
  deleteEmptyTable &&
714
757
  condition == TRUE &&
@@ -720,7 +763,13 @@ const getCommandFunctions = (
720
763
  return;
721
764
  }
722
765
  const currentColumnNames = mapGet(schemaMap, tableName);
723
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
766
+ const unaccountedColumnNames = setNew(
767
+ arrayFilter(
768
+ collValues(currentColumnNames),
769
+ (columnName) =>
770
+ columnName == rowIdColumnName || includeContentSubId(columnName),
771
+ ),
772
+ );
724
773
  if (!arrayIsEmpty(settingColumnNames)) {
725
774
  if (!collHas(schemaMap, tableName)) {
726
775
  await databaseExecuteCommand(
@@ -786,11 +835,13 @@ const getCommandFunctions = (
786
835
  ]);
787
836
  if (partial) {
788
837
  if (isUndefined(content)) {
789
- await databaseExecuteCommand(
790
- DELETE_FROM +
791
- escapeId(tableName) +
792
- getWhereCondition(tableName, condition),
793
- );
838
+ if (isUndefined(contentSubIdSet)) {
839
+ await databaseExecuteCommand(
840
+ DELETE_FROM +
841
+ escapeId(tableName) +
842
+ getWhereCondition(tableName, condition),
843
+ );
844
+ }
794
845
  } else {
795
846
  await promiseAll(
796
847
  objToArray(content, async (row, rowId) => {
@@ -803,18 +854,24 @@ const getCommandFunctions = (
803
854
  [rowId],
804
855
  );
805
856
  } else if (!arrayIsEmpty(settingColumnNames)) {
806
- await upsert(
807
- databaseExecuteCommand,
808
- tableName,
809
- rowIdColumnName,
857
+ const changingColumnNames = arrayFilter(
810
858
  objIds(row),
811
- {
812
- [rowId]: encode
813
- ? arrayMap(objValues(row), encode)
814
- : objValues(row),
815
- },
816
- currentColumnNames,
859
+ includeContentSubId,
817
860
  );
861
+ if (!arrayIsEmpty(changingColumnNames)) {
862
+ await upsert(
863
+ databaseExecuteCommand,
864
+ tableName,
865
+ rowIdColumnName,
866
+ changingColumnNames,
867
+ {
868
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
869
+ encode ? encode(row[cellId]) : row[cellId],
870
+ ),
871
+ },
872
+ currentColumnNames,
873
+ );
874
+ }
818
875
  }
819
876
  }),
820
877
  );
@@ -823,7 +880,9 @@ const getCommandFunctions = (
823
880
  if (!arrayIsEmpty(settingColumnNames)) {
824
881
  const changingColumnNames = arrayFilter(
825
882
  collValues(mapGet(schemaMap, tableName)),
826
- (changingColumnName) => changingColumnName != rowIdColumnName,
883
+ (changingColumnName) =>
884
+ changingColumnName != rowIdColumnName &&
885
+ includeContentSubId(changingColumnName),
827
886
  );
828
887
  const rows = {};
829
888
  const deleteRowIds = [];
@@ -839,6 +898,7 @@ const getCommandFunctions = (
839
898
  rowIdColumnName,
840
899
  changingColumnNames,
841
900
  rows,
901
+ currentColumnNames,
842
902
  );
843
903
  await databaseExecuteCommand(
844
904
  DELETE_FROM +
@@ -847,7 +907,10 @@ const getCommandFunctions = (
847
907
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
848
908
  deleteRowIds,
849
909
  );
850
- } else if (collHas(schemaMap, tableName)) {
910
+ } else if (
911
+ isUndefined(contentSubIdSet) &&
912
+ collHas(schemaMap, tableName)
913
+ ) {
851
914
  await databaseExecuteCommand(
852
915
  DELETE_FROM +
853
916
  escapeId(tableName) +
@@ -986,7 +1049,13 @@ const createTabularPersister = (
986
1049
  [
987
1050
  tablesLoadConfig,
988
1051
  tablesSaveConfig,
989
- [valuesLoad, valuesSave, valuesTableName],
1052
+ [
1053
+ valuesLoad,
1054
+ valuesSave,
1055
+ valuesTableName,
1056
+ valuesLoadValueIds,
1057
+ valuesSaveValueIds,
1058
+ ],
990
1059
  ],
991
1060
  managedTableNames,
992
1061
  querySchema,
@@ -1036,15 +1105,33 @@ const createTabularPersister = (
1036
1105
  },
1037
1106
  ),
1038
1107
  );
1108
+ const getValuesSubset = (values, valueIds, partial) =>
1109
+ objNew(
1110
+ partial == true
1111
+ ? arrayFilter(
1112
+ objToArray(values, (value, valueId) => [valueId, value]),
1113
+ ([valueId]) => arrayHas(valueIds, valueId),
1114
+ )
1115
+ : arrayFilter(
1116
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1117
+ ([, value]) => !isUndefined(value),
1118
+ ),
1119
+ );
1039
1120
  const saveValues = async (values, partial) =>
1040
1121
  valuesSave
1041
1122
  ? await saveTable(
1042
1123
  valuesTableName,
1043
1124
  DEFAULT_ROW_ID_COLUMN_NAME,
1044
- {[SINGLE_ROW_ID]: values},
1125
+ {
1126
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1127
+ ? values
1128
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1129
+ },
1045
1130
  true,
1046
1131
  true,
1047
1132
  partial,
1133
+ void 0,
1134
+ valuesSaveValueIds,
1048
1135
  )
1049
1136
  : null;
1050
1137
  const loadTables = async () =>
@@ -1064,9 +1151,14 @@ const createTabularPersister = (
1064
1151
  );
1065
1152
  const loadValues = async () =>
1066
1153
  valuesLoad
1067
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1068
- SINGLE_ROW_ID
1069
- ]
1154
+ ? (
1155
+ await loadTable(
1156
+ valuesTableName,
1157
+ DEFAULT_ROW_ID_COLUMN_NAME,
1158
+ void 0,
1159
+ valuesLoadValueIds,
1160
+ )
1161
+ )[SINGLE_ROW_ID]
1070
1162
  : {};
1071
1163
  const getPersisted = () =>
1072
1164
  transaction(async () => {
@@ -49,6 +49,7 @@ const tryCatch = async (action, then1, then2) => {
49
49
  }
50
50
  };
51
51
 
52
+ const arrayHas = (array, value) => array.includes(value);
52
53
  const arrayForEach = (array, cb) => array.forEach(cb);
53
54
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
54
55
  const arrayMap = (array, cb) => array.map(cb);
@@ -208,6 +209,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
208
209
  save: 0,
209
210
  [TABLE_NAME]: TINYBASE + '_values',
210
211
  };
212
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
213
+ const hasValues = (config) => isTrue(config) || isArray(config);
211
214
  const getDefaultedConfig = (configOrStoreTableName) =>
212
215
  objMerge(
213
216
  DEFAULT_CONFIG,
@@ -258,11 +261,15 @@ const getConfigStructures = (configOrStoreTableName) => {
258
261
  ];
259
262
  }
260
263
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
261
- const valuesConfig = slice(
262
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
263
- 0,
264
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
265
- );
264
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
265
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
266
+ const valuesConfig = [
267
+ hasValues(valuesLoad),
268
+ hasValues(valuesSave),
269
+ valuesConfigObj[TABLE_NAME],
270
+ getValuesIn(valuesLoad),
271
+ getValuesIn(valuesSave),
272
+ ];
266
273
  const valuesTable = valuesConfig[2];
267
274
  const managedTableNames = setNew(valuesTable);
268
275
  const excludedTableNames = setNew(valuesTable);
@@ -671,8 +678,18 @@ const getCommandFunctions = (
671
678
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
672
679
  );
673
680
  };
674
- const loadTable = async (tableName, rowIdColumnName, condition) =>
675
- canSelect(tableName, rowIdColumnName)
681
+ const loadTable = async (
682
+ tableName,
683
+ rowIdColumnName,
684
+ condition,
685
+ contentSubIds,
686
+ ) => {
687
+ const contentSubIdSet = isUndefined(contentSubIds)
688
+ ? void 0
689
+ : setNew(contentSubIds);
690
+ const includeContentSubId = (contentSubId) =>
691
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
692
+ return canSelect(tableName, rowIdColumnName)
676
693
  ? objNew(
677
694
  arrayFilter(
678
695
  arrayMap(
@@ -681,17 +698,35 @@ const getCommandFunctions = (
681
698
  escapeId(tableName) +
682
699
  getWhereCondition(tableName, condition),
683
700
  ),
684
- (row) => [
685
- row[rowIdColumnName],
686
- decode
701
+ (row) => {
702
+ const rowId = row[rowIdColumnName];
703
+ const rowContent = decode
687
704
  ? objMap(objDel(row, rowIdColumnName), decode)
688
- : objDel(row, rowIdColumnName),
689
- ],
705
+ : objDel(row, rowIdColumnName);
706
+ return [
707
+ rowId,
708
+ isUndefined(contentSubIdSet)
709
+ ? rowContent
710
+ : objNew(
711
+ arrayFilter(
712
+ objToArray(
713
+ rowContent,
714
+ (cellOrValue, contentSubId) => [
715
+ contentSubId,
716
+ cellOrValue,
717
+ ],
718
+ ),
719
+ ([contentSubId]) => includeContentSubId(contentSubId),
720
+ ),
721
+ ),
722
+ ];
723
+ },
690
724
  ),
691
725
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
692
726
  ),
693
727
  )
694
728
  : {};
729
+ };
695
730
  const saveTable = async (
696
731
  tableName,
697
732
  rowIdColumnName,
@@ -700,15 +735,23 @@ const getCommandFunctions = (
700
735
  deleteEmptyTable,
701
736
  partial = false,
702
737
  condition = TRUE,
738
+ contentSubIds,
703
739
  ) => {
740
+ const contentSubIdSet = isUndefined(contentSubIds)
741
+ ? void 0
742
+ : setNew(contentSubIds);
743
+ const includeContentSubId = (contentSubId) =>
744
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
704
745
  const settingColumnNameSet = setNew();
705
746
  objMap(content ?? {}, (contentRow) =>
706
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
707
- setAdd(settingColumnNameSet, cellOrValueId),
747
+ arrayMap(
748
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
749
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
708
750
  ),
709
751
  );
710
752
  const settingColumnNames = collValues(settingColumnNameSet);
711
753
  if (
754
+ isUndefined(contentSubIdSet) &&
712
755
  !partial &&
713
756
  deleteEmptyTable &&
714
757
  condition == TRUE &&
@@ -720,7 +763,13 @@ const getCommandFunctions = (
720
763
  return;
721
764
  }
722
765
  const currentColumnNames = mapGet(schemaMap, tableName);
723
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
766
+ const unaccountedColumnNames = setNew(
767
+ arrayFilter(
768
+ collValues(currentColumnNames),
769
+ (columnName) =>
770
+ columnName == rowIdColumnName || includeContentSubId(columnName),
771
+ ),
772
+ );
724
773
  if (!arrayIsEmpty(settingColumnNames)) {
725
774
  if (!collHas(schemaMap, tableName)) {
726
775
  await databaseExecuteCommand(
@@ -786,11 +835,13 @@ const getCommandFunctions = (
786
835
  ]);
787
836
  if (partial) {
788
837
  if (isUndefined(content)) {
789
- await databaseExecuteCommand(
790
- DELETE_FROM +
791
- escapeId(tableName) +
792
- getWhereCondition(tableName, condition),
793
- );
838
+ if (isUndefined(contentSubIdSet)) {
839
+ await databaseExecuteCommand(
840
+ DELETE_FROM +
841
+ escapeId(tableName) +
842
+ getWhereCondition(tableName, condition),
843
+ );
844
+ }
794
845
  } else {
795
846
  await promiseAll(
796
847
  objToArray(content, async (row, rowId) => {
@@ -803,18 +854,24 @@ const getCommandFunctions = (
803
854
  [rowId],
804
855
  );
805
856
  } else if (!arrayIsEmpty(settingColumnNames)) {
806
- await upsert(
807
- databaseExecuteCommand,
808
- tableName,
809
- rowIdColumnName,
857
+ const changingColumnNames = arrayFilter(
810
858
  objIds(row),
811
- {
812
- [rowId]: encode
813
- ? arrayMap(objValues(row), encode)
814
- : objValues(row),
815
- },
816
- currentColumnNames,
859
+ includeContentSubId,
817
860
  );
861
+ if (!arrayIsEmpty(changingColumnNames)) {
862
+ await upsert(
863
+ databaseExecuteCommand,
864
+ tableName,
865
+ rowIdColumnName,
866
+ changingColumnNames,
867
+ {
868
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
869
+ encode ? encode(row[cellId]) : row[cellId],
870
+ ),
871
+ },
872
+ currentColumnNames,
873
+ );
874
+ }
818
875
  }
819
876
  }),
820
877
  );
@@ -823,7 +880,9 @@ const getCommandFunctions = (
823
880
  if (!arrayIsEmpty(settingColumnNames)) {
824
881
  const changingColumnNames = arrayFilter(
825
882
  collValues(mapGet(schemaMap, tableName)),
826
- (changingColumnName) => changingColumnName != rowIdColumnName,
883
+ (changingColumnName) =>
884
+ changingColumnName != rowIdColumnName &&
885
+ includeContentSubId(changingColumnName),
827
886
  );
828
887
  const rows = {};
829
888
  const deleteRowIds = [];
@@ -839,6 +898,7 @@ const getCommandFunctions = (
839
898
  rowIdColumnName,
840
899
  changingColumnNames,
841
900
  rows,
901
+ currentColumnNames,
842
902
  );
843
903
  await databaseExecuteCommand(
844
904
  DELETE_FROM +
@@ -847,7 +907,10 @@ const getCommandFunctions = (
847
907
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
848
908
  deleteRowIds,
849
909
  );
850
- } else if (collHas(schemaMap, tableName)) {
910
+ } else if (
911
+ isUndefined(contentSubIdSet) &&
912
+ collHas(schemaMap, tableName)
913
+ ) {
851
914
  await databaseExecuteCommand(
852
915
  DELETE_FROM +
853
916
  escapeId(tableName) +
@@ -986,7 +1049,13 @@ const createTabularPersister = (
986
1049
  [
987
1050
  tablesLoadConfig,
988
1051
  tablesSaveConfig,
989
- [valuesLoad, valuesSave, valuesTableName],
1052
+ [
1053
+ valuesLoad,
1054
+ valuesSave,
1055
+ valuesTableName,
1056
+ valuesLoadValueIds,
1057
+ valuesSaveValueIds,
1058
+ ],
990
1059
  ],
991
1060
  managedTableNames,
992
1061
  querySchema,
@@ -1036,15 +1105,33 @@ const createTabularPersister = (
1036
1105
  },
1037
1106
  ),
1038
1107
  );
1108
+ const getValuesSubset = (values, valueIds, partial) =>
1109
+ objNew(
1110
+ partial == true
1111
+ ? arrayFilter(
1112
+ objToArray(values, (value, valueId) => [valueId, value]),
1113
+ ([valueId]) => arrayHas(valueIds, valueId),
1114
+ )
1115
+ : arrayFilter(
1116
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1117
+ ([, value]) => !isUndefined(value),
1118
+ ),
1119
+ );
1039
1120
  const saveValues = async (values, partial) =>
1040
1121
  valuesSave
1041
1122
  ? await saveTable(
1042
1123
  valuesTableName,
1043
1124
  DEFAULT_ROW_ID_COLUMN_NAME,
1044
- {[SINGLE_ROW_ID]: values},
1125
+ {
1126
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1127
+ ? values
1128
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1129
+ },
1045
1130
  true,
1046
1131
  true,
1047
1132
  partial,
1133
+ void 0,
1134
+ valuesSaveValueIds,
1048
1135
  )
1049
1136
  : null;
1050
1137
  const loadTables = async () =>
@@ -1064,9 +1151,14 @@ const createTabularPersister = (
1064
1151
  );
1065
1152
  const loadValues = async () =>
1066
1153
  valuesLoad
1067
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1068
- SINGLE_ROW_ID
1069
- ]
1154
+ ? (
1155
+ await loadTable(
1156
+ valuesTableName,
1157
+ DEFAULT_ROW_ID_COLUMN_NAME,
1158
+ void 0,
1159
+ valuesLoadValueIds,
1160
+ )
1161
+ )[SINGLE_ROW_ID]
1070
1162
  : {};
1071
1163
  const getPersisted = () =>
1072
1164
  transaction(async () => {