init helder

This commit is contained in:
2026-06-15 22:33:46 +02:00
parent 3d77fdfeff
commit 3f5078841d
38 changed files with 6349 additions and 2083 deletions

85
src/preload/index.ts Normal file
View File

@@ -0,0 +1,85 @@
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),
},
project: {
current: () => ipcRenderer.invoke('project:current'),
open: () => ipcRenderer.invoke('project:open'),
},
fs: {
tree: () => ipcRenderer.invoke('fs:tree'),
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),
},
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),
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'),
},
search: {
content: (query: string) => ipcRenderer.invoke('search:content', query),
files: (): Promise<string[]> => ipcRenderer.invoke('search:files'),
},
/** 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