108 lines
4.2 KiB
TypeScript
108 lines
4.2 KiB
TypeScript
import { contextBridge, clipboard, ipcRenderer } from 'electron'
|
|
|
|
/**
|
|
* The single bridge between renderer and main. The renderer NEVER touches the
|
|
* filesystem, git or the OS clipboard directly — everything goes through here.
|
|
* (PTYs land here next, for the terminals.)
|
|
*/
|
|
const api = {
|
|
platform: process.platform,
|
|
|
|
clipboard: {
|
|
writeText: (text: string) => clipboard.writeText(text),
|
|
readText: (): string => clipboard.readText(),
|
|
},
|
|
|
|
project: {
|
|
current: () => ipcRenderer.invoke('project:current'),
|
|
open: () => ipcRenderer.invoke('project:open'),
|
|
openPath: (path: string) => ipcRenderer.invoke('project:openPath', path),
|
|
recent: (): Promise<{ path: string; name: string }[]> => ipcRenderer.invoke('projects:recent'),
|
|
},
|
|
|
|
fs: {
|
|
tree: () => ipcRenderer.invoke('fs:tree'),
|
|
readDir: (path: string) => ipcRenderer.invoke('fs:readDir', path),
|
|
files: () => ipcRenderer.invoke('fs:files'),
|
|
read: (path: string) => ipcRenderer.invoke('fs:read', path),
|
|
write: (path: string, content: string): Promise<void> => ipcRenderer.invoke('fs:write', path, content),
|
|
delete: (path: string): Promise<void> => ipcRenderer.invoke('fs:delete', path),
|
|
create: (path: string): Promise<void> => ipcRenderer.invoke('fs:create', path),
|
|
mkdir: (path: string): Promise<void> => ipcRenderer.invoke('fs:mkdir', path),
|
|
},
|
|
|
|
shell: {
|
|
reveal: (path: string): void => { ipcRenderer.invoke('shell:reveal', path) },
|
|
},
|
|
|
|
git: {
|
|
load: () => ipcRenderer.invoke('git:load'),
|
|
stage: (paths: string[]) => ipcRenderer.invoke('git:stage', paths),
|
|
unstage: (paths: string[]) => ipcRenderer.invoke('git:unstage', paths),
|
|
commit: (message: string) => ipcRenderer.invoke('git:commit', message),
|
|
push: (): Promise<{ ok: boolean; message: string }> => ipcRenderer.invoke('git:push'),
|
|
discard: (paths: string[]) => ipcRenderer.invoke('git:discard', paths),
|
|
},
|
|
|
|
pty: {
|
|
available: (): Promise<boolean> => ipcRenderer.invoke('pty:available'),
|
|
create: (kind: 'agent' | 'shell', cols: number, rows: number): Promise<number> =>
|
|
ipcRenderer.invoke('pty:create', kind, cols, rows),
|
|
write: (id: number, data: string): void => ipcRenderer.send('pty:write', id, data),
|
|
resize: (id: number, cols: number, rows: number): void => ipcRenderer.send('pty:resize', id, cols, rows),
|
|
kill: (id: number): void => ipcRenderer.send('pty:kill', id),
|
|
onData: (cb: (id: number, data: string) => void): (() => void) => {
|
|
const h = (_e: unknown, p: { id: number; data: string }): void => cb(p.id, p.data)
|
|
ipcRenderer.on('pty:data', h)
|
|
return () => ipcRenderer.removeListener('pty:data', h)
|
|
},
|
|
onExit: (cb: (id: number) => void): (() => void) => {
|
|
const h = (_e: unknown, p: { id: number }): void => cb(p.id)
|
|
ipcRenderer.on('pty:exit', h)
|
|
return () => ipcRenderer.removeListener('pty:exit', h)
|
|
},
|
|
},
|
|
|
|
config: {
|
|
get: () => ipcRenderer.invoke('config:get'),
|
|
theme: (): Promise<string> => ipcRenderer.invoke('config:theme'),
|
|
},
|
|
|
|
recent: {
|
|
get: (): Promise<string[]> => ipcRenderer.invoke('recent:get'),
|
|
set: (list: string[]): Promise<void> => ipcRenderer.invoke('recent:set', list),
|
|
},
|
|
|
|
search: {
|
|
content: (query: string) => ipcRenderer.invoke('search:content', query),
|
|
files: (): Promise<string[]> => ipcRenderer.invoke('search:files'),
|
|
},
|
|
|
|
dialog: {
|
|
unsavedClose: (path: string): Promise<'save' | 'discard' | 'cancel'> =>
|
|
ipcRenderer.invoke('dialog:unsavedClose', path),
|
|
},
|
|
|
|
/** Subscribe to "the project changed on disk" pings. Returns an unsubscribe. */
|
|
onProjectChanged: (cb: () => void): (() => void) => {
|
|
const handler = (): void => cb()
|
|
ipcRenderer.on('project:changed', handler)
|
|
return () => ipcRenderer.removeListener('project:changed', handler)
|
|
},
|
|
|
|
/** Subscribe to .helder config/theme edits. Returns an unsubscribe. */
|
|
onConfigChanged: (cb: () => void): (() => void) => {
|
|
const handler = (): void => cb()
|
|
ipcRenderer.on('config:changed', handler)
|
|
return () => ipcRenderer.removeListener('config:changed', handler)
|
|
},
|
|
}
|
|
|
|
if (process.contextIsolated) {
|
|
contextBridge.exposeInMainWorld('helder', api)
|
|
} else {
|
|
;(globalThis as unknown as { helder: typeof api }).helder = api
|
|
}
|
|
|
|
export type HelderApi = typeof api
|