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
@@ -22,6 +22,7 @@ const GLOBAL = globalThis;
22
22
  const isNullish = (thing) => thing == null;
23
23
  const isUndefined = (thing) => thing === void 0;
24
24
  const isNull = (thing) => thing === null;
25
+ const isTrue = (thing) => thing === true;
25
26
  const ifNotNullish = getIfNotFunction(isNullish);
26
27
  const ifNotUndefined = getIfNotFunction(isUndefined);
27
28
  const isString = (thing) => getTypeOf(thing) == STRING;
@@ -42,6 +43,7 @@ const tryCatch = async (action, then1, then2) => {
42
43
  }
43
44
  };
44
45
 
46
+ const arrayHas = (array, value) => array.includes(value);
45
47
  const arrayForEach = (array, cb) => array.forEach(cb);
46
48
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
47
49
  const arrayMap = (array, cb) => array.map(cb);
@@ -227,6 +229,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
227
229
  save: 0,
228
230
  [TABLE_NAME]: TINYBASE + '_values',
229
231
  };
232
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
233
+ const hasValues = (config) => isTrue(config) || isArray(config);
230
234
  const getDefaultedConfig = (configOrStoreTableName) =>
231
235
  objMerge(
232
236
  DEFAULT_CONFIG,
@@ -277,11 +281,15 @@ const getConfigStructures = (configOrStoreTableName) => {
277
281
  ];
278
282
  }
279
283
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
280
- const valuesConfig = slice(
281
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
282
- 0,
283
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
284
- );
284
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
285
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
286
+ const valuesConfig = [
287
+ hasValues(valuesLoad),
288
+ hasValues(valuesSave),
289
+ valuesConfigObj[TABLE_NAME],
290
+ getValuesIn(valuesLoad),
291
+ getValuesIn(valuesSave),
292
+ ];
285
293
  const valuesTable = valuesConfig[2];
286
294
  const managedTableNames = setNew(valuesTable);
287
295
  const excludedTableNames = setNew(valuesTable);
@@ -674,8 +682,18 @@ const getCommandFunctions = (
674
682
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
675
683
  );
676
684
  };
