typescript-virtual-container 1.5.5 → 1.5.6

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 CHANGED
@@ -22,7 +22,7 @@
22
22
  - [How It Works](#how-it-works)
23
23
  - [API Reference](#api-reference)
24
24
  - [Examples](#examples)
25
- - [Built-in Commands (106)](#built-in-commands-106)
25
+ - [Built-in Commands (118)](#built-in-commands-118)
26
26
  - [Shell Scripting](#shell-scripting)
27
27
  - [Linux Rootfs & VFS PATH Resolution](#linux-rootfs--vfs-path-resolution)
28
28
  - [Configuration](#configuration)
@@ -44,8 +44,8 @@
44
44
  | Mode | Entry point | Use case |
45
45
  |------|-------------|----------|
46
46
  | **SSH/SFTP server** | `VirtualSshServer` / `VirtualSftpServer` | Honeypots, remote testing, training environments |
47
- | **Web shell** | `builds/fortune-nyx-v1.5.5-web.min.js` (ESM) | Embedded terminals, interactive tutorials, browser demos |
48
- | **Standalone CLI** | `builds/fortune-nyx-v1.5.5-directbash-k6.1.0.mjs` (single file) | Local shell, one-liner demos, no install required |
47
+ | **Web shell** | `builds/fortune-nyx-v1.5.6-web.min.js` (ESM) | Embedded terminals, interactive tutorials, browser demos |
48
+ | **Standalone CLI** | `builds/fortune-nyx-v1.5.6-directbash-k6.1.0.mjs` (single file) | Local shell, one-liner demos, no install required |
49
49
  <!-- /BUILD:mode-table -->
50
50
 
51
51
  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.
@@ -66,17 +66,17 @@ npm install typescript-virtual-container
66
66
  <!-- BUILD:curl-start -->
67
67
  #### Interactivea local shell — persists VFS in .vfs/ in the current directory
68
68
  ```bash
69
- curl -s https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/fortune-nyx-v1.5.5-directbash-k6.1.0.mjs -o fortune-nyx-v1.5.5-directbash-k6.1.0.mjs && node fortune-nyx-v1.5.5-directbash-k6.1.0.mjs
69
+ curl -s https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/fortune-nyx-v1.5.6-directbash-k6.1.0.mjs -o fortune-nyx-v1.5.6-directbash-k6.1.0.mjs && node fortune-nyx-v1.5.6-directbash-k6.1.0.mjs
70
70
  ```
71
71
 
72
72
  #### SSH server (connect with any SSH client on port 2222)
73
73
  ```bash
74
- curl -s https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/fortune-nyx-v1.5.5-ssh.cjs -o fortune-nyx-v1.5.5-ssh.cjs && node fortune-nyx-v1.5.5-ssh.cjs
74
+ curl -s https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/fortune-nyx-v1.5.6-ssh.cjs -o fortune-nyx-v1.5.6-ssh.cjs && node fortune-nyx-v1.5.6-ssh.cjs
75
75
  ```
76
76
 
77
77
  #### SSH server without SFTP (lighter build)
78
78
  ```bash
79
- curl -s https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/fortune-nyx-v1.5.5-ssh-nosftp.js -o fortune-nyx-v1.5.5-ssh-nosftp.js && node fortune-nyx-v1.5.5-ssh-nosftp.js
79
+ curl -s https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-container/refs/heads/main/builds/fortune-nyx-v1.5.6-ssh-nosftp.js -o fortune-nyx-v1.5.6-ssh-nosftp.js && node fortune-nyx-v1.5.6-ssh-nosftp.js
80
80
  ```
81
81
  <!-- /BUILD:curl-start -->
82
82
 
@@ -84,13 +84,13 @@ curl -s https://raw.githubusercontent.com/itsrealfortune/typescript-virtual-cont
84
84
  > The standalone builds are intended for quick demos and testing. For production use, it's recommended to install the package and import the relevant classes directly in your codebase for better performance, stability, and security.
85
85
 
86
86
  <!-- BUILD:selfStandalone-options -->
87
- **`fortune-nyx-v1.5.5-directbash-k6.1.0.mjs` options:**
87
+ **`fortune-nyx-v1.5.6-directbash-k6.1.0.mjs` options:**
88
88
 
89
89
  ```bash
90
- node fortune-nyx-v1.5.5-directbash-k6.1.0.mjs # boot as root
91
- node fortune-nyx-v1.5.5-directbash-k6.1.0.mjs --user alice # boot as alice (prompts for password if set)
92
- node fortune-nyx-v1.5.5-directbash-k6.1.0.mjs --user=alice # same, inline form
93
- SSH_MIMIC_HOSTNAME=my-box node fortune-nyx-v1.5.5-directbash-k6.1.0.mjs # custom hostname
90
+ node fortune-nyx-v1.5.6-directbash-k6.1.0.mjs # boot as root
91
+ node fortune-nyx-v1.5.6-directbash-k6.1.0.mjs --user alice # boot as alice (prompts for password if set)
92
+ node fortune-nyx-v1.5.6-directbash-k6.1.0.mjs --user=alice # same, inline form
93
+ SSH_MIMIC_HOSTNAME=my-box node fortune-nyx-v1.5.6-directbash-k6.1.0.mjs # custom hostname
94
94
  ```
95
95
  <!-- /BUILD:selfStandalone-options -->
96
96
 
@@ -117,7 +117,7 @@ Two browser bundles are available:
117
117
  <!-- BUILD:web-table -->
118
118
  | Bundle | Format | Entry point | Use case |
119
119
  |--------|--------|-------------|----------|
120
- | `builds/fortune-nyx-v1.5.5-web.min.js` | ESM | `createWebShell()` | Embedded terminals, modern bundlers |
120
+ | `builds/fortune-nyx-v1.5.6-web.min.js` | ESM | `createWebShell()` | Embedded terminals, modern bundlers |
121
121
  <!-- /BUILD:web-table -->
122
122
 
123
123
  Both bundles persist the VFS in **IndexedDB** — state survives page reloads.
@@ -129,11 +129,11 @@ bun run build-all # rebuild everything
129
129
  ```
130
130
 
131
131
  <!-- BUILD:web-options -->
132
- **`fortune-nyx-v1.5.5-web.min.js`** — lightweight shell with IndexedDB VFS:
132
+ **`fortune-nyx-v1.5.6-web.min.js`** — lightweight shell with IndexedDB VFS:
133
133
 
134
134
  ```html
135
135
  <script type="module">
136
- import { createWebShell } from "./builds/fortune-nyx-v1.5.5-web.min.js";
136
+ import { createWebShell } from "./builds/fortune-nyx-v1.5.6-web.min.js";
137
137
 
138
138
  const shell = createWebShell("web-vm", {
139
139
  vfs: { databaseName: "virtual-env-js", storeName: "vfs" },
@@ -145,11 +145,11 @@ bun run build-all # rebuild everything
145
145
  </script>
146
146
  ```
147
147
 
148
- **`fortune-nyx-v1.5.5-web.min.js`** — mirrors the `VirtualShell` programmatic API:
148
+ **`fortune-nyx-v1.5.6-web.min.js`** — mirrors the `VirtualShell` programmatic API:
149
149
 
150
150
  ```html
151
151
  <script type="module">
152
- import { createVirtualShellShim } from "./builds/fortune-nyx-v1.5.5-web.min.js";
152
+ import { createVirtualShellShim } from "./builds/fortune-nyx-v1.5.6-web.min.js";
153
153
 
154
154
  const shell = createVirtualShellShim("web-vm");
155
155
  await shell.ensureInitialized();
@@ -475,9 +475,9 @@ echo "Welcome back, root!"
475
475
  ---
476
476
 
477
477
  <details>
478
- <summary><strong>Built-in Commands (106)</strong></summary>
478
+ <summary><strong>Built-in Commands (118)</strong></summary>
479
479
 
480
- Type `help` in the shell for a grouped, colorized listing. Type `help <command>` for detailed usage. Type `man <command>` for full manual pages — all 106 commands are documented.
480
+ Type `help` in the shell for a grouped, colorized listing. Type `help <command>` for detailed usage. Type `man <command>` for full manual pages — all 118 commands are documented.
481
481
 
482
482
  ### Navigation
483
483
 
@@ -495,7 +495,7 @@ Type `help` in the shell for a grouped, colorized listing. Type `help <command>`
495
495
  | `cat <path...>` | `-n` `-b` | Concatenate and print; `-n` numbers lines, `-b` numbers non-blank |
496
496
  | `chmod <mode> <file>` | | Octal (`755`) or symbolic (`+x`, `u+x`, `go-w`, `a=rx`) |
497
497
  | `cp <src> <dest>` | `-r` | Copy file or directory |
498
- | `find [path]` | `-name` `-type` | Search for files |
498
+ | `find [path]` | `-name` `-iname` `-type` `-maxdepth` `-mindepth` `-exec` `-not` `-o` `-a` `-empty` `-size` | Search for files |
499
499
  | `ln <target> <link>` | `-s` | Hard or symbolic link |
500
500
  | `readlink <path>` | `-f` | Print resolved path of symbolic link |
501
501
  | `mkdir <path>` | `-p` | Create directory |
@@ -509,13 +509,13 @@ Type `help` in the shell for a grouped, colorized listing. Type `help <command>`
509
509
 
510
510
  | Command | Flags | Description |
511
511
  |---------|-------|-------------|
512
- | `awk [-F <sep>] '<prog>'` | | Pattern scanning |
512
+ | `awk [-F <sep>] '<prog>'` | `-v var=val` | Pattern scanning — NR/NF, `BEGIN`/`END`, field assign, `gsub`/`sub`/`substr`/`split`/`length`, `printf` |
513
513
  | `base64` | `-d` | Encode/decode base64 |
514
514
  | `cut` | `-d` `-f` | Remove sections from lines |
515
515
  | `diff <f1> <f2>` | | Compare files line by line |
516
516
  | `grep <pattern> [files]` | `-i` `-v` `-n` `-r` | Search file content |
517
517
  | `head [files]` | `-n <N>` | First N lines |
518
- | `sed -e 's/pat/rep/[g]'` | `-i` | Stream editor |
518
+ | `sed -e 's/pat/rep/[g]'` | `-n` `-i` `-e` | Stream editor — `s///[gI]`, `d`, `p`, `=`, `q`, line/regex/range addresses |
519
519
  | `sort [files]` | `-r` `-n` `-u` | Sort lines |
520
520
  | `tail [files]` | `-n <N>` | Last N lines |
521
521
  | `tee [files]` | `-a` | Read stdin, write to stdout and files |
@@ -531,8 +531,10 @@ Type `help` in the shell for a grouped, colorized listing. Type `help <command>`
531
531
 
532
532
  | Command | Flags | Description |
533
533
  |---------|-------|-------------|
534
- | `gzip <file>` / `gunzip <file>` | | Compress / decompress |
535
- | `tar <archive> [files]` | `-czf` `-xzf` `-tf` | Archive utility |
534
+ | `gzip <file>` / `gunzip <file>` | `-k` `-d` | Compress / decompress (real gzip, browser-native) |
535
+ | `bzip2 <file>` / `bunzip2 <file>` | `-k` `-d` | Compress / decompress bzip2 (VFS round-trip) |
536
+ | `zip [-r] <archive> <files>` / `unzip <archive>` | `-l` `-d <dir>` | Real PKZIP + DEFLATE (interoperable) |
537
+ | `tar <archive> [files]` | `-czf` `-xzf` `-tf` `-v` | Archive utility — real POSIX ustar binary format (interoperable) |
536
538
 
537
539
  ### System
538
540
 
@@ -560,6 +562,9 @@ Type `help` in the shell for a grouped, colorized listing. Type `help <command>`
560
562
  | `python3` | `--version` `-c` `-V` | Virtual Python 3 interpreter; alias `python`; **requires `apt install python3`** |
561
563
  | `sleep <seconds>` | | Delay execution |
562
564
  | `uname` | `-a` `-r` `-m` | System information |
565
+ | `bc` | | Arithmetic calculator (integer; `+` `-` `*` `/` `%` `**` `()`) |
566
+ | `lsof` | `-i` | List open files (simulated) |
567
+ | `strace <cmd>` | `-e` `-o` | Trace system calls (stub with realistic output) |
563
568
  | `uptime` | `-p` `-s` | Running time |
564
569
  | `w` | | Who is logged on and what they are doing |
565
570
  | `who` | | Active sessions |
@@ -586,12 +591,16 @@ Type `help` in the shell for a grouped, colorized listing. Type `help <command>`
586
591
  | `false` | | Return exit code 1 |
587
592
  | `help [command]` | | List commands or show command usage |
588
593
  | `history [n]` | | Command history |
594
+ | `jobs` | | List active jobs |
595
+ | `bg [%n]` | | Resume job in background |
596
+ | `fg [%n]` | | Resume job in foreground |
589
597
  | `man <command>` | | Command reference manual |
590
598
  | `printf <fmt> [args...]` | | Format and print (`%s` `%d` `%f` `%x` `\n` `\t`) |
591
599
  | `read [-r] <var...>` | `-r` `-p` | Read stdin into variable(s) |
592
600
  | `return [n]` | | Return from shell function |
593
- | `set [VAR=val]` | | Display or set shell variables |
594
- | `sh` | `-c <script>` `[file]` | Execute shell script — `if`/`for`/`while`/`case`/functions, `$((expr))`, single-quote-safe |
601
+ | `set [VAR=val]` | `-e` `-x` `+e` `+x` | Display or set shell variables; `-e` exit on error, `-x` trace execution |
602
+ | `sh` | `-c <script>` `[file]` | Execute shell script — `if`/`for`/`while`/`until`/`case`/functions, arrays `arr=(a b c)`, `$((expr))`, single-quote-safe |
603
+ | `perl` | `-e` `-p` `-n` | One-liner interpreter (`print`/`say`, `s///`, `-p`/`-n` loop) |
595
604
  | `shift [n]` | | Shift positional parameters |
596
605
  | `source <file>` | | Execute file in current env; alias `.` |
597
606
  | `test <expr>` / `[ <expr> ]` | | POSIX conditional: `-f` `-d` `-e` `-z` `-n` `-x` `-s` `=` `!=` `-eq` `-lt` `-gt` `-le` `-ge` `!` `-a` `-o` |
@@ -635,7 +644,7 @@ Type `help` in the shell for a grouped, colorized listing. Type `help <command>`
635
644
  | `su [user]` | | Switch user |
636
645
  | `sudo <cmd>` | `-i` | Run as root |
637
646
 
638
- **ℹ️ All 106 built-in commands include complete JSDoc documentation** with `@category` and `@params` tags. See [src/commands/](https://github.com/itsrealfortune/typescript-virtual-container/tree/main/src/commands) for source code and inline documentation.
647
+ **ℹ️ All 118 built-in commands include complete JSDoc documentation** with `@category` and `@params` tags. See [src/commands/](https://github.com/itsrealfortune/typescript-virtual-container/tree/main/src/commands) for source code and inline documentation.
639
648
 
640
649
  Custom commands: `shell.addCommand(name, params, callback)`.
641
650
 
@@ -670,8 +679,22 @@ echo "${UNSET:-default}" # default
670
679
  echo "${NAME:+alternate}" # alternate (only if NAME is set)
671
680
  echo "${UNSET:=assigned}" # assigns and returns "assigned"
672
681
  echo "${#NAME}" # 5 (string length)
682
+ echo "${NAME:2}" # rld (substring from offset 2)
683
+ echo "${NAME:1:3}" # orl (substring offset 1, length 3)
684
+ echo "${NAME/o/0}" # w0rld (replace first)
685
+ echo "${NAME//l/L}" # worLd (replace all)
686
+ echo "${PATH##*/}" # strip longest prefix match
687
+ echo "${FILE%.txt}" # strip shortest suffix match
673
688
  echo "$?" # last exit code
689
+ echo "$RANDOM" # random integer 0–32767
690
+ echo "$LINENO" # current line number
674
691
  echo ~ # /home/<user> (tilde expansion)
692
+
693
+ # Arrays
694
+ arr=(alpha beta gamma)
695
+ echo "${arr[0]}" # alpha
696
+ echo "${arr[@]}" # alpha beta gamma
697
+ echo "${#arr[@]}" # 3
675
698
  ```
676
699
 
677
700
  > **Single-quote isolation** — `$VAR` and `$((...))` are never expanded inside `'...'`.
@@ -711,6 +734,12 @@ while [ $COUNT -lt 3 ]; do
711
734
  echo "Count: $COUNT"
712
735
  COUNT=$((COUNT + 1))
713
736
  done
737
+
738
+ COUNT=5
739
+ until [ $COUNT -eq 0 ]; do
740
+ echo "Countdown: $COUNT"
741
+ COUNT=$((COUNT - 1))
742
+ done
714
743
  ```
715
744
 
716
745
  ### Functions and case
@@ -728,6 +757,30 @@ case "$1" in
728
757
  esac
729
758
  ```
730
759
 
760
+ ### Heredoc
761
+
762
+ ```bash
763
+ cat << EOF
764
+ line one
765
+ line two
766
+ EOF
767
+
768
+ # write to file
769
+ cat > /tmp/config << EOF
770
+ HOST=localhost
771
+ PORT=3000
772
+ EOF
773
+ ```
774
+
775
+ ### set -e / set -x
776
+
777
+ ```bash
778
+ set -e # exit immediately on any non-zero exit code
779
+ set -x # print each command before executing (trace)
780
+ set +e # disable errexit
781
+ set +x # disable xtrace
782
+ ```
783
+
731
784
  ### Script Files
732
785
 
733
786
  ```typescript
@@ -740,9 +793,13 @@ done
740
793
  await client.exec("sh /usr/local/bin/setup.sh");
741
794
  ```
742
795
 
743
- ### .bashrc
796
+ ### Login Files
744
797
 
745
- Sourced automatically on every interactive session from `/home/<user>/.bashrc`:
798
+ Sourced automatically at session start, in order:
799
+
800
+ 1. `/etc/environment` — `KEY=VALUE` pairs only, no shell syntax
801
+ 2. `~/.profile` — user login script
802
+ 3. `~/.bashrc` — interactive shell config
746
803
 
747
804
  ```bash
748
805
  export EDITOR=nano
@@ -750,6 +807,20 @@ alias ll="ls -l"
750
807
  echo "Welcome, $USER!"
751
808
  ```
752
809
 
810
+ ### Line Editing
811
+
812
+ Interactive shell supports full readline-style key bindings:
813
+
814
+ | Key | Action |
815
+ |-----|--------|
816
+ | `←` / `→` | Move cursor left / right |
817
+ | `Home` / `Ctrl+A` | Jump to start of line |
818
+ | `End` / `Ctrl+E` | Jump to end of line |
819
+ | `Ctrl+K` | Kill to end of line |
820
+ | `Ctrl+U` | Kill to start of line |
821
+ | `Ctrl+W` | Kill word backward |
822
+ | `!!` | Expand to last command |
823
+
753
824
  </details>
754
825
 
755
826
  ---
@@ -1158,18 +1229,21 @@ Open:
1158
1229
  - [x] Pure in-memory VFS · symlinks · binary snapshot format (VFSB, ~27% smaller than JSON+base64)
1159
1230
  - [x] Linux rootfs on boot — `/etc`, `/proc`, `/sys`, `/dev`, `/usr`, `/var`
1160
1231
  - [x] Virtual package manager — `apt`/`dpkg`, 25 packages, VFS file writes
1161
- - [x] 106 built-in commands across 10 categories (added `w`, `ip`, `dmesg`, `last`, `basename`, `dirname`, `file`, `tput`, `stty`, `yes`, `fortune`, `cowsay`, `cowthink`, `cmatrix`, `sl`)
1162
- - [x] Real shell interpreter — `if`/`for`/`while`/`case`/functions, `$(cmd)`, `$((expr))`, `${#VAR}`, `{a,b,c}` brace expansion, `{1..N}` ranges, `*.glob` expansion, `!!`/`!n` history expansion, `\` line continuation, `2>/dev/null` stderr redirect, `2>&1`, `(( x++ ))`
1232
+ - [x] 118 built-in commands across 11 categories (added `zip`, `unzip`, `bzip2`, `bunzip2`, `lsof`, `strace`, `perl`, `w`, `ip`, `dmesg`, `last`, `basename`, `dirname`, `file`, `tput`, `stty`, `yes`, `fortune`, `cowsay`, `cowthink`, `cmatrix`, `sl`, `bc`, `jobs`, `bg`, `fg`)
1233
+ - [x] Real shell interpreter — `if`/`for`/`while`/`until`/`case`/functions, arrays `arr=(...)`, `$(cmd)`, `$((expr))`, `${#VAR}`, `${var#pfx}` `${var##pfx}` `${var%sfx}` `${var%%sfx}` `${var/p/r}` `${var//p/r}` `${var:off:len}` `${arr[@]}`, `{a,b,c}` brace expansion, `{1..N}` ranges, `*.glob` expansion, `!!` history expansion, `\` line continuation, `2>/dev/null` stderr redirect, `2>&1`, `(( x++ ))`, heredoc `<< EOF`, `set -e`/`set -x`, `$RANDOM`/`$LINENO`
1163
1234
  - [x] `curl`/`wget` as pure `fetch()` · VFS PATH resolution · `/sbin` root-only
1164
1235
  - [x] `/proc/self` and `/proc/<pid>` per-session entries
1165
1236
  - [x] Snapshot diff tooling — `diffSnapshots`, `formatDiff`, `assertDiff`
1166
1237
  - [x] `node`/`python3`/`npm`/`npx` — package-gated virtual REPL stubs
1167
1238
  <!-- BUILD:changelog -->
1168
- - [x] Web shell bundles (`fortune-nyx-v1.5.5-web.min.js`) — fully browser-native with IndexedDB VFS
1169
- - [x] Self-standalone CLI (`fortune-nyx-v1.5.5-directbash-k6.1.0.mjs`) — single-file interactive shell, per-user history, tab completion
1239
+ - [x] Web shell bundles (`fortune-nyx-v1.5.6-web.min.js`) — fully browser-native with IndexedDB VFS
1240
+ - [x] Self-standalone CLI (`fortune-nyx-v1.5.6-directbash-k6.1.0.mjs`) — single-file interactive shell, per-user history, tab completion
1170
1241
  <!-- /BUILD:changelog -->
1171
1242
  - [x] 120+ `man` pages — all built-in commands documented via `man <cmd>`
1172
1243
  - [x] Shared `tokenize.ts` — unified tokenizer for shell parser and runtime (eliminates duplication)
1244
+ - [x] Full readline line editing — `Ctrl+A/E/K/U/W`, `Home`/`End`, `!!` history expansion, `/etc/environment` + `~/.profile` login sourcing
1245
+ - [x] Interoperable archive formats — `tar` writes real POSIX ustar binary; `zip`/`unzip` use PKZIP+DEFLATE (fflate); files extracted by real system tools via SFTP
1246
+ - [x] Overhauled `sed` — `d`/`p`/`=`/`q`, `-n` suppress, line/regex/range/`$` addresses; overhauled `awk` — `-v`, field assignment, `gsub`/`sub`/`substr`/`split`/`length`/`printf`/`next`; overhauled `find` — `-exec`, `-maxdepth`, `-iname`, `-not`/`!`, `-o`/`-a`, `-empty`, `-size`
1173
1247
  - [x] `PasswordChallenge` type — generic interactive password flow for `adduser`, `passwd`, `deluser`
1174
1248
  - [x] `VirtualFileSystem.mount(vPath, hostPath, { readOnly })` — bind-mount host directories into the VM; read-only by default; browser-safe (silent no-op)
1175
1249