typescript-virtual-container 1.4.2 → 1.4.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.
- package/README.md +72 -35
- package/builds/self-standalone.js +160 -160
- package/builds/self-standalone.js.map +4 -4
- package/builds/standalone-wo-sftp.js +18 -18
- package/builds/standalone-wo-sftp.js.map +3 -3
- package/builds/standalone.js +46 -46
- package/builds/standalone.js.map +3 -3
- package/dist/VirtualFileSystem/index.d.ts +47 -0
- package/dist/VirtualFileSystem/index.d.ts.map +1 -1
- package/dist/VirtualFileSystem/index.js +159 -0
- package/dist/VirtualShell/index.d.ts +29 -0
- package/dist/VirtualShell/index.d.ts.map +1 -1
- package/dist/VirtualShell/index.js +29 -0
- package/dist/VirtualShell/shellParser.js +28 -1
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +5 -3
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +2 -0
- package/dist/commands/runtime.d.ts.map +1 -1
- package/dist/commands/runtime.js +28 -3
- package/dist/commands/seq.d.ts +4 -0
- package/dist/commands/seq.d.ts.map +1 -0
- package/dist/commands/seq.js +50 -0
- package/dist/commands/sh.d.ts +0 -6
- package/dist/commands/sh.d.ts.map +1 -1
- package/dist/commands/sh.js +153 -10
- package/dist/types/pipeline.d.ts +6 -0
- package/dist/types/pipeline.d.ts.map +1 -1
- package/dist/types/vfs.d.ts +15 -0
- package/dist/types/vfs.d.ts.map +1 -1
- package/dist/utils/expand.d.ts +9 -0
- package/dist/utils/expand.d.ts.map +1 -1
- package/dist/utils/expand.js +84 -2
- package/dist/utils/tokenize.d.ts.map +1 -1
- package/dist/utils/tokenize.js +40 -0
- package/package.json +1 -1
- package/src/VirtualFileSystem/index.ts +164 -1
- package/src/VirtualShell/index.ts +36 -0
- package/src/VirtualShell/shellParser.ts +26 -1
- package/src/commands/export.ts +5 -3
- package/src/commands/registry.ts +2 -0
- package/src/commands/runtime.ts +30 -3
- package/src/commands/seq.ts +43 -0
- package/src/commands/sh.ts +144 -19
- package/src/types/pipeline.ts +6 -0
- package/src/types/vfs.ts +17 -0
- package/src/utils/expand.ts +75 -2
- package/src/utils/tokenize.ts +20 -0
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
- [`VirtualSftpServer`](#virtualsftpserver)
|
|
25
25
|
- [`VirtualShell`](#virtualshell)
|
|
26
26
|
- [`VirtualFileSystem`](#virtualfilesystem)
|
|
27
|
+
- [Mount API](#mount-api)
|
|
27
28
|
- [`VirtualUserManager`](#virtualusermanager)
|
|
28
29
|
- [`VirtualPackageManager`](#virtualpackagemanager)
|
|
29
30
|
- [Snapshot Diff Tooling](#snapshot-diff-tooling)
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
| Mode | Entry point | Use case |
|
|
54
55
|
|------|-------------|----------|
|
|
55
56
|
| **SSH/SFTP server** | `VirtualSshServer` / `VirtualSftpServer` | Honeypots, remote testing, training environments |
|
|
56
|
-
| **Web shell** | `builds/web.min.js` (
|
|
57
|
+
| **Web shell** | `builds/web.min.js` / `builds/web-full-api.min.js` (ESM) | Embedded terminals, interactive tutorials, browser demos |
|
|
57
58
|
| **Standalone CLI** | `builds/self-standalone.js` (single file) | Local shell, one-liner demos, no install required |
|
|
58
59
|
|
|
59
60
|
All three modes share the same core: a pure in-memory VFS, a real shell interpreter, a virtual package manager, and a typed programmatic API.
|
|
@@ -111,24 +112,22 @@ await ssh.start();
|
|
|
111
112
|
|
|
112
113
|
### Web shell (browser)
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
Two browser bundles are available:
|
|
115
116
|
|
|
116
|
-
| Bundle | Format | Entry | Use case |
|
|
117
|
-
|
|
118
|
-
| `builds/web.min.js` | ESM | `createWebShell()` |
|
|
119
|
-
| `builds/web-
|
|
120
|
-
| `builds/web-full-api.min.js` | ESM | `createVirtualShellShim()` | API surface close to `VirtualShell` |
|
|
117
|
+
| Bundle | Format | Entry point | Use case |
|
|
118
|
+
|--------|--------|-------------|----------|
|
|
119
|
+
| `builds/web.min.js` | ESM | `createWebShell()` | Embedded terminals, modern bundlers |
|
|
120
|
+
| `builds/web-full-api.min.js` | ESM | `createVirtualShellShim()` | Full `VirtualShell`-like API in the browser |
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
Both bundles persist the VFS in **IndexedDB** — state survives page reloads.
|
|
123
123
|
|
|
124
124
|
```bash
|
|
125
|
-
bun run web-build
|
|
126
|
-
bun run web-build
|
|
127
|
-
bun run
|
|
128
|
-
bun run build-all # rebuild everything
|
|
125
|
+
bun run web-build # → builds/web.min.js + examples/web.min.js
|
|
126
|
+
bun run web-full-build # → builds/web-full-api.min.js
|
|
127
|
+
bun run build-all # rebuild everything
|
|
129
128
|
```
|
|
130
129
|
|
|
131
|
-
|
|
130
|
+
**`web.min.js`** — lightweight shell with IndexedDB VFS:
|
|
132
131
|
|
|
133
132
|
```html
|
|
134
133
|
<script type="module">
|
|
@@ -144,19 +143,7 @@ bun run build-all # rebuild everything
|
|
|
144
143
|
</script>
|
|
145
144
|
```
|
|
146
145
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
```html
|
|
150
|
-
<script src="./builds/web-iife.min.js"></script>
|
|
151
|
-
<script>
|
|
152
|
-
const shell = WebShellLib.createWebShell("web-vm");
|
|
153
|
-
shell.ensureInitialized().then(() =>
|
|
154
|
-
shell.executeCommandLine("whoami").then(r => console.log(r.stdout))
|
|
155
|
-
);
|
|
156
|
-
</script>
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
**Full API shim (`web-full-api.min.js`)** — mirrors the `VirtualShell` programmatic API:
|
|
146
|
+
**`web-full-api.min.js`** — mirrors the `VirtualShell` programmatic API:
|
|
160
147
|
|
|
161
148
|
```html
|
|
162
149
|
<script type="module">
|
|
@@ -165,8 +152,7 @@ bun run build-all # rebuild everything
|
|
|
165
152
|
const shell = createVirtualShellShim("web-vm");
|
|
166
153
|
await shell.ensureInitialized();
|
|
167
154
|
await shell.executeCommandLine("mkdir -p /app && echo hello > /app/file.txt");
|
|
168
|
-
|
|
169
|
-
console.log(vfs.readFile("/app/file.txt")); // hello
|
|
155
|
+
console.log(shell.getVfs().readFile("/app/file.txt")); // hello
|
|
170
156
|
</script>
|
|
171
157
|
```
|
|
172
158
|
|
|
@@ -174,8 +160,7 @@ bun run build-all # rebuild everything
|
|
|
174
160
|
|
|
175
161
|
```bash
|
|
176
162
|
bun run example-serve
|
|
177
|
-
# Open http://localhost:8787/index.html
|
|
178
|
-
# or http://localhost:8787/index-cf.html (IIFE, Cloudflare-compatible)
|
|
163
|
+
# Open http://localhost:8787/index.html
|
|
179
164
|
```
|
|
180
165
|
|
|
181
166
|
### Programmatic API
|
|
@@ -327,6 +312,9 @@ interface ShellProperties {
|
|
|
327
312
|
| `writeFileAsUser(authUser, path, content)` | Write with quota enforcement. |
|
|
328
313
|
| `refreshProcFs(): void` | Refresh all `/proc/*` files (uptime, meminfo, cpuinfo, per-pid). |
|
|
329
314
|
| `refreshProcSessions(): void` | Lightweight refresh of `/proc/<pid>` and `/proc/self` only. |
|
|
315
|
+
| `mount(vPath, hostPath, options?): void` | Mount a host directory into the VFS. See [Mount API](#mount-api). |
|
|
316
|
+
| `unmount(vPath): void` | Remove a host directory mount. |
|
|
317
|
+
| `getMounts()` | List all active mounts as `{ vPath, hostPath, readOnly }[]`. |
|
|
330
318
|
| `syncPasswd(): void` | Sync `/etc/passwd`, `/etc/group`, `/etc/shadow` from user manager. |
|
|
331
319
|
| `getVfs(): VirtualFileSystem \| null` | Access VFS instance. |
|
|
332
320
|
| `getUsers(): VirtualUserManager \| null` | Access user manager. |
|
|
@@ -398,6 +386,40 @@ await vfs.flushMirror(); // save to disk
|
|
|
398
386
|
|
|
399
387
|
**Events:** `file:write { path, size }`, `file:read { path, size }`, `dir:create { path, mode }`, `node:remove { path }`, `symlink:create { link, target }`, `snapshot:import`, `snapshot:restore { path }`, `mirror:flush { path? }`
|
|
400
388
|
|
|
389
|
+
|
|
390
|
+
#### Mount API
|
|
391
|
+
|
|
392
|
+
Mount a host directory inside the VM — all standard VFS operations (`readFile`, `writeFile`, `exists`, `stat`, `list`) are transparently delegated to the host filesystem.
|
|
393
|
+
|
|
394
|
+
> **Node.js only.** In browser environments `mount()` is a silent no-op — the `vPath` remains an empty in-memory directory.
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
// Read-only mount (default) — shell commands can read host files
|
|
398
|
+
shell.mount("/workspace", "./my-project");
|
|
399
|
+
|
|
400
|
+
// Read-write mount — shell commands can also write back to the host
|
|
401
|
+
shell.mount("/data", "./data", { readOnly: false });
|
|
402
|
+
|
|
403
|
+
// Unmount — delegation removed, vPath stays as an empty VFS directory
|
|
404
|
+
shell.unmount("/workspace");
|
|
405
|
+
|
|
406
|
+
// Introspect
|
|
407
|
+
shell.getMounts();
|
|
408
|
+
// → [{ vPath: "/workspace", hostPath: "/abs/path/my-project", readOnly: true }]
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Direct VFS usage:
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
shell.vfs.mount("/workspace", "./my-project");
|
|
415
|
+
shell.vfs.unmount("/workspace");
|
|
416
|
+
shell.vfs.getMounts();
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Events:** `mount { vPath, hostPath, readOnly }`, `unmount { vPath }`
|
|
420
|
+
|
|
421
|
+
**Snapshot behaviour:** mounted files are **not** included in `toSnapshot()` — only the in-memory VFS tree is serialised. The mount configuration itself is also not persisted; restore it after each `fromSnapshot()` or `restoreMirror()`.
|
|
422
|
+
|
|
401
423
|
#### VFSB Binary Format
|
|
402
424
|
|
|
403
425
|
In `"fs"` mode, state is persisted as a compact binary file (`vfs-snapshot.vfsb`).
|
|
@@ -654,6 +676,17 @@ interface VirtualActiveSession {
|
|
|
654
676
|
remoteAddress: string;
|
|
655
677
|
startedAt: string; // ISO-8601
|
|
656
678
|
}
|
|
679
|
+
|
|
680
|
+
/** Returned by adduser, passwd, deluser — triggers interactive password prompt in the terminal. */
|
|
681
|
+
interface PasswordChallenge {
|
|
682
|
+
preamble?: string; // Lines printed before the first prompt
|
|
683
|
+
prompt: string; // e.g. "New password: "
|
|
684
|
+
confirmPrompt?: string; // Second prompt for confirmation
|
|
685
|
+
confirmText?: string; // Destructive confirmation prompt (y/N)
|
|
686
|
+
action: "adduser" | "passwd" | "deluser" | "su";
|
|
687
|
+
targetUsername: string;
|
|
688
|
+
newUsername?: string; // adduser only
|
|
689
|
+
}
|
|
657
690
|
```
|
|
658
691
|
|
|
659
692
|
---
|
|
@@ -932,7 +965,7 @@ echo "Welcome back, root!"
|
|
|
932
965
|
<details>
|
|
933
966
|
<summary><strong>Built-in Commands (91)</strong></summary>
|
|
934
967
|
|
|
935
|
-
Type `help` in the shell for a grouped, colorized listing. Type `help <command>` for detailed usage.
|
|
968
|
+
Type `help` in the shell for a grouped, colorized listing. Type `help <command>` for detailed usage. Type `man <command>` for full manual pages — all 91 commands are documented.
|
|
936
969
|
|
|
937
970
|
### Navigation
|
|
938
971
|
|
|
@@ -1440,13 +1473,17 @@ Open:
|
|
|
1440
1473
|
- [x] Pure in-memory VFS · symlinks · binary snapshot format (VFSB, ~27% smaller than JSON+base64)
|
|
1441
1474
|
- [x] Linux rootfs on boot — `/etc`, `/proc`, `/sys`, `/dev`, `/usr`, `/var`
|
|
1442
1475
|
- [x] Virtual package manager — `apt`/`dpkg`, 25 packages, VFS file writes
|
|
1443
|
-
- [x]
|
|
1444
|
-
- [x] Real shell interpreter — `if`/`for`/`while`/`case`/functions, `$(cmd)`, `$((expr))`, `${#VAR}`,
|
|
1476
|
+
- [x] 92 built-in commands across 9 categories (`seq` added)
|
|
1477
|
+
- [x] Real shell interpreter — `if`/`for`/`while`/`case`/functions, `$(cmd)`, `$((expr))`, `${#VAR}`, `{a,b,c}` brace expansion, `{1..N}` ranges, `2>/dev/null` stderr redirect, `2>&1`, `(( x++ ))`
|
|
1445
1478
|
- [x] `curl`/`wget` as pure `fetch()` · VFS PATH resolution · `/sbin` root-only
|
|
1446
1479
|
- [x] `/proc/self` and `/proc/<pid>` per-session entries
|
|
1447
1480
|
- [x] Snapshot diff tooling — `diffSnapshots`, `formatDiff`, `assertDiff`
|
|
1448
1481
|
- [x] `node`/`python3`/`npm`/`npx` — package-gated virtual REPL stubs
|
|
1449
|
-
- [x] Web shell
|
|
1450
|
-
- [x] Self-standalone CLI (`self-standalone.js`) — single-file interactive shell,
|
|
1482
|
+
- [x] Web shell bundles (`web.min.js`, `web-full-api.min.js`) — fully browser-native with IndexedDB VFS
|
|
1483
|
+
- [x] Self-standalone CLI (`self-standalone.js`) — single-file interactive shell, per-user history, tab completion
|
|
1484
|
+
- [x] 120+ `man` pages — all built-in commands documented via `man <cmd>`
|
|
1485
|
+
- [x] Shared `tokenize.ts` — unified tokenizer for shell parser and runtime (eliminates duplication)
|
|
1486
|
+
- [x] `PasswordChallenge` type — generic interactive password flow for `adduser`, `passwd`, `deluser`
|
|
1487
|
+
- [x] `VirtualFileSystem.mount(vPath, hostPath, { readOnly })` — bind-mount host directories into the VM; read-only by default; browser-safe (silent no-op)
|
|
1451
1488
|
|
|
1452
1489
|
</details>
|