| import type { WebContainer } from '@webcontainer/api'; | |
| import { atom } from 'nanostores'; | |
| export interface PreviewInfo { | |
| port: number; | |
| ready: boolean; | |
| baseUrl: string; | |
| } | |
| export class PreviewsStore { | |
| #availablePreviews = new Map<number, PreviewInfo>(); | |
| #webcontainer: Promise<WebContainer>; | |
| previews = atom<PreviewInfo[]>([]); | |
| constructor(webcontainerPromise: Promise<WebContainer>) { | |
| this.#webcontainer = webcontainerPromise; | |
| this.#init(); | |
| } | |
| async #init() { | |
| const webcontainer = await this.#webcontainer; | |
| webcontainer.on('port', (port, type, url) => { | |
| let previewInfo = this.#availablePreviews.get(port); | |
| if (type === 'close' && previewInfo) { | |
| this.#availablePreviews.delete(port); | |
| this.previews.set(this.previews.get().filter((preview) => preview.port !== port)); | |
| return; | |
| } | |
| const previews = this.previews.get(); | |
| if (!previewInfo) { | |
| previewInfo = { port, ready: type === 'open', baseUrl: url }; | |
| this.#availablePreviews.set(port, previewInfo); | |
| previews.push(previewInfo); | |
| } | |
| previewInfo.ready = type === 'open'; | |
| previewInfo.baseUrl = url; | |
| this.previews.set([...previews]); | |
| }); | |
| } | |
| } | |