@pnpm/installing.linking.real-hoist 1100.1.21 → 1100.1.22

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/lib/index.js +138 -111
  3. package/package.json +6 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @pnpm/real-hoist
2
2
 
3
+ ## 1100.1.22
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies:
8
+ - @pnpm/deps.path@1101.0.6
9
+ - @pnpm/error@1100.2.2
10
+ - @pnpm/lockfile.utils@1102.1.6
11
+
3
12
  ## 1100.1.21
4
13
 
5
14
  ### Patch Changes
package/lib/index.js CHANGED
@@ -53,141 +53,168 @@ export function getHoistingLimits(lockfile, mode) {
53
53
  const hoistingLimits = new Map();
54
54
  const rootHoistingLimit = new Set();
55
55
  for (const [importerId, importer] of Object.entries(lockfile.importers)) {
56
- const isWorkspaceRoot = importerId === '.';
57
- const encodedId = encodeURIComponent(importerId);
58
- if (!isWorkspaceRoot) {
59
- rootHoistingLimit.add(encodedId);
60
- if (mode !== 'dependencies') {
61
- // In `'workspaces'` mode it's enough to border each workspace
62
- // package at the root; their own direct deps don't need a
63
- // per-importer border.
64
- continue;
65
- }
66
- }
67
- const reference = isWorkspaceRoot ? '' : `workspace:${importerId}`;
68
- const hoistingLimit = isWorkspaceRoot ? rootHoistingLimit : new Set();
69
- hoistingLimits.set(`${encodedId}@${reference}`, hoistingLimit);
70
- for (const deps of [importer.dependencies, importer.devDependencies, importer.optionalDependencies]) {
71
- if (!deps)
72
- continue;
73
- for (const dep of Object.keys(deps)) {
74
- hoistingLimit.add(dep);
75
- }
76
- }
56
+ addImporterHoistingLimits({
57
+ hoistingLimits,
58
+ importer,
59
+ importerId,
60
+ mode,
61
+ rootHoistingLimit,
62
+ });
77
63
  }
78
64
  if (!hoistingLimits.has('.@')) {
79
65
  hoistingLimits.set('.@', rootHoistingLimit);
80
66
  }
81
67
  return hoistingLimits;
82
68
  }
69
+ function addImporterHoistingLimits(opts) {
70
+ const { hoistingLimits, importer, importerId, mode, rootHoistingLimit } = opts;
71
+ const isWorkspaceRoot = importerId === '.';
72
+ const encodedId = encodeURIComponent(importerId);
73
+ if (!isWorkspaceRoot) {
74
+ rootHoistingLimit.add(encodedId);
75
+ if (mode !== 'dependencies') {
76
+ return;
77
+ }
78
+ }
79
+ const reference = isWorkspaceRoot ? '' : `workspace:${importerId}`;
80
+ const hoistingLimit = isWorkspaceRoot ? rootHoistingLimit : new Set();
81
+ hoistingLimits.set(`${encodedId}@${reference}`, hoistingLimit);
82
+ collectDirectDeps(importer, hoistingLimit);
83
+ }
84
+ function collectDirectDeps(importer, targetSet) {
85
+ const depGroups = [importer.dependencies, importer.devDependencies, importer.optionalDependencies];
86
+ for (const deps of depGroups) {
87
+ if (!deps)
88
+ continue;
89
+ for (const dep of Object.keys(deps)) {
90
+ targetSet.add(dep);
91
+ }
92
+ }
93
+ }
83
94
  export function hoist(lockfile, opts) {
84
- const nodes = new Map();
85
95
  const ctx = {
86
96
  autoInstallPeers: opts?.autoInstallPeers,
87
- nodes,
88
- lockfile,
89
97
  depPathByPkgId: new Map(),
98
+ lockfile,
99
+ nodes: new Map(),
90
100
  };
91
- const _toTree = toTree.bind(null, ctx);
92
- const node = {
93
- name: '.',
94
- identName: '.',
95
- reference: '',
96
- peerNames: new Set([]),
97
- dependencyKind: HoisterDependencyKind.WORKSPACE,
98
- dependencies: _toTree({
99
- ...lockfile.importers['.']?.dependencies,
100
- ...lockfile.importers['.']?.devDependencies,
101
- ...lockfile.importers['.']?.optionalDependencies,
102
- ...(Array.from(opts?.externalDependencies ?? [])).reduce((acc, dep) => {
103
- // It doesn't matter what version spec is used here.
104
- // This dependency will be removed from the tree anyway.
105
- // It is only needed to prevent the hoister from hoisting deps with this name to the root of node_modules.
106
- acc[dep] = 'link:';
107
- return acc;
108
- }, {}),
109
- }),
110
- };
101
+ const rootNode = buildRootHoisterTree(lockfile, ctx, opts?.externalDependencies);
111
102
  for (const [importerId, importer] of Object.entries(lockfile.importers)) {
112
103
  if (importerId === '.')
113
104
  continue;
114
- const importerNode = {
115
- name: encodeURIComponent(importerId),
116
- identName: encodeURIComponent(importerId),
117
- reference: `workspace:${importerId}`,
118
- peerNames: new Set([]),
119
- dependencyKind: HoisterDependencyKind.WORKSPACE,
120
- dependencies: _toTree({
121
- ...importer.dependencies,
122
- ...importer.devDependencies,
123
- ...importer.optionalDependencies,
124
- }),
125
- };
126
- node.dependencies.add(importerNode);
105
+ rootNode.dependencies.add(buildImporterHoisterTree(importerId, importer, ctx));
127
106
  }
128
107
  const hoistingLimits = getHoistingLimits(lockfile, opts?.hoistingLimits);
129
- const hoisterResult = _hoist(node, { ...opts, hoistingLimits });
108
+ const hoisterResult = _hoist(rootNode, { ...opts, hoistingLimits });
130
109
  if (opts?.externalDependencies) {
131
- for (const hoistedDep of hoisterResult.dependencies.values()) {
132
- if (opts.externalDependencies.has(hoistedDep.name)) {
133
- hoisterResult.dependencies.delete(hoistedDep);
134
- }
135
- }
110
+ filterExternalDependencies(hoisterResult, opts.externalDependencies);
136
111
  }
137
112
  return hoisterResult;
138
113
  }
