@componentor/fs 3.0.25 → 3.0.26

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
@@ -160,147 +160,6 @@ function statusToError(status, syscall, path) {
160
160
  return createError(code, syscall, path);
161
161
  }
162
162
 
163
- // src/methods/readFile.ts
164
- var decoder2 = new TextDecoder();
165
- function readFileSync(syncRequest, filePath, options) {
166
- const encoding = typeof options === "string" ? options : options?.encoding;
167
- const buf = encodeRequest(OP.READ, filePath);
168
- const { status, data } = syncRequest(buf);
169
- if (status !== 0) throw statusToError(status, "read", filePath);
170
- const result = data ?? new Uint8Array(0);
171
- if (encoding) return decoder2.decode(result);
172
- return result;
173
- }
174
- async function readFile(asyncRequest, filePath, options) {
175
- const encoding = typeof options === "string" ? options : options?.encoding;
176
- const { status, data } = await asyncRequest(OP.READ, filePath);
177
- if (status !== 0) throw statusToError(status, "read", filePath);
178
- const result = data ?? new Uint8Array(0);
179
- if (encoding) return decoder2.decode(result);
180
- return result;
181
- }
182
-
183
- // src/methods/writeFile.ts
184
- var encoder2 = new TextEncoder();
185
- function writeFileSync(syncRequest, filePath, data, options) {
186
- const opts = typeof options === "string" ? { } : options;
187
- const encoded = typeof data === "string" ? encoder2.encode(data) : data;
188
- const flags = opts?.flush === true ? 1 : 0;
189
- const buf = encodeRequest(OP.WRITE, filePath, flags, encoded);
190
- const { status } = syncRequest(buf);
191
- if (status !== 0) throw statusToError(status, "write", filePath);
192
- }
193
- async function writeFile(asyncRequest, filePath, data, options) {
194
- const opts = typeof options === "string" ? { } : options;
195
- const flags = opts?.flush === true ? 1 : 0;
196
- const encoded = typeof data === "string" ? encoder2.encode(data) : data;
197
- const { status } = await asyncRequest(OP.WRITE, filePath, flags, encoded);
198
- if (status !== 0) throw statusToError(status, "write", filePath);
199
- }
200
-
201
- // src/methods/appendFile.ts
202
- var encoder3 = new TextEncoder();
203
- function appendFileSync(syncRequest, filePath, data, options) {
204
- const encoded = typeof data === "string" ? encoder3.encode(data) : data;
205
- const buf = encodeRequest(OP.APPEND, filePath, 0, encoded);
206
- const { status } = syncRequest(buf);
207
- if (status !== 0) throw statusToError(status, "appendFile", filePath);
208
- }
209
- async function appendFile(asyncRequest, filePath, data, options) {
210
- const encoded = typeof data === "string" ? encoder3.encode(data) : data;
211
- const { status } = await asyncRequest(OP.APPEND, filePath, 0, encoded);
212
- if (status !== 0) throw statusToError(status, "appendFile", filePath);
213
- }
214
-
215
- // src/methods/exists.ts
216
- function existsSync(syncRequest, filePath) {
217
- const buf = encodeRequest(OP.EXISTS, filePath);
218
- const { data } = syncRequest(buf);
219
- return data ? data[0] === 1 : false;
220
- }
221
- async function exists(asyncRequest, filePath) {
222
- const { data } = await asyncRequest(OP.EXISTS, filePath);
223
- return data ? data[0] === 1 : false;
224
- }
225
-
226
- // src/methods/mkdir.ts
227
- var decoder3 = new TextDecoder();
228
- function mkdirSync(syncRequest, filePath, options) {
229
- const opts = typeof options === "number" ? { } : options;
230
- const flags = opts?.recursive ? 1 : 0;
231
- const buf = encodeRequest(OP.MKDIR, filePath, flags);
232
- const { status, data } = syncRequest(buf);
233
- if (status !== 0) throw statusToError(status, "mkdir", filePath);
234
- return data ? decoder3.decode(data) : void 0;
235
- }
236
- async function mkdir(asyncRequest, filePath, options) {
237
- const opts = typeof options === "number" ? { } : options;
238
- const flags = opts?.recursive ? 1 : 0;
239
- const { status, data } = await asyncRequest(OP.MKDIR, filePath, flags);
240
- if (status !== 0) throw statusToError(status, "mkdir", filePath);
241
- return data ? decoder3.decode(data) : void 0;
242
- }
243
-
244
- // src/methods/rmdir.ts
245
- function rmdirSync(syncRequest, filePath, options) {
246
- const flags = options?.recursive ? 1 : 0;
247
- const buf = encodeRequest(OP.RMDIR, filePath, flags);
248
- const { status } = syncRequest(buf);
249
- if (status !== 0) throw statusToError(status, "rmdir", filePath);
250
- }
251
- async function rmdir(asyncRequest, filePath, options) {
252
- const flags = options?.recursive ? 1 : 0;
253
- const { status } = await asyncRequest(OP.RMDIR, filePath, flags);
254
- if (status !== 0) throw statusToError(status, "rmdir", filePath);
255
- }
256
-
257
- // src/methods/rm.ts
258
- function rmSync(syncRequest, filePath, options) {
259
- const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
260
- const buf = encodeRequest(OP.UNLINK, filePath, flags);
261
- const { status } = syncRequest(buf);
262
- if (status === 3) {
263
- const rmdirBuf = encodeRequest(OP.RMDIR, filePath, flags);
264
- const rmdirResult = syncRequest(rmdirBuf);
265
- if (rmdirResult.status !== 0) {
266
- if (options?.force && rmdirResult.status === 1) return;
267
- throw statusToError(rmdirResult.status, "rm", filePath);
268
- }
269
- return;
270
- }
271
- if (status !== 0) {
272
- if (options?.force && status === 1) return;
273
- throw statusToError(status, "rm", filePath);
274
- }
275
- }
276
- async function rm(asyncRequest, filePath, options) {
277
- const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
278
- const { status } = await asyncRequest(OP.UNLINK, filePath, flags);
279
- if (status === 3) {
280
- const { status: s2 } = await asyncRequest(OP.RMDIR, filePath, flags);
281
- if (s2 !== 0) {
282
- if (options?.force && s2 === 1) return;
283
- throw statusToError(s2, "rm", filePath);
284
- }
285
- return;
286
- }
287
- if (status !== 0) {
288
- if (options?.force && status === 1) return;
289
- throw statusToError(status, "rm", filePath);
290
- }
291
- }
292
-
293
- // src/methods/unlink.ts
294
- function unlinkSync(syncRequest, filePath) {
295
- const buf = encodeRequest(OP.UNLINK, filePath);
296
- const { status } = syncRequest(buf);
297
- if (status !== 0) throw statusToError(status, "unlink", filePath);
298
- }
299
- async function unlink(asyncRequest, filePath) {
300
- const { status } = await asyncRequest(OP.UNLINK, filePath);
301
- if (status !== 0) throw statusToError(status, "unlink", filePath);
302
- }
303
-
304
163
  // src/vfs/layout.ts
305
164
  var VFS_MAGIC = 1447449377;
306
165
  var VFS_VERSION = 1;
