#!/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 <dir> [<dir> ...]

'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.`);