typescript-virtual-container 1.2.7 → 1.2.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 (130) hide show
  1. package/README.md +457 -42
  2. package/dist/SSHMimic/executor.js +3 -5
  3. package/dist/VirtualFileSystem/binaryPack.d.ts +49 -0
  4. package/dist/VirtualFileSystem/binaryPack.d.ts.map +1 -0
  5. package/dist/VirtualFileSystem/binaryPack.js +193 -0
  6. package/dist/VirtualFileSystem/index.d.ts +7 -5
  7. package/dist/VirtualFileSystem/index.d.ts.map +1 -1
  8. package/dist/VirtualFileSystem/index.js +20 -9
  9. package/dist/VirtualPackageManager/index.d.ts +202 -0
  10. package/dist/VirtualPackageManager/index.d.ts.map +1 -0
  11. package/dist/VirtualPackageManager/index.js +676 -0
  12. package/dist/VirtualShell/index.d.ts +87 -12
  13. package/dist/VirtualShell/index.d.ts.map +1 -1
  14. package/dist/VirtualShell/index.js +83 -12
  15. package/dist/VirtualUserManager/index.d.ts +52 -20
  16. package/dist/VirtualUserManager/index.d.ts.map +1 -1
  17. package/dist/VirtualUserManager/index.js +54 -20
  18. package/dist/commands/alias.d.ts +4 -0
  19. package/dist/commands/alias.d.ts.map +1 -0
  20. package/dist/commands/alias.js +58 -0
  21. package/dist/commands/apt.d.ts +4 -0
  22. package/dist/commands/apt.d.ts.map +1 -0
  23. package/dist/commands/apt.js +182 -0
  24. package/dist/commands/cat.d.ts.map +1 -1
  25. package/dist/commands/cat.js +27 -8
  26. package/dist/commands/chmod.d.ts.map +1 -1
  27. package/dist/commands/chmod.js +52 -3
  28. package/dist/commands/command-helpers.d.ts +78 -4
  29. package/dist/commands/command-helpers.d.ts.map +1 -1
  30. package/dist/commands/command-helpers.js +78 -4
  31. package/dist/commands/curl.d.ts.map +1 -1
  32. package/dist/commands/curl.js +81 -29
  33. package/dist/commands/dpkg.d.ts +4 -0
  34. package/dist/commands/dpkg.d.ts.map +1 -0
  35. package/dist/commands/dpkg.js +144 -0
  36. package/dist/commands/echo.d.ts.map +1 -1
  37. package/dist/commands/echo.js +24 -12
  38. package/dist/commands/free.d.ts +3 -0
  39. package/dist/commands/free.d.ts.map +1 -0
  40. package/dist/commands/free.js +38 -0
  41. package/dist/commands/helpers.d.ts +3 -0
  42. package/dist/commands/helpers.d.ts.map +1 -1
  43. package/dist/commands/helpers.js +3 -0
  44. package/dist/commands/history.d.ts +3 -0
  45. package/dist/commands/history.d.ts.map +1 -0
  46. package/dist/commands/history.js +21 -0
  47. package/dist/commands/index.d.ts +8 -1
  48. package/dist/commands/index.d.ts.map +1 -1
  49. package/dist/commands/index.js +120 -11
  50. package/dist/commands/ls.d.ts.map +1 -1
  51. package/dist/commands/ls.js +4 -3
  52. package/dist/commands/lsb-release.d.ts +3 -0
  53. package/dist/commands/lsb-release.d.ts.map +1 -0
  54. package/dist/commands/lsb-release.js +50 -0
  55. package/dist/commands/man.d.ts +3 -0
  56. package/dist/commands/man.d.ts.map +1 -0
  57. package/dist/commands/man.js +155 -0
  58. package/dist/commands/neofetch.d.ts.map +1 -1
  59. package/dist/commands/neofetch.js +5 -0
  60. package/dist/commands/ping.d.ts.map +1 -1
  61. package/dist/commands/ping.js +5 -2
  62. package/dist/commands/ps.d.ts.map +1 -1
  63. package/dist/commands/ps.js +27 -6
  64. package/dist/commands/sh.d.ts.map +1 -1
  65. package/dist/commands/sh.js +29 -11
  66. package/dist/commands/source.d.ts +3 -0
  67. package/dist/commands/source.d.ts.map +1 -0
  68. package/dist/commands/source.js +31 -0
  69. package/dist/commands/test.d.ts +3 -0
  70. package/dist/commands/test.d.ts.map +1 -0
  71. package/dist/commands/test.js +92 -0
  72. package/dist/commands/type.d.ts +3 -0
  73. package/dist/commands/type.d.ts.map +1 -0
  74. package/dist/commands/type.js +34 -0
  75. package/dist/commands/uptime.d.ts +3 -0
  76. package/dist/commands/uptime.d.ts.map +1 -0
  77. package/dist/commands/uptime.js +40 -0
  78. package/dist/commands/wget.d.ts.map +1 -1
  79. package/dist/commands/wget.js +71 -100
  80. package/dist/commands/which.d.ts +3 -0
  81. package/dist/commands/which.d.ts.map +1 -0
  82. package/dist/commands/which.js +32 -0
  83. package/dist/index.d.ts +5 -2
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +2 -1
  86. package/dist/modules/linuxRootfs.d.ts +24 -0
  87. package/dist/modules/linuxRootfs.d.ts.map +1 -0
  88. package/dist/modules/linuxRootfs.js +297 -0
  89. package/dist/modules/neofetch.d.ts.map +1 -1
  90. package/dist/modules/neofetch.js +1 -0
  91. package/dist/standalone.js +4 -1
  92. package/package.json +2 -1
  93. package/src/SSHMimic/executor.ts +3 -5
  94. package/src/VirtualFileSystem/binaryPack.ts +219 -0
  95. package/src/VirtualFileSystem/index.ts +21 -11
  96. package/src/VirtualPackageManager/index.ts +820 -0
  97. package/src/VirtualShell/index.ts +104 -13
  98. package/src/VirtualUserManager/index.ts +55 -20
  99. package/src/commands/alias.ts +60 -0
  100. package/src/commands/apt.ts +198 -0
  101. package/src/commands/cat.ts +32 -8
  102. package/src/commands/chmod.ts +48 -3
  103. package/src/commands/command-helpers.ts +78 -4
  104. package/src/commands/curl.ts +78 -37
  105. package/src/commands/dpkg.ts +158 -0
  106. package/src/commands/echo.ts +30 -14
  107. package/src/commands/free.ts +40 -0
  108. package/src/commands/helpers.ts +8 -0
  109. package/src/commands/history.ts +29 -0
  110. package/src/commands/index.ts +116 -11
  111. package/src/commands/ls.ts +5 -4
  112. package/src/commands/lsb-release.ts +52 -0
  113. package/src/commands/man.ts +166 -0
  114. package/src/commands/neofetch.ts +5 -0
  115. package/src/commands/ping.ts +5 -2
  116. package/src/commands/ps.ts +28 -6
  117. package/src/commands/sh.ts +33 -11
  118. package/src/commands/source.ts +35 -0
  119. package/src/commands/test.ts +100 -0
  120. package/src/commands/type.ts +40 -0
  121. package/src/commands/uptime.ts +46 -0
  122. package/src/commands/wget.ts +70 -123
  123. package/src/commands/which.ts +34 -0
  124. package/src/index.ts +10 -0
  125. package/src/modules/linuxRootfs.ts +439 -0
  126. package/src/modules/neofetch.ts +1 -0
  127. package/src/standalone.ts +4 -1
  128. package/standalone.js +418 -103
  129. package/standalone.js.map +4 -4
  130. package/tests/new-features.test.ts +626 -0
