84 lines
3.7 KiB
TypeScript
84 lines
3.7 KiB
TypeScript
import { serveFile } from "jsr:@std/http/file-server";
|
|
import { createSSRApp } from "vue";
|
|
import { renderToString } from "vue/server-renderer";
|
|
import { createRouter, createMemoryHistory } from 'vue-router';
|
|
import Home from "@/home/App.tsx";
|
|
import GERoot, { routes as geRoutes } from "@/generative-energy/GERoot.tsx";
|
|
import transpileResponse from "./transpile.ts";
|
|
import { DOMParser } from 'jsr:@b-fuze/deno-dom'
|
|
|
|
const utf8Decoder = new TextDecoder("utf-8");
|
|
|
|
const parser = new DOMParser();
|
|
|
|
Deno.serve({
|
|
port: 8080,
|
|
hostname: "0.0.0.0",
|
|
onListen({ port, hostname }) {
|
|
console.log(`Listening on port http://${hostname}:${port}/`);
|
|
},
|
|
}, async (req, _conn) => {
|
|
if (req.method === "GET") {
|
|
const pathname = URL.parse(req.url)?.pathname ?? "/";
|
|
if (pathname.startsWith('/static/') ||
|
|
pathname.startsWith('/generative-energy/static/')) {
|
|
if (pathname.startsWith('/static/')) {
|
|
return serveFile(req, `public/home/${ pathname }`);
|
|
} else {
|
|
return serveFile(req, `public${pathname}`);
|
|
}
|
|
} else if (pathname === "/") {
|
|
const rendered = await renderToString(createSSRApp(Home));
|
|
const content = utf8Decoder.decode(await Deno.readFile("./public/home/index.html"))
|
|
.replace(`<!-- SSR OUTLET -->`, rendered)
|
|
.replace(`<!-- SSR HEAD OUTLET -->`, "");
|
|
return new Response(content, { headers: { "Content-Type": "text/html" } });
|
|
} else if (pathname.startsWith('/generative-energy')) {
|
|
const app = createSSRApp(GERoot);
|
|
const router = createRouter({
|
|
routes: geRoutes,
|
|
history: createMemoryHistory('/generative-energy'),
|
|
});
|
|
app.use(router);
|
|
app.provide('dom-parse', (innerHTML: string) => {
|
|
return parser.parseFromString(innerHTML, 'text/html').documentElement;
|
|
});
|
|
const ssrContext = { registry: {}};
|
|
await router.replace(pathname.split('/generative-energy')[1]);
|
|
await router.isReady();
|
|
const rendered = await renderToString(app, ssrContext);
|
|
const content = utf8Decoder.decode(await Deno.readFile("./public/generative-energy/index.html"))
|
|
.replace('%TITLE%', 'Generative Energy')
|
|
.replace('<!-- SSR HEAD OUTLET -->', `
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"vue": "/deps/vue/dist/vue.esm-browser.prod.js",
|
|
"vue-router": "/deps/vue-router/dist/vue-router.esm-browser.js",
|
|
"vue/jsx-runtime": "/deps/vue/jsx-runtime/index.mjs",
|
|
"@vue/devtools-api": "/deps/@vue/devtools-api/lib/esm/index.js",
|
|
"@/": "/app/"
|
|
}
|
|
}
|
|
</script>
|
|
<script> window.appstate = ${ JSON.stringify(ssrContext.registry) }; </script>
|
|
`)
|
|
.replace(`<!-- SSR OUTLET -->`, rendered);
|
|
return new Response(content, { headers: { "Content-Type": "text/html" } });
|
|
} else if (pathname.startsWith("/app") && (pathname.endsWith(".ts") || pathname.endsWith(".tsx"))) {
|
|
const response = await serveFile(req, "./" + pathname);
|
|
return await transpileResponse(response, req.url, pathname);
|
|
} else if (pathname.startsWith("/deps")) {
|
|
return serveFile(req, `node_modules/${pathname.split("/deps")[1]}`);
|
|
}
|
|
return new Response("Not found.", { status: 404 });
|
|
} else {
|
|
return new Response("Only GET allowed.", { status: 500 });
|
|
}
|
|
});
|
|
|
|
Deno.addSignalListener("SIGINT", () => {
|
|
console.info("Shutting down (received SIGINT)");
|
|
Deno.exit();
|
|
});
|