typescript-virtual-container 1.4.9 → 1.5.1

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 (135) hide show
  1. package/.vscode/settings.json +1 -1
  2. package/README.md +141 -89
  3. package/builds/fortune-nyx-v1.5.1-directbash-k6.1.0.mjs +1768 -0
  4. package/builds/fortune-nyx-v1.5.1-ssh-nosftp.js +1768 -0
  5. package/builds/fortune-nyx-v1.5.1-ssh.cjs +1769 -0
  6. package/bun.lock +3 -3
  7. package/dist/SSHMimic/exec.js +2 -2
  8. package/dist/SSHMimic/exec.js.map +1 -1
  9. package/dist/SSHMimic/index.d.ts.map +1 -1
  10. package/dist/SSHMimic/index.js +2 -1
  11. package/dist/SSHMimic/index.js.map +1 -1
  12. package/dist/SSHMimic/sftp.d.ts.map +1 -1
  13. package/dist/SSHMimic/sftp.js +4 -3
  14. package/dist/SSHMimic/sftp.js.map +1 -1
  15. package/dist/VirtualFileSystem/index.d.ts +14 -0
  16. package/dist/VirtualFileSystem/index.d.ts.map +1 -1
  17. package/dist/VirtualFileSystem/index.js +51 -3
  18. package/dist/VirtualFileSystem/index.js.map +1 -1
  19. package/dist/VirtualFileSystem/journal.d.ts.map +1 -1
  20. package/dist/VirtualFileSystem/journal.js +13 -5
  21. package/dist/VirtualFileSystem/journal.js.map +1 -1
  22. package/dist/VirtualShell/shell.js +12 -12
  23. package/dist/VirtualShell/shell.js.map +1 -1
  24. package/dist/VirtualUserManager/index.js +8 -11
  25. package/dist/VirtualUserManager/index.js.map +1 -1
  26. package/dist/commands/apt.js +3 -3
  27. package/dist/commands/apt.js.map +1 -1
  28. package/dist/commands/cd.d.ts.map +1 -1
  29. package/dist/commands/cd.js +2 -1
  30. package/dist/commands/cd.js.map +1 -1
  31. package/dist/commands/helpers.d.ts +1 -1
  32. package/dist/commands/helpers.d.ts.map +1 -1
  33. package/dist/commands/helpers.js +3 -2
  34. package/dist/commands/helpers.js.map +1 -1
  35. package/dist/commands/index.d.ts +1 -1
  36. package/dist/commands/index.d.ts.map +1 -1
  37. package/dist/commands/index.js +1 -1
  38. package/dist/commands/index.js.map +1 -1
  39. package/dist/commands/lsb-release.js +1 -1
  40. package/dist/commands/lsb-release.js.map +1 -1
  41. package/dist/commands/runtime.d.ts +2 -0
  42. package/dist/commands/runtime.d.ts.map +1 -1
  43. package/dist/commands/runtime.js +5 -1
  44. package/dist/commands/runtime.js.map +1 -1
  45. package/dist/modules/linuxRootfs.d.ts +9 -5
  46. package/dist/modules/linuxRootfs.d.ts.map +1 -1
  47. package/dist/modules/linuxRootfs.js +1079 -148
  48. package/dist/modules/linuxRootfs.js.map +1 -1
  49. package/dist/self-standalone.js +22 -12
  50. package/dist/self-standalone.js.map +1 -1
  51. package/docs/assets/hierarchy.js +1 -1
  52. package/docs/classes/HoneyPot.html +9 -9
  53. package/docs/classes/IdleManager.html +8 -8
  54. package/docs/classes/SshClient.html +18 -18
  55. package/docs/classes/VirtualFileSystem.html +34 -34
  56. package/docs/classes/VirtualPackageManager.html +13 -13
  57. package/docs/classes/VirtualSftpServer.html +3 -3
  58. package/docs/classes/VirtualShell.html +28 -28
  59. package/docs/classes/VirtualSshServer.html +5 -5
  60. package/docs/classes/VirtualUserManager.html +27 -27
  61. package/docs/functions/assertDiff.html +2 -2
  62. package/docs/functions/diffSnapshots.html +2 -2
  63. package/docs/functions/formatDiff.html +2 -2
  64. package/docs/functions/getArg.html +2 -2
  65. package/docs/functions/getFlag.html +2 -2
  66. package/docs/functions/ifFlag.html +2 -2
  67. package/docs/hierarchy.html +1 -1
  68. package/docs/index.html +37 -31
  69. package/docs/interfaces/AuditLogEntry.html +3 -3
  70. package/docs/interfaces/CommandContext.html +12 -12
  71. package/docs/interfaces/CommandResult.html +13 -13
  72. package/docs/interfaces/ExecStream.html +6 -6
  73. package/docs/interfaces/HoneyPotStats.html +3 -3
  74. package/docs/interfaces/IdleManagerOptions.html +3 -3
  75. package/docs/interfaces/InstalledPackage.html +11 -11
  76. package/docs/interfaces/NanoEditorSession.html +5 -5
  77. package/docs/interfaces/PackageDefinition.html +14 -14
  78. package/docs/interfaces/PackageFile.html +5 -5
  79. package/docs/interfaces/PasswordChallenge.html +9 -9
  80. package/docs/interfaces/RemoveOptions.html +3 -3
  81. package/docs/interfaces/ShellEnv.html +4 -4
  82. package/docs/interfaces/ShellModule.html +8 -8
  83. package/docs/interfaces/ShellProperties.html +5 -5
  84. package/docs/interfaces/ShellStream.html +7 -7
  85. package/docs/interfaces/SudoChallenge.html +9 -9
  86. package/docs/interfaces/VfsBaseNode.html +7 -7
  87. package/docs/interfaces/VfsDiff.html +6 -6
  88. package/docs/interfaces/VfsDiffEntry.html +4 -4
  89. package/docs/interfaces/VfsDiffModified.html +6 -6
  90. package/docs/interfaces/VfsDirectoryNode.html +8 -8
  91. package/docs/interfaces/VfsFileNode.html +9 -9
  92. package/docs/interfaces/VfsOptions.html +6 -6
  93. package/docs/interfaces/VfsSnapshot.html +3 -3
  94. package/docs/interfaces/VfsSnapshotBaseNode.html +4 -4
  95. package/docs/interfaces/VfsSnapshotDirectoryNode.html +5 -5
  96. package/docs/interfaces/VfsSnapshotFileNode.html +6 -6
  97. package/docs/interfaces/VirtualActiveSession.html +7 -7
  98. package/docs/interfaces/VirtualSftpServerOptions.html +3 -3
  99. package/docs/interfaces/VirtualShellVfsLike.html +3 -3
  100. package/docs/interfaces/VirtualShellVfsOptions.html +3 -3
  101. package/docs/interfaces/WriteFileOptions.html +4 -4
  102. package/docs/modules.html +1 -1
  103. package/docs/types/ArgParseOptions.html +3 -3
  104. package/docs/types/CommandMode.html +2 -2
  105. package/docs/types/CommandOutcome.html +2 -2
  106. package/docs/types/IdleState.html +1 -1
  107. package/docs/types/VfsNodeStats.html +2 -2
  108. package/docs/types/VfsNodeType.html +2 -2
  109. package/docs/types/VfsPersistenceMode.html +2 -2
  110. package/docs/types/VfsSnapshotNode.html +2 -2
  111. package/package.json +6 -5
  112. package/scripts/build-all.mjs +198 -0
  113. package/scripts/build-names.mjs +44 -0
  114. package/src/SSHMimic/exec.ts +2 -2
  115. package/src/SSHMimic/index.ts +2 -1
  116. package/src/SSHMimic/sftp.ts +4 -3
  117. package/src/VirtualFileSystem/index.ts +46 -3
  118. package/src/VirtualFileSystem/journal.ts +12 -5
  119. package/src/VirtualShell/shell.ts +12 -12
  120. package/src/VirtualUserManager/index.ts +11 -11
  121. package/src/commands/apt.ts +3 -3
  122. package/src/commands/cd.ts +2 -1
  123. package/src/commands/helpers.ts +3 -2
  124. package/src/commands/index.ts +1 -1
  125. package/src/commands/lsb-release.ts +1 -1
  126. package/src/commands/runtime.ts +6 -1
  127. package/src/modules/linuxRootfs.ts +1293 -207
  128. package/src/self-standalone.ts +26 -12
  129. package/tests/new-features.test.ts +2 -2
  130. package/tests/sftp.test.ts +13 -13
  131. package/builds/self-standalone.js +0 -1299
  132. package/builds/standalone-wo-sftp.js +0 -1300
  133. package/builds/standalone.cjs +0 -1301
  134. /package/builds/{web-full-api.min.js → fortune-nyx-v1.5.1-web-full.min.js} +0 -0
  135. /package/builds/{web.min.js → fortune-nyx-v1.5.1-web.min.js} +0 -0