@@ -1,4 +1,4 @@
1
- import { runCommand as runSingleCommand } from "../commands";
1
+ import { runCommandDirect } from "../commands";
2
2
  import { resolvePath } from "../commands/helpers";
3
3
  // ── Script executor (handles &&/||/;) ────────────────────────────────────────
4
4
  export async function executeScript(script, authUser, hostname, mode, cwd, shell, env) {
@@ -71,8 +71,7 @@ async function executeSingleCommandWithRedirections(cmd, authUser, hostname, mod
71
71
  return { stderr: `${cmd.inputFile}: No such file or directory`, exitCode: 1 };
72
72
  }
73
73
  }
74
- const rawInput = [cmd.name, ...cmd.args].join(" ");
75
- const result = await runSingleCommand(rawInput, authUser, hostname, mode, cwd, shell, stdin, env);
74
+ const result = await runCommandDirect(cmd.name, cmd.args, authUser, hostname, mode, cwd, shell, stdin, env);
76
75
  if (cmd.outputFile) {
77
76
  const outputPath = resolvePath(cwd, cmd.outputFile);
78
77
  const output = result.stdout || "";
@@ -111,8 +110,7 @@ async function executePipelineChain(commands, authUser, hostname, mode, cwd, she
111
110
  return { stderr: `${cmd.inputFile}: No such file or directory`, exitCode: 1 };
112
111
  }
113
112
  }
