import * as path from "node:path"; import * as fs from "node:fs/promises"; import { tsImport } from "tsx/esm/api"; const root = process.cwd(); const getAllFiles = async (dir: string) => { const localEntries = await fs.readdir(dir, { withFileTypes: true }); const entries = localEntries.filter((e) => e.isFile()).map((e) => e.name); for (const entry of localEntries) { if ( entry.isDirectory() && !entry.isSymbolicLink() && !entry.name.startsWith(".") && entry.name !== "node_modules" ) { entries.push( ...(await getAllFiles(path.join(dir, 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")) .map((fname) => path.resolve(root, fname)); }; const filesBeingGenned: Record> = {}; const genFromFile = async (fname: string) => { console.log("Processing", fname); const context = { async import(moduleName: string) { const fullname = path.resolve(path.dirname(fname), moduleName); await filesBeingGenned[fullname]; return tsImport(fullname, import.meta.url); }, }; type CodegenContext = typeof context; const brain: (context: CodegenContext) => string | Promise = ( await tsImport(fname, import.meta.url) ).default; const fileToWrite = fname.replace(/\.gen\.ts?$/, ".out.ts"); await fs.writeFile(fileToWrite, await brain(context)); }; for (const file of await getFilesToGenFrom()) { filesBeingGenned[file] = genFromFile(file); }