2024-07-17 18:54:46 +00:00
|
|
|
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);
|
|
|
|
|
2024-07-22 15:40:28 +00:00
|
|
|
if (type === 'close' && previewInfo) {
|
|
|
|
this.#availablePreviews.delete(port);
|
|
|
|
this.previews.set(this.previews.get().filter((preview) => preview.port !== port));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-17 18:54:46 +00:00
|
|
|
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]);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|