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.
Files changed (156) hide show
  1. package/README.md +1 -2
  2. package/benchmark-results.txt +21 -21
  3. package/builds/self-standalone.js +979 -168
  4. package/builds/standalone-wo-sftp.js +982 -173
  5. package/builds/standalone.cjs +989 -179
  6. package/builds/web-full-api.min.js +0 -1
  7. package/builds/web.min.js +0 -1
  8. package/dist/Honeypot/index.d.ts +6 -0
  9. package/dist/Honeypot/index.d.ts.map +1 -1
  10. package/dist/Honeypot/index.js +20 -0
  11. package/dist/Honeypot/index.js.map +1 -1
  12. package/dist/SSHMimic/index.d.ts +6 -5
  13. package/dist/SSHMimic/index.d.ts.map +1 -1
  14. package/dist/SSHMimic/index.js +8 -5
  15. package/dist/SSHMimic/index.js.map +1 -1
  16. package/dist/SSHMimic/sftp.d.ts +1 -0
  17. package/dist/SSHMimic/sftp.d.ts.map +1 -1
  18. package/dist/SSHMimic/sftp.js.map +1 -1
  19. package/dist/VirtualFileSystem/binaryPack.d.ts.map +1 -1
  20. package/dist/VirtualFileSystem/binaryPack.js +21 -9
  21. package/dist/VirtualFileSystem/binaryPack.js.map +1 -1
  22. package/dist/VirtualFileSystem/index.d.ts +25 -0
  23. package/dist/VirtualFileSystem/index.d.ts.map +1 -1
  24. package/dist/VirtualFileSystem/index.js +152 -47
  25. package/dist/VirtualFileSystem/index.js.map +1 -1
  26. package/dist/VirtualFileSystem/internalTypes.d.ts +23 -4
  27. package/dist/VirtualFileSystem/internalTypes.d.ts.map +1 -1
  28. package/dist/VirtualFileSystem/journal.d.ts +1 -0
  29. package/dist/VirtualFileSystem/journal.d.ts.map +1 -1
  30. package/dist/VirtualFileSystem/journal.js.map +1 -1
  31. package/dist/VirtualFileSystem/path.js +1 -1
  32. package/dist/VirtualFileSystem/path.js.map +1 -1
  33. package/dist/VirtualShell/idleManager.d.ts +69 -0
  34. package/dist/VirtualShell/idleManager.d.ts.map +1 -0
  35. package/dist/VirtualShell/idleManager.js +110 -0
  36. package/dist/VirtualShell/idleManager.js.map +1 -0
  37. package/dist/VirtualShell/index.d.ts +41 -1
  38. package/dist/VirtualShell/index.d.ts.map +1 -1
  39. package/dist/VirtualShell/index.js +54 -1
  40. package/dist/VirtualShell/index.js.map +1 -1
  41. package/dist/VirtualUserManager/index.d.ts +4 -2
  42. package/dist/VirtualUserManager/index.d.ts.map +1 -1
  43. package/dist/VirtualUserManager/index.js +0 -1
  44. package/dist/VirtualUserManager/index.js.map +1 -1
  45. package/dist/commands/command-helpers.d.ts +5 -2
  46. package/dist/commands/command-helpers.d.ts.map +1 -1
  47. package/dist/commands/command-helpers.js.map +1 -1
  48. package/dist/commands/man.d.ts.map +1 -1
  49. package/dist/commands/man.js +5 -28
  50. package/dist/commands/man.js.map +1 -1
  51. package/dist/commands/manuals-bundle.d.ts +11 -0
  52. package/dist/commands/manuals-bundle.d.ts.map +1 -0
  53. package/dist/commands/manuals-bundle.js +898 -0
  54. package/dist/commands/manuals-bundle.js.map +1 -0
  55. package/dist/index.d.ts +7 -2
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +1 -0
  58. package/dist/index.js.map +1 -1
  59. package/dist/modules/linuxRootfs.d.ts +8 -1
  60. package/dist/modules/linuxRootfs.d.ts.map +1 -1
  61. package/dist/modules/linuxRootfs.js +47 -14
  62. package/dist/modules/linuxRootfs.js.map +1 -1
  63. package/dist/self-standalone.js +15 -0
  64. package/dist/self-standalone.js.map +1 -1
  65. package/dist/standalone.js +22 -0
  66. package/dist/standalone.js.map +1 -1
  67. package/docs/assets/hierarchy.js +1 -1
  68. package/docs/assets/navigation.js +1 -1
  69. package/docs/assets/search.js +1 -1
  70. package/docs/classes/HoneyPot.html +9 -9
  71. package/docs/classes/IdleManager.html +162 -0
  72. package/docs/classes/SshClient.html +18 -18
  73. package/docs/classes/VirtualFileSystem.html +50 -33
  74. package/docs/classes/VirtualPackageManager.html +13 -13
  75. package/docs/classes/VirtualSftpServer.html +3 -3
  76. package/docs/classes/VirtualShell.html +47 -28
  77. package/docs/classes/VirtualSshServer.html +12 -7
  78. package/docs/classes/VirtualUserManager.html +30 -30
  79. package/docs/functions/assertDiff.html +2 -2
  80. package/docs/functions/diffSnapshots.html +2 -2
  81. package/docs/functions/formatDiff.html +2 -2
  82. package/docs/functions/getArg.html +3 -3
  83. package/docs/functions/getFlag.html +2 -2
  84. package/docs/functions/ifFlag.html +2 -2
  85. package/docs/hierarchy.html +1 -1
  86. package/docs/index.html +4 -5
  87. package/docs/interfaces/AuditLogEntry.html +3 -3
  88. package/docs/interfaces/CommandContext.html +13 -13
  89. package/docs/interfaces/CommandResult.html +13 -13
  90. package/docs/interfaces/ExecStream.html +6 -6
  91. package/docs/interfaces/HoneyPotStats.html +5 -3
  92. package/docs/interfaces/IdleManagerOptions.html +7 -0
  93. package/docs/interfaces/InstalledPackage.html +11 -11
  94. package/docs/interfaces/NanoEditorSession.html +5 -5
  95. package/docs/interfaces/PackageDefinition.html +14 -14
  96. package/docs/interfaces/PackageFile.html +5 -5
  97. package/docs/interfaces/PasswordChallenge.html +16 -0
  98. package/docs/interfaces/RemoveOptions.html +3 -3
  99. package/docs/interfaces/ShellEnv.html +4 -4
  100. package/docs/interfaces/ShellModule.html +8 -8
  101. package/docs/interfaces/ShellProperties.html +5 -5
  102. package/docs/interfaces/ShellStream.html +7 -7
  103. package/docs/interfaces/SudoChallenge.html +9 -9
  104. package/docs/interfaces/VfsBaseNode.html +7 -7
  105. package/docs/interfaces/VfsDiff.html +6 -6
  106. package/docs/interfaces/VfsDiffEntry.html +4 -4
  107. package/docs/interfaces/VfsDiffModified.html +6 -6
  108. package/docs/interfaces/VfsDirectoryNode.html +8 -8
  109. package/docs/interfaces/VfsFileNode.html +9 -9
  110. package/docs/interfaces/VfsOptions.html +18 -4
  111. package/docs/interfaces/VfsSnapshot.html +3 -3
  112. package/docs/interfaces/VfsSnapshotBaseNode.html +4 -4
  113. package/docs/interfaces/VfsSnapshotDirectoryNode.html +5 -5
  114. package/docs/interfaces/VfsSnapshotFileNode.html +6 -6
  115. package/docs/interfaces/VirtualActiveSession.html +12 -0
  116. package/docs/interfaces/VirtualSftpServerOptions.html +7 -0
  117. package/docs/interfaces/VirtualShellVfsLike.html +15 -0
  118. package/docs/interfaces/VirtualShellVfsOptions.html +3 -0
  119. package/docs/interfaces/WriteFileOptions.html +4 -4
  120. package/docs/modules.html +1 -1
  121. package/docs/types/ArgParseOptions.html +4 -0
  122. package/docs/types/CommandMode.html +2 -2
  123. package/docs/types/CommandOutcome.html +2 -2
  124. package/docs/types/IdleState.html +1 -0
  125. package/docs/types/VfsNodeStats.html +2 -2
  126. package/docs/types/VfsNodeType.html +2 -2
  127. package/docs/types/VfsPersistenceMode.html +2 -2
  128. package/docs/types/VfsSnapshotNode.html +2 -2
  129. package/examples/web.min.js +0 -1
  130. package/package.json +13 -12
  131. package/scripts/generate-manuals-bundle.mjs +49 -0
  132. package/scripts/publish-package.sh +1 -1
  133. package/src/Honeypot/index.ts +24 -0
  134. package/src/SSHMimic/index.ts +9 -5
  135. package/src/SSHMimic/sftp.ts +6 -0
  136. package/src/VirtualFileSystem/binaryPack.ts +21 -9
  137. package/src/VirtualFileSystem/index.ts +151 -53
  138. package/src/VirtualFileSystem/internalTypes.ts +24 -4
  139. package/src/VirtualFileSystem/journal.ts +1 -0
  140. package/src/VirtualFileSystem/path.ts +1 -1
  141. package/src/VirtualShell/idleManager.ts +137 -0
  142. package/src/VirtualShell/index.ts +64 -1
  143. package/src/VirtualUserManager/index.ts +4 -2
  144. package/src/commands/command-helpers.ts +5 -1
  145. package/src/commands/man.ts +5 -37
  146. package/src/commands/manuals-bundle.ts +898 -0
  147. package/src/index.ts +7 -1
  148. package/src/modules/linuxRootfs.ts +58 -14
  149. package/src/self-standalone.ts +13 -0
  150. package/src/standalone.ts +23 -0
  151. package/typedoc.json +45 -0
  152. package/builds/self-standalone.js.map +0 -7
  153. package/builds/standalone-wo-sftp.js.map +0 -7
  154. package/builds/standalone.cjs.map +0 -7
  155. package/builds/web-full-api.min.js.map +0 -7
  156. 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 vfsOptions Optional VFS persistence options (mode, snapshotPath).
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
- /** Persisted virtual user credential record. */
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(
@@ -1,4 +1,8 @@
1
- type ArgParseOptions = {
1
+ /**
2
+ * Options for argument parsing helpers.
3
+ * @public
4
+ */
5
+ export type ArgParseOptions = {
2
6
  flags?: string[];
3
7
  flagsWithValue?: string[];
4
8
  };
@@ -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
- const page = await loadBundledManual(name);
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 };