typescript-virtual-container 1.3.4 → 1.4.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 (282) hide show
  1. package/.vscode/settings.json +0 -1
  2. package/README.md +674 -1504
  3. package/benchmark-results.txt +21 -21
  4. package/builds/self-standalone.js +274 -208
  5. package/builds/self-standalone.js.map +4 -4
  6. package/builds/standalone-wo-sftp.js +201 -149
  7. package/builds/standalone-wo-sftp.js.map +4 -4
  8. package/builds/standalone.js +263 -211
  9. package/builds/standalone.js.map +4 -4
  10. package/builds/web-full-api.min.js +3 -3
  11. package/builds/web-full-api.min.js.map +4 -4
  12. package/builds/web.min.js +2 -2
  13. package/builds/web.min.js.map +4 -4
  14. package/bun.lock +14 -12
  15. package/dist/SSHClient/index.d.ts.map +1 -1
  16. package/dist/SSHClient/index.js +5 -3
  17. package/dist/SSHMimic/executor.d.ts +1 -3
  18. package/dist/SSHMimic/executor.d.ts.map +1 -1
  19. package/dist/SSHMimic/executor.js +20 -22
  20. package/dist/SSHMimic/index.d.ts.map +1 -1
  21. package/dist/SSHMimic/index.js +5 -3
  22. package/dist/SSHMimic/sftp.d.ts.map +1 -1
  23. package/dist/SSHMimic/sftp.js +26 -21
  24. package/dist/VirtualShell/shell.d.ts.map +1 -1
  25. package/dist/VirtualShell/shell.js +25 -3
  26. package/dist/VirtualShell/shellParser.d.ts +1 -8
  27. package/dist/VirtualShell/shellParser.d.ts.map +1 -1
  28. package/dist/VirtualShell/shellParser.js +2 -81
  29. package/dist/VirtualUserManager/index.d.ts +7 -1
  30. package/dist/VirtualUserManager/index.d.ts.map +1 -1
  31. package/dist/VirtualUserManager/index.js +47 -16
  32. package/dist/commands/adduser.d.ts +10 -4
  33. package/dist/commands/adduser.d.ts.map +1 -1
  34. package/dist/commands/adduser.js +75 -12
  35. package/dist/commands/alias.d.ts +5 -0
  36. package/dist/commands/alias.d.ts.map +1 -1
  37. package/dist/commands/alias.js +5 -0
  38. package/dist/commands/apt.d.ts +5 -0
  39. package/dist/commands/apt.d.ts.map +1 -1
  40. package/dist/commands/apt.js +5 -0
  41. package/dist/commands/awk.d.ts +10 -8
  42. package/dist/commands/awk.d.ts.map +1 -1
  43. package/dist/commands/awk.js +156 -28
  44. package/dist/commands/cd.d.ts.map +1 -1
  45. package/dist/commands/cd.js +0 -3
  46. package/dist/commands/clear.d.ts +5 -0
  47. package/dist/commands/clear.d.ts.map +1 -1
  48. package/dist/commands/clear.js +5 -0
  49. package/dist/commands/command-helpers.d.ts.map +1 -1
  50. package/dist/commands/command-helpers.js +8 -0
  51. package/dist/commands/declare.d.ts +5 -0
  52. package/dist/commands/declare.d.ts.map +1 -1
  53. package/dist/commands/declare.js +5 -0
  54. package/dist/commands/deluser.d.ts +12 -0
  55. package/dist/commands/deluser.d.ts.map +1 -1
  56. package/dist/commands/deluser.js +72 -6
  57. package/dist/commands/df.d.ts +5 -0
  58. package/dist/commands/df.d.ts.map +1 -1
  59. package/dist/commands/df.js +5 -0
  60. package/dist/commands/du.d.ts +5 -0
  61. package/dist/commands/du.d.ts.map +1 -1
  62. package/dist/commands/du.js +5 -0
  63. package/dist/commands/export.d.ts +5 -0
  64. package/dist/commands/export.d.ts.map +1 -1
  65. package/dist/commands/export.js +5 -0
  66. package/dist/commands/grep.d.ts.map +1 -1
  67. package/dist/commands/grep.js +22 -4
  68. package/dist/commands/groups.d.ts +5 -0
  69. package/dist/commands/groups.d.ts.map +1 -1
  70. package/dist/commands/groups.js +5 -0
  71. package/dist/commands/gzip.d.ts +5 -2
  72. package/dist/commands/gzip.d.ts.map +1 -1
  73. package/dist/commands/gzip.js +48 -28
  74. package/dist/commands/head.d.ts.map +1 -1
  75. package/dist/commands/head.js +12 -3
  76. package/dist/commands/htop.d.ts +5 -0
  77. package/dist/commands/htop.d.ts.map +1 -1
  78. package/dist/commands/htop.js +5 -0
  79. package/dist/commands/kill.d.ts +5 -0
  80. package/dist/commands/kill.d.ts.map +1 -1
  81. package/dist/commands/kill.js +5 -0
  82. package/dist/commands/ln.d.ts +2 -0
  83. package/dist/commands/ln.d.ts.map +1 -1
  84. package/dist/commands/ln.js +22 -0
  85. package/dist/commands/ls.d.ts.map +1 -1
  86. package/dist/commands/ls.js +15 -0
  87. package/dist/commands/lsb-release.d.ts +5 -0
  88. package/dist/commands/lsb-release.d.ts.map +1 -1
  89. package/dist/commands/lsb-release.js +5 -0
  90. package/dist/commands/mkdir.d.ts +5 -0
  91. package/dist/commands/mkdir.d.ts.map +1 -1
  92. package/dist/commands/mkdir.js +5 -0
  93. package/dist/commands/mv.d.ts +5 -0
  94. package/dist/commands/mv.d.ts.map +1 -1
  95. package/dist/commands/mv.js +5 -0
  96. package/dist/commands/nano.d.ts +5 -0
  97. package/dist/commands/nano.d.ts.map +1 -1
  98. package/dist/commands/nano.js +5 -0
  99. package/dist/commands/neofetch.d.ts +5 -0
  100. package/dist/commands/neofetch.d.ts.map +1 -1
  101. package/dist/commands/neofetch.js +8 -5
  102. package/dist/commands/passwd.d.ts +8 -0
  103. package/dist/commands/passwd.d.ts.map +1 -1
  104. package/dist/commands/passwd.js +32 -11
  105. package/dist/commands/ping.d.ts +5 -0
  106. package/dist/commands/ping.d.ts.map +1 -1
  107. package/dist/commands/ping.js +5 -0
  108. package/dist/commands/printf.d.ts +5 -0
  109. package/dist/commands/printf.d.ts.map +1 -1
  110. package/dist/commands/printf.js +43 -12
  111. package/dist/commands/ps.d.ts +5 -0
  112. package/dist/commands/ps.d.ts.map +1 -1
  113. package/dist/commands/ps.js +5 -0
  114. package/dist/commands/read.d.ts +5 -0
  115. package/dist/commands/read.d.ts.map +1 -1
  116. package/dist/commands/read.js +5 -0
  117. package/dist/commands/registry.d.ts.map +1 -1
  118. package/dist/commands/registry.js +4 -1
  119. package/dist/commands/rm.d.ts +5 -0
  120. package/dist/commands/rm.d.ts.map +1 -1
  121. package/dist/commands/rm.js +5 -0
  122. package/dist/commands/runtime.d.ts.map +1 -1
  123. package/dist/commands/runtime.js +1 -57
  124. package/dist/commands/sed.d.ts +5 -0
  125. package/dist/commands/sed.d.ts.map +1 -1
  126. package/dist/commands/sed.js +5 -0
  127. package/dist/commands/set.d.ts +5 -6
  128. package/dist/commands/set.d.ts.map +1 -1
  129. package/dist/commands/set.js +5 -22
  130. package/dist/commands/sh.d.ts +6 -0
  131. package/dist/commands/sh.d.ts.map +1 -1
  132. package/dist/commands/sh.js +6 -0
  133. package/dist/commands/shift.d.ts +10 -0
  134. package/dist/commands/shift.d.ts.map +1 -1
  135. package/dist/commands/shift.js +10 -0
  136. package/dist/commands/sleep.d.ts +5 -0
  137. package/dist/commands/sleep.d.ts.map +1 -1
  138. package/dist/commands/sleep.js +5 -0
  139. package/dist/commands/sort.d.ts +5 -0
  140. package/dist/commands/sort.d.ts.map +1 -1
  141. package/dist/commands/sort.js +5 -0
  142. package/dist/commands/source.d.ts +5 -0
  143. package/dist/commands/source.d.ts.map +1 -1
  144. package/dist/commands/source.js +5 -0
  145. package/dist/commands/stat.d.ts +7 -0
  146. package/dist/commands/stat.d.ts.map +1 -0
  147. package/dist/commands/stat.js +56 -0
  148. package/dist/commands/su.d.ts +13 -0
  149. package/dist/commands/su.d.ts.map +1 -1
  150. package/dist/commands/su.js +45 -14
  151. package/dist/commands/sudo.d.ts.map +1 -1
  152. package/dist/commands/sudo.js +5 -0
  153. package/dist/commands/tail.d.ts +5 -0
  154. package/dist/commands/tail.d.ts.map +1 -1
  155. package/dist/commands/tail.js +15 -3
  156. package/dist/commands/tar.d.ts +5 -0
  157. package/dist/commands/tar.d.ts.map +1 -1
  158. package/dist/commands/tar.js +40 -10
  159. package/dist/commands/tee.d.ts +5 -0
  160. package/dist/commands/tee.d.ts.map +1 -1
  161. package/dist/commands/tee.js +5 -0
  162. package/dist/commands/touch.d.ts +5 -0
  163. package/dist/commands/touch.d.ts.map +1 -1
  164. package/dist/commands/touch.js +5 -0
  165. package/dist/commands/tr.d.ts.map +1 -1
  166. package/dist/commands/tr.js +45 -10
  167. package/dist/commands/tree.d.ts +5 -0
  168. package/dist/commands/tree.d.ts.map +1 -1
  169. package/dist/commands/tree.js +5 -0
  170. package/dist/commands/true.d.ts +10 -0
  171. package/dist/commands/true.d.ts.map +1 -1
  172. package/dist/commands/true.js +10 -0
  173. package/dist/commands/type.d.ts +5 -0
  174. package/dist/commands/type.d.ts.map +1 -1
  175. package/dist/commands/type.js +5 -0
  176. package/dist/commands/uname.d.ts +5 -0
  177. package/dist/commands/uname.d.ts.map +1 -1
  178. package/dist/commands/uname.js +5 -0
  179. package/dist/commands/uniq.d.ts +5 -0
  180. package/dist/commands/uniq.d.ts.map +1 -1
  181. package/dist/commands/uniq.js +5 -0
  182. package/dist/commands/unset.d.ts +5 -0
  183. package/dist/commands/unset.d.ts.map +1 -1
  184. package/dist/commands/unset.js +5 -0
  185. package/dist/commands/uptime.d.ts +5 -0
  186. package/dist/commands/uptime.d.ts.map +1 -1
  187. package/dist/commands/uptime.js +5 -0
  188. package/dist/commands/wc.d.ts +5 -0
  189. package/dist/commands/wc.d.ts.map +1 -1
  190. package/dist/commands/wc.js +5 -0
  191. package/dist/commands/wget.d.ts +5 -0
  192. package/dist/commands/wget.d.ts.map +1 -1
  193. package/dist/commands/wget.js +5 -0
  194. package/dist/commands/who.d.ts +5 -0
  195. package/dist/commands/who.d.ts.map +1 -1
  196. package/dist/commands/who.js +5 -0
  197. package/dist/commands/whoami.d.ts +5 -0
  198. package/dist/commands/whoami.d.ts.map +1 -1
  199. package/dist/commands/whoami.js +5 -0
  200. package/dist/commands/xargs.d.ts +5 -0
  201. package/dist/commands/xargs.d.ts.map +1 -1
  202. package/dist/commands/xargs.js +5 -0
  203. package/dist/self-standalone.js +254 -30
  204. package/dist/types/commands.d.ts +36 -0
  205. package/dist/types/commands.d.ts.map +1 -1
  206. package/dist/utils/tokenize.d.ts +20 -0
  207. package/dist/utils/tokenize.d.ts.map +1 -0
  208. package/dist/utils/tokenize.js +74 -0
  209. package/examples/web.min.js +2 -2
  210. package/package.json +1 -1
  211. package/src/SSHClient/index.ts +6 -3
  212. package/src/SSHMimic/executor.ts +21 -44
  213. package/src/SSHMimic/index.ts +7 -5
  214. package/src/SSHMimic/sftp.ts +28 -21
  215. package/src/VirtualShell/shell.ts +34 -4
  216. package/src/VirtualShell/shellParser.ts +2 -103
  217. package/src/VirtualUserManager/index.ts +43 -19
  218. package/src/commands/adduser.ts +86 -13
  219. package/src/commands/alias.ts +5 -0
  220. package/src/commands/apt.ts +5 -0
  221. package/src/commands/awk.ts +154 -29
  222. package/src/commands/cd.ts +0 -4
  223. package/src/commands/clear.ts +5 -0
  224. package/src/commands/command-helpers.ts +9 -0
  225. package/src/commands/declare.ts +5 -0
  226. package/src/commands/deluser.ts +84 -7
  227. package/src/commands/df.ts +5 -0
  228. package/src/commands/du.ts +5 -0
  229. package/src/commands/export.ts +5 -0
  230. package/src/commands/grep.ts +21 -8
  231. package/src/commands/groups.ts +5 -0
  232. package/src/commands/gzip.ts +54 -28
  233. package/src/commands/head.ts +14 -4
  234. package/src/commands/htop.ts +5 -0
  235. package/src/commands/kill.ts +5 -0
  236. package/src/commands/ln.ts +22 -0
  237. package/src/commands/ls.ts +17 -0
  238. package/src/commands/lsb-release.ts +5 -0
  239. package/src/commands/mkdir.ts +5 -0
  240. package/src/commands/mv.ts +5 -0
  241. package/src/commands/nano.ts +5 -0
  242. package/src/commands/neofetch.ts +8 -6
  243. package/src/commands/passwd.ts +35 -12
  244. package/src/commands/ping.ts +5 -0
  245. package/src/commands/printf.ts +30 -13
  246. package/src/commands/ps.ts +5 -0
  247. package/src/commands/read.ts +5 -0
  248. package/src/commands/registry.ts +4 -1
  249. package/src/commands/rm.ts +5 -0
  250. package/src/commands/runtime.ts +1 -61
  251. package/src/commands/sed.ts +5 -0
  252. package/src/commands/set.ts +5 -24
  253. package/src/commands/sh.ts +9 -3
  254. package/src/commands/shift.ts +10 -0
  255. package/src/commands/sleep.ts +5 -0
  256. package/src/commands/sort.ts +5 -0
  257. package/src/commands/source.ts +5 -0
  258. package/src/commands/stat.ts +61 -0
  259. package/src/commands/su.ts +54 -16
  260. package/src/commands/sudo.ts +5 -0
  261. package/src/commands/tail.ts +17 -3
  262. package/src/commands/tar.ts +38 -15
  263. package/src/commands/tee.ts +5 -0
  264. package/src/commands/touch.ts +5 -0
  265. package/src/commands/tr.ts +54 -10
  266. package/src/commands/tree.ts +5 -0
  267. package/src/commands/true.ts +10 -0
  268. package/src/commands/type.ts +5 -0
  269. package/src/commands/uname.ts +5 -0
  270. package/src/commands/uniq.ts +5 -0
  271. package/src/commands/unset.ts +5 -0
  272. package/src/commands/uptime.ts +5 -0
  273. package/src/commands/wc.ts +5 -0
  274. package/src/commands/wget.ts +5 -0
  275. package/src/commands/who.ts +5 -0
  276. package/src/commands/whoami.ts +5 -0
  277. package/src/commands/xargs.ts +5 -0
  278. package/src/self-standalone.ts +316 -33
  279. package/src/types/commands.ts +37 -0
  280. package/src/utils/tokenize.ts +78 -0
  281. package/builds/web-iife.min.js +0 -13
  282. package/builds/web-iife.min.js.map +0 -7
