graphql-lint-clint-platform
Version:
GraphQL unused fields linter for Clint platform - Custom patterns and actions.graphql support
111 lines (91 loc) • 3.17 kB
text/typescript
import { GraphQLQuery, GraphQLField } from "@graphql-lint/core";
import fs from "fs";
import path from "path";
import { glob } from "glob";
interface ClintAction {
name: string;
pattern: string; // clint.entity.method
file: string;
line: number;
}
export class ClintGraphQLExtractor {
async extractFromPath(targetPath: string, actions: ClintAction[], includePatterns: string[], excludePatterns: string[]): Promise<void> {
const stats = fs.statSync(targetPath);
if (stats.isFile()) {
if (targetPath.endsWith('actions.graphql')) {
await this.extractFromFile(targetPath, actions);
}
} else if (stats.isDirectory()) {
// Buscar por arquivos actions.graphql
const files = await glob("**/actions.graphql", {
cwd: targetPath,
ignore: excludePatterns,
absolute: true
});
for (const file of files) {
await this.extractFromFile(file, actions);
}
}
}
async extractFromFile(filePath: string, actions: ClintAction[]): Promise<void> {
try {
const content = fs.readFileSync(filePath, 'utf-8');
const extractedActions = this.parseActionsGraphQL(content, filePath);
actions.push(...extractedActions);
} catch (error) {
console.warn(`⚠️ Erro ao ler arquivo ${filePath}:`, error);
}
}
private parseActionsGraphQL(content: string, filePath: string): ClintAction[] {
const actions: ClintAction[] = [];
const lines = content.split('\n');
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const lineNumber = i + 1;
// Detectar definições de actions (padrão comum do Hasura)
// Exemplo: action_name { ... }
const actionMatch = line.match(/^\s*([a-z_]+)\s*\{/);
if (actionMatch) {
const actionName = actionMatch[1];
const clintPattern = this.actionToClintPattern(actionName);
actions.push({
name: actionName,
pattern: clintPattern,
file: filePath,
line: lineNumber
});
}
}
return actions;
}
/**
* Converte nome de action do Hasura para padrão Clint
* Exemplo: owner_get_name -> clint.owner.getName
*/
actionToClintPattern(actionName: string): string {
const parts = actionName.split('_');
if (parts.length < 3) {
return `clint.${actionName}`;
}
const [entity, action, ...details] = parts;
const methodName = action + details.map(d =>
d.charAt(0).toUpperCase() + d.slice(1)
).join('');
return `clint.${entity}.${methodName}`;
}
/**
* Converte padrão Clint para nome de action do Hasura
* Exemplo: clint.owner.getName -> owner_get_name
*/
clintPatternToAction(pattern: string): string {
const match = pattern.match(/^clint\.([^.]+)\.([^.]+)$/);
if (!match) {
return pattern.replace('clint.', '');
}
const [, entity, method] = match;
// Converter camelCase para snake_case
const actionPart = method.replace(/([A-Z])/g, '_$1').toLowerCase();
return `${entity}_${actionPart}`;
}
}
export { ClintAction };