got it!
This commit is contained in:
parent
e64ce9a144
commit
47ef75c55b
15
_lib_/boot.tsx
Normal file
15
_lib_/boot.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import "../serve.tsx";
|
||||||
|
|
||||||
|
Deno.args.forEach(arg=>
|
||||||
|
{
|
||||||
|
if(arg.startsWith("--"))
|
||||||
|
{
|
||||||
|
const kvp = arg.substring(2).split("=");
|
||||||
|
Deno.env.set(kvp[0], kvp[1] || "true");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(Deno.env.get("dev"))
|
||||||
|
{
|
||||||
|
await import("../local.tsx");
|
||||||
|
}
|
@ -24,6 +24,42 @@ export const Shadow =(inElement:HTMLElement, inConfig?:TW.TwindUserConfig)=>
|
|||||||
return ShadowDiv;
|
return ShadowDiv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let booted = false;
|
||||||
|
export const Boot =async(inSettings:{App:()=>React.JSX.Element, CSS?:TW.TwindUserConfig, DOM?:string})=>
|
||||||
|
{
|
||||||
|
if(booted){return;}
|
||||||
|
booted = true;
|
||||||
|
|
||||||
|
const settings = {CSS:{...Configure, ...inSettings.CSS||{} }, DOM:inSettings.DOM||"#app", App:inSettings.App};
|
||||||
|
|
||||||
|
console.log("Clinet boot called")
|
||||||
|
|
||||||
|
let dom = document.querySelector(settings.DOM);
|
||||||
|
if(!dom)
|
||||||
|
{
|
||||||
|
console.log(`element "${settings.DOM}" not found.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom = Shadow(dom as HTMLElement, settings.CSS)
|
||||||
|
|
||||||
|
const app = React.createElement(()=> React.createElement(settings.App, null), null);
|
||||||
|
if(React.render)
|
||||||
|
{
|
||||||
|
React.render(app, dom);
|
||||||
|
return ()=>dom && React.unmountComponentAtNode(dom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const reactDom = await import(`https://esm.sh/react-dom@${React.version}/client`);
|
||||||
|
const root = reactDom.createRoot(dom);
|
||||||
|
root.render(app);
|
||||||
|
return root.unmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export default async(inSelector:string, inModulePath:string, inMemberApp="default", inMemberCSS="CSS"):Promise<(()=>void)|false>=>
|
export default async(inSelector:string, inModulePath:string, inMemberApp="default", inMemberCSS="CSS"):Promise<(()=>void)|false>=>
|
||||||
{
|
{
|
||||||
let dom = document.querySelector(inSelector);
|
let dom = document.querySelector(inSelector);
|
||||||
|
23
deno.lock
23
deno.lock
@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "2",
|
|
||||||
"remote": {
|
|
||||||
"https://esm.sh/preact@10.15.1": "2b79349676a4942fbcf835c4efa909791c2f0aeca195225bf22bac9866e94b4e",
|
|
||||||
"https://esm.sh/preact@10.15.1/compat": "07273e22b1c335b8acc9f33c5e78165319c59bd8e2d0f3e5a2b4e028329424d9",
|
|
||||||
"https://esm.sh/react@18.2.0": "742d8246041966ba1137ec8c60888c35882a9d2478bce63583875f86c1e3687c",
|
|
||||||
"https://esm.sh/stable/preact@10.15.1/denonext/compat.js": "bad6b5b4d4fdfa5975b7a8d30410bd6877247f058e4952799fab39f66a94b8cf",
|
|
||||||
"https://esm.sh/stable/preact@10.15.1/denonext/hooks.js": "5c989ad368cf4f2cb3a5d7d1801843d9348c599fe3e7731d04728f7b845d724e",
|
|
||||||
"https://esm.sh/stable/preact@10.15.1/denonext/preact.mjs": "30710ac1d5ff3711ae0c04eddbeb706f34f82d97489f61aaf09897bc75d2a628",
|
|
||||||
"https://esm.sh/stable/react@18.2.0/deno/react.mjs": "a5a73ee24acca4744ee22c51d9357f31968d1f684ce253bde222b4e26d09f49f",
|
|
||||||
"https://esm.sh/v118/@types/prop-types@15.7.5/index.d.ts": "6a386ff939f180ae8ef064699d8b7b6e62bc2731a62d7fbf5e02589383838dea",
|
|
||||||
"https://esm.sh/v118/@types/react@18.2.0/global.d.ts": "549df62b64a71004aee17685b445a8289013daf96246ce4d9b087d13d7a27a61",
|
|
||||||
"https://esm.sh/v118/@types/react@18.2.0/index.d.ts": "b091747b1f503f434d3cac4217a13858baba87b421a7054ffdfd797da7737678",
|
|
||||||
"https://esm.sh/v118/@types/scheduler@0.16.3/tracing.d.ts": "f5a8b384f182b3851cec3596ccc96cb7464f8d3469f48c74bf2befb782a19de5",
|
|
||||||
"https://esm.sh/v118/csstype@3.1.2/index.d.ts": "4c68749a564a6facdf675416d75789ee5a557afda8960e0803cf6711fa569288",
|
|
||||||
"https://esm.sh/v118/preact@10.15.1/compat/src/index.d.ts": "9ec63be9612a10ff72fd4183179cde7d551ce43b3a0c2f549d8f788910d8263d",
|
|
||||||
"https://esm.sh/v118/preact@10.15.1/compat/src/suspense-list.d.ts": "b8e274324392157ce476ef3a48ae215c9f7003b08525d140645f19eab20d1948",
|
|
||||||
"https://esm.sh/v118/preact@10.15.1/compat/src/suspense.d.ts": "81f5266e0977a94347505d11b8103024211f2b4f3b2eb2aa276a10d8fd169e65",
|
|
||||||
"https://esm.sh/v118/preact@10.15.1/hooks/src/index.d.ts": "933eab6436614f8cd8e9b7c9b8bd54c6f3f14c3f065ba42c8c87a42d93de6595",
|
|
||||||
"https://esm.sh/v118/preact@10.15.1/src/index.d.ts": "fa83186a4b6caca36d52ca2d49b481c3ca5460988d4a8388d44dadc28987fb27",
|
|
||||||
"https://esm.sh/v118/preact@10.15.1/src/jsx.d.ts": "a6e4b7e4af3b959f8cfd41a0f475c547807ebcec8524d9605ab5c6de79f302fa"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,4 @@
|
|||||||
|
import "../_lib_/boot.tsx";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const CTXString = React.createContext("lol");
|
const CTXString = React.createContext("lol");
|
||||||
@ -30,13 +31,13 @@ const builder =(inState:Store):Store=>
|
|||||||
return inState;
|
return inState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default ()=>
|
export default ()=>
|
||||||
{
|
{
|
||||||
|
|
||||||
const [Store, Dispatch] = React.useReducer(reducer, {name:"seth", age:24} as Store, builder)
|
const [Store, Dispatch] = React.useReducer(reducer, {name:"seth", age:24} as Store, builder)
|
||||||
return <CTXString.Provider value="intradestink">
|
return <CTXString.Provider value="intradestink">
|
||||||
<div class="my-4 font-sans">
|
<div class="my-4 font-sans">
|
||||||
<h1 class="font-black text-xl">Title!!!!</h1>
|
<h1 class="font-black text-xl text-red-500">Title?</h1>
|
||||||
<h2>subtitle!</h2>
|
<h2>subtitle!</h2>
|
||||||
<p>
|
<p>
|
||||||
<button onClick={e=>Dispatch(1)}>{Store.name}|{Store.age}?</button>
|
<button onClick={e=>Dispatch(1)}>{Store.name}|{Store.age}?</button>
|
||||||
@ -48,5 +49,5 @@ export default ()=>
|
|||||||
<Outer>
|
<Outer>
|
||||||
<Inner/>
|
<Inner/>
|
||||||
</Outer>
|
</Outer>
|
||||||
</CTXString.Provider>
|
</CTXString.Provider>;
|
||||||
}
|
}
|
@ -2,12 +2,11 @@
|
|||||||
"compilerOptions": { "lib": ["deno.window", "dom"] },
|
"compilerOptions": { "lib": ["deno.window", "dom"] },
|
||||||
"imports":
|
"imports":
|
||||||
{
|
{
|
||||||
"react":"https://esm.sh/preact@10.15.1/compat",
|
"react":"https://esm.sh/preact@10.15.1/compat"
|
||||||
"@app": "./app.tsx"
|
|
||||||
},
|
},
|
||||||
"tasks":
|
"tasks":
|
||||||
{
|
{
|
||||||
"local": "deno run -A --no-lock ../local.tsx",
|
"local": "deno run -A --no-lock app.tsx --dev",
|
||||||
"serve": "deno run -A --no-lock ../serve.tsx"
|
"serve": "deno run -A --no-lock app.tsx"
|
||||||
}
|
}
|
||||||
}
|
}
|
51
local.tsx
51
local.tsx
@ -2,10 +2,8 @@ import {Configure, Transpile, Extension} from "./serve.tsx";
|
|||||||
|
|
||||||
const SocketsLive:Set<WebSocket> = new Set();
|
const SocketsLive:Set<WebSocket> = new Set();
|
||||||
const SocketsSend =(inData:string)=>{ console.log(inData); for (const socket of SocketsLive){ socket.send(inData); } }
|
const SocketsSend =(inData:string)=>{ console.log(inData); for (const socket of SocketsLive){ socket.send(inData); } }
|
||||||
const Directory = `file://${Deno.cwd().replaceAll("\\", "/")}`;
|
|
||||||
|
|
||||||
Configure({
|
Configure({
|
||||||
Proxy:Directory,
|
|
||||||
SWCOp:
|
SWCOp:
|
||||||
{
|
{
|
||||||
sourceMaps: "inline",
|
sourceMaps: "inline",
|
||||||
@ -36,11 +34,11 @@ Configure({
|
|||||||
console.log(inImports);
|
console.log(inImports);
|
||||||
return inImports;
|
return inImports;
|
||||||
},
|
},
|
||||||
async Serve(inReq, inURL, inExt, inMap)
|
async Serve(inReq, inURL, inExt, inMap, inProxy)
|
||||||
{
|
{
|
||||||
if(Transpile.Check(inExt) && !inURL.searchParams.get("reload") && !inURL.pathname.startsWith("/_lib_/"))
|
if(Transpile.Check(inExt) && !inURL.searchParams.get("reload") && !inURL.pathname.startsWith("/_lib_/"))
|
||||||
{
|
{
|
||||||
const imp = await import(Directory+inURL.pathname);
|
const imp = await import(inProxy+inURL.pathname);
|
||||||
const members = [];
|
const members = [];
|
||||||
for( const key in imp ) { members.push(key); }
|
for( const key in imp ) { members.push(key); }
|
||||||
|
|
||||||
@ -73,35 +71,40 @@ FileListen("${inURL.pathname}", (updatedModule)=>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let blocking = false;
|
const Watcher =async()=>
|
||||||
const filesChanged:Map<string, string> = new Map();
|
|
||||||
for await (const event of Deno.watchFs(Deno.cwd()))
|
|
||||||
{
|
{
|
||||||
event.paths.forEach( path => filesChanged.set(path, event.kind) );
|
let blocking = false;
|
||||||
if(!blocking)
|
const filesChanged:Map<string, string> = new Map();
|
||||||
|
for await (const event of Deno.watchFs(Deno.cwd()))
|
||||||
{
|
{
|
||||||
blocking = true;
|
event.paths.forEach( path => filesChanged.set(path, event.kind) );
|
||||||
setTimeout(async()=>
|
if(!blocking)
|
||||||
{
|
{
|
||||||
for await (const [path, action] of filesChanged)
|
blocking = true;
|
||||||
|
setTimeout(async()=>
|
||||||
{
|
{
|
||||||
if(Transpile.Check(Extension(path)))
|
for await (const [path, action] of filesChanged)
|
||||||
{
|
{
|
||||||
const key = path.substring(Deno.cwd().length).replaceAll("\\", "/");
|
if(Transpile.Check(Extension(path)))
|
||||||
if(action != "remove")
|
|
||||||
{
|
{
|
||||||
const tsx = await Transpile.Fetch(Directory+key, key, true);
|
const key = path.substring(Deno.cwd().length).replaceAll("\\", "/");
|
||||||
tsx && SocketsSend(key);
|
if(action != "remove")
|
||||||
}
|
{
|
||||||
else
|
const tsx = await Transpile.Fetch(`file://${Deno.cwd().replaceAll("\\", "/")}`+key, key, true);
|
||||||
{
|
tsx && SocketsSend(key);
|
||||||
Transpile.Cache.delete(key);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Transpile.Cache.delete(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
filesChanged.clear();
|
||||||
|
blocking = false;
|
||||||
}
|
}
|
||||||
filesChanged.clear();
|
, 1000);
|
||||||
blocking = false;
|
|
||||||
}
|
}
|
||||||
, 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Watcher().then(()=>console.log("done watching"));
|
43
serve.tsx
43
serve.tsx
@ -23,16 +23,16 @@ const ImportMapReload =async()=>
|
|||||||
ImportMap.imports = Configuration.Remap(json.imports);
|
ImportMap.imports = Configuration.Remap(json.imports);
|
||||||
};
|
};
|
||||||
|
|
||||||
type CustomHTTPHandler = (inReq:Request, inURL:URL, inExt:string|false, inMap:{imports:Record<string, string>})=>void|false|Response|Promise<Response|void|false>;
|
type CustomHTTPHandler = (inReq:Request, inURL:URL, inExt:string|false, inMap:{imports:Record<string, string>}, inProxy:string)=>void|false|Response|Promise<Response|void|false>;
|
||||||
type CustomRemapper = (inImports:Record<string, string>)=>Record<string, string>;
|
type CustomRemapper = (inImports:Record<string, string>)=>Record<string, string>;
|
||||||
type Configuration = {Proxy:string, Allow:string, Reset:string, SWCOp:SWCW.Options, Serve:CustomHTTPHandler, Shell:CustomHTTPHandler, Remap:CustomRemapper};
|
type Configuration = {Proxy:string, Allow:string, Reset:string, SWCOp:SWCW.Options, Serve:CustomHTTPHandler, Shell:CustomHTTPHandler, Remap:CustomRemapper};
|
||||||
type ConfigurationArgs = {Proxy?:string, Allow?:string, Reset?:string, SWCOp?:SWCW.Options, Serve?:CustomHTTPHandler, Shell?:CustomHTTPHandler, Remap?:CustomRemapper};
|
type ConfigurationArgs = {Proxy?:string, Allow?:string, Reset?:string, SWCOp?:SWCW.Options, Serve?:CustomHTTPHandler, Shell?:CustomHTTPHandler, Remap?:CustomRemapper};
|
||||||
let Configuration:Configuration =
|
let Configuration:Configuration =
|
||||||
{
|
{
|
||||||
Proxy: `file://${Deno.cwd().replaceAll("\\", "/")}`,
|
Proxy: new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString(),
|
||||||
Allow: "*",
|
Allow: "*",
|
||||||
Reset: "/clear-cache",
|
Reset: "/clear-cache",
|
||||||
Serve(inReq, inURL, inExt, inMap){},
|
Serve(inReq, inURL, inExt, inMap, inProxy){},
|
||||||
Remap: (inImports)=>
|
Remap: (inImports)=>
|
||||||
{
|
{
|
||||||
Object.entries(inImports).forEach(([key, value])=>
|
Object.entries(inImports).forEach(([key, value])=>
|
||||||
@ -51,8 +51,13 @@ let Configuration:Configuration =
|
|||||||
console.log(inImports);
|
console.log(inImports);
|
||||||
return inImports;
|
return inImports;
|
||||||
},
|
},
|
||||||
Shell(inReq, inURL, inExt, inMap)
|
Shell(inReq, inURL, inExt, inMap, inProxy)
|
||||||
{
|
{
|
||||||
|
console.log("Start app:", Deno.mainModule, "start dir", inProxy);
|
||||||
|
console.log("Split:", Deno.mainModule.split(inProxy) );
|
||||||
|
|
||||||
|
const parts = Deno.mainModule.split(inProxy);
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
`<!doctype html>
|
`<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
@ -62,8 +67,8 @@ let Configuration:Configuration =
|
|||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="importmap">${JSON.stringify(inMap)}</script>
|
<script type="importmap">${JSON.stringify(inMap)}</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import Mount from "/_lib_/mount.tsx";
|
import Mount from "/_lib_/mount.tsx";
|
||||||
Mount("#app", "@app");
|
Mount("#app", "${parts[1]??"/app.tsx"}");
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>`, {status:200, headers:{"content-type":"text/html"}});
|
</html>`, {status:200, headers:{"content-type":"text/html"}});
|
||||||
@ -162,7 +167,7 @@ HTTP.serve(async(req: Request)=>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow for custom handler
|
// allow for custom handler
|
||||||
const custom = await Configuration.Serve(req, url, ext, ImportMap);
|
const custom = await Configuration.Serve(req, url, ext, ImportMap, Configuration.Proxy);
|
||||||
if(custom)
|
if(custom)
|
||||||
{
|
{
|
||||||
return custom;
|
return custom;
|
||||||
@ -171,26 +176,36 @@ HTTP.serve(async(req: Request)=>
|
|||||||
// transpileable files
|
// transpileable files
|
||||||
if(Transpile.Check(ext))
|
if(Transpile.Check(ext))
|
||||||
{
|
{
|
||||||
|
let code;
|
||||||
|
let path;
|
||||||
if(url.pathname.startsWith("/_lib_/"))
|
if(url.pathname.startsWith("/_lib_/"))
|
||||||
{
|
{
|
||||||
const path = import.meta.url+"/.."+url.pathname;
|
if(url.pathname.endsWith("boot.tsx"))
|
||||||
const code = await Transpile.Fetch(path, url.pathname, true);
|
|
||||||
if(code)
|
|
||||||
{
|
{
|
||||||
return new Response(code, {headers:{"content-type":"application/javascript"}});
|
path = import.meta.url+"/../_lib_/mount.tsx";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = import.meta.url+"/.."+url.pathname;
|
||||||
|
}
|
||||||
|
code = await Transpile.Fetch(path, url.pathname, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const lookup = await Transpile.Fetch(Configuration.Proxy + url.pathname, url.pathname);
|
path = Configuration.Proxy + url.pathname;
|
||||||
return new Response(lookup, {status:lookup?200:404, headers:{...headers, "content-type":"application/javascript"}} );
|
code = await Transpile.Fetch(path, url.pathname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(code)
|
||||||
|
{
|
||||||
|
return new Response(code, {headers:{...headers, "content-type":"application/javascript"}} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom page html
|
// custom page html
|
||||||
if(!ext)
|
if(!ext)
|
||||||
{
|
{
|
||||||
const shell = await Configuration.Shell(req, url, ext, ImportMap);
|
const shell = await Configuration.Shell(req, url, ext, ImportMap, Configuration.Proxy);
|
||||||
if(shell)
|
if(shell)
|
||||||
{
|
{
|
||||||
return shell;
|
return shell;
|
||||||
|
Loading…
Reference in New Issue
Block a user