diff --git a/quc/src/worker.js b/quc/src/worker.js index c61a1fd..3112a45 100644 --- a/quc/src/worker.js +++ b/quc/src/worker.js @@ -1,6 +1,6 @@ // quc: app shell + API in one Worker (no build step; the same module runs on Cloudflare and under dev.mjs). -// GET / the shell GET /chair.svg the chair-in-the-corner motif -// GET /api/health {ok, rev} anything else 404 +// GET / the shell (start form) GET /run/:id the shell (chair view) GET /chair.svg the chair-in-the-corner motif +// GET /api/health {ok, rev} anything else 404 // Fonts: system stacks on purpose (no webfont files, no third-party requests). shortcut: swap in self-hosted fonts when the brand picks them. export const CHAIR = ` @@ -8,13 +8,24 @@ export const CHAIR = ` `; +// Inlined into the page via toString(), so the browser and the tests run the same code. Returns {repo?, task?} errors; {} is valid. +export function validate(repo, task) { + const e = {}; + if (!/^https:\/\/github\.com\/[\w.-]+\/[\w.-]+?(\.git)?\/?$/.test(repo)) e.repo = "Use a public GitHub repo URL, like https://github.com/owner/name."; + if (task.length < 10) e.task = "Say a bit more: at least 10 characters."; + else if (task.length > 200) e.task = "Keep it to one line: 200 characters at most."; + return e; +} + +const NOTICE = "Replays are public. Anyone with the link to a run can watch it, so don't point this at anything you wouldn't show a stranger."; + export const PAGE = ` quc - +
quc
-

Coming together.

The app shell is up. Nothing to do here yet.

checking…

- +
+
+

Leave it with the chair.

+

Point quc at a public GitHub repo, say in one line what you want done, and go do something else. It works in the corner, quietly, and you can watch the replay.

+
+
+ +
+
+ +
+

${NOTICE}

+ +
+
+ +
+ `; const headers = (type, extra = {}) => ({ "content-type": type, ...extra }); @@ -46,7 +108,7 @@ export default { if (req.method !== "GET" && req.method !== "HEAD") return new Response("method not allowed", { status: 405 }); if (pathname === "/api/health") return Response.json({ ok: true, rev: env.REV || "" }, { headers: { "cache-control": "no-store" } }); if (pathname === "/chair.svg") return new Response(CHAIR, { headers: headers("image/svg+xml", { "cache-control": "public, max-age=3600" }) }); - if (pathname === "/" || pathname === "/index.html") return new Response(PAGE, { headers: headers("text/html; charset=utf-8") }); + if (pathname === "/" || pathname === "/index.html" || /^\/run\/[\w-]+$/.test(pathname)) return new Response(PAGE, { headers: headers("text/html; charset=utf-8") }); return new Response("not found", { status: 404 }); }, };