UNPKG

graphql-lint-clint-platform

Version:

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

235 lines 8.93 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.ClintGraphQLExtractor = void 0; exports.actionToClintPattern = actionToClintPattern; exports.clintPatternToAction = clintPatternToAction; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const graphql_1 = require("graphql"); class ClintGraphQLExtractor { constructor() { this.actionsQueries = new Map(); } /** * Detecta queries customizadas da Clint baseadas em actions.graphql */ async extractClintQueries(projectPath) { const queries = []; // Extrair queries do actions.graphql da Clint const actionsQueries = await this.extractFromActionsGraphQL(projectPath); queries.push(...actionsQueries); return queries; } /** * Extrai queries do arquivo actions.graphql da Clint */ async extractFromActionsGraphQL(projectPath) { const actionsFiles = this.findActionsFiles(projectPath); const queries = []; for (const actionsFile of actionsFiles) { try { const content = fs.readFileSync(actionsFile, 'utf-8'); const document = (0, graphql_1.parse)(content); const actionsQueries = this.parseActionsDocument(document, actionsFile); queries.push(...actionsQueries); // Armazenar para mapeamento posterior actionsQueries.forEach(query => { this.actionsQueries.set(query.name, query); }); } catch (error) { console.warn(`⚠️ Erro ao processar actions.graphql em ${actionsFile}:`, error); } } return queries; } /** * Procura arquivos actions.graphql no projeto */ findActionsFiles(projectPath) { const actionsFiles = []; const searchPaths = [ path.join(projectPath, 'actions.graphql'), path.join(projectPath, 'hasura', 'actions.graphql'), path.join(projectPath, 'graphql', 'actions.graphql'), path.join(projectPath, 'schema', 'actions.graphql'), ]; // Busca recursiva por actions.graphql const findRecursive = (dir) => { try { const items = fs.readdirSync(dir); for (const item of items) { const fullPath = path.join(dir, item); const stat = fs.statSync(fullPath); if (stat.isDirectory() && !item.includes('node_modules')) { findRecursive(fullPath); } else if (item === 'actions.graphql') { actionsFiles.push(fullPath); } } } catch (error) { // Ignorar diretórios inacessíveis } }; // Verificar caminhos conhecidos searchPaths.forEach(filePath => { if (fs.existsSync(filePath)) { actionsFiles.push(filePath); } }); // Busca recursiva a partir da raiz findRecursive(projectPath); return [...new Set(actionsFiles)]; // Remove duplicatas } /** * Parseia o documento GraphQL do actions.graphql */ parseActionsDocument(document, filePath) { const queries = []; for (const definition of document.definitions) { if (definition.kind === 'ObjectTypeDefinition' && definition.name.value === 'Query') { // Processar campos da Query type if (definition.fields) { for (const field of definition.fields) { const query = this.parseActionField(field, filePath); if (query) { queries.push(query); } } } } } return queries; } /** * Converte um campo de action em GraphQLQuery * owner_get_name(id: uuid!) -> owner_get_name query */ parseActionField(field, filePath) { try { const queryName = field.name.value; // Extrair campos do tipo de retorno (se disponível) const fields = this.extractFieldsFromActionReturnType(field, queryName); return { name: queryName, fields: fields, rawQuery: `# Action: ${queryName}`, location: { file: filePath, line: field.loc?.startToken?.line || 0, column: field.loc?.startToken?.column || 0 } }; } catch (error) { console.warn(`⚠️ Erro ao processar action field ${field.name.value}:`, error); return null; } } /** * Extrai campos baseados no tipo de retorno da action */ extractFieldsFromActionReturnType(field, queryName) { // Por enquanto, criar campos sintéticos baseados no nome da action // Em uma implementação mais completa, poderia analisar o schema completo const fields = []; // Padrão: owner_get_name -> campos relacionados a owner const entityMatch = queryName.match(/^(\w+)_/); if (entityMatch) { const entity = entityMatch[1]; // Campos comuns baseados na entidade const commonFields = this.getCommonFieldsForEntity(entity); fields.push(...commonFields); } // Adicionar campo de status padrão para actions fields.push({ name: 'status', path: ['status'], line: field.loc?.startToken?.line || 0, column: field.loc?.startToken?.column || 0 }); return fields; } /** * Gera campos comuns para uma entidade */ getCommonFieldsForEntity(entity) { const commonFieldsByEntity = { owner: ['id', 'name', 'email', 'type'], user: ['id', 'name', 'email', 'avatar'], payment: ['id', 'amount', 'status', 'method'], order: ['id', 'total', 'status', 'items'], product: ['id', 'name', 'price', 'category'], }; const fieldNames = commonFieldsByEntity[entity] || ['id', 'name']; return fieldNames.map((fieldName, index) => ({ name: fieldName, path: [fieldName], line: 0, column: index * 10 })); } } exports.ClintGraphQLExtractor = ClintGraphQLExtractor; /** * Converte nome de action para padrão Clint * owner_get_name -> clint.owner.getName */ function actionToClintPattern(actionName) { const match = actionName.match(/^(\w+)_(.+)$/); if (!match) return null; const [, entity, action] = match; // Converter action para camelCase const camelAction = action.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()); return `clint.${entity}.${camelAction}`; } /** * Converte padrão Clint para nome de action * clint.owner.getName -> owner_get_name */ function clintPatternToAction(clintPattern) { const match = clintPattern.match(/^clint\.(\w+)\.(.+)$/); if (!match) return null; const [, entity, method] = match; // Converter camelCase para snake_case const snakeAction = method.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`); return `${entity}_${snakeAction}`; } //# sourceMappingURL=clintExtractor-old.js.map