fixes started

This commit is contained in:
Seth Trowbridge 2025-10-13 17:03:35 -04:00
parent bfeb85b674
commit 597aabe924
3 changed files with 53 additions and 35 deletions

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
function App(){ function App(){
const [countGet, countSet] = React.useState(2); const [countGet, countSet] = React.useState(2);

View File

@ -117,29 +117,28 @@ export const ModuleShape =(inText:string)=>
export const ModuleProxy =(inText:string, inPath:string)=> export const ModuleProxy =(inText:string, inPath:string)=>
{ {
const [local, foreign] = ModuleShape(inText); const [local, foreign] = ModuleShape(inText);
console.log("shape local", local);
return ` return `
import {FileListen} from "/^/hmr/hmr-listen.tsx"; import {FileListen} from "/^/hmr/hmr-listen.tsx";
import * as Import from "${inPath}?reload=${new Date().getTime()}"; import * as Import from "${inPath}?reload=${new Date().getTime()}";
${ local.map(m=>`let proxy_${m} = Import.${m}; export { proxy_${m} as ${m} };`).join("\n") } ${ local.map(m=>`let proxy_${m} = Import.${m}; export { proxy_${m} as ${m} };`).join("\n") }
FileListen("${inPath}", (updatedModule)=> FileListen("${inPath}", (updatedModule)=>
{ {
${ local.map(m=>`proxy_${m} = updatedModule.${m};`).join("\n") } ${ local.map(m=>`proxy_${m} = updatedModule.${m};`).join("\n\t") }
}); });
${ foreign.join(";\n") }`; ${ foreign.join(";\n") }`;
}; };
/////////////////////////////////////////////// ///////////////////////////////////////////////
const [local, global] = ModuleShape(` // const [local, global] = ModuleShape(`
// export in comment // // export in comment
export { A as B } // export { A as B }
export * from "react"; // export * from "react";
const fakeexport =()=>{}; // const fakeexport =()=>{};
export{ thing1 as remapped, thing2} // export{ thing1 as remapped, thing2}
export { thing1 as remapped, thing2} from 'React'; // export { thing1 as remapped, thing2} from 'React';
export // export
export const func=()=>{}; // export const func=()=>{};
`); // `);
//
console.log(local); // console.log(local);

View File

@ -11,9 +11,12 @@ const extractExtension =(path:string)=>
return ind === -1 ? "" : path.substring(ind+1); return ind === -1 ? "" : path.substring(ind+1);
} }
const RootRunning = new URL(`file://${Deno.cwd()}`).toString(); const RootRunning = new URL(`file://${Deno.cwd()}`).toString() + "/";
const RootSiblings = import.meta.resolve("./"); const RootSiblings = import.meta.resolve("./");
console.log("Root Running:", RootRunning);
console.log("Root Siblings:", RootSiblings);
const bakeConfigPackage:Deno.bundle.Options = const bakeConfigPackage:Deno.bundle.Options =
{ {
entrypoints:[""], entrypoints:[""],
@ -23,19 +26,23 @@ const bakeConfigPackage:Deno.bundle.Options =
minify: false, minify: false,
} }
const bakeConfigLocal:Deno.bundle.Options = {...bakeConfigPackage, sourcemap:"inline", inlineImports:false }; const bakeConfigLocal:Deno.bundle.Options = {...bakeConfigPackage, sourcemap:"inline", inlineImports:false };
async function BakeForce(path:string, type?:"package")
type FullBakeConfig = {
bundle: Deno.bundle.Options,
};
async function BakeForce(prefix:string, path:string, key:string, type?:"package")
{ {
// If already baking, return the in-flight promise. (Caller may also call BakeCheck which handles this.) // If already baking, return the in-flight promise. (Caller may also call Bake Check which handles this.)
if (BakeCache[path] && typeof (BakeCache[path] as any)?.then === "function") if (BakeCache[key] && typeof (BakeCache[key] as any)?.then === "function")
{ {
return await BakeCache[path] as CachedTranspile | undefined; return await BakeCache[key] as CachedTranspile | undefined;
} }
// Create a fresh config per bake to avoid shared mutation. // Create a fresh config per bake to avoid shared mutation.
const config = {...(type ? bakeConfigPackage : bakeConfigLocal)}; const config = {...(type ? bakeConfigPackage : bakeConfigLocal), entrypoints:[prefix + path]};
config.entrypoints = [...config.entrypoints]; console.log("baking", config.entrypoints, "as", [prefix, path]);
config.entrypoints[0] = type ? path : RootRunning+path;
console.log("baking", config.entrypoints);
// store the in-flight promise immediately so concurrent callers reuse it // store the in-flight promise immediately so concurrent callers reuse it
const inflight = (async () => const inflight = (async () =>
@ -47,28 +54,28 @@ async function BakeForce(path:string, type?:"package")
{ {
const body = result.outputFiles.map(file=>file.text()).join("\n"); const body = result.outputFiles.map(file=>file.text()).join("\n");
const save:CachedTranspile = [body, type ? "" : ModuleProxy(body, path)]; const save:CachedTranspile = [body, type ? "" : ModuleProxy(body, path)];
BakeCache[path] = save; // replace promise with resolved value BakeCache[key] = save; // replace promise with resolved value
return save; return save;
} }
} }
catch (e) catch (e)
{ {
console.log("BakeForce error for", path, e); console.log("Bake error", path, e);
} }
// failed - remove cache entry so next attempt can retry // failed - remove cache entry so next attempt can retry
delete BakeCache[path]; delete BakeCache[key];
return undefined; return undefined;
})(); })();
BakeCache[path] = inflight; BakeCache[key] = inflight;
return await inflight; return await inflight;
}; };
async function BakeCheck(path:string, type?:"package") async function BakeCheck(prefix:string, path:string, key:string, type?:"package")
{ {
const lookup = BakeCache[path]; const lookup = BakeCache[path];
if(!lookup) if(!lookup)
{ {
return await BakeForce(path, type); return await BakeForce(prefix, path, type);
} }
// if an in-flight promise is stored, await it // if an in-flight promise is stored, await it
if (typeof (lookup as any)?.then === "function") if (typeof (lookup as any)?.then === "function")
@ -81,7 +88,7 @@ type CachedTranspile = [file:string, profile:string]
// BakeCache may hold a resolved cached tuple or an in-flight Promise that resolves to one. // BakeCache may hold a resolved cached tuple or an in-flight Promise that resolves to one.
const BakeCache:Record<string, CachedTranspile | Promise<CachedTranspile|undefined> | undefined> = {} const BakeCache:Record<string, CachedTranspile | Promise<CachedTranspile|undefined> | undefined> = {}
const denoBody = await fetch(RootRunning+"/deno.json").then(resp=>resp.json()); const denoBody = await fetch(RootRunning+"deno.json").then(resp=>resp.json());
for(const key in denoBody.imports) for(const key in denoBody.imports)
{ {
const value = denoBody.imports[key]; const value = denoBody.imports[key];
@ -95,11 +102,20 @@ denoBody.imports["react-original"] = denoBody.imports[react];
denoBody.imports[react] = "/^/hmr/hmr-react.tsx"; denoBody.imports[react] = "/^/hmr/hmr-react.tsx";
denoBody.imports[react+"/jsx-runtime"] = "/^/hmr/hmr-react.tsx"; denoBody.imports[react+"/jsx-runtime"] = "/^/hmr/hmr-react.tsx";
/*
npm:react | bundle | no-prefix
hrm/hmr-listen.tsx | transpile | server-prefix
local/file/component.tsx | transpile | local-prefix
*/
console.log(denoBody.imports); console.log(denoBody.imports);
const importMap = `<script type="importmap">{"imports":${JSON.stringify(denoBody.imports, null, 2)}}</script>`; const importMap = `<script type="importmap">{"imports":${JSON.stringify(denoBody.imports, null, 2)}}</script>`;
let htmlPageBody = await fetch(RootRunning+"/index.html").then(resp=>resp.text()); let htmlPageBody = await fetch(RootRunning+"index.html").then(resp=>resp.text());
htmlPageBody = htmlPageBody.replace("<head>", "<head>"+importMap); htmlPageBody = htmlPageBody.replace("<head>", "<head>"+importMap);
const htmlPageHead = {headers:{"content-type":"text/html"}} const htmlPageHead = {headers:{"content-type":"text/html"}}
const IndexResponse =()=> new Response(htmlPageBody, htmlPageHead); const IndexResponse =()=> new Response(htmlPageBody, htmlPageHead);
@ -154,13 +170,14 @@ Deno.serve(async(req:Request)=>
} }
if(parts[0] == keyAdjacent) if(parts[0] == keyAdjacent)
{ {
const proxiedPath = "/"+parts.slice(1).join("/"); const proxiedPath = RootSiblings + "/" + parts.slice(1).join("/");
const transpiled = await BakeCheck(proxiedPath); const transpiled = await BakeCheck(proxiedPath);
return JSResponse(transpiled[0]); return JSResponse(transpiled[0]);
} }
if(keysExtension.includes(extension)) if(keysExtension.includes(extension))
{ {
const transpiled = await BakeCheck(url.pathname); const proxiedPath = parts.join("/");
const transpiled = await BakeCheck(RootRunning, proxiedPath, proxiedPath+url.search);
//return JSResponse(transpiled[0]); //return JSResponse(transpiled[0]);
return JSResponse(transpiled[url.searchParams.has(keyReload) ? 0 : 1]); return JSResponse(transpiled[url.searchParams.has(keyReload) ? 0 : 1]);
} }
@ -193,6 +210,7 @@ const SocketsSend = (inData: string) => {
const Watcher =async()=> const Watcher =async()=>
{ {
let blocking = false; let blocking = false;
const cutOff = Deno.cwd().length + 1;
const filesChanged:Map<string, string> = new Map(); const filesChanged:Map<string, string> = new Map();
for await (const event of Deno.watchFs(Deno.cwd())) for await (const event of Deno.watchFs(Deno.cwd()))
{ {
@ -210,11 +228,11 @@ const Watcher =async()=>
if(keysExtension.includes(extension)) if(keysExtension.includes(extension))
{ {
const key = path.substring(Deno.cwd().length).replaceAll("\\", "/"); const key = path.substring(cutOff).replaceAll("\\", "/");
console.log("File change", path, key); console.log("File change", path, key);
if(action != "remove") if(action != "remove")
{ {
await BakeForce(key); await BakeForce(RootRunning, key, key);
SocketsSend(key); SocketsSend(key);
} }
else else