| |
| |
| |
| |
| |
| "use strict"; |
|
|
| |
| const { versions } = require("process"); |
|
|
| const AliasFieldPlugin = require("./AliasFieldPlugin"); |
| const AliasPlugin = require("./AliasPlugin"); |
| const AppendPlugin = require("./AppendPlugin"); |
| const ConditionalPlugin = require("./ConditionalPlugin"); |
| const DescriptionFilePlugin = require("./DescriptionFilePlugin"); |
| const DirectoryExistsPlugin = require("./DirectoryExistsPlugin"); |
| const ExportsFieldPlugin = require("./ExportsFieldPlugin"); |
| const ExtensionAliasPlugin = require("./ExtensionAliasPlugin"); |
| const FileExistsPlugin = require("./FileExistsPlugin"); |
| const ImportsFieldPlugin = require("./ImportsFieldPlugin"); |
| const JoinRequestPartPlugin = require("./JoinRequestPartPlugin"); |
| const JoinRequestPlugin = require("./JoinRequestPlugin"); |
| const MainFieldPlugin = require("./MainFieldPlugin"); |
| const ModulesInHierarchicalDirectoriesPlugin = require("./ModulesInHierarchicalDirectoriesPlugin"); |
| const ModulesInRootPlugin = require("./ModulesInRootPlugin"); |
| const NextPlugin = require("./NextPlugin"); |
| const ParsePlugin = require("./ParsePlugin"); |
| const PnpPlugin = require("./PnpPlugin"); |
| const Resolver = require("./Resolver"); |
| const RestrictionsPlugin = require("./RestrictionsPlugin"); |
| const ResultPlugin = require("./ResultPlugin"); |
| const RootsPlugin = require("./RootsPlugin"); |
| const SelfReferencePlugin = require("./SelfReferencePlugin"); |
| const SymlinkPlugin = require("./SymlinkPlugin"); |
| const SyncAsyncFileSystemDecorator = require("./SyncAsyncFileSystemDecorator"); |
| const TryNextPlugin = require("./TryNextPlugin"); |
| const TsconfigPathsPlugin = require("./TsconfigPathsPlugin"); |
| const UnsafeCachePlugin = require("./UnsafeCachePlugin"); |
| const UseFilePlugin = require("./UseFilePlugin"); |
| const { PathType, getType } = require("./util/path"); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| function processPnpApiOption(option) { |
| if ( |
| option === undefined && |
| versions.pnp |
| ) { |
| const _findPnpApi = |
| |
| ( |
| |
| require("module").findPnpApi |
| ); |
|
|
| if (_findPnpApi) { |
| return { |
| resolveToUnqualified(request, issuer, opts) { |
| const pnpapi = _findPnpApi(issuer); |
|
|
| if (!pnpapi) { |
| |
| return null; |
| } |
|
|
| return pnpapi.resolveToUnqualified(request, issuer, opts); |
| }, |
| }; |
| } |
| } |
|
|
| return option || null; |
| } |
|
|
| |
| |
| |
| |
| function normalizeAlias(alias) { |
| return typeof alias === "object" && !Array.isArray(alias) && alias !== null |
| ? Object.keys(alias).map((key) => { |
| |
| const obj = { name: key, onlyModule: false, alias: alias[key] }; |
|
|
| if (/\$$/.test(key)) { |
| obj.onlyModule = true; |
| obj.name = key.slice(0, -1); |
| } |
|
|
| return obj; |
| }) |
| : (alias) || []; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function mergeFilteredToArray(array, filter) { |
| |
| const result = []; |
| const set = new Set(array); |
|
|
| for (const item of set) { |
| if (filter(item)) { |
| const lastElement = |
| result.length > 0 ? result[result.length - 1] : undefined; |
| if (Array.isArray(lastElement)) { |
| lastElement.push(item); |
| } else { |
| result.push([item]); |
| } |
| } else { |
| result.push(item); |
| } |
| } |
|
|
| return result; |
| } |
|
|
| |
| |
| |
| |
| function createOptions(options) { |
| const mainFieldsSet = new Set(options.mainFields || ["main"]); |
| |
| const mainFields = []; |
|
|
| for (const item of mainFieldsSet) { |
| if (typeof item === "string") { |
| mainFields.push({ |
| name: [item], |
| forceRelative: true, |
| }); |
| } else if (Array.isArray(item)) { |
| mainFields.push({ |
| name: item, |
| forceRelative: true, |
| }); |
| } else { |
| mainFields.push({ |
| name: Array.isArray(item.name) ? item.name : [item.name], |
| forceRelative: item.forceRelative, |
| }); |
| } |
| } |
|
|
| return { |
| alias: normalizeAlias(options.alias), |
| fallback: normalizeAlias(options.fallback), |
| aliasFields: new Set(options.aliasFields), |
| cachePredicate: |
| options.cachePredicate || |
| function trueFn() { |
| return true; |
| }, |
| cacheWithContext: |
| typeof options.cacheWithContext !== "undefined" |
| ? options.cacheWithContext |
| : true, |
| exportsFields: new Set(options.exportsFields || ["exports"]), |
| importsFields: new Set(options.importsFields || ["imports"]), |
| conditionNames: new Set(options.conditionNames), |
| descriptionFiles: [ |
| ...new Set(options.descriptionFiles || ["package.json"]), |
| ], |
| enforceExtension: |
| options.enforceExtension === undefined |
| ? Boolean(options.extensions && options.extensions.includes("")) |
| : options.enforceExtension, |
| extensions: new Set(options.extensions || [".js", ".json", ".node"]), |
| extensionAlias: options.extensionAlias |
| ? Object.keys(options.extensionAlias).map((k) => ({ |
| extension: k, |
| alias: (options.extensionAlias)[ |
| k |
| ], |
| })) |
| : [], |
| fileSystem: options.useSyncFileSystemCalls |
| ? new SyncAsyncFileSystemDecorator( |
| ( |
| (options.fileSystem) |
| ), |
| ) |
| : options.fileSystem, |
| unsafeCache: |
| options.unsafeCache && typeof options.unsafeCache !== "object" |
| ? ({}) |
| : options.unsafeCache || false, |
| symlinks: typeof options.symlinks !== "undefined" ? options.symlinks : true, |
| resolver: options.resolver, |
| modules: mergeFilteredToArray( |
| Array.isArray(options.modules) |
| ? options.modules |
| : options.modules |
| ? [options.modules] |
| : ["node_modules"], |
| (item) => { |
| const type = getType(item); |
| return type === PathType.Normal || type === PathType.Relative; |
| }, |
| ), |
| mainFields, |
| mainFiles: new Set(options.mainFiles || ["index"]), |
| plugins: options.plugins || [], |
| pnpApi: processPnpApiOption(options.pnpApi), |
| roots: new Set(options.roots || undefined), |
| fullySpecified: options.fullySpecified || false, |
| resolveToContext: options.resolveToContext || false, |
| preferRelative: options.preferRelative || false, |
| preferAbsolute: options.preferAbsolute || false, |
| restrictions: new Set(options.restrictions), |
| tsconfig: |
| typeof options.tsconfig === "undefined" ? false : options.tsconfig, |
| }; |
| } |
|
|
| |
| |
| |
| |
| module.exports.createResolver = function createResolver(options) { |
| const normalizedOptions = createOptions(options); |
|
|
| const { |
| alias, |
| fallback, |
| aliasFields, |
| cachePredicate, |
| cacheWithContext, |
| conditionNames, |
| descriptionFiles, |
| enforceExtension, |
| exportsFields, |
| extensionAlias, |
| importsFields, |
| extensions, |
| fileSystem, |
| fullySpecified, |
| mainFields, |
| mainFiles, |
| modules, |
| plugins: userPlugins, |
| pnpApi, |
| resolveToContext, |
| preferRelative, |
| preferAbsolute, |
| symlinks, |
| unsafeCache, |
| resolver: customResolver, |
| restrictions, |
| roots, |
| tsconfig, |
| } = normalizedOptions; |
|
|
| const plugins = [...userPlugins]; |
|
|
| const resolver = |
| customResolver || new Resolver(fileSystem, normalizedOptions); |
|
|
| |
|
|
| resolver.ensureHook("resolve"); |
| resolver.ensureHook("internalResolve"); |
| resolver.ensureHook("newInternalResolve"); |
| resolver.ensureHook("parsedResolve"); |
| resolver.ensureHook("describedResolve"); |
| resolver.ensureHook("rawResolve"); |
| resolver.ensureHook("normalResolve"); |
| resolver.ensureHook("internal"); |
| resolver.ensureHook("rawModule"); |
| resolver.ensureHook("alternateRawModule"); |
| resolver.ensureHook("module"); |
| resolver.ensureHook("resolveAsModule"); |
| resolver.ensureHook("undescribedResolveInPackage"); |
| resolver.ensureHook("resolveInPackage"); |
| resolver.ensureHook("resolveInExistingDirectory"); |
| resolver.ensureHook("relative"); |
| resolver.ensureHook("describedRelative"); |
| resolver.ensureHook("directory"); |
| resolver.ensureHook("undescribedExistingDirectory"); |
| resolver.ensureHook("existingDirectory"); |
| resolver.ensureHook("undescribedRawFile"); |
| resolver.ensureHook("rawFile"); |
| resolver.ensureHook("file"); |
| resolver.ensureHook("finalFile"); |
| resolver.ensureHook("existingFile"); |
| resolver.ensureHook("resolved"); |
|
|
| |
| |
| |
| |
| resolver.hooks.newInteralResolve = resolver.hooks.newInternalResolve; |
|
|
| |
| for (const { source, resolveOptions } of [ |
| { source: "resolve", resolveOptions: { fullySpecified } }, |
| { source: "internal-resolve", resolveOptions: { fullySpecified: false } }, |
| ]) { |
| plugins.push(new ParsePlugin(source, resolveOptions, "parsed-resolve")); |
| } |
|
|
| |
| plugins.push( |
| new DescriptionFilePlugin( |
| "parsed-resolve", |
| descriptionFiles, |
| false, |
| "described-resolve", |
| ), |
| ); |
| plugins.push(new NextPlugin("after-parsed-resolve", "described-resolve")); |
|
|
| |
| if (unsafeCache) { |
| plugins.push( |
| new UnsafeCachePlugin( |
| "described-resolve", |
| cachePredicate, |
| (unsafeCache), |
| cacheWithContext, |
| "raw-resolve", |
| ), |
| ); |
| } else { |
| plugins.push(new NextPlugin("described-resolve", "raw-resolve")); |
| } |
| if (fallback.length > 0) { |
| plugins.push( |
| new AliasPlugin("described-resolve", fallback, "internal-resolve"), |
| ); |
| } |
| |
| if (alias.length > 0) { |
| plugins.push(new AliasPlugin("raw-resolve", alias, "internal-resolve")); |
| } |
| if (tsconfig) { |
| plugins.push(new TsconfigPathsPlugin(tsconfig)); |
| } |
| for (const item of aliasFields) { |
| plugins.push(new AliasFieldPlugin("raw-resolve", item, "internal-resolve")); |
| } |
| for (const item of extensionAlias) { |
| plugins.push( |
| new ExtensionAliasPlugin("raw-resolve", item, "normal-resolve"), |
| ); |
| } |
| plugins.push(new NextPlugin("raw-resolve", "normal-resolve")); |
|
|
| |
| if (preferRelative) { |
| plugins.push(new JoinRequestPlugin("after-normal-resolve", "relative")); |
| } |
| plugins.push( |
| new ConditionalPlugin( |
| "after-normal-resolve", |
| { module: true }, |
| "resolve as module", |
| false, |
| "raw-module", |
| ), |
| ); |
| plugins.push( |
| new ConditionalPlugin( |
| "after-normal-resolve", |
| { internal: true }, |
| "resolve as internal import", |
| false, |
| "internal", |
| ), |
| ); |
| if (preferAbsolute) { |
| plugins.push(new JoinRequestPlugin("after-normal-resolve", "relative")); |
| } |
| if (roots.size > 0) { |
| plugins.push(new RootsPlugin("after-normal-resolve", roots, "relative")); |
| } |
| if (!preferRelative && !preferAbsolute) { |
| plugins.push(new JoinRequestPlugin("after-normal-resolve", "relative")); |
| } |
|
|
| |
| for (const importsField of importsFields) { |
| plugins.push( |
| new ImportsFieldPlugin( |
| "internal", |
| conditionNames, |
| importsField, |
| "relative", |
| "internal-resolve", |
| ), |
| ); |
| } |
|
|
| |
| for (const exportsField of exportsFields) { |
| plugins.push( |
| new SelfReferencePlugin("raw-module", exportsField, "resolve-as-module"), |
| ); |
| } |
| for (const item of modules) { |
| if (Array.isArray(item)) { |
| if (item.includes("node_modules") && pnpApi) { |
| plugins.push( |
| new ModulesInHierarchicalDirectoriesPlugin( |
| "raw-module", |
| item.filter((i) => i !== "node_modules"), |
| "module", |
| ), |
| ); |
| plugins.push( |
| new PnpPlugin( |
| "raw-module", |
| pnpApi, |
| "undescribed-resolve-in-package", |
| "alternate-raw-module", |
| ), |
| ); |
|
|
| plugins.push( |
| new ModulesInHierarchicalDirectoriesPlugin( |
| "alternate-raw-module", |
| ["node_modules"], |
| "module", |
| ), |
| ); |
| } else { |
| plugins.push( |
| new ModulesInHierarchicalDirectoriesPlugin( |
| "raw-module", |
| item, |
| "module", |
| ), |
| ); |
| } |
| } else { |
| plugins.push(new ModulesInRootPlugin("raw-module", item, "module")); |
| } |
| } |
|
|
| |
| plugins.push(new JoinRequestPartPlugin("module", "resolve-as-module")); |
|
|
| |
| if (!resolveToContext) { |
| plugins.push( |
| new ConditionalPlugin( |
| "resolve-as-module", |
| { directory: false, request: "." }, |
| "single file module", |
| true, |
| "undescribed-raw-file", |
| ), |
| ); |
| } |
| plugins.push( |
| new DirectoryExistsPlugin( |
| "resolve-as-module", |
| "undescribed-resolve-in-package", |
| ), |
| ); |
|
|
| |
| plugins.push( |
| new DescriptionFilePlugin( |
| "undescribed-resolve-in-package", |
| descriptionFiles, |
| false, |
| "resolve-in-package", |
| ), |
| ); |
| plugins.push( |
| new NextPlugin( |
| "after-undescribed-resolve-in-package", |
| "resolve-in-package", |
| ), |
| ); |
|
|
| |
| for (const exportsField of exportsFields) { |
| plugins.push( |
| new ExportsFieldPlugin( |
| "resolve-in-package", |
| conditionNames, |
| exportsField, |
| "relative", |
| ), |
| ); |
| } |
| plugins.push( |
| new NextPlugin("resolve-in-package", "resolve-in-existing-directory"), |
| ); |
|
|
| |
| plugins.push( |
| new JoinRequestPlugin("resolve-in-existing-directory", "relative"), |
| ); |
|
|
| |
| plugins.push( |
| new DescriptionFilePlugin( |
| "relative", |
| descriptionFiles, |
| true, |
| "described-relative", |
| ), |
| ); |
| plugins.push(new NextPlugin("after-relative", "described-relative")); |
|
|
| |
| if (resolveToContext) { |
| plugins.push(new NextPlugin("described-relative", "directory")); |
| } else { |
| plugins.push( |
| new ConditionalPlugin( |
| "described-relative", |
| { directory: false }, |
| null, |
| true, |
| "raw-file", |
| ), |
| ); |
| plugins.push( |
| new ConditionalPlugin( |
| "described-relative", |
| { fullySpecified: false }, |
| "as directory", |
| true, |
| "directory", |
| ), |
| ); |
| } |
|
|
| |
| plugins.push( |
| new DirectoryExistsPlugin("directory", "undescribed-existing-directory"), |
| ); |
|
|
| if (resolveToContext) { |
| |
| plugins.push(new NextPlugin("undescribed-existing-directory", "resolved")); |
| } else { |
| |
| plugins.push( |
| new DescriptionFilePlugin( |
| "undescribed-existing-directory", |
| descriptionFiles, |
| false, |
| "existing-directory", |
| ), |
| ); |
| for (const item of mainFiles) { |
| plugins.push( |
| new UseFilePlugin( |
| "undescribed-existing-directory", |
| item, |
| "undescribed-raw-file", |
| ), |
| ); |
| } |
|
|
| |
| for (const item of mainFields) { |
| plugins.push( |
| new MainFieldPlugin( |
| "existing-directory", |
| item, |
| "resolve-in-existing-directory", |
| ), |
| ); |
| } |
| for (const item of mainFiles) { |
| plugins.push( |
| new UseFilePlugin("existing-directory", item, "undescribed-raw-file"), |
| ); |
| } |
|
|
| |
| plugins.push( |
| new DescriptionFilePlugin( |
| "undescribed-raw-file", |
| descriptionFiles, |
| true, |
| "raw-file", |
| ), |
| ); |
| plugins.push(new NextPlugin("after-undescribed-raw-file", "raw-file")); |
|
|
| |
| plugins.push( |
| new ConditionalPlugin( |
| "raw-file", |
| { fullySpecified: true }, |
| null, |
| false, |
| "file", |
| ), |
| ); |
| if (!enforceExtension) { |
| plugins.push(new TryNextPlugin("raw-file", "no extension", "file")); |
| } |
| for (const item of extensions) { |
| plugins.push(new AppendPlugin("raw-file", item, "file")); |
| } |
|
|
| |
| if (alias.length > 0) { |
| plugins.push(new AliasPlugin("file", alias, "internal-resolve")); |
| } |
| for (const item of aliasFields) { |
| plugins.push(new AliasFieldPlugin("file", item, "internal-resolve")); |
| } |
| plugins.push(new NextPlugin("file", "final-file")); |
|
|
| |
| plugins.push(new FileExistsPlugin("final-file", "existing-file")); |
|
|
| |
| if (symlinks) { |
| plugins.push(new SymlinkPlugin("existing-file", "existing-file")); |
| } |
| plugins.push(new NextPlugin("existing-file", "resolved")); |
| } |
|
|
| const { resolved } = |
| |
| (resolver.hooks); |
|
|
| |
| if (restrictions.size > 0) { |
| plugins.push(new RestrictionsPlugin(resolved, restrictions)); |
| } |
|
|
| plugins.push(new ResultPlugin(resolved)); |
|
|
| |
|
|
| for (const plugin of plugins) { |
| if (typeof plugin === "function") { |
| |
| (plugin).call(resolver, resolver); |
| } else if (plugin) { |
| plugin.apply(resolver); |
| } |
| } |
|
|
| return resolver; |
| }; |
|
|