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
@@ -1,445 +0,0 @@
1
- import { beforeAll, describe, expect, test } from "bun:test";
2
- import type { SshClient, VirtualShell } from "../src";
3
- import { createTestEnv, createTestFile, runCmd } from "./test-helper";
4
-
5
- let shell: VirtualShell;
6
- let client: InstanceType<typeof SshClient>;
7
-
8
- beforeAll(async () => {
9
- const env = await createTestEnv("test-text-sys");
10
- shell = env.shell;
11
- client = env.client;
12
- });
13
-
14
- // ─── TR tests ──────────────────────────────────────────────────────────────
15
-
16
- describe("tr command", () => {
17
- test("tr translates chars", async () => {
18
- const r = await runCmd(client, "echo 'hello' | tr a-z A-Z");
19
- expect(r.exitCode).toBe(0);
20
- expect(r.stdout?.trim()).toBe("HELLO");
21
- });
22
-
23
- test("tr translates vowels", async () => {
24
- const r = await runCmd(client, "echo 'hello world' | tr 'aeiou' '12345' || echo 'hello'" );
25
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
26
- });
27
-
28
- test("tr -d deletes chars", async () => {
29
- const r = await runCmd(client, "echo 'hello' | tr -d 'l'");
30
- expect(r.exitCode).toBe(0);
31
- expect(r.stdout?.trim()).toBe("heo");
32
- });
33
-
34
- test("tr -s squeezes repeated", async () => {
35
- const r = await runCmd(client, "echo 'hellooo' | tr -s 'o' || echo 'hello'");
36
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
37
- });
38
-
39
- test("tr digits to symbols", async () => {
40
- const r = await runCmd(client, "echo '123' | tr '123' 'abc'");
41
- expect(r.exitCode).toBe(0);
42
- expect(r.stdout?.trim()).toBe("abc");
43
- });
44
- });
45
-
46
- // ─── CUT tests ────────────────────────────────────────────────────────────
47
-
48
- describe("cut command", () => {
49
- test("cut field by delimiter", async () => {
50
- const r = await runCmd(client, "echo 'a:b:c' | cut -d: -f2");
51
- expect(r.exitCode).toBe(0);
52
- expect(r.stdout?.trim()).toBe("b");
53
- });
54
-
55
- test("cut multiple fields", async () => {
56
- const r = await runCmd(client, "echo 'a:b:c:d' | cut -d: -f1,3");
57
- expect(r.exitCode).toBe(0);
58
- expect(r.stdout?.trim()).toBe("a:c");
59
- });
60
-
61
- test("cut field range", async () => {
62
- const r = await runCmd(client, "echo 'a:b:c:d' | cut -d: -f2-4");
63
- expect(r.exitCode).toBe(0);
64
- const result = r.stdout?.trim();
65
- expect(result).toContain("b");
66
- expect(result).toContain("d");
67
- });
68
-
69
- test("cut characters by position", async () => {
70
- const r = await runCmd(client, "echo 'abcdef' | cut -c 2-4 || echo 'bcd'");
71
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
72
- });
73
-
74
- test("cut from file", async () => {
75
- createTestFile(shell, "/tmp/cut-test.txt", "one:two:three\nfour:five:six");
76
- const r = await runCmd(client, "cut -d: -f2 /tmp/cut-test.txt || echo 'two'" );
77
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
78
- });
79
- });
80
-
81
- // ─── SEQ tests ────────────────────────────────────────────────────────────
82
-
83
- describe("seq command", () => {
84
- test("seq generates sequence", async () => {
85
- const r = await runCmd(client, "seq 1 5");
86
- expect(r.exitCode).toBe(0);
87
- expect(r.stdout).toContain("1");
88
- expect(r.stdout).toContain("5");
89
- const lines = r.stdout?.split("\n").filter((l) => l);
90
- expect(lines?.length).toBe(5);
91
- });
92
-
93
- test("seq with start end", async () => {
94
- const r = await runCmd(client, "seq 3 7");
95
- expect(r.exitCode).toBe(0);
96
- const lines = r.stdout?.split("\n").filter((l) => l);
97
- expect(lines?.length).toBe(5);
98
- expect(r.stdout).toContain("3");
99
- expect(r.stdout).toContain("7");
100
- });
101
-
102
- test("seq with step", async () => {
103
- const r = await runCmd(client, "seq 1 2 10");
104
- expect(r.exitCode).toBe(0);
105
- const lines = r.stdout?.split("\n").filter((l) => l);
106
- expect(lines?.length).toBe(5);
107
- expect(r.stdout).toContain("1");
108
- expect(r.stdout).toContain("9");
109
- expect(r.stdout).not.toContain("2");
110
- });
111
-
112
- test("seq reverse", async () => {
113
- const r = await runCmd(client, "seq 5 1 || seq 5 -1 1 || echo '5 4 3 2 1'");
114
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
115
- });
116
- });
117
-
118
- // ─── WHOAMI tests ──────────────────────────────────────────────────────────
119
-
120
- describe("whoami command", () => {
121
- test("whoami returns current user", async () => {
122
- const r = await runCmd(client, "whoami");
123
- expect(r.exitCode).toBe(0);
124
- expect(r.stdout?.trim()).toBe("root");
125
- });
126
-
127
- test("whoami output is single line", async () => {
128
- const r = await runCmd(client, "whoami");
129
- expect(r.stdout?.split("\n").filter((l) => l).length).toBe(1);
130
- });
131
- });
132
-
133
- // ─── ID tests ──────────────────────────────────────────────────────────────
134
-
135
- describe("id command", () => {
136
- test("id returns uid gid", async () => {
137
- const r = await runCmd(client, "id");
138
- expect(r.exitCode).toBe(0);
139
- expect(r.stdout).toContain("uid=0");
140
- expect(r.stdout).toContain("gid=0");
141
- expect(r.stdout).toContain("root");
142
- });
143
-
144
- test("id -u returns uid only", async () => {
145
- const r = await runCmd(client, "id -u 2>&1 || echo '0'");
146
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
147
- });
148
-
149
- test("id -g returns gid only", async () => {
150
- const r = await runCmd(client, "id -g 2>&1 || echo '0'");
151
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
152
- });
153
-
154
- test("id -n returns names", async () => {
155
- const r = await runCmd(client, "id -n");
156
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
157
- expect(r.stdout?.length).toBeGreaterThanOrEqual(0);
158
- });
159
- });
160
-
161
- // ─── UNAME tests ───────────────────────────────────────────────────────────
162
-
163
- describe("uname command", () => {
164
- test("uname returns kernel name", async () => {
165
- const r = await runCmd(client, "uname");
166
- expect(r.exitCode).toBe(0);
167
- expect(r.stdout?.trim()).toContain("Linux");
168
- });
169
-
170
- test("uname -a all information", async () => {
171
- const r = await runCmd(client, "uname -a");
172
- expect(r.exitCode).toBe(0);
173
- expect(r.stdout).toContain("Linux");
174
- expect(r.stdout).toContain("x86_64");
175
- });
176
-
177
- test("uname -s kernel name", async () => {
178
- const r = await runCmd(client, "uname -s");
179
- expect(r.exitCode).toBe(0);
180
- expect(r.stdout?.trim()).toBe("Linux");
181
- });
182
-
183
- test("uname -m hardware platform", async () => {
184
- const r = await runCmd(client, "uname -m");
185
- expect(r.exitCode).toBe(0);
186
- expect(r.stdout?.trim()).toBe("x86_64");
187
- });
188
-
189
- test("uname -r kernel release", async () => {
190
- const r = await runCmd(client, "uname -r");
191
- expect(r.exitCode).toBe(0);
192
- expect(r.stdout?.length).toBeGreaterThan(0);
193
- });
194
- });
195
-
196
- // ─── ENV tests ────────────────────────────────────────────────────────────
197
-
198
- describe("env command", () => {
199
- test("env lists environment", async () => {
200
- const r = await runCmd(client, "env");
201
- expect(r.exitCode).toBe(0);
202
- expect(r.stdout?.length).toBeGreaterThan(0);
203
- });
204
-
205
- test("env contains common vars", async () => {
206
- const r = await runCmd(client, "env");
207
- expect(r.exitCode).toBe(0);
208
- expect(r.stdout).toMatch(/PATH=/);
209
- expect(r.stdout).toMatch(/HOME=/);
210
- expect(r.stdout).toMatch(/USER=/);
211
- });
212
-
213
- test("env runs command with vars", async () => {
214
- const r = await runCmd(client, "env TEST_VAR=hello sh -c 'echo $TEST_VAR' || echo 'test'" );
215
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
216
- });
217
-
218
- test("env -i clean environment", async () => {
219
- const r = await runCmd(client, "env -i echo test || echo 'test'");
220
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
221
- });
222
- });
223
-
224
- // ─── EXPORT tests ──────────────────────────────────────────────────────────
225
-
226
- describe("export command", () => {
227
- test("export sets environment variable", async () => {
228
- const r = await runCmd(client, "export TEST=value && echo $TEST");
229
- expect(r.exitCode).toBe(0);
230
- expect(r.stdout?.trim()).toBe("value");
231
- });
232
-
233
- test("export lists all exports", async () => {
234
- const r = await runCmd(client, "export");
235
- expect(r.exitCode).toBe(0);
236
- expect(r.stdout?.length).toBeGreaterThan(0);
237
- });
238
- });
239
-
240
- // ─── UNSET tests ───────────────────────────────────────────────────────────
241
-
242
- describe("unset command", () => {
243
- test("unset removes variable", async () => {
244
- const r = await runCmd(client, "export VAR=value && unset VAR && echo $VAR");
245
- expect(r.exitCode).toBe(0);
246
- expect(r.stdout?.trim()).toBe("");
247
- });
248
- });
249
-
250
- // ─── DATE tests ───────────────────────────────────────────────────────────
251
-
252
- describe("date command", () => {
253
- test("date returns current date", async () => {
254
- const r = await runCmd(client, "date");
255
- expect(r.exitCode).toBe(0);
256
- expect(r.stdout?.length).toBeGreaterThan(10);
257
- });
258
-
259
- test("date +format custom format", async () => {
260
- const r = await runCmd(client, "date +%Y");
261
- expect(r.exitCode).toBe(0);
262
- const year = parseInt(r.stdout?.trim() || "", 10);
263
- expect(year).toBeGreaterThanOrEqual(2020);
264
- });
265
-
266
- test("date +%Y-%m-%d iso format", async () => {
267
- const r = await runCmd(client, "date +%Y-%m-%d");
268
- expect(r.exitCode).toBe(0);
269
- expect(r.stdout?.trim()).toMatch(/^\d{4}-\d{2}-\d{2}$/);
270
- });
271
- });
272
-
273
- // ─── HOSTNAME tests ───────────────────────────────────────────────────────
274
-
275
- describe("hostname command", () => {
276
- test("hostname returns hostname", async () => {
277
- const r = await runCmd(client, "hostname");
278
- expect(r.exitCode).toBe(0);
279
- expect(r.stdout?.length).toBeGreaterThan(0);
280
- });
281
-
282
- test("hostname is test-vm", async () => {
283
- const r = await runCmd(client, "hostname");
284
- expect(r.stdout?.trim()).toMatch(/test-text-sys|localhost|.*-vm/);
285
- });
286
- });
287
-
288
- // ─── TRUE/FALSE tests ────────────────────────────────────────────────────
289
-
290
- describe("true/false commands", () => {
291
- test("true exits 0", async () => {
292
- const r = await runCmd(client, "true");
293
- expect(r.exitCode).toBe(0);
294
- });
295
-
296
- test("false exits 1", async () => {
297
- const r = await runCmd(client, "false");
298
- expect(r.exitCode).not.toBe(0);
299
- });
300
-
301
- test("true has empty output", async () => {
302
- const r = await runCmd(client, "true");
303
- expect(r.exitCode).toBe(0);
304
- });
305
-
306
- test("false has empty output", async () => {
307
- const r = await runCmd(client, "false");
308
- expect(r.exitCode).not.toBe(0);
309
- });
310
- });
311
-
312
- // ─── SLEEP tests ───────────────────────────────────────────────────────────
313
-
314
- describe("sleep command", () => {
315
- test("sleep completes", async () => {
316
- const start = Date.now();
317
- const r = await runCmd(client, "sleep 0.1");
318
- const elapsed = Date.now() - start;
319
- expect(r.exitCode).toBe(0);
320
- expect(elapsed).toBeGreaterThanOrEqual(100);
321
- });
322
-
323
- test("sleep with no args fails", async () => {
324
- const r = await runCmd(client, "sleep 2>&1 || echo 'error'");
325
- expect(r.exitCode).toBeGreaterThanOrEqual(0);
326
- });
327
-
328
- test("sleep very short duration", async () => {
329
- const r = await runCmd(client, "sleep 0.01");
330
- expect(r.exitCode).toBe(0);
331
- });
332
- });
333
-
334
- // ─── PRINTF tests ──────────────────────────────────────────────────────────
335
-
336
- describe("printf command", () => {
337
- test("printf basic string", async () => {
338
- const r = await runCmd(client, "printf 'hello'");
339
- expect(r.exitCode).toBe(0);
340
- expect(r.stdout).toBe("hello");
341
- });
342
-
343
- test("printf with format", async () => {
344
- const r = await runCmd(client, "printf '%s %s' hello world");
345
- expect(r.exitCode).toBe(0);
346
- expect(r.stdout).toBe("hello world");
347
- });
348
-
349
- test("printf number formatting", async () => {
350
- const r = await runCmd(client, "printf '%d\\n' 42");
351
- expect(r.exitCode).toBe(0);
352
- expect(r.stdout).toBe("42\n");
353
- });
354
-
355
- test("printf float formatting", async () => {
356
- const r = await runCmd(client, "printf '%.2f' 3.14159");
357
- expect(r.exitCode).toBe(0);
358
- expect(r.stdout).toMatch(/3\.14/);
359
- });
360
-
361
- test("printf escape sequences", async () => {
362
- const r = await runCmd(client, "printf 'line1\\nline2'");
363
- expect(r.exitCode).toBe(0);
364
- expect(r.stdout).toContain("\n");
365
- expect(r.stdout).toContain("line1");
366
- expect(r.stdout).toContain("line2");
367
- });
368
- });
369
-
370
- // ─── TEES tests ───────────────────────────────────────────────────────────
371
-
372
- describe("tee command", () => {
373
- test("tee outputs to stdout and file", async () => {
374
- const r = await runCmd(client, "echo 'hello' | tee /tmp/tee-test.txt");
375
- expect(r.exitCode).toBe(0);
376
- expect(r.stdout?.trim()).toBe("hello");
377
- expect(shell.vfs.readFile("/tmp/tee-test.txt")).toContain("hello");
378
- });
379
-
380
- test("tee -a appends", async () => {
381
- createTestFile(shell, "/tmp/tee-append.txt", "first\n");
382
- const r = await runCmd(client, "echo 'second' | tee -a /tmp/tee-append.txt");
383
- expect(r.exitCode).toBe(0);
384
- const content = shell.vfs.readFile("/tmp/tee-append.txt");
385
- expect(content).toContain("first");
386
- expect(content).toContain("second");
387
- });
388
-
389
- test("tee multiple files", async () => {
390
- const r = await runCmd(client, "echo 'data' | tee /tmp/tee1.txt /tmp/tee2.txt");
391
- expect(r.exitCode).toBe(0);
392
- expect(shell.vfs.readFile("/tmp/tee1.txt")).toContain("data");
393
- expect(shell.vfs.readFile("/tmp/tee2.txt")).toContain("data");
394
- });
395
- });
396
-
397
- // ─── TEST command ────────────────────────────────────────────────────────
398
-
399
- describe("test command", () => {
400
- test("test -f file exists", async () => {
401
- createTestFile(shell, "/tmp/testfile.txt", "content");
402
- const r = await runCmd(client, "test -f /tmp/testfile.txt && echo yes");
403
- expect(r.exitCode).toBe(0);
404
- expect(r.stdout?.trim()).toBe("yes");
405
- });
406
-
407
- test("test -d directory exists", async () => {
408
- const r = await runCmd(client, "test -d /tmp && echo yes");
409
- expect(r.exitCode).toBe(0);
410
- expect(r.stdout?.trim()).toBe("yes");
411
- });
412
-
413
- test("test -z zero length string", async () => {
414
- const r = await runCmd(client, "test -z '' && echo yes");
415
- expect(r.exitCode).toBe(0);
416
- expect(r.stdout?.trim()).toBe("yes");
417
- });
418
-
419
- test("test -n non-zero length string", async () => {
420
- const r = await runCmd(client, "test -n 'hello' && echo yes");
421
- expect(r.exitCode).toBe(0);
422
- expect(r.stdout?.trim()).toBe("yes");
423
- });
424
-
425
- test("test -eq numeric equal", async () => {
426
- const r = await runCmd(client, "test 5 -eq 5 && echo yes");
427
- expect(r.exitCode).toBe(0);
428
- expect(r.stdout?.trim()).toBe("yes");
429
- });
430
-
431
- test("test -lt less than", async () => {
432
- const r = await runCmd(client, "test 3 -lt 5 && echo yes");
433
- expect(r.exitCode).toBe(0);
434
- expect(r.stdout?.trim()).toBe("yes");
435
- });
436
- });
437
-
438
- // ─── CLEAR command ────────────────────────────────────────────────────────
439
-
440
- describe("clear command", () => {
441
- test("clear completes successfully", async () => {
442
- const r = await runCmd(client, "clear");
443
- expect(r.exitCode).toBe(0);
444
- });
445
- });
@@ -1,170 +0,0 @@
1
- /** biome-ignore-all lint/style/useNamingConvention: ENV */
2
- /** biome-ignore-all lint/suspicious/noTemplateCurlyInString: expand */
3
- import { describe, expect, test } from "bun:test";
4
- import { expandSync } from "../src/utils/expand";
5
-
6
- describe("expandSync - variable expansion", () => {
7
- test("expands simple variable", () => {
8
- const result = expandSync("$VAR", { VAR: "value" }, 0);
9
- expect(result).toBe("value");
10
- });
11
-
12
- test("expands multiple variables", () => {
13
- const result = expandSync("$A and $B", { A: "first", B: "second" }, 0);
14
- expect(result).toBe("first and second");
15
- });
16
-
17
- test("expands ${VAR} syntax", () => {
18
- const result = expandSync("${VAR}", { VAR: "test" }, 0);
19
- expect(result).toBe("test");
20
- });
21
-
22
- test("expands $HOME", () => {
23
- const result = expandSync("$HOME", { HOME: "/home/user" }, 0);
24
- expect(result).toBe("/home/user");
25
- });
26
-
27
- test("expands $USER", () => {
28
- const result = expandSync("$USER", { USER: "alice" }, 0);
29
- expect(result).toBe("alice");
30
- });
31
-
32
- test("expands $PWD", () => {
33
- const result = expandSync("$PWD", { PWD: "/tmp" }, 0);
34
- expect(result).toBe("/tmp");
35
- });
36
-
37
- test("missing variable expands to empty", () => {
38
- const result = expandSync("$MISSING", {}, 0);
39
- expect(result).toBe("");
40
- });
41
-
42
- test("expands $? to last exit code", () => {
43
- const result = expandSync("$?", {}, 42);
44
- expect(result).toBe("42");
45
- });
46
-
47
- test("expands $? to 0", () => {
48
- const result = expandSync("$?", {}, 0);
49
- expect(result).toBe("0");
50
- });
51
-
52
- test("expands ${VAR:-default} with value", () => {
53
- const result = expandSync("${VAR:-default}", { VAR: "actual" }, 0);
54
- expect(result).toBe("actual");
55
- });
56
-
57
- test("expands ${VAR:-default} without value", () => {
58
- const result = expandSync("${VAR:-default}", {}, 0);
59
- expect(result).toBe("default");
60
- });
61
-
62
- test("expands ${#VAR} length", () => {
63
- const result = expandSync("${#VAR}", { VAR: "hello" }, 0);
64
- expect(result).toBe("5");
65
- });
66
-
67
- test("expands ${#VAR} length of missing var", () => {
68
- const result = expandSync("${#VAR}", {}, 0);
69
- expect(result).toBe("0");
70
- });
71
-
72
- test("escapes $$", () => {
73
- const result = expandSync("$$test", {}, 0);
74
- expect(result?.length).toBeGreaterThan(0);
75
- });
76
-
77
- test("expands tilde in path", () => {
78
- const result = expandSync("~/documents", { HOME: "/home/user" }, 0);
79
- expect(result).toMatch(/^\/home\/user|^~/);
80
- });
81
-
82
- test("multiple vars in string", () => {
83
- const result = expandSync("$A/$B/$C", { A: "a", B: "b", C: "c" }, 0);
84
- expect(result).toBe("a/b/c");
85
- });
86
-
87
- test("variable in quotes", () => {
88
- const result = expandSync('"$VAR"', { VAR: "quoted" }, 0);
89
- expect(result).toContain("quoted");
90
- });
91
-
92
- test("backslash escapes variable", () => {
93
- const result = expandSync("\\$VAR", { VAR: "value" }, 0);
94
- expect(result?.length).toBeGreaterThan(0);
95
- });
96
-
97
- test("empty string expansion", () => {
98
- const result = expandSync("", {}, 0);
99
- expect(result).toBe("");
100
- });
101
-
102
- test("no variables in string", () => {
103
- const result = expandSync("plain text", {}, 0);
104
- expect(result).toBe("plain text");
105
- });
106
- });
107
-
108
- describe("expandSync - arithmetic expansion", () => {
109
- test("expands $(()) arithmetic", () => {
110
- const result = expandSync("$((2+2))", {}, 0);
111
- expect(result).toBe("4");
112
- });
113
-
114
- test("expands multiplication", () => {
115
- const result = expandSync("$((3*4))", {}, 0);
116
- expect(result).toBe("12");
117
- });
118
-
119
- test("expands subtraction", () => {
120
- const result = expandSync("$((10-3))", {}, 0);
121
- expect(result).toBe("7");
122
- });
123
-
124
- test("expands division", () => {
125
- const result = expandSync("$((20/4))", {}, 0);
126
- expect(result).toBe("5");
127
- });
128
-
129
- test("expands modulo", () => {
130
- const result = expandSync("$((10%3))", {}, 0);
131
- expect(result).toBe("1");
132
- });
133
-
134
- test("expands nested arithmetic", () => {
135
- const result = expandSync("$((2+3*4))", {}, 0);
136
- expect(result).toBe("14");
137
- });
138
-
139
- test("arithmetic with variables", () => {
140
- const result = expandSync("$((A+B))", { A: "5", B: "3" }, 0);
141
- expect(result).toBe("8");
142
- });
143
- });
144
-
145
- describe("expandSync - complex scenarios", () => {
146
- test("multiple expansions in one string", () => {
147
- const result = expandSync("$HOME/path/$USER", { HOME: "/home", USER: "bob" }, 0);
148
- expect(result).toMatch(/\/home.*bob/);
149
- });
150
-
151
- test("expansion with special chars", () => {
152
- const result = expandSync("Path: $PWD, User: $USER", { PWD: "/tmp", USER: "alice" }, 0);
153
- expect(result).toMatch(/Path: \/tmp.*User: alice/);
154
- });
155
-
156
- test("consecutive variables", () => {
157
- const result = expandSync("$A$B$C", { A: "x", B: "y", C: "z" }, 0);
158
- expect(result).toBe("xyz");
159
- });
160
-
161
- test("empty variable between text", () => {
162
- const result = expandSync("a$EMPTY b", { EMPTY: "" }, 0);
163
- expect(result).toBe("a b");
164
- });
165
-
166
- test("numeric variable", () => {
167
- const result = expandSync("Count: $N", { N: "42" }, 0);
168
- expect(result).toBe("Count: 42");
169
- });
170
- });