zen-fs-config 0.3.23 → 0.3.25
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 +1 -4
- package/dist/index.d.ts +1 -4
- package/dist/index.js +24 -59
- package/dist/index.mjs +24 -59
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -222,7 +222,7 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
222
222
|
private onConflictCallback?;
|
|
223
223
|
private disposed;
|
|
224
224
|
private configCache;
|
|
225
|
-
constructor(appId: string, nodeId: string, cachedFS: MinimalAsyncFS, serializer: PathAwareSerializer, onConflict?: (conflict: ConflictInfo) => Promise<unknown | null>);
|
|
225
|
+
constructor(appId: string, nodeId: string, primaryBackendId: string, cachedFS: MinimalAsyncFS, serializer: PathAwareSerializer, onConflict?: (conflict: ConflictInfo) => Promise<unknown | null>);
|
|
226
226
|
/** Full path to this node's directory on the primary backend. */
|
|
227
227
|
get nodePath(): string;
|
|
228
228
|
load(rawConfig?: string): Promise<void>;
|
|
@@ -244,9 +244,6 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
244
244
|
* Called automatically by createConfigRepo() after setupSync().
|
|
245
245
|
*/
|
|
246
246
|
syncMetaToReplicas(): Promise<void>;
|
|
247
|
-
/** Compare two file contents (handles Uint8Array, ArrayBuffer, string, Buffer). */
|
|
248
|
-
private bufferEqual;
|
|
249
|
-
private toUint8Array;
|
|
250
247
|
getSyncStatuses(): Map<string, SyncPairStatus>;
|
|
251
248
|
resolveConflict(conflictId: string, mergedContent: unknown): Promise<void>;
|
|
252
249
|
listConflicts(): Promise<ConflictArchive[]>;
|
package/dist/index.d.ts
CHANGED
|
@@ -222,7 +222,7 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
222
222
|
private onConflictCallback?;
|
|
223
223
|
private disposed;
|
|
224
224
|
private configCache;
|
|
225
|
-
constructor(appId: string, nodeId: string, cachedFS: MinimalAsyncFS, serializer: PathAwareSerializer, onConflict?: (conflict: ConflictInfo) => Promise<unknown | null>);
|
|
225
|
+
constructor(appId: string, nodeId: string, primaryBackendId: string, cachedFS: MinimalAsyncFS, serializer: PathAwareSerializer, onConflict?: (conflict: ConflictInfo) => Promise<unknown | null>);
|
|
226
226
|
/** Full path to this node's directory on the primary backend. */
|
|
227
227
|
get nodePath(): string;
|
|
228
228
|
load(rawConfig?: string): Promise<void>;
|
|
@@ -244,9 +244,6 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
244
244
|
* Called automatically by createConfigRepo() after setupSync().
|
|
245
245
|
*/
|
|
246
246
|
syncMetaToReplicas(): Promise<void>;
|
|
247
|
-
/** Compare two file contents (handles Uint8Array, ArrayBuffer, string, Buffer). */
|
|
248
|
-
private bufferEqual;
|
|
249
|
-
private toUint8Array;
|
|
250
247
|
getSyncStatuses(): Map<string, SyncPairStatus>;
|
|
251
248
|
resolveConflict(conflictId: string, mergedContent: unknown): Promise<void>;
|
|
252
249
|
listConflicts(): Promise<ConflictArchive[]>;
|
package/dist/index.js
CHANGED
|
@@ -225,8 +225,8 @@ async function ensureParentDir(absolutePath) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// src/adapters.ts
|
|
228
|
-
function backendToSyncableFS(backend) {
|
|
229
|
-
|
|
228
|
+
function backendToSyncableFS(backend, name) {
|
|
229
|
+
const syncable = {
|
|
230
230
|
async readdir(path) {
|
|
231
231
|
return backend.readdir(path);
|
|
232
232
|
},
|
|
@@ -265,9 +265,17 @@ function backendToSyncableFS(backend) {
|
|
|
265
265
|
return backend.exists(path);
|
|
266
266
|
}
|
|
267
267
|
};
|
|
268
|
+
if (name) {
|
|
269
|
+
syncable.backendName = name;
|
|
270
|
+
} else if (backend.backendName) {
|
|
271
|
+
syncable.backendName = backend.backendName;
|
|
272
|
+
} else {
|
|
273
|
+
syncable.backendName = backend.constructor.name || "Backend";
|
|
274
|
+
}
|
|
275
|
+
return syncable;
|
|
268
276
|
}
|
|
269
|
-
function cachedFSToSyncableFS(cached) {
|
|
270
|
-
|
|
277
|
+
function cachedFSToSyncableFS(cached, name) {
|
|
278
|
+
const syncable = {
|
|
271
279
|
async readdir(path) {
|
|
272
280
|
return cached.readdir(path);
|
|
273
281
|
},
|
|
@@ -306,6 +314,8 @@ function cachedFSToSyncableFS(cached) {
|
|
|
306
314
|
return cached.exists(path);
|
|
307
315
|
}
|
|
308
316
|
};
|
|
317
|
+
syncable.backendName = name || "CachedFS";
|
|
318
|
+
return syncable;
|
|
309
319
|
}
|
|
310
320
|
|
|
311
321
|
// src/backend-registry.ts
|
|
@@ -502,7 +512,7 @@ var ConfigRepo = class {
|
|
|
502
512
|
onConflictCallback;
|
|
503
513
|
disposed = false;
|
|
504
514
|
configCache = /* @__PURE__ */ new Map();
|
|
505
|
-
constructor(appId, nodeId, cachedFS, serializer, onConflict) {
|
|
515
|
+
constructor(appId, nodeId, primaryBackendId, cachedFS, serializer, onConflict) {
|
|
506
516
|
this.appId = appId;
|
|
507
517
|
this.nodeId = nodeId;
|
|
508
518
|
this.cachedFS = cachedFS;
|
|
@@ -510,7 +520,7 @@ var ConfigRepo = class {
|
|
|
510
520
|
this.syncEngine = new import_zen_fs_sync.ZenFSSync();
|
|
511
521
|
this.replicaBackends = /* @__PURE__ */ new Map();
|
|
512
522
|
this.onConflictCallback = onConflict;
|
|
513
|
-
this.fullFS = cachedFSToSyncableFS(cachedFS);
|
|
523
|
+
this.fullFS = cachedFSToSyncableFS(cachedFS, `CachedFS(${primaryBackendId})`);
|
|
514
524
|
this.fs = createChrootFS(cachedFS, `/${appId}`);
|
|
515
525
|
this.rootFS = createChrootFS(cachedFS, "/");
|
|
516
526
|
}
|
|
@@ -667,59 +677,12 @@ var ConfigRepo = class {
|
|
|
667
677
|
*/
|
|
668
678
|
async syncMetaToReplicas() {
|
|
669
679
|
this.assertNotDisposed();
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
vContent = await this.cachedFS.readFile(vPath);
|
|
676
|
-
} catch {
|
|
677
|
-
}
|
|
678
|
-
for (const [id, replica] of this.replicaBackends) {
|
|
679
|
-
try {
|
|
680
|
-
let needWrite = true;
|
|
681
|
-
try {
|
|
682
|
-
const existing = await replica.syncable.readFile(BACKENDS_FILE);
|
|
683
|
-
if (this.bufferEqual(content, existing)) {
|
|
684
|
-
needWrite = false;
|
|
685
|
-
console.log(`[ConfigRepo] ${BACKENDS_FILE} already up-to-date on ${id}, skipping`);
|
|
686
|
-
}
|
|
687
|
-
} catch {
|
|
688
|
-
}
|
|
689
|
-
if (needWrite) {
|
|
690
|
-
await replica.syncable.writeFile(BACKENDS_FILE, content);
|
|
691
|
-
console.log(`[ConfigRepo] Synced ${BACKENDS_FILE} to replica ${id}`);
|
|
692
|
-
}
|
|
693
|
-
if (vContent) {
|
|
694
|
-
try {
|
|
695
|
-
await replica.syncable.writeFile(vPath, vContent);
|
|
696
|
-
} catch (err) {
|
|
697
|
-
console.error(`[ConfigRepo] Failed to sync ${vPath} to ${id}:`, err.message);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
} catch (err) {
|
|
701
|
-
console.error(`[ConfigRepo] Failed to sync ${BACKENDS_FILE} to ${id}:`, err.message);
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
} catch {
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
/** Compare two file contents (handles Uint8Array, ArrayBuffer, string, Buffer). */
|
|
708
|
-
bufferEqual(a, b) {
|
|
709
|
-
const ua = this.toUint8Array(a);
|
|
710
|
-
const ub = this.toUint8Array(b);
|
|
711
|
-
if (ua.length !== ub.length) return false;
|
|
712
|
-
for (let i = 0; i < ua.length; i++) {
|
|
713
|
-
if (ua[i] !== ub[i]) return false;
|
|
680
|
+
const results = await this.flush();
|
|
681
|
+
for (const result of results) {
|
|
682
|
+
console.log(
|
|
683
|
+
`[ConfigRepo] syncMetaToReplicas: ${result.pairId} +${result.filesCreated}/~${result.filesUpdated}/-${result.filesDeleted} skip:${result.filesSkipped} ${result.durationMs}ms`
|
|
684
|
+
);
|
|
714
685
|
}
|
|
715
|
-
return true;
|
|
716
|
-
}
|
|
717
|
-
toUint8Array(raw) {
|
|
718
|
-
if (raw instanceof ArrayBuffer) return new Uint8Array(raw);
|
|
719
|
-
if (raw instanceof Uint8Array) return raw;
|
|
720
|
-
if (typeof raw === "string") return new TextEncoder().encode(raw);
|
|
721
|
-
if (Buffer.isBuffer(raw)) return new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
722
|
-
return new Uint8Array(raw);
|
|
723
686
|
}
|
|
724
687
|
getSyncStatuses() {
|
|
725
688
|
this.assertNotDisposed();
|
|
@@ -816,7 +779,7 @@ var ConfigRepo = class {
|
|
|
816
779
|
console.log(`[ConfigRepo] Creating replica backend: id=${desc.id}, type=${desc.type}`);
|
|
817
780
|
try {
|
|
818
781
|
const instance = await createBackend(desc);
|
|
819
|
-
const syncable = backendToSyncableFS(instance);
|
|
782
|
+
const syncable = backendToSyncableFS(instance, `${desc.type}(${desc.id})`);
|
|
820
783
|
this.replicaBackends.set(desc.id, { instance, syncable });
|
|
821
784
|
console.log(`[ConfigRepo] Replica ${desc.id} created successfully`);
|
|
822
785
|
} catch (err) {
|
|
@@ -1062,6 +1025,7 @@ async function createConfigRepo(appId, options) {
|
|
|
1062
1025
|
const tempRepo = new ConfigRepo(
|
|
1063
1026
|
appId,
|
|
1064
1027
|
"",
|
|
1028
|
+
options.primaryBackendId,
|
|
1065
1029
|
cachedFS,
|
|
1066
1030
|
createSerializerChain(),
|
|
1067
1031
|
void 0
|
|
@@ -1118,6 +1082,7 @@ async function createConfigRepo(appId, options) {
|
|
|
1118
1082
|
const repo = new ConfigRepo(
|
|
1119
1083
|
appId,
|
|
1120
1084
|
nodeId,
|
|
1085
|
+
options.primaryBackendId,
|
|
1121
1086
|
cachedFS,
|
|
1122
1087
|
serializer,
|
|
1123
1088
|
options.onConflict
|
package/dist/index.mjs
CHANGED
|
@@ -176,8 +176,8 @@ async function ensureParentDir(absolutePath) {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
// src/adapters.ts
|
|
179
|
-
function backendToSyncableFS(backend) {
|
|
180
|
-
|
|
179
|
+
function backendToSyncableFS(backend, name) {
|
|
180
|
+
const syncable = {
|
|
181
181
|
async readdir(path) {
|
|
182
182
|
return backend.readdir(path);
|
|
183
183
|
},
|
|
@@ -216,9 +216,17 @@ function backendToSyncableFS(backend) {
|
|
|
216
216
|
return backend.exists(path);
|
|
217
217
|
}
|
|
218
218
|
};
|
|
219
|
+
if (name) {
|
|
220
|
+
syncable.backendName = name;
|
|
221
|
+
} else if (backend.backendName) {
|
|
222
|
+
syncable.backendName = backend.backendName;
|
|
223
|
+
} else {
|
|
224
|
+
syncable.backendName = backend.constructor.name || "Backend";
|
|
225
|
+
}
|
|
226
|
+
return syncable;
|
|
219
227
|
}
|
|
220
|
-
function cachedFSToSyncableFS(cached) {
|
|
221
|
-
|
|
228
|
+
function cachedFSToSyncableFS(cached, name) {
|
|
229
|
+
const syncable = {
|
|
222
230
|
async readdir(path) {
|
|
223
231
|
return cached.readdir(path);
|
|
224
232
|
},
|
|
@@ -257,6 +265,8 @@ function cachedFSToSyncableFS(cached) {
|
|
|
257
265
|
return cached.exists(path);
|
|
258
266
|
}
|
|
259
267
|
};
|
|
268
|
+
syncable.backendName = name || "CachedFS";
|
|
269
|
+
return syncable;
|
|
260
270
|
}
|
|
261
271
|
|
|
262
272
|
// src/backend-registry.ts
|
|
@@ -453,7 +463,7 @@ var ConfigRepo = class {
|
|
|
453
463
|
onConflictCallback;
|
|
454
464
|
disposed = false;
|
|
455
465
|
configCache = /* @__PURE__ */ new Map();
|
|
456
|
-
constructor(appId, nodeId, cachedFS, serializer, onConflict) {
|
|
466
|
+
constructor(appId, nodeId, primaryBackendId, cachedFS, serializer, onConflict) {
|
|
457
467
|
this.appId = appId;
|
|
458
468
|
this.nodeId = nodeId;
|
|
459
469
|
this.cachedFS = cachedFS;
|
|
@@ -461,7 +471,7 @@ var ConfigRepo = class {
|
|
|
461
471
|
this.syncEngine = new ZenFSSync();
|
|
462
472
|
this.replicaBackends = /* @__PURE__ */ new Map();
|
|
463
473
|
this.onConflictCallback = onConflict;
|
|
464
|
-
this.fullFS = cachedFSToSyncableFS(cachedFS);
|
|
474
|
+
this.fullFS = cachedFSToSyncableFS(cachedFS, `CachedFS(${primaryBackendId})`);
|
|
465
475
|
this.fs = createChrootFS(cachedFS, `/${appId}`);
|
|
466
476
|
this.rootFS = createChrootFS(cachedFS, "/");
|
|
467
477
|
}
|
|
@@ -618,59 +628,12 @@ var ConfigRepo = class {
|
|
|
618
628
|
*/
|
|
619
629
|
async syncMetaToReplicas() {
|
|
620
630
|
this.assertNotDisposed();
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
vContent = await this.cachedFS.readFile(vPath);
|
|
627
|
-
} catch {
|
|
628
|
-
}
|
|
629
|
-
for (const [id, replica] of this.replicaBackends) {
|
|
630
|
-
try {
|
|
631
|
-
let needWrite = true;
|
|
632
|
-
try {
|
|
633
|
-
const existing = await replica.syncable.readFile(BACKENDS_FILE);
|
|
634
|
-
if (this.bufferEqual(content, existing)) {
|
|
635
|
-
needWrite = false;
|
|
636
|
-
console.log(`[ConfigRepo] ${BACKENDS_FILE} already up-to-date on ${id}, skipping`);
|
|
637
|
-
}
|
|
638
|
-
} catch {
|
|
639
|
-
}
|
|
640
|
-
if (needWrite) {
|
|
641
|
-
await replica.syncable.writeFile(BACKENDS_FILE, content);
|
|
642
|
-
console.log(`[ConfigRepo] Synced ${BACKENDS_FILE} to replica ${id}`);
|
|
643
|
-
}
|
|
644
|
-
if (vContent) {
|
|
645
|
-
try {
|
|
646
|
-
await replica.syncable.writeFile(vPath, vContent);
|
|
647
|
-
} catch (err) {
|
|
648
|
-
console.error(`[ConfigRepo] Failed to sync ${vPath} to ${id}:`, err.message);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
} catch (err) {
|
|
652
|
-
console.error(`[ConfigRepo] Failed to sync ${BACKENDS_FILE} to ${id}:`, err.message);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
} catch {
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
/** Compare two file contents (handles Uint8Array, ArrayBuffer, string, Buffer). */
|
|
659
|
-
bufferEqual(a, b) {
|
|
660
|
-
const ua = this.toUint8Array(a);
|
|
661
|
-
const ub = this.toUint8Array(b);
|
|
662
|
-
if (ua.length !== ub.length) return false;
|
|
663
|
-
for (let i = 0; i < ua.length; i++) {
|
|
664
|
-
if (ua[i] !== ub[i]) return false;
|
|
631
|
+
const results = await this.flush();
|
|
632
|
+
for (const result of results) {
|
|
633
|
+
console.log(
|
|
634
|
+
`[ConfigRepo] syncMetaToReplicas: ${result.pairId} +${result.filesCreated}/~${result.filesUpdated}/-${result.filesDeleted} skip:${result.filesSkipped} ${result.durationMs}ms`
|
|
635
|
+
);
|
|
665
636
|
}
|
|
666
|
-
return true;
|
|
667
|
-
}
|
|
668
|
-
toUint8Array(raw) {
|
|
669
|
-
if (raw instanceof ArrayBuffer) return new Uint8Array(raw);
|
|
670
|
-
if (raw instanceof Uint8Array) return raw;
|
|
671
|
-
if (typeof raw === "string") return new TextEncoder().encode(raw);
|
|
672
|
-
if (Buffer.isBuffer(raw)) return new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
673
|
-
return new Uint8Array(raw);
|
|
674
637
|
}
|
|
675
638
|
getSyncStatuses() {
|
|
676
639
|
this.assertNotDisposed();
|
|
@@ -767,7 +730,7 @@ var ConfigRepo = class {
|
|
|
767
730
|
console.log(`[ConfigRepo] Creating replica backend: id=${desc.id}, type=${desc.type}`);
|
|
768
731
|
try {
|
|
769
732
|
const instance = await createBackend(desc);
|
|
770
|
-
const syncable = backendToSyncableFS(instance);
|
|
733
|
+
const syncable = backendToSyncableFS(instance, `${desc.type}(${desc.id})`);
|
|
771
734
|
this.replicaBackends.set(desc.id, { instance, syncable });
|
|
772
735
|
console.log(`[ConfigRepo] Replica ${desc.id} created successfully`);
|
|
773
736
|
} catch (err) {
|
|
@@ -1013,6 +976,7 @@ async function createConfigRepo(appId, options) {
|
|
|
1013
976
|
const tempRepo = new ConfigRepo(
|
|
1014
977
|
appId,
|
|
1015
978
|
"",
|
|
979
|
+
options.primaryBackendId,
|
|
1016
980
|
cachedFS,
|
|
1017
981
|
createSerializerChain(),
|
|
1018
982
|
void 0
|
|
@@ -1069,6 +1033,7 @@ async function createConfigRepo(appId, options) {
|
|
|
1069
1033
|
const repo = new ConfigRepo(
|
|
1070
1034
|
appId,
|
|
1071
1035
|
nodeId,
|
|
1036
|
+
options.primaryBackendId,
|
|
1072
1037
|
cachedFS,
|
|
1073
1038
|
serializer,
|
|
1074
1039
|
options.onConflict
|