1import{accepts}from"jsr:@std/http@1.0.12/negotiation" 2import{escape}from"jsr:@std/html@1.0.3" 3import{decodeBase64}from"jsr:@std/encoding@1.0.8/base64" 4 5functioncleanStack(str?: string){ 6if(!str)returnundefined; 7returnstr 8.split("\n") 9.filter( 10(line)=> 11!line.includes(import.meta.url)&& 12!line.includes("deno_http/00_serve.ts")&& 13!line.includes("core/01_core.js") 14) 15.join("\n"); 16} 17 18functionserializeError(e: Error){ 19return{name: e.name,message: e.message,stack: cleanStack(e.stack)}; 20}; 21 22functionrespondWithError(request: Request,error: Error){ 23conste=serializeError(error); 24if(accepts(request,"text/html")){ 25returnnewResponse(/* html */`<!DOCTYPE html>
26 <html>
27 <head>
28 <title>Error</title>
29 <style>
30 * { box-sizing: border-box }
31 body {
32 margin: 0;
33 font-family: monospace;
34 min-height: 100vh;
35 display: flex;
36 flex-direction: column;
37 color: black;
38 background-color: white;
39 }
40 div {
41 padding: 0 16px;
42 width: 100%;
43 margin: auto;
44 max-width: 768px;
45 color: inherit;
46 border-left: 0.25em solid #3d444d;
47 border-color: #da3633;
48 }
49 h1 {
50 font-weight: 500;
51 color: #f85149;
52 }
53 pre {
54 margin: 0;
55 padding-bottom: 16px;
56 font-size: 12px;
57 line-height: 1.5;
58 overflow: auto;
59 white-space: pre-wrap;
60 width: 100%;
61 }
62 </style>
63 </head>
64 <body>
65 <div>
66 <h1>
67${escape(e.name)} 68 </h1>
69 <pre>${escape(e.stack??e.message)}</pre>
70 </div>
71 </body>
72 </html>`,{status: 500,headers:{'Content-Type':'text/html'}}); 73} 74 75returnResponse.json( 76{error: e}, 77{status: 500,headers:{'Content-Type':'application/json'}}, 78); 79} 80 81constpayload=JSON.parse(Deno.args[0]); 82 83if(!payload||!payload.command){ 84console.error("Invalid input."); 85Deno.exit(1); 86} 87 88if(payload.command==="fetch"){ 89Deno.serve( 90{ 91port: parseInt(payload.port), 92onListen:()=>{ 93// This line will signal that the server is ready to the go
94console.error("READY"); 95}, 96}, 97async(req)=>{ 98try{ 99constmod=awaitimport(payload.entrypoint);100if(!mod.default){101returnnewResponse("The app does not provide a default export.",{status: 500});102}103104if(typeofmod.default!=="object"){105returnnewResponse("The app default export must be an object.",{status: 500});106}107if(108!("fetch"inmod.default)||109typeofmod.default.fetch!=="function"110){111returnnewResponse("The app default export does not have a fetch method.",{status: 500});112}113114consthandler=mod.default.fetch;115// Websocket requests are stateful and should be handled differently
116if(req.headers.get("upgrade")==="websocket"){117constresp=awaithandler(req);118if(!(respinstanceofResponse)){119returnnewResponse("Fetch handler must return a Response object.",{status: 500});120}121122returnresp;123}124125consturl=newURL(req.url);126constproto=req.headers.get("x-forwarded-proto");127consthost=req.headers.get("x-forwarded-host");128constresp=awaithandler(newRequest(`${proto}://${host}${url.pathname}${url.search}`,{129method: req.method,130headers: req.headers,131body: req.body,132}));133if(!(respinstanceofResponse)){134thrownewError("Fetch handler must return a Response object.");135}136137returnresp;138}catch(e){139returnrespondWithError(req,easError);140}141},142);143}elseif(payload.command==="run"){144constmod=awaitimport(payload.entrypoint);145if(!mod.default||typeofmod.default!=="object"){146console.error(147"The mod does not provide an object as it's default export.",148);149Deno.exit(1);150}151152consthandler=mod.default;153if(!("run"inhandler)){154console.error("The mod default export does not have a run function.");155Deno.exit(1);156}157158if(!(typeofhandler.run==="function")){159console.error("The mod default export run property must be a function.");160Deno.exit(1);161}162163awaithandler.run(payload.args);164}elseif(payload.command==="email"){165constmod=awaitimport(payload.entrypoint);166if(!mod.default||typeofmod.default!=="object"){167console.error(168"The mod does not provide an object as it's default export.",169);170Deno.exit(1);171}172173consthandler=mod.default;174if(!("email"inhandler)){175console.error("The mod default export does not have a email function.");176Deno.exit(1);177}178179constdata=decodeBase64(payload.msg)180constblob=newBlob([data]);181awaithandler.email(blob.stream());182}else{183console.error("Unknown command: ",payload.command);184Deno.exit(1);185}