shell-dsl 0.0.31 → 0.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -564,7 +564,7 @@ import { echo, cat, grep, wc, cp, mv, touch, tee, tree, find, sed, awk, cut } fr
564
564
  | `mv` | Move/rename files/directories (`-n` no-clobber) |
565
565
  | `touch` | Create empty files or update timestamps (`-c` no-create) |
566
566
  | `tee` | Duplicate stdin to stdout and files (`-a` append) |
567
- | `tree` | Display directory structure as tree (`-a` all, `-d` dirs only, `-L <n>` depth) |
567
+ | `tree` | Display directory structure as tree (`-a` all, `-d` dirs only, `-L <n>` depth, `-I <pattern>` ignore, `--prune` remove empty dirs) |
568
568
  | `find` | Search for files (`-name`, `-iname`, `-type f\|d`, `-maxdepth`, `-mindepth`) |
569
569
  | `sed` | Stream editor (`s///`, `d`, `p`, `-n`, `-e`) |
570
570
  | `awk` | Pattern scanning (`{print $1}`, `-F`, `NF`, `NR`) |
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "shell-dsl",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "type": "commonjs"
5
5
  }
@@ -43,6 +43,7 @@ __export(exports_mv, {
43
43
  });
44
44
  module.exports = __toCommonJS(exports_mv);
45
45
  var import_flag_parser = require("../../utils/flag-parser.cjs");
