接入proto
This commit is contained in:
+83
-32
@@ -1,13 +1,15 @@
|
||||
// Tools/build-proto.js
|
||||
// Tools/Proto/build-proto.js
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
const SRC = path.join(__dirname, '..', '..', 'Proto'); // .proto 源文件目录
|
||||
const OUT_JS = path.join(__dirname, '..', '..', 'assets', 'Scripts', 'proto', 'proto.pb.js');
|
||||
const OUT_DTS = path.join(__dirname, '..', '..', 'assets', 'Scripts', 'proto', 'proto.pb.d.ts');
|
||||
const SRC = path.join(__dirname, '..', '..', 'Proto'); // 源 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 文件路径
|
||||
/** 递归收集所有 .proto 文件 */
|
||||
function walk(dir) {
|
||||
const files = [];
|
||||
for (const name of fs.readdirSync(dir)) {
|
||||
@@ -19,34 +21,83 @@ function walk(dir) {
|
||||
return files;
|
||||
}
|
||||
|
||||
const allProtoFiles = walk(SRC);
|
||||
if (allProtoFiles.length === 0) {
|
||||
console.error('没有找到任何 .proto 文件!');
|
||||
process.exit(1);
|
||||
/** 清空输出目录 */
|
||||
function clearOutput() {
|
||||
fs.emptyDirSync(OUT_DIR);
|
||||
console.log(`已清空目录: ${OUT_DIR}`);
|
||||
}
|
||||
|
||||
// 确保输出目录存在
|
||||
fs.mkdirSync(path.dirname(OUT_JS), { recursive: true });
|
||||
/** 给 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 导出`);
|
||||
}
|
||||
}
|
||||
|
||||
// 1) 生成一个 JS 文件
|
||||
execSync([
|
||||
'pbjs',
|
||||
'-t static-module',
|
||||
'-w es6', // 生成 ESM 语法
|
||||
'--dependency protobufjs/minimal.js',
|
||||
`-o "${OUT_JS}"`,
|
||||
`-p "${SRC}"`, // 让 pbjs 识别 proto import
|
||||
...allProtoFiles.map(f => `"${f}"`) // 所有 proto 文件
|
||||
].join(' '), { stdio: 'inherit' });
|
||||
/** 包装 d.ts 文件,修复 $protobuf & public 报错 */
|
||||
function wrapDTS(filePath) {
|
||||
let original = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// 2) 生成一个 TS 声明文件
|
||||
execSync([
|
||||
'pbts',
|
||||
'--main',
|
||||
`-o "${OUT_DTS}"`,
|
||||
`"${OUT_JS}"`
|
||||
].join(' '), { stdio: 'inherit' });
|
||||
// 1. 提取顶层 import(避免包进 namespace)
|
||||
const importLines = [];
|
||||
original = original.replace(/^(import\s+.*?;)\s*$/gm, (_, imp) => {
|
||||
importLines.push(imp);
|
||||
return '';
|
||||
});
|
||||
|
||||
console.log(`生成完成!
|
||||
JS 文件: ${OUT_JS}
|
||||
TS 文件: ${OUT_DTS}`);
|
||||
// 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();
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
const fs = require('fs-extra');
|
||||
const ps = require('path');
|
||||
|
||||
(async () => {
|
||||
// 目标输出目录(proto 生成文件存放处)
|
||||
const outDir = ps.join(__dirname, '..', '..', 'assets', 'Scripts', 'proto');
|
||||
|
||||
try {
|
||||
await fs.emptyDir(outDir);
|
||||
console.log(`已清空目录: ${outDir}`);
|
||||
} catch (err) {
|
||||
console.error(`清空目录失败: ${outDir}`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
@@ -1,34 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const DTS_DIR = path.join(__dirname, '..', '..', 'assets', 'Scripts', 'proto');
|
||||
const NAMESPACE = 'proto';
|
||||
|
||||
function walk(dir) {
|
||||
let results = [];
|
||||
for (const name of fs.readdirSync(dir)) {
|
||||
const p = path.join(dir, name);
|
||||
const stat = fs.statSync(p);
|
||||
if (stat.isDirectory()) results = results.concat(walk(p));
|
||||
else if (name.endsWith('.d.ts')) results.push(p);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
function wrapFile(filePath) {
|
||||
const original = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
if (original.includes(`declare namespace ${NAMESPACE}`)) {
|
||||
console.log(`跳过已包装文件: ${filePath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const wrapped = `declare namespace ${NAMESPACE} {\n${original}\n}\nexport default ${NAMESPACE};\n`;
|
||||
fs.writeFileSync(filePath, wrapped, 'utf8');
|
||||
console.log(`已包装文件: ${filePath}`);
|
||||
}
|
||||
|
||||
const files = walk(DTS_DIR);
|
||||
files.forEach(wrapFile);
|
||||
|
||||
console.log(`处理完成,共包装 ${files.length} 个 .d.ts 文件`);
|
||||
Reference in New Issue
Block a user