@pnpm/installing.commands 1004.6.10

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 (47) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +15 -0
  3. package/lib/add.d.ts +17 -0
  4. package/lib/add.js +285 -0
  5. package/lib/ci.d.ts +6 -0
  6. package/lib/ci.js +20 -0
  7. package/lib/createProjectManifestWriter.d.ts +2 -0
  8. package/lib/createProjectManifestWriter.js +17 -0
  9. package/lib/dedupe.d.ts +9 -0
  10. package/lib/dedupe.js +59 -0
  11. package/lib/fetch.d.ts +10 -0
  12. package/lib/fetch.js +75 -0
  13. package/lib/getFetchFullMetadata.d.ts +8 -0
  14. package/lib/getFetchFullMetadata.js +7 -0
  15. package/lib/getPinnedVersion.d.ts +4 -0
  16. package/lib/getPinnedVersion.js +6 -0
  17. package/lib/getSaveType.d.ts +3 -0
  18. package/lib/getSaveType.js +10 -0
  19. package/lib/import/index.d.ts +9 -0
  20. package/lib/import/index.js +238 -0
  21. package/lib/import/yarnUtil.d.ts +8 -0
  22. package/lib/import/yarnUtil.js +65 -0
  23. package/lib/index.d.ts +13 -0
  24. package/lib/index.js +13 -0
  25. package/lib/install.d.ts +28 -0
  26. package/lib/install.js +281 -0
  27. package/lib/installDeps.d.ts +41 -0
  28. package/lib/installDeps.js +349 -0
  29. package/lib/link.d.ts +9 -0
  30. package/lib/link.js +130 -0
  31. package/lib/nodeExecPath.d.ts +1 -0
  32. package/lib/nodeExecPath.js +16 -0
  33. package/lib/prune.d.ts +6 -0
  34. package/lib/prune.js +49 -0
  35. package/lib/recursive.d.ts +41 -0
  36. package/lib/recursive.js +406 -0
  37. package/lib/remove.d.ts +12 -0
  38. package/lib/remove.js +189 -0
  39. package/lib/unlink.d.ts +6 -0
  40. package/lib/unlink.js +62 -0
  41. package/lib/update/getUpdateChoices.d.ts +14 -0
  42. package/lib/update/getUpdateChoices.js +126 -0
  43. package/lib/update/index.d.ts +15 -0
  44. package/lib/update/index.js +295 -0
  45. package/lib/updateWorkspaceDependencies.d.ts +4 -0
  46. package/lib/updateWorkspaceDependencies.js +27 -0
  47. package/package.json +134 -0
