const fs = require('fs') const path = require('path') /** * PB 模块导入导出代码生成器 * @param {string} pbDir - PB 文件所在的目录路径 * @param {string} outputFile - 生成的代码输出文件路径 * @param {string} [relativePath='../pb'] - 导入语句中的相对路径 */ function generatePbImportsAndExports(pbDir, outputFile, relativePath = '../pb') { try { // 读取 PB 目录下的所有文件 const files = fs.readdirSync(pbDir) // 过滤出 .js 文件并去除扩展名 const jsFiles = files.filter((file) => file.endsWith('.js')) if (jsFiles.length === 0) { console.warn(`警告: 在目录 ${pbDir} 中没有找到任何 .js 文件`) return } // 生成导入语句 const importStatements = jsFiles .map((file) => { const moduleName = file.replace('.js', '') return `import ${moduleName} from '${relativePath}/${moduleName}.js'` }) .join('\n') // 为每个文件生成导出内容 const moduleExports = {} const allExports = new Set() const exportSources = {} // 记录每个导出项的来源 jsFiles.forEach((file) => { const filePath = path.join(pbDir, file) const code = fs.readFileSync(filePath, 'utf-8') const moduleName = file.replace('.js', '') // 提取 $root.X 形式的导出 const rootExports = extractRootExports(code) // 提取 enum 定义 const enumExports = extractEnumExports(code) // 合并所有导出 const exports = [...rootExports, ...enumExports] if (exports.length > 0) { moduleExports[moduleName] = exports // 记录导出项的来源 exports.forEach((exp) => { if (!exportSources[exp]) { exportSources[exp] = moduleName allExports.add(exp) } }) } }) if (allExports.size === 0) { console.warn(`警告: 没有找到任何可导出的类或枚举`) return } // 生成解构赋值语句(只包含首次出现的导出项) const destructureStatements = Object.entries(moduleExports) .map(([moduleName, exports]) => { // 过滤出该模块独有的导出项 const uniqueExports = exports.filter((exp) => exportSources[exp] === moduleName) if (uniqueExports.length > 0) { return `const { ${uniqueExports.join(', ')} } = ${moduleName}` } return '' }) .filter(Boolean) // 移除空字符串 .join('\n') // 生成导出语句(所有唯一导出项) const exportList = Array.from(allExports) // 完整的输出代码 const outputCode = `// 由 pb-import-export-generator 自动生成,请勿手动修改\n\n` + `// 导入语句\n${importStatements}\n\n` + `// 解构赋值\n${destructureStatements}\n\n` + `// 导出语句\nexport {\n ${exportList.join(',\n ')}\n};\n` // 确保输出目录存在 const outputDir = path.dirname(outputFile) if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }) } // 写入输出文件 fs.writeFileSync(outputFile, outputCode) console.log(`成功生成 PB 导入导出代码到 ${outputFile}`) console.log(`共生成 ${jsFiles.length} 个导入语句和 ${exportList.length} 个导出变量`) } catch (error) { console.error('生成 PB 导入导出代码时出错:', error.message) } } /** * 提取 $root.X 形式的导出 */ function extractRootExports(code) { const exports = [] const rootExportRegex = /\$root\.([A-Za-z][A-Za-z0-9_]*)\s*=/g let match while ((match = rootExportRegex.exec(code)) !== null) { exports.push(match[1]) } return exports } /** * 提取 enum 定义 */ function extractEnumExports(code) { const exports = [] const enumRegex = /@enum\s*{.*?}\s*\n\s*\*\s*@exports\s+([A-Za-z][A-Za-z0-9_]*)/g let match while ((match = enumRegex.exec(code)) !== null) { exports.push(match[1]) } return exports } // 示例用法 generatePbImportsAndExports('../assets/scripts/pb', '../assets/scripts/network/pbExport.ts')