@@ -2,7 +2,7 @@ import type { ChildProcessWithoutNullStreams } from "node:child_process";
2
2
  import { readFile, unlink, writeFile } from "node:fs/promises";
3
3
  import * as path from "node:path";
4
4
  import type { ShellProperties, VirtualShell } from ".";
5
- import { getCommandNames, makeDefaultEnv, runCommand } from "../commands";
5
+ import { getCommandNames, makeDefaultEnv, runCommand, userHome } from "../commands";
6
6
  import {
7
7
  spawnHtopProcess,
8
8
  spawnNanoEditorProcess,
@@ -55,12 +55,12 @@ export function startShell(
55
55
  let history = loadHistory(shell.vfs, authUser);
56
56
  let historyIndex: number | null = null;
57
57
  let historyDraft = "";
58
- let cwd = `/home/${authUser}`;
58
+ let cwd = userHome(authUser);
59
59
  const shellEnv: ShellEnv = makeDefaultEnv(authUser, hostname);
60
60
  let nanoSession: NanoSession | null = null;
61
61
  let pendingSudo: PendingSudo | null = null;
62
62
  const buildCurrentPrompt = (): string => {
63
- const homePath = `/home/${authUser}`;
63
+ const homePath = userHome(authUser);
64
64
  const cwdLabel = cwd === homePath ? "~" : path.posix.basename(cwd) || "/";
65
65
  return buildPrompt(authUser, hostname, cwdLabel);
66
66
  };
@@ -71,7 +71,7 @@ export function startShell(
71
71
 
72
72
  // Load .bashrc if it exists
73
73
  void (async () => {
74
- const bashrcPath = `/home/${authUser}/.bashrc`;
74
+ const bashrcPath = `${userHome(authUser)}/.bashrc`;
75
75
  if (shell.vfs.exists(bashrcPath)) {
76
76
  try {
77
77
  const bashrc = shell.vfs.readFile(bashrcPath);
@@ -146,7 +146,7 @@ export function startShell(
146
146
  if (!challenge.commandLine) {
147
147
  authUser = challenge.targetUser;
148
148
  if (challenge.loginShell) {
149
- cwd = `/home/${authUser}`;
149
+ cwd = userHome(authUser);
150
150
  }
151
151
  shell.users.updateSession(sessionId, authUser, remoteAddress);
152
152
  stream.write("\r\n");
@@ -154,7 +154,7 @@ export function startShell(
154
154
  return;
155
155
  }
156
156
 
157
- const runCwd = challenge.loginShell ? `/home/${challenge.targetUser}` : cwd;
157
+ const runCwd = challenge.loginShell ? userHome(challenge.targetUser) : cwd;
158
158
  const result = await Promise.resolve(
159
159
  runCommand(
160
160
  challenge.commandLine,
@@ -196,7 +196,7 @@ export function startShell(
196
196
 
197
197
  if (result.switchUser) {
198
198
  authUser = result.switchUser;
199
- cwd = result.nextCwd ?? `/home/${authUser}`;
199
+ cwd = result.nextCwd ?? userHome(authUser);
200
200
  shell.users.updateSession(sessionId, authUser, remoteAddress);
201
201
  } else if (result.nextCwd) {
202
202
  cwd = result.nextCwd;
@@ -388,11 +388,11 @@ export function startShell(
388
388
  }
389
389
 
390
390
  const data = history.length > 0 ? `${history.join("\n")}\n` : "";
391
- shell.vfs.writeFile(`/home/${authUser}/.bash_history`, data);
391
+ shell.vfs.writeFile(`${userHome(authUser)}/.bash_history`, data);
392
392
  }
393
393
 
394
394
  function readLastLogin(): { at: string; from: string } | null {
395
- const lastlogPath = `/home/${authUser}/.lastlog.json`;
395
+ const lastlogPath = `${userHome(authUser)}/.lastlog.json`;
396
396
  if (!shell.vfs.exists(lastlogPath)) {
397
397
  return null;
398
398
  }
@@ -408,7 +408,7 @@ export function startShell(
408
408
  }
409
409
 
410
410
  function writeLastLogin(nowIso: string): void {
411
- const lastlogPath = `/home/${authUser}/.lastlog`;
411
+ const lastlogPath = `${userHome(authUser)}/.lastlog`;
412
412
  shell.vfs.writeFile(
413
413
  lastlogPath,
414
414
  JSON.stringify({ at: nowIso, from: remoteAddress }),
@@ -651,7 +651,7 @@ export function startShell(
651
651
 
652
652
  if (result.switchUser) {
653
653
  authUser = result.switchUser;
654
- cwd = result.nextCwd ?? `/home/${authUser}`;
654
+ cwd = result.nextCwd ?? userHome(authUser);
655
655
  shell.users.updateSession(sessionId, authUser, remoteAddress);
656
656
  lineBuffer = "";
657
657
  cursorPos = 0;
@@ -686,7 +686,7 @@ export function startShell(
686
686
  }
687
687
 
688
688
  function loadHistory(vfs: VirtualFileSystem, authUser: string): string[] {
689
- const historyPath = `/home/${authUser}/.bash_history`;
689
+ const historyPath = `${userHome(authUser)}/.bash_history`;
690
690
  if (!vfs.exists(historyPath)) {
691
691
  vfs.writeFile(historyPath, "");
692
692
  return [];
@@ -103,14 +103,14 @@ export class VirtualUserManager extends EventEmitter {
103
103
  // changed = true;
104
104
  // }
105
105
 
106
- // const homePath = `/home/root`;
107
- // if (!this.vfs.exists(homePath)) {
108
- // this.vfs.mkdir(homePath, 0o755);
109
- // this.vfs.writeFile(
110
- // `${homePath}/README.txt`,
111
- // `Welcome to the virtual environment, root`,
112
- // );
113
- // }
106
+ const homePath = "/root";
107
+ if (!this.vfs.exists(homePath)) {
108
+ this.vfs.mkdir(homePath, 0o755);
109
+ this.vfs.writeFile(
110
+ `${homePath}/README.txt`,
111
+ `Welcome to the virtual environment, root`,
112
+ );
113
+ }
114
114
 
115
115
  if (changed) {
116
116
  await this.persist();
@@ -173,7 +173,7 @@ export class VirtualUserManager extends EventEmitter {
173
173
  */
174
174
  public getUsageBytes(username: string): number {
175
175
  perf.mark("getUsageBytes");
176
- const homePath = `/home/${username}`;
176
+ const homePath = username === "root" ? "/root" : `/home/${username}`;
177
177
  if (!this.vfs.exists(homePath)) {
178
178
  return 0;
179
179
  }
@@ -202,7 +202,7 @@ export class VirtualUserManager extends EventEmitter {
202
202
  }
203
203
 
204
204
  const normalizedPath = normalizeVfsPath(targetPath);
205
- const homePath = normalizeVfsPath(`/home/${username}`);
205
+ const homePath = normalizeVfsPath(username === "root" ? "/root" : `/home/${username}`);
206
206
  const inUserHome =
207
207
  normalizedPath === homePath || normalizedPath.startsWith(`${homePath}/`);
208
208
  if (!inUserHome) {
@@ -279,7 +279,7 @@ export class VirtualUserManager extends EventEmitter {
279
279
  if (this.autoSudoForNewUsers) {
280
280
  this.sudoers.add(username);
281
281
  }
282
- const homePath = `/home/${username}`;
282
+ const homePath = username === "root" ? "/root" : `/home/${username}`;
283
283
  if (!this.vfs.exists(homePath)) {
284
284
  this.vfs.mkdir(homePath, 0o755);
285
285
  this.vfs.writeFile(
@@ -57,8 +57,8 @@ export const aptCommand: ShellModule = {
57
57
  case "update": {
58
58
  return {
59
59
  stdout: [
60
- "Hit:1 fortune://packages.fortune.local aurora InRelease",
61
- "Hit:2 fortune://security.fortune.local aurora-security InRelease",
60
+ "Hit:1 fortune://packages.fortune.local nyx InRelease",
61
+ "Hit:2 fortune://security.fortune.local nyx-security InRelease",
62
62
  "Reading package lists... Done",
63
63
  "Building dependency tree... Done",
64
64
  "Reading state information... Done",
@@ -218,7 +218,7 @@ export const aptCacheCommand: ShellModule = {
218
218
  ` Candidate: ${def.version}`,
219
219
  ` Version table:`,
220
220
  ` ${def.version} 500`,
221
- ` 500 fortune://packages.fortune.local aurora/main amd64 Packages`,
221
+ ` 500 fortune://packages.fortune.local nyx/main amd64 Packages`,
222
222
  ].join("\n"),
223
223
  exitCode: 0,
224
224
  };
@@ -1,5 +1,6 @@
1
1
  import type { ShellModule } from "../types/commands";
2
2
  import { assertPathAccess, resolvePath } from "./helpers";
3
+ import { userHome } from "./runtime";
3
4
 
4
5
  /**
5
6
  * Change current working directory.
@@ -12,7 +13,7 @@ export const cdCommand: ShellModule = {
12
13
  category: "navigation",
13
14
  params: ["[path]"],
14
15
  run: ({ authUser, shell, cwd, args }) => {
15
- const target = resolvePath(cwd, args[0] ?? `~`);
16
+ const target = resolvePath(cwd, args[0] ?? "~", userHome(authUser));
16
17
  assertPathAccess(authUser, target, "cd");
17
18
  const stats = shell.vfs.stat(target);
18
19
  if (stats.type !== "directory") {
@@ -28,12 +28,13 @@ export function normalizeTerminalOutput(text: string): string {
28
28
  .trimEnd();
29
29
  }
30
30
 
31
- export function resolvePath(cwd: string, inputPath: string): string {
31
+ export function resolvePath(cwd: string, inputPath: string, homeDir?: string): string {
32
32
  if (!inputPath || inputPath.trim() === "") {
33
33
  return cwd;
34
34
  }
35
35
  if (inputPath.startsWith("~")) {
36
- return path.posix.normalize(`/home/${inputPath.slice(1)}`);
36
+ const home = homeDir ?? "/root";
37
+ return path.posix.normalize(`${home}${inputPath.slice(1)}`);
37
38
  }
38
39
  return inputPath.startsWith("/")
39
40
  ? path.posix.normalize(inputPath)
@@ -6,4 +6,4 @@ export {
6
6
  resolveModule
7
7
  } from "./registry";
8
8
 
9
- export { makeDefaultEnv, runCommand, runCommandDirect } from "./runtime";
9
+ export { makeDefaultEnv, runCommand, runCommandDirect, userHome } from "./runtime";
@@ -13,7 +13,7 @@ export const lsbReleaseCommand: ShellModule = {
13
13
  params: ["[-a] [-i] [-d] [-r] [-c]"],
14
14
  run: ({ args, shell }) => {
15
15
  let osName = shell.properties?.os ?? "Fortune GNU/Linux x64";
16
- let codename = "aurora";
16
+ let codename = "nyx";
17
17
  let version = "1.0";
18
18
 
19
19
  try {
@@ -11,11 +11,16 @@ import { expandAsync, expandBraces } from "../utils/expand";
11
11
  import { tokenizeCommand } from "../utils/tokenize";
12
12
  import { resolveModule } from "./registry";
13
13
 
14
+ /** Returns the home directory path for a given user. Root lives at /root. */
15
+ export function userHome(authUser: string): string {
16
+ return authUser === "root" ? "/root" : `/home/${authUser}`;
17
+ }
18
+
14
19
  export function makeDefaultEnv(authUser: string, hostname: string): ShellEnv {
15
20
  return {
16
21
  vars: {
17
22
  PATH: "/usr/local/bin:/usr/bin:/bin",
18
- HOME: `/home/${authUser}`,
23
+ HOME: userHome(authUser),
19
24
  USER: authUser,
20
25
  LOGNAME: authUser,
21
26
  SHELL: "/bin/sh",