// Info: this file has been generated by Yarn with the approval of the // `resolve` maintainers. Bugs caused by a code located here should be // opened against the Yarn repository. const path = require(`path`); module.exports = function (_, opts) { opts = opts || {}; if (opts.forceNodeResolution || !process.versions.pnp) return opts; // It would be nice if we could throw, but that would break the transparent // compatibility with packages that use `resolve` today (such as Gulp). Since // it's the whole point of this patch, we don't. // // if (opts.packageIterator || opts.paths) // throw new Error(`The "packageIterator" and "paths" options cannot be used in PnP environments. Set "forceNodeResolution: true" if absolutely needed, or branch on process.versions.pnp otherwise.`); const {findPnpApi} = require(`module`); const runPnpResolution = (request, basedir) => { // Extract the name of the package being requested (1=package name, 2=internal path) const parts = request.match(/^((?:@[^/]+\/)?[^/]+)(\/.*)?/); if (!parts) throw new Error(`Assertion failed: Expected the "resolve" package to call the "paths" callback with package names only (got "${request}")`); // Make sure that basedir ends with a slash if (basedir.charAt(basedir.length - 1) !== `/`) basedir = path.join(basedir, `/`); const api = findPnpApi(basedir); if (api === null) return undefined; // This is guaranteed to return the path to the "package.json" file from the given package let manifestPath; try { manifestPath = api.resolveToUnqualified(`${parts[1]}/package.json`, basedir, {considerBuiltins: false}); } catch (err) { return null; } if (manifestPath === null) throw new Error(`Assertion failed: The resolution thinks that "${parts[1]}" is a Node builtin`); // Strip the package.json to get the package folder const packagePath = path.dirname(manifestPath); // Attach the internal path to the resolved package directory const unqualifiedPath = typeof parts[2] !== `undefined` ? path.join(packagePath, parts[2]) : packagePath; return {packagePath, unqualifiedPath}; }; const runPnpResolutionOnArray = (request, paths) => { for (let i = 0; i < paths.length; i++) { const resolution = runPnpResolution(request, paths[i]); if (resolution || i === paths.length - 1) { return resolution; } } return null; }; const originalPaths = Array.isArray(opts.paths) ? opts.paths : []; const packageIterator = (request, basedir, getCandidates, opts) => { const pathsToTest = [basedir].concat(originalPaths); const resolution = runPnpResolutionOnArray(request, pathsToTest); if (resolution == null) return getCandidates(); return [resolution.unqualifiedPath]; }; const paths = (request, basedir, getNodeModulePaths, opts) => { const pathsToTest = [basedir].concat(originalPaths); const resolution = runPnpResolutionOnArray(request, pathsToTest); if (resolution == null) return getNodeModulePaths().concat(originalPaths); // Stip the local named folder let nodeModules = path.dirname(resolution.packagePath); // Strip the scope named folder if needed if (request.match(/^@[^/]+\//)) nodeModules = path.dirname(nodeModules); return [nodeModules]; }; // We need to keep track whether we're in `packageIterator` or not so that // the code is compatible with both `resolve` 1.9+ and `resolve` 1.15+ let isInsideIterator = false; if (!opts.__skipPackageIterator) { opts.packageIterator = function (request, basedir, getCandidates, opts) { isInsideIterator = true; try { return packageIterator(request, basedir, getCandidates, opts); } finally { isInsideIterator = false; } }; } opts.paths = function (request, basedir, getNodeModulePaths, opts) { if (isInsideIterator) return getNodeModulePaths().concat(originalPaths); return paths(request, basedir, getNodeModulePaths, opts); }; return opts; };