#!/usr/bin/env node // Transpiles all .js files under a directory (in place) to syntax supported // by nodejs-mobile-cordova's embedded Node 12.19 — primarily optional // chaining (?.) and nullish coalescing (??) used by some npm dependencies // and by this project's own source. // // Usage: node transpile-node12.js [ ...] 'use strict'; const fs = require('fs'); const path = require('path'); // Resolve esbuild from this project's own node_modules (no longer parent repo) const esbuild = require('esbuild'); const SKIP_DIRS = new Set(['.bin']); function walk(dir, cb) { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { if (SKIP_DIRS.has(entry.name)) continue; const full = path.join(dir, entry.name); if (entry.isSymbolicLink()) continue; if (entry.isDirectory()) { walk(full, cb); } else if (entry.name.endsWith('.js') || entry.name.endsWith('.cjs') || entry.name === 'package.json') { cb(full); } } } let count = 0; let pkgCount = 0; for (const dir of process.argv.slice(2)) { if (!fs.existsSync(dir)) continue; walk(dir, (file) => { if (path.basename(file) === 'package.json') { // esbuild converts ESM (import/export) to CJS (module.exports) below, // but Node still treats .js files as ES modules if the nearest // package.json has "type": "module" — drop that so the converted // CJS output is loaded correctly under Node 12. const pkg = JSON.parse(fs.readFileSync(file, 'utf8')); if (pkg.type === 'module') { delete pkg.type; fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + '\n'); pkgCount++; } return; } const src = fs.readFileSync(file, 'utf8'); let out; try { out = esbuild.transformSync(src, { target: 'node12', format: 'cjs', loader: 'js' }).code; } catch (err) { console.warn(`Skipping ${file}: ${err.message.split('\n')[0]}`); return; } // Node 12 doesn't understand the "node:" builtin-module prefix // (added in Node 14.18/16), used by some dependencies (e.g. express-rate-limit). out = out.replace(/require\((['"])node:([a-z/_-]+)\1\)/g, "require($1$2$1)"); if (out !== src) { fs.writeFileSync(file, out); count++; } }); } console.log(`Transpiled ${count} file(s) and dropped "type": "module" from ${pkgCount} package.json file(s) for Node 12 compatibility.`);