From 223bebe48db6f204171553733fa8ed79c0c35c13 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Tue, 6 Jun 2023 17:22:14 -0400 Subject: [PATCH] client started --- client.tsx | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ serve.tsx | 70 +++++++----------------------------------------------- xpile.tsx | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 62 deletions(-) create mode 100644 client.tsx create mode 100644 xpile.tsx diff --git a/client.tsx b/client.tsx new file mode 100644 index 0000000..cdc75c1 --- /dev/null +++ b/client.tsx @@ -0,0 +1,64 @@ +import * as HTTP from "https://deno.land/std@0.177.0/http/server.ts"; +import * as Transpile from "./xpile.tsx"; + +const dir = `file://${Deno.cwd().replaceAll("\\", "/")}`; + +const Sockets:Set = new Set(); +const SocketsBroadcast =(inData:string)=>{ console.log(inData); for (const socket of Sockets){ socket.send(inData); } } +const SocketsHandler = (_req:Request)=> +{ + if(_req.headers.get("upgrade") == "websocket") + { + try + { + const { response, socket } = Deno.upgradeWebSocket(_req); + socket.onopen = () => Sockets.add(socket); + socket.onclose = () => Sockets.delete(socket); + socket.onmessage = (e) => {}; + socket.onerror = (e) => console.log("Socket errored:", e); + return response; + } + catch(e) + { + // + return new Response(e); + } + } + return new Response(`websockets only`); +}; + +HTTP.serve(SocketsHandler, { port: 4444 }); + +const watcher =async()=> +{ + let blocking = false; + const filesChanged:Map = new Map(); + for await (const event of Deno.watchFs(Deno.cwd())) + { + event.paths.forEach( path => filesChanged.set(path, event.kind) ); + if(!blocking) + { + blocking = true; + setTimeout(async()=> + { + for await (const [path, action] of filesChanged) + { + const key = path.substring(Deno.cwd().length).replaceAll("\\", "/"); + if(action != "remove") + { + await Transpile.Fetch(dir+key, key, true); + SocketsBroadcast(key); + } + else + { + Transpile.Cache.delete(key); + } + } + filesChanged.clear(); + blocking = false; + } + , 1000); + } + } +} +watcher().then(()=>console.log("done watching")); \ No newline at end of file diff --git a/serve.tsx b/serve.tsx index 66660dd..fea1461 100644 --- a/serve.tsx +++ b/serve.tsx @@ -1,88 +1,34 @@ import * as MIME from "https://deno.land/std@0.180.0/media_types/mod.ts"; import * as HTTP from "https://deno.land/std@0.177.0/http/server.ts"; -import * as SWCW from "https://esm.sh/@swc/wasm-web@1.3.62"; +import * as Transpile from "./xpile.tsx"; -type Configuration = {Proxy:string, Allow:string, Reset:string}; -type ConfigurationArgs = {Proxy?:string, Allow?:string, Reset?:string}; +type Configuration = {Proxy:string, Allow:string, Reset:string, Local:boolean}; +type ConfigurationArgs = {Proxy?:string, Allow?:string, Reset?:string, Local?:boolean}; let Configure:Configuration = { Proxy: "", Allow: "*", - Reset: "/clear-cache" + Reset: "/clear-cache", + Local: false }; export default (config:ConfigurationArgs)=> Configure = {...Configure, ...config}; -const TranspileConfig:SWCW.Options = { - sourceMaps: true, - minify: true, - jsc: - { - minify: - { - compress: { unused: true }, - mangle: true - }, - parser: - { - syntax: "typescript", - tsx: true, - }, - transform: - { - react: { runtime: "automatic" } - } - }, -} -const TranspileCache:Map = new Map(); -const TranspileFetch =async(inPath:string)=> -{ - if(inPath.endsWith(".tsx") || inPath.endsWith(".jsx") || inPath.endsWith(".js") || inPath.endsWith(".mjs")) - { - const check = TranspileCache.get(inPath); - if(check) - { - return check; - } - else - { - try - { - const resp = await fetch(Configure.Proxy + inPath); - const text = await resp.text(); - const {code, map} = await SWCW.transform(text, TranspileConfig); - TranspileCache.set(inPath, code); - return code; - } - catch(e) - { - return null; - } - } - } - else - { - return false; - } -}; -await SWCW.default(); HTTP.serve(async(req: Request)=> { const url:URL = new URL(req.url); if(url.pathname === Configure.Reset) { - const size = TranspileCache.size; - TranspileCache.clear(); - return new Response(`cache cleared (${size} items)`); + return new Response(`cache cleared (${Transpile.Clear()} items)`); } - const lookup = await TranspileFetch(url.pathname); + const lookup = await Transpile.Fetch(Configure.Proxy + url.pathname); if(lookup === null) { // error - return new Response(`error (see console)`, {status:404, headers:{"content-type":"application/javascript", "Access-Control-Allow-Origin": Configure.Allow, charset:"utf-8"}}); + return new Response(`transpile error (see console)`, {status:404, headers:{"content-type":"application/javascript", "Access-Control-Allow-Origin": Configure.Allow, charset:"utf-8"}}); } else if(lookup === false) { diff --git a/xpile.tsx b/xpile.tsx new file mode 100644 index 0000000..1ec85da --- /dev/null +++ b/xpile.tsx @@ -0,0 +1,65 @@ +import * as SWCW from "https://esm.sh/@swc/wasm-web@1.3.62"; + +await SWCW.default(); + +export const Config:SWCW.Options = +{ + sourceMaps: false, + minify: true, + jsc: + { + minify: + { + compress: { unused: true }, + mangle: true + }, + parser: + { + syntax: "typescript", + tsx: true, + }, + transform: + { + react: { runtime: "automatic" } + } + }, +} +export const Cache:Map = new Map(); +export const Clear =()=> +{ + const size = Cache.size; + Cache.clear(); + return size; +}; +export const Fetch =async(inPath:string, inKey:string, inCheckCache=true)=> +{ + if(inPath.endsWith(".tsx") || inPath.endsWith(".jsx") || inPath.endsWith(".js") || inPath.endsWith(".mjs")) + { + const check = Cache.get(inPath); + if(check && inCheckCache) + { + return check; + } + else + { + + try + { + const resp = await fetch(inPath); + const text = await resp.text(); + const {code} = await SWCW.transform(text, Config); + Cache.set(inKey, code); + return code; + } + catch(e) + { + console.log(`xpile.tsx error. Key:${inKey} Path:${inPath} Error:"${e}"`); + return null; + } + } + } + else + { + return false; + } +}; \ No newline at end of file