139
- function toTree({ nodes, lockfile, depPathByPkgId, autoInstallPeers }, deps) {
114
+ function buildRootHoisterTree(lockfile, ctx, externalDependencies) {
115
+ const rootImporter = lockfile.importers['.'];
116
+ const externalDepsMap = {};
117
+ for (const dep of externalDependencies ?? []) {
118
+ externalDepsMap[dep] = 'link:';
119
+ }
120
+ return {
121
+ dependencies: toTree(ctx, {
122
+ ...rootImporter?.dependencies,
123
+ ...rootImporter?.devDependencies,
124
+ ...rootImporter?.optionalDependencies,
125
+ ...externalDepsMap,
126
+ }),
127
+ dependencyKind: HoisterDependencyKind.WORKSPACE,
128
+ identName: '.',
129
+ name: '.',
130
+ peerNames: new Set([]),
131
+ reference: '',
132
+ };
133
+ }
134
+ function buildImporterHoisterTree(importerId, importer, ctx) {
135
+ return {
136
+ dependencies: toTree(ctx, {
137
+ ...importer.dependencies,
138
+ ...importer.devDependencies,
139
+ ...importer.optionalDependencies,
140
+ }),
141
+ dependencyKind: HoisterDependencyKind.WORKSPACE,
142
+ identName: encodeURIComponent(importerId),
143
+ name: encodeURIComponent(importerId),
144
+ peerNames: new Set([]),
145
+ reference: `workspace:${importerId}`,
146
+ };
147
+ }
148
+ function filterExternalDependencies(result, externalDependencies) {
149
+ for (const hoistedDep of result.dependencies.values()) {
150
+ if (externalDependencies.has(hoistedDep.name)) {
151
+ result.dependencies.delete(hoistedDep);
152
+ }
153
+ }
154
+ }
155
+ function toTree(ctx, deps) {
140
156
  return new Set(Object.entries(deps).map(([alias, ref]) => {
141
157
  const depPath = dp.refToRelative(ref, alias);
142
158
  if (!depPath) {
143
- const key = `${alias}:${ref}`;
144
- let node = nodes.get(key);
145
- if (!node) {
146
- node = {
147
- name: alias,
148
- identName: alias,
149
- reference: ref,
150
- // A link into the declaring package must stay next to that package,
151
- // and the hoister never moves a workspace node.
152
- dependencyKind: dp.packageRootLinkTarget(ref) != null
153
- ? HoisterDependencyKind.WORKSPACE
154
- : HoisterDependencyKind.REGULAR,
155
- dependencies: new Set(),
156
- peerNames: new Set(),
157
- };
158
- nodes.set(key, node);
159
- }
160
- return node;
161
- }
162
- const key = `${alias}:${depPath}`;
163
- let node = nodes.get(key);
164
- if (!node) {
165
- const pkgSnapshot = lockfile.packages[depPath];
166
- if (!pkgSnapshot) {
167
- throw new LockfileMissingDependencyError(depPath);
168
- }
169
- const { name: pkgName } = nameVerFromPkgSnapshot(depPath, pkgSnapshot);
170
- const id = getHoisterPkgId(depPath, pkgSnapshot);
171
- if (!depPathByPkgId.has(id)) {
172
- depPathByPkgId.set(id, depPath);
173
- }
174
- node = {
175
- name: alias,
176
- identName: pkgName,
177
- reference: depPathByPkgId.get(id),
178
- dependencyKind: HoisterDependencyKind.REGULAR,
179
- dependencies: new Set(),
180
- peerNames: new Set(autoInstallPeers
181
- ? []
182
- : [
183
- ...Object.keys(pkgSnapshot.peerDependencies ?? {}),
184
- ...(pkgSnapshot.transitivePeerDependencies ?? []),
185
- ]),
186
- };
187
- nodes.set(key, node);
188
- node.dependencies = toTree({ nodes, lockfile, depPathByPkgId, autoInstallPeers }, { ...pkgSnapshot.dependencies, ...pkgSnapshot.optionalDependencies });
159
+ return getOrCreateWorkspaceNode(ctx.nodes, alias, ref);
189
160
  }
190
- return node;
161
+ return getOrCreatePackageNode(ctx, alias, depPath);
191
162
  }));
192
163
  }
164
+ function getOrCreateWorkspaceNode(nodes, alias, ref) {
165
+ const key = `${alias}:${ref}`;
166
+ let node = nodes.get(key);
167
+ if (!node) {
168
+ node = {
169
+ dependencies: new Set(),
170
+ dependencyKind: dp.packageRootLinkTarget(ref) != null
171
+ ? HoisterDependencyKind.WORKSPACE
172
+ : HoisterDependencyKind.REGULAR,
173
+ identName: alias,
174
+ name: alias,
175
+ peerNames: new Set(),
176
+ reference: ref,
177
+ };
178
+ nodes.set(key, node);
179
+ }
180
+ return node;
181
+ }
182
+ function getOrCreatePackageNode(ctx, alias, depPath) {
183
+ const key = `${alias}:${depPath}`;
184
+ let node = ctx.nodes.get(key);
185
+ if (!node) {
186
+ const pkgSnapshot = ctx.lockfile.packages?.[depPath];
187
+ if (!pkgSnapshot) {
188
+ throw new LockfileMissingDependencyError(depPath);
189
+ }
190
+ const { name: pkgName } = nameVerFromPkgSnapshot(depPath, pkgSnapshot);
191
+ const id = getHoisterPkgId(depPath, pkgSnapshot);
192
+ if (!ctx.depPathByPkgId.has(id)) {
193
+ ctx.depPathByPkgId.set(id, depPath);
194
+ }
195
+ node = {
196
+ dependencies: new Set(),
197
+ dependencyKind: HoisterDependencyKind.REGULAR,
198
+ identName: pkgName,
199
+ name: alias,
200
+ peerNames: resolvePeerNames(pkgSnapshot, ctx.autoInstallPeers),
201
+ reference: ctx.depPathByPkgId.get(id),
202
+ };
203
+ ctx.nodes.set(key, node);
204
+ node.dependencies = toTree(ctx, {
205
+ ...pkgSnapshot.dependencies,
206
+ ...pkgSnapshot.optionalDependencies,
207
+ });
208
+ }
209
+ return node;
210
+ }
211
+ function resolvePeerNames(pkgSnapshot, autoInstallPeers) {
212
+ if (autoInstallPeers) {
213
+ return new Set();
214
+ }
215
+ return new Set([
216
+ ...Object.keys(pkgSnapshot.peerDependencies ?? {}),
217
+ ...(pkgSnapshot.transitivePeerDependencies ?? []),
218
+ ]);
219
+ }
193
220
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/installing.linking.real-hoist",
3
- "version": "1100.1.21",
3
+ "version": "1100.1.22",
4
4
  "description": "Hoists dependencies in a node_modules created by pnpm",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -27,16 +27,16 @@
27
27
  "!*.map"
28
28
  ],
29
29
  "dependencies": {
30
- "@pnpm/deps.path": "1101.0.5",
31
- "@pnpm/error": "1100.2.1",
30
+ "@pnpm/deps.path": "1101.0.6",
31
+ "@pnpm/error": "1100.2.2",
32
32
  "@pnpm/lockfile.types": "1100.1.4",
33
- "@pnpm/lockfile.utils": "1102.1.5",
33
+ "@pnpm/lockfile.utils": "1102.1.6",
34
34
  "@yarnpkg/nm": "4.1.1"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@jest/globals": "30.4.1",
38
- "@pnpm/installing.linking.real-hoist": "1100.1.21",
39
- "@pnpm/lockfile.fs": "1100.2.10",
38
+ "@pnpm/installing.linking.real-hoist": "1100.1.22",
39
+ "@pnpm/lockfile.fs": "1100.2.13",
40
40
  "@pnpm/test-fixtures": "1100.0.1",
41
41
  "@pnpm/types": "1102.1.1"
42
42
  },