scripts/serve.mjs
scripts/serve.mjsBrowse 22 files
576 tokens
2,063 bytes
Token encoding: o200k_base
Snapshot 24fd22b
← Back to SKILL.md
1#!/usr/bin/env node2/**3 * scrollcraft static server.4 *5 * A scrollcraft page cannot be verified from file://. The engine fetches each6 * clip as a Blob, and file:// fetches are blocked by CORS in every browser, so7 * the page silently falls back to posters and looks fine while proving nothing.8 * Serve it.9 *10 * node serve.mjs --root builds/perkform --port 450011 */12import http from "node:http";13import fs from "node:fs";14import path from "node:path";15 16const argv = process.argv.slice(2);17const arg = (n, d) => { const i = argv.indexOf(n); return i > -1 && argv[i + 1] ? argv[i + 1] : d; };18 19const ROOT = path.resolve(arg("--root", "."));20const PORT = parseInt(arg("--port", "4500"), 10);21 22const TYPES = {23 ".html": "text/html; charset=utf-8", ".css": "text/css; charset=utf-8",24 ".js": "text/javascript; charset=utf-8", ".json": "application/json",25 ".mp4": "video/mp4", ".webm": "video/webm",26 ".webp": "image/webp", ".png": "image/png", ".jpg": "image/jpeg",27 ".svg": "image/svg+xml", ".woff2": "font/woff2",28};29 30http.createServer((req, res) => {31 const url = decodeURIComponent(req.url.split("?")[0]);32 let file = path.join(ROOT, url === "/" ? "/index.html" : url);33 34 // Refuse to serve outside the root even if the path walks up.35 if (!file.startsWith(ROOT)) { res.writeHead(403).end("forbidden"); return; }36 if (fs.existsSync(file) && fs.statSync(file).isDirectory()) file = path.join(file, "index.html");37 if (!fs.existsSync(file)) { res.writeHead(404).end("not found"); return; }38 39 const ext = path.extname(file).toLowerCase();40 const stat = fs.statSync(file);41 res.writeHead(200, {42 "Content-Type": TYPES[ext] || "application/octet-stream",43 "Content-Length": stat.size,44 // No caching: verification loops re-shoot the same URLs after edits, and a45 // cached clip or stylesheet makes you screenshot the previous build.46 "Cache-Control": "no-store",47 "Accept-Ranges": "bytes",48 });49 fs.createReadStream(file).pipe(res);50}).listen(PORT, () => {51 console.log(`scrollcraft: ${ROOT}\n http://localhost:${PORT}`);52});53