path-resolver.ts•3.31 kB
import * as path from 'path';
/**
* 路径解析器
* 提供统一的路径处理功能
*/
export class PathResolver {
constructor() {}
/**
* 解析为绝对路径
* @param inputPath 输入路径
* @returns 规范化的绝对路径
*/
resolveAbsolute(inputPath: string): string {
if (!inputPath) {
throw new Error('路径不能为空');
}
// 如果已经是绝对路径,直接规范化
if (path.isAbsolute(inputPath)) {
return path.normalize(inputPath);
}
// 使用当前工作目录解析相对路径
return path.normalize(
path.join(
process.cwd(),
inputPath
)
);
}
/**
* 解析为相对路径
* @param inputPath 输入路径
* @param base 基准路径(默认为当前工作目录)
* @returns 相对路径
*/
resolveRelative(inputPath: string, base?: string): string {
if (!inputPath) {
throw new Error('路径不能为空');
}
const absPath = this.resolveAbsolute(inputPath);
const basePath = base ? this.resolveAbsolute(base) : process.cwd();
return path.relative(basePath, absPath);
}
/**
* 解析目录中的所有路径
* @param dir 目录路径
* @returns 解析后的目录路径
*/
resolveDirectory(dir: string): string {
return this.resolveAbsolute(dir);
}
/**
* 解析文件路径
* @param filePath 文件路径
* @returns 解析后的文件路径
*/
resolveFile(filePath: string): string {
return this.resolveAbsolute(filePath);
}
/**
* 解析对象中的所有路径属性
* @param obj 包含路径的对象
* @returns 解析后的新对象
*/
resolvePaths<T extends Record<string, unknown>>(obj: T): T {
const result = { ...obj } as T;
for (const [key, value] of Object.entries(obj)) {
// 处理路径相关的属性
if (typeof value === 'string' && (
key.toLowerCase().includes('path') ||
key.toLowerCase().includes('dir') ||
key.toLowerCase().includes('file')
)) {
try {
(result as Record<string, unknown>)[key] = this.resolveAbsolute(value);
} catch (err) {
const error = err instanceof Error ? err : new Error(String(err));
throw new Error(`解析路径失败 ${key}: ${value} - ${error.message}`);
}
}
// 递归处理嵌套对象
else if (value && typeof value === 'object' && !Array.isArray(value)) {
(result as Record<string, unknown>)[key] = this.resolvePaths(value as Record<string, unknown>);
}
}
return result;
}
/**
* 获取路径的共同根目录
* @param paths 路径数组
* @returns 共同的根目录
*/
findCommonRoot(paths: string[]): string {
if (paths.length === 0) {
return '';
}
const normalized = paths.map(p => this.resolveAbsolute(p));
let common = normalized[0].split(path.sep);
for (let i = 1; i < normalized.length; i++) {
const parts = normalized[i].split(path.sep);
const len = Math.min(common.length, parts.length);
for (let j = 0; j < len; j++) {
if (common[j] !== parts[j]) {
common = common.slice(0, j);
break;
}
}
}
return common.join(path.sep);
}
}