@@ -0,0 +1,41 @@
1
+ import type { Config } from '@pnpm/config.reader';
2
+ import { type UpdateMatchingFunction } from '@pnpm/installing.deps-installer';
3
+ import type { LockfileObject } from '@pnpm/lockfile.types';
4
+ import { type CreateStoreControllerOptions } from '@pnpm/store.connection-manager';
5
+ import type { IncludedDependencies, PackageVulnerabilityAudit } from '@pnpm/types';
6
+ export type InstallDepsOptions = Pick<Config, 'allProjects' | 'allProjectsGraph' | 'autoInstallPeers' | 'bail' | 'bin' | 'catalogs' | 'catalogMode' | 'cleanupUnusedCatalogs' | 'cliOptions' | 'dedupePeerDependents' | 'depth' | 'dev' | 'enableGlobalVirtualStore' | 'virtualStoreOnly' | 'engineStrict' | 'excludeLinksFromLockfile' | 'global' | 'globalPnpmfile' | 'hooks' | 'ignoreCurrentSpecifiers' | 'ignorePnpmfile' | 'ignoreScripts' | 'optimisticRepeatInstall' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'production' | 'preferWorkspacePackages' | 'rawLocalConfig' | 'registries' | 'rootProjectManifestDir' | 'rootProjectManifest' | 'save' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'scriptsPrependNodePath' | 'scriptShell' | 'selectedProjectsGraph' | 'sideEffectsCache' | 'sideEffectsCacheReadonly' | 'sort' | 'sharedWorkspaceLockfile' | 'shellEmulator' | 'tag' | 'allowBuilds' | 'optional' | 'workspaceConcurrency' | 'workspaceDir' | 'workspacePackagePatterns' | 'extraEnv' | 'ignoreWorkspaceCycles' | 'disallowWorkspaceCycles' | 'configDependencies' | 'packageExtensions' | 'updateConfig'> & CreateStoreControllerOptions & {
7
+ argv: {
8
+ original: string[];
9
+ };
10
+ allowNew?: boolean;
11
+ forceFullResolution?: boolean;
12
+ frozenLockfileIfExists?: boolean;
13
+ include?: IncludedDependencies;
14
+ includeDirect?: IncludedDependencies;
15
+ latest?: boolean;
16
+ /**
17
+ * If specified, the installation will only be performed for comparison of the
18
+ * wanted lockfile. The wanted lockfile will not be updated on disk and no
19
+ * modules will be linked.
20
+ *
21
+ * The given callback is passed the wanted lockfile before installation and
22
+ * after. This allows functions to reasonably determine whether the wanted
23
+ * lockfile will change on disk after installation. The lockfile arguments
24
+ * passed to this callback should not be mutated.
25
+ */
26
+ lockfileCheck?: (prev: LockfileObject, next: LockfileObject) => void;
27
+ update?: boolean;
28
+ updateToLatest?: boolean;
29
+ updateMatching?: UpdateMatchingFunction;
30
+ updatePackageManifest?: boolean;
31
+ useBetaCli?: boolean;
32
+ recursive?: boolean;
33
+ dedupe?: boolean;
34
+ workspace?: boolean;
35
+ includeOnlyPackageFiles?: boolean;
36
+ fetchFullMetadata?: boolean;
37
+ pruneLockfileImporters?: boolean;
38
+ pnpmfile: string[];
39
+ packageVulnerabilityAudit?: PackageVulnerabilityAudit;
40
+ } & Partial<Pick<Config, 'pnpmHomeDir' | 'strictDepBuilds'>>;
41
+ export declare function installDeps(opts: InstallDepsOptions, params: string[]): Promise<void>;
@@ -0,0 +1,349 @@
1
+ import path from 'node:path';
2
+ import { buildProjects } from '@pnpm/building.after-install';
3
+ import { readProjectManifestOnly, tryReadProjectManifest, } from '@pnpm/cli.utils';
4
+ import { checkDepsStatus } from '@pnpm/deps.status';
5
+ import { PnpmError } from '@pnpm/error';
6
+ import { arrayOfWorkspacePackagesToMap } from '@pnpm/installing.context';
7
+ import { IgnoredBuildsError, install, mutateModulesInSingleProject, } from '@pnpm/installing.deps-installer';
8
+ import { globalInfo, logger } from '@pnpm/logger';
9
+ import { filterDependenciesByType } from '@pnpm/pkg-manifest.utils';
10
+ import { createStoreController } from '@pnpm/store.connection-manager';
11
+ import { filterProjectsBySelectorObjects } from '@pnpm/workspace.projects-filter';
12
+ import { createProjectsGraph } from '@pnpm/workspace.projects-graph';
13
+ import { findWorkspaceProjects } from '@pnpm/workspace.projects-reader';
14
+ import { sequenceGraph } from '@pnpm/workspace.projects-sorter';
15
+ import { updateWorkspaceState } from '@pnpm/workspace.state';
16
+ import { updateWorkspaceManifest } from '@pnpm/workspace.workspace-manifest-writer';
17
+ import { getPinnedVersion } from './getPinnedVersion.js';
18
+ import { getSaveType } from './getSaveType.js';
19
+ import { createMatcher, makeIgnorePatterns, matchDependencies, recursive, } from './recursive.js';
20
+ import { createWorkspaceSpecs, updateToWorkspacePackagesFromManifest } from './updateWorkspaceDependencies.js';
21
+ const OVERWRITE_UPDATE_OPTIONS = {
22
+ allowNew: true,
23
+ update: false,
24
+ };
25
+ export async function installDeps(opts, params) {
26
+ if (!opts.update && !opts.dedupe && params.length === 0 && opts.optimisticRepeatInstall) {
27
+ const { upToDate } = await checkDepsStatus({
28
+ ...opts,
29
+ ignoreFilteredInstallCache: true,
30
+ });
31
+ if (upToDate) {
32
+ globalInfo('Already up to date');
33
+ return;
34
+ }
35
+ }
36
+ if (opts.workspace) {
37
+ if (opts.latest) {
38
+ throw new PnpmError('BAD_OPTIONS', 'Cannot use --latest with --workspace simultaneously');
39
+ }
40
+ if (!opts.workspaceDir) {
41
+ throw new PnpmError('WORKSPACE_OPTION_OUTSIDE_WORKSPACE', '--workspace can only be used inside a workspace');
42
+ }
43
+ if (!opts.linkWorkspacePackages && !opts.saveWorkspaceProtocol) {
44
+ if (opts.rawLocalConfig['save-workspace-protocol'] === false) {
45
+ throw new PnpmError('BAD_OPTIONS', 'This workspace has link-workspace-packages turned off, \
46
+ so dependencies are linked from the workspace only when the workspace protocol is used. \
47
+ Either set link-workspace-packages to true or don\'t use the --no-save-workspace-protocol option \
48
+ when running add/update with the --workspace option');
49
+ }
50
+ else {
51
+ opts.saveWorkspaceProtocol = true;
52
+ }
53
+ }
54
+ // @ts-expect-error
55
+ opts['preserveWorkspaceProtocol'] = !opts.linkWorkspacePackages;
56
+ }
57
+ const store = await createStoreController(opts);
58
+ const includeDirect = opts.includeDirect ?? {
59
+ dependencies: true,
60
+ devDependencies: true,
61
+ optionalDependencies: true,
62
+ };
63
+ const forceHoistPattern = typeof opts.rawLocalConfig['hoist-pattern'] !== 'undefined' ||
64
+ typeof opts.rawLocalConfig['hoist'] !== 'undefined';
65
+ const forcePublicHoistPattern = typeof opts.rawLocalConfig['shamefully-hoist'] !== 'undefined' ||
66
+ typeof opts.rawLocalConfig['public-hoist-pattern'] !== 'undefined';
67
+ const allProjects = opts.allProjects ?? (opts.workspaceDir
68
+ ? await findWorkspaceProjects(opts.workspaceDir, { ...opts, patterns: opts.workspacePackagePatterns })
69
+ : []);
70
+ if (opts.workspaceDir) {
71
+ const selectedProjectsGraph = opts.selectedProjectsGraph ?? selectProjectByDir(allProjects, opts.dir);
72
+ if (selectedProjectsGraph != null) {
73
+ const sequencedGraph = sequenceGraph(selectedProjectsGraph);
74
+ // Check and warn if there are cyclic dependencies
75
+ if (!opts.ignoreWorkspaceCycles && !sequencedGraph.safe) {
76
+ const cyclicDependenciesInfo = sequencedGraph.cycles.length > 0
77
+ ? `: ${sequencedGraph.cycles.map(deps => deps.join(', ')).join('; ')}`
78
+ : '';
79
+ if (opts.disallowWorkspaceCycles) {
80
+ throw new PnpmError('DISALLOW_WORKSPACE_CYCLES', `There are cyclic workspace dependencies${cyclicDependenciesInfo}`);
81
+ }
82
+ logger.warn({
83
+ message: `There are cyclic workspace dependencies${cyclicDependenciesInfo}`,
84
+ prefix: opts.workspaceDir,
85
+ });
86
+ }
87
+ const allProjectsGraph = opts.allProjectsGraph ?? createProjectsGraph(allProjects, {
88
+ linkWorkspacePackages: Boolean(opts.linkWorkspacePackages),
89
+ }).graph;
90
+ await recursiveInstallThenUpdateWorkspaceState(allProjects, params, {
91
+ ...opts,
92
+ forceHoistPattern,
93
+ forcePublicHoistPattern,
94
+ preferredVersions: opts.packageVulnerabilityAudit ? preferNonvulnerablePackageVersions(opts.packageVulnerabilityAudit) : undefined,
95
+ allProjectsGraph,
96
+ selectedProjectsGraph,
97
+ storeControllerAndDir: store,
98
+ workspaceDir: opts.workspaceDir,
99
+ }, opts.update ? 'update' : (params.length === 0 ? 'install' : 'add'));
100
+ return;
101
+ }
102
+ }
103
+ // `pnpm install ""` is going to be just `pnpm install`
104
+ params = params.filter(Boolean);
105
+ const dir = opts.dir || process.cwd();
106
+ let workspacePackages;
107
+ if (opts.workspaceDir) {
108
+ workspacePackages = arrayOfWorkspacePackagesToMap(allProjects);
109
+ }
110
+ let { manifest, writeProjectManifest } = await tryReadProjectManifest(opts.dir, opts);
111
+ if (manifest === null) {
112
+ if (opts.update === true || params.length === 0) {
113
+ throw new PnpmError('NO_PKG_MANIFEST', `No package.json found in ${opts.dir}`);
114
+ }
115
+ manifest = {};
116
+ }
117
+ const installOpts = {
118
+ ...opts,
119
+ forceHoistPattern,
120
+ forcePublicHoistPattern,
121
+ // In case installation is done in a multi-package repository
122
+ // The dependencies should be built first,
123
+ // so ignoring scripts for now
124
+ ignoreScripts: !!workspacePackages || opts.ignoreScripts,
125
+ linkWorkspacePackagesDepth: opts.linkWorkspacePackages === 'deep' ? Infinity : opts.linkWorkspacePackages ? 0 : -1,
126
+ sideEffectsCacheRead: opts.sideEffectsCache ?? opts.sideEffectsCacheReadonly,
127
+ sideEffectsCacheWrite: opts.sideEffectsCache,
128
+ storeController: store.ctrl,
129
+ storeDir: store.dir,
130
+ workspacePackages,
131
+ preferredVersions: opts.packageVulnerabilityAudit ? preferNonvulnerablePackageVersions(opts.packageVulnerabilityAudit) : undefined,
132
+ };
133
+ let updateMatch;
134
+ let updatePackageManifest = opts.updatePackageManifest;
135
+ let updateMatching;
136
+ if (opts.update) {
137
+ if (params.length === 0) {
138
+ const ignoreDeps = opts.updateConfig?.ignoreDependencies;
139
+ if (ignoreDeps?.length) {
140
+ params = makeIgnorePatterns(ignoreDeps);
141
+ }
142
+ }
143
+ updateMatch = params.length ? createMatcher(params) : null;
144
+ }
145
+ else {
146
+ updateMatch = null;
147
+ }
148
+ if (opts.packageVulnerabilityAudit != null) {
149
+ updateMatch = null;
150
+ const { packageVulnerabilityAudit } = opts;
151
+ updateMatching = (pkgName, version) => version != null && packageVulnerabilityAudit.isVulnerable(pkgName, version);
152
+ }
153
+ if (updateMatch != null) {
154
+ params = matchDependencies(updateMatch, manifest, includeDirect);
155
+ if (params.length === 0) {
156
+ if (opts.latest)
157
+ return;
158
+ if (opts.depth === 0) {
159
+ throw new PnpmError('NO_PACKAGE_IN_DEPENDENCIES', 'None of the specified packages were found in the dependencies.');
160
+ }
161
+ // No direct dependencies matched, so we're updating indirect dependencies only
162
+ // Don't update package.json in this case, and limit updates to only matching dependencies
163
+ updatePackageManifest = false;
164
+ updateMatching = (pkgName) => updateMatch(pkgName) != null;
165
+ }
166
+ }
167
+ if (opts.update && opts.latest && (!params || (params.length === 0))) {
168
+ params = Object.keys(filterDependenciesByType(manifest, includeDirect));
169
+ }
170
+ if (opts.workspace) {
171
+ if (!params || (params.length === 0)) {
172
+ params = updateToWorkspacePackagesFromManifest(manifest, includeDirect, workspacePackages);
173
+ }
174
+ else {
175
+ params = createWorkspaceSpecs(params, workspacePackages);
176
+ }
177
+ }
178
+ if (params?.length) {
179
+ const mutatedProject = {
180
+ allowNew: opts.allowNew,
181
+ binsDir: opts.bin,
182
+ dependencySelectors: params,
183
+ manifest,
184
+ mutation: 'installSome',
185
+ peer: opts.savePeer,
186
+ pinnedVersion: getPinnedVersion(opts),
187
+ rootDir: opts.dir,
188
+ targetDependenciesField: getSaveType(opts),
189
+ };
190
+ const { updatedCatalogs, updatedProject, ignoredBuilds } = await mutateModulesInSingleProject(mutatedProject, installOpts);
191
+ if (opts.save !== false) {
192
+ await Promise.all([
193
+ writeProjectManifest(updatedProject.manifest),
194
+ updateWorkspaceManifest(opts.workspaceDir ?? opts.dir, {
195
+ updatedCatalogs,
196
+ cleanupUnusedCatalogs: opts.cleanupUnusedCatalogs,
197
+ allProjects: opts.allProjects,
198
+ }),
199
+ ]);
200
+ }
201
+ if (!opts.lockfileOnly) {
202
+ await updateWorkspaceState({
203
+ allProjects,
204
+ settings: opts,
205
+ workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
206
+ pnpmfiles: opts.pnpmfile,
207
+ filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
208
+ configDependencies: opts.configDependencies,
209
+ });
210
+ }
211
+ if (opts.strictDepBuilds && ignoredBuilds?.size) {
212
+ throw new IgnoredBuildsError(ignoredBuilds);
213
+ }
214
+ return;
215
+ }
216
+ const { updatedCatalogs, updatedManifest, ignoredBuilds } = await install(manifest, {
217
+ ...installOpts,
218
+ updatePackageManifest,
219
+ updateMatching,
220
+ });
221
+ if (opts.update === true && opts.save !== false) {
222
+ await Promise.all([
223
+ writeProjectManifest(updatedManifest),
224
+ updateWorkspaceManifest(opts.workspaceDir ?? opts.dir, {
225
+ updatedCatalogs,
226
+ cleanupUnusedCatalogs: opts.cleanupUnusedCatalogs,
227
+ allProjects,
228
+ }),
229
+ ]);
230
+ }
231
+ if (opts.strictDepBuilds && ignoredBuilds?.size) {
232
+ throw new IgnoredBuildsError(ignoredBuilds);
233
+ }
234
+ if (opts.linkWorkspacePackages && opts.workspaceDir) {
235
+ const { selectedProjectsGraph } = await filterProjectsBySelectorObjects(allProjects, [
236
+ {
237
+ excludeSelf: true,
238
+ includeDependencies: true,
239
+ parentDir: dir,
240
+ },
241
+ ], {
242
+ workspaceDir: opts.workspaceDir,
243
+ });
244
+ await recursiveInstallThenUpdateWorkspaceState(allProjects, [], {
245
+ ...opts,
246
+ ...OVERWRITE_UPDATE_OPTIONS,
247
+ allProjectsGraph: opts.allProjectsGraph,
248
+ selectedProjectsGraph,
249
+ workspaceDir: opts.workspaceDir, // Otherwise TypeScript doesn't understand that is not undefined
250
+ }, 'install');
251
+ if (opts.ignoreScripts)
252
+ return;
253
+ await buildProjects([
254
+ {
255
+ buildIndex: 0,
256
+ manifest: await readProjectManifestOnly(opts.dir, opts),
257
+ rootDir: opts.dir,
258
+ },
259
+ ], {
260
+ ...opts,
261
+ pending: true,
262
+ storeController: store.ctrl,
263
+ storeDir: store.dir,
264
+ skipIfHasSideEffectsCache: true,
265
+ });
266
+ }
267
+ else {
268
+ if (!opts.lockfileOnly) {
269
+ await updateWorkspaceState({
270
+ allProjects,
271
+ settings: opts,
272
+ workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
273
+ pnpmfiles: opts.pnpmfile,
274
+ filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
275
+ configDependencies: opts.configDependencies,
276
+ });
277
+ }
278
+ }
279
+ }
280
+ function selectProjectByDir(projects, searchedDir) {
281
+ const project = projects.find(({ rootDir }) => path.relative(rootDir, searchedDir) === '');
282
+ if (project == null)
283
+ return undefined;
284
+ return { [searchedDir]: { dependencies: [], package: project } };
285
+ }
286
+ async function recursiveInstallThenUpdateWorkspaceState(allProjects, params, opts, cmdFullName) {
287
+ const recursiveResult = await recursive(allProjects, params, opts, cmdFullName);
288
+ if (!opts.lockfileOnly) {
289
+ await updateWorkspaceState({
290
+ allProjects,
291
+ settings: opts,
292
+ workspaceDir: opts.workspaceDir,
293
+ pnpmfiles: opts.pnpmfile,
294
+ filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
295
+ configDependencies: opts.configDependencies,
296
+ });
297
+ }
298
+ return recursiveResult;
299
+ }
300
+ function severityStringToNumber(severity) {
301
+ switch (severity) {
302
+ case 'low': return 0;
303
+ case 'moderate': return 1;
304
+ case 'high': return 2;
305
+ case 'critical': return 3;
306
+ default: return -1;
307
+ }
308
+ }
309
+ function getVulnerabilityPenalty(severity) {
310
+ switch (severity) {
311
+ case 'low': return -1100; // 100 more than DIRECT_DEP_SELECTOR_WEIGHT from @pnpm/resolving.resolver-base
312
+ case 'moderate': return -2000;
313
+ case 'high': return -3000;
314
+ case 'critical': return -4000;
315
+ // Treat unrecognized severity as the lowest severity
316
+ default: return -1100;
317
+ }
318
+ }
319
+ function preferNonvulnerablePackageVersions(packageVulnerabilityAudit) {
320
+ const preferredVersions = {};
321
+ for (const [packageName, vulnerabilities] of packageVulnerabilityAudit.getVulnerabilities()) {
322
+ const vulnerableRanges = new Map();
323
+ for (const vuln of vulnerabilities) {
324
+ const existingSeverity = vulnerableRanges.get(vuln.versionRange);
325
+ if (existingSeverity == null) {
326
+ vulnerableRanges.set(vuln.versionRange, vuln.severity);
327
+ continue;
328
+ }
329
+ // Choose the highest severity for the same version range
330
+ if (severityStringToNumber(vuln.severity) > severityStringToNumber(existingSeverity)) {
331
+ vulnerableRanges.set(vuln.versionRange, vuln.severity);
332
+ }
333
+ }
334
+ const preferredVersionSelectors = {};
335
+ for (const [vulnRange, severity] of vulnerableRanges) {
336
+ if (vulnRange === '__proto__' || vulnRange === 'constructor' || vulnRange === 'prototype') {
337
+ // Prevent prototype pollution
338
+ continue;
339
+ }
340
+ preferredVersionSelectors[vulnRange] = {
341
+ selectorType: 'range',
342
+ weight: getVulnerabilityPenalty(severity),
343
+ };
344
+ }
345
+ preferredVersions[packageName] = preferredVersionSelectors;
346
+ }
347
+ return preferredVersions;
348
+ }
349
+ //# sourceMappingURL=installDeps.js.map
package/lib/link.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { type Config } from '@pnpm/config.reader';
2
+ import * as install from './install.js';
3
+ type LinkOpts = Pick<Config, 'bin' | 'cliOptions' | 'engineStrict' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'overrides' | 'saveDev' | 'saveOptional' | 'saveProd' | 'workspaceDir' | 'workspacePackagePatterns' | 'sharedWorkspaceLockfile'> & Partial<Pick<Config, 'linkWorkspacePackages'>> & install.InstallCommandOptions;
4
+ export declare const rcOptionsTypes: typeof cliOptionsTypes;
5
+ export declare function cliOptionsTypes(): Record<string, unknown>;
6
+ export declare const commandNames: string[];
7
+ export declare function help(): string;
8
+ export declare function handler(opts: LinkOpts, params?: string[]): Promise<void>;
9
+ export {};
package/lib/link.js ADDED
@@ -0,0 +1,130 @@
1
+ import path from 'node:path';
2
+ import { UNIVERSAL_OPTIONS } from '@pnpm/cli.common-cli-options-help';
3
+ import { docsUrl, tryReadProjectManifest, } from '@pnpm/cli.utils';
4
+ import { types as allTypes } from '@pnpm/config.reader';
5
+ import { writeSettings } from '@pnpm/config.writer';
6
+ import { PnpmError } from '@pnpm/error';
7
+ import { arrayOfWorkspacePackagesToMap } from '@pnpm/installing.context';
8
+ import { logger } from '@pnpm/logger';
9
+ import { DEPENDENCIES_FIELDS } from '@pnpm/types';
10
+ import { findWorkspaceProjects } from '@pnpm/workspace.projects-reader';
11
+ import normalize from 'normalize-path';
12
+ import { partition, pick } from 'ramda';
13
+ import { renderHelp } from 'render-help';
14
+ import { createProjectManifestWriter } from './createProjectManifestWriter.js';
15
+ import { getSaveType } from './getSaveType.js';
16
+ import * as install from './install.js';
17
+ // @ts-expect-error
18
+ const isWindows = process.platform === 'win32' || global['FAKE_WINDOWS'];
19
+ const isFilespec = isWindows ? /^(?:[./\\]|~\/|[a-z]:)/i : /^(?:[./]|~\/|[a-z]:)/i;
20
+ export const rcOptionsTypes = cliOptionsTypes;
21
+ export function cliOptionsTypes() {
22
+ return pick([
23
+ 'global-dir',
24
+ 'global',
25
+ 'only',
26
+ 'package-import-method',
27
+ 'production',
28
+ 'registry',
29
+ 'reporter',
30
+ 'save-dev',
31
+ 'save-exact',
32
+ 'save-optional',
33
+ 'save-prefix',
34
+ 'unsafe-perm',
35
+ ], allTypes);
36
+ }
37
+ export const commandNames = ['link', 'ln'];
38
+ export function help() {
39
+ return renderHelp({
40
+ aliases: ['ln'],
41
+ descriptionLists: [
42
+ {
43
+ title: 'Options',
44
+ list: UNIVERSAL_OPTIONS,
45
+ },
46
+ ],
47
+ url: docsUrl('link'),
48
+ usages: [
49
+ 'pnpm link <dir>',
50
+ ],
51
+ });
52
+ }
53
+ async function checkPeerDeps(linkCwdDir, opts) {
54
+ const { manifest } = await tryReadProjectManifest(linkCwdDir, opts);
55
+ if (manifest?.peerDependencies && Object.keys(manifest.peerDependencies).length > 0) {
56
+ const packageName = manifest.name ?? path.basename(linkCwdDir); // Assuming the name property exists in newManifest
57
+ const peerDeps = Object.entries(manifest.peerDependencies)
58
+ .map(([key, value]) => ` - ${key}@${String(value)}`)
59
+ .join(', ');
60
+ logger.warn({
61
+ message: `The package ${packageName}, which you have just pnpm linked, has the following peerDependencies specified in its package.json:
62
+
63
+ ${peerDeps}
64
+
65
+ The linked in dependency will not resolve the peer dependencies from the target node_modules.
66
+ This might cause issues in your project. To resolve this, you may use the "file:" protocol to reference the local dependency.`,
67
+ prefix: opts.dir,
68
+ });
69
+ }
70
+ }
71
+ export async function handler(opts, params) {
72
+ let workspacePackagesArr;
73
+ let workspacePackages;
74
+ if (opts.workspaceDir) {
75
+ workspacePackagesArr = await findWorkspaceProjects(opts.workspaceDir, {
76
+ ...opts,
77
+ patterns: opts.workspacePackagePatterns,
78
+ });
79
+ workspacePackages = arrayOfWorkspacePackagesToMap(workspacePackagesArr);
80
+ }
81
+ else {
82
+ workspacePackages = new Map();
83
+ }
84
+ const linkOpts = Object.assign(opts, {
85
+ targetDependenciesField: getSaveType(opts),
86
+ workspacePackages,
87
+ binsDir: opts.bin,
88
+ });
89
+ const writeProjectManifest = await createProjectManifestWriter(opts.rootProjectManifestDir);
90
+ if ((params == null) || (params.length === 0)) {
91
+ throw new PnpmError('LINK_BAD_PARAMS', 'You must provide a parameter. Usage: pnpm link <dir>');
92
+ }
93
+ const [pkgPaths, pkgNames] = partition((inp) => isFilespec.test(inp), params);
94
+ if (pkgNames.length > 0) {
95
+ throw new PnpmError('LINK_BAD_PARAMS', `Cannot link by package name. Use a relative or absolute path instead, e.g. "pnpm link ./${pkgNames[0]}"`);
96
+ }
97
+ const newManifest = opts.rootProjectManifest ?? {};
98
+ await Promise.all(pkgPaths.map(async (dir) => {
99
+ await addLinkToManifest(opts, newManifest, dir, opts.rootProjectManifestDir);
100
+ await checkPeerDeps(dir, opts);
101
+ }));
102
+ await writeProjectManifest(newManifest);
103
+ await install.handler({
104
+ ...linkOpts,
105
+ _calledFromLink: true,
106
+ frozenLockfileIfExists: false,
107
+ rootProjectManifest: newManifest,
108
+ });
109
+ }
110
+ async function addLinkToManifest(opts, manifest, linkedDepDir, manifestDir) {
111
+ const { manifest: linkedManifest } = await tryReadProjectManifest(linkedDepDir, opts);
112
+ const linkedPkgName = linkedManifest?.name ?? path.basename(linkedDepDir);
113
+ const linkedPkgSpec = `link:${normalize(path.relative(manifestDir, linkedDepDir))}`;
114
+ opts.overrides = {
115
+ ...opts.overrides,
116
+ [linkedPkgName]: linkedPkgSpec,
117
+ };
118
+ await writeSettings({
119
+ ...opts,
120
+ workspaceDir: opts.workspaceDir ?? opts.rootProjectManifestDir,
121
+ updatedSettings: {
122
+ overrides: opts.overrides,
123
+ },
124
+ });
125
+ if (DEPENDENCIES_FIELDS.every((depField) => manifest[depField]?.[linkedPkgName] == null)) {
126
+ manifest.dependencies = manifest.dependencies ?? {};
127
+ manifest.dependencies[linkedPkgName] = linkedPkgSpec;
128
+ }
129
+ }
130
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ export declare function getNodeExecPath(): Promise<string>;
@@ -0,0 +1,16 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import which from 'which';
3
+ export async function getNodeExecPath() {
4
+ try {
5
+ // The system default Node.js executable is preferred
6
+ // not the one used to run the pnpm CLI.
7
+ const nodeExecPath = await which('node');
8
+ return fs.realpath(nodeExecPath);
9
+ }
10
+ catch (err) { // eslint-disable-line
11
+ if (err['code'] !== 'ENOENT')
12
+ throw err;
13
+ return process.env.NODE ?? process.execPath;
14
+ }
15
+ }
16
+ //# sourceMappingURL=nodeExecPath.js.map
package/lib/prune.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import * as install from './install.js';
2
+ export declare const rcOptionsTypes: typeof cliOptionsTypes;
3
+ export declare function cliOptionsTypes(): Record<string, unknown>;
4
+ export declare const commandNames: string[];
5
+ export declare function help(): string;
6
+ export declare function handler(opts: install.InstallCommandOptions): Promise<void>;
package/lib/prune.js ADDED
@@ -0,0 +1,49 @@
1
+ import { OPTIONS, UNIVERSAL_OPTIONS } from '@pnpm/cli.common-cli-options-help';
2
+ import { docsUrl } from '@pnpm/cli.utils';
3
+ import { types as allTypes } from '@pnpm/config.reader';
4
+ import { pick } from 'ramda';
5
+ import { renderHelp } from 'render-help';
6
+ import * as install from './install.js';
7
+ export const rcOptionsTypes = cliOptionsTypes;
8
+ export function cliOptionsTypes() {
9
+ return pick([
10
+ 'dev',
11
+ 'optional',
12
+ 'production',
13
+ 'ignore-scripts',
14
+ ], allTypes);
15
+ }
16
+ export const commandNames = ['prune'];
17
+ export function help() {
18
+ return renderHelp({
19
+ description: 'Removes extraneous packages',
20
+ descriptionLists: [
21
+ {
22
+ title: 'Options',
23
+ list: [
24
+ {
25
+ description: 'Remove the packages specified in `devDependencies`',
26
+ name: '--prod',
27
+ },
28
+ {
29
+ description: 'Remove the packages specified in `optionalDependencies`',
30
+ name: '--no-optional',
31
+ },
32
+ OPTIONS.ignoreScripts,
33
+ ...UNIVERSAL_OPTIONS,
34
+ ],
35
+ },
36
+ ],
37
+ url: docsUrl('prune'),
38
+ usages: ['pnpm prune [--prod]'],
39
+ });
40
+ }
41
+ export async function handler(opts) {
42
+ return install.handler({
43
+ ...opts,
44
+ modulesCacheMaxAge: 0,
45
+ pruneDirectDependencies: true,
46
+ pruneStore: true,
47
+ });
48
+ }
49
+ //# sourceMappingURL=prune.js.map
@@ -0,0 +1,41 @@
1
+ import { type Config } from '@pnpm/config.reader';
2
+ import { type UpdateMatchingFunction } from '@pnpm/installing.deps-installer';
3
+ import type { PreferredVersions } from '@pnpm/resolving.resolver-base';
4
+ import { type CreateStoreControllerOptions } from '@pnpm/store.connection-manager';
5
+ import type { StoreController } from '@pnpm/store.controller';
6
+ import type { IncludedDependencies, Project, ProjectManifest, ProjectsGraph } from '@pnpm/types';
7
+ export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config, 'bail' | 'configDependencies' | 'dedupePeerDependents' | 'depth' | 'globalPnpmfile' | 'hoistPattern' | 'hooks' | 'ignorePnpmfile' | 'ignoreScripts' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'modulesDir' | 'allowBuilds' | 'rawLocalConfig' | 'registries' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'save' | 'saveCatalogName' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'sharedWorkspaceLockfile' | 'tag' | 'cleanupUnusedCatalogs' | 'packageConfigs' | 'updateConfig'> & {
8
+ include?: IncludedDependencies;
9
+ includeDirect?: IncludedDependencies;
10
+ latest?: boolean;
11
+ pending?: boolean;
12
+ workspace?: boolean;
13
+ allowNew?: boolean;
14
+ forceHoistPattern?: boolean;
15
+ forcePublicHoistPattern?: boolean;
16
+ ignoredPackages?: Set<string>;
17
+ update?: boolean;
18
+ updatePackageManifest?: boolean;
19
+ updateMatching?: UpdateMatchingFunction;
20
+ useBetaCli?: boolean;
21
+ allProjectsGraph: ProjectsGraph;
22
+ selectedProjectsGraph: ProjectsGraph;
23
+ preferredVersions?: PreferredVersions;
24
+ pruneDirectDependencies?: boolean;
25
+ pruneLockfileImporters?: boolean;
26
+ storeControllerAndDir?: {
27
+ ctrl: StoreController;
28
+ dir: string;
29
+ };
30
+ pnpmfile: string[];
31
+ } & Partial<Pick<Config, 'sort' | 'strictDepBuilds' | 'workspaceConcurrency'>> & Required<Pick<Config, 'workspaceDir'>>;
32
+ export type CommandFullName = 'install' | 'add' | 'remove' | 'update' | 'import';
33
+ export declare function recursive(allProjects: Project[], params: string[], opts: RecursiveOptions, cmdFullName: CommandFullName): Promise<boolean | string>;
34
+ export declare function matchDependencies(match: (input: string) => string | null, manifest: ProjectManifest, include: IncludedDependencies): string[];
35
+ export type UpdateDepsMatcher = (input: string) => string | null;
36
+ export declare function createMatcher(params: string[]): UpdateDepsMatcher;
37
+ export declare function parseUpdateParam(param: string): {
38
+ pattern: string;
39
+ versionSpec: string | undefined;
40
+ };
41
+ export declare function makeIgnorePatterns(ignoredDependencies: string[]): string[];