@ai-ecoverse/slicc-jsh 0.3.5 → 0.3.6

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/jsh.mjs CHANGED
@@ -1539,7 +1539,7 @@ ${e3}`;
1539
1539
  // package.json
1540
1540
  var package_default = {
1541
1541
  name: "@ai-ecoverse/slicc-jsh",
1542
- version: "0.3.5",
1542
+ version: "0.3.6",
1543
1543
  description: "Node.js-compatible runtime for slicc-kernel: the node and jsh commands (abi: js)",
1544
1544
  type: "module",
1545
1545
  license: "Apache-2.0",
@@ -11284,8 +11284,10 @@ var ERRNO = {
11284
11284
  EACCES: -13,
11285
11285
  EINVAL: -22,
11286
11286
  EIO: -5,
11287
- ENOTEMPTY: -66,
11288
- EBADF: -9
11287
+ ENOTEMPTY: -39,
11288
+ // Linux (the shim's process.platform)
11289
+ EBADF: -9,
11290
+ ENOTSUP: -45
11289
11291
  };
11290
11292
  var DESCRIPTIONS = {
11291
11293
  ENOENT: "no such file or directory",
@@ -11297,7 +11299,8 @@ var DESCRIPTIONS = {
11297
11299
  EINVAL: "invalid argument",
11298
11300
  EIO: "i/o error",
11299
11301
  ENOTEMPTY: "directory not empty",
11300
- EBADF: "bad file descriptor"
11302
+ EBADF: "bad file descriptor",
11303
+ ENOTSUP: "operation not supported"
11301
11304
  };
11302
11305
  function nodeFsError(code, syscall, pathArg, err, dest) {
11303
11306
  const c = typeof code === "string" ? code : err?.code || "EIO";
@@ -11318,37 +11321,90 @@ function nodeFsError(code, syscall, pathArg, err, dest) {
11318
11321
  if (dest !== void 0) e.dest = dest;
11319
11322
  return e;
11320
11323
  }
11324
+ var FS_READ_STREAM = /* @__PURE__ */ Symbol("fs.ReadStream");
11325
+ var FS_WRITE_STREAM = /* @__PURE__ */ Symbol("fs.WriteStream");
11326
+ function cpInvalid(message) {
11327
+ const e = new Error(message);
11328
+ e.code = "ERR_FS_CP_EINVAL";
11329
+ return e;
11330
+ }
11331
+ function rmIsDirectoryError(pathArg) {
11332
+ const e = new Error(`Path is a directory: rm returned EISDIR (is a directory) ${pathArg}`);
11333
+ e.name = "SystemError";
11334
+ e.code = "ERR_FS_EISDIR";
11335
+ e.errno = 21;
11336
+ e.syscall = "rm";
11337
+ e.path = String(pathArg);
11338
+ e.info = { code: "EISDIR", message: "is a directory", path: String(pathArg), syscall: "rm", errno: 21 };
11339
+ return e;
11340
+ }
11321
11341
  function toBytes(data2) {
11322
11342
  if (typeof data2 === "string") return encoder3.encode(data2);
11323
11343
  if (data2 instanceof Uint8Array) return data2;
11324
11344
  if (ArrayBuffer.isView(data2)) return new Uint8Array(data2.buffer, data2.byteOffset, data2.byteLength);
11325
11345
  return encoder3.encode(String(data2));
11326
11346
  }
11347
+ var S_IFMT = 61440;
11348
+ var S_IFREG = 32768;
11349
+ var S_IFDIR = 16384;
11350
+ var S_IFLNK = 40960;
11351
+ var Stats = class {
11352
+ isFile() {
11353
+ return (this.mode & S_IFMT) === S_IFREG;
11354
+ }
11355
+ isDirectory() {
11356
+ return (this.mode & S_IFMT) === S_IFDIR;
11357
+ }
11358
+ isSymbolicLink() {
11359
+ return (this.mode & S_IFMT) === S_IFLNK;
11360
+ }
11361
+ isBlockDevice() {
11362
+ return false;
11363
+ }
11364
+ isCharacterDevice() {
11365
+ return false;
11366
+ }
11367
+ isFIFO() {
11368
+ return false;
11369
+ }
11370
+ isSocket() {
11371
+ return false;
11372
+ }
11373
+ };
11327
11374
  function statView(st) {
11328
11375
  const mtimeMs = st.mtimeMs ?? (st.mtime ? Number(st.mtime) : 0);
11329
11376
  const atimeMs = st.atimeMs ?? mtimeMs;
11330
11377
  const ctimeMs = st.ctimeMs ?? mtimeMs;
11331
- return {
11332
- isFile: () => !!st.isFile,
11333
- isDirectory: () => !!st.isDirectory,
11334
- isSymbolicLink: () => !!st.isSymbolicLink,
11335
- size: st.size ?? 0,
11336
- mode: st.mode,
11337
- mtimeMs,
11378
+ const type = st.isDirectory ? S_IFDIR : st.isSymbolicLink ? S_IFLNK : S_IFREG;
11379
+ const perm = typeof st.mode === "number" ? st.mode & ~S_IFMT : st.isDirectory ? 493 : 420;
11380
+ const size = st.size ?? 0;
11381
+ return Object.assign(new Stats(), {
11382
+ dev: st.dev ?? 0,
11383
+ mode: type | perm,
11384
+ nlink: st.nlink ?? 1,
11385
+ uid: st.uid ?? 0,
11386
+ gid: st.gid ?? 0,
11387
+ rdev: 0,
11388
+ blksize: 4096,
11389
+ ino: st.ino ?? 0,
11390
+ size,
11391
+ blocks: Math.ceil(size / 512),
11338
11392
  atimeMs,
11393
+ mtimeMs,
11339
11394
  ctimeMs,
11340
- mtime: new Date(mtimeMs),
11395
+ birthtimeMs: ctimeMs,
11341
11396
  atime: new Date(atimeMs),
11397
+ mtime: new Date(mtimeMs),
11342
11398
  ctime: new Date(ctimeMs),
11343
- birthtime: new Date(ctimeMs),
11344
- ino: st.ino,
11345
- dev: st.dev
11346
- };
11399
+ birthtime: new Date(ctimeMs)
11400
+ });
11347
11401
  }
11348
11402
  var Dirent = class {
11349
- constructor(name, type) {
11403
+ constructor(name, type, parentPath) {
11350
11404
  this.name = name;
11351
- this._type = type;
11405
+ this.parentPath = parentPath;
11406
+ this.path = parentPath;
11407
+ Object.defineProperty(this, "_type", { value: type, enumerable: false });
11352
11408
  }
11353
11409
  isFile() {
11354
11410
  return this._type === "file";
@@ -11380,6 +11436,20 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11380
11436
  const syncFs = ctx.sync.fs;
11381
11437
  const asyncFs = ctx.fs;
11382
11438
  const wrapBuffer = (bytes) => Buffer2 ? Buffer2.from(bytes) : bytes;
11439
+ const optEncoding = (options) => typeof options === "string" ? options : options?.encoding ?? null;
11440
+ const optFlag = (options, fallback) => options && typeof options === "object" && options.flag || fallback;
11441
+ const decodeAs = (bytes, encoding) => {
11442
+ if (!encoding || encoding === "buffer") return wrapBuffer(bytes);
11443
+ if (encoding === "utf8" || encoding === "utf-8") return decoder3.decode(bytes);
11444
+ return Buffer2 ? Buffer2.from(bytes).toString(encoding) : decoder3.decode(bytes);
11445
+ };
11446
+ const encodeAs = (data2, encoding) => {
11447
+ if (typeof data2 === "string" && encoding && encoding !== "utf8" && encoding !== "utf-8" && Buffer2) {
11448
+ const b = Buffer2.from(data2, encoding);
11449
+ return new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
11450
+ }
11451
+ return toBytes(data2);
11452
+ };
11383
11453
  const track = (p) => handles ? trackPromise(handles, p) : p;
11384
11454
  const fdTable = /* @__PURE__ */ new Map();
11385
11455
  let nextFd = 3;
@@ -11505,12 +11575,10 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11505
11575
  function readStdinSync(encoding) {
11506
11576
  try {
11507
11577
  if (typeof process2?._readStdinSync === "function") {
11508
- const out = process2._readStdinSync();
11509
- return encoding ? decoder3.decode(out) : wrapBuffer(out);
11578
+ return decodeAs(process2._readStdinSync(), encoding);
11510
11579
  }
11511
11580
  if (typeof process2?.stdin?._readAllSync === "function") {
11512
- const out = process2.stdin._readAllSync();
11513
- return encoding ? decoder3.decode(out) : wrapBuffer(out);
11581
+ return decodeAs(process2.stdin._readAllSync(), encoding);
11514
11582
  }
11515
11583
  if (typeof ctx.sync?.read === "function") {
11516
11584
  const chunks = [];
@@ -11527,11 +11595,11 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11527
11595
  out.set(c, at2);
11528
11596
  at2 += c.length;
11529
11597
  }
11530
- return encoding ? decoder3.decode(out) : wrapBuffer(out);
11598
+ return decodeAs(out, encoding);
11531
11599
  }
11532
11600
  } catch {
11533
11601
  }
11534
- return encoding ? "" : wrapBuffer(new Uint8Array(0));
11602
+ return decodeAs(new Uint8Array(0), encoding);
11535
11603
  }
11536
11604
  function mkdirSync(p, options = {}) {
11537
11605
  const pathArg = p;
@@ -11548,42 +11616,105 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11548
11616
  }
11549
11617
  const parts = String(target).split("/").filter(Boolean);
11550
11618
  let cur = "";
11619
+ let first;
11551
11620
  for (const part of parts) {
11552
11621
  cur += `/${part}`;
11553
- if (syncFs.exists(cur)) continue;
11622
+ if (syncFs.exists(cur)) {
11623
+ let st;
11624
+ try {
11625
+ st = syncFs.stat(cur);
11626
+ } catch {
11627
+ st = null;
11628
+ }
11629
+ if (st && !st.isDirectory) throw nodeFsError("ENOTDIR", "mkdir", pathArg);
11630
+ continue;
11631
+ }
11554
11632
  try {
11555
11633
  syncFs.mkdir(cur);
11634
+ first ??= path.isAbsolute(String(p)) ? cur : path.relative(process2.cwd(), cur);
11556
11635
  } catch (err) {
11557
11636
  if (err?.code === "EEXIST") continue;
11558
11637
  throw nodeFsError(err?.code || "EIO", "mkdir", pathArg, err);
11559
11638
  }
11560
11639
  }
11640
+ return first;
11641
+ }
11642
+ const typeAt = (full) => {
11643
+ try {
11644
+ const st = syncFs.lstat(full);
11645
+ return st.isDirectory ? "dir" : st.isSymbolicLink ? "link" : st.isFile ? "file" : "unknown";
11646
+ } catch {
11647
+ return "unknown";
11648
+ }
11649
+ };
11650
+ function mustExist(p, syscall) {
11651
+ let ok = false;
11652
+ try {
11653
+ ok = syncFs.exists(abs(p));
11654
+ } catch {
11655
+ ok = false;
11656
+ }
11657
+ if (!ok) throw nodeFsError("ENOENT", syscall, p);
11561
11658
  }
11562
11659
  function readdirSync(p, options) {
11563
11660
  const pathArg = p;
11564
11661
  const target = abs(p);
11662
+ const encoding = optEncoding(options);
11663
+ const asName = (name) => encoding === "buffer" ? wrapBuffer(encoder3.encode(name)) : name;
11664
+ let names;
11565
11665
  try {
11566
- const names = syncFs.readdir(target);
11666
+ names = syncFs.readdir(target);
11667
+ } catch (err) {
11668
+ throw nodeFsError(err?.code || "ENOENT", "scandir", pathArg, err);
11669
+ }
11670
+ if (!options?.recursive) {
11567
11671
  if (options?.withFileTypes) {
11568
- return names.map((name) => {
11569
- let type = "unknown";
11672
+ return names.map((name) => new Dirent(name, typeAt(path.join(target, name)), String(pathArg)));
11673
+ }
11674
+ return names.map(asName);
11675
+ }
11676
+ const out = [];
11677
+ const queue = [{ dir: target, rel: "", parent: String(pathArg), names }];
11678
+ while (queue.length) {
11679
+ const { dir, rel, parent, names: entries } = queue.shift();
11680
+ for (const name of entries) {
11681
+ const full = path.join(dir, name);
11682
+ const type = typeAt(full);
11683
+ out.push(options.withFileTypes ? new Dirent(name, type, parent) : asName(rel ? `${rel}/${name}` : name));
11684
+ if (type === "dir") {
11685
+ let children;
11570
11686
  try {
11571
- const st = syncFs.lstat(path.join(target, name));
11572
- type = st.isDirectory ? "dir" : st.isSymbolicLink ? "link" : st.isFile ? "file" : "unknown";
11687
+ children = syncFs.readdir(full);
11573
11688
  } catch {
11689
+ children = [];
11574
11690
  }
11575
- return new Dirent(name, type);
11576
- });
11691
+ queue.push({
11692
+ dir: full,
11693
+ rel: rel ? `${rel}/${name}` : name,
11694
+ parent: path.join(parent, name),
11695
+ names: children
11696
+ });
11697
+ }
11577
11698
  }
11578
- return names;
11579
- } catch (err) {
11580
- throw nodeFsError(err?.code || "ENOENT", "scandir", pathArg, err);
11581
11699
  }
11700
+ return out;
11582
11701
  }
11583
11702
  const syncApi = {
11584
11703
  readFileSync(p, options) {
11585
- const encoding = typeof options === "string" ? options : options?.encoding;
11704
+ const encoding = optEncoding(options);
11586
11705
  if (p === 0 || p === "0") return readStdinSync(encoding);
11706
+ if (typeof p === "number") {
11707
+ const ent = fdTable.get(p);
11708
+ if (!ent || !ent.readable) throw nodeFsError("EBADF", "read", void 0);
11709
+ try {
11710
+ const bytes = syncFs.readFile(ent.path);
11711
+ const rest = bytes.subarray(Math.min(ent.pos, bytes.length));
11712
+ ent.pos += rest.length;
11713
+ return decodeAs(rest, encoding);
11714
+ } catch (err) {
11715
+ throw nodeFsError(err?.code || "EIO", "read", void 0, err);
11716
+ }
11717
+ }
11587
11718
  const pathArg = p;
11588
11719
  if (pathArg === "/dev/stdin" || pathArg === "/dev/fd/0") {
11589
11720
  return readStdinSync(encoding);
@@ -11598,32 +11729,52 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11598
11729
  e.syscall = "read";
11599
11730
  throw e;
11600
11731
  }
11601
- const bytes = syncFs.readFile(target);
11602
- if (encoding) return decoder3.decode(bytes);
11603
- return wrapBuffer(bytes);
11732
+ return decodeAs(syncFs.readFile(target), encoding);
11604
11733
  } catch (err) {
11605
11734
  if (err?.code && err.syscall) throw err;
11606
11735
  throw nodeFsError(err?.code || "ENOENT", "open", pathArg, err);
11607
11736
  }
11608
11737
  },
11609
11738
  writeFileSync(p, data2, options) {
11739
+ const bytes = encodeAs(data2, optEncoding(options));
11740
+ const flag = optFlag(options, "w");
11741
+ if (typeof p === "number") {
11742
+ syncApi.writeSync(p, bytes);
11743
+ return;
11744
+ }
11745
+ if (flag.includes("a")) {
11746
+ syncApi.appendFileSync(p, bytes);
11747
+ return;
11748
+ }
11610
11749
  const pathArg = p;
11611
11750
  const target = abs(p);
11612
- void options;
11751
+ if (flag.includes("x") && syncFs.exists(target)) throw nodeFsError("EEXIST", "open", pathArg);
11613
11752
  try {
11614
- syncFs.writeFile(target, toBytes(data2));
11753
+ syncFs.writeFile(target, bytes);
11615
11754
  } catch (err) {
11616
11755
  throw nodeFsError(err?.code || "EIO", "open", pathArg, err);
11617
11756
  }
11618
11757
  },
11619
11758
  appendFileSync(p, data2, options) {
11759
+ const next = encodeAs(data2, optEncoding(options));
11760
+ if (typeof p === "number") {
11761
+ const ent = fdTable.get(p);
11762
+ let end = null;
11763
+ if (ent) {
11764
+ try {
11765
+ end = syncFs.stat(ent.path).size ?? 0;
11766
+ } catch {
11767
+ end = 0;
11768
+ }
11769
+ }
11770
+ syncApi.writeSync(p, next, 0, next.length, end);
11771
+ return;
11772
+ }
11620
11773
  const pathArg = p;
11621
11774
  const target = abs(p);
11622
- void options;
11623
11775
  try {
11624
11776
  let prev = new Uint8Array(0);
11625
11777
  if (syncFs.exists(target)) prev = syncFs.readFile(target);
11626
- const next = toBytes(data2);
11627
11778
  const merged = new Uint8Array(prev.length + next.length);
11628
11779
  merged.set(prev);
11629
11780
  merged.set(next, prev.length);
@@ -11650,20 +11801,24 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11650
11801
  throw nodeFsError(err?.code || "ENOENT", "access", pathArg, err);
11651
11802
  }
11652
11803
  },
11653
- statSync(p) {
11804
+ statSync(p, options) {
11654
11805
  const pathArg = p;
11655
11806
  try {
11656
11807
  return statView(syncFs.stat(abs(p)));
11657
11808
  } catch (err) {
11658
- throw nodeFsError(err?.code || "ENOENT", "stat", pathArg, err);
11809
+ const code = err?.code || "ENOENT";
11810
+ if (options?.throwIfNoEntry === false && (code === "ENOENT" || code === "ENOTDIR")) return void 0;
11811
+ throw nodeFsError(code, "stat", pathArg, err);
11659
11812
  }
11660
11813
  },
11661
- lstatSync(p) {
11814
+ lstatSync(p, options) {
11662
11815
  const pathArg = p;
11663
11816
  try {
11664
11817
  return statView(syncFs.lstat(abs(p)));
11665
11818
  } catch (err) {
11666
- throw nodeFsError(err?.code || "ENOENT", "lstat", pathArg, err);
11819
+ const code = err?.code || "ENOENT";
11820
+ if (options?.throwIfNoEntry === false && (code === "ENOENT" || code === "ENOTDIR")) return void 0;
11821
+ throw nodeFsError(code, "lstat", pathArg, err);
11667
11822
  }
11668
11823
  },
11669
11824
  /**
@@ -11683,37 +11838,57 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11683
11838
  },
11684
11839
  readdirSync,
11685
11840
  mkdirSync,
11841
+ // The kernel's rm is recursive: only ever hand it an empty directory.
11686
11842
  rmdirSync(p, options = {}) {
11687
11843
  const pathArg = p;
11688
11844
  const target = abs(p);
11845
+ let st;
11689
11846
  try {
11690
- if (options.recursive) {
11691
- syncApi.rmSync(p, { recursive: true, force: options.force });
11692
- return;
11693
- }
11694
- syncFs.rm(target);
11847
+ st = syncFs.lstat(target);
11695
11848
  } catch (err) {
11696
11849
  throw nodeFsError(err?.code || "ENOENT", "rmdir", pathArg, err);
11697
11850
  }
11851
+ if (!st.isDirectory) throw nodeFsError("ENOTDIR", "rmdir", pathArg);
11852
+ if (options?.recursive) {
11853
+ syncApi.rmSync(p, { recursive: true, force: options.force });
11854
+ return;
11855
+ }
11856
+ let entries;
11857
+ try {
11858
+ entries = syncFs.readdir(target);
11859
+ } catch (err) {
11860
+ throw nodeFsError(err?.code || "EIO", "rmdir", pathArg, err);
11861
+ }
11862
+ if (entries.length > 0) throw nodeFsError("ENOTEMPTY", "rmdir", pathArg);
11863
+ try {
11864
+ syncFs.rm(target);
11865
+ } catch (err) {
11866
+ throw nodeFsError(err?.code || "EIO", "rmdir", pathArg, err);
11867
+ }
11698
11868
  },
11699
11869
  rmSync(p, options = {}) {
11700
11870
  const pathArg = p;
11701
11871
  const target = abs(p);
11872
+ let st;
11873
+ try {
11874
+ st = syncFs.lstat(target);
11875
+ } catch (err) {
11876
+ if (options?.force && (err?.code === "ENOENT" || err?.code === "ENOTDIR")) return;
11877
+ throw nodeFsError(err?.code || "ENOENT", "lstat", pathArg, err);
11878
+ }
11879
+ if (st.isDirectory && !options?.recursive) throw rmIsDirectoryError(pathArg);
11702
11880
  try {
11703
- const st = syncFs.lstat(target);
11704
11881
  if (st.isDirectory) {
11705
- if (options.recursive) {
11706
- for (const name of syncFs.readdir(target)) {
11707
- syncApi.rmSync(path.join(target, name), { recursive: true, force: options.force });
11708
- }
11882
+ for (const name of syncFs.readdir(target)) {
11883
+ syncApi.rmSync(path.join(target, name), { recursive: true, force: options.force });
11709
11884
  }
11710
11885
  syncFs.rm(target);
11711
11886
  } else {
11712
11887
  syncFs.unlink(target);
11713
11888
  }
11714
11889
  } catch (err) {
11715
- if (options.force && (err?.code === "ENOENT" || !syncFs.exists(target))) return;
11716
- throw nodeFsError(err?.code || "ENOENT", "rm", pathArg, err);
11890
+ if (err?.syscall) throw err;
11891
+ throw nodeFsError(err?.code || "EIO", "rm", pathArg, err);
11717
11892
  }
11718
11893
  },
11719
11894
  unlinkSync(p) {
@@ -11788,7 +11963,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11788
11963
  return n;
11789
11964
  }
11790
11965
  const ent = fdTable.get(fd);
11791
- if (!ent) throw nodeFsError("EBADF", "read", void 0);
11966
+ if (!ent || !ent.readable) throw nodeFsError("EBADF", "read", void 0);
11792
11967
  try {
11793
11968
  const bytes = syncFs.readFile(ent.path);
11794
11969
  const pos = filePosition == null ? ent.pos : filePosition;
@@ -11807,7 +11982,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11807
11982
  return bytes2.byteLength;
11808
11983
  }
11809
11984
  const ent = fdTable.get(fd);
11810
- if (!ent) throw nodeFsError("EBADF", "write", void 0);
11985
+ if (!ent || !ent.writable) throw nodeFsError("EBADF", "write", void 0);
11811
11986
  const { bytes, filePosition } = parseWriteSyncArgs(data2, offset2, length, position);
11812
11987
  try {
11813
11988
  return writeBytesAtPath(ent, bytes, filePosition);
@@ -11859,8 +12034,176 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11859
12034
  } catch (err) {
11860
12035
  throw nodeFsError(err?.code || "ENOENT", "readlink", p, err);
11861
12036
  }
12037
+ },
12038
+ copyFileSync(src, dest, mode = 0) {
12039
+ const from = abs(src);
12040
+ const to = abs(dest);
12041
+ let st;
12042
+ try {
12043
+ st = syncFs.stat(from);
12044
+ } catch (err) {
12045
+ throw nodeFsError(err?.code || "ENOENT", "copyfile", src, err, dest);
12046
+ }
12047
+ if (st.isDirectory) throw nodeFsError("EISDIR", "copyfile", src, void 0, dest);
12048
+ if (mode & 1 && syncFs.exists(to)) throw nodeFsError("EEXIST", "copyfile", src, void 0, dest);
12049
+ try {
12050
+ syncFs.writeFile(to, syncFs.readFile(from));
12051
+ } catch (err) {
12052
+ throw nodeFsError(err?.code || "EIO", "copyfile", src, err, dest);
12053
+ }
12054
+ },
12055
+ cpSync(src, dest, options = {}) {
12056
+ const from = abs(src);
12057
+ const to = abs(dest);
12058
+ if (from === to) throw cpInvalid(`src and dest cannot be the same ${src}`);
12059
+ if (to.startsWith(`${from}/`)) {
12060
+ throw cpInvalid(`Cannot copy ${src}/ to a subdirectory of self ${dest}`);
12061
+ }
12062
+ let st;
12063
+ try {
12064
+ st = syncFs.stat(from);
12065
+ } catch (err) {
12066
+ throw nodeFsError(err?.code || "ENOENT", "cp", src, err);
12067
+ }
12068
+ if (st.isDirectory) {
12069
+ if (!options?.recursive) {
12070
+ const e = new Error(`Recursive option not enabled, cannot copy a directory: ${src}/`);
12071
+ e.code = "ERR_FS_EISDIR";
12072
+ throw e;
12073
+ }
12074
+ mkdirSync(to, { recursive: true });
12075
+ for (const name of syncFs.readdir(from)) {
12076
+ syncApi.cpSync(path.join(from, name), path.join(to, name), options);
12077
+ }
12078
+ return;
12079
+ }
12080
+ const exists = syncFs.exists(to);
12081
+ if (exists && options?.errorOnExist && options?.force === false) {
12082
+ const e = new Error(`Target already exists: cp returned EEXIST (${to} already exists)`);
12083
+ e.name = "SystemError";
12084
+ e.code = "ERR_FS_CP_EEXIST";
12085
+ throw e;
12086
+ }
12087
+ if (exists && options?.force === false) return;
12088
+ syncFs.writeFile(to, syncFs.readFile(from));
12089
+ },
12090
+ mkdtempSync(prefix, options) {
12091
+ const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
12092
+ const bytes = new Uint8Array(6);
12093
+ for (let attempt = 0; attempt < 100; attempt++) {
12094
+ crypto.getRandomValues(bytes);
12095
+ const name = `${prefix}${[...bytes].map((b) => chars[b % chars.length]).join("")}`;
12096
+ const target = abs(name);
12097
+ if (syncFs.exists(target)) continue;
12098
+ try {
12099
+ syncFs.mkdir(target);
12100
+ } catch (err) {
12101
+ throw nodeFsError(err?.code || "ENOENT", "mkdtemp", `${prefix}XXXXXX`, err);
12102
+ }
12103
+ return optEncoding(options) === "buffer" ? wrapBuffer(encoder3.encode(name)) : name;
12104
+ }
12105
+ throw nodeFsError("EEXIST", "mkdtemp", `${prefix}XXXXXX`);
12106
+ },
12107
+ truncateSync(p, len = 0) {
12108
+ if (typeof p === "number") {
12109
+ syncApi.ftruncateSync(p, len);
12110
+ return;
12111
+ }
12112
+ const target = abs(p);
12113
+ let cur;
12114
+ try {
12115
+ cur = syncFs.readFile(target);
12116
+ } catch (err) {
12117
+ throw nodeFsError(err?.code || "ENOENT", "open", p, err);
12118
+ }
12119
+ const out = new Uint8Array(Math.max(0, len));
12120
+ out.set(cur.subarray(0, Math.min(cur.length, out.length)), 0);
12121
+ syncFs.writeFile(target, out);
12122
+ },
12123
+ // The kernel's JS fs has no mode bits, owners or times to set: these
12124
+ // check that the path exists, as Node's do, and change nothing.
12125
+ chmodSync(p) {
12126
+ mustExist(p, "chmod");
12127
+ },
12128
+ lchmodSync(p) {
12129
+ mustExist(p, "lchmod");
12130
+ },
12131
+ fchmodSync(fd) {
12132
+ syncApi.fstatSync(fd);
12133
+ },
12134
+ chownSync(p) {
12135
+ mustExist(p, "chown");
12136
+ },
12137
+ lchownSync(p) {
12138
+ mustExist(p, "lchown");
12139
+ },
12140
+ fchownSync(fd) {
12141
+ syncApi.fstatSync(fd);
12142
+ },
12143
+ utimesSync(p) {
12144
+ mustExist(p, "utime");
12145
+ },
12146
+ lutimesSync(p) {
12147
+ mustExist(p, "lutime");
12148
+ },
12149
+ futimesSync(fd) {
12150
+ syncApi.fstatSync(fd);
12151
+ },
12152
+ fsyncSync(fd) {
12153
+ if (fd !== 0 && fd !== 1 && fd !== 2 && !fdTable.has(fd)) throw nodeFsError("EBADF", "fsync", void 0);
12154
+ },
12155
+ fdatasyncSync(fd) {
12156
+ if (fd !== 0 && fd !== 1 && fd !== 2 && !fdTable.has(fd)) throw nodeFsError("EBADF", "fdatasync", void 0);
12157
+ },
12158
+ opendirSync(p) {
12159
+ const entries = readdirSync(p, { withFileTypes: true });
12160
+ return createDir(String(p), entries);
11862
12161
  }
11863
12162
  };
12163
+ function createDir(dirPath, entries) {
12164
+ let closed = false;
12165
+ const next = () => {
12166
+ if (closed) {
12167
+ const e = new Error("Directory handle was closed");
12168
+ e.code = "ERR_DIR_CLOSED";
12169
+ throw e;
12170
+ }
12171
+ return entries.length ? entries.shift() : null;
12172
+ };
12173
+ return {
12174
+ path: dirPath,
12175
+ readSync: next,
12176
+ read(cb) {
12177
+ if (typeof cb === "function") {
12178
+ queueMicrotask(() => {
12179
+ try {
12180
+ cb(null, next());
12181
+ } catch (err) {
12182
+ cb(err);
12183
+ }
12184
+ });
12185
+ return void 0;
12186
+ }
12187
+ return Promise.resolve().then(next);
12188
+ },
12189
+ closeSync() {
12190
+ closed = true;
12191
+ },
12192
+ close(cb) {
12193
+ closed = true;
12194
+ if (typeof cb === "function") queueMicrotask(() => cb(null));
12195
+ else return Promise.resolve();
12196
+ return void 0;
12197
+ },
12198
+ async *[Symbol.asyncIterator]() {
12199
+ try {
12200
+ for (let d = next(); d; d = next()) yield d;
12201
+ } finally {
12202
+ closed = true;
12203
+ }
12204
+ }
12205
+ };
12206
+ }
11864
12207
  function requireCallback(cb) {
11865
12208
  if (typeof cb === "function") return cb;
11866
12209
  let received;
@@ -11902,11 +12245,9 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11902
12245
  readFile(p, options) {
11903
12246
  return track(
11904
12247
  (async () => {
11905
- const encoding = typeof options === "string" ? options : options?.encoding;
12248
+ const encoding = optEncoding(options);
11906
12249
  try {
11907
- const bytes = await asyncFs.readFile(abs(p));
11908
- if (encoding) return decoder3.decode(bytes);
11909
- return wrapBuffer(bytes);
12250
+ return decodeAs(await asyncFs.readFile(abs(p)), encoding);
11910
12251
  } catch (err) {
11911
12252
  throw nodeFsError(err?.code || "ENOENT", "open", p, err);
11912
12253
  }
@@ -11916,23 +12257,27 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11916
12257
  writeFile(p, data2, options) {
11917
12258
  return track(
11918
12259
  (async () => {
11919
- void options;
12260
+ const bytes = encodeAs(data2, optEncoding(options));
12261
+ const flag = optFlag(options, "w");
12262
+ if (flag.includes("a")) return promises.appendFile(p, bytes);
12263
+ const target = abs(p);
12264
+ if (flag.includes("x") && await asyncFs.exists(target)) throw nodeFsError("EEXIST", "open", p);
11920
12265
  try {
11921
- await asyncFs.writeFile(abs(p), toBytes(data2));
12266
+ await asyncFs.writeFile(target, bytes);
11922
12267
  } catch (err) {
11923
12268
  throw nodeFsError(err?.code || "EIO", "open", p, err);
11924
12269
  }
12270
+ return void 0;
11925
12271
  })()
11926
12272
  );
11927
12273
  },
11928
12274
  appendFile(p, data2, options) {
11929
12275
  return track(
11930
12276
  (async () => {
11931
- void options;
11932
12277
  const target = abs(p);
11933
12278
  let prev = new Uint8Array(0);
11934
12279
  if (await asyncFs.exists(target)) prev = await asyncFs.readFile(target);
11935
- const next = toBytes(data2);
12280
+ const next = encodeAs(data2, optEncoding(options));
11936
12281
  const merged = new Uint8Array(prev.length + next.length);
11937
12282
  merged.set(prev);
11938
12283
  merged.set(next, prev.length);
@@ -11963,75 +12308,52 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11963
12308
  );
11964
12309
  },
11965
12310
  readdir(p, options) {
11966
- return track(
11967
- (async () => {
11968
- try {
11969
- const names = await asyncFs.readdir(abs(p));
11970
- if (options?.withFileTypes) {
11971
- const out = [];
11972
- for (const name of names) {
11973
- let type = "unknown";
11974
- try {
11975
- const st = await asyncFs.lstat(path.join(abs(p), name));
11976
- type = st.isDirectory ? "dir" : st.isSymbolicLink ? "link" : st.isFile ? "file" : "unknown";
11977
- } catch {
11978
- }
11979
- out.push(new Dirent(name, type));
11980
- }
11981
- return out;
11982
- }
11983
- return names;
11984
- } catch (err) {
11985
- throw nodeFsError(err?.code || "ENOENT", "scandir", p, err);
11986
- }
11987
- })()
11988
- );
12311
+ return track((async () => readdirSync(p, options))());
11989
12312
  },
11990
12313
  mkdir(p, options = {}) {
11991
- return track(
11992
- (async () => {
11993
- const target = abs(p);
11994
- if (options?.recursive) {
11995
- const parts = String(target).split("/").filter(Boolean);
11996
- let cur = "";
11997
- for (const part of parts) {
11998
- cur += `/${part}`;
11999
- if (await asyncFs.exists(cur)) continue;
12000
- try {
12001
- await asyncFs.mkdir(cur);
12002
- } catch (err) {
12003
- if (err?.code !== "EEXIST") throw nodeFsError(err?.code || "EIO", "mkdir", p, err);
12004
- }
12005
- }
12006
- return;
12007
- }
12008
- if (await asyncFs.exists(target)) throw nodeFsError("EEXIST", "mkdir", p);
12009
- await asyncFs.mkdir(target);
12010
- })()
12011
- );
12314
+ return track((async () => mkdirSync(p, options))());
12012
12315
  },
12013
12316
  rm(p, options = {}) {
12014
- return track(
12015
- (async () => {
12016
- const target = abs(p);
12017
- try {
12018
- const st = await asyncFs.lstat(target);
12019
- if (st.isDirectory) {
12020
- if (options.recursive) {
12021
- for (const name of await asyncFs.readdir(target)) {
12022
- await promises.rm(path.join(target, name), { recursive: true, force: options.force });
12023
- }
12024
- }
12025
- await asyncFs.rm(target);
12026
- } else {
12027
- await asyncFs.unlink(target);
12028
- }
12029
- } catch (err) {
12030
- if (options.force && err?.code === "ENOENT") return;
12031
- throw nodeFsError(err?.code || "ENOENT", "rm", p, err);
12032
- }
12033
- })()
12034
- );
12317
+ return track((async () => syncApi.rmSync(p, options))());
12318
+ },
12319
+ rmdir(p, options = {}) {
12320
+ return track((async () => syncApi.rmdirSync(p, options))());
12321
+ },
12322
+ copyFile(src, dest, mode) {
12323
+ return track((async () => syncApi.copyFileSync(src, dest, mode))());
12324
+ },
12325
+ cp(src, dest, options) {
12326
+ return track((async () => syncApi.cpSync(src, dest, options))());
12327
+ },
12328
+ mkdtemp(prefix, options) {
12329
+ return track((async () => syncApi.mkdtempSync(prefix, options))());
12330
+ },
12331
+ truncate(p, len) {
12332
+ return track((async () => syncApi.truncateSync(p, len))());
12333
+ },
12334
+ realpath(p) {
12335
+ return track((async () => syncApi.realpathSync(p))());
12336
+ },
12337
+ chmod(p) {
12338
+ return track((async () => syncApi.chmodSync(p))());
12339
+ },
12340
+ lchmod(p) {
12341
+ return track((async () => syncApi.lchmodSync(p))());
12342
+ },
12343
+ chown(p) {
12344
+ return track((async () => syncApi.chownSync(p))());
12345
+ },
12346
+ lchown(p) {
12347
+ return track((async () => syncApi.lchownSync(p))());
12348
+ },
12349
+ utimes(p) {
12350
+ return track((async () => syncApi.utimesSync(p))());
12351
+ },
12352
+ lutimes(p) {
12353
+ return track((async () => syncApi.lutimesSync(p))());
12354
+ },
12355
+ opendir(p) {
12356
+ return track((async () => syncApi.opendirSync(p))());
12035
12357
  },
12036
12358
  unlink(p) {
12037
12359
  return track(
@@ -12120,10 +12442,32 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12120
12442
  ensureOpen("truncate");
12121
12443
  syncApi.ftruncateSync(fd, len);
12122
12444
  },
12445
+ async readFile(options) {
12446
+ ensureOpen("readFile");
12447
+ return syncApi.readFileSync(fd, options);
12448
+ },
12449
+ async sync() {
12450
+ ensureOpen("fsync");
12451
+ },
12452
+ async datasync() {
12453
+ ensureOpen("fdatasync");
12454
+ },
12455
+ async chmod() {
12456
+ ensureOpen("fchmod");
12457
+ },
12458
+ async chown() {
12459
+ ensureOpen("fchown");
12460
+ },
12461
+ async utimes() {
12462
+ ensureOpen("futimes");
12463
+ },
12123
12464
  async close() {
12124
12465
  ensureOpen("close");
12125
12466
  closed = true;
12126
12467
  syncApi.closeSync(fd);
12468
+ },
12469
+ async [Symbol.asyncDispose ?? /* @__PURE__ */ Symbol.for("nodejs.asyncDispose")]() {
12470
+ if (!closed) await handle.close();
12127
12471
  }
12128
12472
  };
12129
12473
  return handle;
@@ -12185,6 +12529,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12185
12529
  });
12186
12530
  r.path = p;
12187
12531
  r.bytesRead = 0;
12532
+ Object.defineProperty(r, FS_READ_STREAM, { value: true });
12188
12533
  if (!openEmitted) {
12189
12534
  queueMicrotask(() => {
12190
12535
  if (openEmitted || r.destroyed) return;
@@ -12248,6 +12593,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12248
12593
  });
12249
12594
  w.path = p;
12250
12595
  w.bytesWritten = 0;
12596
+ Object.defineProperty(w, FS_WRITE_STREAM, { value: true });
12251
12597
  if (!openEmitted) {
12252
12598
  queueMicrotask(() => {
12253
12599
  if (openEmitted || w.destroyed) return;
@@ -12270,10 +12616,20 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12270
12616
  }
12271
12617
  return w;
12272
12618
  }
12619
+ function ReadStream(p, options) {
12620
+ return createReadStream(p, options);
12621
+ }
12622
+ Object.defineProperty(ReadStream, Symbol.hasInstance, { value: (x) => !!x?.[FS_READ_STREAM] });
12623
+ function WriteStream(p, options) {
12624
+ return createWriteStream(p, options);
12625
+ }
12626
+ Object.defineProperty(WriteStream, Symbol.hasInstance, { value: (x) => !!x?.[FS_WRITE_STREAM] });
12273
12627
  return {
12274
12628
  ...syncApi,
12275
12629
  promises,
12276
12630
  Dirent,
12631
+ ReadStream,
12632
+ WriteStream,
12277
12633
  createReadStream,
12278
12634
  createWriteStream,
12279
12635
  readFile: callbackify(syncApi.readFileSync),
@@ -12321,10 +12677,55 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12321
12677
  lstat: callbackify(syncApi.lstatSync),
12322
12678
  realpath: callbackify(syncApi.realpathSync),
12323
12679
  readdir: callbackify(syncApi.readdirSync),
12324
- mkdir: callbackify(syncApi.mkdirSync),
12680
+ mkdir: callbackify(syncApi.mkdirSync, { minArgsBeforeCb: 2 }),
12325
12681
  rmdir: callbackify(syncApi.rmdirSync),
12326
12682
  unlink: callbackify(syncApi.unlinkSync),
12327
12683
  rename: callbackify(syncApi.renameSync, { minArgsBeforeCb: 2 }),
12684
+ // Node 22's rm does not check its callback up front: without one it does
12685
+ // the work, then calls the missing callback and throws from there.
12686
+ rm(p, options, callback) {
12687
+ const cb = typeof options === "function" ? options : callback;
12688
+ const opts = typeof options === "function" ? void 0 : options;
12689
+ if (typeof cb === "function") return callbackify(syncApi.rmSync)(p, opts ?? {}, cb);
12690
+ let err = null;
12691
+ try {
12692
+ syncApi.rmSync(p, opts ?? {});
12693
+ } catch (e) {
12694
+ err = e;
12695
+ }
12696
+ void err;
12697
+ setTimeout(() => {
12698
+ const e = new TypeError("callback is not a function");
12699
+ e._fsPretty = `node:fs:1225
12700
+ return callback(err);
12701
+ ^
12702
+
12703
+ ${e.stack}
12704
+ `;
12705
+ throw e;
12706
+ }, 0);
12707
+ return void 0;
12708
+ },
12709
+ copyFile: callbackify(syncApi.copyFileSync, { minArgsBeforeCb: 2 }),
12710
+ cp: callbackify(syncApi.cpSync, { minArgsBeforeCb: 2 }),
12711
+ mkdtemp: callbackify(syncApi.mkdtempSync),
12712
+ truncate: callbackify(syncApi.truncateSync),
12713
+ ftruncate: callbackify(syncApi.ftruncateSync),
12714
+ chmod: callbackify(syncApi.chmodSync, { minArgsBeforeCb: 2 }),
12715
+ lchmod: callbackify(syncApi.lchmodSync, { minArgsBeforeCb: 2 }),
12716
+ fchmod: callbackify(syncApi.fchmodSync, { minArgsBeforeCb: 2 }),
12717
+ chown: callbackify(syncApi.chownSync, { minArgsBeforeCb: 3 }),
12718
+ lchown: callbackify(syncApi.lchownSync, { minArgsBeforeCb: 3 }),
12719
+ fchown: callbackify(syncApi.fchownSync, { minArgsBeforeCb: 3 }),
12720
+ utimes: callbackify(syncApi.utimesSync, { minArgsBeforeCb: 3 }),
12721
+ lutimes: callbackify(syncApi.lutimesSync, { minArgsBeforeCb: 3 }),
12722
+ futimes: callbackify(syncApi.futimesSync, { minArgsBeforeCb: 3 }),
12723
+ fsync: callbackify(syncApi.fsyncSync),
12724
+ fdatasync: callbackify(syncApi.fdatasyncSync),
12725
+ opendir: callbackify(syncApi.opendirSync),
12726
+ symlink: callbackify(syncApi.symlinkSync, { minArgsBeforeCb: 2 }),
12727
+ readlink: callbackify(syncApi.readlinkSync),
12728
+ Stats,
12328
12729
  constants: {
12329
12730
  F_OK: 0,
12330
12731
  R_OK: 4,
@@ -12335,7 +12736,15 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12335
12736
  O_RDWR: 2,
12336
12737
  O_CREAT: 64,
12337
12738
  O_TRUNC: 512,
12338
- O_APPEND: 1024
12739
+ O_APPEND: 1024,
12740
+ O_EXCL: 128,
12741
+ S_IFMT,
12742
+ S_IFREG,
12743
+ S_IFDIR,
12744
+ S_IFLNK,
12745
+ COPYFILE_EXCL: 1,
12746
+ COPYFILE_FICLONE: 2,
12747
+ COPYFILE_FICLONE_FORCE: 4
12339
12748
  }
12340
12749
  };
12341
12750
  }