#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const { promisify } = require('util'); const readdir = promisify(fs.readdir); const readFile = promisify(fs.readFile); const writeFile = promisify(fs.writeFile); const stat = promisify(fs.stat); // Regex to match import statements with relative paths without extensions const importRegex = /import\s+(?:(?:[\w*\s{},]*)\s+from\s+)?['"](\.[^'"]*)['"]/g; async function processFile(filePath) { try { // Read file content const content = await readFile(filePath, 'utf8'); // Skip files that are already processed or don't need processing if (!content.match(importRegex)) { return { filePath, changed: false }; } // Replace imports without extensions let modifiedContent = content.replace(importRegex, (match, importPath) => { // Skip if already has an extension if (path.extname(importPath)) { return match; } // Add .js extension return match.replace(importPath, `${importPath}.js`); }); // Only write if content changed if (content !== modifiedContent) { await writeFile(filePath, modifiedContent, 'utf8'); return { filePath, changed: true }; } return { filePath, changed: false }; } catch (error) { return { filePath, error: error.message }; } } async function walkDir(dir, fileTypes = ['.ts', '.tsx', '.js', '.jsx']) { const entries = await readdir(dir, { withFileTypes: true }); const files = []; for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { // Skip node_modules and .git directories if (entry.name !== 'node_modules' && entry.name !== '.git') { files.push(...await walkDir(fullPath, fileTypes)); } } else if (entry.isFile()) { const ext = path.extname(entry.name); if (fileTypes.includes(ext)) { files.push(fullPath); } } } return files; } async function main() { const rootDir = process.argv[2] || path.resolve(process.cwd(), 'src'); console.log(`Scanning directory: ${rootDir}`); try { const files = await walkDir(rootDir); console.log(`Found ${files.length} files to process`); const results = await Promise.all(files.map(processFile)); // Collect statistics const changed = results.filter(r => r.changed); const errors = results.filter(r => r.error); console.log('\nSummary:'); console.log(`- Total files scanned: ${files.length}`); console.log(`- Files modified: ${changed.length}`); console.log(`- Errors encountered: ${errors.length}`); if (changed.length > 0) { console.log('\nModified files:'); changed.forEach(({ filePath }) => { console.log(`- ${path.relative(process.cwd(), filePath)}`); }); } if (errors.length > 0) { console.log('\nErrors:'); errors.forEach(({ filePath, error }) => { console.log(`- ${path.relative(process.cwd(), filePath)}: ${error}`); }); } } catch (error) { console.error('Error:', error.message); process.exit(1); } } main().catch(console.error);