bolt.diy/app/lib/webcontainer/index.ts
KevIsDev fcaf8f66f0 feat: enhance error handling and add new search feature
- Add support for `PREVIEW_CONSOLE_ERROR` in WebContainer error handling

- Introduce new Search component for text search functionality

- Extend `ScrollPosition` interface to include `line` and `column`
- Implement scroll-to-line functionality in CodeMirrorEditor
- Add tab-based navigation for files and search in EditorPanel

This commit introduces several enhancements to the editor, including improved error handling, better scrolling capabilities, and a new search feature. The changes are focused on improving the user experience and adding new functionality to the editor components.
2025-05-01 15:56:08 +01:00

76 lines
2.5 KiB
TypeScript

import { WebContainer } from '@webcontainer/api';
import { WORK_DIR_NAME } from '~/utils/constants';
import { cleanStackTrace } from '~/utils/stacktrace';
interface WebContainerContext {
loaded: boolean;
}
export const webcontainerContext: WebContainerContext = import.meta.hot?.data.webcontainerContext ?? {
loaded: false,
};
if (import.meta.hot) {
import.meta.hot.data.webcontainerContext = webcontainerContext;
}
export let webcontainer: Promise<WebContainer> = new Promise(() => {
// noop for ssr
});
if (!import.meta.env.SSR) {
webcontainer =
import.meta.hot?.data.webcontainer ??
Promise.resolve()
.then(() => {
return WebContainer.boot({
coep: 'credentialless',
workdirName: WORK_DIR_NAME,
forwardPreviewErrors: true, // Enable error forwarding from iframes
});
})
.then(async (webcontainer) => {
webcontainerContext.loaded = true;
const { workbenchStore } = await import('~/lib/stores/workbench');
// Listen for preview errors
webcontainer.on('preview-message', (message) => {
console.log('WebContainer preview message:', message);
// Handle both uncaught exceptions and unhandled promise rejections
if (
message.type === 'PREVIEW_UNCAUGHT_EXCEPTION' ||
message.type === 'PREVIEW_UNHANDLED_REJECTION' ||
message.type === 'PREVIEW_CONSOLE_ERROR'
) {
const isPromise = message.type === 'PREVIEW_UNHANDLED_REJECTION';
const isConsoleError = message.type === 'PREVIEW_CONSOLE_ERROR';
const title = isPromise
? 'Unhandled Promise Rejection'
: isConsoleError
? 'Console Error'
: 'Uncaught Exception';
workbenchStore.actionAlert.set({
type: 'preview',
title,
description:
'message' in message
? message.message
: 'args' in message && Array.isArray(message.args) && message.args.length > 0
? message.args[0]
: 'Unknown error',
content: `Error occurred at ${message.pathname}${message.search}${message.hash}\nPort: ${message.port}\n\nStack trace:\n${cleanStackTrace(message.stack || '')}`,
source: 'preview',
});
}
});
return webcontainer;
});
if (import.meta.hot) {
import.meta.hot.data.webcontainer = webcontainer;
}
}