typescript-virtual-container 1.5.3 → 1.5.4

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 (365) hide show
  1. package/README.md +43 -23
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/SSHMimic/executor.js +23 -5
  4. package/dist/VirtualPackageManager/index.js +10 -0
  5. package/dist/commands/basename.d.ts +13 -0
  6. package/dist/commands/basename.js +45 -0
  7. package/dist/commands/file.d.ts +8 -0
  8. package/dist/commands/file.js +57 -0
  9. package/dist/commands/fun.d.ts +32 -0
  10. package/dist/commands/fun.js +172 -0
  11. package/dist/commands/ifconfig.d.ts +7 -0
  12. package/dist/commands/ifconfig.js +52 -0
  13. package/dist/commands/last.d.ts +13 -0
  14. package/dist/commands/last.js +68 -0
  15. package/dist/commands/manuals-bundle.js +598 -6
  16. package/dist/commands/registry.js +24 -2
  17. package/dist/commands/runtime.js +22 -2
  18. package/dist/commands/sh.js +5 -0
  19. package/dist/commands/tput.d.ts +13 -0
  20. package/dist/commands/tput.js +76 -0
  21. package/dist/commands/w.d.ts +7 -0
  22. package/dist/commands/w.js +38 -0
  23. package/dist/utils/expand.d.ts +12 -0
  24. package/dist/utils/expand.js +84 -0
  25. package/package.json +9 -3
  26. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -50
  27. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -31
  28. package/.github/dependabot.yml +0 -27
  29. package/.github/pull_request_template.md +0 -21
  30. package/.github/workflows/create-pull-request.yml +0 -85
  31. package/.github/workflows/publish.yml +0 -25
  32. package/.github/workflows/test-battery.yml +0 -102
  33. package/.vscode/settings.json +0 -20
  34. package/CODE_OF_CONDUCT.md +0 -39
  35. package/CONTRIBUTING.md +0 -59
  36. package/HONEYPOT.md +0 -358
  37. package/SECURITY.md +0 -33
  38. package/benchmark-results.txt +0 -40
  39. package/benchmark-virtualshell.ts +0 -88
  40. package/biome.json +0 -37
  41. package/build.js +0 -22
  42. package/builds/fortune-nyx-v1.5.3-directbash-k6.1.0.mjs +0 -1764
  43. package/builds/fortune-nyx-v1.5.3-ssh-nosftp.js +0 -1764
  44. package/builds/fortune-nyx-v1.5.3-ssh.cjs +0 -1765
  45. package/builds/fortune-nyx-v1.5.3-web.min.js +0 -17036
  46. package/bun.lock +0 -244
  47. package/docs/.nojekyll +0 -1
  48. package/docs/app.js +0 -1751
  49. package/docs/assets/hierarchy.js +0 -1
  50. package/docs/assets/highlight.css +0 -162
  51. package/docs/assets/icons.js +0 -18
  52. package/docs/assets/icons.svg +0 -1
  53. package/docs/assets/main.js +0 -60
  54. package/docs/assets/navigation.js +0 -1
  55. package/docs/assets/search.js +0 -1
  56. package/docs/assets/style.css +0 -1633
  57. package/docs/classes/HoneyPot.html +0 -31
  58. package/docs/classes/IdleManager.html +0 -162
  59. package/docs/classes/SshClient.html +0 -66
  60. package/docs/classes/VirtualFileSystem.html +0 -279
  61. package/docs/classes/VirtualPackageManager.html +0 -63
  62. package/docs/classes/VirtualSftpServer.html +0 -169
  63. package/docs/classes/VirtualShell.html +0 -285
  64. package/docs/classes/VirtualSshServer.html +0 -182
  65. package/docs/classes/VirtualUserManager.html +0 -276
  66. package/docs/demo.html +0 -82
  67. package/docs/functions/assertDiff.html +0 -6
  68. package/docs/functions/diffSnapshots.html +0 -7
  69. package/docs/functions/formatDiff.html +0 -6
  70. package/docs/functions/getArg.html +0 -13
  71. package/docs/functions/getFlag.html +0 -15
  72. package/docs/functions/ifFlag.html +0 -11
  73. package/docs/hierarchy.html +0 -1
  74. package/docs/index.html +0 -1869
  75. package/docs/interfaces/AuditLogEntry.html +0 -6
  76. package/docs/interfaces/CommandContext.html +0 -22
  77. package/docs/interfaces/CommandResult.html +0 -26
  78. package/docs/interfaces/ExecStream.html +0 -11
  79. package/docs/interfaces/HoneyPotStats.html +0 -16
  80. package/docs/interfaces/IdleManagerOptions.html +0 -7
  81. package/docs/interfaces/InstalledPackage.html +0 -20
  82. package/docs/interfaces/NanoEditorSession.html +0 -8
  83. package/docs/interfaces/PackageDefinition.html +0 -30
  84. package/docs/interfaces/PackageFile.html +0 -8
  85. package/docs/interfaces/PasswordChallenge.html +0 -16
  86. package/docs/interfaces/RemoveOptions.html +0 -4
  87. package/docs/interfaces/ShellEnv.html +0 -6
  88. package/docs/interfaces/ShellModule.html +0 -14
  89. package/docs/interfaces/ShellProperties.html +0 -14
  90. package/docs/interfaces/ShellStream.html +0 -11
  91. package/docs/interfaces/SudoChallenge.html +0 -24
  92. package/docs/interfaces/VfsBaseNode.html +0 -12
  93. package/docs/interfaces/VfsDiff.html +0 -10
  94. package/docs/interfaces/VfsDiffEntry.html +0 -6
  95. package/docs/interfaces/VfsDiffModified.html +0 -10
  96. package/docs/interfaces/VfsDirectoryNode.html +0 -15
  97. package/docs/interfaces/VfsFileNode.html +0 -17
  98. package/docs/interfaces/VfsOptions.html +0 -26
  99. package/docs/interfaces/VfsSnapshot.html +0 -3
  100. package/docs/interfaces/VfsSnapshotBaseNode.html +0 -8
  101. package/docs/interfaces/VfsSnapshotDirectoryNode.html +0 -10
  102. package/docs/interfaces/VfsSnapshotFileNode.html +0 -12
  103. package/docs/interfaces/VirtualActiveSession.html +0 -12
  104. package/docs/interfaces/VirtualSftpServerOptions.html +0 -7
  105. package/docs/interfaces/VirtualShellVfsLike.html +0 -15
  106. package/docs/interfaces/VirtualShellVfsOptions.html +0 -3
  107. package/docs/interfaces/WriteFileOptions.html +0 -6
  108. package/docs/media/LICENSE +0 -21
  109. package/docs/modules.html +0 -1
  110. package/docs/types/ArgParseOptions.html +0 -4
  111. package/docs/types/CommandMode.html +0 -2
  112. package/docs/types/CommandOutcome.html +0 -2
  113. package/docs/types/IdleState.html +0 -1
  114. package/docs/types/VfsNodeStats.html +0 -2
  115. package/docs/types/VfsNodeType.html +0 -2
  116. package/docs/types/VfsPersistenceMode.html +0 -5
  117. package/docs/types/VfsSnapshotNode.html +0 -2
  118. package/examples/README.md +0 -288
  119. package/examples/app.js +0 -1751
  120. package/examples/app.ts +0 -299
  121. package/examples/build.js +0 -27
  122. package/examples/demo.html +0 -33
  123. package/examples/honeypot-audit.ts +0 -180
  124. package/examples/honeypot-export.ts +0 -253
  125. package/examples/honeypot-quickstart.ts +0 -110
  126. package/examples/index.html +0 -82
  127. package/examples/server.js +0 -55
  128. package/polyfills/buffer.js +0 -117
  129. package/polyfills/node_child_process/index.js +0 -2
  130. package/polyfills/node_crypto/index.js +0 -167
  131. package/polyfills/node_events/index.js +0 -9
  132. package/polyfills/node_fs/index.js +0 -202
  133. package/polyfills/node_fs/promises.js +0 -4
  134. package/polyfills/node_os/index.js +0 -9
  135. package/polyfills/node_path/index.js +0 -28
  136. package/polyfills/node_vm/index.js +0 -7
  137. package/polyfills/node_zlib/index.js +0 -3
  138. package/polyfills/process.js +0 -14
  139. package/polyfills/ssh2/index.js +0 -75
  140. package/scripts/build-all.mjs +0 -226
  141. package/scripts/build-names.mjs +0 -43
  142. package/scripts/generate-manuals-bundle.mjs +0 -49
  143. package/scripts/postinstall.js +0 -42
  144. package/scripts/publish-package.sh +0 -70
  145. package/src/Honeypot/index.ts +0 -457
  146. package/src/SSHClient/index.ts +0 -270
  147. package/src/SSHMimic/exec.ts +0 -49
  148. package/src/SSHMimic/executor.ts +0 -251
  149. package/src/SSHMimic/hostKey.ts +0 -21
  150. package/src/SSHMimic/index.ts +0 -337
  151. package/src/SSHMimic/loginBanner.ts +0 -36
  152. package/src/SSHMimic/loginFormat.ts +0 -10
  153. package/src/SSHMimic/prompt.ts +0 -14
  154. package/src/SSHMimic/sftp.ts +0 -883
  155. package/src/VirtualFileSystem/binaryPack.ts +0 -258
  156. package/src/VirtualFileSystem/index.ts +0 -1193
  157. package/src/VirtualFileSystem/internalTypes.ts +0 -43
  158. package/src/VirtualFileSystem/journal.ts +0 -171
  159. package/src/VirtualFileSystem/path.ts +0 -74
  160. package/src/VirtualPackageManager/index.ts +0 -996
  161. package/src/VirtualShell/idleManager.ts +0 -137
  162. package/src/VirtualShell/index.ts +0 -475
  163. package/src/VirtualShell/shell.ts +0 -700
  164. package/src/VirtualShell/shellParser.ts +0 -285
  165. package/src/VirtualUserManager/index.ts +0 -758
  166. package/src/bun.d.ts +0 -1
  167. package/src/commands/adduser.ts +0 -103
  168. package/src/commands/alias.ts +0 -69
  169. package/src/commands/apt.ts +0 -233
  170. package/src/commands/awk.ts +0 -168
  171. package/src/commands/base64.ts +0 -29
  172. package/src/commands/cat.ts +0 -52
  173. package/src/commands/cd.ts +0 -25
  174. package/src/commands/chmod.ts +0 -85
  175. package/src/commands/clear.ts +0 -15
  176. package/src/commands/command-helpers.ts +0 -286
  177. package/src/commands/cp.ts +0 -83
  178. package/src/commands/curl.ts +0 -147
  179. package/src/commands/cut.ts +0 -36
  180. package/src/commands/date.ts +0 -30
  181. package/src/commands/declare.ts +0 -49
  182. package/src/commands/deluser.ts +0 -98
  183. package/src/commands/df.ts +0 -23
  184. package/src/commands/diff.ts +0 -43
  185. package/src/commands/dpkg.ts +0 -180
  186. package/src/commands/du.ts +0 -56
  187. package/src/commands/echo.ts +0 -58
  188. package/src/commands/env.ts +0 -23
  189. package/src/commands/exit.ts +0 -18
  190. package/src/commands/export.ts +0 -34
  191. package/src/commands/find.ts +0 -68
  192. package/src/commands/free.ts +0 -47
  193. package/src/commands/grep.ts +0 -116
  194. package/src/commands/groups.ts +0 -19
  195. package/src/commands/gzip.ts +0 -88
  196. package/src/commands/head.ts +0 -52
  197. package/src/commands/help.ts +0 -152
  198. package/src/commands/helpers.ts +0 -234
  199. package/src/commands/history.ts +0 -34
  200. package/src/commands/hostname.ts +0 -14
  201. package/src/commands/htop.ts +0 -20
  202. package/src/commands/id.ts +0 -19
  203. package/src/commands/index.ts +0 -9
  204. package/src/commands/kill.ts +0 -19
  205. package/src/commands/ln.ts +0 -71
  206. package/src/commands/ls.ts +0 -243
  207. package/src/commands/lsb-release.ts +0 -63
  208. package/src/commands/man.ts +0 -31
  209. package/src/commands/manuals/adduser.txt +0 -11
  210. package/src/commands/manuals/apt-cache.txt +0 -12
  211. package/src/commands/manuals/apt.txt +0 -20
  212. package/src/commands/manuals/awk.txt +0 -13
  213. package/src/commands/manuals/cat.txt +0 -14
  214. package/src/commands/manuals/cd.txt +0 -16
  215. package/src/commands/manuals/chmod.txt +0 -16
  216. package/src/commands/manuals/clear.txt +0 -10
  217. package/src/commands/manuals/cp.txt +0 -10
  218. package/src/commands/manuals/curl.txt +0 -20
  219. package/src/commands/manuals/date.txt +0 -14
  220. package/src/commands/manuals/declare.txt +0 -12
  221. package/src/commands/manuals/deluser.txt +0 -10
  222. package/src/commands/manuals/df.txt +0 -10
  223. package/src/commands/manuals/dpkg-query.txt +0 -11
  224. package/src/commands/manuals/dpkg.txt +0 -14
  225. package/src/commands/manuals/du.txt +0 -11
  226. package/src/commands/manuals/echo.txt +0 -11
  227. package/src/commands/manuals/false.txt +0 -10
  228. package/src/commands/manuals/find.txt +0 -11
  229. package/src/commands/manuals/free.txt +0 -12
  230. package/src/commands/manuals/grep.txt +0 -13
  231. package/src/commands/manuals/groups.txt +0 -10
  232. package/src/commands/manuals/gzip.txt +0 -11
  233. package/src/commands/manuals/head.txt +0 -10
  234. package/src/commands/manuals/help.txt +0 -11
  235. package/src/commands/manuals/history.txt +0 -11
  236. package/src/commands/manuals/hostname.txt +0 -10
  237. package/src/commands/manuals/id.txt +0 -10
  238. package/src/commands/manuals/kill.txt +0 -13
  239. package/src/commands/manuals/ls.txt +0 -20
  240. package/src/commands/manuals/lsb_release.txt +0 -14
  241. package/src/commands/manuals/mkdir.txt +0 -10
  242. package/src/commands/manuals/mv.txt +0 -10
  243. package/src/commands/manuals/nano.txt +0 -11
  244. package/src/commands/manuals/neofetch.txt +0 -10
  245. package/src/commands/manuals/node.txt +0 -13
  246. package/src/commands/manuals/npm.txt +0 -13
  247. package/src/commands/manuals/npx.txt +0 -13
  248. package/src/commands/manuals/passwd.txt +0 -11
  249. package/src/commands/manuals/ping.txt +0 -10
  250. package/src/commands/manuals/printf.txt +0 -11
  251. package/src/commands/manuals/ps.txt +0 -10
  252. package/src/commands/manuals/pwd.txt +0 -10
  253. package/src/commands/manuals/python3.txt +0 -13
  254. package/src/commands/manuals/readlink.txt +0 -10
  255. package/src/commands/manuals/return.txt +0 -10
  256. package/src/commands/manuals/rm.txt +0 -10
  257. package/src/commands/manuals/sed.txt +0 -11
  258. package/src/commands/manuals/set.txt +0 -11
  259. package/src/commands/manuals/shift.txt +0 -10
  260. package/src/commands/manuals/sleep.txt +0 -10
  261. package/src/commands/manuals/sort.txt +0 -12
  262. package/src/commands/manuals/source.txt +0 -11
  263. package/src/commands/manuals/ssh.txt +0 -11
  264. package/src/commands/manuals/stat.txt +0 -10
  265. package/src/commands/manuals/su.txt +0 -13
  266. package/src/commands/manuals/sudo.txt +0 -11
  267. package/src/commands/manuals/tail.txt +0 -10
  268. package/src/commands/manuals/tar.txt +0 -19
  269. package/src/commands/manuals/tee.txt +0 -10
  270. package/src/commands/manuals/test.txt +0 -11
  271. package/src/commands/manuals/touch.txt +0 -11
  272. package/src/commands/manuals/tr.txt +0 -10
  273. package/src/commands/manuals/trap.txt +0 -10
  274. package/src/commands/manuals/true.txt +0 -10
  275. package/src/commands/manuals/type.txt +0 -10
  276. package/src/commands/manuals/uname.txt +0 -12
  277. package/src/commands/manuals/uniq.txt +0 -12
  278. package/src/commands/manuals/unset.txt +0 -10
  279. package/src/commands/manuals/uptime.txt +0 -11
  280. package/src/commands/manuals/wc.txt +0 -12
  281. package/src/commands/manuals/wget.txt +0 -12
  282. package/src/commands/manuals/which.txt +0 -10
  283. package/src/commands/manuals/whoami.txt +0 -10
  284. package/src/commands/manuals/xargs.txt +0 -10
  285. package/src/commands/manuals-bundle.ts +0 -898
  286. package/src/commands/mkdir.ts +0 -31
  287. package/src/commands/mv.ts +0 -50
  288. package/src/commands/nano.ts +0 -38
  289. package/src/commands/neofetch.ts +0 -53
  290. package/src/commands/node.ts +0 -341
  291. package/src/commands/npm.ts +0 -132
  292. package/src/commands/passwd.ts +0 -50
  293. package/src/commands/ping.ts +0 -32
  294. package/src/commands/printf.ts +0 -129
  295. package/src/commands/ps.ts +0 -58
  296. package/src/commands/pwd.ts +0 -9
  297. package/src/commands/python.ts +0 -2229
  298. package/src/commands/read.ts +0 -46
  299. package/src/commands/registry.ts +0 -249
  300. package/src/commands/rm.ts +0 -42
  301. package/src/commands/runtime.ts +0 -421
  302. package/src/commands/sed.ts +0 -68
  303. package/src/commands/seq.ts +0 -43
  304. package/src/commands/set.ts +0 -29
  305. package/src/commands/sh.ts +0 -467
  306. package/src/commands/shift.ts +0 -63
  307. package/src/commands/sleep.ts +0 -20
  308. package/src/commands/sort.ts +0 -46
  309. package/src/commands/source.ts +0 -52
  310. package/src/commands/stat.ts +0 -61
  311. package/src/commands/su.ts +0 -72
  312. package/src/commands/sudo.ts +0 -76
  313. package/src/commands/tail.ts +0 -53
  314. package/src/commands/tar.ts +0 -102
  315. package/src/commands/tee.ts +0 -36
  316. package/src/commands/test.ts +0 -137
  317. package/src/commands/touch.ts +0 -28
  318. package/src/commands/tr.ts +0 -70
  319. package/src/commands/tree.ts +0 -20
  320. package/src/commands/true.ts +0 -27
  321. package/src/commands/type.ts +0 -48
  322. package/src/commands/uname.ts +0 -29
  323. package/src/commands/uniq.ts +0 -39
  324. package/src/commands/unset.ts +0 -17
  325. package/src/commands/uptime.ts +0 -54
  326. package/src/commands/wc.ts +0 -55
  327. package/src/commands/wget.ts +0 -148
  328. package/src/commands/which.ts +0 -37
  329. package/src/commands/who.ts +0 -25
  330. package/src/commands/whoami.ts +0 -14
  331. package/src/commands/xargs.ts +0 -31
  332. package/src/index.ts +0 -67
  333. package/src/modules/linuxRootfs.ts +0 -1961
  334. package/src/modules/neofetch.ts +0 -358
  335. package/src/modules/shellInteractive.ts +0 -57
  336. package/src/modules/shellRuntime.ts +0 -76
  337. package/src/self-standalone.ts +0 -542
  338. package/src/standalone-wo-sftp.ts +0 -38
  339. package/src/standalone.ts +0 -72
  340. package/src/types/commands.ts +0 -146
  341. package/src/types/pipeline.ts +0 -52
  342. package/src/types/streams.ts +0 -32
  343. package/src/types/tar-stream.d.ts +0 -38
  344. package/src/types/vfs.ts +0 -98
  345. package/src/utils/expand.ts +0 -491
  346. package/src/utils/perfLogger.ts +0 -72
  347. package/src/utils/tokenize.ts +0 -98
  348. package/src/utils/vfsDiff.ts +0 -275
  349. package/tests/command-helpers.test.ts +0 -116
  350. package/tests/commands-admin-net.test.ts +0 -441
  351. package/tests/commands-advanced.test.ts +0 -456
  352. package/tests/commands-core.test.ts +0 -562
  353. package/tests/commands-missing.test.ts +0 -570
  354. package/tests/commands-specific-units.test.ts +0 -327
  355. package/tests/commands-text-sys.test.ts +0 -445
  356. package/tests/expand.test.ts +0 -170
  357. package/tests/helpers.test.ts +0 -97
  358. package/tests/new-features.test.ts +0 -1036
  359. package/tests/parser-executor.test.ts +0 -37
  360. package/tests/sftp.test.ts +0 -323
  361. package/tests/ssh-exec.test.ts +0 -45
  362. package/tests/test-helper.ts +0 -79
  363. package/tests/users.test.ts +0 -86
  364. package/tsconfig.json +0 -49
  365. package/typedoc.json +0 -47
