typescript-virtual-container 1.5.6 → 1.5.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/README.md +28 -20
- package/dist/.tsbuildinfo +1 -1
- package/dist/SSHMimic/index.d.ts +5 -1
- package/dist/SSHMimic/index.js +27 -3
- package/dist/SSHMimic/prompt.d.ts +2 -1
- package/dist/SSHMimic/prompt.js +27 -5
- package/dist/SSHMimic/scp.d.ts +34 -0
- package/dist/SSHMimic/scp.js +285 -0
- package/dist/SSHMimic/sftp.d.ts +53 -3
- package/dist/SSHMimic/sftp.js +9 -3
- package/dist/VirtualFileSystem/binaryPack.d.ts +7 -0
- package/dist/VirtualFileSystem/binaryPack.js +37 -1
- package/dist/VirtualFileSystem/index.d.ts +7 -0
- package/dist/VirtualFileSystem/index.js +67 -27
- package/dist/VirtualFileSystem/internalTypes.d.ts +2 -0
- package/dist/VirtualFileSystem/path.d.ts +5 -0
- package/dist/VirtualFileSystem/path.js +24 -11
- package/dist/VirtualPackageManager/index.d.ts +4 -2
- package/dist/VirtualPackageManager/index.js +24 -4
- package/dist/VirtualShell/index.d.ts +6 -3
- package/dist/VirtualShell/index.js +3 -10
- package/dist/VirtualShell/shell.js +114 -140
- package/dist/VirtualShell/shellParser.js +1 -22
- package/dist/commands/exit.js +1 -1
- package/dist/commands/find.js +1 -4
- package/dist/commands/helpers.d.ts +0 -20
- package/dist/commands/helpers.js +0 -97
- package/dist/commands/id.js +8 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/manuals-bundle.js +10 -1
- package/dist/commands/perl.js +1 -1
- package/dist/commands/python.js +5 -2
- package/dist/commands/registry.js +6 -1
- package/dist/commands/rm.d.ts +1 -1
- package/dist/commands/rm.js +48 -11
- package/dist/commands/runtime.d.ts +5 -0
- package/dist/commands/runtime.js +90 -88
- package/dist/commands/strace.js +1 -1
- package/dist/commands/tar.js +2 -2
- package/dist/commands/test.js +2 -2
- package/dist/modules/linuxRootfs.js +7 -6
- package/dist/modules/nanoEditor.d.ts +92 -0
- package/dist/modules/nanoEditor.js +956 -0
- package/dist/modules/neofetch.js +2 -2
- package/dist/modules/webTermRenderer.d.ts +42 -0
- package/dist/modules/webTermRenderer.js +291 -0
- package/dist/types/commands.d.ts +4 -0
- package/dist/utils/argv.d.ts +6 -0
- package/dist/utils/argv.js +32 -0
- package/dist/utils/expand.d.ts +5 -2
- package/dist/utils/expand.js +70 -67
- package/dist/utils/glob.d.ts +6 -0
- package/dist/utils/glob.js +34 -0
- package/dist/utils/shellSession.d.ts +10 -0
- package/dist/utils/shellSession.js +56 -0
- package/dist/utils/tokenize.js +13 -13
- package/package.json +7 -6
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const _globCache = new Map();
|
|
2
|
+
/**
|
|
3
|
+
* Convert a shell glob pattern to a RegExp.
|
|
4
|
+
* Supports: * (any chars), ? (one char), [...] (char class), flags (e.g. "i").
|
|
5
|
+
* Results are memoized — same pattern+flags returns the cached instance.
|
|
6
|
+
*/
|
|
7
|
+
export function globToRegex(pattern, flags = "") {
|
|
8
|
+
const key = `${flags}:${pattern}`;
|
|
9
|
+
const cached = _globCache.get(key);
|
|
10
|
+
if (cached)
|
|
11
|
+
return cached;
|
|
12
|
+
let re = "^";
|
|
13
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
14
|
+
const c = pattern[i];
|
|
15
|
+
if (c === "*")
|
|
16
|
+
re += ".*";
|
|
17
|
+
else if (c === "?")
|
|
18
|
+
re += ".";
|
|
19
|
+
else if (c === "[") {
|
|
20
|
+
const close = pattern.indexOf("]", i + 1);
|
|
21
|
+
if (close === -1)
|
|
22
|
+
re += "\\[";
|
|
23
|
+
else {
|
|
24
|
+
re += `[${pattern.slice(i + 1, close)}]`;
|
|
25
|
+
i = close;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else
|
|
29
|
+
re += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
30
|
+
}
|
|
31
|
+
const result = new RegExp(`${re}$`, flags);
|
|
32
|
+
_globCache.set(key, result);
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type VirtualFileSystem from "../VirtualFileSystem";
|
|
2
|
+
export declare function loadHistory(vfs: VirtualFileSystem, authUser: string): string[];
|
|
3
|
+
export declare function saveHistory(vfs: VirtualFileSystem, authUser: string, history: string[]): void;
|
|
4
|
+
export interface LastLogin {
|
|
5
|
+
at: string;
|
|
6
|
+
from: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function readLastLogin(vfs: VirtualFileSystem, authUser: string): LastLogin | null;
|
|
9
|
+
export declare function writeLastLogin(vfs: VirtualFileSystem, authUser: string, from: string): void;
|
|
10
|
+
export declare function listPathCompletions(vfs: VirtualFileSystem, cwd: string, prefix: string): string[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { resolvePath } from "../commands/helpers";
|
|
3
|
+
import { userHome } from "../commands/runtime";
|
|
4
|
+
// ── History ───────────────────────────────────────────────────────────────────
|
|
5
|
+
export function loadHistory(vfs, authUser) {
|
|
6
|
+
const historyPath = `${userHome(authUser)}/.bash_history`;
|
|
7
|
+
if (!vfs.exists(historyPath)) {
|
|
8
|
+
vfs.writeFile(historyPath, "");
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
return vfs.readFile(historyPath)
|
|
12
|
+
.split("\n")
|
|
13
|
+
.map((l) => l.trim())
|
|
14
|
+
.filter((l) => l.length > 0);
|
|
15
|
+
}
|
|
16
|
+
export function saveHistory(vfs, authUser, history) {
|
|
17
|
+
const data = history.length > 0 ? `${history.join("\n")}\n` : "";
|
|
18
|
+
vfs.writeFile(`${userHome(authUser)}/.bash_history`, data);
|
|
19
|
+
}
|
|
20
|
+
export function readLastLogin(vfs, authUser) {
|
|
21
|
+
const p = authUser === "root" ? "/root/.lastlog.json" : `/home/${authUser}/.lastlog`;
|
|
22
|
+
if (!vfs.exists(p))
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(vfs.readFile(p));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function writeLastLogin(vfs, authUser, from) {
|
|
32
|
+
const p = authUser === "root" ? "/root/.lastlog.json" : `/home/${authUser}/.lastlog`;
|
|
33
|
+
vfs.writeFile(p, JSON.stringify({ at: new Date().toISOString(), from }));
|
|
34
|
+
}
|
|
35
|
+
// ── Path completion ───────────────────────────────────────────────────────────
|
|
36
|
+
export function listPathCompletions(vfs, cwd, prefix) {
|
|
37
|
+
const slashIndex = prefix.lastIndexOf("/");
|
|
38
|
+
const dirPart = slashIndex >= 0 ? prefix.slice(0, slashIndex + 1) : "";
|
|
39
|
+
const namePart = slashIndex >= 0 ? prefix.slice(slashIndex + 1) : prefix;
|
|
40
|
+
const basePath = resolvePath(cwd, dirPart || ".");
|
|
41
|
+
try {
|
|
42
|
+
return vfs
|
|
43
|
+
.list(basePath)
|
|
44
|
+
.filter((e) => e.startsWith(namePart))
|
|
45
|
+
.filter((e) => namePart.startsWith(".") || !e.startsWith("."))
|
|
46
|
+
.map((e) => {
|
|
47
|
+
const fullPath = path.posix.join(basePath, e);
|
|
48
|
+
const st = vfs.stat(fullPath);
|
|
49
|
+
return `${dirPart}${e}${st.type === "directory" ? "/" : ""}`;
|
|
50
|
+
})
|
|
51
|
+
.sort();
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
package/dist/utils/tokenize.js
CHANGED
|
@@ -51,9 +51,11 @@ export function tokenizeCommand(input) {
|
|
|
51
51
|
continue;
|
|
52
52
|
}
|
|
53
53
|
// Handle 2>&1, 2>>, 2>, >&, >>
|
|
54
|
-
if (!inQ && ch === "2" &&
|
|
55
|
-
const
|
|
56
|
-
|
|
54
|
+
if (!inQ && ch === "2" && next === ">") {
|
|
55
|
+
const c2 = input[i + 2];
|
|
56
|
+
const c3 = input[i + 3];
|
|
57
|
+
const c4 = input[i + 4];
|
|
58
|
+
if (c2 === ">" && c3 === "&" && c4 === "1") {
|
|
57
59
|
if (current) {
|
|
58
60
|
tokens.push(current);
|
|
59
61
|
current = "";
|
|
@@ -62,7 +64,7 @@ export function tokenizeCommand(input) {
|
|
|
62
64
|
i += 5;
|
|
63
65
|
continue;
|
|
64
66
|
}
|
|
65
|
-
if (
|
|
67
|
+
if (c2 === "&" && c3 === "1") {
|
|
66
68
|
if (current) {
|
|
67
69
|
tokens.push(current);
|
|
68
70
|
current = "";
|
|
@@ -71,7 +73,7 @@ export function tokenizeCommand(input) {
|
|
|
71
73
|
i += 4;
|
|
72
74
|
continue;
|
|
73
75
|
}
|
|
74
|
-
if (
|
|
76
|
+
if (c2 === ">") {
|
|
75
77
|
if (current) {
|
|
76
78
|
tokens.push(current);
|
|
77
79
|
current = "";
|
|
@@ -80,15 +82,13 @@ export function tokenizeCommand(input) {
|
|
|
80
82
|
i += 3;
|
|
81
83
|
continue;
|
|
82
84
|
}
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
current = "";
|
|
87
|
-
}
|
|
88
|
-
tokens.push("2>");
|
|
89
|
-
i += 2;
|
|
90
|
-
continue;
|
|
85
|
+
if (current) {
|
|
86
|
+
tokens.push(current);
|
|
87
|
+
current = "";
|
|
91
88
|
}
|
|
89
|
+
tokens.push("2>");
|
|
90
|
+
i += 2;
|
|
91
|
+
continue;
|
|
92
92
|
}
|
|
93
93
|
if ((ch === ">" || ch === "<") && !inQ) {
|
|
94
94
|
if (current) {
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "1.5.
|
|
7
|
+
"version": "1.5.8",
|
|
8
8
|
"files": [
|
|
9
9
|
"dist/",
|
|
10
10
|
"README.md",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"test": "bun run test-salve",
|
|
34
34
|
"test-battery": "bun test tests/",
|
|
35
35
|
"test-salve": "for f in tests/*.test.ts; do echo \"\\n🧪 Testing $f...\"; bun test \"$f\" --timeout 10000; sleep 0.25; done",
|
|
36
|
-
"build": "tsc --project tsconfig.json",
|
|
36
|
+
"build": "tsc --project tsconfig.json && rm -f dist/*standalone*",
|
|
37
37
|
"deploy:npm": "bun publish --access public",
|
|
38
38
|
"bench": "rm -rf .benchmark-shells/ && bun benchmark-virtualshell.ts",
|
|
39
|
-
"
|
|
40
|
-
|
|
39
|
+
"benchmark": "bun benchmark-virtualshell.ts > benchmark-results.txt",
|
|
40
|
+
"web-build": "bunx esbuild src/web.ts --bundle --platform=browser --format=esm --target=es2020 --outfile=builds/web.min.js --tree-shaking=true --minify",
|
|
41
41
|
"web-build-iife": "bunx esbuild src/web.ts --bundle --platform=browser --format=iife --target=es2020 --outfile=builds/web-iife.min.js --tree-shaking=true --minify --global-name=WebShellLib",
|
|
42
42
|
"example-build": "bun run web-build && cp builds/web.min.js examples/web.min.js",
|
|
43
43
|
"example-serve": "cd examples && bun server.js",
|
|
@@ -45,8 +45,9 @@
|
|
|
45
45
|
"publish-package": "bash ./scripts/publish-package.sh",
|
|
46
46
|
"self-standalone-build": "node scripts/build-all.mjs",
|
|
47
47
|
"standalone-build": "bunx esbuild src/standalone.ts --bundle --platform=node --target=node18 --outfile=builds/standalone.cjs --tree-shaking=true --minify --banner:js='#!/usr/bin/env node'",
|
|
48
|
-
"build-all": "node scripts/build-all.mjs",
|
|
49
|
-
"publish-doc": "bunx typedoc && bun build-all &&
|
|
48
|
+
"build-all": "bun run build && node scripts/build-all.mjs && cd examples && node build && cd .. && cp examples/app.js docs/app.js",
|
|
49
|
+
"publish-doc": "bunx typedoc && bun build-all && bunx gh-pages -d docs && git add docs && git commit -m 'docs: update documentation' && git push",
|
|
50
|
+
"publish-doc-app": "bun build-all && bunx gh-pages -d docs && git add docs/app.js && git commit -m 'docs: update web terminal app' && git push",
|
|
50
51
|
"generate-manuals": "node scripts/generate-manuals-bundle.mjs"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|