zen-fs-config 0.3.18 → 0.3.20
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 +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +39 -4
- package/dist/index.mjs +39 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -170,6 +170,11 @@ interface IConfigRepo {
|
|
|
170
170
|
getSyncRules(): Promise<SyncRulesMeta | null>;
|
|
171
171
|
/** Write .meta/sync-rules.json. */
|
|
172
172
|
updateSyncRules(meta: SyncRulesMeta): Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* Sync .meta/ files (backends.json, sync-rules.json) to all replica backends.
|
|
175
|
+
* Called automatically by createConfigRepo() after setupSync().
|
|
176
|
+
*/
|
|
177
|
+
syncMetaToReplicas(): Promise<void>;
|
|
173
178
|
/** Dispose: stop all sync, release cache FS and resources. */
|
|
174
179
|
dispose(): Promise<void>;
|
|
175
180
|
}
|
|
@@ -254,6 +259,16 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
254
259
|
}): Promise<SyncResult>;
|
|
255
260
|
peekNodeConfig<T = unknown>(nodeId: string, path: string): Promise<T>;
|
|
256
261
|
flush(): Promise<SyncResult[]>;
|
|
262
|
+
/**
|
|
263
|
+
* Sync .meta/ files (backends.json, sync-rules.json) to all replica backends.
|
|
264
|
+
*
|
|
265
|
+
* This ensures the backend topology is available on every replica, enabling
|
|
266
|
+
* any program that connects to any backend to discover the full topology.
|
|
267
|
+
*
|
|
268
|
+
* Called automatically by createConfigRepo() after setupSync().
|
|
269
|
+
* Can also be called manually after updateBackends() / updateSyncRules().
|
|
270
|
+
*/
|
|
271
|
+
syncMetaToReplicas(): Promise<void>;
|
|
257
272
|
getSyncStatuses(): Map<string, SyncPairStatus>;
|
|
258
273
|
resolveConflict(conflictId: string, mergedContent: unknown): Promise<void>;
|
|
259
274
|
listConflicts(): Promise<ConflictArchive[]>;
|
package/dist/index.d.ts
CHANGED
|
@@ -170,6 +170,11 @@ interface IConfigRepo {
|
|
|
170
170
|
getSyncRules(): Promise<SyncRulesMeta | null>;
|
|
171
171
|
/** Write .meta/sync-rules.json. */
|
|
172
172
|
updateSyncRules(meta: SyncRulesMeta): Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* Sync .meta/ files (backends.json, sync-rules.json) to all replica backends.
|
|
175
|
+
* Called automatically by createConfigRepo() after setupSync().
|
|
176
|
+
*/
|
|
177
|
+
syncMetaToReplicas(): Promise<void>;
|
|
173
178
|
/** Dispose: stop all sync, release cache FS and resources. */
|
|
174
179
|
dispose(): Promise<void>;
|
|
175
180
|
}
|
|
@@ -254,6 +259,16 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
254
259
|
}): Promise<SyncResult>;
|
|
255
260
|
peekNodeConfig<T = unknown>(nodeId: string, path: string): Promise<T>;
|
|
256
261
|
flush(): Promise<SyncResult[]>;
|
|
262
|
+
/**
|
|
263
|
+
* Sync .meta/ files (backends.json, sync-rules.json) to all replica backends.
|
|
264
|
+
*
|
|
265
|
+
* This ensures the backend topology is available on every replica, enabling
|
|
266
|
+
* any program that connects to any backend to discover the full topology.
|
|
267
|
+
*
|
|
268
|
+
* Called automatically by createConfigRepo() after setupSync().
|
|
269
|
+
* Can also be called manually after updateBackends() / updateSyncRules().
|
|
270
|
+
*/
|
|
271
|
+
syncMetaToReplicas(): Promise<void>;
|
|
257
272
|
getSyncStatuses(): Map<string, SyncPairStatus>;
|
|
258
273
|
resolveConflict(conflictId: string, mergedContent: unknown): Promise<void>;
|
|
259
274
|
listConflicts(): Promise<ConflictArchive[]>;
|
package/dist/index.js
CHANGED
|
@@ -414,9 +414,12 @@ async function sha256(data) {
|
|
|
414
414
|
const hex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
415
415
|
return `sha256:${hex}`;
|
|
416
416
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
417
|
+
if (typeof globalThis.window === "undefined") {
|
|
418
|
+
const nodeCrypto = await new Function("return import('node:crypto')")();
|
|
419
|
+
const hash = nodeCrypto.createHash("sha256").update(Buffer.from(buffer)).digest("hex");
|
|
420
|
+
return `sha256:${hash}`;
|
|
421
|
+
}
|
|
422
|
+
throw new Error("SHA-256 not available: neither Web Crypto nor Node.js crypto module found");
|
|
420
423
|
}
|
|
421
424
|
async function readVersion(fs, versionFilePath) {
|
|
422
425
|
try {
|
|
@@ -662,6 +665,32 @@ var ConfigRepo = class {
|
|
|
662
665
|
const resultsMap = await this.syncEngine.syncAll();
|
|
663
666
|
return Array.from(resultsMap.values());
|
|
664
667
|
}
|
|
668
|
+
/**
|
|
669
|
+
* Sync .meta/ files (backends.json, sync-rules.json) to all replica backends.
|
|
670
|
+
*
|
|
671
|
+
* This ensures the backend topology is available on every replica, enabling
|
|
672
|
+
* any program that connects to any backend to discover the full topology.
|
|
673
|
+
*
|
|
674
|
+
* Called automatically by createConfigRepo() after setupSync().
|
|
675
|
+
* Can also be called manually after updateBackends() / updateSyncRules().
|
|
676
|
+
*/
|
|
677
|
+
async syncMetaToReplicas() {
|
|
678
|
+
this.assertNotDisposed();
|
|
679
|
+
for (const metaFile of [BACKENDS_FILE, SYNC_RULES_FILE]) {
|
|
680
|
+
try {
|
|
681
|
+
const content = await this.cachedFS.readFile(metaFile);
|
|
682
|
+
for (const [id, replica] of this.replicaBackends) {
|
|
683
|
+
try {
|
|
684
|
+
await replica.syncable.writeFile(metaFile, content);
|
|
685
|
+
console.log(`[ConfigRepo] Synced ${metaFile} to replica ${id}`);
|
|
686
|
+
} catch (err) {
|
|
687
|
+
console.error(`[ConfigRepo] Failed to sync ${metaFile} to ${id}:`, err.message);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
} catch {
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
665
694
|
getSyncStatuses() {
|
|
666
695
|
this.assertNotDisposed();
|
|
667
696
|
return this.syncEngine.getStatusAll();
|
|
@@ -1049,7 +1078,12 @@ async function createConfigRepo(appId, options) {
|
|
|
1049
1078
|
replicas: backendsMeta.backends.map((b) => b.id)
|
|
1050
1079
|
},
|
|
1051
1080
|
{ prefix: `${NODES_DIR}/`, direction: "none" },
|
|
1052
|
-
{
|
|
1081
|
+
{
|
|
1082
|
+
prefix: `${META_DIR}/`,
|
|
1083
|
+
direction: "one-way",
|
|
1084
|
+
conflictStrategy: "source-wins",
|
|
1085
|
+
replicas: backendsMeta.backends.map((b) => b.id)
|
|
1086
|
+
}
|
|
1053
1087
|
]
|
|
1054
1088
|
};
|
|
1055
1089
|
}
|
|
@@ -1091,6 +1125,7 @@ async function createConfigRepo(appId, options) {
|
|
|
1091
1125
|
backendsMeta.backends,
|
|
1092
1126
|
options.primaryBackendId
|
|
1093
1127
|
);
|
|
1128
|
+
await repo.syncMetaToReplicas();
|
|
1094
1129
|
await repo.load();
|
|
1095
1130
|
return repo;
|
|
1096
1131
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -365,9 +365,12 @@ async function sha256(data) {
|
|
|
365
365
|
const hex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
366
366
|
return `sha256:${hex}`;
|
|
367
367
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
368
|
+
if (typeof globalThis.window === "undefined") {
|
|
369
|
+
const nodeCrypto = await new Function("return import('node:crypto')")();
|
|
370
|
+
const hash = nodeCrypto.createHash("sha256").update(Buffer.from(buffer)).digest("hex");
|
|
371
|
+
return `sha256:${hash}`;
|
|
372
|
+
}
|
|
373
|
+
throw new Error("SHA-256 not available: neither Web Crypto nor Node.js crypto module found");
|
|
371
374
|
}
|
|
372
375
|
async function readVersion(fs, versionFilePath) {
|
|
373
376
|
try {
|
|
@@ -613,6 +616,32 @@ var ConfigRepo = class {
|
|
|
613
616
|
const resultsMap = await this.syncEngine.syncAll();
|
|
614
617
|
return Array.from(resultsMap.values());
|
|
615
618
|
}
|
|
619
|
+
/**
|
|
620
|
+
* Sync .meta/ files (backends.json, sync-rules.json) to all replica backends.
|
|
621
|
+
*
|
|
622
|
+
* This ensures the backend topology is available on every replica, enabling
|
|
623
|
+
* any program that connects to any backend to discover the full topology.
|
|
624
|
+
*
|
|
625
|
+
* Called automatically by createConfigRepo() after setupSync().
|
|
626
|
+
* Can also be called manually after updateBackends() / updateSyncRules().
|
|
627
|
+
*/
|
|
628
|
+
async syncMetaToReplicas() {
|
|
629
|
+
this.assertNotDisposed();
|
|
630
|
+
for (const metaFile of [BACKENDS_FILE, SYNC_RULES_FILE]) {
|
|
631
|
+
try {
|
|
632
|
+
const content = await this.cachedFS.readFile(metaFile);
|
|
633
|
+
for (const [id, replica] of this.replicaBackends) {
|
|
634
|
+
try {
|
|
635
|
+
await replica.syncable.writeFile(metaFile, content);
|
|
636
|
+
console.log(`[ConfigRepo] Synced ${metaFile} to replica ${id}`);
|
|
637
|
+
} catch (err) {
|
|
638
|
+
console.error(`[ConfigRepo] Failed to sync ${metaFile} to ${id}:`, err.message);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
} catch {
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
616
645
|
getSyncStatuses() {
|
|
617
646
|
this.assertNotDisposed();
|
|
618
647
|
return this.syncEngine.getStatusAll();
|
|
@@ -1000,7 +1029,12 @@ async function createConfigRepo(appId, options) {
|
|
|
1000
1029
|
replicas: backendsMeta.backends.map((b) => b.id)
|
|
1001
1030
|
},
|
|
1002
1031
|
{ prefix: `${NODES_DIR}/`, direction: "none" },
|
|
1003
|
-
{
|
|
1032
|
+
{
|
|
1033
|
+
prefix: `${META_DIR}/`,
|
|
1034
|
+
direction: "one-way",
|
|
1035
|
+
conflictStrategy: "source-wins",
|
|
1036
|
+
replicas: backendsMeta.backends.map((b) => b.id)
|
|
1037
|
+
}
|
|
1004
1038
|
]
|
|
1005
1039
|
};
|
|
1006
1040
|
}
|
|
@@ -1042,6 +1076,7 @@ async function createConfigRepo(appId, options) {
|
|
|
1042
1076
|
backendsMeta.backends,
|
|
1043
1077
|
options.primaryBackendId
|
|
1044
1078
|
);
|
|
1079
|
+
await repo.syncMetaToReplicas();
|
|
1045
1080
|
await repo.load();
|
|
1046
1081
|
return repo;
|
|
1047
1082
|
}
|