UNPKG

graphql-lint-clint-platform

Version:

GraphQL unused fields linter for Clint platform - Custom patterns and actions.graphql support

137 lines (108 loc) 5.88 kB
#!/usr/bin/env node import { Command } from "commander"; import path from "path"; import { ClintGraphQLExtractor, ClintAction } from "./clintExtractor"; import { ClintUsageAnalyzer, ClintUsageResult } from "./clintAnalyzer"; const program = new Command(); program .name("graphql-lint-clint") .description("🎯 Ferramenta específica da Clint para análise de actions GraphQL do Hasura") .version("1.0.0") .argument("[paths...]", "Caminhos dos arquivos ou diretórios para analisar", ["."]) .option("-i, --include <patterns...>", "Padrões de arquivos para incluir", ["**/*.{ts,tsx,js,jsx}", "**/actions.graphql"]) .option("-e, --exclude <patterns...>", "Padrões de arquivos para excluir", ["node_modules/**", "dist/**", "build/**"]) .option("-f, --format <format>", "Formato de saída (console, json)", "console") .option("-o, --output <file>", "Arquivo de saída (se não especificado, usa stdout)") .option("--verbose", "Modo verboso") .action(async (paths: string[], options) => { try { console.log("🎯 CLINT GRAPHQL LINT - HASURA ACTIONS ANALYZER\n"); if (options.verbose) { console.log("📋 Configuração:"); console.log(` 🎯 Caminhos: ${paths.join(", ")}`); console.log(` 📁 Incluir: ${options.include.join(", ")}`); console.log(` 🚫 Excluir: ${options.exclude.join(", ")}`); console.log(""); } // 1. Extrair actions do Hasura console.log("🔍 Extraindo actions do Hasura..."); const extractor = new ClintGraphQLExtractor(); const actions: ClintAction[] = []; for (const targetPath of paths) { const absolutePath = path.resolve(targetPath); await extractor.extractFromPath(absolutePath, actions, options.include, options.exclude); } const actionPatterns = extractor.getActionPatterns(); const totalActions = Object.keys(actionPatterns).length; console.log(` ✅ ${totalActions} actions encontradas\n`); // 2. Analisar uso das actions no código console.log("🔍 Analisando uso das actions no código..."); const analyzer = new ClintUsageAnalyzer(actionPatterns); const sourcePath = paths[0] ? path.resolve(paths[0]) : process.cwd(); const result = await analyzer.analyzeUsageInPath(sourcePath, options.verbose); // 3. Reportar resultados console.log("📊 RESULTADOS DA ANÁLISE CLINT:"); console.log("".padEnd(50, "=")); const usedActions = Object.keys(result.usedActions).length; const unusedActions = result.unusedActions.length; console.log(`🎯 Actions analisadas: ${totalActions}`); console.log(`✅ Actions em uso: ${usedActions} (${Math.round((usedActions/totalActions)*100)}%)`); console.log(`❌ Actions não utilizadas: ${unusedActions} (${Math.round((unusedActions/totalActions)*100)}%)`); if (unusedActions > 0) { console.log("\n🚨 ACTIONS NÃO UTILIZADAS (NECESSITAM OTIMIZAÇÃO):"); console.log("".padEnd(60, "=")); result.unusedActions.forEach(actionName => { // Usar códigos ANSI para cor vermelha const redText = `\x1b[31m❌ ${actionName}\x1b[0m`; const patternText = `\x1b[33m→ Padrões: ${actionPatterns[actionName].join(', ')}\x1b[0m`; console.log(` ${redText}`); console.log(` 🔗 ${patternText}`); console.log(""); }); console.log("".padEnd(60, "=")); console.log(`\x1b[31m⚠️ TOTAL DE ACTIONS DESPERDIÇADAS: ${unusedActions}\x1b[0m`); console.log(`\x1b[33m💡 Remova ou implemente o uso dessas actions para otimizar o projeto!\x1b[0m`); } if (options.format === "json") { const jsonOutput = { summary: { total: totalActions, used: usedActions, unused: unusedActions, usagePercentage: Math.round((usedActions/totalActions)*100) }, result: result }; if (options.output) { const fs = await import("fs"); fs.writeFileSync(options.output, JSON.stringify(jsonOutput, null, 2)); console.log(`\n📁 Resultado salvo em: ${options.output}`); } else { console.log("\n📄 JSON OUTPUT:"); console.log(JSON.stringify(jsonOutput, null, 2)); } } console.log("\n🎯 Análise Clint concluída!"); // NOVA FUNCIONALIDADE: Throw error se houver actions não utilizadas if (unusedActions > 0) { console.log(`\n\x1b[31m💥 ERRO: Encontradas ${unusedActions} actions não utilizadas!\x1b[0m`); console.log(`\x1b[33m🔧 AÇÃO NECESSÁRIA: Otimize as seguintes queries removendo ou implementando seu uso:\x1b[0m`); // Lista resumida para o erro result.unusedActions.forEach(actionName => { console.log(`\x1b[31m • ${actionName}${actionPatterns[actionName].join(', ')}\x1b[0m`); }); console.log(`\n\x1b[37m📖 DICA: Execute novamente após implementar o uso ou remover as actions desnecessárias.\x1b[0m`); // Throw com informações detalhadas const errorMessage = `🚨 OTIMIZAÇÃO NECESSÁRIA: ${unusedActions} actions da Clint não estão sendo utilizadas no código. ` + `Actions desperdiçadas: ${result.unusedActions.join(', ')}. ` + `Implemente o uso ou remova essas actions para otimizar o projeto.`; throw new Error(errorMessage); } // Exit com sucesso se não houver actions não utilizadas console.log("\n\x1b[32m✅ Todas as actions estão sendo utilizadas corretamente!\x1b[0m"); } catch (error) { console.error("❌ Erro na análise:", error); process.exit(1); } }); program.parse();