|
| 1 | +/** |
| 2 | + * Post-build script: rewrites extensionless relative imports in the server |
| 3 | + * package's dist/ output to include explicit ".js" extensions. |
| 4 | + * |
| 5 | + * Keep this package-local so the server feature does not change the existing |
| 6 | + * root-level core rewrite script. |
| 7 | + */ |
| 8 | +import { existsSync, readFileSync, writeFileSync } from "node:fs"; |
| 9 | +import { dirname, join } from "node:path"; |
| 10 | +import { fileURLToPath } from "node:url"; |
| 11 | +import { globSync } from "glob"; |
| 12 | + |
| 13 | +const __dirname = dirname(fileURLToPath(import.meta.url)); |
| 14 | +const packageRoot = join(__dirname, ".."); |
| 15 | +const distDir = join(packageRoot, "dist"); |
| 16 | + |
| 17 | +if (!existsSync(distDir)) { |
| 18 | + throw new Error(`Cannot rewrite server ESM imports because dist directory does not exist: ${distDir}`); |
| 19 | +} |
| 20 | + |
| 21 | +const files = globSync("**/*.js", { cwd: distDir, absolute: true }); |
| 22 | + |
| 23 | +// Match: from "./anything" or from "../anything" |
| 24 | +// Negative lookahead: skip if already ends with .js, .json, .node, or is a bare specifier |
| 25 | +const IMPORT_RE = /(from\s+["'])(\.\.?\/[^"']+?)(?<!\.[a-zA-Z0-9]{1,4})(["'])/g; |
| 26 | + |
| 27 | +let totalRewrites = 0; |
| 28 | + |
| 29 | +for (const filePath of files) { |
| 30 | + const original = readFileSync(filePath, "utf8"); |
| 31 | + let rewrites = 0; |
| 32 | + |
| 33 | + const updated = original.replace(IMPORT_RE, (_match, prefix, specifier, quote) => { |
| 34 | + rewrites++; |
| 35 | + return `${prefix}${specifier}.js${quote}`; |
| 36 | + }); |
| 37 | + |
| 38 | + if (rewrites > 0) { |
| 39 | + writeFileSync(filePath, updated, "utf8"); |
| 40 | + totalRewrites += rewrites; |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +console.log(`\n✅ Rewrote ${totalRewrites} imports across ${files.length} files in server/dist/\n`); |
0 commit comments