cli #6

Merged
SethTrowbridge merged 11 commits from cli into master 2023-09-24 09:33:29 -04:00
2 changed files with 112 additions and 28 deletions
Showing only changes of commit c558ecb6d2 - Show all commits

133
cli.tsx
View File

@ -2,6 +2,9 @@ import { parse as JSONC } from "https://deno.land/x/jsonct@v0.1.0/mod.ts";
const RootFile = new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString(); const RootFile = new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString();
const RootHost = import.meta.resolve("./"); const RootHost = import.meta.resolve("./");
type ConfigCheck = {path?:string, text?:string, json?:Record<string, string|Record<string, string|string[]>>};
type ConfigCheckPair = [config:ConfigCheck, imports:ConfigCheck];
export async function HuntConfig() export async function HuntConfig()
{ {
let path:string, resp:Response, text="", json; let path:string, resp:Response, text="", json;
@ -30,7 +33,8 @@ export async function HuntConfig()
json = undefined; json = undefined;
if(path) if(path)
{ {
resp = await fetch(RootFile + "/" + path); path = RootFile + "/" + path
resp = await fetch(path);
text = await resp.text(); text = await resp.text();
} }
} }
@ -49,16 +53,33 @@ export async function HuntConfig()
} }
catch(e) catch(e)
{ {
// malformed json // malformed config
} }
} }
return {path, text, json}; let imports:ConfigCheck = {};
} if(json && json.imports)
{
export async function HuntImport() imports.json = json;
{ imports.text = JSON.stringify(json.imports);
imports.path = path;
}
else if(json && !json.imports && json.importMap)
{
try
{
imports.path = RootFile + "/" + json.importMap;
resp = await fetch(imports.path);
imports.text = await resp.text();
imports.json = JSONC(text);
}
catch(e)
{
// malformed import map
}
}
return [{path, text, json}, imports] as ConfigCheckPair
} }
async function Prompt(question: string):Promise<string> async function Prompt(question: string):Promise<string>
@ -120,16 +141,16 @@ export async function Install(file:string, handler:(content:string)=>string = (s
} }
} }
const config = await HuntConfig(); try
if(!config.path)
{ {
const pathServer = import.meta.resolve("./"); let [config, imports] = await HuntConfig();
try console.log(`1) Checking for Deno configuration...`)
if(!config.path)
{ {
const resp1 = await Prompt("No Deno configuration found. Create one? [y/n]"); const resp1 = await Prompt(" ! No Deno configuration found. Create one? [y/n]");
if(resp1 == "y") if(resp1 == "y")
{ {
const resp2 = await Prompt("Do you also want to add starter files? [y/n]"); const resp2 = await Prompt(" ? Do you also want to add starter files? [y/n]");
let replaceApp = "./path/to/app.tsx"; let replaceApp = "./path/to/app.tsx";
let replaceApi = "./path/to/api.tsx"; let replaceApi = "./path/to/api.tsx";
let replaceCommentApp = "// (required) module with default export ()=>React.JSX.Element"; let replaceCommentApp = "// (required) module with default export ()=>React.JSX.Element";
@ -144,6 +165,10 @@ if(!config.path)
await Install("app.tsx"); await Install("app.tsx");
await Install("api.tsx"); await Install("api.tsx");
} }
else
{
// config initialized with no app or api
}
await Install("deno.jsonc", (s)=>s await Install("deno.jsonc", (s)=>s
.replace("{{server}}", RootHost) .replace("{{server}}", RootHost)
@ -152,20 +177,80 @@ if(!config.path)
.replace("{{commentApp}}", replaceCommentApp) .replace("{{commentApp}}", replaceCommentApp)
.replace("{{commentApi}}", replaceCommentApi) .replace("{{commentApi}}", replaceCommentApi)
); );
[config, imports] = await HuntConfig();
} }
else else
{ {
throw("Config declined."); throw(" X Config is required.");
} }
}
catch(e)
{
console.log(e, "(Exiting...)");
Deno.exit();
}
}
else if(config.json)
{
}
/*
const inputString = `Some text 'imports' more text { some content }`;
const regex = /(?<=(['"`])imports\1[^{}]*{)/;
const match = inputString.search(regex);
if (match !== -1) {
console.log("Index of '{':", match);
} else {
console.log("'{': Not found.");
}
*/
console.log(`2) Verifying configuration...`)
if(config.json && imports.json?.imports)
{
const importMap = imports.json.imports as Record<string, string>;
let changes = false;
if(!importMap["react"])
{
const resp = await Prompt(` ! Import map has no specifier for React. Add it now? (will use Preact compat) [y/n]`);
if(resp == "y")
{
importMap["react"] = "https://esm.sh/preact@10.16.0/compat";
changes = true;
}
else
{
throw(" X A React import is required.");
}
}
if(!importMap[">able/"])
{
const resp = await Prompt(` ! Import map has no specifier for Able (">able/"). Add it now? [y/n]`);
if(resp == "y")
{
importMap[">able/"] = RootHost;
changes = true;
}
else
{
throw(" X Able is required.");
}
}
const compOpts = imports.json.compilerOptions as Record<string, string>;
if(compOpts)
{
const compJSX = compOpts["jsx"];
const compJSXImportSource = compOpts["jsxImportSource"]
if(compJSX || compJSXImportSource)
{
if(!importMap["react/"])
{
//const resp = await Prompt(` ! Import map has no specifier for React ("react"). Add it now? [y/n]`);
}
}
}
}
}
catch(e)
{
console.log(e, "\n (Able Exiting...)");
Deno.exit();
} }
console.log(config);

View File

@ -1,11 +1,10 @@
{ {
"imports": "imports":
{ {
"react":"https://esm.sh/preact@10.15.1/compat", // (required) Specifier for 'react'
"react/":"https://esm.sh/preact@10.15.1/compat/", // (conditional) This allows the use of JSX without explicitly importing React into a module. If you choose to remove this (and make importing react required), also remove "jsx" and "jsxImportSource" from "compilerOptions" (below) "react/":"https://esm.sh/preact@10.15.1/compat/", // (conditional) This allows the use of JSX without explicitly importing React into a module. If you choose to remove this (and make importing react required), also remove "jsx" and "jsxImportSource" from "compilerOptions" (below)
">able/": "http://localhost:4507/", // (required) Specifier 'able'. (See note below about "isomorphic proxies") ">able/": "file:///C:/Web%20Projects/able-baker/", // (required) Specifier 'able'. (See note below about "isomorphic proxies")
// (required) module with default export ()=>React.JSX.Element">able/app.tsx": "./path/to/app.tsx", ">able/app.tsx": "./app.tsx",
// (optional) module with default export (req:Request, url:URL)=>Promise<Response|false>">able/api.tsx": "./path/to/api.tsx" ">able/api.tsx": "./api.tsx"
}, },
"tasks": "tasks":