UNPKG

@arms/rum-harmonyos-plugin

Version:

Alibaba Cloud RUM plugin for HarmonyOS applications

197 lines (196 loc) 8.14 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AlibabaCloudRumPlugin = AlibabaCloudRumPlugin; const hvigor_1 = require("@ohos/hvigor"); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); // 插件标识符 const PLUGIN_TAG = "AlibabaCloudRum"; // 获取当前节点信息 const currentNode = (0, hvigor_1.getNode)(__filename); // 存储文件规则 let filesAndRules = { allFiles: [], replaceRules: [] }; /** * 创建插件实例 */ function AlibabaCloudRumPlugin() { return { pluginId: 'localAlibabaCloudRumPlugin', apply: (hvigorNode) => { // 注册注入任务 hvigorNode.registerTask({ name: 'alibabaCloudRumInjectTask', run: (context) => { filesAndRules = performInjection(hvigorNode); }, postDependencies: ['default@CompileArkTS'] }); // 注册重置任务 hvigorNode.registerTask({ name: 'resetAlibabaCloudRumInjectTask', run: () => { revertInjection(filesAndRules.allFiles, filesAndRules.replaceRules); }, dependencies: ['default@CompileArkTS'], postDependencies: ['assembleHap'] }); } }; } /** * 执行注入操作 * @param hvigorNode - 当前节点对象 * @returns 文件列表及替换规则 */ function performInjection(hvigorNode) { console.log(PLUGIN_TAG, '------------start AlibabaCloudRum -----------------'); if (!hvigorNode?.nodeDir?.filePath) { return { allFiles: [], replaceRules: [] }; } const projectRoot = hvigorNode.nodeDir.filePath; const configFilePath = path_1.default.join(projectRoot, 'alibabaCloudRumConfig.txt'); // 解析配置文件内容 const { filesToProcess, keepFiles } = parseConfigFile(configFilePath, projectRoot); // 使用插件内部的替换规则 const replaceRules = getInternalReplaceRules(); let processedFiles = []; // 处理指定目录或文件中的所有文件 processedFiles = getProcessedFiles(filesToProcess, keepFiles, projectRoot); // 筛选特定类型的文件(如 ts/js/ets) processedFiles = processedFiles.filter(filePath => /\.(ts|js|ets)$/.test(filePath)); // 对每个筛选出的文件执行替换操作 processedFiles.forEach(filePath => processReplacement(filePath, replaceRules, false)); console.log(PLUGIN_TAG, '------------end AlibabaCloudRum -----------------'); return { allFiles: processedFiles, replaceRules }; } /** * 获取插件内部的替换规则 * @returns 固定的替换规则数组 */ function getInternalReplaceRules() { return [ { pattern: escapeRegExp('http.createHttp();'), replacement: 'ALRHttp.createHttp();', imports: ['import {ALRHttp} from \'@alibabacloud_rum/harmony_sdk\';'] }, { pattern: escapeRegExp('rcp.createSession('), replacement: 'ALRRcp.createSession(', imports: ['import {ALRRcp} from \'@alibabacloud_rum/harmony_sdk\';'] }, { pattern: escapeRegExp('socket.constructTCPSocketInstance()'), replacement: 'ALRTcpSocket.constructTCPSocketInstance()', imports: ['import { ALRTcpSocket } from \'@alibabacloud_rum/harmony_sdk\';'] }, { pattern: escapeRegExp('webSocket.createWebSocket()'), replacement: 'ALRWebSocket.createWebSocket()', imports: ['import { ALRWebSocket } from \'@alibabacloud_rum/harmony_sdk\';'] } ]; } /** * 执行重置操作 * @param processedFiles - 已处理过的文件列表 * @param rules - 替换规则 */ function revertInjection(processedFiles, rules) { console.log(PLUGIN_TAG, '============start reset AlibabaCloudRum ================='); // 如果缺少必要的参数,则打印错误信息并返回 if (!processedFiles || !rules) { console.error(PLUGIN_TAG, 'ERROR: Missing required parameters for revertInjection.'); return; } // 对每个已处理过的文件执行反向替换操作 processedFiles.forEach(filePath => processReplacement(filePath, rules, true)); console.log(PLUGIN_TAG, '============end reset AlibabaCloudRum ================='); } // 辅助函数 function parseConfigFile(configFilePath, rootDir) { const filesToProcess = []; const keepFiles = []; const lines = fs_1.default.readFileSync(configFilePath, 'utf-8').split('\n'); lines.map(line => line.trim()) .filter(line => line.length > 0 && !line.startsWith('#')) .forEach(line => { if (line.startsWith('-hook ')) { filesToProcess.push(resolvePath(line.substring(6).trim(), rootDir)); } else if (line.startsWith('-keep ')) { keepFiles.push(resolvePath(line.substring(6).trim(), rootDir)); } }); return { filesToProcess, keepFiles }; } function resolvePath(filePath, rootDir) { let absPath = path_1.default.isAbsolute(filePath) ? filePath : path_1.default.resolve(rootDir, `.${path_1.default.sep}${filePath}`); return absPath; } function escapeRegExp(string) { return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); } function unescapeRegExp(string) { return string.replace(/\\([.*+\-?^${}()|[\]\\])/g, '$1'); } function getProcessedFiles(filesToProcess, keepFiles, projectRoot) { let processedFiles = []; if (filesToProcess.length > 0) { processedFiles = filesToProcess.flatMap(fileOrDir => { if (fs_1.default.statSync(fileOrDir).isDirectory()) { return getAllFiles(fileOrDir, keepFiles); } else { return shouldKeep(fileOrDir, keepFiles) ? [] : [fileOrDir]; } }); } else { processedFiles = getAllFiles(projectRoot, keepFiles); } return processedFiles; } function getAllFiles(dir, keepFiles, fileList = []) { if (!fs_1.default.existsSync(dir)) { console.error(PLUGIN_TAG, `ERROR: Directory does not exist: ${dir}`); return fileList; } fs_1.default.readdirSync(dir).forEach(file => { const filePath = path_1.default.join(dir, file); if (fs_1.default.statSync(filePath).isDirectory()) { if (!shouldKeep(filePath, keepFiles)) { getAllFiles(filePath, keepFiles, fileList); } } else { if (!shouldKeep(filePath, keepFiles)) { fileList.push(filePath); } } }); return fileList; } function shouldKeep(filePath, keepFiles) { return keepFiles.some(keepFile => filePath.startsWith(keepFile)); } function processReplacement(filePath, rules, isReverse) { let contentLines = fs_1.default.readFileSync(filePath, 'utf-8').split('\n'); let modified = false; if (isReverse) { rules.forEach(({ imports }) => { imports.forEach((importStatement) => { contentLines = contentLines.filter(line => line.trim() !== importStatement.trim()); }); }); } rules.forEach(({ pattern, replacement, imports }) => { const searchPattern = isReverse ? escapeRegExp(replacement) : pattern; const replaceValue = isReverse ? unescapeRegExp(pattern) : replacement; const regex = new RegExp(searchPattern, 'g'); contentLines.forEach((line, index) => { if (line.match(regex)) { contentLines[index] = line.replace(regex, replaceValue); modified = true; } }); if (!isReverse && modified) { imports.forEach((statement) => { if (!contentLines.includes(statement)) { contentLines.unshift(statement); } }); } }); if (modified) { fs_1.default.writeFileSync(filePath, contentLines.join('\n'), 'utf-8'); console.warn(PLUGIN_TAG, isReverse ? `File reset: ${filePath}` : `File modified: ${filePath}`); } }