UNPKG

woaru

Version:

Universal Project Setup Autopilot - Analyze and automatically configure development tools for ANY programming language

141 lines 6.02 kB
import { BaseAction } from './BaseAction.js'; import { t } from '../config/i18n.js'; import * as path from 'path'; export class EslintAction extends BaseAction { name = 'eslint'; description = 'Install and configure ESLint for code linting'; async canExecute(projectPath) { const packageJsonPath = path.join(projectPath, 'package.json'); const packageJson = await this.readJsonFile(packageJsonPath); if (!packageJson) return false; // Check if eslint is already installed const hasEslint = packageJson.devDependencies?.eslint || packageJson.dependencies?.eslint; return !hasEslint; } async execute(projectPath, options) { try { const packageJsonPath = path.join(projectPath, 'package.json'); const eslintrcPath = path.join(projectPath, '.eslintrc.json'); if (options.dryRun) { console.log(t('actions.eslint.dry_run_install')); console.log(t('actions.eslint.dry_run_create_config')); return true; } // Create backups if (!options.skipBackup) { await this.createBackup(packageJsonPath); await this.createBackup(eslintrcPath); } // Detect project characteristics const packageJson = await this.readJsonFile(packageJsonPath); const hasNext = packageJson?.dependencies?.next || packageJson?.devDependencies?.next; const hasReact = packageJson?.dependencies?.react || packageJson?.devDependencies?.react; const hasTypeScript = await this.fileExists(path.join(projectPath, 'tsconfig.json')); // Determine packages to install const packages = ['eslint']; if (hasNext) { packages.push('eslint-config-next'); } else if (hasReact) { packages.push('@eslint/js', 'eslint-plugin-react', 'eslint-plugin-react-hooks'); } if (hasTypeScript) { packages.push('@typescript-eslint/eslint-plugin', '@typescript-eslint/parser'); } // Install packages const installResult = await this.runCommand('npm', ['install', '--save-dev', ...packages], projectPath); if (!installResult.success) { throw new Error(t('actions.failed_to_install_packages', { output: installResult.output, })); } // Create ESLint configuration const eslintConfig = { env: { browser: true, es2021: true, node: true, }, extends: [], }; if (hasNext) { eslintConfig.extends.push('next/core-web-vitals'); } else { eslintConfig.extends.push('eslint:recommended'); if (hasReact) { eslintConfig.extends.push('plugin:react/recommended', 'plugin:react-hooks/recommended'); eslintConfig.plugins = ['react', 'react-hooks']; eslintConfig.settings = { react: { version: 'detect', }, }; } } if (hasTypeScript) { eslintConfig.extends.push('@typescript-eslint/recommended'); eslintConfig.parser = '@typescript-eslint/parser'; eslintConfig.plugins = [ ...(eslintConfig.plugins || []), '@typescript-eslint', ]; eslintConfig.parserOptions = { ecmaVersion: 'latest', sourceType: 'module', ...(hasReact && { ecmaFeatures: { jsx: true } }), }; } eslintConfig.rules = { 'no-unused-vars': 'warn', 'no-console': 'warn', ...(hasReact && { 'react/react-in-jsx-scope': 'off' }), }; await this.writeJsonFile(eslintrcPath, eslintConfig); // Add scripts to package.json if (packageJson) { if (!packageJson.scripts) { packageJson.scripts = {}; } packageJson.scripts['lint'] = 'eslint . --ext .js,.jsx,.ts,.tsx'; packageJson.scripts['lint:fix'] = 'eslint . --ext .js,.jsx,.ts,.tsx --fix'; await this.writeJsonFile(packageJsonPath, packageJson); } console.log(t('actions.eslint.setup_success')); return true; } catch (error) { console.error(t('actions.eslint.setup_failed'), error); return false; } } async rollback(projectPath) { try { const fs = await import('fs-extra'); const glob = await import('glob'); // Find backup files const backupFiles = await glob.glob(path.join(projectPath, '*.woaru-backup-*')); for (const backupFile of backupFiles) { const originalFile = backupFile.replace(/\.woaru-backup-\d+$/, ''); await fs.move(backupFile, originalFile, { overwrite: true }); } // Remove created files const filesToRemove = ['.eslintrc.json']; for (const file of filesToRemove) { const filePath = path.join(projectPath, file); if (await fs.pathExists(filePath)) { await fs.remove(filePath); } } console.log(t('actions.eslint.rollback_success')); return true; } catch (error) { console.error(t('actions.eslint.rollback_failed'), error); return false; } } } //# sourceMappingURL=EslintAction.js.map