Fix TypeScript and ESLint errors (#31)
- Add proper type annotations for WebSocketMessage and ServerInfo types - Fix type imports to use type-only imports where appropriate - Replace logical OR operators with nullish coalescing operators - Fix floating promises by adding void operator - Add proper type assertions for database results - Fix useEffect dependencies in Terminal component - Remove unused variables and fix unescaped entities - Add JSDoc type annotations for database methods - Fix singleton instance type annotations
This commit is contained in:
committed by
GitHub
parent
2f1df95d90
commit
433d8121e8
@@ -1,6 +1,8 @@
|
||||
import { WebSocketServer, WebSocket } from 'ws';
|
||||
import type { IncomingMessage } from 'http';
|
||||
import { scriptManager } from '~/server/lib/scripts';
|
||||
import { getSSHExecutionService } from '~/server/ssh-execution-service';
|
||||
import type { Server } from '~/types/server';
|
||||
|
||||
interface ScriptExecutionMessage {
|
||||
type: 'start' | 'output' | 'error' | 'end';
|
||||
@@ -48,13 +50,15 @@ export class ScriptExecutionHandler {
|
||||
});
|
||||
}
|
||||
|
||||
private async handleMessage(ws: WebSocket, message: { action: string; scriptPath?: string; executionId?: string }) {
|
||||
const { action, scriptPath, executionId } = message;
|
||||
private async handleMessage(ws: WebSocket, message: { action: string; scriptPath?: string; executionId?: string; mode?: 'local' | 'ssh'; server?: any }) {
|
||||
const { action, scriptPath, executionId, mode, server } = message;
|
||||
|
||||
console.log('WebSocket message received:', { action, scriptPath, executionId, mode, server: server ? { name: server.name, ip: server.ip } : null });
|
||||
|
||||
switch (action) {
|
||||
case 'start':
|
||||
if (scriptPath && executionId) {
|
||||
await this.startScriptExecution(ws, scriptPath, executionId);
|
||||
await this.startScriptExecution(ws, scriptPath, executionId, mode, server);
|
||||
} else {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
@@ -79,19 +83,10 @@ export class ScriptExecutionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private async startScriptExecution(ws: WebSocket, scriptPath: string, executionId: string) {
|
||||
private async startScriptExecution(ws: WebSocket, scriptPath: string, executionId: string, mode?: 'local' | 'ssh', server?: any) {
|
||||
console.log('startScriptExecution called with:', { scriptPath, executionId, mode, server: server ? { name: server.name, ip: server.ip } : null });
|
||||
|
||||
try {
|
||||
// Validate script path
|
||||
const validation = scriptManager.validateScriptPath(scriptPath);
|
||||
if (!validation.valid) {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: validation.message ?? 'Invalid script path',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if execution is already running
|
||||
if (this.activeExecutions.has(executionId)) {
|
||||
this.sendMessage(ws, {
|
||||
@@ -102,61 +97,135 @@ export class ScriptExecutionHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start script execution
|
||||
const process = await scriptManager.executeScript(scriptPath);
|
||||
let process: any;
|
||||
|
||||
if (mode === 'ssh' && server) {
|
||||
// SSH execution
|
||||
console.log('Starting SSH execution:', { scriptPath, server });
|
||||
console.log('SSH execution mode detected, calling SSH service...');
|
||||
console.log('Mode check: mode=', mode, 'server=', !!server);
|
||||
this.sendMessage(ws, {
|
||||
type: 'start',
|
||||
data: `Starting SSH execution of ${scriptPath} on ${server.name ?? server.ip}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
const sshService = getSSHExecutionService();
|
||||
console.log('SSH service obtained, calling executeScript...');
|
||||
console.log('SSH service object:', typeof sshService, sshService.constructor.name);
|
||||
|
||||
try {
|
||||
const result = await sshService.executeScript(server as Server, scriptPath,
|
||||
(data: string) => {
|
||||
console.log('SSH onData callback:', data.substring(0, 100) + '...');
|
||||
this.sendMessage(ws, {
|
||||
type: 'output',
|
||||
data: data,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
},
|
||||
(error: string) => {
|
||||
console.log('SSH onError callback:', error);
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: error,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
},
|
||||
(code: number) => {
|
||||
console.log('SSH onExit callback, code:', code);
|
||||
this.sendMessage(ws, {
|
||||
type: 'end',
|
||||
data: `SSH script execution finished with code: ${code}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
this.activeExecutions.delete(executionId);
|
||||
}
|
||||
);
|
||||
console.log('SSH service executeScript completed, result:', result);
|
||||
process = (result as any).process;
|
||||
} catch (sshError) {
|
||||
console.error('SSH service executeScript failed:', sshError);
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: `SSH execution failed: ${sshError instanceof Error ? sshError.message : String(sshError)}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Local execution
|
||||
console.log('Starting local execution:', { scriptPath });
|
||||
console.log('Local execution mode detected, calling local script manager...');
|
||||
console.log('Mode check: mode=', mode, 'server=', !!server, 'condition result:', mode === 'ssh' && server);
|
||||
|
||||
// Validate script path
|
||||
const validation = scriptManager.validateScriptPath(scriptPath);
|
||||
if (!validation.valid) {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: validation.message ?? 'Invalid script path',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Start script execution
|
||||
process = await scriptManager.executeScript(scriptPath);
|
||||
|
||||
// Send start message
|
||||
this.sendMessage(ws, {
|
||||
type: 'start',
|
||||
data: `Starting execution of ${scriptPath}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Handle stdout
|
||||
process.stdout?.on('data', (data: Buffer) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'output',
|
||||
data: data.toString(),
|
||||
timestamp: Date.now()
|
||||
});
|
||||
});
|
||||
|
||||
// Handle stderr
|
||||
process.stderr?.on('data', (data: Buffer) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: data.toString(),
|
||||
timestamp: Date.now()
|
||||
});
|
||||
});
|
||||
|
||||
// Handle process exit
|
||||
process.on('exit', (code: number | null, signal: string | null) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'end',
|
||||
data: `Script execution finished with code: ${code}, signal: ${signal}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Clean up
|
||||
this.activeExecutions.delete(executionId);
|
||||
});
|
||||
|
||||
// Handle process error
|
||||
process.on('error', (error: Error) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: `Process error: ${error.message}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Clean up
|
||||
this.activeExecutions.delete(executionId);
|
||||
});
|
||||
}
|
||||
|
||||
// Store the execution
|
||||
this.activeExecutions.set(executionId, { process, ws });
|
||||
|
||||
// Send start message
|
||||
this.sendMessage(ws, {
|
||||
type: 'start',
|
||||
data: `Starting execution of ${scriptPath}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Handle stdout
|
||||
process.stdout?.on('data', (data: Buffer) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'output',
|
||||
data: data.toString(),
|
||||
timestamp: Date.now()
|
||||
});
|
||||
});
|
||||
|
||||
// Handle stderr
|
||||
process.stderr?.on('data', (data: Buffer) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: data.toString(),
|
||||
timestamp: Date.now()
|
||||
});
|
||||
});
|
||||
|
||||
// Handle process exit
|
||||
process.on('exit', (code: number | null, signal: string | null) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'end',
|
||||
data: `Script execution finished with code: ${code}, signal: ${signal}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Clean up
|
||||
this.activeExecutions.delete(executionId);
|
||||
});
|
||||
|
||||
// Handle process error
|
||||
process.on('error', (error: Error) => {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
data: `Process error: ${error.message}`,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Clean up
|
||||
this.activeExecutions.delete(executionId);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
this.sendMessage(ws, {
|
||||
type: 'error',
|
||||
|
||||
Reference in New Issue
Block a user