import "./style.css"; import * as aftercare from "@char/aftercare"; import * as jsxRuntime from "@char/aftercare/jsx-runtime"; import { HOST_GLOBAL, type HostModule } from "@berry/api/host.ts"; import * as webApi from "@berry/api/web.ts"; import { app } from "./app.tsx"; import { setToken, token } from "./client.ts"; import { Scope } from "./ui.ts"; if (!(Symbol.asyncIterator in ReadableStream.prototype)) { await import("./stream-iterator.ts"); } function login(): Element { const input = ( ) as HTMLInputElement; const error =

as HTMLParagraphElement; return (

{ event.preventDefault(); const response = await fetch("/api/extensions", { headers: { authorization: `Bearer ${input.value}` }, }); await response.body?.cancel(); if (response.ok) setToken(input.value); else {error.textContent = response.status === 401 ? "that token is not it" : `server said ${response.status}`;} }} >

berry

{input} {error}
); } // what extensions' frontends import of these is the app's own instance (globalThis as Record)[HOST_GLOBAL] = { "@char/aftercare": aftercare, "@char/aftercare/jsx-runtime": jsxRuntime, "@berry/api/web.ts": webApi, } satisfies Record; let scope = new Scope(); token.subscribeImmediate((value) => { scope.dispose(); scope = new Scope(); document.body.replaceChildren(value === null ? login() : app(scope)); });