esbuild-wasm-bundler/serve.tsx

134 lines
3.9 KiB
TypeScript

import bundler from "./mod.ts";
import mime from "https://esm.sh/mime@4.0.3";
import { parseArgs } from "jsr:@std/cli/parse-args";
if(Deno.mainModule == import.meta.url)
{
serve(parseArgs(Deno.args) as ServeArgs);
}
type ServeArgs = {path?:string, html?:string, port?:string|number};
function serve(settings:ServeArgs):void
{
let basePath = "";
const SetDirectory =(inPath:string)=>{
if(inPath.startsWith("http://")||inPath.startsWith("https://")||inPath.startsWith("file://"))
{
basePath = inPath;
}
else
{
basePath = new URL(inPath, new URL(`file://${Deno.cwd().replaceAll("\\", "/")}/`).toString()).href;
}
if(!basePath.endsWith("/"))
{
basePath = basePath + "/";
}
console.log("Base Path:", basePath);
}
SetDirectory(settings.path||"./");
const transpiled:Map<string, string> = new Map();
const ServeJSCode =(inText:string)=> new Response(inText, {headers:{"content-type":"application/javascript"}});
const ServeStatic =async(inPath:string)=>
{
try
{
const handle = await fetch(basePath+inPath.substring(1));
return new Response(handle.body, {headers:{"content-type": mime.getType(inPath)??""}})
}
catch(_e)
{
console.log("404", inPath);
return resp404;
}
};
const resp404 = new Response("404", {status:404});
let respIndex:false|Response|Promise<Response> = false;
if(settings.html)
{
if(settings.html.indexOf("<") != -1)
{
respIndex= new Response(settings.html, {headers:{"content-type":"text-html"}});
}
else
{
respIndex = ServeStatic(settings.html);
}
}
Deno.serve({port:parseInt(settings.port as string)||8000}, async(req)=>{
const url = new URL(req.url);
const index = url.pathname.lastIndexOf(".");
if(index > -1)
{
const ext = url.pathname.substring(index+1);
if(ext === "ts" || ext == "tsx" || ext == "js" || ext == "jsx")
{
if(ext == "js")
{
const lookup = transpiled.get(url.pathname);
if(lookup)
{
return ServeJSCode(lookup);
}
}
else
{
const lookup = transpiled.get(url.pathname.substring(0, index)+".js");
if(lookup)
{
return ServeJSCode(lookup);
}
}
try
{
const results = await bundler({
entryPoints:[basePath+url.pathname],
outdir:"/",
entryNames: `[dir][name]`,
splitting: true
}, basePath);
if(results.outputFiles)
{
results.outputFiles.forEach(output=>transpiled.set(output.path, output.text))
return ServeJSCode(results.outputFiles[0].text);
}
else
{
throw(new Error("no output"));
}
}
catch(_e)
{
return resp404;
}
}
else
{
return ServeStatic(url.pathname);
}
}
if(respIndex)
{
return respIndex;
}
else
{
let indexLookup = url.pathname;
if(!indexLookup.endsWith("/"))
{
indexLookup = indexLookup+"/";
}
return ServeStatic(indexLookup+"index.html");
}
});
}
export default serve