@componentor/fs 3.0.6 → 3.0.8
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 +12 -0
- package/dist/index.js +106 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -509,6 +509,18 @@ Make sure `opfsSync` is enabled (it's `true` by default). Files are mirrored to
|
|
|
509
509
|
|
|
510
510
|
## Changelog
|
|
511
511
|
|
|
512
|
+
### v3.0.8 (2026)
|
|
513
|
+
|
|
514
|
+
**Improvements:**
|
|
515
|
+
- Add VFS helper functions: `unpackToOPFS`, `loadFromOPFS`, and `repairVFS` for VFS maintenance, migration, and recovery
|
|
516
|
+
- Helpers work in both Worker (sync access handle) and main thread (in-memory buffer + async writable) contexts
|
|
517
|
+
- Remove redundant I/O call in `unpackToOPFS` directory creation
|
|
518
|
+
|
|
519
|
+
### v3.0.7 (2026)
|
|
520
|
+
|
|
521
|
+
**Fixes:**
|
|
522
|
+
- Fix `fs.watch()` path matching for root `/` watchers — watching `/` now correctly matches all child paths instead of missing them due to an off-by-one boundary check
|
|
523
|
+
|
|
512
524
|
### v3.0.6 (2026)
|
|
513
525
|
|
|
514
526
|
**Performance:**
|
package/dist/index.js
CHANGED
|
@@ -1080,10 +1080,11 @@ function matchWatcher(entry, mutatedPath) {
|
|
|
1080
1080
|
if (mutatedPath === absPath) {
|
|
1081
1081
|
return basename(mutatedPath);
|
|
1082
1082
|
}
|
|
1083
|
-
|
|
1083
|
+
const prefix = absPath.endsWith("/") ? absPath : absPath + "/";
|
|
1084
|
+
if (!mutatedPath.startsWith(prefix)) {
|
|
1084
1085
|
return null;
|
|
1085
1086
|
}
|
|
1086
|
-
const relativePath = mutatedPath.substring(
|
|
1087
|
+
const relativePath = mutatedPath.substring(prefix.length);
|
|
1087
1088
|
if (recursive) return relativePath;
|
|
1088
1089
|
return relativePath.indexOf("/") === -1 ? relativePath : null;
|
|
1089
1090
|
}
|
|
@@ -3235,6 +3236,87 @@ var VFSEngine = class {
|
|
|
3235
3236
|
};
|
|
3236
3237
|
|
|
3237
3238
|
// src/helpers.ts
|
|
3239
|
+
var MemoryHandle = class {
|
|
3240
|
+
buf;
|
|
3241
|
+
len;
|
|
3242
|
+
constructor(initialData) {
|
|
3243
|
+
if (initialData && initialData.byteLength > 0) {
|
|
3244
|
+
this.buf = new Uint8Array(initialData);
|
|
3245
|
+
this.len = initialData.byteLength;
|
|
3246
|
+
} else {
|
|
3247
|
+
this.buf = new Uint8Array(1024 * 1024);
|
|
3248
|
+
this.len = 0;
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
getSize() {
|
|
3252
|
+
return this.len;
|
|
3253
|
+
}
|
|
3254
|
+
read(target, opts) {
|
|
3255
|
+
const offset = opts?.at ?? 0;
|
|
3256
|
+
const dst = new Uint8Array(target.buffer, target.byteOffset, target.byteLength);
|
|
3257
|
+
const bytesToRead = Math.min(dst.length, this.len - offset);
|
|
3258
|
+
if (bytesToRead <= 0) return 0;
|
|
3259
|
+
dst.set(this.buf.subarray(offset, offset + bytesToRead));
|
|
3260
|
+
return bytesToRead;
|
|
3261
|
+
}
|
|
3262
|
+
write(data, opts) {
|
|
3263
|
+
const offset = opts?.at ?? 0;
|
|
3264
|
+
const src = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
3265
|
+
const needed = offset + src.length;
|
|
3266
|
+
if (needed > this.buf.length) {
|
|
3267
|
+
this.grow(needed);
|
|
3268
|
+
}
|
|
3269
|
+
this.buf.set(src, offset);
|
|
3270
|
+
if (needed > this.len) this.len = needed;
|
|
3271
|
+
return src.length;
|
|
3272
|
+
}
|
|
3273
|
+
truncate(size) {
|
|
3274
|
+
if (size > this.buf.length) {
|
|
3275
|
+
this.grow(size);
|
|
3276
|
+
}
|
|
3277
|
+
if (size > this.len) {
|
|
3278
|
+
this.buf.fill(0, this.len, size);
|
|
3279
|
+
}
|
|
3280
|
+
this.len = size;
|
|
3281
|
+
}
|
|
3282
|
+
flush() {
|
|
3283
|
+
}
|
|
3284
|
+
close() {
|
|
3285
|
+
}
|
|
3286
|
+
/** Get the current data as an ArrayBuffer (trimmed to actual size) */
|
|
3287
|
+
getBuffer() {
|
|
3288
|
+
return this.buf.buffer.slice(0, this.len);
|
|
3289
|
+
}
|
|
3290
|
+
grow(minSize) {
|
|
3291
|
+
const newSize = Math.max(minSize, this.buf.length * 2);
|
|
3292
|
+
const newBuf = new Uint8Array(newSize);
|
|
3293
|
+
newBuf.set(this.buf.subarray(0, this.len));
|
|
3294
|
+
this.buf = newBuf;
|
|
3295
|
+
}
|
|
3296
|
+
};
|
|
3297
|
+
async function openVFSHandle(fileHandle) {
|
|
3298
|
+
try {
|
|
3299
|
+
const handle = await fileHandle.createSyncAccessHandle();
|
|
3300
|
+
return { handle, isMemory: false };
|
|
3301
|
+
} catch {
|
|
3302
|
+
const file = await fileHandle.getFile();
|
|
3303
|
+
const data = await file.arrayBuffer();
|
|
3304
|
+
return { handle: new MemoryHandle(data), isMemory: true };
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
async function openFreshVFSHandle(fileHandle) {
|
|
3308
|
+
try {
|
|
3309
|
+
const handle = await fileHandle.createSyncAccessHandle();
|
|
3310
|
+
return { handle, isMemory: false };
|
|
3311
|
+
} catch {
|
|
3312
|
+
return { handle: new MemoryHandle(), isMemory: true };
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
async function saveMemoryHandle(fileHandle, memHandle) {
|
|
3316
|
+
const writable = await fileHandle.createWritable();
|
|
3317
|
+
await writable.write(memHandle.getBuffer());
|
|
3318
|
+
await writable.close();
|
|
3319
|
+
}
|
|
3238
3320
|
async function navigateToRoot(root) {
|
|
3239
3321
|
let dir = await navigator.storage.getDirectory();
|
|
3240
3322
|
if (root && root !== "/") {
|
|
@@ -3261,15 +3343,21 @@ async function writeOPFSFile(rootDir, path, data) {
|
|
|
3261
3343
|
const parentDir = await ensureParentDirs(rootDir, path);
|
|
3262
3344
|
const name = basename2(path);
|
|
3263
3345
|
const fileHandle = await parentDir.getFileHandle(name, { create: true });
|
|
3264
|
-
const syncHandle = await fileHandle.createSyncAccessHandle();
|
|
3265
3346
|
try {
|
|
3266
|
-
syncHandle.
|
|
3267
|
-
|
|
3268
|
-
syncHandle.
|
|
3347
|
+
const syncHandle = await fileHandle.createSyncAccessHandle();
|
|
3348
|
+
try {
|
|
3349
|
+
syncHandle.truncate(0);
|
|
3350
|
+
if (data.byteLength > 0) {
|
|
3351
|
+
syncHandle.write(data, { at: 0 });
|
|
3352
|
+
}
|
|
3353
|
+
syncHandle.flush();
|
|
3354
|
+
} finally {
|
|
3355
|
+
syncHandle.close();
|
|
3269
3356
|
}
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3357
|
+
} catch {
|
|
3358
|
+
const writable = await fileHandle.createWritable();
|
|
3359
|
+
await writable.write(data);
|
|
3360
|
+
await writable.close();
|
|
3273
3361
|
}
|
|
3274
3362
|
}
|
|
3275
3363
|
async function clearDirectory(dir, skip) {
|
|
@@ -3301,7 +3389,7 @@ async function readOPFSRecursive(dir, prefix, skip) {
|
|
|
3301
3389
|
async function unpackToOPFS(root = "/") {
|
|
3302
3390
|
const rootDir = await navigateToRoot(root);
|
|
3303
3391
|
const vfsFileHandle = await rootDir.getFileHandle(".vfs.bin");
|
|
3304
|
-
const handle = await vfsFileHandle
|
|
3392
|
+
const { handle } = await openVFSHandle(vfsFileHandle);
|
|
3305
3393
|
let entries;
|
|
3306
3394
|
try {
|
|
3307
3395
|
const engine = new VFSEngine();
|
|
@@ -3339,7 +3427,7 @@ async function loadFromOPFS(root = "/") {
|
|
|
3339
3427
|
} catch (_) {
|
|
3340
3428
|
}
|
|
3341
3429
|
const vfsFileHandle = await rootDir.getFileHandle(".vfs.bin", { create: true });
|
|
3342
|
-
const handle = await vfsFileHandle
|
|
3430
|
+
const { handle, isMemory } = await openFreshVFSHandle(vfsFileHandle);
|
|
3343
3431
|
try {
|
|
3344
3432
|
const engine = new VFSEngine();
|
|
3345
3433
|
engine.init(handle);
|
|
@@ -3356,6 +3444,9 @@ async function loadFromOPFS(root = "/") {
|
|
|
3356
3444
|
files++;
|
|
3357
3445
|
}
|
|
3358
3446
|
engine.flush();
|
|
3447
|
+
if (isMemory) {
|
|
3448
|
+
await saveMemoryHandle(vfsFileHandle, handle);
|
|
3449
|
+
}
|
|
3359
3450
|
return { files, directories };
|
|
3360
3451
|
} finally {
|
|
3361
3452
|
handle.close();
|
|
@@ -3457,7 +3548,7 @@ async function repairVFS(root = "/") {
|
|
|
3457
3548
|
}
|
|
3458
3549
|
await rootDir.removeEntry(".vfs.bin");
|
|
3459
3550
|
const newFileHandle = await rootDir.getFileHandle(".vfs.bin", { create: true });
|
|
3460
|
-
const handle = await newFileHandle
|
|
3551
|
+
const { handle, isMemory } = await openFreshVFSHandle(newFileHandle);
|
|
3461
3552
|
try {
|
|
3462
3553
|
const engine = new VFSEngine();
|
|
3463
3554
|
engine.init(handle);
|
|
@@ -3478,6 +3569,9 @@ async function repairVFS(root = "/") {
|
|
|
3478
3569
|
if (result.status !== 0) lost++;
|
|
3479
3570
|
}
|
|
3480
3571
|
engine.flush();
|
|
3572
|
+
if (isMemory) {
|
|
3573
|
+
await saveMemoryHandle(newFileHandle, handle);
|
|
3574
|
+
}
|
|
3481
3575
|
} finally {
|
|
3482
3576
|
handle.close();
|
|
3483
3577
|
}
|