typescript-virtual-container 1.4.7 → 1.4.9
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/README.md +1 -2
- package/benchmark-results.txt +21 -21
- package/builds/self-standalone.js +979 -168
- package/builds/standalone-wo-sftp.js +982 -173
- package/builds/standalone.cjs +989 -179
- package/builds/web-full-api.min.js +0 -1
- package/builds/web.min.js +0 -1
- package/dist/Honeypot/index.d.ts +6 -0
- package/dist/Honeypot/index.d.ts.map +1 -1
- package/dist/Honeypot/index.js +20 -0
- package/dist/Honeypot/index.js.map +1 -1
- package/dist/SSHMimic/index.d.ts +6 -5
- package/dist/SSHMimic/index.d.ts.map +1 -1
- package/dist/SSHMimic/index.js +8 -5
- package/dist/SSHMimic/index.js.map +1 -1
- package/dist/SSHMimic/sftp.d.ts +1 -0
- package/dist/SSHMimic/sftp.d.ts.map +1 -1
- package/dist/SSHMimic/sftp.js.map +1 -1
- package/dist/VirtualFileSystem/binaryPack.d.ts.map +1 -1
- package/dist/VirtualFileSystem/binaryPack.js +21 -9
- package/dist/VirtualFileSystem/binaryPack.js.map +1 -1
- package/dist/VirtualFileSystem/index.d.ts +25 -0
- package/dist/VirtualFileSystem/index.d.ts.map +1 -1
- package/dist/VirtualFileSystem/index.js +152 -47
- package/dist/VirtualFileSystem/index.js.map +1 -1
- package/dist/VirtualFileSystem/internalTypes.d.ts +23 -4
- package/dist/VirtualFileSystem/internalTypes.d.ts.map +1 -1
- package/dist/VirtualFileSystem/journal.d.ts +1 -0
- package/dist/VirtualFileSystem/journal.d.ts.map +1 -1
- package/dist/VirtualFileSystem/journal.js.map +1 -1
- package/dist/VirtualFileSystem/path.js +1 -1
- package/dist/VirtualFileSystem/path.js.map +1 -1
- package/dist/VirtualShell/idleManager.d.ts +69 -0
- package/dist/VirtualShell/idleManager.d.ts.map +1 -0
- package/dist/VirtualShell/idleManager.js +110 -0
- package/dist/VirtualShell/idleManager.js.map +1 -0
- package/dist/VirtualShell/index.d.ts +41 -1
- package/dist/VirtualShell/index.d.ts.map +1 -1
- package/dist/VirtualShell/index.js +54 -1
- package/dist/VirtualShell/index.js.map +1 -1
- package/dist/VirtualUserManager/index.d.ts +4 -2
- package/dist/VirtualUserManager/index.d.ts.map +1 -1
- package/dist/VirtualUserManager/index.js +0 -1
- package/dist/VirtualUserManager/index.js.map +1 -1
- package/dist/commands/command-helpers.d.ts +5 -2
- package/dist/commands/command-helpers.d.ts.map +1 -1
- package/dist/commands/command-helpers.js.map +1 -1
- package/dist/commands/man.d.ts.map +1 -1
- package/dist/commands/man.js +5 -28
- package/dist/commands/man.js.map +1 -1
- package/dist/commands/manuals-bundle.d.ts +11 -0
- package/dist/commands/manuals-bundle.d.ts.map +1 -0
- package/dist/commands/manuals-bundle.js +898 -0
- package/dist/commands/manuals-bundle.js.map +1 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/linuxRootfs.d.ts +8 -1
- package/dist/modules/linuxRootfs.d.ts.map +1 -1
- package/dist/modules/linuxRootfs.js +47 -14
- package/dist/modules/linuxRootfs.js.map +1 -1
- package/dist/self-standalone.js +15 -0
- package/dist/self-standalone.js.map +1 -1
- package/dist/standalone.js +22 -0
- package/dist/standalone.js.map +1 -1
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/HoneyPot.html +9 -9
- package/docs/classes/IdleManager.html +162 -0
- package/docs/classes/SshClient.html +18 -18
- package/docs/classes/VirtualFileSystem.html +50 -33
- package/docs/classes/VirtualPackageManager.html +13 -13
- package/docs/classes/VirtualSftpServer.html +3 -3
- package/docs/classes/VirtualShell.html +47 -28
- package/docs/classes/VirtualSshServer.html +12 -7
- package/docs/classes/VirtualUserManager.html +30 -30
- package/docs/functions/assertDiff.html +2 -2
- package/docs/functions/diffSnapshots.html +2 -2
- package/docs/functions/formatDiff.html +2 -2
- package/docs/functions/getArg.html +3 -3
- package/docs/functions/getFlag.html +2 -2
- package/docs/functions/ifFlag.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +4 -5
- package/docs/interfaces/AuditLogEntry.html +3 -3
- package/docs/interfaces/CommandContext.html +13 -13
- package/docs/interfaces/CommandResult.html +13 -13
- package/docs/interfaces/ExecStream.html +6 -6
- package/docs/interfaces/HoneyPotStats.html +5 -3
- package/docs/interfaces/IdleManagerOptions.html +7 -0
- package/docs/interfaces/InstalledPackage.html +11 -11
- package/docs/interfaces/NanoEditorSession.html +5 -5
- package/docs/interfaces/PackageDefinition.html +14 -14
- package/docs/interfaces/PackageFile.html +5 -5
- package/docs/interfaces/PasswordChallenge.html +16 -0
- package/docs/interfaces/RemoveOptions.html +3 -3
- package/docs/interfaces/ShellEnv.html +4 -4
- package/docs/interfaces/ShellModule.html +8 -8
- package/docs/interfaces/ShellProperties.html +5 -5
- package/docs/interfaces/ShellStream.html +7 -7
- package/docs/interfaces/SudoChallenge.html +9 -9
- package/docs/interfaces/VfsBaseNode.html +7 -7
- package/docs/interfaces/VfsDiff.html +6 -6
- package/docs/interfaces/VfsDiffEntry.html +4 -4
- package/docs/interfaces/VfsDiffModified.html +6 -6
- package/docs/interfaces/VfsDirectoryNode.html +8 -8
- package/docs/interfaces/VfsFileNode.html +9 -9
- package/docs/interfaces/VfsOptions.html +18 -4
- package/docs/interfaces/VfsSnapshot.html +3 -3
- package/docs/interfaces/VfsSnapshotBaseNode.html +4 -4
- package/docs/interfaces/VfsSnapshotDirectoryNode.html +5 -5
- package/docs/interfaces/VfsSnapshotFileNode.html +6 -6
- package/docs/interfaces/VirtualActiveSession.html +12 -0
- package/docs/interfaces/VirtualSftpServerOptions.html +7 -0
- package/docs/interfaces/VirtualShellVfsLike.html +15 -0
- package/docs/interfaces/VirtualShellVfsOptions.html +3 -0
- package/docs/interfaces/WriteFileOptions.html +4 -4
- package/docs/modules.html +1 -1
- package/docs/types/ArgParseOptions.html +4 -0
- package/docs/types/CommandMode.html +2 -2
- package/docs/types/CommandOutcome.html +2 -2
- package/docs/types/IdleState.html +1 -0
- package/docs/types/VfsNodeStats.html +2 -2
- package/docs/types/VfsNodeType.html +2 -2
- package/docs/types/VfsPersistenceMode.html +2 -2
- package/docs/types/VfsSnapshotNode.html +2 -2
- package/examples/web.min.js +0 -1
- package/package.json +13 -12
- package/scripts/generate-manuals-bundle.mjs +49 -0
- package/scripts/publish-package.sh +1 -1
- package/src/Honeypot/index.ts +24 -0
- package/src/SSHMimic/index.ts +9 -5
- package/src/SSHMimic/sftp.ts +6 -0
- package/src/VirtualFileSystem/binaryPack.ts +21 -9
- package/src/VirtualFileSystem/index.ts +151 -53
- package/src/VirtualFileSystem/internalTypes.ts +24 -4
- package/src/VirtualFileSystem/journal.ts +1 -0
- package/src/VirtualFileSystem/path.ts +1 -1
- package/src/VirtualShell/idleManager.ts +137 -0
- package/src/VirtualShell/index.ts +64 -1
- package/src/VirtualUserManager/index.ts +4 -2
- package/src/commands/command-helpers.ts +5 -1
- package/src/commands/man.ts +5 -37
- package/src/commands/manuals-bundle.ts +898 -0
- package/src/index.ts +7 -1
- package/src/modules/linuxRootfs.ts +58 -14
- package/src/self-standalone.ts +13 -0
- package/src/standalone.ts +23 -0
- package/typedoc.json +45 -0
- package/builds/self-standalone.js.map +0 -7
- package/builds/standalone-wo-sftp.js.map +0 -7
- package/builds/standalone.cjs.map +0 -7
- package/builds/web-full-api.min.js.map +0 -7
- package/builds/web.min.js.map +0 -7
|
@@ -14,6 +14,7 @@ import { createPerfLogger } from "../utils/perfLogger";
|
|
|
14
14
|
import VirtualFileSystem, { type VfsOptions } from "../VirtualFileSystem";
|
|
15
15
|
import { VirtualPackageManager } from "../VirtualPackageManager";
|
|
16
16
|
import { VirtualUserManager } from "../VirtualUserManager";
|
|
17
|
+
import { IdleManager, type IdleManagerOptions } from "./idleManager";
|
|
17
18
|
import { startShell } from "./shell";
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -41,6 +42,10 @@ export interface ShellProperties {
|
|
|
41
42
|
arch: string;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Minimal VFS interface accepted by {@link VirtualShell} as a drop-in replacement
|
|
47
|
+
* for the built-in {@link VirtualFileSystem}.
|
|
48
|
+
*/
|
|
44
49
|
export interface VirtualShellVfsLike {
|
|
45
50
|
restoreMirror(): Promise<void>;
|
|
46
51
|
flushMirror(): Promise<void>;
|
|
@@ -56,6 +61,9 @@ export interface VirtualShellVfsLike {
|
|
|
56
61
|
getUsageBytes?(targetPath?: string): number;
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Constructor options for {@link VirtualShell} when passing an existing VFS instance.
|
|
66
|
+
*/
|
|
59
67
|
export interface VirtualShellVfsOptions {
|
|
60
68
|
vfsInstance?: VirtualShellVfsLike;
|
|
61
69
|
}
|
|
@@ -143,6 +151,8 @@ class VirtualShell extends EventEmitter {
|
|
|
143
151
|
properties: ShellProperties;
|
|
144
152
|
/** Unix ms timestamp of shell creation — used by `uptime` and `/proc/uptime`. */
|
|
145
153
|
startTime: number;
|
|
154
|
+
/** Idle / cold-start manager — null until `enableIdleManagement()` is called. */
|
|
155
|
+
private _idle: IdleManager | null = null;
|
|
146
156
|
private initialized: Promise<void>;
|
|
147
157
|
|
|
148
158
|
/**
|
|
@@ -150,7 +160,7 @@ class VirtualShell extends EventEmitter {
|
|
|
150
160
|
*
|
|
151
161
|
* @param hostname Virtual hostname used for prompts and idents.
|
|
152
162
|
* @param properties Customizable properties shown in `uname -a` and similar commands.
|
|
153
|
-
* @param
|
|
163
|
+
* @param vfsOptionsOrInstance Optional VFS persistence options (mode, snapshotPath) or an existing VFS instance.
|
|
154
164
|
*/
|
|
155
165
|
constructor(
|
|
156
166
|
hostname: string,
|
|
@@ -236,6 +246,7 @@ class VirtualShell extends EventEmitter {
|
|
|
236
246
|
*/
|
|
237
247
|
executeCommand(rawInput: string, authUser: string, cwd: string): void {
|
|
238
248
|
perf.mark("executeCommand");
|
|
249
|
+
this._idle?.ping();
|
|
239
250
|
runCommand(rawInput, authUser, this.hostname, "shell", cwd, this);
|
|
240
251
|
this.emit("command", { command: rawInput, user: authUser, cwd });
|
|
241
252
|
}
|
|
@@ -262,6 +273,7 @@ class VirtualShell extends EventEmitter {
|
|
|
262
273
|
terminalSize: { cols: number; rows: number },
|
|
263
274
|
): void {
|
|
264
275
|
perf.mark("startInteractiveSession");
|
|
276
|
+
this._idle?.ping();
|
|
265
277
|
// Interactive shell logic
|
|
266
278
|
this.emit("session:start", { user: authUser, sessionId, remoteAddress });
|
|
267
279
|
startShell(
|
|
@@ -404,6 +416,57 @@ class VirtualShell extends EventEmitter {
|
|
|
404
416
|
this.users.assertWriteWithinQuota(authUser, targetPath, content);
|
|
405
417
|
this.vfs.writeFile(targetPath, content);
|
|
406
418
|
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Enable idle detection and cold-start freeze/thaw for this shell.
|
|
422
|
+
*
|
|
423
|
+
* After `idleThresholdMs` of inactivity the VFS tree is serialised and
|
|
424
|
+
* released from RAM. The next command transparently restores it in ~0.1 ms.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* await shell.ensureInitialized();
|
|
429
|
+
* shell.enableIdleManagement({ idleThresholdMs: 60_000 });
|
|
430
|
+
* ```
|
|
431
|
+
*/
|
|
432
|
+
public enableIdleManagement(options?: IdleManagerOptions): void {
|
|
433
|
+
if (this._idle) return; // already enabled
|
|
434
|
+
this._idle = new IdleManager(this.vfs, options);
|
|
435
|
+
this._idle.on("freeze", () => this.emit("shell:freeze"));
|
|
436
|
+
this._idle.on("thaw", () => this.emit("shell:thaw"));
|
|
437
|
+
this._idle.start();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Disable idle management and thaw the shell if currently frozen.
|
|
442
|
+
* Safe to call even if idle management was never enabled.
|
|
443
|
+
*/
|
|
444
|
+
public async disableIdleManagement(): Promise<void> {
|
|
445
|
+
if (!this._idle) return;
|
|
446
|
+
await this._idle.stop();
|
|
447
|
+
this._idle = null;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Current idle state — `"active"` or `"frozen"`.
|
|
452
|
+
* Returns `"active"` when idle management is disabled.
|
|
453
|
+
*/
|
|
454
|
+
public get idleState(): "active" | "frozen" {
|
|
455
|
+
return this._idle?.state ?? "active";
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** Milliseconds since last shell activity. 0 when idle management is disabled. */
|
|
459
|
+
public get idleMs(): number {
|
|
460
|
+
return this._idle?.idleMs ?? 0;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Ping the idle manager to signal external activity (e.g. SFTP, direct VFS writes).
|
|
465
|
+
* No-op when idle management is disabled.
|
|
466
|
+
*/
|
|
467
|
+
public pingIdle(): void {
|
|
468
|
+
this._idle?.ping();
|
|
469
|
+
}
|
|
407
470
|
}
|
|
408
471
|
|
|
409
472
|
export { VirtualShell };
|
|
@@ -5,7 +5,10 @@ import type { PerfLogger } from "../utils/perfLogger";
|
|
|
5
5
|
import { createPerfLogger } from "../utils/perfLogger";
|
|
6
6
|
import type VirtualFileSystem from "../VirtualFileSystem";
|
|
7
7
|
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Persisted virtual user credential record.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
9
12
|
export interface VirtualUserRecord {
|
|
10
13
|
/** Unique login name. */
|
|
11
14
|
username: string;
|
|
@@ -61,7 +64,6 @@ export class VirtualUserManager extends EventEmitter {
|
|
|
61
64
|
* Creates a user manager instance backed by a virtual filesystem.
|
|
62
65
|
*
|
|
63
66
|
* @param vfs Backing virtual filesystem used for persistence.
|
|
64
|
-
* @param defaultRootPassword Initial root password used when root is created.
|
|
65
67
|
* @param autoSudoForNewUsers Whether newly created users are added to sudoers.
|
|
66
68
|
*/
|
|
67
69
|
constructor(
|
package/src/commands/man.ts
CHANGED
|
@@ -1,45 +1,10 @@
|
|
|
1
1
|
import type { ShellModule } from "../types/commands";
|
|
2
|
+
import { MANUALS } from "./manuals-bundle";
|
|
2
3
|
|
|
3
4
|
const MANUAL_ALIASES: Record<string, string> = {
|
|
4
5
|
gunzip: "gzip",
|
|
5
6
|
};
|
|
6
7
|
|
|
7
|
-
const __dirname = import.meta.dirname;
|
|
8
|
-
|
|
9
|
-
const manualCache = new Map<string, string | null>();
|
|
10
|
-
const manualsBaseUrl = new URL("./manuals/", import.meta.url);
|
|
11
|
-
|
|
12
|
-
async function dynamicImport(specifier: string): Promise<unknown> {
|
|
13
|
-
const importer = new Function(
|
|
14
|
-
"moduleName",
|
|
15
|
-
"return import(moduleName)",
|
|
16
|
-
) as (moduleName: string) => Promise<unknown>;
|
|
17
|
-
return importer(specifier);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function loadBundledManual(commandName: string): Promise<string | null> {
|
|
21
|
-
const normalized = commandName.toLowerCase();
|
|
22
|
-
const lookupName = MANUAL_ALIASES[normalized] ?? normalized;
|
|
23
|
-
const cacheKey = `builtin:${lookupName}`;
|
|
24
|
-
if (manualCache.has(cacheKey)) {
|
|
25
|
-
return manualCache.get(cacheKey) ?? null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
const fsModule = (await dynamicImport("node:fs/promises")) as {
|
|
30
|
-
readFile: (path: URL, encoding: "utf8") => Promise<string>;
|
|
31
|
-
};
|
|
32
|
-
const manualUrl = new URL(`${lookupName}.txt`, manualsBaseUrl);
|
|
33
|
-
const content = await fsModule.readFile(manualUrl, "utf8");
|
|
34
|
-
const page = content.replace(/\n$/, "");
|
|
35
|
-
manualCache.set(cacheKey, page);
|
|
36
|
-
return page;
|
|
37
|
-
} catch {
|
|
38
|
-
manualCache.set(cacheKey, null);
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
8
|
export const manCommand: ShellModule = {
|
|
44
9
|
name: "man",
|
|
45
10
|
description: "Interface to the system reference manuals",
|
|
@@ -55,7 +20,10 @@ export const manCommand: ShellModule = {
|
|
|
55
20
|
return { stdout: shell.vfs.readFile(manPath), exitCode: 0 };
|
|
56
21
|
}
|
|
57
22
|
|
|
58
|
-
|
|
23
|
+
// Bundled manuals — available in all build modes (standalone, web, dev)
|
|
24
|
+
const normalized = name.toLowerCase();
|
|
25
|
+
const lookupName = MANUAL_ALIASES[normalized] ?? normalized;
|
|
26
|
+
const page = MANUALS[lookupName] ?? null;
|
|
59
27
|
if (page) return { stdout: page, exitCode: 0 };
|
|
60
28
|
|
|
61
29
|
return { stderr: `No manual entry for ${name}`, exitCode: 16 };
|