UNPKG

agentsqripts

Version:

Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems

159 lines (141 loc) 5.95 kB
/** * @file Multi-library frontend API call extraction for integration analysis * @description Single responsibility: Extract API calls from diverse frontend HTTP libraries * * This module implements comprehensive API call extraction across multiple frontend * HTTP libraries including Fetch API, Axios, jQuery AJAX, and XMLHttpRequest. * It identifies method types, endpoints, and calling contexts to enable accurate * frontend-backend integration analysis and detect mismatches or unused endpoints. * * Design rationale: * - Multi-library support covers diverse frontend technology stacks * - Pattern-based extraction efficiently handles syntax variations * - Library-specific patterns ensure accurate call identification * - Extensible pattern system supports adding new HTTP libraries */ const fs = require('fs'); const path = require('path'); /** * Extract frontend API calls using multi-library pattern matching * * Technical function: Comprehensive API call extraction with library-specific pattern recognition * * Implementation rationale: * - Library-specific patterns handle diverse API call syntaxes accurately * - Async file reading enables concurrent processing for performance * - Pattern matching efficiently identifies calls without AST parsing overhead * - Error handling maintains analysis robustness across file reading failures * * Library coverage strategy: * - Fetch API: Modern native browser API with various syntax patterns * - Axios: Popular HTTP library with method-specific and config-object patterns * - jQuery: Legacy AJAX patterns still common in many applications * - XMLHttpRequest: Low-level API patterns for comprehensive coverage * * Pattern matching design: * - Regex patterns optimized for each library's characteristic syntax * - Multiple pattern variants handle different usage styles * - Global matching captures all API calls within files * - Method extraction normalizes diverse method specification approaches * * Call identification accuracy: * - Library tagging enables differentiation of call patterns * - Method validation ensures only valid HTTP methods are captured * - Route cleaning normalizes URLs for accurate comparison * - Line number tracking enables precise location identification * * @param {Array<string>} files - Array of frontend file paths to analyze for API calls * @returns {Promise<Array<Object>>} Array of API call objects with method, route, library, and location * @example * const calls = await extractFrontendCalls([ * 'components/UserList.jsx', // React component with fetch calls * 'services/api.js' // Service layer with axios calls * ]); * // Returns: [{ method: 'GET', route: '/api/users', library: 'fetch', file: '...', line: 15 }] */ async function extractFrontendCalls(files) { const calls = []; // Fetch API patterns const fetchPatterns = [ /fetch\s*\(\s*['"`]([^'"`]+)['"`]\s*,?\s*\{[^}]*method\s*:\s*['"`]([^'"`]+)['"`]/gi, /fetch\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/gi ]; // Axios patterns const axiosPatterns = [ /axios\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/gi, /axios\s*\(\s*\{[^}]*url\s*:\s*['"`]([^'"`]+)['"`][^}]*method\s*:\s*['"`]([^'"`]+)['"`]/gi, /axios\s*\(\s*\{[^}]*method\s*:\s*['"`]([^'"`]+)['"`][^}]*url\s*:\s*['"`]([^'"`]+)['"`]/gi ]; // jQuery patterns const jqueryPatterns = [ /\$\.ajax\s*\(\s*\{[^}]*url\s*:\s*['"`]([^'"`]+)['"`][^}]*type\s*:\s*['"`]([^'"`]+)['"`]/gi, /\$\.(get|post)\s*\(\s*['"`]([^'"`]+)['"`]/gi ]; // XMLHttpRequest patterns const xhrPatterns = [ /\.open\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*['"`]([^'"`]+)['"`]/gi ]; for (const file of files) { try { const content = await fs.promises.readFile(file, 'utf8'); // Extract calls using all patterns extractCallsWithPatterns(content, file, fetchPatterns, calls, 'fetch'); extractCallsWithPatterns(content, file, axiosPatterns, calls, 'axios'); extractCallsWithPatterns(content, file, jqueryPatterns, calls, 'jquery'); extractCallsWithPatterns(content, file, xhrPatterns, calls, 'xhr'); } catch (error) { console.warn(`Warning: Could not read frontend file ${file}: ${error.message}`); } } return calls; } /** * Helper function to extract calls using regex patterns */ function extractCallsWithPatterns(content, file, patterns, calls, library) { const { cleanRoute } = require('./routeCleaner'); // Pre-compile method check for efficiency const validMethods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']); // Process patterns and extract calls efficiently for (let i = 0; i < patterns.length; i++) { const pattern = patterns[i]; const matches = [...content.matchAll(pattern)]; for (let j = 0; j < matches.length; j++) { const match = matches[j]; let method, route; // Handle different match patterns if (match[1] && match[2]) { const method1Upper = match[1].toUpperCase(); const method2Upper = match[2].toUpperCase(); if (validMethods.has(method1Upper)) { method = method1Upper; route = match[2]; } else if (validMethods.has(method2Upper)) { method = method2Upper; route = match[1]; } else { method = method1Upper; route = match[2]; } } else if (match[1]) { method = 'GET'; // Default method route = match[1]; } if (route) { const lines = content.substring(0, match.index).split('\n'); const lineNumber = lines.length; calls.push({ method: method || 'GET', route: cleanRoute(route), file, line: lineNumber, library, originalMatch: match[0] }); } } } } module.exports = { extractFrontendCalls };