A vibe coded tangled fork which supports pijul.
at master 96 lines 2.7 kB view raw
1import { cardPayloadSchema } from "./validation"; 2import { renderCard } from "./lib/render"; 3import { RepositoryCard } from "./components/cards/repository"; 4import { IssueCard } from "./components/cards/issue"; 5import { PullRequestCard } from "./components/cards/pull-request"; 6import { z } from "zod"; 7 8declare global { 9 interface CacheStorage { 10 default: Cache; 11 } 12} 13 14interface Env { 15 ENVIRONMENT: string; 16} 17 18export default { 19 async fetch(request: Request, env: Env): Promise<Response> { 20 if (request.method !== "POST") { 21 return new Response("Method not allowed", { status: 405 }); 22 } 23 24 const url = new URL(request.url); 25 const cardType = url.pathname.split("/").pop(); 26 27 try { 28 const body = await request.json(); 29 const payload = cardPayloadSchema.parse(body); 30 31 let component; 32 switch (payload.type) { 33 case "repository": 34 component = <RepositoryCard {...payload} />; 35 break; 36 case "issue": 37 component = <IssueCard {...payload} />; 38 break; 39 case "pullRequest": 40 component = <PullRequestCard {...payload} />; 41 break; 42 default: 43 return new Response("Unknown card type", { status: 400 }); 44 } 45 46 const cacheKeyUrl = new URL(request.url); 47 cacheKeyUrl.searchParams.set("payload", JSON.stringify(payload)); 48 const cacheKey = new Request(cacheKeyUrl.toString(), { method: "GET" }); 49 const cache = caches.default; 50 const cached = await cache.match(cacheKey); 51 52 if (cached) { 53 return cached; 54 } 55 56 const { png: pngBuffer } = await renderCard(component); 57 58 const response = new Response(pngBuffer as any, { 59 headers: { 60 "Content-Type": "image/png", 61 "Cache-Control": "public, max-age=3600", 62 }, 63 }); 64 65 await cache.put(cacheKey, response.clone()); 66 67 return response; 68 } catch (error) { 69 if (error instanceof z.ZodError) { 70 return new Response( 71 JSON.stringify({ errors: (error as z.ZodError).issues }), 72 { 73 status: 400, 74 headers: { "Content-Type": "application/json" }, 75 }, 76 ); 77 } 78 79 console.error("Error generating card:", error); 80 const errorMessage = 81 error instanceof Error ? error.message : String(error); 82 const errorStack = error instanceof Error ? error.stack : ""; 83 console.error("Error stack:", errorStack); 84 return new Response( 85 JSON.stringify({ 86 error: errorMessage, 87 stack: errorStack, 88 }), 89 { 90 status: 500, 91 headers: { "Content-Type": "application/json" }, 92 }, 93 ); 94 } 95 }, 96};