zen-fs-config 0.3.2 → 0.3.4

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.js CHANGED
@@ -319,40 +319,54 @@ function listBackends() {
319
319
  async function wrapZenFSFileSystem(config) {
320
320
  const zenfs = await import("@zenfs/core");
321
321
  const isolatedFS = await zenfs.resolveMountConfig(config);
322
- const pfs = isolatedFS.promises;
323
322
  return {
324
323
  async readFile(path, ...args) {
325
- return args.length > 0 ? pfs.readFile(path, ...args) : pfs.readFile(path);
324
+ const st = await isolatedFS.stat(path);
325
+ const size = st.size;
326
+ const buf = new Uint8Array(size);
327
+ await isolatedFS.read(path, buf, 0, size);
328
+ if (args[0] === "utf-8") return new TextDecoder().decode(buf);
329
+ return buf;
326
330
  },
327
- async writeFile(path, data, options) {
328
- return pfs.writeFile(path, data, options);
331
+ async writeFile(path, data, _options) {
332
+ const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data instanceof Uint8Array ? data : new TextEncoder().encode(data);
333
+ const parts = path.split("/").filter(Boolean);
334
+ parts.pop();
335
+ let dir = "";
336
+ for (const p of parts) {
337
+ dir += "/" + p;
338
+ if (!await isolatedFS.exists(dir)) {
339
+ await isolatedFS.mkdir(dir, { uid: 0, gid: 0, mode: 493 });
340
+ }
341
+ }
342
+ await isolatedFS.write(path, bytes, 0);
329
343
  },
330
344
  async readdir(path) {
331
- const entries = await pfs.readdir(path);
332
- return entries.map((e) => typeof e === "string" ? e : e.name);
345
+ return isolatedFS.readdir(path);
333
346
  },
334
- async stat(path, ...args) {
335
- return pfs.stat(path, ...args);
347
+ async stat(path, ..._args) {
348
+ const st = await isolatedFS.stat(path);
349
+ return {
350
+ isFile: () => st.isDirectory?.() === false || st.mode !== void 0 && (st.mode & 61440) === 32768,
351
+ isDirectory: () => st.isDirectory?.() === true || st.mode !== void 0 && (st.mode & 61440) === 16384,
352
+ size: st.size,
353
+ mtime: st.mtimeMs ?? st.mtime
354
+ };
336
355
  },
337
356
  async exists(path) {
338
- try {
339
- await pfs.stat(path);
340
- return true;
341
- } catch {
342
- return false;
343
- }
357
+ return isolatedFS.exists(path);
344
358
  },
345
359
  async mkdir(path, options) {
346
- return pfs.mkdir(path, options);
360
+ return isolatedFS.mkdir(path, options ?? { uid: 0, gid: 0, mode: 493 });
347
361
  },
348
362
  async unlink(path) {
349
- return pfs.unlink(path);
363
+ return isolatedFS.unlink(path);
350
364
  },
351
365
  async rmdir(path) {
352
- return pfs.rmdir(path);
366
+ return isolatedFS.rmdir(path);
353
367
  },
354
368
  async rename(oldPath, newPath) {
355
- return pfs.rename(oldPath, newPath);
369
+ return isolatedFS.rename(oldPath, newPath);
356
370
  }
357
371
  };
358
372
  }
@@ -1047,20 +1061,35 @@ var ConfigRepo = class {
1047
1061
  // Internal — Setup
1048
1062
  // -----------------------------------------------------------------------
1049
1063
  async setupSync(rules, backends, primaryBackendId) {
1064
+ console.log(`[ConfigRepo] setupSync: ${backends.length} backends, primary=${primaryBackendId}`);
1065
+ console.log(`[ConfigRepo] setupSync: rules=`, JSON.stringify(rules, null, 2));
1050
1066
  for (const desc of backends) {
1051
1067
  if (desc.id === primaryBackendId) continue;
1052
- const instance = await createBackend(desc);
1053
- const syncable = backendToSyncableFS(instance);
1054
- this.replicaBackends.set(desc.id, { instance, syncable });
1068
+ console.log(`[ConfigRepo] Creating replica backend: id=${desc.id}, type=${desc.type}`);
1069
+ try {
1070
+ const instance = await createBackend(desc);
1071
+ const syncable = backendToSyncableFS(instance);
1072
+ this.replicaBackends.set(desc.id, { instance, syncable });
1073
+ console.log(`[ConfigRepo] Replica ${desc.id} created successfully`);
1074
+ } catch (err) {
1075
+ console.error(`[ConfigRepo] Failed to create replica ${desc.id} (${desc.type}):`, err);
1076
+ }
1055
1077
  }
1078
+ console.log(`[ConfigRepo] Available replicas:`, Array.from(this.replicaBackends.keys()));
1056
1079
  for (const rule of rules) {
1057
1080
  if (rule.direction === "none") continue;
1058
- if (!rule.replicas?.length) continue;
1081
+ if (!rule.replicas?.length) {
1082
+ console.log(`[ConfigRepo] Skipping rule ${rule.prefix}: no replicas`);
1083
+ continue;
1084
+ }
1059
1085
  const zenSyncDirection = rule.direction === "bi-directional" ? import_zen_fs_sync.SyncDirection.BiDirectional : import_zen_fs_sync.SyncDirection.OneWay;
1060
1086
  for (const replicaId of rule.replicas) {
1061
1087
  if (replicaId === primaryBackendId) continue;
1062
1088
  const replica = this.replicaBackends.get(replicaId);
1063
- if (!replica) continue;
1089
+ if (!replica) {
1090
+ console.warn(`[ConfigRepo] Skipping pair ${replicaId}: replica not found (available: ${Array.from(this.replicaBackends.keys()).join(", ")})`);
1091
+ continue;
1092
+ }
1064
1093
  const pair = this.syncEngine.addPair(
1065
1094
  this.fullFS,
1066
1095
  replica.syncable,
@@ -1073,6 +1102,7 @@ var ConfigRepo = class {
1073
1102
  },
1074
1103
  "/"
1075
1104
  );
1105
+ console.log(`[ConfigRepo] Sync pair added: pairId=${pair.pairId}, prefix=${rule.prefix}, dir=${rule.direction}, replica=${replicaId}`);
1076
1106
  const conflictHandler = (event) => {
1077
1107
  this.handleConflict(event, rule);
1078
1108
  };
@@ -1080,6 +1110,7 @@ var ConfigRepo = class {
1080
1110
  this.syncEngine.watch(pair.pairId);
1081
1111
  }
1082
1112
  }
1113
+ console.log(`[ConfigRepo] setupSync complete. Sync statuses:`, this.getSyncStatuses());
1083
1114
  }
1084
1115
  // -----------------------------------------------------------------------
1085
1116
  // Internal — Persistence
package/dist/index.mjs CHANGED
@@ -272,40 +272,54 @@ function listBackends() {
272
272
  async function wrapZenFSFileSystem(config) {
273
273
  const zenfs = await import("@zenfs/core");
274
274
  const isolatedFS = await zenfs.resolveMountConfig(config);
275
- const pfs = isolatedFS.promises;
276
275
  return {
277
276
  async readFile(path, ...args) {
278
- return args.length > 0 ? pfs.readFile(path, ...args) : pfs.readFile(path);
277
+ const st = await isolatedFS.stat(path);
278
+ const size = st.size;
279
+ const buf = new Uint8Array(size);
280
+ await isolatedFS.read(path, buf, 0, size);
281
+ if (args[0] === "utf-8") return new TextDecoder().decode(buf);
282
+ return buf;
279
283
  },
280
- async writeFile(path, data, options) {
281
- return pfs.writeFile(path, data, options);
284
+ async writeFile(path, data, _options) {
285
+ const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data instanceof Uint8Array ? data : new TextEncoder().encode(data);
286
+ const parts = path.split("/").filter(Boolean);
287
+ parts.pop();
288
+ let dir = "";
289
+ for (const p of parts) {
290
+ dir += "/" + p;
291
+ if (!await isolatedFS.exists(dir)) {
292
+ await isolatedFS.mkdir(dir, { uid: 0, gid: 0, mode: 493 });
293
+ }
294
+ }
295
+ await isolatedFS.write(path, bytes, 0);
282
296
  },
283
297
  async readdir(path) {
284
- const entries = await pfs.readdir(path);
285
- return entries.map((e) => typeof e === "string" ? e : e.name);
298
+ return isolatedFS.readdir(path);
286
299
  },
287
- async stat(path, ...args) {
288
- return pfs.stat(path, ...args);
300
+ async stat(path, ..._args) {
301
+ const st = await isolatedFS.stat(path);
302
+ return {
303
+ isFile: () => st.isDirectory?.() === false || st.mode !== void 0 && (st.mode & 61440) === 32768,
304
+ isDirectory: () => st.isDirectory?.() === true || st.mode !== void 0 && (st.mode & 61440) === 16384,
305
+ size: st.size,
306
+ mtime: st.mtimeMs ?? st.mtime
307
+ };
289
308
  },
290
309
  async exists(path) {
291
- try {
292
- await pfs.stat(path);
293
- return true;
294
- } catch {
295
- return false;
296
- }
310
+ return isolatedFS.exists(path);
297
311
  },
298
312
  async mkdir(path, options) {
299
- return pfs.mkdir(path, options);
313
+ return isolatedFS.mkdir(path, options ?? { uid: 0, gid: 0, mode: 493 });
300
314
  },
301
315
  async unlink(path) {
302
- return pfs.unlink(path);
316
+ return isolatedFS.unlink(path);
303
317
  },
304
318
  async rmdir(path) {
305
- return pfs.rmdir(path);
319
+ return isolatedFS.rmdir(path);
306
320
  },
307
321
  async rename(oldPath, newPath) {
308
- return pfs.rename(oldPath, newPath);
322
+ return isolatedFS.rename(oldPath, newPath);
309
323
  }
310
324
  };
311
325
  }
@@ -1000,20 +1014,35 @@ var ConfigRepo = class {
1000
1014
  // Internal — Setup
1001
1015
  // -----------------------------------------------------------------------
1002
1016
  async setupSync(rules, backends, primaryBackendId) {
1017
+ console.log(`[ConfigRepo] setupSync: ${backends.length} backends, primary=${primaryBackendId}`);
1018
+ console.log(`[ConfigRepo] setupSync: rules=`, JSON.stringify(rules, null, 2));
1003
1019
  for (const desc of backends) {
1004
1020
  if (desc.id === primaryBackendId) continue;
1005
- const instance = await createBackend(desc);
1006
- const syncable = backendToSyncableFS(instance);
1007
- this.replicaBackends.set(desc.id, { instance, syncable });
1021
+ console.log(`[ConfigRepo] Creating replica backend: id=${desc.id}, type=${desc.type}`);
1022
+ try {
1023
+ const instance = await createBackend(desc);
1024
+ const syncable = backendToSyncableFS(instance);
1025
+ this.replicaBackends.set(desc.id, { instance, syncable });
1026
+ console.log(`[ConfigRepo] Replica ${desc.id} created successfully`);
1027
+ } catch (err) {
1028
+ console.error(`[ConfigRepo] Failed to create replica ${desc.id} (${desc.type}):`, err);
1029
+ }
1008
1030
  }
1031
+ console.log(`[ConfigRepo] Available replicas:`, Array.from(this.replicaBackends.keys()));
1009
1032
  for (const rule of rules) {
1010
1033
  if (rule.direction === "none") continue;
1011
- if (!rule.replicas?.length) continue;
1034
+ if (!rule.replicas?.length) {
1035
+ console.log(`[ConfigRepo] Skipping rule ${rule.prefix}: no replicas`);
1036
+ continue;
1037
+ }
1012
1038
  const zenSyncDirection = rule.direction === "bi-directional" ? SyncDirection.BiDirectional : SyncDirection.OneWay;
1013
1039
  for (const replicaId of rule.replicas) {
1014
1040
  if (replicaId === primaryBackendId) continue;
1015
1041
  const replica = this.replicaBackends.get(replicaId);
1016
- if (!replica) continue;
1042
+ if (!replica) {
1043
+ console.warn(`[ConfigRepo] Skipping pair ${replicaId}: replica not found (available: ${Array.from(this.replicaBackends.keys()).join(", ")})`);
1044
+ continue;
1045
+ }
1017
1046
  const pair = this.syncEngine.addPair(
1018
1047
  this.fullFS,
1019
1048
  replica.syncable,
@@ -1026,6 +1055,7 @@ var ConfigRepo = class {
1026
1055
  },
1027
1056
  "/"
1028
1057
  );
1058
+ console.log(`[ConfigRepo] Sync pair added: pairId=${pair.pairId}, prefix=${rule.prefix}, dir=${rule.direction}, replica=${replicaId}`);
1029
1059
  const conflictHandler = (event) => {
1030
1060
  this.handleConflict(event, rule);
1031
1061
  };
@@ -1033,6 +1063,7 @@ var ConfigRepo = class {
1033
1063
  this.syncEngine.watch(pair.pairId);
1034
1064
  }
1035
1065
  }
1066
+ console.log(`[ConfigRepo] setupSync complete. Sync statuses:`, this.getSyncStatuses());
1036
1067
  }
1037
1068
  // -----------------------------------------------------------------------
1038
1069
  // Internal — Persistence
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zen-fs-config",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
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",