|
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(() => { |
|
|
|
}); |
|
|
|
if (!import.meta.env.SSR) { |
|
webcontainer = |
|
import.meta.hot?.data.webcontainer ?? |
|
Promise.resolve() |
|
.then(() => { |
|
return WebContainer.boot({ |
|
workdirName: WORK_DIR_NAME, |
|
forwardPreviewErrors: true, |
|
}); |
|
}) |
|
.then(async (webcontainer) => { |
|
webcontainerContext.loaded = true; |
|
|
|
const { workbenchStore } = await import('~/lib/stores/workbench'); |
|
|
|
|
|
webcontainer.on('preview-message', (message) => { |
|
console.log('WebContainer preview message:', message); |
|
|
|
|
|
if (message.type === 'PREVIEW_UNCAUGHT_EXCEPTION' || message.type === 'PREVIEW_UNHANDLED_REJECTION') { |
|
const isPromise = message.type === 'PREVIEW_UNHANDLED_REJECTION'; |
|
workbenchStore.actionAlert.set({ |
|
type: 'preview', |
|
title: isPromise ? 'Unhandled Promise Rejection' : 'Uncaught Exception', |
|
description: message.message, |
|
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; |
|
} |
|
} |
|
|