devbonzai 2.2.302 → 2.2.304
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/cli.js
CHANGED
|
@@ -109,6 +109,8 @@ async function main() {
|
|
|
109
109
|
packageJson.dependencies.express = "^4.18.2";
|
|
110
110
|
packageJson.dependencies.cors = "^2.8.5";
|
|
111
111
|
packageJson.dependencies["@babel/parser"] = "^7.23.0";
|
|
112
|
+
packageJson.dependencies["node-pty"] = "^1.0.0";
|
|
113
|
+
packageJson.dependencies.ws = "^8.16.0";
|
|
112
114
|
|
|
113
115
|
// Add script to run receiver
|
|
114
116
|
if (!packageJson.scripts) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devbonzai",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.304",
|
|
4
4
|
"description": "Quickly set up a local file server in any repository for browser-based file access",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"express": "^4.18.2",
|
|
26
26
|
"cors": "^2.8.5",
|
|
27
|
-
"@babel/parser": "^7.23.0"
|
|
27
|
+
"@babel/parser": "^7.23.0",
|
|
28
|
+
"node-pty": "^1.0.0",
|
|
29
|
+
"ws": "^8.16.0"
|
|
28
30
|
}
|
|
29
31
|
}
|
|
@@ -7,7 +7,9 @@ function indexHandler(req, res) {
|
|
|
7
7
|
'GET /read?path=<filepath>': 'Read file content',
|
|
8
8
|
'POST /delete': 'Delete file or directory (body: {path})',
|
|
9
9
|
'POST /open-cursor': 'Open Cursor (body: {path, line?})',
|
|
10
|
-
'POST /shutdown': 'Gracefully shutdown the server'
|
|
10
|
+
'POST /shutdown': 'Gracefully shutdown the server',
|
|
11
|
+
'POST /scan_code_quality': 'Scan code quality (body: {projectPath})',
|
|
12
|
+
'WS /terminal?cwd=<path>': 'WebSocket terminal connection (optional cwd query param)'
|
|
11
13
|
},
|
|
12
14
|
example: 'Try: /list or /read?path=README.md'
|
|
13
15
|
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { ROOT } = require('../config');
|
|
4
|
+
|
|
5
|
+
function scanCodeQualityHandler(req, res) {
|
|
6
|
+
try {
|
|
7
|
+
const { projectPath } = req.body;
|
|
8
|
+
|
|
9
|
+
if (!projectPath) {
|
|
10
|
+
return res.status(400).json({ error: 'projectPath is required' });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const targetPath = path.join(ROOT, projectPath);
|
|
14
|
+
|
|
15
|
+
if (!targetPath.startsWith(ROOT)) {
|
|
16
|
+
return res.status(400).json({ error: 'Invalid path' });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!fs.existsSync(targetPath)) {
|
|
20
|
+
return res.status(404).json({ error: 'Path not found' });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const issues = [];
|
|
24
|
+
|
|
25
|
+
// Basic code quality checks
|
|
26
|
+
function scanDirectory(dir) {
|
|
27
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
28
|
+
|
|
29
|
+
for (const entry of entries) {
|
|
30
|
+
const fullPath = path.join(dir, entry.name);
|
|
31
|
+
const relativePath = path.relative(ROOT, fullPath);
|
|
32
|
+
|
|
33
|
+
// Skip node_modules and other ignored directories
|
|
34
|
+
if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'bonzai') {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (entry.isDirectory()) {
|
|
39
|
+
scanDirectory(fullPath);
|
|
40
|
+
} else if (entry.isFile()) {
|
|
41
|
+
// Check file size (warn if > 500KB)
|
|
42
|
+
const stats = fs.statSync(fullPath);
|
|
43
|
+
if (stats.size > 500 * 1024) {
|
|
44
|
+
issues.push({
|
|
45
|
+
file: relativePath,
|
|
46
|
+
severity: 'warning',
|
|
47
|
+
message: `Large file detected (${(stats.size / 1024).toFixed(2)}KB). Consider splitting into smaller modules.`,
|
|
48
|
+
type: 'file-size'
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check for common code quality issues in JS/TS files
|
|
53
|
+
if (entry.name.endsWith('.js') || entry.name.endsWith('.jsx') ||
|
|
54
|
+
entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) {
|
|
55
|
+
try {
|
|
56
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
57
|
+
const lines = content.split('\n');
|
|
58
|
+
|
|
59
|
+
// Check for very long lines
|
|
60
|
+
lines.forEach((line, index) => {
|
|
61
|
+
if (line.length > 200) {
|
|
62
|
+
issues.push({
|
|
63
|
+
file: relativePath,
|
|
64
|
+
line: index + 1,
|
|
65
|
+
severity: 'info',
|
|
66
|
+
message: `Long line detected (${line.length} characters). Consider breaking into multiple lines.`,
|
|
67
|
+
type: 'line-length'
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Check for TODO/FIXME comments
|
|
73
|
+
lines.forEach((line, index) => {
|
|
74
|
+
if (line.match(/TODO|FIXME|XXX|HACK/i)) {
|
|
75
|
+
issues.push({
|
|
76
|
+
file: relativePath,
|
|
77
|
+
line: index + 1,
|
|
78
|
+
severity: 'info',
|
|
79
|
+
message: `TODO/FIXME comment found: ${line.trim().substring(0, 100)}`,
|
|
80
|
+
type: 'todo-comment'
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Check for console.log statements (potential debug code)
|
|
86
|
+
lines.forEach((line, index) => {
|
|
87
|
+
if (line.match(/console\.(log|debug|info|warn|error)/) && !line.includes('//')) {
|
|
88
|
+
issues.push({
|
|
89
|
+
file: relativePath,
|
|
90
|
+
line: index + 1,
|
|
91
|
+
severity: 'warning',
|
|
92
|
+
message: `Console statement found. Consider removing or using a proper logging library.`,
|
|
93
|
+
type: 'console-statement'
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
} catch (e) {
|
|
99
|
+
// Skip files that can't be read
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const stat = fs.statSync(targetPath);
|
|
107
|
+
if (stat.isDirectory()) {
|
|
108
|
+
scanDirectory(targetPath);
|
|
109
|
+
} else {
|
|
110
|
+
// Single file scan
|
|
111
|
+
const relativePath = path.relative(ROOT, targetPath);
|
|
112
|
+
const content = fs.readFileSync(targetPath, 'utf8');
|
|
113
|
+
const lines = content.split('\n');
|
|
114
|
+
|
|
115
|
+
lines.forEach((line, index) => {
|
|
116
|
+
if (line.length > 200) {
|
|
117
|
+
issues.push({
|
|
118
|
+
file: relativePath,
|
|
119
|
+
line: index + 1,
|
|
120
|
+
severity: 'info',
|
|
121
|
+
message: `Long line detected (${line.length} characters)`,
|
|
122
|
+
type: 'line-length'
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
res.json({
|
|
129
|
+
success: true,
|
|
130
|
+
issues: issues,
|
|
131
|
+
totalIssues: issues.length,
|
|
132
|
+
summary: {
|
|
133
|
+
errors: issues.filter(i => i.severity === 'error').length,
|
|
134
|
+
warnings: issues.filter(i => i.severity === 'warning').length,
|
|
135
|
+
info: issues.filter(i => i.severity === 'info').length
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
} catch (e) {
|
|
140
|
+
res.status(500).json({ error: e.message });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = scanCodeQualityHandler;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const pty = require('node-pty');
|
|
2
|
+
|
|
3
|
+
// Store active terminal sessions
|
|
4
|
+
const terminals = new Map();
|
|
5
|
+
|
|
6
|
+
function handleTerminalConnection(ws, workingDirectory) {
|
|
7
|
+
const shell = process.platform === 'win32' ? 'powershell.exe' : 'zsh';
|
|
8
|
+
const cwd = workingDirectory || process.env.HOME;
|
|
9
|
+
|
|
10
|
+
console.log('🖥️ Terminal session started in:', cwd);
|
|
11
|
+
|
|
12
|
+
const ptyProcess = pty.spawn(shell, [], {
|
|
13
|
+
name: 'xterm-256color',
|
|
14
|
+
cols: 80,
|
|
15
|
+
rows: 24,
|
|
16
|
+
cwd: cwd,
|
|
17
|
+
env: {
|
|
18
|
+
...process.env,
|
|
19
|
+
TERM: 'xterm-256color',
|
|
20
|
+
COLORTERM: 'truecolor',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const terminalId = Date.now().toString();
|
|
25
|
+
terminals.set(terminalId, { pty: ptyProcess, ws });
|
|
26
|
+
|
|
27
|
+
// Send PTY output to WebSocket
|
|
28
|
+
ptyProcess.onData((data) => {
|
|
29
|
+
try {
|
|
30
|
+
if (ws.readyState === 1) { // WebSocket.OPEN
|
|
31
|
+
ws.send(data);
|
|
32
|
+
}
|
|
33
|
+
} catch (err) {
|
|
34
|
+
console.error('Error sending to WebSocket:', err);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Handle incoming messages from WebSocket
|
|
39
|
+
ws.on('message', (msg) => {
|
|
40
|
+
try {
|
|
41
|
+
const message = msg.toString();
|
|
42
|
+
|
|
43
|
+
// Check if it's a resize command
|
|
44
|
+
if (message.startsWith('\x1b[8;')) {
|
|
45
|
+
// Parse resize: ESC[8;rows;colst
|
|
46
|
+
const match = message.match(/\x1b\[8;(\d+);(\d+)t/);
|
|
47
|
+
if (match) {
|
|
48
|
+
const rows = parseInt(match[1], 10);
|
|
49
|
+
const cols = parseInt(match[2], 10);
|
|
50
|
+
ptyProcess.resize(cols, rows);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Check for JSON resize command
|
|
56
|
+
if (message.startsWith('{')) {
|
|
57
|
+
try {
|
|
58
|
+
const json = JSON.parse(message);
|
|
59
|
+
if (json.type === 'resize' && json.cols && json.rows) {
|
|
60
|
+
ptyProcess.resize(json.cols, json.rows);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
} catch (e) {
|
|
64
|
+
// Not JSON, treat as regular input
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Regular terminal input
|
|
69
|
+
ptyProcess.write(message);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.error('Error processing message:', err);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Clean up on WebSocket close
|
|
76
|
+
ws.on('close', () => {
|
|
77
|
+
console.log('🖥️ Terminal session closed');
|
|
78
|
+
ptyProcess.kill();
|
|
79
|
+
terminals.delete(terminalId);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Handle PTY exit
|
|
83
|
+
ptyProcess.onExit(({ exitCode, signal }) => {
|
|
84
|
+
console.log(`🖥️ Terminal process exited (code: ${exitCode}, signal: ${signal})`);
|
|
85
|
+
terminals.delete(terminalId);
|
|
86
|
+
if (ws.readyState === 1) {
|
|
87
|
+
ws.close();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = { handleTerminalConnection };
|
package/templates/receiver.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const express = require('./node_modules/express');
|
|
4
4
|
const cors = require('./node_modules/cors');
|
|
5
|
+
const WebSocket = require('./node_modules/ws');
|
|
6
|
+
const { ROOT } = require('./config');
|
|
5
7
|
|
|
6
8
|
// Import handlers
|
|
7
9
|
const indexHandler = require('./handlers/index');
|
|
@@ -10,6 +12,8 @@ const readHandler = require('./handlers/read');
|
|
|
10
12
|
const deleteHandler = require('./handlers/delete');
|
|
11
13
|
const openCursorHandler = require('./handlers/open-cursor');
|
|
12
14
|
const shutdownHandler = require('./handlers/shutdown');
|
|
15
|
+
const scanCodeQualityHandler = require('./handlers/scan_code_quality');
|
|
16
|
+
const { handleTerminalConnection } = require('./handlers/terminal');
|
|
13
17
|
|
|
14
18
|
const app = express();
|
|
15
19
|
|
|
@@ -23,8 +27,33 @@ app.get('/read', readHandler);
|
|
|
23
27
|
app.post('/delete', deleteHandler);
|
|
24
28
|
app.post('/open-cursor', openCursorHandler);
|
|
25
29
|
app.post('/shutdown', shutdownHandler);
|
|
30
|
+
app.post('/scan_code_quality', scanCodeQualityHandler);
|
|
26
31
|
|
|
27
32
|
const port = 3001;
|
|
28
|
-
app.listen(port, () => {
|
|
33
|
+
const server = app.listen(port, () => {
|
|
29
34
|
console.log('📂 File server running on http://localhost:' + port);
|
|
30
35
|
});
|
|
36
|
+
|
|
37
|
+
// WebSocket server for terminal
|
|
38
|
+
const wss = new WebSocket.Server({
|
|
39
|
+
server,
|
|
40
|
+
path: '/terminal'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
wss.on('connection', (ws, req) => {
|
|
44
|
+
// Extract working directory from query string if provided
|
|
45
|
+
let workingDirectory = ROOT;
|
|
46
|
+
|
|
47
|
+
if (req.url) {
|
|
48
|
+
const urlMatch = req.url.match(/[?&]cwd=([^&]+)/);
|
|
49
|
+
if (urlMatch) {
|
|
50
|
+
try {
|
|
51
|
+
workingDirectory = decodeURIComponent(urlMatch[1]);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.warn('Invalid cwd parameter, using default:', e.message);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
handleTerminalConnection(ws, workingDirectory);
|
|
59
|
+
});
|