@@ -3,6 +3,7 @@ import { aliasCommand, unaliasCommand } from "./alias";
3
3
  import { aptCacheCommand, aptCommand } from "./apt";
4
4
  import { awkCommand } from "./awk";
5
5
  import { base64Command } from "./base64";
6
+ import { basenameCommand, dirnameCommand } from "./basename";
6
7
  import { catCommand } from "./cat";
7
8
  import { cdCommand } from "./cd";
8
9
  import { chmodCommand } from "./chmod";
@@ -21,8 +22,10 @@ import { echoCommand } from "./echo";
21
22
  import { envCommand } from "./env";
22
23
  import { exitCommand } from "./exit";
23
24
  import { exportCommand } from "./export";
25
+ import { fileCommand } from "./file";
24
26
  import { findCommand } from "./find";
25
27
  import { freeCommand } from "./free";
28
+ import { cmatrixCommand, cowsayCommand, cowthinkCommand, fortuneCommand, slCommand, yesCommand } from "./fun";
26
29
  import { grepCommand } from "./grep";
27
30
  import { groupsCommand } from "./groups";
28
31
  import { gunzipCommand, gzipCommand } from "./gzip";
@@ -32,10 +35,10 @@ import { historyCommand } from "./history";
32
35
  import { hostnameCommand } from "./hostname";
