| 3 | import { fileURLToPath } from 'node:url'; |
| 4 | |
| 5 | export async function compileDevTemplates() { |
| 6 | const dirRoot = new URL('../', import.meta.url); |
| 7 | |
| 8 | // Compile the `doT.js` template files for `vercel dev` |
| 9 | const templatesDirURL = new URL('src/util/dev/templates/', dirRoot); |
| 10 | doT.process({ path: fileURLToPath(templatesDirURL) }); |
| 11 | |
| 12 | const files = await readdir(templatesDirURL); |
| 13 | const compiledFiles = files.filter(f => f.endsWith('.js')); |
| 14 | |
| 15 | for (const file of compiledFiles) { |
| 16 | const fnPath = new URL(file, templatesDirURL); |
| 17 | const cjsPath = new URL(file.replace(/\.js$/, '.cjs'), templatesDirURL); |
| 18 | const tsPath = fnPath.href.replace(/\.js$/, '.ts'); |
| 19 | const def = await readFile( |
| 20 | new URL(fnPath.href.replace(/\.js$/, '.tsdef')), |
| 21 | 'utf8' |
| 22 | ); |
| 23 | const interfaceName = def.match(/interface (\w+)/)[1]; |
| 24 | |
| 25 | // doT generates CommonJS code, but since this is an ESM package (.js files |
| 26 | // are treated as ESM), we rename to .cjs so Node.js treats it as CommonJS. |
| 27 | // After extracting the function, we delete the temp .cjs file since we're |
| 28 | // generating a TypeScript version instead. |
| 29 | await rename(fnPath, cjsPath); |
| 30 | const mod = await import(cjsPath.href); |
| 31 | const fn = mod.default; |
| 32 | await unlink(cjsPath); |
| 33 | |
| 34 | const contents = `import encodeHTML from 'escape-html'; |
| 35 | |
| 36 | ${def} |
| 37 | export default ${fn |
| 38 | .toString() |
| 39 | .replace(/var encodeHTML.+\(\)\);/s, '') |
| 40 | .replace(/\bvar\b/g, 'let') |
| 41 | .replace(/\(it\s*\)/s, `(it: ${interfaceName}): string`)}`; |
| 42 | |
| 43 | await writeFile(new URL(tsPath), contents); |
| 44 | } |
| 45 | } |