gebeya-dala-error-fixer
Version:
Automatic runtime error detection and fix suggestions for Next.js applications with config-based setup
98 lines (97 loc) • 4.51 kB
JavaScript
'use client';
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useCallback, useEffect } from 'react';
import { ErrorDetector } from './ErrorDetector';
import { ErrorModal } from './ErrorModal';
import { ErrorBoundary } from './ErrorBoundary';
export const ErrorFixerProvider = ({ children, enabled = true, autoShow = true, position = 'top-right' }) => {
const [currentError, setCurrentError] = useState(null);
const [currentSuggestion, setCurrentSuggestion] = useState(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [errorDetector, setErrorDetector] = useState(null);
const [errorCount, setErrorCount] = useState(0);
const handleError = useCallback((error, suggestion) => {
console.log('Error detected:', error);
setCurrentError(error);
setCurrentSuggestion(suggestion);
setErrorCount(prev => prev + 1);
if (autoShow) {
setIsModalOpen(true);
}
}, [autoShow]);
const closeModal = useCallback(() => {
setIsModalOpen(false);
}, []);
const openModal = useCallback(() => {
setIsModalOpen(true);
}, []);
useEffect(() => {
if (enabled && typeof window !== 'undefined') {
const detector = new ErrorDetector(handleError);
setErrorDetector(detector);
return () => {
detector.destroy();
};
}
}, [enabled, handleError]);
// Don't render anything if disabled or on server
if (!enabled || typeof window === 'undefined') {
return _jsx(_Fragment, { children: children });
}
const getFloatingButtonPosition = () => {
const base = {
position: 'fixed',
zIndex: 9998,
width: '50px',
height: '50px',
borderRadius: '50%',
backgroundColor: errorCount > 0 ? '#ef4444' : '#333',
border: '2px solid #555',
color: '#fff',
fontSize: '18px',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
transition: 'all 0.2s ease',
fontFamily: 'system-ui, -apple-system, sans-serif'
};
switch (position) {
case 'top-right':
return { ...base, top: '20px', right: '20px' };
case 'top-left':
return { ...base, top: '20px', left: '20px' };
case 'bottom-right':
return { ...base, bottom: '20px', right: '20px' };
case 'bottom-left':
return { ...base, bottom: '20px', left: '20px' };
default:
return { ...base, top: '20px', right: '20px' };
}
};
return (_jsxs(ErrorBoundary, { onError: handleError, children: [children, _jsxs("button", { onClick: openModal, style: getFloatingButtonPosition(), title: errorCount > 0 ? `${errorCount} error${errorCount > 1 ? 's' : ''} detected` : 'No errors', children: [errorCount > 0 ? '!' : '✓', errorCount > 0 && (_jsx("div", { style: {
position: 'absolute',
top: '-8px',
right: '-8px',
backgroundColor: '#dc2626',
color: '#fff',
borderRadius: '50%',
width: '20px',
height: '20px',
fontSize: '12px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold'
}, children: errorCount > 99 ? '99+' : errorCount }))] }), _jsx(ErrorModal, { isOpen: isModalOpen, error: currentError, suggestion: currentSuggestion, onClose: closeModal, fixItEnabled: true, onFixIt: (error, suggestion) => {
// Default fix it action - copy code to clipboard
if (suggestion.code) {
navigator.clipboard.writeText(suggestion.code);
alert('Code copied to clipboard! Apply the fix to your code.');
}
else {
alert('Please follow the suggested actions to fix this error.');
}
} })] }));
};