zen-fs-config 0.4.0 → 0.4.1

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.
package/dist/index.d.mts CHANGED
@@ -399,7 +399,13 @@ declare class ConfigRepo implements IConfigRepo {
399
399
  readMetaFile<T>(path: string): Promise<T | null>;
400
400
  /** Path for a single backend descriptor: .meta/backends/{id}.json */
401
401
  backendFilePath(id: string): string;
402
- /** Read all backend descriptors from .meta/backends/*.json */
402
+ /**
403
+ * Read all backend descriptors from .meta/backends/*.json.
404
+ *
405
+ * If duplicate backends are detected (same type + options but different id),
406
+ * only the first one (sorted by id) is kept and the rest are removed
407
+ * (including their version sidecar files).
408
+ */
403
409
  readAllBackendDescriptors(): Promise<BackendDescriptor[]>;
404
410
  /** Write a single backend descriptor as .meta/backends/{id}.json */
405
411
  writeBackendDescriptor(desc: BackendDescriptor): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -399,7 +399,13 @@ declare class ConfigRepo implements IConfigRepo {
399
399
  readMetaFile<T>(path: string): Promise<T | null>;
400
400
  /** Path for a single backend descriptor: .meta/backends/{id}.json */
401
401
  backendFilePath(id: string): string;
402
- /** Read all backend descriptors from .meta/backends/*.json */
402
+ /**
403
+ * Read all backend descriptors from .meta/backends/*.json.
404
+ *
405
+ * If duplicate backends are detected (same type + options but different id),
406
+ * only the first one (sorted by id) is kept and the rest are removed
407
+ * (including their version sidecar files).
408
+ */
403
409
  readAllBackendDescriptors(): Promise<BackendDescriptor[]>;
404
410
  /** Write a single backend descriptor as .meta/backends/{id}.json */
405
411
  writeBackendDescriptor(desc: BackendDescriptor): Promise<void>;
package/dist/index.js CHANGED
@@ -1080,7 +1080,13 @@ var ConfigRepo = class {
1080
1080
  backendFilePath(id) {
1081
1081
  return `${BACKENDS_DIR}/${id}.json`;
1082
1082
  }
1083
- /** Read all backend descriptors from .meta/backends/*.json */
1083
+ /**
1084
+ * Read all backend descriptors from .meta/backends/*.json.
1085
+ *
1086
+ * If duplicate backends are detected (same type + options but different id),
1087
+ * only the first one (sorted by id) is kept and the rest are removed
1088
+ * (including their version sidecar files).
1089
+ */
1084
1090
  async readAllBackendDescriptors() {
1085
1091
  try {
1086
1092
  const entries = await this.cachedFS.readdir(BACKENDS_DIR);
@@ -1089,11 +1095,33 @@ var ConfigRepo = class {
1089
1095
  if (!entry.endsWith(".json")) continue;
1090
1096
  try {
1091
1097
  const raw = await this.cachedFS.readFile(`${BACKENDS_DIR}/${entry}`);
1092
- descriptors.push(JSON.parse(new TextDecoder().decode(toUint8Array(raw))));
1098
+ const desc = JSON.parse(new TextDecoder().decode(toUint8Array(raw)));
1099
+ if (desc.id && desc.type) {
1100
+ descriptors.push(desc);
1101
+ }
1093
1102
  } catch {
1094
1103
  }
1095
1104
  }
1096
- return descriptors;
1105
+ const seen = /* @__PURE__ */ new Map();
1106
+ const duplicates = [];
1107
+ descriptors.sort((a, b) => a.id.localeCompare(b.id));
1108
+ for (const desc of descriptors) {
1109
+ const key = `${desc.type}:${JSON.stringify(desc.options ?? {})}`;
1110
+ if (seen.has(key)) {
1111
+ duplicates.push(desc.id);
1112
+ } else {
1113
+ seen.set(key, desc.id);
1114
+ }
1115
+ }
1116
+ if (duplicates.length > 0) {
1117
+ console.log(
1118
+ `[ConfigRepo] readAllBackendDescriptors: removing ${duplicates.length} duplicate(s): ${duplicates.join(", ")}`
1119
+ );
1120
+ for (const dupId of duplicates) {
1121
+ await this.removeBackendDescriptor(dupId);
1122
+ }
1123
+ }
1124
+ return descriptors.filter((d) => !duplicates.includes(d.id));
1097
1125
  } catch {
1098
1126
  return [];
1099
1127
  }
package/dist/index.mjs CHANGED
@@ -1028,7 +1028,13 @@ var ConfigRepo = class {
1028
1028
  backendFilePath(id) {
1029
1029
  return `${BACKENDS_DIR}/${id}.json`;
1030
1030
  }
1031
- /** Read all backend descriptors from .meta/backends/*.json */
1031
+ /**
1032
+ * Read all backend descriptors from .meta/backends/*.json.
1033
+ *
1034
+ * If duplicate backends are detected (same type + options but different id),
1035
+ * only the first one (sorted by id) is kept and the rest are removed
1036
+ * (including their version sidecar files).
1037
+ */
1032
1038
  async readAllBackendDescriptors() {
1033
1039
  try {
1034
1040
  const entries = await this.cachedFS.readdir(BACKENDS_DIR);
@@ -1037,11 +1043,33 @@ var ConfigRepo = class {
1037
1043
  if (!entry.endsWith(".json")) continue;
1038
1044
  try {
1039
1045
  const raw = await this.cachedFS.readFile(`${BACKENDS_DIR}/${entry}`);
1040
- descriptors.push(JSON.parse(new TextDecoder().decode(toUint8Array(raw))));
1046
+ const desc = JSON.parse(new TextDecoder().decode(toUint8Array(raw)));
1047
+ if (desc.id && desc.type) {
1048
+ descriptors.push(desc);
1049
+ }
1041
1050
  } catch {
1042
1051
  }
1043
1052
  }
1044
- return descriptors;
1053
+ const seen = /* @__PURE__ */ new Map();
1054
+ const duplicates = [];
1055
+ descriptors.sort((a, b) => a.id.localeCompare(b.id));
1056
+ for (const desc of descriptors) {
1057
+ const key = `${desc.type}:${JSON.stringify(desc.options ?? {})}`;
1058
+ if (seen.has(key)) {
1059
+ duplicates.push(desc.id);
1060
+ } else {
1061
+ seen.set(key, desc.id);
1062
+ }
1063
+ }
1064
+ if (duplicates.length > 0) {
1065
+ console.log(
1066
+ `[ConfigRepo] readAllBackendDescriptors: removing ${duplicates.length} duplicate(s): ${duplicates.join(", ")}`
1067
+ );
1068
+ for (const dupId of duplicates) {
1069
+ await this.removeBackendDescriptor(dupId);
1070
+ }
1071
+ }
1072
+ return descriptors.filter((d) => !duplicates.includes(d.id));
1045
1073
  } catch {
1046
1074
  return [];
1047
1075
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zen-fs-config",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Distributed config management library built on ZenFS, zen-fs-cache, and zen-fs-sync",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",