typescript-virtual-container 1.1.1-b → 1.1.1-c
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.
- package/.vscode/settings.json +1 -1
- package/dist/SSHClient/index.d.ts +138 -0
- package/dist/SSHClient/index.d.ts.map +1 -0
- package/dist/SSHClient/index.js +216 -0
- package/dist/SSHMimic/exec.d.ts +4 -0
- package/dist/SSHMimic/exec.d.ts.map +1 -0
- package/dist/SSHMimic/exec.js +21 -0
- package/dist/SSHMimic/executor.d.ts +9 -0
- package/dist/SSHMimic/executor.d.ts.map +1 -0
- package/dist/SSHMimic/executor.js +131 -0
- package/dist/SSHMimic/hostKey.d.ts +2 -0
- package/dist/SSHMimic/hostKey.d.ts.map +1 -0
- package/dist/SSHMimic/hostKey.js +17 -0
- package/dist/SSHMimic/index.d.ts +39 -0
- package/dist/SSHMimic/index.d.ts.map +1 -0
- package/dist/SSHMimic/index.js +113 -0
- package/dist/SSHMimic/loginFormat.d.ts +2 -0
- package/dist/SSHMimic/loginFormat.d.ts.map +1 -0
- package/dist/SSHMimic/loginFormat.js +10 -0
- package/dist/SSHMimic/prompt.d.ts +2 -0
- package/dist/SSHMimic/prompt.d.ts.map +1 -0
- package/dist/SSHMimic/prompt.js +9 -0
- package/dist/VirtualFileSystem/archive.d.ts +5 -0
- package/dist/VirtualFileSystem/archive.d.ts.map +1 -0
- package/dist/VirtualFileSystem/archive.js +56 -0
- package/dist/VirtualFileSystem/index.d.ts +131 -0
- package/dist/VirtualFileSystem/index.d.ts.map +1 -0
- package/dist/VirtualFileSystem/index.js +355 -0
- package/dist/VirtualFileSystem/internalTypes.d.ts +18 -0
- package/dist/VirtualFileSystem/internalTypes.d.ts.map +1 -0
- package/dist/VirtualFileSystem/internalTypes.js +0 -0
- package/dist/VirtualFileSystem/path.d.ts +9 -0
- package/dist/VirtualFileSystem/path.d.ts.map +1 -0
- package/dist/VirtualFileSystem/path.js +49 -0
- package/dist/VirtualFileSystem/snapshot.d.ts +5 -0
- package/dist/VirtualFileSystem/snapshot.d.ts.map +1 -0
- package/dist/VirtualFileSystem/snapshot.js +59 -0
- package/dist/VirtualFileSystem/tree.d.ts +3 -0
- package/dist/VirtualFileSystem/tree.d.ts.map +1 -0
- package/dist/VirtualFileSystem/tree.js +19 -0
- package/dist/VirtualShell/index.d.ts +86 -0
- package/dist/VirtualShell/index.d.ts.map +1 -0
- package/dist/VirtualShell/index.js +129 -0
- package/dist/VirtualShell/shell.d.ts +5 -0
- package/dist/VirtualShell/shell.d.ts.map +1 -0
- package/dist/VirtualShell/shell.js +473 -0
- package/dist/VirtualShell/shellParser.d.ts +4 -0
- package/dist/VirtualShell/shellParser.d.ts.map +1 -0
- package/dist/VirtualShell/shellParser.js +207 -0
- package/dist/VirtualUserManager/index.d.ts +168 -0
- package/dist/VirtualUserManager/index.d.ts.map +1 -0
- package/dist/VirtualUserManager/index.js +375 -0
- package/dist/commands/adduser.d.ts +3 -0
- package/dist/commands/adduser.d.ts.map +1 -0
- package/dist/commands/adduser.js +18 -0
- package/dist/commands/cat.d.ts +3 -0
- package/dist/commands/cat.d.ts.map +1 -0
- package/dist/commands/cat.js +15 -0
- package/dist/commands/cd.d.ts +3 -0
- package/dist/commands/cd.d.ts.map +1 -0
- package/dist/commands/cd.js +17 -0
- package/dist/commands/clear.d.ts +3 -0
- package/dist/commands/clear.d.ts.map +1 -0
- package/dist/commands/clear.js +5 -0
- package/dist/commands/command-helpers.d.ts +23 -0
- package/dist/commands/command-helpers.d.ts.map +1 -0
- package/dist/commands/command-helpers.js +139 -0
- package/dist/commands/curl.d.ts +3 -0
- package/dist/commands/curl.d.ts.map +1 -0
- package/dist/commands/curl.js +44 -0
- package/dist/commands/deluser.d.ts +3 -0
- package/dist/commands/deluser.d.ts.map +1 -0
- package/dist/commands/deluser.js +15 -0
- package/dist/commands/echo.d.ts +3 -0
- package/dist/commands/echo.d.ts.map +1 -0
- package/dist/commands/echo.js +22 -0
- package/dist/commands/env.d.ts +3 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +18 -0
- package/dist/commands/exit.d.ts +3 -0
- package/dist/commands/exit.d.ts.map +1 -0
- package/dist/commands/exit.js +5 -0
- package/dist/commands/export.d.ts +3 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +34 -0
- package/dist/commands/grep.d.ts +3 -0
- package/dist/commands/grep.d.ts.map +1 -0
- package/dist/commands/grep.js +69 -0
- package/dist/commands/help.d.ts +3 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +7 -0
- package/dist/commands/helpers.d.ts +26 -0
- package/dist/commands/helpers.d.ts.map +1 -0
- package/dist/commands/helpers.js +160 -0
- package/dist/commands/hostname.d.ts +3 -0
- package/dist/commands/hostname.d.ts.map +1 -0
- package/dist/commands/hostname.js +5 -0
- package/dist/commands/htop.d.ts +3 -0
- package/dist/commands/htop.d.ts.map +1 -0
- package/dist/commands/htop.js +10 -0
- package/dist/commands/index.d.ts +8 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +212 -0
- package/dist/commands/ls.d.ts +3 -0
- package/dist/commands/ls.d.ts.map +1 -0
- package/dist/commands/ls.js +47 -0
- package/dist/commands/mkdir.d.ts +3 -0
- package/dist/commands/mkdir.d.ts.map +1 -0
- package/dist/commands/mkdir.js +21 -0
- package/dist/commands/nano.d.ts +3 -0
- package/dist/commands/nano.d.ts.map +1 -0
- package/dist/commands/nano.js +27 -0
- package/dist/commands/neofetch.d.ts +3 -0
- package/dist/commands/neofetch.d.ts.map +1 -0
- package/dist/commands/neofetch.js +32 -0
- package/dist/commands/pwd.d.ts +3 -0
- package/dist/commands/pwd.d.ts.map +1 -0
- package/dist/commands/pwd.js +5 -0
- package/dist/commands/rm.d.ts +3 -0
- package/dist/commands/rm.d.ts.map +1 -0
- package/dist/commands/rm.js +29 -0
- package/dist/commands/set.d.ts +7 -0
- package/dist/commands/set.d.ts.map +1 -0
- package/dist/commands/set.js +64 -0
- package/dist/commands/sh.d.ts +4 -0
- package/dist/commands/sh.d.ts.map +1 -0
- package/dist/commands/sh.js +45 -0
- package/dist/commands/su.d.ts +3 -0
- package/dist/commands/su.d.ts.map +1 -0
- package/dist/commands/su.js +24 -0
- package/dist/commands/sudo.d.ts +3 -0
- package/dist/commands/sudo.d.ts.map +1 -0
- package/dist/commands/sudo.js +47 -0
- package/dist/commands/touch.d.ts +3 -0
- package/dist/commands/touch.d.ts.map +1 -0
- package/dist/commands/touch.js +18 -0
- package/dist/commands/tree.d.ts +3 -0
- package/dist/commands/tree.d.ts.map +1 -0
- package/dist/commands/tree.js +11 -0
- package/dist/commands/unset.d.ts +3 -0
- package/dist/commands/unset.d.ts.map +1 -0
- package/dist/commands/unset.js +15 -0
- package/dist/commands/wget.d.ts +3 -0
- package/dist/commands/wget.d.ts.map +1 -0
- package/dist/commands/wget.js +113 -0
- package/dist/commands/who.d.ts +3 -0
- package/dist/commands/who.d.ts.map +1 -0
- package/dist/commands/who.js +15 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +5 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/modules/neofetch.d.ts +19 -0
- package/dist/modules/neofetch.d.ts.map +1 -0
- package/dist/modules/neofetch.js +284 -0
- package/dist/modules/shellInteractive.d.ts +6 -0
- package/dist/modules/shellInteractive.d.ts.map +1 -0
- package/dist/modules/shellInteractive.js +26 -0
- package/dist/modules/shellRuntime.d.ts +11 -0
- package/dist/modules/shellRuntime.d.ts.map +1 -0
- package/dist/modules/shellRuntime.js +52 -0
- package/dist/standalone.d.ts +2 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/standalone.js +25 -0
- package/dist/types/commands.d.ts +89 -0
- package/dist/types/commands.d.ts.map +1 -0
- package/dist/types/commands.js +0 -0
- package/dist/types/pipeline.d.ts +23 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +0 -0
- package/dist/types/streams.d.ts +32 -0
- package/dist/types/streams.d.ts.map +1 -0
- package/dist/types/streams.js +0 -0
- package/dist/types/vfs.d.ts +71 -0
- package/dist/types/vfs.d.ts.map +1 -0
- package/dist/types/vfs.js +0 -0
- package/package.json +4 -2
- package/src/VirtualShell/shell.ts +3 -3
- package/src/commands/neofetch.ts +1 -1
- package/{modules → src/modules}/neofetch.ts +56 -51
- package/{modules → src/modules}/shellInteractive.ts +16 -4
- package/tsconfig.json +19 -8
- /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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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,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 @@
|
|
|
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 @@
|
|
|
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,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"}
|