mp-lens
Version:
微信小程序分析工具 (Unused Code, Dependencies, Visualization)
241 lines • 11.8 kB
JavaScript
;
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.PathResolver = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const debug_logger_1 = require("./debug-logger");
class PathResolver {
constructor(projectRoot, options, aliasResolver, hasAliasConfig) {
this.projectRoot = projectRoot;
this.options = options; // Store options, especially for miniappRoot
this.aliasResolver = aliasResolver;
this.hasAliasConfig = hasAliasConfig;
}
/**
* Resolves an import path (which could be relative, absolute, alias, or implicit root)
* to an existing file path, considering context-specific allowed extensions.
*
* @param importPath The original import string (e.g., './utils', '/pages/index', '@/comp', 'image.png').
* @param sourcePath The absolute path of the file containing the import.
* @param allowedExtensions An ordered array of extensions to check (e.g., ['.js', '.ts'] or ['.wxml']).
* @returns The absolute path of the resolved existing file, or null if not found.
*/
resolveAnyPath(importPath, sourcePath, allowedExtensions) {
debug_logger_1.logger.trace(`Resolving import '${importPath}' from '${sourcePath}' with allowed extensions: [${allowedExtensions.join(', ')}]`);
// Rule 0: Handle data URIs and remote URLs
if (/^data:/.test(importPath) || /^(http|https|\/\/):/.test(importPath)) {
debug_logger_1.logger.trace(`Skipping resolution for data URI or remote URL: ${importPath}`);
return null;
}
if (this.isNpmPackageImport(importPath)) {
debug_logger_1.logger.trace(`Skipping resolution for npm package import: ${importPath}`);
return null;
}
if (path.isAbsolute(importPath)) {
debug_logger_1.logger.trace(`Input importPath '${importPath}' is absolute. Checking direct existence first.`);
const existingAbsolutePath = this.findExistingPath(importPath, allowedExtensions);
if (existingAbsolutePath) {
debug_logger_1.logger.trace(`Found existing file at true absolute path: ${existingAbsolutePath}. Returning directly.`);
return existingAbsolutePath;
}
else {
debug_logger_1.logger.trace(`Absolute path '${importPath}' not found directly. Will proceed to normal resolution (might be root-relative).`);
}
}
let potentialBasePath = null;
let isAlias = false;
if (this.isAliasPath(importPath) && this.aliasResolver) {
isAlias = true;
potentialBasePath = this.aliasResolver.resolve(importPath, sourcePath);
if (potentialBasePath) {
debug_logger_1.logger.trace(`Alias resolved to base path: ${potentialBasePath}`);
}
else {
debug_logger_1.logger.warn(`Alias '${importPath}' detected but could not be resolved by AliasResolver.`);
return null;
}
}
if (!potentialBasePath) {
const sourceDir = path.dirname(sourcePath);
const miniappRoot = this.options.miniappRoot || this.projectRoot;
if (importPath.startsWith('/')) {
potentialBasePath = path.resolve(miniappRoot, importPath.slice(1));
}
else if (importPath.startsWith('.')) {
potentialBasePath = path.resolve(sourceDir, importPath);
}
else {
potentialBasePath = path.resolve(miniappRoot, importPath);
}
debug_logger_1.logger.trace(`Path resolved to potential base path: ${potentialBasePath}`);
}
if (potentialBasePath) {
const existingPath = this.findExistingPath(potentialBasePath, allowedExtensions);
if (existingPath) {
debug_logger_1.logger.trace(`Resolved '${importPath}' to existing file: ${existingPath}`);
return existingPath;
}
else if (isAlias) {
debug_logger_1.logger.warn(`Alias resolved to '${potentialBasePath}', but no existing file found with extensions [${allowedExtensions.join(', ')}]`);
}
}
if (!isAlias) {
debug_logger_1.logger.warn(`Failed to resolve import '${importPath}' from '${sourcePath}'.`);
}
return null;
}
/**
* Given a potential absolute base path (without extension or index), finds the
* actual existing file path by checking for the path itself, adding allowed
* extensions, or checking for directory index files with allowed extensions.
*
* @param potentialPath Absolute path, possibly without extension (e.g., '/path/to/file' or '/path/to/dir')
* @param allowedExtensions Ordered list of extensions to check (e.g., ['.js', '.ts'])
* @returns The existing absolute file path, or null.
*/
findExistingPath(potentialPath, allowedExtensions) {
debug_logger_1.logger.trace(`Looking for existing path: ${potentialPath} with extensions: ${allowedExtensions}`);
let potentialPathIsDir = false;
try {
const stats = fs.statSync(potentialPath);
if (stats.isFile()) {
debug_logger_1.logger.trace(`Check 1: Exact path exists and is a file: ${potentialPath}`);
return potentialPath; // Exact match and is a file
}
else if (stats.isDirectory()) {
debug_logger_1.logger.trace(`Check 1: Exact path exists and is a directory: ${potentialPath}`);
potentialPathIsDir = true; // It's a directory, continue to check index files
}
}
catch (e) {
debug_logger_1.logger.trace(`Check 1: Exact path does not exist: ${potentialPath}`);
}
// Check 2: Try appending allowed extensions if it wasn't a directory
if (!potentialPathIsDir) {
debug_logger_1.logger.trace(`Check 2: Trying extensions for base path: ${potentialPath}`);
for (const ext of allowedExtensions) {
const pathWithExt = potentialPath + ext;
debug_logger_1.logger.trace(`Check 2a: Checking path with extension: ${pathWithExt}`);
try {
const stats = fs.statSync(pathWithExt);
if (stats.isFile()) {
debug_logger_1.logger.trace(`Check 2b: Found file with extension: ${pathWithExt}`);
return pathWithExt;
}
else {
debug_logger_1.logger.trace(`Check 2b: Path with extension not found or not a file: ${pathWithExt}`);
}
}
catch (e) {
debug_logger_1.logger.trace(`Check 2b: Error stating path ${pathWithExt}: ${e.message}`);
}
}
}
// Check 3: If the original path was a directory OR it wasn't found with extensions, check for index files
debug_logger_1.logger.trace(`Check 3: Checking for index files in directory: ${potentialPath}`);
for (const ext of allowedExtensions) {
const indexFilePath = path.join(potentialPath, 'index' + ext);
debug_logger_1.logger.trace(`Check 3a: Checking index file: ${indexFilePath}`);
try {
const stats = fs.statSync(indexFilePath);
if (stats.isFile()) {
debug_logger_1.logger.trace(`Check 3b: Found index file: ${indexFilePath}`);
return indexFilePath;
}
else {
debug_logger_1.logger.trace(`Check 3b: Index file not found or not a file: ${indexFilePath}`);
}
}
catch (e) {
debug_logger_1.logger.trace(`Check 3b: Error stating index file ${indexFilePath}: ${e.message}`);
}
}
debug_logger_1.logger.trace(`Failed to find existing path for: ${potentialPath}`);
return null; // Nothing found
}
/**
* Check if the import path looks like an alias based on the loaded configuration.
*/
isAliasPath(importPath) {
if (!this.hasAliasConfig || !this.aliasResolver) {
return false;
}
const aliases = this.aliasResolver.getAliases();
if (Object.keys(aliases).length === 0) {
return false;
}
if (importPath in aliases) {
return true;
}
for (const alias of Object.keys(aliases)) {
if (importPath === alias || importPath.startsWith(`${alias}/`)) {
return true;
}
}
return false;
}
/**
* Check if the import path looks like an npm package that we shouldn't try to resolve
* on the file system or with aliases.
*/
isNpmPackageImport(importPath) {
// First check: if it's an absolute path, it's definitely not an npm package
if (path.isAbsolute(importPath)) {
return false;
}
if (importPath.startsWith('@')) {
const scope = importPath.split('/')[0];
if (this.hasAliasConfig && this.aliasResolver) {
const aliases = this.aliasResolver.getAliases();
if (scope in aliases ||
Object.keys(aliases).some((alias) => alias === scope || alias.startsWith(`${scope}/`))) {
return false; // It's a configured alias, not necessarily an npm package
}
}
return true; // Starts with @ and doesn't match a configured alias scope
}
// Basic check: if it doesn't start with '.', '/', or match an alias, it *might* be an npm package.
if (!importPath.startsWith('.') &&
!importPath.startsWith('/') &&
!this.isAliasPath(importPath)) {
debug_logger_1.logger.trace(`Path '${importPath}' is non-relative, non-absolute, non-alias. Considering as NPM package.`);
return true; // MODIFIED: Was false, now true for paths like 'lodash'
}
return false; // Default to false if none of the above conditions met (e.g. relative paths)
}
}
exports.PathResolver = PathResolver;
//# sourceMappingURL=path-resolver.js.map