import axios from 'axios'; interface SSHHostData { name?: string; ip: string; port: number; username: string; folder?: string; tags?: string[]; pin?: boolean; authType: 'password' | 'key'; password?: string; key?: File | null; keyPassword?: string; keyType?: string; enableTerminal?: boolean; enableTunnel?: boolean; enableFileManager?: boolean; defaultPath?: string; tunnelConnections?: any[]; } interface SSHHost { id: number; name: string; ip: string; port: number; username: string; folder: string; tags: string[]; pin: boolean; authType: string; password?: string; key?: string; keyPassword?: string; keyType?: string; enableTerminal: boolean; enableTunnel: boolean; enableFileManager: boolean; defaultPath: string; tunnelConnections: any[]; createdAt: string; updatedAt: string; } interface TunnelConfig { name: string; hostName: string; sourceIP: string; sourceSSHPort: number; sourceUsername: string; sourcePassword?: string; sourceAuthMethod: string; sourceSSHKey?: string; sourceKeyPassword?: string; sourceKeyType?: string; endpointIP: string; endpointSSHPort: number; endpointUsername: string; endpointPassword?: string; endpointAuthMethod: string; endpointSSHKey?: string; endpointKeyPassword?: string; endpointKeyType?: string; sourcePort: number; endpointPort: number; maxRetries: number; retryInterval: number; autoStart: boolean; isPinned: boolean; } interface TunnelStatus { status: string; reason?: string; errorType?: string; retryCount?: number; maxRetries?: number; nextRetryIn?: number; retryExhausted?: boolean; } interface FileManagerFile { name: string; path: string; type?: 'file' | 'directory'; isSSH?: boolean; sshSessionId?: string; } interface FileManagerShortcut { name: string; path: string; } export type ServerStatus = { status: 'online' | 'offline'; lastChecked: string; }; export type ServerMetrics = { cpu: { percent: number | null; cores: number | null; load: [number, number, number] | null }; memory: { percent: number | null; usedGiB: number | null; totalGiB: number | null }; disk: { percent: number | null; usedHuman: string | null; totalHuman: string | null }; lastChecked: string; }; const isLocalhost = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'; const sshHostApi = axios.create({ baseURL: isLocalhost ? 'http://localhost:8081' : '', headers: { 'Content-Type': 'application/json', }, }); const tunnelApi = axios.create({ baseURL: isLocalhost ? 'http://localhost:8083' : '', headers: { 'Content-Type': 'application/json', }, }); const fileManagerApi = axios.create({ baseURL: isLocalhost ? 'http://localhost:8084' : '', headers: { 'Content-Type': 'application/json', } }) const statsApi = axios.create({ baseURL: isLocalhost ? 'http://localhost:8085' : '', headers: { 'Content-Type': 'application/json', } }) function getCookie(name: string): string | undefined { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop()?.split(';').shift(); } sshHostApi.interceptors.request.use((config) => { const token = getCookie('jwt'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); statsApi.interceptors.request.use((config) => { const token = getCookie('jwt'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); tunnelApi.interceptors.request.use((config) => { const token = getCookie('jwt'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); fileManagerApi.interceptors.request.use((config) => { const token = getCookie('jwt'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); export async function getSSHHosts(): Promise { try { const response = await sshHostApi.get('/ssh/db/host'); return response.data; } catch (error) { throw error; } } export async function createSSHHost(hostData: SSHHostData): Promise { try { const submitData = { name: hostData.name || '', ip: hostData.ip, port: parseInt(hostData.port.toString()) || 22, username: hostData.username, folder: hostData.folder || '', tags: hostData.tags || [], pin: hostData.pin || false, authMethod: hostData.authType, password: hostData.authType === 'password' ? hostData.password : '', key: hostData.authType === 'key' ? hostData.key : null, keyPassword: hostData.authType === 'key' ? hostData.keyPassword : '', keyType: hostData.authType === 'key' ? hostData.keyType : '', enableTerminal: hostData.enableTerminal !== false, enableTunnel: hostData.enableTunnel !== false, enableFileManager: hostData.enableFileManager !== false, defaultPath: hostData.defaultPath || '/', tunnelConnections: hostData.tunnelConnections || [], }; if (!submitData.enableTunnel) { submitData.tunnelConnections = []; } if (!submitData.enableFileManager) { submitData.defaultPath = ''; } if (hostData.authType === 'key' && hostData.key instanceof File) { const formData = new FormData(); formData.append('key', hostData.key); const dataWithoutFile = {...submitData}; delete dataWithoutFile.key; formData.append('data', JSON.stringify(dataWithoutFile)); const response = await sshHostApi.post('/ssh/db/host', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); return response.data; } else { const response = await sshHostApi.post('/ssh/db/host', submitData); return response.data; } } catch (error) { throw error; } } export async function updateSSHHost(hostId: number, hostData: SSHHostData): Promise { try { const submitData = { name: hostData.name || '', ip: hostData.ip, port: parseInt(hostData.port.toString()) || 22, username: hostData.username, folder: hostData.folder || '', tags: hostData.tags || [], pin: hostData.pin || false, authMethod: hostData.authType, password: hostData.authType === 'password' ? hostData.password : '', key: hostData.authType === 'key' ? hostData.key : null, keyPassword: hostData.authType === 'key' ? hostData.keyPassword : '', keyType: hostData.authType === 'key' ? hostData.keyType : '', enableTerminal: hostData.enableTerminal !== false, enableTunnel: hostData.enableTunnel !== false, enableFileManager: hostData.enableFileManager !== false, defaultPath: hostData.defaultPath || '/', tunnelConnections: hostData.tunnelConnections || [], }; if (!submitData.enableTunnel) { submitData.tunnelConnections = []; } if (!submitData.enableFileManager) { submitData.defaultPath = ''; } if (hostData.authType === 'key' && hostData.key instanceof File) { const formData = new FormData(); formData.append('key', hostData.key); const dataWithoutFile = {...submitData}; delete dataWithoutFile.key; formData.append('data', JSON.stringify(dataWithoutFile)); const response = await sshHostApi.put(`/ssh/db/host/${hostId}`, formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); return response.data; } else { const response = await sshHostApi.put(`/ssh/db/host/${hostId}`, submitData); return response.data; } } catch (error) { throw error; } } export async function bulkImportSSHHosts(hosts: SSHHostData[]): Promise<{ message: string; success: number; failed: number; errors: string[]; }> { try { const response = await sshHostApi.post('/ssh/bulk-import', {hosts}); return response.data; } catch (error) { throw error; } } export async function deleteSSHHost(hostId: number): Promise { try { const response = await sshHostApi.delete(`/ssh/db/host/${hostId}`); return response.data; } catch (error) { throw error; } } export async function getSSHHostById(hostId: number): Promise { try { const response = await sshHostApi.get(`/ssh/db/host/${hostId}`); return response.data; } catch (error) { throw error; } } export async function getTunnelStatuses(): Promise> { try { const response = await tunnelApi.get('/ssh/tunnel/status'); return response.data || {}; } catch (error) { throw error; } } export async function getTunnelStatusByName(tunnelName: string): Promise { const statuses = await getTunnelStatuses(); return statuses[tunnelName]; } export async function connectTunnel(tunnelConfig: TunnelConfig): Promise { try { const response = await tunnelApi.post('/ssh/tunnel/connect', tunnelConfig); return response.data; } catch (error) { throw error; } } export async function disconnectTunnel(tunnelName: string): Promise { try { const response = await tunnelApi.post('/ssh/tunnel/disconnect', {tunnelName}); return response.data; } catch (error) { throw error; } } export async function cancelTunnel(tunnelName: string): Promise { try { const response = await tunnelApi.post('/ssh/tunnel/cancel', {tunnelName}); return response.data; } catch (error) { throw error; } } export async function getFileManagerRecent(hostId: number): Promise { try { const response = await sshHostApi.get(`/ssh/file_manager/recent?hostId=${hostId}`); return response.data || []; } catch (error) { return []; } } export async function addFileManagerRecent(file: { name: string; path: string; isSSH: boolean; sshSessionId?: string; hostId: number }): Promise { try { const response = await sshHostApi.post('/ssh/file_manager/recent', file); return response.data; } catch (error) { throw error; } } export async function removeFileManagerRecent(file: { name: string; path: string; isSSH: boolean; sshSessionId?: string; hostId: number }): Promise { try { const response = await sshHostApi.delete('/ssh/file_manager/recent', {data: file}); return response.data; } catch (error) { throw error; } } export async function getFileManagerPinned(hostId: number): Promise { try { const response = await sshHostApi.get(`/ssh/file_manager/pinned?hostId=${hostId}`); return response.data || []; } catch (error) { return []; } } export async function addFileManagerPinned(file: { name: string; path: string; isSSH: boolean; sshSessionId?: string; hostId: number }): Promise { try { const response = await sshHostApi.post('/ssh/file_manager/pinned', file); return response.data; } catch (error) { throw error; } } export async function removeFileManagerPinned(file: { name: string; path: string; isSSH: boolean; sshSessionId?: string; hostId: number }): Promise { try { const response = await sshHostApi.delete('/ssh/file_manager/pinned', {data: file}); return response.data; } catch (error) { throw error; } } export async function getFileManagerShortcuts(hostId: number): Promise { try { const response = await sshHostApi.get(`/ssh/file_manager/shortcuts?hostId=${hostId}`); return response.data || []; } catch (error) { return []; } } export async function addFileManagerShortcut(shortcut: { name: string; path: string; isSSH: boolean; sshSessionId?: string; hostId: number }): Promise { try { const response = await sshHostApi.post('/ssh/file_manager/shortcuts', shortcut); return response.data; } catch (error) { throw error; } } export async function removeFileManagerShortcut(shortcut: { name: string; path: string; isSSH: boolean; sshSessionId?: string; hostId: number }): Promise { try { const response = await sshHostApi.delete('/ssh/file_manager/shortcuts', {data: shortcut}); return response.data; } catch (error) { throw error; } } export async function connectSSH(sessionId: string, config: { ip: string; port: number; username: string; password?: string; sshKey?: string; keyPassword?: string; }): Promise { try { const response = await fileManagerApi.post('/ssh/file_manager/ssh/connect', { sessionId, ...config }); return response.data; } catch (error) { throw error; } } export async function disconnectSSH(sessionId: string): Promise { try { const response = await fileManagerApi.post('/ssh/file_manager/ssh/disconnect', {sessionId}); return response.data; } catch (error) { throw error; } } export async function getSSHStatus(sessionId: string): Promise<{ connected: boolean }> { try { const response = await fileManagerApi.get('/ssh/file_manager/ssh/status', { params: {sessionId} }); return response.data; } catch (error) { throw error; } } export async function listSSHFiles(sessionId: string, path: string): Promise { try { const response = await fileManagerApi.get('/ssh/file_manager/ssh/listFiles', { params: {sessionId, path} }); return response.data || []; } catch (error) { throw error; } } export async function readSSHFile(sessionId: string, path: string): Promise<{ content: string; path: string }> { try { const response = await fileManagerApi.get('/ssh/file_manager/ssh/readFile', { params: {sessionId, path} }); return response.data; } catch (error) { throw error; } } export async function writeSSHFile(sessionId: string, path: string, content: string): Promise { try { const response = await fileManagerApi.post('/ssh/file_manager/ssh/writeFile', { sessionId, path, content }); if (response.data && (response.data.message === 'File written successfully' || response.status === 200)) { return response.data; } else { throw new Error('File write operation did not return success status'); } } catch (error) { throw error; } } export async function uploadSSHFile(sessionId: string, path: string, fileName: string, content: string): Promise { try { const response = await fileManagerApi.post('/ssh/file_manager/ssh/uploadFile', { sessionId, path, fileName, content }); return response.data; } catch (error) { throw error; } } export async function createSSHFile(sessionId: string, path: string, fileName: string, content: string = ''): Promise { try { const response = await fileManagerApi.post('/ssh/file_manager/ssh/createFile', { sessionId, path, fileName, content }); return response.data; } catch (error) { throw error; } } export async function createSSHFolder(sessionId: string, path: string, folderName: string): Promise { try { const response = await fileManagerApi.post('/ssh/file_manager/ssh/createFolder', { sessionId, path, folderName }); return response.data; } catch (error) { throw error; } } export async function deleteSSHItem(sessionId: string, path: string, isDirectory: boolean): Promise { try { const response = await fileManagerApi.delete('/ssh/file_manager/ssh/deleteItem', { data: { sessionId, path, isDirectory } }); return response.data; } catch (error) { throw error; } } export async function renameSSHItem(sessionId: string, oldPath: string, newName: string): Promise { try { const response = await fileManagerApi.put('/ssh/file_manager/ssh/renameItem', { sessionId, oldPath, newName }); return response.data; } catch (error) { throw error; } } export {sshHostApi, tunnelApi, fileManagerApi}; export async function getAllServerStatuses(): Promise> { try { const response = await statsApi.get('/status'); return response.data || {}; } catch (error) { throw error; } } export async function getServerStatusById(id: number): Promise { try { const response = await statsApi.get(`/status/${id}`); return response.data; } catch (error) { throw error; } } export async function getServerMetricsById(id: number): Promise { try { const response = await statsApi.get(`/metrics/${id}`); return response.data; } catch (error) { throw error; } }