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.
Files changed (185) hide show
  1. package/.vscode/settings.json +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 +19 -8
  185. /package/{modules → src/modules}/shellRuntime.ts +0 -0
@@ -0,0 +1,18 @@
1
+ import { assertPathAccess, resolvePath } from "./helpers";
2
+ export const touchCommand = {
3
+ name: "touch",
4
+ params: ["<file>"],
5
+ run: ({ authUser, shell, cwd, args }) => {
6
+ if (args.length === 0) {
7
+ return { stderr: "touch: missing file operand", exitCode: 1 };
8
+ }
9
+ for (const file of args) {
10
+ const target = resolvePath(cwd, file);
11
+ assertPathAccess(authUser, target, "touch");
12
+ if (!shell.vfs.exists(target)) {
13
+ shell.writeFileAsUser(authUser, target, "");
14
+ }
15
+ }
16
+ return { exitCode: 0 };
17
+ },
18
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const treeCommand: ShellModule;
3
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/commands/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,eAAO,MAAM,WAAW,EAAE,WAQzB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { getArg } from "./command-helpers";
2
+ import { assertPathAccess, resolvePath } from "./helpers";
3
+ export const treeCommand = {
4
+ name: "tree",
5
+ params: ["[path]"],
6
+ run: ({ authUser, shell, cwd, args }) => {
7
+ const target = resolvePath(cwd, getArg(args, 0) ?? cwd);
8
+ assertPathAccess(authUser, target, "tree");
9
+ return { stdout: shell.vfs.tree(target), exitCode: 0 };
10
+ },
11
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const unsetCommand: ShellModule;
3
+ //# sourceMappingURL=unset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unset.d.ts","sourceRoot":"","sources":["../../src/commands/unset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,eAAO,MAAM,YAAY,EAAE,WAe1B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { setEnvVar } from "./set";
2
+ export const unsetCommand = {
3
+ name: "unset",
4
+ params: ["<VAR...>"],
5
+ run: ({ args }) => {
6
+ if (args.length === 0) {
7
+ return { stderr: "unset: missing variable name", exitCode: 1 };
8
+ }
9
+ // Unset (remove) all specified variables
10
+ for (const varName of args) {
11
+ setEnvVar(varName, "");
12
+ }
13
+ return { exitCode: 0 };
14
+ },
15
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const wgetCommand: ShellModule;
3
+ //# sourceMappingURL=wget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wget.d.ts","sourceRoot":"","sources":["../../src/commands/wget.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA8ErD,eAAO,MAAM,WAAW,EAAE,WA6DzB,CAAC"}
@@ -0,0 +1,113 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdtemp, readFile, rm } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { ifFlag, parseArgs } from "./command-helpers";
6
+ import { assertPathAccess, normalizeTerminalOutput, resolvePath, runHostCommand, stripUrlFilename, } from "./helpers";
7
+ function runHostWget(args) {
8
+ return new Promise((resolve) => {
9
+ let childProcess;
10
+ try {
11
+ childProcess = spawn("wget", args, {
12
+ stdio: ["ignore", "pipe", "pipe"],
13
+ });
14
+ }
15
+ catch (error) {
16
+ resolve({
17
+ stdout: "",
18
+ stderr: `wget: ${error instanceof Error ? error.message : String(error)}`,
19
+ exitCode: 1,
20
+ });
21
+ return;
22
+ }
23
+ let stdout = "";
24
+ let stderr = "";
25
+ const stdoutStream = childProcess.stdout;
26
+ const stderrStream = childProcess.stderr;
27
+ if (!stdoutStream || !stderrStream) {
28
+ resolve({
29
+ stdout: "",
30
+ stderr: "wget: failed to capture process output",
31
+ exitCode: 1,
32
+ });
33
+ return;
34
+ }
35
+ stdoutStream.setEncoding("utf8");
36
+ stderrStream.setEncoding("utf8");
37
+ stdoutStream.on("data", (chunk) => {
38
+ stdout += chunk;
39
+ });
40
+ stderrStream.on("data", (chunk) => {
41
+ stderr += chunk;
42
+ });
43
+ childProcess.on("error", (error) => {
44
+ const errorCode = error instanceof Error && "code" in error
45
+ ? String(error.code ?? "")
46
+ : "";
47
+ resolve({
48
+ stdout: "",
49
+ stderr: `wget: ${error.message}`,
50
+ exitCode: errorCode === "ENOENT" ? 127 : 1,
51
+ });
52
+ });
53
+ childProcess.on("close", (code) => {
54
+ resolve({
55
+ stdout,
56
+ stderr,
57
+ exitCode: code ?? 1,
58
+ });
59
+ });
60
+ });
61
+ }
62
+ export const wgetCommand = {
63
+ name: "wget",
64
+ params: ["[url]"],
65
+ run: async ({ authUser, cwd, args, shell }) => {
66
+ const { flagsWithValues, positionals } = parseArgs(args, {
67
+ flagsWithValue: ["-o", "-O", "--output", "--output-document"],
68
+ });
69
+ const outputPath = flagsWithValues.get("-o") ||
70
+ flagsWithValues.get("-O") ||
71
+ flagsWithValues.get("--output") ||
72
+ flagsWithValues.get("--output-document") ||
73
+ null;
74
+ const url = positionals[0];
75
+ if (!url) {
76
+ return { stderr: "wget: missing URL", exitCode: 1 };
77
+ }
78
+ const isHelpLike = ifFlag(args, ["-h", "--help", "-V", "--version"]);
79
+ if (isHelpLike) {
80
+ const result = await runHostWget(args);
81
+ return {
82
+ stdout: normalizeTerminalOutput(result.stdout),
83
+ stderr: result.stderr
84
+ ? normalizeTerminalOutput(result.stderr)
85
+ : undefined,
86
+ exitCode: result.exitCode,
87
+ };
88
+ }
89
+ const tempDir = await mkdtemp(join(tmpdir(), "virtual-env-js-wget-"));
90
+ const tempFile = join(tempDir, "download");
91
+ try {
92
+ const hostArgs = [...positionals, "-O", tempFile];
93
+ const result = await runHostCommand("wget", hostArgs);
94
+ if (result.exitCode !== 0) {
95
+ return {
96
+ stderr: normalizeTerminalOutput(result.stderr || `wget: exited with code ${result.exitCode}`),
97
+ exitCode: result.exitCode,
98
+ };
99
+ }
100
+ const content = await readFile(tempFile, "utf8");
101
+ const target = resolvePath(cwd, outputPath || stripUrlFilename(url));
102
+ assertPathAccess(authUser, target, "wget");
103
+ shell.writeFileAsUser(authUser, target, content);
104
+ return {
105
+ stdout: `saved ${target}`,
106
+ exitCode: 0,
107
+ };
108
+ }
109
+ finally {
110
+ await rm(tempDir, { recursive: true, force: true });
111
+ }
112
+ },
113
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const whoCommand: ShellModule;
3
+ //# sourceMappingURL=who.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"who.d.ts","sourceRoot":"","sources":["../../src/commands/who.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,UAAU,EAAE,WAcxB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { formatLoginDate } from "../SSHMimic/loginFormat";
2
+ export const whoCommand = {
3
+ name: "who",
4
+ params: [],
5
+ run: ({ shell }) => {
6
+ const lines = shell.users.listActiveSessions().map((session) => {
7
+ const loginAt = new Date(session.startedAt);
8
+ const displayDate = Number.isNaN(loginAt.getTime())
9
+ ? session.startedAt
10
+ : formatLoginDate(loginAt);
11
+ return `${session.username} ${session.tty} ${displayDate} (${session.remoteAddress || "unknown"})`;
12
+ });
13
+ return { stdout: lines.join("\n"), exitCode: 0 };
14
+ },
15
+ };
@@ -0,0 +1,3 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const whoamiCommand: ShellModule;
3
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,eAAO,MAAM,aAAa,EAAE,WAI3B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export const whoamiCommand = {
2
+ name: "whoami",
3
+ params: [],
4
+ run: ({ authUser }) => ({ stdout: authUser, exitCode: 0 }),
5
+ };
@@ -0,0 +1,11 @@
1
+ import { SshClient } from "./SSHClient";
2
+ import { SshMimic } from "./SSHMimic/index";
3
+ import VirtualFileSystem from "./VirtualFileSystem";
4
+ import { VirtualShell } from "./VirtualShell";
5
+ import { VirtualUserManager } from "./VirtualUserManager";
6
+ export type { CommandContext, CommandMode, CommandOutcome, CommandResult, NanoEditorSession, ShellModule, SudoChallenge, } from "./types/commands";
7
+ export type { ExecStream, ShellStream } from "./types/streams";
8
+ export type { RemoveOptions, VfsBaseNode, VfsDirectoryNode, VfsFileNode, VfsNodeStats, VfsNodeType, VfsSnapshot, VfsSnapshotBaseNode, VfsSnapshotDirectoryNode, VfsSnapshotFileNode, VfsSnapshotNode, WriteFileOptions, } from "./types/vfs";
9
+ export { SshClient, VirtualFileSystem, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
10
+ export { getArg, getFlag, ifFlag, } from "./commands/command-helpers";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,YAAY,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,aAAa,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,YAAY,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,QAAQ,IAAI,gBAAgB,EAC5B,kBAAkB,GAClB,CAAC;AAEF,OAAO,EACN,MAAM,EACN,OAAO,EACP,MAAM,GACN,MAAM,4BAA4B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import { SshClient } from "./SSHClient";
2
+ import { SshMimic } from "./SSHMimic/index";
3
+ import VirtualFileSystem from "./VirtualFileSystem";
4
+ import { VirtualShell } from "./VirtualShell";
5
+ import { VirtualUserManager } from "./VirtualUserManager";
6
+ export { SshClient, VirtualFileSystem, VirtualShell, SshMimic as VirtualSshServer, VirtualUserManager, };
7
+ export { getArg, getFlag, ifFlag, } from "./commands/command-helpers";
@@ -0,0 +1,19 @@
1
+ import type { ShellProperties } from "../VirtualShell";
2
+ export interface NeofetchInfo {
3
+ user: string;
4
+ host: string;
5
+ osName?: string;
6
+ kernel?: string;
7
+ uptimeSeconds?: number;
8
+ packages?: string;
9
+ shell?: string;
10
+ shellProps?: ShellProperties;
11
+ resolution?: string;
12
+ terminal?: string;
13
+ cpu?: string;
14
+ gpu?: string;
15
+ memoryUsedMiB?: number;
16
+ memoryTotalMiB?: number;
17
+ }
18
+ export declare function buildNeofetchOutput(info: NeofetchInfo): string;
19
+ //# sourceMappingURL=neofetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neofetch.d.ts","sourceRoot":"","sources":["../../src/modules/neofetch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAsGvD,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAoKD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA0E9D"}
@@ -0,0 +1,284 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ function formatUptime(seconds) {
5
+ const totalMinutes = Math.max(1, Math.floor(seconds / 60));
6
+ const days = Math.floor(totalMinutes / (24 * 60));
7
+ const hours = Math.floor((totalMinutes % (24 * 60)) / 60);
8
+ const minutes = totalMinutes % 60;
9
+ const parts = [];
10
+ if (days > 0) {
11
+ parts.push(`${days} day${days > 1 ? "s" : ""}`);
12
+ }
13
+ if (hours > 0) {
14
+ parts.push(`${hours} hour${hours > 1 ? "s" : ""}`);
15
+ }
16
+ if (minutes > 0 || parts.length === 0) {
17
+ parts.push(`${minutes} min${minutes > 1 ? "s" : ""}`);
18
+ }
19
+ return parts.join(", ");
20
+ }
21
+ function colorBlock(code) {
22
+ return `\u001b[${code}m \u001b[0m`;
23
+ }
24
+ function buildColorBars() {
25
+ const normal = [40, 41, 42, 43, 44, 45, 46, 47].map(colorBlock).join("");
26
+ const bright = [100, 101, 102, 103, 104, 105, 106, 107]
27
+ .map(colorBlock)
28
+ .join("");
29
+ return [normal, bright];
30
+ }
31
+ function colorizeLogoLine(line, index, total) {
32
+ if (line.trim().length === 0) {
33
+ return line;
34
+ }
35
+ const start = { r: 255, g: 255, b: 255 };
36
+ const end = { r: 168, g: 85, b: 247 };
37
+ const ratio = total <= 1 ? 0 : index / (total - 1);
38
+ const r = Math.round(start.r + (end.r - start.r) * ratio);
39
+ const g = Math.round(start.g + (end.g - start.g) * ratio);
40
+ const b = Math.round(start.b + (end.b - start.b) * ratio);
41
+ return `\u001b[38;2;${r};${g};${b}m${line}\u001b[0m`;
42
+ }
43
+ function colorizeDetailLine(line) {
44
+ if (line.trim().length === 0) {
45
+ return line;
46
+ }
47
+ const colonIndex = line.indexOf(":");
48
+ if (colonIndex === -1) {
49
+ // Pas de ':', chercher '@' pour identifier user@host
50
+ if (line.includes("@")) {
51
+ // C'est user@host, appliquer dégradé horizontal
52
+ return applyHorizontalGradient(line);
53
+ }
54
+ // Sinon c'est un separator ou autre, laisser tel quel
55
+ return line;
56
+ }
57
+ // Il y a un ':', c'est titre: valeur
58
+ const title = line.substring(0, colonIndex + 1);
59
+ const value = line.substring(colonIndex + 1);
60
+ // Appliquer le dégradé seulement au titre
61
+ const colorized = applyHorizontalGradient(title);
62
+ return colorized + value;
63
+ }
64
+ function applyHorizontalGradient(text) {
65
+ // Nettoyer les codes ANSI existants
66
+ const ansiRegex = new RegExp(`${String.fromCharCode(27)}\\[[\\d;]*m`, "g");
67
+ const cleaned = text.replace(ansiRegex, "");
68
+ if (cleaned.trim().length === 0) {
69
+ return text;
70
+ }
71
+ const start = { r: 255, g: 255, b: 255 };
72
+ const end = { r: 168, g: 85, b: 247 };
73
+ let result = "";
74
+ for (let i = 0; i < cleaned.length; i += 1) {
75
+ const ratio = cleaned.length <= 1 ? 0 : i / (cleaned.length - 1);
76
+ const r = Math.round(start.r + (end.r - start.r) * ratio);
77
+ const g = Math.round(start.g + (end.g - start.g) * ratio);
78
+ const b = Math.round(start.b + (end.b - start.b) * ratio);
79
+ result += `\u001b[38;2;${r};${g};${b}m${cleaned[i]}\u001b[0m`;
80
+ }
81
+ return result;
82
+ }
83
+ function toMiB(bytes) {
84
+ return Math.max(0, Math.round(bytes / (1024 * 1024)));
85
+ }
86
+ function readOsPrettyName() {
87
+ try {
88
+ const data = readFileSync("/etc/os-release", "utf8");
89
+ for (const line of data.split("\n")) {
90
+ if (!line.startsWith("PRETTY_NAME=")) {
91
+ continue;
92
+ }
93
+ const value = line.slice("PRETTY_NAME=".length).trim();
94
+ return value.replace(/^"|"$/g, "");
95
+ }
96
+ }
97
+ catch {
98
+ return undefined;
99
+ }
100
+ return undefined;
101
+ }
102
+ function readFirstLine(filePath) {
103
+ try {
104
+ const data = readFileSync(filePath, "utf8").split("\n")[0]?.trim();
105
+ if (!data || data.length === 0) {
106
+ return undefined;
107
+ }
108
+ return data;
109
+ }
110
+ catch {
111
+ return undefined;
112
+ }
113
+ }
114
+ function resolveHostLabel(fallback) {
115
+ const vendor = readFirstLine("/sys/devices/virtual/dmi/id/sys_vendor");
116
+ const product = readFirstLine("/sys/devices/virtual/dmi/id/product_name");
117
+ if (vendor && product) {
118
+ return `${vendor} ${product}`;
119
+ }
120
+ if (product) {
121
+ return product;
122
+ }
123
+ return fallback;
124
+ }
125
+ function countDpkgPackages() {
126
+ const candidates = ["/var/lib/dpkg/status", "/usr/local/var/lib/dpkg/status"];
127
+ for (const filePath of candidates) {
128
+ if (!existsSync(filePath)) {
129
+ continue;
130
+ }
131
+ try {
132
+ const data = readFileSync(filePath, "utf8");
133
+ const matches = data.match(/^Package:\s+/gm);
134
+ return matches?.length ?? 0;
135
+ }
136
+ catch { }
137
+ }
138
+ return undefined;
139
+ }
140
+ function countSnapPackages() {
141
+ const candidates = ["/snap", "/var/lib/snapd/snaps"];
142
+ for (const dirPath of candidates) {
143
+ if (!existsSync(dirPath)) {
144
+ continue;
145
+ }
146
+ try {
147
+ const entries = readdirSync(dirPath, { withFileTypes: true });
148
+ const count = entries.filter((entry) => entry.isDirectory()).length;
149
+ return count;
150
+ }
151
+ catch { }
152
+ }
153
+ return undefined;
154
+ }
155
+ function resolvePackagesLabel() {
156
+ const dpkgCount = countDpkgPackages();
157
+ const snapCount = countSnapPackages();
158
+ if (dpkgCount !== undefined && snapCount !== undefined) {
159
+ return `${dpkgCount} (dpkg), ${snapCount} (snap)`;
160
+ }
161
+ if (dpkgCount !== undefined) {
162
+ return `${dpkgCount} (dpkg)`;
163
+ }
164
+ if (snapCount !== undefined) {
165
+ return `${snapCount} (snap)`;
166
+ }
167
+ return "n/a";
168
+ }
169
+ function resolveCpuLabel() {
170
+ const cpus = os.cpus();
171
+ if (cpus.length === 0) {
172
+ return "unknown";
173
+ }
174
+ const first = cpus[0];
175
+ if (!first) {
176
+ return "unknown";
177
+ }
178
+ const ghz = (first.speed / 1000).toFixed(2);
179
+ return `${first.model} (${cpus.length}) @ ${ghz}GHz`;
180
+ }
181
+ function resolveShellLabel(shell) {
182
+ if (!shell || shell.trim().length === 0) {
183
+ return "unknown";
184
+ }
185
+ return path.posix.basename(shell.trim());
186
+ }
187
+ function resolveDefaults(info) {
188
+ const totalMem = os.totalmem();
189
+ const freeMem = os.freemem();
190
+ const usedMem = Math.max(0, totalMem - freeMem);
191
+ const shellProps = info.shellProps;
192
+ const processUptime = process.uptime();
193
+ if (info.uptimeSeconds === undefined) {
194
+ info.uptimeSeconds = Math.round(processUptime);
195
+ }
196
+ console.log("Resolving neofetch info with shellProps:", shellProps);
197
+ return {
198
+ user: info.user,
199
+ host: info.host,
200
+ osName: shellProps?.os ??
201
+ info.osName ??
202
+ `${readOsPrettyName() ?? os.type()} ${os.arch()}`,
203
+ kernel: shellProps?.kernel ?? info.kernel ?? os.release(),
204
+ uptimeSeconds: info.uptimeSeconds ?? os.uptime(),
205
+ packages: info.packages ?? resolvePackagesLabel(),
206
+ shell: resolveShellLabel(info.shell),
207
+ shellProps: info.shellProps ?? {
208
+ kernel: info.kernel ?? os.release(),
209
+ os: info.osName ?? `${readOsPrettyName() ?? os.type()} ${os.arch()}`,
210
+ arch: os.arch(),
211
+ },
212
+ resolution: info.resolution ?? "n/a (ssh)",
213
+ terminal: info.terminal ?? "unknown",
214
+ cpu: info.cpu ?? resolveCpuLabel(),
215
+ gpu: info.gpu ?? "n/a",
216
+ memoryUsedMiB: info.memoryUsedMiB ?? toMiB(usedMem),
217
+ memoryTotalMiB: info.memoryTotalMiB ?? toMiB(totalMem),
218
+ };
219
+ }
220
+ export function buildNeofetchOutput(info) {
221
+ const fields = resolveDefaults(info);
222
+ const uptime = formatUptime(fields.uptimeSeconds);
223
+ const colorBars = buildColorBars();
224
+ const distroLogo = [
225
+ " .. .:. ",
226
+ " .::.. .. .. ",
227
+ ". .... ... .. ",
228
+ ": .... .:. .. ",
229
+ ": .:.:........:. .. ",
230
+ ": .. ",
231
+ ". : ",
232
+ ". : ",
233
+ ".. : ",
234
+ " :. .. ",
235
+ " .. .. ",
236
+ " :-. :: ",
237
+ " .:. :. ",
238
+ " ..: ... ",
239
+ " ..: :.. ",
240
+ " :... :....",
241
+ " .. ....",
242
+ " . .. ",
243
+ " .:. .: ",
244
+ " :. .. ",
245
+ " ::. .. ",
246
+ "..... ..:... ",
247
+ "...:. .. ",
248
+ ".:...:. ::. .. ",
249
+ " ... ..:::::.. ..:::::::.. ",
250
+ ];
251
+ const details = [
252
+ `${fields.user}@${fields.host}`,
253
+ "-------------------------",
254
+ `OS: ${fields.osName}`,
255
+ `Host: ${resolveHostLabel(fields.host)}`,
256
+ `Kernel: ${fields.kernel}`,
257
+ `Uptime: ${uptime}`,
258
+ // `Packages: ${fields.packages}`,
259
+ `Shell: ${fields.shell}`,
260
+ // `Shell Props: ${fields.shellProps}`,
261
+ `Resolution: ${fields.resolution}`,
262
+ `Terminal: ${fields.terminal}`,
263
+ `CPU: ${fields.cpu}`,
264
+ `GPU: ${fields.gpu}`,
265
+ `Memory: ${fields.memoryUsedMiB}MiB / ${fields.memoryTotalMiB}MiB`,
266
+ "",
267
+ colorBars[0],
268
+ colorBars[1],
269
+ ];
270
+ const width = Math.max(distroLogo.length, details.length);
271
+ const lines = [];
272
+ for (let i = 0; i < width; i += 1) {
273
+ const rawLeft = distroLogo[i] ?? "";
274
+ const right = details[i] ?? "";
275
+ if (right.length > 0) {
276
+ const left = colorizeLogoLine(rawLeft.padEnd(31, " "), i, distroLogo.length);
277
+ const coloredRight = colorizeDetailLine(right);
278
+ lines.push(`${left} ${coloredRight}`);
279
+ continue;
280
+ }
281
+ lines.push(colorizeLogoLine(rawLeft, i, distroLogo.length));
282
+ }
283
+ return lines.join("\n");
284
+ }
@@ -0,0 +1,6 @@
1
+ import { type ChildProcessWithoutNullStreams } from "node:child_process";
2
+ import type { ShellStream } from "../types/streams";
3
+ import { type TerminalSize } from "./shellRuntime";
4
+ export declare function spawnNanoEditorProcess(tempPath: string, terminalSize: TerminalSize, stream: ShellStream): ChildProcessWithoutNullStreams;
5
+ export declare function spawnHtopProcess(pidList: string, terminalSize: TerminalSize, stream: ShellStream): ChildProcessWithoutNullStreams;
6
+ //# sourceMappingURL=shellInteractive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellInteractive.d.ts","sourceRoot":"","sources":["../../src/modules/shellInteractive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,8BAA8B,EAAS,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAEN,KAAK,YAAY,EAEjB,MAAM,gBAAgB,CAAC;AA4BxB,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,WAAW,GACjB,8BAA8B,CAMhC;AAED,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,WAAW,GACjB,8BAA8B,CAMhC"}
@@ -0,0 +1,26 @@
1
+ import { spawn } from "node:child_process";
2
+ import { shellQuote, withTerminalSize, } from "./shellRuntime";
3
+ function spawnScriptProcess(command, terminalSize, stream) {
4
+ const formatted = withTerminalSize(command, terminalSize);
5
+ const proc = spawn("script", ["-qfec", formatted, "/dev/null"], {
6
+ stdio: ["pipe", "pipe", "pipe"],
7
+ env: {
8
+ ...process.env,
9
+ // biome-ignore lint/style/useNamingConvention: env variable should be uppercase
10
+ TERM: process.env.TERM ?? "xterm-256color",
11
+ },
12
+ });
13
+ proc.stdout.on("data", (data) => {
14
+ stream.write(data.toString("utf8"));
15
+ });
16
+ proc.stderr.on("data", (data) => {
17
+ stream.write(data.toString("utf8"));
18
+ });
19
+ return proc;
20
+ }
21
+ export function spawnNanoEditorProcess(tempPath, terminalSize, stream) {
22
+ return spawnScriptProcess(`nano -- ${shellQuote(tempPath)}`, terminalSize, stream);
23
+ }
24
+ export function spawnHtopProcess(pidList, terminalSize, stream) {
25
+ return spawnScriptProcess(`htop -p ${shellQuote(pidList)}`, terminalSize, stream);
26
+ }
@@ -0,0 +1,11 @@
1
+ export interface TerminalSize {
2
+ cols: number;
3
+ rows: number;
4
+ }
5
+ export declare function shellQuote(value: string): string;
6
+ export declare function toTtyLines(text: string): string;
7
+ export declare function withTerminalSize(command: string, terminalSize: TerminalSize): string;
8
+ export declare function resolvePath(base: string, inputPath: string): string;
9
+ export declare function collectChildPids(parentPid: number): Promise<number[]>;
10
+ export declare function getVisibleHtopPidList(rootPid?: number): Promise<string | null>;
11
+ //# sourceMappingURL=shellRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellRuntime.d.ts","sourceRoot":"","sources":["../../src/modules/shellRuntime.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,YAAY,GACxB,MAAM,CAUR;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB3E;AAED,wBAAsB,qBAAqB,CAC1C,OAAO,SAAc,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQxB"}