Compare commits
	
		
			No commits in common. "main" and "debug/local-file-paths" have entirely different histories.
		
	
	
		
			main
			...
			debug/loca
		
	
		
							
								
								
									
										48
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								README.md
									
									
									
									
									
								
							@ -1,48 +0,0 @@
 | 
			
		||||
# ESBuild Typescript Bunder
 | 
			
		||||
 | 
			
		||||
## Supports import maps and runs on Deno Deploy
 | 
			
		||||
Uses the WASM version of ESBuild for use on Deno Deploy and adds some plugins to allow for import maps. ***Unfortunately, `npm:*` and `jsr:*` specifiers are not supported currently***.
 | 
			
		||||
 | 
			
		||||
### Manual Bundle API
 | 
			
		||||
```typescript
 | 
			
		||||
import Bundle from "./mod.ts";
 | 
			
		||||
Bundle(
 | 
			
		||||
    // directory to work from
 | 
			
		||||
    "./some_folder",
 | 
			
		||||
 | 
			
		||||
    // ESBuild configuration (entry points are relative to "directory"):
 | 
			
		||||
    {entry:["./app.tsx"]},
 | 
			
		||||
 | 
			
		||||
    // import map (if omitted, will scan for a deno configuration within "directory" and use that)
 | 
			
		||||
    {"imports": {
 | 
			
		||||
        "react": "https://esm.sh/preact@10.22.0/compat",
 | 
			
		||||
        "react/": "https://esm.sh/preact@10.22.0/compat/"
 | 
			
		||||
    }}
 | 
			
		||||
);
 | 
			
		||||
if(outputFiles){
 | 
			
		||||
    for(const item of outputFiles){
 | 
			
		||||
        // do something with the output...
 | 
			
		||||
        console.log(item.text);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Static bundle server
 | 
			
		||||
 | 
			
		||||
#### API
 | 
			
		||||
```typescript
 | 
			
		||||
import Serve from "./serve.tsx";
 | 
			
		||||
Serve({path:"./some_folder", html:"index.html", port:8080});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### CLI
 | 
			
		||||
