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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinybase",
3
- "version": "8.6.0-beta.0",
3
+ "version": "9.0.0-beta.0",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinybase",
6
6
  "license": "MIT",
@@ -24,10 +24,10 @@
24
24
  "sideEffects": false,
25
25
  "peerDependencies": {
26
26
  "@automerge/automerge-repo": "^2.5.6",
27
- "@cloudflare/workers-types": "^4.20260621.1",
27
+ "@cloudflare/workers-types": "^4.20260630.1",
28
28
  "@electric-sql/pglite": "^0.5.3",
29
29
  "@libsql/client": "^0.17.4",
30
- "@powersync/common": "^1.55.0",
30
+ "@powersync/common": "^1.57.0",
31
31
  "@sinclair/typebox": "^0.34.49",
32
32
  "@sqlite.org/sqlite-wasm": "^3.53.0-build1",
33
33
  "@vlcn.io/crsqlite-wasm": "^0.16.0",
@@ -38,16 +38,16 @@
38
38
  "expo": "^56.0.12",
39
39
  "expo-sqlite": "^56.0.5",
40
40
  "partykit": "^0.0.115",
41
- "partysocket": "^1.2.0",
41
+ "partysocket": "^1.3.0",
42
42
  "postgres": "^3.4.9",
43
43
  "react": "^19.2.7",
44
44
  "react-dom": "^19.2.7",
45
- "react-native-mmkv": "4.3.1",
45
+ "react-native-mmkv": "4.3.2",
46
46
  "react-native-sqlite-storage": "^6.0.1",
47
47
  "solid-js": "^1.9.13",
48
48
  "sqlite3": "^5.1.7",
49
- "svelte": "^5.56.3",
50
- "valibot": "^1.4.1",
49
+ "svelte": "^5.56.4",
50
+ "valibot": "^1.4.2",
51
51
  "ws": "^8.21.0",
52
52
  "yjs": "^13.6.31",
53
53
  "zod": "^4.4.3"
@@ -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);
@@ -579,6 +580,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
579
580
  save: 0,
580
581
  [TABLE_NAME]: TINYBASE + '_values',
581
582
  };
583
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
584
+ const hasValues = (config) => isTrue(config) || isArray(config);
582
585
  const getDefaultedConfig = (configOrStoreTableName) =>
583
586
  objMerge(
584
587
  DEFAULT_CONFIG,
@@ -629,11 +632,15 @@ const getConfigStructures = (configOrStoreTableName) => {
629
632
  ];
630
633
  }
631
634
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
632
- const valuesConfig = slice(
633
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
634
- 0,
635
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
636
- );
635
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
636
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
637
+ const valuesConfig = [
638
+ hasValues(valuesLoad),
639
+ hasValues(valuesSave),
640
+ valuesConfigObj[TABLE_NAME],
641
+ getValuesIn(valuesLoad),
642
+ getValuesIn(valuesSave),
643
+ ];
637
644
  const valuesTable = valuesConfig[2];
638
645
  const managedTableNames = setNew(valuesTable);
639
646
  const excludedTableNames = setNew(valuesTable);
@@ -695,8 +702,18 @@ const getCommandFunctions = (
695
702
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
696
703
  );
697
704
  };
