import { FileSystem } from "./fileSystem"; /** 表示一个模块路径解析器 */ export declare class Resolver { /** * 初始化新的解析器 * @param options 附加选项 * @param fs 使用的文件系统 */ constructor(options?: ResolverOptions, fs?: FileSystem); /** 解析结果的缓存,键为要解析的模块名和所在文件夹 */ private _resolveCache; /** 缓存的键是否包含所在的文件夹 */ private _cacheWithContainingDir?; /** * 解析指定的模块名对应的绝对路径,如果找不到模块则返回 `null`,如果模块被忽略则返回 `false` * @param moduleName 要解析的模块名,不允许是空字符串 * @param containingDir 所在文件夹的绝对路径 * @param trace 如果提供了数组,则用于收集本次解析的日志 */ resolve(moduleName: string, containingDir: string, trace?: string[]): Promise; /** 获取所有模块的别名 */ readonly alias: ({ /** 匹配的正则表达式 */ match: RegExp; /** 匹配后用于替换的内容,如果是 `false` 表示忽略该模块 */ replacements: (string | ((input: string, ...parts: any[]) => string) | false)[]; })[]; /** 获取要搜索的文件夹路径 */ readonly modules: { /** 当前文件夹路径是否是绝对路径 */ absolute: boolean; /** 当前文件夹路径 */ path: string; }[]; /** 获取所有包描述文件中包含模块别名信息的字段名 */ readonly aliasFields: string[]; /** * 忽略缓存解析指定的模块名对应的绝对路径,如果找不到模块则返回 `null`,如果模块被忽略则返回 `false` * @param moduleName 要解析的模块名,不允许是空字符串 * @param containingDir 所在文件夹的绝对路径 * @param trace 如果提供了数组,则用于收集本次解析的日志 * @param ignoreAliasField 是否忽略别名字段 * @param ignoreAlias 是否忽略别名 */ protected resolveNoCache(moduleName: string, containingDir: string, trace?: string[], ignoreAliasField?: boolean, ignoreAlias?: boolean): Promise; /** 获取所有包描述文件中包含入口模块的字段名 */ readonly mainFields: string[]; /** 获取所有默认的入口模块名 */ readonly mainFiles: string[]; /** 获取所有解析模块名时尝试自动追加的扩展名 */ readonly extensions: string[]; /** * 解析一个文件或文件夹路径,如果找不到模块则返回 `null`,如果模块被忽略则返回 `false` * @param moduleName 要解析的模块名,不允许是空字符串 * @param containingDir 所在文件夹的绝对路径 * @param trace 如果提供了数组,则用于收集本次解析的日志 * @param ignoreAliasField 如果路径已成功解析为文件,是否忽略别名字段 * @param ignoreMainFields 如果路径是文件夹,是否忽略入口模块字段 * @param noExtension 如果为 `true`,则解析文件路径时允许不追加扩展名,如果为 `false`,则强制解析文件路径时追加扩展名 */ protected resolveFileOrDir(moduleName: string, containingDir: string, trace?: string[], ignoreAliasField?: boolean, ignoreMainFields?: boolean, noExtension?: boolean): Promise; /** 获取所有包描述文件名 */ readonly descriptionFiles: string[]; /** 描述文件数据的缓存 */ private readonly _descriptionFileCache; /** * 查找并解析属于某个文件夹的描述文件(如 `package.json`),如果文件不存在或解析失败则返回 `null` * @param dir 要查找的文件夹 * @param trace 如果提供了数组,则用于收集本次解析的日志 */ lookupDescriptionFile(dir: string, trace?: string[]): Promise; /** * 读取属于某个文件夹的描述文件(如 `package.json`),如果文件不存在或解析失败则返回 `null` * @param dir 要查找的文件夹 * @param trace 如果提供了数组,则用于收集本次解析的日志 */ protected readDescriptionFile(dir: string, trace?: string[]): Promise; /** * 忽略缓存读取属于某个文件夹的描述文件(如 `package.json`),如果文件不存在或解析失败则返回 `null` * @param dir 要查找的文件夹 * @param trace 如果提供了数组,则用于收集本次解析的日志 */ protected readDescriptionFileNoCache(dir: string, trace?: string[]): Promise; /** * 路径读取结果的缓存,键是文件或文件夹绝对路径,对象的值是: * - `Promise`: 正在读取该路径的数据 * - `null`: 该路径不存在 * - `true`: 该路径是一个文件 * - `false`: 该路径是一个文件夹,但未读取内部文件项 * - `Set`: 该路径是一个文件夹,值是内部所有直接子文件或子文件夹项,如果文件名大小写不匹配,则 `realPath` 存储了实际的文件名 */ private _fsCache; /** 获取使用的文件系统 */ readonly fs: FileSystem; /** 是否忽略路径的大小写 */ readonly ignoreCase: boolean; /** * 读取文件夹内所有文件的列表,如果文件夹不存在则返回 `null`,如果路径存在但不是文件夹则返回 `false`,如果路径存在但大小写错误则返回实际路径字符串 * @param path 要读取的绝对路径 */ protected readDir(path: string): Promise & { realPath?: string; })>; /** 底层读取文件夹 */ private _readDirNoCache; /** * 判断指定的路径是否是文件 * @param path 要判断的绝对路径 * @returns 如果文件不存在则返回 `null`,如果路径存在但不是文件则返回 `false` */ protected existsFile(path: string): Promise; /** 底层读取文件 */ private _existsFileNoCache; /** 清除所有缓存 */ clearCache(): void; } /** 表示模块解析器的附加选项 */ export interface ResolverOptions { /** * 快速设置所有选项 * - `"node"`: 采用和 Node.js 中 `require` 相同的方式解析路径 * - `"browser"`: 类似 `"node"`,但针对浏览器运行环境提供适配方案 * @default "node" */ type?: "node" | "browser"; /** * 是否允许缓存解析结果 * - `true`: 启用完整缓存 * - `"name"`: 根据模块名缓存,忽略所在文件夹,如果只有一个全局搜索文件夹,启用后可以加速解析 * - `false`: 不缓存 * @description 注意如果启用了缓存,则在少数极端情况会得到错误的解析结果 * @default true */ cache?: boolean | "name"; /** * 是否强制区分路径大小写 * @description 启用后可以在避免不同环境得到不同的解析结果 * @default this.type === "browser" ? true : false */ enforceCaseSensitive?: boolean; /** * 所有模块的别名 * @example * { * alias: { * "abc": "xyz", // import "abc/foo" 将等价于 import "xyz/foo" * "abc$": "xyz", // import "abc" 将等价于 import "xyz",但 import "abc/foo" 不变 * "tealui-*": [ * "./tealui/*", * (input, match) => input + "/" + match * ], * "ignore": false // 忽略本模块 * } * } */ alias?: { [name: string]: string | ((source: string, ...parts: string[]) => string) | false | (string | ((source: string, ...parts: string[]) => string) | false)[]; }; /** * 要搜索的文件夹路径 * @description * 如果路径名包含了 `/` 或 `\`(比如 `./src` 和绝对路径),则解析时会在指定的单个文件夹内搜索模块 * 如果路径名不含 `/` 和 `\`(比如 `bower_components`),则解析时会从当前层级一直往上查找同名文件夹,依次搜索模块 * @default ["node_modules"] */ modules?: string[]; /** * 所有包描述文件名,包描述文件应该是一个 JSON 文件 * @default ["package.json"] */ descriptionFiles?: string[]; /** * 所有包描述文件中包含模块别名信息的字段名 * @see https://github.com/defunctzombie/package-browser-field-spec * @default this.type === "browser" ? ["browser"] : [] */ aliasFields?: string[]; /** * 所有包描述文件中包含入口模块的字段名 * @default this.type === "browser" ? ["module", "jsnext:main", "browser", "main"] : ["main"] */ mainFields?: string[]; /** * 所有默认的入口模块名,其中 `""` 表示所在文件夹的名称 * @default this.type === "browser" ? ["index", ""] : ["index"] */ mainFiles?: string[]; /** * 所有解析模块名时尝试自动追加的扩展名 * @description * 如果希望支持引用模块时不省略扩展名,需要在数组插入空字符串(建议插入到第一项) * 如果希望强制引用模块时不省略扩展名,即不自动插入扩展名,可以设置为空数组 * @default this.type === "browser" ? ["", ".wasm", ".tsx", ".ts", ".jsx", ".mjs", ".js", ".json"] : ["", ".js", ".json", ".node"] */ extensions?: string[]; } /** 表示一个包描述文件 */ export interface PackageFile { /** 文件绝对路径 */ path: string; /** 别名字段 */ aliasField?: string; /** 所有别名字段的值 */ alias?: any; /** 入口模块字段 */ mainField?: string; /** 入口模块名 */ main?: any; }