```
 | 
			
		||||
deno run -A <hosted-location>/serve.tsx --path=./some_folder --html=index.html --port=8080
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Accepts three optional settings:
 | 
			
		||||
- `path` A directory to serve content from. Defaults to the current working directory.
 | 
			
		||||
- `html` A path to an html file or actual html string to *always use* when the server would serve up a non-file route. If `html` is a path, it is assumed to be relative to `path`. If not specified, routes that don't match files will 404.
 | 
			
		||||
- `port` Port number (default is 8000).
 | 
			
		||||
 | 
			
		||||
When requests to typescript files are made to the server, it will treat that file as an entrypoint and return the corresponding plain javascript bundle.
 | 
			
		||||
							
								
								
									
										15
									
								
								deno.json
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								deno.json
									
									
									
									
									
								
							@ -2,8 +2,19 @@
 | 
			
		||||
    "name": "@ttf/wasm-bundle",
 | 
			
		||||
    "version": "0.1.0",
 | 
			
		||||
    "exports": "./mod.ts",
 | 
			
		||||
    "imports": {
 | 
			
		||||
        "react": "https://esm.sh/preact@10.22.0/compat",
 | 
			
		||||
        "react/": "https://esm.sh/preact@10.22.0/compat/",
 | 
			
		||||
        "other": "./other.tsx",
 | 
			
		||||
        "entry": "./app.tsx",
 | 
			
		||||
        "config": "./deno.json"
 | 
			
		||||
    },
 | 
			
		||||
    "tasks": {
 | 
			
		||||
        "serve": "deno run -A --no-lock serve.tsx --path=./test --html=index.html",
 | 
			
		||||
        "jsapi": "deno run -A --no-lock jsapi.tsx"
 | 
			
		||||
        "go": "deno run -A bundler-inc.tsx",
 | 
			
		||||
        "serve": "deno run -A serve.tsx"
 | 
			
		||||
    },
 | 
			
		||||
    "compilerOptions": {
 | 
			
		||||
        "jsx": "react-jsx",
 | 
			
		||||
        "jsxImportSource": "react"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								deno.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								deno.lock
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
{
 | 
			
		||||
  "version": "3",
 | 
			
		||||
  "remote": {
 | 
			
		||||
    "https://deno.land/x/esbuild@v0.19.2/wasm.js": "5ffeb3d973e57351eb4d2d03ffafc8ce5672e946d0f0a786c4aed2ca29cec004",
 | 
			
		||||
    "https://deno.land/x/jsonct@v0.1.0/mod.ts": "dba7e7f3529be6369f5c718e3a18b69f15ffa176006d2a7565073ce6c5bd9f3f",
 | 
			
		||||
    "https://deno.land/x/jsonct@v0.1.0/src/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462",
 | 
			
		||||
    "https://deno.land/x/jsonct@v0.1.0/src/parse.ts": "a3a016822446b0584b40bae9098df480db5590a9915c9e3c623ba2801cf1b8df",
 | 
			
		||||
    "https://esm.sh/esbuild-plugin-importmaps@1.0.0": "ab9e79660ff4d57d2ed7ef5e8516fbe0e79305267f22e1e7270d0a17ae0c2029",
 | 
			
		||||
    "https://esm.sh/preact@10.22.0/compat/jsx-runtime": "a2f6ddc2ce374813df1c13826a9ad010e90b5a70a989f1069a367ef60dd52eb0",
 | 
			
		||||
    "https://esm.sh/stable/preact@10.22.0/denonext/compat.js": "7c0b206984707cfef58efae492ea8d5212b8f620dd8c83294a5c832fb422c766",
 | 
			
		||||
    "https://esm.sh/stable/preact@10.22.0/denonext/compat/jsx-runtime.js": "fecfa3df69d580507801575175087de9a2a9fc23bb4900004a1f4cbd5b362634",
 | 
			
		||||
    "https://esm.sh/stable/preact@10.22.0/denonext/hooks.js": "09230113132c216bbc3847aaad11289771e088be1b0eb9e49cbc724faaeac205",
 | 
			
		||||
    "https://esm.sh/stable/preact@10.22.0/denonext/jsx-runtime.js": "de60943799b1cbe6066c4f83f4ca71ef37011d7f5be7bef58ed980e8ff3f996a",
 | 
			
		||||
    "https://esm.sh/stable/preact@10.22.0/denonext/preact.mjs": "20c9563e051dd66e053d3afb450f61b48f2fa0d0ce4f69f8f0a2f23c1ef090da",
 | 
			
		||||
    "https://esm.sh/v135/@jspm/import-map@1.0.8/denonext/import-map.mjs": "fc291e729df6bef849df47df8893b64749785ca65fd5fe1d0e7969db5d3b63ea",
 | 
			
		||||
    "https://esm.sh/v135/esbuild-plugin-importmaps@1.0.0/denonext/esbuild-plugin-importmaps.mjs": "08b603d074dd2861345f7d224c255c46d7f7213a283026552c492f465fe595ce"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -2,21 +2,16 @@ import { parse as JSONC } from "https://deno.land/x/jsonct@v0.1.0/mod.ts";
 | 
			
		||||
 | 
			
		||||
type JsonLike = { [key: string]: string | string[] | JsonLike; };
 | 
			
		||||
 | 
			
		||||
/** A `file://` url version of Deno.cwd() (contains trailing slash) */
 | 
			
		||||
export const Root:string = new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString() + "/";
 | 
			
		||||
export default async function HuntConfig(directory=Root):Promise<{
 | 
			
		||||
    imports: JsonLike;
 | 
			
		||||
    compilerOptions: JsonLike;
 | 
			
		||||
}>
 | 
			
		||||
/** A `file://` url version of Deno.cwd() */
 | 
			
		||||
export const Root = new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString() + "/";
 | 
			
		||||
