核心修复:
- ssh-service.ts: 新增 resolvePrivateKey(),将私钥文件路径(~/.ssh/id_rsa)解析为内容后传给 ssh2,
解决 'Cannot parse privateKey: Unsupported key format' 错误
- useTerminalConnection.ts + sessionHelper.ts: 根据 authType 过滤字段,password/agent 认证不再传 privateKey
- sessionStore.ts: addSession() 现在先调用 sessionCreate() 持久化到 SQLite,解决恢复标签'无可用连接信息'问题
- database-service.ts: updateSession() 补充 private_key_path 字段持久化
- SessionDialog.tsx: 默认 username='root'、privateKey='~/.ssh/id_rsa'
UI/UX:
- 语义化主题系统(app-theme.ts),强制深色模式,全局无边框设计
- macOS 标题栏支持双击最大化(window:toggleMaximize IPC)
- macOS 菜单栏('OpsXShell' 应用菜单 + Settings Cmd+,)
- WelcomeView 4卡片布局,移除 Settings 按钮
- TabBar/TabItem 背景色统一(bg-dark-800/900),消除白色边框线
架构优化:
- SFTP 生命周期修复(useSFTP.ts useRef + autoConnectAttempted guard)
- 连接池竞态修复,支持快速多标签连接
- IPC 接口规范化,安全错误处理
- Vite 代码分割优化
质量: lint零错误 | tsc零错误 | build成功 | 49 tests pass
80 lines
5.0 KiB
TypeScript
80 lines
5.0 KiB
TypeScript
// Type declarations for Electron IPC API exposed via preload
|
|
// All types imported from shared/types for consistency
|
|
|
|
interface ElectronAPI {
|
|
// SSH
|
|
sshConnect: (config: import('../shared/types/ipc.types').SSHConnectRequest) => Promise<import('../shared/types/ipc.types').SSHConnectResponse>
|
|
sshDisconnect: (connectionId: string) => Promise<{ success: boolean; error?: string }>
|
|
sshExec: (connectionId: string, command: string) => Promise<{ success: boolean; result?: string; error?: string }>
|
|
sshCreateShell: (connectionId: string, options?: import('../shared/types/ipc.types').SSHCreateShellRequest, shellId?: string) => Promise<{ success: boolean; shellId?: string; error?: string }>
|
|
sshShellWrite: (shellId: string, data: string | Uint8Array) => Promise<{ success: boolean; error?: string }>
|
|
sshShellResize: (shellId: string, cols: number, rows: number) => Promise<{ success: boolean; error?: string }>
|
|
sshForwardLocal: (connectionId: string, localPort: number, remoteHost: string, remotePort: number) => Promise<import('../shared/types/ipc.types').SSHForwardResponse>
|
|
sshForwardRemote: (connectionId: string, remotePort: number, localHost: string, localPort: number) => Promise<import('../shared/types/ipc.types').SSHForwardResponse>
|
|
sshForwardDynamic: (connectionId: string, localPort: number) => Promise<import('../shared/types/ipc.types').SSHForwardResponse>
|
|
|
|
// Sessions
|
|
sessionGetAll: () => Promise<{ success: boolean; sessions?: import('../shared/types/session.types').Session[]; error?: string }>
|
|
sessionGetById: (id: string) => Promise<{ success: boolean; session?: import('../shared/types/session.types').Session; error?: string }>
|
|
sessionCreate: (session: Omit<import('../shared/types/session.types').Session, 'id'>) => Promise<import('../shared/types/ipc.types').SessionCreateResponse>
|
|
sessionUpdate: (id: string, updates: Partial<import('../shared/types/session.types').Session>) => Promise<import('../shared/types/ipc.types').SessionUpdateResponse>
|
|
sessionDelete: (id: string) => Promise<{ success: boolean; error?: string }>
|
|
|
|
// SFTP
|
|
sftpConnect: (connectionId: string) => Promise<{ success: boolean; sftpId?: string; error?: string }>
|
|
sftpListDirectory: (sftpId: string, path: string) => Promise<{ success: boolean; files?: unknown[]; error?: string }>
|
|
sftpUpload: (sftpId: string, localPath: string, remotePath: string) => Promise<{ success: boolean; error?: string }>
|
|
sftpDownload: (sftpId: string, remotePath: string, localPath: string) => Promise<{ success: boolean; error?: string }>
|
|
sftpRename: (sftpId: string, oldPath: string, newPath: string) => Promise<{ success: boolean; error?: string }>
|
|
sftpDelete: (sftpId: string, path: string, isDirectory: boolean) => Promise<{ success: boolean; error?: string }>
|
|
sftpMkdir: (sftpId: string, path: string) => Promise<{ success: boolean; error?: string }>
|
|
sftpStat: (sftpId: string, filePath: string) => Promise<{ success: boolean; stats?: unknown; error?: string }>
|
|
sftpChmod: (sftpId: string, filePath: string, mode: number) => Promise<{ success: boolean; error?: string }>
|
|
|
|
// Settings
|
|
settingsGet: (key: string) => Promise<{ success: boolean; value?: unknown; error?: string }>
|
|
settingsSet: (key: string, value: unknown) => Promise<{ success: boolean; error?: string }>
|
|
|
|
// Dialogs
|
|
showSaveDialog: (options: import('../shared/types/ipc.types').DialogOptions) => Promise<import('../shared/types/ipc.types').DialogResult>
|
|
showOpenDialog: (options: import('../shared/types/ipc.types').DialogOptions) => Promise<import('../shared/types/ipc.types').DialogResult>
|
|
|
|
// File operations
|
|
readFile: (filePath: string) => Promise<{ success: boolean; data?: string; error?: string }>
|
|
writeFile: (filePath: string, data: string) => Promise<{ success: boolean; error?: string }>
|
|
|
|
// Local filesystem
|
|
getHomePath: () => Promise<{ success: boolean; path?: string; error?: string }>
|
|
getDownloadsPath: () => Promise<string>
|
|
localReadDir: (dirPath: string) => Promise<unknown>
|
|
localGetStats: (filePath: string) => Promise<unknown>
|
|
localDelete: (filePath: string) => Promise<unknown>
|
|
localRename: (oldPath: string, newPath: string) => Promise<unknown>
|
|
localMkdir: (dirPath: string) => Promise<unknown>
|
|
|
|
// App
|
|
getVersion: () => Promise<string>
|
|
|
|
// Window
|
|
toggleMaximize: () => Promise<void>
|
|
|
|
// Events
|
|
onMenuNewSession: (callback: () => void) => void
|
|
onMenuQuickConnect: (callback: () => void) => void
|
|
onMenuImportSessions: (callback: () => void) => void
|
|
onMenuExportSessions: (callback: () => void) => void
|
|
onMenuOpenSettings: (callback: () => void) => void
|
|
onShellData: (callback: (event: Electron.IpcRendererEvent, connectionId: string, shellId: string, data: Buffer) => void) => void
|
|
onSFTPProgress: (callback: (event: Electron.IpcRendererEvent, sftpId: string, progress: { transferred: number; total: number; percentage: number }) => void) => void
|
|
removeListener: (channel: string, callback: (...args: unknown[]) => void) => void
|
|
removeAllListeners: (channel: string) => void
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
electronAPI: ElectronAPI
|
|
}
|
|
}
|
|
|
|
export {}
|