diff --git a/circ/b.tsx b/circ/b.tsx
index a9b326c..be8d563 100644
--- a/circ/b.tsx
+++ b/circ/b.tsx
@@ -1,8 +1,20 @@
+import * as mod from "https://deno.land/std@0.185.0/path/mod.ts";
import { doSomethingElse } from './a.tsx';
export function doSomething() {
+ const pathInit = Deno.mainModule;
+
+ const pathProj = mod.toFileUrl(Deno.cwd());
+
+ console.log(pathInit);
+ console.log(import.meta.url);
+
+ console.log(pathInit.split(pathProj));
+
console.log("b main?", Deno.mainModule);
+ console.log("deno main?", Deno.cwd());
+
Deno.env.set("b", "called");
console.log("b action");
diff --git a/example/app.tsx b/example/app.tsx
index 8a7cd9e..da58b1d 100644
--- a/example/app.tsx
+++ b/example/app.tsx
@@ -3,34 +3,36 @@ import * as Iso from "@eno/iso";
const Comp = React.lazy(()=>import("./deep/component.tsx"));
-export default ()=>
-{
- return
-
-
-
-
Title!!
-
suspended:
-
Loading! }>
-
-
-
-
-
-
- <>
-
- About us!
- >
-
- sorry no page
-
-
- lol/idk
- 404!
-
- ;
-};
\ No newline at end of file
+Iso.Boot(
+ ()=>
+ {
+ return
+
+
+
+
Title!!!!!!
+
suspended:
+
Loading! }>
+
+
+
+
+
+
+ <>
+
+ About us!
+ >
+
+ sorry no page
+
+
+ lol/idk
+ 404!
+
+ ;
+ }
+);
\ No newline at end of file
diff --git a/lib/boot-client.tsx b/lib/boot-client.tsx
new file mode 100644
index 0000000..6eb1f15
--- /dev/null
+++ b/lib/boot-client.tsx
@@ -0,0 +1,30 @@
+import React, {hydrate} from "react";
+import * as Twind from "https://esm.sh/v115/@twind/core@1.1.3/es2022/core.mjs";
+import {Router, CSS, Meta} from "@eno/iso";
+
+export function Boot(inApp:()=>React.JSX.Element, inCSS?:object)
+{
+ console.log(inApp, inCSS);
+ Twind.install(inCSS ? {...CSS, ...inCSS} : CSS);
+
+ const HMRWrap =()=> React.createElement(inApp, null, null);
+
+ const root = document.querySelector("#app");
+
+ if(root)
+ {
+ hydrate(
+
+
+
+
+ ,
+ root
+ );
+ }
+ else
+ {
+ console.log(`no "#app" element is present!`)
+ }
+
+};
\ No newline at end of file
diff --git a/lib/iso.tsx b/lib/iso.tsx
index c10e021..231e35e 100644
--- a/lib/iso.tsx
+++ b/lib/iso.tsx
@@ -1,15 +1,7 @@
import TWPreTail from "https://esm.sh/v115/@twind/preset-tailwind@1.1.4/es2022/preset-tailwind.mjs";
import TWPreAuto from "https://esm.sh/v115/@twind/preset-autoprefix@1.0.7/es2022/preset-autoprefix.mjs";
import React from "react";
-
-import {INIT} from "../server.tsx";
-
-function wrapper()
-{
- INIT();
-}
-
-wrapper();
+import { Boot as _Boot } from "../server.tsx";
export const CSS = {
presets: [TWPreTail(), TWPreAuto()],
@@ -22,6 +14,12 @@ if(!window.innerWidth)
}
*/
+export function Boot(inApp:React.FunctionComponent, inCSS?:object)
+{
+ _Boot(inApp, inCSS);
+}
+
+
type MetasInputs = { [Property in MetaKeys]?: string };
type MetasModeArgs = {concatListed?:boolean; dropUnlisted?:boolean};
type MetasStackItem = MetasModeArgs&MetasInputs&{id:string, depth:number}
diff --git a/server.tsx b/server.tsx
index f36f489..49bccdb 100644
--- a/server.tsx
+++ b/server.tsx
@@ -2,16 +2,13 @@ import * as ESBuild from 'https://deno.land/x/esbuild@v0.17.4/mod.js';
import * as MIME from "https://deno.land/std@0.180.0/media_types/mod.ts";
import { debounce } from "https://deno.land/std@0.151.0/async/debounce.ts";
import { parse as JSONC} from "https://deno.land/std@0.185.0/jsonc/mod.ts";
+import { toFileUrl } from "https://deno.land/std@0.185.0/path/mod.ts";
import SSR from "https://esm.sh/v113/preact-render-to-string@6.0.2";
import Prepass from "https://esm.sh/preact-ssr-prepass@1.2.0";
import * as Twind from "https://esm.sh/@twind/core@1.1.3";
import React from "react";
import * as Iso from "@eno/iso";
-Deno.env.set("initialized", "true");
-
-export const INIT =()=> console.log("init!");
-
/**
* Setup a transpiler.
* @param inDevMode When true, starts a file-watcher
@@ -136,6 +133,7 @@ function Transpiler(inDevMode:boolean)
}
+type ImportMap = {imports?:Record, importMap?:string};
/**
* Extract all configuration info form a project's deno.jsonc file
* @param inDevMode When true, proxies react to an HMR-enabled version
@@ -144,8 +142,7 @@ function Transpiler(inDevMode:boolean)
*/
async function Configure(inDevMode:boolean, inLibPath:string)
{
- type ImportMap = {imports?:Record, importMap?:string};
- const output:{Imports?:ImportMap, App?:React.FunctionComponent, TwindInst?:Twind.Twind, Error?:string} = {};
+ const output:{Imports?:ImportMap, Error?:string} = {};
let ImportObject:ImportMap = {};
try
{
@@ -206,52 +203,6 @@ async function Configure(inDevMode:boolean, inLibPath:string)
return output;
}
- const importApp = output.Imports.imports["@eno/app"];
- if(importApp)
- {
- let appImport
- try
- {
- appImport = await import(Path.Active+importApp);
- }
- catch(e)
- {
- output.Error = `"@eno/app" entry-point (${importApp}) file not found`;
- return output;
- }
-
- if(typeof appImport.default == "function" )
- {
- output.App = appImport.default;
- }
- else
- {
- output.Error = `"@eno/app" entry-point (${importApp}) needs to export a default function to use as the app root.`;
- return output;
- }
-
- let twindConfig = Iso.CSS;
- if(typeof appImport.CSS == "object")
- {
- twindConfig = {...twindConfig, ...appImport.CSS};
- }
- try
- {
- // @ts-ignore
- output.TwindInst = Twind.install(twindConfig);
- }
- catch(e)
- {
- output.Error = `CSS configuration is malformed`;
- return output;
- }
- }
- else
- {
- output.Error = `"imports" configuration does not alias an entry-point file as "@eno/app"`;
- return output;
- }
-
Object.entries(output.Imports.imports).forEach(([key, value])=>{
if(value.startsWith("./") && output.Imports?.imports)
@@ -274,166 +225,196 @@ async function Configure(inDevMode:boolean, inLibPath:string)
return output;
}
-const Flags:Record = {};
Deno.args.forEach(arg=>
{
if(arg.startsWith("--"))
{
const kvp = arg.substring(2).split("=");
- Flags[kvp[0]] = kvp[1] ? kvp[1] : true;
+ Deno.env.set(kvp[0], kvp[1] ? kvp[1] : "true");
}
});
-let Booted = false;
-export function Boot(inApp:React.JSX.Element, inCSS?:object)
-{
- if(Booted){return;}
- Booted = true;
-
-}
-
-let DevMode = Flags.dev ? true : false;
+let DevMode = Deno.env.get("dev") ? true : false;
let hosted = import.meta.resolve("./");
const Path = {
Hosted: hosted.substring(0, hosted.length-1),
Active: `file://${Deno.cwd().replaceAll("\\", "/")}`,
- LibDir: "lib"
+ LibDir: "lib",
+ AppDir: ""
};
console.log(Path);
console.log(`Dev Mode: ${DevMode}`);
-console.log(`Args seen: `, Flags);
+console.log(`Args seen: `, Deno.env.toObject);
-const {Transpileable, TranspileURL, SocketsHandler} = Transpiler(DevMode);
-const {Imports, App, TwindInst, Error} = await Configure(DevMode, Path.LibDir);
-if(Error)
+
+let Booted = false;
+let TwindInst:Twind.Twind;
+export function Boot(inApp:React.FunctionComponent, inCSS?:object)
{
- console.log(Error);
+ if(Booted){return;}
+ Booted = true;
+
+ const pathInit = Deno.mainModule;
+ const pathProj = toFileUrl(Deno.cwd());
+
+ //@ts-ignore
+ TwindInst = Twind.install({...Iso.CSS, ...inCSS||{}});
+
+ const App = inApp;
+ Path.AppDir = pathInit.split(pathProj.toString())[1];
+
+ Server(App, Path.AppDir, TwindInst);
}
-else if(App && TwindInst)
+
+async function Server(App:React.FunctionComponent, AppPath:string, TwindInst:Twind.Twind)
{
- Deno.serve({ port: Flags?.port||3000 }, async(_req:Request) =>
+ const {Transpileable, TranspileURL, SocketsHandler} = Transpiler(DevMode);
+ const {Imports, Error} = await Configure(DevMode, Path.LibDir);
+ if(Error)
{
- const url:URL = new URL(_req.url);
- const pathParts = url.pathname.substring(1, url.pathname.endsWith("/") ? url.pathname.length-1 : url.pathname.length).split("/");
- const pathLast = pathParts.at(-1);
- const pathExt:string|undefined = pathLast?.split(".")[1];
-
- const resp = SocketsHandler(_req);
- if(resp){ return resp; }
-
- try
+ console.log(Error);
+ }
+ else if(App && TwindInst)
+ {
+ Deno.serve({ port: Deno.env.get("port")||3000 }, async(_req:Request) =>
{
- // serve index by default
- let type = `text/html`;
- let body:BodyInit = ``;
-
- const isLib = url.pathname.startsWith(`/${Path.LibDir}/`);
-
- if(Transpileable(url.pathname))
+ const url:URL = new URL(_req.url);
+ const pathParts = url.pathname.substring(1, url.pathname.endsWith("/") ? url.pathname.length-1 : url.pathname.length).split("/");
+ const pathLast = pathParts.at(-1);
+ const pathExt:string|undefined = pathLast?.split(".")[1];
+
+ const resp = SocketsHandler(_req);
+ if(resp){ return resp; }
+
+ console.log(url.pathname);
+
+ try
{
- type = `application/javascript`;
- if(isLib)
+ // serve index by default
+ let type = `text/html`;
+ let body:BodyInit = ``;
+
+ const isLib = url.pathname.startsWith(`/${Path.LibDir}/`);
+
+ if(Transpileable(url.pathname))
{
- body = await TranspileURL(Path.Hosted+url.pathname, url.pathname, true);
+ type = `application/javascript`;
+ if(isLib)
+ {
+ body = await TranspileURL(Path.Hosted+url.pathname, url.pathname, true);
+ }
+ else if(url.pathname == "/server.tsx")
+ {
+body = `
+
+import {hydrate, createElement as H} from "react";
+import * as Twind from "https://esm.sh/v115/@twind/core@1.1.3/es2022/core.mjs";
+import {Router, CSS, Meta} from "@eno/iso";
+export function Boot(inApp, inCSS)
+{
+ console.log(inApp, inCSS);
+ Twind.install(inCSS ? {...CSS, ...inCSS} : CSS);
+
+ const hmrWrap = H( ()=>H(inApp) );
+ hydrate(
+ H(Router.Provider, {url:window.location},
+ H(Meta.Provider, null, hmrWrap)
+ ),
+ document.querySelector("#app")
+ );
+
+}`;
+ }
+ else if(DevMode && !url.searchParams.get("reload"))
+ {
+ const imp = await import(Path.Active+url.pathname);
+ const members = [];
+ for( const key in imp ) { members.push(key); }
+ body =
+ `
+ import {FileListen} from "/${Path.LibDir}/hmr.tsx";
+ import * as Import from "${url.pathname}?reload=0";
+ ${ members.map(m=>`let proxy_${m} = Import.${m};
+ export { proxy_${m} as ${m} };
+ `).join(" ") }
+ const reloadHandler = (updatedModule)=>
+ {
+ ${ members.map(m=>`proxy_${m} = updatedModule.${m};`).join("\n") }
+ };
+ FileListen("${url.pathname}", reloadHandler);`;
+
+ }
+ else
+ {
+ body = await TranspileURL(Path.Active+url.pathname, url.pathname, true);
+ }
}
- else if(DevMode && !url.searchParams.get("reload"))
+ // serve static media
+ else if( pathExt )
{
- const imp = await import(Path.Active+url.pathname);
- const members = [];
- for( const key in imp ) { members.push(key); }
- body =
- `
- import {FileListen} from "/${Path.LibDir}/hmr.tsx";
- import * as Import from "${url.pathname}?reload=0";
- ${ members.map(m=>`let proxy_${m} = Import.${m};
- export { proxy_${m} as ${m} };
- `).join(" ") }
- const reloadHandler = (updatedModule)=>
- {
- ${ members.map(m=>`proxy_${m} = updatedModule.${m};`).join("\n") }
- };
- FileListen("${url.pathname}", reloadHandler);`;
-
+ type = MIME.typeByExtension(pathExt) || "text/html";
+ const _fetch = await fetch((Path.Active)+url.pathname);
+ body = await _fetch.text();
}
else
{
- body = await TranspileURL(Path.Active+url.pathname, url.pathname, true);
- }
- }
- // serve static media
- else if( pathExt )
- {
- type = MIME.typeByExtension(pathExt) || "text/html";
- const _fetch = await fetch((Path.Active)+url.pathname);
- body = await _fetch.text();
- }
- else
- {
- Iso.Fetch.ServerBlocking = [];
- Iso.Fetch.ServerTouched = new Set();
- Iso.Fetch.ServerRemove = new Set();
- let app = ;
- await Prepass(app)
- let bake = SSR(app);
- while(Iso.Fetch.ServerBlocking.length)
- {
- await Promise.all(Iso.Fetch.ServerBlocking);
Iso.Fetch.ServerBlocking = [];
- // at this point, anything that was requested that was not cached, has now been loaded and cached
- // this next render will use cached resources. using a cached resource (if its "Seed" is true) adds it to the "touched" set.
- app = ;
+ Iso.Fetch.ServerTouched = new Set();
+ Iso.Fetch.ServerRemove = new Set();
+ let app = ;
await Prepass(app)
- bake = SSR(app);
+ let bake = SSR(app);
+ while(Iso.Fetch.ServerBlocking.length)
+ {
+ await Promise.all(Iso.Fetch.ServerBlocking);
+ Iso.Fetch.ServerBlocking = [];
+ // at this point, anything that was requested that was not cached, has now been loaded and cached
+ // this next render will use cached resources. using a cached resource (if its "Seed" is true) adds it to the "touched" set.
+ app = ;
+ await Prepass(app)
+ bake = SSR(app);
+ }
+
+ const seed:Iso.FetchRecord[] = [];
+ Iso.Fetch.ServerTouched.forEach((record)=>{
+ const r:Iso.FetchRecord = {...record};
+ delete r.Promise;
+ seed.push(r);
+ });
+ Iso.Fetch.ServerTouched = false;
+
+ const results = Twind.extract(bake, TwindInst);
+
+ type = `text/html`;
+ body =
+ `
+
+
+ ${Iso.Meta.Meta.title}
+
+
+
+
+
+
+ ${results.html}
+
+
+ `;
}
-
- const seed:Iso.FetchRecord[] = [];
- Iso.Fetch.ServerTouched.forEach((record)=>{
- const r:Iso.FetchRecord = {...record};
- delete r.Promise;
- seed.push(r);
- });
- Iso.Fetch.ServerTouched = false;
-
- const results = Twind.extract(bake, TwindInst);
-
- type = `text/html`;
- body =
- `
-
-
- ${Iso.Meta.Meta.title}
-
-
-
-
-
-
- ${results.html}
-
-
- `;
+
+ return new Response(body, {headers:{"content-type":type as string, "Access-Control-Allow-Origin":"*", charset:"utf-8"}});
}
-
- return new Response(body, {headers:{"content-type":type as string, "Access-Control-Allow-Origin":"*", charset:"utf-8"}});
- }
- catch(error)
- {
- console.log(error);
- return new Response(error, {status:404});
- }
- });
-}
\ No newline at end of file
+ catch(error)
+ {
+ console.log(error);
+ return new Response(error, {status:404});
+ }
+ });
+ }
+}