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
JavaScript
/**
* @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
};