[READ-ONLY] Mirror of https://github.com/bombshell-dev/docs. bomb.sh/docs
Something went wrong. Try again.
3.7 kB · 113 lines
Astro
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114---import Terminal from "./Terminal.astro";
interface Props { name: string;}const { name } = Astro.props;---
<web-container name={name}> <slot /> <Terminal /></web-container>
<script> import type { Terminal } from "@xterm/xterm"; import { WebContainer, auth } from "@webcontainer/api"; const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); let host: WebContainer; let bootError: string | null = null;
auth.init({ clientId: 'wc_api_natemoo_re_679fe059f5f36e18deed13fb4a9c7b4f', scope: '', });
try { host = await WebContainer.boot({ coep: 'require-corp', workdirName: 'demo' }); const base = (import.meta.env.BASE_URL || '/').replace(/\/?$/, ''); const snapshotUrl = `${base}/snapshot`; const snapshotResponse = await fetch(snapshotUrl); if (!snapshotResponse.ok) { throw new Error(`Snapshot failed (${snapshotResponse.status}). Run \`pnpm run snapshot\` and ensure the dev server can serve ${snapshotUrl}.`); } const snapshot = await snapshotResponse.arrayBuffer(); await host.mount(snapshot, { mountPoint: "/" }); } catch (e) { bootError = e instanceof Error ? e.message : String(e); }
customElements.define( "web-container", class extends HTMLElement { get dir() { return `${this.name}/` } get file() { return `${this.dir}index.js`; } get fileContent() { const text = this.querySelector("pre code")!.textContent; return `import { intro, outro } from "@clack/prompts";console.clear();intro("\\x1b[46m\\x1b[30m ${this.name} \\x1b[0m");\n${text};`; } get name() { return this.getAttribute("name")!; } get terminal(): Terminal | undefined { return (this.querySelector("docs-terminal") as any)?.instance; } async connectedCallback() { if (bootError) { this.innerHTML = `<div style="padding:1rem;background:var(--sl-color-accent-low);color:var(--sl-color-text);border-radius:0.5rem;font-family:monospace;font-size:0.875rem;">WebContainer: ${bootError}</div>`; return; } const termEl = this.querySelector("docs-terminal") as any; const deadline = Date.now() + 10000; while (!termEl?.instance && Date.now() < deadline) { await sleep(50); } await host.fs.mkdir(this.dir, { recursive: true }); await host.fs.writeFile( this.file, this.fileContent, { encoding: "utf-8" } ); await this.render(); }
async render() { const { terminal, name } = this; terminal?.reset(); const main = async () => { // we set an infinite loop so that when the node process exits, we restart while (true) { const process = await host.spawn("node", ["index.js"], { cwd: name, terminal: { rows: terminal?.rows!, cols: terminal?.cols! }, }); process.output.pipeTo( new WritableStream({ write(data) { terminal?.write(data); } }) ); // write the terminal input to the process const terminalWriter = terminal?.onData((data) => { const writer = process.input.getWriter(); writer.write(data); writer.releaseLock(); }); // wait for the process to finish await process.exit; await sleep(2000); terminal?.clear(); terminalWriter?.dispose(); } } main(); } } );</script>