UNPKG

mp-lens

Version:

微信小程序分析工具 (Unused Code, Dependencies, Visualization)

223 lines 10.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.AliasResolver = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const debug_logger_1 = require("./debug-logger"); /** * 别名解析器: 负责从不同配置文件中加载路径别名 */ class AliasResolver { constructor(projectRoot) { this.aliases = {}; this.initialized = false; this.projectRoot = projectRoot; } /** * 初始化别名解析器 * @returns 是否找到有效的别名配置 */ initialize() { if (this.initialized) return Object.keys(this.aliases).length > 0; // 尝试从不同来源加载别名 const foundTsConfig = this.loadFromTsConfig(); const foundCustomConfig = this.loadFromCustomConfig(); if (foundTsConfig) { debug_logger_1.logger.info(`已从tsconfig.json加载别名配置`); } if (foundCustomConfig) { debug_logger_1.logger.info(`已从mp-lens.config.json加载别名配置`); } if (this.projectRoot) { debug_logger_1.logger.info(`alias解析的根目录: ${this.projectRoot}`); } this.initialized = true; // 如果至少找到一个来源的别名配置,返回true return foundTsConfig || foundCustomConfig; } /** * 解析别名路径 * @param importPath 导入路径 * @param currentFile 当前文件路径 * @returns 解析后的路径,如果找不到匹配的别名则返回null */ resolve(importPath, currentFile) { if (!this.initialized) { this.initialize(); } debug_logger_1.logger.trace(`Resolving alias prefix for import '${importPath}' in file '${currentFile}'`); for (const [alias, targets] of Object.entries(this.aliases)) { // Basic alias pattern check (e.g., starts with @/ or aliasName/) const aliasPrefix = alias + '/'; // e.g., "@/" if (importPath.startsWith(aliasPrefix)) { debug_logger_1.logger.trace(`Found matching alias prefix: ${alias} => ${targets.join(' or ')}`); // Try the first target path defined for the alias // TODO: Handle multiple targets? For now, use the first. if (targets.length > 0) { const target = targets[0]; // target can be absolute (tsconfig) or relative (custom config) const resolvedBaseDir = path.isAbsolute(target) ? target : path.resolve(this.projectRoot, target); // Get the part of the import path *after* the alias prefix const remainingPath = importPath.substring(aliasPrefix.length); // Construct the potential absolute path *without* extension checking const potentialPath = path.join(resolvedBaseDir, remainingPath); debug_logger_1.logger.trace(`Alias resolved to potential base path: ${potentialPath}`); // Return the potential path. The caller (FileParser) will handle existence checks, // index files, and extension appending based on context. return potentialPath; } else { debug_logger_1.logger.warn(`Alias '${alias}' found but has no target paths defined.`); } // If we found a matching alias but couldn't resolve (e.g., no targets), // stop checking other aliases for this import path. return null; } // Handle aliases without a trailing slash (e.g., alias maps directly to a file/dir) else if (importPath === alias) { debug_logger_1.logger.trace(`Found matching alias (exact match): ${alias} => ${targets.join(' or ')}`); if (targets.length > 0) { const target = targets[0]; const potentialPath = path.isAbsolute(target) ? target : path.resolve(this.projectRoot, target); debug_logger_1.logger.trace(`Alias resolved to potential base path: ${potentialPath}`); return potentialPath; } else { debug_logger_1.logger.warn(`Alias '${alias}' found but has no target paths defined.`); } return null; } } debug_logger_1.logger.trace(`No matching alias prefix found for ${importPath}`); return null; // No alias matched } /** * 从tsconfig.json加载路径别名 * @returns 是否成功加载到别名配置 */ loadFromTsConfig() { // 首先尝试在项目根目录查找 let tsconfigPath = path.join(this.projectRoot, 'tsconfig.json'); // 如果根目录没有,可能在上级目录 if (!fs.existsSync(tsconfigPath)) { // 尝试向上查找,最多向上3级 let currentDir = this.projectRoot; let found = false; for (let i = 0; i < 3; i++) { currentDir = path.dirname(currentDir); const testPath = path.join(currentDir, 'tsconfig.json'); if (fs.existsSync(testPath)) { tsconfigPath = testPath; found = true; break; } } if (!found) { return false; } } try { debug_logger_1.logger.debug(`尝试从${tsconfigPath}加载别名配置`); const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf-8')); if (tsconfig.compilerOptions && tsconfig.compilerOptions.paths) { // 获取tsconfig所在目录,因为paths是相对于tsconfig的baseUrl const tsconfigDir = path.dirname(tsconfigPath); const baseUrl = tsconfig.compilerOptions.baseUrl || '.'; const baseDir = path.resolve(tsconfigDir, baseUrl); debug_logger_1.logger.debug(`tsconfig.json的baseUrl: ${baseUrl}, 解析为: ${baseDir}`); for (const [alias, targets] of Object.entries(tsconfig.compilerOptions.paths)) { // 处理 paths 中的通配符模式 (如 "@/*" => ["src/*"]) const normalizedAlias = alias.replace(/\/\*$/, ''); // e.g., '@' this.aliases[normalizedAlias] = targets.map((target) => { const targetPath = target.replace(/\/\*$/, ''); // e.g., 'src' // 总是解析为绝对路径 const absoluteTargetPath = path.resolve(baseDir, targetPath); debug_logger_1.logger.verbose(`Mapping alias '${normalizedAlias}' target '${target}' -> '${absoluteTargetPath}'`); return absoluteTargetPath; }); } debug_logger_1.logger.debug('从tsconfig.json加载的别名:', this.aliases); return Object.keys(this.aliases).length > 0; } } catch (error) { debug_logger_1.logger.warn(`无法解析 tsconfig.json: ${error.message}`); } return false; } /** * 从自定义配置文件加载路径别名 * @returns 是否成功加载到别名配置 */ loadFromCustomConfig() { // 尝试从mp-lens.config.json加载配置 const configPath = path.join(this.projectRoot, 'mp-lens.config.json'); if (!fs.existsSync(configPath)) { return false; } try { const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); if (config.aliases && typeof config.aliases === 'object') { const initialAliasCount = Object.keys(this.aliases).length; for (const [alias, targets] of Object.entries(config.aliases)) { this.aliases[alias] = Array.isArray(targets) ? targets : [targets]; } // 检查是否添加了新的别名 return Object.keys(this.aliases).length > initialAliasCount; } } catch (error) { debug_logger_1.logger.warn(`Failed to parse mp-lens.config.json: ${error.message}`); } return false; } /** * 获取所有配置的别名 */ getAliases() { if (!this.initialized) { this.initialize(); } return this.aliases; } } exports.AliasResolver = AliasResolver; //# sourceMappingURL=alias-resolver.js.map