46
+ var import_special_files = require("../../fs/special-files.cjs");
46
47
  var spec = {
47
48
  name: "mv",
48
49
  flags: [
@@ -88,6 +89,11 @@ var mv = async (ctx) => {
88
89
  try {
89
90
  await ctx.fs.stat(srcPath);
90
91
  const finalDest = destIsDir ? ctx.fs.resolve(destPath, ctx.fs.basename(srcPath)) : destPath;
92
+ if (import_special_files.isDevNullPath(srcPath) || import_special_files.isDevNullPath(finalDest)) {
93
+ await ctx.stderr.writeText(`mv: cannot move to or from special file '${import_special_files.DEV_NULL_PATH}'
94
+ `);
95
+ return 1;
96
+ }
91
97
  if (noClobber) {
92
98
  const exists = await ctx.fs.exists(finalDest);
93
99
  if (exists)
@@ -132,4 +138,4 @@ async function moveDirectory(ctx, src, dest, noClobber) {
132
138
  await ctx.fs.rm(src, { recursive: true });
133
139
  }
134
140
 
135
- //# debugId=54B51AB3A551E2C964756E2164756E21
141
+ //# debugId=C4CE62A58C3EA07364756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/commands/mv/mv.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../../types.cjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.cjs\";\n\ninterface MvFlags {\n noClobber: boolean;\n}\n\nconst spec = {\n name: \"mv\",\n flags: [\n { short: \"n\", long: \"no-clobber\" },\n { short: \"f\", long: \"force\" },\n ] as FlagDefinition[],\n usage: \"mv [-nf] source ... dest\",\n};\n\nconst defaults: MvFlags = { noClobber: false };\n\nconst handler = (flags: MvFlags, flag: FlagDefinition) => {\n if (flag.short === \"n\") flags.noClobber = true;\n // -f is default behavior, so we don't need to do anything\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const mv: Command = async (ctx) => {\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n const { noClobber } = result.flags;\n const paths = result.args;\n\n if (paths.length < 2) {\n await ctx.stderr.writeText(\"mv: missing destination file operand\\n\");\n return 1;\n }\n\n const sources = paths.slice(0, -1);\n const dest = paths[paths.length - 1]!;\n const destPath = ctx.fs.resolve(ctx.cwd, dest);\n\n // Check if destination is a directory\n let destIsDir = false;\n try {\n const stat = await ctx.fs.stat(destPath);\n destIsDir = stat.isDirectory();\n } catch {\n // Destination doesn't exist\n }\n\n // If multiple sources, dest must be a directory\n if (sources.length > 1 && !destIsDir) {\n await ctx.stderr.writeText(`mv: target '${dest}' is not a directory\\n`);\n return 1;\n }\n\n for (const source of sources) {\n const srcPath = ctx.fs.resolve(ctx.cwd, source);\n\n try {\n // Check source exists\n await ctx.fs.stat(srcPath);\n\n // Determine final destination path\n const finalDest = destIsDir\n ? ctx.fs.resolve(destPath, ctx.fs.basename(srcPath))\n : destPath;\n\n // Check if dest exists and noClobber\n if (noClobber) {\n const exists = await ctx.fs.exists(finalDest);\n if (exists) continue; // Skip silently\n }\n\n // Move: copy then delete\n const srcStat = await ctx.fs.stat(srcPath);\n if (srcStat.isDirectory()) {\n await moveDirectory(ctx, srcPath, finalDest, noClobber);\n } else {\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(finalDest, content);\n await ctx.fs.rm(srcPath);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`mv: cannot stat '${source}': ${message}\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n\nasync function moveDirectory(\n ctx: Parameters<Command>[0],\n src: string,\n dest: string,\n noClobber: boolean\n): Promise<void> {\n // Create destination directory\n await ctx.fs.mkdir(dest, { recursive: true });\n\n // Read source directory contents\n const entries = await ctx.fs.readdir(src);\n\n for (const entry of entries) {\n const srcPath = ctx.fs.resolve(src, entry);\n const destPath = ctx.fs.resolve(dest, entry);\n\n const stat = await ctx.fs.stat(srcPath);\n\n if (stat.isDirectory()) {\n await moveDirectory(ctx, srcPath, destPath, noClobber);\n } else {\n if (noClobber) {\n const exists = await ctx.fs.exists(destPath);\n if (exists) continue;\n }\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(destPath, content);\n }\n }\n\n // Remove source directory after copying\n await ctx.fs.rm(src, { recursive: true });\n}\n"
5
+ "import type { Command } from \"../../types.cjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.cjs\";\nimport { DEV_NULL_PATH, isDevNullPath } from \"../../fs/special-files.cjs\";\n\ninterface MvFlags {\n noClobber: boolean;\n}\n\nconst spec = {\n name: \"mv\",\n flags: [\n { short: \"n\", long: \"no-clobber\" },\n { short: \"f\", long: \"force\" },\n ] as FlagDefinition[],\n usage: \"mv [-nf] source ... dest\",\n};\n\nconst defaults: MvFlags = { noClobber: false };\n\nconst handler = (flags: MvFlags, flag: FlagDefinition) => {\n if (flag.short === \"n\") flags.noClobber = true;\n // -f is default behavior, so we don't need to do anything\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const mv: Command = async (ctx) => {\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n const { noClobber } = result.flags;\n const paths = result.args;\n\n if (paths.length < 2) {\n await ctx.stderr.writeText(\"mv: missing destination file operand\\n\");\n return 1;\n }\n\n const sources = paths.slice(0, -1);\n const dest = paths[paths.length - 1]!;\n const destPath = ctx.fs.resolve(ctx.cwd, dest);\n\n // Check if destination is a directory\n let destIsDir = false;\n try {\n const stat = await ctx.fs.stat(destPath);\n destIsDir = stat.isDirectory();\n } catch {\n // Destination doesn't exist\n }\n\n // If multiple sources, dest must be a directory\n if (sources.length > 1 && !destIsDir) {\n await ctx.stderr.writeText(`mv: target '${dest}' is not a directory\\n`);\n return 1;\n }\n\n for (const source of sources) {\n const srcPath = ctx.fs.resolve(ctx.cwd, source);\n\n try {\n // Check source exists\n await ctx.fs.stat(srcPath);\n\n // Determine final destination path\n const finalDest = destIsDir\n ? ctx.fs.resolve(destPath, ctx.fs.basename(srcPath))\n : destPath;\n\n if (isDevNullPath(srcPath) || isDevNullPath(finalDest)) {\n await ctx.stderr.writeText(`mv: cannot move to or from special file '${DEV_NULL_PATH}'\\n`);\n return 1;\n }\n\n // Check if dest exists and noClobber\n if (noClobber) {\n const exists = await ctx.fs.exists(finalDest);\n if (exists) continue; // Skip silently\n }\n\n // Move: copy then delete\n const srcStat = await ctx.fs.stat(srcPath);\n if (srcStat.isDirectory()) {\n await moveDirectory(ctx, srcPath, finalDest, noClobber);\n } else {\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(finalDest, content);\n await ctx.fs.rm(srcPath);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`mv: cannot stat '${source}': ${message}\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n\nasync function moveDirectory(\n ctx: Parameters<Command>[0],\n src: string,\n dest: string,\n noClobber: boolean\n): Promise<void> {\n // Create destination directory\n await ctx.fs.mkdir(dest, { recursive: true });\n\n // Read source directory contents\n const entries = await ctx.fs.readdir(src);\n\n for (const entry of entries) {\n const srcPath = ctx.fs.resolve(src, entry);\n const destPath = ctx.fs.resolve(dest, entry);\n\n const stat = await ctx.fs.stat(srcPath);\n\n if (stat.isDirectory()) {\n await moveDirectory(ctx, srcPath, destPath, noClobber);\n } else {\n if (noClobber) {\n const exists = await ctx.fs.exists(destPath);\n if (exists) continue;\n }\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(destPath, content);\n }\n }\n\n // Remove source directory after copying\n await ctx.fs.rm(src, { recursive: true });\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "54B51AB3A551E2C964756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "C4CE62A58C3EA07364756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -51,11 +51,19 @@ var spec = {
51
51
  { short: "d" },
52
52
  { short: "L", takesValue: true },
53
53
  { short: "I", takesValue: true },
54
- { long: "dirsfirst" }
54
+ { long: "dirsfirst" },
55
+ { long: "prune" }
55
56
  ],
56
- usage: "tree [-adI] [-L level] [-I pattern] [--dirsfirst] [directory ...]"
57
+ usage: "tree [-adI] [-L level] [-I pattern] [--dirsfirst] [--prune] [directory ...]"
58
+ };
59
+ var defaults = {
60
+ all: false,
61
+ directoriesOnly: false,
62
+ maxDepth: Infinity,
63
+ dirsfirst: true,
64
+ prune: false,
65
+ ignorePatterns: []
57
66
  };
58
- var defaults = { all: false, directoriesOnly: false, maxDepth: Infinity, dirsfirst: true, ignorePatterns: [] };
59
67
  var handlerResult = {};
60
68
  var handler = (flags, flag, value) => {
61
69
  if (flag.short === "a")
@@ -64,6 +72,8 @@ var handler = (flags, flag, value) => {
64
72
  flags.directoriesOnly = true;
65
73
  if (flag.long === "dirsfirst")
66
74
  flags.dirsfirst = true;
75
+ if (flag.long === "prune")
76
+ flags.prune = true;
67
77
  if (flag.short === "I" && value) {
68
78
  if (flags.ignorePatterns === defaults.ignorePatterns) {
69
79
  flags.ignorePatterns = [];
@@ -93,7 +103,7 @@ var tree = async (ctx) => {
93
103
  await ctx.stderr.writeText(handlerResult.error);
94
104
  return 1;
95
105
  }
96
- const { all: showAll, directoriesOnly, maxDepth, ignorePatterns } = result.flags;
106
+ const { all: showAll, directoriesOnly, maxDepth, prune, ignorePatterns } = result.flags;
97
107
  const targetPath = result.args[0] ?? ".";
98
108
  if (maxDepth < 1) {
99
109
  await ctx.stderr.writeText(`tree: Invalid level, must be greater than 0
@@ -118,11 +128,14 @@ var tree = async (ctx) => {
118
128
  }
119
129
  let dirCount = 0;
120
130
  let fileCount = 0;
131
+ const entriesCache = new Map;
132
+ const visibleContentCache = new Map;
121
133
  await ctx.stdout.writeText(targetPath + `
122
134
  `);
123
- async function printTree(path, prefix, depth) {
124
- if (depth > maxDepth)
125
- return;
135
+ async function getEntries(path) {
136
+ const cached = entriesCache.get(path);
137
+ if (cached)
138
+ return cached;
126
139
  let entries = await ctx.fs.readdir(path);
127
140
  if (!showAll) {
128
141
  entries = entries.filter((e) => !e.startsWith("."));
@@ -131,39 +144,63 @@ var tree = async (ctx) => {
131
144
  entries = entries.filter((e) => !ignorePatterns.some((p) => import_match_glob.matchGlob(p, e)));
132
145
  }
133
146
  entries.sort();
147
+ const resolvedEntries = [];
148
+ for (const name of entries) {
149
+ const entryPath = ctx.fs.resolve(path, name);
150
+ try {
151
+ const entryStat = await ctx.fs.stat(entryPath);
152
+ resolvedEntries.push({ name, path: entryPath, isDir: entryStat.isDirectory() });
153
+ } catch {}
154
+ }
155
+ entriesCache.set(path, resolvedEntries);
156
+ return resolvedEntries;
157
+ }
158
+ async function hasVisibleContent(path) {
159
+ const cached = visibleContentCache.get(path);
160
+ if (cached !== undefined)
161
+ return cached;
162
+ const entries = await getEntries(path);
163
+ for (const entry of entries) {
164
+ if (!entry.isDir) {
165
+ visibleContentCache.set(path, true);
166
+ return true;
167
+ }
168
+ if (await hasVisibleContent(entry.path)) {
169
+ visibleContentCache.set(path, true);
170
+ return true;
171
+ }
172
+ }
173
+ visibleContentCache.set(path, false);
174
+ return false;
175
+ }
176
+ async function printTree(path, prefix, depth) {
177
+ if (depth > maxDepth)
178
+ return;
179
+ const entries = await getEntries(path);
134
180
  const dirEntries = [];
135
181
  const fileEntries = [];
136
182
  for (const entry of entries) {
137
- const entryPath = ctx.fs.resolve(path, entry);
138
- try {
139
- const entryStat = await ctx.fs.stat(entryPath);
140
- if (entryStat.isDirectory()) {
141
- dirEntries.push(entry);
142
- } else {
143
- fileEntries.push(entry);
183
+ if (entry.isDir) {
184
+ if (prune && !await hasVisibleContent(entry.path)) {
185
+ continue;
144
186
  }
145
- } catch {}
187
+ dirEntries.push(entry);
188
+ } else {
189
+ fileEntries.push(entry);
190
+ }
146
191
  }
147
192
  const sortedEntries = directoriesOnly ? dirEntries : [...dirEntries, ...fileEntries];
148
193
  for (let i = 0;i < sortedEntries.length; i++) {
149
194
  const entry = sortedEntries[i];
150
195
  const isLast = i === sortedEntries.length - 1;
151
196
  const connector = isLast ? "└── " : "├── ";
152
- const entryPath = ctx.fs.resolve(path, entry);
153
- let isDir = false;
154
- try {
155
- const entryStat = await ctx.fs.stat(entryPath);
156
- isDir = entryStat.isDirectory();
157
- } catch {
158
- continue;
159
- }
160
- await ctx.stdout.writeText(prefix + connector + entry + `
197
+ await ctx.stdout.writeText(prefix + connector + entry.name + `
161
198
  `);
162
- if (isDir) {
199
+ if (entry.isDir) {
163
200
  dirCount++;
164
201
  if (depth < maxDepth) {
165
202
  const newPrefix = prefix + (isLast ? " " : "│ ");
166
- await printTree(entryPath, newPrefix, depth + 1);
203
+ await printTree(entry.path, newPrefix, depth + 1);
167
204
  }
168
205
  } else {
169
206
  fileCount++;
@@ -179,4 +216,4 @@ ${dirCount} ${dirWord}, ${fileCount} ${fileWord}
179
216
  return 0;
180
217
  };
181
218
 
182
- //# debugId=84C05E2FE694C09E64756E2164756E21
219
+ //# debugId=F4832ADA9F283A9964756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/commands/tree/tree.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../../types.cjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.cjs\";\nimport { matchGlob } from \"../../utils/match-glob.cjs\";\n\ninterface TreeFlags {\n all: boolean;\n directoriesOnly: boolean;\n maxDepth: number;\n dirsfirst: boolean;\n ignorePatterns: string[];\n}\n\nconst spec = {\n name: \"tree\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"d\" },\n { short: \"L\", takesValue: true },\n { short: \"I\", takesValue: true },\n { long: \"dirsfirst\" },\n ] as FlagDefinition[],\n usage: \"tree [-adI] [-L level] [-I pattern] [--dirsfirst] [directory ...]\",\n};\n\nconst defaults: TreeFlags = { all: false, directoriesOnly: false, maxDepth: Infinity, dirsfirst: true, ignorePatterns: [] };\n\ninterface HandlerResult {\n error?: string;\n}\n\nlet handlerResult: HandlerResult = {};\n\nconst handler = (flags: TreeFlags, flag: FlagDefinition, value?: string) => {\n if (flag.short === \"a\") flags.all = true;\n if (flag.short === \"d\") flags.directoriesOnly = true;\n if (flag.long === \"dirsfirst\") flags.dirsfirst = true;\n if (flag.short === \"I\" && value) {\n if (flags.ignorePatterns === defaults.ignorePatterns) {\n flags.ignorePatterns = [];\n }\n flags.ignorePatterns.push(...value.split(\"|\"));\n }\n if (flag.short === \"L\" && value) {\n const depth = parseInt(value, 10);\n if (isNaN(depth) || !/^\\d+$/.test(value)) {\n handlerResult.error = `tree: -L option requires a numeric argument\\nusage: ${spec.usage}\\n`;\n } else {\n flags.maxDepth = depth;\n }\n }\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const tree: Command = async (ctx) => {\n // Reset handler result for each invocation\n handlerResult = {};\n\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n if (handlerResult.error) {\n await ctx.stderr.writeText(handlerResult.error);\n return 1;\n }\n\n const { all: showAll, directoriesOnly, maxDepth, ignorePatterns } = result.flags;\n const targetPath = result.args[0] ?? \".\";\n\n // Validate maxDepth\n if (maxDepth < 1) {\n await ctx.stderr.writeText(\"tree: Invalid level, must be greater than 0\\n\");\n return 1;\n }\n\n const resolvedPath = ctx.fs.resolve(ctx.cwd, targetPath);\n\n // Check if path exists\n let stat;\n try {\n stat = await ctx.fs.stat(resolvedPath);\n } catch {\n await ctx.stderr.writeText(`tree: ${targetPath}: No such file or directory\\n`);\n return 1;\n }\n\n // If it's a file, just print the filename\n if (stat.isFile()) {\n await ctx.stdout.writeText(targetPath + \"\\n\\n0 directories, 1 file\\n\");\n return 0;\n }\n\n let dirCount = 0;\n let fileCount = 0;\n\n // Print root\n await ctx.stdout.writeText(targetPath + \"\\n\");\n\n // Recursive function to build tree\n async function printTree(path: string, prefix: string, depth: number): Promise<void> {\n if (depth > maxDepth) return;\n\n let entries = await ctx.fs.readdir(path);\n\n // Filter hidden files unless -a\n if (!showAll) {\n entries = entries.filter((e) => !e.startsWith(\".\"));\n }\n\n // Filter by -I ignore patterns\n if (ignorePatterns.length > 0) {\n entries = entries.filter((e) => !ignorePatterns.some((p) => matchGlob(p, e)));\n }\n\n // Sort entries\n entries.sort();\n\n // Separate dirs and files, dirs first\n const dirEntries: string[] = [];\n const fileEntries: string[] = [];\n\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(path, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n if (entryStat.isDirectory()) {\n dirEntries.push(entry);\n } else {\n fileEntries.push(entry);\n }\n } catch {\n // Skip entries we can't stat\n }\n }\n\n // Combine: directories first, then files (unless directoriesOnly)\n const sortedEntries = directoriesOnly\n ? dirEntries\n : [...dirEntries, ...fileEntries];\n\n for (let i = 0; i < sortedEntries.length; i++) {\n const entry = sortedEntries[i]!;\n const isLast = i === sortedEntries.length - 1;\n const connector = isLast ? \"└── \" : \"├── \";\n const entryPath = ctx.fs.resolve(path, entry);\n\n let isDir = false;\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n isDir = entryStat.isDirectory();\n } catch {\n continue;\n }\n\n await ctx.stdout.writeText(prefix + connector + entry + \"\\n\");\n\n if (isDir) {\n dirCount++;\n if (depth < maxDepth) {\n const newPrefix = prefix + (isLast ? \" \" : \"│ \");\n await printTree(entryPath, newPrefix, depth + 1);\n }\n } else {\n fileCount++;\n }\n }\n }\n\n await printTree(resolvedPath, \"\", 1);\n\n // Print summary\n const dirWord = dirCount === 1 ? \"directory\" : \"directories\";\n const fileWord = fileCount === 1 ? \"file\" : \"files\";\n await ctx.stdout.writeText(`\\n${dirCount} ${dirWord}, ${fileCount} ${fileWord}\\n`);\n\n return 0;\n};\n"
5
+ "import type { Command } from \"../../types.cjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.cjs\";\nimport { matchGlob } from \"../../utils/match-glob.cjs\";\n\ninterface TreeFlags {\n all: boolean;\n directoriesOnly: boolean;\n maxDepth: number;\n dirsfirst: boolean;\n prune: boolean;\n ignorePatterns: string[];\n}\n\nconst spec = {\n name: \"tree\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"d\" },\n { short: \"L\", takesValue: true },\n { short: \"I\", takesValue: true },\n { long: \"dirsfirst\" },\n { long: \"prune\" },\n ] as FlagDefinition[],\n usage: \"tree [-adI] [-L level] [-I pattern] [--dirsfirst] [--prune] [directory ...]\",\n};\n\nconst defaults: TreeFlags = {\n all: false,\n directoriesOnly: false,\n maxDepth: Infinity,\n dirsfirst: true,\n prune: false,\n ignorePatterns: [],\n};\n\ninterface HandlerResult {\n error?: string;\n}\n\nlet handlerResult: HandlerResult = {};\n\nconst handler = (flags: TreeFlags, flag: FlagDefinition, value?: string) => {\n if (flag.short === \"a\") flags.all = true;\n if (flag.short === \"d\") flags.directoriesOnly = true;\n if (flag.long === \"dirsfirst\") flags.dirsfirst = true;\n if (flag.long === \"prune\") flags.prune = true;\n if (flag.short === \"I\" && value) {\n if (flags.ignorePatterns === defaults.ignorePatterns) {\n flags.ignorePatterns = [];\n }\n flags.ignorePatterns.push(...value.split(\"|\"));\n }\n if (flag.short === \"L\" && value) {\n const depth = parseInt(value, 10);\n if (isNaN(depth) || !/^\\d+$/.test(value)) {\n handlerResult.error = `tree: -L option requires a numeric argument\\nusage: ${spec.usage}\\n`;\n } else {\n flags.maxDepth = depth;\n }\n }\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const tree: Command = async (ctx) => {\n // Reset handler result for each invocation\n handlerResult = {};\n\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n if (handlerResult.error) {\n await ctx.stderr.writeText(handlerResult.error);\n return 1;\n }\n\n const { all: showAll, directoriesOnly, maxDepth, prune, ignorePatterns } = result.flags;\n const targetPath = result.args[0] ?? \".\";\n\n // Validate maxDepth\n if (maxDepth < 1) {\n await ctx.stderr.writeText(\"tree: Invalid level, must be greater than 0\\n\");\n return 1;\n }\n\n const resolvedPath = ctx.fs.resolve(ctx.cwd, targetPath);\n\n // Check if path exists\n let stat;\n try {\n stat = await ctx.fs.stat(resolvedPath);\n } catch {\n await ctx.stderr.writeText(`tree: ${targetPath}: No such file or directory\\n`);\n return 1;\n }\n\n // If it's a file, just print the filename\n if (stat.isFile()) {\n await ctx.stdout.writeText(targetPath + \"\\n\\n0 directories, 1 file\\n\");\n return 0;\n }\n\n let dirCount = 0;\n let fileCount = 0;\n const entriesCache = new Map<string, { name: string; path: string; isDir: boolean }[]>();\n const visibleContentCache = new Map<string, boolean>();\n\n // Print root\n await ctx.stdout.writeText(targetPath + \"\\n\");\n\n async function getEntries(path: string): Promise<{ name: string; path: string; isDir: boolean }[]> {\n const cached = entriesCache.get(path);\n if (cached) return cached;\n\n let entries = await ctx.fs.readdir(path);\n\n // Filter hidden files unless -a\n if (!showAll) {\n entries = entries.filter((e) => !e.startsWith(\".\"));\n }\n\n // Filter by -I ignore patterns\n if (ignorePatterns.length > 0) {\n entries = entries.filter((e) => !ignorePatterns.some((p) => matchGlob(p, e)));\n }\n\n // Sort entries\n entries.sort();\n\n const resolvedEntries: { name: string; path: string; isDir: boolean }[] = [];\n\n for (const name of entries) {\n const entryPath = ctx.fs.resolve(path, name);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n resolvedEntries.push({ name, path: entryPath, isDir: entryStat.isDirectory() });\n } catch {\n // Skip entries we can't stat\n }\n }\n\n entriesCache.set(path, resolvedEntries);\n return resolvedEntries;\n }\n\n async function hasVisibleContent(path: string): Promise<boolean> {\n const cached = visibleContentCache.get(path);\n if (cached !== undefined) return cached;\n\n const entries = await getEntries(path);\n\n for (const entry of entries) {\n if (!entry.isDir) {\n visibleContentCache.set(path, true);\n return true;\n }\n\n if (await hasVisibleContent(entry.path)) {\n visibleContentCache.set(path, true);\n return true;\n }\n }\n\n visibleContentCache.set(path, false);\n return false;\n }\n\n // Recursive function to build tree\n async function printTree(path: string, prefix: string, depth: number): Promise<void> {\n if (depth > maxDepth) return;\n\n const entries = await getEntries(path);\n\n // Separate dirs and files, dirs first\n const dirEntries: { name: string; path: string; isDir: boolean }[] = [];\n const fileEntries: { name: string; path: string; isDir: boolean }[] = [];\n\n for (const entry of entries) {\n if (entry.isDir) {\n if (prune && !(await hasVisibleContent(entry.path))) {\n continue;\n }\n dirEntries.push(entry);\n } else {\n fileEntries.push(entry);\n }\n }\n\n // Combine: directories first, then files (unless directoriesOnly)\n const sortedEntries = directoriesOnly\n ? dirEntries\n : [...dirEntries, ...fileEntries];\n\n for (let i = 0; i < sortedEntries.length; i++) {\n const entry = sortedEntries[i]!;\n const isLast = i === sortedEntries.length - 1;\n const connector = isLast ? \"└── \" : \"├── \";\n\n await ctx.stdout.writeText(prefix + connector + entry.name + \"\\n\");\n\n if (entry.isDir) {\n dirCount++;\n if (depth < maxDepth) {\n const newPrefix = prefix + (isLast ? \" \" : \"│ \");\n await printTree(entry.path, newPrefix, depth + 1);\n }\n } else {\n fileCount++;\n }\n }\n }\n\n await printTree(resolvedPath, \"\", 1);\n\n // Print summary\n const dirWord = dirCount === 1 ? \"directory\" : \"directories\";\n const fileWord = fileCount === 1 ? \"file\" : \"files\";\n await ctx.stdout.writeText(`\\n${dirCount} ${dirWord}, ${fileCount} ${fileWord}\\n`);\n\n return 0;\n};\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "84C05E2FE694C09E64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "F4832ADA9F283A9964756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -68,21 +68,29 @@ __export(exports_memfs_adapter, {
68
68
  module.exports = __toCommonJS(exports_memfs_adapter);
69
69
  var pathModule = __toESM(require("path"));
70
70
  var import_glob = require("../utils/glob.cjs");
71
+ var import_special_files = require("./special-files.cjs");
71
72
  function createVirtualFS(memfs) {
72
73
  const { promises: fs } = memfs;
73
74
  return {
74
75
  readFile: async (path, encoding) => {
75
- if (path === "/dev/null")
76
- return encoding ? "" : Buffer.alloc(0);
76
+ const specialContent = import_special_files.readSpecialFile(path, encoding);
77
+ if (specialContent !== undefined)
78
+ return specialContent;
77
79
  const content = await fs.readFile(path);
78
80
  const buf = Buffer.from(content);
79
81
  return encoding ? buf.toString(encoding) : buf;
80
82
  },
81
83
  async readdir(path) {
84
+ const specialError = import_special_files.getSpecialPathError(path, "readdir");
85
+ if (specialError)
86
+ throw specialError;
82
87
  const entries = await fs.readdir(path);
83
88
  return entries.map(String);
84
89
  },
85
90
  async stat(path) {
91
+ const specialStat = import_special_files.statSpecialFile(path);
92
+ if (specialStat)
93
+ return specialStat;
86
94
  const stats = await fs.stat(path);
87
95
  return {
88
96
  isFile: () => stats.isFile(),
@@ -92,6 +100,9 @@ function createVirtualFS(memfs) {
92
100
  };
93
101
  },
94
102
  async exists(path) {
103
+ const specialExists = import_special_files.existsSpecialFile(path);
104
+ if (specialExists !== undefined)
105
+ return specialExists;
95
106
  try {
96
107
  await fs.stat(path);
97
108
  return true;
@@ -100,15 +111,27 @@ function createVirtualFS(memfs) {
100
111
  }
101
112
  },
102
113
  async writeFile(path, data) {
114
+ if (import_special_files.discardsSpecialFileWrites(path)) {
115
+ return;
116
+ }
103
117
  await fs.writeFile(path, data);
104
118
  },
105
119
  async appendFile(path, data) {
120
+ if (import_special_files.discardsSpecialFileWrites(path)) {
121
+ return;
122
+ }
106
123
  await fs.appendFile(path, data);
107
124
  },
108
125
  async mkdir(path, opts) {
126
+ const specialError = import_special_files.getSpecialPathError(path, "mkdir");
127
+ if (specialError)
128
+ throw specialError;
109
129
  await fs.mkdir(path, opts);
110
130
  },
111
131
  async rm(path, opts) {
132
+ const specialError = import_special_files.getSpecialPathError(path, "rm");
133
+ if (specialError)
134
+ throw specialError;
112
135
  try {
113
136
  const stats = await fs.stat(path);
114
137
  if (stats.isDirectory()) {
@@ -141,4 +164,4 @@ function createVirtualFS(memfs) {
141
164
  };
142
165
  }
143
166
 
144
- //# debugId=60E8B0C48B1EE27B64756E2164756E21
167
+ //# debugId=F25975C12E3475B564756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/fs/memfs-adapter.ts"],
4
4
  "sourcesContent": [
5
- "import type { IFs } from \"memfs\";\nimport type { VirtualFS, FileStat } from \"../types.cjs\";\nimport * as pathModule from \"path\";\nimport { globVirtualFS } from \"../utils/glob.cjs\";\n\nexport function createVirtualFS(memfs: IFs): VirtualFS {\n const { promises: fs } = memfs;\n\n return {\n readFile: (async (path: string, encoding?: BufferEncoding): Promise<Buffer | string> => {\n if (path === \"/dev/null\") return encoding ? \"\" : Buffer.alloc(0);\n const content = await fs.readFile(path);\n const buf = Buffer.from(content);\n return encoding ? buf.toString(encoding) : buf;\n }) as VirtualFS[\"readFile\"],\n\n async readdir(path: string): Promise<string[]> {\n const entries = await fs.readdir(path);\n return entries.map(String);\n },\n\n async stat(path: string): Promise<FileStat> {\n const stats = await fs.stat(path);\n return {\n isFile: () => stats.isFile(),\n isDirectory: () => stats.isDirectory(),\n size: Number(stats.size),\n mtime: new Date(stats.mtime),\n };\n },\n\n async exists(path: string): Promise<boolean> {\n try {\n await fs.stat(path);\n return true;\n } catch {\n return false;\n }\n },\n\n async writeFile(path: string, data: Buffer | string): Promise<void> {\n await fs.writeFile(path, data);\n },\n\n async appendFile(path: string, data: Buffer | string): Promise<void> {\n await fs.appendFile(path, data);\n },\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n await fs.mkdir(path, opts);\n },\n\n async rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void> {\n try {\n const stats = await fs.stat(path);\n if (stats.isDirectory()) {\n await fs.rmdir(path, { recursive: opts?.recursive });\n } else {\n await fs.unlink(path);\n }\n } catch (err) {\n if (!opts?.force) throw err;\n }\n },\n\n resolve(...paths: string[]): string {\n return pathModule.resolve(...paths);\n },\n\n dirname(path: string): string {\n return pathModule.dirname(path);\n },\n\n basename(path: string): string {\n return pathModule.basename(path);\n },\n\n async glob(pattern: string, opts?: { cwd?: string }): Promise<string[]> {\n const cwd = opts?.cwd ?? \"/\";\n return globVirtualFS(\n {\n readdir: (filePath: string) => this.readdir(filePath),\n stat: (filePath: string) => this.stat(filePath),\n resolve: (...paths: string[]) => this.resolve(...paths),\n },\n pattern,\n { cwd }\n );\n },\n };\n}\n"
5
+ "import type { IFs } from \"memfs\";\nimport type { VirtualFS, FileStat } from \"../types.cjs\";\nimport * as pathModule from \"path\";\nimport { globVirtualFS } from \"../utils/glob.cjs\";\nimport {\n discardsSpecialFileWrites,\n existsSpecialFile,\n getSpecialPathError,\n readSpecialFile,\n statSpecialFile,\n} from \"./special-files.cjs\";\n\nexport function createVirtualFS(memfs: IFs): VirtualFS {\n const { promises: fs } = memfs;\n\n return {\n readFile: (async (path: string, encoding?: BufferEncoding): Promise<Buffer | string> => {\n const specialContent = readSpecialFile(path, encoding);\n if (specialContent !== undefined) return specialContent;\n const content = await fs.readFile(path);\n const buf = Buffer.from(content);\n return encoding ? buf.toString(encoding) : buf;\n }) as VirtualFS[\"readFile\"],\n\n async readdir(path: string): Promise<string[]> {\n const specialError = getSpecialPathError(path, \"readdir\");\n if (specialError) throw specialError;\n const entries = await fs.readdir(path);\n return entries.map(String);\n },\n\n async stat(path: string): Promise<FileStat> {\n const specialStat = statSpecialFile(path);\n if (specialStat) return specialStat;\n const stats = await fs.stat(path);\n return {\n isFile: () => stats.isFile(),\n isDirectory: () => stats.isDirectory(),\n size: Number(stats.size),\n mtime: new Date(stats.mtime),\n };\n },\n\n async exists(path: string): Promise<boolean> {\n const specialExists = existsSpecialFile(path);\n if (specialExists !== undefined) return specialExists;\n try {\n await fs.stat(path);\n return true;\n } catch {\n return false;\n }\n },\n\n async writeFile(path: string, data: Buffer | string): Promise<void> {\n if (discardsSpecialFileWrites(path)) {\n return;\n }\n await fs.writeFile(path, data);\n },\n\n async appendFile(path: string, data: Buffer | string): Promise<void> {\n if (discardsSpecialFileWrites(path)) {\n return;\n }\n await fs.appendFile(path, data);\n },\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const specialError = getSpecialPathError(path, \"mkdir\");\n if (specialError) throw specialError;\n await fs.mkdir(path, opts);\n },\n\n async rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const specialError = getSpecialPathError(path, \"rm\");\n if (specialError) throw specialError;\n try {\n const stats = await fs.stat(path);\n if (stats.isDirectory()) {\n await fs.rmdir(path, { recursive: opts?.recursive });\n } else {\n await fs.unlink(path);\n }\n } catch (err) {\n if (!opts?.force) throw err;\n }\n },\n\n resolve(...paths: string[]): string {\n return pathModule.resolve(...paths);\n },\n\n dirname(path: string): string {\n return pathModule.dirname(path);\n },\n\n basename(path: string): string {\n return pathModule.basename(path);\n },\n\n async glob(pattern: string, opts?: { cwd?: string }): Promise<string[]> {\n const cwd = opts?.cwd ?? \"/\";\n return globVirtualFS(\n {\n readdir: (filePath: string) => this.readdir(filePath),\n stat: (filePath: string) => this.stat(filePath),\n resolve: (...paths: string[]) => this.resolve(...paths),\n },\n pattern,\n { cwd }\n );\n },\n };\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE4B,IAA5B;AAC8B,IAA9B;AAEO,SAAS,eAAe,CAAC,OAAuB;AAAA,EACrD,QAAQ,UAAU,OAAO;AAAA,EAEzB,OAAO;AAAA,IACL,UAAW,OAAO,MAAc,aAAwD;AAAA,MACtF,IAAI,SAAS;AAAA,QAAa,OAAO,WAAW,KAAK,OAAO,MAAM,CAAC;AAAA,MAC/D,MAAM,UAAU,MAAM,GAAG,SAAS,IAAI;AAAA,MACtC,MAAM,MAAM,OAAO,KAAK,OAAO;AAAA,MAC/B,OAAO,WAAW,IAAI,SAAS,QAAQ,IAAI;AAAA;AAAA,SAGvC,QAAO,CAAC,MAAiC;AAAA,MAC7C,MAAM,UAAU,MAAM,GAAG,QAAQ,IAAI;AAAA,MACrC,OAAO,QAAQ,IAAI,MAAM;AAAA;AAAA,SAGrB,KAAI,CAAC,MAAiC;AAAA,MAC1C,MAAM,QAAQ,MAAM,GAAG,KAAK,IAAI;AAAA,MAChC,OAAO;AAAA,QACL,QAAQ,MAAM,MAAM,OAAO;AAAA,QAC3B,aAAa,MAAM,MAAM,YAAY;AAAA,QACrC,MAAM,OAAO,MAAM,IAAI;AAAA,QACvB,OAAO,IAAI,KAAK,MAAM,KAAK;AAAA,MAC7B;AAAA;AAAA,SAGI,OAAM,CAAC,MAAgC;AAAA,MAC3C,IAAI;AAAA,QACF,MAAM,GAAG,KAAK,IAAI;AAAA,QAClB,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA;AAAA;AAAA,SAIL,UAAS,CAAC,MAAc,MAAsC;AAAA,MAClE,MAAM,GAAG,UAAU,MAAM,IAAI;AAAA;AAAA,SAGzB,WAAU,CAAC,MAAc,MAAsC;AAAA,MACnE,MAAM,GAAG,WAAW,MAAM,IAAI;AAAA;AAAA,SAG1B,MAAK,CAAC,MAAc,MAA+C;AAAA,MACvE,MAAM,GAAG,MAAM,MAAM,IAAI;AAAA;AAAA,SAGrB,GAAE,CAAC,MAAc,MAAgE;AAAA,MACrF,IAAI;AAAA,QACF,MAAM,QAAQ,MAAM,GAAG,KAAK,IAAI;AAAA,QAChC,IAAI,MAAM,YAAY,GAAG;AAAA,UACvB,MAAM,GAAG,MAAM,MAAM,EAAE,WAAW,MAAM,UAAU,CAAC;AAAA,QACrD,EAAO;AAAA,UACL,MAAM,GAAG,OAAO,IAAI;AAAA;AAAA,QAEtB,OAAO,KAAK;AAAA,QACZ,IAAI,CAAC,MAAM;AAAA,UAAO,MAAM;AAAA;AAAA;AAAA,IAI5B,OAAO,IAAI,OAAyB;AAAA,MAClC,OAAkB,mBAAQ,GAAG,KAAK;AAAA;AAAA,IAGpC,OAAO,CAAC,MAAsB;AAAA,MAC5B,OAAkB,mBAAQ,IAAI;AAAA;AAAA,IAGhC,QAAQ,CAAC,MAAsB;AAAA,MAC7B,OAAkB,oBAAS,IAAI;AAAA;AAAA,SAG3B,KAAI,CAAC,SAAiB,MAA4C;AAAA,MACtE,MAAM,MAAM,MAAM,OAAO;AAAA,MACzB,OAAO,0BACL;AAAA,QACE,SAAS,CAAC,aAAqB,KAAK,QAAQ,QAAQ;AAAA,QACpD,MAAM,CAAC,aAAqB,KAAK,KAAK,QAAQ;AAAA,QAC9C,SAAS,IAAI,UAAoB,KAAK,QAAQ,GAAG,KAAK;AAAA,MACxD,GACA,SACA,EAAE,IAAI,CACR;AAAA;AAAA,EAEJ;AAAA;",
8
- "debugId": "60E8B0C48B1EE27B64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "F25975C12E3475B564756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -69,6 +69,7 @@ module.exports = __toCommonJS(exports_real_fs);
69
69
  var path = __toESM(require("path"));
70
70
  var nodeFs = __toESM(require("node:fs/promises"));
71
71
  var import_glob = require("../utils/glob.cjs");
72
+ var import_special_files = require("./special-files.cjs");
72
73
  var defaultFS = { promises: nodeFs };
73
74
  var nodePathOps = {
74
75
  separator: path.sep,
@@ -167,6 +168,10 @@ class FileSystem {
167
168
  return resolved;
168
169
  }
169
170
  async readFile(filePath, encoding) {
171
+ const specialContent = import_special_files.readSpecialFile(filePath, encoding);
172
+ if (specialContent !== undefined) {
173
+ return specialContent;
174
+ }
170
175
  this.checkPermission(filePath, "read");
171
176
  const realPath = this.resolveSafePath(filePath);
172
177
  const content = await this.underlyingFs.promises.readFile(realPath);
@@ -174,12 +179,20 @@ class FileSystem {
174
179
  return encoding ? buf.toString(encoding) : buf;
175
180
  }
176
181
  async readdir(dirPath) {
182
+ const specialError = import_special_files.getSpecialPathError(dirPath, "readdir");
183
+ if (specialError) {
184
+ throw specialError;
185
+ }
177
186
  this.checkPermission(dirPath, "read");
178
187
  const realPath = this.resolveSafePath(dirPath);
179
188
  const entries = await this.underlyingFs.promises.readdir(realPath);
180
189
  return entries.map(String);
181
190
  }
182
191
  async stat(filePath) {
192
+ const specialStat = import_special_files.statSpecialFile(filePath);
193
+ if (specialStat) {
194
+ return specialStat;
195
+ }
183
196
  this.checkPermission(filePath, "read");
184
197
  const realPath = this.resolveSafePath(filePath);
185
198
  const stats = await this.underlyingFs.promises.stat(realPath);
@@ -191,6 +204,10 @@ class FileSystem {
191
204
  };
192
205
  }
193
206
  async exists(filePath) {
207
+ const specialExists = import_special_files.existsSpecialFile(filePath);
208
+ if (specialExists !== undefined) {
209
+ return specialExists;
210
+ }
194
211
  try {
195
212
  this.checkPermission(filePath, "read");
196
213
  const realPath = this.resolveSafePath(filePath);
@@ -201,21 +218,35 @@ class FileSystem {
201
218
  }
202
219
  }
203
220
  async writeFile(filePath, data) {
221
+ if (import_special_files.discardsSpecialFileWrites(filePath)) {
222
+ return;
223
+ }
204
224
  this.checkPermission(filePath, "write");
205
225
  const realPath = this.resolveSafePath(filePath);
206
226
  await this.underlyingFs.promises.writeFile(realPath, data);
207
227
  }
208
228
  async appendFile(filePath, data) {
229
+ if (import_special_files.discardsSpecialFileWrites(filePath)) {
230
+ return;
231
+ }
209
232
  this.checkPermission(filePath, "write");
210
233
  const realPath = this.resolveSafePath(filePath);
211
234
  await this.underlyingFs.promises.appendFile(realPath, data);
212
235
  }
213
236
  async mkdir(dirPath, opts) {
237
+ const specialError = import_special_files.getSpecialPathError(dirPath, "mkdir");
238
+ if (specialError) {
239
+ throw specialError;
240
+ }
214
241
  this.checkPermission(dirPath, "write");
215
242
  const realPath = this.resolveSafePath(dirPath);
216
243
  await this.underlyingFs.promises.mkdir(realPath, opts);
217
244
  }
218
245
  async rm(filePath, opts) {
246
+ const specialError = import_special_files.getSpecialPathError(filePath, "rm");
247
+ if (specialError) {
248
+ throw specialError;
249
+ }
219
250
  this.checkPermission(filePath, "write");
220
251
  const realPath = this.resolveSafePath(filePath);
221
252
  await this.underlyingFs.promises.rm(realPath, opts);
@@ -236,4 +267,4 @@ class FileSystem {
236
267
  }
237
268
  }
238
269
 
239
- //# debugId=6E371DB9ABEDFA8764756E2164756E21
270
+ //# debugId=58FDFA4CFF76BA5364756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/fs/real-fs.ts"],
4
4
  "sourcesContent": [
5
- "import * as path from \"path\";\nimport * as nodeFs from \"node:fs/promises\";\nimport type { VirtualFS, FileStat } from \"../types.cjs\";\nimport { globVirtualFS } from \"../utils/glob.cjs\";\n\nexport type Permission = \"read-write\" | \"read-only\" | \"excluded\";\nexport type PermissionRules = Record<string, Permission>;\nexport interface PathOps {\n readonly separator: string;\n resolve(...paths: string[]): string;\n normalize(path: string): string;\n join(...paths: string[]): string;\n relative(from: string, to: string): string;\n isAbsolute(path: string): boolean;\n dirname(path: string): string;\n basename(path: string): string;\n}\n\n// Minimal interface for the underlying fs (compatible with node:fs and memfs)\nexport interface UnderlyingFS {\n pathOps?: PathOps;\n promises: {\n readFile(path: string): Promise<Buffer | Uint8Array | string>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<{\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n }>;\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<string | undefined | void>;\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n };\n}\n\n// Default: use real node:fs\nconst defaultFS: UnderlyingFS = { promises: nodeFs };\nconst nodePathOps: PathOps = {\n separator: path.sep,\n resolve: (...paths) => path.resolve(...paths),\n normalize: (filePath) => path.normalize(filePath),\n join: (...paths) => path.join(...paths),\n relative: (from, to) => path.relative(from, to),\n isAbsolute: (filePath) => path.isAbsolute(filePath),\n dirname: (filePath) => path.dirname(filePath),\n basename: (filePath) => path.basename(filePath),\n};\n\ninterface CompiledRule {\n pattern: string;\n permission: Permission;\n specificity: number;\n}\n\nexport class FileSystem implements VirtualFS {\n private readonly mountBase: string | null;\n private readonly rules: CompiledRule[];\n private readonly pathOps: PathOps;\n protected readonly underlyingFs: UnderlyingFS;\n\n constructor(mountPath?: string, permissions?: PermissionRules, fs?: UnderlyingFS) {\n const underlyingFs = fs ?? defaultFS;\n this.pathOps = underlyingFs.pathOps ?? nodePathOps;\n this.mountBase = mountPath ? this.pathOps.resolve(mountPath) : null;\n this.rules = this.compileRules(permissions ?? {});\n this.underlyingFs = underlyingFs;\n }\n\n private compileRules(permissions: PermissionRules): CompiledRule[] {\n return Object.entries(permissions)\n .map(([pattern, permission]) => ({\n pattern,\n permission,\n specificity: this.calculateSpecificity(pattern),\n }))\n .sort((a, b) => b.specificity - a.specificity); // highest first\n }\n\n private calculateSpecificity(pattern: string): number {\n const segments = pattern.split(\"/\").filter(Boolean);\n let score = segments.length * 1000; // segment count is primary\n\n for (const seg of segments) {\n if (seg === \"**\") score += 0;\n else if (seg.includes(\"*\")) score += 1;\n else score += 10; // literal segment\n }\n return score;\n }\n\n public getPermission(virtualPath: string): Permission {\n const normalized = virtualPath.replace(/^\\/+/, \"\"); // strip leading slashes\n\n for (const rule of this.rules) {\n if (this.matchGlob(rule.pattern, normalized)) {\n return rule.permission;\n }\n }\n return \"read-write\"; // default\n }\n\n private matchGlob(pattern: string, filePath: string): boolean {\n // Convert glob to regex\n // ** matches any path segments, * matches within segment\n const regex = pattern\n .split(\"/\")\n .map((seg) => {\n if (seg === \"**\") return \".*\";\n return seg.replace(/\\*/g, \"[^/]*\").replace(/\\?/g, \"[^/]\");\n })\n .join(\"/\");\n return new RegExp(`^${regex}$`).test(filePath);\n }\n\n public checkPermission(virtualPath: string, operation: \"read\" | \"write\"): void {\n const perm = this.getPermission(virtualPath);\n\n if (perm === \"excluded\") {\n throw new Error(`Access denied: \"${virtualPath}\" is excluded`);\n }\n if (operation === \"write\" && perm === \"read-only\") {\n throw new Error(`Access denied: \"${virtualPath}\" is read-only`);\n }\n }\n\n private resolveSafePath(virtualPath: string): string {\n if (this.mountBase === null) {\n return this.pathOps.resolve(virtualPath);\n }\n\n // Check for path traversal by tracking depth\n const segments = virtualPath.split(\"/\").filter(Boolean);\n let depth = 0;\n for (const seg of segments) {\n if (seg === \"..\") {\n depth--;\n if (depth < 0) {\n throw new Error(`Path traversal blocked: \"${virtualPath}\" escapes mount point`);\n }\n } else if (seg !== \".\") {\n depth++;\n }\n }\n\n const normalized = this.pathOps.normalize(virtualPath);\n const relativePath = normalized.startsWith(\"/\") ? normalized.slice(1) : normalized;\n const realPath = this.pathOps.join(this.mountBase, relativePath);\n const resolved = this.pathOps.resolve(realPath);\n\n // Double-check containment (defense in depth), including root mounts.\n const relativeFromMount = this.pathOps.relative(this.mountBase, resolved);\n const escapesMount =\n relativeFromMount === \"..\" ||\n relativeFromMount.startsWith(`..${this.pathOps.separator}`) ||\n this.pathOps.isAbsolute(relativeFromMount);\n if (escapesMount) {\n throw new Error(`Path traversal blocked: \"${virtualPath}\" escapes mount point`);\n }\n\n return resolved;\n }\n\n // Read operations\n async readFile(filePath: string): Promise<Buffer>;\n async readFile(filePath: string, encoding: BufferEncoding): Promise<string>;\n async readFile(filePath: string, encoding?: BufferEncoding): Promise<Buffer | string> {\n this.checkPermission(filePath, \"read\");\n const realPath = this.resolveSafePath(filePath);\n const content = await this.underlyingFs.promises.readFile(realPath);\n const buf = Buffer.from(content);\n return encoding ? buf.toString(encoding) : buf;\n }\n\n async readdir(dirPath: string): Promise<string[]> {\n this.checkPermission(dirPath, \"read\");\n const realPath = this.resolveSafePath(dirPath);\n const entries = await this.underlyingFs.promises.readdir(realPath);\n return entries.map(String);\n }\n\n async stat(filePath: string): Promise<FileStat> {\n this.checkPermission(filePath, \"read\");\n const realPath = this.resolveSafePath(filePath);\n const stats = await this.underlyingFs.promises.stat(realPath);\n return {\n isFile: () => stats.isFile(),\n isDirectory: () => stats.isDirectory(),\n size: stats.size,\n mtime: stats.mtime,\n };\n }\n\n async exists(filePath: string): Promise<boolean> {\n try {\n this.checkPermission(filePath, \"read\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.stat(realPath);\n return true;\n } catch {\n return false;\n }\n }\n\n // Write operations\n async writeFile(filePath: string, data: Buffer | string): Promise<void> {\n this.checkPermission(filePath, \"write\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.writeFile(realPath, data);\n }\n\n async appendFile(filePath: string, data: Buffer | string): Promise<void> {\n this.checkPermission(filePath, \"write\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.appendFile(realPath, data);\n }\n\n async mkdir(dirPath: string, opts?: { recursive?: boolean }): Promise<void> {\n this.checkPermission(dirPath, \"write\");\n const realPath = this.resolveSafePath(dirPath);\n await this.underlyingFs.promises.mkdir(realPath, opts);\n }\n\n async rm(filePath: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void> {\n this.checkPermission(filePath, \"write\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.rm(realPath, opts);\n }\n\n // Path utilities (no permission check needed)\n resolve(...paths: string[]): string {\n return this.pathOps.resolve(\"/\", ...paths);\n }\n\n dirname(filePath: string): string {\n return this.pathOps.dirname(filePath);\n }\n\n basename(filePath: string): string {\n return this.pathOps.basename(filePath);\n }\n\n // Glob expansion\n async glob(pattern: string, opts?: { cwd?: string }): Promise<string[]> {\n const cwd = opts?.cwd ?? \"/\";\n this.checkPermission(cwd, \"read\");\n return globVirtualFS(this, pattern, { cwd });\n }\n}\n"
5
+ "import * as path from \"path\";\nimport * as nodeFs from \"node:fs/promises\";\nimport type { VirtualFS, FileStat } from \"../types.cjs\";\nimport { globVirtualFS } from \"../utils/glob.cjs\";\nimport {\n discardsSpecialFileWrites,\n existsSpecialFile,\n getSpecialPathError,\n readSpecialFile,\n statSpecialFile,\n} from \"./special-files.cjs\";\n\nexport type Permission = \"read-write\" | \"read-only\" | \"excluded\";\nexport type PermissionRules = Record<string, Permission>;\nexport interface PathOps {\n readonly separator: string;\n resolve(...paths: string[]): string;\n normalize(path: string): string;\n join(...paths: string[]): string;\n relative(from: string, to: string): string;\n isAbsolute(path: string): boolean;\n dirname(path: string): string;\n basename(path: string): string;\n}\n\n// Minimal interface for the underlying fs (compatible with node:fs and memfs)\nexport interface UnderlyingFS {\n pathOps?: PathOps;\n promises: {\n readFile(path: string): Promise<Buffer | Uint8Array | string>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<{\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n }>;\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<string | undefined | void>;\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n };\n}\n\n// Default: use real node:fs\nconst defaultFS: UnderlyingFS = { promises: nodeFs };\nconst nodePathOps: PathOps = {\n separator: path.sep,\n resolve: (...paths) => path.resolve(...paths),\n normalize: (filePath) => path.normalize(filePath),\n join: (...paths) => path.join(...paths),\n relative: (from, to) => path.relative(from, to),\n isAbsolute: (filePath) => path.isAbsolute(filePath),\n dirname: (filePath) => path.dirname(filePath),\n basename: (filePath) => path.basename(filePath),\n};\n\ninterface CompiledRule {\n pattern: string;\n permission: Permission;\n specificity: number;\n}\n\nexport class FileSystem implements VirtualFS {\n private readonly mountBase: string | null;\n private readonly rules: CompiledRule[];\n private readonly pathOps: PathOps;\n protected readonly underlyingFs: UnderlyingFS;\n\n constructor(mountPath?: string, permissions?: PermissionRules, fs?: UnderlyingFS) {\n const underlyingFs = fs ?? defaultFS;\n this.pathOps = underlyingFs.pathOps ?? nodePathOps;\n this.mountBase = mountPath ? this.pathOps.resolve(mountPath) : null;\n this.rules = this.compileRules(permissions ?? {});\n this.underlyingFs = underlyingFs;\n }\n\n private compileRules(permissions: PermissionRules): CompiledRule[] {\n return Object.entries(permissions)\n .map(([pattern, permission]) => ({\n pattern,\n permission,\n specificity: this.calculateSpecificity(pattern),\n }))\n .sort((a, b) => b.specificity - a.specificity); // highest first\n }\n\n private calculateSpecificity(pattern: string): number {\n const segments = pattern.split(\"/\").filter(Boolean);\n let score = segments.length * 1000; // segment count is primary\n\n for (const seg of segments) {\n if (seg === \"**\") score += 0;\n else if (seg.includes(\"*\")) score += 1;\n else score += 10; // literal segment\n }\n return score;\n }\n\n public getPermission(virtualPath: string): Permission {\n const normalized = virtualPath.replace(/^\\/+/, \"\"); // strip leading slashes\n\n for (const rule of this.rules) {\n if (this.matchGlob(rule.pattern, normalized)) {\n return rule.permission;\n }\n }\n return \"read-write\"; // default\n }\n\n private matchGlob(pattern: string, filePath: string): boolean {\n // Convert glob to regex\n // ** matches any path segments, * matches within segment\n const regex = pattern\n .split(\"/\")\n .map((seg) => {\n if (seg === \"**\") return \".*\";\n return seg.replace(/\\*/g, \"[^/]*\").replace(/\\?/g, \"[^/]\");\n })\n .join(\"/\");\n return new RegExp(`^${regex}$`).test(filePath);\n }\n\n public checkPermission(virtualPath: string, operation: \"read\" | \"write\"): void {\n const perm = this.getPermission(virtualPath);\n\n if (perm === \"excluded\") {\n throw new Error(`Access denied: \"${virtualPath}\" is excluded`);\n }\n if (operation === \"write\" && perm === \"read-only\") {\n throw new Error(`Access denied: \"${virtualPath}\" is read-only`);\n }\n }\n\n private resolveSafePath(virtualPath: string): string {\n if (this.mountBase === null) {\n return this.pathOps.resolve(virtualPath);\n }\n\n // Check for path traversal by tracking depth\n const segments = virtualPath.split(\"/\").filter(Boolean);\n let depth = 0;\n for (const seg of segments) {\n if (seg === \"..\") {\n depth--;\n if (depth < 0) {\n throw new Error(`Path traversal blocked: \"${virtualPath}\" escapes mount point`);\n }\n } else if (seg !== \".\") {\n depth++;\n }\n }\n\n const normalized = this.pathOps.normalize(virtualPath);\n const relativePath = normalized.startsWith(\"/\") ? normalized.slice(1) : normalized;\n const realPath = this.pathOps.join(this.mountBase, relativePath);\n const resolved = this.pathOps.resolve(realPath);\n\n // Double-check containment (defense in depth), including root mounts.\n const relativeFromMount = this.pathOps.relative(this.mountBase, resolved);\n const escapesMount =\n relativeFromMount === \"..\" ||\n relativeFromMount.startsWith(`..${this.pathOps.separator}`) ||\n this.pathOps.isAbsolute(relativeFromMount);\n if (escapesMount) {\n throw new Error(`Path traversal blocked: \"${virtualPath}\" escapes mount point`);\n }\n\n return resolved;\n }\n\n // Read operations\n async readFile(filePath: string): Promise<Buffer>;\n async readFile(filePath: string, encoding: BufferEncoding): Promise<string>;\n async readFile(filePath: string, encoding?: BufferEncoding): Promise<Buffer | string> {\n const specialContent = readSpecialFile(filePath, encoding);\n if (specialContent !== undefined) {\n return specialContent;\n }\n this.checkPermission(filePath, \"read\");\n const realPath = this.resolveSafePath(filePath);\n const content = await this.underlyingFs.promises.readFile(realPath);\n const buf = Buffer.from(content);\n return encoding ? buf.toString(encoding) : buf;\n }\n\n async readdir(dirPath: string): Promise<string[]> {\n const specialError = getSpecialPathError(dirPath, \"readdir\");\n if (specialError) {\n throw specialError;\n }\n this.checkPermission(dirPath, \"read\");\n const realPath = this.resolveSafePath(dirPath);\n const entries = await this.underlyingFs.promises.readdir(realPath);\n return entries.map(String);\n }\n\n async stat(filePath: string): Promise<FileStat> {\n const specialStat = statSpecialFile(filePath);\n if (specialStat) {\n return specialStat;\n }\n this.checkPermission(filePath, \"read\");\n const realPath = this.resolveSafePath(filePath);\n const stats = await this.underlyingFs.promises.stat(realPath);\n return {\n isFile: () => stats.isFile(),\n isDirectory: () => stats.isDirectory(),\n size: stats.size,\n mtime: stats.mtime,\n };\n }\n\n async exists(filePath: string): Promise<boolean> {\n const specialExists = existsSpecialFile(filePath);\n if (specialExists !== undefined) {\n return specialExists;\n }\n try {\n this.checkPermission(filePath, \"read\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.stat(realPath);\n return true;\n } catch {\n return false;\n }\n }\n\n // Write operations\n async writeFile(filePath: string, data: Buffer | string): Promise<void> {\n if (discardsSpecialFileWrites(filePath)) {\n return;\n }\n this.checkPermission(filePath, \"write\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.writeFile(realPath, data);\n }\n\n async appendFile(filePath: string, data: Buffer | string): Promise<void> {\n if (discardsSpecialFileWrites(filePath)) {\n return;\n }\n this.checkPermission(filePath, \"write\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.appendFile(realPath, data);\n }\n\n async mkdir(dirPath: string, opts?: { recursive?: boolean }): Promise<void> {\n const specialError = getSpecialPathError(dirPath, \"mkdir\");\n if (specialError) {\n throw specialError;\n }\n this.checkPermission(dirPath, \"write\");\n const realPath = this.resolveSafePath(dirPath);\n await this.underlyingFs.promises.mkdir(realPath, opts);\n }\n\n async rm(filePath: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const specialError = getSpecialPathError(filePath, \"rm\");\n if (specialError) {\n throw specialError;\n }\n this.checkPermission(filePath, \"write\");\n const realPath = this.resolveSafePath(filePath);\n await this.underlyingFs.promises.rm(realPath, opts);\n }\n\n // Path utilities (no permission check needed)\n resolve(...paths: string[]): string {\n return this.pathOps.resolve(\"/\", ...paths);\n }\n\n dirname(filePath: string): string {\n return this.pathOps.dirname(filePath);\n }\n\n basename(filePath: string): string {\n return this.pathOps.basename(filePath);\n }\n\n // Glob expansion\n async glob(pattern: string, opts?: { cwd?: string }): Promise<string[]> {\n const cwd = opts?.cwd ?? \"/\";\n this.checkPermission(cwd, \"read\");\n return globVirtualFS(this, pattern, { cwd });\n }\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "6E371DB9ABEDFA8764756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "58FDFA4CFF76BA5364756E2164756E21",
9
9
  "names": []
10
10
  }