#!/usr/bin/env node /** * One-shot refactor: replace every hardcoded `JWT_SECRET = process.env... * || 'africa-alert-secret-key-2024'` with `const { jwtSecret: JWT_SECRET } * = require('../config')` (or relative path appropriate to the file). * * Also rewrites inline `process.env.JWT_SECRET || 'africa-alert...'` * patterns inside `jwt.verify(...)` calls to use the config module. * * Idempotent: if the pattern is already converted, the file is left alone. * * Usage: `node server/scripts/refactor-jwt-secret.js [path1 path2 ...]` * If no paths given, operates on every server/src/*.js file. */ const fs = require('fs'); const path = require('path'); const HARD_CODED_LINE = /const\s+JWT_SECRET\s*=\s*process\.env\.JWT_SECRET\s*\|\|\s*'africa-alert-secret-key-2024'\s*;/g; const INLINE_PATTERN = /process\.env\.JWT_SECRET\s*\|\|\s*'africa-alert-secret-key-2024'/g; function relativeConfigRequire(filePath) { // file is in server/src/controllers/X.js or server/src/services/X.js // config is in server/src/config/index.js // require path is ../config from controllers/services, ./config from index.js if (filePath.endsWith('index.js') && /[\\/]server[\\/]src[\\/]index\.js$/.test(filePath)) { return './config'; } return '../config'; } function* walk(dir) { if (!fs.existsSync(dir)) return; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { if (entry.name === 'node_modules' || entry.name === 'config' || entry.name.startsWith('.')) continue; const full = path.join(dir, entry.name); if (entry.isDirectory()) { yield* walk(full); } else if (full.endsWith('.js')) { yield full; } } } function refactorFile(filePath) { const original = fs.readFileSync(filePath, 'utf8'); let content = original; const requirePath = relativeConfigRequire(filePath); // Pattern 1: top-level const JWT_SECRET = ... || 'africa-alert-...' content = content.replace(HARD_CODED_LINE, (match) => { // Preserve any leading whitespace const indent = (match.match(/^(\s*)/) || ['', ''])[1]; return `${indent}const { jwtSecret: JWT_SECRET } = require('${requirePath}');`; }); // Pattern 2: inline `process.env.JWT_SECRET || 'africa-alert-...'` inside jwt.verify(...) content = content.replace(INLINE_PATTERN, `require('${requirePath}').jwtSecret`); if (content !== original) { fs.writeFileSync(filePath, content); return true; } return false; } const args = process.argv.slice(2); const targets = args.length > 0 ? args : [path.join(__dirname, '..', 'src')]; let changed = 0; let visited = 0; for (const target of targets) { for (const file of walk(target)) { visited++; if (refactorFile(file)) { changed++; console.log(' refactored: ' + path.relative(process.cwd(), file)); } } } console.log(`\nDone. Visited ${visited} files, refactored ${changed}.`); console.log('Next: grep for "africa-alert-secret-key-2024" — should be 0 hits.');