@@ -1,4 +1,9 @@
1
1
  import { parseArgs } from "./command-helpers";
2
+ /**
3
+ * Send ICMP ECHO_REQUEST packets (mock implementation).
4
+ * @category network
5
+ * @params ["[-c <count>] <host>"]
6
+ */
2
7
  export const pingCommand = {
3
8
  name: "ping",
4
9
  description: "Send ICMP ECHO_REQUEST (mock)",
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Format and print data to stdout.
4
+ * @category shell
5
+ * @params ["<format> [args...]"]
6
+ */
2
7
  export declare const printfCommand: ShellModule;
3
8
  //# sourceMappingURL=printf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"printf.d.ts","sourceRoot":"","sources":["../../src/commands/printf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAoGrD,eAAO,MAAM,aAAa,EAAE,WAW3B,CAAC"}
1
+ {"version":3,"file":"printf.d.ts","sourceRoot":"","sources":["../../src/commands/printf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAgHrD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WAW3B,CAAC"}
@@ -48,38 +48,64 @@ function renderPrintf(fmt, args) {
48
48
  }
49
49
  }
50
50
  if (fmt[i] === "%" && i + 1 < fmt.length) {
51
- // Optional width/precision: %[-][width][.prec]spec
52
51
  let j = i + 1;
53
- if (fmt[j] === "-")
52
+ let leftAlign = false;
53
+ if (fmt[j] === "-") {
54
+ leftAlign = true;
54
55
  j++;
55
- while (j < fmt.length && /\d/.test(fmt[j]))
56
+ }
57
+ let zeroPad = false;
58
+ if (fmt[j] === "0") {
59
+ zeroPad = true;
60
+ j++;
61
+ }
62
+ let width = 0;
63
+ while (j < fmt.length && /\d/.test(fmt[j])) {
64
+ width = width * 10 + parseInt(fmt[j], 10);
56
65
  j++;
66
+ }
67
+ let precision = -1;
57
68
  if (fmt[j] === ".") {
58
69
  j++;
59
- while (j < fmt.length && /\d/.test(fmt[j]))
70
+ precision = 0;
71
+ while (j < fmt.length && /\d/.test(fmt[j])) {
72
+ precision = precision * 10 + parseInt(fmt[j], 10);
60
73
  j++;
74
+ }
61
75
  }
62
76
  const spec = fmt[j];
63
77
  const arg = args[argIdx++] ?? "";
78
+ const pad = (s, ch = " ") => {
79
+ if (width <= 0 || s.length >= width)
80
+ return s;
81
+ const fill = ch.repeat(width - s.length);
82
+ return leftAlign ? s + fill : fill + s;
83
+ };
64
84
  switch (spec) {
65
- case "s":
66
- out += arg;
85
+ case "s": {
86
+ let val = String(arg);
87
+ if (precision >= 0)
88
+ val = val.slice(0, precision);
89
+ out += pad(val);
67
90
  break;
91
+ }
68
92
  case "d":
69
93
  case "i":
70
- out += String(parseInt(arg, 10) || 0);
94
+ out += pad(String(parseInt(arg, 10) || 0), zeroPad ? "0" : " ");
71
95
  break;
72
- case "f":
73
- out += String(parseFloat(arg) || 0);
96
+ case "f": {
97
+ const prec = precision >= 0 ? precision : 6;
98
+ out += pad((parseFloat(arg) || 0).toFixed(prec));
74
99
  break;
100
+ }
75
101
  case "o":
76
- out += (parseInt(arg, 10) || 0).toString(8);
102
+ out += pad((parseInt(arg, 10) || 0).toString(8), zeroPad ? "0" : " ");
77
103
  break;
78
104
  case "x":
79
- out += (parseInt(arg, 10) || 0).toString(16);
105
+ out += pad((parseInt(arg, 10) || 0).toString(16), zeroPad ? "0" : " ");
80
106
  break;
81
107
  case "X":
82
- out += (parseInt(arg, 10) || 0).toString(16).toUpperCase();
108
+ out += pad((parseInt(arg, 10) || 0).toString(16).toUpperCase(), zeroPad ? "0" : " ");
83
109
  break;
84
110
  case "%":
85
111
  out += "%";
@@ -98,6 +124,11 @@ function renderPrintf(fmt, args) {
98
124
  }
99
125
  return out;
100
126
  }
127
+ /**
128
+ * Format and print data to stdout.
129
+ * @category shell
130
+ * @params ["<format> [args...]"]
131
+ */
101
132
  export const printfCommand = {
102
133
  name: "printf",
103
134
  description: "Format and print data",
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Report process status with various formatting options.
4
+ * @category system
5
+ * @params ["[-a] [-u] [-x] [aux]"]
6
+ */
2
7
  export declare const psCommand: ShellModule;
3
8
  //# sourceMappingURL=ps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ps.d.ts","sourceRoot":"","sources":["../../src/commands/ps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,SAAS,EAAE,WAiDvB,CAAC"}
1
+ {"version":3,"file":"ps.d.ts","sourceRoot":"","sources":["../../src/commands/ps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,WAiDvB,CAAC"}
@@ -1,4 +1,9 @@
1
1
  import { ifFlag } from "./command-helpers";
2
+ /**
3
+ * Report process status with various formatting options.
4
+ * @category system
5
+ * @params ["[-a] [-u] [-x] [aux]"]
6
+ */
2
7
  export const psCommand = {
3
8
  name: "ps",
4
9
  description: "Report process status",
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Read a line from stdin into one or more variables.
4
+ * @category shell
5
+ * @params ["[-r] [-p prompt] <var...>"]
6
+ */
2
7
  export declare const readCommand: ShellModule;
3
8
  //# sourceMappingURL=read.d.ts.map
@@ -1 +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"}
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;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,WAqCzB,CAAC"}
@@ -1,4 +1,9 @@
1
1
  import { ifFlag } from "./command-helpers";
2
+ /**
3
+ * Read a line from stdin into one or more variables.
4
+ * @category shell
5
+ * @params ["[-r] [-p prompt] <var...>"]
6
+ */
2
7
  export const readCommand = {
3
8
  name: "read",
4
9
  description: "Read a line from stdin into variables",
@@ -1 +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"}
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;AAmNpF,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"}
@@ -33,7 +33,8 @@ import { hostnameCommand } from "./hostname";
33
33
  import { htopCommand } from "./htop";
34
34
  import { idCommand } from "./id";
35
35
  import { killCommand } from "./kill";
36
- import { lnCommand } from "./ln";
36
+ import { lnCommand, readlinkCommand } from "./ln";
37
+ import { statCommand } from "./stat";
37
38
  import { lsCommand } from "./ls";
38
39
  import { lsbReleaseCommand } from "./lsb-release";
39
40
  import { manCommand } from "./man";
@@ -93,7 +94,9 @@ const BASE_COMMANDS = [
93
94
  cpCommand,
94
95
  mvCommand,
95
96
  lnCommand,
97
+ readlinkCommand,
96
98
  chmodCommand,
99
+ statCommand,
97
100
  findCommand,
98
101
  // Text processing
99
102
  grepCommand,
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Remove files or directories from the filesystem.
4
+ * @category files
5
+ * @params ["[-r|-rf] <path>"]
6
+ */
2
7
  export declare const rmCommand: ShellModule;
3
8
  //# sourceMappingURL=rm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rm.d.ts","sourceRoot":"","sources":["../../src/commands/rm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,SAAS,EAAE,WAgCvB,CAAC"}
1
+ {"version":3,"file":"rm.d.ts","sourceRoot":"","sources":["../../src/commands/rm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,WAgCvB,CAAC"}
@@ -1,5 +1,10 @@
1
1
  import { getArg, ifFlag } from "./command-helpers";
2
2
  import { assertPathAccess, resolvePath } from "./helpers";
3
+ /**
4
+ * Remove files or directories from the filesystem.
5
+ * @category files
6
+ * @params ["[-r|-rf] <path>"]
7
+ */
3
8
  export const rmCommand = {
4
9
  name: "rm",
5
10
  description: "Remove files or directories",
@@ -1 +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"}
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;AAK3B,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"}
@@ -2,64 +2,8 @@
2
2
  import { executeStatements } from "../SSHMimic/executor";
3
3
  import { parseScript } from "../VirtualShell/shellParser";
4
4
  import { expandAsync } from "../utils/expand";
5
+ import { tokenizeCommand } from "../utils/tokenize";
5
6
  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
7
  export function makeDefaultEnv(authUser, hostname) {
64
8
  return {
65
9
  vars: {
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Stream editor for filtering and transforming text lines.
4
+ * @category text
5
+ * @params ["-e <expr> [file]", "s/pattern/replace/[g]"]
6
+ */
2
7
  export declare const sedCommand: ShellModule;
3
8
  //# sourceMappingURL=sed.d.ts.map
@@ -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,WA0DxB,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;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,WA0DxB,CAAC"}
@@ -1,5 +1,10 @@
1
1
  import { getFlag, ifFlag } from "./command-helpers";
2
2
  import { resolvePath } from "./helpers";
3
+ /**
4
+ * Stream editor for filtering and transforming text lines.
5
+ * @category text
6
+ * @params ["-e <expr> [file]", "s/pattern/replace/[g]"]
7
+ */
3
8
  export const sedCommand = {
4
9
  name: "sed",
5
10
  description: "Stream editor for filtering and transforming text",
@@ -1,10 +1,9 @@
1
1
  /** biome-ignore-all lint/style/useNamingConvention: env variables */
2
2
  import type { ShellModule } from "../types/commands";
3
- /** @deprecated use env.vars from CommandContext */
4
- export declare function getEnvVar(name: string): string | undefined;
5
- /** @deprecated use env.vars from CommandContext */
6
- export declare function setEnvVar(name: string, value: string): void;
7
- /** @deprecated use env.vars from CommandContext */
8
- export declare function getAllEnvVars(authUser: string): Record<string, string>;
3
+ /**
4
+ * Display or set shell variables and options.
5
+ * @category shell
6
+ * @params ["[VAR=value]"]
7
+ */
9
8
  export declare const setCommand: ShellModule;
10
9
  //# sourceMappingURL=set.d.ts.map
@@ -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,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"}
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;AAErD;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,WAoBxB,CAAC"}
@@ -1,25 +1,8 @@
1
- // Legacy global store kept for compatibility with older callers
2
- const _globalEnv = {
3
- PATH: "/usr/local/bin:/usr/bin:/bin",
4
- HOME: "/home/user",
5
- SHELL: "/bin/sh",
6
- TERM: "xterm-256color",
7
- USER: "user",
8
- };
9
- /** @deprecated use env.vars from CommandContext */
10
- export function getEnvVar(name) {
11
- return _globalEnv[name];
12
- }
13
- /** @deprecated use env.vars from CommandContext */
14
- export function setEnvVar(name, value) {
15
- _globalEnv[name] = value;
16
- }
17
- /** @deprecated use env.vars from CommandContext */
18
- export function getAllEnvVars(authUser) {
19
- _globalEnv.USER = authUser;
20
- _globalEnv.HOME = `/home/${authUser}`;
21
- return { ..._globalEnv };
22
- }
1
+ /**
2
+ * Display or set shell variables and options.
3
+ * @category shell
4
+ * @params ["[VAR=value]"]
5
+ */
23
6
  export const setCommand = {
24
7
  name: "set",
25
8
  description: "Display or set shell variables",
@@ -1,3 +1,9 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Execute shell scripts or commands with a minimal shell interpreter.
4
+ * Supports if/elif/else, for loops, while loops, and variable expansion.
5
+ * @category shell
6
+ * @params ["-c <script>", "[<file>]"]
7
+ */
2
8
  export declare const shCommand: ShellModule;
3
9
  //# sourceMappingURL=sh.d.ts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"sh.d.ts","sourceRoot":"","sources":["../../src/commands/sh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGX,WAAW,EACX,MAAM,mBAAmB,CAAC;AA4R3B;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,WA4CvB,CAAC"}
@@ -233,6 +233,12 @@ async function runBlocks(blocks, ctx) {
233
233
  }
234
234
  return { ...lastResult, stdout: output.trim() || lastResult.stdout };
235
235
  }
236
+ /**
237
+ * Execute shell scripts or commands with a minimal shell interpreter.
238
+ * Supports if/elif/else, for loops, while loops, and variable expansion.
239
+ * @category shell
240
+ * @params ["-c <script>", "[<file>]"]
241
+ */
236
242
  export const shCommand = {
237
243
  name: "sh",
238
244
  aliases: ["bash"],
@@ -1,5 +1,15 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Shift positional parameters (remove first N arguments).
4
+ * @category shell
5
+ * @params ["[n]"]
6
+ */
2
7
  export declare const shiftCommand: ShellModule;
8
+ /**
9
+ * Trap signals and execute actions on signal receipt or shell exit.
10
+ * @category shell
11
+ * @params ["[action] [signal...]"]
12
+ */
3
13
  export declare const trapCommand: ShellModule;
4
14
  export declare const returnCommand: ShellModule;
5
15
  //# sourceMappingURL=shift.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shift.d.ts","sourceRoot":"","sources":["../../src/commands/shift.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,YAAY,EAAE,WAoB1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,WAezB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAW3B,CAAC"}
1
+ {"version":3,"file":"shift.d.ts","sourceRoot":"","sources":["../../src/commands/shift.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,WAoB1B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,WAezB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAW3B,CAAC"}
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Shift positional parameters (remove first N arguments).
3
+ * @category shell
4
+ * @params ["[n]"]
5
+ */
1
6
  export const shiftCommand = {
2
7
  name: "shift",
3
8
  description: "Shift positional parameters",
@@ -20,6 +25,11 @@ export const shiftCommand = {
20
25
  return { exitCode: 0 };
21
26
  },
22
27
  };
28
+ /**
29
+ * Trap signals and execute actions on signal receipt or shell exit.
30
+ * @category shell
31
+ * @params ["[action] [signal...]"]
32
+ */
23
33
  export const trapCommand = {
24
34
  name: "trap",
25
35
  description: "Trap signals and events",
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Delay execution for a specified number of seconds.
4
+ * @category system
5
+ * @params ["<seconds>"]
6
+ */
2
7
  export declare const sleepCommand: ShellModule;
3
8
  //# sourceMappingURL=sleep.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../src/commands/sleep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,YAAY,EAAE,WAY1B,CAAC"}
1
+ {"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../src/commands/sleep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,WAY1B,CAAC"}
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Delay execution for a specified number of seconds.
3
+ * @category system
4
+ * @params ["<seconds>"]
5
+ */
1
6
  export const sleepCommand = {
2
7
  name: "sleep",
3
8
  description: "Delay execution",
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Sort lines of text with various options (reverse, numeric, unique).
4
+ * @category text
5
+ * @params ["[-r] [-n] [-u] [-k <col>] [file...]"]
6
+ */
2
7
  export declare const sortCommand: ShellModule;
3
8
  //# sourceMappingURL=sort.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../../src/commands/sort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,WAAW,EAAE,WAoCzB,CAAC"}
1
+ {"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../../src/commands/sort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,WAoCzB,CAAC"}
@@ -1,5 +1,10 @@
1
1
  import { ifFlag } from "./command-helpers";
2
2
  import { assertPathAccess, resolvePath } from "./helpers";
3
+ /**
4
+ * Sort lines of text with various options (reverse, numeric, unique).
5
+ * @category text
6
+ * @params ["[-r] [-n] [-u] [-k <col>] [file...]"]
7
+ */
3
8
  export const sortCommand = {
4
9
  name: "sort",
5
10
  description: "Sort lines of text",
@@ -1,3 +1,8 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Execute commands from a file in the current shell environment.
4
+ * @category shell
5
+ * @params ["<file> [args...]"]
6
+ */
2
7
  export declare const sourceCommand: ShellModule;
3
8
  //# sourceMappingURL=source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/commands/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,aAAa,EAAE,WA0C3B,CAAC"}
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/commands/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WA0C3B,CAAC"}
@@ -1,5 +1,10 @@
1
1
  import { resolvePath } from "./helpers";
2
2
  import { runCommand } from "./runtime";
3
+ /**
4
+ * Execute commands from a file in the current shell environment.
5
+ * @category shell
6
+ * @params ["<file> [args...]"]
7
+ */
3
8
  export const sourceCommand = {
4
9
  name: "source",
5
10
  aliases: ["."],
@@ -0,0 +1,7 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Display file or filesystem status.
4
+ * Outputs: path, size, mode, type, timestamps — similar to `stat` on Linux.
5
+ */
6
+ export declare const statCommand: ShellModule;
7
+ //# sourceMappingURL=stat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../src/commands/stat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,WAqDzB,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { resolvePath } from "./helpers";
2
+ /**
3
+ * Display file or filesystem status.
4
+ * Outputs: path, size, mode, type, timestamps — similar to `stat` on Linux.
5
+ */
6
+ export const statCommand = {
7
+ name: "stat",
8
+ description: "Display file status",
9
+ category: "files",
10
+ params: ["[-c <format>] <file>"],
11
+ run: ({ shell, cwd, args }) => {
12
+ const fmtIdx = args.findIndex((a) => a === "-c" || a === "--format");
13
+ const fmt = fmtIdx !== -1 ? args[fmtIdx + 1] : undefined;
14
+ const file = args.find((a) => !a.startsWith("-") && a !== fmt);
15
+ if (!file)
16
+ return { stderr: "stat: missing operand\n", exitCode: 1 };
17
+ const p = resolvePath(cwd, file);
18
+ if (!shell.vfs.exists(p)) {
19
+ return { stderr: `stat: cannot stat '${file}': No such file or directory\n`, exitCode: 1 };
20
+ }
21
+ const st = shell.vfs.stat(p);
22
+ const isDir = st.type === "directory";
23
+ const _isLink = shell.vfs.isSymlink(p);
24
+ const isSymlink = shell.vfs.isSymlink(p);
25
+ const modePerm = (mode) => {
26
+ const bits = [0o400, 0o200, 0o100, 0o040, 0o020, 0o010, 0o004, 0o002, 0o001];
27
+ const syms = ["r", "w", "x", "r", "w", "x", "r", "w", "x"];
28
+ return (isDir ? "d" : isSymlink ? "l" : "-") +
29
+ bits.map((b, i) => mode & b ? syms[i] : "-").join("");
30
+ };
31
+ const octal = (st.mode).toString(8).padStart(4, "0");
32
+ const modeStr = modePerm(st.mode);
33
+ const size = "size" in st ? st.size : 0;
34
+ const ts = (d) => d.toISOString().replace("T", " ").replace(/\.\d+Z$/, " +0000");
35
+ // -c format string support
36
+ if (fmt) {
37
+ const out = fmt
38
+ .replace("%n", file)
39
+ .replace("%s", String(size))
40
+ .replace("%a", octal.slice(1)) // access in octal (no leading 0)
41
+ .replace("%A", modeStr)
42
+ .replace("%F", isSymlink ? "symbolic link" : isDir ? "directory" : "regular file")
43
+ .replace("%y", ts(st.updatedAt))
44
+ .replace("%z", ts(st.updatedAt));
45
+ return { stdout: `${out}\n`, exitCode: 0 };
46
+ }
47
+ const out = [
48
+ ` File: ${file}${isSymlink ? ` -> ${shell.vfs.resolveSymlink(p)}` : ""}`,
49
+ ` Size: ${size}${"\t".repeat(3)}${isSymlink ? "symbolic link" : isDir ? "directory" : "regular file"}`,
50
+ `Access: (${octal}/${modeStr}) Uid: ( 0/ root) Gid: ( 0/ root)`,
51
+ `Modify: ${ts(st.updatedAt)}`,
52
+ `Change: ${ts(st.updatedAt)}`,
53
+ ].join("\n");
54
+ return { stdout: `${out}\n`, exitCode: 0 };
55
+ },
56
+ };
@@ -1,3 +1,16 @@
1
1
  import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Switch to another user account.
4
+ *
5
+ * Usage:
6
+ * su [username] — switch to username (defaults to root)
7
+ * su - [username] — login shell (changes cwd to target home)
8
+ * su -c 'cmd' [user] — run command as user
9
+ *
10
+ * - Root can switch to any user without a password.
11
+ * - Non-root sudoers must enter the target user's password.
12
+ * - Non-sudoers are denied.
13
+ * - Switching to a non-existent user returns an error immediately.
14
+ */
2
15
  export declare const suCommand: ShellModule;
3
16
  //# sourceMappingURL=su.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"su.d.ts","sourceRoot":"","sources":["../../src/commands/su.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,SAAS,EAAE,WA8BvB,CAAC"}
1
+ {"version":3,"file":"su.d.ts","sourceRoot":"","sources":["../../src/commands/su.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,SAAS,EAAE,WAuDvB,CAAC"}