33
36
  import { htopCommand } from "./htop";
34
37
  import { idCommand } from "./id";
38
+ import { ifconfigCommand } from "./ifconfig";
35
39
  import { killCommand } from "./kill";
40
+ import { dmesgCommand, lastCommand } from "./last";
36
41
  import { lnCommand, readlinkCommand } from "./ln";
37
- import { seqCommand } from "./seq";
38
- import { statCommand } from "./stat";
39
42
  import { lsCommand } from "./ls";
40
43
  import { lsbReleaseCommand } from "./lsb-release";
41
44
  import { manCommand } from "./man";
@@ -54,12 +57,14 @@ import { python3Command } from "./python";
54
57
  import { readCommand } from "./read";
55
58
  import { rmCommand } from "./rm";
56
59
  import { sedCommand } from "./sed";
60
+ import { seqCommand } from "./seq";
57
61
  import { setCommand } from "./set";
58
62
  import { shCommand } from "./sh";
59
63
  import { returnCommand, shiftCommand, trapCommand } from "./shift";
60
64
  import { sleepCommand } from "./sleep";
61
65
  import { sortCommand } from "./sort";
62
66
  import { sourceCommand } from "./source";
67
+ import { statCommand } from "./stat";
63
68
  import { suCommand } from "./su";
64
69
  import { sudoCommand } from "./sudo";
