Harden audit findings: correctness, type-safety, Windows conventions & polish
Audit-pass over CODE-AUDIT.md (~48 items closed this pass; all verified — typecheck + 234 tests + eslint + prettier green). Correctness / bugs: - B3: match the release checksum to the asset's filename line (no wrong-hash verify) - B4: newline-safe metadata probe (one --print with a unit-separator delimiter) - B5 / L88: guard the meta event against canceled items; progress no longer promotes a queued item outside pump() - B7: cookie-login promise always resolves (handles destroy-without-close) - L146: trim parser rejects >2 colon-group times; M36: Library selection counts only actionable rows - L11 / L50 / L156 / L57 / L159 / L15 / L3: live queue count, empty-cookie message, schedule picker min, dead-code/comment cleanup Type safety: - Enable noUncheckedIndexedAccess + noFallthroughCasesInSwitch (15 real edge cases fixed) Resilience / Windows / metadata: - R5: settings write failure handled (no unhandled IPC rejection; reconciles to truth) - W1 / W5 / W6: min window size, seeded folder picker, parented sign-in window; L147 dead macOS branches removed - CL1: shared stdout markers; package/builder metadata (license, homepage, repository, copyright, tsbuildinfo glob) Copy / docs / tests: - M37 / SR9 dev-jargon cleanup in hints; M8 / M25 / M26 / L66 / L80 / L81 reconciled - New unit tests for L35 (isValidMediaItem) and L36 (compareVersions) This commit also checkpoints the previously-uncommitted feat/tray-background-clipboard work it builds on: background running + auto-download, library clipboard detection, tray, binary management & library scale, credential encryption at rest, the shared jsonStore and ui/ primitives, and the eslint/prettier tooling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+24
-19
@@ -57,8 +57,7 @@ const api = {
|
||||
return () => ipcRenderer.removeListener(IpcChannels.appUpdateProgress, listener)
|
||||
},
|
||||
|
||||
getYtdlpVersion: (): Promise<YtdlpVersionResult> =>
|
||||
ipcRenderer.invoke(IpcChannels.ytdlpVersion),
|
||||
getYtdlpVersion: (): Promise<YtdlpVersionResult> => ipcRenderer.invoke(IpcChannels.ytdlpVersion),
|
||||
|
||||
/** Versions of the bundled ffmpeg + ffprobe (display-only; not auto-updated). */
|
||||
getFfmpegVersions: (): Promise<FfmpegVersionResult> =>
|
||||
@@ -69,20 +68,16 @@ const api = {
|
||||
startDownload: (opts: StartDownloadOptions): Promise<StartDownloadResult> =>
|
||||
ipcRenderer.invoke(IpcChannels.downloadStart, opts),
|
||||
|
||||
cancelDownload: (id: string): Promise<void> =>
|
||||
ipcRenderer.invoke(IpcChannels.downloadCancel, id),
|
||||
cancelDownload: (id: string): Promise<void> => ipcRenderer.invoke(IpcChannels.downloadCancel, id),
|
||||
|
||||
pauseDownload: (id: string): Promise<void> =>
|
||||
ipcRenderer.invoke(IpcChannels.downloadPause, id),
|
||||
pauseDownload: (id: string): Promise<void> => ipcRenderer.invoke(IpcChannels.downloadPause, id),
|
||||
|
||||
getDefaultFolder: (): Promise<string> => ipcRenderer.invoke(IpcChannels.defaultFolder),
|
||||
|
||||
chooseFolder: (): Promise<string | null> => ipcRenderer.invoke(IpcChannels.chooseFolder),
|
||||
chooseFolder: (current?: string): Promise<string | null> =>
|
||||
ipcRenderer.invoke(IpcChannels.chooseFolder, current),
|
||||
|
||||
openPath: (path: string): Promise<string> => ipcRenderer.invoke(IpcChannels.openPath, path),
|
||||
|
||||
showInFolder: (path: string): Promise<void> =>
|
||||
ipcRenderer.invoke(IpcChannels.showInFolder, path),
|
||||
showInFolder: (path: string): Promise<void> => ipcRenderer.invoke(IpcChannels.showInFolder, path),
|
||||
|
||||
readClipboard: (): Promise<string> => ipcRenderer.invoke(IpcChannels.clipboardRead),
|
||||
|
||||
@@ -184,8 +179,7 @@ const api = {
|
||||
reindexSource: (id: string): Promise<IndexSourceResult> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceReindex, id),
|
||||
|
||||
removeSource: (id: string): Promise<Source[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceRemove, id),
|
||||
removeSource: (id: string): Promise<Source[]> => ipcRenderer.invoke(IpcChannels.sourceRemove, id),
|
||||
|
||||
listSourceItems: (sourceId: string): Promise<MediaItem[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceItems, sourceId),
|
||||
@@ -220,8 +214,7 @@ const api = {
|
||||
runTerminal: (id: string, args: string): Promise<TerminalRunResult> =>
|
||||
ipcRenderer.invoke(IpcChannels.terminalRun, id, args),
|
||||
|
||||
cancelTerminal: (id: string): Promise<void> =>
|
||||
ipcRenderer.invoke(IpcChannels.terminalCancel, id),
|
||||
cancelTerminal: (id: string): Promise<void> => ipcRenderer.invoke(IpcChannels.terminalCancel, id),
|
||||
|
||||
/** Subscribe to live terminal output. Returns an unsubscribe function. */
|
||||
onTerminalOutput: (cb: (ev: TerminalEvent) => void): (() => void) => {
|
||||
@@ -232,7 +225,11 @@ const api = {
|
||||
|
||||
/** Reflect overall queue progress on the Windows taskbar (fire-and-forget). */
|
||||
setTaskbarProgress: (p: TaskbarProgress): void =>
|
||||
ipcRenderer.send(IpcChannels.taskbarProgress, p)
|
||||
ipcRenderer.send(IpcChannels.taskbarProgress, p),
|
||||
|
||||
/** Open a YouTube WebView to automatically extract a PO token (Phase P). */
|
||||
mintPoToken: (): Promise<string | null> =>
|
||||
ipcRenderer.invoke(IpcChannels.youtubePoTokenMint) as Promise<string | null>
|
||||
}
|
||||
|
||||
export type Api = typeof api
|
||||
@@ -248,11 +245,19 @@ if (process.contextIsolated) {
|
||||
contextBridge.exposeInMainWorld('electron', electron)
|
||||
contextBridge.exposeInMainWorld('api', api)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
// M30: a broken bridge causes the renderer to silently run in preview/mock mode.
|
||||
// Notify the main process so it can show a hard error dialog — without this the
|
||||
// failure is completely invisible to the user.
|
||||
console.error('[AeroFetch preload] contextBridge failed:', error)
|
||||
try {
|
||||
ipcRenderer.send(IpcChannels.preloadBridgeFailure, String(error))
|
||||
} catch {
|
||||
/* if IPC itself is broken there is nothing more we can do */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore (defined in index.d.ts)
|
||||
// @ts-ignore window.electron is declared in index.d.ts
|
||||
window.electron = electron
|
||||
// @ts-ignore (defined in index.d.ts)
|
||||
// @ts-ignore window.api is declared in index.d.ts
|
||||
window.api = api
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user