vợ bảo okeoke

This commit is contained in:
2026-01-04 19:35:55 +07:00
parent 2b0f88fa16
commit aa9df98926
6 changed files with 775 additions and 11 deletions

View File

@@ -3,15 +3,18 @@ import { createApp } from './main';
import { renderToWebStream } from 'vue/server-renderer';
import { streamText } from 'hono/streaming';
import { renderSSRHead } from '@unhead/vue/server';
import { buildBootstrapScript, getHrefFromManifest } from './lib/manifest';
import { buildBootstrapScript, getHrefFromManifest, loadCssByModules } from './lib/manifest';
import { contextStorage } from 'hono/context-storage';
import { cors } from "hono/cors";
import { jwtRpc, rpcServer } from './api/rpc';
import isMobile from 'is-mobile';
import { useAuthStore } from './stores/auth';
import { cssContent } from './lib/primeCssContent';
import { styleTags } from './lib/primePassthrough';
// @ts-ignore
import Base from '@primevue/core/base';
const app = new Hono()
const defaultNames = ['primitive', 'semantic', 'global', 'base', 'ripple-directive']
// app.use(renderer)
app.use('*', contextStorage());
app.use(cors(), async (c, next) => {
@@ -28,7 +31,7 @@ app.get("/.well-known/*", (c) => {
});
app.get("*", async (c) => {
const url = new URL(c.req.url);
const { app, router, head, pinia } = createApp();
const { app, router, head, pinia, bodyClass } = createApp();
app.provide("honoContext", c);
await router.push(url.pathname);
await router.isReady().then(() => {
@@ -36,24 +39,27 @@ app.get("*", async (c) => {
auth.initialized = false;
auth.init();
});
let usedStyles = new Set(defaultNames);
Base.setLoadedStyleName = async (name: string) => usedStyles.add(name)
return streamText(c, async (stream) => {
c.header("Content-Type", "text/html; charset=utf-8");
c.header("Content-Encoding", "Identity");
const ctx = {};
const ctx: Record<string, any> = {};
const appStream = renderToWebStream(app, ctx);
// console.log("ctx: ", );
await stream.write("<!DOCTYPE html><html lang='en'><head>");
await stream.write("<base href='" + url.origin + "'/>");
await renderSSRHead(head).then((headString) => stream.write(headString.headTags.replace(/\n/g, "")));
await stream.write(`<link href="https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"rel="stylesheet"></link>`);
await stream.write('<link rel="icon" href="/favicon.ico" />');
await stream.write(buildBootstrapScript());
await stream.write("</head><body class='font-sans bg-[#f9fafd] text-gray-800 antialiased flex flex-col min-h-screen'>");
await Promise.all(styleTags.filter(tag => usedStyles.has(tag.name.replace(/-(variables|style)$/, ""))).map(tag => stream.write(`<style type="text/css" data-primevue-style-id="${tag.name}">${tag.value}</style>`)));
await stream.write(`</head><body class='${bodyClass}'>`);
await stream.pipe(appStream);
await stream.write(`<script>window.__SSR_STATE__ = JSON.parse(${htmlEscape(JSON.stringify(JSON.stringify(ctx)))});</script>`);
await stream.write(`<script>window.__PINIA_STATE__ = JSON.parse(${htmlEscape(JSON.stringify(JSON.stringify(pinia.state.value)))});</script>`);
await stream.write("</body></html>");
});
// return c.body(renderToWebStream(app, {}));
})
const ESCAPE_LOOKUP: { [match: string]: string } = {
"&": "\\u0026",

View File

@@ -57,6 +57,18 @@ export const getHrefFromManifest = ({
return href;
}
};
export const loadCssByModules = (m: Array<string>) => {
let manifest: Manifest = import.meta.env.PROD
? loadManifest() ?? {} : {};
let cssFiles: string[] = [];
m.forEach((moduleName) => {
const assetInManifest = manifest[moduleName];
if (assetInManifest && assetInManifest.css) {
cssFiles = cssFiles.concat(assetInManifest.css);
}
});
return cssFiles;
}
export function buildBootstrapScript() {
let script = "";
let styles = "";

File diff suppressed because one or more lines are too long

742
src/lib/primePassthrough.ts Normal file

File diff suppressed because one or more lines are too long

View File

@@ -10,7 +10,7 @@ import Aura from '@primeuix/themes/aura';
import { createPinia } from "pinia";
import { useAuthStore } from './stores/auth';
const bodyClass = ":uno: font-sans bg-[#f9fafd] text-gray-800 antialiased flex flex-col min-h-screen"
export function createApp() {
const pinia = createPinia();
const app = createSSRApp(withErrorBoundary(RouterView));
@@ -23,8 +23,10 @@ export function createApp() {
preset: Aura,
options: {
darkModeSelector: '.my-app-dark',
cssLayer: false,
prefix: 'pv-',
// cssLayer: {
// name: 'primevue',
// order: 'theme, base, primevue'
// }
}
}
});
@@ -45,5 +47,5 @@ export function createApp() {
});
}
return { app, router, head, pinia };
return { app, router, head, pinia, bodyClass };
}

View File

@@ -55,6 +55,7 @@ export const useAuthStore = defineStore('auth', () => {
csrfToken.value = response.csrfToken;
router.push('/');
} catch (e: any) {
console.log(JSON.parse(e.message))
error.value = e.message || 'Login failed';
throw e;
} finally {