// Tools/Proto/build-proto.js const { execSync } = require('child_process'); const fs = require('fs-extra'); const path = require('path'); const SRC = path.join(__dirname, '..', '..', 'proto_cs'); // 源 proto 文件目录 const OUT_DIR = path.join(__dirname, '..', '..', 'assets', 'Scripts', 'proto'); const OUT_JS = path.join(OUT_DIR, 'proto.pb.js'); const OUT_DTS = path.join(OUT_DIR, 'proto.pb.d.ts'); const NAMESPACE = 'proto'; /** 递归收集所有 .proto 文件 */ function walk(dir) { const files = []; for (const name of fs.readdirSync(dir)) { const p = path.join(dir, name); const stat = fs.statSync(p); if (stat.isDirectory()) files.push(...walk(p)); else if (name.endsWith('.proto')) files.push(p); } return files; } /** 清空输出目录 */ function clearOutput() { fs.emptyDirSync(OUT_DIR); console.log(`已清空目录: ${OUT_DIR}`); } /** 给 CJS 文件添加 default 导出 */ function addDefaultExport(jsFile) { let code = fs.readFileSync(jsFile, 'utf8'); if (/module\.exports\s*=/.test(code) && !/module\.exports\.default\s*=/.test(code)) { code += `\nmodule.exports.default = module.exports;`; fs.writeFileSync(jsFile, code, 'utf8'); console.log(`已为 ${path.basename(jsFile)} 添加 default 导出`); } } /** 包装 d.ts 文件,修复 $protobuf & public 报错 */ function wrapDTS(filePath) { let original = fs.readFileSync(filePath, 'utf8'); // 1. 提取顶层 import(避免包进 namespace) const importLines = []; original = original.replace(/^(import\s+.*?;)\s*$/gm, (_, imp) => { importLines.push(imp); return ''; }); // 2. 去掉 public 修饰符 original = original.replace(/^\s*public\s+/gm, ''); // 3. 包装 namespace const wrapped = `${importLines.join('\n')}\n\ndeclare namespace ${NAMESPACE} {\n${original}\n}\nexport default ${NAMESPACE};\n`; fs.writeFileSync(filePath, wrapped, 'utf8'); console.log(`已包装文件: ${filePath}`); } /** 主构建流程 */ function build() { clearOutput(); const allProtoFiles = walk(SRC); if (allProtoFiles.length === 0) { console.error('没有找到任何 .proto 文件!'); process.exit(1); } fs.mkdirpSync(OUT_DIR); // 1) 生成 JS(CJS 格式,方便加 default) execSync([ 'pbjs', '-t static-module', '-w commonjs', // 用 commonjs 避免 ESM 重复 default '--dependency protobufjs/minimal.js', `-o "${OUT_JS}"`, `-p "${SRC}"`, ...allProtoFiles.map(f => `"${f}"`) ].join(' '), { stdio: 'inherit' }); // 2) 添加 default 导出 addDefaultExport(OUT_JS); // 3) 生成 d.ts execSync([ 'pbts', '--main', `-o "${OUT_DTS}"`, `"${OUT_JS}"` ].join(' '), { stdio: 'inherit' }); // 4) wrap d.ts wrapDTS(OUT_DTS); console.log(`\nProto 生成完成! JS 文件: ${OUT_JS} TS 文件: ${OUT_DTS} 共处理 ${allProtoFiles.length} 个 .proto 文件`); } build();