typescript-virtual-container 1.6.1 → 1.6.3

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.
@@ -43,7 +43,7 @@ export const dmesgCommand = {
43
43
  const n = args.includes("-n") ? parseInt(args[args.indexOf("-n") + 1] ?? "20", 10) : 20;
44
44
  const msgs = [
45
45
  "[ 0.000000] Booting Linux on physical CPU 0x0",
46
- "[ 0.000000] Linux version 6.1.0-fortune (gcc version 12.2.0)",
46
+ "[ 0.000000] Linux version 6.1.0-fortune (gcc (Fortune 13.3.0-nyx1) 13.3.0)",
47
47
  "[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-6.1.0 root=/dev/sda1 ro quiet",
48
48
  "[ 0.000000] BIOS-provided physical RAM map:",
49
49
  "[ 0.000000] ACPI: IRQ0 used by override.",
@@ -429,7 +429,7 @@ OPTIONS
429
429
  "dpkg": `DPKG(1) User Commands DPKG(1)
430
430
 
431
431
  NAME
432
- dpkg - package manager for Debian-like systems
432
+ dpkg - package manager for Fortune GNU/Linux
433
433
 
434
434
  SYNOPSIS
435
435
  dpkg [OPTION]... ACTION
@@ -23,7 +23,7 @@ export const realpathCommand = {
23
23
  const resolved = shell.vfs.isSymlink(p)
24
24
  ? shell.vfs.resolveSymlink(p)
25
25
  : p;
26
- return { stdout: path.posix.normalize(resolved) + "\n", exitCode: 0 };
26
+ return { stdout: `${path.posix.normalize(resolved)}\n`, exitCode: 0 };
27
27
  },
28
28
  };
29
29
  /**
@@ -106,7 +106,7 @@ export const stringsCommand = {
106
106
  }
107
107
  if (current.length >= 4)
108
108
  results.push(current);
109
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
109
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
110
110
  },
111
111
  };
112
112
  /**
@@ -228,6 +228,6 @@ export const fmtCommand = {
228
228
  }
229
229
  if (current)
230
230
  lines.push(current);
231
- return { stdout: lines.join("\n") + "\n", exitCode: 0 };
231
+ return { stdout: `${lines.join("\n")}\n`, exitCode: 0 };
232
232
  },
233
233
  };
@@ -0,0 +1,2 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const mousepadCommand: ShellModule;
@@ -0,0 +1,21 @@
1
+ export const mousepadCommand = {
2
+ name: "mousepad",
3
+ aliases: ["gedit", "xed"],
4
+ params: ["[file]"],
5
+ description: "Open a text file in the desktop text editor",
6
+ category: "desktop",
7
+ run(ctx) {
8
+ const dm = ctx.shell.desktopManager;
9
+ if (!dm) {
10
+ return { stderr: "mousepad: desktop is only available in the browser", exitCode: 1 };
11
+ }
12
+ if (!dm.isActive()) {
13
+ return { stderr: "mousepad: no desktop session running (start with startxfce4)", exitCode: 1 };
14
+ }
15
+ const path = ctx.args[0]
16
+ ? ctx.args[0].startsWith("/") ? ctx.args[0] : `${ctx.cwd}/${ctx.args[0]}`
17
+ : "/root/untitled.txt";
18
+ dm.createEditorWindow(path);
19
+ return { exitCode: 0 };
20
+ },
21
+ };
@@ -42,7 +42,7 @@ export const ncCommand = {
42
42
  const nonFlag = args.filter((a) => !a.startsWith("-"));
43
43
  const host = nonFlag[0];
44
44
  const portNum = nonFlag[1] ? parseInt(nonFlag[1], 10) : NaN;
45
- if (host && !isNaN(portNum)) {
45
+ if (host && !Number.isNaN(portNum)) {
46
46
  return new Promise((resolve) => {
47
47
  const socket = net.createConnection({ host, port: portNum }, () => {
48
48
  if (verbose) {
@@ -27,7 +27,7 @@ export const pgrepCommand = {
27
27
  }
28
28
  if (results.length === 0)
29
29
  return { exitCode: 1 };
30
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
30
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
31
31
  }
32
32
  catch {
33
33
  return { stderr: "pgrep: invalid pattern\n", exitCode: 2 };
@@ -109,6 +109,9 @@ import { pgrepCommand, pkillCommand } from "./procUtils";
109
109
  import { lscpuCommand, lsusbCommand, lspciCommand } from "./sysinfo";
110
110
  import { joinCommand, commCommand, splitCommand, csplitCommand } from "./textutils";
111
111
  import { topCommand } from "./top";
112
+ import { startxfce4Command } from "./startxfce4";
113
+ import { thunarCommand } from "./xfceDesktop";
114
+ import { mousepadCommand } from "./mousepad";
112
115
  const BASE_COMMANDS = [
113
116
  // Navigation
114
117
  pwdCommand,
@@ -258,6 +261,10 @@ const BASE_COMMANDS = [
258
261
  nodeCommand,
259
262
  python3Command,
260
263
  exprCommand,
264
+ // Desktop
265
+ startxfce4Command,
266
+ thunarCommand,
267
+ mousepadCommand,
261
268
  // System (extended)
262
269
  uptimeCommand,
263
270
  freeCommand,
@@ -0,0 +1,2 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const startxfce4Command: ShellModule;
@@ -0,0 +1,13 @@
1
+ export const startxfce4Command = {
2
+ name: "startxfce4",
3
+ aliases: ["xfce4-session"],
4
+ params: [],
5
+ async run(ctx) {
6
+ const dm = ctx.shell.desktopManager;
7
+ if (!dm) {
8
+ return { stderr: "startxfce4: desktop is only available in the browser", exitCode: 1 };
9
+ }
10
+ await dm.start();
11
+ return { exitCode: 0 };
12
+ },
13
+ };
@@ -27,7 +27,7 @@ export const lscpuCommand = {
27
27
  `Socket(s): 1`,
28
28
  `Vendor ID: GenuineIntel`,
29
29
  ];
30
- return { stdout: lines.join("\n") + "\n", exitCode: 0 };
30
+ return { stdout: `${lines.join("\n")}\n`, exitCode: 0 };
31
31
  },
32
32
  };
33
33
  /**
@@ -46,7 +46,7 @@ export const lsusbCommand = {
46
46
  "Bus 001 Device 002: ID 80ee:0021 VirtualBox USB Tablet",
47
47
  "Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub",
48
48
  ];
49
- return { stdout: devices.join("\n") + "\n", exitCode: 0 };
49
+ return { stdout: `${devices.join("\n")}\n`, exitCode: 0 };
50
50
  },
51
51
  };
52
52
  /**
@@ -68,6 +68,6 @@ export const lspciCommand = {
68
68
  "00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller",
69
69
  "00:04.0 SATA controller: Intel Corporation 82801IR/IO (ICH9R) SATA Controller",
70
70
  ];
71
- return { stdout: devices.join("\n") + "\n", exitCode: 0 };
71
+ return { stdout: `${devices.join("\n")}\n`, exitCode: 0 };
72
72
  },
73
73
  };
@@ -49,7 +49,7 @@ export const joinCommand = {
49
49
  results.push(`${match} ${line}`);
50
50
  }
51
51
  }
52
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
52
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
53
53
  },
54
54
  };
55
55
  /**
@@ -105,7 +105,7 @@ export const commCommand = {
105
105
  const col3 = i < both.length ? both[i] : "";
106
106
  results.push(`${col1}\t${col2}\t${col3}`);
107
107
  }
108
- return { stdout: results.join("\n") + "\n", exitCode: 0 };
108
+ return { stdout: `${results.join("\n")}\n`, exitCode: 0 };
109
109
  },
110
110
  };
111
111
  /**
@@ -49,6 +49,6 @@ export const topCommand = {
49
49
  const status = p.status === "running" ? "R" : "S";
50
50
  lines.push(`${String(p.pid).padStart(5)} ${p.username.padEnd(8).slice(0, 8)} 20 0 ${String(virt).padStart(7)} ${String(res).padStart(6)} ${String(shr).padStart(6)} ${status} ${cpu.padStart(4)} ${mem.padStart(5)} 0:00.00 ${p.command}`);
51
51
  });
52
- return { stdout: lines.join("\n") + "\n", exitCode: 0 };
52
+ return { stdout: `${lines.join("\n")}\n`, exitCode: 0 };
53
53
  },
54
54
  };
@@ -12,7 +12,7 @@ export const unameCommand = {
12
12
  run: ({ shell, args }) => {
13
13
  const all = ifFlag(args, ["-a"]);
14
14
  const sysname = "Linux";
15
- const release = shell.properties?.kernel ?? "5.15.0";
15
+ const release = shell.properties?.kernel ?? "1.0.0+itsrealfortune+1-amd64";
16
16
  const machine = shell.properties?.arch ?? "x86_64";
17
17
  const hostname = shell.hostname;
18
18
  if (all)
@@ -0,0 +1,2 @@
1
+ import type { ShellModule } from "../types/commands";
2
+ export declare const thunarCommand: ShellModule;
@@ -0,0 +1,13 @@
1
+ export const thunarCommand = {
2
+ name: "thunar",
3
+ params: [],
4
+ run(ctx) {
5
+ const dm = ctx.shell.desktopManager;
6
+ if (!dm?.isActive()) {
7
+ return { stderr: "thunar: desktop is not running (start it with startxfce4)", exitCode: 1 };
8
+ }
9
+ const path = ctx.args[0] || ctx.env.vars.HOME || "/root";
10
+ dm.createThunarWindow(path);
11
+ return { exitCode: 0 };
12
+ },
13
+ };
@@ -5,6 +5,7 @@
5
5
  * latency and packet loss. Used by the `ip`, `ping`, and `netstat` commands
6
6
  * to produce dynamic, deterministic output instead of hardcoded strings.
7
7
  */
8
+ /** Generates a random MAC address in the 02:42:xx:xx:xx:xx range. */
8
9
  function randomMac() {
9
10
  const hex = () => Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
10
11
  return `02:42:${hex()}:${hex()}:${hex()}:${hex()}`;
@@ -0,0 +1,104 @@
1
+ import type { VirtualShell } from "../VirtualShell";
2
+ import type { ShellStream } from "../types/streams";
3
+ import { WebTermRenderer } from "./webTermRenderer";
4
+ export interface TerminalContent {
5
+ type: "terminal";
6
+ termRenderer: WebTermRenderer;
7
+ dataListeners: Array<(chunk: Buffer) => void>;
8
+ preEl?: HTMLPreElement;
9
+ stream?: ShellStream;
10
+ }
11
+ export interface ThunarContent {
12
+ type: "thunar";
13
+ path: string;
14
+ }
15
+ export interface AboutContent {
16
+ type: "about";
17
+ }
18
+ export interface EditorContent {
19
+ type: "editor";
20
+ path: string;
21
+ dirty: boolean;
22
+ }
23
+ export type WindowContent = TerminalContent | ThunarContent | AboutContent | EditorContent;
24
+ export interface DesktopWindow {
25
+ id: string;
26
+ title: string;
27
+ x: number;
28
+ y: number;
29
+ width: number;
30
+ height: number;
31
+ minimized: boolean;
32
+ focused: boolean;
33
+ zIndex: number;
34
+ content: WindowContent;
35
+ }
36
+ export interface DesktopState {
37
+ active: boolean;
38
+ windows: DesktopWindow[];
39
+ menuOpen: boolean;
40
+ clock: string;
41
+ focusedWindowId: string | null;
42
+ }
43
+ export declare class DesktopManager {
44
+ private shell;
45
+ private container;
46
+ private active;
47
+ private windows;
48
+ private zCounter;
49
+ private menuOpen;
50
+ private nextWinId;
51
+ private clockInterval?;
52
+ private onExit;
53
+ private stopResolve;
54
+ private dragState;
55
+ private _renderGuard;
56
+ private readonly trashPath;
57
+ private docListeners;
58
+ private pendingTimeouts;
59
+ constructor(shell: VirtualShell, container: HTMLElement);
60
+ isActive(): boolean;
61
+ setOnExit(cb: () => void): void;
62
+ start(): Promise<void>;
63
+ stop(): void;
64
+ getFocusedTerminal(): {
65
+ stream: ShellStream;
66
+ dataListeners: Array<(chunk: Buffer) => void>;
67
+ preEl: HTMLPreElement;
68
+ } | null;
69
+ handleKeyDown(e: KeyboardEvent): void;
70
+ handlePaste(e: ClipboardEvent): void;
71
+ createTerminalWindow(): string;
72
+ createThunarWindow(path?: string): string;
73
+ createEditorWindow(path?: string): string;
74
+ createAboutWindow(): string;
75
+ closeWindow(id: string): void;
76
+ toggleMinimize(id: string): void;
77
+ focusWindow(id: string): void;
78
+ private createWindow;
79
+ private ensureWindowElement;
80
+ private renderWindowElement;
81
+ private addDocListener;
82
+ private removeAllDocListeners;
83
+ private setupEventDelegation;
84
+ private renderAll;
85
+ private renderPanel;
86
+ private renderDesktopIcons;
87
+ private renderWindows;
88
+ private renderWindowPositions;
89
+ private renderTerminalContentById;
90
+ private renderThunarContent;
91
+ private renderEditorContent;
92
+ private saveEditor;
93
+ private renderAboutContent;
94
+ private updateClock;
95
+ private showContextMenu;
96
+ private closeContextMenu;
97
+ private ensureTrashDir;
98
+ private refreshThunarWindow;
99
+ private moveToTrash;
100
+ private trashRestore;
101
+ private trashDelete;
102
+ private renamePrompt;
103
+ private escapeHtml;
104
+ }