typescript-virtual-container 1.1.1 → 1.1.2

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 (185) hide show
  1. package/README.md +1 -1
  2. package/dist/SSHClient/index.d.ts +138 -0
  3. package/dist/SSHClient/index.d.ts.map +1 -0
  4. package/dist/SSHClient/index.js +216 -0
  5. package/dist/SSHMimic/exec.d.ts +4 -0
  6. package/dist/SSHMimic/exec.d.ts.map +1 -0
  7. package/dist/SSHMimic/exec.js +21 -0
  8. package/dist/SSHMimic/executor.d.ts +9 -0
  9. package/dist/SSHMimic/executor.d.ts.map +1 -0
  10. package/dist/SSHMimic/executor.js +131 -0
  11. package/dist/SSHMimic/hostKey.d.ts +2 -0
  12. package/dist/SSHMimic/hostKey.d.ts.map +1 -0
  13. package/dist/SSHMimic/hostKey.js +17 -0
  14. package/dist/SSHMimic/index.d.ts +39 -0
  15. package/dist/SSHMimic/index.d.ts.map +1 -0
  16. package/dist/SSHMimic/index.js +113 -0
  17. package/dist/SSHMimic/loginFormat.d.ts +2 -0
  18. package/dist/SSHMimic/loginFormat.d.ts.map +1 -0
  19. package/dist/SSHMimic/loginFormat.js +10 -0
  20. package/dist/SSHMimic/prompt.d.ts +2 -0
  21. package/dist/SSHMimic/prompt.d.ts.map +1 -0
  22. package/dist/SSHMimic/prompt.js +9 -0
  23. package/dist/VirtualFileSystem/archive.d.ts +5 -0
  24. package/dist/VirtualFileSystem/archive.d.ts.map +1 -0
  25. package/dist/VirtualFileSystem/archive.js +56 -0
  26. package/dist/VirtualFileSystem/index.d.ts +131 -0
  27. package/dist/VirtualFileSystem/index.d.ts.map +1 -0
  28. package/dist/VirtualFileSystem/index.js +355 -0
  29. package/dist/VirtualFileSystem/internalTypes.d.ts +18 -0
  30. package/dist/VirtualFileSystem/internalTypes.d.ts.map +1 -0
  31. package/dist/VirtualFileSystem/internalTypes.js +0 -0
  32. package/dist/VirtualFileSystem/path.d.ts +9 -0
  33. package/dist/VirtualFileSystem/path.d.ts.map +1 -0
  34. package/dist/VirtualFileSystem/path.js +49 -0
  35. package/dist/VirtualFileSystem/snapshot.d.ts +5 -0
  36. package/dist/VirtualFileSystem/snapshot.d.ts.map +1 -0
  37. package/dist/VirtualFileSystem/snapshot.js +59 -0
  38. package/dist/VirtualFileSystem/tree.d.ts +3 -0
  39. package/dist/VirtualFileSystem/tree.d.ts.map +1 -0
  40. package/dist/VirtualFileSystem/tree.js +19 -0
  41. package/dist/VirtualShell/index.d.ts +86 -0
  42. package/dist/VirtualShell/index.d.ts.map +1 -0
  43. package/dist/VirtualShell/index.js +129 -0
  44. package/dist/VirtualShell/shell.d.ts +5 -0
  45. package/dist/VirtualShell/shell.d.ts.map +1 -0
  46. package/dist/VirtualShell/shell.js +473 -0
  47. package/dist/VirtualShell/shellParser.d.ts +4 -0
  48. package/dist/VirtualShell/shellParser.d.ts.map +1 -0
  49. package/dist/VirtualShell/shellParser.js +207 -0
  50. package/dist/VirtualUserManager/index.d.ts +168 -0
  51. package/dist/VirtualUserManager/index.d.ts.map +1 -0
  52. package/dist/VirtualUserManager/index.js +375 -0
  53. package/dist/commands/adduser.d.ts +3 -0
  54. package/dist/commands/adduser.d.ts.map +1 -0
  55. package/dist/commands/adduser.js +18 -0
  56. package/dist/commands/cat.d.ts +3 -0
  57. package/dist/commands/cat.d.ts.map +1 -0
  58. package/dist/commands/cat.js +15 -0
  59. package/dist/commands/cd.d.ts +3 -0
  60. package/dist/commands/cd.d.ts.map +1 -0
  61. package/dist/commands/cd.js +17 -0
  62. package/dist/commands/clear.d.ts +3 -0
  63. package/dist/commands/clear.d.ts.map +1 -0
  64. package/dist/commands/clear.js +5 -0
  65. package/dist/commands/command-helpers.d.ts +23 -0
  66. package/dist/commands/command-helpers.d.ts.map +1 -0
  67. package/dist/commands/command-helpers.js +139 -0
  68. package/dist/commands/curl.d.ts +3 -0
  69. package/dist/commands/curl.d.ts.map +1 -0
  70. package/dist/commands/curl.js +44 -0
  71. package/dist/commands/deluser.d.ts +3 -0
  72. package/dist/commands/deluser.d.ts.map +1 -0
  73. package/dist/commands/deluser.js +15 -0
  74. package/dist/commands/echo.d.ts +3 -0
  75. package/dist/commands/echo.d.ts.map +1 -0
  76. package/dist/commands/echo.js +22 -0
  77. package/dist/commands/env.d.ts +3 -0
  78. package/dist/commands/env.d.ts.map +1 -0
  79. package/dist/commands/env.js +18 -0
  80. package/dist/commands/exit.d.ts +3 -0
  81. package/dist/commands/exit.d.ts.map +1 -0
  82. package/dist/commands/exit.js +5 -0
  83. package/dist/commands/export.d.ts +3 -0
  84. package/dist/commands/export.d.ts.map +1 -0
  85. package/dist/commands/export.js +34 -0
  86. package/dist/commands/grep.d.ts +3 -0
  87. package/dist/commands/grep.d.ts.map +1 -0
  88. package/dist/commands/grep.js +69 -0
  89. package/dist/commands/help.d.ts +3 -0
  90. package/dist/commands/help.d.ts.map +1 -0
  91. package/dist/commands/help.js +7 -0
  92. package/dist/commands/helpers.d.ts +26 -0
  93. package/dist/commands/helpers.d.ts.map +1 -0
  94. package/dist/commands/helpers.js +160 -0
  95. package/dist/commands/hostname.d.ts +3 -0
  96. package/dist/commands/hostname.d.ts.map +1 -0
  97. package/dist/commands/hostname.js +5 -0
  98. package/dist/commands/htop.d.ts +3 -0
  99. package/dist/commands/htop.d.ts.map +1 -0
  100. package/dist/commands/htop.js +10 -0
  101. package/dist/commands/index.d.ts +8 -0
  102. package/dist/commands/index.d.ts.map +1 -0
  103. package/dist/commands/index.js +212 -0
  104. package/dist/commands/ls.d.ts +3 -0
  105. package/dist/commands/ls.d.ts.map +1 -0
  106. package/dist/commands/ls.js +47 -0
  107. package/dist/commands/mkdir.d.ts +3 -0
  108. package/dist/commands/mkdir.d.ts.map +1 -0
  109. package/dist/commands/mkdir.js +21 -0
  110. package/dist/commands/nano.d.ts +3 -0
  111. package/dist/commands/nano.d.ts.map +1 -0
  112. package/dist/commands/nano.js +27 -0
  113. package/dist/commands/neofetch.d.ts +3 -0
  114. package/dist/commands/neofetch.d.ts.map +1 -0
  115. package/dist/commands/neofetch.js +32 -0
  116. package/dist/commands/pwd.d.ts +3 -0
  117. package/dist/commands/pwd.d.ts.map +1 -0
  118. package/dist/commands/pwd.js +5 -0
  119. package/dist/commands/rm.d.ts +3 -0
  120. package/dist/commands/rm.d.ts.map +1 -0
  121. package/dist/commands/rm.js +29 -0
  122. package/dist/commands/set.d.ts +7 -0
  123. package/dist/commands/set.d.ts.map +1 -0
  124. package/dist/commands/set.js +64 -0
  125. package/dist/commands/sh.d.ts +4 -0
  126. package/dist/commands/sh.d.ts.map +1 -0
  127. package/dist/commands/sh.js +45 -0
  128. package/dist/commands/su.d.ts +3 -0
  129. package/dist/commands/su.d.ts.map +1 -0
  130. package/dist/commands/su.js +24 -0
  131. package/dist/commands/sudo.d.ts +3 -0
  132. package/dist/commands/sudo.d.ts.map +1 -0
  133. package/dist/commands/sudo.js +47 -0
  134. package/dist/commands/touch.d.ts +3 -0
  135. package/dist/commands/touch.d.ts.map +1 -0
  136. package/dist/commands/touch.js +18 -0
  137. package/dist/commands/tree.d.ts +3 -0
  138. package/dist/commands/tree.d.ts.map +1 -0
  139. package/dist/commands/tree.js +11 -0
  140. package/dist/commands/unset.d.ts +3 -0
  141. package/dist/commands/unset.d.ts.map +1 -0
  142. package/dist/commands/unset.js +15 -0
  143. package/dist/commands/wget.d.ts +3 -0
  144. package/dist/commands/wget.d.ts.map +1 -0
  145. package/dist/commands/wget.js +113 -0
  146. package/dist/commands/who.d.ts +3 -0
  147. package/dist/commands/who.d.ts.map +1 -0
  148. package/dist/commands/who.js +15 -0
  149. package/dist/commands/whoami.d.ts +3 -0
  150. package/dist/commands/whoami.d.ts.map +1 -0
  151. package/dist/commands/whoami.js +5 -0
  152. package/dist/index.d.ts +11 -0
  153. package/dist/index.d.ts.map +1 -0
  154. package/dist/index.js +7 -0
  155. package/dist/modules/neofetch.d.ts +19 -0
  156. package/dist/modules/neofetch.d.ts.map +1 -0
  157. package/dist/modules/neofetch.js +284 -0
  158. package/dist/modules/shellInteractive.d.ts +6 -0
  159. package/dist/modules/shellInteractive.d.ts.map +1 -0
  160. package/dist/modules/shellInteractive.js +26 -0
  161. package/dist/modules/shellRuntime.d.ts +11 -0
  162. package/dist/modules/shellRuntime.d.ts.map +1 -0
  163. package/dist/modules/shellRuntime.js +52 -0
  164. package/dist/standalone.d.ts +2 -0
  165. package/dist/standalone.d.ts.map +1 -0
  166. package/dist/standalone.js +25 -0
  167. package/dist/types/commands.d.ts +89 -0
  168. package/dist/types/commands.d.ts.map +1 -0
  169. package/dist/types/commands.js +0 -0
  170. package/dist/types/pipeline.d.ts +23 -0
  171. package/dist/types/pipeline.d.ts.map +1 -0
  172. package/dist/types/pipeline.js +0 -0
  173. package/dist/types/streams.d.ts +32 -0
  174. package/dist/types/streams.d.ts.map +1 -0
  175. package/dist/types/streams.js +0 -0
  176. package/dist/types/vfs.d.ts +71 -0
  177. package/dist/types/vfs.d.ts.map +1 -0
  178. package/dist/types/vfs.js +0 -0
  179. package/package.json +4 -2
  180. package/src/VirtualShell/shell.ts +3 -3
  181. package/src/commands/neofetch.ts +1 -1
  182. package/{modules → src/modules}/neofetch.ts +56 -51
  183. package/{modules → src/modules}/shellInteractive.ts +16 -4
  184. package/tsconfig.json +20 -8
  185. /package/{modules → src/modules}/shellRuntime.ts +0 -0