114
- const rawInput = [cmd.name, ...cmd.args].join(" ");
115
- const result = await runSingleCommand(rawInput, authUser, hostname, mode, cwd, shell, currentOutput, env);
113
+ const result = await runCommandDirect(cmd.name, cmd.args, authUser, hostname, mode, cwd, shell, currentOutput, env);
116
114
  exitCode = result.exitCode ?? 0;
117
115
  if (i === commands.length - 1 && cmd.outputFile) {
118
116
  const outputPath = resolvePath(cwd, cmd.outputFile);
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Binary serialisation format for VirtualFileSystem snapshots.
3
+ *
4
+ * Replaces the JSON+base64 approach. No external dependencies.
5
+ *
6
+ * Wire format (little-endian throughout):
7
+ *
8
+ * File header:
9
+ * [4] magic = 0x56 0x46 0x53 0x21 ("VFS!")
10
+ * [1] version = 0x01
11
+ *
12
+ * Node (recursive):
13
+ * [1] type = 0x01 (file) | 0x02 (directory)
14
+ * [2] name length (uint16)
15
+ * [N] name bytes (utf8)
16
+ * [4] mode (uint32)
17
+ * [8] createdAt ms (float64)
18
+ * [8] updatedAt ms (float64)
19
+ *
20
+ * File node extra:
21
+ * [1] compressed flag (0x00 | 0x01)
22
+ * [4] content length (uint32)
23
+ * [N] content bytes (raw — no base64)
24
+ *
25
+ * Directory node extra:
26
+ * [4] children count (uint32)
27
+ * [N] children nodes (recursive)
28
+ *
29
+ * Total overhead vs JSON+base64 for 1 MB of file data:
30
+ * JSON+base64 : ~1.37 MB (base64 33% bloat) + JSON string wrapping
31
+ * Binary pack : ~1.00 MB + ~40 bytes/node header → ~27% smaller, no string parsing
32
+ */
33
+ import type { InternalDirectoryNode } from "./internalTypes";
34
+ /**
35
+ * Serialise an in-memory VFS root to a compact binary Buffer.
36
+ * No base64, no JSON. ~27% smaller than the JSON+base64 format for typical VFS trees.
37
+ */
38
+ export declare function encodeVfs(root: InternalDirectoryNode): Buffer;
39
+ /**
40
+ * Deserialise a binary Buffer produced by {@link encodeVfs} back into an
41
+ * InternalDirectoryNode tree. Throws on magic/version mismatch or truncation.
42
+ */
43
+ export declare function decodeVfs(buf: Buffer): InternalDirectoryNode;
44
+ /**
45
+ * Returns true if `buf` looks like a VFS binary snapshot (starts with magic bytes).
46
+ * Used to auto-detect format when loading from disk.
47
+ */
48
+ export declare function isBinarySnapshot(buf: Buffer): boolean;
49
+ //# sourceMappingURL=binaryPack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binaryPack.d.ts","sourceRoot":"","sources":["../../src/VirtualFileSystem/binaryPack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAkC,MAAM,iBAAiB,CAAC;AA2E7F;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAM7D;AAuED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAiB5D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Binary serialisation format for VirtualFileSystem snapshots.
3
+ *
4
+ * Replaces the JSON+base64 approach. No external dependencies.
5
+ *
6
+ * Wire format (little-endian throughout):
7
+ *
8
+ * File header:
9
+ * [4] magic = 0x56 0x46 0x53 0x21 ("VFS!")
10
+ * [1] version = 0x01
11
+ *
12
+ * Node (recursive):
13
+ * [1] type = 0x01 (file) | 0x02 (directory)
14
+ * [2] name length (uint16)
15
+ * [N] name bytes (utf8)
16
+ * [4] mode (uint32)
17
+ * [8] createdAt ms (float64)
18
+ * [8] updatedAt ms (float64)
19
+ *
20
+ * File node extra:
21
+ * [1] compressed flag (0x00 | 0x01)
22
+ * [4] content length (uint32)
23
+ * [N] content bytes (raw — no base64)
24
+ *
25
+ * Directory node extra:
26
+ * [4] children count (uint32)
27
+ * [N] children nodes (recursive)
28
+ *
29
+ * Total overhead vs JSON+base64 for 1 MB of file data:
30
+ * JSON+base64 : ~1.37 MB (base64 33% bloat) + JSON string wrapping
31
+ * Binary pack : ~1.00 MB + ~40 bytes/node header → ~27% smaller, no string parsing
32
+ */
33
+ const MAGIC = Buffer.from([0x56, 0x46, 0x53, 0x21]); // "VFS!"
34
+ const VERSION = 0x01;
35
+ const TYPE_FILE = 0x01;
36
+ const TYPE_DIR = 0x02;
37
+ // ── Encoder ───────────────────────────────────────────────────────────────────
38
+ class Encoder {
39
+ chunks = [];
40
+ write(buf) { this.chunks.push(buf); }
41
+ writeUint8(n) {
42
+ const b = Buffer.allocUnsafe(1);
43
+ b.writeUInt8(n, 0);
44
+ this.chunks.push(b);
45
+ }
46
+ writeUint16(n) {
47
+ const b = Buffer.allocUnsafe(2);
48
+ b.writeUInt16LE(n, 0);
49
+ this.chunks.push(b);
50
+ }
51
+ writeUint32(n) {
52
+ const b = Buffer.allocUnsafe(4);
53
+ b.writeUInt32LE(n, 0);
54
+ this.chunks.push(b);
55
+ }
56
+ writeFloat64(n) {
57
+ const b = Buffer.allocUnsafe(8);
58
+ b.writeDoubleBE(n, 0);
59
+ this.chunks.push(b);
60
+ }
61
+ writeString(s) {
62
+ const encoded = Buffer.from(s, "utf8");
63
+ this.writeUint16(encoded.length);
64
+ this.chunks.push(encoded);
65
+ }
66
+ writeBytes(bytes) {
67
+ this.writeUint32(bytes.length);
68
+ this.chunks.push(bytes);
69
+ }
70
+ toBuffer() { return Buffer.concat(this.chunks); }
71
+ }
72
+ function encodeNode(enc, node) {
73
+ if (node.type === "file") {
74
+ const f = node;
75
+ enc.writeUint8(TYPE_FILE);
76
+ enc.writeString(f.name);
77
+ enc.writeUint32(f.mode);
78
+ enc.writeFloat64(f.createdAt.getTime());
79
+ enc.writeFloat64(f.updatedAt.getTime());
80
+ enc.writeUint8(f.compressed ? 0x01 : 0x00);
81
+ enc.writeBytes(f.content);
82
+ }
83
+ else {
84
+ const d = node;
85
+ enc.writeUint8(TYPE_DIR);
86
+ enc.writeString(d.name);
87
+ enc.writeUint32(d.mode);
88
+ enc.writeFloat64(d.createdAt.getTime());
89
+ enc.writeFloat64(d.updatedAt.getTime());
90
+ const children = Array.from(d.children.values());
91
+ enc.writeUint32(children.length);
92
+ for (const child of children)
93
+ encodeNode(enc, child);
94
+ }
95
+ }
96
+ /**
97
+ * Serialise an in-memory VFS root to a compact binary Buffer.
98
+ * No base64, no JSON. ~27% smaller than the JSON+base64 format for typical VFS trees.
99
+ */
100
+ export function encodeVfs(root) {
101
+ const enc = new Encoder();
102
+ enc.write(MAGIC);
103
+ enc.writeUint8(VERSION);
104
+ encodeNode(enc, root);
105
+ return enc.toBuffer();
106
+ }
107
+ // ── Decoder ───────────────────────────────────────────────────────────────────
108
+ class Decoder {
109
+ buf;
110
+ pos = 0;
111
+ constructor(buf) {
112
+ this.buf = buf;
113
+ }
114
+ readUint8() { return this.buf.readUInt8(this.pos++); }
115
+ readUint16() {
116
+ const v = this.buf.readUInt16LE(this.pos);
117
+ this.pos += 2;
118
+ return v;
119
+ }
120
+ readUint32() {
121
+ const v = this.buf.readUInt32LE(this.pos);
122
+ this.pos += 4;
123
+ return v;
124
+ }
125
+ readFloat64() {
126
+ const v = this.buf.readDoubleBE(this.pos);
127
+ this.pos += 8;
128
+ return v;
129
+ }
130
+ readString() {
131
+ const len = this.readUint16();
132
+ const s = this.buf.toString("utf8", this.pos, this.pos + len);
133
+ this.pos += len;
134
+ return s;
135
+ }
136
+ readBytes() {
137
+ const len = this.readUint32();
138
+ const b = this.buf.slice(this.pos, this.pos + len);
139
+ this.pos += len;
140
+ return b;
141
+ }
142
+ remaining() { return this.buf.length - this.pos; }
143
+ }
144
+ function decodeNode(dec) {
145
+ const type = dec.readUint8();
146
+ const name = dec.readString();
147
+ const mode = dec.readUint32();
148
+ const createdAt = new Date(dec.readFloat64());
149
+ const updatedAt = new Date(dec.readFloat64());
150
+ if (type === TYPE_FILE) {
151
+ const compressed = dec.readUint8() === 0x01;
152
+ const content = dec.readBytes();
153
+ return { type: "file", name, mode, createdAt, updatedAt, compressed, content };
154
+ }
155
+ if (type === TYPE_DIR) {
156
+ const count = dec.readUint32();
157
+ const children = new Map();
158
+ for (let i = 0; i < count; i++) {
159
+ const child = decodeNode(dec);
160
+ children.set(child.name, child);
161
+ }
162
+ return { type: "directory", name, mode, createdAt, updatedAt, children };
163
+ }
164
+ throw new Error(`[VFS binary] Unknown node type: 0x${type.toString(16)}`);
165
+ }
166
+ /**
167
+ * Deserialise a binary Buffer produced by {@link encodeVfs} back into an
168
+ * InternalDirectoryNode tree. Throws on magic/version mismatch or truncation.
169
+ */
170
+ export function decodeVfs(buf) {
171
+ if (buf.length < 5)
172
+ throw new Error("[VFS binary] Buffer too short");
173
+ const magic = buf.slice(0, 4);
174
+ if (!magic.equals(MAGIC)) {
175
+ throw new Error("[VFS binary] Invalid magic — not a VFS binary snapshot");
176
+ }
177
+ const dec = new Decoder(buf);
178
+ // skip magic (4) + version (1)
179
+ for (let i = 0; i < 5; i++)
180
+ dec.readUint8();
181
+ const root = decodeNode(dec);
182
+ if (root.type !== "directory") {
183
+ throw new Error("[VFS binary] Root node must be a directory");
184
+ }
185
+ return root;
186
+ }
187
+ /**
188
+ * Returns true if `buf` looks like a VFS binary snapshot (starts with magic bytes).
189
+ * Used to auto-detect format when loading from disk.
190
+ */
191
+ export function isBinarySnapshot(buf) {
192
+ return buf.length >= 4 && buf.slice(0, 4).equals(MAGIC);
193
+ }
@@ -4,8 +4,8 @@ import type { RemoveOptions, VfsNodeStats, VfsSnapshot, WriteFileOptions } from
4
4
  * "memory" — pure in-memory, no disk I/O (default).
5
5
  *
6
6
  * "fs" — mirrors the VFS tree to a directory on the host filesystem.
7
- * `snapshotPath` must be set to the directory where the JSON
8
- * snapshot file will be read/written.
7
+ * `snapshotPath` must be set to the directory where the binary
8
+ * snapshot file will be read/written (`vfs-snapshot.vfsb`).
9
9
  */
10
10
  export type VfsPersistenceMode = "memory" | "fs";
11
11
  export interface VfsOptions {
@@ -29,7 +29,7 @@ export interface VfsOptions {
29
29
  * **Memory mode** (default) — all state lives in a fast recursive tree.
30
30
  * Use `toSnapshot()` / `fromSnapshot()` / `importSnapshot()` for serialisation.
31
31
  *
32
- * **FS mode** — same in-memory tree, but `restoreMirror()` loads a JSON
32
+ * **FS mode** — same in-memory tree, but `restoreMirror()` loads a binary
33
33
  * snapshot from disk and `flushMirror()` writes it back. This gives you
34
34
  * persistent VFS state across process restarts without any real POSIX filesystem
35
35
  * semantics leaking through.
@@ -55,14 +55,16 @@ declare class VirtualFileSystem extends EventEmitter {
55
55
  private makeFile;
56
56
  private mkdirRecursive;
57
57
  /**
58
- * In `"fs"` mode: reads the JSON snapshot from disk and hydrates the tree.
58
+ * In `"fs"` mode: reads the binary snapshot (`vfs-snapshot.vfsb`) from disk.
59
+ * Automatically falls back to legacy JSON format for backward compatibility.
59
60
  * Silently succeeds when the snapshot file does not exist yet.
60
61
  *
61
62
  * In `"memory"` mode: no-op (kept for API compatibility).
62
63
  */
63
64
  restoreMirror(): Promise<void>;
64
65
  /**
65
- * In `"fs"` mode: serialises the in-memory tree to a JSON snapshot on disk.
66
+ * In `"fs"` mode: serialises the in-memory tree to a binary snapshot on disk
67
+ * (`vfs-snapshot.vfsb`). ~27% smaller and significantly faster than JSON+base64.
66
68
  * The directory is created if it does not exist.
67
69
  *
68
70
  * In `"memory"` mode: emits `"mirror:flush"` and returns (no disk write).
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/VirtualFileSystem/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/VirtualFileSystem/index.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { EventEmitter } from "node:events";
2
2
  import * as fsSync from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { gunzipSync, gzipSync } from "node:zlib";
5
+ import { decodeVfs, encodeVfs, isBinarySnapshot } from "./binaryPack";
5
6
  import { getNode, getParentDirectory, normalizePath } from "./path";
6
7
  // ── VirtualFileSystem ─────────────────────────────────────────────────────────
7
8
  /**
@@ -10,7 +11,7 @@ import { getNode, getParentDirectory, normalizePath } from "./path";
10
11
  * **Memory mode** (default) — all state lives in a fast recursive tree.
11
12
  * Use `toSnapshot()` / `fromSnapshot()` / `importSnapshot()` for serialisation.
12
13
  *
13
- * **FS mode** — same in-memory tree, but `restoreMirror()` loads a JSON
14
+ * **FS mode** — same in-memory tree, but `restoreMirror()` loads a binary
14
15
  * snapshot from disk and `flushMirror()` writes it back. This gives you
15
16
  * persistent VFS state across process restarts without any real POSIX filesystem
16
17
  * semantics leaking through.
@@ -38,7 +39,7 @@ class VirtualFileSystem extends EventEmitter {
38
39
  if (!options.snapshotPath) {
39
40
  throw new Error('VirtualFileSystem: "snapshotPath" is required when mode is "fs".');
40
41
  }
41
- this.snapshotFile = path.resolve(options.snapshotPath, "vfs-snapshot.json");
42
+ this.snapshotFile = path.resolve(options.snapshotPath, "vfs-snapshot.vfsb");
42
43
  }
43
44
  else {
44
45
  this.snapshotFile = null;
@@ -92,7 +93,8 @@ class VirtualFileSystem extends EventEmitter {
92
93
  }
93
94
  // ── Persistence ───────────────────────────────────────────────────────────
94
95
  /**
95
- * In `"fs"` mode: reads the JSON snapshot from disk and hydrates the tree.
96
+ * In `"fs"` mode: reads the binary snapshot (`vfs-snapshot.vfsb`) from disk.
97
+ * Automatically falls back to legacy JSON format for backward compatibility.
96
98
  * Silently succeeds when the snapshot file does not exist yet.
97
99
  *
98
100
  * In `"memory"` mode: no-op (kept for API compatibility).
@@ -103,9 +105,17 @@ class VirtualFileSystem extends EventEmitter {
103
105
  if (!fsSync.existsSync(this.snapshotFile))
104
106
  return;
105
107
  try {
106
- const raw = fsSync.readFileSync(this.snapshotFile, "utf8");
107
- const snapshot = JSON.parse(raw);
108
- this.root = this.deserializeDir(snapshot.root, "");
108
+ const raw = fsSync.readFileSync(this.snapshotFile);
109
+ if (isBinarySnapshot(raw)) {
110
+ // Fast binary format (current)
111
+ this.root = decodeVfs(raw);
112
+ }
113
+ else {
114
+ // Legacy JSON fallback — auto-migrates on next flushMirror()
115
+ const snapshot = JSON.parse(raw.toString("utf8"));
116
+ this.root = this.deserializeDir(snapshot.root, "");
117
+ console.info("[VirtualFileSystem] Migrating legacy JSON snapshot to binary format.");
118
+ }
109
119
  this.emit("snapshot:restore", { path: this.snapshotFile });
110
120
  }
111
121
  catch (err) {
@@ -114,7 +124,8 @@ class VirtualFileSystem extends EventEmitter {
114
124
  }
115
125
  }
116
126
  /**
117
- * In `"fs"` mode: serialises the in-memory tree to a JSON snapshot on disk.
127
+ * In `"fs"` mode: serialises the in-memory tree to a binary snapshot on disk
128
+ * (`vfs-snapshot.vfsb`). ~27% smaller and significantly faster than JSON+base64.
118
129
  * The directory is created if it does not exist.
119
130
  *
120
131
  * In `"memory"` mode: emits `"mirror:flush"` and returns (no disk write).
@@ -126,8 +137,8 @@ class VirtualFileSystem extends EventEmitter {
126
137
  }
127
138
  const dir = path.dirname(this.snapshotFile);
128
139
  fsSync.mkdirSync(dir, { recursive: true });
129
- const snapshot = this.toSnapshot();
130
- fsSync.writeFileSync(this.snapshotFile, JSON.stringify(snapshot), "utf8");
140
+ const binary = encodeVfs(this.root);
141
+ fsSync.writeFileSync(this.snapshotFile, binary);
131
142
  this.emit("mirror:flush", { path: this.snapshotFile });
132
143
  }
133
144
  /** Returns the current persistence mode. */
@@ -0,0 +1,202 @@
1
+ import type VirtualFileSystem from "../VirtualFileSystem";
2
+ import type { VirtualUserManager } from "../VirtualUserManager";
3
+ /**
4
+ * A single file entry written into the VFS when a package is installed.
5
+ */
6
+ export interface PackageFile {
7
+ /** Absolute VFS destination path (e.g. `"/usr/bin/vim"`). */
8
+ path: string;
9
+ /** Text content to write. */
10
+ content: string;
11
+ /** POSIX mode bits (default `0o644`; use `0o755` for executables). */
12
+ mode?: number;
13
+ }
14
+ /**
15
+ * Metadata and behaviour definition for a single package in the registry.
16
+ *
17
+ * Used both for the built-in registry entries and for consumer-supplied custom
18
+ * packages. `files` are written to the VFS on `install()`, and `onInstall` /
19
+ * `onRemove` hooks allow arbitrary VFS mutations.
20
+ */
21
+ export interface PackageDefinition {
22
+ /** Package name — lowercase, no spaces (e.g. `"vim"`, `"build-essential"`). */
23
+ name: string;
24
+ /** Debian-style version string (e.g. `"2:9.0.1378-2"`). */
25
+ version: string;
26
+ /** CPU architecture label (default `"amd64"`). */
27
+ architecture?: string;
28
+ /** Maintainer name and email shown in `apt show` output. */
29
+ maintainer?: string;
30
+ /** Full package description. */
31
+ description: string;
32
+ /** Short one-line summary shown in `apt search` results. */
33
+ shortDesc?: string;
34
+ /** Installed disk usage in kilobytes (informational). */
35
+ installedSizeKb?: number;
36
+ /** Other package names that must be installed first (resolved recursively). */
37
+ depends?: string[];
38
+ /** Repository section (e.g. `"utils"`, `"net"`, `"editors"`, `"devel"`). */
39
+ section?: string;
40
+ /** Files to write into the VFS during installation. */
41
+ files?: PackageFile[];
42
+ /**
43
+ * Hook called after all files are written.
44
+ * Use to create directories, write config, or register shell commands.
45
+ */
46
+ onInstall?: (vfs: VirtualFileSystem, users: VirtualUserManager) => void;
47
+ /** Hook called before VFS files are removed during uninstall. */
48
+ onRemove?: (vfs: VirtualFileSystem) => void;
49
+ }
50
+ /**
51
+ * Runtime record of an installed package, persisted to `/var/lib/dpkg/status`.
52
+ */
53
+ export interface InstalledPackage {
54
+ /** Package name. */
55
+ name: string;
56
+ /** Installed version string. */
57
+ version: string;
58
+ /** CPU architecture. */
59
+ architecture: string;
60
+ /** Maintainer display string. */
61
+ maintainer: string;
62
+ /** Full description. */
63
+ description: string;
64
+ /** Repository section. */
65
+ section: string;
66
+ /** Installed disk usage in kilobytes. */
67
+ installedSizeKb: number;
68
+ /** ISO-8601 timestamp of when the package was installed. */
69
+ installedAt: string;
70
+ /** Absolute VFS paths written by this package (used by `dpkg -L`). */
71
+ files: string[];
72
+ }
73
+ /**
74
+ * Pure-TypeScript APT/dpkg package manager backed by a built-in registry.
75
+ *
76
+ * Accessed via `shell.packageManager` — not constructed directly.
77
+ *
78
+ * `install()` resolves dependencies recursively, writes declared files to the
79
+ * VFS, runs `onInstall` hooks, and persists state to `/var/lib/dpkg/status`.
80
+ * `remove()` reverses the process. All state survives VFS snapshot round-trips.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const pm = shell.packageManager;
85
+ * pm.install(["vim", "git"]);
86
+ * console.log(pm.isInstalled("vim")); // true
87
+ * console.log(pm.installedCount()); // 2
88
+ * ```
89
+ */
90
+ export declare class VirtualPackageManager {
91
+ private readonly vfs;
92
+ private readonly users;
93
+ private readonly installed;
94
+ private readonly registryPath;
95
+ private readonly logPath;
96
+ private readonly aptLogPath;
97
+ /**
98
+ * @param vfs Backing virtual filesystem for file I/O and dpkg status persistence.
99
+ * @param users User manager reference passed to `onInstall` hooks.
100
+ */
101
+ constructor(vfs: VirtualFileSystem, users: VirtualUserManager);
102
+ /**
103
+ * Loads installed package state from `/var/lib/dpkg/status` in the VFS.
104
+ *
105
+ * Called automatically by `VirtualShell` after `bootstrapLinuxRootfs`.
106
+ * Safe to call again to reload state after a snapshot restore.
107
+ */
108
+ load(): void;
109
+ /** Persist installed state to /var/lib/dpkg/status. */
110
+ private persist;
111
+ private parseFields;
112
+ private log;
113
+ private aptLog;
114
+ /**
115
+ * Looks up a package definition in the built-in registry by name.
116
+ *
117
+ * @param name Package name (case-insensitive).
118
+ * @returns The matching `PackageDefinition`, or `undefined` if not found.
119
+ */
120
+ findInRegistry(name: string): PackageDefinition | undefined;
121
+ /**
122
+ * Returns all packages in the built-in registry, sorted alphabetically.
123
+ *
124
+ * @returns Array of `PackageDefinition` entries.
125
+ */
126
+ listAvailable(): PackageDefinition[];
127
+ /**
128
+ * Returns all currently installed packages, sorted alphabetically.
129
+ *
130
+ * @returns Array of `InstalledPackage` records.
131
+ */
132
+ listInstalled(): InstalledPackage[];
133
+ /**
134
+ * Returns `true` when the given package is currently installed.
135
+ *
136
+ * @param name Package name (case-insensitive).
137
+ */
138
+ isInstalled(name: string): boolean;
139
+ /**
140
+ * Returns the total number of installed packages.
141
+ *
142
+ * Used by `neofetch` to populate the `Packages:` field.
143
+ */
144
+ installedCount(): number;
145
+ /**
146
+ * Installs one or more packages from the registry.
147
+ *
148
+ * Dependencies listed in `PackageDefinition.depends` are resolved and
149
+ * installed automatically. Already-installed packages are skipped. Files
150
+ * declared in `PackageDefinition.files` are written to the VFS and
151
+ * `onInstall` hooks are called in dependency order.
152
+ *
153
+ * @param names Package names to install.
154
+ * @param opts Installation options.
155
+ * @param opts.quiet Suppress progress output lines when `true`.
156
+ * @returns Terminal-style `output` string and an APT-compatible `exitCode`
157
+ * (`0` on success, `100` when a package is not found).
158
+ */
159
+ install(names: string[], opts?: {
160
+ quiet?: boolean;
161
+ }): {
162
+ output: string;
163
+ exitCode: number;
164
+ };
165
+ /**
166
+ * Removes one or more installed packages.
167
+ *
168
+ * Package files are deleted from the VFS. Config files (paths under
169
+ * `/etc/` or ending in `.conf`) are preserved unless `opts.purge` is set.
170
+ * The `onRemove` hook is called for each package.
171
+ *
172
+ * @param names Package names to remove.
173
+ * @param opts Removal options.
174
+ * @param opts.purge Also delete configuration files when `true`.
175
+ * @param opts.quiet Suppress progress output lines when `true`.
176
+ * @returns Terminal-style `output` string and exit code (`0` on success).
177
+ */
178
+ remove(names: string[], opts?: {
179
+ purge?: boolean;
180
+ quiet?: boolean;
181
+ }): {
182
+ output: string;
183
+ exitCode: number;
184
+ };
185
+ /**
186
+ * Searches the registry for packages whose name or description contains
187
+ * the given term (case-insensitive). Equivalent to `apt-cache search`.
188
+ *
189
+ * @param term Search string.
190
+ * @returns Matching `PackageDefinition` entries sorted alphabetically.
191
+ */
192
+ search(term: string): PackageDefinition[];
193
+ /**
194
+ * Returns a dpkg-style metadata block for a package, including its
195
+ * install status. Equivalent to `apt-cache show` / `dpkg -s`.
196
+ *
197
+ * @param name Package name.
198
+ * @returns Multi-line metadata string, or `null` if not in the registry.
199
+ */
200
+ show(name: string): string | null;
201
+ }
202
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/VirtualPackageManager/index.ts"],"names":[],"mappings":"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"}