698
- const loadTable = async (tableName, rowIdColumnName, condition) =>
699
- canSelect(tableName, rowIdColumnName)
705
+ const loadTable = async (
706
+ tableName,
707
+ rowIdColumnName,
708
+ condition,
709
+ contentSubIds,
710
+ ) => {
711
+ const contentSubIdSet = isUndefined(contentSubIds)
712
+ ? void 0
713
+ : setNew(contentSubIds);
714
+ const includeContentSubId = (contentSubId) =>
715
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
716
+ return canSelect(tableName, rowIdColumnName)
700
717
  ? objNew(
701
718
  arrayFilter(
702
719
  arrayMap(
@@ -705,17 +722,35 @@ const getCommandFunctions = (
705
722
  escapeId(tableName) +
706
723
  getWhereCondition(tableName, condition),
707
724
  ),
708
- (row) => [
709
- row[rowIdColumnName],
710
- decode
725
+ (row) => {
726
+ const rowId = row[rowIdColumnName];
727
+ const rowContent = decode
711
728
  ? objMap(objDel(row, rowIdColumnName), decode)
712
- : objDel(row, rowIdColumnName),
713
- ],
729
+ : objDel(row, rowIdColumnName);
730
+ return [
731
+ rowId,
732
+ isUndefined(contentSubIdSet)
733
+ ? rowContent
734
+ : objNew(
735
+ arrayFilter(
736
+ objToArray(
737
+ rowContent,
738
+ (cellOrValue, contentSubId) => [
739
+ contentSubId,
740
+ cellOrValue,
741
+ ],
742
+ ),
743
+ ([contentSubId]) => includeContentSubId(contentSubId),
744
+ ),
745
+ ),
746
+ ];
747
+ },
714
748
  ),
715
749
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
716
750
  ),
717
751
  )
718
752
  : {};
753
+ };
719
754
  const saveTable = async (
720
755
  tableName,
721
756
  rowIdColumnName,
@@ -724,15 +759,23 @@ const getCommandFunctions = (
724
759
  deleteEmptyTable,
725
760
  partial = false,
726
761
  condition = TRUE,
762
+ contentSubIds,
727
763
  ) => {
764
+ const contentSubIdSet = isUndefined(contentSubIds)
765
+ ? void 0
766
+ : setNew(contentSubIds);
767
+ const includeContentSubId = (contentSubId) =>
768
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
728
769
  const settingColumnNameSet = setNew();
729
770
  objMap(content ?? {}, (contentRow) =>
730
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
731
- setAdd(settingColumnNameSet, cellOrValueId),
771
+ arrayMap(
772
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
773
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
732
774
  ),
733
775
  );
734
776
  const settingColumnNames = collValues(settingColumnNameSet);
735
777
  if (
778
+ isUndefined(contentSubIdSet) &&
736
779
  !partial &&
737
780
  deleteEmptyTable &&
738
781
  condition == TRUE &&
@@ -744,7 +787,13 @@ const getCommandFunctions = (
744
787
  return;
745
788
  }
746
789
  const currentColumnNames = mapGet(schemaMap, tableName);
747
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
790
+ const unaccountedColumnNames = setNew(
791
+ arrayFilter(
792
+ collValues(currentColumnNames),
793
+ (columnName) =>
794
+ columnName == rowIdColumnName || includeContentSubId(columnName),
795
+ ),
796
+ );
748
797
  if (!arrayIsEmpty(settingColumnNames)) {
749
798
  if (!collHas(schemaMap, tableName)) {
750
799
  await databaseExecuteCommand(
@@ -810,11 +859,13 @@ const getCommandFunctions = (
810
859
  ]);
811
860
  if (partial) {
812
861
  if (isUndefined(content)) {
813
- await databaseExecuteCommand(
814
- DELETE_FROM +
815
- escapeId(tableName) +
816
- getWhereCondition(tableName, condition),
817
- );
862
+ if (isUndefined(contentSubIdSet)) {
863
+ await databaseExecuteCommand(
864
+ DELETE_FROM +
865
+ escapeId(tableName) +
866
+ getWhereCondition(tableName, condition),
867
+ );
868
+ }
818
869
  } else {
819
870
  await promiseAll(
820
871
  objToArray(content, async (row, rowId) => {
@@ -827,18 +878,24 @@ const getCommandFunctions = (
827
878
  [rowId],
828
879
  );
829
880
  } else if (!arrayIsEmpty(settingColumnNames)) {
830
- await upsert(
831
- databaseExecuteCommand,
832
- tableName,
833
- rowIdColumnName,
881
+ const changingColumnNames = arrayFilter(
834
882
  objIds(row),
835
- {
836
- [rowId]: encode
837
- ? arrayMap(objValues(row), encode)
838
- : objValues(row),
839
- },
840
- currentColumnNames,
883
+ includeContentSubId,
841
884
  );
885
+ if (!arrayIsEmpty(changingColumnNames)) {
886
+ await upsert(
887
+ databaseExecuteCommand,
888
+ tableName,
889
+ rowIdColumnName,
890
+ changingColumnNames,
891
+ {
892
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
893
+ encode ? encode(row[cellId]) : row[cellId],
894
+ ),
895
+ },
896
+ currentColumnNames,
897
+ );
898
+ }
842
899
  }
843
900
  }),
844
901
  );
@@ -847,7 +904,9 @@ const getCommandFunctions = (
847
904
  if (!arrayIsEmpty(settingColumnNames)) {
848
905
  const changingColumnNames = arrayFilter(
849
906
  collValues(mapGet(schemaMap, tableName)),
850
- (changingColumnName) => changingColumnName != rowIdColumnName,
907
+ (changingColumnName) =>
908
+ changingColumnName != rowIdColumnName &&
909
+ includeContentSubId(changingColumnName),
851
910
  );
852
911
  const rows = {};
853
912
  const deleteRowIds = [];
@@ -863,6 +922,7 @@ const getCommandFunctions = (
863
922
  rowIdColumnName,
864
923
  changingColumnNames,
865
924
  rows,
925
+ currentColumnNames,
866
926
  );
867
927
  await databaseExecuteCommand(
868
928
  DELETE_FROM +
@@ -871,7 +931,10 @@ const getCommandFunctions = (
871
931
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
872
932
  deleteRowIds,
873
933
  );
874
- } else if (collHas(schemaMap, tableName)) {
934
+ } else if (
935
+ isUndefined(contentSubIdSet) &&
936
+ collHas(schemaMap, tableName)
937
+ ) {
875
938
  await databaseExecuteCommand(
876
939
  DELETE_FROM +
877
940
  escapeId(tableName) +
@@ -1010,7 +1073,13 @@ const createTabularPersister = (
1010
1073
  [
1011
1074
  tablesLoadConfig,
1012
1075
  tablesSaveConfig,
1013
- [valuesLoad, valuesSave, valuesTableName],
1076
+ [
1077
+ valuesLoad,
1078
+ valuesSave,
1079
+ valuesTableName,
1080
+ valuesLoadValueIds,
1081
+ valuesSaveValueIds,
1082
+ ],
1014
1083
  ],
1015
1084
  managedTableNames,
1016
1085
  querySchema,
@@ -1060,15 +1129,33 @@ const createTabularPersister = (
1060
1129
  },
1061
1130
  ),
1062
1131
  );
1132
+ const getValuesSubset = (values, valueIds, partial) =>
1133
+ objNew(
1134
+ partial == true
1135
+ ? arrayFilter(
1136
+ objToArray(values, (value, valueId) => [valueId, value]),
1137
+ ([valueId]) => arrayHas(valueIds, valueId),
1138
+ )
1139
+ : arrayFilter(
1140
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1141
+ ([, value]) => !isUndefined(value),
1142
+ ),
1143
+ );
1063
1144
  const saveValues = async (values, partial) =>
1064
1145
  valuesSave
1065
1146
  ? await saveTable(
1066
1147
  valuesTableName,
1067
1148
  DEFAULT_ROW_ID_COLUMN_NAME,
1068
- {[SINGLE_ROW_ID]: values},
1149
+ {
1150
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1151
+ ? values
1152
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1153
+ },
1069
1154
  true,
1070
1155
  true,
1071
1156
  partial,
1157
+ void 0,
1158
+ valuesSaveValueIds,
1072
1159
  )
1073
1160
  : null;
1074
1161
  const loadTables = async () =>
@@ -1088,9 +1175,14 @@ const createTabularPersister = (
1088
1175
  );
1089
1176
  const loadValues = async () =>
1090
1177
  valuesLoad
1091
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1092
- SINGLE_ROW_ID
1093
- ]
1178
+ ? (
1179
+ await loadTable(
1180
+ valuesTableName,
1181
+ DEFAULT_ROW_ID_COLUMN_NAME,
1182
+ void 0,
1183
+ valuesLoadValueIds,
1184
+ )
1185
+ )[SINGLE_ROW_ID]
1094
1186
  : {};
1095
1187
  const getPersisted = () =>
1096
1188
  transaction(async () => {
@@ -48,6 +48,7 @@ const tryCatch = async (action, then1, then2) => {
48
48
  }
49
49
  };
50
50
 
51
+ const arrayHas = (array, value) => array.includes(value);
51
52
  const arrayForEach = (array, cb) => array.forEach(cb);
52
53
  const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
53
54
  const arrayMap = (array, cb) => array.map(cb);
@@ -207,6 +208,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
207
208
  save: 0,
208
209
  [TABLE_NAME]: TINYBASE + '_values',
209
210
  };
211
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
212
+ const hasValues = (config) => isTrue(config) || isArray(config);
210
213
  const getDefaultedConfig = (configOrStoreTableName) =>
211
214
  objMerge(
212
215
  DEFAULT_CONFIG,
@@ -257,11 +260,15 @@ const getConfigStructures = (configOrStoreTableName) => {
257
260
  ];
258
261
  }
259
262
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
260
- const valuesConfig = slice(
261
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
262
- 0,
263
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
264
- );
263
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
264
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
265
+ const valuesConfig = [
266
+ hasValues(valuesLoad),
267
+ hasValues(valuesSave),
268
+ valuesConfigObj[TABLE_NAME],
269
+ getValuesIn(valuesLoad),
270
+ getValuesIn(valuesSave),
271
+ ];
265
272
  const valuesTable = valuesConfig[2];
266
273
  const managedTableNames = setNew(valuesTable);
267
274
  const excludedTableNames = setNew(valuesTable);
@@ -670,8 +677,18 @@ const getCommandFunctions = (
670
677
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
671
678
  );
672
679
  };
673
- const loadTable = async (tableName, rowIdColumnName, condition) =>
674
- canSelect(tableName, rowIdColumnName)
680
+ const loadTable = async (
681
+ tableName,
682
+ rowIdColumnName,
683
+ condition,
684
+ contentSubIds,
685
+ ) => {
686
+ const contentSubIdSet = isUndefined(contentSubIds)
687
+ ? void 0
688
+ : setNew(contentSubIds);
689
+ const includeContentSubId = (contentSubId) =>
690
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
691
+ return canSelect(tableName, rowIdColumnName)
675
692
  ? objNew(
676
693
  arrayFilter(
677
694
  arrayMap(
@@ -680,17 +697,35 @@ const getCommandFunctions = (
680
697
  escapeId(tableName) +
681
698
  getWhereCondition(tableName, condition),
682
699
  ),
683
- (row) => [
684
- row[rowIdColumnName],
685
- decode
700
+ (row) => {
701
+ const rowId = row[rowIdColumnName];
702
+ const rowContent = decode
686
703
  ? objMap(objDel(row, rowIdColumnName), decode)
687
- : objDel(row, rowIdColumnName),
688
- ],
704
+ : objDel(row, rowIdColumnName);
705
+ return [
706
+ rowId,
707
+ isUndefined(contentSubIdSet)
708
+ ? rowContent
709
+ : objNew(
710
+ arrayFilter(
711
+ objToArray(
712
+ rowContent,
713
+ (cellOrValue, contentSubId) => [
714
+ contentSubId,
715
+ cellOrValue,
716
+ ],
717
+ ),
718
+ ([contentSubId]) => includeContentSubId(contentSubId),
719
+ ),
720
+ ),
721
+ ];
722
+ },
689
723
  ),
690
724
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
691
725
  ),
692
726
  )
693
727
  : {};
728
+ };
694
729
  const saveTable = async (
695
730
  tableName,
696
731
  rowIdColumnName,
@@ -699,15 +734,23 @@ const getCommandFunctions = (
699
734
  deleteEmptyTable,
700
735
  partial = false,
701
736
  condition = TRUE,
737
+ contentSubIds,
702
738
  ) => {
739
+ const contentSubIdSet = isUndefined(contentSubIds)
740
+ ? void 0
741
+ : setNew(contentSubIds);
742
+ const includeContentSubId = (contentSubId) =>
743
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
703
744
  const settingColumnNameSet = setNew();
704
745
  objMap(content ?? {}, (contentRow) =>
705
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
706
- setAdd(settingColumnNameSet, cellOrValueId),
746
+ arrayMap(
747
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
748
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
707
749
  ),
708
750
  );
709
751
  const settingColumnNames = collValues(settingColumnNameSet);
710
752
  if (
753
+ isUndefined(contentSubIdSet) &&
711
754
  !partial &&
712
755
  deleteEmptyTable &&
713
756
  condition == TRUE &&
@@ -719,7 +762,13 @@ const getCommandFunctions = (
719
762
  return;
720
763
  }
721
764
  const currentColumnNames = mapGet(schemaMap, tableName);
722
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
765
+ const unaccountedColumnNames = setNew(
766
+ arrayFilter(
767
+ collValues(currentColumnNames),
768
+ (columnName) =>
769
+ columnName == rowIdColumnName || includeContentSubId(columnName),
770
+ ),
771
+ );
723
772
  if (!arrayIsEmpty(settingColumnNames)) {
724
773
  if (!collHas(schemaMap, tableName)) {
725
774
  await databaseExecuteCommand(
@@ -785,11 +834,13 @@ const getCommandFunctions = (
785
834
  ]);
786
835
  if (partial) {
787
836
  if (isUndefined(content)) {
788
- await databaseExecuteCommand(
789
- DELETE_FROM +
790
- escapeId(tableName) +
791
- getWhereCondition(tableName, condition),
792
- );
837
+ if (isUndefined(contentSubIdSet)) {
838
+ await databaseExecuteCommand(
839
+ DELETE_FROM +
840
+ escapeId(tableName) +
841
+ getWhereCondition(tableName, condition),
842
+ );
843
+ }
793
844
  } else {
794
845
  await promiseAll(
795
846
  objToArray(content, async (row, rowId) => {
@@ -802,18 +853,24 @@ const getCommandFunctions = (
802
853
  [rowId],
803
854
  );
804
855
  } else if (!arrayIsEmpty(settingColumnNames)) {
805
- await upsert(
806
- databaseExecuteCommand,
807
- tableName,
808
- rowIdColumnName,
856
+ const changingColumnNames = arrayFilter(
809
857
  objIds(row),
810
- {
811
- [rowId]: encode
812
- ? arrayMap(objValues(row), encode)
813
- : objValues(row),
814
- },
815
- currentColumnNames,
858
+ includeContentSubId,
816
859
  );
860
+ if (!arrayIsEmpty(changingColumnNames)) {
861
+ await upsert(
862
+ databaseExecuteCommand,
863
+ tableName,
864
+ rowIdColumnName,
865
+ changingColumnNames,
866
+ {
867
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
868
+ encode ? encode(row[cellId]) : row[cellId],
869
+ ),
870
+ },
871
+ currentColumnNames,
872
+ );
873
+ }
817
874
  }
818
875
  }),
819
876
  );
@@ -822,7 +879,9 @@ const getCommandFunctions = (
822
879
  if (!arrayIsEmpty(settingColumnNames)) {
823
880
  const changingColumnNames = arrayFilter(
824
881
  collValues(mapGet(schemaMap, tableName)),
825
- (changingColumnName) => changingColumnName != rowIdColumnName,
882
+ (changingColumnName) =>
883
+ changingColumnName != rowIdColumnName &&
884
+ includeContentSubId(changingColumnName),
826
885
  );
827
886
  const rows = {};
828
887
  const deleteRowIds = [];
@@ -838,6 +897,7 @@ const getCommandFunctions = (
838
897
  rowIdColumnName,
839
898
  changingColumnNames,
840
899
  rows,
900
+ currentColumnNames,
841
901
  );
842
902
  await databaseExecuteCommand(
843
903
  DELETE_FROM +
@@ -846,7 +906,10 @@ const getCommandFunctions = (
846
906
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
847
907
  deleteRowIds,
848
908
  );
849
- } else if (collHas(schemaMap, tableName)) {
909
+ } else if (
910
+ isUndefined(contentSubIdSet) &&
911
+ collHas(schemaMap, tableName)
912
+ ) {
850
913
  await databaseExecuteCommand(
851
914
  DELETE_FROM +
852
915
  escapeId(tableName) +
@@ -985,7 +1048,13 @@ const createTabularPersister = (
985
1048
  [
986
1049
  tablesLoadConfig,
987
1050
  tablesSaveConfig,
988
- [valuesLoad, valuesSave, valuesTableName],
1051
+ [
1052
+ valuesLoad,
1053
+ valuesSave,
1054
+ valuesTableName,
1055
+ valuesLoadValueIds,
1056
+ valuesSaveValueIds,
1057
+ ],
989
1058
  ],
990
1059
  managedTableNames,
991
1060
  querySchema,
@@ -1035,15 +1104,33 @@ const createTabularPersister = (
1035
1104
  },
1036
1105
  ),
1037
1106
  );
1107
+ const getValuesSubset = (values, valueIds, partial) =>
1108
+ objNew(
1109
+ partial == true
1110
+ ? arrayFilter(
1111
+ objToArray(values, (value, valueId) => [valueId, value]),
1112
+ ([valueId]) => arrayHas(valueIds, valueId),
1113
+ )
1114
+ : arrayFilter(
1115
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
1116
+ ([, value]) => !isUndefined(value),
1117
+ ),
1118
+ );
1038
1119
  const saveValues = async (values, partial) =>
1039
1120
  valuesSave
1040
1121
  ? await saveTable(
1041
1122
  valuesTableName,
1042
1123
  DEFAULT_ROW_ID_COLUMN_NAME,
1043
- {[SINGLE_ROW_ID]: values},
1124
+ {
1125
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
1126
+ ? values
1127
+ : getValuesSubset(values, valuesSaveValueIds, partial),
1128
+ },
1044
1129
  true,
1045
1130
  true,
1046
1131
  partial,
1132
+ void 0,
1133
+ valuesSaveValueIds,
1047
1134
  )
1048
1135
  : null;
1049
1136
  const loadTables = async () =>
@@ -1063,9 +1150,14 @@ const createTabularPersister = (
1063
1150
  );
1064
1151
  const loadValues = async () =>
1065
1152
  valuesLoad
1066
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
1067
- SINGLE_ROW_ID
1068
- ]
1153
+ ? (
1154
+ await loadTable(
1155
+ valuesTableName,
1156
+ DEFAULT_ROW_ID_COLUMN_NAME,
1157
+ void 0,
1158
+ valuesLoadValueIds,
1159
+ )
1160
+ )[SINGLE_ROW_ID]
1069
1161
  : {};
1070
1162
  const getPersisted = () =>
1071
1163
  transaction(async () => {