Update public/_kleap/kleap-nextjs-error-detector.js
This commit is contained in:
parent
3122733fb9
commit
0d4ed9302d
|
|
@ -0,0 +1,263 @@
|
|||
/**
|
||||
* Kleap Next.js Error Detector
|
||||
*
|
||||
* Detects and reports Next.js build/runtime errors to parent window via postMessage
|
||||
* Works with Next.js 15 error overlay system
|
||||
*
|
||||
* Version: 1.0.0
|
||||
*/
|
||||
(function () {
|
||||
console.debug('[Kleap] Next.js error detector loaded v1.0.0');
|
||||
|
||||
// Only run inside iframe
|
||||
const isInsideIframe = window.parent !== window;
|
||||
if (!isInsideIframe) {
|
||||
console.debug('[Kleap] Not inside iframe, skipping error detection');
|
||||
return;
|
||||
}
|
||||
|
||||
const PARENT_TARGET_ORIGIN = '*';
|
||||
|
||||
// Track reported errors to avoid duplicates
|
||||
const reportedErrors = new Set();
|
||||
const ERROR_COOLDOWN_MS = 5000;
|
||||
|
||||
/**
|
||||
* Send error report to parent window
|
||||
*/
|
||||
function reportError(errorData) {
|
||||
const errorKey = `${errorData.type}-${errorData.message}`;
|
||||
|
||||
// Check if already reported recently
|
||||
if (reportedErrors.has(errorKey)) {
|
||||
console.debug('[Kleap] Error already reported, skipping:', errorKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark as reported
|
||||
reportedErrors.add(errorKey);
|
||||
setTimeout(() => reportedErrors.delete(errorKey), ERROR_COOLDOWN_MS);
|
||||
|
||||
console.log('[Kleap] Reporting error to parent:', errorData);
|
||||
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: 'nextjs-build-error',
|
||||
payload: errorData,
|
||||
},
|
||||
PARENT_TARGET_ORIGIN
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract error details from Next.js error overlay
|
||||
*/
|
||||
function extractNextJsError(container) {
|
||||
try {
|
||||
// Next.js 15 error overlay structure
|
||||
// Look for common error patterns
|
||||
|
||||
// Method 1: Check for Next.js error container
|
||||
const errorTitle = container.querySelector('[data-nextjs-dialog-header]');
|
||||
const errorBody = container.querySelector('[data-nextjs-dialog-body]');
|
||||
|
||||
if (errorTitle || errorBody) {
|
||||
const title = errorTitle?.textContent?.trim() || '';
|
||||
const body = errorBody?.textContent?.trim() || '';
|
||||
|
||||
return {
|
||||
type: 'build-error',
|
||||
message: title || 'Build error detected',
|
||||
details: body,
|
||||
fullText: `${title}\n\n${body}`.trim(),
|
||||
};
|
||||
}
|
||||
|
||||
// Method 2: Look for error message in generic containers
|
||||
const h4 = container.querySelector('h4');
|
||||
const pre = container.querySelector('pre');
|
||||
|
||||
if (h4 || pre) {
|
||||
return {
|
||||
type: 'build-error',
|
||||
message: h4?.textContent?.trim() || 'Build error',
|
||||
details: pre?.textContent?.trim() || '',
|
||||
fullText: container.textContent?.trim() || 'Unknown error',
|
||||
};
|
||||
}
|
||||
|
||||
// Method 3: Generic text extraction
|
||||
const text = container.textContent?.trim();
|
||||
if (text && text.length > 10) {
|
||||
// Check for common Next.js error patterns
|
||||
if (text.includes('Module not found') ||
|
||||
text.includes("Can't resolve") ||
|
||||
text.includes('Build Error') ||
|
||||
text.includes('Compile Error') ||
|
||||
text.includes('Runtime Error')) {
|
||||
|
||||
// Extract first meaningful line as message
|
||||
const lines = text.split('\n').map(l => l.trim()).filter(Boolean);
|
||||
const message = lines[0] || 'Build error detected';
|
||||
|
||||
return {
|
||||
type: 'build-error',
|
||||
message: message.substring(0, 200), // Limit length
|
||||
details: text.substring(0, 1000), // Limit details
|
||||
fullText: text.substring(0, 2000), // Full context
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[Kleap] Error extracting Next.js error:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch for Next.js error overlay in DOM
|
||||
*/
|
||||
function watchForNextJsErrors() {
|
||||
console.debug('[Kleap] Setting up Next.js error detection');
|
||||
|
||||
// Configuration for MutationObserver
|
||||
const config = {
|
||||
childList: true,
|
||||
subtree: true, // Watch all descendants (Next.js uses portals)
|
||||
attributes: false,
|
||||
};
|
||||
|
||||
// Callback when DOM changes
|
||||
const observerCallback = function (mutationsList) {
|
||||
for (const mutation of mutationsList) {
|
||||
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
|
||||
for (const node of mutation.addedNodes) {
|
||||
if (node.nodeType !== Node.ELEMENT_NODE) continue;
|
||||
|
||||
// Check for Next.js error overlay elements
|
||||
// Next.js 15 uses various IDs and attributes
|
||||
const isErrorOverlay =
|
||||
node.id?.includes('nextjs') ||
|
||||
node.id?.includes('error') ||
|
||||
node.getAttribute?.('data-nextjs-dialog') !== null ||
|
||||
node.getAttribute?.('data-nextjs-toast') !== null ||
|
||||
node.className?.includes?.('nextjs') ||
|
||||
node.className?.includes?.('error-overlay');
|
||||
|
||||
if (isErrorOverlay) {
|
||||
console.log('[Kleap] Detected Next.js error overlay:', node);
|
||||
|
||||
// Wait a bit for content to populate
|
||||
setTimeout(() => {
|
||||
const errorData = extractNextJsError(node);
|
||||
if (errorData) {
|
||||
reportError(errorData);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Also check children recursively
|
||||
if (node.querySelector) {
|
||||
const errorChildren = node.querySelectorAll('[data-nextjs-dialog], [data-nextjs-toast], [id*="nextjs"], [id*="error"]');
|
||||
errorChildren.forEach(child => {
|
||||
setTimeout(() => {
|
||||
const errorData = extractNextJsError(child);
|
||||
if (errorData) {
|
||||
reportError(errorData);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Start observing when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.debug('[Kleap] DOM loaded, starting error detection');
|
||||
const observer = new MutationObserver(observerCallback);
|
||||
observer.observe(document.body || document.documentElement, config);
|
||||
|
||||
// Check for existing errors
|
||||
checkExistingErrors();
|
||||
});
|
||||
} else {
|
||||
console.debug('[Kleap] DOM already loaded, starting error detection');
|
||||
const observer = new MutationObserver(observerCallback);
|
||||
observer.observe(document.body || document.documentElement, config);
|
||||
|
||||
// Check for existing errors
|
||||
checkExistingErrors();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for errors that already exist in the DOM
|
||||
*/
|
||||
function checkExistingErrors() {
|
||||
console.debug('[Kleap] Checking for existing errors');
|
||||
|
||||
try {
|
||||
// Look for Next.js error elements
|
||||
const selectors = [
|
||||
'[data-nextjs-dialog]',
|
||||
'[data-nextjs-toast]',
|
||||
'[id*="nextjs"][id*="error"]',
|
||||
'div[class*="error-overlay"]',
|
||||
];
|
||||
|
||||
selectors.forEach(selector => {
|
||||
const elements = document.querySelectorAll(selector);
|
||||
elements.forEach(element => {
|
||||
console.log('[Kleap] Found existing error element:', element);
|
||||
const errorData = extractNextJsError(element);
|
||||
if (errorData) {
|
||||
reportError(errorData);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Kleap] Error checking existing errors:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Also intercept console.error for build errors
|
||||
* Next.js sometimes logs errors to console before showing overlay
|
||||
*/
|
||||
const originalConsoleError = console.error;
|
||||
console.error = function(...args) {
|
||||
// Call original
|
||||
originalConsoleError.apply(console, args);
|
||||
|
||||
// Check if it looks like a Next.js error
|
||||
const message = args.map(arg =>
|
||||
typeof arg === 'string' ? arg : String(arg)
|
||||
).join(' ');
|
||||
|
||||
if (message.includes('Module not found') ||
|
||||
message.includes("Can't resolve 'tailwindcss'") ||
|
||||
message.includes('Build Error') ||
|
||||
message.includes('Compile Error')) {
|
||||
|
||||
console.log('[Kleap] Detected build error in console.error');
|
||||
|
||||
reportError({
|
||||
type: 'build-error',
|
||||
message: message.substring(0, 200),
|
||||
details: message.substring(0, 1000),
|
||||
fullText: message.substring(0, 2000),
|
||||
source: 'console.error',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Start watching
|
||||
watchForNextJsErrors();
|
||||
|
||||
console.debug('[Kleap] Next.js error detector initialized');
|
||||
})();
|
||||
Loading…
Reference in New Issue