mirror of
https://github.com/hpd840321/starRiverProperty.git
synced 2026-06-09 08:20:31 +08:00
feat: add API call extractor script
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Former-commit-id: 32eb1a04435e3e1adf760c8a9bd3f499f23e4c3a
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* API 调用提取器
|
||||
* 从格式化后的 JS 中提取 HTTP 请求模式,输出 API 清单 JSON
|
||||
*
|
||||
* 用法: node extract-api-calls.js <formatted-dir> <output.json>
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const parser = require('@babel/parser');
|
||||
const traverse = require('@babel/traverse').default;
|
||||
|
||||
function extractApiCalls(inputDir, outputFile) {
|
||||
const apiCalls = [];
|
||||
const files = fs.readdirSync(inputDir).filter(f => f.endsWith('.formatted.js'));
|
||||
|
||||
for (const file of files) {
|
||||
const code = fs.readFileSync(path.join(inputDir, file), 'utf-8');
|
||||
|
||||
try {
|
||||
const ast = parser.parse(code, {
|
||||
sourceType: 'script',
|
||||
plugins: ['jsx', 'typescript', 'classProperties', 'dynamicImport'],
|
||||
errorRecovery: true,
|
||||
});
|
||||
|
||||
traverse(ast, {
|
||||
// Match: axios.get('/api/xxx'), axios.post('/api/xxx', data)
|
||||
CallExpression(nodePath) {
|
||||
const node = nodePath.node;
|
||||
const callee = node.callee;
|
||||
|
||||
if (
|
||||
callee.type === 'MemberExpression' &&
|
||||
callee.object.type === 'Identifier' &&
|
||||
(callee.object.name === 'axios' || callee.object.name === 'http')
|
||||
) {
|
||||
const method = callee.property.name;
|
||||
if (['get', 'post', 'put', 'delete', 'patch'].includes(method)) {
|
||||
const url = node.arguments[0];
|
||||
if (url && url.type === 'StringLiteral') {
|
||||
apiCalls.push({
|
||||
file: file,
|
||||
method: method.toUpperCase(),
|
||||
url: url.value,
|
||||
hasBody: method !== 'get' && node.arguments.length > 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this.$http.get|post
|
||||
if (
|
||||
callee.type === 'MemberExpression' &&
|
||||
callee.object.type === 'MemberExpression' &&
|
||||
callee.object.property.name === '$http'
|
||||
) {
|
||||
const method = callee.property.name;
|
||||
const url = node.arguments[0];
|
||||
if (url && url.type === 'StringLiteral') {
|
||||
apiCalls.push({
|
||||
file: file,
|
||||
method: method.toUpperCase(),
|
||||
url: url.value,
|
||||
via: '$http',
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Match string constants containing API paths
|
||||
StringLiteral(nodePath) {
|
||||
const value = nodePath.node.value;
|
||||
if (typeof value === 'string' && value.startsWith('/api/') && value.length > 5) {
|
||||
const parent = nodePath.parent;
|
||||
if (parent.type === 'CallExpression') return;
|
||||
|
||||
apiCalls.push({
|
||||
file: file,
|
||||
method: 'REFERENCE',
|
||||
url: value,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`解析失败: ${file} — ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Deduplicate + sort
|
||||
const unique = {};
|
||||
apiCalls.forEach(call => {
|
||||
const key = `${call.method} ${call.url}`;
|
||||
if (!unique[key]) {
|
||||
unique[key] = call;
|
||||
}
|
||||
});
|
||||
|
||||
const result = Object.values(unique).sort((a, b) => a.url.localeCompare(b.url));
|
||||
|
||||
fs.writeFileSync(outputFile, JSON.stringify(result, null, 2));
|
||||
console.log(`提取完成: ${result.length} 个 API 端点 → ${outputFile}`);
|
||||
|
||||
// Also generate Markdown report
|
||||
const mdPath = outputFile.replace('.json', '.md');
|
||||
let md = '# API 端点清单\n\n';
|
||||
md += `| Method | URL | 来源文件 |\n`;
|
||||
md += `|--------|-----|----------|\n`;
|
||||
result.forEach(call => {
|
||||
md += '| ' + call.method + ' | `' + call.url + '` | ' + call.file + ' |\n';
|
||||
});
|
||||
fs.writeFileSync(mdPath, md);
|
||||
console.log(`Markdown 清单: ${mdPath}`);
|
||||
}
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length < 2) {
|
||||
console.log('用法: node extract-api-calls.js <formatted-dir> <output.json>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
extractApiCalls(args[0], args[1]);
|
||||
Reference in New Issue
Block a user