import { serializeQueryCache } from '@pinia/colada'; import { renderSSRHead } from '@unhead/vue/server'; import { streamText } from 'hono/streaming'; import { renderToWebStream } from 'vue/server-renderer'; import { buildBootstrapScript } from '@/lib/manifest'; import { createApp } from '@/main'; import { htmlEscape } from '@/server/utils/htmlEscape'; import { useAuthStore } from '@/stores/auth'; import type { Hono } from 'hono'; const parseCookie = (cookieHeader: string | undefined, key: string): string | undefined => { if (!cookieHeader) return undefined; const segments = cookieHeader.split(';'); for (const segment of segments) { const [rawKey, ...rest] = segment.trim().split('='); if (rawKey !== key) continue; return decodeURIComponent(rest.join('=')); } return undefined; }; export function registerSSRRoutes(app: Hono) { app.get("*", async (c) => { const nonce = crypto.randomUUID(); const url = new URL(c.req.url); const lang = c.get("language") const { app: vueApp, router, head, pinia, bodyClass, queryCache } = await createApp(lang); vueApp.provide("honoContext", c); const auth = useAuthStore(); auth.$reset(); await auth.init(); await router.push(url.pathname); await router.isReady(); return streamText(c, async (stream) => { c.header("Content-Type", "text/html; charset=utf-8"); c.header("Content-Encoding", "Identity"); const ctx: Record = {}; const appStream = renderToWebStream(vueApp, ctx); // HTML Head await stream.write(``); await stream.write(""); // SSR Head tags const headResult = await renderSSRHead(head); await stream.write(headResult.headTags.replace(/\n/g, "")); // Fonts & Favicon await stream.write(''); await stream.write(``); await stream.write(``); // Bootstrap scripts await stream.write(buildBootstrapScript()); // Body start await stream.write(``); // App content await stream.pipe(appStream); // Cleanup context delete ctx.teleports; delete ctx.__teleportBuffers; delete ctx.modules; // Inject state Object.assign(ctx, { $p: pinia.state.value, $colada: serializeQueryCache(queryCache), $locale: lang, }); // App data script const appDataScript = ``; await stream.write(appDataScript); // Close HTML await stream.write(""); }); }); }