docs: add static website and docs

This commit is contained in:
Federico Jaramillo Martinez
2026-05-15 23:35:48 +02:00
parent aab9ffb8e2
commit c66d834c88
11 changed files with 1421 additions and 1 deletions
+83
View File
@@ -1,10 +1,93 @@
import { createReadStream } from "node:fs";
import { stat } from "node:fs/promises";
import type { IncomingMessage, ServerResponse } from "node:http";
import { extname, join, resolve, sep } from "node:path";
import type { Plugin } from "vite";
import { defineConfig } from "vite";
import { effectivePiWebConfig } from "./src/config";
const { config } = effectivePiWebConfig();
const apiPort = config.port ?? 8504;
const docsRoot = resolve("docs");
const docsPrefix = "/site";
const contentTypes: Record<string, string> = {
".css": "text/css; charset=utf-8",
".gif": "image/gif",
".html": "text/html; charset=utf-8",
".js": "text/javascript; charset=utf-8",
".md": "text/markdown; charset=utf-8",
".png": "image/png",
".svg": "image/svg+xml",
".webm": "video/webm",
};
type MiddlewareNext = (error?: unknown) => void;
async function serveDevDocs(request: IncomingMessage, response: ServerResponse, next: MiddlewareNext): Promise<void> {
const requestUrl = request.url;
if (requestUrl === undefined) {
next();
return;
}
const url = new URL(requestUrl, "http://localhost");
if (url.pathname === docsPrefix) {
response.statusCode = 302;
response.setHeader("Location", `${docsPrefix}/`);
response.end();
return;
}
if (!url.pathname.startsWith(`${docsPrefix}/`)) {
next();
return;
}
const relativePath = decodeURIComponent(url.pathname.slice(docsPrefix.length + 1)) || "index.html";
const requestedPath = relativePath.endsWith("/") ? join(relativePath, "index.html") : relativePath;
const filePath = resolve(docsRoot, requestedPath);
if (filePath !== docsRoot && !filePath.startsWith(`${docsRoot}${sep}`)) {
response.statusCode = 403;
response.end("Forbidden");
return;
}
try {
const fileStat = await stat(filePath);
if (!fileStat.isFile()) {
response.statusCode = 404;
response.end("Not found");
return;
}
response.statusCode = 200;
response.setHeader("Content-Type", contentTypes[extname(filePath)] ?? "application/octet-stream");
response.setHeader("Cache-Control", "no-store");
createReadStream(filePath).pipe(response);
} catch (error) {
const code = error instanceof Error && "code" in error ? error.code : undefined;
if (code === "ENOENT") {
response.statusCode = 404;
response.end("Not found");
return;
}
next(error);
}
}
function devDocsPlugin(): Plugin {
return {
name: "pi-web-dev-docs",
apply: "serve",
configureServer(server) {
server.middlewares.use((request, response, next) => {
void serveDevDocs(request, response, next);
});
},
};
}
export default defineConfig({
plugins: [devDocsPlugin()],
root: "src/client",
build: {
outDir: "../../dist/client",