- Implemented a new tool `stella-callgraph-node` that extracts call graphs from JavaScript/TypeScript projects using Babel AST. - Added command-line interface with options for JSON output and help. - Included functionality to analyze project structure, detect functions, and build call graphs. - Created a package.json file for dependency management. feat: introduce stella-callgraph-python for Python call graph extraction - Developed `stella-callgraph-python` to extract call graphs from Python projects using AST analysis. - Implemented command-line interface with options for JSON output and verbose logging. - Added framework detection to identify popular web frameworks and their entry points. - Created an AST analyzer to traverse Python code and extract function definitions and calls. - Included requirements.txt for project dependencies. chore: add framework detection for Python projects - Implemented framework detection logic to identify frameworks like Flask, FastAPI, Django, and others based on project files and import patterns. - Enhanced the AST analyzer to recognize entry points based on decorators and function definitions.
179 lines
4.8 KiB
JavaScript
179 lines
4.8 KiB
JavaScript
// -----------------------------------------------------------------------------
|
|
// framework-detect.js
|
|
// Framework detection patterns for JavaScript/TypeScript projects.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Framework detection patterns
|
|
*/
|
|
export const frameworkPatterns = {
|
|
express: {
|
|
packageNames: ['express'],
|
|
patterns: [
|
|
/const\s+\w+\s*=\s*require\(['"]express['"]\)/,
|
|
/import\s+\w+\s+from\s+['"]express['"]/,
|
|
/app\.(get|post|put|delete|patch)\s*\(/
|
|
],
|
|
entrypointType: 'http_handler'
|
|
},
|
|
|
|
fastify: {
|
|
packageNames: ['fastify'],
|
|
patterns: [
|
|
/require\(['"]fastify['"]\)/,
|
|
/import\s+\w+\s+from\s+['"]fastify['"]/,
|
|
/fastify\.(get|post|put|delete|patch)\s*\(/
|
|
],
|
|
entrypointType: 'http_handler'
|
|
},
|
|
|
|
koa: {
|
|
packageNames: ['koa', '@koa/router'],
|
|
patterns: [
|
|
/require\(['"]koa['"]\)/,
|
|
/import\s+\w+\s+from\s+['"]koa['"]/,
|
|
/router\.(get|post|put|delete|patch)\s*\(/
|
|
],
|
|
entrypointType: 'http_handler'
|
|
},
|
|
|
|
hapi: {
|
|
packageNames: ['@hapi/hapi'],
|
|
patterns: [
|
|
/require\(['"]@hapi\/hapi['"]\)/,
|
|
/import\s+\w+\s+from\s+['"]@hapi\/hapi['"]/,
|
|
/server\.route\s*\(/
|
|
],
|
|
entrypointType: 'http_handler'
|
|
},
|
|
|
|
nestjs: {
|
|
packageNames: ['@nestjs/core', '@nestjs/common'],
|
|
patterns: [
|
|
/@Controller\s*\(/,
|
|
/@Get\s*\(/,
|
|
/@Post\s*\(/,
|
|
/@Put\s*\(/,
|
|
/@Delete\s*\(/,
|
|
/@Patch\s*\(/
|
|
],
|
|
entrypointType: 'http_handler'
|
|
},
|
|
|
|
socketio: {
|
|
packageNames: ['socket.io'],
|
|
patterns: [
|
|
/require\(['"]socket\.io['"]\)/,
|
|
/import\s+\w+\s+from\s+['"]socket\.io['"]/,
|
|
/io\.on\s*\(\s*['"]connection['"]/,
|
|
/socket\.on\s*\(/
|
|
],
|
|
entrypointType: 'websocket_handler'
|
|
},
|
|
|
|
awsLambda: {
|
|
packageNames: ['aws-lambda', '@types/aws-lambda'],
|
|
patterns: [
|
|
/exports\.handler\s*=/,
|
|
/export\s+(const|async function)\s+handler/,
|
|
/module\.exports\.handler/,
|
|
/APIGatewayProxyHandler/,
|
|
/APIGatewayEvent/
|
|
],
|
|
entrypointType: 'lambda'
|
|
},
|
|
|
|
azureFunctions: {
|
|
packageNames: ['@azure/functions'],
|
|
patterns: [
|
|
/require\(['"]@azure\/functions['"]\)/,
|
|
/import\s+\w+\s+from\s+['"]@azure\/functions['"]/,
|
|
/app\.(http|timer|queue|blob)\s*\(/
|
|
],
|
|
entrypointType: 'cloud_function'
|
|
},
|
|
|
|
gcpFunctions: {
|
|
packageNames: ['@google-cloud/functions-framework'],
|
|
patterns: [
|
|
/require\(['"]@google-cloud\/functions-framework['"]\)/,
|
|
/functions\.(http|cloudEvent)\s*\(/
|
|
],
|
|
entrypointType: 'cloud_function'
|
|
},
|
|
|
|
electron: {
|
|
packageNames: ['electron'],
|
|
patterns: [
|
|
/require\(['"]electron['"]\)/,
|
|
/import\s+\{[^}]*\}\s+from\s+['"]electron['"]/,
|
|
/ipcMain\.on\s*\(/,
|
|
/ipcRenderer\.on\s*\(/
|
|
],
|
|
entrypointType: 'event_handler'
|
|
},
|
|
|
|
grpc: {
|
|
packageNames: ['@grpc/grpc-js', 'grpc'],
|
|
patterns: [
|
|
/require\(['"]@grpc\/grpc-js['"]\)/,
|
|
/addService\s*\(/,
|
|
/loadPackageDefinition\s*\(/
|
|
],
|
|
entrypointType: 'grpc_method'
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Detect frameworks from package.json dependencies
|
|
* @param {object} packageJson
|
|
* @returns {string[]}
|
|
*/
|
|
export function detectFrameworks(packageJson) {
|
|
const detected = [];
|
|
const allDeps = {
|
|
...packageJson.dependencies,
|
|
...packageJson.devDependencies
|
|
};
|
|
|
|
for (const [framework, config] of Object.entries(frameworkPatterns)) {
|
|
for (const pkgName of config.packageNames) {
|
|
if (allDeps[pkgName]) {
|
|
detected.push(framework);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return detected;
|
|
}
|
|
|
|
/**
|
|
* Detect frameworks from source code patterns
|
|
* @param {string} content
|
|
* @returns {string[]}
|
|
*/
|
|
export function detectFrameworksFromCode(content) {
|
|
const detected = [];
|
|
|
|
for (const [framework, config] of Object.entries(frameworkPatterns)) {
|
|
for (const pattern of config.patterns) {
|
|
if (pattern.test(content)) {
|
|
detected.push(framework);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return detected;
|
|
}
|
|
|
|
/**
|
|
* Get entrypoint type for a detected framework
|
|
* @param {string} framework
|
|
* @returns {string}
|
|
*/
|
|
export function getEntrypointType(framework) {
|
|
return frameworkPatterns[framework]?.entrypointType || 'unknown';
|
|
}
|