arela
Version:
AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.
144 lines • 4.07 kB
JavaScript
/**
* Extract API calls from frontend code via Graph DB
*/
import Database from 'better-sqlite3';
/**
* Extract all API calls from frontend code
*/
export function extractCalls(dbPath) {
const db = new Database(dbPath);
try {
// Query api_calls table
const stmt = db.prepare(`
SELECT
id,
method,
url,
file_id,
line_number,
created_at
FROM api_calls
ORDER BY method, url
`);
const rows = stmt.all();
return rows.map(call => ({
id: call.id,
method: call.method.toUpperCase(),
url: normalizeUrl(call.url),
fileId: call.file_id,
lineNumber: call.line_number,
createdAt: call.created_at,
}));
}
finally {
db.close();
}
}
/**
* Extract API calls by slice
*/
export function extractCallsBySlice(dbPath, sliceNames) {
const db = new Database(dbPath);
try {
const result = new Map();
// For each slice, find calls
for (const sliceName of sliceNames) {
// Query calls that match slice (by url pattern)
const stmt = db.prepare(`
SELECT
id,
method,
url,
file_id,
line_number,
created_at
FROM api_calls
WHERE url LIKE ?
ORDER BY method, url
`);
// Use slice name as path prefix
const pattern = `/api/${sliceName}%`;
const rows = stmt.all(pattern);
result.set(sliceName, rows.map(c => ({
id: c.id,
method: c.method.toUpperCase(),
url: normalizeUrl(c.url),
fileId: c.file_id,
lineNumber: c.line_number,
createdAt: c.created_at,
})));
}
return result;
}
finally {
db.close();
}
}
/**
* Get file info for calls
*/
export function getCallFileInfo(dbPath, fileIds) {
if (fileIds.length === 0) {
return new Map();
}
const db = new Database(dbPath);
try {
const placeholders = fileIds.map(() => '?').join(',');
const stmt = db.prepare(`
SELECT id, path, language, is_backend, is_frontend, created_at
FROM files
WHERE id IN (${placeholders})
`);
const rows = stmt.all(...fileIds);
const result = new Map();
for (const row of rows) {
result.set(row.id, {
id: row.id,
path: row.path,
language: row.language,
isBackend: row.is_backend,
isFrontend: row.is_frontend,
createdAt: row.created_at,
});
}
return result;
}
finally {
db.close();
}
}
/**
* Normalize API URL to standard path format
* Converts dynamic segments to :param
*/
function normalizeUrl(url) {
// Remove query parameters
let path = url.split('?')[0];
// Remove hash fragments
path = path.split('#')[0];
// Convert template literals ${...} to :param
path = path.replace(/\$\{([^}]+)\}/g, ':param');
// Convert numeric IDs to :id
path = path.replace(/\/\d+(?=\/|$)/g, '/:id');
// Convert UUIDs to :uuid
path = path.replace(/\/[a-f0-9-]{36}(?=\/|$)/gi, '/:uuid');
// Convert hex IDs to :id
path = path.replace(/\/[a-f0-9]{8,}(?=\/|$)/gi, '/:id');
// Convert {param} to :param (in case some are formatted this way)
path = path.replace(/\{([^}]+)\}/g, ':$1');
return path;
}
/**
* Extract path from various URL formats
*/
export function extractPathFromUrl(url) {
// Handle fetch(url) where url is a string
// Handle fetch(`/api/...`) where url is a template literal
// Handle fetch('/api/...') where url is a regular string
// Remove protocol if present
let path = url.replace(/^https?:\/\/[^\/]+/, '');
// Get just the path part
path = path.split('?')[0].split('#')[0];
return path;
}
//# sourceMappingURL=call-extractor.js.map