eslint-config-ai-swe
Version:
ESLint configuration optimized for AI Agents SWE with TypeScript and multi-framework support.
324 lines (281 loc) • 11.4 kB
JavaScript
#!/usr/bin/env node
import { Command } from 'commander';
import fs from 'fs';
import path from 'path';
import { detectFramework, suggestConfig } from './utils/framework-detector.js';
import { generateAgentsMd } from './utils/agents-md-generator.js';
import { installFrameworkDependencies, getMissingDependencies } from './utils/dependency-installer.js';
const program = new Command();
program
.name('eslint-config-ai-swe')
.description('CLI pour configurer et gérer le linter optimisé pour les AI Agents SWE.');
program
.command('setup')
.description('Génère un fichier eslint.config.js à la racine du projet.')
.option('-f, --force', 'Écrase le fichier existant')
.option('--ide', 'Configure également les paramètres IDE pour VS Code')
.option('--agents', 'Génère également le fichier AGENTS.md pour les agents IA')
.option('--install-deps', 'Installe automatiquement les dépendances optionnelles requises')
.option('--dry-run', 'Simule l\'installation sans rien installer')
.action(async (options) => {
console.log('🚀 Configuration de eslint-config-ai-swe...');
const { framework } = detectFramework();
const suggestedConfigs = suggestConfig(framework);
console.log(`📋 Framework détecté: ${framework}`);
console.log(`📦 Configurations suggérées: ${suggestedConfigs.join(', ')}`);
// Check for missing dependencies
const missingDeps = getMissingDependencies(framework);
if (missingDeps.length > 0) {
console.log(`⚠️ Dépendances manquantes: ${missingDeps.join(', ')}`);
if (options.installDeps || options.dryRun) {
console.log('🔧 Installation des dépendances...');
const installSuccess = await installFrameworkDependencies(framework, {
dryRun: options.dryRun,
silent: false,
});
if (!installSuccess && !options.dryRun) {
console.warn('⚠️ Certaines dépendances n\'ont pas pu être installées automatiquement.');
console.log('💡 Vous pouvez les installer manuellement avec:');
console.log(` npm install ${missingDeps.join(' ')}`);
}
} else {
console.log('💡 Installez-les avec: npm install --save-dev eslint-config-ai-swe');
console.log('💡 Ou utilisez --install-deps pour les installer automatiquement');
}
} else {
console.log('✅ Toutes les dépendances sont déjà installées');
}
const configContent = `// eslint.config.js
// Auto-généré par eslint-config-ai-swe
// Framework détecté: ${framework}
import aiSwe from 'eslint-config-ai-swe';
export default aiSwe({
${suggestedConfigs.map(config => `${config}: true,`).join('\n ')}
// Ajoutez ici vos configurations spécifiques supplémentaires
});
`;
const configPath = path.join(process.cwd(), 'eslint.config.js');
if (fs.existsSync(configPath) && !options.force) {
console.warn('⚠️ Un fichier eslint.config.js existe déjà. Utilisez --force pour l\'écraser.');
return;
}
fs.writeFileSync(configPath, configContent);
console.log('✅ Fichier eslint.config.js créé avec succès !');
// Configuration IDE si demandée
if (options.ide) {
setupIdeConfiguration();
}
// Génération AGENTS.md si demandée
if (options.agents) {
console.log('📝 Génération du fichier AGENTS.md...');
const agentsMdContent = generateAgentsMd(suggestedConfigs);
const agentsMdPath = path.join(process.cwd(), 'AGENTS.md');
if (fs.existsSync(agentsMdPath) && !options.force) {
console.warn('⚠️ Un fichier AGENTS.md existe déjà. Utilisez --force pour l\'écraser.');
} else {
fs.writeFileSync(agentsMdPath, agentsMdContent);
console.log('✅ AGENTS.md créé avec des règles de guidage pour l\'IA !');
}
}
// Instructions supplémentaires selon le framework
if (framework === 'react') {
console.log('💡 Pour React, assurez-vous d\'avoir installé: eslint-plugin-react eslint-plugin-react-hooks');
} else if (framework === 'vue') {
console.log('💡 Pour Vue, assurez-vous d\'avoir installé: eslint-plugin-vue');
}
console.log("🎯 Exécutez 'npx eslint .' pour tester votre configuration !");
});
program
.command('detect')
.description('Détecte le framework et les dépendances du projet.')
.action(() => {
const { framework, dependencies } = detectFramework();
const suggestedConfigs = suggestConfig(framework);
console.log('🔍 Analyse du projet:');
console.log(` Framework: ${framework}`);
console.log(` Configurations suggérées: ${suggestedConfigs.join(', ')}`);
console.log(` Dépendances détectées: ${dependencies.length}`);
dependencies.forEach(dep => console.log(` - ${dep}`));
});
function createInitConfig(framework) {
return `// eslint.config.js
// Auto-généré par eslint-config-ai-swe
// Framework détecté: ${framework}
import aiSwe from 'eslint-config-ai-swe';
export default aiSwe({
typescript: true,
ai: true,
${framework === 'react' ? 'react: true,' : ''}
${framework === 'vue' ? 'vue: true,' : ''}
${framework === 'node' ? 'node: true,' : ''}
// Personnalisez vos règles ici
});
`;
}
function createEslintIgnore() {
return `# Auto-généré par eslint-config-ai-swe
node_modules/
dist/
build/
coverage/
*.min.js
*.test.js
*.spec.js
`;
}
program
.command('init')
.description('Initialise une configuration complète pour le projet.')
.option('-f, --force', 'Écrase les fichiers existants')
.option('--ide', 'Configure également les paramètres IDE pour VS Code')
.option('--agents', 'Génère également le fichier AGENTS.md pour les agents IA')
.option('--install-deps', 'Installe automatiquement les dépendances optionnelles requises')
.option('--dry-run', 'Simule l\'installation sans rien installer')
.action(async (options) => {
console.log('🚀 Initialisation complète de eslint-config-ai-swe...');
const { framework } = detectFramework();
// const suggestedConfigs = suggestConfig(framework);
// Check for missing dependencies
const missingDeps = getMissingDependencies(framework);
if (missingDeps.length > 0) {
console.log(`⚠️ Dépendances manquantes: ${missingDeps.join(', ')}`);
if (options.installDeps || options.dryRun) {
console.log('🔧 Installation des dépendances...');
const installSuccess = await installFrameworkDependencies(framework, {
dryRun: options.dryRun,
silent: false,
});
if (!installSuccess && !options.dryRun) {
console.warn('⚠️ Certaines dépendances n\'ont pas pu être installées automatiquement.');
console.log('💡 Vous pouvez les installer manuellement avec:');
console.log(` npm install ${missingDeps.join(' ')}`);
}
} else {
console.log('💡 Installez-les avec: npm install --save-dev eslint-config-ai-swe');
console.log('💡 Ou utilisez --install-deps pour les installer automatiquement');
}
} else {
console.log('✅ Toutes les dépendances sont déjà installées');
}
// Créer eslint.config.js
const configContent = createInitConfig(framework);
const configPath = path.join(process.cwd(), 'eslint.config.js');
if (fs.existsSync(configPath) && !options.force) {
console.warn('⚠️ eslint.config.js existe déjà. Utilisez --force pour l\'écraser.');
} else {
fs.writeFileSync(configPath, configContent);
console.log('✅ eslint.config.js créé');
}
// Créer .eslintignore
const ignoreContent = createEslintIgnore();
const ignorePath = path.join(process.cwd(), '.eslintignore');
if (fs.existsSync(ignorePath) && !options.force) {
console.warn('⚠️ .eslintignore existe déjà. Utilisez --force pour l\'écraser.');
} else {
fs.writeFileSync(ignorePath, ignoreContent);
console.log('✅ .eslintignore créé');
}
// Configuration IDE si demandée
if (options.ide) {
setupIdeConfiguration();
}
// Génération AGENTS.md si demandée
if (options.agents) {
console.log('📝 Génération du fichier AGENTS.md...');
const agentsConfigs = suggestConfig(framework);
const agentsMdContent = generateAgentsMd(agentsConfigs);
const agentsMdPath = path.join(process.cwd(), 'AGENTS.md');
if (fs.existsSync(agentsMdPath) && !options.force) {
console.warn('⚠️ Un fichier AGENTS.md existe déjà. Utilisez --force pour l\'écraser.');
} else {
fs.writeFileSync(agentsMdPath, agentsMdContent);
console.log('✅ AGENTS.md créé avec des règles de guidage pour l\'IA !');
}
}
console.log('🎯 Configuration terminée ! Exécutez "npx eslint ." pour tester.');
});
// Configuration IDE pour VS Code
function setupIdeConfiguration() {
const vscodeDir = path.join(process.cwd(), '.vscode');
const settingsPath = path.join(vscodeDir, 'settings.json');
// Créer le dossier .vscode s'il n'existe pas
if (!fs.existsSync(vscodeDir)) {
fs.mkdirSync(vscodeDir, { recursive: true });
}
const settingsContent = getIdeSettingsContent();
if (fs.existsSync(settingsPath)) {
console.log('⚠️ .vscode/settings.json existe déjà. Configuration IDE ignorée.');
console.log('💡 Utilisez --force pour écraser la configuration existante.');
} else {
fs.writeFileSync(settingsPath, settingsContent);
console.log('✅ .vscode/settings.json créé avec configuration ESLint');
console.log('🎯 Installez l\'extension ESLint pour VS Code: https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint');
}
}
function getIdeSettingsContent() {
return `{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"editor.formatOnSave": false,
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"svelte",
"astro",
"json",
"jsonc",
"yaml",
"toml",
"markdown",
"html"
],
"eslint.packageManager": "npm",
"eslint.run": "onType",
"eslint.workingDirectories": [
{
"mode": "auto"
}
],
"typescript.preferences.preferTypeOnlyAutoImports": true,
"typescript.suggest.autoImports": true,
"editor.quickSuggestions": {
"strings": true,
"comments": true,
"other": true
},
"editor.suggest.showStatusBar": true,
"editor.tabSize": 2,
"editor.insertSpaces": true,
"files.associations": {
"*.config.js": "javascript",
"*.config.ts": "typescript"
},
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/build": true,
"**/.git": true,
"**/.cache": true
},
"files.watcherExclude": {
"**/node_modules/**": true,
"**/dist/**": true,
"**/build/**": true
}
}`;
}
// Commande interactive pour la configuration IDE
program
.command('ide')
.description('Configure les paramètres IDE pour VS Code.')
.option('-f, --force', 'Écrase le fichier existant')
.action((_options) => {
console.log('💻 Configuration IDE pour VS Code...');
setupIdeConfiguration();
});
program.parse(process.argv);