diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8fba44c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +examples/* +!*.gen.ts +!*.gen.js \ No newline at end of file diff --git a/README.md b/README.md index 118308c..70544ea 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # codegen +Use: + +```sh +deno run --allow-read --allow-write src/codegen.ts +``` \ No newline at end of file diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..54141c7 --- /dev/null +++ b/deno.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "lib": ["deno.ns", "DOM"], + "strict": true + }, + "include": ["src"], + "tasks": {}, + "imports": {}, + "fmt": { + "useTabs": true + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..8730971 --- /dev/null +++ b/deno.lock @@ -0,0 +1,19 @@ +{ + "version": "4", + "specifiers": { + "jsr:@std/fs@*": "1.0.6", + "jsr:@std/path@*": "1.0.8", + "jsr:@std/path@^1.0.8": "1.0.8" + }, + "jsr": { + "@std/fs@1.0.6": { + "integrity": "42b56e1e41b75583a21d5a37f6a6a27de9f510bcd36c0c85791d685ca0b85fa2", + "dependencies": [ + "jsr:@std/path@^1.0.8" + ] + }, + "@std/path@1.0.8": { + "integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be" + } + } +} diff --git a/examples/sample.gen.ts b/examples/sample.gen.ts new file mode 100644 index 0000000..131b29a --- /dev/null +++ b/examples/sample.gen.ts @@ -0,0 +1,3 @@ +export default () => { + return `console.log("Hello, World!");`; +}; diff --git a/examples/somethingEarly.gen.ts b/examples/somethingEarly.gen.ts new file mode 100644 index 0000000..015818b --- /dev/null +++ b/examples/somethingEarly.gen.ts @@ -0,0 +1,3 @@ +export default () => { + return `export const five = 5;`; +}; diff --git a/examples/somethingLate.gen.ts b/examples/somethingLate.gen.ts new file mode 100644 index 0000000..514248b --- /dev/null +++ b/examples/somethingLate.gen.ts @@ -0,0 +1,4 @@ +export default async (context: any) => { + const { five } = await context.import("./somethingEarly.ts"); + return five.toString(); +}; diff --git a/src/codegen.ts b/src/codegen.ts new file mode 100644 index 0000000..e1d55f5 --- /dev/null +++ b/src/codegen.ts @@ -0,0 +1,55 @@ +import * as path from "jsr:@std/path"; + +const root = Deno.cwd(); + +const getAllFiles = async (dir: string) => { + const localEntries = await Array.fromAsync(Deno.readDir(dir)); + const entries = localEntries.filter((e) => e.isFile).map((e) => e.name); + for (const entry of localEntries) { + if ( + entry.isDirectory && + !entry.isSymlink && + !entry.name.startsWith(".") + ) { + entries.push( + ...(await getAllFiles(entry.name)).map((fname) => + path.join(entry.name, fname) + ) + ); + } + } + return entries; +}; + +const getFilesToGenFrom = async () => { + const allFiles = await getAllFiles(root); + return allFiles + .filter( + (fname) => fname.endsWith(".gen.ts") || fname.endsWith(".gen.js") + ) + .map((fname) => path.join(root, fname)); +}; + +const filesBeingGenned: Record> = {}; + +const genFromFile = async (fname: string) => { + const context = { + async import(moduleName: string) { + const fullname = path.resolve(path.dirname(fname), moduleName); + await filesBeingGenned[fullname]; + return import(fullname); + }, + }; + type CodegenContext = typeof context; + const brain: (context: CodegenContext) => string | Promise = ( + await import(fname) + ).default; + const fileToWrite = fname.replace(/\.gen\.[tj]sx?$/, (ext) => + ext.slice(".gen".length) + ); + Deno.writeTextFile(fileToWrite, await brain(context)); +}; + +for (const file of await getFilesToGenFrom()) { + filesBeingGenned[file] = genFromFile(file); +}