forked from yarnpkg/berry
-
Notifications
You must be signed in to change notification settings - Fork 0
/
normalize-options.js
119 lines (92 loc) Β· 4.03 KB
/
normalize-options.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// 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;
};