/* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { hvigor, HvigorNode } from '@ohos/hvigor'; import path from 'path'; import fs from 'fs'; import { PathConstants } from '../constants/PathConstants'; import { Logger } from '../core/logger/Logger'; export class PBConfig { exePath: string; pluginPath: string; scanDir: Array; public saveDir: string; namePattern: string; sendable: boolean; debug: boolean; enableFunctions: string[]; srcDir: string; otheMap: Map = new Map(); paras: Record = {}; public protoFiles: string[] = []; public setParas(paras: Record) { this.paras = paras; } constructor() { this.exePath = PathConstants.exePath; this.scanDir = PathConstants.scanDir; this.saveDir = PathConstants.saveDir; this.namePattern = PathConstants.namePattern; this.sendable = PathConstants.sendable; this.debug = PathConstants.debug; this.enableFunctions = PathConstants.enableFunctions; this.pluginPath = PathConstants.pluginPath; this.srcDir = PathConstants.srcDir; } public parseParas() { Object.entries(this.paras).forEach(([key, value]) => { if (key == "scanDir") { this.scanDir = value; } else if (key == "saveDir") { this.saveDir = value; } else if (key == "namePattern") { this.namePattern = value; } else if (key == "sendable") { this.sendable = value; } else if (key == "debug") { this.debug = value; } else if (key == "enableFunctions") { this.enableFunctions = value; } else if (key == "ignoreModuleNames") { } else { this.otheMap.set(key, value); } }); } public getExeParaStr(subNode: HvigorNode): string { if (this.exePath == "") { this.exePath = this.getDefaultExePath(); } const subNodeName = subNode.getNodeName(); let str: string = '\"' + this.exePath + '\"'; const subNodePath = subNode.getNodePath(); const scanPath = this.getScanPath(subNodePath); if (scanPath === '') { return ''; // 立即返回 } str += this.getSrcPath(); str += this.getPluginPath(); str += this.getSavePath(subNodePath); str += this.getOptInfo(); str += scanPath; this.otheMap.forEach((value, key) => { str += " " + key; if ((value != null) && (value != "")) { str += "=" + value; } }); return str; } private getDefaultExePath(): string { const rootNode = hvigor.getRootNode(); const moduleFile = rootNode.nodeDir; let exePath = path.join(moduleFile.getPath(), PathConstants.exePath); return exePath; } private getSrcPath(): string { let pluginPathStr = " -I="; return pluginPathStr += this.srcDir; } private getPluginPath(): string { let pluginPathStr = " --plugin=protoc-gen-ArkTS="; return pluginPathStr += this.pluginPath; } private getSavePath(subNodePath: string): string { let savePathStr = " --ArkTS_out="; const saveDir = path.join(subNodePath, this.saveDir); return savePathStr += saveDir; } private _scanDirectory(currentPath: string, rootPath: string): string[] { const protoFiles: string[] = []; const files = fs.readdirSync(currentPath); for (const file of files) { const fullPath = path.join(currentPath, file); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { // 递归扫描子目录 const subDirResults = this._scanDirectory(fullPath, rootPath); protoFiles.push(...subDirResults); } else if (stat.isFile() && file.endsWith('.proto')) { // 获取文件相对于根路径的相对路径 const relativePath = path.relative(rootPath, fullPath); protoFiles.push(relativePath); } } return protoFiles; } private getScanPath(subNodePath: string): string { let scanPathStr = " -I="; const protoFiles: string[] = []; const rootNodePath = hvigor.getRootNode().getNodePath(); const currentPath = path.relative(rootNodePath, subNodePath); // 遍历 scanDir 中的每个子目录 for (const dir of this.scanDir) { const fullPath = path.join(currentPath, dir); // 检查目录是否存在 if (!fs.existsSync(fullPath)) { continue; } // 递归扫描目录 const scanResults = this._scanDirectory(fullPath, rootNodePath); if (scanResults.length !== 0) { scanPathStr += fullPath + ' '; } protoFiles.push(...scanResults); } const scanDirStr = '[' + this.scanDir.map(dir => `'${dir}'`).join(', ') + ']'; // 如果没有找到任何 .proto 文件,立即返回空字符串 if (protoFiles.length === 0) { Logger.debug(`No .proto files found in: ${subNodePath}, scanDir: ${scanDirStr}`); return ''; } else { Logger.info(`Scanned ${protoFiles.length} .proto files in: ${subNodePath}, scanDir: ${scanDirStr}`); try { const saveDir = path.join(subNodePath, this.saveDir); if (!fs.existsSync(saveDir)) { fs.mkdirSync(saveDir, { recursive: true }); Logger.info(`Directory created successfully: ${saveDir}`); } } catch (error: any) { Logger.error(`Failed to create directory: ${error}`); } } this.protoFiles = protoFiles; // 用空格拼接所有文件的路径 return scanPathStr + protoFiles.join(' '); } private getOptInfo(): string { let optInfoStr = ' --ArkTS_opt='; const transformedOptInfo: Record = {}; transformedOptInfo['logPattern'] = this.debug ? 'Debug' : 'DefaultLog'; if (this.enableFunctions.length > 0) { transformedOptInfo['enableFunctions'] = `"${this.enableFunctions.join('&')}"`; } transformedOptInfo['sendable'] = this.sendable; transformedOptInfo['namePattern'] = this.namePattern; optInfoStr += Object.entries(transformedOptInfo) .map(([key, val]) => `${key}=${val}`) .join(','); return optInfoStr; } }