198 lines
8.7 KiB
TypeScript
198 lines
8.7 KiB
TypeScript
import { contextBridge, ipcRenderer } from 'electron'
|
|
import { IPC } from '../shared/constants'
|
|
import type { AppSettings, FlowGitApi } from '../shared/types/ipc.types'
|
|
import type { CreatePRInput } from '../shared/types/provider.types'
|
|
|
|
// Typed IPC invoker helpers
|
|
function invoke<T = any>(channel: string, ...args: unknown[]): Promise<T> {
|
|
return ipcRenderer.invoke(channel, ...args)
|
|
}
|
|
|
|
function on(channel: string, callback: (...args: unknown[]) => void): () => void {
|
|
const sub = (_event: Electron.IpcRendererEvent, ...args: unknown[]): void => callback(...args)
|
|
ipcRenderer.on(channel, sub)
|
|
return () => ipcRenderer.removeListener(channel, sub)
|
|
}
|
|
|
|
// The typed API surface exposed to the renderer via window.flowgit
|
|
const api: FlowGitApi = {
|
|
// App
|
|
getVersion: () => invoke<string>(IPC.APP_VERSION),
|
|
|
|
// Window controls
|
|
window: {
|
|
minimize: () => invoke<void>('window:minimize'),
|
|
maximize: () => invoke<void>('window:maximize'),
|
|
close: () => invoke<void>('window:close'),
|
|
isMaximized: () => invoke<boolean>('window:isMaximized'),
|
|
},
|
|
|
|
// Dialogs
|
|
openDirectory: (options?: { title?: string }) =>
|
|
invoke<string | null>(IPC.DIALOG_OPEN_DIR, options),
|
|
|
|
// Shell
|
|
openPath: (path: string) => invoke<void>(IPC.SHELL_OPEN, path),
|
|
|
|
// Git detection
|
|
detectGit: () => invoke(IPC.GIT_DETECT),
|
|
getGitVersion: () => invoke<string | null>(IPC.GIT_VERSION),
|
|
|
|
// Repository
|
|
repo: {
|
|
open: (path: string) => invoke(IPC.REPO_OPEN, path),
|
|
init: (path: string) => invoke(IPC.REPO_INIT, path),
|
|
clone: (url: string, targetPath: string, onProgress?: (p: unknown) => void) => {
|
|
if (onProgress) {
|
|
const unsub = on(IPC.REPO_CLONE + ':progress', onProgress)
|
|
return invoke(IPC.REPO_CLONE, url, targetPath).finally(unsub)
|
|
}
|
|
return invoke(IPC.REPO_CLONE, url, targetPath)
|
|
},
|
|
getStatus: (repoPath: string) => invoke(IPC.REPO_STATUS, repoPath),
|
|
list: () => invoke(IPC.REPO_LIST),
|
|
add: (repoPath: string) => invoke(IPC.REPO_ADD, repoPath),
|
|
remove: (repoId: string) => invoke(IPC.REPO_REMOVE, repoId),
|
|
refresh: (repoPath: string) => invoke(IPC.REPO_REFRESH, repoPath),
|
|
},
|
|
|
|
// Changes & staging
|
|
changes: {
|
|
get: (repoPath: string) => invoke(IPC.CHANGES_GET, repoPath),
|
|
stage: (repoPath: string, filePath: string) => invoke(IPC.CHANGES_STAGE, repoPath, filePath),
|
|
unstage: (repoPath: string, filePath: string) => invoke(IPC.CHANGES_UNSTAGE, repoPath, filePath),
|
|
stageAll: (repoPath: string) => invoke(IPC.CHANGES_STAGE_ALL, repoPath),
|
|
unstageAll: (repoPath: string) => invoke(IPC.CHANGES_UNSTAGE_ALL, repoPath),
|
|
discard: (repoPath: string, filePath: string) => invoke(IPC.CHANGES_DISCARD, repoPath, filePath),
|
|
discardAll: (repoPath: string) => invoke(IPC.CHANGES_DISCARD_ALL, repoPath),
|
|
stageHunk: (repoPath: string, filePath: string, hunkIndex: number) =>
|
|
invoke(IPC.CHANGES_STAGE_HUNK, repoPath, filePath, hunkIndex),
|
|
unstageHunk: (repoPath: string, filePath: string, hunkIndex: number) =>
|
|
invoke(IPC.CHANGES_UNSTAGE_HUNK, repoPath, filePath, hunkIndex),
|
|
},
|
|
|
|
// Commits
|
|
commit: {
|
|
create: (repoPath: string, message: string, options?: { amend?: boolean }) =>
|
|
invoke(IPC.COMMIT_CREATE, repoPath, message, options),
|
|
amend: (repoPath: string, message: string) => invoke(IPC.COMMIT_AMEND, repoPath, message),
|
|
cherryPick: (repoPath: string, hash: string) => invoke(IPC.COMMIT_CHERRY_PICK, repoPath, hash),
|
|
revert: (repoPath: string, hash: string) => invoke(IPC.COMMIT_REVERT, repoPath, hash),
|
|
},
|
|
|
|
// Diff
|
|
diff: {
|
|
file: (repoPath: string, filePath: string, options?: { staged?: boolean; ref?: string }) =>
|
|
invoke(IPC.DIFF_FILE, repoPath, filePath, options),
|
|
commit: (repoPath: string, hash: string) => invoke(IPC.DIFF_COMMIT, repoPath, hash),
|
|
commits: (repoPath: string, fromHash: string, toHash: string) =>
|
|
invoke(IPC.DIFF_COMMITS, repoPath, fromHash, toHash),
|
|
branch: (repoPath: string, branchA: string, branchB: string) =>
|
|
invoke(IPC.DIFF_BRANCH, repoPath, branchA, branchB),
|
|
},
|
|
|
|
// History
|
|
history: {
|
|
log: (repoPath: string, options?: { skip?: number; limit?: number; ref?: string; author?: string; search?: string }) =>
|
|
invoke(IPC.HISTORY_LOG, repoPath, options),
|
|
graph: (repoPath: string, options?: { limit?: number }) =>
|
|
invoke(IPC.HISTORY_GRAPH, repoPath, options),
|
|
getCommit: (repoPath: string, hash: string) => invoke(IPC.HISTORY_COMMIT, repoPath, hash),
|
|
getCommitFiles: (repoPath: string, hash: string) => invoke(IPC.HISTORY_COMMIT_FILES, repoPath, hash),
|
|
},
|
|
|
|
// Branches
|
|
branch: {
|
|
list: (repoPath: string) => invoke(IPC.BRANCH_LIST, repoPath),
|
|
create: (repoPath: string, name: string, from?: string) =>
|
|
invoke(IPC.BRANCH_CREATE, repoPath, name, from),
|
|
rename: (repoPath: string, oldName: string, newName: string) =>
|
|
invoke(IPC.BRANCH_RENAME, repoPath, oldName, newName),
|
|
switch: (repoPath: string, name: string) => invoke(IPC.BRANCH_SWITCH, repoPath, name),
|
|
delete: (repoPath: string, name: string, force?: boolean) =>
|
|
invoke(IPC.BRANCH_DELETE, repoPath, name, force),
|
|
merge: (repoPath: string, source: string, options?: { strategy?: string }) =>
|
|
invoke(IPC.BRANCH_MERGE, repoPath, source, options),
|
|
rebase: (repoPath: string, onto: string) => invoke(IPC.BRANCH_REBASE, repoPath, onto),
|
|
},
|
|
|
|
// Tags
|
|
tag: {
|
|
list: (repoPath: string) => invoke(IPC.TAG_LIST, repoPath),
|
|
create: (repoPath: string, name: string, ref: string, message?: string) =>
|
|
invoke(IPC.TAG_CREATE, repoPath, name, ref, message),
|
|
delete: (repoPath: string, name: string) => invoke(IPC.TAG_DELETE, repoPath, name),
|
|
push: (repoPath: string, remote: string, tagName: string) =>
|
|
invoke(IPC.TAG_PUSH, repoPath, remote, tagName),
|
|
},
|
|
|
|
// Stash
|
|
stash: {
|
|
list: (repoPath: string) => invoke(IPC.STASH_LIST, repoPath),
|
|
create: (repoPath: string, message?: string, includeUntracked?: boolean) =>
|
|
invoke(IPC.STASH_CREATE, repoPath, message, includeUntracked),
|
|
apply: (repoPath: string, index: number) => invoke(IPC.STASH_APPLY, repoPath, index),
|
|
pop: (repoPath: string, index: number) => invoke(IPC.STASH_POP, repoPath, index),
|
|
drop: (repoPath: string, index: number) => invoke(IPC.STASH_DROP, repoPath, index),
|
|
},
|
|
|
|
// Remotes
|
|
remote: {
|
|
list: (repoPath: string) => invoke(IPC.REMOTE_LIST, repoPath),
|
|
add: (repoPath: string, name: string, url: string) => invoke(IPC.REMOTE_ADD, repoPath, name, url),
|
|
remove: (repoPath: string, name: string) => invoke(IPC.REMOTE_REMOVE, repoPath, name),
|
|
fetch: (repoPath: string, remote?: string) => invoke(IPC.REMOTE_FETCH, repoPath, remote),
|
|
pull: (repoPath: string, remote?: string, branch?: string) =>
|
|
invoke(IPC.REMOTE_PULL, repoPath, remote, branch),
|
|
push: (repoPath: string, remote?: string, branch?: string, force?: boolean) =>
|
|
invoke(IPC.REMOTE_PUSH, repoPath, remote, branch, force),
|
|
},
|
|
|
|
// Conflicts
|
|
conflict: {
|
|
list: (repoPath: string) => invoke(IPC.CONFLICT_LIST, repoPath),
|
|
markResolved: (repoPath: string, filePath: string) =>
|
|
invoke(IPC.CONFLICT_MARK_RESOLVED, repoPath, filePath),
|
|
continue: (repoPath: string) => invoke(IPC.CONFLICT_CONTINUE, repoPath),
|
|
abort: (repoPath: string) => invoke(IPC.CONFLICT_ABORT, repoPath),
|
|
},
|
|
|
|
// Providers
|
|
provider: {
|
|
list: () => invoke(IPC.PROVIDER_LIST),
|
|
connect: (type: string, token: string, baseUrl?: string) =>
|
|
invoke(IPC.PROVIDER_CONNECT, type, token, baseUrl),
|
|
disconnect: (id: string) => invoke(IPC.PROVIDER_DISCONNECT, id),
|
|
getRepos: (accountId: string) => invoke(IPC.PROVIDER_REPOS, accountId),
|
|
getPRs: (repoPath: string, accountId: string) => invoke(IPC.PROVIDER_PRS, repoPath, accountId),
|
|
createPR: (repoPath: string, accountId: string, input: CreatePRInput) =>
|
|
invoke(IPC.PROVIDER_CREATE_PR, repoPath, accountId, input),
|
|
},
|
|
|
|
// Settings
|
|
settings: {
|
|
get: () => invoke<AppSettings>(IPC.SETTINGS_GET),
|
|
set: (key: keyof AppSettings, value: unknown) => invoke(IPC.SETTINGS_SET, key, value),
|
|
},
|
|
|
|
// Terminal
|
|
terminal: {
|
|
create: (repoPath: string) => invoke<string>(IPC.TERMINAL_CREATE, repoPath),
|
|
sendInput: (id: string, data: string) => ipcRenderer.send(IPC.TERMINAL_INPUT, id, data),
|
|
resize: (id: string, cols: number, rows: number) =>
|
|
ipcRenderer.send(IPC.TERMINAL_RESIZE, id, cols, rows),
|
|
destroy: (id: string) => ipcRenderer.send(IPC.TERMINAL_DESTROY, id),
|
|
onData: (id: string, callback: (data: string) => void) =>
|
|
on(IPC.TERMINAL_DATA + ':' + id, (data) => callback(data as string)),
|
|
},
|
|
|
|
// Blame
|
|
blame: {
|
|
file: (repoPath: string, filePath: string, ref?: string) =>
|
|
invoke(IPC.BLAME_FILE, repoPath, filePath, ref),
|
|
},
|
|
}
|
|
|
|
contextBridge.exposeInMainWorld('flowgit', api)
|
|
export { api }
|