UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

247 lines (246 loc) 9.37 kB
import { BaseLanguageHandler } from './base.js'; import { getNodeText } from '../astAnalyzer.js'; import logger from '../../../logger.js'; export class GraphQLHandler extends BaseLanguageHandler { getFunctionQueryPatterns() { return [ 'field_definition', 'operation_definition', 'fragment_definition', 'directive_definition' ]; } getClassQueryPatterns() { return [ 'type_definition', 'interface_definition', 'union_definition', 'enum_definition', 'input_object_type_definition', 'scalar_type_definition' ]; } getImportQueryPatterns() { return [ 'import_declaration', 'include_directive', 'import_statement', 'call_expression' ]; } extractFunctionName(node, sourceCode, _options) { try { if (node.type === 'field_definition') { const nameNode = node.childForFieldName('name'); if (nameNode) { const name = getNodeText(nameNode, sourceCode); if (this.hasArguments(node)) { return `resolver_${name}`; } return name; } } if (node.type === 'operation_definition') { const operationNode = node.childForFieldName('operation_type'); const nameNode = node.childForFieldName('name'); if (operationNode) { const operationType = getNodeText(operationNode, sourceCode); if (nameNode) { return `${operationType}_${getNodeText(nameNode, sourceCode)}`; } return `anonymous_${operationType}`; } } if (node.type === 'fragment_definition') { const nameNode = node.childForFieldName('name'); if (nameNode) { return `fragment_${getNodeText(nameNode, sourceCode)}`; } } if (node.type === 'directive_definition') { const nameNode = node.childForFieldName('name'); if (nameNode) { return `directive_${getNodeText(nameNode, sourceCode)}`; } } return 'anonymous'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting GraphQL/Schema function name'); return 'anonymous'; } } hasArguments(node) { try { const argsNode = node.childForFieldName('arguments'); return !!argsNode && argsNode.childCount > 0; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error checking if GraphQL field has arguments'); return false; } } extractClassName(node, sourceCode) { try { if (node.type === 'type_definition' || node.type === 'interface_definition' || node.type === 'union_definition' || node.type === 'enum_definition' || node.type === 'input_object_type_definition' || node.type === 'scalar_type_definition') { const nameNode = node.childForFieldName('name'); if (nameNode) { return getNodeText(nameNode, sourceCode); } } return 'AnonymousType'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting GraphQL/Schema class name'); return 'AnonymousType'; } } extractImplementedInterfaces(node, sourceCode) { try { if (node.type === 'type_definition') { const implementsNode = node.childForFieldName('implements'); if (implementsNode) { const interfaces = []; const namedTypes = implementsNode.descendantsOfType('named_type'); for (const namedType of namedTypes) { interfaces.push(getNodeText(namedType, sourceCode)); } return interfaces.length > 0 ? interfaces : undefined; } } return undefined; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting GraphQL/Schema implemented interfaces'); return undefined; } } extractImportPath(node, sourceCode) { try { if (node.type === 'import_declaration') { const pathNode = node.childForFieldName('path'); if (pathNode) { return getNodeText(pathNode, sourceCode); } } else if (node.type === 'include_directive') { const argumentNode = node.childForFieldName('argument'); if (argumentNode) { return getNodeText(argumentNode, sourceCode); } } if (node.type === 'import_statement' || node.type === 'import_declaration') { const source = node.childForFieldName('source'); if (source && source.text) { return source.text.replace(/['"`]/g, ''); } } if (node.type === 'call_expression' && node.childForFieldName('function')?.text === 'require') { const args = node.childForFieldName('arguments'); const firstArg = args?.firstChild; if (firstArg && firstArg.text) { return firstArg.text.replace(/['"`]/g, ''); } } return 'unknown'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting GraphQL/Schema import path'); return 'unknown'; } } extractFunctionComment(node, sourceCode) { try { const descriptionNode = node.childForFieldName('description'); if (descriptionNode) { return this.parseGraphQLDescription(descriptionNode.text); } const current = node; let prev = current.previousNamedSibling; while (prev && prev.type !== 'comment') { prev = prev.previousNamedSibling; } if (prev && prev.type === 'comment') { const commentText = getNodeText(prev, sourceCode); return commentText .replace(/^#\s*/mg, '') .trim(); } return undefined; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting GraphQL/Schema function comment'); return undefined; } } extractClassComment(node, sourceCode) { try { const descriptionNode = node.childForFieldName('description'); if (descriptionNode) { return this.parseGraphQLDescription(descriptionNode.text); } const current = node; let prev = current.previousNamedSibling; while (prev && prev.type !== 'comment') { prev = prev.previousNamedSibling; } if (prev && prev.type === 'comment') { const commentText = getNodeText(prev, sourceCode); return commentText .replace(/^#\s*/mg, '') .trim(); } return undefined; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting GraphQL/Schema class comment'); return undefined; } } parseGraphQLDescription(description) { try { return description .replace(/^"""|"""$/g, '') .replace(/^"|"$/g, '') .trim(); } catch (error) { logger.warn({ err: error }, 'Error parsing GraphQL description'); return description; } } detectFramework(sourceCode) { try { if (sourceCode.includes('ApolloServer') || sourceCode.includes('gql`') || sourceCode.includes('apollo-server')) { return 'apollo'; } if (sourceCode.includes('Relay') || sourceCode.includes('graphql-relay') || sourceCode.includes('relay-runtime')) { return 'relay'; } if (sourceCode.includes('GraphQLYoga') || sourceCode.includes('createYoga') || sourceCode.includes('graphql-yoga')) { return 'yoga'; } if (sourceCode.includes('Prisma') || sourceCode.includes('prisma') || sourceCode.includes('@prisma/client')) { return 'prisma'; } return null; } catch (error) { logger.warn({ err: error }, 'Error detecting GraphQL/Schema framework'); return null; } } }