@yarnpkg/nm 3.0.1-rc.8 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,606 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildLocatorMap = exports.buildNodeModulesTree = exports.getArchivePath = exports.NodeModulesHoistingLimits = exports.LinkType = void 0;
4
- const core_1 = require("@yarnpkg/core");
5
- const fslib_1 = require("@yarnpkg/fslib");
6
- const fslib_2 = require("@yarnpkg/fslib");
7
- const hoist_1 = require("./hoist");
8
- // Babel doesn't support const enums, thats why we use non-const enum for LinkType in @yarnpkg/pnp
9
- // But because of this TypeScript requires @yarnpkg/pnp during runtime
10
- // To prevent this we redeclare LinkType enum here, to not depend on @yarnpkg/pnp during runtime
11
- var LinkType;
12
- (function (LinkType) {
13
- LinkType["HARD"] = "HARD";
14
- LinkType["SOFT"] = "SOFT";
15
- })(LinkType = exports.LinkType || (exports.LinkType = {}));
16
- var NodeModulesHoistingLimits;
17
- (function (NodeModulesHoistingLimits) {
18
- NodeModulesHoistingLimits["WORKSPACES"] = "workspaces";
19
- NodeModulesHoistingLimits["DEPENDENCIES"] = "dependencies";
20
- NodeModulesHoistingLimits["NONE"] = "none";
21
- })(NodeModulesHoistingLimits = exports.NodeModulesHoistingLimits || (exports.NodeModulesHoistingLimits = {}));
22
- /** node_modules path segment */
23
- const NODE_MODULES = `node_modules`;
24
- /**
25
- * The workspace name suffix used internally by this implementation and appeneded to the name of workspace package.
26
- * It is needed to create and distinguuish special nodes for workspaces
27
- */
28
- const WORKSPACE_NAME_SUFFIX = `$wsroot$`;
29
- /**
30
- * Returns path to archive, if package location is inside the archive.
31
- *
32
- * @param packagePath package location
33
- *
34
- * @returns path to archive is location is insde the archive or null otherwise
35
- */
36
- const getArchivePath = (packagePath) => packagePath.indexOf(`.zip/${NODE_MODULES}/`) >= 0 ?
37
- fslib_1.npath.toPortablePath(packagePath.split(`/${NODE_MODULES}/`)[0]) :
38
- null;
39
- exports.getArchivePath = getArchivePath;
40
- /**
41
- * Retrieve full package list and build hoisted `node_modules` directories
42
- * representation in-memory.
43
- *
44
- * @param pnp PnP API
45
- *
46
- * @returns hoisted `node_modules` directories representation in-memory
47
- */
48
- const buildNodeModulesTree = (pnp, options) => {
49
- const { packageTree, hoistingLimits, errors, preserveSymlinksRequired } = buildPackageTree(pnp, options);
50
- let tree = null;
51
- if (errors.length === 0) {
52
- const hoistedTree = (0, hoist_1.hoist)(packageTree, { hoistingLimits });
53
- tree = populateNodeModulesTree(pnp, hoistedTree, options);
54
- }
55
- return { tree, errors, preserveSymlinksRequired };
56
- };
57
- exports.buildNodeModulesTree = buildNodeModulesTree;
58
- const stringifyLocator = (locator) => `${locator.name}@${locator.reference}`;
59
- const buildLocatorMap = (nodeModulesTree) => {
60
- const map = new Map();
61
- for (const [location, val] of nodeModulesTree.entries()) {
62
- if (!val.dirList) {
63
- let entry = map.get(val.locator);
64
- if (!entry) {
65
- entry = { target: val.target, linkType: val.linkType, locations: [], aliases: val.aliases };
66
- map.set(val.locator, entry);
67
- }
68
- entry.locations.push(location);
69
- }
70
- }
71
- for (const val of map.values()) {
72
- // Sort locations by depth first and then alphabetically for determinism
73
- val.locations = val.locations.sort((loc1, loc2) => {
74
- const len1 = loc1.split(fslib_1.ppath.delimiter).length;
75
- const len2 = loc2.split(fslib_1.ppath.delimiter).length;
76
- if (loc2 === loc1) {
77
- return 0;
78
- }
79
- else if (len1 !== len2) {
80
- return len2 - len1;
81
- }
82
- else {
83
- return loc2 > loc1 ? 1 : -1;
84
- }
85
- });
86
- }
87
- return map;
88
- };
89
- exports.buildLocatorMap = buildLocatorMap;
90
- const areRealLocatorsEqual = (a, b) => {
91
- const realA = core_1.structUtils.isVirtualLocator(a) ? core_1.structUtils.devirtualizeLocator(a) : a;
92
- const realB = core_1.structUtils.isVirtualLocator(b) ? core_1.structUtils.devirtualizeLocator(b) : b;
93
- return core_1.structUtils.areLocatorsEqual(realA, realB);
94
- };
95
- const isExternalSoftLink = (pkg, locator, pnp, topPkgPortableLocation) => {
96
- if (pkg.linkType !== LinkType.SOFT)
97
- return false;
98
- const realSoftLinkPath = fslib_1.npath.toPortablePath(pnp.resolveVirtual && locator.reference && locator.reference.startsWith(`virtual:`) ? pnp.resolveVirtual(pkg.packageLocation) : pkg.packageLocation);
99
- return fslib_1.ppath.contains(topPkgPortableLocation, realSoftLinkPath) === null;
100
- };
101
- /**
102
- * Builds a map representing layout of nested workspaces and internal portals on the file system.
103
- */
104
- const buildWorkspaceMap = (pnp) => {
105
- const topPkg = pnp.getPackageInformation(pnp.topLevel);
106
- if (topPkg === null)
107
- throw new Error(`Assertion failed: Expected the top-level package to have been registered`);
108
- const topLocator = pnp.findPackageLocator(topPkg.packageLocation);
109
- if (topLocator === null)
110
- throw new Error(`Assertion failed: Expected the top-level package to have a physical locator`);
111
- const topPkgPortableLocation = fslib_1.npath.toPortablePath(topPkg.packageLocation.slice(0, -1));
112
- const workspaceMap = new Map();
113
- const workspaceTree = { children: new Map() };
114
- const pnpRoots = pnp.getDependencyTreeRoots();
115
- // Workspace and internal portal locations to locators map
116
- const workspaceLikeLocators = new Map();
117
- const seen = new Set();
118
- const visit = (locator, parentLocator) => {
119
- const locatorKey = stringifyLocator(locator);
120
- if (seen.has(locatorKey))
121
- return;
122
- seen.add(locatorKey);
123
- const pkg = pnp.getPackageInformation(locator);
124
- if (pkg) {
125
- const parentLocatorKey = parentLocator ? stringifyLocator(parentLocator) : ``;
126
- if (stringifyLocator(locator) !== parentLocatorKey && pkg.linkType === LinkType.SOFT && !isExternalSoftLink(pkg, locator, pnp, topPkgPortableLocation)) {
127
- const location = getRealPackageLocation(pkg, locator, pnp);
128
- const prevLocator = workspaceLikeLocators.get(location);
129
- // Give workspaces a priority over portals and other protocols pointing to the same location
130
- // The devDependencies are not installed for portals, but installed for workspaces
131
- if (!prevLocator || locator.reference.startsWith(`workspace:`)) {
132
- workspaceLikeLocators.set(location, locator);
133
- }
134
- }
135
- for (const [name, referencish] of pkg.packageDependencies) {
136
- if (referencish !== null) {
137
- if (!pkg.packagePeers.has(name)) {
138
- visit(pnp.getLocator(name, referencish), locator);
139
- }
140
- }
141
- }
142
- }
143
- };
144
- for (const locator of pnpRoots)
145
- visit(locator, null);
146
- const cwdSegments = topPkgPortableLocation.split(fslib_1.ppath.sep);
147
- for (const locator of workspaceLikeLocators.values()) {
148
- const pkg = pnp.getPackageInformation(locator);
149
- const location = fslib_1.npath.toPortablePath(pkg.packageLocation.slice(0, -1));
150
- const segments = location.split(fslib_1.ppath.sep).slice(cwdSegments.length);
151
- let node = workspaceTree;
152
- for (const segment of segments) {
153
- let nextNode = node.children.get(segment);
154
- if (!nextNode) {
155
- nextNode = { children: new Map() };
156
- node.children.set(segment, nextNode);
157
- }
158
- node = nextNode;
159
- }
160
- node.workspaceLocator = locator;
161
- }
162
- const addWorkspace = (node, parentWorkspaceLocator) => {
163
- if (node.workspaceLocator) {
164
- const parentLocatorKey = stringifyLocator(parentWorkspaceLocator);
165
- let dependencies = workspaceMap.get(parentLocatorKey);
166
- if (!dependencies) {
167
- dependencies = new Set();
168
- workspaceMap.set(parentLocatorKey, dependencies);
169
- }
170
- dependencies.add(node.workspaceLocator);
171
- }
172
- for (const child of node.children.values()) {
173
- addWorkspace(child, node.workspaceLocator || parentWorkspaceLocator);
174
- }
175
- };
176
- for (const child of workspaceTree.children.values())
177
- addWorkspace(child, workspaceTree.workspaceLocator);
178
- return workspaceMap;
179
- };
180
- /**
181
- * Traverses PnP tree and produces input for the `RawHoister`
182
- *
183
- * @param pnp PnP API
184
- *
185
- * @returns package tree, packages info and locators
186
- */
187
- const buildPackageTree = (pnp, options) => {
188
- const errors = [];
189
- let preserveSymlinksRequired = false;
190
- const hoistingLimits = new Map();
191
- const workspaceMap = buildWorkspaceMap(pnp);
192
- const topPkg = pnp.getPackageInformation(pnp.topLevel);
193
- if (topPkg === null)
194
- throw new Error(`Assertion failed: Expected the top-level package to have been registered`);
195
- const topLocator = pnp.findPackageLocator(topPkg.packageLocation);
196
- if (topLocator === null)
197
- throw new Error(`Assertion failed: Expected the top-level package to have a physical locator`);
198
- const topPkgPortableLocation = fslib_1.npath.toPortablePath(topPkg.packageLocation.slice(0, -1));
199
- const packageTree = {
200
- name: topLocator.name,
201
- identName: topLocator.name,
202
- reference: topLocator.reference,
203
- peerNames: topPkg.packagePeers,
204
- dependencies: new Set(),
205
- isWorkspace: true,
206
- };
207
- const nodes = new Map();
208
- const getNodeKey = (name, locator) => `${stringifyLocator(locator)}:${name}`;
209
- const addPackageToTree = (name, pkg, locator, parent, parentPkg, parentDependencies, parentRelativeCwd, isHoistBorder) => {
210
- var _a, _b;
211
- const nodeKey = getNodeKey(name, locator);
212
- let node = nodes.get(nodeKey);
213
- const isSeen = !!node;
214
- if (!isSeen && locator.name === topLocator.name && locator.reference === topLocator.reference) {
215
- node = packageTree;
216
- nodes.set(nodeKey, packageTree);
217
- }
218
- const isExternalSoftLinkPackage = isExternalSoftLink(pkg, locator, pnp, topPkgPortableLocation);
219
- if (!node) {
220
- const isWorkspace = pkg.linkType === LinkType.SOFT && locator.name.endsWith(WORKSPACE_NAME_SUFFIX);
221
- node = {
222
- name,
223
- identName: locator.name,
224
- reference: locator.reference,
225
- dependencies: new Set(),
226
- // View peer dependencies as regular dependencies for workspaces
227
- // (meeting workspace peer dependency constraints is sometimes hard, sometimes impossible for the nm linker)
228
- peerNames: isWorkspace ? new Set() : pkg.packagePeers,
229
- isWorkspace,
230
- };
231
- nodes.set(nodeKey, node);
232
- }
233
- let hoistPriority;
234
- if (isExternalSoftLinkPackage)
235
- // External soft link dependencies have the highest priority - we don't want to install inside them
236
- hoistPriority = 2;
237
- else if (parentPkg.linkType === LinkType.SOFT)
238
- // Internal soft link dependencies should have priority over transitive dependencies - to maximize chances having only one top-level node_modules
239
- hoistPriority = 1;
240
- else
241
- hoistPriority = 0;
242
- node.hoistPriority = Math.max(node.hoistPriority || 0, hoistPriority);
243
- if (isHoistBorder && !isExternalSoftLinkPackage) {
244
- const parentLocatorKey = stringifyLocator({ name: parent.identName, reference: parent.reference });
245
- const dependencyBorders = hoistingLimits.get(parentLocatorKey) || new Set();
246
- hoistingLimits.set(parentLocatorKey, dependencyBorders);
247
- dependencyBorders.add(node.name);
248
- }
249
- const allDependencies = new Map(pkg.packageDependencies);
250
- if (options.project) {
251
- const workspace = options.project.workspacesByCwd.get(fslib_1.npath.toPortablePath(pkg.packageLocation.slice(0, -1)));
252
- if (workspace) {
253
- const peerCandidates = new Set([
254
- ...Array.from(workspace.manifest.peerDependencies.values(), x => core_1.structUtils.stringifyIdent(x)),
255
- ...Array.from(workspace.manifest.peerDependenciesMeta.keys()),
256
- ]);
257
- for (const peerName of peerCandidates) {
258
- if (!allDependencies.has(peerName)) {
259
- allDependencies.set(peerName, parentDependencies.get(peerName) || null);
260
- node.peerNames.add(peerName);
261
- }
262
- }
263
- }
264
- }
265
- const locatorKey = stringifyLocator({ name: locator.name.replace(WORKSPACE_NAME_SUFFIX, ``), reference: locator.reference });
266
- const innerWorkspaces = workspaceMap.get(locatorKey);
267
- if (innerWorkspaces) {
268
- for (const workspaceLocator of innerWorkspaces) {
269
- allDependencies.set(`${workspaceLocator.name}${WORKSPACE_NAME_SUFFIX}`, workspaceLocator.reference);
270
- }
271
- }
272
- if (pkg !== parentPkg || pkg.linkType !== LinkType.SOFT || !options.selfReferencesByCwd || options.selfReferencesByCwd.get(parentRelativeCwd))
273
- parent.dependencies.add(node);
274
- const isWorkspaceDependency = locator !== topLocator && pkg.linkType === LinkType.SOFT && !locator.name.endsWith(WORKSPACE_NAME_SUFFIX) && !isExternalSoftLinkPackage;
275
- if (!isSeen && !isWorkspaceDependency) {
276
- const siblingPortalDependencyMap = new Map();
277
- for (const [depName, referencish] of allDependencies) {
278
- if (referencish !== null) {
279
- const depLocator = pnp.getLocator(depName, referencish);
280
- const pkgLocator = pnp.getLocator(depName.replace(WORKSPACE_NAME_SUFFIX, ``), referencish);
281
- const depPkg = pnp.getPackageInformation(pkgLocator);
282
- if (depPkg === null)
283
- throw new Error(`Assertion failed: Expected the package to have been registered`);
284
- const isExternalSoftLinkDep = isExternalSoftLink(depPkg, depLocator, pnp, topPkgPortableLocation);
285
- if (options.validateExternalSoftLinks && options.project && isExternalSoftLinkDep) {
286
- if (depPkg.packageDependencies.size > 0)
287
- preserveSymlinksRequired = true;
288
- for (const [name, referencish] of depPkg.packageDependencies) {
289
- if (referencish !== null) {
290
- const portalDependencyLocator = core_1.structUtils.parseLocator(Array.isArray(referencish) ? `${referencish[0]}@${referencish[1]}` : `${name}@${referencish}`);
291
- // Ignore self-references during portal hoistability check
292
- if (stringifyLocator(portalDependencyLocator) !== stringifyLocator(depLocator)) {
293
- const parentDependencyReferencish = allDependencies.get(name);
294
- if (parentDependencyReferencish) {
295
- const parentDependencyLocator = core_1.structUtils.parseLocator(Array.isArray(parentDependencyReferencish) ? `${parentDependencyReferencish[0]}@${parentDependencyReferencish[1]}` : `${name}@${parentDependencyReferencish}`);
296
- if (!areRealLocatorsEqual(parentDependencyLocator, portalDependencyLocator)) {
297
- errors.push({
298
- messageName: core_1.MessageName.NM_CANT_INSTALL_EXTERNAL_SOFT_LINK,
299
- text: `Cannot link ${core_1.structUtils.prettyIdent(options.project.configuration, core_1.structUtils.parseIdent(depLocator.name))} ` +
300
- `into ${core_1.structUtils.prettyLocator(options.project.configuration, core_1.structUtils.parseLocator(`${locator.name}@${locator.reference}`))} ` +
301
- `dependency ${core_1.structUtils.prettyLocator(options.project.configuration, portalDependencyLocator)} ` +
302
- `conflicts with parent dependency ${core_1.structUtils.prettyLocator(options.project.configuration, parentDependencyLocator)}`,
303
- });
304
- }
305
- }
306
- else {
307
- const siblingPortalDependency = siblingPortalDependencyMap.get(name);
308
- if (siblingPortalDependency) {
309
- const siblingReferncish = siblingPortalDependency.target;
310
- const siblingPortalDependencyLocator = core_1.structUtils.parseLocator(Array.isArray(siblingReferncish) ? `${siblingReferncish[0]}@${siblingReferncish[1]}` : `${name}@${siblingReferncish}`);
311
- if (!areRealLocatorsEqual(siblingPortalDependencyLocator, portalDependencyLocator)) {
312
- errors.push({
313
- messageName: core_1.MessageName.NM_CANT_INSTALL_EXTERNAL_SOFT_LINK,
314
- text: `Cannot link ${core_1.structUtils.prettyIdent(options.project.configuration, core_1.structUtils.parseIdent(depLocator.name))} ` +
315
- `into ${core_1.structUtils.prettyLocator(options.project.configuration, core_1.structUtils.parseLocator(`${locator.name}@${locator.reference}`))} ` +
316
- `dependency ${core_1.structUtils.prettyLocator(options.project.configuration, portalDependencyLocator)} ` +
317
- `conflicts with dependency ${core_1.structUtils.prettyLocator(options.project.configuration, siblingPortalDependencyLocator)} ` +
318
- `from sibling portal ${core_1.structUtils.prettyIdent(options.project.configuration, core_1.structUtils.parseIdent(siblingPortalDependency.portal.name))}`,
319
- });
320
- }
321
- }
322
- else {
323
- siblingPortalDependencyMap.set(name, { target: portalDependencyLocator.reference, portal: depLocator });
324
- }
325
- }
326
- }
327
- }
328
- }
329
- }
330
- const parentHoistingLimits = (_a = options.hoistingLimitsByCwd) === null || _a === void 0 ? void 0 : _a.get(parentRelativeCwd);
331
- const relativeDepCwd = isExternalSoftLinkDep ? parentRelativeCwd : fslib_1.ppath.relative(topPkgPortableLocation, fslib_1.npath.toPortablePath(depPkg.packageLocation)) || fslib_2.PortablePath.dot;
332
- const depHoistingLimits = (_b = options.hoistingLimitsByCwd) === null || _b === void 0 ? void 0 : _b.get(relativeDepCwd);
333
- const isHoistBorder = parentHoistingLimits === NodeModulesHoistingLimits.DEPENDENCIES
334
- || depHoistingLimits === NodeModulesHoistingLimits.DEPENDENCIES
335
- || depHoistingLimits === NodeModulesHoistingLimits.WORKSPACES;
336
- addPackageToTree(depName, depPkg, depLocator, node, pkg, allDependencies, relativeDepCwd, isHoistBorder);
337
- }
338
- }
339
- }
340
- };
341
- addPackageToTree(topLocator.name, topPkg, topLocator, packageTree, topPkg, topPkg.packageDependencies, fslib_2.PortablePath.dot, false);
342
- return { packageTree, hoistingLimits, errors, preserveSymlinksRequired };
343
- };
344
- function getRealPackageLocation(pkg, locator, pnp) {
345
- const realPath = pnp.resolveVirtual && locator.reference && locator.reference.startsWith(`virtual:`)
346
- ? pnp.resolveVirtual(pkg.packageLocation)
347
- : pkg.packageLocation;
348
- return fslib_1.npath.toPortablePath(realPath || pkg.packageLocation);
349
- }
350
- function getTargetLocatorPath(locator, pnp, options) {
351
- const pkgLocator = pnp.getLocator(locator.name.replace(WORKSPACE_NAME_SUFFIX, ``), locator.reference);
352
- const info = pnp.getPackageInformation(pkgLocator);
353
- if (info === null)
354
- throw new Error(`Assertion failed: Expected the package to be registered`);
355
- let linkType;
356
- let target;
357
- if (options.pnpifyFs) {
358
- // In case of pnpifyFs we represent modules as symlinks to archives in NodeModulesFS
359
- // `/home/user/project/foo` is a symlink to `/home/user/project/.yarn/.cache/foo.zip/node_modules/foo`
360
- // To make this fs layout work with legacy tools we make
361
- // `/home/user/project/.yarn/.cache/foo.zip/node_modules/foo/node_modules` (which normally does not exist inside archive) a symlink to:
362
- // `/home/user/project/node_modules/foo/node_modules`, so that the tools were able to access it
363
- target = fslib_1.npath.toPortablePath(info.packageLocation);
364
- linkType = LinkType.SOFT;
365
- }
366
- else {
367
- target = getRealPackageLocation(info, locator, pnp);
368
- linkType = info.linkType;
369
- }
370
- return { linkType, target };
371
- }
372
- /**
373
- * Converts hoisted tree to node modules map
374
- *
375
- * @param pnp PnP API
376
- * @param hoistedTree hoisted package tree from `RawHoister`
377
- * @param locators locators
378
- * @param packages package weights
379
- *
380
- * @returns node modules map
381
- */
382
- const populateNodeModulesTree = (pnp, hoistedTree, options) => {
383
- const tree = new Map();
384
- const makeLeafNode = (locator, nodePath, aliases) => {
385
- const { linkType, target } = getTargetLocatorPath(locator, pnp, options);
386
- return {
387
- locator: stringifyLocator(locator),
388
- nodePath,
389
- target,
390
- linkType,
391
- aliases,
392
- };
393
- };
394
- const getPackageName = (identName) => {
395
- const [nameOrScope, name] = identName.split(`/`);
396
- return name ? {
397
- scope: (0, fslib_1.toFilename)(nameOrScope),
398
- name: (0, fslib_1.toFilename)(name),
399
- } : {
400
- scope: null,
401
- name: (0, fslib_1.toFilename)(nameOrScope),
402
- };
403
- };
404
- const seenNodes = new Set();
405
- const buildTree = (pkg, locationPrefix, parentNodePath) => {
406
- if (seenNodes.has(pkg))
407
- return;
408
- seenNodes.add(pkg);
409
- for (const dep of pkg.dependencies) {
410
- // We do not want self-references in node_modules, since they confuse existing tools
411
- if (dep === pkg)
412
- continue;
413
- const references = Array.from(dep.references).sort();
414
- const locator = { name: dep.identName, reference: references[0] };
415
- const { name, scope } = getPackageName(dep.name);
416
- const packageNameParts = scope
417
- ? [scope, name]
418
- : [name];
419
- const nodeModulesDirPath = fslib_1.ppath.join(locationPrefix, NODE_MODULES);
420
- const nodeModulesLocation = fslib_1.ppath.join(nodeModulesDirPath, ...packageNameParts);
421
- const nodePath = `${parentNodePath}/${locator.name}`;
422
- const leafNode = makeLeafNode(locator, parentNodePath, references.slice(1));
423
- // We don't want to create self-referencing symlinks for anonymous workspaces
424
- let isAnonymousWorkspace = false;
425
- if (leafNode.linkType === LinkType.SOFT && options.project) {
426
- const workspace = options.project.workspacesByCwd.get(leafNode.target.slice(0, -1));
427
- isAnonymousWorkspace = !!(workspace && !workspace.manifest.name);
428
- }
429
- if (!dep.name.endsWith(WORKSPACE_NAME_SUFFIX) && !isAnonymousWorkspace) {
430
- const prevNode = tree.get(nodeModulesLocation);
431
- if (prevNode) {
432
- if (prevNode.dirList) {
433
- throw new Error(`Assertion failed: ${nodeModulesLocation} cannot merge dir node with leaf node`);
434
- }
435
- else {
436
- const locator1 = core_1.structUtils.parseLocator(prevNode.locator);
437
- const locator2 = core_1.structUtils.parseLocator(leafNode.locator);
438
- if (prevNode.linkType !== leafNode.linkType)
439
- throw new Error(`Assertion failed: ${nodeModulesLocation} cannot merge nodes with different link types ${prevNode.nodePath}/${core_1.structUtils.stringifyLocator(locator1)} and ${parentNodePath}/${core_1.structUtils.stringifyLocator(locator2)}`);
440
- else if (locator1.identHash !== locator2.identHash)
441
- throw new Error(`Assertion failed: ${nodeModulesLocation} cannot merge nodes with different idents ${prevNode.nodePath}/${core_1.structUtils.stringifyLocator(locator1)} and ${parentNodePath}/s${core_1.structUtils.stringifyLocator(locator2)}`);
442
- leafNode.aliases = [...leafNode.aliases, ...prevNode.aliases, core_1.structUtils.parseLocator(prevNode.locator).reference];
443
- }
444
- }
445
- tree.set(nodeModulesLocation, leafNode);
446
- const segments = nodeModulesLocation.split(`/`);
447
- const nodeModulesIdx = segments.indexOf(NODE_MODULES);
448
- let segCount = segments.length - 1;
449
- while (nodeModulesIdx >= 0 && segCount > nodeModulesIdx) {
450
- const dirPath = fslib_1.npath.toPortablePath(segments.slice(0, segCount).join(fslib_1.ppath.sep));
451
- const targetDir = (0, fslib_1.toFilename)(segments[segCount]);
452
- const subdirs = tree.get(dirPath);
453
- if (!subdirs) {
454
- tree.set(dirPath, { dirList: new Set([targetDir]) });
455
- }
456
- else if (subdirs.dirList) {
457
- if (subdirs.dirList.has(targetDir)) {
458
- break;
459
- }
460
- else {
461
- subdirs.dirList.add(targetDir);
462
- }
463
- }
464
- segCount--;
465
- }
466
- }
467
- buildTree(dep, leafNode.linkType === LinkType.SOFT ? leafNode.target : nodeModulesLocation, nodePath);
468
- }
469
- };
470
- const rootNode = makeLeafNode({ name: hoistedTree.name, reference: Array.from(hoistedTree.references)[0] }, ``, []);
471
- const rootPath = rootNode.target;
472
- tree.set(rootPath, rootNode);
473
- buildTree(hoistedTree, rootPath, ``);
474
- return tree;
475
- };
476
- /**
477
- * Benchmarks raw hoisting performance.
478
- *
479
- * The function is used for troubleshooting purposes only.
480
- *
481
- * @param packageTree package tree
482
- * @param packages package info
483
- *
484
- * @returns average raw hoisting time
485
- */
486
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
487
- const benchmarkRawHoisting = (packageTree) => {
488
- const iterCount = 10;
489
- const startTime = Date.now();
490
- for (let iter = 0; iter < iterCount; iter++)
491
- (0, hoist_1.hoist)(packageTree);
492
- const endTime = Date.now();
493
- return (endTime - startTime) / iterCount;
494
- };
495
- /**
496
- * Benchmarks node_modules tree building.
497
- *
498
- * The function is used for troubleshooting purposes only.
499
- *
500
- * @param packageTree package tree
501
- * @param packages package info
502
- *
503
- * @returns average raw hoisting time
504
- */
505
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
506
- const benchmarkBuildTree = (pnp, options) => {
507
- const iterCount = 100;
508
- const startTime = Date.now();
509
- for (let iter = 0; iter < iterCount; iter++) {
510
- const { packageTree, hoistingLimits } = buildPackageTree(pnp, options);
511
- const hoistedTree = (0, hoist_1.hoist)(packageTree, { hoistingLimits });
512
- populateNodeModulesTree(pnp, hoistedTree, options);
513
- }
514
- const endTime = Date.now();
515
- return (endTime - startTime) / iterCount;
516
- };
517
- /**
518
- * Pretty-prints node_modules tree.
519
- *
520
- * The function is used for troubleshooting purposes only.
521
- *
522
- * @param tree node_modules tree
523
- * @param rootPath top-level project root folder
524
- *
525
- * @returns sorted node_modules tree
526
- */
527
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
528
- const dumpNodeModulesTree = (tree, rootPath) => {
529
- const sortedTree = new Map();
530
- const keys = Array.from(tree.keys()).sort();
531
- for (const key of keys) {
532
- const val = tree.get(key);
533
- sortedTree.set(key, val.dirList ? { dirList: new Set(Array.from(val.dirList).sort()) } : val);
534
- }
535
- const seenPaths = new Set();
536
- const dumpTree = (nodePath, prefix = ``, dirPrefix = ``) => {
537
- const node = sortedTree.get(nodePath);
538
- if (!node)
539
- return ``;
540
- seenPaths.add(nodePath);
541
- let str = ``;
542
- if (node.dirList) {
543
- const dirs = Array.from(node.dirList);
544
- for (let idx = 0; idx < dirs.length; idx++) {
545
- const dir = dirs[idx];
546
- str += `${prefix}${idx < dirs.length - 1 ? `├─` : `└─`}${dirPrefix}${dir}\n`;
547
- str += dumpTree(fslib_1.ppath.join(nodePath, dir), `${prefix}${idx < dirs.length - 1 ? `│ ` : ` `}`);
548
- }
549
- }
550
- else {
551
- const { target, linkType } = node;
552
- str += dumpTree(fslib_1.ppath.join(nodePath, NODE_MODULES), `${prefix}│ `, `${NODE_MODULES}/`);
553
- str += `${prefix}└─${linkType === LinkType.SOFT ? `s>` : `>`}${target}\n`;
554
- }
555
- return str;
556
- };
557
- let str = dumpTree(fslib_1.ppath.join(rootPath, NODE_MODULES));
558
- for (const key of sortedTree.keys()) {
559
- if (!seenPaths.has(key)) {
560
- str += `${key.replace(rootPath, ``)}\n${dumpTree(key)}`;
561
- }
562
- }
563
- return str;
564
- };
565
- /**
566
- * Pretty-prints dependency tree in the `yarn why`-like format
567
- *
568
- * The function is used for troubleshooting purposes only.
569
- *
570
- * @param pkg node_modules tree
571
- *
572
- * @returns sorted node_modules tree
573
- */
574
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
575
- const dumpDepTree = (tree) => {
576
- const dumpLocator = (locator) => {
577
- if (locator.reference === `workspace:.`) {
578
- return `.`;
579
- }
580
- else if (!locator.reference) {
581
- return `${locator.name}@${locator.reference}`;
582
- }
583
- else {
584
- const version = (locator.reference.indexOf(`#`) > 0 ? locator.reference.split(`#`)[1] : locator.reference).replace(`npm:`, ``);
585
- if (locator.reference.startsWith(`virtual`)) {
586
- return `v:${locator.name}@${version}`;
587
- }
588
- else {
589
- return `${locator.name}@${version}`;
590
- }
591
- }
592
- };
593
- const dumpPackage = (pkg, parents, prefix = ``) => {
594
- if (parents.includes(pkg))
595
- return ``;
596
- const dependencies = Array.from(pkg.dependencies);
597
- let str = ``;
598
- for (let idx = 0; idx < dependencies.length; idx++) {
599
- const dep = dependencies[idx];
600
- str += `${prefix}${idx < dependencies.length - 1 ? `├─` : `└─`}${(parents.includes(dep) ? `>` : ``) + dumpLocator({ name: dep.name, reference: Array.from(dep.references)[0] })}\n`;
601
- str += dumpPackage(dep, [...parents, dep], `${prefix}${idx < dependencies.length - 1 ? `│ ` : ` `}`);
602
- }
603
- return str;
604
- };
605
- return dumpPackage(tree, []);
606
- };