Compare commits
4 Commits
debug/loca
...
main
Author | SHA1 | Date | |
---|---|---|---|
3aa0b3a7ff | |||
2f21977fca | |||
b5aece91e1 | |||
85631f2173 |
48
README.md
Normal file
48
README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# 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,19 +2,8 @@
|
|||||||
"name": "@ttf/wasm-bundle",
|
"name": "@ttf/wasm-bundle",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"exports": "./mod.ts",
|
"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": {
|
"tasks": {
|
||||||
"go": "deno run -A bundler-inc.tsx",
|
"serve": "deno run -A --no-lock serve.tsx --path=./test --html=index.html",
|
||||||
"serve": "deno run -A serve.tsx"
|
"jsapi": "deno run -A --no-lock jsapi.tsx"
|
||||||
},
|
|
||||||
"compilerOptions": {
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"jsxImportSource": "react"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
18
deno.lock
18
deno.lock
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"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,16 +2,21 @@ import { parse as JSONC } from "https://deno.land/x/jsonct@v0.1.0/mod.ts";
|
|||||||
|
|
||||||
type JsonLike = { [key: string]: string | string[] | JsonLike; };
|
type JsonLike = { [key: string]: string | string[] | JsonLike; };
|
||||||
|
|
||||||
/** A `file://` url version of Deno.cwd() */
|
/** A `file://` url version of Deno.cwd() (contains trailing slash) */
|
||||||
export const Root = new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString() + "/";
|
export const Root:string = new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString() + "/";
|
||||||
export default async function HuntConfig()
|
export default async function HuntConfig(directory=Root):Promise<{
|
||||||
|
imports: JsonLike;
|
||||||
|
compilerOptions: JsonLike;
|
||||||
|
}>
|
||||||
{
|
{
|
||||||
let path:string, json:JsonLike|undefined;
|
let path:string, json:JsonLike|undefined;
|
||||||
|
console.log("searchig in directory", directory)
|
||||||
const loadJSON =async(inPath:string)=>{
|
const loadJSON =async(inPath:string)=>{
|
||||||
try{
|
try{
|
||||||
const resp = await fetch(Root + inPath);
|
const path = new URL(inPath, directory);
|
||||||
if(inPath.endsWith(".jsonc"))
|
console.log("looking at", path.href);
|
||||||
|
const resp = await fetch(path);
|
||||||
|
if(inPath.endsWith("./.jsonc"))
|
||||||
{
|
{
|
||||||
const text = await resp.text();
|
const text = await resp.text();
|
||||||
json = JSONC(text) as JsonLike;
|
json = JSONC(text) as JsonLike;
|
||||||
@ -30,20 +35,20 @@ export default async function HuntConfig()
|
|||||||
|
|
||||||
try// look for `deno.json`
|
try// look for `deno.json`
|
||||||
{
|
{
|
||||||
json = await loadJSON("deno.json");
|
json = await loadJSON("./deno.json");
|
||||||
}
|
}
|
||||||
catch(_e)
|
catch(_e)
|
||||||
{
|
{
|
||||||
|
|
||||||
try // look for `deno.jsonc`
|
try // look for `deno.jsonc`
|
||||||
{
|
{
|
||||||
json = await loadJSON("deno.jsonc");
|
json = await loadJSON("./deno.jsonc");
|
||||||
}
|
}
|
||||||
catch(_e)
|
catch(_e)
|
||||||
{
|
{
|
||||||
try // look in the vscode plugin settings
|
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 : "";
|
path = json ? json["deno.config"] as string : "";
|
||||||
json = undefined;
|
json = undefined;
|
||||||
if(path)
|
if(path)
|
||||||
|
11
jsapi.test.tsx
Normal file
11
jsapi.test.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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 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 * as Mapper from "https://esm.sh/esbuild-plugin-importmaps@1.0.0"; // https://github.com/andstellar/esbuild-plugin-importmaps
|
||||||
import Introspect, {Root} from "./introspect.ts";
|
import Introspect from "./introspect.ts";
|
||||||
|
|
||||||
const prefix = "/_dot_importer_/";
|
const prefix = "/_dot_importer_/";
|
||||||
const resolvePlugin:ESBuild.Plugin = {
|
const resolvePlugin =(fullPathDir:string):ESBuild.Plugin=>({
|
||||||
name: "resolve-plugin",
|
name: "resolve-plugin",
|
||||||
setup(build) {
|
setup(build) {
|
||||||
build.onResolve({ filter: /^(\.\/|\.\.\/).*/ }, (args)=>
|
build.onResolve({ filter: /^(\.\/|\.\.\/).*/ }, (args)=>
|
||||||
{
|
{
|
||||||
let resolveRoot = args.importer||Root;
|
let resolveRoot = args.importer||fullPathDir;
|
||||||
if(resolveRoot.startsWith(prefix))
|
if(resolveRoot.startsWith(prefix))
|
||||||
{
|
{
|
||||||
resolveRoot = resolveRoot.substring(prefix.length);
|
resolveRoot = resolveRoot.substring(prefix.length);
|
||||||
@ -21,23 +21,31 @@ const resolvePlugin:ESBuild.Plugin = {
|
|||||||
});
|
});
|
||||||
build.onLoad({ filter: /.*/, namespace:"http" }, async(args)=> {
|
build.onLoad({ filter: /.*/, namespace:"http" }, async(args)=> {
|
||||||
const fetchPath = args.path.substring(prefix.length);
|
const fetchPath = args.path.substring(prefix.length);
|
||||||
|
console.log("fetch path", fetchPath);
|
||||||
const result = await fetch(fetchPath);
|
const result = await fetch(fetchPath);
|
||||||
const contents = await result.text();
|
const contents = await result.text();
|
||||||
return { contents, loader: `tsx` };
|
return { contents, loader: `tsx` };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
await ESBuild.initialize({ worker: false });
|
await ESBuild.initialize({ worker: false });
|
||||||
export type ImportMap = Parameters<typeof Mapper.importmapPlugin>[0];
|
export type ImportMap = Parameters<typeof Mapper.importmapPlugin>[0];
|
||||||
export type BuildOptions = ESBuild.BuildOptions;
|
export type BuildOptions = ESBuild.BuildOptions;
|
||||||
export default async function(buildOptions={} as BuildOptions, importMap:ImportMap|false = false):Promise<ESBuild.BuildResult<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>>
|
||||||
{
|
{
|
||||||
if(importMap === false)
|
if(!importMap)
|
||||||
{
|
{
|
||||||
importMap = await Introspect() as ImportMap;
|
importMap = await Introspect(directory) as ImportMap
|
||||||
}
|
}
|
||||||
|
console.log("using import map", importMap);
|
||||||
const configuration:ESBuild.BuildOptions = {
|
const configuration:ESBuild.BuildOptions = {
|
||||||
entryPoints: ["entry"],
|
entryPoints: ["entry"],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
@ -47,7 +55,7 @@ export default async function(buildOptions={} as BuildOptions, importMap:ImportM
|
|||||||
jsxImportSource: "react",
|
jsxImportSource: "react",
|
||||||
...buildOptions,
|
...buildOptions,
|
||||||
plugins: [
|
plugins: [
|
||||||
resolvePlugin,
|
resolvePlugin(directory),
|
||||||
Mapper.importmapPlugin(importMap) as ESBuild.Plugin,
|
Mapper.importmapPlugin(importMap) as ESBuild.Plugin,
|
||||||
...buildOptions.plugins||[]
|
...buildOptions.plugins||[]
|
||||||
]
|
]
|
||||||
|
177
serve.tsx
177
serve.tsx
@ -1,19 +1,39 @@
|
|||||||
import bundler from "./mod.ts";
|
|
||||||
import mime from "https://esm.sh/mime@4.0.3";
|
import mime from "https://esm.sh/mime@4.0.3";
|
||||||
import { parseArgs } from "jsr:@std/cli/parse-args";
|
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)
|
if(Deno.mainModule == import.meta.url)
|
||||||
{
|
{
|
||||||
serve(parseArgs(Deno.args) as ServeArgs);
|
serve(parseArgs(Deno.args) as ServeArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServeArgs = {path?:string, html?:string, port?:string|number};
|
export type ServeArgs = {path?:string, html?:string, port?:string|number};
|
||||||
function serve(settings:ServeArgs):void
|
async function serve(settings:ServeArgs):Promise<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 basePath = "";
|
||||||
const SetDirectory =(inPath:string)=>{
|
let DenoConfig:ImportMap
|
||||||
|
const SetDirectory =async(inPath:string)=>{
|
||||||
if(inPath.startsWith("http://")||inPath.startsWith("https://")||inPath.startsWith("file://"))
|
if(inPath.startsWith("http://")||inPath.startsWith("https://")||inPath.startsWith("file://"))
|
||||||
{
|
{
|
||||||
basePath = inPath;
|
basePath = inPath;
|
||||||
@ -27,106 +47,103 @@ function serve(settings:ServeArgs):void
|
|||||||
basePath = basePath + "/";
|
basePath = basePath + "/";
|
||||||
}
|
}
|
||||||
console.log("Base Path:", basePath);
|
console.log("Base Path:", basePath);
|
||||||
|
|
||||||
|
DenoConfig = await Introspect(basePath) as ImportMap;
|
||||||
|
console.log("found config", DenoConfig);
|
||||||
}
|
}
|
||||||
|
await SetDirectory(settings.path||"./");
|
||||||
|
|
||||||
SetDirectory(settings.path||"./");
|
// bundler
|
||||||
|
|
||||||
const transpiled:Map<string, string> = new Map();
|
const transpiled:Map<string, string> = new Map();
|
||||||
const ServeJSCode =(inText:string)=> new Response(inText, {headers:{"content-type":"application/javascript"}});
|
const defaultConfig:ESBuild.BuildOptions = { entryPoints:[] as string[], outdir:"/", entryNames: `[dir][name]`, splitting: true };
|
||||||
const ServeStatic =async(inPath:string)=>
|
const bundle =async(pathName:string, pathBase:string, buildConfig:ESBuild.BuildOptions = {}):Promise<string|void>=>
|
||||||
{
|
{
|
||||||
try
|
const lookupKey = pathName.substring(0, pathName.lastIndexOf("."))+".js";
|
||||||
{
|
const lookup = transpiled.get(lookupKey);
|
||||||
const handle = await fetch(basePath+inPath.substring(1));
|
|
||||||
return new Response(handle.body, {headers:{"content-type": mime.getType(inPath)??""}})
|
|
||||||
}
|
|
||||||
catch(_e)
|
|
||||||
{
|
|
||||||
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)
|
if(lookup)
|
||||||
{
|
{
|
||||||
return ServeJSCode(lookup);
|
return lookup;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const lookup = transpiled.get(url.pathname.substring(0, index)+".js");
|
|
||||||
if(lookup)
|
|
||||||
{
|
|
||||||
return ServeJSCode(lookup);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
buildConfig = {...defaultConfig, ...buildConfig}
|
||||||
|
buildConfig.entryPoints = [pathBase+pathName];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const results = await bundler({
|
const results = await bundler(basePath, buildConfig, DenoConfig);
|
||||||
entryPoints:[basePath+url.pathname],
|
|
||||||
outdir:"/",
|
|
||||||
entryNames: `[dir][name]`,
|
|
||||||
splitting: true
|
|
||||||
});
|
|
||||||
if(results.outputFiles)
|
if(results.outputFiles)
|
||||||
{
|
{
|
||||||
results.outputFiles.forEach(output=>transpiled.set(output.path, output.text))
|
results.outputFiles.forEach(output=>{transpiled.set(output.path, output.text); console.log("building", output.path);})
|
||||||
return ServeJSCode(results.outputFiles[0].text);
|
return results.outputFiles[0].text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
if(settings.html)
|
||||||
|
{
|
||||||
|
if(settings.html.indexOf("<") != -1) // if html is actual markup instead of a url
|
||||||
|
{
|
||||||
|
respIndexBody = settings.html;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw(new Error("no output"));
|
const load = await fetch(basePath+settings.html);
|
||||||
|
respIndexBody = await load.text();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(_e)
|
|
||||||
|
///// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 checkBuild = await bundle(path, basePath);
|
||||||
|
if(checkBuild)
|
||||||
|
{
|
||||||
|
return new Response(checkBuild, {headers});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// serve static
|
||||||
|
if(type)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
const handle = await fetch(basePath+path.substring(1));
|
||||||
|
return new Response(handle.body, {headers});
|
||||||
|
}
|
||||||
|
catch(_e){
|
||||||
return resp404;
|
return resp404;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return ServeStatic(url.pathname);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
// serve routes/implied index html files
|
||||||
|
if(respIndexBody)
|
||||||
if(respIndex)
|
|
||||||
{
|
{
|
||||||
return respIndex;
|
return new Response(respIndexBody, {headers});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
let indexLookup = url.pathname;
|
try{
|
||||||
if(!indexLookup.endsWith("/"))
|
const handle = await fetch(basePath+path.substring(1));
|
||||||
{
|
headers["content-type"] = "text/html"
|
||||||
indexLookup = indexLookup+"/";
|
return new Response(handle.body, {headers});
|
||||||
|
}
|
||||||
|
catch(_e){
|
||||||
|
return resp404;
|
||||||
}
|
}
|
||||||
return ServeStatic(indexLookup+"index.html");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
10
test/deno.json
Normal file
10
test/deno.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
2
test/leaf.ts
Normal file
2
test/leaf.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
const message:string = "leaf default export!"
|
||||||
|
export default ()=>console.log(message);
|
Loading…
Reference in New Issue
Block a user