import type { AppSettings, ColumnKey, ConnectionConfig, ConnectionsFile, EntryType, FileEntry, Result, SavedConnection, SshConfigHost, Stack, TransferSnapshot, } from "./types"; /** Everything an editor window needs to know about the file it hosts. */ export interface EditorOpenContext { sessionId: string; path: string; name: string; sessionTitle: string; } // Structurally equivalent to electrobun's ElectrobunRPCSchema, written in // resolved form so this file stays importable from the Angular bundle without // pulling in bun-only type modules. // // bun.requests = calls the webview makes, handled in src/bun/rpc-handlers.ts // webview.messages = push events from bun, handled in ui rpc.service.ts // // ONE schema serves both window kinds (main + editor): electrobun allows // partial handler sets, and messages nobody listens to are silently dropped, // so each side only implements/hears what applies to it. export type AppRPC = { bun: { requests: { // sessions connect: { params: { config: ConnectionConfig }; response: Result<{ sessionId: string; homeDir: string; fsKey: string }>; }; disconnect: { params: { sessionId: string }; response: Result }; // filesystem (uniform across "local" and sftp sessions) listDir: { params: { sessionId: string; path: string | null }; // null -> home dir response: Result<{ path: string; entries: FileEntry[] }>; }; // Local dirs to fs.watch for auto-refresh (the active tab's local panels); // a change pushes pathRefresh. Remote panels are polled UI-side instead. setWatchedDirs: { params: { dirs: string[] }; response: Result }; mkdir: { params: { sessionId: string; path: string }; response: Result }; createFile: { params: { sessionId: string; path: string }; response: Result }; rename: { params: { sessionId: string; oldPath: string; newPath: string }; response: Result; }; deleteEntries: { params: { sessionId: string; entries: { path: string; type: EntryType }[] }; response: Result; }; chmod: { params: { sessionId: string; paths: string[]; mode: number }; response: Result; }; // transfers enqueueTransfers: { params: { srcSessionId: string; items: { path: string; type: EntryType }[]; dstSessionId: string; dstDir: string; }; response: Result<{ jobIds: string[] }>; }; cancelTransfer: { params: { jobId: string }; response: Result }; dismissTransfer: { params: { jobId: string }; response: Result }; // connection store getConnections: { params: Record; response: Result<{ store: ConnectionsFile }>; }; upsertConnection: { params: { connection: SavedConnection }; response: Result<{ id: string }>; }; deleteConnection: { params: { id: string }; response: Result }; upsertStack: { params: { stack: Stack }; response: Result<{ id: string }> }; deleteStack: { params: { id: string }; response: Result }; /** Native file picker + parse of a WinSCP.ini export into the store. */ importWinScp: { params: Record; response: Result<{ connections: number; stacks: number; skipped: number }>; }; getSshConfigHosts: { params: Record; response: Result<{ hosts: SshConfigHost[] }>; }; // settings getSettings: { params: Record; response: Result<{ settings: AppSettings }>; }; saveSettings: { params: { settings: AppSettings }; response: Result }; // file editing readFile: { params: { sessionId: string; path: string }; response: Result<{ content: string }>; }; writeFile: { params: { sessionId: string; path: string; content: string }; response: Result; }; editExternal: { params: { sessionId: string; path: string }; response: Result<{ watching: boolean }>; }; pickEditorApp: { params: Record; response: Result<{ path: string | null }>; }; pickKeyFile: { params: Record; response: Result<{ path: string | null }>; }; getEditLeftovers: { params: Record; response: Result<{ names: string[] }>; }; clearEditLeftovers: { params: Record; response: Result }; // context menu + local shell integration showRowMenu: { params: { path: string; name: string; type: EntryType; isLocal: boolean; hasEntry: boolean; }; response: Result; }; moveToTrash: { params: { path: string }; response: Result }; /** Native column-picker menu (right-click on the list headers). */ showColumnsMenu: { params: { visible: ColumnKey[] }; response: Result }; /** Native About box (name, Build n, commit, engine versions). */ showAbout: { params: Record; response: Result }; /** Windows drive roots for the local panel ("C:\", …); empty elsewhere. */ listDrives: { params: Record; response: Result<{ drives: string[] }> }; // editor windows /** Main window only: open (or focus) a native editor window. */ openEditor: { params: EditorOpenContext; response: Result }; /** Editor windows only — handled by that window's own rpc closure. */ editorSave: { params: { content: string }; response: Result }; editorClose: { params: Record; response: Result }; // connection-manager window /** Main window: open (or focus) the single connection-manager window. */ openConnectionManager: { params: Record; response: Result }; /** Manager window only: connect/open-stack run in the MAIN window. */ managerConnect: { params: { id: string }; response: Result }; managerOpenStack: { params: { id: string }; response: Result }; managerClose: { params: Record; response: Result }; // auto-updater (electrobun Updater) /** Main window: re-run the update check on demand (menu item). */ checkForUpdate: { params: Record; response: Result<{ updateAvailable: boolean; version: string }>; }; /** Download the pending update (patch-chain, else full). Progress arrives via updateStatus. */ downloadUpdate: { params: Record; response: Result }; /** Swap in the downloaded update and relaunch — quits the app, so may not resolve. */ applyUpdate: { params: Record; response: Result }; }; messages: { /** Editor → bun draft mirror; safety net for the non-cancellable native close. */ editorState: { dirty: boolean; content: string }; }; }; webview: { requests: Record; messages: { transferUpdate: TransferSnapshot; sessionClosed: { sessionId: string; reason: string }; menuAction: { action: string }; /** bun → editor windows when the main window saves settings. */ settingsChanged: { settings: AppSettings }; /** bun → main after an editor save, so matching panels refresh. */ pathRefresh: { sessionId: string; dir: string }; /** bun → one editor: run the in-window close flow (dirty prompt). */ editorCloseRequest: Record; /** bun → main: the modal connection manager opened/closed. */ managerState: { open: boolean }; /** bun → main: the manager window changed the connection store. */ connectionsChanged: Record; /** * bun → main: auto-updater lifecycle, drives the tab-bar update pill. * "ready" is not a phase — the UI derives it from downloadUpdate resolving ok. */ updateStatus: { phase: "available" | "downloading" | "error"; version?: string; progress?: number; error?: string; }; }; }; };