|
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]); |
|
}); |
|
} |
|
} |
|
|