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