typescript-virtual-container 1.4.6 → 1.4.8
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 -0
- package/README.md +0 -1
- package/benchmark-results.txt +21 -21
- package/builds/self-standalone.js +1111 -299
- package/builds/self-standalone.js.map +4 -4
- package/builds/standalone-wo-sftp.js +993 -183
- package/builds/standalone-wo-sftp.js.map +4 -4
- package/builds/standalone.cjs +984 -173
- package/builds/standalone.cjs.map +4 -4
- package/dist/SSHMimic/exec.d.ts.map +1 -1
- package/dist/SSHMimic/exec.js +0 -1
- package/dist/SSHMimic/exec.js.map +1 -1
- package/dist/SSHMimic/index.d.ts.map +1 -1
- package/dist/SSHMimic/index.js +3 -1
- package/dist/SSHMimic/index.js.map +1 -1
- package/dist/SSHMimic/sftp.d.ts.map +1 -1
- package/dist/SSHMimic/sftp.js +0 -6
- 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 +93 -0
- package/dist/VirtualFileSystem/index.d.ts.map +1 -1
- package/dist/VirtualFileSystem/index.js +361 -46
- 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 +47 -0
- package/dist/VirtualFileSystem/journal.d.ts.map +1 -0
- package/dist/VirtualFileSystem/journal.js +178 -0
- package/dist/VirtualFileSystem/journal.js.map +1 -0
- package/dist/VirtualFileSystem/path.js +1 -1
- package/dist/VirtualFileSystem/path.js.map +1 -1
- package/dist/VirtualShell/idleManager.d.ts +65 -0
- package/dist/VirtualShell/idleManager.d.ts.map +1 -0
- package/dist/VirtualShell/idleManager.js +106 -0
- package/dist/VirtualShell/idleManager.js.map +1 -0
- package/dist/VirtualShell/index.d.ts +28 -0
- package/dist/VirtualShell/index.d.ts.map +1 -1
- package/dist/VirtualShell/index.js +48 -0
- package/dist/VirtualShell/index.js.map +1 -1
- package/dist/VirtualShell/shell.js +4 -4
- package/dist/VirtualShell/shell.js.map +1 -1
- package/dist/commands/man.d.ts.map +1 -1
- package/dist/commands/man.js +5 -27
- 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 +2 -0
- 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 +16 -1
- 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 +8 -8
- package/docs/classes/IdleManager.html +159 -0
- package/docs/classes/SshClient.html +18 -18
- package/docs/classes/VirtualFileSystem.html +57 -32
- package/docs/classes/VirtualPackageManager.html +12 -12
- package/docs/classes/VirtualSftpServer.html +3 -3
- package/docs/classes/VirtualShell.html +40 -25
- package/docs/classes/VirtualSshServer.html +5 -5
- package/docs/classes/VirtualUserManager.html +26 -26
- package/docs/functions/assertDiff.html +1 -1
- package/docs/functions/diffSnapshots.html +1 -1
- package/docs/functions/formatDiff.html +1 -1
- package/docs/functions/getArg.html +1 -1
- package/docs/functions/getFlag.html +1 -1
- package/docs/functions/ifFlag.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +1 -2
- package/docs/interfaces/AuditLogEntry.html +2 -2
- package/docs/interfaces/CommandContext.html +11 -11
- package/docs/interfaces/CommandResult.html +12 -12
- package/docs/interfaces/ExecStream.html +5 -5
- package/docs/interfaces/HoneyPotStats.html +2 -2
- package/docs/interfaces/IdleManagerOptions.html +7 -0
- package/docs/interfaces/InstalledPackage.html +10 -10
- package/docs/interfaces/NanoEditorSession.html +4 -4
- package/docs/interfaces/PackageDefinition.html +13 -13
- package/docs/interfaces/PackageFile.html +4 -4
- package/docs/interfaces/RemoveOptions.html +2 -2
- package/docs/interfaces/ShellEnv.html +3 -3
- package/docs/interfaces/ShellModule.html +7 -7
- package/docs/interfaces/ShellProperties.html +4 -4
- package/docs/interfaces/ShellStream.html +6 -6
- package/docs/interfaces/SudoChallenge.html +8 -8
- package/docs/interfaces/VfsBaseNode.html +6 -6
- package/docs/interfaces/VfsDiff.html +5 -5
- package/docs/interfaces/VfsDiffEntry.html +3 -3
- package/docs/interfaces/VfsDiffModified.html +5 -5
- package/docs/interfaces/VfsDirectoryNode.html +7 -7
- package/docs/interfaces/VfsFileNode.html +8 -8
- package/docs/interfaces/VfsOptions.html +18 -4
- package/docs/interfaces/VfsSnapshot.html +2 -2
- package/docs/interfaces/VfsSnapshotBaseNode.html +3 -3
- package/docs/interfaces/VfsSnapshotDirectoryNode.html +4 -4
- package/docs/interfaces/VfsSnapshotFileNode.html +5 -5
- package/docs/interfaces/WriteFileOptions.html +3 -3
- package/docs/modules.html +1 -1
- package/docs/types/CommandMode.html +1 -1
- package/docs/types/CommandOutcome.html +1 -1
- package/docs/types/IdleState.html +1 -0
- package/docs/types/VfsNodeStats.html +1 -1
- package/docs/types/VfsNodeType.html +1 -1
- package/docs/types/VfsPersistenceMode.html +1 -1
- package/docs/types/VfsSnapshotNode.html +1 -1
- package/package.json +5 -4
- package/scripts/generate-manuals-bundle.mjs +49 -0
- package/src/SSHMimic/exec.ts +0 -1
- package/src/SSHMimic/index.ts +3 -1
- package/src/SSHMimic/sftp.ts +0 -6
- package/src/VirtualFileSystem/binaryPack.ts +21 -9
- package/src/VirtualFileSystem/index.ts +369 -52
- package/src/VirtualFileSystem/internalTypes.ts +24 -4
- package/src/VirtualFileSystem/journal.ts +163 -0
- package/src/VirtualFileSystem/path.ts +1 -1
- package/src/VirtualShell/idleManager.ts +133 -0
- package/src/VirtualShell/index.ts +48 -0
- package/src/VirtualShell/shell.ts +4 -4
- package/src/commands/man.ts +5 -35
- package/src/commands/manuals-bundle.ts +898 -0
- package/src/index.ts +2 -0
- package/src/modules/linuxRootfs.ts +58 -14
- package/src/self-standalone.ts +14 -1
- package/src/standalone.ts +23 -0
- package/builds/standalone.js +0 -491
- package/builds/standalone.js.map +0 -7
package/src/index.ts
CHANGED
|
@@ -5,6 +5,8 @@ export { default as VirtualFileSystem } from "./VirtualFileSystem/index";
|
|
|
5
5
|
export { VirtualPackageManager } from "./VirtualPackageManager/index";
|
|
6
6
|
export { VirtualShell } from "./VirtualShell/index";
|
|
7
7
|
export { VirtualUserManager } from "./VirtualUserManager/index";
|
|
8
|
+
export { IdleManager } from "./VirtualShell/idleManager";
|
|
9
|
+
export type { IdleManagerOptions, IdleState } from "./VirtualShell/idleManager";
|
|
8
10
|
|
|
9
11
|
export type {
|
|
10
12
|
AuditLogEntry,
|
|
@@ -15,10 +15,12 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import * as os from "node:os";
|
|
18
|
-
import
|
|
18
|
+
import VirtualFileSystem from "../VirtualFileSystem";
|
|
19
|
+
import { decodeVfs } from "../VirtualFileSystem/binaryPack";
|
|
19
20
|
import type { ShellProperties } from "../VirtualShell";
|
|
20
21
|
import type { VirtualActiveSession, VirtualUserManager } from "../VirtualUserManager";
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
// ─── helpers ────────────────────────────────────────────────────────────────
|
|
23
25
|
|
|
24
26
|
function ensureDir(vfs: VirtualFileSystem, path: string, mode = 0o755): void {
|
|
@@ -31,7 +33,8 @@ function ensureFile(
|
|
|
31
33
|
content: string,
|
|
32
34
|
mode = 0o644,
|
|
33
35
|
): void {
|
|
34
|
-
|
|
36
|
+
// Use lazy stub — no Buffer allocated until the file is actually read or overwritten
|
|
37
|
+
vfs.writeStub(path, content, mode);
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
function write(vfs: VirtualFileSystem, path: string, content: string): void {
|
|
@@ -766,6 +769,50 @@ function bootstrapMisc(vfs: VirtualFileSystem, props: ShellProperties): void {
|
|
|
766
769
|
ensureDir(vfs, "/lost+found", 0o700);
|
|
767
770
|
}
|
|
768
771
|
|
|
772
|
+
// ── Static rootfs snapshot cache ─────────────────────────────────────────────
|
|
773
|
+
// The static parts of the rootfs (dev, usr, var, bin, tmp, etc, sys, misc)
|
|
774
|
+
// are identical for all shells sharing the same hostname+props.
|
|
775
|
+
// We build them once, serialise to VFSB binary, and clone via decodeVfs()
|
|
776
|
+
// for each new shell — avoiding ~250 JS object allocations per instance.
|
|
777
|
+
|
|
778
|
+
const _staticRootfsCache = new Map<string, Buffer>();
|
|
779
|
+
|
|
780
|
+
function _staticCacheKey(hostname: string, props: ShellProperties): string {
|
|
781
|
+
return `${hostname}|${props.kernel}|${props.os}|${props.arch}`;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Build or retrieve the static rootfs VFSB snapshot for the given
|
|
786
|
+
* hostname + ShellProperties combination.
|
|
787
|
+
*
|
|
788
|
+
* Subsequent calls with the same key return the cached Buffer in ~0ms.
|
|
789
|
+
*/
|
|
790
|
+
export function getStaticRootfsSnapshot(
|
|
791
|
+
hostname: string,
|
|
792
|
+
props: ShellProperties,
|
|
793
|
+
): Buffer {
|
|
794
|
+
const key = _staticCacheKey(hostname, props);
|
|
795
|
+
const cached = _staticRootfsCache.get(key);
|
|
796
|
+
if (cached) return cached;
|
|
797
|
+
|
|
798
|
+
// Build the static subset into a temporary VFS
|
|
799
|
+
const tmp = new VirtualFileSystem({ mode: "memory" });
|
|
800
|
+
bootstrapEtc(tmp, hostname, props);
|
|
801
|
+
bootstrapSys(tmp, hostname, props);
|
|
802
|
+
bootstrapDev(tmp);
|
|
803
|
+
bootstrapUsr(tmp);
|
|
804
|
+
bootstrapVar(tmp);
|
|
805
|
+
bootstrapBin(tmp);
|
|
806
|
+
bootstrapTmp(tmp);
|
|
807
|
+
bootstrapMisc(tmp, props);
|
|
808
|
+
bootProcLog(tmp, props);
|
|
809
|
+
|
|
810
|
+
const snapshot = tmp.encodeBinary();
|
|
811
|
+
_staticRootfsCache.set(key, snapshot);
|
|
812
|
+
return snapshot;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
|
|
769
816
|
// ─── main entry point ─────────────────────────────────────────────────────────
|
|
770
817
|
|
|
771
818
|
/**
|
|
@@ -787,18 +834,15 @@ export function bootstrapLinuxRootfs(
|
|
|
787
834
|
shellStartTime: number,
|
|
788
835
|
sessions: VirtualActiveSession[] = [],
|
|
789
836
|
): void {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
bootProcLog(vfs, props);
|
|
800
|
-
refreshProc(vfs, props, hostname, shellStartTime, sessions);
|
|
801
|
-
syncEtcPasswd(vfs, users);
|
|
837
|
+
// Fast path: clone the cached static rootfs snapshot (VFSB decode ~0.07ms)
|
|
838
|
+
// instead of rebuilding ~250 JS objects from scratch each time.
|
|
839
|
+
const snapshot = getStaticRootfsSnapshot(hostname, props);
|
|
840
|
+
vfs.importRootTree(decodeVfs(snapshot));
|
|
841
|
+
|
|
842
|
+
// Dynamic parts: per-instance data injected after the static clone
|
|
843
|
+
bootstrapRoot(vfs); // /root home dir + .bashrc
|
|
844
|
+
refreshProc(vfs, props, hostname, shellStartTime, sessions); // /proc live data
|
|
845
|
+
syncEtcPasswd(vfs, users); // /etc/passwd|group|shadow
|
|
802
846
|
}
|
|
803
847
|
|
|
804
848
|
// ─── optional live engine ─────────────────────────────────────────────────────
|
package/src/self-standalone.ts
CHANGED
|
@@ -62,7 +62,7 @@ function writeLastLogin(username: string, from: string): void {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
async function flushVfs(): Promise<void> {
|
|
65
|
-
await virtualShell.vfs.
|
|
65
|
+
await virtualShell.vfs.stopAutoFlush();
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function loadHistory(authUser: string): string[] {
|
|
@@ -506,6 +506,19 @@ runReadlineShell().catch((error: unknown) => {
|
|
|
506
506
|
process.exit(1);
|
|
507
507
|
});
|
|
508
508
|
|
|
509
|
+
|
|
510
|
+
// ── Graceful shutdown (process-level) ────────────────────────────────────────
|
|
511
|
+
let _shuttingDown = false;
|
|
512
|
+
async function _gracefulShutdown(signal: string): Promise<void> {
|
|
513
|
+
if (_shuttingDown) return;
|
|
514
|
+
_shuttingDown = true;
|
|
515
|
+
process.stdout.write(`\n[${signal}] Saving VFS...\n`);
|
|
516
|
+
try { await virtualShell.vfs.stopAutoFlush(); } catch {}
|
|
517
|
+
process.exit(0);
|
|
518
|
+
}
|
|
519
|
+
process.on("SIGTERM", () => { void _gracefulShutdown("SIGTERM"); });
|
|
520
|
+
process.on("beforeExit", () => { void virtualShell.vfs.stopAutoFlush(); });
|
|
521
|
+
|
|
509
522
|
process.on("uncaughtException", (error) => {
|
|
510
523
|
console.error("Uncaught exception:", error);
|
|
511
524
|
});
|
package/src/standalone.ts
CHANGED
|
@@ -31,6 +31,29 @@ new VirtualSftpServer({ port: 2223, hostname, shell: virtualShell })
|
|
|
31
31
|
process.exit(1);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
+
|
|
35
|
+
// ── Graceful shutdown ─────────────────────────────────────────────────────────
|
|
36
|
+
// On SIGINT / SIGTERM: flush the WAL journal to a full checkpoint before exit.
|
|
37
|
+
// A kill -9 or OOM crash is unrecoverable here, but the WAL journal on disk
|
|
38
|
+
// guarantees all writes since the last checkpoint are replayed on next start.
|
|
39
|
+
let isShuttingDown = false;
|
|
40
|
+
async function gracefulShutdown(signal: string): Promise<void> {
|
|
41
|
+
if (isShuttingDown) return;
|
|
42
|
+
isShuttingDown = true;
|
|
43
|
+
console.log(`\n[${signal}] Flushing VFS checkpoint before exit...`);
|
|
44
|
+
try {
|
|
45
|
+
await virtualShell.vfs.stopAutoFlush();
|
|
46
|
+
console.log("[shutdown] Checkpoint written. Goodbye.");
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error("[shutdown] Flush failed:", err);
|
|
49
|
+
}
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
process.on("SIGINT", () => { void gracefulShutdown("SIGINT"); });
|
|
54
|
+
process.on("SIGTERM", () => { void gracefulShutdown("SIGTERM"); });
|
|
55
|
+
process.on("beforeExit", () => { void virtualShell.vfs.stopAutoFlush(); });
|
|
56
|
+
|
|
34
57
|
process.on("uncaughtException", (error) => {
|
|
35
58
|
console.debug("Oh my god, something terrible happened: ", error);
|
|
36
59
|
});
|