export default async function HuntConfig()
 | 
			
		||||
{
 | 
			
		||||
    let path:string, json:JsonLike|undefined;
 | 
			
		||||
    console.log("searchig in directory", directory)
 | 
			
		||||
 | 
			
		||||
    const loadJSON =async(inPath:string)=>{
 | 
			
		||||
        try{
 | 
			
		||||
            const path = new URL(inPath, directory);
 | 
			
		||||
            console.log("looking at", path.href);
 | 
			
		||||
            const resp = await fetch(path);
 | 
			
		||||
            if(inPath.endsWith("./.jsonc"))
 | 
			
		||||
            const resp = await fetch(Root + inPath);
 | 
			
		||||
            if(inPath.endsWith(".jsonc"))
 | 
			
		||||
            {
 | 
			
		||||
                const text = await resp.text();
 | 
			
		||||
                json = JSONC(text) as JsonLike;
 | 
			
		||||
@ -35,20 +30,20 @@ export default async function HuntConfig(directory=Root):Promise<{
 | 
			
		||||
 | 
			
		||||
    try// look for `deno.json`
 | 
			
		||||
    {
 | 
			
		||||
        json = await loadJSON("./deno.json");
 | 
			
		||||
        json = await loadJSON("deno.json");
 | 
			
		||||
    }
 | 
			
		||||
    catch(_e)
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
        try // look for `deno.jsonc`
 | 
			
		||||
        {
 | 
			
		||||
            json = await loadJSON("./deno.jsonc");
 | 
			
		||||
            json = await loadJSON("deno.jsonc");
 | 
			
		||||
        }
 | 
			
		||||
        catch(_e)
 | 
			
		||||
        {
 | 
			
		||||
            try // look in the vscode plugin settings
 | 
			
		||||
            {
 | 
			
		||||
                json = await loadJSON("./.vscode/settings.json")
 | 
			
		||||
                json = await loadJSON(".vscode/settings.json")
 | 
			
		||||
                path = json ? json["deno.config"] as string : "";
 | 
			
		||||
                json = undefined;
 | 
			
		||||
                if(path)
 | 
			
		||||
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
import * as Test from "https://deno.land/std@0.224.0/assert/mod.ts";
 | 
			
		||||
import Bundle, {ESBuild} from "./mod.ts";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const path = await import.meta.resolve("./test/");
 | 
			
		||||
const {outputFiles} = await Bundle(path, {entryPoints:["./app.tsx"]});
 | 
			
		||||
 | 
			
		||||
Deno.test("check", ()=>{
 | 
			
		||||
    Test.assert(outputFiles?.length == 1);
 | 
			
		||||
    Test.assert(outputFiles[0].text.length > 1000);
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										26
									
								
								mod.ts
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								mod.ts
									
									
									
									
									
								
							@ -1,14 +1,14 @@
 | 
			
		||||
import * as ESBuild from "https://deno.land/x/esbuild@v0.19.2/wasm.js";
 | 
			
		||||
import * as Mapper from "https://esm.sh/esbuild-plugin-importmaps@1.0.0"; // https://github.com/andstellar/esbuild-plugin-importmaps
 | 
			
		||||
import Introspect from "./introspect.ts";
 | 
			
		||||
import Introspect, {Root} from "./introspect.ts";
 | 
			
		||||
 | 
			
		||||
const prefix = "/_dot_importer_/";
 | 
			
		||||
const resolvePlugin =(fullPathDir:string):ESBuild.Plugin=>({
 | 
			
		||||
const resolvePlugin:ESBuild.Plugin = {
 | 
			
		||||
  name: "resolve-plugin",
 | 
			
		||||
  setup(build) {
 | 
			
		||||
    build.onResolve({ filter: /^(\.\/|\.\.\/).*/ }, (args)=>
 | 
			
		||||
    {
 | 
			
		||||
      let resolveRoot = args.importer||fullPathDir;
 | 
			
		||||
      let resolveRoot = args.importer||Root;
 | 
			
		||||
      if(resolveRoot.startsWith(prefix))
 | 
			
		||||
      {
 | 
			
		||||
        resolveRoot = resolveRoot.substring(prefix.length);
 | 
			
		||||
@ -21,31 +21,23 @@ const resolvePlugin =(fullPathDir:string):ESBuild.Plugin=>({
 | 
			
		||||
    });
 | 
			
		||||
    build.onLoad({ filter: /.*/, namespace:"http" }, async(args)=> {
 | 
			
		||||
      const fetchPath = args.path.substring(prefix.length);
 | 
			
		||||
      console.log("fetch path", fetchPath);
 | 
			
		||||
      const result = await fetch(fetchPath);
 | 
			
		||||
      const contents = await result.text();
 | 
			
		||||
      return { contents, loader: `tsx` };
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
await ESBuild.initialize({ worker: false });
 | 
			
		||||
export type ImportMap = Parameters<typeof Mapper.importmapPlugin>[0];
 | 
			
		||||
export type BuildOptions = ESBuild.BuildOptions;
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @param directory Full file:// or http(s):// path to the directory containing assets you want to build (needed to resolve relative imports)
 | 
			
		||||
 * @param buildOptions ESBuild "build" options (will be merged with "reasonable defaults") for docs: https://esbuild.github.io/api/#general-options
 | 
			
		||||
 * @param importMap An object to act as the import map ({imports:Record<string, string>}). If this is left blank, a configuration will be scanned for in the "directory"
 | 
			
		||||
 * @returns build result
 | 
			
		||||
 */
 | 
			
		||||
export default async function(directory:string, buildOptions={} as BuildOptions, importMap?:ImportMap):Promise<ESBuild.BuildResult<ESBuild.BuildOptions>>
 | 
			
		||||
export default async function(buildOptions={} as BuildOptions, importMap:ImportMap|false = false):Promise<ESBuild.BuildResult<ESBuild.BuildOptions>>
 | 
			
		||||
{
 | 
			
		||||
  if(!importMap)
 | 
			
		||||
  if(importMap === false)
 | 
			
		||||
  {
 | 
			
		||||
    importMap = await Introspect(directory) as ImportMap
 | 
			
		||||
    importMap = await Introspect() as ImportMap;
 | 
			
		||||
  }
 | 
			
		||||
  console.log("using import map", importMap);
 | 
			
		||||
 | 
			
		||||
  const configuration:ESBuild.BuildOptions = {
 | 
			
		||||
    entryPoints: ["entry"],
 | 
			
		||||
    bundle: true,
 | 
			
		||||
@ -55,7 +47,7 @@ export default async function(directory:string, buildOptions={} as BuildOptions,
 | 
			
		||||
    jsxImportSource: "react",
 | 
			
		||||
    ...buildOptions,
 | 
			
		||||
    plugins: [
 | 
			
		||||
      resolvePlugin(directory),
 | 
			
		||||
      resolvePlugin,
 | 
			
		||||
      Mapper.importmapPlugin(importMap) as ESBuild.Plugin,
 | 
			
		||||
      ...buildOptions.plugins||[]
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										173
									
								
								serve.tsx
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								serve.tsx
									
									
									
									
									
								
							@ -1,39 +1,19 @@
 | 
			
		||||
import bundler from "./mod.ts";
 | 
			
		||||
import mime from "https://esm.sh/mime@4.0.3";
 | 
			
		||||
import { parseArgs } from "jsr:@std/cli/parse-args";
 | 
			
		||||
import bundler, {type ESBuild, type ImportMap} from "./mod.ts";
 | 
			
		||||
import Introspect from "./introspect.ts";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if(Deno.mainModule == import.meta.url)
 | 
			
		||||
{
 | 
			
		||||
    serve(parseArgs(Deno.args) as ServeArgs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type ServeArgs = {path?:string, html?:string, port?:string|number};
 | 
			
		||||
async function serve(settings:ServeArgs):Promise<void>
 | 
			
		||||
type ServeArgs = {path?:string, html?:string, port?:string|number};
 | 
			
		||||
function serve(settings:ServeArgs):void
 | 
			
		||||
{
 | 
			
		||||
    // etag hash
 | 
			
		||||
    const ETag = new Date().getTime().toString();
 | 
			
		||||
 | 
			
		||||
    // extra parsing
 | 
			
		||||
    const ExtensionsJS = ["tsx", "ts", "jsx", "js", "jsx", "mjs"];
 | 
			
		||||
    const PathExtensionType=(inPath:string)=>
 | 
			
		||||
    {
 | 
			
		||||
        const path = inPath.endsWith("/") ? inPath.substring(0, inPath.length-1) : inPath;
 | 
			
		||||
        const posDot = path.lastIndexOf(".");
 | 
			
		||||
        const extension = (posDot > path.lastIndexOf("/")) ? path.substring(posDot+1) : null;
 | 
			
		||||
        let type:string|null = null
 | 
			
		||||
        if(extension)
 | 
			
		||||
        {
 | 
			
		||||
            type = (ExtensionsJS.includes(extension)) ? "application/javascript" : mime.getType(extension);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {path, extension, type};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // base path
 | 
			
		||||
    let basePath = "";
 | 
			
		||||
    let DenoConfig:ImportMap
 | 
			
		||||
    const SetDirectory =async(inPath:string)=>{
 | 
			
		||||
    const SetDirectory =(inPath:string)=>{
 | 
			
		||||
        if(inPath.startsWith("http://")||inPath.startsWith("https://")||inPath.startsWith("file://"))
 | 
			
		||||
        {
 | 
			
		||||
            basePath = inPath;
 | 
			
		||||
@ -47,105 +27,108 @@ async function serve(settings:ServeArgs):Promise<void>
 | 
			
		||||
            basePath = basePath + "/";
 | 
			
		||||
        }
 | 
			
		||||
        console.log("Base Path:", basePath);
 | 
			
		||||
 | 
			
		||||
        DenoConfig = await Introspect(basePath) as ImportMap;
 | 
			
		||||
        console.log("found config", DenoConfig);
 | 
			
		||||
    }
 | 
			
		||||
    await SetDirectory(settings.path||"./");
 | 
			
		||||
 | 
			
		||||
    // bundler
 | 
			
		||||
    SetDirectory(settings.path||"./");
 | 
			
		||||
 | 
			
		||||
    const transpiled:Map<string, string> = new Map();
 | 
			
		||||
    const defaultConfig:ESBuild.BuildOptions = { entryPoints:[] as string[], outdir:"/", entryNames: `[dir][name]`, splitting: true };
 | 
			
		||||
    const bundle =async(pathName:string, pathBase:string, buildConfig:ESBuild.BuildOptions = {}):Promise<string|void>=>
 | 
			
		||||
    const ServeJSCode =(inText:string)=> new Response(inText, {headers:{"content-type":"application/javascript"}});
 | 
			
		||||
    const ServeStatic =async(inPath:string)=>
 | 
			
		||||
    {
 | 
			
		||||
        const lookupKey = pathName.substring(0, pathName.lastIndexOf("."))+".js";
 | 
			
		||||
        const lookup = transpiled.get(lookupKey);
 | 
			
		||||
        if(lookup)
 | 
			
		||||
        {
 | 
			
		||||
            return lookup;
 | 
			
		||||
        }
 | 
			
		||||
        buildConfig = {...defaultConfig, ...buildConfig}
 | 
			
		||||
        buildConfig.entryPoints = [pathBase+pathName];
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            const results = await bundler(basePath, buildConfig, DenoConfig);
 | 
			
		||||
            if(results.outputFiles)
 | 
			
		||||
            {
 | 
			
		||||
                results.outputFiles.forEach(output=>{transpiled.set(output.path, output.text); console.log("building", output.path);})
 | 
			
		||||
                return results.outputFiles[0].text;
 | 
			
		||||
            }            
 | 
			
		||||
            const handle = await fetch(basePath+inPath.substring(1));
 | 
			
		||||
            return new Response(handle.body, {headers:{"content-type": mime.getType(inPath)??""}})        
 | 
			
		||||
        }
 | 
			
		||||
        catch(_e)
 | 
			
		||||
        {
 | 
			
		||||
            return resp404;
 | 
			
		||||
        }
 | 
			
		||||
        catch(_e){return;}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // index html serving
 | 
			
		||||
    
 | 
			
		||||
    const resp404 = new Response("404", {status:404});
 | 
			
		||||
    const resp304 = new Response(null, {status:304});
 | 
			
		||||
    let respIndexBody:false|string = false;
 | 
			
		||||
    let respIndex:false|Response|Promise<Response> = false;
 | 
			
		||||
    if(settings.html)
 | 
			
		||||
    {
 | 
			
		||||
        if(settings.html.indexOf("<") != -1) // if html is actual markup instead of a url
 | 
			
		||||
        if(settings.html.indexOf("<") != -1)
 | 
			
		||||
        {
 | 
			
		||||
            respIndexBody = settings.html;
 | 
			
		||||
            respIndex= new Response(settings.html, {headers:{"content-type":"text-html"}});
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const load = await fetch(basePath+settings.html);
 | 
			
		||||
            respIndexBody = await load.text();
 | 
			
		||||
            respIndex = ServeStatic(settings.html);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ///// go
 | 
			
		||||
    Deno.serve({port:parseInt(settings.port as string)||8000}, async(req)=>
 | 
			
		||||
    {
 | 
			
		||||
        const checkHash = req.headers.get("if-none-match")
 | 
			
		||||
        if(checkHash === ETag){
 | 
			
		||||
            return resp304;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    Deno.serve({port:parseInt(settings.port as string)||8000}, async(req)=>{
 | 
			
		||||
        const url = new URL(req.url);
 | 
			
		||||
        const {path, type} = PathExtensionType(url.pathname);
 | 
			
		||||
        const headers = {"content-type":type||"", ETag, "Cache-Control":"max-age=3600"}
 | 
			
		||||
 | 
			
		||||
        // serve javascript
 | 
			
		||||
        if(type === "application/javascript")
 | 
			
		||||
        const index = url.pathname.lastIndexOf(".");
 | 
			
		||||
        if(index > -1)
 | 
			
		||||
        {
 | 
			
		||||
            const checkBuild = await bundle(path, basePath);
 | 
			
		||||
            if(checkBuild)
 | 
			
		||||
            const ext = url.pathname.substring(index+1);
 | 
			
		||||
            if(ext === "ts" || ext == "tsx" || ext == "js" || ext == "jsx")
 | 
			
		||||
            {
 | 
			
		||||
                return new Response(checkBuild, {headers});
 | 
			
		||||
            }            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // serve static
 | 
			
		||||
        if(type)
 | 
			
		||||
        {
 | 
			
		||||
            try{
 | 
			
		||||
                const handle = await fetch(basePath+path.substring(1));
 | 
			
		||||
                return new Response(handle.body, {headers});
 | 
			
		||||
                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
 | 
			
		||||
                    });
 | 
			
		||||
                    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;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch(_e){
 | 
			
		||||
                return resp404;
 | 
			
		||||
            }     
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return ServeStatic(url.pathname);
 | 
			
		||||
            }
 | 
			
		||||
    
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // serve routes/implied index html files
 | 
			
		||||
        if(respIndexBody)
 | 
			
		||||
        if(respIndex)
 | 
			
		||||
        {
 | 
			
		||||
            return new Response(respIndexBody, {headers});
 | 
			
		||||
            return respIndex;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            try{
 | 
			
		||||
                const handle = await fetch(basePath+path.substring(1));
 | 
			
		||||
                headers["content-type"] = "text/html"
 | 
			
		||||
                return new Response(handle.body, {headers});
 | 
			
		||||
            }
 | 
			
		||||
            catch(_e){
 | 
			
		||||
                return resp404;
 | 
			
		||||
            let indexLookup = url.pathname;
 | 
			
		||||
            if(!indexLookup.endsWith("/"))
 | 
			
		||||
            {
 | 
			
		||||
                indexLookup = indexLookup+"/";
 | 
			
		||||
            }
 | 
			
		||||
            return ServeStatic(indexLookup+"index.html");            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
    "imports": {
 | 
			
		||||
        "react":  "https://esm.sh/preact@10.22.0/compat",
 | 
			
		||||
        "react/": "https://esm.sh/preact@10.22.0/compat/"
 | 
			
		||||
    },
 | 
			
		||||
    "compilerOptions": {
 | 
			
		||||
        "jsx": "react-jsx",
 | 
			
		||||
        "jsxImportSource": "react"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,2 +0,0 @@
 | 
			
		||||
const message:string = "leaf default export!"
 | 
			
		||||
export default ()=>console.log(message);
 | 
			
		||||
		Reference in New Issue
	
	Block a user