| 30 | } |
| 31 | |
| 32 | function copyRecursiveSync(src, dest) { |
| 33 | if (!fs.existsSync(src)) return; |
| 34 | // statSync (not lstatSync) follows symlinks — so symlinked source dirs |
| 35 | // dereference into real copies at the destination. |
| 36 | const stats = fs.statSync(src); |
| 37 | if (stats.isDirectory()) { |
| 38 | if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true }); |
| 39 | for (const child of fs.readdirSync(src)) { |
| 40 | copyRecursiveSync(path.join(src, child), path.join(dest, child)); |
| 41 | } |
| 42 | } else { |
| 43 | fs.copyFileSync(src, dest); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | function ensureDir(p) { |
| 48 | if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true }); |