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,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const readCommand: ShellModule;
3
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/commands/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,WAAW,EAAE,WAqCzB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { ifFlag } from "./command-helpers";
2
+ export const readCommand = {
3
+ name: "read",
4
+ description: "Read a line from stdin into variables",
5
+ category: "shell",
6
+ params: ["[-r] [-p prompt] <var...>"],
7
+ run: ({ args, stdin, env }) => {
8
+ const _promptIdx = args.indexOf("-p");
9
+ const varNames = args.filter((a, i) => a !== "-r" && a !== "-p" && args[i - 1] !== "-p");
10
+ // In non-interactive context, read from stdin pipe
11
+ const input = (stdin ?? "").split("\n")[0] ?? "";
12
+ const line = ifFlag(args, ["-r"])
13
+ ? input
14
+ : input.replace(/\\(?:\r?\n|.)/g, (m) => m[1] === "\n" || m[1] === "\r" ? "" : m[1]);
15
+ if (!env)
16
+ return { exitCode: 0 };
17
+ if (varNames.length === 0) {
18
+ // No var names: store into REPLY
19
+ env.vars.REPLY = line;
20
+ }
21
+ else if (varNames.length === 1) {
22
+ env.vars[varNames[0]] = line;
23
+ }
24
+ else {
25
+ // Split on whitespace, last var gets remainder
26
+ const parts = line.split(/\s+/);
27
+ for (let i = 0; i < varNames.length; i++) {
28
+ env.vars[varNames[i]] =
29
+ i < varNames.length - 1 ? (parts[i] ?? "") : parts.slice(i).join(" ");
30
+ }
31
+ }
32
+ return { exitCode: 0 };
33
+ },
34
+ };
@@ -0,0 +1,8 @@
1
+ /** biome-ignore-all lint/style/useNamingConvention: ENV VARIABLES */
2
+ import type { CommandContext, CommandResult, ShellModule } from "../types/commands";
3
+ export declare function registerCommand(module: ShellModule): void;
4
+ export declare function createCustomCommand(name: string, params: string[], run: (ctx: CommandContext) => CommandResult | Promise<CommandResult>): ShellModule;
5
+ export declare function getCommandNames(): string[];
6
+ export declare function getCommandModulesPublic(): ShellModule[];
7
+ export declare function resolveModule(name: string): ShellModule | undefined;
8
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/commands/registry.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAgNpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAYzD;AAED,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EAAE,EAChB,GAAG,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,GAClE,WAAW,CAEb;AAED,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAG1C;AAED,wBAAgB,uBAAuB,IAAI,WAAW,EAAE,CAEvD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGnE"}
@@ -0,0 +1,229 @@
1
+ import { adduserCommand } from "./adduser";
2
+ import { aliasCommand, unaliasCommand } from "./alias";
3
+ import { aptCacheCommand, aptCommand } from "./apt";
4
+ import { awkCommand } from "./awk";
5
+ import { base64Command } from "./base64";
6
+ import { catCommand } from "./cat";
7
+ import { cdCommand } from "./cd";
8
+ import { chmodCommand } from "./chmod";
9
+ import { clearCommand } from "./clear";
10
+ import { cpCommand } from "./cp";
11
+ import { curlCommand } from "./curl";
12
+ import { cutCommand } from "./cut";
13
+ import { dateCommand } from "./date";
14
+ import { declareCommand } from "./declare";
15
+ import { deluserCommand } from "./deluser";
16
+ import { dfCommand } from "./df";
17
+ import { diffCommand } from "./diff";
18
+ import { dpkgCommand, dpkgQueryCommand } from "./dpkg";
19
+ import { duCommand } from "./du";
20
+ import { echoCommand } from "./echo";
21
+ import { envCommand } from "./env";
22
+ import { exitCommand } from "./exit";
23
+ import { exportCommand } from "./export";
24
+ import { findCommand } from "./find";
25
+ import { freeCommand } from "./free";
26
+ import { grepCommand } from "./grep";
27
+ import { groupsCommand } from "./groups";
28
+ import { gunzipCommand, gzipCommand } from "./gzip";
29
+ import { headCommand } from "./head";
30
+ import { createHelpCommand } from "./help";
31
+ import { historyCommand } from "./history";
32
+ import { hostnameCommand } from "./hostname";
33
+ import { htopCommand } from "./htop";
34
+ import { idCommand } from "./id";
35
+ import { killCommand } from "./kill";
36
+ import { lnCommand } from "./ln";
37
+ import { lsCommand } from "./ls";
38
+ import { lsbReleaseCommand } from "./lsb-release";
39
+ import { manCommand } from "./man";
40
+ import { mkdirCommand } from "./mkdir";
41
+ import { mvCommand } from "./mv";
42
+ import { nanoCommand } from "./nano";
43
+ import { neofetchCommand } from "./neofetch";
44
+ import { nodeCommand } from "./node";
45
+ import { npmCommand, npxCommand } from "./npm";
46
+ import { passwdCommand } from "./passwd";
47
+ import { pingCommand } from "./ping";
48
+ import { printfCommand } from "./printf";
49
+ import { psCommand } from "./ps";
50
+ import { pwdCommand } from "./pwd";
51
+ import { python3Command } from "./python";
52
+ import { readCommand } from "./read";
53
+ import { rmCommand } from "./rm";
54
+ import { sedCommand } from "./sed";
55
+ import { setCommand } from "./set";
56
+ import { shCommand } from "./sh";
57
+ import { returnCommand, shiftCommand, trapCommand } from "./shift";
58
+ import { sleepCommand } from "./sleep";
59
+ import { sortCommand } from "./sort";
60
+ import { sourceCommand } from "./source";
61
+ import { suCommand } from "./su";
62
+ import { sudoCommand } from "./sudo";
63
+ import { tailCommand } from "./tail";
64
+ import { tarCommand } from "./tar";
65
+ import { teeCommand } from "./tee";
66
+ import { testCommand } from "./test";
67
+ import { touchCommand } from "./touch";
68
+ import { trCommand } from "./tr";
69
+ import { treeCommand } from "./tree";
70
+ import { falseCommand, trueCommand } from "./true";
71
+ import { typeCommand } from "./type";
72
+ import { unameCommand } from "./uname";
73
+ import { uniqCommand } from "./uniq";
74
+ import { unsetCommand } from "./unset";
75
+ import { uptimeCommand } from "./uptime";
76
+ import { wcCommand } from "./wc";
77
+ import { wgetCommand } from "./wget";
78
+ import { whichCommand } from "./which";
79
+ import { whoCommand } from "./who";
80
+ import { whoamiCommand } from "./whoami";
81
+ import { xargsCommand } from "./xargs";
82
+ const BASE_COMMANDS = [
83
+ // Navigation
84
+ pwdCommand,
85
+ cdCommand,
86
+ lsCommand,
87
+ treeCommand,
88
+ // Files
89
+ catCommand,
90
+ touchCommand,
91
+ rmCommand,
92
+ mkdirCommand,
93
+ cpCommand,
94
+ mvCommand,
95
+ lnCommand,
96
+ chmodCommand,
97
+ findCommand,
98
+ // Text processing
99
+ grepCommand,
100
+ sedCommand,
101
+ awkCommand,
102
+ sortCommand,
103
+ uniqCommand,
104
+ wcCommand,
105
+ headCommand,
106
+ tailCommand,
107
+ cutCommand,
108
+ trCommand,
109
+ teeCommand,
110
+ xargsCommand,
111
+ diffCommand,
112
+ // Archives
113
+ tarCommand,
114
+ gzipCommand,
115
+ gunzipCommand,
116
+ base64Command,
117
+ // System info
118
+ whoamiCommand,
119
+ whoCommand,
120
+ hostnameCommand,
121
+ idCommand,
122
+ groupsCommand,
123
+ unameCommand,
124
+ psCommand,
125
+ killCommand,
126
+ dfCommand,
127
+ duCommand,
128
+ dateCommand,
129
+ sleepCommand,
130
+ pingCommand,
131
+ // Shell
132
+ echoCommand,
133
+ envCommand,
134
+ exportCommand,
135
+ setCommand,
136
+ unsetCommand,
137
+ shCommand,
138
+ clearCommand,
139
+ exitCommand,
140
+ // Editors
141
+ nanoCommand,
142
+ htopCommand,
143
+ // Network
144
+ curlCommand,
145
+ wgetCommand,
146
+ // Users
147
+ adduserCommand,
148
+ passwdCommand,
149
+ deluserCommand,
150
+ sudoCommand,
151
+ suCommand,
152
+ // Misc
153
+ neofetchCommand,
154
+ // Package management
155
+ aptCommand,
156
+ aptCacheCommand,
157
+ dpkgCommand,
158
+ dpkgQueryCommand,
159
+ // Shell (extended)
160
+ whichCommand,
161
+ typeCommand,
162
+ manCommand,
163
+ aliasCommand,
164
+ unaliasCommand,
165
+ testCommand,
166
+ sourceCommand,
167
+ historyCommand,
168
+ printfCommand,
169
+ readCommand,
170
+ declareCommand,
171
+ shiftCommand,
172
+ trapCommand,
173
+ returnCommand,
174
+ trueCommand,
175
+ falseCommand,
176
+ npmCommand,
177
+ npxCommand,
178
+ nodeCommand,
179
+ python3Command,
180
+ // System (extended)
181
+ uptimeCommand,
182
+ freeCommand,
183
+ lsbReleaseCommand,
184
+ ];
185
+ const customCommands = [];
186
+ const commandRegistry = new Map();
187
+ let cachedCommandNames = null;
188
+ const helpCommand = createHelpCommand(() => getCommandModules().map((cmd) => cmd.name));
189
+ function buildCache() {
190
+ commandRegistry.clear();
191
+ for (const mod of getCommandModules()) {
192
+ commandRegistry.set(mod.name, mod);
193
+ for (const alias of mod.aliases ?? [])
194
+ commandRegistry.set(alias, mod);
195
+ }
196
+ cachedCommandNames = Array.from(commandRegistry.keys()).sort();
197
+ }
198
+ function getCommandModules() {
199
+ return [...BASE_COMMANDS, ...customCommands, helpCommand];
200
+ }
201
+ export function registerCommand(module) {
202
+ const normalized = {
203
+ ...module,
204
+ name: module.name.trim().toLowerCase(),
205
+ aliases: module.aliases?.map((a) => a.trim().toLowerCase()),
206
+ };
207
+ const names = [normalized.name, ...(normalized.aliases ?? [])];
208
+ if (names.some((n) => n.length === 0 || /\s/.test(n))) {
209
+ throw new Error("Command names must be non-empty and contain no spaces");
210
+ }
211
+ customCommands.push(normalized);
212
+ buildCache();
213
+ }
214
+ export function createCustomCommand(name, params, run) {
215
+ return { name, params, run };
216
+ }
217
+ export function getCommandNames() {
218
+ if (!cachedCommandNames)
219
+ buildCache();
220
+ return cachedCommandNames;
221
+ }
222
+ export function getCommandModulesPublic() {
223
+ return getCommandModules();
224
+ }
225
+ export function resolveModule(name) {
226
+ if (!cachedCommandNames)
227
+ buildCache();
228
+ return commandRegistry.get(name.toLowerCase());
229
+ }
@@ -0,0 +1,6 @@
1
+ import type { VirtualShell } from "../VirtualShell";
2
+ import type { CommandMode, CommandResult, ShellEnv } from "../types/commands";
3
+ export declare function makeDefaultEnv(authUser: string, hostname: string): ShellEnv;
4
+ export declare function runCommandDirect(name: string, args: string[], authUser: string, hostname: string, mode: CommandMode, cwd: string, shell: VirtualShell, stdin: string | undefined, env: ShellEnv): Promise<CommandResult>;
5
+ export declare function runCommand(rawInput: string, authUser: string, hostname: string, mode: CommandMode, cwd: string, shell: VirtualShell, stdin?: string, env?: ShellEnv): Promise<CommandResult>;
6
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/commands/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,KAAK,EACR,WAAW,EACX,aAAa,EACb,QAAQ,EACX,MAAM,mBAAmB,CAAC;AAiE3B,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAc3E;AAyCD,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,GAAG,EAAE,QAAQ,GACX,OAAO,CAAC,aAAa,CAAC,CA4ExB;AAED,wBAAsB,UAAU,CAC/B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,GAAG,CAAC,EAAE,QAAQ,GACZ,OAAO,CAAC,aAAa,CAAC,CA+HxB"}
@@ -0,0 +1,280 @@
1
+ /** biome-ignore-all lint/style/useNamingConvention: ENV VARIABLES */
2
+ import { executeStatements } from "../SSHMimic/executor";
3
+ import { parseScript } from "../VirtualShell/shellParser";
4
+ import { expandAsync } from "../utils/expand";
5
+ import { resolveModule } from "./registry";
6
+ // ── Tokenize command input respecting quotes ──────────────────────────────────
7
+ function tokenizeCommand(input) {
8
+ const tokens = [];
9
+ let current = "";
10
+ let inQ = false;
11
+ let qChar = "";
12
+ let i = 0;
13
+ while (i < input.length) {
14
+ const ch = input[i];
15
+ const next = input[i + 1];
16
+ if ((ch === '"' || ch === "'") && !inQ) {
17
+ inQ = true;
18
+ qChar = ch;
19
+ i++;
20
+ continue;
21
+ }
22
+ if (inQ && ch === qChar) {
23
+ inQ = false;
24
+ qChar = "";
25
+ i++;
26
+ continue;
27
+ }
28
+ if (inQ) {
29
+ current += ch;
30
+ i++;
31
+ continue;
32
+ }
33
+ if (ch === " ") {
34
+ if (current) {
35
+ tokens.push(current);
36
+ current = "";
37
+ }
38
+ i++;
39
+ continue;
40
+ }
41
+ if ((ch === ">" || ch === "<") && !inQ) {
42
+ if (current) {
43
+ tokens.push(current);
44
+ current = "";
45
+ }
46
+ if (ch === ">" && next === ">") {
47
+ tokens.push(">>");
48
+ i += 2;
49
+ }
50
+ else {
51
+ tokens.push(ch);
52
+ i++;
53
+ }
54
+ continue;
55
+ }
56
+ current += ch;
57
+ i++;
58
+ }
59
+ if (current)
60
+ tokens.push(current);
61
+ return tokens;
62
+ }
63
+ export function makeDefaultEnv(authUser, hostname) {
64
+ return {
65
+ vars: {
66
+ PATH: "/usr/local/bin:/usr/bin:/bin",
67
+ HOME: `/home/${authUser}`,
68
+ USER: authUser,
69
+ LOGNAME: authUser,
70
+ SHELL: "/bin/sh",
71
+ TERM: "xterm-256color",
72
+ HOSTNAME: hostname,
73
+ PS1: "\\u@\\h:\\w\\$ ",
74
+ },
75
+ lastExitCode: 0,
76
+ };
77
+ }
78
+ function resolveVfsBinary(name, env, shell, authUser) {
79
+ if (name.startsWith("/")) {
80
+ if (!shell.vfs.exists(name))
81
+ return null;
82
+ try {
83
+ const st = shell.vfs.stat(name);
84
+ if (st.type !== "file")
85
+ return null;
86
+ if (!(st.mode & 0o111))
87
+ return null;
88
+ if ((name.startsWith("/sbin/") || name.startsWith("/usr/sbin/")) &&
89
+ authUser !== "root")
90
+ return null;
91
+ return name;
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }
97
+ const pathDirs = (env.vars.PATH ?? "/usr/local/bin:/usr/bin:/bin").split(":");
98
+ for (const dir of pathDirs) {
99
+ if ((dir === "/sbin" || dir === "/usr/sbin") && authUser !== "root")
100
+ continue;
101
+ const full = `${dir}/${name}`;
102
+ if (!shell.vfs.exists(full))
103
+ continue;
104
+ try {
105
+ const st = shell.vfs.stat(full);
106
+ if (st.type !== "file")
107
+ continue;
108
+ if (!(st.mode & 0o111))
109
+ continue;
110
+ return full;
111
+ }
112
+ catch { }
113
+ }
114
+ return null;
115
+ }
116
+ export async function runCommandDirect(name, args, authUser, hostname, mode, cwd, shell, stdin, env) {
117
+ const aliasVal = env.vars[`__alias_${name}`];
118
+ if (aliasVal) {
119
+ return runCommand(`${aliasVal} ${args.join(" ")}`, authUser, hostname, mode, cwd, shell, stdin, env);
120
+ }
121
+ const mod = resolveModule(name);
122
+ if (!mod) {
123
+ const vfsBinary = resolveVfsBinary(name, env, shell, authUser);
124
+ if (vfsBinary) {
125
+ const stubContent = shell.vfs.readFile(vfsBinary);
126
+ const builtinMatch = stubContent.match(/exec\s+builtin\s+(\S+)/);
127
+ if (builtinMatch) {
128
+ const builtinMod = resolveModule(builtinMatch[1]);
129
+ if (builtinMod) {
130
+ return await builtinMod.run({
131
+ authUser,
132
+ hostname,
133
+ activeSessions: shell.users.listActiveSessions(),
134
+ rawInput: [name, ...args].join(" "),
135
+ mode,
136
+ args,
137
+ stdin,
138
+ cwd,
139
+ shell,
140
+ env,
141
+ });
142
+ }
143
+ }
144
+ const shMod = resolveModule("sh");
145
+ if (shMod) {
146
+ return await shMod.run({
147
+ authUser,
148
+ hostname,
149
+ activeSessions: shell.users.listActiveSessions(),
150
+ rawInput: `sh -c ${JSON.stringify(stubContent)}`,
151
+ mode,
152
+ args: ["-c", stubContent, "--", ...args],
153
+ stdin,
154
+ cwd,
155
+ shell,
156
+ env,
157
+ });
158
+ }
159
+ }
160
+ return { stderr: `${name}: command not found`, exitCode: 127 };
161
+ }
162
+ try {
163
+ return await mod.run({
164
+ authUser,
165
+ hostname,
166
+ activeSessions: shell.users.listActiveSessions(),
167
+ rawInput: [name, ...args].join(" "),
168
+ mode,
169
+ args,
170
+ stdin,
171
+ cwd,
172
+ shell,
173
+ env,
174
+ });
175
+ }
176
+ catch (error) {
177
+ return {
178
+ stderr: error instanceof Error ? error.message : "Command failed",
179
+ exitCode: 1,
180
+ };
181
+ }
182
+ }
183
+ export async function runCommand(rawInput, authUser, hostname, mode, cwd, shell, stdin, env) {
184
+ const trimmed = rawInput.trim();
185
+ if (trimmed.length === 0)
186
+ return { exitCode: 0 };
187
+ const shellEnv = env ?? makeDefaultEnv(authUser, hostname);
188
+ const rawTokens = tokenizeCommand(trimmed);
189
+ const rawFirstWord = rawTokens[0]?.toLowerCase() ?? "";
190
+ const aliasVal = shellEnv.vars[`__alias_${rawFirstWord}`];
191
+ const aliasExpanded = aliasVal
192
+ ? trimmed.replace(rawFirstWord, aliasVal)
193
+ : trimmed;
194
+ const hasOperators = /(?<![|&])[|](?![|])/.test(aliasExpanded) ||
195
+ aliasExpanded.includes(">") ||
196
+ aliasExpanded.includes("<") ||
197
+ aliasExpanded.includes("&&") ||
198
+ aliasExpanded.includes("||") ||
199
+ aliasExpanded.includes(";");
200
+ if (hasOperators) {
201
+ const script = parseScript(aliasExpanded);
202
+ if (!script.isValid)
203
+ return { stderr: script.error || "Syntax error", exitCode: 1 };
204
+ try {
205
+ return await executeStatements(script.statements, authUser, hostname, mode, cwd, shell, shellEnv);
206
+ }
207
+ catch (error) {
208
+ return {
209
+ stderr: error instanceof Error ? error.message : "Execution failed",
210
+ exitCode: 1,
211
+ };
212
+ }
213
+ }
214
+ const expanded = await expandAsync(aliasExpanded, shellEnv.vars, shellEnv.lastExitCode, (sub) => runCommand(sub, authUser, hostname, mode, cwd, shell, undefined, shellEnv).then((r) => r.stdout ?? ""));
215
+ const parts = tokenizeCommand(expanded.trim());
216
+ const commandName = parts[0]?.toLowerCase() ?? "";
217
+ const args = parts.slice(1);
218
+ const mod = resolveModule(commandName);
219
+ if (!mod) {
220
+ const vfsBinary = resolveVfsBinary(commandName, shellEnv, shell, authUser);
221
+ if (vfsBinary) {
222
+ const stubContent = shell.vfs.readFile(vfsBinary);
223
+ const builtinMatch = stubContent.match(/exec\s+builtin\s+(\S+)/);
224
+ if (builtinMatch) {
225
+ const builtinName = builtinMatch[1];
226
+ const builtinMod = resolveModule(builtinName);
227
+ if (builtinMod) {
228
+ return await builtinMod.run({
229
+ authUser,
230
+ hostname,
231
+ activeSessions: shell.users.listActiveSessions(),
232
+ rawInput: [commandName, ...args].join(" "),
233
+ mode,
234
+ args,
235
+ stdin,
236
+ cwd,
237
+ shell,
238
+ env: shellEnv,
239
+ });
240
+ }
241
+ }
242
+ const shMod = resolveModule("sh");
243
+ if (shMod) {
244
+ return await shMod.run({
245
+ authUser,
246
+ hostname,
247
+ activeSessions: shell.users.listActiveSessions(),
248
+ rawInput: `sh -c ${JSON.stringify(stubContent)}`,
249
+ mode,
250
+ args: ["-c", stubContent, "--", ...args],
251
+ stdin,
252
+ cwd,
253
+ shell,
254
+ env: shellEnv,
255
+ });
256
+ }
257
+ }
258
+ return { stderr: `${commandName}: command not found`, exitCode: 127 };
259
+ }
260
+ try {
261
+ return await mod.run({
262
+ authUser,
263
+ hostname,
264
+ activeSessions: shell.users.listActiveSessions(),
265
+ rawInput: expanded,
266
+ mode,
267
+ args,
268
+ stdin,
269
+ cwd,
270
+ shell,
271
+ env: shellEnv,
272
+ });
273
+ }
274
+ catch (error) {
275
+ return {
276
+ stderr: error instanceof Error ? error.message : "Command failed",
277
+ exitCode: 1,
278
+ };
279
+ }
280
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"sed.d.ts","sourceRoot":"","sources":["../../src/commands/sed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,UAAU,EAAE,WAwCxB,CAAC"}
1
+ {"version":3,"file":"sed.d.ts","sourceRoot":"","sources":["../../src/commands/sed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,UAAU,EAAE,WA0DxB,CAAC"}
@@ -7,7 +7,8 @@ export const sedCommand = {
7
7
  params: ["-e <expr> [file]", "s/pattern/replace/[g]"],
8
8
  run: ({ authUser, shell, cwd, args, stdin }) => {
9
9
  const inPlace = ifFlag(args, ["-i"]);
10
- const expr = getFlag(args, ["-e"]) ?? args.find((a) => !a.startsWith("-"));
10
+ const expr = getFlag(args, ["-e"]) ??
11
+ args.find((a) => !a.startsWith("-"));
11
12
  const fileArg = args.filter((a) => !a.startsWith("-") && a !== expr).pop();
12
13
  if (!expr)
13
14
  return { stderr: "sed: no expression", exitCode: 1 };
@@ -18,7 +19,10 @@ export const sedCommand = {
18
19
  content = shell.vfs.readFile(p);
19
20
  }
20
21
  catch {
21
- return { stderr: `sed: ${fileArg}: No such file or directory`, exitCode: 1 };
22
+ return {
23
+ stderr: `sed: ${fileArg}: No such file or directory`,
24
+ exitCode: 1,
25
+ };
22
26
  }
23
27
  }
24
28
  // Parse s/from/to/[g]
@@ -26,7 +30,11 @@ export const sedCommand = {
26
30
  if (!sMatch)
27
31
  return { stderr: `sed: unrecognized command: ${expr}`, exitCode: 1 };
28
32
  const [, , from, to, flags] = sMatch;
29
- const regexFlags = (flags ?? "").includes("i") ? "gi" : (flags ?? "").includes("g") ? "g" : "";
33
+ const regexFlags = (flags ?? "").includes("i")
34
+ ? "gi"
35
+ : (flags ?? "").includes("g")
36
+ ? "g"
37
+ : "";
30
38
  let regex;
31
39
  try {
32
40
  regex = new RegExp(from, regexFlags || "");
@@ -1 +1 @@
1
- {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/commands/set.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAWrD,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAA6B;AACxF,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAA8B;AAC1F,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAItE;AAED,eAAO,MAAM,UAAU,EAAE,WAkBxB,CAAC"}
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/commands/set.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAWrD,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1D;AACD,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE3D;AACD,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAItE;AAED,eAAO,MAAM,UAAU,EAAE,WAoBxB,CAAC"}
@@ -7,9 +7,13 @@ const _globalEnv = {
7
7
  USER: "user",
8
8
  };
9
9
  /** @deprecated use env.vars from CommandContext */
10
- export function getEnvVar(name) { return _globalEnv[name]; }
10
+ export function getEnvVar(name) {
11
+ return _globalEnv[name];
12
+ }
11
13
  /** @deprecated use env.vars from CommandContext */
12
- export function setEnvVar(name, value) { _globalEnv[name] = value; }
14
+ export function setEnvVar(name, value) {
15
+ _globalEnv[name] = value;
16
+ }
13
17
  /** @deprecated use env.vars from CommandContext */
14
18
  export function getAllEnvVars(authUser) {
15
19
  _globalEnv.USER = authUser;
@@ -23,7 +27,9 @@ export const setCommand = {
23
27
  params: ["[VAR=value]"],
24
28
  run: ({ args, env }) => {
25
29
  if (args.length === 0) {
26
- const out = Object.entries(env.vars).map(([k, v]) => `${k}=${v}`).join("\n");
30
+ const out = Object.entries(env.vars)
31
+ .map(([k, v]) => `${k}=${v}`)
32
+ .join("\n");
27
33
  return { stdout: out, exitCode: 0 };
28
34
  }
29
35
  for (const arg of args) {
@@ -1 +1 @@
1
- {"version":3,"file":"sh.d.ts","sourceRoot":"","sources":["../../src/commands/sh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiC,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA+KpF,eAAO,MAAM,SAAS,EAAE,WA+BvB,CAAC"}
1
+ {"version":3,"file":"sh.d.ts","sourceRoot":"","sources":["../../src/commands/sh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGR,WAAW,EACd,MAAM,mBAAmB,CAAC;AA4R3B,eAAO,MAAM,SAAS,EAAE,WA4CvB,CAAC"}