mirror of
https://github.com/stackblitz/bolt.new
synced 2024-11-27 22:42:21 +00:00
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
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]);
|
|
});
|
|
}
|
|
}
|