typescript-virtual-container 1.2.8 → 1.3.0

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.
Files changed (307) hide show
  1. package/.vscode/settings.json +0 -1
  2. package/README.md +462 -44
  3. package/biome.json +7 -0
  4. package/dist/SSHMimic/exec.d.ts.map +1 -1
  5. package/dist/SSHMimic/executor.d.ts.map +1 -1
  6. package/dist/SSHMimic/executor.js +35 -21
  7. package/dist/SSHMimic/index.d.ts.map +1 -1
  8. package/dist/SSHMimic/index.js +20 -6
  9. package/dist/VirtualFileSystem/binaryPack.d.ts.map +1 -1
  10. package/dist/VirtualFileSystem/binaryPack.js +29 -6
  11. package/dist/VirtualFileSystem/index.d.ts.map +1 -1
  12. package/dist/VirtualFileSystem/index.js +36 -13
  13. package/dist/VirtualPackageManager/index.d.ts +202 -0
  14. package/dist/VirtualPackageManager/index.d.ts.map +1 -0
  15. package/dist/VirtualPackageManager/index.js +825 -0
  16. package/dist/VirtualShell/index.d.ts +93 -12
  17. package/dist/VirtualShell/index.d.ts.map +1 -1
  18. package/dist/VirtualShell/index.js +95 -13
  19. package/dist/VirtualShell/shell.d.ts.map +1 -1
  20. package/dist/VirtualShell/shell.js +3 -1
  21. package/dist/VirtualShell/shellParser.d.ts.map +1 -1
  22. package/dist/VirtualUserManager/index.d.ts +52 -20
  23. package/dist/VirtualUserManager/index.d.ts.map +1 -1
  24. package/dist/VirtualUserManager/index.js +54 -20
  25. package/dist/commands/adduser.d.ts +6 -0
  26. package/dist/commands/adduser.d.ts.map +1 -1
  27. package/dist/commands/adduser.js +6 -0
  28. package/dist/commands/alias.d.ts +9 -0
  29. package/dist/commands/alias.d.ts.map +1 -0
  30. package/dist/commands/alias.js +63 -0
  31. package/dist/commands/apt.d.ts +9 -0
  32. package/dist/commands/apt.d.ts.map +1 -0
  33. package/dist/commands/apt.js +205 -0
  34. package/dist/commands/awk.d.ts +11 -0
  35. package/dist/commands/awk.d.ts.map +1 -1
  36. package/dist/commands/awk.js +15 -2
  37. package/dist/commands/base64.d.ts +5 -0
  38. package/dist/commands/base64.d.ts.map +1 -1
  39. package/dist/commands/base64.js +9 -1
  40. package/dist/commands/cat.d.ts +5 -0
  41. package/dist/commands/cat.d.ts.map +1 -1
  42. package/dist/commands/cat.js +35 -8
  43. package/dist/commands/cd.d.ts +5 -0
  44. package/dist/commands/cd.d.ts.map +1 -1
  45. package/dist/commands/cd.js +5 -0
  46. package/dist/commands/chmod.d.ts +5 -0
  47. package/dist/commands/chmod.d.ts.map +1 -1
  48. package/dist/commands/chmod.js +57 -3
  49. package/dist/commands/command-helpers.d.ts +78 -4
  50. package/dist/commands/command-helpers.d.ts.map +1 -1
  51. package/dist/commands/command-helpers.js +78 -4
  52. package/dist/commands/cp.d.ts +5 -0
  53. package/dist/commands/cp.d.ts.map +1 -1
  54. package/dist/commands/cp.js +5 -0
  55. package/dist/commands/curl.d.ts +5 -0
  56. package/dist/commands/curl.d.ts.map +1 -1
  57. package/dist/commands/curl.js +106 -26
  58. package/dist/commands/cut.d.ts +5 -0
  59. package/dist/commands/cut.d.ts.map +1 -1
  60. package/dist/commands/cut.js +8 -1
  61. package/dist/commands/date.d.ts +5 -0
  62. package/dist/commands/date.d.ts.map +1 -1
  63. package/dist/commands/date.js +7 -1
  64. package/dist/commands/declare.d.ts +3 -0
  65. package/dist/commands/declare.d.ts.map +1 -0
  66. package/dist/commands/declare.js +39 -0
  67. package/dist/commands/diff.d.ts +5 -0
  68. package/dist/commands/diff.d.ts.map +1 -1
  69. package/dist/commands/diff.js +5 -0
  70. package/dist/commands/dpkg.d.ts +9 -0
  71. package/dist/commands/dpkg.d.ts.map +1 -0
  72. package/dist/commands/dpkg.js +161 -0
  73. package/dist/commands/du.d.ts.map +1 -1
  74. package/dist/commands/du.js +8 -2
  75. package/dist/commands/echo.d.ts +5 -0
  76. package/dist/commands/echo.d.ts.map +1 -1
  77. package/dist/commands/echo.js +33 -12
  78. package/dist/commands/env.d.ts +5 -0
  79. package/dist/commands/env.d.ts.map +1 -1
  80. package/dist/commands/env.js +11 -1
  81. package/dist/commands/exit.d.ts +5 -0
  82. package/dist/commands/exit.d.ts.map +1 -1
  83. package/dist/commands/exit.js +12 -2
  84. package/dist/commands/export.d.ts.map +1 -1
  85. package/dist/commands/export.js +3 -1
  86. package/dist/commands/find.d.ts +5 -0
  87. package/dist/commands/find.d.ts.map +1 -1
  88. package/dist/commands/find.js +5 -0
  89. package/dist/commands/free.d.ts +8 -0
  90. package/dist/commands/free.d.ts.map +1 -0
  91. package/dist/commands/free.js +43 -0
  92. package/dist/commands/grep.d.ts +5 -0
  93. package/dist/commands/grep.d.ts.map +1 -1
  94. package/dist/commands/grep.js +12 -2
  95. package/dist/commands/gzip.d.ts +5 -0
  96. package/dist/commands/gzip.d.ts.map +1 -1
  97. package/dist/commands/gzip.js +18 -2
  98. package/dist/commands/head.d.ts +5 -0
  99. package/dist/commands/head.d.ts.map +1 -1
  100. package/dist/commands/head.js +5 -0
  101. package/dist/commands/help.d.ts.map +1 -1
  102. package/dist/commands/help.js +98 -45
  103. package/dist/commands/helpers.d.ts +3 -0
  104. package/dist/commands/helpers.d.ts.map +1 -1
  105. package/dist/commands/helpers.js +3 -0
  106. package/dist/commands/history.d.ts +8 -0
  107. package/dist/commands/history.d.ts.map +1 -0
  108. package/dist/commands/history.js +26 -0
  109. package/dist/commands/hostname.d.ts +5 -0
  110. package/dist/commands/hostname.d.ts.map +1 -1
  111. package/dist/commands/hostname.js +5 -0
  112. package/dist/commands/id.d.ts.map +1 -1
  113. package/dist/commands/id.js +4 -1
  114. package/dist/commands/index.d.ts +2 -10
  115. package/dist/commands/index.d.ts.map +1 -1
  116. package/dist/commands/index.js +2 -231
  117. package/dist/commands/ls.d.ts.map +1 -1
  118. package/dist/commands/ls.js +6 -3
  119. package/dist/commands/lsb-release.d.ts +3 -0
  120. package/dist/commands/lsb-release.d.ts.map +1 -0
  121. package/dist/commands/lsb-release.js +56 -0
  122. package/dist/commands/man.d.ts +3 -0
  123. package/dist/commands/man.d.ts.map +1 -0
  124. package/dist/commands/man.js +155 -0
  125. package/dist/commands/nano.js +1 -1
  126. package/dist/commands/neofetch.d.ts.map +1 -1
  127. package/dist/commands/neofetch.js +6 -1
  128. package/dist/commands/node.d.ts +9 -0
  129. package/dist/commands/node.d.ts.map +1 -0
  130. package/dist/commands/node.js +316 -0
  131. package/dist/commands/npm.d.ts +19 -0
  132. package/dist/commands/npm.d.ts.map +1 -0
  133. package/dist/commands/npm.js +109 -0
  134. package/dist/commands/ping.d.ts.map +1 -1
  135. package/dist/commands/ping.js +7 -2
  136. package/dist/commands/printf.d.ts +3 -0
  137. package/dist/commands/printf.d.ts.map +1 -0
  138. package/dist/commands/printf.js +113 -0
  139. package/dist/commands/ps.d.ts.map +1 -1
  140. package/dist/commands/ps.js +30 -6
  141. package/dist/commands/python.d.ts +30 -0
  142. package/dist/commands/python.d.ts.map +1 -0
  143. package/dist/commands/python.js +2058 -0
  144. package/dist/commands/read.d.ts +3 -0
  145. package/dist/commands/read.d.ts.map +1 -0
  146. package/dist/commands/read.js +34 -0
  147. package/dist/commands/registry.d.ts +8 -0
  148. package/dist/commands/registry.d.ts.map +1 -0
  149. package/dist/commands/registry.js +229 -0
  150. package/dist/commands/runtime.d.ts +6 -0
  151. package/dist/commands/runtime.d.ts.map +1 -0
  152. package/dist/commands/runtime.js +280 -0
  153. package/dist/commands/sed.d.ts.map +1 -1
  154. package/dist/commands/sed.js +11 -3
  155. package/dist/commands/set.d.ts.map +1 -1
  156. package/dist/commands/set.js +9 -3
  157. package/dist/commands/sh.d.ts.map +1 -1
  158. package/dist/commands/sh.js +69 -30
  159. package/dist/commands/shift.d.ts +5 -0
  160. package/dist/commands/shift.d.ts.map +1 -0
  161. package/dist/commands/shift.js +52 -0
  162. package/dist/commands/sleep.d.ts.map +1 -1
  163. package/dist/commands/sort.d.ts.map +1 -1
  164. package/dist/commands/sort.js +4 -2
  165. package/dist/commands/source.d.ts +3 -0
  166. package/dist/commands/source.d.ts.map +1 -0
  167. package/dist/commands/source.js +34 -0
  168. package/dist/commands/sudo.js +1 -1
  169. package/dist/commands/tar.d.ts.map +1 -1
  170. package/dist/commands/tar.js +11 -3
  171. package/dist/commands/tee.d.ts.map +1 -1
  172. package/dist/commands/tee.js +8 -6
  173. package/dist/commands/test.d.ts +3 -0
  174. package/dist/commands/test.d.ts.map +1 -0
  175. package/dist/commands/test.js +114 -0
  176. package/dist/commands/tr.d.ts.map +1 -1
  177. package/dist/commands/tr.js +3 -1
  178. package/dist/commands/true.d.ts +4 -0
  179. package/dist/commands/true.d.ts.map +1 -0
  180. package/dist/commands/true.js +14 -0
  181. package/dist/commands/type.d.ts +3 -0
  182. package/dist/commands/type.d.ts.map +1 -0
  183. package/dist/commands/type.js +34 -0
  184. package/dist/commands/uname.d.ts.map +1 -1
  185. package/dist/commands/uname.js +4 -1
  186. package/dist/commands/uniq.d.ts.map +1 -1
  187. package/dist/commands/uptime.d.ts +3 -0
  188. package/dist/commands/uptime.d.ts.map +1 -0
  189. package/dist/commands/uptime.js +43 -0
  190. package/dist/commands/wget.d.ts.map +1 -1
  191. package/dist/commands/wget.js +92 -96
  192. package/dist/commands/which.d.ts +3 -0
  193. package/dist/commands/which.d.ts.map +1 -0
  194. package/dist/commands/which.js +32 -0
  195. package/dist/commands/xargs.d.ts.map +1 -1
  196. package/dist/commands/xargs.js +1 -1
  197. package/dist/index.d.ts +15 -11
  198. package/dist/index.d.ts.map +1 -1
  199. package/dist/index.js +9 -8
  200. package/dist/modules/linuxRootfs.d.ts +41 -0
  201. package/dist/modules/linuxRootfs.d.ts.map +1 -0
  202. package/dist/modules/linuxRootfs.js +440 -0
  203. package/dist/modules/neofetch.d.ts.map +1 -1
  204. package/dist/modules/neofetch.js +1 -0
  205. package/dist/standalone-wo-sftp.d.ts +2 -0
  206. package/dist/standalone-wo-sftp.d.ts.map +1 -0
  207. package/dist/standalone-wo-sftp.js +30 -0
  208. package/dist/utils/expand.d.ts +50 -0
  209. package/dist/utils/expand.d.ts.map +1 -0
  210. package/dist/utils/expand.js +183 -0
  211. package/dist/utils/vfsDiff.d.ts +90 -0
  212. package/dist/utils/vfsDiff.d.ts.map +1 -0
  213. package/dist/utils/vfsDiff.js +177 -0
  214. package/package.json +3 -1
  215. package/src/SSHMimic/exec.ts +10 -1
  216. package/src/SSHMimic/executor.ts +105 -21
  217. package/src/SSHMimic/index.ts +49 -15
  218. package/src/VirtualFileSystem/binaryPack.ts +35 -8
  219. package/src/VirtualFileSystem/index.ts +78 -28
  220. package/src/VirtualPackageManager/index.ts +979 -0
  221. package/src/VirtualShell/index.ts +133 -14
  222. package/src/VirtualShell/shell.ts +23 -3
  223. package/src/VirtualShell/shellParser.ts +134 -36
  224. package/src/VirtualUserManager/index.ts +62 -22
  225. package/src/commands/adduser.ts +6 -0
  226. package/src/commands/alias.ts +64 -0
  227. package/src/commands/apt.ts +228 -0
  228. package/src/commands/awk.ts +20 -6
  229. package/src/commands/base64.ts +13 -2
  230. package/src/commands/cat.ts +40 -8
  231. package/src/commands/cd.ts +5 -0
  232. package/src/commands/chmod.ts +53 -3
  233. package/src/commands/command-helpers.ts +78 -4
  234. package/src/commands/cp.ts +5 -0
  235. package/src/commands/curl.ts +118 -33
  236. package/src/commands/cut.ts +8 -1
  237. package/src/commands/date.ts +7 -1
  238. package/src/commands/declare.ts +44 -0
  239. package/src/commands/diff.ts +17 -3
  240. package/src/commands/dpkg.ts +180 -0
  241. package/src/commands/du.ts +17 -5
  242. package/src/commands/echo.ts +41 -12
  243. package/src/commands/env.ts +11 -1
  244. package/src/commands/exit.ts +12 -2
  245. package/src/commands/export.ts +3 -1
  246. package/src/commands/find.ts +5 -0
  247. package/src/commands/free.ts +47 -0
  248. package/src/commands/grep.ts +12 -2
  249. package/src/commands/gzip.ts +28 -4
  250. package/src/commands/head.ts +5 -0
  251. package/src/commands/help.ts +121 -47
  252. package/src/commands/helpers.ts +8 -0
  253. package/src/commands/history.ts +34 -0
  254. package/src/commands/hostname.ts +5 -0
  255. package/src/commands/id.ts +4 -1
  256. package/src/commands/index.ts +9 -255
  257. package/src/commands/ls.ts +6 -3
  258. package/src/commands/lsb-release.ts +58 -0
  259. package/src/commands/man.ts +166 -0
  260. package/src/commands/nano.ts +1 -1
  261. package/src/commands/neofetch.ts +6 -1
  262. package/src/commands/node.ts +341 -0
  263. package/src/commands/npm.ts +132 -0
  264. package/src/commands/ping.ts +10 -3
  265. package/src/commands/printf.ts +112 -0
  266. package/src/commands/ps.ts +40 -6
  267. package/src/commands/python.ts +2229 -0
  268. package/src/commands/read.ts +41 -0
  269. package/src/commands/registry.ts +244 -0
  270. package/src/commands/runtime.ts +353 -0
  271. package/src/commands/sed.ts +27 -9
  272. package/src/commands/set.ts +9 -3
  273. package/src/commands/sh.ts +170 -44
  274. package/src/commands/shift.ts +53 -0
  275. package/src/commands/sleep.ts +2 -1
  276. package/src/commands/sort.ts +10 -6
  277. package/src/commands/source.ts +47 -0
  278. package/src/commands/sudo.ts +1 -1
  279. package/src/commands/tar.ts +28 -7
  280. package/src/commands/tee.ts +7 -1
  281. package/src/commands/test.ts +135 -0
  282. package/src/commands/tr.ts +3 -1
  283. package/src/commands/true.ts +17 -0
  284. package/src/commands/type.ts +43 -0
  285. package/src/commands/uname.ts +5 -1
  286. package/src/commands/uniq.ts +8 -2
  287. package/src/commands/uptime.ts +49 -0
  288. package/src/commands/wget.ts +105 -119
  289. package/src/commands/which.ts +37 -0
  290. package/src/commands/xargs.ts +11 -2
  291. package/src/index.ts +27 -18
  292. package/src/modules/linuxRootfs.ts +642 -0
  293. package/src/modules/neofetch.ts +1 -0
  294. package/src/standalone-wo-sftp.ts +38 -0
  295. package/src/utils/expand.ts +238 -0
  296. package/src/utils/vfsDiff.ts +275 -0
  297. package/standalone-wo-sftp.js +507 -0
  298. package/standalone-wo-sftp.js.map +7 -0
  299. package/standalone.js +486 -109
  300. package/standalone.js.map +4 -4
  301. package/tests/bun-test-shim.ts +9 -1
  302. package/tests/command-helpers.test.ts +1 -5
  303. package/tests/new-features.test.ts +1036 -0
  304. package/tests/parser-executor.test.ts +27 -27
  305. package/tests/sftp.test.ts +122 -42
  306. package/tests/users.test.ts +23 -5
  307. package/CHANGELOG.md +0 -150
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uptime.d.ts","sourceRoot":"","sources":["../../src/commands/uptime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,aAAa,EAAE,WA6C3B,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { ifFlag } from "./command-helpers";
2
+ export const uptimeCommand = {
3
+ name: "uptime",
4
+ description: "Tell how long the system has been running",
5
+ category: "system",
6
+ params: ["[-p] [-s]"],
7
+ run: ({ args, shell }) => {
8
+ const pretty = ifFlag(args, ["-p"]);
9
+ const since = ifFlag(args, ["-s"]);
10
+ const uptimeSec = Math.floor((Date.now() - shell.startTime) / 1000);
11
+ const days = Math.floor(uptimeSec / 86400);
12
+ const hours = Math.floor((uptimeSec % 86400) / 3600);
13
+ const mins = Math.floor((uptimeSec % 3600) / 60);
14
+ if (since) {
15
+ return {
16
+ stdout: new Date(shell.startTime)
17
+ .toISOString()
18
+ .slice(0, 19)
19
+ .replace("T", " "),
20
+ exitCode: 0,
21
+ };
22
+ }
23
+ if (pretty) {
24
+ const parts = [];
25
+ if (days > 0)
26
+ parts.push(`${days} day${days > 1 ? "s" : ""}`);
27
+ if (hours > 0)
28
+ parts.push(`${hours} hour${hours > 1 ? "s" : ""}`);
29
+ parts.push(`${mins} minute${mins !== 1 ? "s" : ""}`);
30
+ return { stdout: `up ${parts.join(", ")}`, exitCode: 0 };
31
+ }
32
+ const timeStr = new Date().toTimeString().slice(0, 8);
33
+ const uptimeStr = days > 0
34
+ ? `${days} day${days > 1 ? "s" : ""}, ${String(hours).padStart(2)}:${String(mins).padStart(2, "0")}`
35
+ : `${String(hours).padStart(2)}:${String(mins).padStart(2, "0")}`;
36
+ const sessions = shell.users.listActiveSessions().length;
37
+ const load = (Math.random() * 0.5).toFixed(2);
38
+ return {
39
+ stdout: ` ${timeStr} up ${uptimeStr}, ${sessions} user${sessions !== 1 ? "s" : ""}, load average: ${load}, ${load}, ${load}`,
40
+ exitCode: 0,
41
+ };
42
+ },
43
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"wget.d.ts","sourceRoot":"","sources":["../../src/commands/wget.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA8ErD,eAAO,MAAM,WAAW,EAAE,WA+DzB,CAAC"}
1
+ {"version":3,"file":"wget.d.ts","sourceRoot":"","sources":["../../src/commands/wget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,WAAW,EAAE,WA+HzB,CAAC"}
@@ -1,115 +1,111 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdtemp, readFile, rm } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
1
  import { ifFlag, parseArgs } from "./command-helpers";
6
- import { assertPathAccess, normalizeTerminalOutput, resolvePath, runHostCommand, stripUrlFilename, } from "./helpers";
7
- function runHostWget(args) {
8
- return new Promise((resolve) => {
9
- let childProcess;
10
- try {
11
- childProcess = spawn("wget", args, {
12
- stdio: ["ignore", "pipe", "pipe"],
13
- });
14
- }
15
- catch (error) {
16
- resolve({
17
- stdout: "",
18
- stderr: `wget: ${error instanceof Error ? error.message : String(error)}`,
19
- exitCode: 1,
20
- });
21
- return;
22
- }
23
- let stdout = "";
24
- let stderr = "";
25
- const stdoutStream = childProcess.stdout;
26
- const stderrStream = childProcess.stderr;
27
- if (!stdoutStream || !stderrStream) {
28
- resolve({
29
- stdout: "",
30
- stderr: "wget: failed to capture process output",
31
- exitCode: 1,
32
- });
33
- return;
34
- }
35
- stdoutStream.setEncoding("utf8");
36
- stderrStream.setEncoding("utf8");
37
- stdoutStream.on("data", (chunk) => {
38
- stdout += chunk;
39
- });
40
- stderrStream.on("data", (chunk) => {
41
- stderr += chunk;
42
- });
43
- childProcess.on("error", (error) => {
44
- const errorCode = error instanceof Error && "code" in error
45
- ? String(error.code ?? "")
46
- : "";
47
- resolve({
48
- stdout: "",
49
- stderr: `wget: ${error.message}`,
50
- exitCode: errorCode === "ENOENT" ? 127 : 1,
51
- });
52
- });
53
- childProcess.on("close", (code) => {
54
- resolve({
55
- stdout,
56
- stderr,
57
- exitCode: code ?? 1,
58
- });
59
- });
60
- });
61
- }
2
+ import { assertPathAccess, resolvePath, stripUrlFilename } from "./helpers";
62
3
  export const wgetCommand = {
63
4
  name: "wget",
64
- description: "File downloader",
5
+ description: "File downloader (pure fetch)",
65
6
  category: "network",
66
- params: ["[url]"],
7
+ params: ["[options] <url>"],
67
8
  run: async ({ authUser, cwd, args, shell }) => {
68
9
  const { flagsWithValues, positionals } = parseArgs(args, {
69
- flagsWithValue: ["-o", "-O", "--output", "--output-document"],
10
+ flagsWithValue: [
11
+ "-O",
12
+ "--output-document",
13
+ "-o",
14
+ "--output-file",
15
+ "-P",
16
+ "--directory-prefix",
17
+ "--tries",
18
+ "--timeout",
19
+ ],
70
20
  });
71
- const outputPath = flagsWithValues.get("-o") ||
72
- flagsWithValues.get("-O") ||
73
- flagsWithValues.get("--output") ||
74
- flagsWithValues.get("--output-document") ||
75
- null;
76
- const url = positionals[0];
77
- if (!url) {
78
- return { stderr: "wget: missing URL", exitCode: 1 };
21
+ if (ifFlag(args, ["-h", "--help"])) {
22
+ return {
23
+ stdout: [
24
+ "Usage: wget [option]... [URL]...",
25
+ " -O, --output-document=FILE Write to FILE ('-' for stdout)",
26
+ " -P, --directory-prefix=DIR Save files in DIR",
27
+ " -q, --quiet Quiet mode",
28
+ " -v, --verbose Verbose output (default)",
29
+ " -c, --continue Continue partial download",
30
+ " --tries=N Retry N times",
31
+ " --timeout=N Timeout in seconds",
32
+ ].join("\n"),
33
+ exitCode: 0,
34
+ };
79
35
  }
80
- const isHelpLike = ifFlag(args, ["-h", "--help", "-V", "--version"]);
81
- if (isHelpLike) {
82
- const result = await runHostWget(args);
36
+ if (ifFlag(args, ["-V", "--version"])) {
83
37
  return {
84
- stdout: normalizeTerminalOutput(result.stdout),
85
- stderr: result.stderr
86
- ? normalizeTerminalOutput(result.stderr)
87
- : undefined,
88
- exitCode: result.exitCode,
38
+ stdout: "GNU Wget 1.21.3 (virtual) built on Fortune GNU/Linux.",
39
+ exitCode: 0,
89
40
  };
90
41
  }
91
- const tempDir = await mkdtemp(join(tmpdir(), "virtual-env-js-wget-"));
92
- const tempFile = join(tempDir, "download");
42
+ const url = positionals[0];
43
+ if (!url)
44
+ return {
45
+ stderr: "wget: missing URL\nUsage: wget [OPTION]... [URL]...",
46
+ exitCode: 1,
47
+ };
48
+ const outputArg = flagsWithValues.get("-O") ??
49
+ flagsWithValues.get("--output-document") ??
50
+ null;
51
+ const dirPrefix = flagsWithValues.get("-P") ??
52
+ flagsWithValues.get("--directory-prefix") ??
53
+ null;
54
+ const quiet = ifFlag(args, ["-q", "--quiet"]);
55
+ // Derive target filename
56
+ const filename = outputArg === "-" ? null : (outputArg ?? stripUrlFilename(url));
57
+ const targetPath = filename
58
+ ? resolvePath(cwd, dirPrefix ? `${dirPrefix}/${filename}` : filename)
59
+ : null;
60
+ if (targetPath)
61
+ assertPathAccess(authUser, targetPath, "wget");
62
+ const stderrLines = [];
63
+ if (!quiet) {
64
+ stderrLines.push(`--${new Date().toISOString()}-- ${url}`);
65
+ stderrLines.push(`Resolving ${new URL(url).host}...`);
66
+ stderrLines.push(`Connecting to ${new URL(url).host}...`);
67
+ }
68
+ let response;
93
69
  try {
94
- const hostArgs = [...positionals, "-O", tempFile];
95
- const result = await runHostCommand("wget", hostArgs);
96
- if (result.exitCode !== 0) {
97
- return {
98
- stderr: normalizeTerminalOutput(result.stderr || `wget: exited with code ${result.exitCode}`),
99
- exitCode: result.exitCode,
100
- };
101
- }
102
- const content = await readFile(tempFile, "utf8");
103
- const target = resolvePath(cwd, outputPath || stripUrlFilename(url));
104
- assertPathAccess(authUser, target, "wget");
105
- shell.writeFileAsUser(authUser, target, content);
70
+ response = await fetch(url, {
71
+ headers: { "User-Agent": "Wget/1.21.3 (Fortune GNU/Linux)" },
72
+ });
73
+ }
74
+ catch (err) {
75
+ const msg = err instanceof Error ? err.message : String(err);
76
+ stderrLines.push(`wget: unable to resolve host: ${msg}`);
77
+ return { stderr: stderrLines.join("\n"), exitCode: 4 };
78
+ }
79
+ if (!response.ok) {
80
+ stderrLines.push(`ERROR ${response.status}: ${response.statusText}`);
81
+ return { stderr: stderrLines.join("\n"), exitCode: 8 };
82
+ }
83
+ let body;
84
+ try {
85
+ body = await response.text();
86
+ }
87
+ catch {
88
+ return { stderr: "wget: failed to read response", exitCode: 1 };
89
+ }
90
+ if (!quiet) {
91
+ const ct = response.headers.get("content-type") ?? "application/octet-stream";
92
+ stderrLines.push(`HTTP request sent, awaiting response... ${response.status} ${response.statusText}`);
93
+ stderrLines.push(`Length: ${body.length} [${ct}]`);
94
+ }
95
+ // Output to stdout (pipe) or file
96
+ if (outputArg === "-") {
106
97
  return {
107
- stdout: `saved ${target}`,
98
+ stdout: body,
99
+ stderr: stderrLines.join("\n") || undefined,
108
100
  exitCode: 0,
109
101
  };
110
102
  }
111
- finally {
112
- await rm(tempDir, { recursive: true, force: true });
103
+ if (targetPath) {
104
+ shell.writeFileAsUser(authUser, targetPath, body);
105
+ if (!quiet)
106
+ stderrLines.push(`Saving to: '${targetPath}'\n${targetPath} 100%[==================>] ${body.length} B`);
107
+ return { stderr: stderrLines.join("\n") || undefined, exitCode: 0 };
113
108
  }
109
+ return { stdout: body, exitCode: 0 };
114
110
  },
115
111
  };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const whichCommand: ShellModule;
3
+ //# sourceMappingURL=which.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"which.d.ts","sourceRoot":"","sources":["../../src/commands/which.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,YAAY,EAAE,WAkC1B,CAAC"}
@@ -0,0 +1,32 @@
1
+ export const whichCommand = {
2
+ name: "which",
3
+ description: "Locate a command in PATH",
4
+ category: "shell",
5
+ params: ["<command...>"],
6
+ run: ({ args, shell, env }) => {
7
+ if (args.length === 0)
8
+ return { stderr: "which: missing argument", exitCode: 1 };
9
+ const pathDirs = (env?.vars?.PATH ?? "/usr/local/bin:/usr/bin:/bin").split(":");
10
+ const lines = [];
11
+ let anyMissing = false;
12
+ for (const name of args) {
13
+ let found = false;
14
+ for (const dir of pathDirs) {
15
+ const full = `${dir}/${name}`;
16
+ if (shell.vfs.exists(full)) {
17
+ const st = shell.vfs.stat(full);
18
+ if (st.type === "file") {
19
+ lines.push(full);
20
+ found = true;
21
+ break;
22
+ }
23
+ }
24
+ }
25
+ if (!found)
26
+ anyMissing = true;
27
+ }
28
+ if (lines.length === 0)
29
+ return { exitCode: 1 };
30
+ return { stdout: lines.join("\n"), exitCode: anyMissing ? 1 : 0 };
31
+ },
32
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"xargs.d.ts","sourceRoot":"","sources":["../../src/commands/xargs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,YAAY,EAAE,WAa1B,CAAC"}
1
+ {"version":3,"file":"xargs.d.ts","sourceRoot":"","sources":["../../src/commands/xargs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,YAAY,EAAE,WAsB1B,CAAC"}
@@ -1,4 +1,4 @@
1
- import { runCommand } from "./index";
1
+ import { runCommand } from "./runtime";
2
2
  export const xargsCommand = {
3
3
  name: "xargs",
4
4
  description: "Build and execute command lines from stdin",
package/dist/index.d.ts CHANGED
@@ -1,14 +1,18 @@
1
- import { HoneyPot } from "./Honeypot/index";
2
- import { SshClient } from "./SSHClient/index";
3
- import { SftpMimic, SshMimic } from "./SSHMimic/index";
4
- import VirtualFileSystem from "./VirtualFileSystem/index";
5
- import { VirtualShell } from "./VirtualShell/index";
6
- import { VirtualUserManager } from "./VirtualUserManager/index";
7
- export type { AuditLogEntry, HoneyPotStats, } from "./Honeypot/index";
8
- export type { CommandContext, CommandMode, CommandOutcome, CommandResult, NanoEditorSession, ShellModule, SudoChallenge, } from "./types/commands";
1
+ export { HoneyPot } from "./Honeypot/index";
2
+ export { SshClient } from "./SSHClient/index";
3
+ export { SftpMimic as VirtualSftpServer, SshMimic as VirtualSshServer } from "./SSHMimic/index";
4
+ export { default as VirtualFileSystem } from "./VirtualFileSystem/index";
5
+ export { VirtualPackageManager } from "./VirtualPackageManager/index";
6
+ export { VirtualShell } from "./VirtualShell/index";
7
+ export { VirtualUserManager } from "./VirtualUserManager/index";
8
+ export type { AuditLogEntry, HoneyPotStats } from "./Honeypot/index";
9
+ export type { CommandContext, CommandMode, CommandOutcome, CommandResult, NanoEditorSession, ShellEnv, ShellModule, SudoChallenge } from "./types/commands";
9
10
  export type { ExecStream, ShellStream } from "./types/streams";
10
- export type { RemoveOptions, VfsBaseNode, VfsDirectoryNode, VfsFileNode, VfsNodeStats, VfsNodeType, VfsSnapshot, VfsSnapshotBaseNode, VfsSnapshotDirectoryNode, VfsSnapshotFileNode, VfsSnapshotNode, WriteFileOptions, } from "./types/vfs";
11
+ export type { RemoveOptions, VfsBaseNode, VfsDirectoryNode, VfsFileNode, VfsNodeStats, VfsNodeType, VfsSnapshot, VfsSnapshotBaseNode, VfsSnapshotDirectoryNode, VfsSnapshotFileNode, VfsSnapshotNode, WriteFileOptions } from "./types/vfs";
11
12
  export type { VfsOptions, VfsPersistenceMode } from "./VirtualFileSystem/index";
12
- export { HoneyPot, SshClient, VirtualFileSystem, SftpMimic as VirtualSftpServer, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
13
- export { getArg, getFlag, ifFlag, } from "./commands/command-helpers";
13
+ export type { ShellProperties } from "./VirtualShell/index";
14
+ export type { InstalledPackage, PackageDefinition, PackageFile } from "./VirtualPackageManager/index";
15
+ export { assertDiff, diffSnapshots, formatDiff } from "./utils/vfsDiff";
16
+ export type { VfsDiff, VfsDiffEntry, VfsDiffModified } from "./utils/vfsDiff";
17
+ export { getArg, getFlag, ifFlag } from "./commands/command-helpers";
14
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,iBAAiB,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,YAAY,EACX,aAAa,EACb,aAAa,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,aAAa,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEhF,OAAO,EACN,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,SAAS,IAAI,iBAAiB,EAC9B,YAAY,EACZ,QAAQ,IAAI,gBAAgB,EAC5B,kBAAkB,GAClB,CAAC;AAEF,OAAO,EACN,MAAM,EACN,OAAO,EACP,MAAM,GACN,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,SAAS,IAAI,iBAAiB,EAAE,QAAQ,IAAI,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChG,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,YAAY,EACX,aAAa,EACb,aAAa,EACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,aAAa,EACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAChF,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,YAAY,EACX,gBAAgB,EAAE,iBAAiB,EACnC,WAAW,EACX,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACN,UAAU,EAAE,aAAa,EACzB,UAAU,EACV,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACX,OAAO,EACP,YAAY,EACZ,eAAe,EACf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACN,MAAM,EACN,OAAO,EACP,MAAM,EACN,MAAM,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
- import { HoneyPot } from "./Honeypot/index";
2
- import { SshClient } from "./SSHClient/index";
3
- import { SftpMimic, SshMimic } from "./SSHMimic/index";
4
- import VirtualFileSystem from "./VirtualFileSystem/index";
5
- import { VirtualShell } from "./VirtualShell/index";
6
- import { VirtualUserManager } from "./VirtualUserManager/index";
7
- export { HoneyPot, SshClient, VirtualFileSystem, SftpMimic as VirtualSftpServer, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
8
- export { getArg, getFlag, ifFlag, } from "./commands/command-helpers";
1
+ export { HoneyPot } from "./Honeypot/index";
2
+ export { SshClient } from "./SSHClient/index";
3
+ export { SftpMimic as VirtualSftpServer, SshMimic as VirtualSshServer } from "./SSHMimic/index";
4
+ export { default as VirtualFileSystem } from "./VirtualFileSystem/index";
5
+ export { VirtualPackageManager } from "./VirtualPackageManager/index";
6
+ export { VirtualShell } from "./VirtualShell/index";
7
+ export { VirtualUserManager } from "./VirtualUserManager/index";
8
+ export { assertDiff, diffSnapshots, formatDiff } from "./utils/vfsDiff";
9
+ export { getArg, getFlag, ifFlag } from "./commands/command-helpers";
@@ -0,0 +1,41 @@
1
+ /** biome-ignore-all lint/style/useNamingConvention: ENV VAR KEYS */
2
+ /**
3
+ * linuxRootfs.ts
4
+ *
5
+ * Bootstraps a realistic Linux directory hierarchy in the VFS.
6
+ * Called once during VirtualShell initialization. Idempotent — skips
7
+ * paths that already exist so FS-mode snapshots survive restarts.
8
+ */
9
+ import type { ShellProperties } from "../VirtualShell";
10
+ import type VirtualFileSystem from "../VirtualFileSystem";
11
+ import type { VirtualUserManager } from "../VirtualUserManager";
12
+ /**
13
+ * Sync `/etc/passwd`, `/etc/group`, and `/etc/shadow` from the
14
+ * VirtualUserManager's current user list into the VFS.
15
+ * @param vfs VirtualFileSystem instance to write files into
16
+ * @param users VirtualUserManager to source users from
17
+ */
18
+ export declare function syncEtcPasswd(vfs: VirtualFileSystem, users: VirtualUserManager): void;
19
+ /**
20
+ * Populate and refresh `/proc` virtual entries based on host stats and
21
+ * provided active sessions. Rewrites `/proc/uptime`, `/proc/meminfo`,
22
+ * `/proc/cpuinfo`, `/proc/<pid>` entries and `/proc/self` content.
23
+ * @param vfs VirtualFileSystem instance
24
+ * @param props ShellProperties used for version strings
25
+ * @param hostname Hostname to write into /proc/hostname
26
+ * @param shellStartTime Start time used to compute uptime
27
+ * @param sessions Optional active sessions list to populate per-pid entries
28
+ */
29
+ export declare function refreshProc(vfs: VirtualFileSystem, props: ShellProperties, hostname: string, shellStartTime: number, sessions?: import("../VirtualUserManager").VirtualActiveSession[]): void;
30
+ /**
31
+ * Bootstraps the full Linux rootfs hierarchy in the VFS.
32
+ * Safe to call multiple times — idempotent.
33
+ *
34
+ * @param vfs Target virtual filesystem.
35
+ * @param users User manager (for /etc/passwd sync).
36
+ * @param hostname Virtual hostname.
37
+ * @param props Shell properties (kernel, os, arch).
38
+ * @param shellStartTime Unix ms of shell creation (for uptime).
39
+ */
40
+ export declare function bootstrapLinuxRootfs(vfs: VirtualFileSystem, users: VirtualUserManager, hostname: string, props: ShellProperties, shellStartTime: number): void;
41
+ //# sourceMappingURL=linuxRootfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linuxRootfs.d.ts","sourceRoot":"","sources":["../../src/modules/linuxRootfs.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,iBAAiB,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAgHhE;;;;;GAKG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,kBAAkB,GACvB,IAAI,CAsCN;AAgED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAC1B,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,OAAO,uBAAuB,EAAE,oBAAoB,EAAE,GAC/D,IAAI,CAmJN;AAuND;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,kBAAkB,EACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,eAAe,EACtB,cAAc,EAAE,MAAM,GACpB,IAAI,CAYN"}