@pnpm/installing.linking.hoist 1002.0.8
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.
- package/LICENSE +22 -0
- package/README.md +15 -0
- package/lib/index.d.ts +71 -0
- package/lib/index.js +305 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015-2016 Rico Sta. Cruz and other contributors
|
|
4
|
+
Copyright (c) 2016-2026 Zoltan Kochan and other contributors
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { DependenciesField, DepPath, HoistedDependencies, ProjectId } from '@pnpm/types';
|
|
2
|
+
export interface DependenciesGraphNode<T extends string> {
|
|
3
|
+
dir: string;
|
|
4
|
+
children: Record<string, T>;
|
|
5
|
+
optionalDependencies: Set<string>;
|
|
6
|
+
hasBin: boolean;
|
|
7
|
+
name: string;
|
|
8
|
+
depPath: DepPath;
|
|
9
|
+
}
|
|
10
|
+
export type DependenciesGraph<T extends string> = Record<T, DependenciesGraphNode<T>>;
|
|
11
|
+
export interface DirectDependenciesByImporterId<T extends string> {
|
|
12
|
+
[importerId: string]: Map<string, T>;
|
|
13
|
+
}
|
|
14
|
+
export interface HoistOpts<T extends string> extends GetHoistedDependenciesOpts<T> {
|
|
15
|
+
extraNodePath?: string[];
|
|
16
|
+
preferSymlinkedExecutables?: boolean;
|
|
17
|
+
virtualStoreDir: string;
|
|
18
|
+
virtualStoreDirMaxLength: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function hoist<T extends string>(opts: HoistOpts<T>): Promise<HoistedDependencies | null>;
|
|
21
|
+
export interface GetHoistedDependenciesOpts<T extends string> {
|
|
22
|
+
graph: DependenciesGraph<T>;
|
|
23
|
+
skipped: Set<DepPath>;
|
|
24
|
+
directDepsByImporterId: DirectDependenciesByImporterId<T>;
|
|
25
|
+
importerIds?: ProjectId[];
|
|
26
|
+
privateHoistPattern: string[];
|
|
27
|
+
privateHoistedModulesDir: string;
|
|
28
|
+
publicHoistPattern: string[];
|
|
29
|
+
publicHoistedModulesDir: string;
|
|
30
|
+
hoistedWorkspacePackages?: Record<ProjectId, HoistedWorkspaceProject>;
|
|
31
|
+
}
|
|
32
|
+
export interface HoistedWorkspaceProject {
|
|
33
|
+
name: string;
|
|
34
|
+
dir: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function getHoistedDependencies<T extends string>(opts: GetHoistedDependenciesOpts<T>): HoistGraphResult<T> | null;
|
|
37
|
+
export interface Dependency<T extends string> {
|
|
38
|
+
children: Record<string, T | ProjectId>;
|
|
39
|
+
nodeId: T;
|
|
40
|
+
depth: number;
|
|
41
|
+
}
|
|
42
|
+
interface HoistGraphResult<T extends string> {
|
|
43
|
+
hoistedDependencies: HoistedDependencies;
|
|
44
|
+
hoistedDependenciesByNodeId: HoistedDependenciesByNodeId<T>;
|
|
45
|
+
hoistedAliasesWithBins: string[];
|
|
46
|
+
}
|
|
47
|
+
type HoistedDependenciesByNodeId<T extends string> = Map<T | ProjectId, Record<string, 'public' | 'private'>>;
|
|
48
|
+
export declare function graphWalker<T extends string>(graph: DependenciesGraph<T>, directDepsByImporterId: DirectDependenciesByImporterId<T>, opts?: {
|
|
49
|
+
include?: {
|
|
50
|
+
[dependenciesField in DependenciesField]: boolean;
|
|
51
|
+
};
|
|
52
|
+
skipped?: Set<DepPath>;
|
|
53
|
+
}): GraphWalker<T>;
|
|
54
|
+
export interface GraphWalker<T extends string> {
|
|
55
|
+
directDeps: Array<{
|
|
56
|
+
alias: string;
|
|
57
|
+
nodeId: T;
|
|
58
|
+
}>;
|
|
59
|
+
step: GraphWalkerStep<T>;
|
|
60
|
+
}
|
|
61
|
+
export interface GraphWalkerStep<T extends string> {
|
|
62
|
+
dependencies: Array<GraphDependency<T>>;
|
|
63
|
+
links: string[];
|
|
64
|
+
missing: string[];
|
|
65
|
+
}
|
|
66
|
+
export interface GraphDependency<T extends string> {
|
|
67
|
+
nodeId: T;
|
|
68
|
+
node: DependenciesGraphNode<T>;
|
|
69
|
+
next: () => GraphWalkerStep<T>;
|
|
70
|
+
}
|
|
71
|
+
export {};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { linkBinsOfPkgsByAliases } from '@pnpm/bins.linker';
|
|
4
|
+
import { createMatcher } from '@pnpm/config.matcher';
|
|
5
|
+
import { WANTED_LOCKFILE } from '@pnpm/constants';
|
|
6
|
+
import { linkLogger } from '@pnpm/core-loggers';
|
|
7
|
+
import { logger } from '@pnpm/logger';
|
|
8
|
+
import { lexCompare } from '@pnpm/util.lex-comparator';
|
|
9
|
+
import { isSubdir } from 'is-subdir';
|
|
10
|
+
import { resolveLinkTarget } from 'resolve-link-target';
|
|
11
|
+
import symlinkDir from 'symlink-dir';
|
|
12
|
+
const hoistLogger = logger('hoist');
|
|
13
|
+
export async function hoist(opts) {
|
|
14
|
+
const result = getHoistedDependencies(opts);
|
|
15
|
+
if (!result)
|
|
16
|
+
return null;
|
|
17
|
+
const { hoistedDependencies, hoistedAliasesWithBins, hoistedDependenciesByNodeId } = result;
|
|
18
|
+
await symlinkHoistedDependencies(hoistedDependenciesByNodeId, {
|
|
19
|
+
graph: opts.graph,
|
|
20
|
+
directDepsByImporterId: opts.directDepsByImporterId,
|
|
21
|
+
privateHoistedModulesDir: opts.privateHoistedModulesDir,
|
|
22
|
+
publicHoistedModulesDir: opts.publicHoistedModulesDir,
|
|
23
|
+
virtualStoreDir: opts.virtualStoreDir,
|
|
24
|
+
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
|
25
|
+
hoistedWorkspacePackages: opts.hoistedWorkspacePackages,
|
|
26
|
+
});
|
|
27
|
+
// Here we only link the bins of the privately hoisted modules.
|
|
28
|
+
// The bins of the publicly hoisted modules will be linked together with
|
|
29
|
+
// the bins of the project's direct dependencies.
|
|
30
|
+
// This is possible because the publicly hoisted modules
|
|
31
|
+
// are in the same directory as the regular dependencies.
|
|
32
|
+
await linkAllBins(opts.privateHoistedModulesDir, {
|
|
33
|
+
extraNodePaths: opts.extraNodePath,
|
|
34
|
+
hoistedAliasesWithBins,
|
|
35
|
+
preferSymlinkedExecutables: opts.preferSymlinkedExecutables,
|
|
36
|
+
});
|
|
37
|
+
return hoistedDependencies;
|
|
38
|
+
}
|
|
39
|
+
export function getHoistedDependencies(opts) {
|
|
40
|
+
if (Object.keys(opts.graph ?? {}).length === 0)
|
|
41
|
+
return null;
|
|
42
|
+
const { directDeps, step } = graphWalker(opts.graph, opts.directDepsByImporterId);
|
|
43
|
+
// We want to hoist all the workspace packages, not only those that are in the dependencies
|
|
44
|
+
// of any other workspace packages.
|
|
45
|
+
// That is why we can't just simply use the lockfile walker to include links to local workspace packages too.
|
|
46
|
+
// We have to explicitly include all the workspace packages.
|
|
47
|
+
const hoistedWorkspaceDeps = Object.fromEntries(Object.entries(opts.hoistedWorkspacePackages ?? {})
|
|
48
|
+
.map(([id, { name }]) => [name, id]));
|
|
49
|
+
const deps = [
|
|
50
|
+
{
|
|
51
|
+
children: {
|
|
52
|
+
...hoistedWorkspaceDeps,
|
|
53
|
+
...directDeps
|
|
54
|
+
.reduce((acc, { alias, nodeId }) => {
|
|
55
|
+
if (!acc[alias]) {
|
|
56
|
+
acc[alias] = nodeId;
|
|
57
|
+
}
|
|
58
|
+
return acc;
|
|
59
|
+
}, {}),
|
|
60
|
+
},
|
|
61
|
+
nodeId: '',
|
|
62
|
+
depth: -1,
|
|
63
|
+
},
|
|
64
|
+
...getDependencies(0, step),
|
|
65
|
+
];
|
|
66
|
+
const getAliasHoistType = createGetAliasHoistType(opts.publicHoistPattern, opts.privateHoistPattern);
|
|
67
|
+
return hoistGraph(deps, opts.directDepsByImporterId['.'] ?? new Map(), {
|
|
68
|
+
getAliasHoistType,
|
|
69
|
+
graph: opts.graph,
|
|
70
|
+
skipped: opts.skipped,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function createGetAliasHoistType(publicHoistPattern, privateHoistPattern) {
|
|
74
|
+
const publicMatcher = createMatcher(publicHoistPattern);
|
|
75
|
+
const privateMatcher = createMatcher(privateHoistPattern);
|
|
76
|
+
return (alias) => {
|
|
77
|
+
if (publicMatcher(alias))
|
|
78
|
+
return 'public';
|
|
79
|
+
if (privateMatcher(alias))
|
|
80
|
+
return 'private';
|
|
81
|
+
return false;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function linkAllBins(modulesDir, opts) {
|
|
85
|
+
const bin = path.join(modulesDir, '.bin');
|
|
86
|
+
const warn = (message, code) => {
|
|
87
|
+
if (code === 'BINARIES_CONFLICT')
|
|
88
|
+
return;
|
|
89
|
+
logger.info({ message, prefix: path.join(modulesDir, '../..') });
|
|
90
|
+
};
|
|
91
|
+
try {
|
|
92
|
+
await linkBinsOfPkgsByAliases(opts.hoistedAliasesWithBins, bin, {
|
|
93
|
+
allowExoticManifests: true,
|
|
94
|
+
extraNodePaths: opts.extraNodePaths,
|
|
95
|
+
modulesDir,
|
|
96
|
+
preferSymlinkedExecutables: opts.preferSymlinkedExecutables,
|
|
97
|
+
warn,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (err) { // eslint-disable-line
|
|
101
|
+
// Some packages generate their commands with lifecycle hooks.
|
|
102
|
+
// At this stage, such commands are not generated yet.
|
|
103
|
+
// For now, we don't hoist such generated commands.
|
|
104
|
+
// Related issue: https://github.com/pnpm/pnpm/issues/2071
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function getDependencies(depth, step) {
|
|
108
|
+
const deps = [];
|
|
109
|
+
const nextSteps = [];
|
|
110
|
+
for (const { node, nodeId, next } of step.dependencies) {
|
|
111
|
+
deps.push({
|
|
112
|
+
children: node.children,
|
|
113
|
+
nodeId,
|
|
114
|
+
depth,
|
|
115
|
+
});
|
|
116
|
+
nextSteps.push(next());
|
|
117
|
+
}
|
|
118
|
+
for (const depPath of step.missing) {
|
|
119
|
+
// It might make sense to fail if the depPath is not in the skipped list from .modules.yaml
|
|
120
|
+
// However, the skipped list currently contains package IDs, not dep paths.
|
|
121
|
+
logger.debug({ message: `No entry for "${depPath}" in ${WANTED_LOCKFILE}` });
|
|
122
|
+
}
|
|
123
|
+
return [
|
|
124
|
+
...deps,
|
|
125
|
+
...nextSteps.flatMap(getDependencies.bind(null, depth + 1)),
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
function hoistGraph(depNodes, currentSpecifiers, opts) {
|
|
129
|
+
const hoistedAliases = new Set(currentSpecifiers.keys());
|
|
130
|
+
const hoistedDependencies = Object.create(null);
|
|
131
|
+
const hoistedDependenciesByNodeId = new Map();
|
|
132
|
+
const hoistedAliasesWithBins = new Set();
|
|
133
|
+
depNodes
|
|
134
|
+
// sort by depth and then alphabetically
|
|
135
|
+
.sort((a, b) => {
|
|
136
|
+
const depthDiff = a.depth - b.depth;
|
|
137
|
+
return depthDiff === 0 ? lexCompare(a.nodeId, b.nodeId) : depthDiff;
|
|
138
|
+
})
|
|
139
|
+
// build the alias map and the id map
|
|
140
|
+
.forEach((depNode) => {
|
|
141
|
+
for (const [childAlias, childNodeId] of Object.entries(depNode.children)) {
|
|
142
|
+
const hoist = opts.getAliasHoistType(childAlias);
|
|
143
|
+
if (!hoist)
|
|
144
|
+
continue;
|
|
145
|
+
const childAliasNormalized = childAlias.toLowerCase();
|
|
146
|
+
// if this alias has already been taken, skip it
|
|
147
|
+
if (hoistedAliases.has(childAliasNormalized)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (!hoistedDependenciesByNodeId.has(childNodeId)) {
|
|
151
|
+
hoistedDependenciesByNodeId.set(childNodeId, {});
|
|
152
|
+
}
|
|
153
|
+
hoistedDependenciesByNodeId.get(childNodeId)[childAlias] = hoist;
|
|
154
|
+
const node = opts.graph[childNodeId];
|
|
155
|
+
if (node?.depPath == null || opts.skipped.has(node.depPath)) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (node.hasBin) {
|
|
159
|
+
hoistedAliasesWithBins.add(childAlias);
|
|
160
|
+
}
|
|
161
|
+
hoistedAliases.add(childAliasNormalized);
|
|
162
|
+
if (!hoistedDependencies[node.depPath]) {
|
|
163
|
+
hoistedDependencies[node.depPath] = {};
|
|
164
|
+
}
|
|
165
|
+
hoistedDependencies[node.depPath][childAlias] = hoist;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return {
|
|
169
|
+
hoistedDependencies,
|
|
170
|
+
hoistedDependenciesByNodeId,
|
|
171
|
+
hoistedAliasesWithBins: Array.from(hoistedAliasesWithBins),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async function symlinkHoistedDependencies(hoistedDependenciesByNodeId, opts) {
|
|
175
|
+
const symlink = symlinkHoistedDependency.bind(null, opts);
|
|
176
|
+
const promises = [];
|
|
177
|
+
for (const [hoistedDepNodeId, pkgAliases] of hoistedDependenciesByNodeId.entries()) {
|
|
178
|
+
promises.push((async () => {
|
|
179
|
+
const node = opts.graph[hoistedDepNodeId];
|
|
180
|
+
let depLocation;
|
|
181
|
+
if (node) {
|
|
182
|
+
depLocation = node.dir;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
if (!opts.directDepsByImporterId[hoistedDepNodeId]) {
|
|
186
|
+
// This dependency is probably a skipped optional dependency.
|
|
187
|
+
hoistLogger.debug({ hoistFailedFor: hoistedDepNodeId });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
depLocation = opts.hoistedWorkspacePackages[hoistedDepNodeId].dir;
|
|
191
|
+
}
|
|
192
|
+
await Promise.all(Object.entries(pkgAliases).map(async ([pkgAlias, hoistType]) => {
|
|
193
|
+
const targetDir = hoistType === 'public'
|
|
194
|
+
? opts.publicHoistedModulesDir
|
|
195
|
+
: opts.privateHoistedModulesDir;
|
|
196
|
+
const dest = path.join(targetDir, pkgAlias);
|
|
197
|
+
return symlink(depLocation, dest);
|
|
198
|
+
}));
|
|
199
|
+
})());
|
|
200
|
+
}
|
|
201
|
+
await Promise.all(promises);
|
|
202
|
+
}
|
|
203
|
+
async function symlinkHoistedDependency(opts, depLocation, dest) {
|
|
204
|
+
try {
|
|
205
|
+
await symlinkDir(depLocation, dest, { overwrite: false });
|
|
206
|
+
linkLogger.debug({ target: dest, link: depLocation });
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
catch (err) { // eslint-disable-line
|
|
210
|
+
if (err.code !== 'EEXIST' && err.code !== 'EISDIR')
|
|
211
|
+
throw err;
|
|
212
|
+
}
|
|
213
|
+
let existingSymlink;
|
|
214
|
+
try {
|
|
215
|
+
existingSymlink = await resolveLinkTarget(dest);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
hoistLogger.debug({
|
|
219
|
+
skipped: dest,
|
|
220
|
+
reason: 'a directory is present at the target location',
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (!isSubdir(opts.virtualStoreDir, existingSymlink)) {
|
|
225
|
+
hoistLogger.debug({
|
|
226
|
+
skipped: dest,
|
|
227
|
+
existingSymlink,
|
|
228
|
+
reason: 'an external symlink is present at the target location',
|
|
229
|
+
});
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
await fs.promises.unlink(dest);
|
|
233
|
+
await symlinkDir(depLocation, dest);
|
|
234
|
+
linkLogger.debug({ target: dest, link: depLocation });
|
|
235
|
+
}
|
|
236
|
+
export function graphWalker(graph, directDepsByImporterId, opts) {
|
|
237
|
+
const startNodeIds = [];
|
|
238
|
+
const allDirectDeps = [];
|
|
239
|
+
for (const directDeps of Object.values(directDepsByImporterId)) {
|
|
240
|
+
for (const [alias, nodeId] of directDeps.entries()) {
|
|
241
|
+
const depNode = graph[nodeId];
|
|
242
|
+
if (depNode == null)
|
|
243
|
+
continue;
|
|
244
|
+
startNodeIds.push(nodeId);
|
|
245
|
+
allDirectDeps.push({ alias, nodeId });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const visited = new Set();
|
|
249
|
+
return {
|
|
250
|
+
directDeps: allDirectDeps,
|
|
251
|
+
step: makeStep({
|
|
252
|
+
includeOptionalDependencies: opts?.include?.optionalDependencies !== false,
|
|
253
|
+
graph,
|
|
254
|
+
visited,
|
|
255
|
+
skipped: opts?.skipped,
|
|
256
|
+
}, startNodeIds),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function makeStep(ctx, nextNodeIds) {
|
|
260
|
+
const result = {
|
|
261
|
+
dependencies: [],
|
|
262
|
+
links: [],
|
|
263
|
+
missing: [],
|
|
264
|
+
};
|
|
265
|
+
const _next = collectChildNodeIds.bind(null, {
|
|
266
|
+
includeOptionalDependencies: ctx.includeOptionalDependencies,
|
|
267
|
+
});
|
|
268
|
+
for (const nodeId of nextNodeIds) {
|
|
269
|
+
if (ctx.visited.has(nodeId))
|
|
270
|
+
continue;
|
|
271
|
+
ctx.visited.add(nodeId);
|
|
272
|
+
const node = ctx.graph[nodeId];
|
|
273
|
+
if (node == null) {
|
|
274
|
+
if (nodeId.startsWith('link:')) {
|
|
275
|
+
result.links.push(nodeId);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
result.missing.push(nodeId);
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
if (ctx.skipped?.has(node.depPath))
|
|
282
|
+
continue;
|
|
283
|
+
result.dependencies.push({
|
|
284
|
+
nodeId,
|
|
285
|
+
next: () => makeStep(ctx, _next(node)),
|
|
286
|
+
node,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
function collectChildNodeIds(opts, nextPkg) {
|
|
292
|
+
if (opts.includeOptionalDependencies) {
|
|
293
|
+
return Object.values(nextPkg.children);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
const nextNodeIds = [];
|
|
297
|
+
for (const [alias, nodeId] of Object.entries(nextPkg.children)) {
|
|
298
|
+
if (!nextPkg.optionalDependencies.has(alias)) {
|
|
299
|
+
nextNodeIds.push(nodeId);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return nextNodeIds;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pnpm/installing.linking.hoist",
|
|
3
|
+
"version": "1002.0.8",
|
|
4
|
+
"description": "Hoists dependencies in a node_modules created by pnpm",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pnpm",
|
|
7
|
+
"pnpm11"
|
|
8
|
+
],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"funding": "https://opencollective.com/pnpm",
|
|
11
|
+
"repository": "https://github.com/pnpm/pnpm/tree/main/installing/linking/hoist",
|
|
12
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/installing/linking/hoist#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/pnpm/pnpm/issues"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"types": "lib/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./lib/index.js"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"lib",
|
|
24
|
+
"!*.map"
|
|
25
|
+
],
|
|
26
|
+
"directories": {
|
|
27
|
+
"test": "test"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@pnpm/util.lex-comparator": "^3.0.2",
|
|
31
|
+
"is-subdir": "^2.0.0",
|
|
32
|
+
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
33
|
+
"resolve-link-target": "^3.0.0",
|
|
34
|
+
"symlink-dir": "^7.0.0",
|
|
35
|
+
"@pnpm/bins.linker": "1000.2.6",
|
|
36
|
+
"@pnpm/core-loggers": "1001.0.4",
|
|
37
|
+
"@pnpm/constants": "1001.3.1",
|
|
38
|
+
"@pnpm/types": "1000.9.0",
|
|
39
|
+
"@pnpm/config.matcher": "1000.1.0"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@pnpm/logger": ">=1001.0.0 <1002.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/ramda": "0.29.12",
|
|
46
|
+
"@pnpm/logger": "1001.0.1",
|
|
47
|
+
"@pnpm/installing.linking.hoist": "1002.0.8"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22.13"
|
|
51
|
+
},
|
|
52
|
+
"jest": {
|
|
53
|
+
"preset": "@pnpm/jest-config"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"start": "tsgo --watch",
|
|
57
|
+
"test": "pnpm run compile",
|
|
58
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
59
|
+
"compile": "tsgo --build && pnpm run lint --fix"
|
|
60
|
+
}
|
|
61
|
+
}
|