fix(arch-scan): 修复多语言扫描器并添加 DELETE 清空表
- scanner.ts: 添加 DELETE 清空旧数据语句,避免重复插入 - ts-scanner: 改用 regex 替代 ts-morph 解析(避免解析失败) - go-scanner/py-scanner/proto-scanner: 完善实现
This commit is contained in:
@@ -1,10 +1,92 @@
|
||||
import type { Database as DBType } from 'better-sqlite3';
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
import type { Database as DBType } from "better-sqlite3";
|
||||
|
||||
interface ScanStats {
|
||||
contracts: number;
|
||||
}
|
||||
|
||||
// Proto 符号正则
|
||||
const PROTO_SERVICE_RE = /^service\s+(\w+)\s*\{/gm;
|
||||
const PROTO_MESSAGE_RE = /^message\s+(\w+)\s*\{/gm;
|
||||
const PROTO_RPC_RE = /^\s*rpc\s+(\w+)\s*\(/gm;
|
||||
|
||||
export function scanProtobuf(db: DBType, root: string): ScanStats {
|
||||
// Protobuf 扫描器骨架:扫描 packages/shared-proto/proto/*.proto
|
||||
return { contracts: 0 };
|
||||
}
|
||||
const insertContract = db.prepare(
|
||||
"INSERT OR IGNORE INTO contracts (name, type, file_path, service, content) VALUES (?, ?, ?, ?, ?)",
|
||||
);
|
||||
|
||||
let contracts = 0;
|
||||
|
||||
// 扫描 packages/shared-proto/proto/*.proto
|
||||
const protoDir = path.join(root, "packages", "shared-proto", "proto");
|
||||
if (!fs.existsSync(protoDir)) return { contracts };
|
||||
|
||||
const entries = fs.readdirSync(protoDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (!entry.isFile() || !entry.name.endsWith(".proto")) continue;
|
||||
const filePath = path.join(protoDir, entry.name);
|
||||
const protoName = path.basename(entry.name, ".proto");
|
||||
const serviceName = protoName.replace("_", "-");
|
||||
|
||||
let content: string;
|
||||
try {
|
||||
content = fs.readFileSync(filePath, "utf-8");
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 提取 package 名
|
||||
const pkgMatch = content.match(/^package\s+(\S+);/m);
|
||||
const pkgName = pkgMatch ? pkgMatch[1] : "";
|
||||
|
||||
// 记录 proto 文件作为契约
|
||||
insertContract.run(protoName, "proto-file", filePath, serviceName, pkgName);
|
||||
contracts++;
|
||||
|
||||
// 提取 service 定义
|
||||
let match: RegExpExecArray | null;
|
||||
const serviceRe = new RegExp(PROTO_SERVICE_RE);
|
||||
while ((match = serviceRe.exec(content)) !== null) {
|
||||
const name = match[1];
|
||||
insertContract.run(
|
||||
`${protoName}.${name}`,
|
||||
"service",
|
||||
filePath,
|
||||
serviceName,
|
||||
name,
|
||||
);
|
||||
contracts++;
|
||||
}
|
||||
|
||||
// 提取 message 定义
|
||||
const messageRe = new RegExp(PROTO_MESSAGE_RE);
|
||||
while ((match = messageRe.exec(content)) !== null) {
|
||||
const name = match[1];
|
||||
insertContract.run(
|
||||
`${protoName}.${name}`,
|
||||
"message",
|
||||
filePath,
|
||||
serviceName,
|
||||
name,
|
||||
);
|
||||
contracts++;
|
||||
}
|
||||
|
||||
// 提取 rpc 方法
|
||||
const rpcRe = new RegExp(PROTO_RPC_RE);
|
||||
while ((match = rpcRe.exec(content)) !== null) {
|
||||
const name = match[1];
|
||||
insertContract.run(
|
||||
`${protoName}.rpc.${name}`,
|
||||
"rpc",
|
||||
filePath,
|
||||
serviceName,
|
||||
name,
|
||||
);
|
||||
contracts++;
|
||||
}
|
||||
}
|
||||
|
||||
return { contracts };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user