@@ -0,0 +1,44 @@
1
+ import { parseArgs } from "./command-helpers";
2
+ import { assertPathAccess, normalizeTerminalOutput, resolvePath, runHostCommand, } from "./helpers";
3
+ export const curlCommand = {
4
+ name: "curl",
5
+ params: ["[-o file] <url>"],
6
+ run: async ({ authUser, cwd, args, shell }) => {
7
+ const { flagsWithValues, positionals } = parseArgs(args, {
8
+ flagsWithValue: ["-o", "--output"],
9
+ });
10
+ const outputPath = flagsWithValues.get("-o") || flagsWithValues.get("--output") || null;
11
+ const url = positionals[0];
12
+ if (!url) {
13
+ return { stderr: "curl: missing URL", exitCode: 1 };
14
+ }
15
+ const passthroughArgs = outputPath
16
+ ? [...positionals, "-o", "-"]
17
+ : positionals;
18
+ const result = await runHostCommand("curl", passthroughArgs);
19
+ if (result.exitCode !== 0) {
20
+ return {
21
+ stderr: normalizeTerminalOutput(result.stderr || `curl: exited with code ${result.exitCode}`),
22
+ exitCode: result.exitCode,
23
+ };
24
+ }
25
+ if (outputPath) {
26
+ const target = resolvePath(cwd, outputPath);
27
+ assertPathAccess(authUser, target, "curl");
28
+ shell.writeFileAsUser(authUser, target, result.stdout);
29
+ return {
30
+ stderr: result.stderr
31
+ ? normalizeTerminalOutput(result.stderr)
32
+ : undefined,
33
+ exitCode: 0,
34
+ };
35
+ }
36
+ return {
37
+ stdout: result.stdout,
38
+ stderr: result.stderr
39
+ ? normalizeTerminalOutput(result.stderr)
40
+ : undefined,
41
+ exitCode: 0,
42
+ };
43
+ },
44
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const deluserCommand: ShellModule;
3
+ //# sourceMappingURL=deluser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deluser.d.ts","sourceRoot":"","sources":["../../src/commands/deluser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,cAAc,EAAE,WAgB5B,CAAC"}
@@ -0,0 +1,15 @@
1
+ export const deluserCommand = {
2
+ name: "deluser",
3
+ params: ["<username>"],
4
+ run: async ({ authUser, args, shell }) => {
5
+ if (authUser !== "root") {
6
+ return { stderr: "deluser: permission denied", exitCode: 1 };
7
+ }
8
+ const [username] = args;
9
+ if (!username) {
10
+ return { stderr: "deluser: usage: deluser <username>", exitCode: 1 };
11
+ }
12
+ await shell.users.deleteUser(username);
13
+ return { stdout: `deluser: user '${username}' deleted`, exitCode: 0 };
14
+ },
15
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const echoCommand: ShellModule;
3
+ //# sourceMappingURL=echo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echo.d.ts","sourceRoot":"","sources":["../../src/commands/echo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAUrD,eAAO,MAAM,WAAW,EAAE,WAgBzB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { parseArgs } from "./command-helpers";
2
+ import { getAllEnvVars } from "./set";
3
+ function expandEnvVars(input, env) {
4
+ return input.replace(/\$([A-Za-z_][A-Za-z0-9_]*)/g, (_, name) => {
5
+ return env[name] ?? "";
6
+ });
7
+ }
8
+ export const echoCommand = {
9
+ name: "echo",
10
+ params: ["[options] [text...]"],
11
+ run: ({ args, authUser, stdin }) => {
12
+ const { flags, positionals } = parseArgs(args, { flags: ["-n"] });
13
+ const newline = !flags.has("-n");
14
+ const rawText = positionals.length > 0 ? positionals.join(" ") : (stdin ?? "");
15
+ const env = getAllEnvVars(authUser);
16
+ const text = expandEnvVars(rawText, env);
17
+ return {
18
+ stdout: newline ? text : text.trimEnd(),
19
+ exitCode: 0,
20
+ };
21
+ },
22
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const envCommand: ShellModule;
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,UAAU,EAAE,WAkBxB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { getAllEnvVars } from "./set";
2
+ export const envCommand = {
3
+ name: "env",
4
+ params: ["[VAR=value...] [command]"],
5
+ run: ({ authUser }) => {
6
+ // For now, just display all environment variables
7
+ // In a full implementation, this would also handle running commands with modified env
8
+ const allVars = getAllEnvVars(authUser);
9
+ const envVarsOutput = Object.entries(allVars)
10
+ .map(([key, value]) => `${key}=${value}`)
11
+ .sort()
12
+ .join("\n");
13
+ return {
14
+ stdout: envVarsOutput,
15
+ exitCode: 0,
16
+ };
17
+ },
18
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const exitCommand: ShellModule;
3
+ //# sourceMappingURL=exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit.d.ts","sourceRoot":"","sources":["../../src/commands/exit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,WAAW,EAAE,WAIzB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export const exitCommand = {
2
+ name: "exit",
3
+ params: [],
4
+ run: () => ({ closeSession: true, exitCode: 0 }),
5
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const exportCommand: ShellModule;
3
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,aAAa,EAAE,WAiC3B,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { getArg } from "./command-helpers";
2
+ import { getEnvVar, setEnvVar } from "./set";
3
+ export const exportCommand = {
4
+ name: "export",
5
+ params: ["[VAR=value]"],
6
+ run: ({ args }) => {
7
+ // export VAR=value or export VAR (to make it available to child processes)
8
+ if (args.length === 0) {
9
+ // List all exported variables
10
+ return {
11
+ stdout: "# export command - sets variables for child processes",
12
+ exitCode: 0,
13
+ };
14
+ }
15
+ // Parse VAR=value format
16
+ for (let index = 0;; index += 1) {
17
+ const arg = getArg(args, index);
18
+ if (!arg) {
19
+ break;
20
+ }
21
+ if (arg.includes("=")) {
22
+ const [varName, varValue] = arg.split("=", 2);
23
+ if (varName && varValue !== undefined) {
24
+ setEnvVar(varName, varValue);
25
+ }
26
+ }
27
+ else {
28
+ // export VAR_NAME makes it available but we just set it
29
+ setEnvVar(arg, getEnvVar(arg) || "");
30
+ }
31
+ }
32
+ return { exitCode: 0 };
33
+ },
34
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const grepCommand: ShellModule;
3
+ //# sourceMappingURL=grep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../src/commands/grep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,WAAW,EAAE,WA2EzB,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { parseArgs } from "./command-helpers";
2
+ import { assertPathAccess, resolvePath } from "./helpers";
3
+ export const grepCommand = {
4
+ name: "grep",
5
+ params: ["[-i] [-v] <pattern> [file...]"],
6
+ run: ({ authUser, shell, cwd, args, stdin }) => {
7
+ const { flags, positionals } = parseArgs(args, { flags: ["-i", "-v"] });
8
+ const caseInsensitive = flags.has("-i");
9
+ const invertMatch = flags.has("-v");
10
+ const pattern = positionals[0];
11
+ const files = positionals.slice(1);
12
+ if (!pattern) {
13
+ return { stderr: "grep: no pattern specified", exitCode: 1 };
14
+ }
15
+ let regex;
16
+ try {
17
+ const flags = caseInsensitive ? "gmi" : "gm";
18
+ regex = new RegExp(pattern, flags);
19
+ }
20
+ catch {
21
+ return { stderr: `grep: invalid regex: ${pattern}`, exitCode: 1 };
22
+ }
23
+ const results = [];
24
+ if (files.length === 0) {
25
+ if (!stdin) {
26
+ return { stdout: "", exitCode: 1 };
27
+ }
28
+ const lines = stdin.split("\n");
29
+ for (const line of lines) {
30
+ regex.lastIndex = 0;
31
+ const matches = regex.test(line);
32
+ const shouldInclude = invertMatch ? !matches : matches;
33
+ if (shouldInclude) {
34
+ results.push(line);
35
+ }
36
+ }
37
+ return {
38
+ stdout: results.length > 0 ? results.join("\n") : "",
39
+ exitCode: results.length > 0 ? 0 : 1,
40
+ };
41
+ }
42
+ for (const file of files) {
43
+ const target = resolvePath(cwd, file);
44
+ try {
45
+ assertPathAccess(authUser, target, "grep");
46
+ const content = shell.vfs.readFile(target);
47
+ const lines = content.split("\n");
48
+ for (const line of lines) {
49
+ regex.lastIndex = 0;
50
+ const matches = regex.test(line);
51
+ const shouldInclude = invertMatch ? !matches : matches;
52
+ if (shouldInclude) {
53
+ results.push(line);
54
+ }
55
+ }
56
+ }
57
+ catch {
58
+ return {
59
+ stderr: `grep: ${file}: No such file or directory`,
60
+ exitCode: 1,
61
+ };
62
+ }
63
+ }
64
+ return {
65
+ stdout: results.length > 0 ? results.join("\n") : "",
66
+ exitCode: results.length > 0 ? 0 : 1,
67
+ };
68
+ },
69
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare function createHelpCommand(getNames: () => string[]): ShellModule;
3
+ //# sourceMappingURL=help.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/commands/help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,MAAM,EAAE,GAAG,WAAW,CAMvE"}
@@ -0,0 +1,7 @@
1
+ export function createHelpCommand(getNames) {
2
+ return {
3
+ name: "help",
4
+ params: [],
5
+ run: () => ({ stdout: `Builtins: ${getNames().join(" ")}`, exitCode: 0 }),
6
+ };
7
+ }
@@ -0,0 +1,26 @@
1
+ import type VirtualFileSystem from "../VirtualFileSystem";
2
+ export declare function normalizeTerminalOutput(text: string): string;
3
+ export declare function resolvePath(cwd: string, inputPath: string): string;
4
+ export declare function assertPathAccess(authUser: string, targetPath: string, operation: string): void;
5
+ export declare function stripUrlFilename(url: string): string;
6
+ export declare function fetchResource(url: string): Promise<{
7
+ text: string;
8
+ status: number;
9
+ contentType: string | null;
10
+ }>;
11
+ /**
12
+ * Run a host command like curl or wget and capture its output.
13
+ * @param binary - The binary to execute (e.g., "curl", "wget").
14
+ * @param args - Arguments to pass to the binary.
15
+ * @returns Promise resolving with stdout, stderr, and exit code.
16
+ */
17
+ export declare function runHostCommand(binary: string, args: string[]): Promise<{
18
+ stdout: string;
19
+ stderr: string;
20
+ exitCode: number;
21
+ }>;
22
+ export declare function resolveReadablePath(vfs: VirtualFileSystem, cwd: string, inputPath: string): string;
23
+ export declare function joinListWithType(cwd: string, items: string[], statAt: (p: string) => {
24
+ type: "file" | "directory";
25
+ }): string;
26
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/commands/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,iBAAiB,MAAM,sBAAsB,CAAC;AAY1D,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAY5D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAOlE;AAYD,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf,IAAI,CAQN;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED,wBAAsB,aAAa,CAClC,GAAG,EAAE,MAAM,GACT,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAQvE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAAE,GACZ,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA8D/D;AA4BD,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,iBAAiB,EACtB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GACf,MAAM,CAyBR;AAED,wBAAgB,gBAAgB,CAC/B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,GACnD,MAAM,CAQR"}
@@ -0,0 +1,160 @@
1
+ import { spawn } from "node:child_process";
2
+ import * as path from "node:path";
3
+ const PROTECTED_PREFIXES = ["/virtual-env-js/.auth"];
4
+ function normalizeFetchUrl(input) {
5
+ if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(input)) {
6
+ return input;
7
+ }
8
+ return `http://${input}`;
9
+ }
10
+ export function normalizeTerminalOutput(text) {
11
+ return text
12
+ .replace(/\r\n/g, "\n")
13
+ .replace(/\r/g, "\n")
14
+ .replace(/\t/g, " ")
15
+ .split("\n")
16
+ .map((line) => line.replace(/^[ \u00A0]{8,}/, " ").replace(/[ \u00A0]{3,}/g, " "))
17
+ .join("\n")
18
+ .replace(/\n{3,}/g, "\n\n")
19
+ .trimEnd();
20
+ }
21
+ export function resolvePath(cwd, inputPath) {
22
+ if (!inputPath || inputPath.trim() === "") {
23
+ return cwd;
24
+ }
25
+ return inputPath.startsWith("/")
26
+ ? path.posix.normalize(inputPath)
27
+ : path.posix.normalize(path.posix.join(cwd, inputPath));
28
+ }
29
+ function isProtectedPath(targetPath) {
30
+ const normalized = targetPath.startsWith("/")
31
+ ? path.posix.normalize(targetPath)
32
+ : path.posix.normalize(`/${targetPath}`);
33
+ return PROTECTED_PREFIXES.some((prefix) => normalized === prefix || normalized.startsWith(`${prefix}/`));
34
+ }
35
+ export function assertPathAccess(authUser, targetPath, operation) {
36
+ if (authUser === "root") {
37
+ return;
38
+ }
39
+ if (isProtectedPath(targetPath)) {
40
+ throw new Error(`${operation}: permission denied: ${targetPath}`);
41
+ }
42
+ }
43
+ export function stripUrlFilename(url) {
44
+ const cleaned = url.split("?")[0]?.split("#")[0] ?? url;
45
+ const lastPart = cleaned.split("/").filter(Boolean).pop();
46
+ return lastPart && lastPart.length > 0 ? lastPart : "index.html";
47
+ }
48
+ export async function fetchResource(url) {
49
+ const response = await fetch(normalizeFetchUrl(url));
50
+ const contentType = response.headers.get("content-type");
51
+ return {
52
+ text: await response.text(),
53
+ status: response.status,
54
+ contentType,
55
+ };
56
+ }
57
+ /**
58
+ * Run a host command like curl or wget and capture its output.
59
+ * @param binary - The binary to execute (e.g., "curl", "wget").
60
+ * @param args - Arguments to pass to the binary.
61
+ * @returns Promise resolving with stdout, stderr, and exit code.
62
+ */
63
+ export function runHostCommand(binary, args) {
64
+ return new Promise((resolve) => {
65
+ let childProcess;
66
+ try {
67
+ childProcess = spawn(binary, args, {
68
+ stdio: ["ignore", "pipe", "pipe"],
69
+ });
70
+ }
71
+ catch (error) {
72
+ resolve({
73
+ stdout: "",
74
+ stderr: `${binary}: ${error instanceof Error ? error.message : String(error)}`,
75
+ exitCode: 1,
76
+ });
77
+ return;
78
+ }
79
+ let stdout = "";
80
+ let stderr = "";
81
+ const stdoutStream = childProcess.stdout;
82
+ const stderrStream = childProcess.stderr;
83
+ if (!stdoutStream || !stderrStream) {
84
+ resolve({
85
+ stdout: "",
86
+ stderr: `${binary}: failed to capture process output`,
87
+ exitCode: 1,
88
+ });
89
+ return;
90
+ }
91
+ stdoutStream.setEncoding("utf8");
92
+ stderrStream.setEncoding("utf8");
93
+ stdoutStream.on("data", (chunk) => {
94
+ stdout += chunk;
95
+ });
96
+ stderrStream.on("data", (chunk) => {
97
+ stderr += chunk;
98
+ });
99
+ childProcess.on("error", (error) => {
100
+ const errorCode = error instanceof Error && "code" in error
101
+ ? String(error.code ?? "")
102
+ : "";
103
+ resolve({
104
+ stdout: "",
105
+ stderr: `${binary}: ${error.message}`,
106
+ exitCode: errorCode === "ENOENT" ? 127 : 1,
107
+ });
108
+ });
109
+ childProcess.on("close", (code) => {
110
+ resolve({
111
+ stdout,
112
+ stderr,
113
+ exitCode: code ?? 1,
114
+ });
115
+ });
116
+ });
117
+ }
118
+ function levenshtein(a, b) {
119
+ const dp = Array.from({ length: a.length + 1 }, () => Array(b.length + 1).fill(0));
120
+ for (let i = 0; i <= a.length; i += 1) {
121
+ dp[i][0] = i;
122
+ }
123
+ for (let j = 0; j <= b.length; j += 1) {
124
+ dp[0][j] = j;
125
+ }
126
+ for (let i = 1; i <= a.length; i += 1) {
127
+ for (let j = 1; j <= b.length; j += 1) {
128
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
129
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
130
+ }
131
+ }
132
+ return dp[a.length][b.length];
133
+ }
134
+ export function resolveReadablePath(vfs, cwd, inputPath) {
135
+ const exactPath = resolvePath(cwd, inputPath);
136
+ if (vfs.exists(exactPath)) {
137
+ return exactPath;
138
+ }
139
+ const parent = path.posix.dirname(exactPath);
140
+ const fileName = path.posix.basename(exactPath);
141
+ const siblings = vfs.list(parent);
142
+ const caseInsensitive = siblings.filter((name) => name.toLowerCase() === fileName.toLowerCase());
143
+ if (caseInsensitive.length === 1) {
144
+ return path.posix.join(parent, caseInsensitive[0]);
145
+ }
146
+ const near = siblings.filter((name) => levenshtein(name.toLowerCase(), fileName.toLowerCase()) <= 1);
147
+ if (near.length === 1) {
148
+ return path.posix.join(parent, near[0]);
149
+ }
150
+ return exactPath;
151
+ }
152
+ export function joinListWithType(cwd, items, statAt) {
153
+ return items
154
+ .map((name) => {
155
+ const childPath = resolvePath(cwd, name);
156
+ const stats = statAt(childPath);
157
+ return stats.type === "directory" ? `${name}/` : name;
158
+ })
159
+ .join(" ");
160
+ }
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const hostnameCommand: ShellModule;
3
+ //# sourceMappingURL=hostname.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostname.d.ts","sourceRoot":"","sources":["../../src/commands/hostname.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,eAAe,EAAE,WAI7B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export const hostnameCommand = {
2
+ name: "hostname",
3
+ params: [],
4
+ run: ({ hostname }) => ({ stdout: hostname, exitCode: 0 }),
5
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const htopCommand: ShellModule;
3
+ //# sourceMappingURL=htop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"htop.d.ts","sourceRoot":"","sources":["../../src/commands/htop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,WAAW,EAAE,WAUzB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export const htopCommand = {
2
+ name: "htop",
3
+ params: [],
4
+ run: ({ mode }) => {
5
+ if (mode === "exec") {
6
+ return { stderr: "htop: interactive terminal required", exitCode: 1 };
7
+ }
8
+ return { openHtop: true, exitCode: 0 };
9
+ },
10
+ };
@@ -0,0 +1,8 @@
1
+ import type { VirtualShell } from "../VirtualShell";
2
+ import type { CommandContext, CommandMode, CommandResult, ShellModule } from "../types/commands";
3
+ export declare function registerCommand(module: ShellModule): void;
4
+ export declare function createCustomCommand(name: string, params: string[], run: (ctx: CommandContext) => CommandResult | Promise<CommandResult>): ShellModule;
5
+ export declare function getCommandNames(): string[];
6
+ export declare function resolveModule(name: string): ShellModule | undefined;
7
+ export declare function runCommand(rawInput: string, authUser: string, hostname: string, mode: CommandMode, cwd: string, shell: VirtualShell, stdin?: string): Promise<CommandResult>;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EACX,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,MAAM,mBAAmB,CAAC;AA8F3B,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAsBzD;AAED,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EAAE,EAChB,GAAG,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,GAClE,WAAW,CAMb;AAED,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAK1C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAKnE;AAsDD,wBAAsB,UAAU,CAC/B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,CAAC,CA6DxB"}