dev experience

This commit is contained in:
2026-01-01 17:43:38 +01:00
parent df7e5db5ba
commit 9958053462
8 changed files with 208 additions and 173 deletions

View File

@@ -117,10 +117,6 @@ export class GlobalErrorHandler {
// Store in history
this.addToHistory(error, enhancedContext);
// Show dev overlay if enabled
if (this.options.showDevOverlay) {
this.showDevOverlay(error, enhancedContext);
}
// Report to external if enabled
if (this.options.reportToExternal) {
@@ -161,10 +157,6 @@ export class GlobalErrorHandler {
// Store in history
this.addToHistory(error, enhancedContext);
// Show dev overlay if enabled
if (this.options.showDevOverlay) {
this.showDevOverlay(error, enhancedContext);
}
// Report to external if enabled
if (this.options.reportToExternal) {
@@ -200,10 +192,7 @@ export class GlobalErrorHandler {
// Store in history
this.addToHistory(error, enhancedContext);
// Show dev overlay if enabled
if (this.options.showDevOverlay) {
this.showDevOverlay(error, enhancedContext);
}
// No overlay - just enhanced console logging
}
};
}
@@ -357,137 +346,6 @@ export class GlobalErrorHandler {
this.logger.error(error.message, error, context);
}
/**
* Show development overlay with error details
*/
private showDevOverlay(error: Error | ApiError, context: Record<string, unknown>): void {
// Check if overlay already exists
const existingOverlay = document.getElementById('gridpilot-error-overlay');
if (existingOverlay) {
// Update existing overlay
this.updateDevOverlay(existingOverlay, error, context);
return;
}
// Create new overlay
const overlay = document.createElement('div');
overlay.id = 'gridpilot-error-overlay';
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.95);
color: #fff;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 12px;
z-index: 999999;
overflow: auto;
padding: 20px;
border: 4px solid #ff4444;
box-shadow: 0 0 50px rgba(255, 68, 68, 0.5);
`;
this.updateDevOverlay(overlay, error, context);
document.body.appendChild(overlay);
// Add keyboard shortcut to dismiss
const dismissHandler = (e: KeyboardEvent) => {
if (e.key === 'Escape' || e.key === 'Enter') {
overlay.remove();
document.removeEventListener('keydown', dismissHandler);
}
};
document.addEventListener('keydown', dismissHandler);
}
/**
* Update existing dev overlay
*/
private updateDevOverlay(overlay: HTMLElement, error: Error | ApiError, context: Record<string, unknown>): void {
const isApiError = error instanceof ApiError;
const timestamp = new Date().toLocaleTimeString();
overlay.innerHTML = `
<div style="max-width: 1200px; margin: 0 auto;">
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 20px;">
<div>
<h1 style="color: #ff4444; margin: 0 0 10px 0; font-size: 24px;">
🚨 UNCAUGHT ERROR - DEVELOPMENT MODE
</h1>
<div style="color: #888;">${timestamp} | Press ESC or ENTER to dismiss</div>
</div>
<button onclick="this.parentElement.parentElement.remove()"
style="background: #ff4444; color: white; border: none; padding: 8px 16px; cursor: pointer; border-radius: 4px; font-weight: bold;">
CLOSE
</button>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
<div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;">
<h3 style="color: #ffaa00; margin-top: 0;">Error Information</h3>
<div style="line-height: 1.6;">
<div><strong>Type:</strong> <span style="color: #ff4444;">${isApiError ? error.type : error.name}</span></div>
<div><strong>Message:</strong> ${error.message}</div>
${isApiError ? `<div><strong>Severity:</strong> ${error.getSeverity()}</div>` : ''}
${isApiError ? `<div><strong>Retryable:</strong> ${error.isRetryable()}</div>` : ''}
${isApiError ? `<div><strong>Connectivity:</strong> ${error.isConnectivityIssue()}</div>` : ''}
</div>
</div>
<div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;">
<h3 style="color: #00aaff; margin-top: 0;">Environment</h3>
<div style="line-height: 1.6;">
<div><strong>Mode:</strong> ${process.env.NODE_ENV}</div>
<div><strong>App Mode:</strong> ${process.env.NEXT_PUBLIC_GRIDPILOT_MODE || 'pre-launch'}</div>
<div><strong>URL:</strong> ${window.location.href}</div>
<div><strong>User Agent:</strong> ${navigator.userAgent}</div>
</div>
</div>
</div>
${isApiError && error.context ? `
<div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-bottom: 20px;">
<h3 style="color: #00ff88; margin-top: 0;">API Context</h3>
<pre style="background: #000; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 0;">${JSON.stringify(error.context, null, 2)}</pre>
</div>
` : ''}
<div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-bottom: 20px;">
<h3 style="color: #ff4444; margin-top: 0;">Stack Trace</h3>
<pre style="background: #000; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 0; white-space: pre-wrap;">${context.enhancedStack || error.stack || 'No stack trace available'}</pre>
</div>
<div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-bottom: 20px;">
<h3 style="color: #ffaa00; margin-top: 0;">Additional Context</h3>
<pre style="background: #000; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 0;">${JSON.stringify(context, null, 2)}</pre>
</div>
<div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;">
<h3 style="color: #00aaff; margin-top: 0;">Quick Actions</h3>
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<button onclick="navigator.clipboard.writeText(\`${error.message}\n\nStack:\n${error.stack}\n\nContext:\n${JSON.stringify(context, null, 2)}\`)"
style="background: #0066cc; color: white; border: none; padding: 8px 12px; cursor: pointer; border-radius: 4px;">
📋 Copy Error Details
</button>
<button onclick="window.location.reload()"
style="background: #cc6600; color: white; border: none; padding: 8px 12px; cursor: pointer; border-radius: 4px;">
🔄 Reload Page
</button>
<button onclick="console.clear(); console.log('Error details:', ${JSON.stringify({ error: error.message, stack: error.stack, context }).replace(/"/g, '"')})"
style="background: #6600cc; color: white; border: none; padding: 8px 12px; cursor: pointer; border-radius: 4px;">
📝 Log to Console
</button>
</div>
</div>
<div style="margin-top: 20px; padding: 15px; background: #222; border-radius: 4px; border-left: 4px solid #ffaa00;">
<strong>💡 Tip:</strong> This overlay only appears in development mode. In production, errors are logged silently and handled gracefully.
</div>
</div>
`;
}
/**
* Report error to external services
@@ -581,10 +439,8 @@ export class GlobalErrorHandler {
this.logErrorWithMaximumDetail(error, context);
this.addToHistory(error, context);
// Auto-capture for replay in development
if (this.options.showDevOverlay) {
this.showDevOverlay(error, context);
// Auto-capture for replay
const replaySystem = getGlobalReplaySystem();
replaySystem.autoCapture(error, context);
}
@@ -606,12 +462,6 @@ export class GlobalErrorHandler {
console.error = (console as any)._originalError;
}
// Remove overlay if exists
const overlay = document.getElementById('gridpilot-error-overlay');
if (overlay) {
overlay.remove();
}
this.isInitialized = false;
if (this.options.verboseLogging) {