2023-08-12 20:30:44 -04:00
|
|
|
import { parse as JSONC } from "https://deno.land/x/jsonct@v0.1.0/mod.ts";
|
|
|
|
|
|
|
|
type ConfigCheck = {path?:string, text?:string, json?:Record<string, string|Record<string, string|string[]>>};
|
|
|
|
type ConfigCheckPair = [config:ConfigCheck, imports:ConfigCheck];
|
|
|
|
|
|
|
|
export const RootHost = import.meta.resolve("./");
|
|
|
|
export const Root = new URL(`file://${Deno.cwd().replaceAll("\\", "/")}`).toString();
|
|
|
|
export async function HuntConfig()
|
|
|
|
{
|
2023-09-24 09:19:50 -04:00
|
|
|
console.log("hunting in", Root);
|
2023-08-12 20:30:44 -04:00
|
|
|
let path:string, resp:Response, text="", json;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
path = "deno.json"
|
|
|
|
resp = await fetch(Root + "/" + path);
|
|
|
|
text = await resp.text();
|
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
path = "deno.jsonc";
|
|
|
|
resp = await fetch(Root + "/" + path);
|
|
|
|
text = await resp.text();
|
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
path = ".vscode/settings.json";
|
|
|
|
resp = await fetch(Root + "/" + path);
|
|
|
|
json = await resp.json();
|
2023-08-13 11:00:48 -04:00
|
|
|
|
2023-08-12 20:30:44 -04:00
|
|
|
path = json["deno.config"];
|
|
|
|
json = undefined;
|
|
|
|
if(path)
|
|
|
|
{
|
|
|
|
resp = await fetch(Root + "/" + path);
|
|
|
|
text = await resp.text();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
path = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-13 11:00:48 -04:00
|
|
|
if(path)
|
2023-08-12 20:30:44 -04:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
json = JSONC(text);
|
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
json = undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let imports:ConfigCheck = {};
|
|
|
|
if(json && json.imports)
|
|
|
|
{
|
2023-08-13 11:00:48 -04:00
|
|
|
// config.imports
|
2023-08-12 20:30:44 -04:00
|
|
|
imports.json = json;
|
|
|
|
imports.text = JSON.stringify(json);
|
|
|
|
imports.path = path;
|
|
|
|
}
|
|
|
|
else if(json && !json.imports && json.importMap)
|
|
|
|
{
|
2023-08-13 11:00:48 -04:00
|
|
|
// config.importMap
|
2023-08-12 20:30:44 -04:00
|
|
|
try
|
|
|
|
{
|
|
|
|
imports.path = json.importMap;
|
|
|
|
resp = await fetch(Root + "/" + imports.path);
|
|
|
|
imports.text = await resp.text();
|
2023-08-13 11:00:48 -04:00
|
|
|
try
|
|
|
|
{
|
|
|
|
imports.json = JSONC(imports.text);
|
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
imports.json = undefined;
|
|
|
|
}
|
2023-08-12 20:30:44 -04:00
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
// malformed import map
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return [{path, text, json}, imports] as ConfigCheckPair
|
|
|
|
}
|
|
|
|
|
2023-08-13 11:00:48 -04:00
|
|
|
export async function Install(file:string, overrideName?:string, handler?:(content:string)=>string)
|
2023-08-12 20:30:44 -04:00
|
|
|
{
|
|
|
|
const pathFile = RootHost + "install__/" + file;
|
|
|
|
|
|
|
|
try{
|
|
|
|
const check = await Deno.readTextFile(Deno.cwd()+"/"+file);
|
|
|
|
const replace = confirm(`⚠️🚧 The file "${file}" already exists. Replace it?`);
|
|
|
|
if(replace)
|
|
|
|
{
|
|
|
|
throw("")
|
|
|
|
}
|
|
|
|
console.log(`Using pre-existing "${file}" for now.`);
|
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
const resp = await fetch(pathFile);
|
|
|
|
const text = await resp.text();
|
2023-08-13 11:00:48 -04:00
|
|
|
const name = overrideName || file;
|
|
|
|
await Deno.writeTextFile(Deno.cwd()+"/"+name, handler ? handler(text) : text);
|
2023-08-12 20:30:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function Check()
|
|
|
|
{
|
2023-08-28 22:16:56 -04:00
|
|
|
let [config, imports] = await HuntConfig();
|
2023-08-12 20:30:44 -04:00
|
|
|
try
|
|
|
|
{
|
2023-08-28 22:16:56 -04:00
|
|
|
|
2023-08-13 11:00:48 -04:00
|
|
|
//console.log(config, imports);
|
2023-08-12 20:30:44 -04:00
|
|
|
if(!config.path)
|
|
|
|
{
|
2023-09-24 09:19:50 -04:00
|
|
|
console.log(`🛠️ No Deno configuration found. Creating "deno.json" now.`);
|
|
|
|
await Deno.writeTextFile(Deno.cwd()+"/deno.json", `{"imports":{}}`);
|
2023-08-13 11:00:48 -04:00
|
|
|
Check();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(!config.json)
|
|
|
|
{
|
|
|
|
if(confirm(`🚧 Deno configuration is malformed. Replace "${config.path}" with a new one?.`))
|
2023-08-12 20:30:44 -04:00
|
|
|
{
|
2023-08-13 11:00:48 -04:00
|
|
|
await Deno.writeTextFile(Deno.cwd()+"/"+config.path, `{"imports":{}}`);
|
2023-08-12 20:30:44 -04:00
|
|
|
Check();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-08-13 11:00:48 -04:00
|
|
|
throw("⛔ Invalid configuration.");
|
2023-08-12 20:30:44 -04:00
|
|
|
}
|
|
|
|
}
|
2023-08-13 11:00:48 -04:00
|
|
|
else if(!imports.json)
|
|
|
|
{
|
|
|
|
if(imports.path != config.path)
|
2023-08-12 20:30:44 -04:00
|
|
|
{
|
2023-08-13 11:00:48 -04:00
|
|
|
if(confirm(`🚧 External import map "${imports.path}" is missing or malformed. Replace it with defaults?.`))
|
|
|
|
{
|
|
|
|
await Deno.writeTextFile(Deno.cwd()+"/"+imports.path, `{"imports":{}}`);
|
|
|
|
Check();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw("⛔ Invalid configuration.");
|
|
|
|
}
|
2023-08-12 20:30:44 -04:00
|
|
|
}
|
|
|
|
}
|
2023-08-13 11:00:48 -04:00
|
|
|
else if(!imports.json?.imports)
|
|
|
|
{
|
|
|
|
imports.json.imports = {};
|
|
|
|
}
|
2023-08-12 20:30:44 -04:00
|
|
|
|
2023-08-13 11:00:48 -04:00
|
|
|
if(config.json && imports.json?.imports)
|
2023-08-12 20:30:44 -04:00
|
|
|
{
|
|
|
|
const importMap = imports.json.imports as Record<string, string>;
|
2023-08-13 11:00:48 -04:00
|
|
|
const bake =async(obj:ConfigCheck)=> await Deno.writeTextFile(Deno.cwd()+"/"+obj.path, JSON.stringify(obj.json, null, "\t"));
|
2023-08-12 20:30:44 -04:00
|
|
|
|
2023-10-14 23:47:20 -04:00
|
|
|
importMap["react"] = `https://esm.sh/preact@10.18.1/compat`;
|
|
|
|
importMap["react/"] = `https://esm.sh/preact@10.18.1/compat/`;
|
2023-09-24 09:19:50 -04:00
|
|
|
importMap["@preact/signals"] = `https://esm.sh/@preact/signals@1.2.1`;
|
2023-10-12 22:47:45 -04:00
|
|
|
importMap["@twind/core"] = `https://esm.sh/@twind/core@1.1.3`;
|
2023-09-24 09:19:50 -04:00
|
|
|
importMap[">able/"] = `${RootHost}`;
|
|
|
|
if(!importMap[">able/app.tsx"])
|
2023-08-12 20:30:44 -04:00
|
|
|
{
|
2023-09-24 09:19:50 -04:00
|
|
|
importMap[">able/app.tsx"] = `./app.tsx`;
|
|
|
|
await Install("app.tsx");
|
2023-08-12 20:30:44 -04:00
|
|
|
}
|
2023-09-24 09:19:50 -04:00
|
|
|
if(!importMap[">able/api.tsx"])
|
2023-08-12 20:30:44 -04:00
|
|
|
{
|
2023-09-24 09:19:50 -04:00
|
|
|
if(confirm(`🤔 OPTIONAL: Add backend ">able/api.tsx"?`))
|
|
|
|
{
|
|
|
|
importMap[">able/api.tsx"] = "./api.tsx";
|
|
|
|
await Install("api.tsx");
|
|
|
|
}
|
2023-08-12 20:30:44 -04:00
|
|
|
}
|
2023-08-13 11:00:48 -04:00
|
|
|
|
2023-08-28 22:16:56 -04:00
|
|
|
const tasks:Record<string, string> = {
|
|
|
|
"check": `deno run -A --no-lock ${RootHost}cli.tsx check`,
|
|
|
|
"local": `deno run -A --no-lock ${RootHost}cli.tsx local`,
|
|
|
|
"debug": `deno run -A --no-lock ${RootHost}cli.tsx debug`,
|
|
|
|
"serve": `deno run -A --no-lock ${RootHost}cli.tsx serve`,
|
|
|
|
"cloud": `deno run -A --no-lock ${RootHost}cli.tsx cloud`
|
|
|
|
};
|
|
|
|
const confTasks = (config.json.tasks || {}) as Record<string, string>;
|
2023-09-24 09:19:50 -04:00
|
|
|
config.json.tasks = {...confTasks, ...tasks};
|
2023-08-28 22:16:56 -04:00
|
|
|
|
2023-10-14 12:06:11 -04:00
|
|
|
const optionsRequired =
|
2023-08-28 22:16:56 -04:00
|
|
|
{
|
2023-10-14 12:06:11 -04:00
|
|
|
"lib": ["deno.window", "dom", "dom.iterable", "dom.asynciterable"],
|
2023-08-28 22:16:56 -04:00
|
|
|
"jsx": "react-jsx",
|
|
|
|
"jsxImportSource": "react"
|
|
|
|
}
|
2023-10-14 12:06:11 -04:00
|
|
|
const optionsCurrent = config.json.compilerOptions as Record<string, string|string[]> || {};
|
|
|
|
//const compLib:string[] = compOpts.lib as string[] || [];
|
|
|
|
|
|
|
|
if(!optionsCurrent.lib)
|
|
|
|
{
|
|
|
|
optionsCurrent.lib = [];
|
|
|
|
}
|
|
|
|
optionsRequired.lib.forEach(s=>
|
|
|
|
{
|
|
|
|
if(!optionsCurrent.lib.includes(s))
|
|
|
|
{
|
|
|
|
(optionsCurrent.lib as string[]).push(s);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
optionsCurrent.jsx = optionsRequired.jsx;
|
|
|
|
optionsCurrent.jsxImportSource = optionsRequired.jsxImportSource;
|
|
|
|
config.json.compilerOptions = optionsCurrent;
|
2023-08-13 11:00:48 -04:00
|
|
|
|
2023-09-24 09:19:50 -04:00
|
|
|
await bake(imports);
|
|
|
|
await bake(config);
|
2023-08-12 20:30:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(e)
|
|
|
|
{
|
|
|
|
console.log(e, "\n (Able Exiting...)");
|
|
|
|
Deno.exit();
|
|
|
|
}
|
|
|
|
console.log(`🚗 Good to go!`);
|
|
|
|
|
2023-08-28 22:16:56 -04:00
|
|
|
}
|