65
70
  import { tailCommand } from "./tail";
@@ -67,6 +72,7 @@ import { tarCommand } from "./tar";
67
72
  import { teeCommand } from "./tee";
68
73
  import { testCommand } from "./test";
69
74
  import { touchCommand } from "./touch";
75
+ import { sttyCommand, tputCommand } from "./tput";
70
76
  import { trCommand } from "./tr";
71
77
  import { treeCommand } from "./tree";
72
78
  import { falseCommand, trueCommand } from "./true";
@@ -81,6 +87,7 @@ import { whichCommand } from "./which";
81
87
  import { whoCommand } from "./who";
82
88
  import { whoamiCommand } from "./whoami";
83
89
  import { xargsCommand } from "./xargs";
90
+ import { wCommand } from "./w";
84
91
  const BASE_COMMANDS = [
85
92
  // Navigation
86
93
  pwdCommand,
@@ -144,6 +151,21 @@ const BASE_COMMANDS = [
144
151
  exitCommand,
145
152
  // Editors
146
153
  nanoCommand,
154
+ wCommand,
155
+ basenameCommand,
156
+ dirnameCommand,
157
+ fileCommand,
158
+ tputCommand,
159
+ sttyCommand,
160
+ lastCommand,
161
+ dmesgCommand,
162
+ ifconfigCommand,
163
+ yesCommand,
164
+ fortuneCommand,
165
+ cowsayCommand,
166
+ cowthinkCommand,
167
+ cmatrixCommand,
168
+ slCommand,
147
169
  htopCommand,
148
170
  // Network
149
171
  curlCommand,
@@ -1,7 +1,7 @@
1
1
  /** biome-ignore-all lint/style/useNamingConvention: ENV VARIABLES */
2
2
  import { executeStatements } from "../SSHMimic/executor";
3
3
  import { parseScript } from "../VirtualShell/shellParser";
4
- import { expandAsync, expandBraces } from "../utils/expand";
4
+ import { expandAsync, expandBraces, expandGlob } from "../utils/expand";
5
5
  import { tokenizeCommand } from "../utils/tokenize";
6
6
  import { resolveModule } from "./registry";
7
7
  /** Returns the home directory path for a given user. Root lives at /root. */
@@ -192,6 +192,26 @@ export async function runCommand(rawInput, authUser, hostname, mode, cwd, shell,
192
192
  return { stderr: `${trimmed.split(" ")[0]}: maximum call depth (${MAX_CALL_DEPTH}) exceeded`, exitCode: 126 };
193
193
  }
194
194
  try {
195
+ // History expansion: !! and !n
196
+ if (trimmed === '!!' || /^!-?\d+$/.test(trimmed) || trimmed.startsWith('!! ')) {
197
+ const histPath = `${shellEnv.vars.HOME ?? `/home/${authUser}`}/.bash_history`;
198
+ if (shell.vfs.exists(histPath)) {
199
+ const lines = shell.vfs.readFile(histPath).split('\n').filter(Boolean);
200
+ let cmd;
201
+ if (trimmed === '!!' || trimmed.startsWith('!! ')) {
202
+ cmd = lines[lines.length - 1];
203
+ }
204
+ else {
205
+ const n = parseInt(trimmed.slice(1), 10);
206
+ cmd = n > 0 ? lines[n - 1] : lines[lines.length + n];
207
+ }
208
+ if (cmd) {
209
+ const suffix = trimmed.startsWith('!! ') ? trimmed.slice(3) : '';
210
+ return runCommand(`${cmd}${suffix ? ` ${suffix}` : ''}`, authUser, hostname, mode, cwd, shell, stdin, shellEnv);
211
+ }
212
+ }
213
+ return { stderr: `${trimmed}: event not found`, exitCode: 1 };
214
+ }
195
215
  const rawTokens = tokenizeCommand(trimmed);
196
216
  const rawFirstWord = rawTokens[0]?.toLowerCase() ?? "";
197
217
  const aliasVal = shellEnv.vars[`__alias_${rawFirstWord}`];
@@ -252,7 +272,7 @@ export async function runCommand(rawInput, authUser, hostname, mode, cwd, shell,
252
272
  }
253
273
  const commandName = parts[0]?.toLowerCase() ?? "";
254
274
  // Apply brace expansion to each arg token
255
- const args = parts.slice(1).flatMap(expandBraces);
275
+ const args = parts.slice(1).flatMap(expandBraces).flatMap(token => expandGlob(token, cwd, shell.vfs));
256
276
  const mod = resolveModule(commandName);
257
277
  if (!mod) {
258
278
  const vfsBinary = resolveVfsBinary(commandName, shellEnv, shell, authUser);
@@ -369,6 +369,11 @@ function splitShScript(script) {
369
369
  }
370
370
  continue;
371
371
  }
372
+ // Backslash-newline continuation: join lines
373
+ if (!inSingleQ && ch === '\\' && i + 1 < script.length && script[i + 1] === '\n') {
374
+ i += 2; // skip \ and \n
375
+ continue;
376
+ }
372
377
  if (depth === 0 && (ch === ";" || ch === "\n")) {
373
378
  const t = current.trim();
374
379
  if (t && !t.startsWith("#"))
@@ -0,0 +1,13 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Terminal control.
4
+ * @category shell
5
+ * @params ["<cap> [args...]"]
6
+ */
7
+ export declare const tputCommand: ShellModule;
8
+ /**
9
+ * Print or set terminal line settings.
10
+ * @category shell
11
+ * @params ["[args...]"]
12
+ */
13
+ export declare const sttyCommand: ShellModule;
@@ -0,0 +1,76 @@
1
+ const CAPS = {
2
+ cols: 220, lines: 50, colors: 256,
3
+ bold: "\x1b[1m", dim: "\x1b[2m", smul: "\x1b[4m", rmul: "\x1b[24m",
4
+ rev: "\x1b[7m", smso: "\x1b[7m", rmso: "\x1b[27m",
5
+ sgr0: "\x1b[0m", el: "\x1b[K", ed: "\x1b[J",
6
+ clear: "\x1b[2J\x1b[H", cup: "", setaf: "", setab: "",
7
+ };
8
+ const ANSI_COLORS = [
9
+ "30", "31", "32", "33", "34", "35", "36", "37",
10
+ "90", "91", "92", "93", "94", "95", "96", "97",
11
+ ];
12
+ /**
13
+ * Terminal control.
14
+ * @category shell
15
+ * @params ["<cap> [args...]"]
16
+ */
17
+ export const tputCommand = {
18
+ name: "tput",
19
+ description: "Query terminfo database",
20
+ category: "shell",
21
+ params: ["<cap> [args...]"],
22
+ run: ({ args }) => {
23
+ const cap = args[0];
24
+ if (!cap)
25
+ return { stderr: "tput: missing capability", exitCode: 1 };
26
+ if (cap === "setaf" && args[1] !== undefined) {
27
+ const n = parseInt(args[1], 10);
28
+ const code = ANSI_COLORS[n] ?? "39";
29
+ return { stdout: `\x1b[${code}m`, exitCode: 0 };
30
+ }
31
+ if (cap === "setab" && args[1] !== undefined) {
32
+ const n = parseInt(args[1], 10);
33
+ const code = ANSI_COLORS[n]?.replace(/3/, "4").replace(/9/, "10") ?? "49";
34
+ return { stdout: `\x1b[${code}m`, exitCode: 0 };
35
+ }
36
+ if (cap === "cup" && args[1] !== undefined && args[2] !== undefined) {
37
+ return { stdout: `\x1b[${parseInt(args[1], 10) + 1};${parseInt(args[2], 10) + 1}H`, exitCode: 0 };
38
+ }
39
+ const val = CAPS[cap];
40
+ if (val === undefined)
41
+ return { stderr: `tput: unknown terminal capability '${cap}'`, exitCode: 1 };
42
+ return { stdout: String(val), exitCode: 0 };
43
+ },
44
+ };
45
+ /**
46
+ * Print or set terminal line settings.
47
+ * @category shell
48
+ * @params ["[args...]"]
49
+ */
50
+ export const sttyCommand = {
51
+ name: "stty",
52
+ description: "Change and print terminal line settings",
53
+ category: "shell",
54
+ params: ["[args...]"],
55
+ run: ({ args }) => {
56
+ if (args.includes("-a") || args.includes("--all")) {
57
+ return {
58
+ stdout: [
59
+ "speed 38400 baud; rows 50; columns 220; line = 0;",
60
+ "intr = ^C; quit = ^\\; erase = ^?; kill = ^U; eof = ^D;",
61
+ "eol = M-^?; eol2 = M-^?; swtch = <undef>; start = ^Q; stop = ^S;",
62
+ "-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts",
63
+ "brkint -icrnl ixon -ixoff -iuclc ixany imaxbel -iutf8",
64
+ "opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0",
65
+ "isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke",
66
+ ].join("\n"),
67
+ exitCode: 0,
68
+ };
69
+ }
70
+ if (args.includes("size")) {
71
+ return { stdout: "50 220", exitCode: 0 };
72
+ }
73
+ // silently accept set operations
74
+ return { exitCode: 0 };
75
+ },
76
+ };
@@ -0,0 +1,7 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ /**
3
+ * Show who is logged on and what they are doing.
4
+ * @category system
5
+ * @params ["[user]"]
6
+ */
7
+ export declare const wCommand: ShellModule;
@@ -0,0 +1,38 @@
1
+ import { userHome } from "./runtime";
2
+ /**
3
+ * Show who is logged on and what they are doing.
4
+ * @category system
5
+ * @params ["[user]"]
6
+ */
7
+ export const wCommand = {
8
+ name: "w",
9
+ description: "Show who is logged on and what they are doing",
10
+ category: "system",
11
+ params: ["[user]"],
12
+ run: ({ shell, authUser }) => {
13
+ const now = new Date();
14
+ const upSecs = Math.floor(performance.now() / 1000);
15
+ const upMins = Math.floor(upSecs / 60);
16
+ const upHours = Math.floor(upMins / 60);
17
+ const uptimeStr = upHours > 0
18
+ ? `${upHours}:${String(upMins % 60).padStart(2, "0")}`
19
+ : `${upMins} min`;
20
+ const timeStr = now.toTimeString().slice(0, 5);
21
+ // Read active sessions
22
+ shell.users.listActiveSessions?.();
23
+ const logPath = `${userHome(authUser)}/.lastlog`;
24
+ let loginTime = timeStr;
25
+ if (shell.vfs.exists(logPath)) {
26
+ try {
27
+ const log = JSON.parse(shell.vfs.readFile(logPath));
28
+ loginTime = new Date(log.at).toTimeString().slice(0, 5);
29
+ }
30
+ catch { }
31
+ }
32
+ const header = ` ${timeStr} up ${uptimeStr}, 1 user, load average: 0.${Math.floor(Math.random() * 30).toString().padStart(2, "0")}, 0.${Math.floor(Math.random() * 15).toString().padStart(2, "0")}, 0.${Math.floor(Math.random() * 10).toString().padStart(2, "0")}`;
33
+ const colHeader = "USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT";
34
+ const idle = "0.00s";
35
+ const row = `${authUser.padEnd(8)} pts/0 browser ${loginTime} ${idle} 0.01s 0.00s -bash`;
36
+ return { stdout: [header, colHeader, row].join("\n"), exitCode: 0 };
37
+ },
38
+ };
@@ -56,3 +56,15 @@ export declare function expandSync(input: string, env: Record<string, string>, l
56
56
  * @param runCmd Async callback to execute a command and return its stdout.
57
57
  */
58
58
  export declare function expandAsync(input: string, env: Record<string, string>, lastExit: number, runCmd: (cmd: string) => Promise<string>): Promise<string>;
59
+ /**
60
+ * Expand a glob pattern against a VirtualShell VFS.
61
+ * Supports * (any chars in segment) and ** (any path).
62
+ * Returns the original pattern if no matches found (bash behavior).
63
+ */
64
+ export declare function expandGlob(pattern: string, cwd: string, vfs: {
65
+ list: (p: string) => string[];
66
+ exists: (p: string) => boolean;
67
+ stat: (p: string) => {
68
+ type: string;
69
+ };
70
+ }): string[];
@@ -474,3 +474,87 @@ export async function expandAsync(input, env, lastExit, runCmd) {
474
474
  env[depthKey] = String(currentDepth);
475
475
  }
476
476
  }
477
+ // ─── Glob expansion ──────────────────────────────────────────────────────────
478
+ /**
479
+ * Expand a glob pattern against a VirtualShell VFS.
480
+ * Supports * (any chars in segment) and ** (any path).
481
+ * Returns the original pattern if no matches found (bash behavior).
482
+ */
483
+ export function expandGlob(pattern, cwd, vfs) {
484
+ // No glob chars → return as-is
485
+ if (!pattern.includes('*') && !pattern.includes('?'))
486
+ return [pattern];
487
+ const isAbsolute = pattern.startsWith('/');
488
+ const base = isAbsolute ? '/' : cwd;
489
+ const relPattern = isAbsolute ? pattern.slice(1) : pattern;
490
+ const results = matchGlob(base, relPattern.split('/'), vfs);
491
+ if (results.length === 0)
492
+ return [pattern]; // no match → literal
493
+ return results.sort();
494
+ }
495
+ function matchGlob(dir, segments, vfs) {
496
+ if (segments.length === 0)
497
+ return [dir];
498
+ const [seg, ...rest] = segments;
499
+ if (!seg)
500
+ return [dir];
501
+ // ** matches zero or more path segments
502
+ if (seg === '**') {
503
+ const all = walkAll(dir, vfs);
504
+ return rest.length === 0 ? all : all.flatMap(d => {
505
+ try {
506
+ if (vfs.stat(d).type === 'directory')
507
+ return matchGlob(d, rest, vfs);
508
+ }
509
+ catch { }
510
+ return [];
511
+ });
512
+ }
513
+ let entries = [];
514
+ try {
515
+ entries = vfs.list(dir);
516
+ }
517
+ catch {
518
+ return [];
519
+ }
520
+ const re = globToRegex(seg);
521
+ return entries
522
+ .filter(e => !e.startsWith('.') || seg.startsWith('.'))
523
+ .filter(e => re.test(e))
524
+ .flatMap(e => {
525
+ const full = dir === '/' ? `/${e}` : `${dir}/${e}`;
526
+ if (rest.length === 0)
527
+ return [full];
528
+ try {
529
+ if (vfs.stat(full).type === 'directory')
530
+ return matchGlob(full, rest, vfs);
531
+ }
532
+ catch { }
533
+ return [];
534
+ });
535
+ }
536
+ function walkAll(dir, vfs) {
537
+ const results = [dir];
538
+ let entries = [];
539
+ try {
540
+ entries = vfs.list(dir);
541
+ }
542
+ catch {
543
+ return results;
544
+ }
545
+ for (const e of entries) {
546
+ const full = dir === '/' ? `/${e}` : `${dir}/${e}`;
547
+ try {
548
+ if (vfs.stat(full).type === 'directory')
549
+ results.push(...walkAll(full, vfs));
550
+ }
551
+ catch { }
552
+ }
553
+ return results;
554
+ }
555
+ function globToRegex(pattern) {
556
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&')
557
+ .replace(/\*/g, '.*')
558
+ .replace(/\?/g, '.');
559
+ return new RegExp(`^${escaped}$`);
560
+ }
package/package.json CHANGED
@@ -4,7 +4,13 @@
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
7
- "version": "1.5.3",
7
+ "version": "1.5.4",
8
+ "files": [
9
+ "dist/",
10
+ "README.md",
11
+ "LICENSE",
12
+ "CHANGELOG.md"
13
+ ],
8
14
  "license": "MIT",
9
15
  "repository": {
10
16
  "type": "git",
@@ -26,7 +32,7 @@
26
32
  "lint:write": "bunx --bun @biomejs/biome lint --write ./src",
27
33
  "test": "bun run test-salve",
28
34
  "test-battery": "bun test tests/",
29
- "test-salve": "for f in tests/*.test.ts; do echo \"\\n🧪 Testing $f...\"; bun test \"$f\" --timeout 10000; sleep 0.25; done",
35
+ "test-salve": "for f in tests/*.test.ts; do echo \"\\n\ud83e\uddea Testing $f...\"; bun test \"$f\" --timeout 10000; sleep 0.25; done",
30
36
  "build": "tsc --project tsconfig.json",
31
37
  "deploy:npm": "bun publish --access public",
32
38
  "bench": "rm -rf .benchmark-shells/ && bun benchmark-virtualshell.ts",
@@ -59,4 +65,4 @@
59
65
  "dependencies": {
60
66
  "ssh2": "^1.17.0"
61
67
  }
62
- }
68
+ }
@@ -1,50 +0,0 @@
1
- name: Bug report
2
- description: Report a reproducible problem
3
- labels: [bug]
4
- body:
5
- - type: markdown
6
- attributes:
7
- value: |
8
- Thanks for reporting a bug. Please fill out the details below.
9
- - type: input
10
- id: version
11
- attributes:
12
- label: Package version
13
- placeholder: 1.0.0
14
- validations:
15
- required: true
16
- - type: input
17
- id: runtime
18
- attributes:
19
- label: Runtime and version
20
- description: Node or Bun
21
- placeholder: Node 20.12.0
22
- validations:
23
- required: true
24
- - type: textarea
25
- id: reproduction
26
- attributes:
27
- label: Reproduction steps
28
- placeholder: |
29
- 1. Start server with ...
30
- 2. Run command ...
31
- 3. Observe error ...
32
- validations:
33
- required: true
34
- - type: textarea
35
- id: expected
36
- attributes:
37
- label: Expected behavior
38
- validations:
39
- required: true
40
- - type: textarea
41
- id: actual
42
- attributes:
43
- label: Actual behavior
44
- validations:
45
- required: true
46
- - type: textarea
47
- id: logs
48
- attributes:
49
- label: Logs or stack trace
50
- render: shell
@@ -1,31 +0,0 @@
1
- name: Feature request
2
- description: Suggest an improvement
3
- labels: [enhancement]
4
- body:
5
- - type: markdown
6
- attributes:
7
- value: |
8
- Thanks for proposing an improvement.
9
- - type: textarea
10
- id: problem
11
- attributes:
12
- label: Problem statement
13
- description: What problem are you trying to solve?
14
- validations:
15
- required: true
16
- - type: textarea
17
- id: proposal
18
- attributes:
19
- label: Proposed solution
20
- description: Describe the API or behavior you want.
21
- validations:
22
- required: true
23
- - type: textarea
24
- id: alternatives
25
- attributes:
26
- label: Alternatives considered
27
- - type: textarea
28
- id: impact
29
- attributes:
30
- label: Breaking change impact
31
- description: Does this change public API behavior?
@@ -1,27 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: "npm"
4
- directory: "/"
5
- schedule:
6
- interval: "daily"
7
- time: "04:00"
8
- timezone: "Europe/Paris"
9
- open-pull-requests-limit: 20
10
- rebase-strategy: "auto"
11
- versioning-strategy: "increase-if-necessary"
12
- # Exclude metric/analytics packages from version update PRs.
13
- ignore:
14
- - dependency-name: "*metrics*"
15
- - dependency-name: "*analytics*"
16
- groups:
17
- patch-and-minor:
18
- patterns:
19
- - "*"
20
- update-types:
21
- - "minor"
22
- - "patch"
23
- major:
24
- patterns:
25
- - "*"
26
- update-types:
27
- - "major"
@@ -1,21 +0,0 @@
1
- ## Summary
2
-
3
- Describe what changed and why.
4
-
5
- ## Type of change
6
-
7
- - [ ] Bug fix
8
- - [ ] New feature
9
- - [ ] Breaking change
10
- - [ ] Documentation update
11
- - [ ] Refactor
12
-
13
- ## Validation
14
-
15
- - [ ] I ran bun format
16
- - [ ] I ran bun check
17
- - [ ] I tested the changed behavior locally
18
-
19
- ## Notes for reviewers
20
-
21
- Include anything reviewers should focus on (tradeoffs, edge cases, risks).
@@ -1,85 +0,0 @@
1
- name: Auto Create Pull Request
2
-
3
- on:
4
- push:
5
- branches:
6
-
7
- jobs:
8
- create-pull-request:
9
- if: github.ref != 'refs/heads/main'
10
- runs-on: ubuntu-latest
11
- steps:
12
- - name: Validate pull request token
13
- env:
14
- AUTO_PR_TOKEN: ${{ secrets.AUTO_PR_TOKEN }}
15
- run: |
16
- if [ -z "$AUTO_PR_TOKEN" ]; then
17
- echo "AUTO_PR_TOKEN is required to create pull requests from GitHub Actions. Use a PAT or GitHub App token with contents:write and pull-requests:write."
18
- exit 1
19
- fi
20
-
21
- - name: Create pull request if none exists
22
- uses: actions/github-script@v8
23
- with:
24
- github-token: ${{ secrets.AUTO_PR_TOKEN }}
25
- script: |
26
- const owner = context.repo.owner;
27
- const repo = context.repo.repo;
28
- const sourceBranch = context.ref.startsWith('refs/heads/')
29
- ? context.ref.slice('refs/heads/'.length)
30
- : context.ref;
31
- const head = `${owner}:${sourceBranch}`;
32
- const base = 'main';
33
-
34
- // Check if there are commits between main and the current branch
35
- const { data: comparison } = await github.rest.repos.compareCommits({
36
- owner,
37
- repo,
38
- base: 'main',
39
- head: sourceBranch,
40
- }).catch(err => {
41
- if (err.status === 404 && err.message.includes('No commits')) {
42
- core.info('No commits between main and ' + sourceBranch + ' - skipping PR creation');
43
- return { data: { ahead_by: 0 } };
44
- }
45
- throw err;
46
- });
47
-
48
- if (comparison.ahead_by === 0) {
49
- core.info('Branches are identical - no pull request needed');
50
- return;
51
- }
52
-
53
- const { data: existingPullRequests } = await github.rest.pulls.list({
54
- owner,
55
- repo,
56
- state: 'open',
57
- head,
58
- base,
59
- });
60
-
61
- if (existingPullRequests.length > 0) {
62
- core.info(`Pull request already exists: #${existingPullRequests[0].number}`);
63
- return;
64
- }
65
-
66
- const { data: pullRequest } = await github.rest.pulls.create({
67
- owner,
68
- repo,
69
- head: sourceBranch,
70
- base,
71
- title: `chore: auto PR from ${sourceBranch} to main`,
72
- body: [
73
- 'This pull request was created automatically by GitHub Actions.',
74
- '',
75
- `- source branch: \`${sourceBranch}\``,
76
- `- target branch: \`main\``,
77
- `- triggered by commit \`${context.sha}\``,
78
- ].join('\n'),
79
- });
80
-
81
- core.info(`Created pull request #${pullRequest.number}: ${pullRequest.html_url}`);
82
-
83
- permissions:
84
- contents: write
85
- pull-requests: write
@@ -1,25 +0,0 @@
1
- name: Publish Package
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
- workflow_dispatch:
8
-
9
- permissions:
10
- id-token: write # Required for OIDC
11
- contents: read
12
-
13
- jobs:
14
- publish:
15
- runs-on: ubuntu-latest
16
- steps:
17
- - uses: actions/checkout@v6
18
-
19
- - uses: actions/setup-node@v6
20
- with:
21
- node-version: '24'
22
- registry-url: 'https://registry.npmjs.org'
23
- - run: npm install
24
- - run: npm run build --if-present
25
- - run: npm publish