commit 02c1a48e37a9992199ae9f2d965906f30b2ab782 Author: Seth Trowbridge Date: Thu Dec 1 17:10:59 2022 -0500 setup diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8675ad5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "deno.enable": true, + "deno.unstable": true +} \ No newline at end of file diff --git a/deep/file.txt b/deep/file.txt new file mode 100644 index 0000000..e69de29 diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..df9bcff --- /dev/null +++ b/deno.json @@ -0,0 +1,6 @@ +{ + "tasks": + { + "install": "deno install -f -A --unstable --no-lock -n tsx server.tsx" + } +} \ No newline at end of file diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..f896ca5 --- /dev/null +++ b/deno.lock @@ -0,0 +1,10 @@ +{ + "version": "2", + "remote": { + "https://deno.land/std@0.151.0/async/debounce.ts": "564273ef242bcfcda19a439132f940db8694173abffc159ea34f07d18fc42620", + "https://deno.land/x/denoflate@1.2.1/mod.ts": "f5628e44b80b3d80ed525afa2ba0f12408e3849db817d47a883b801f9ce69dd6", + "https://deno.land/x/denoflate@1.2.1/pkg/denoflate.js": "b9f9ad9457d3f12f28b1fb35c555f57443427f74decb403113d67364e4f2caf4", + "https://deno.land/x/denoflate@1.2.1/pkg/denoflate_bg.wasm.js": "d581956245407a2115a3d7e8d85a9641c032940a8e810acbd59ca86afd34d44d", + "https://deno.land/x/esbuild@v0.14.45/mod.js": "ab18347f6a57e56f776a9997a5b726f7f6c8d1f008f08e41e7273be8c31e12f4" + } +} diff --git a/runner.tsx b/runner.tsx new file mode 100644 index 0000000..f6b7cfa --- /dev/null +++ b/runner.tsx @@ -0,0 +1,7 @@ +import * as FS from "https://deno.land/std@0.144.0/fs/mod.ts"; + +console.log(Deno.args, import.meta.url); +/* +await Deno.mkdir("deep"); +await Deno.create(`deep/file.txt`, "sup"); +*/ \ No newline at end of file diff --git a/server.tsx b/server.tsx new file mode 100644 index 0000000..6d15434 --- /dev/null +++ b/server.tsx @@ -0,0 +1,213 @@ +import * as esbuild from 'https://deno.land/x/esbuild@v0.14.45/mod.js'; +import { debounce } from "https://deno.land/std@0.151.0/async/debounce.ts"; +console.log(`Serving files from "${Deno.cwd()}"`); + +const MIME:Record = { + ".aac": "audio/aac", + ".abw": "application/x-abiword", + ".arc": "application/x-freearc", + ".avif": "image/avif", + ".avi": "video/x-msvideo", + ".azw": "application/vnd.amazon.ebook", + ".bin": "application/octet-stream", + ".bmp": "image/bmp", + ".bz": "application/x-bzip", + ".bz2": "application/x-bzip2", + ".cda": "application/x-cdf", + ".csh": "application/x-csh", + ".css": "text/css", + ".csv": "text/csv", + ".doc": "application/msword", + ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ".eot": "application/vnd.ms-fontobject", + ".epub": "application/epub+zip", + ".gz": "application/gzip", + ".gif": "image/gif", + ".htm": "text/html", + ".html": "text/html", + ".ico": "image/x-icon", + ".ics": "text/calendar", + ".jar": "application/java-archive", + ".jpeg": "image/jpeg", + ".jpg": "image/jpeg", + ".js": "application/javascript", + ".jsx": "application/javascript", + ".json": "application/json", + ".jsonld": "application/ld+json", + ".mid": "audio/midi", + ".midi": "audio/midi", + ".mjs": "text/javascript", + ".mp3": "audio/mpeg", + ".mp4": "video/mp4", + ".mpeg": "video/mpeg", + ".mpkg": "application/vnd.apple.installer+xml", + ".odp": "application/vnd.oasis.opendocument.presentation", + ".ods": "application/vnd.oasis.opendocument.spreadsheet", + ".odt": "application/vnd.oasis.opendocument.text", + ".oga": "audio/ogg", + ".ogv": "video/ogg", + ".ogx": "application/ogg", + ".opus": "audio/opus", + ".otf": "font/otf", + ".png": "image/png", + ".pdf": "application/pdf", + ".php": "application/x-httpd-php", + ".ppt": "application/vnd.ms-powerpoint", + ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation", + ".rar": "application/vnd.rar", + ".rtf": "application/rtf", + ".sh": "application/x-sh", + ".svg": "image/svg+xml", + ".swf": "application/x-shockwave-flash", + ".tar": "application/x-tar", + ".tif": "image/tiff", + ".tiff": "image/tiff", + ".ts": "application/javascript", + ".tsx": "application/javascript", + ".ttf": "font/ttf", + ".txt": "text/plain", + ".vsd": "application/vnd.visio", + ".wav": "audio/wav", + ".weba": "audio/webm", + ".webm": "video/webm", + ".webp": "image/webp", + ".woff": "font/woff", + ".woff2": "font/woff2", + ".xhtml": "application/xhtml+xml", + ".xls": "application/vnd.ms-excel", + ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ".xml": "application/xml", + ".xul": "application/vnd.mozilla.xul+xml", + ".zip": "application/zip", + ".3gp": "video/3gpp", + ".3g2": "video/3gpp2", + ".7z": "application/x-7z-compressed" +}; +const Type =(inPath:string):string|undefined=> +{ + const dot:number = inPath.lastIndexOf("."); + const ext = dot > -1 ? inPath.substring(dot) : ".html"; + return MIME[ext]; +}; + +const Transpiled = new Map(); +const Transpile =async(inPath:string, inKey:string):Promise=> +{ + const body = await Deno.readTextFile(inPath); + const transpile = await esbuild.transform(body, { loader: 'tsx' }); + Transpiled.set(inKey, transpile.code); + return transpile.code; +}; + +const confDeno = await Deno.readTextFile(Deno.cwd()+"/deno.json"); +const pathImport = JSON.parse(confDeno).importMap; +const confImports = await Deno.readTextFile(pathImport); + +const Index = ` + + + + + + +
Loading
+ + + + + +`; + +Deno.serve({ port: 3000 }, async(_req:Request) => +{ + const url:URL = new URL(_req.url); + const type = Type(url.pathname); + const fsPath = Deno.cwd()+url.pathname; + + console.log(`Request for "${url.pathname}"...`); + + try + { + let body:BodyInit; + if(type == "application/javascript") + { + body = Transpiled.get(url.pathname); + if(!body) + { + body = await Transpile(fsPath, url.pathname); + console.log(` ...added to cache`); + } + else + { + console.log(` ...retrieved from cache`); + } + } + else + { + if(url.pathname == "/") + { + body = Index; + } + else + { + let file = fsPath; + if(url.pathname.endsWith("/")) + { + console.log(` ...implied index.html`); + file += "index.html"; + } + body = await Deno.readFile(file); + } + } + + return new Response(body, {headers:{"content-type":type as string}}); + } + catch(error) + { + console.log(` ...404`); + return new Response(error, {status:404}); + } +}); + +const filesChanged:Map = new Map(); +const ProcessFiles =debounce(async()=> +{ + console.log("Files changed...") + for await (const [file, action] of filesChanged) + { + const pathname = file.substring(Deno.cwd().length).replaceAll("\\", "/"); + const type = Type(pathname); + console.log(pathname, type, action); + if(type == "application/javascript") + { + if(action !== "remove") + { + await Transpile(file, pathname); + console.log(` ...cached "${pathname}"`); + } + } + } + filesChanged.clear(); +}, 1000); + +const watcher = Deno.watchFs(Deno.cwd()); +for await (const event of watcher) +{ + event.paths.forEach( path => filesChanged.set(path, event.kind) ); + ProcessFiles(); +} \ No newline at end of file