Refresh UI components and showcase; release updated framework packages

This commit is contained in:
Clintchiz committed 2026-09-20 18:13:24 +05:30
1 parent d800228585
commit c77f5e1cec
293 files changed
+22544 -35778

No files matched your search

+4 -1
View File
@@ -64,7 +64,10 @@ export async function readPluginAsset(asset: ServedPluginAsset): Promise<string
if (asset.source instanceof Uint8Array) return toBody(asset.source);
if (!asset.entry) throw new Error(`Plugin asset '${asset.id}' has no source.`);
const shouldBundle = asset.runtime && (asset.bundle ?? /\.[cm]?tsx?$/.test(asset.entry));
// Published runtimes are JavaScript too, often with relative split chunks.
// Serve a self-contained browser entry unless the plugin explicitly opts out
// (for example, prebuilt pdf.js modules whose worker protocol needs raw ESM).
const shouldBundle = asset.runtime && (asset.bundle ?? /\.[cm]?[jt]sx?$/.test(asset.entry));
if (!shouldBundle) return toBody(await readFile(asset.entry));
const result = await Bun.build({
+41 -35
View File
@@ -896,7 +896,7 @@ function forbiddenOrigin(): Response {
}
export interface UpgradeServer {
upgrade(req: Request, opts: { data: WsData }): boolean;
upgrade(req: Request, opts: { data: WsData; headers?: Headers }): boolean;
/** Bun's per-request socket peer address (used for the non-spoofable client IP). */
requestIP?(req: Request): { address: string } | null;
}
@@ -1258,44 +1258,50 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
return secure(new Response("Expected a WebSocket upgrade request", { status: 426 }));
}
// --- Realtime: try to upgrade BEFORE the normal HTTP pipeline. ---
// Upgrade only after the same authentication/authorization middleware as HTTP.
const rt = router.matchRealtime(url.pathname);
if (rt) {
// Reject cross-site WebSocket handshakes (CSWSH) before doing any work.
if (!isWebSocketOriginAllowed(req, deps.security)) return secure(forbiddenOrigin());
const mod = await loadModule(rt.route.file);
let data: WsData;
if (isRoomDefinition(mod.default)) {
// Identify the connection: an authenticated session user id, else ?user=.
const wsCtx = createContext(req, url);
const sessionUser = wsCtx.session.get<{ id?: unknown }>("user");
const user =
sessionUser && typeof sessionUser === "object" && sessionUser.id != null
? String(sessionUser.id)
: (url.searchParams.get("user") ?? undefined);
const query = Object.fromEntries(url.searchParams);
// Room-level gate (e.g. require auth) — reject before accepting the socket.
const allowed = await mod.default.handlers.authorize?.({
user,
query,
headers: req.headers,
});
if (allowed === false) {
return secure(new Response("Forbidden", { status: 403 }));
const wsCtx = createContext(req, url);
return runWithRequestContext(wsCtx, async () => {
try {
initializeRequestCache(wsCtx);
wsCtx.ip = server.requestIP?.(req)?.address ?? undefined;
wsCtx.locals.cspNonce = nonce;
let data: WsData | undefined;
const permit = crypto.randomUUID();
const response = await runMiddleware(await resolveMiddleware(), wsCtx, async () => {
const mod = await loadModule(rt.route.file);
if (isRoomDefinition(mod.default)) {
const sessionUser = wsCtx.session.get<{ id?: unknown }>("user");
const authenticatedUser = wsCtx.user as { id?: unknown } | null;
const id = authenticatedUser?.id ?? sessionUser?.id;
// Query parameters are untrusted and must never supply an identity.
const user = id == null ? undefined : String(id);
const query = Object.fromEntries(url.searchParams);
if (mod.default.handlers.security?.requireUser && !user)
return new Response("Forbidden", { status: 403 });
const allowed = await mod.default.handlers.authorize?.({ user, query, headers: req.headers });
if (allowed === false) return new Response("Forbidden", { status: 403 });
data = { kind: "room", meta: { room: url.pathname, def: mod.default, query, user } };
} else if (mod.websocket && typeof mod.websocket === "object") {
data = { kind: "realtime", handler: mod.websocket as WsHandler };
} else {
return new Response("Realtime route needs a default defineRoom() or a `websocket` export", { status: 500 });
}
// A response lets post-processing middleware complete before upgrading.
return new Response(null, { status: 204, headers: { "x-wrnexus-upgrade-permit": permit } });
});
const allowed = data && response.status === 204 && response.headers.get("x-wrnexus-upgrade-permit") === permit;
response.headers.delete("x-wrnexus-upgrade-permit");
const result = secure(withContextHeaders(wsCtx, response));
if (!allowed) return result;
if (server.upgrade(req, { data: data!, headers: result.headers })) return undefined;
return secure(new Response("Expected a WebSocket upgrade request", { status: 426 }));
} catch {
return secure(new Response("Realtime connection failed", { status: 500 }));
}
data = { kind: "room", meta: { room: url.pathname, def: mod.default, query, user } };
} else if (mod.websocket && typeof mod.websocket === "object") {
data = { kind: "realtime", handler: mod.websocket as WsHandler };
} else {
return secure(
new Response("Realtime route needs a default defineRoom() or a `websocket` export", {
status: 500,
}),
);
}
const upgraded = server.upgrade(req, { data });
if (upgraded) return undefined; // Bun takes over the socket.
return secure(new Response("Expected a WebSocket upgrade request", { status: 426 }));
});
}
const ctx = createContext(req, url);