fix(desktop): CSP via webRequest + boot error visibility
Two problems from the first alpha4 run reported as "blank window + CSP
warning in devtools":
1. CSP was set via <meta> in index.html with a strict policy (script-src
'self'). Vite's dev server uses eval() for HMR, which the strict CSP
blocked at module-load time, so the renderer never ran. The meta CSP
also conflicted with Electron's own security heuristics (hence the
warning even though *we* had a policy — Electron was looking for it
on the HTTP response).
Moved the CSP to electron/main.ts via session.webRequest
.onHeadersReceived. Dev profile enables 'unsafe-eval' + ws:/wss: for
HMR; production profile stays strict (no eval, no remote scripts,
connect-src still wide because the user picks arbitrary node URLs).
2. When window.dchain isn't available (preload failed to load, dev
misconfig, etc.), loadKeyFile() throws inside a useEffect. React
swallows async-effect throws, so the app renders blank forever.
Added:
- requireDchain() guard in storage.ts with an explicit error.
- App.tsx catches boot-effect errors and renders them inline.
- ErrorBoundary.tsx for render-time throws.
- window.addEventListener('error') in main.tsx as a last-resort
paint for throws that escape React entirely.
Also: npm script electron:dev now rebuilds main.ts before spawning
Electron (was a silent concurrency bug — TypeScript errors in main.ts
would produce stale dist-electron/).
This commit is contained in:
@@ -20,9 +20,26 @@ declare global {
|
||||
}
|
||||
|
||||
// ─── KeyFile (safeStorage-backed via IPC) ────────────────────────────────
|
||||
//
|
||||
// All keyfile operations go through window.dchain.keyfile — the preload
|
||||
// script bridges them to Electron's safeStorage. If preload failed to
|
||||
// load (dev misconfig, broken build), we surface a loud error rather
|
||||
// than silently failing, since a missing keyfile layer means nothing
|
||||
// else in the app can work.
|
||||
|
||||
function requireDchain() {
|
||||
if (typeof window === 'undefined' || !window.dchain) {
|
||||
throw new Error(
|
||||
'window.dchain is not available — the Electron preload failed to ' +
|
||||
'load. Check dist-electron/preload.js exists and that main.ts is ' +
|
||||
'pointing at it.',
|
||||
);
|
||||
}
|
||||
return window.dchain;
|
||||
}
|
||||
|
||||
export async function loadKeyFile(): Promise<KeyFile | null> {
|
||||
const raw = await window.dchain.keyfile.load();
|
||||
const raw = await requireDchain().keyfile.load();
|
||||
if (!raw) return null;
|
||||
try {
|
||||
return JSON.parse(raw) as KeyFile;
|
||||
@@ -32,11 +49,11 @@ export async function loadKeyFile(): Promise<KeyFile | null> {
|
||||
}
|
||||
|
||||
export async function saveKeyFile(kf: KeyFile): Promise<void> {
|
||||
await window.dchain.keyfile.save(JSON.stringify(kf));
|
||||
await requireDchain().keyfile.save(JSON.stringify(kf));
|
||||
}
|
||||
|
||||
export async function deleteKeyFile(): Promise<void> {
|
||||
await window.dchain.keyfile.delete();
|
||||
await requireDchain().keyfile.delete();
|
||||
}
|
||||
|
||||
// ─── Settings ─────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user