feat(main): CC8 — file-backed leveled logger + renderer log sink
Diagnostics were invisible in a packaged build: main catches did a bare console.error (DevTools suppressed in prod, M31) and the renderer's logError (M29) wrote to an unreachable console. Add a small leveled logger (src/main/logger.ts) appending to <userData>/logs/aerofetch.log with size-capped rotation; all app/fs access is lazy+guarded so it's a safe no-op under tests. - Route the 5 main-process console.* catch sites (jsonStore write-fail, settings write-fail + plaintext-secret warn, cookie loadURL, yt-dlp auto-update) through the logger. - Add a fire-and-forget log:write IPC channel + preload logError() so the renderer's logError forwards failures to the main file sink (closes the M29 "sink" half the code comments deferred to CC8). mockApi + Api type updated. - Unit-test pure formatLine/composeMessage + no-op safety; update the R6 jsonStore test to assert against the logger. The user-facing toast half of CC8 ties to the global status surface (UI25/UX9). typecheck + 258 tests + lint + prettier green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,7 @@ export const mockApi: Api = {
|
||||
openUrl: async () => {},
|
||||
showInFolder: async () => {},
|
||||
readClipboard: async () => '',
|
||||
logError: () => {},
|
||||
getSettings: async () => MOCK_SETTINGS,
|
||||
setSettings: async (partial) => Object.assign(MOCK_SETTINGS, partial),
|
||||
listHistory: async () => [],
|
||||
|
||||
@@ -4,10 +4,18 @@
|
||||
// Replaces the swallowed `.catch(() => {})` sites the audit flagged (M29) with a
|
||||
// single, consistent log format. `op` names the operation, e.g. 'addHistory'.
|
||||
//
|
||||
// Note: in production the DevTools console isn't reachable (the app menu is
|
||||
// suppressed), so this is primarily a development/`--inspect` diagnostic until a
|
||||
// persistent renderer log sink lands (CC8). It is still strictly better than
|
||||
// discarding the error.
|
||||
// The failure is both printed to the renderer console (dev/`--inspect`) and
|
||||
// forwarded to the main process's file-backed diagnostic log (CC8), so it survives
|
||||
// into a packaged build where the renderer console is unreachable.
|
||||
export function logError(op: string): (e: unknown) => void {
|
||||
return (e) => console.error(`[AeroFetch] ${op} failed:`, e)
|
||||
return (e) => {
|
||||
console.error(`[AeroFetch] ${op} failed:`, e)
|
||||
try {
|
||||
const detail = e instanceof Error ? e.message : String(e)
|
||||
// window.api is absent in the browser UI preview and in unit tests.
|
||||
if (typeof window !== 'undefined') window.api?.logError?.(op, detail)
|
||||
} catch {
|
||||
/* logging must never throw out of a catch handler */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user