typescript-virtual-container 1.2.5 → 1.2.7

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 (248) hide show
  1. package/README.md +387 -193
  2. package/benchmark-results.txt +21 -21
  3. package/biome.json +1 -1
  4. package/bun.lock +15 -41
  5. package/dist/SSHMimic/exec.js +2 -2
  6. package/dist/SSHMimic/executor.d.ts +6 -7
  7. package/dist/SSHMimic/executor.d.ts.map +1 -1
  8. package/dist/SSHMimic/executor.js +77 -60
  9. package/dist/SSHMimic/index.d.ts.map +1 -1
  10. package/dist/SSHMimic/index.js +6 -20
  11. package/dist/SSHMimic/sftp.d.ts.map +1 -1
  12. package/dist/SSHMimic/sftp.js +14 -0
  13. package/dist/VirtualFileSystem/index.d.ts.map +1 -1
  14. package/dist/VirtualFileSystem/index.js +13 -36
  15. package/dist/VirtualShell/shell.d.ts.map +1 -1
  16. package/dist/VirtualShell/shell.js +19 -2
  17. package/dist/VirtualShell/shellParser.d.ts +20 -2
  18. package/dist/VirtualShell/shellParser.d.ts.map +1 -1
  19. package/dist/VirtualShell/shellParser.js +229 -120
  20. package/dist/VirtualUserManager/index.d.ts.map +1 -1
  21. package/dist/commands/adduser.d.ts.map +1 -1
  22. package/dist/commands/adduser.js +2 -0
  23. package/dist/commands/awk.d.ts +3 -0
  24. package/dist/commands/awk.d.ts.map +1 -0
  25. package/dist/commands/awk.js +29 -0
  26. package/dist/commands/base64.d.ts +3 -0
  27. package/dist/commands/base64.d.ts.map +1 -0
  28. package/dist/commands/base64.js +20 -0
  29. package/dist/commands/cat.d.ts.map +1 -1
  30. package/dist/commands/cat.js +2 -0
  31. package/dist/commands/cd.d.ts.map +1 -1
  32. package/dist/commands/cd.js +2 -0
  33. package/dist/commands/chmod.d.ts.map +1 -1
  34. package/dist/commands/chmod.js +2 -0
  35. package/dist/commands/clear.d.ts.map +1 -1
  36. package/dist/commands/clear.js +4 -1
  37. package/dist/commands/cp.d.ts.map +1 -1
  38. package/dist/commands/cp.js +2 -0
  39. package/dist/commands/curl.d.ts.map +1 -1
  40. package/dist/commands/curl.js +2 -0
  41. package/dist/commands/cut.d.ts +3 -0
  42. package/dist/commands/cut.d.ts.map +1 -0
  43. package/dist/commands/cut.js +27 -0
  44. package/dist/commands/date.d.ts +3 -0
  45. package/dist/commands/date.d.ts.map +1 -0
  46. package/dist/commands/date.js +22 -0
  47. package/dist/commands/deluser.d.ts.map +1 -1
  48. package/dist/commands/deluser.js +2 -0
  49. package/dist/commands/df.d.ts +3 -0
  50. package/dist/commands/df.d.ts.map +1 -0
  51. package/dist/commands/df.js +16 -0
  52. package/dist/commands/diff.d.ts +3 -0
  53. package/dist/commands/diff.d.ts.map +1 -0
  54. package/dist/commands/diff.js +40 -0
  55. package/dist/commands/du.d.ts +3 -0
  56. package/dist/commands/du.d.ts.map +1 -0
  57. package/dist/commands/du.js +39 -0
  58. package/dist/commands/echo.d.ts.map +1 -1
  59. package/dist/commands/echo.js +2 -0
  60. package/dist/commands/env.d.ts +1 -0
  61. package/dist/commands/env.d.ts.map +1 -1
  62. package/dist/commands/env.js +6 -14
  63. package/dist/commands/export.d.ts.map +1 -1
  64. package/dist/commands/export.js +11 -21
  65. package/dist/commands/find.d.ts.map +1 -1
  66. package/dist/commands/find.js +2 -0
  67. package/dist/commands/grep.d.ts.map +1 -1
  68. package/dist/commands/grep.js +4 -7
  69. package/dist/commands/groups.d.ts +3 -0
  70. package/dist/commands/groups.d.ts.map +1 -0
  71. package/dist/commands/groups.js +12 -0
  72. package/dist/commands/gzip.d.ts +4 -0
  73. package/dist/commands/gzip.d.ts.map +1 -0
  74. package/dist/commands/gzip.js +40 -0
  75. package/dist/commands/head.d.ts.map +1 -1
  76. package/dist/commands/head.js +2 -0
  77. package/dist/commands/help.d.ts +1 -1
  78. package/dist/commands/help.d.ts.map +1 -1
  79. package/dist/commands/help.js +66 -3
  80. package/dist/commands/hostname.d.ts.map +1 -1
  81. package/dist/commands/hostname.js +2 -0
  82. package/dist/commands/htop.d.ts.map +1 -1
  83. package/dist/commands/htop.js +2 -0
  84. package/dist/commands/id.d.ts +3 -0
  85. package/dist/commands/id.d.ts.map +1 -0
  86. package/dist/commands/id.js +14 -0
  87. package/dist/commands/index.d.ts +5 -2
  88. package/dist/commands/index.d.ts.map +1 -1
  89. package/dist/commands/index.js +89 -62
  90. package/dist/commands/kill.d.ts +3 -0
  91. package/dist/commands/kill.d.ts.map +1 -0
  92. package/dist/commands/kill.js +13 -0
  93. package/dist/commands/ln.d.ts.map +1 -1
  94. package/dist/commands/ln.js +2 -0
  95. package/dist/commands/ls.d.ts.map +1 -1
  96. package/dist/commands/ls.js +2 -0
  97. package/dist/commands/mkdir.d.ts.map +1 -1
  98. package/dist/commands/mkdir.js +2 -0
  99. package/dist/commands/mv.d.ts.map +1 -1
  100. package/dist/commands/mv.js +2 -0
  101. package/dist/commands/nano.d.ts.map +1 -1
  102. package/dist/commands/nano.js +2 -0
  103. package/dist/commands/neofetch.d.ts.map +1 -1
  104. package/dist/commands/neofetch.js +2 -0
  105. package/dist/commands/passwd.d.ts.map +1 -1
  106. package/dist/commands/passwd.js +2 -0
  107. package/dist/commands/ping.d.ts +3 -0
  108. package/dist/commands/ping.d.ts.map +1 -0
  109. package/dist/commands/ping.js +18 -0
  110. package/dist/commands/ps.d.ts +3 -0
  111. package/dist/commands/ps.d.ts.map +1 -0
  112. package/dist/commands/ps.js +17 -0
  113. package/dist/commands/pwd.d.ts.map +1 -1
  114. package/dist/commands/pwd.js +2 -0
  115. package/dist/commands/rm.d.ts.map +1 -1
  116. package/dist/commands/rm.js +2 -0
  117. package/dist/commands/sed.d.ts +3 -0
  118. package/dist/commands/sed.d.ts.map +1 -0
  119. package/dist/commands/sed.js +47 -0
  120. package/dist/commands/set.d.ts +3 -0
  121. package/dist/commands/set.d.ts.map +1 -1
  122. package/dist/commands/set.js +19 -46
  123. package/dist/commands/sh.d.ts +0 -1
  124. package/dist/commands/sh.d.ts.map +1 -1
  125. package/dist/commands/sh.js +229 -35
  126. package/dist/commands/sleep.d.ts +3 -0
  127. package/dist/commands/sleep.d.ts.map +1 -0
  128. package/dist/commands/sleep.js +13 -0
  129. package/dist/commands/sort.d.ts +3 -0
  130. package/dist/commands/sort.d.ts.map +1 -0
  131. package/dist/commands/sort.js +37 -0
  132. package/dist/commands/su.d.ts.map +1 -1
  133. package/dist/commands/su.js +2 -0
  134. package/dist/commands/sudo.d.ts.map +1 -1
  135. package/dist/commands/sudo.js +2 -0
  136. package/dist/commands/tail.d.ts.map +1 -1
  137. package/dist/commands/tail.js +2 -0
  138. package/dist/commands/tar.d.ts +3 -0
  139. package/dist/commands/tar.d.ts.map +1 -0
  140. package/dist/commands/tar.js +64 -0
  141. package/dist/commands/tee.d.ts +3 -0
  142. package/dist/commands/tee.d.ts.map +1 -0
  143. package/dist/commands/tee.js +29 -0
  144. package/dist/commands/touch.d.ts.map +1 -1
  145. package/dist/commands/touch.js +2 -0
  146. package/dist/commands/tr.d.ts +3 -0
  147. package/dist/commands/tr.d.ts.map +1 -0
  148. package/dist/commands/tr.js +24 -0
  149. package/dist/commands/tree.d.ts.map +1 -1
  150. package/dist/commands/tree.js +2 -0
  151. package/dist/commands/uname.d.ts +3 -0
  152. package/dist/commands/uname.d.ts.map +1 -0
  153. package/dist/commands/uname.js +21 -0
  154. package/dist/commands/uniq.d.ts +3 -0
  155. package/dist/commands/uniq.d.ts.map +1 -0
  156. package/dist/commands/uniq.js +33 -0
  157. package/dist/commands/unset.d.ts.map +1 -1
  158. package/dist/commands/unset.js +6 -10
  159. package/dist/commands/wc.d.ts.map +1 -1
  160. package/dist/commands/wc.js +2 -0
  161. package/dist/commands/wget.d.ts.map +1 -1
  162. package/dist/commands/wget.js +2 -0
  163. package/dist/commands/who.d.ts.map +1 -1
  164. package/dist/commands/who.js +2 -0
  165. package/dist/commands/whoami.d.ts.map +1 -1
  166. package/dist/commands/whoami.js +2 -0
  167. package/dist/commands/xargs.d.ts +3 -0
  168. package/dist/commands/xargs.d.ts.map +1 -0
  169. package/dist/commands/xargs.js +16 -0
  170. package/dist/types/commands.d.ts +13 -0
  171. package/dist/types/commands.d.ts.map +1 -1
  172. package/dist/types/pipeline.d.ts +20 -0
  173. package/dist/types/pipeline.d.ts.map +1 -1
  174. package/package.json +3 -3
  175. package/src/SSHMimic/exec.ts +2 -2
  176. package/src/SSHMimic/executor.ts +95 -98
  177. package/src/SSHMimic/index.ts +15 -49
  178. package/src/SSHMimic/sftp.ts +15 -0
  179. package/src/VirtualFileSystem/index.ts +27 -75
  180. package/src/VirtualShell/shell.ts +19 -2
  181. package/src/VirtualShell/shellParser.ts +202 -168
  182. package/src/VirtualUserManager/index.ts +2 -7
  183. package/src/commands/adduser.ts +2 -0
  184. package/src/commands/awk.ts +30 -0
  185. package/src/commands/base64.ts +18 -0
  186. package/src/commands/cat.ts +2 -0
  187. package/src/commands/cd.ts +2 -0
  188. package/src/commands/chmod.ts +2 -0
  189. package/src/commands/clear.ts +4 -1
  190. package/src/commands/cp.ts +2 -0
  191. package/src/commands/curl.ts +2 -0
  192. package/src/commands/cut.ts +29 -0
  193. package/src/commands/date.ts +24 -0
  194. package/src/commands/deluser.ts +2 -0
  195. package/src/commands/df.ts +18 -0
  196. package/src/commands/diff.ts +29 -0
  197. package/src/commands/du.ts +39 -0
  198. package/src/commands/echo.ts +2 -0
  199. package/src/commands/env.ts +7 -16
  200. package/src/commands/export.ts +11 -24
  201. package/src/commands/find.ts +2 -0
  202. package/src/commands/grep.ts +4 -7
  203. package/src/commands/groups.ts +14 -0
  204. package/src/commands/gzip.ts +31 -0
  205. package/src/commands/head.ts +2 -0
  206. package/src/commands/help.ts +72 -3
  207. package/src/commands/hostname.ts +2 -0
  208. package/src/commands/htop.ts +2 -0
  209. package/src/commands/id.ts +16 -0
  210. package/src/commands/index.ts +98 -99
  211. package/src/commands/kill.ts +14 -0
  212. package/src/commands/ln.ts +2 -0
  213. package/src/commands/ls.ts +2 -0
  214. package/src/commands/mkdir.ts +2 -0
  215. package/src/commands/mv.ts +2 -0
  216. package/src/commands/nano.ts +2 -0
  217. package/src/commands/neofetch.ts +2 -0
  218. package/src/commands/passwd.ts +2 -0
  219. package/src/commands/ping.ts +20 -0
  220. package/src/commands/ps.ts +19 -0
  221. package/src/commands/pwd.ts +2 -0
  222. package/src/commands/rm.ts +2 -0
  223. package/src/commands/sed.ts +45 -0
  224. package/src/commands/set.ts +19 -50
  225. package/src/commands/sh.ts +193 -43
  226. package/src/commands/sleep.ts +14 -0
  227. package/src/commands/sort.ts +37 -0
  228. package/src/commands/su.ts +2 -0
  229. package/src/commands/sudo.ts +2 -0
  230. package/src/commands/tail.ts +2 -0
  231. package/src/commands/tar.ts +58 -0
  232. package/src/commands/tee.ts +25 -0
  233. package/src/commands/touch.ts +2 -0
  234. package/src/commands/tr.ts +24 -0
  235. package/src/commands/tree.ts +2 -0
  236. package/src/commands/uname.ts +20 -0
  237. package/src/commands/uniq.ts +28 -0
  238. package/src/commands/unset.ts +5 -12
  239. package/src/commands/wc.ts +2 -0
  240. package/src/commands/wget.ts +2 -0
  241. package/src/commands/who.ts +2 -0
  242. package/src/commands/whoami.ts +2 -0
  243. package/src/commands/xargs.ts +17 -0
  244. package/src/types/commands.ts +14 -0
  245. package/src/types/pipeline.ts +23 -0
  246. package/standalone.js +92 -64
  247. package/standalone.js.map +4 -4
  248. package/tests/users.test.ts +5 -34
