gitignore-synthesizer
Version:
Generate smart .gitignore files based on your project's actual contents
94 lines (75 loc) • 3.04 kB
JavaScript
import fs from 'fs/promises';
import path from 'path';
import inquirer from 'inquirer';
import { detectFrameworks } from './lib/detectFrameworks.js';
import { fetchGitignoreTemplate } from './lib/fetchTemplate.js';
import { scanFiles } from './lib/scanFiles.js';
import { mergeGitignore } from './lib/mergeGitignore.js';
import { backupGitignore } from './lib/backup.js';
import { setVerbose, log, warn, error } from './lib/logger.js';
async function main() {
const projectDir = process.cwd();
const args = process.argv.slice(2);
const verbose = args.includes('--verbose') || args.includes('-v');
setVerbose(verbose);
log('Detecting frameworks and files...');
const detectedFrameworks = await detectFrameworks(projectDir);
log('Detected:', detectedFrameworks.join(', ') || 'None');
// Ask user to confirm detected or add more
const { selectedFrameworks } = await inquirer.prompt([{
type: 'checkbox',
name: 'selectedFrameworks',
message: 'Select the frameworks/languages to include in .gitignore',
choices: detectedFrameworks.length > 0 ? detectedFrameworks : Object.keys(require('./lib/detectFrameworks.js').frameworkFiles),
default: detectedFrameworks,
}]);
// Scan for common files to ignore (env, IDE files)
const commonIgnores = await scanFiles();
log('Detected common ignore files:', commonIgnores.join(', ') || 'None');
// Fetch templates for selected frameworks
let combinedGitignore = '';
for (const fw of selectedFrameworks) {
log(`Fetching template for ${fw}...`);
const tpl = await fetchGitignoreTemplate(fw);
combinedGitignore += `# ${fw} .gitignore\n${tpl}\n\n`;
}
// Append common ignores
if (commonIgnores.length) {
combinedGitignore += '# Common ignores\n' + commonIgnores.join('\n') + '\n';
}
// Read existing .gitignore if exists
let existingGitignore = '';
try {
existingGitignore = await fs.readFile(path.join(projectDir, '.gitignore'), 'utf-8');
} catch {}
// Merge intelligently
const merged = mergeGitignore(existingGitignore, combinedGitignore);
// Preview
console.log('\n===== Generated .gitignore Preview =====\n');
console.log(merged);
console.log('========================================\n');
// Confirm before writing
const { confirmWrite } = await inquirer.prompt([{
type: 'confirm',
name: 'confirmWrite',
message: 'Write above content to .gitignore? (existing will be backed up)',
default: true,
}]);
if (!confirmWrite) {
warn('Aborted by user.');
process.exit(0);
}
// Backup existing
const backupName = await backupGitignore(projectDir);
if (backupName) {
log(`Backed up existing .gitignore to ${backupName}`);
}
// Write new .gitignore
await fs.writeFile(path.join(projectDir, '.gitignore'), merged, 'utf-8');
log('.gitignore updated successfully.');
}
main().catch(err => {
error('Error:', err);
process.exit(1);
});