1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const constants_1 = require("@pnpm/constants");
|
4 | const link_bins_1 = require("@pnpm/link-bins");
|
5 | const lockfile_utils_1 = require("@pnpm/lockfile-utils");
|
6 | const lockfile_walker_1 = require("@pnpm/lockfile-walker");
|
7 | const logger_1 = require("@pnpm/logger");
|
8 | const pkgid_to_filename_1 = require("@pnpm/pkgid-to-filename");
|
9 | const symlink_dependency_1 = require("@pnpm/symlink-dependency");
|
10 | const dp = require("dependency-path");
|
11 | const path = require("path");
|
12 | const R = require("ramda");
|
13 | async function hoistByLockfile(match, opts) {
|
14 | if (!opts.lockfile.packages)
|
15 | return {};
|
16 | const deps = await getDependencies(lockfile_walker_1.default(opts.lockfile, Object.keys(opts.lockfile.importers)), 0, {
|
17 | getIndependentPackageLocation: opts.getIndependentPackageLocation,
|
18 | lockfileDir: opts.lockfileDir,
|
19 | registries: opts.registries,
|
20 | virtualStoreDir: opts.virtualStoreDir,
|
21 | });
|
22 | const aliasesByDependencyPath = await hoistGraph(deps, opts.lockfile.importers['.'].specifiers, {
|
23 | dryRun: false,
|
24 | match,
|
25 | modulesDir: opts.modulesDir,
|
26 | });
|
27 | const bin = path.join(opts.modulesDir, '.bin');
|
28 | const warn = (message) => logger_1.default.warn({ message, prefix: path.join(opts.modulesDir, '../..') });
|
29 | try {
|
30 | await link_bins_1.default(opts.modulesDir, bin, { allowExoticManifests: true, warn });
|
31 | }
|
32 | catch (err) {
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | }
|
38 | return aliasesByDependencyPath;
|
39 | }
|
40 | exports.default = hoistByLockfile;
|
41 | async function getDependencies(step, depth, opts) {
|
42 | const deps = [];
|
43 | const nextSteps = [];
|
44 | for (const { pkgSnapshot, relDepPath, next } of step.dependencies) {
|
45 | const absolutePath = dp.resolve(opts.registries, relDepPath);
|
46 | const pkgName = lockfile_utils_1.nameVerFromPkgSnapshot(relDepPath, pkgSnapshot).name;
|
47 | const modules = path.join(opts.virtualStoreDir, pkgid_to_filename_1.default(absolutePath, opts.lockfileDir), 'node_modules');
|
48 | const independent = opts.getIndependentPackageLocation && lockfile_utils_1.packageIsIndependent(pkgSnapshot);
|
49 | const allDeps = {
|
50 | ...pkgSnapshot.dependencies,
|
51 | ...pkgSnapshot.optionalDependencies,
|
52 | };
|
53 | deps.push({
|
54 | absolutePath,
|
55 | children: Object.keys(allDeps).reduce((children, alias) => {
|
56 | children[alias] = dp.refToAbsolute(allDeps[alias], alias, opts.registries);
|
57 | return children;
|
58 | }, {}),
|
59 | depth,
|
60 | location: !independent
|
61 | ? path.join(modules, pkgName)
|
62 | : await opts.getIndependentPackageLocation(pkgSnapshot.id || absolutePath, pkgName),
|
63 | name: pkgName,
|
64 | });
|
65 | nextSteps.push(next());
|
66 | }
|
67 | for (const relDepPath of step.missing) {
|
68 |
|
69 |
|
70 | logger_1.default.debug({ message: `No entry for "${relDepPath}" in ${constants_1.WANTED_LOCKFILE}` });
|
71 | }
|
72 | return (await Promise.all(nextSteps.map((nextStep) => getDependencies(nextStep, depth + 1, opts)))).reduce((acc, deps) => [...acc, ...deps], deps);
|
73 | }
|
74 | async function hoistGraph(depNodes, currentSpecifiers, opts) {
|
75 | const hoistedAliases = new Set(R.keys(currentSpecifiers));
|
76 | const aliasesByDependencyPath = {};
|
77 | await Promise.all(depNodes
|
78 |
|
79 | .sort((a, b) => {
|
80 | const depthDiff = a.depth - b.depth;
|
81 | return depthDiff === 0 ? a.name.localeCompare(b.name) : depthDiff;
|
82 | })
|
83 |
|
84 | .map((depNode) => {
|
85 | for (const childAlias of Object.keys(depNode.children)) {
|
86 | if (!opts.match(childAlias))
|
87 | continue;
|
88 |
|
89 | if (hoistedAliases.has(childAlias)) {
|
90 | continue;
|
91 | }
|
92 | hoistedAliases.add(childAlias);
|
93 | const childPath = depNode.children[childAlias];
|
94 | if (!aliasesByDependencyPath[childPath]) {
|
95 | aliasesByDependencyPath[childPath] = [];
|
96 | }
|
97 | aliasesByDependencyPath[childPath].push(childAlias);
|
98 | }
|
99 | return depNode;
|
100 | })
|
101 | .map(async (depNode) => {
|
102 | const pkgAliases = aliasesByDependencyPath[depNode.absolutePath];
|
103 | if (!pkgAliases) {
|
104 | return;
|
105 | }
|
106 |
|
107 |
|
108 | if (!opts.dryRun) {
|
109 | await Promise.all(pkgAliases.map(async (pkgAlias) => {
|
110 | await symlink_dependency_1.default(depNode.location, opts.modulesDir, pkgAlias);
|
111 | }));
|
112 | }
|
113 | }));
|
114 | return aliasesByDependencyPath;
|
115 | }
|