677
- const loadTable = async (tableName, rowIdColumnName, condition) =>
678
- canSelect(tableName, rowIdColumnName)
685
+ const loadTable = async (
686
+ tableName,
687
+ rowIdColumnName,
688
+ condition,
689
+ contentSubIds,
690
+ ) => {
691
+ const contentSubIdSet = isUndefined(contentSubIds)
692
+ ? void 0
693
+ : setNew(contentSubIds);
694
+ const includeContentSubId = (contentSubId) =>
695
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
696
+ return canSelect(tableName, rowIdColumnName)
679
697
  ? objNew(
680
698
  arrayFilter(
681
699
  arrayMap(
@@ -684,17 +702,35 @@ const getCommandFunctions = (
684
702
  escapeId(tableName) +
685
703
  getWhereCondition(tableName, condition),
686
704
  ),
687
- (row) => [
688
- row[rowIdColumnName],
689
- decode
705
+ (row) => {
706
+ const rowId = row[rowIdColumnName];
707
+ const rowContent = decode
690
708
  ? objMap(objDel(row, rowIdColumnName), decode)
691
- : objDel(row, rowIdColumnName),
692
- ],
709
+ : objDel(row, rowIdColumnName);
710
+ return [
711
+ rowId,
712
+ isUndefined(contentSubIdSet)
713
+ ? rowContent
714
+ : objNew(
715
+ arrayFilter(
716
+ objToArray(
717
+ rowContent,
718
+ (cellOrValue, contentSubId) => [
719
+ contentSubId,
720
+ cellOrValue,
721
+ ],
722
+ ),
723
+ ([contentSubId]) => includeContentSubId(contentSubId),
724
+ ),
725
+ ),
726
+ ];
727
+ },
693
728
  ),
694
729
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
695
730
  ),
696
731
  )
697
732
  : {};
733
+ };
698
734
  const saveTable = async (
699
735
  tableName,
700
736
  rowIdColumnName,
@@ -703,15 +739,23 @@ const getCommandFunctions = (
703
739
  deleteEmptyTable,
704
740
  partial = false,
705
741
  condition = TRUE,
742
+ contentSubIds,
706
743
  ) => {
744
+ const contentSubIdSet = isUndefined(contentSubIds)
745
+ ? void 0
746
+ : setNew(contentSubIds);
747
+ const includeContentSubId = (contentSubId) =>
748
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
707
749
  const settingColumnNameSet = setNew();
708
750
  objMap(content ?? {}, (contentRow) =>
709
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
710
- setAdd(settingColumnNameSet, cellOrValueId),
751
+ arrayMap(
752
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
753
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
711
754
  ),
712
755
  );
713
756
  const settingColumnNames = collValues(settingColumnNameSet);
714
757
  if (
758
+ isUndefined(contentSubIdSet) &&
715
759
  !partial &&
716
760
  deleteEmptyTable &&
717
761
  condition == TRUE &&
@@ -723,7 +767,13 @@ const getCommandFunctions = (
723
767
  return;
724
768
  }
725
769
  const currentColumnNames = mapGet(schemaMap, tableName);
726
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
770
+ const unaccountedColumnNames = setNew(
771
+ arrayFilter(
772
+ collValues(currentColumnNames),
773
+ (columnName) =>
774
+ columnName == rowIdColumnName || includeContentSubId(columnName),
775
+ ),
776
+ );
727
777
  if (!arrayIsEmpty(settingColumnNames)) {
728
778
  if (!collHas(schemaMap, tableName)) {
729
779
  await databaseExecuteCommand(
@@ -789,11 +839,13 @@ const getCommandFunctions = (
789
839
  ]);
790
840
  if (partial) {
791
841
  if (isUndefined(content)) {
792
- await databaseExecuteCommand(
793
- DELETE_FROM +
794
- escapeId(tableName) +
795
- getWhereCondition(tableName, condition),
796
- );
842
+ if (isUndefined(contentSubIdSet)) {
843
+ await databaseExecuteCommand(
844
+ DELETE_FROM +
845
+ escapeId(tableName) +
846
+ getWhereCondition(tableName, condition),
847
+ );
848
+ }
797
849
  } else {
798
850
  await promiseAll(
799
851
  objToArray(content, async (row, rowId) => {
@@ -806,18 +858,24 @@ const getCommandFunctions = (
806
858
  [rowId],
807
859
  );
808
860
  } else if (!arrayIsEmpty(settingColumnNames)) {
809
- await upsert(
810
- databaseExecuteCommand,
811
- tableName,
812
- rowIdColumnName,
861
+ const changingColumnNames = arrayFilter(
813
862
  objIds(row),
814
- {
815
- [rowId]: encode
816
- ? arrayMap(objValues(row), encode)
817
- : objValues(row),
818
- },
819
- currentColumnNames,
863
+ includeContentSubId,
820
864
  );
865
+ if (!arrayIsEmpty(changingColumnNames)) {
866
+ await upsert(
867
+ databaseExecuteCommand,
868
+ tableName,
869
+ rowIdColumnName,
870
+ changingColumnNames,
871
+ {
872
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
873
+ encode ? encode(row[cellId]) : row[cellId],
874
+ ),
875
+ },
876
+ currentColumnNames,
877
+ );
878
+ }
821
879
  }
822
880
  }),
823
881
  );
@@ -826,7 +884,9 @@ const getCommandFunctions = (
826
884
  if (!arrayIsEmpty(settingColumnNames)) {
827
885
  const changingColumnNames = arrayFilter(
828
886
  collValues(mapGet(schemaMap, tableName)),
829
- (changingColumnName) => changingColumnName != rowIdColumnName,
887
+ (changingColumnName) =>
888
+ changingColumnName != rowIdColumnName &&
889
+ includeContentSubId(changingColumnName),
830
890
  );
831
891
  const rows = {};
832
892
  const deleteRowIds = [];
@@ -842,6 +902,7 @@ const getCommandFunctions = (
842
902
  rowIdColumnName,
843
903
  changingColumnNames,
844
904
  rows,
905
+ currentColumnNames,
845
906
  );
846
907
  await databaseExecuteCommand(
847
908
  DELETE_FROM +
@@ -850,7 +911,10 @@ const getCommandFunctions = (
850
911
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
851
912
  deleteRowIds,
852
913
  );
853
- } else if (collHas(schemaMap, tableName)) {
914
+ } else if (
915
+ isUndefined(contentSubIdSet) &&
916
+ collHas(schemaMap, tableName)
917
+ ) {
854
918
  await databaseExecuteCommand(
855
919
  DELETE_FROM +
856
920
  escapeId(tableName) +
@@ -989,7 +1053,13 @@ const createTabularPersister = (
989
1053
  [
990
1054
  tablesLoadConfig,
991
1055
  tablesSaveConfig,
992
- [valuesLoad, valuesSave, valuesTableName],
1056
+ [
1057
+ valuesLoad,
1058
+ valuesSave,
1059
+ valuesTableName,
1060
+ valuesLoadValueIds,
1061
+ valuesSaveValueIds,
1062
+ ],
993
1063
  ],
994
1064
  managedTableNames,
995
1065
  querySchema,
@@ -1039,15 +1109,33 @@ const createTabularPersister = (
1039
1109
  },
1040
1110
  ),
1041
1111
  );
1112
+ const getValuesSubset = (values, valueIds, partial) =>
1113
+ objNew(
1114
+ partial == true
1115
+ ? arrayFilter(
1116
+ objToArray(values, (value, valueId) => [valueId, value]),
1117
+ ([valueId]) => arrayHas(valueIds, valueId),
1118
+ )
1119
+ : arrayFilter(
1120
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1121
+ ([, value]) => !isUndefined(value),
1122
+ ),
1123
+ );
1042
1124
  const saveValues = async (values, partial) =>
1043
1125
  valuesSave
1044
1126
  ? await saveTable(
1045
1127
  valuesTableName,
1046
1128
  DEFAULT_ROW_ID_COLUMN_NAME,
1047
- {[SINGLE_ROW_ID]: values},
1129
+ {
1130
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1131
+ ? values
1132
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1133
+ },
1048
1134
  true,
1049
1135
  true,
1050
1136
  partial,
1137
+ void 0,
1138
+ valuesSaveValueIds,
1051
1139
  )
1052
1140
  : null;
1053
1141
  const loadTables = async () =>
@@ -1067,9 +1155,14 @@ const createTabularPersister = (
1067
1155
  );
1068
1156
  const loadValues = async () =>
1069
1157
  valuesLoad
1070
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1071
- SINGLE_ROW_ID
1072
- ]
1158
+ ? (
1159
+ await loadTable(
1160
+ valuesTableName,
1161
+ DEFAULT_ROW_ID_COLUMN_NAME,
1162
+ void 0,
1163
+ valuesLoadValueIds,
1164
+ )
1165
+ )[SINGLE_ROW_ID]
1073
1166
  : {};
1074
1167
  const getPersisted = () =>
1075
1168
  transaction(async () => {
@@ -22,6 +22,7 @@ const GLOBAL = globalThis;
22
22
  const isNullish = (thing) => thing == null;
23
23
  const isUndefined = (thing) => thing === void 0;
24
24
  const isNull = (thing) => thing === null;
25
+ const isTrue = (thing) => thing === true;
25
26
  const ifNotNullish = getIfNotFunction(isNullish);
26
27
  const ifNotUndefined = getIfNotFunction(isUndefined);
27
28
  const isString = (thing) => getTypeOf(thing) == STRING;
@@ -42,6 +43,7 @@ const tryCatch = async (action, then1, then2) => {
42
43
  }
43
44
  };
44
45
 
46
+ const arrayHas = (array, value) => array.includes(value);
45
47
  const arrayForEach = (array, cb) => array.forEach(cb);
46
48
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
47
49
  const arrayMap = (array, cb) => array.map(cb);
@@ -227,6 +229,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
227
229
  save: 0,
228
230
  [TABLE_NAME]: TINYBASE + '_values',
229
231
  };
232
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
233
+ const hasValues = (config) => isTrue(config) || isArray(config);
230
234
  const getDefaultedConfig = (configOrStoreTableName) =>
231
235
  objMerge(
232
236
  DEFAULT_CONFIG,
@@ -277,11 +281,15 @@ const getConfigStructures = (configOrStoreTableName) => {
277
281
  ];
278
282
  }
279
283
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
280
- const valuesConfig = slice(
281
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
282
- 0,
283
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
284
- );
284
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
285
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
286
+ const valuesConfig = [
287
+ hasValues(valuesLoad),
288
+ hasValues(valuesSave),
289
+ valuesConfigObj[TABLE_NAME],
290
+ getValuesIn(valuesLoad),
291
+ getValuesIn(valuesSave),
292
+ ];
285
293
  const valuesTable = valuesConfig[2];
286
294
  const managedTableNames = setNew(valuesTable);
287
295
  const excludedTableNames = setNew(valuesTable);
@@ -674,8 +682,18 @@ const getCommandFunctions = (
674
682
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
675
683
  );
676
684
  };
677
- const loadTable = async (tableName, rowIdColumnName, condition) =>
678
- canSelect(tableName, rowIdColumnName)
685
+ const loadTable = async (
686
+ tableName,
687
+ rowIdColumnName,
688
+ condition,
689
+ contentSubIds,
690
+ ) => {
691
+ const contentSubIdSet = isUndefined(contentSubIds)
692
+ ? void 0
693
+ : setNew(contentSubIds);
694
+ const includeContentSubId = (contentSubId) =>
695
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
696
+ return canSelect(tableName, rowIdColumnName)
679
697
  ? objNew(
680
698
  arrayFilter(
681
699
  arrayMap(
@@ -684,17 +702,35 @@ const getCommandFunctions = (
684
702
  escapeId(tableName) +
685
703
  getWhereCondition(tableName, condition),
686
704
  ),
687
- (row) => [
688
- row[rowIdColumnName],
689
- decode
705
+ (row) => {
706
+ const rowId = row[rowIdColumnName];
707
+ const rowContent = decode
690
708
  ? objMap(objDel(row, rowIdColumnName), decode)
691
- : objDel(row, rowIdColumnName),
692
- ],
709
+ : objDel(row, rowIdColumnName);
710
+ return [
711
+ rowId,
712
+ isUndefined(contentSubIdSet)
713
+ ? rowContent
714
+ : objNew(
715
+ arrayFilter(
716
+ objToArray(
717
+ rowContent,
718
+ (cellOrValue, contentSubId) => [
719
+ contentSubId,
720
+ cellOrValue,
721
+ ],
722
+ ),
723
+ ([contentSubId]) => includeContentSubId(contentSubId),
724
+ ),
725
+ ),
726
+ ];
727
+ },
693
728
  ),
694
729
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
695
730
  ),
696
731
  )
697
732
  : {};
733
+ };
698
734
  const saveTable = async (
699
735
  tableName,
700
736
  rowIdColumnName,
@@ -703,15 +739,23 @@ const getCommandFunctions = (
703
739
  deleteEmptyTable,
704
740
  partial = false,
705
741
  condition = TRUE,
742
+ contentSubIds,
706
743
  ) => {
744
+ const contentSubIdSet = isUndefined(contentSubIds)
745
+ ? void 0
746
+ : setNew(contentSubIds);
747
+ const includeContentSubId = (contentSubId) =>
748
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
707
749
  const settingColumnNameSet = setNew();
708
750
  objMap(content ?? {}, (contentRow) =>
709
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
710
- setAdd(settingColumnNameSet, cellOrValueId),
751
+ arrayMap(
752
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
753
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
711
754
  ),
712
755
  );
713
756
  const settingColumnNames = collValues(settingColumnNameSet);
714
757
  if (
758
+ isUndefined(contentSubIdSet) &&
715
759
  !partial &&
716
760
  deleteEmptyTable &&
717
761
  condition == TRUE &&
@@ -723,7 +767,13 @@ const getCommandFunctions = (
723
767
  return;
724
768
  }
725
769
  const currentColumnNames = mapGet(schemaMap, tableName);
726
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
770
+ const unaccountedColumnNames = setNew(
771
+ arrayFilter(
772
+ collValues(currentColumnNames),
773
+ (columnName) =>
774
+ columnName == rowIdColumnName || includeContentSubId(columnName),
775
+ ),
776
+ );
727
777
  if (!arrayIsEmpty(settingColumnNames)) {
728
778
  if (!collHas(schemaMap, tableName)) {
729
779
  await databaseExecuteCommand(
@@ -789,11 +839,13 @@ const getCommandFunctions = (
789
839
  ]);
790
840
  if (partial) {
791
841
  if (isUndefined(content)) {
792
- await databaseExecuteCommand(
793
- DELETE_FROM +
794
- escapeId(tableName) +
795
- getWhereCondition(tableName, condition),
796
- );
842
+ if (isUndefined(contentSubIdSet)) {
843
+ await databaseExecuteCommand(
844
+ DELETE_FROM +
845
+ escapeId(tableName) +
846
+ getWhereCondition(tableName, condition),
847
+ );
848
+ }
797
849
  } else {
798
850
  await promiseAll(
799
851
  objToArray(content, async (row, rowId) => {
@@ -806,18 +858,24 @@ const getCommandFunctions = (
806
858
  [rowId],
807
859
  );
808
860
  } else if (!arrayIsEmpty(settingColumnNames)) {
809
- await upsert(
810
- databaseExecuteCommand,
811
- tableName,
812
- rowIdColumnName,
861
+ const changingColumnNames = arrayFilter(
813
862
  objIds(row),
814
- {
815
- [rowId]: encode
816
- ? arrayMap(objValues(row), encode)
817
- : objValues(row),
818
- },
819
- currentColumnNames,
863
+ includeContentSubId,
820
864
  );
865
+ if (!arrayIsEmpty(changingColumnNames)) {
866
+ await upsert(
867
+ databaseExecuteCommand,
868
+ tableName,
869
+ rowIdColumnName,
870
+ changingColumnNames,
871
+ {
872
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
873
+ encode ? encode(row[cellId]) : row[cellId],
874
+ ),
875
+ },
876
+ currentColumnNames,
877
+ );
878
+ }
821
879
  }
822
880
  }),
823
881
  );
@@ -826,7 +884,9 @@ const getCommandFunctions = (
826
884
  if (!arrayIsEmpty(settingColumnNames)) {
827
885
  const changingColumnNames = arrayFilter(
828
886
  collValues(mapGet(schemaMap, tableName)),
829
- (changingColumnName) => changingColumnName != rowIdColumnName,
887
+ (changingColumnName) =>
888
+ changingColumnName != rowIdColumnName &&
889
+ includeContentSubId(changingColumnName),
830
890
  );
831
891
  const rows = {};
832
892
  const deleteRowIds = [];
@@ -842,6 +902,7 @@ const getCommandFunctions = (
842
902
  rowIdColumnName,
843
903
  changingColumnNames,
844
904
  rows,
905
+ currentColumnNames,
845
906
  );
846
907
  await databaseExecuteCommand(
847
908
  DELETE_FROM +
@@ -850,7 +911,10 @@ const getCommandFunctions = (
850
911
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
851
912
  deleteRowIds,
852
913
  );
853
- } else if (collHas(schemaMap, tableName)) {
914
+ } else if (
915
+ isUndefined(contentSubIdSet) &&
916
+ collHas(schemaMap, tableName)
917
+ ) {
854
918
  await databaseExecuteCommand(
855
919
  DELETE_FROM +
856
920
  escapeId(tableName) +
@@ -989,7 +1053,13 @@ const createTabularPersister = (
989
1053
  [
990
1054
  tablesLoadConfig,
991
1055
  tablesSaveConfig,
992
- [valuesLoad, valuesSave, valuesTableName],
1056
+ [
1057
+ valuesLoad,
1058
+ valuesSave,
1059
+ valuesTableName,
1060
+ valuesLoadValueIds,
1061
+ valuesSaveValueIds,
1062
+ ],
993
1063
  ],
994
1064
  managedTableNames,
995
1065
  querySchema,
@@ -1039,15 +1109,33 @@ const createTabularPersister = (
1039
1109
  },
1040
1110
  ),
1041
1111
  );
1112
+ const getValuesSubset = (values, valueIds, partial) =>
1113
+ objNew(
1114
+ partial == true
1115
+ ? arrayFilter(
1116
+ objToArray(values, (value, valueId) => [valueId, value]),
1117
+ ([valueId]) => arrayHas(valueIds, valueId),
1118
+ )
1119
+ : arrayFilter(
1120
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1121
+ ([, value]) => !isUndefined(value),
1122
+ ),
1123
+ );
1042
1124
  const saveValues = async (values, partial) =>
1043
1125
  valuesSave
1044
1126
  ? await saveTable(
1045
1127
  valuesTableName,
1046
1128
  DEFAULT_ROW_ID_COLUMN_NAME,
1047
- {[SINGLE_ROW_ID]: values},
1129
+ {
1130
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1131
+ ? values
1132
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1133
+ },
1048
1134
  true,
1049
1135
  true,
1050
1136
  partial,
1137
+ void 0,
1138
+ valuesSaveValueIds,
1051
1139
  )
1052
1140
  : null;
1053
1141
  const loadTables = async () =>
@@ -1067,9 +1155,14 @@ const createTabularPersister = (
1067
1155
  );
1068
1156
  const loadValues = async () =>
1069
1157
  valuesLoad
1070
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1071
- SINGLE_ROW_ID
1072
- ]
1158
+ ? (
1159
+ await loadTable(
1160
+ valuesTableName,
1161
+ DEFAULT_ROW_ID_COLUMN_NAME,
1162
+ void 0,
1163
+ valuesLoadValueIds,
1164
+ )
1165
+ )[SINGLE_ROW_ID]
1073
1166
  : {};
1074
1167
  const getPersisted = () =>
1075
1168
  transaction(async () => {