lunel-cli 0.1.5 → 0.1.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/dist/index.js +50 -43
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -8,9 +8,8 @@ import * as path from "path";
|
|
|
8
8
|
import * as os from "os";
|
|
9
9
|
import { spawn, execSync } from "child_process";
|
|
10
10
|
import { createServer } from "net";
|
|
11
|
-
import * as pty from "node-pty";
|
|
12
11
|
const PROXY_URL = process.env.LUNEL_PROXY_URL || "https://gateway.lunel.dev";
|
|
13
|
-
const VERSION = "0.1.
|
|
12
|
+
const VERSION = "0.1.6";
|
|
14
13
|
// Root directory - sandbox all file operations to this
|
|
15
14
|
const ROOT_DIR = process.cwd();
|
|
16
15
|
const terminals = new Map();
|
|
@@ -481,40 +480,61 @@ async function handleGitDiscard(payload) {
|
|
|
481
480
|
// ============================================================================
|
|
482
481
|
let dataChannel = null;
|
|
483
482
|
function handleTerminalSpawn(payload) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const
|
|
483
|
+
// Find a working shell
|
|
484
|
+
let shell = payload.shell || process.env.SHELL || '';
|
|
485
|
+
const possibleShells = os.platform() === 'win32'
|
|
486
|
+
? ['powershell.exe', 'cmd.exe']
|
|
487
|
+
: [shell, '/bin/zsh', '/bin/bash', '/bin/sh'].filter(Boolean);
|
|
488
|
+
shell = '';
|
|
489
|
+
for (const candidate of possibleShells) {
|
|
490
|
+
if (!candidate)
|
|
491
|
+
continue;
|
|
492
|
+
try {
|
|
493
|
+
if (os.platform() !== 'win32') {
|
|
494
|
+
execSync(`test -x "${candidate}"`, { stdio: 'ignore' });
|
|
495
|
+
}
|
|
496
|
+
shell = candidate;
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
catch {
|
|
500
|
+
// Try next
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (!shell) {
|
|
504
|
+
throw Object.assign(new Error('No valid shell found'), { code: 'ENOSHELL' });
|
|
505
|
+
}
|
|
487
506
|
const terminalId = `term-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
|
|
488
|
-
//
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
507
|
+
// Clean environment
|
|
508
|
+
const cleanEnv = {};
|
|
509
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
510
|
+
if (value !== undefined) {
|
|
511
|
+
cleanEnv[key] = value;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
cleanEnv['TERM'] = 'dumb'; // Simple terminal - no escape codes
|
|
515
|
+
// Spawn shell process
|
|
516
|
+
const proc = spawn(shell, ['-i'], {
|
|
493
517
|
cwd: ROOT_DIR,
|
|
494
|
-
env:
|
|
495
|
-
|
|
496
|
-
TERM: 'xterm-256color',
|
|
497
|
-
},
|
|
518
|
+
env: cleanEnv,
|
|
519
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
498
520
|
});
|
|
499
|
-
terminals.set(terminalId, {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
rows,
|
|
503
|
-
});
|
|
504
|
-
// Stream output to app via data channel
|
|
505
|
-
ptyProcess.onData((data) => {
|
|
521
|
+
terminals.set(terminalId, { proc, shell });
|
|
522
|
+
// Stream output to app
|
|
523
|
+
const sendOutput = (data) => {
|
|
506
524
|
if (dataChannel && dataChannel.readyState === WebSocket.OPEN) {
|
|
507
525
|
const msg = {
|
|
508
526
|
v: 1,
|
|
509
527
|
id: `evt-${Date.now()}`,
|
|
510
528
|
ns: "terminal",
|
|
511
529
|
action: "output",
|
|
512
|
-
payload: { terminalId, data },
|
|
530
|
+
payload: { terminalId, data: data.toString() },
|
|
513
531
|
};
|
|
514
532
|
dataChannel.send(JSON.stringify(msg));
|
|
515
533
|
}
|
|
516
|
-
}
|
|
517
|
-
|
|
534
|
+
};
|
|
535
|
+
proc.stdout?.on('data', sendOutput);
|
|
536
|
+
proc.stderr?.on('data', sendOutput);
|
|
537
|
+
proc.on('close', (code) => {
|
|
518
538
|
terminals.delete(terminalId);
|
|
519
539
|
if (dataChannel && dataChannel.readyState === WebSocket.OPEN) {
|
|
520
540
|
const msg = {
|
|
@@ -522,12 +542,12 @@ function handleTerminalSpawn(payload) {
|
|
|
522
542
|
id: `evt-${Date.now()}`,
|
|
523
543
|
ns: "terminal",
|
|
524
544
|
action: "exit",
|
|
525
|
-
payload: { terminalId, code:
|
|
545
|
+
payload: { terminalId, code: code || 0 },
|
|
526
546
|
};
|
|
527
547
|
dataChannel.send(JSON.stringify(msg));
|
|
528
548
|
}
|
|
529
549
|
});
|
|
530
|
-
return { terminalId };
|
|
550
|
+
return { terminalId, shell };
|
|
531
551
|
}
|
|
532
552
|
function handleTerminalWrite(payload) {
|
|
533
553
|
const terminalId = payload.terminalId;
|
|
@@ -539,24 +559,11 @@ function handleTerminalWrite(payload) {
|
|
|
539
559
|
const session = terminals.get(terminalId);
|
|
540
560
|
if (!session)
|
|
541
561
|
throw Object.assign(new Error("Terminal not found"), { code: "ENOTERM" });
|
|
542
|
-
session.
|
|
562
|
+
session.proc.stdin?.write(data);
|
|
543
563
|
return {};
|
|
544
564
|
}
|
|
545
565
|
function handleTerminalResize(payload) {
|
|
546
|
-
|
|
547
|
-
const cols = payload.cols;
|
|
548
|
-
const rows = payload.rows;
|
|
549
|
-
if (!terminalId)
|
|
550
|
-
throw Object.assign(new Error("terminalId is required"), { code: "EINVAL" });
|
|
551
|
-
if (!cols || !rows)
|
|
552
|
-
throw Object.assign(new Error("cols and rows are required"), { code: "EINVAL" });
|
|
553
|
-
const session = terminals.get(terminalId);
|
|
554
|
-
if (!session)
|
|
555
|
-
throw Object.assign(new Error("Terminal not found"), { code: "ENOTERM" });
|
|
556
|
-
// Resize PTY
|
|
557
|
-
session.pty.resize(cols, rows);
|
|
558
|
-
session.cols = cols;
|
|
559
|
-
session.rows = rows;
|
|
566
|
+
// No-op for simple terminal - resize not supported without PTY
|
|
560
567
|
return {};
|
|
561
568
|
}
|
|
562
569
|
function handleTerminalKill(payload) {
|
|
@@ -566,7 +573,7 @@ function handleTerminalKill(payload) {
|
|
|
566
573
|
const session = terminals.get(terminalId);
|
|
567
574
|
if (!session)
|
|
568
575
|
throw Object.assign(new Error("Terminal not found"), { code: "ENOTERM" });
|
|
569
|
-
session.
|
|
576
|
+
session.proc.kill();
|
|
570
577
|
terminals.delete(terminalId);
|
|
571
578
|
return {};
|
|
572
579
|
}
|
|
@@ -1363,7 +1370,7 @@ function connectWebSocket(code) {
|
|
|
1363
1370
|
console.log("\nShutting down...");
|
|
1364
1371
|
// Kill all terminals
|
|
1365
1372
|
for (const [id, session] of terminals) {
|
|
1366
|
-
session.
|
|
1373
|
+
session.proc.kill();
|
|
1367
1374
|
}
|
|
1368
1375
|
terminals.clear();
|
|
1369
1376
|
// Kill all managed processes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lunel-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"author": [
|
|
5
5
|
{
|
|
6
6
|
"name": "Soham Bharambe",
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"ignore": "^6.0.2",
|
|
29
|
-
"node-pty": "^1.0.0",
|
|
30
29
|
"qrcode-terminal": "^0.12.0",
|
|
31
30
|
"ws": "^8.18.0"
|
|
32
31
|
},
|