@@ -233,24 +233,15 @@ class VirtualFileSystem extends EventEmitter {
233
233
  if (node.type === "file") {
234
234
  const f = node;
235
235
  return {
236
- type: "file",
237
- name,
238
- path: normalized,
239
- mode: f.mode,
240
- createdAt: f.createdAt,
241
- updatedAt: f.updatedAt,
242
- compressed: f.compressed,
243
- size: f.content.length,
236
+ type: "file", name, path: normalized, mode: f.mode,
237
+ createdAt: f.createdAt, updatedAt: f.updatedAt,
238
+ compressed: f.compressed, size: f.content.length,
244
239
  };
245
240
  }
246
241
  const d = node;
247
242
  return {
248
- type: "directory",
249
- name,
250
- path: normalized,
251
- mode: d.mode,
252
- createdAt: d.createdAt,
253
- updatedAt: d.updatedAt,
243
+ type: "directory", name, path: normalized, mode: d.mode,
244
+ createdAt: d.createdAt, updatedAt: d.updatedAt,
254
245
  childrenCount: d.children.size,
255
246
  };
256
247
  }
@@ -285,8 +276,7 @@ class VirtualFileSystem extends EventEmitter {
285
276
  lines.push(`${connector}${name}`);
286
277
  if (child.type === "directory") {
287
278
  const sub = this.renderTreeLines(child, "")
288
- .split("\n")
289
- .slice(1)
279
+ .split("\n").slice(1)
290
280
  .map((l) => `${nextPrefix}${l}`);
291
281
  lines.push(...sub);
292
282
  }
@@ -341,19 +331,14 @@ class VirtualFileSystem extends EventEmitter {
341
331
  : targetPath;
342
332
  const { parent, name } = getParentDirectory(this.root, normalizedLink, true, (p) => this.mkdirRecursive(p, 0o755));
343
333
  const symNode = {
344
- type: "file",
345
- name,
334
+ type: "file", name,
346
335
  content: Buffer.from(normalizedTarget, "utf8"),
347
336
  mode: 0o120777,
348
337
  compressed: false,
349
- createdAt: new Date(),
350
- updatedAt: new Date(),
338
+ createdAt: new Date(), updatedAt: new Date(),
351
339
  };
352
340
  parent.children.set(name, symNode);
353
- this.emit("symlink:create", {
354
- link: normalizedLink,
355
- target: normalizedTarget,
356
- });
341
+ this.emit("symlink:create", { link: normalizedLink, target: normalizedTarget });
357
342
  }
358
343
  /** Returns true when the path is a symbolic link node. */
359
344
  isSymlink(targetPath) {
@@ -441,9 +426,7 @@ class VirtualFileSystem extends EventEmitter {
441
426
  : this.serializeDir(child));
442
427
  }
443
428
  return {
444
- type: "directory",
445
- name: dir.name,
446
- mode: dir.mode,
429
+ type: "directory", name: dir.name, mode: dir.mode,
447
430
  createdAt: dir.createdAt.toISOString(),
448
431
  updatedAt: dir.updatedAt.toISOString(),
449
432
  children,
@@ -451,9 +434,7 @@ class VirtualFileSystem extends EventEmitter {
451
434
  }
452
435
  serializeFile(file) {
453
436
  return {
454
- type: "file",
455
- name: file.name,
456
- mode: file.mode,
437
+ type: "file", name: file.name, mode: file.mode,
457
438
  createdAt: file.createdAt.toISOString(),
458
439
  updatedAt: file.updatedAt.toISOString(),
459
440
  compressed: file.compressed,
@@ -488,9 +469,7 @@ class VirtualFileSystem extends EventEmitter {
488
469
  }
489
470
  deserializeDir(snap, name) {
490
471
  const dir = {
491
- type: "directory",
492
- name,
493
- mode: snap.mode,
472
+ type: "directory", name, mode: snap.mode,
494
473
  createdAt: new Date(snap.createdAt),
495
474
  updatedAt: new Date(snap.updatedAt),
496
475
  children: new Map(),
@@ -499,9 +478,7 @@ class VirtualFileSystem extends EventEmitter {
499
478
  if (child.type === "file") {
500
479
  const f = child;
501
480
  dir.children.set(f.name, {
502
- type: "file",
503
- name: f.name,
504
- mode: f.mode,
481
+ type: "file", name: f.name, mode: f.mode,
505
482
  createdAt: new Date(f.createdAt),
506
483
  updatedAt: new Date(f.updatedAt),
507
484
  compressed: f.compressed,
@@ -1 +1 @@
1
- {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/VirtualShell/shell.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,GAAG,CAAC;AAMvD,OAAO,EAGN,KAAK,YAAY,EAEjB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAmBpD,wBAAgB,UAAU,CACzB,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,aAAa,oBAAY,EACzB,YAAY,EAAE,YAAY,YAAyB,EACnD,KAAK,EAAE,YAAY,GACjB,IAAI,CA8lBN"}
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/VirtualShell/shell.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,GAAG,CAAC;AAOvD,OAAO,EAGN,KAAK,YAAY,EAEjB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAmBpD,wBAAgB,UAAU,CACzB,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,aAAa,oBAAY,EACzB,YAAY,EAAE,YAAY,YAAyB,EACnD,KAAK,EAAE,YAAY,GACjB,IAAI,CA8mBN"}
@@ -1,6 +1,6 @@
1
1
  import { readFile, unlink, writeFile } from "node:fs/promises";
2
2
  import * as path from "node:path";
3
- import { getCommandNames, runCommand } from "../commands";
3
+ import { getCommandNames, makeDefaultEnv, runCommand } from "../commands";
4
4
  import { spawnHtopProcess, spawnNanoEditorProcess, } from "../modules/shellInteractive";
5
5
  import { getVisibleHtopPidList, resolvePath, toTtyLines, } from "../modules/shellRuntime";
6
6
  import { formatLoginDate } from "../SSHMimic/loginFormat";
@@ -12,6 +12,7 @@ export function startShell(properties, stream, authUser, hostname, sessionId, re
12
12
  let historyIndex = null;
13
13
  let historyDraft = "";
14
14
  let cwd = `/home/${authUser}`;
15
+ const shellEnv = makeDefaultEnv(authUser, hostname);
15
16
  let nanoSession = null;
16
17
  let pendingSudo = null;
17
18
  const buildCurrentPrompt = () => {
@@ -21,6 +22,22 @@ export function startShell(properties, stream, authUser, hostname, sessionId, re
21
22
  };
22
23
  const commandNames = Array.from(new Set(getCommandNames())).sort();
23
24
  console.log(`[${sessionId}] Shell started for user '${authUser}' at ${remoteAddress}`);
25
+ // Load .bashrc if it exists
26
+ void (async () => {
27
+ const bashrcPath = `/home/${authUser}/.bashrc`;
28
+ if (shell.vfs.exists(bashrcPath)) {
29
+ try {
30
+ const bashrc = shell.vfs.readFile(bashrcPath);
31
+ for (const line of bashrc.split("\n")) {
32
+ const l = line.trim();
33
+ if (!l || l.startsWith("#"))
34
+ continue;
35
+ await runCommand(l, authUser, hostname, "shell", cwd, shell, undefined, shellEnv);
36
+ }
37
+ }
38
+ catch { /* ignore bashrc errors */ }
39
+ }
40
+ })();
24
41
  function renderLine() {
25
42
  const prompt = buildCurrentPrompt();
26
43
  stream.write(`\r${prompt}${lineBuffer}\u001b[K`);
@@ -404,7 +421,7 @@ export function startShell(properties, stream, authUser, hostname, sessionId, re
404
421
  historyDraft = "";
405
422
  stream.write("\r\n");
406
423
  if (line.length > 0) {
407
- const result = await Promise.resolve(runCommand(line, authUser, hostname, "shell", cwd, shell));
424
+ const result = await Promise.resolve(runCommand(line, authUser, hostname, "shell", cwd, shell, undefined, shellEnv));
408
425
  pushHistory(line);
409
426
  if (result.openEditor) {
410
427
  await startNanoEditor(result.openEditor.targetPath, result.openEditor.initialContent, result.openEditor.tempPath);
@@ -1,4 +1,22 @@
1
- import type { Pipeline } from "../types/pipeline";
2
- /** Parse a shell command line into a structured pipeline */
1
+ import type { Pipeline, Script } from "../types/pipeline";
2
+ /**
3
+ * Parse a shell input line into a Script (sequence of statements connected
4
+ * by && / || / ;). Each statement contains one Pipeline (commands connected
5
+ * by |).
6
+ */
7
+ export declare function parseScript(rawInput: string): Script;
8
+ /** Legacy compat: parse a single pipeline (no &&/||/;) */
3
9
  export declare function parseShellPipeline(rawInput: string): Pipeline;
10
+ /**
11
+ * Expand ~ and $VAR / ${VAR} / ${VAR:-default} / $(cmd placeholder) in a
12
+ * token, given the current env vars and home path.
13
+ * Command substitution $(…) is NOT executed here — it's left as a marker so
14
+ * the executor can handle it.
15
+ */
16
+ export declare function expandToken(token: string, env: Record<string, string>, authUser: string, lastExitCode?: number): string;
17
+ /**
18
+ * Expand glob patterns (*, ?, [abc]) against a list of entries.
19
+ * Returns the original pattern if no match.
20
+ */
21
+ export declare function expandGlob(pattern: string, entries: string[]): string[];
4
22
  //# sourceMappingURL=shellParser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shellParser.d.ts","sourceRoot":"","sources":["../../src/VirtualShell/shellParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,mBAAmB,CAAC;AAEnE,4DAA4D;AAC5D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAkC7D"}
1
+ {"version":3,"file":"shellParser.d.ts","sourceRoot":"","sources":["../../src/VirtualShell/shellParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,EAAwB,MAAM,mBAAmB,CAAC;AAIjG;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED,0DAA0D;AAC1D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAS7D;AAID;;;;;GAKG;AACH,wBAAgB,WAAW,CAC1B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,QAAQ,EAAE,MAAM,EAChB,YAAY,SAAI,GACd,MAAM,CA4BR;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAKvE"}
@@ -1,91 +1,225 @@
1
- /** Parse a shell command line into a structured pipeline */
1
+ // ── Public API ───────────────────────────────────────────────────────────────
2
+ /**
3
+ * Parse a shell input line into a Script (sequence of statements connected
4
+ * by && / || / ;). Each statement contains one Pipeline (commands connected
5
+ * by |).
6
+ */
7
+ export function parseScript(rawInput) {
8
+ const trimmed = rawInput.trim();
9
+ if (!trimmed)
10
+ return { statements: [], isValid: true };
11
+ try {
12
+ const statements = parseStatements(trimmed);
13
+ return { statements, isValid: true };
14
+ }
15
+ catch (e) {
16
+ return { statements: [], isValid: false, error: e.message };
17
+ }
18
+ }
19
+ /** Legacy compat: parse a single pipeline (no &&/||/;) */
2
20
  export function parseShellPipeline(rawInput) {
3
21
  const trimmed = rawInput.trim();
4
- if (!trimmed) {
22
+ if (!trimmed)
5
23
  return { commands: [], isValid: true };
24
+ try {
25
+ const commands = parsePipeline(trimmed);
26
+ return { commands, isValid: true };
6
27
  }
7
- const commands = [];
8
- const tokenized = tokenizePipeline(trimmed);
9
- if (tokenized.error) {
10
- return {
11
- commands: [],
12
- isValid: false,
13
- error: tokenized.error,
14
- };
28
+ catch (e) {
29
+ return { commands: [], isValid: false, error: e.message };
15
30
  }
16
- const pipeTokens = tokenized.tokens;
17
- for (const token of pipeTokens) {
18
- const cmd = parseCommandWithRedirections(token);
19
- if (!cmd.isValid) {
20
- return {
21
- commands: [],
22
- isValid: false,
23
- error: cmd.error,
24
- };
25
- }
26
- if (cmd.command) {
27
- commands.push(cmd.command);
31
+ }
32
+ // ── Variable & tilde expansion ────────────────────────────────────────────────
33
+ /**
34
+ * Expand ~ and $VAR / ${VAR} / ${VAR:-default} / $(cmd placeholder) in a
35
+ * token, given the current env vars and home path.
36
+ * Command substitution $(…) is NOT executed here — it's left as a marker so
37
+ * the executor can handle it.
38
+ */
39
+ export function expandToken(token, env, authUser, lastExitCode = 0) {
40
+ // tilde expansion
41
+ token = token.replace(/^~(\/|$)/, `/home/${authUser}$1`);
42
+ // $? special var
43
+ token = token.replace(/\$\?/g, String(lastExitCode));
44
+ // $$ PID (mock)
45
+ token = token.replace(/\$\$/g, "1");
46
+ // $# argc (0 for interactive)
47
+ token = token.replace(/\$#/g, "0");
48
+ // ${VAR:-default} and ${VAR:+value}
49
+ token = token.replace(/\$\{([^}:]+):-([^}]*)\}/g, (_, name, def) => env[name] ?? def);
50
+ token = token.replace(/\$\{([^}:]+):\+([^}]*)\}/g, (_, name, val) => env[name] ? val : "");
51
+ // ${VAR}
52
+ token = token.replace(/\$\{([^}]+)\}/g, (_, name) => env[name] ?? "");
53
+ // $VAR (greedy: match longest valid identifier)
54
+ token = token.replace(/\$([A-Za-z_][A-Za-z0-9_]*)/g, (_, name) => env[name] ?? "");
55
+ return token;
56
+ }
57
+ /**
58
+ * Expand glob patterns (*, ?, [abc]) against a list of entries.
59
+ * Returns the original pattern if no match.
60
+ */
61
+ export function expandGlob(pattern, entries) {
62
+ if (!/[*?[]/.test(pattern))
63
+ return [pattern];
64
+ const regex = globToRegex(pattern);
65
+ const matches = entries.filter((e) => regex.test(e));
66
+ return matches.length > 0 ? matches.sort() : [pattern];
67
+ }
68
+ function globToRegex(pattern) {
69
+ let re = "^";
70
+ for (let i = 0; i < pattern.length; i++) {
71
+ const c = pattern[i];
72
+ if (c === "*")
73
+ re += ".*";
74
+ else if (c === "?")
75
+ re += ".";
76
+ else if (c === "[") {
77
+ const close = pattern.indexOf("]", i + 1);
78
+ if (close === -1)
79
+ re += "\\[";
80
+ else {
81
+ re += `[${pattern.slice(i + 1, close)}]`;
82
+ i = close;
83
+ }
28
84
  }
85
+ else
86
+ re += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
29
87
  }
30
- return { commands, isValid: true };
88
+ return new RegExp(`${re}$`);
31
89
  }
32
- /** Tokenize input by pipes, respecting quoted strings */
33
- function tokenizePipeline(input) {
34
- const tokens = [];
90
+ // ── Internal parser ───────────────────────────────────────────────────────────
91
+ function parseStatements(input) {
92
+ // Split by ;, &&, || — respecting quotes and parens
93
+ const segments = splitByLogicalOps(input);
94
+ const statements = [];
95
+ for (const seg of segments) {
96
+ const commands = parsePipeline(seg.text.trim());
97
+ const stmt = { pipeline: { commands, isValid: true } };
98
+ if (seg.op)
99
+ stmt.op = seg.op;
100
+ statements.push(stmt);
101
+ }
102
+ return statements;
103
+ }
104
+ function splitByLogicalOps(input) {
105
+ const segments = [];
35
106
  let current = "";
36
- let inQuotes = false;
37
- let quoteChar = "";
107
+ let depth = 0; // parens/subshell depth
108
+ let inQ = false;
109
+ let qChar = "";
38
110
  let i = 0;
111
+ const flush = (op) => {
112
+ if (current.trim())
113
+ segments.push({ text: current, op });
114
+ current = "";
115
+ };
39
116
  while (i < input.length) {
40
117
  const ch = input[i];
41
- if ((ch === '"' || ch === "'") && (i === 0 || input[i - 1] !== "\\")) {
42
- if (!inQuotes) {
43
- inQuotes = true;
44
- quoteChar = ch;
45
- }
46
- else if (ch === quoteChar) {
47
- inQuotes = false;
48
- }
118
+ const ch2 = input.slice(i, i + 2);
119
+ if ((ch === '"' || ch === "'") && !inQ) {
120
+ inQ = true;
121
+ qChar = ch;
49
122
  current += ch;
50
123
  i++;
124
+ continue;
51
125
  }
52
- else if (ch === "|" && !inQuotes) {
53
- if (!current.trim()) {
54
- return {
55
- tokens: [],
56
- error: "Syntax error near unexpected token '|'",
57
- };
58
- }
59
- tokens.push(current.trim());
60
- current = "";
126
+ if (inQ && ch === qChar) {
127
+ inQ = false;
128
+ current += ch;
61
129
  i++;
130
+ continue;
62
131
  }
63
- else {
132
+ if (inQ) {
64
133
  current += ch;
65
134
  i++;
135
+ continue;
66
136
  }
137
+ if (ch === "(") {
138
+ depth++;
139
+ current += ch;
140
+ i++;
141
+ continue;
142
+ }
143
+ if (ch === ")") {
144
+ depth--;
145
+ current += ch;
146
+ i++;
147
+ continue;
148
+ }
149
+ if (depth > 0) {
150
+ current += ch;
151
+ i++;
152
+ continue;
153
+ }
154
+ if (ch2 === "&&") {
155
+ flush("&&");
156
+ i += 2;
157
+ continue;
158
+ }
159
+ if (ch2 === "||") {
160
+ flush("||");
161
+ i += 2;
162
+ continue;
163
+ }
164
+ if (ch === ";") {
165
+ flush(";");
166
+ i++;
167
+ continue;
168
+ }
169
+ current += ch;
170
+ i++;
67
171
  }
68
- if (inQuotes) {
69
- return {
70
- tokens: [],
71
- error: "Syntax error: unterminated quote",
72
- };
73
- }
74
- if (!current.trim()) {
75
- return {
76
- tokens: [],
77
- error: "Syntax error near unexpected token '|'",
78
- };
172
+ flush();
173
+ return segments;
174
+ }
175
+ function parsePipeline(input) {
176
+ const pipeTokens = splitByPipe(input);
177
+ return pipeTokens.map(parseCommandWithRedirections);
178
+ }
179
+ function splitByPipe(input) {
180
+ const tokens = [];
181
+ let current = "";
182
+ let inQ = false;
183
+ let qChar = "";
184
+ for (let i = 0; i < input.length; i++) {
185
+ const ch = input[i];
186
+ if ((ch === '"' || ch === "'") && !inQ) {
187
+ inQ = true;
188
+ qChar = ch;
189
+ current += ch;
190
+ continue;
191
+ }
192
+ if (inQ && ch === qChar) {
193
+ inQ = false;
194
+ current += ch;
195
+ continue;
196
+ }
197
+ if (inQ) {
198
+ current += ch;
199
+ continue;
200
+ }
201
+ // || was already consumed at statement level, bare | is pipe
202
+ if (ch === "|" && input[i + 1] !== "|") {
203
+ if (!current.trim())
204
+ throw new Error("Syntax error near unexpected token '|'");
205
+ tokens.push(current.trim());
206
+ current = "";
207
+ }
208
+ else {
209
+ current += ch;
210
+ }
79
211
  }
80
- tokens.push(current.trim());
81
- return { tokens };
212
+ const tail = current.trim();
213
+ if (!tail && tokens.length > 0)
214
+ throw new Error("Syntax error near unexpected token '|'");
215
+ if (tail)
216
+ tokens.push(tail);
217
+ return tokens;
82
218
  }
83
- /** Parse a single command with its redirections (>, >>, <) */
84
219
  function parseCommandWithRedirections(token) {
85
220
  const parts = tokenizeCommand(token);
86
- if (parts.length === 0) {
87
- return { isValid: true };
88
- }
221
+ if (parts.length === 0)
222
+ return { name: "", args: [] };
89
223
  const cmdParts = [];
90
224
  let inputFile;
91
225
  let outputFile;
@@ -95,35 +229,23 @@ function parseCommandWithRedirections(token) {
95
229
  const part = parts[i];
96
230
  if (part === "<") {
97
231
  i++;
98
- if (i >= parts.length) {
99
- return {
100
- isValid: false,
101
- error: "Syntax error: expected filename after <",
102
- };
103
- }
232
+ if (i >= parts.length)
233
+ throw new Error("Syntax error: expected filename after <");
104
234
  inputFile = parts[i];
105
235
  i++;
106
236
  }
107
237
  else if (part === ">>") {
108
238
  i++;
109
- if (i >= parts.length) {
110
- return {
111
- isValid: false,
112
- error: "Syntax error: expected filename after >>",
113
- };
114
- }
239
+ if (i >= parts.length)
240
+ throw new Error("Syntax error: expected filename after >>");
115
241
  outputFile = parts[i];
116
242
  appendOutput = true;
117
243
  i++;
118
244
  }
119
245
  else if (part === ">") {
120
246
  i++;
121
- if (i >= parts.length) {
122
- return {
123
- isValid: false,
124
- error: "Syntax error: expected filename after >",
125
- };
126
- }
247
+ if (i >= parts.length)
248
+ throw new Error("Syntax error: expected filename after >");
127
249
  outputFile = parts[i];
128
250
  appendOutput = false;
129
251
  i++;
@@ -133,55 +255,44 @@ function parseCommandWithRedirections(token) {
133
255
  i++;
134
256
  }
135
257
  }
136
- if (cmdParts.length === 0) {
137
- return { isValid: true };
138
- }
139
- const name = cmdParts[0].toLowerCase();
140
- const args = cmdParts.slice(1);
141
- return {
142
- command: {
143
- name,
144
- args,
145
- inputFile,
146
- outputFile,
147
- appendOutput,
148
- },
149
- isValid: true,
150
- };
258
+ const name = (cmdParts[0] ?? "").toLowerCase();
259
+ return { name, args: cmdParts.slice(1), inputFile, outputFile, appendOutput };
151
260
  }
152
- /** Tokenize a command, respecting quotes and handling >> vs > */
153
261
  function tokenizeCommand(input) {
154
262
  const tokens = [];
155
263
  let current = "";
156
- let inQuotes = false;
157
- let quoteChar = "";
264
+ let inQ = false;
265
+ let qChar = "";
158
266
  let i = 0;
159
267
  while (i < input.length) {
160
268
  const ch = input[i];
161
269
  const next = input[i + 1];
162
- // Handle quotes
163
- if ((ch === '"' || ch === "'") && (i === 0 || input[i - 1] !== "\\")) {
164
- if (!inQuotes) {
165
- inQuotes = true;
166
- quoteChar = ch;
167
- }
168
- else if (ch === quoteChar) {
169
- inQuotes = false;
170
- quoteChar = "";
171
- }
172
- else {
173
- current += ch;
174
- }
270
+ if ((ch === '"' || ch === "'") && !inQ) {
271
+ inQ = true;
272
+ qChar = ch;
273
+ i++;
274
+ continue;
275
+ }
276
+ if (inQ && ch === qChar) {
277
+ inQ = false;
278
+ qChar = "";
175
279
  i++;
280
+ continue;
176
281
  }
177
- else if (ch === " " && !inQuotes) {
282
+ if (inQ) {
283
+ current += ch;
284
+ i++;
285
+ continue;
286
+ }
287
+ if (ch === " ") {
178
288
  if (current) {
179
289
  tokens.push(current);
180
290
  current = "";
181
291
  }
182
292
  i++;
293
+ continue;
183
294
  }
184
- else if ((ch === ">" || ch === "<") && !inQuotes) {
295
+ if ((ch === ">" || ch === "<") && !inQ) {
185
296
  if (current) {
186
297
  tokens.push(current);
187
298
  current = "";
@@ -194,14 +305,12 @@ function tokenizeCommand(input) {
194
305
  tokens.push(ch);
195
306
  i++;
196
307
  }
308
+ continue;
197
309
  }
198
- else {
199
- current += ch;
200
- i++;
201
- }
310
+ current += ch;
311
+ i++;
202
312
  }
203
- if (current) {
313
+ if (current)
204
314
  tokens.push(current);
205
- }
206
315
  return tokens;
207
316
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/VirtualUserManager/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/VirtualUserManager/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"adduser.d.ts","sourceRoot":"","sources":["../../src/commands/adduser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,cAAc,EAAE,WAmB5B,CAAC"}
1
+ {"version":3,"file":"adduser.d.ts","sourceRoot":"","sources":["../../src/commands/adduser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,cAAc,EAAE,WAqB5B,CAAC"}
@@ -1,5 +1,7 @@
1
1
  export const adduserCommand = {
2
2
  name: "adduser",
3
+ description: "Add a new user",
4
+ category: "users",
3
5
  params: ["<username> <password>"],
4
6
  run: async ({ authUser, shell, args }) => {
5
7
  if (authUser !== "root") {
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const awkCommand: ShellModule;
3
+ //# sourceMappingURL=awk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"awk.d.ts","sourceRoot":"","sources":["../../src/commands/awk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,UAAU,EAAE,WA0BxB,CAAC"}