@@ -339,8 +198,8 @@ var INODE = {
339
198
  // uint32 - byte offset into path table
340
199
  PATH_LENGTH: 8,
341
200
  // uint16 - length of path string
342
- RESERVED_10: 10,
343
- // uint16
201
+ NLINK: 10,
202
+ // uint16 - hard link count
344
203
  MODE: 12,
345
204
  // uint32 - permissions (e.g. 0o100644)
346
205
  SIZE: 16,
@@ -408,6 +267,7 @@ function decodeStats(data) {
408
267
  const uid = view.getUint32(37, true);
409
268
  const gid = view.getUint32(41, true);
410
269
  const ino = view.getUint32(45, true);
270
+ const nlink = data.byteLength >= 53 ? view.getUint32(49, true) : 1;
411
271
  const isFile = type === INODE_TYPE.FILE;
412
272
  const isDirectory = type === INODE_TYPE.DIRECTORY;
413
273
  const isSymlink = type === INODE_TYPE.SYMLINK;
@@ -422,7 +282,7 @@ function decodeStats(data) {
422
282
  dev: 0,
423
283
  ino,
424
284
  mode,
425
- nlink: 1,
285
+ nlink,
426
286
  uid,
427
287
  gid,
428
288
  rdev: 0,
@@ -439,7 +299,57 @@ function decodeStats(data) {
439
299
  birthtime: new Date(ctimeMs)
440
300
  };
441
301
  }
442
- function decodeDirents(data) {
302
+ function decodeStatsBigInt(data) {
303
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
304
+ const type = view.getUint8(0);
305
+ const mode = view.getUint32(1, true);
306
+ const size = view.getFloat64(5, true);
307
+ const mtimeMs = view.getFloat64(13, true);
308
+ const ctimeMs = view.getFloat64(21, true);
309
+ const atimeMs = view.getFloat64(29, true);
310
+ const uid = view.getUint32(37, true);
311
+ const gid = view.getUint32(41, true);
312
+ const ino = view.getUint32(45, true);
313
+ const nlink = data.byteLength >= 53 ? view.getUint32(49, true) : 1;
314
+ const isFile = type === INODE_TYPE.FILE;
315
+ const isDirectory = type === INODE_TYPE.DIRECTORY;
316
+ const isSymlink = type === INODE_TYPE.SYMLINK;
317
+ const atimeMsBigInt = BigInt(Math.trunc(atimeMs));
318
+ const mtimeMsBigInt = BigInt(Math.trunc(mtimeMs));
319
+ const ctimeMsBigInt = BigInt(Math.trunc(ctimeMs));
320
+ return {
321
+ isFile: () => isFile,
322
+ isDirectory: () => isDirectory,
323
+ isBlockDevice: () => false,
324
+ isCharacterDevice: () => false,
325
+ isSymbolicLink: () => isSymlink,
326
+ isFIFO: () => false,
327
+ isSocket: () => false,
328
+ dev: 0n,
329
+ ino: BigInt(ino),
330
+ mode: BigInt(mode),
331
+ nlink: BigInt(nlink),
332
+ uid: BigInt(uid),
333
+ gid: BigInt(gid),
334
+ rdev: 0n,
335
+ size: BigInt(Math.trunc(size)),
336
+ blksize: 4096n,
337
+ blocks: BigInt(Math.ceil(size / 512)),
338
+ atimeMs: atimeMsBigInt,
339
+ mtimeMs: mtimeMsBigInt,
340
+ ctimeMs: ctimeMsBigInt,
341
+ birthtimeMs: ctimeMsBigInt,
342
+ atime: new Date(atimeMs),
343
+ mtime: new Date(mtimeMs),
344
+ ctime: new Date(ctimeMs),
345
+ birthtime: new Date(ctimeMs),
346
+ atimeNs: atimeMsBigInt * 1000000n,
347
+ mtimeNs: mtimeMsBigInt * 1000000n,
348
+ ctimeNs: ctimeMsBigInt * 1000000n,
349
+ birthtimeNs: ctimeMsBigInt * 1000000n
350
+ };
351
+ }
352
+ function decodeDirents(data, parentPath = "") {
443
353
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
444
354
  const count = view.getUint32(0, true);
445
355
  const decoder9 = new TextDecoder();
@@ -456,6 +366,8 @@ function decodeDirents(data) {
456
366
  const isSymlink = type === INODE_TYPE.SYMLINK;
457
367
  entries.push({
458
368
  name,
369
+ parentPath,
370
+ path: parentPath,
459
371
  isFile: () => isFile,
460
372
  isDirectory: () => isDirectory,
461
373
  isBlockDevice: () => false,
@@ -482,96 +394,6 @@ function decodeNames(data) {
482
394
  return names;
483
395
  }
484
396
 
485
- // src/methods/readdir.ts
486
- function readdirSync(syncRequest, filePath, options) {
487
- const opts = typeof options === "string" ? { } : options;
488
- const flags = opts?.withFileTypes ? 1 : 0;
489
- const buf = encodeRequest(OP.READDIR, filePath, flags);
490
- const { status, data } = syncRequest(buf);
491
- if (status !== 0) throw statusToError(status, "readdir", filePath);
492
- if (!data) return [];
493
- return opts?.withFileTypes ? decodeDirents(data) : decodeNames(data);
494
- }
495
- async function readdir(asyncRequest, filePath, options) {
496
- const opts = typeof options === "string" ? { } : options;
497
- const flags = opts?.withFileTypes ? 1 : 0;
498
- const { status, data } = await asyncRequest(OP.READDIR, filePath, flags);
499
- if (status !== 0) throw statusToError(status, "readdir", filePath);
500
- if (!data) return [];
501
- return opts?.withFileTypes ? decodeDirents(data) : decodeNames(data);
502
- }
503
-
504
- // src/methods/stat.ts
505
- function statSync(syncRequest, filePath) {
506
- const buf = encodeRequest(OP.STAT, filePath);
507
- const { status, data } = syncRequest(buf);
508
- if (status !== 0) throw statusToError(status, "stat", filePath);
509
- return decodeStats(data);
510
- }
511
- function lstatSync(syncRequest, filePath) {
512
- const buf = encodeRequest(OP.LSTAT, filePath);
513
- const { status, data } = syncRequest(buf);
514
- if (status !== 0) throw statusToError(status, "lstat", filePath);
515
- return decodeStats(data);
516
- }
517
- async function stat(asyncRequest, filePath) {
518
- const { status, data } = await asyncRequest(OP.STAT, filePath);
519
- if (status !== 0) throw statusToError(status, "stat", filePath);
520
- return decodeStats(data);
521
- }
522
- async function lstat(asyncRequest, filePath) {
523
- const { status, data } = await asyncRequest(OP.LSTAT, filePath);
524
- if (status !== 0) throw statusToError(status, "lstat", filePath);
525
- return decodeStats(data);
526
- }
527
-
528
- // src/methods/rename.ts
529
- var encoder4 = new TextEncoder();
530
- function renameSync(syncRequest, oldPath, newPath) {
531
- const buf = encodeTwoPathRequest(OP.RENAME, oldPath, newPath);
532
- const { status } = syncRequest(buf);
533
- if (status !== 0) throw statusToError(status, "rename", oldPath);
534
- }
535
- async function rename(asyncRequest, oldPath, newPath) {
536
- const path2Bytes = encoder4.encode(newPath);
537
- const payload = new Uint8Array(4 + path2Bytes.byteLength);
538
- new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
539
- payload.set(path2Bytes, 4);
540
- const { status } = await asyncRequest(OP.RENAME, oldPath, 0, payload);
541
- if (status !== 0) throw statusToError(status, "rename", oldPath);
542
- }
543
-
544
- // src/methods/copyFile.ts
545
- var encoder5 = new TextEncoder();
546
- function copyFileSync(syncRequest, src, dest, mode) {
547
- const buf = encodeTwoPathRequest(OP.COPY, src, dest, mode ?? 0);
548
- const { status } = syncRequest(buf);
549
- if (status !== 0) throw statusToError(status, "copyFile", src);
550
- }
551
- async function copyFile(asyncRequest, src, dest, mode) {
552
- const path2Bytes = encoder5.encode(dest);
553
- const payload = new Uint8Array(4 + path2Bytes.byteLength);
554
- new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
555
- payload.set(path2Bytes, 4);
556
- const { status } = await asyncRequest(OP.COPY, src, mode ?? 0, payload);
557
- if (status !== 0) throw statusToError(status, "copyFile", src);
558
- }
559
-
560
- // src/methods/truncate.ts
561
- function truncateSync(syncRequest, filePath, len = 0) {
562
- const lenBuf = new Uint8Array(4);
563
- new DataView(lenBuf.buffer).setUint32(0, len, true);
564
- const buf = encodeRequest(OP.TRUNCATE, filePath, 0, lenBuf);
565
- const { status } = syncRequest(buf);
566
- if (status !== 0) throw statusToError(status, "truncate", filePath);
567
- }
568
- async function truncate(asyncRequest, filePath, len) {
569
- const lenBuf = new Uint8Array(4);
570
- new DataView(lenBuf.buffer).setUint32(0, len ?? 0, true);
571
- const { status } = await asyncRequest(OP.TRUNCATE, filePath, 0, lenBuf);
572
- if (status !== 0) throw statusToError(status, "truncate", filePath);
573
- }
574
-
575
397
  // src/constants.ts
576
398
  var constants = {
577
399
  // File access constants
@@ -616,29 +438,677 @@ var constants = {
616
438
  S_IXOTH: 1
617
439
  };
618
440
 
619
- // src/methods/access.ts
620
- function accessSync(syncRequest, filePath, mode = constants.F_OK) {
621
- const buf = encodeRequest(OP.ACCESS, filePath, mode);
622
- const { status } = syncRequest(buf);
623
- if (status !== 0) throw statusToError(status, "access", filePath);
441
+ // src/methods/open.ts
442
+ var encoder2 = new TextEncoder();
443
+ var decoder2 = new TextDecoder();
444
+ function parseFlags(flags) {
445
+ switch (flags) {
446
+ case "r":
447
+ return constants.O_RDONLY;
448
+ case "r+":
449
+ return constants.O_RDWR;
450
+ case "w":
451
+ return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC;
452
+ case "w+":
453
+ return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC;
454
+ case "a":
455
+ return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND;
456
+ case "a+":
457
+ return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND;
458
+ case "wx":
459
+ return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
460
+ case "wx+":
461
+ return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
462
+ case "ax":
463
+ return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
464
+ case "ax+":
465
+ return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
466
+ default:
467
+ return constants.O_RDONLY;
468
+ }
624
469
  }
625
- async function access(asyncRequest, filePath, mode) {
626
- const { status } = await asyncRequest(OP.ACCESS, filePath, mode ?? 0);
627
- if (status !== 0) throw statusToError(status, "access", filePath);
470
+ function openSync(syncRequest, filePath, flags = "r", _mode) {
471
+ const numFlags = typeof flags === "string" ? parseFlags(flags) : flags;
472
+ const buf = encodeRequest(OP.OPEN, filePath, numFlags);
473
+ const { status, data } = syncRequest(buf);
474
+ if (status !== 0) throw statusToError(status, "open", filePath);
475
+ return new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true);
476
+ }
477
+ function closeSync(syncRequest, fd) {
478
+ const fdBuf = new Uint8Array(4);
479
+ new DataView(fdBuf.buffer).setUint32(0, fd, true);
480
+ const buf = encodeRequest(OP.CLOSE, "", 0, fdBuf);
481
+ const { status } = syncRequest(buf);
482
+ if (status !== 0) throw statusToError(status, "close", String(fd));
483
+ }
484
+ function readSync(syncRequest, fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
485
+ const fdBuf = new Uint8Array(16);
486
+ const dv = new DataView(fdBuf.buffer);
487
+ dv.setUint32(0, fd, true);
488
+ dv.setUint32(4, length, true);
489
+ dv.setFloat64(8, position ?? -1, true);
490
+ const buf = encodeRequest(OP.FREAD, "", 0, fdBuf);
491
+ const { status, data } = syncRequest(buf);
492
+ if (status !== 0) throw statusToError(status, "read", String(fd));
493
+ if (data) {
494
+ buffer.set(data.subarray(0, Math.min(data.byteLength, length)), offset);
495
+ return data.byteLength;
496
+ }
497
+ return 0;
498
+ }
499
+ function writeSyncFd(syncRequest, fd, bufferOrString, offsetOrPosition, lengthOrEncoding, position) {
500
+ let writeData;
501
+ let pos;
502
+ if (typeof bufferOrString === "string") {
503
+ writeData = encoder2.encode(bufferOrString);
504
+ pos = offsetOrPosition != null ? offsetOrPosition : null;
505
+ } else {
506
+ const offset = offsetOrPosition ?? 0;
507
+ const length = lengthOrEncoding != null ? lengthOrEncoding : bufferOrString.byteLength;
508
+ pos = position ?? null;
509
+ writeData = bufferOrString.subarray(offset, offset + length);
510
+ }
511
+ const fdBuf = new Uint8Array(12 + writeData.byteLength);
512
+ const dv = new DataView(fdBuf.buffer);
513
+ dv.setUint32(0, fd, true);
514
+ dv.setFloat64(4, pos ?? -1, true);
515
+ fdBuf.set(writeData, 12);
516
+ const buf = encodeRequest(OP.FWRITE, "", 0, fdBuf);
517
+ const { status, data } = syncRequest(buf);
518
+ if (status !== 0) throw statusToError(status, "write", String(fd));
519
+ return data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
520
+ }
521
+ function fstatSync(syncRequest, fd) {
522
+ const fdBuf = new Uint8Array(4);
523
+ new DataView(fdBuf.buffer).setUint32(0, fd, true);
524
+ const buf = encodeRequest(OP.FSTAT, "", 0, fdBuf);
525
+ const { status, data } = syncRequest(buf);
526
+ if (status !== 0) throw statusToError(status, "fstat", String(fd));
527
+ return decodeStats(data);
528
+ }
529
+ function ftruncateSync(syncRequest, fd, len = 0) {
530
+ const fdBuf = new Uint8Array(12);
531
+ const dv = new DataView(fdBuf.buffer);
532
+ dv.setUint32(0, fd, true);
533
+ dv.setFloat64(4, len, true);
534
+ const buf = encodeRequest(OP.FTRUNCATE, "", 0, fdBuf);
535
+ const { status } = syncRequest(buf);
536
+ if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
537
+ }
538
+ function fdatasyncSync(syncRequest, fd) {
539
+ const buf = encodeRequest(OP.FSYNC, "");
540
+ const { status } = syncRequest(buf);
541
+ if (status !== 0) throw statusToError(status, "fdatasync", String(fd));
542
+ }
543
+ async function open(asyncRequest, filePath, flags, _mode) {
544
+ const numFlags = typeof flags === "string" ? parseFlags(flags ?? "r") : flags ?? 0;
545
+ const { status, data } = await asyncRequest(OP.OPEN, filePath, numFlags);
546
+ if (status !== 0) throw statusToError(status, "open", filePath);
547
+ const fd = new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true);
548
+ return createFileHandle(fd, asyncRequest);
549
+ }
550
+ function createFileHandle(fd, asyncRequest) {
551
+ return {
552
+ fd,
553
+ async read(buffer, offset = 0, length = buffer.byteLength, position = null) {
554
+ const { status, data } = await asyncRequest(OP.FREAD, "", 0, null, void 0, { fd, length, position: position ?? -1 });
555
+ if (status !== 0) throw statusToError(status, "read", String(fd));
556
+ const bytesRead = data ? data.byteLength : 0;
557
+ if (data) buffer.set(data.subarray(0, Math.min(bytesRead, length)), offset);
558
+ return { bytesRead, buffer };
559
+ },
560
+ async write(bufferOrString, offsetOrPosition, lengthOrEncoding, position) {
561
+ let writeData;
562
+ let pos;
563
+ let resultBuffer;
564
+ if (typeof bufferOrString === "string") {
565
+ resultBuffer = encoder2.encode(bufferOrString);
566
+ writeData = resultBuffer;
567
+ pos = offsetOrPosition != null ? offsetOrPosition : -1;
568
+ } else {
569
+ resultBuffer = bufferOrString;
570
+ const offset = offsetOrPosition ?? 0;
571
+ const length = lengthOrEncoding != null ? lengthOrEncoding : bufferOrString.byteLength;
572
+ pos = position != null ? position : -1;
573
+ writeData = bufferOrString.subarray(offset, offset + length);
574
+ }
575
+ const { status, data } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: writeData, position: pos });
576
+ if (status !== 0) throw statusToError(status, "write", String(fd));
577
+ const bytesWritten = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
578
+ return { bytesWritten, buffer: resultBuffer };
579
+ },
580
+ async readFile(options) {
581
+ const encoding = typeof options === "string" ? options : options?.encoding;
582
+ const { status, data } = await asyncRequest(OP.FREAD, "", 0, null, void 0, { fd, length: Number.MAX_SAFE_INTEGER, position: 0 });
583
+ if (status !== 0) throw statusToError(status, "read", String(fd));
584
+ const result = data ?? new Uint8Array(0);
585
+ if (encoding) return decoder2.decode(result);
586
+ return result;
587
+ },
588
+ async writeFile(data, _options) {
589
+ const encoded = typeof data === "string" ? encoder2.encode(data) : data;
590
+ const { status } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: encoded, position: 0 });
591
+ if (status !== 0) throw statusToError(status, "write", String(fd));
592
+ },
593
+ async truncate(len = 0) {
594
+ const { status } = await asyncRequest(OP.FTRUNCATE, "", 0, null, void 0, { fd, length: len });
595
+ if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
596
+ },
597
+ async stat() {
598
+ const { status, data } = await asyncRequest(OP.FSTAT, "", 0, null, void 0, { fd });
599
+ if (status !== 0) throw statusToError(status, "fstat", String(fd));
600
+ return decodeStats(data);
601
+ },
602
+ async sync() {
603
+ await asyncRequest(OP.FSYNC, "");
604
+ },
605
+ async datasync() {
606
+ await asyncRequest(OP.FSYNC, "");
607
+ },
608
+ async close() {
609
+ const { status } = await asyncRequest(OP.CLOSE, "", 0, null, void 0, { fd });
610
+ if (status !== 0) throw statusToError(status, "close", String(fd));
611
+ }
612
+ };
628
613
  }
629
614
 
630
- // src/methods/realpath.ts
615
+ // src/encoding.ts
616
+ function decodeBuffer(data, encoding) {
617
+ switch (encoding) {
618
+ case "utf8":
619
+ case "utf-8":
620
+ return new TextDecoder("utf-8").decode(data);
621
+ case "latin1":
622
+ case "binary": {
623
+ let result = "";
624
+ for (let i = 0; i < data.length; i++) {
625
+ result += String.fromCharCode(data[i]);
626
+ }
627
+ return result;
628
+ }
629
+ case "ascii": {
630
+ let result = "";
631
+ for (let i = 0; i < data.length; i++) {
632
+ result += String.fromCharCode(data[i] & 127);
633
+ }
634
+ return result;
635
+ }
636
+ case "base64": {
637
+ let binary = "";
638
+ for (let i = 0; i < data.length; i++) {
639
+ binary += String.fromCharCode(data[i]);
640
+ }
641
+ return btoa(binary);
642
+ }
643
+ case "hex": {
644
+ let hex = "";
645
+ for (let i = 0; i < data.length; i++) {
646
+ hex += data[i].toString(16).padStart(2, "0");
647
+ }
648
+ return hex;
649
+ }
650
+ case "ucs2":
651
+ case "ucs-2":
652
+ case "utf16le":
653
+ case "utf-16le":
654
+ return new TextDecoder("utf-16le").decode(data);
655
+ default:
656
+ return new TextDecoder("utf-8").decode(data);
657
+ }
658
+ }
659
+ function encodeString(str, encoding) {
660
+ switch (encoding) {
661
+ case "utf8":
662
+ case "utf-8":
663
+ return new TextEncoder().encode(str);
664
+ case "latin1":
665
+ case "binary": {
666
+ const buf = new Uint8Array(str.length);
667
+ for (let i = 0; i < str.length; i++) {
668
+ buf[i] = str.charCodeAt(i) & 255;
669
+ }
670
+ return buf;
671
+ }
672
+ case "ascii": {
673
+ const buf = new Uint8Array(str.length);
674
+ for (let i = 0; i < str.length; i++) {
675
+ buf[i] = str.charCodeAt(i) & 127;
676
+ }
677
+ return buf;
678
+ }
679
+ case "base64": {
680
+ const binary = atob(str);
681
+ const buf = new Uint8Array(binary.length);
682
+ for (let i = 0; i < binary.length; i++) {
683
+ buf[i] = binary.charCodeAt(i);
684
+ }
685
+ return buf;
686
+ }
687
+ case "hex": {
688
+ const len = str.length >>> 1;
689
+ const buf = new Uint8Array(len);
690
+ for (let i = 0; i < len; i++) {
691
+ buf[i] = parseInt(str.slice(i * 2, i * 2 + 2), 16);
692
+ }
693
+ return buf;
694
+ }
695
+ case "ucs2":
696
+ case "ucs-2":
697
+ case "utf16le":
698
+ case "utf-16le": {
699
+ const buf = new Uint8Array(str.length * 2);
700
+ for (let i = 0; i < str.length; i++) {
701
+ const code = str.charCodeAt(i);
702
+ buf[i * 2] = code & 255;
703
+ buf[i * 2 + 1] = code >>> 8 & 255;
704
+ }
705
+ return buf;
706
+ }
707
+ default:
708
+ return new TextEncoder().encode(str);
709
+ }
710
+ }
711
+
712
+ // src/methods/readFile.ts
713
+ new TextDecoder();
714
+ function readFileSync(syncRequest, filePath, options) {
715
+ const encoding = typeof options === "string" ? options : options?.encoding;
716
+ const flag = typeof options === "string" ? void 0 : options?.flag;
717
+ if (!flag || flag === "r") {
718
+ const buf = encodeRequest(OP.READ, filePath);
719
+ const { status, data } = syncRequest(buf);
720
+ if (status !== 0) throw statusToError(status, "read", filePath);
721
+ const result = data ?? new Uint8Array(0);
722
+ if (encoding) return decodeBuffer(result, encoding);
723
+ return result;
724
+ }
725
+ const fd = openSync(syncRequest, filePath, flag);
726
+ try {
727
+ const chunks = [];
728
+ let totalRead = 0;
729
+ const chunkSize = 64 * 1024;
730
+ while (true) {
731
+ const chunk = new Uint8Array(chunkSize);
732
+ const bytesRead = readSync(syncRequest, fd, chunk, 0, chunkSize, totalRead);
733
+ if (bytesRead === 0) break;
734
+ chunks.push(chunk.subarray(0, bytesRead));
735
+ totalRead += bytesRead;
736
+ if (bytesRead < chunkSize) break;
737
+ }
738
+ let result;
739
+ if (chunks.length === 0) {
740
+ result = new Uint8Array(0);
741
+ } else if (chunks.length === 1) {
742
+ result = chunks[0];
743
+ } else {
744
+ result = new Uint8Array(totalRead);
745
+ let offset = 0;
746
+ for (const chunk of chunks) {
747
+ result.set(chunk, offset);
748
+ offset += chunk.byteLength;
749
+ }
750
+ }
751
+ if (encoding) return decodeBuffer(result, encoding);
752
+ return result;
753
+ } finally {
754
+ closeSync(syncRequest, fd);
755
+ }
756
+ }
757
+ async function readFile(asyncRequest, filePath, options) {
758
+ const encoding = typeof options === "string" ? options : options?.encoding;
759
+ const flag = typeof options === "string" ? void 0 : options?.flag;
760
+ if (!flag || flag === "r") {
761
+ const { status, data } = await asyncRequest(OP.READ, filePath);
762
+ if (status !== 0) throw statusToError(status, "read", filePath);
763
+ const result = data ?? new Uint8Array(0);
764
+ if (encoding) return decodeBuffer(result, encoding);
765
+ return result;
766
+ }
767
+ const handle = await open(asyncRequest, filePath, flag);
768
+ try {
769
+ const result = await handle.readFile(encoding ? encoding : void 0);
770
+ return result;
771
+ } finally {
772
+ await handle.close();
773
+ }
774
+ }
775
+
776
+ // src/methods/writeFile.ts
777
+ var encoder3 = new TextEncoder();
778
+ function writeFileSync(syncRequest, filePath, data, options) {
779
+ const opts = typeof options === "string" ? { encoding: options } : options;
780
+ const encoded = typeof data === "string" ? opts?.encoding ? encodeString(data, opts.encoding) : encoder3.encode(data) : data;
781
+ const flag = opts?.flag;
782
+ if (!flag || flag === "w") {
783
+ const flags = opts?.flush === true ? 1 : 0;
784
+ const buf = encodeRequest(OP.WRITE, filePath, flags, encoded);
785
+ const { status } = syncRequest(buf);
786
+ if (status !== 0) throw statusToError(status, "write", filePath);
787
+ return;
788
+ }
789
+ const fd = openSync(syncRequest, filePath, flag);
790
+ try {
791
+ writeSyncFd(syncRequest, fd, encoded, 0, encoded.byteLength, 0);
792
+ } finally {
793
+ closeSync(syncRequest, fd);
794
+ }
795
+ }
796
+ async function writeFile(asyncRequest, filePath, data, options) {
797
+ const opts = typeof options === "string" ? { encoding: options } : options;
798
+ const encoded = typeof data === "string" ? opts?.encoding ? encodeString(data, opts.encoding) : encoder3.encode(data) : data;
799
+ const flag = opts?.flag;
800
+ if (!flag || flag === "w") {
801
+ const flags = opts?.flush === true ? 1 : 0;
802
+ const { status } = await asyncRequest(OP.WRITE, filePath, flags, encoded);
803
+ if (status !== 0) throw statusToError(status, "write", filePath);
804
+ return;
805
+ }
806
+ const handle = await open(asyncRequest, filePath, flag);
807
+ try {
808
+ await handle.writeFile(encoded);
809
+ } finally {
810
+ await handle.close();
811
+ }
812
+ }
813
+
814
+ // src/methods/appendFile.ts
815
+ var encoder4 = new TextEncoder();
816
+ function appendFileSync(syncRequest, filePath, data, options) {
817
+ const encoded = typeof data === "string" ? encoder4.encode(data) : data;
818
+ const buf = encodeRequest(OP.APPEND, filePath, 0, encoded);
819
+ const { status } = syncRequest(buf);
820
+ if (status !== 0) throw statusToError(status, "appendFile", filePath);
821
+ }
822
+ async function appendFile(asyncRequest, filePath, data, options) {
823
+ const encoded = typeof data === "string" ? encoder4.encode(data) : data;
824
+ const { status } = await asyncRequest(OP.APPEND, filePath, 0, encoded);
825
+ if (status !== 0) throw statusToError(status, "appendFile", filePath);
826
+ }
827
+
828
+ // src/methods/exists.ts
829
+ function existsSync(syncRequest, filePath) {
830
+ const buf = encodeRequest(OP.EXISTS, filePath);
831
+ const { data } = syncRequest(buf);
832
+ return data ? data[0] === 1 : false;
833
+ }
834
+ async function exists(asyncRequest, filePath) {
835
+ const { data } = await asyncRequest(OP.EXISTS, filePath);
836
+ return data ? data[0] === 1 : false;
837
+ }
838
+
839
+ // src/methods/mkdir.ts
631
840
  var decoder4 = new TextDecoder();
841
+ function mkdirSync(syncRequest, filePath, options) {
842
+ const opts = typeof options === "number" ? { } : options;
843
+ const flags = opts?.recursive ? 1 : 0;
844
+ const buf = encodeRequest(OP.MKDIR, filePath, flags);
845
+ const { status, data } = syncRequest(buf);
846
+ if (status !== 0) throw statusToError(status, "mkdir", filePath);
847
+ return data ? decoder4.decode(data) : void 0;
848
+ }
849
+ async function mkdir(asyncRequest, filePath, options) {
850
+ const opts = typeof options === "number" ? { } : options;
851
+ const flags = opts?.recursive ? 1 : 0;
852
+ const { status, data } = await asyncRequest(OP.MKDIR, filePath, flags);
853
+ if (status !== 0) throw statusToError(status, "mkdir", filePath);
854
+ return data ? decoder4.decode(data) : void 0;
855
+ }
856
+
857
+ // src/methods/rmdir.ts
858
+ function rmdirSync(syncRequest, filePath, options) {
859
+ const flags = options?.recursive ? 1 : 0;
860
+ const buf = encodeRequest(OP.RMDIR, filePath, flags);
861
+ const { status } = syncRequest(buf);
862
+ if (status !== 0) throw statusToError(status, "rmdir", filePath);
863
+ }
864
+ async function rmdir(asyncRequest, filePath, options) {
865
+ const flags = options?.recursive ? 1 : 0;
866
+ const { status } = await asyncRequest(OP.RMDIR, filePath, flags);
867
+ if (status !== 0) throw statusToError(status, "rmdir", filePath);
868
+ }
869
+
870
+ // src/methods/rm.ts
871
+ function rmSync(syncRequest, filePath, options) {
872
+ const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
873
+ const buf = encodeRequest(OP.UNLINK, filePath, flags);
874
+ const { status } = syncRequest(buf);
875
+ if (status === 3) {
876
+ const rmdirBuf = encodeRequest(OP.RMDIR, filePath, flags);
877
+ const rmdirResult = syncRequest(rmdirBuf);
878
+ if (rmdirResult.status !== 0) {
879
+ if (options?.force && rmdirResult.status === 1) return;
880
+ throw statusToError(rmdirResult.status, "rm", filePath);
881
+ }
882
+ return;
883
+ }
884
+ if (status !== 0) {
885
+ if (options?.force && status === 1) return;
886
+ throw statusToError(status, "rm", filePath);
887
+ }
888
+ }
889
+ async function rm(asyncRequest, filePath, options) {
890
+ const flags = (options?.recursive ? 1 : 0) | (options?.force ? 2 : 0);
891
+ const { status } = await asyncRequest(OP.UNLINK, filePath, flags);
892
+ if (status === 3) {
893
+ const { status: s2 } = await asyncRequest(OP.RMDIR, filePath, flags);
894
+ if (s2 !== 0) {
895
+ if (options?.force && s2 === 1) return;
896
+ throw statusToError(s2, "rm", filePath);
897
+ }
898
+ return;
899
+ }
900
+ if (status !== 0) {
901
+ if (options?.force && status === 1) return;
902
+ throw statusToError(status, "rm", filePath);
903
+ }
904
+ }
905
+
906
+ // src/methods/unlink.ts
907
+ function unlinkSync(syncRequest, filePath) {
908
+ const buf = encodeRequest(OP.UNLINK, filePath);
909
+ const { status } = syncRequest(buf);
910
+ if (status !== 0) throw statusToError(status, "unlink", filePath);
911
+ }
912
+ async function unlink(asyncRequest, filePath) {
913
+ const { status } = await asyncRequest(OP.UNLINK, filePath);
914
+ if (status !== 0) throw statusToError(status, "unlink", filePath);
915
+ }
916
+
917
+ // src/methods/readdir.ts
918
+ function readdirBaseSync(syncRequest, filePath, withFileTypes) {
919
+ const flags = withFileTypes ? 1 : 0;
920
+ const buf = encodeRequest(OP.READDIR, filePath, flags);
921
+ const { status, data } = syncRequest(buf);
922
+ if (status !== 0) throw statusToError(status, "readdir", filePath);
923
+ if (!data) return [];
924
+ return withFileTypes ? decodeDirents(data, filePath) : decodeNames(data);
925
+ }
926
+ async function readdirBaseAsync(asyncRequest, filePath, withFileTypes) {
927
+ const flags = withFileTypes ? 1 : 0;
928
+ const { status, data } = await asyncRequest(OP.READDIR, filePath, flags);
929
+ if (status !== 0) throw statusToError(status, "readdir", filePath);
930
+ if (!data) return [];
931
+ return withFileTypes ? decodeDirents(data, filePath) : decodeNames(data);
932
+ }
933
+ function readdirRecursiveSync(syncRequest, basePath, prefix, withFileTypes) {
934
+ const entries = readdirBaseSync(syncRequest, basePath, true);
935
+ const results = [];
936
+ for (const entry of entries) {
937
+ const relativePath = prefix ? prefix + "/" + entry.name : entry.name;
938
+ if (withFileTypes) {
939
+ results.push({
940
+ name: relativePath,
941
+ isFile: entry.isFile,
942
+ isDirectory: entry.isDirectory,
943
+ isBlockDevice: entry.isBlockDevice,
944
+ isCharacterDevice: entry.isCharacterDevice,
945
+ isSymbolicLink: entry.isSymbolicLink,
946
+ isFIFO: entry.isFIFO,
947
+ isSocket: entry.isSocket
948
+ });
949
+ } else {
950
+ results.push(relativePath);
951
+ }
952
+ if (entry.isDirectory()) {
953
+ const childPath = basePath + "/" + entry.name;
954
+ results.push(
955
+ ...readdirRecursiveSync(syncRequest, childPath, relativePath, withFileTypes)
956
+ );
957
+ }
958
+ }
959
+ return results;
960
+ }
961
+ async function readdirRecursiveAsync(asyncRequest, basePath, prefix, withFileTypes) {
962
+ const entries = await readdirBaseAsync(asyncRequest, basePath, true);
963
+ const results = [];
964
+ for (const entry of entries) {
965
+ const relativePath = prefix ? prefix + "/" + entry.name : entry.name;
966
+ if (withFileTypes) {
967
+ results.push({
968
+ name: relativePath,
969
+ isFile: entry.isFile,
970
+ isDirectory: entry.isDirectory,
971
+ isBlockDevice: entry.isBlockDevice,
972
+ isCharacterDevice: entry.isCharacterDevice,
973
+ isSymbolicLink: entry.isSymbolicLink,
974
+ isFIFO: entry.isFIFO,
975
+ isSocket: entry.isSocket
976
+ });
977
+ } else {
978
+ results.push(relativePath);
979
+ }
980
+ if (entry.isDirectory()) {
981
+ const childPath = basePath + "/" + entry.name;
982
+ const children = await readdirRecursiveAsync(
983
+ asyncRequest,
984
+ childPath,
985
+ relativePath,
986
+ withFileTypes
987
+ );
988
+ results.push(...children);
989
+ }
990
+ }
991
+ return results;
992
+ }
993
+ function readdirSync(syncRequest, filePath, options) {
994
+ const opts = typeof options === "string" ? { } : options;
995
+ if (opts?.recursive) {
996
+ return readdirRecursiveSync(
997
+ syncRequest,
998
+ filePath,
999
+ "",
1000
+ !!opts?.withFileTypes
1001
+ );
1002
+ }
1003
+ return readdirBaseSync(syncRequest, filePath, !!opts?.withFileTypes);
1004
+ }
1005
+ async function readdir(asyncRequest, filePath, options) {
1006
+ const opts = typeof options === "string" ? { } : options;
1007
+ if (opts?.recursive) {
1008
+ return readdirRecursiveAsync(
1009
+ asyncRequest,
1010
+ filePath,
1011
+ "",
1012
+ !!opts?.withFileTypes
1013
+ );
1014
+ }
1015
+ return readdirBaseAsync(asyncRequest, filePath, !!opts?.withFileTypes);
1016
+ }
1017
+
1018
+ // src/methods/stat.ts
1019
+ function statSync(syncRequest, filePath, options) {
1020
+ const buf = encodeRequest(OP.STAT, filePath);
1021
+ const { status, data } = syncRequest(buf);
1022
+ if (status !== 0) throw statusToError(status, "stat", filePath);
1023
+ return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
1024
+ }
1025
+ function lstatSync(syncRequest, filePath, options) {
1026
+ const buf = encodeRequest(OP.LSTAT, filePath);
1027
+ const { status, data } = syncRequest(buf);
1028
+ if (status !== 0) throw statusToError(status, "lstat", filePath);
1029
+ return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
1030
+ }
1031
+ async function stat(asyncRequest, filePath, options) {
1032
+ const { status, data } = await asyncRequest(OP.STAT, filePath);
1033
+ if (status !== 0) throw statusToError(status, "stat", filePath);
1034
+ return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
1035
+ }
1036
+ async function lstat(asyncRequest, filePath, options) {
1037
+ const { status, data } = await asyncRequest(OP.LSTAT, filePath);
1038
+ if (status !== 0) throw statusToError(status, "lstat", filePath);
1039
+ return options?.bigint ? decodeStatsBigInt(data) : decodeStats(data);
1040
+ }
1041
+
1042
+ // src/methods/rename.ts
1043
+ var encoder5 = new TextEncoder();
1044
+ function renameSync(syncRequest, oldPath, newPath) {
1045
+ const buf = encodeTwoPathRequest(OP.RENAME, oldPath, newPath);
1046
+ const { status } = syncRequest(buf);
1047
+ if (status !== 0) throw statusToError(status, "rename", oldPath);
1048
+ }
1049
+ async function rename(asyncRequest, oldPath, newPath) {
1050
+ const path2Bytes = encoder5.encode(newPath);
1051
+ const payload = new Uint8Array(4 + path2Bytes.byteLength);
1052
+ new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
1053
+ payload.set(path2Bytes, 4);
1054
+ const { status } = await asyncRequest(OP.RENAME, oldPath, 0, payload);
1055
+ if (status !== 0) throw statusToError(status, "rename", oldPath);
1056
+ }
1057
+
1058
+ // src/methods/copyFile.ts
1059
+ var encoder6 = new TextEncoder();
1060
+ function copyFileSync(syncRequest, src, dest, mode) {
1061
+ const buf = encodeTwoPathRequest(OP.COPY, src, dest, mode ?? 0);
1062
+ const { status } = syncRequest(buf);
1063
+ if (status !== 0) throw statusToError(status, "copyFile", src);
1064
+ }
1065
+ async function copyFile(asyncRequest, src, dest, mode) {
1066
+ const path2Bytes = encoder6.encode(dest);
1067
+ const payload = new Uint8Array(4 + path2Bytes.byteLength);
1068
+ new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
1069
+ payload.set(path2Bytes, 4);
1070
+ const { status } = await asyncRequest(OP.COPY, src, mode ?? 0, payload);
1071
+ if (status !== 0) throw statusToError(status, "copyFile", src);
1072
+ }
1073
+
1074
+ // src/methods/truncate.ts
1075
+ function truncateSync(syncRequest, filePath, len = 0) {
1076
+ const lenBuf = new Uint8Array(8);
1077
+ new DataView(lenBuf.buffer).setFloat64(0, len, true);
1078
+ const buf = encodeRequest(OP.TRUNCATE, filePath, 0, lenBuf);
1079
+ const { status } = syncRequest(buf);
1080
+ if (status !== 0) throw statusToError(status, "truncate", filePath);
1081
+ }
1082
+ async function truncate(asyncRequest, filePath, len) {
1083
+ const lenBuf = new Uint8Array(8);
1084
+ new DataView(lenBuf.buffer).setFloat64(0, len ?? 0, true);
1085
+ const { status } = await asyncRequest(OP.TRUNCATE, filePath, 0, lenBuf);
1086
+ if (status !== 0) throw statusToError(status, "truncate", filePath);
1087
+ }
1088
+
1089
+ // src/methods/access.ts
1090
+ function accessSync(syncRequest, filePath, mode = constants.F_OK) {
1091
+ const buf = encodeRequest(OP.ACCESS, filePath, mode);
1092
+ const { status } = syncRequest(buf);
1093
+ if (status !== 0) throw statusToError(status, "access", filePath);
1094
+ }
1095
+ async function access(asyncRequest, filePath, mode = constants.F_OK) {
1096
+ const { status } = await asyncRequest(OP.ACCESS, filePath, mode);
1097
+ if (status !== 0) throw statusToError(status, "access", filePath);
1098
+ }
1099
+
1100
+ // src/methods/realpath.ts
1101
+ var decoder5 = new TextDecoder();
632
1102
  function realpathSync(syncRequest, filePath) {
633
1103
  const buf = encodeRequest(OP.REALPATH, filePath);
634
1104
  const { status, data } = syncRequest(buf);
635
1105
  if (status !== 0) throw statusToError(status, "realpath", filePath);
636
- return decoder4.decode(data);
1106
+ return decoder5.decode(data);
637
1107
  }
638
1108
  async function realpath(asyncRequest, filePath) {
639
1109
  const { status, data } = await asyncRequest(OP.REALPATH, filePath);
640
1110
  if (status !== 0) throw statusToError(status, "realpath", filePath);
641
- return decoder4.decode(data);
1111
+ return decoder5.decode(data);
642
1112
  }
643
1113
 
644
1114
  // src/methods/chmod.ts
@@ -693,212 +1163,65 @@ async function utimes(asyncRequest, filePath, atime, mtime) {
693
1163
  const { status } = await asyncRequest(OP.UTIMES, filePath, 0, buf);
694
1164
  if (status !== 0) throw statusToError(status, "utimes", filePath);
695
1165
  }
696
-
697
- // src/methods/symlink.ts
698
- var encoder6 = new TextEncoder();
699
- var decoder5 = new TextDecoder();
700
- function symlinkSync(syncRequest, target, linkPath) {
701
- const targetBytes = encoder6.encode(target);
702
- const buf = encodeRequest(OP.SYMLINK, linkPath, 0, targetBytes);
703
- const { status } = syncRequest(buf);
704
- if (status !== 0) throw statusToError(status, "symlink", linkPath);
705
- }
706
- function readlinkSync(syncRequest, filePath) {
707
- const buf = encodeRequest(OP.READLINK, filePath);
708
- const { status, data } = syncRequest(buf);
709
- if (status !== 0) throw statusToError(status, "readlink", filePath);
710
- return decoder5.decode(data);
711
- }
712
- async function symlink(asyncRequest, target, linkPath) {
713
- const targetBytes = encoder6.encode(target);
714
- const { status } = await asyncRequest(OP.SYMLINK, linkPath, 0, targetBytes);
715
- if (status !== 0) throw statusToError(status, "symlink", linkPath);
716
- }
717
- async function readlink(asyncRequest, filePath) {
718
- const { status, data } = await asyncRequest(OP.READLINK, filePath);
719
- if (status !== 0) throw statusToError(status, "readlink", filePath);
720
- return decoder5.decode(data);
721
- }
722
-
723
- // src/methods/link.ts
724
- var encoder7 = new TextEncoder();
725
- function linkSync(syncRequest, existingPath, newPath) {
726
- const buf = encodeTwoPathRequest(OP.LINK, existingPath, newPath);
727
- const { status } = syncRequest(buf);
728
- if (status !== 0) throw statusToError(status, "link", existingPath);
729
- }
730
- async function link(asyncRequest, existingPath, newPath) {
731
- const path2Bytes = encoder7.encode(newPath);
732
- const payload = new Uint8Array(4 + path2Bytes.byteLength);
733
- new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
734
- payload.set(path2Bytes, 4);
735
- const { status } = await asyncRequest(OP.LINK, existingPath, 0, payload);
736
- if (status !== 0) throw statusToError(status, "link", existingPath);
737
- }
738
-
739
- // src/methods/mkdtemp.ts
740
- var decoder6 = new TextDecoder();
741
- function mkdtempSync(syncRequest, prefix) {
742
- const buf = encodeRequest(OP.MKDTEMP, prefix);
743
- const { status, data } = syncRequest(buf);
744
- if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
745
- return decoder6.decode(data);
746
- }
747
- async function mkdtemp(asyncRequest, prefix) {
748
- const { status, data } = await asyncRequest(OP.MKDTEMP, prefix);
749
- if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
750
- return decoder6.decode(data);
751
- }
752
-
753
- // src/methods/open.ts
754
- var encoder8 = new TextEncoder();
755
- var decoder7 = new TextDecoder();
756
- function parseFlags(flags) {
757
- switch (flags) {
758
- case "r":
759
- return constants.O_RDONLY;
760
- case "r+":
761
- return constants.O_RDWR;
762
- case "w":
763
- return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC;
764
- case "w+":
765
- return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC;
766
- case "a":
767
- return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND;
768
- case "a+":
769
- return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND;
770
- case "wx":
771
- return constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
772
- case "wx+":
773
- return constants.O_RDWR | constants.O_CREAT | constants.O_TRUNC | constants.O_EXCL;
774
- case "ax":
775
- return constants.O_WRONLY | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
776
- case "ax+":
777
- return constants.O_RDWR | constants.O_CREAT | constants.O_APPEND | constants.O_EXCL;
778
- default:
779
- return constants.O_RDONLY;
780
- }
781
- }
782
- function openSync(syncRequest, filePath, flags = "r", _mode) {
783
- const numFlags = typeof flags === "string" ? parseFlags(flags) : flags;
784
- const buf = encodeRequest(OP.OPEN, filePath, numFlags);
785
- const { status, data } = syncRequest(buf);
786
- if (status !== 0) throw statusToError(status, "open", filePath);
787
- return new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true);
788
- }
789
- function closeSync(syncRequest, fd) {
790
- const fdBuf = new Uint8Array(4);
791
- new DataView(fdBuf.buffer).setUint32(0, fd, true);
792
- const buf = encodeRequest(OP.CLOSE, "", 0, fdBuf);
793
- const { status } = syncRequest(buf);
794
- if (status !== 0) throw statusToError(status, "close", String(fd));
795
- }
796
- function readSync(syncRequest, fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
797
- const fdBuf = new Uint8Array(12);
798
- const dv = new DataView(fdBuf.buffer);
799
- dv.setUint32(0, fd, true);
800
- dv.setUint32(4, length, true);
801
- dv.setInt32(8, position ?? -1, true);
802
- const buf = encodeRequest(OP.FREAD, "", 0, fdBuf);
803
- const { status, data } = syncRequest(buf);
804
- if (status !== 0) throw statusToError(status, "read", String(fd));
805
- if (data) {
806
- buffer.set(data.subarray(0, Math.min(data.byteLength, length)), offset);
807
- return data.byteLength;
808
- }
809
- return 0;
810
- }
811
- function writeSyncFd(syncRequest, fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
812
- const writeData = buffer.subarray(offset, offset + length);
813
- const fdBuf = new Uint8Array(8 + writeData.byteLength);
814
- const dv = new DataView(fdBuf.buffer);
815
- dv.setUint32(0, fd, true);
816
- dv.setInt32(4, position ?? -1, true);
817
- fdBuf.set(writeData, 8);
818
- const buf = encodeRequest(OP.FWRITE, "", 0, fdBuf);
819
- const { status, data } = syncRequest(buf);
820
- if (status !== 0) throw statusToError(status, "write", String(fd));
821
- return data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
1166
+
1167
+ // src/methods/symlink.ts
1168
+ var encoder7 = new TextEncoder();
1169
+ var decoder6 = new TextDecoder();
1170
+ function symlinkSync(syncRequest, target, linkPath, type) {
1171
+ const targetBytes = encoder7.encode(target);
1172
+ const buf = encodeRequest(OP.SYMLINK, linkPath, 0, targetBytes);
1173
+ const { status } = syncRequest(buf);
1174
+ if (status !== 0) throw statusToError(status, "symlink", linkPath);
822
1175
  }
823
- function fstatSync(syncRequest, fd) {
824
- const fdBuf = new Uint8Array(4);
825
- new DataView(fdBuf.buffer).setUint32(0, fd, true);
826
- const buf = encodeRequest(OP.FSTAT, "", 0, fdBuf);
1176
+ function readlinkSync(syncRequest, filePath, options) {
1177
+ const buf = encodeRequest(OP.READLINK, filePath);
827
1178
  const { status, data } = syncRequest(buf);
828
- if (status !== 0) throw statusToError(status, "fstat", String(fd));
829
- return decodeStats(data);
1179
+ if (status !== 0) throw statusToError(status, "readlink", filePath);
1180
+ const encoding = typeof options === "string" ? options : options?.encoding;
1181
+ if (encoding === "buffer") return new Uint8Array(data);
1182
+ return decoder6.decode(data);
830
1183
  }
831
- function ftruncateSync(syncRequest, fd, len = 0) {
832
- const fdBuf = new Uint8Array(8);
833
- const dv = new DataView(fdBuf.buffer);
834
- dv.setUint32(0, fd, true);
835
- dv.setUint32(4, len, true);
836
- const buf = encodeRequest(OP.FTRUNCATE, "", 0, fdBuf);
837
- const { status } = syncRequest(buf);
838
- if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
1184
+ async function symlink(asyncRequest, target, linkPath, type) {
1185
+ const targetBytes = encoder7.encode(target);
1186
+ const { status } = await asyncRequest(OP.SYMLINK, linkPath, 0, targetBytes);
1187
+ if (status !== 0) throw statusToError(status, "symlink", linkPath);
839
1188
  }
840
- function fdatasyncSync(syncRequest, fd) {
841
- const buf = encodeRequest(OP.FSYNC, "");
1189
+ async function readlink(asyncRequest, filePath, options) {
1190
+ const { status, data } = await asyncRequest(OP.READLINK, filePath);
1191
+ if (status !== 0) throw statusToError(status, "readlink", filePath);
1192
+ const encoding = typeof options === "string" ? options : options?.encoding;
1193
+ if (encoding === "buffer") return new Uint8Array(data);
1194
+ return decoder6.decode(data);
1195
+ }
1196
+
1197
+ // src/methods/link.ts
1198
+ var encoder8 = new TextEncoder();
1199
+ function linkSync(syncRequest, existingPath, newPath) {
1200
+ const buf = encodeTwoPathRequest(OP.LINK, existingPath, newPath);
842
1201
  const { status } = syncRequest(buf);
843
- if (status !== 0) throw statusToError(status, "fdatasync", String(fd));
1202
+ if (status !== 0) throw statusToError(status, "link", existingPath);
844
1203
  }
845
- async function open(asyncRequest, filePath, flags, _mode) {
846
- const numFlags = typeof flags === "string" ? parseFlags(flags ?? "r") : flags ?? 0;
847
- const { status, data } = await asyncRequest(OP.OPEN, filePath, numFlags);
848
- if (status !== 0) throw statusToError(status, "open", filePath);
849
- const fd = new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true);
850
- return createFileHandle(fd, asyncRequest);
1204
+ async function link(asyncRequest, existingPath, newPath) {
1205
+ const path2Bytes = encoder8.encode(newPath);
1206
+ const payload = new Uint8Array(4 + path2Bytes.byteLength);
1207
+ new DataView(payload.buffer).setUint32(0, path2Bytes.byteLength, true);
1208
+ payload.set(path2Bytes, 4);
1209
+ const { status } = await asyncRequest(OP.LINK, existingPath, 0, payload);
1210
+ if (status !== 0) throw statusToError(status, "link", existingPath);
851
1211
  }
852
- function createFileHandle(fd, asyncRequest) {
853
- return {
854
- fd,
855
- async read(buffer, offset = 0, length = buffer.byteLength, position = null) {
856
- const { status, data } = await asyncRequest(OP.FREAD, "", 0, null, void 0, { fd, length, position: position ?? -1 });
857
- if (status !== 0) throw statusToError(status, "read", String(fd));
858
- const bytesRead = data ? data.byteLength : 0;
859
- if (data) buffer.set(data.subarray(0, Math.min(bytesRead, length)), offset);
860
- return { bytesRead, buffer };
861
- },
862
- async write(buffer, offset = 0, length = buffer.byteLength, position = null) {
863
- const writeData = buffer.subarray(offset, offset + length);
864
- const { status, data } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: writeData, position: position ?? -1 });
865
- if (status !== 0) throw statusToError(status, "write", String(fd));
866
- const bytesWritten = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;
867
- return { bytesWritten, buffer };
868
- },
869
- async readFile(options) {
870
- const encoding = typeof options === "string" ? options : options?.encoding;
871
- const { status, data } = await asyncRequest(OP.FREAD, "", 0, null, void 0, { fd, length: Number.MAX_SAFE_INTEGER, position: 0 });
872
- if (status !== 0) throw statusToError(status, "read", String(fd));
873
- const result = data ?? new Uint8Array(0);
874
- if (encoding) return decoder7.decode(result);
875
- return result;
876
- },
877
- async writeFile(data, _options) {
878
- const encoded = typeof data === "string" ? encoder8.encode(data) : data;
879
- const { status } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: encoded, position: 0 });
880
- if (status !== 0) throw statusToError(status, "write", String(fd));
881
- },
882
- async truncate(len = 0) {
883
- const { status } = await asyncRequest(OP.FTRUNCATE, "", 0, null, void 0, { fd, length: len });
884
- if (status !== 0) throw statusToError(status, "ftruncate", String(fd));
885
- },
886
- async stat() {
887
- const { status, data } = await asyncRequest(OP.FSTAT, "", 0, null, void 0, { fd });
888
- if (status !== 0) throw statusToError(status, "fstat", String(fd));
889
- return decodeStats(data);
890
- },
891
- async sync() {
892
- await asyncRequest(OP.FSYNC, "");
893
- },
894
- async datasync() {
895
- await asyncRequest(OP.FSYNC, "");
896
- },
897
- async close() {
898
- const { status } = await asyncRequest(OP.CLOSE, "", 0, null, void 0, { fd });
899
- if (status !== 0) throw statusToError(status, "close", String(fd));
900
- }
901
- };
1212
+
1213
+ // src/methods/mkdtemp.ts
1214
+ var decoder7 = new TextDecoder();
1215
+ function mkdtempSync(syncRequest, prefix) {
1216
+ const buf = encodeRequest(OP.MKDTEMP, prefix);
1217
+ const { status, data } = syncRequest(buf);
1218
+ if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
1219
+ return decoder7.decode(data);
1220
+ }
1221
+ async function mkdtemp(asyncRequest, prefix) {
1222
+ const { status, data } = await asyncRequest(OP.MKDTEMP, prefix);
1223
+ if (status !== 0) throw statusToError(status, "mkdtemp", prefix);
1224
+ return decoder7.decode(data);
902
1225
  }
903
1226
 
904
1227
  // src/methods/opendir.ts
@@ -1271,8 +1594,168 @@ async function* watchAsync(ns, _asyncRequest, filePath, options) {
1271
1594
  }
1272
1595
  }
1273
1596
 
1597
+ // src/methods/glob.ts
1598
+ function segmentToRegex(pattern) {
1599
+ let re = "^";
1600
+ for (let i = 0; i < pattern.length; i++) {
1601
+ const ch = pattern[i];
1602
+ if (ch === "*") {
1603
+ re += "[^/]*";
1604
+ } else if (ch === "?") {
1605
+ re += "[^/]";
1606
+ } else if (".+^${}()|[]\\".includes(ch)) {
1607
+ re += "\\" + ch;
1608
+ } else {
1609
+ re += ch;
1610
+ }
1611
+ }
1612
+ re += "$";
1613
+ return new RegExp(re);
1614
+ }
1615
+ function matchSegment(name, pattern) {
1616
+ return segmentToRegex(pattern).test(name);
1617
+ }
1618
+ function joinPath(base, name) {
1619
+ if (base === "/") return "/" + name;
1620
+ return base + "/" + name;
1621
+ }
1622
+ function globSync(syncRequest, pattern, options) {
1623
+ const cwd = options?.cwd ?? "/";
1624
+ const exclude = options?.exclude;
1625
+ const segments = pattern.split("/").filter((s) => s !== "");
1626
+ const results = [];
1627
+ function walk(dir, segIdx) {
1628
+ if (segIdx >= segments.length) return;
1629
+ const seg = segments[segIdx];
1630
+ const isLast = segIdx === segments.length - 1;
1631
+ if (seg === "**") {
1632
+ if (segIdx + 1 < segments.length) {
1633
+ walk(dir, segIdx + 1);
1634
+ }
1635
+ let entries2;
1636
+ try {
1637
+ entries2 = readdirSync(syncRequest, dir);
1638
+ } catch {
1639
+ return;
1640
+ }
1641
+ for (const entry of entries2) {
1642
+ const full = joinPath(dir, entry);
1643
+ if (exclude && exclude(full)) continue;
1644
+ let isDir;
1645
+ try {
1646
+ const s = statSync(syncRequest, full);
1647
+ isDir = s.isDirectory();
1648
+ } catch {
1649
+ continue;
1650
+ }
1651
+ if (isDir) {
1652
+ walk(full, segIdx);
1653
+ }
1654
+ if (isLast) {
1655
+ results.push(full);
1656
+ }
1657
+ }
1658
+ return;
1659
+ }
1660
+ let entries;
1661
+ try {
1662
+ entries = readdirSync(syncRequest, dir);
1663
+ } catch {
1664
+ return;
1665
+ }
1666
+ for (const entry of entries) {
1667
+ if (!matchSegment(entry, seg)) continue;
1668
+ const full = joinPath(dir, entry);
1669
+ if (exclude && exclude(full)) continue;
1670
+ if (isLast) {
1671
+ results.push(full);
1672
+ } else {
1673
+ let isDir;
1674
+ try {
1675
+ const s = statSync(syncRequest, full);
1676
+ isDir = s.isDirectory();
1677
+ } catch {
1678
+ continue;
1679
+ }
1680
+ if (isDir) {
1681
+ walk(full, segIdx + 1);
1682
+ }
1683
+ }
1684
+ }
1685
+ }
1686
+ walk(cwd, 0);
1687
+ return results;
1688
+ }
1689
+ async function glob(asyncRequest, pattern, options) {
1690
+ const cwd = options?.cwd ?? "/";
1691
+ const exclude = options?.exclude;
1692
+ const segments = pattern.split("/").filter((s) => s !== "");
1693
+ const results = [];
1694
+ async function walk(dir, segIdx) {
1695
+ if (segIdx >= segments.length) return;
1696
+ const seg = segments[segIdx];
1697
+ const isLast = segIdx === segments.length - 1;
1698
+ if (seg === "**") {
1699
+ if (segIdx + 1 < segments.length) {
1700
+ await walk(dir, segIdx + 1);
1701
+ }
1702
+ let entries2;
1703
+ try {
1704
+ entries2 = await readdir(asyncRequest, dir);
1705
+ } catch {
1706
+ return;
1707
+ }
1708
+ for (const entry of entries2) {
1709
+ const full = joinPath(dir, entry);
1710
+ if (exclude && exclude(full)) continue;
1711
+ let isDir;
1712
+ try {
1713
+ const s = await stat(asyncRequest, full);
1714
+ isDir = s.isDirectory();
1715
+ } catch {
1716
+ continue;
1717
+ }
1718
+ if (isDir) {
1719
+ await walk(full, segIdx);
1720
+ }
1721
+ if (isLast) {
1722
+ results.push(full);
1723
+ }
1724
+ }
1725
+ return;
1726
+ }
1727
+ let entries;
1728
+ try {
1729
+ entries = await readdir(asyncRequest, dir);
1730
+ } catch {
1731
+ return;
1732
+ }
1733
+ for (const entry of entries) {
1734
+ if (!matchSegment(entry, seg)) continue;
1735
+ const full = joinPath(dir, entry);
1736
+ if (exclude && exclude(full)) continue;
1737
+ if (isLast) {
1738
+ results.push(full);
1739
+ } else {
1740
+ let isDir;
1741
+ try {
1742
+ const s = await stat(asyncRequest, full);
1743
+ isDir = s.isDirectory();
1744
+ } catch {
1745
+ continue;
1746
+ }
1747
+ if (isDir) {
1748
+ await walk(full, segIdx + 1);
1749
+ }
1750
+ }
1751
+ }
1752
+ }
1753
+ await walk(cwd, 0);
1754
+ return results;
1755
+ }
1756
+
1274
1757
  // src/filesystem.ts
1275
- var encoder9 = new TextEncoder();
1758
+ new TextEncoder();
1276
1759
  var DEFAULT_SAB_SIZE = 2 * 1024 * 1024;
1277
1760
  var instanceRegistry = /* @__PURE__ */ new Map();
1278
1761
  var HEADER_SIZE = SAB_OFFSETS.HEADER_SIZE;
@@ -1832,11 +2315,14 @@ var VFSFileSystem = class {
1832
2315
  readdirSync(filePath, options) {
1833
2316
  return readdirSync(this._sync, filePath, options);
1834
2317
  }
1835
- statSync(filePath) {
1836
- return statSync(this._sync, filePath);
2318
+ globSync(pattern, options) {
2319
+ return globSync(this._sync, pattern, options);
2320
+ }
2321
+ statSync(filePath, options) {
2322
+ return statSync(this._sync, filePath, options);
1837
2323
  }
1838
- lstatSync(filePath) {
1839
- return lstatSync(this._sync, filePath);
2324
+ lstatSync(filePath, options) {
2325
+ return lstatSync(this._sync, filePath, options);
1840
2326
  }
1841
2327
  renameSync(oldPath, newPath) {
1842
2328
  renameSync(this._sync, oldPath, newPath);
@@ -1844,6 +2330,112 @@ var VFSFileSystem = class {
1844
2330
  copyFileSync(src, dest, mode) {
1845
2331
  copyFileSync(this._sync, src, dest, mode);
1846
2332
  }
2333
+ cpSync(src, dest, options) {
2334
+ const force = options?.force !== false;
2335
+ const errorOnExist = options?.errorOnExist ?? false;
2336
+ const dereference = options?.dereference ?? false;
2337
+ const preserveTimestamps = options?.preserveTimestamps ?? false;
2338
+ const srcStat = dereference ? this.statSync(src) : this.lstatSync(src);
2339
+ if (srcStat.isDirectory()) {
2340
+ if (!options?.recursive) {
2341
+ throw createError("EISDIR", "cp", src);
2342
+ }
2343
+ try {
2344
+ this.mkdirSync(dest, { recursive: true });
2345
+ } catch (e) {
2346
+ if (e.code !== "EEXIST") throw e;
2347
+ }
2348
+ const entries = this.readdirSync(src, { withFileTypes: true });
2349
+ for (const entry of entries) {
2350
+ const srcChild = join(src, entry.name);
2351
+ const destChild = join(dest, entry.name);
2352
+ this.cpSync(srcChild, destChild, options);
2353
+ }
2354
+ } else if (srcStat.isSymbolicLink() && !dereference) {
2355
+ const target = this.readlinkSync(src);
2356
+ let destExists = false;
2357
+ try {
2358
+ this.lstatSync(dest);
2359
+ destExists = true;
2360
+ } catch {
2361
+ }
2362
+ if (destExists) {
2363
+ if (errorOnExist) throw createError("EEXIST", "cp", dest);
2364
+ if (!force) return;
2365
+ this.unlinkSync(dest);
2366
+ }
2367
+ this.symlinkSync(target, dest);
2368
+ } else {
2369
+ let destExists = false;
2370
+ try {
2371
+ this.lstatSync(dest);
2372
+ destExists = true;
2373
+ } catch {
2374
+ }
2375
+ if (destExists) {
2376
+ if (errorOnExist) throw createError("EEXIST", "cp", dest);
2377
+ if (!force) return;
2378
+ }
2379
+ this.copyFileSync(src, dest, errorOnExist ? constants.COPYFILE_EXCL : 0);
2380
+ }
2381
+ if (preserveTimestamps) {
2382
+ const st = this.statSync(src);
2383
+ this.utimesSync(dest, st.atime, st.mtime);
2384
+ }
2385
+ }
2386
+ async cp(src, dest, options) {
2387
+ const force = options?.force !== false;
2388
+ const errorOnExist = options?.errorOnExist ?? false;
2389
+ const dereference = options?.dereference ?? false;
2390
+ const preserveTimestamps = options?.preserveTimestamps ?? false;
2391
+ const srcStat = dereference ? await this.promises.stat(src) : await this.promises.lstat(src);
2392
+ if (srcStat.isDirectory()) {
2393
+ if (!options?.recursive) {
2394
+ throw createError("EISDIR", "cp", src);
2395
+ }
2396
+ try {
2397
+ await this.promises.mkdir(dest, { recursive: true });
2398
+ } catch (e) {
2399
+ if (e.code !== "EEXIST") throw e;
2400
+ }
2401
+ const entries = await this.promises.readdir(src, { withFileTypes: true });
2402
+ for (const entry of entries) {
2403
+ const srcChild = join(src, entry.name);
2404
+ const destChild = join(dest, entry.name);
2405
+ await this.cp(srcChild, destChild, options);
2406
+ }
2407
+ } else if (srcStat.isSymbolicLink() && !dereference) {
2408
+ const target = await this.promises.readlink(src);
2409
+ let destExists = false;
2410
+ try {
2411
+ await this.promises.lstat(dest);
2412
+ destExists = true;
2413
+ } catch {
2414
+ }
2415
+ if (destExists) {
2416
+ if (errorOnExist) throw createError("EEXIST", "cp", dest);
2417
+ if (!force) return;
2418
+ await this.promises.unlink(dest);
2419
+ }
2420
+ await this.promises.symlink(target, dest);
2421
+ } else {
2422
+ let destExists = false;
2423
+ try {
2424
+ await this.promises.lstat(dest);
2425
+ destExists = true;
2426
+ } catch {
2427
+ }
2428
+ if (destExists) {
2429
+ if (errorOnExist) throw createError("EEXIST", "cp", dest);
2430
+ if (!force) return;
2431
+ }
2432
+ await this.promises.copyFile(src, dest, errorOnExist ? constants.COPYFILE_EXCL : 0);
2433
+ }
2434
+ if (preserveTimestamps) {
2435
+ const st = await this.promises.stat(src);
2436
+ await this.promises.utimes(dest, st.atime, st.mtime);
2437
+ }
2438
+ }
1847
2439
  truncateSync(filePath, len) {
1848
2440
  truncateSync(this._sync, filePath, len);
1849
2441
  }
@@ -1862,11 +2454,11 @@ var VFSFileSystem = class {
1862
2454
  utimesSync(filePath, atime, mtime) {
1863
2455
  utimesSync(this._sync, filePath, atime, mtime);
1864
2456
  }
1865
- symlinkSync(target, linkPath) {
2457
+ symlinkSync(target, linkPath, type) {
1866
2458
  symlinkSync(this._sync, target, linkPath);
1867
2459
  }
1868
- readlinkSync(filePath) {
1869
- return readlinkSync(this._sync, filePath);
2460
+ readlinkSync(filePath, options) {
2461
+ return readlinkSync(this._sync, filePath, options);
1870
2462
  }
1871
2463
  linkSync(existingPath, newPath) {
1872
2464
  linkSync(this._sync, existingPath, newPath);
@@ -1884,8 +2476,8 @@ var VFSFileSystem = class {
1884
2476
  readSync(fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
1885
2477
  return readSync(this._sync, fd, buffer, offset, length, position);
1886
2478
  }
1887
- writeSync(fd, buffer, offset = 0, length = buffer.byteLength, position = null) {
1888
- return writeSyncFd(this._sync, fd, buffer, offset, length, position);
2479
+ writeSync(fd, bufferOrString, offsetOrPosition, lengthOrEncoding, position) {
2480
+ return writeSyncFd(this._sync, fd, bufferOrString, offsetOrPosition, lengthOrEncoding, position);
1889
2481
  }
1890
2482
  fstatSync(fd) {
1891
2483
  return fstatSync(this._sync, fd);
@@ -1896,6 +2488,31 @@ var VFSFileSystem = class {
1896
2488
  fdatasyncSync(fd) {
1897
2489
  fdatasyncSync(this._sync, fd);
1898
2490
  }
2491
+ // ---- statfs methods ----
2492
+ statfsSync(_path) {
2493
+ return {
2494
+ type: 1447449377,
2495
+ // "VFS!"
2496
+ bsize: 4096,
2497
+ blocks: 1024 * 1024,
2498
+ // ~4GB virtual capacity
2499
+ bfree: 512 * 1024,
2500
+ // ~2GB free (estimate)
2501
+ bavail: 512 * 1024,
2502
+ files: 1e4,
2503
+ // default max inodes
2504
+ ffree: 5e3
2505
+ // estimate half free
2506
+ };
2507
+ }
2508
+ statfs(path, callback) {
2509
+ const result = this.statfsSync(path);
2510
+ if (callback) {
2511
+ callback(null, result);
2512
+ return;
2513
+ }
2514
+ return Promise.resolve(result);
2515
+ }
1899
2516
  // ---- Watch methods ----
1900
2517
  watch(filePath, options, listener) {
1901
2518
  return watch(this.ns, filePath, options, listener);
@@ -1908,55 +2525,81 @@ var VFSFileSystem = class {
1908
2525
  }
1909
2526
  // ---- Stream methods ----
1910
2527
  createReadStream(filePath, options) {
1911
- const opts = typeof options === "string" ? { } : options;
2528
+ const opts = typeof options === "string" ? { encoding: options } : options;
1912
2529
  const start = opts?.start ?? 0;
1913
2530
  const end = opts?.end;
1914
2531
  const highWaterMark = opts?.highWaterMark ?? 64 * 1024;
1915
2532
  let position = start;
2533
+ let handle = null;
2534
+ const cleanup = async () => {
2535
+ if (handle) {
2536
+ try {
2537
+ await handle.close();
2538
+ } catch {
2539
+ }
2540
+ handle = null;
2541
+ }
2542
+ };
1916
2543
  return new ReadableStream({
1917
2544
  pull: async (controller) => {
1918
2545
  try {
2546
+ if (!handle) {
2547
+ handle = await this.promises.open(filePath, opts?.flags ?? "r");
2548
+ }
1919
2549
  const readLen = end !== void 0 ? Math.min(highWaterMark, end - position + 1) : highWaterMark;
1920
2550
  if (readLen <= 0) {
2551
+ await cleanup();
1921
2552
  controller.close();
1922
2553
  return;
1923
2554
  }
1924
- const result = await this.promises.readFile(filePath);
1925
- const data = result instanceof Uint8Array ? result : encoder9.encode(result);
1926
- const chunk = data.subarray(position, position + readLen);
1927
- if (chunk.byteLength === 0) {
2555
+ const buffer = new Uint8Array(readLen);
2556
+ const { bytesRead } = await handle.read(buffer, 0, readLen, position);
2557
+ if (bytesRead === 0) {
2558
+ await cleanup();
1928
2559
  controller.close();
1929
2560
  return;
1930
2561
  }
1931
- controller.enqueue(chunk);
1932
- position += chunk.byteLength;
2562
+ controller.enqueue(buffer.subarray(0, bytesRead));
2563
+ position += bytesRead;
1933
2564
  if (end !== void 0 && position > end) {
2565
+ await cleanup();
1934
2566
  controller.close();
1935
2567
  }
1936
2568
  } catch (err) {
2569
+ await cleanup();
1937
2570
  controller.error(err);
1938
2571
  }
2572
+ },
2573
+ cancel: async () => {
2574
+ await cleanup();
1939
2575
  }
1940
2576
  });
1941
2577
  }
1942
2578
  createWriteStream(filePath, options) {
1943
2579
  const opts = typeof options === "string" ? { } : options;
1944
2580
  let position = opts?.start ?? 0;
1945
- let initialized = false;
2581
+ let handle = null;
1946
2582
  return new WritableStream({
1947
2583
  write: async (chunk) => {
1948
- if (!initialized) {
1949
- if (opts?.flags !== "a" && opts?.flags !== "a+") {
1950
- await this.promises.writeFile(filePath, new Uint8Array(0));
1951
- }
1952
- initialized = true;
2584
+ if (!handle) {
2585
+ handle = await this.promises.open(filePath, opts?.flags ?? "w");
1953
2586
  }
1954
- await this.promises.appendFile(filePath, chunk);
1955
- position += chunk.byteLength;
2587
+ const { bytesWritten } = await handle.write(chunk, 0, chunk.byteLength, position);
2588
+ position += bytesWritten;
1956
2589
  },
1957
2590
  close: async () => {
1958
- if (opts?.flush) {
1959
- await this.promises.flush();
2591
+ if (handle) {
2592
+ if (opts?.flush) {
2593
+ await handle.sync();
2594
+ }
2595
+ await handle.close();
2596
+ handle = null;
2597
+ }
2598
+ },
2599
+ abort: async () => {
2600
+ if (handle) {
2601
+ await handle.close();
2602
+ handle = null;
1960
2603
  }
1961
2604
  }
1962
2605
  });
@@ -2097,11 +2740,14 @@ var VFSPromises = class {
2097
2740
  readdir(filePath, options) {
2098
2741
  return readdir(this._async, filePath, options);
2099
2742
  }
2100
- stat(filePath) {
2101
- return stat(this._async, filePath);
2743
+ glob(pattern, options) {
2744
+ return glob(this._async, pattern, options);
2102
2745
  }
2103
- lstat(filePath) {
2104
- return lstat(this._async, filePath);
2746
+ stat(filePath, options) {
2747
+ return stat(this._async, filePath, options);
2748
+ }
2749
+ lstat(filePath, options) {
2750
+ return lstat(this._async, filePath, options);
2105
2751
  }
2106
2752
  access(filePath, mode) {
2107
2753
  return access(this._async, filePath, mode);
@@ -2112,6 +2758,59 @@ var VFSPromises = class {
2112
2758
  copyFile(src, dest, mode) {
2113
2759
  return copyFile(this._async, src, dest, mode);
2114
2760
  }
2761
+ async cp(src, dest, options) {
2762
+ const force = options?.force !== false;
2763
+ const errorOnExist = options?.errorOnExist ?? false;
2764
+ const dereference = options?.dereference ?? false;
2765
+ const preserveTimestamps = options?.preserveTimestamps ?? false;
2766
+ const srcStat = dereference ? await this.stat(src) : await this.lstat(src);
2767
+ if (srcStat.isDirectory()) {
2768
+ if (!options?.recursive) {
2769
+ throw createError("EISDIR", "cp", src);
2770
+ }
2771
+ try {
2772
+ await this.mkdir(dest, { recursive: true });
2773
+ } catch (e) {
2774
+ if (e.code !== "EEXIST") throw e;
2775
+ }
2776
+ const entries = await this.readdir(src, { withFileTypes: true });
2777
+ for (const entry of entries) {
2778
+ const srcChild = join(src, entry.name);
2779
+ const destChild = join(dest, entry.name);
2780
+ await this.cp(srcChild, destChild, options);
2781
+ }
2782
+ } else if (srcStat.isSymbolicLink() && !dereference) {
2783
+ const target = await this.readlink(src);
2784
+ let destExists = false;
2785
+ try {
2786
+ await this.lstat(dest);
2787
+ destExists = true;
2788
+ } catch {
2789
+ }
2790
+ if (destExists) {
2791
+ if (errorOnExist) throw createError("EEXIST", "cp", dest);
2792
+ if (!force) return;
2793
+ await this.unlink(dest);
2794
+ }
2795
+ await this.symlink(target, dest);
2796
+ } else {
2797
+ let destExists = false;
2798
+ try {
2799
+ await this.lstat(dest);
2800
+ destExists = true;
2801
+ } catch {
2802
+ }
2803
+ if (destExists) {
2804
+ if (errorOnExist) throw createError("EEXIST", "cp", dest);
2805
+ if (!force) return;
2806
+ }
2807
+ await this.copyFile(src, dest, errorOnExist ? constants.COPYFILE_EXCL : 0);
2808
+ }
2809
+ if (preserveTimestamps) {
2810
+ const st = await this.stat(src);
2811
+ await this.utimes(dest, st.atime, st.mtime);
2812
+ }
2813
+ }
2115
2814
  truncate(filePath, len) {
2116
2815
  return truncate(this._async, filePath, len);
2117
2816
  }
@@ -2130,11 +2829,11 @@ var VFSPromises = class {
2130
2829
  utimes(filePath, atime, mtime) {
2131
2830
  return utimes(this._async, filePath, atime, mtime);
2132
2831
  }
2133
- symlink(target, linkPath) {
2832
+ symlink(target, linkPath, type) {
2134
2833
  return symlink(this._async, target, linkPath);
2135
2834
  }
2136
- readlink(filePath) {
2137
- return readlink(this._async, filePath);
2835
+ readlink(filePath, options) {
2836
+ return readlink(this._async, filePath, options);
2138
2837
  }
2139
2838
  link(existingPath, newPath) {
2140
2839
  return link(this._async, existingPath, newPath);
@@ -2148,6 +2847,22 @@ var VFSPromises = class {
2148
2847
  mkdtemp(prefix) {
2149
2848
  return mkdtemp(this._async, prefix);
2150
2849
  }
2850
+ async statfs(path) {
2851
+ return {
2852
+ type: 1447449377,
2853
+ // "VFS!"
2854
+ bsize: 4096,
2855
+ blocks: 1024 * 1024,
2856
+ // ~4GB virtual capacity
2857
+ bfree: 512 * 1024,
2858
+ // ~2GB free (estimate)
2859
+ bavail: 512 * 1024,
2860
+ files: 1e4,
2861
+ // default max inodes
2862
+ ffree: 5e3
2863
+ // estimate half free
2864
+ };
2865
+ }
2151
2866
  async *watch(filePath, options) {
2152
2867
  yield* watchAsync(this._ns, this._async, filePath, options);
2153
2868
  }
@@ -2461,6 +3176,7 @@ var VFSEngine = class {
2461
3176
  type,
2462
3177
  pathOffset,
2463
3178
  pathLength,
3179
+ nlink: inodeView.getUint16(off + INODE.NLINK, true) || 1,
2464
3180
  mode: inodeView.getUint32(off + INODE.MODE, true),
2465
3181
  size,
2466
3182
  firstBlock,
@@ -2495,6 +3211,7 @@ var VFSEngine = class {
2495
3211
  type: v.getUint8(INODE.TYPE),
2496
3212
  pathOffset: v.getUint32(INODE.PATH_OFFSET, true),
2497
3213
  pathLength: v.getUint16(INODE.PATH_LENGTH, true),
3214
+ nlink: v.getUint16(INODE.NLINK, true) || 1,
2498
3215
  mode: v.getUint32(INODE.MODE, true),
2499
3216
  size: v.getFloat64(INODE.SIZE, true),
2500
3217
  firstBlock: v.getUint32(INODE.FIRST_BLOCK, true),
@@ -2521,7 +3238,7 @@ var VFSEngine = class {
2521
3238
  v.setUint8(INODE.FLAGS + 2, 0);
2522
3239
  v.setUint32(INODE.PATH_OFFSET, inode.pathOffset, true);
2523
3240
  v.setUint16(INODE.PATH_LENGTH, inode.pathLength, true);
2524
- v.setUint16(INODE.RESERVED_10, 0, true);
3241
+ v.setUint16(INODE.NLINK, inode.nlink, true);
2525
3242
  v.setUint32(INODE.MODE, inode.mode, true);
2526
3243
  v.setFloat64(INODE.SIZE, inode.size, true);
2527
3244
  v.setUint32(INODE.FIRST_BLOCK, inode.firstBlock, true);
@@ -2763,6 +3480,7 @@ var VFSEngine = class {
2763
3480
  type,
2764
3481
  pathOffset: pathOff,
2765
3482
  pathLength: pathLen,
3483
+ nlink: type === INODE_TYPE.DIRECTORY ? 2 : 1,
2766
3484
  mode,
2767
3485
  size,
2768
3486
  firstBlock,
@@ -2915,6 +3633,7 @@ var VFSEngine = class {
2915
3633
  if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT };
2916
3634
  const inode = this.readInode(idx);
2917
3635
  if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };
3636
+ inode.nlink = Math.max(0, inode.nlink - 1);
2918
3637
  this.freeBlockRange(inode.firstBlock, inode.blockCount);
2919
3638
  inode.type = INODE_TYPE.FREE;
2920
3639
  this.writeInode(idx, inode);
@@ -2939,7 +3658,21 @@ var VFSEngine = class {
2939
3658
  }
2940
3659
  encodeStatResponse(idx) {
2941
3660
  const inode = this.readInode(idx);
2942
- const buf = new Uint8Array(49);
3661
+ let nlink = inode.nlink;
3662
+ if (inode.type === INODE_TYPE.DIRECTORY) {
3663
+ const path = this.readPath(inode.pathOffset, inode.pathLength);
3664
+ const children = this.getDirectChildren(path);
3665
+ let subdirCount = 0;
3666
+ for (const child of children) {
3667
+ const childIdx = this.pathIndex.get(child);
3668
+ if (childIdx !== void 0) {
3669
+ const childInode = this.readInode(childIdx);
3670
+ if (childInode.type === INODE_TYPE.DIRECTORY) subdirCount++;
3671
+ }
3672
+ }
3673
+ nlink = 2 + subdirCount;
3674
+ }
3675
+ const buf = new Uint8Array(53);
2943
3676
  const view = new DataView(buf.buffer);
2944
3677
  view.setUint8(0, inode.type);
2945
3678
  view.setUint32(1, inode.mode, true);
@@ -2950,6 +3683,7 @@ var VFSEngine = class {
2950
3683
  view.setUint32(37, inode.uid, true);
2951
3684
  view.setUint32(41, inode.gid, true);
2952
3685
  view.setUint32(45, idx, true);
3686
+ view.setUint32(49, nlink, true);
2953
3687
  return { status: 0, data: buf };
2954
3688
  }
2955
3689
  // ---- MKDIR ----
@@ -3262,9 +3996,26 @@ var VFSEngine = class {
3262
3996
  const target = this.readData(inode.firstBlock, inode.blockCount, inode.size);
3263
3997
  return { status: 0, data: target };
3264
3998
  }
3265
- // ---- LINK (hard link — copies the file) ----
3999
+ // ---- LINK (hard link — copies the file data, tracks nlink) ----
3266
4000
  link(existingPath, newPath) {
3267
- return this.copy(existingPath, newPath);
4001
+ existingPath = this.normalizePath(existingPath);
4002
+ newPath = this.normalizePath(newPath);
4003
+ const srcIdx = this.resolvePathComponents(existingPath, true);
4004
+ if (srcIdx === void 0) return { status: CODE_TO_STATUS.ENOENT };
4005
+ const srcInode = this.readInode(srcIdx);
4006
+ if (srcInode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EPERM };
4007
+ if (this.pathIndex.has(newPath)) return { status: CODE_TO_STATUS.EEXIST };
4008
+ const result = this.copy(existingPath, newPath);
4009
+ if (result.status !== 0) return result;
4010
+ srcInode.nlink++;
4011
+ this.writeInode(srcIdx, srcInode);
4012
+ const destIdx = this.pathIndex.get(newPath);
4013
+ if (destIdx !== void 0) {
4014
+ const destInode = this.readInode(destIdx);
4015
+ destInode.nlink = srcInode.nlink;
4016
+ this.writeInode(destIdx, destInode);
4017
+ }
4018
+ return { status: 0 };
3268
4019
  }
3269
4020
  // ---- OPEN (file descriptor) ----
3270
4021
  open(path, flags, tabId) {