zen-fs-config 0.5.21 → 0.5.24
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/README.md +22 -0
- package/README.zh-CN.md +22 -0
- package/dist/index.d.mts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +172 -30
- package/dist/index.mjs +172 -30
- package/dist/zen-fs-config.js +28472 -0
- package/package.json +5 -2
package/dist/index.mjs
CHANGED
|
@@ -54,9 +54,11 @@ function createSerializerChain(custom) {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
function configKeyToFilePath(configPath) {
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
57
|
+
let p = configPath;
|
|
58
|
+
if (!p.startsWith("/")) p = "/" + p;
|
|
59
|
+
const ext = getExtension(p);
|
|
60
|
+
if (ext !== "") return p;
|
|
61
|
+
return p.endsWith("/") ? p : `${p}.json`;
|
|
60
62
|
}
|
|
61
63
|
function getExtension(path) {
|
|
62
64
|
const lastSlash = path.lastIndexOf("/");
|
|
@@ -172,6 +174,20 @@ async function ensureParentDir(absolutePath) {
|
|
|
172
174
|
}
|
|
173
175
|
|
|
174
176
|
// src/adapters.ts
|
|
177
|
+
function toUint8Array(data) {
|
|
178
|
+
if (data instanceof Uint8Array) return data;
|
|
179
|
+
if (data instanceof ArrayBuffer) return new Uint8Array(data);
|
|
180
|
+
if (typeof data === "string") return new TextEncoder().encode(data);
|
|
181
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
182
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
183
|
+
}
|
|
184
|
+
return new Uint8Array(data);
|
|
185
|
+
}
|
|
186
|
+
function toString(data, encoding) {
|
|
187
|
+
if (typeof data === "string") return data;
|
|
188
|
+
const bytes = toUint8Array(data);
|
|
189
|
+
return new TextDecoder().decode(bytes);
|
|
190
|
+
}
|
|
175
191
|
function backendToSyncableFS(backend, name) {
|
|
176
192
|
const syncable = {
|
|
177
193
|
async readdir(path) {
|
|
@@ -180,15 +196,9 @@ function backendToSyncableFS(backend, name) {
|
|
|
180
196
|
async readFile(path, encoding) {
|
|
181
197
|
const result = await backend.readFile(path, encoding);
|
|
182
198
|
if (encoding) {
|
|
183
|
-
|
|
184
|
-
if (result instanceof Uint8Array) return new TextDecoder().decode(result);
|
|
185
|
-
if (Buffer.isBuffer(result)) return result.toString(encoding);
|
|
186
|
-
return String(result);
|
|
199
|
+
return toString(result, encoding);
|
|
187
200
|
}
|
|
188
|
-
|
|
189
|
-
if (result instanceof Uint8Array) return Buffer.from(result);
|
|
190
|
-
if (Buffer.isBuffer(result)) return result;
|
|
191
|
-
return Buffer.from(String(result));
|
|
201
|
+
return toUint8Array(result);
|
|
192
202
|
},
|
|
193
203
|
async writeFile(path, data) {
|
|
194
204
|
return backend.writeFile(path, data);
|
|
@@ -409,20 +419,150 @@ function versionPathFor(configFilePath) {
|
|
|
409
419
|
const versionFileName = fileName.startsWith(".") ? `${fileName}.version` : `.${fileName}.version`;
|
|
410
420
|
return dir ? `${dir}/${versionFileName}` : versionFileName;
|
|
411
421
|
}
|
|
422
|
+
function sha256PureJS(data) {
|
|
423
|
+
const K = new Uint32Array([
|
|
424
|
+
1116352408,
|
|
425
|
+
1899447441,
|
|
426
|
+
3049323471,
|
|
427
|
+
3921009573,
|
|
428
|
+
961987163,
|
|
429
|
+
1508970993,
|
|
430
|
+
2453635748,
|
|
431
|
+
2870763221,
|
|
432
|
+
3624381080,
|
|
433
|
+
310598401,
|
|
434
|
+
607225278,
|
|
435
|
+
1426881987,
|
|
436
|
+
1925078388,
|
|
437
|
+
2162078206,
|
|
438
|
+
2614888103,
|
|
439
|
+
3248222580,
|
|
440
|
+
3835390401,
|
|
441
|
+
4022224774,
|
|
442
|
+
264347078,
|
|
443
|
+
604807628,
|
|
444
|
+
770255983,
|
|
445
|
+
1249150122,
|
|
446
|
+
1555081692,
|
|
447
|
+
1996064986,
|
|
448
|
+
2554220882,
|
|
449
|
+
2821834349,
|
|
450
|
+
2952996808,
|
|
451
|
+
3210313671,
|
|
452
|
+
3336571891,
|
|
453
|
+
3584528711,
|
|
454
|
+
113926993,
|
|
455
|
+
338241895,
|
|
456
|
+
666307205,
|
|
457
|
+
773529912,
|
|
458
|
+
1294757372,
|
|
459
|
+
1396182291,
|
|
460
|
+
1695183700,
|
|
461
|
+
1986661051,
|
|
462
|
+
2177026350,
|
|
463
|
+
2456956037,
|
|
464
|
+
2730485921,
|
|
465
|
+
2820302411,
|
|
466
|
+
3259730800,
|
|
467
|
+
3345764771,
|
|
468
|
+
3516065817,
|
|
469
|
+
3600352804,
|
|
470
|
+
4094571909,
|
|
471
|
+
275423344,
|
|
472
|
+
430227734,
|
|
473
|
+
506948616,
|
|
474
|
+
659060556,
|
|
475
|
+
883997877,
|
|
476
|
+
958139571,
|
|
477
|
+
1322822218,
|
|
478
|
+
1537002063,
|
|
479
|
+
1747873779,
|
|
480
|
+
1955562222,
|
|
481
|
+
2024104815,
|
|
482
|
+
2227730452,
|
|
483
|
+
2361852424,
|
|
484
|
+
2428436474,
|
|
485
|
+
2756734187,
|
|
486
|
+
3204031479,
|
|
487
|
+
3329325298
|
|
488
|
+
]);
|
|
489
|
+
const H = new Uint32Array([
|
|
490
|
+
1779033703,
|
|
491
|
+
3144134277,
|
|
492
|
+
1013904242,
|
|
493
|
+
2773480762,
|
|
494
|
+
1359893119,
|
|
495
|
+
2600822924,
|
|
496
|
+
528734635,
|
|
497
|
+
1541459225
|
|
498
|
+
]);
|
|
499
|
+
const len = data.length;
|
|
500
|
+
const bitLen = len * 8;
|
|
501
|
+
const padLen = (len + 8 >> 6 << 6) + 64;
|
|
502
|
+
const buf = new Uint8Array(padLen);
|
|
503
|
+
buf.set(data);
|
|
504
|
+
buf[len] = 128;
|
|
505
|
+
const dv = new DataView(buf.buffer);
|
|
506
|
+
dv.setUint32(padLen - 4, bitLen >>> 0, false);
|
|
507
|
+
dv.setUint32(padLen - 8, Math.floor(bitLen / 4294967296) >>> 0, false);
|
|
508
|
+
const W = new Uint32Array(64);
|
|
509
|
+
for (let i = 0; i < padLen; i += 64) {
|
|
510
|
+
for (let t = 0; t < 16; t++) {
|
|
511
|
+
W[t] = dv.getUint32(i + t * 4, false);
|
|
512
|
+
}
|
|
513
|
+
for (let t = 16; t < 64; t++) {
|
|
514
|
+
const s0 = (W[t - 15] >>> 7 | W[t - 15] << 25) ^ (W[t - 15] >>> 18 | W[t - 15] << 14) ^ W[t - 15] >>> 3;
|
|
515
|
+
const s1 = (W[t - 2] >>> 17 | W[t - 2] << 15) ^ (W[t - 2] >>> 19 | W[t - 2] << 13) ^ W[t - 2] >>> 10;
|
|
516
|
+
W[t] = W[t - 16] + s0 + W[t - 7] + s1 >>> 0;
|
|
517
|
+
}
|
|
518
|
+
let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];
|
|
519
|
+
for (let t = 0; t < 64; t++) {
|
|
520
|
+
const S1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7);
|
|
521
|
+
const ch = e & f ^ ~e & g;
|
|
522
|
+
const temp1 = h + S1 + ch + K[t] + W[t] >>> 0;
|
|
523
|
+
const S0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10);
|
|
524
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
525
|
+
const temp2 = S0 + maj >>> 0;
|
|
526
|
+
h = g;
|
|
527
|
+
g = f;
|
|
528
|
+
f = e;
|
|
529
|
+
e = d + temp1 >>> 0;
|
|
530
|
+
d = c;
|
|
531
|
+
c = b;
|
|
532
|
+
b = a;
|
|
533
|
+
a = temp1 + temp2 >>> 0;
|
|
534
|
+
}
|
|
535
|
+
H[0] = H[0] + a >>> 0;
|
|
536
|
+
H[1] = H[1] + b >>> 0;
|
|
537
|
+
H[2] = H[2] + c >>> 0;
|
|
538
|
+
H[3] = H[3] + d >>> 0;
|
|
539
|
+
H[4] = H[4] + e >>> 0;
|
|
540
|
+
H[5] = H[5] + f >>> 0;
|
|
541
|
+
H[6] = H[6] + g >>> 0;
|
|
542
|
+
H[7] = H[7] + h >>> 0;
|
|
543
|
+
}
|
|
544
|
+
const out = new Uint8Array(32);
|
|
545
|
+
const outDv = new DataView(out.buffer);
|
|
546
|
+
for (let i = 0; i < 8; i++) outDv.setUint32(i * 4, H[i], false);
|
|
547
|
+
return out;
|
|
548
|
+
}
|
|
412
549
|
async function sha256(data) {
|
|
413
550
|
const buffer = data.byteLength === data.buffer.byteLength ? data.buffer : data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
414
|
-
|
|
415
|
-
|
|
551
|
+
const webCrypto = globalThis.crypto;
|
|
552
|
+
if (webCrypto && typeof webCrypto.subtle?.digest === "function") {
|
|
553
|
+
const hashBuffer = await webCrypto.subtle.digest("SHA-256", buffer);
|
|
416
554
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
417
|
-
const
|
|
418
|
-
return `sha256:${
|
|
555
|
+
const hex2 = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
556
|
+
return `sha256:${hex2}`;
|
|
419
557
|
}
|
|
420
558
|
if (typeof globalThis.window === "undefined") {
|
|
421
559
|
const nodeCrypto = await new Function("return import('node:crypto')")();
|
|
422
560
|
const hash = nodeCrypto.createHash("sha256").update(Buffer.from(buffer)).digest("hex");
|
|
423
561
|
return `sha256:${hash}`;
|
|
424
562
|
}
|
|
425
|
-
|
|
563
|
+
const digest = sha256PureJS(data);
|
|
564
|
+
const hex = Array.from(digest).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
565
|
+
return `sha256:${hex}`;
|
|
426
566
|
}
|
|
427
567
|
async function readVersion(fs, versionFilePath) {
|
|
428
568
|
try {
|
|
@@ -463,7 +603,7 @@ async function verifyOrRepairVersion(fs, configFilePath, author) {
|
|
|
463
603
|
data = new TextEncoder().encode(content);
|
|
464
604
|
} else if (content instanceof Uint8Array) {
|
|
465
605
|
data = content;
|
|
466
|
-
} else if (Buffer.isBuffer(content)) {
|
|
606
|
+
} else if (typeof Buffer !== "undefined" && Buffer.isBuffer(content)) {
|
|
467
607
|
data = new Uint8Array(content.buffer, content.byteOffset, content.byteLength);
|
|
468
608
|
} else {
|
|
469
609
|
data = new Uint8Array(content);
|
|
@@ -614,7 +754,7 @@ var ConfigRepo = class {
|
|
|
614
754
|
const fullPath = `${NODES_DIR}/${nodeId}${filePath}`;
|
|
615
755
|
try {
|
|
616
756
|
const raw = await this.cachedFS.readFile(fullPath);
|
|
617
|
-
return this.serializer.deserialize(
|
|
757
|
+
return this.serializer.deserialize(toUint8Array2(raw), fullPath);
|
|
618
758
|
} catch {
|
|
619
759
|
throw new Error(`Node config not found: ${nodeId}${path}`);
|
|
620
760
|
}
|
|
@@ -691,7 +831,7 @@ var ConfigRepo = class {
|
|
|
691
831
|
const fullPath = `${NODES_DIR}/${nodeId}${filePath}`;
|
|
692
832
|
try {
|
|
693
833
|
const raw = await this.cachedFS.readFile(fullPath);
|
|
694
|
-
return this.serializer.deserialize(
|
|
834
|
+
return this.serializer.deserialize(toUint8Array2(raw), fullPath);
|
|
695
835
|
} catch {
|
|
696
836
|
throw new Error(`Node config not found: ${nodeId}${path}`);
|
|
697
837
|
}
|
|
@@ -785,7 +925,7 @@ var ConfigRepo = class {
|
|
|
785
925
|
if (!entry.endsWith(".json")) continue;
|
|
786
926
|
try {
|
|
787
927
|
const raw = await this.cachedFS.readFile(`${DELETIONS_DIR}/${entry}`);
|
|
788
|
-
const data = JSON.parse(new TextDecoder().decode(
|
|
928
|
+
const data = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
789
929
|
tombstones.push(data);
|
|
790
930
|
} catch {
|
|
791
931
|
}
|
|
@@ -1028,7 +1168,7 @@ var ConfigRepo = class {
|
|
|
1028
1168
|
try {
|
|
1029
1169
|
const raw = await this.cachedFS.readFile(metaPath);
|
|
1030
1170
|
const archive = JSON.parse(
|
|
1031
|
-
new TextDecoder().decode(
|
|
1171
|
+
new TextDecoder().decode(toUint8Array2(raw))
|
|
1032
1172
|
);
|
|
1033
1173
|
const configPath = archive.conflictPath;
|
|
1034
1174
|
const bytes = this.serializer.serialize(mergedContent, configPath);
|
|
@@ -1064,7 +1204,7 @@ var ConfigRepo = class {
|
|
|
1064
1204
|
try {
|
|
1065
1205
|
const raw = await this.cachedFS.readFile(metaPath);
|
|
1066
1206
|
const archive = JSON.parse(
|
|
1067
|
-
new TextDecoder().decode(
|
|
1207
|
+
new TextDecoder().decode(toUint8Array2(raw))
|
|
1068
1208
|
);
|
|
1069
1209
|
archives.push(archive);
|
|
1070
1210
|
} catch {
|
|
@@ -1079,7 +1219,7 @@ var ConfigRepo = class {
|
|
|
1079
1219
|
const conflictDir = `${CONFLICTS_DIR}/${conflictId}`.replace(/\/meta\.json$/, "");
|
|
1080
1220
|
const filePath = `${conflictDir}/${fileType}`;
|
|
1081
1221
|
const raw = await this.cachedFS.readFile(filePath);
|
|
1082
|
-
return new TextDecoder().decode(
|
|
1222
|
+
return new TextDecoder().decode(toUint8Array2(raw));
|
|
1083
1223
|
}
|
|
1084
1224
|
// -----------------------------------------------------------------------
|
|
1085
1225
|
// IConfigRepo — Lifecycle
|
|
@@ -1210,7 +1350,7 @@ var ConfigRepo = class {
|
|
|
1210
1350
|
files.map(async (filePath) => {
|
|
1211
1351
|
try {
|
|
1212
1352
|
const raw = await this.cachedFS.readFile(filePath);
|
|
1213
|
-
const data = this.serializer.deserialize(
|
|
1353
|
+
const data = this.serializer.deserialize(toUint8Array2(raw), filePath);
|
|
1214
1354
|
return { filePath, data };
|
|
1215
1355
|
} catch {
|
|
1216
1356
|
return null;
|
|
@@ -1340,7 +1480,7 @@ var ConfigRepo = class {
|
|
|
1340
1480
|
async readMetaFile(path) {
|
|
1341
1481
|
try {
|
|
1342
1482
|
const raw = await this.cachedFS.readFile(path);
|
|
1343
|
-
return JSON.parse(new TextDecoder().decode(
|
|
1483
|
+
return JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
1344
1484
|
} catch {
|
|
1345
1485
|
return null;
|
|
1346
1486
|
}
|
|
@@ -1368,7 +1508,7 @@ var ConfigRepo = class {
|
|
|
1368
1508
|
const filePath = `${BACKENDS_DIR}/${entry}`;
|
|
1369
1509
|
try {
|
|
1370
1510
|
const raw = await this.cachedFS.readFile(filePath);
|
|
1371
|
-
const desc = JSON.parse(new TextDecoder().decode(
|
|
1511
|
+
const desc = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
1372
1512
|
if (desc.id && desc.type) {
|
|
1373
1513
|
let mtime = 0;
|
|
1374
1514
|
try {
|
|
@@ -1703,7 +1843,7 @@ var ConfigRepo = class {
|
|
|
1703
1843
|
const descPath = this.appDataGroupFilePath(id);
|
|
1704
1844
|
try {
|
|
1705
1845
|
const raw = await this.cachedFS.readFile(descPath);
|
|
1706
|
-
const descriptor = JSON.parse(new TextDecoder().decode(
|
|
1846
|
+
const descriptor = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
1707
1847
|
const group = new AppDataGroupImpl(
|
|
1708
1848
|
id,
|
|
1709
1849
|
this.appId,
|
|
@@ -1727,7 +1867,7 @@ var ConfigRepo = class {
|
|
|
1727
1867
|
if (!entry.endsWith(".json")) continue;
|
|
1728
1868
|
try {
|
|
1729
1869
|
const raw = await this.cachedFS.readFile(`${dir}/${entry}`);
|
|
1730
|
-
const desc = JSON.parse(new TextDecoder().decode(
|
|
1870
|
+
const desc = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
1731
1871
|
if (desc.id && desc.groupType === "data-sync") {
|
|
1732
1872
|
descriptors.push(desc);
|
|
1733
1873
|
}
|
|
@@ -1893,11 +2033,13 @@ var AppDataGroupImpl = class {
|
|
|
1893
2033
|
this.dataBackends.clear();
|
|
1894
2034
|
}
|
|
1895
2035
|
};
|
|
1896
|
-
function
|
|
2036
|
+
function toUint8Array2(raw) {
|
|
1897
2037
|
if (raw instanceof ArrayBuffer) return new Uint8Array(raw);
|
|
1898
2038
|
if (raw instanceof Uint8Array) return raw;
|
|
1899
2039
|
if (typeof raw === "string") return new TextEncoder().encode(raw);
|
|
1900
|
-
if (Buffer.isBuffer(raw))
|
|
2040
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(raw)) {
|
|
2041
|
+
return new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
2042
|
+
}
|
|
1901
2043
|
return new Uint8Array(raw);
|
|
1902
2044
|
}
|
|
1903
2045
|
async function createConfigRepo(appId, options = {}) {
|