typescript-virtual-container 1.5.5 → 1.5.7
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 +117 -35
- package/dist/.tsbuildinfo +1 -1
- package/dist/SSHMimic/index.d.ts +5 -1
- package/dist/SSHMimic/index.js +27 -3
- 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 +4 -0
- package/dist/VirtualShell/index.js +1 -7
- package/dist/VirtualShell/shell.js +40 -10
- package/dist/VirtualShell/shellParser.js +1 -22
- package/dist/commands/awk.d.ts +6 -11
- package/dist/commands/awk.js +462 -109
- package/dist/commands/bzip2.d.ts +11 -0
- package/dist/commands/bzip2.js +91 -0
- package/dist/commands/exit.js +1 -1
- package/dist/commands/find.d.ts +2 -2
- package/dist/commands/find.js +209 -37
- package/dist/commands/helpers.d.ts +0 -20
- package/dist/commands/helpers.js +0 -97
- package/dist/commands/lsof.d.ts +6 -0
- package/dist/commands/lsof.js +30 -0
- package/dist/commands/perl.d.ts +6 -0
- package/dist/commands/perl.js +76 -0
- package/dist/commands/python.js +5 -2
- package/dist/commands/registry.js +19 -1
- package/dist/commands/runtime.js +65 -87
- package/dist/commands/sed.d.ts +2 -2
- package/dist/commands/sed.js +216 -34
- package/dist/commands/sh.js +42 -0
- package/dist/commands/strace.d.ts +6 -0
- package/dist/commands/strace.js +26 -0
- package/dist/commands/tar.d.ts +2 -1
- package/dist/commands/tar.js +138 -52
- package/dist/commands/test.js +2 -2
- package/dist/commands/zip.d.ts +11 -0
- package/dist/commands/zip.js +232 -0
- package/dist/modules/linuxRootfs.js +1 -4
- package/dist/modules/neofetch.js +2 -2
- 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 +112 -45
- package/dist/utils/glob.d.ts +6 -0
- package/dist/utils/glob.js +34 -0
- package/dist/utils/tokenize.js +13 -13
- package/package.json +9 -7
- package/dist/self-standalone.d.ts +0 -1
- package/dist/self-standalone.js +0 -444
- package/dist/standalone-wo-sftp.d.ts +0 -1
- package/dist/standalone-wo-sftp.js +0 -30
- package/dist/standalone.d.ts +0 -1
- package/dist/standalone.js +0 -61
package/dist/utils/expand.js
CHANGED
|
@@ -17,6 +17,24 @@
|
|
|
17
17
|
* $VAR simple reference
|
|
18
18
|
* $((expr)) arithmetic (integer)
|
|
19
19
|
*/
|
|
20
|
+
import { globToRegex } from "./glob";
|
|
21
|
+
// Memoized shell-pattern → RegExp for ${VAR//pat/rep} etc. forms.
|
|
22
|
+
// Key encodes anchor/greedy options to keep separate caches per form.
|
|
23
|
+
const _shellPatCache = new Map();
|
|
24
|
+
function shellPatToRegex(pat, anchor, greedy, global = false) {
|
|
25
|
+
const key = `${anchor}:${greedy ? "g" : "s"}:${global ? "G" : ""}:${pat}`;
|
|
26
|
+
let re = _shellPatCache.get(key);
|
|
27
|
+
if (re)
|
|
28
|
+
return re;
|
|
29
|
+
const esc = pat.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
30
|
+
const body = greedy
|
|
31
|
+
? esc.replace(/\*/g, ".*").replace(/\?/g, ".")
|
|
32
|
+
: esc.replace(/\*/g, "[^/]*").replace(/\?/g, ".");
|
|
33
|
+
const src = anchor === "prefix" ? `^${body}` : anchor === "suffix" ? `${body}$` : body;
|
|
34
|
+
re = new RegExp(src, global ? "g" : "");
|
|
35
|
+
_shellPatCache.set(key, re);
|
|
36
|
+
return re;
|
|
37
|
+
}
|
|
20
38
|
function tokenizeArith(expr, env) {
|
|
21
39
|
const tokens = [];
|
|
22
40
|
let i = 0;
|
|
@@ -193,25 +211,24 @@ export function evalArith(expr, env) {
|
|
|
193
211
|
* Single-quoted content is passed through verbatim (POSIX sh behaviour).
|
|
194
212
|
*/
|
|
195
213
|
function outsideSingleQuotes(input, replacer) {
|
|
214
|
+
// Fast path: no single quotes → apply replacer to whole string, no allocation
|
|
215
|
+
if (!input.includes("'"))
|
|
216
|
+
return replacer(input);
|
|
196
217
|
const parts = [];
|
|
197
218
|
let i = 0;
|
|
198
219
|
while (i < input.length) {
|
|
199
220
|
const sqIdx = input.indexOf("'", i);
|
|
200
221
|
if (sqIdx === -1) {
|
|
201
|
-
// No more single quotes — expand the rest
|
|
202
222
|
parts.push(replacer(input.slice(i)));
|
|
203
223
|
break;
|
|
204
224
|
}
|
|
205
|
-
// Expand the part before the single quote
|
|
206
225
|
parts.push(replacer(input.slice(i, sqIdx)));
|
|
207
|
-
// Find closing single quote — everything inside is literal
|
|
208
226
|
const closeIdx = input.indexOf("'", sqIdx + 1);
|
|
209
227
|
if (closeIdx === -1) {
|
|
210
|
-
// Unclosed quote — treat rest as literal
|
|
211
228
|
parts.push(input.slice(sqIdx));
|
|
212
229
|
break;
|
|
213
230
|
}
|
|
214
|
-
parts.push(input.slice(sqIdx, closeIdx + 1));
|
|
231
|
+
parts.push(input.slice(sqIdx, closeIdx + 1));
|
|
215
232
|
i = closeIdx + 1;
|
|
216
233
|
}
|
|
217
234
|
return parts.join("");
|
|
@@ -327,10 +344,14 @@ export function expandBraces(token) {
|
|
|
327
344
|
return expandBracesInternal(token, 0);
|
|
328
345
|
}
|
|
329
346
|
function expandArithmeticChunks(input, env) {
|
|
347
|
+
if (!input.includes("$(("))
|
|
348
|
+
return input;
|
|
330
349
|
let result = "";
|
|
331
350
|
let index = 0;
|
|
351
|
+
let flush = 0;
|
|
332
352
|
while (index < input.length) {
|
|
333
353
|
if (input[index] === "$" && input[index + 1] === "(" && input[index + 2] === "(") {
|
|
354
|
+
result += input.slice(flush, index);
|
|
334
355
|
let scan = index + 3;
|
|
335
356
|
let depth = 0;
|
|
336
357
|
while (scan < input.length) {
|
|
@@ -347,6 +368,7 @@ function expandArithmeticChunks(input, env) {
|
|
|
347
368
|
const value = evalArith(expr, env);
|
|
348
369
|
result += Number.isNaN(value) ? "0" : String(value);
|
|
349
370
|
index = scan + 2;
|
|
371
|
+
flush = index;
|
|
350
372
|
break;
|
|
351
373
|
}
|
|
352
374
|
}
|
|
@@ -354,16 +376,18 @@ function expandArithmeticChunks(input, env) {
|
|
|
354
376
|
}
|
|
355
377
|
if (scan >= input.length) {
|
|
356
378
|
result += input.slice(index);
|
|
357
|
-
|
|
379
|
+
return result;
|
|
358
380
|
}
|
|
359
381
|
continue;
|
|
360
382
|
}
|
|
361
|
-
result += input[index];
|
|
362
383
|
index++;
|
|
363
384
|
}
|
|
364
|
-
return result;
|
|
385
|
+
return result + input.slice(flush);
|
|
365
386
|
}
|
|
366
387
|
export function expandSync(input, env, lastExit = 0, home) {
|
|
388
|
+
// Fast path: nothing to expand (no $ and no ~ and no single quotes)
|
|
389
|
+
if (!input.includes("$") && !input.includes("~") && !input.includes("'"))
|
|
390
|
+
return input;
|
|
367
391
|
const homePath = home ?? env.HOME ?? "/home/user";
|
|
368
392
|
return outsideSingleQuotes(input, (chunk) => {
|
|
369
393
|
let s = chunk;
|
|
@@ -377,6 +401,19 @@ export function expandSync(input, env, lastExit = 0, home) {
|
|
|
377
401
|
s = s.replace(/\$LINENO\b/g, "1");
|
|
378
402
|
// $(( arithmetic )) — must come before ${ and $VAR to avoid conflicts
|
|
379
403
|
s = expandArithmeticChunks(s, env);
|
|
404
|
+
// ${arr[@]} and ${arr[*]} — all array elements
|
|
405
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)[@*]\}/g, (_, name) => env[name] ?? "");
|
|
406
|
+
// ${arr[N]} — single array element
|
|
407
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\[(\d+)\]\}/g, (_, name, idx) => env[`${name}[${idx}]`] ?? "");
|
|
408
|
+
// ${#arr[@]} — array length
|
|
409
|
+
s = s.replace(/\$\{#([A-Za-z_][A-Za-z0-9_]*)[@*]\}/g, (_, name) => {
|
|
410
|
+
let count = 0;
|
|
411
|
+
for (const k of Object.keys(env)) {
|
|
412
|
+
if (k.startsWith(`${name}[`))
|
|
413
|
+
count++;
|
|
414
|
+
}
|
|
415
|
+
return String(count);
|
|
416
|
+
});
|
|
380
417
|
// ${#VAR} — string length
|
|
381
418
|
s = s.replace(/\$\{#([A-Za-z_][A-Za-z0-9_]*)\}/g, (_, name) => String((env[name] ?? "").length));
|
|
382
419
|
// ${VAR:-default}
|
|
@@ -389,6 +426,41 @@ export function expandSync(input, env, lastExit = 0, home) {
|
|
|
389
426
|
});
|
|
390
427
|
// ${VAR:+alternate}
|
|
391
428
|
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*):\+([^}]*)\}/g, (_, name, alt) => env[name] !== undefined && env[name] !== "" ? alt : "");
|
|
429
|
+
// ${VAR:offset:len} and ${VAR:offset}
|
|
430
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*):(-?\d+)(?::(\d+))?\}/g, (_, name, offset, len) => {
|
|
431
|
+
const val = env[name] ?? "";
|
|
432
|
+
const off = parseInt(offset, 10);
|
|
433
|
+
const start = off < 0 ? Math.max(0, val.length + off) : Math.min(off, val.length);
|
|
434
|
+
return len !== undefined ? val.slice(start, start + parseInt(len, 10)) : val.slice(start);
|
|
435
|
+
});
|
|
436
|
+
// ${VAR//pattern/replace} — replace all
|
|
437
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\/\/([^/}]*)\/([^}]*)\}/g, (_, name, pat, rep) => {
|
|
438
|
+
const val = env[name] ?? "";
|
|
439
|
+
try {
|
|
440
|
+
return val.replace(shellPatToRegex(pat, "none", true, true), rep);
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
return val;
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
// ${VAR/pattern/replace} — replace first
|
|
447
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\/([^/}]*)\/([^}]*)\}/g, (_, name, pat, rep) => {
|
|
448
|
+
const val = env[name] ?? "";
|
|
449
|
+
try {
|
|
450
|
+
return val.replace(shellPatToRegex(pat, "none", true, false), rep);
|
|
451
|
+
}
|
|
452
|
+
catch {
|
|
453
|
+
return val;
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
// ${VAR##pattern} — strip longest prefix
|
|
457
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)##([^}]+)\}/g, (_, name, pat) => (env[name] ?? "").replace(shellPatToRegex(pat, "prefix", true), ""));
|
|
458
|
+
// ${VAR#pattern} — strip shortest prefix
|
|
459
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)#([^}]+)\}/g, (_, name, pat) => (env[name] ?? "").replace(shellPatToRegex(pat, "prefix", false), ""));
|
|
460
|
+
// ${VAR%%pattern} — strip longest suffix
|
|
461
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)%%([^}]+)\}/g, (_, name, pat) => (env[name] ?? "").replace(shellPatToRegex(pat, "suffix", true), ""));
|
|
462
|
+
// ${VAR%pattern} — strip shortest suffix
|
|
463
|
+
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)%([^}]+)\}/g, (_, name, pat) => (env[name] ?? "").replace(shellPatToRegex(pat, "suffix", false), ""));
|
|
392
464
|
// ${VAR}
|
|
393
465
|
s = s.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_, name) => env[name] ?? "");
|
|
394
466
|
// $VAR and positional params $1 $2 ...
|
|
@@ -476,12 +548,16 @@ export async function expandAsync(input, env, lastExit, runCmd) {
|
|
|
476
548
|
env[depthKey] = String(currentDepth);
|
|
477
549
|
}
|
|
478
550
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
551
|
+
function nodeType(vfs, p) {
|
|
552
|
+
if (vfs.statType)
|
|
553
|
+
return vfs.statType(p);
|
|
554
|
+
try {
|
|
555
|
+
return vfs.stat(p).type;
|
|
556
|
+
}
|
|
557
|
+
catch {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
485
561
|
export function expandGlob(pattern, cwd, vfs) {
|
|
486
562
|
// No glob chars → return as-is
|
|
487
563
|
if (!pattern.includes('*') && !pattern.includes('?'))
|
|
@@ -503,14 +579,14 @@ function matchGlob(dir, segments, vfs) {
|
|
|
503
579
|
// ** matches zero or more path segments
|
|
504
580
|
if (seg === '**') {
|
|
505
581
|
const all = walkAll(dir, vfs);
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
582
|
+
if (rest.length === 0)
|
|
583
|
+
return all;
|
|
584
|
+
const out = [];
|
|
585
|
+
for (const d of all) {
|
|
586
|
+
if (nodeType(vfs, d) === 'directory')
|
|
587
|
+
out.push(...matchGlob(d, rest, vfs));
|
|
588
|
+
}
|
|
589
|
+
return out;
|
|
514
590
|
}
|
|
515
591
|
let entries = [];
|
|
516
592
|
try {
|
|
@@ -520,20 +596,20 @@ function matchGlob(dir, segments, vfs) {
|
|
|
520
596
|
return [];
|
|
521
597
|
}
|
|
522
598
|
const re = globToRegex(seg);
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
.
|
|
599
|
+
const showHidden = seg.startsWith('.');
|
|
600
|
+
const matched = [];
|
|
601
|
+
for (const e of entries) {
|
|
602
|
+
if ((!showHidden && e.startsWith('.')) || !re.test(e))
|
|
603
|
+
continue;
|
|
527
604
|
const full = dir === '/' ? `/${e}` : `${dir}/${e}`;
|
|
528
|
-
if (rest.length === 0)
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
if (vfs.stat(full).type === 'directory')
|
|
532
|
-
return matchGlob(full, rest, vfs);
|
|
605
|
+
if (rest.length === 0) {
|
|
606
|
+
matched.push(full);
|
|
607
|
+
continue;
|
|
533
608
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
609
|
+
if (nodeType(vfs, full) === 'directory')
|
|
610
|
+
matched.push(...matchGlob(full, rest, vfs));
|
|
611
|
+
}
|
|
612
|
+
return matched;
|
|
537
613
|
}
|
|
538
614
|
function walkAll(dir, vfs) {
|
|
539
615
|
const results = [dir];
|
|
@@ -546,17 +622,8 @@ function walkAll(dir, vfs) {
|
|
|
546
622
|
}
|
|
547
623
|
for (const e of entries) {
|
|
548
624
|
const full = dir === '/' ? `/${e}` : `${dir}/${e}`;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
results.push(...walkAll(full, vfs));
|
|
552
|
-
}
|
|
553
|
-
catch { }
|
|
625
|
+
if (nodeType(vfs, full) === 'directory')
|
|
626
|
+
results.push(...walkAll(full, vfs));
|
|
554
627
|
}
|
|
555
628
|
return results;
|
|
556
629
|
}
|
|
557
|
-
function globToRegex(pattern) {
|
|
558
|
-
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
559
|
-
.replace(/\*/g, '.*')
|
|
560
|
-
.replace(/\?/g, '.');
|
|
561
|
-
return new RegExp(`^${escaped}$`);
|
|
562
|
-
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a shell glob pattern to a RegExp.
|
|
3
|
+
* Supports: * (any chars), ? (one char), [...] (char class), flags (e.g. "i").
|
|
4
|
+
* Results are memoized — same pattern+flags returns the cached instance.
|
|
5
|
+
*/
|
|
6
|
+
export declare function globToRegex(pattern: string, flags?: string): RegExp;
|
|
@@ -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
|
+
}
|
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.7",
|
|
8
8
|
"files": [
|
|
9
9
|
"dist/",
|
|
10
10
|
"README.md",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"lint:write": "bunx --bun @biomejs/biome lint --write ./src",
|
|
33
33
|
"test": "bun run test-salve",
|
|
34
34
|
"test-battery": "bun test tests/",
|
|
35
|
-
"test-salve": "for f in tests/*.test.ts; do echo \"\\n
|
|
36
|
-
"build": "tsc --project tsconfig.json",
|
|
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 && 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,14 +45,15 @@
|
|
|
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",
|
|
48
|
+
"build-all": "bun run build && node scripts/build-all.mjs && cd examples && node build && cd .. && cp examples/app.js docs/app.js",
|
|
49
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": {
|
|
53
54
|
"@biomejs/biome": "^2.4.15",
|
|
54
55
|
"@types/bun": "^1.3.14",
|
|
55
|
-
"@types/node": "^25.
|
|
56
|
+
"@types/node": "^25.8.0",
|
|
56
57
|
"@types/ssh2": "^1.15.5",
|
|
57
58
|
"esbuild": "^0.28.0",
|
|
58
59
|
"gh-pages": "^6.3.0",
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
"typescript": "^5"
|
|
64
65
|
},
|
|
65
66
|
"dependencies": {
|
|
67
|
+
"fflate": "^0.8.2",
|
|
66
68
|
"ssh2": "^1.17.0"
|
|
67
69
|
}
|
|
68
70
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|