@pnpm/installing.commands 1100.9.0 → 1100.10.1
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/lib/add.js +9 -2
- package/lib/dedupe.js +3 -1
- package/lib/handleIgnoredBuilds.d.ts +1 -0
- package/lib/handleIgnoredBuilds.js +3 -1
- package/lib/import/index.js +14 -2
- package/lib/install.d.ts +2 -2
- package/lib/install.js +64 -1
- package/lib/installDeps.d.ts +4 -4
- package/lib/installDeps.js +27 -13
- package/lib/policyHandlers.js +10 -4
- package/lib/prune.js +1 -1
- package/lib/recursive.d.ts +18 -3
- package/lib/recursive.js +12 -9
- package/lib/remove.js +5 -0
- package/lib/update/index.js +10 -1
- package/package.json +52 -49
package/lib/add.js
CHANGED
|
@@ -49,6 +49,8 @@ export function rcOptionsTypes() {
|
|
|
49
49
|
'lockfile',
|
|
50
50
|
'modules-dir',
|
|
51
51
|
'network-concurrency',
|
|
52
|
+
'node-experimental-package-map',
|
|
53
|
+
'node-package-map-type',
|
|
52
54
|
'node-linker',
|
|
53
55
|
'noproxy',
|
|
54
56
|
'npm-path',
|
|
@@ -275,21 +277,26 @@ export async function handler(opts, params, commands) {
|
|
|
275
277
|
for (const pkg of opts.allowBuild) {
|
|
276
278
|
mergedAllowBuilds[pkg] = true;
|
|
277
279
|
}
|
|
278
|
-
|
|
280
|
+
await installDeps({
|
|
279
281
|
...opts,
|
|
280
282
|
allowBuilds: mergedAllowBuilds,
|
|
281
283
|
rebuildHandler: commands?.rebuild,
|
|
282
284
|
fetchFullMetadata: getFetchFullMetadata(opts),
|
|
283
285
|
include,
|
|
284
286
|
includeDirect: include,
|
|
287
|
+
// `--dry-run` is an `install`-only preview; never let a config-level
|
|
288
|
+
// `dry-run` turn `add` into a no-op check.
|
|
289
|
+
dryRun: false,
|
|
285
290
|
}, params);
|
|
291
|
+
return;
|
|
286
292
|
}
|
|
287
|
-
|
|
293
|
+
await installDeps({
|
|
288
294
|
...opts,
|
|
289
295
|
rebuildHandler: commands?.rebuild,
|
|
290
296
|
fetchFullMetadata: getFetchFullMetadata(opts),
|
|
291
297
|
include,
|
|
292
298
|
includeDirect: include,
|
|
299
|
+
dryRun: false,
|
|
293
300
|
}, params);
|
|
294
301
|
}
|
|
295
302
|
//# sourceMappingURL=add.js.map
|
package/lib/dedupe.js
CHANGED
|
@@ -49,13 +49,15 @@ export async function handler(opts, _params, commands) {
|
|
|
49
49
|
devDependencies: opts.dev !== false,
|
|
50
50
|
optionalDependencies: opts.optional !== false,
|
|
51
51
|
};
|
|
52
|
-
|
|
52
|
+
await installDeps({
|
|
53
53
|
...opts,
|
|
54
54
|
rebuildHandler: commands?.rebuild,
|
|
55
55
|
dedupe: true,
|
|
56
56
|
include,
|
|
57
57
|
includeDirect: include,
|
|
58
58
|
lockfileCheck: opts.check ? dedupeDiffCheck : undefined,
|
|
59
|
+
// `--dry-run` is an `install`-only preview; `dedupe` has its own `--check`.
|
|
60
|
+
dryRun: false,
|
|
59
61
|
}, []);
|
|
60
62
|
}
|
|
61
63
|
//# sourceMappingURL=dedupe.js.map
|
|
@@ -5,7 +5,9 @@ import { lexCompare } from '@pnpm/util.lex-comparator';
|
|
|
5
5
|
export async function handleIgnoredBuilds(opts, ignoredBuilds) {
|
|
6
6
|
if (!ignoredBuilds?.size)
|
|
7
7
|
return;
|
|
8
|
-
|
|
8
|
+
if (!opts.ignoreWorkspace) {
|
|
9
|
+
await writeIgnoredBuildsToAllowBuilds(opts, ignoredBuilds);
|
|
10
|
+
}
|
|
9
11
|
if (opts.strictDepBuilds) {
|
|
10
12
|
throw new IgnoredBuildsError(ignoredBuilds);
|
|
11
13
|
}
|
package/lib/import/index.js
CHANGED
|
@@ -12,8 +12,8 @@ import { findWorkspaceProjects } from '@pnpm/workspace.projects-reader';
|
|
|
12
12
|
import { sequenceGraph } from '@pnpm/workspace.projects-sorter';
|
|
13
13
|
import * as structUtils from '@yarnpkg/core/structUtils';
|
|
14
14
|
import { parse as parseYarnLockfile } from '@yarnpkg/lockfile';
|
|
15
|
-
import { parseSyml } from '@yarnpkg/parsers';
|
|
16
15
|
import { rimraf } from '@zkochan/rimraf';
|
|
16
|
+
import yaml from 'js-yaml';
|
|
17
17
|
import { loadJsonFile } from 'load-json-file';
|
|
18
18
|
import { map as mapValues } from 'ramda';
|
|
19
19
|
import { renderHelp } from 'render-help';
|
|
@@ -135,7 +135,7 @@ async function readYarnLockFile(dir) {
|
|
|
135
135
|
throw new PnpmError('YARN_LOCKFILE_NOT_FOUND', 'No yarn.lock found');
|
|
136
136
|
}
|
|
137
137
|
function parseYarn2Lock(lockFileContents) {
|
|
138
|
-
const parseYarnLock =
|
|
138
|
+
const parseYarnLock = parseYarn2Yaml(lockFileContents);
|
|
139
139
|
delete parseYarnLock.__metadata;
|
|
140
140
|
const dependencies = {};
|
|
141
141
|
const { parseDescriptor, parseRange } = structUtils;
|
|
@@ -151,6 +151,18 @@ function parseYarn2Lock(lockFileContents) {
|
|
|
151
151
|
type: YarnLockType.yarn2,
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
|
+
function parseYarn2Yaml(lockFileContents) {
|
|
155
|
+
const parseYarnLock = yaml.load(lockFileContents, {
|
|
156
|
+
schema: yaml.FAILSAFE_SCHEMA,
|
|
157
|
+
json: true,
|
|
158
|
+
});
|
|
159
|
+
if (parseYarnLock == null)
|
|
160
|
+
return {};
|
|
161
|
+
if (typeof parseYarnLock !== 'object' || Array.isArray(parseYarnLock)) {
|
|
162
|
+
throw new PnpmError('YARN_LOCKFILE_PARSE_FAILED', `Expected an indexed object, got ${Array.isArray(parseYarnLock) ? 'an array' : `a ${typeof parseYarnLock}`} instead. Does your file follow YAML's rules?`);
|
|
163
|
+
}
|
|
164
|
+
return parseYarnLock;
|
|
165
|
+
}
|
|
154
166
|
async function readNpmLockfile(dir) {
|
|
155
167
|
try {
|
|
156
168
|
return await loadJsonFile(path.join(dir, 'package-lock.json'));
|
package/lib/install.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare const shorthands: Record<string, string>;
|
|
|
7
7
|
export declare const commandNames: string[];
|
|
8
8
|
export declare const recursiveByDefault = true;
|
|
9
9
|
export declare function help(): string;
|
|
10
|
-
export type InstallCommandOptions = Pick<Config, 'autoInstallPeers' | 'bail' | 'bin' | 'catalogs' | 'configDependencies' | 'dedupeInjectedDeps' | 'dedupeDirectDeps' | 'dedupePeerDependents' | 'dedupePeers' | 'deployAllFiles' | 'depth' | 'dev' | 'enableGlobalVirtualStore' | 'engineStrict' | 'excludeLinksFromLockfile' | 'frozenLockfile' | 'global' | 'globalPnpmfile' | 'hoistPattern' | 'hoistingLimits' | 'publicHoistPattern' | 'ignorePnpmfile' | 'ignoreScripts' | 'injectWorkspacePackages' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'optimisticRepeatInstall' | 'modulesDir' | 'nodeLinker' | 'patchedDependencies' | 'preferFrozenLockfile' | 'preferWorkspacePackages' | 'production' | 'registries' | 'save' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveCatalogName' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'sideEffectsCache' | 'sideEffectsCacheReadonly' | 'sort' | 'sharedWorkspaceLockfile' | 'tag' | 'trustLockfile' | 'allowBuilds' | 'optional' | 'virtualStoreDir' | 'workspaceConcurrency' | 'workspaceDir' | 'workspacePackagePatterns' | 'extraEnv' | 'resolutionMode' | 'ignoreWorkspaceCycles' | 'disallowWorkspaceCycles' | 'updateConfig' | 'overrides' | 'packageExtensions' | 'pnprServer' | 'supportedArchitectures' | 'packageConfigs'> & Pick<ConfigContext, 'allProjects' | 'cliOptions' | 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'allProjectsGraph' | 'selectedProjectsGraph'> & CreateStoreControllerOptions & Partial<Pick<Config, 'globalPkgDir'>> & {
|
|
10
|
+
export type InstallCommandOptions = Pick<Config, 'autoInstallPeers' | 'bail' | 'bin' | 'catalogs' | 'configDependencies' | 'dedupeInjectedDeps' | 'dedupeDirectDeps' | 'dedupePeerDependents' | 'dedupePeers' | 'deployAllFiles' | 'depth' | 'dev' | 'dryRun' | 'enableGlobalVirtualStore' | 'engineStrict' | 'excludeLinksFromLockfile' | 'frozenLockfile' | 'global' | 'globalPnpmfile' | 'hoistPattern' | 'hoistingLimits' | 'publicHoistPattern' | 'ignorePnpmfile' | 'ignoreScripts' | 'injectWorkspacePackages' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'optimisticRepeatInstall' | 'modulesDir' | 'nodeLinker' | 'patchedDependencies' | 'preferFrozenLockfile' | 'preferWorkspacePackages' | 'production' | 'registries' | 'save' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveCatalogName' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'sideEffectsCache' | 'sideEffectsCacheReadonly' | 'sort' | 'sharedWorkspaceLockfile' | 'tag' | 'trustLockfile' | 'allowBuilds' | 'optional' | 'virtualStoreDir' | 'workspaceConcurrency' | 'workspaceDir' | 'workspacePackagePatterns' | 'extraEnv' | 'resolutionMode' | 'ignoreWorkspaceCycles' | 'disallowWorkspaceCycles' | 'updateConfig' | 'overrides' | 'packageExtensions' | 'pnprServer' | 'supportedArchitectures' | 'packageConfigs'> & Pick<ConfigContext, 'allProjects' | 'cliOptions' | 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'allProjectsGraph' | 'selectedProjectsGraph'> & CreateStoreControllerOptions & Partial<Pick<Config, 'globalPkgDir'>> & {
|
|
11
11
|
argv: {
|
|
12
12
|
cooked?: string[];
|
|
13
13
|
original: string[];
|
|
@@ -30,4 +30,4 @@ export type InstallCommandOptions = Pick<Config, 'autoInstallPeers' | 'bail' | '
|
|
|
30
30
|
} & Partial<Pick<Config, 'ci' | 'modulesCacheMaxAge' | 'pnpmHomeDir' | 'preferWorkspacePackages' | 'strictDepBuilds' | 'useLockfile' | 'symlink'>>;
|
|
31
31
|
export declare function handler(opts: InstallCommandOptions & {
|
|
32
32
|
_calledFromLink?: boolean;
|
|
33
|
-
}, _params?: string[], commands?: CommandHandlerMap): Promise<void>;
|
|
33
|
+
}, _params?: string[], commands?: CommandHandlerMap): Promise<void | string>;
|
package/lib/install.js
CHANGED
|
@@ -3,6 +3,8 @@ import { docsUrl } from '@pnpm/cli.utils';
|
|
|
3
3
|
import { types as allTypes } from '@pnpm/config.reader';
|
|
4
4
|
import { WANTED_LOCKFILE } from '@pnpm/constants';
|
|
5
5
|
import { PnpmError } from '@pnpm/error';
|
|
6
|
+
import { calcDedupeCheckIssues, countDedupeCheckIssues } from '@pnpm/installing.dedupe.check';
|
|
7
|
+
import { renderDedupeCheckIssues } from '@pnpm/installing.dedupe.issues-renderer';
|
|
6
8
|
import { pick } from 'ramda';
|
|
7
9
|
import { renderHelp } from 'render-help';
|
|
8
10
|
import { getFetchFullMetadata } from './getFetchFullMetadata.js';
|
|
@@ -41,6 +43,8 @@ export function rcOptionsTypes() {
|
|
|
41
43
|
'merge-git-branch-lockfiles-branch-pattern',
|
|
42
44
|
'modules-dir',
|
|
43
45
|
'network-concurrency',
|
|
46
|
+
'node-experimental-package-map',
|
|
47
|
+
'node-package-map-type',
|
|
44
48
|
'node-linker',
|
|
45
49
|
'noproxy',
|
|
46
50
|
'package-import-method',
|
|
@@ -79,6 +83,7 @@ export function rcOptionsTypes() {
|
|
|
79
83
|
export const cliOptionsTypes = () => ({
|
|
80
84
|
...rcOptionsTypes(),
|
|
81
85
|
...pick(['force'], allTypes),
|
|
86
|
+
'dry-run': Boolean,
|
|
82
87
|
'fix-lockfile': Boolean,
|
|
83
88
|
'update-checksums': Boolean,
|
|
84
89
|
'resolution-only': Boolean,
|
|
@@ -128,6 +133,10 @@ For options that may be used with `-r`, see "pnpm help recursive"',
|
|
|
128
133
|
description: 'Skip reinstall if the workspace state is up-to-date',
|
|
129
134
|
name: '--optimistic-repeat-install',
|
|
130
135
|
},
|
|
136
|
+
{
|
|
137
|
+
description: 'Report what an install would change without writing anything to disk (no lockfile, no node_modules). Resolution still runs against the registry.',
|
|
138
|
+
name: '--dry-run',
|
|
139
|
+
},
|
|
131
140
|
{
|
|
132
141
|
description: '`optionalDependencies` are not installed',
|
|
133
142
|
name: '--no-optional',
|
|
@@ -270,6 +279,18 @@ Install all optionalDependencies even when they don\'t satisfy the current envir
|
|
|
270
279
|
description: 'Re-runs resolution: useful for printing out peer dependency issues',
|
|
271
280
|
name: '--resolution-only',
|
|
272
281
|
},
|
|
282
|
+
{
|
|
283
|
+
description: 'Override CPU architecture of native modules to install. Acceptable values are the same as the `cpu` field of `package.json` (from `process.arch`)',
|
|
284
|
+
name: '--cpu <arch>',
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
description: 'Override OS of native modules to install. Acceptable values are the same as the `os` field of `package.json` (from `process.platform`)',
|
|
288
|
+
name: '--os <os>',
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
description: 'Override libc of native modules to install. Acceptable values are the same as the `libc` field of `package.json`',
|
|
292
|
+
name: '--libc <libc>',
|
|
293
|
+
},
|
|
273
294
|
...UNIVERSAL_OPTIONS,
|
|
274
295
|
],
|
|
275
296
|
},
|
|
@@ -304,6 +325,48 @@ export async function handler(opts, _params, commands) {
|
|
|
304
325
|
installDepsOptions.lockfileOnly = true;
|
|
305
326
|
installDepsOptions.forceFullResolution = true;
|
|
306
327
|
}
|
|
307
|
-
|
|
328
|
+
if (opts.dryRun) {
|
|
329
|
+
return dryRunInstall(installDepsOptions, opts);
|
|
330
|
+
}
|
|
331
|
+
await installDeps(installDepsOptions, []);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Runs a full resolution but writes nothing to disk (no lockfile, no
|
|
335
|
+
* `node_modules`), then reports what a real install would change. Exits
|
|
336
|
+
* successfully regardless of whether changes were found — mirroring the
|
|
337
|
+
* preview semantics of `npm install --dry-run`.
|
|
338
|
+
*/
|
|
339
|
+
async function dryRunInstall(installDepsOptions, opts) {
|
|
340
|
+
if (opts.pnprServer) {
|
|
341
|
+
throw new PnpmError('CONFIG_CONFLICT_DRY_RUN_WITH_PNPR_SERVER', 'Cannot use --dry-run with a configured pnpr server because the pnpr install path resolves and links through the server');
|
|
342
|
+
}
|
|
343
|
+
// `dryRun` makes the installer resolve fully and return the before/after
|
|
344
|
+
// wanted lockfile without writing anything. `lockfileOnly` keeps it from
|
|
345
|
+
// materializing `node_modules` and skips the metadata cache (resolution
|
|
346
|
+
// skips fetching). The optimistic fast path is disabled so resolution
|
|
347
|
+
// always runs.
|
|
348
|
+
installDepsOptions.optimisticRepeatInstall = false;
|
|
349
|
+
installDepsOptions.lockfileOnly = true;
|
|
350
|
+
installDepsOptions.dryRun = true;
|
|
351
|
+
const dryRunResult = await installDeps(installDepsOptions, []);
|
|
352
|
+
if (dryRunResult == null) {
|
|
353
|
+
// No comparison was produced — this install configuration's resolve path
|
|
354
|
+
// doesn't surface the dry-run lockfiles (e.g. a workspace without a
|
|
355
|
+
// shared lockfile). Report that explicitly instead of claiming "up to
|
|
356
|
+
// date", but keep `--dry-run`'s exit-0 contract.
|
|
357
|
+
return 'Dry run complete. Could not compute the changes for this install configuration (no shared lockfile to compare).';
|
|
358
|
+
}
|
|
359
|
+
return renderDryRunReport(dryRunResult);
|
|
360
|
+
}
|
|
361
|
+
function renderDryRunReport(dryRunResult) {
|
|
362
|
+
const issues = calcDedupeCheckIssues(dryRunResult.originalLockfile, dryRunResult.wantedLockfile, { includeImporterSpecifiers: true });
|
|
363
|
+
if (countDedupeCheckIssues(issues) === 0) {
|
|
364
|
+
return `Dry run complete. ${WANTED_LOCKFILE} is up to date; a real install would make no changes.`;
|
|
365
|
+
}
|
|
366
|
+
return [
|
|
367
|
+
'Dry run complete. A real install would make the following changes (nothing was written to disk):',
|
|
368
|
+
'',
|
|
369
|
+
renderDedupeCheckIssues(issues),
|
|
370
|
+
].join('\n');
|
|
308
371
|
}
|
|
309
372
|
//# sourceMappingURL=install.js.map
|
package/lib/installDeps.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { CommandHandler } from '@pnpm/cli.command';
|
|
2
2
|
import type { Config, ConfigContext } from '@pnpm/config.reader';
|
|
3
|
-
import { type UpdateMatchingFunction } from '@pnpm/installing.deps-installer';
|
|
3
|
+
import { type DryRunInstallResult, type UpdateMatchingFunction } from '@pnpm/installing.deps-installer';
|
|
4
4
|
import type { LockfileObject } from '@pnpm/lockfile.types';
|
|
5
5
|
import { type CreateStoreControllerOptions } from '@pnpm/store.connection-manager';
|
|
6
6
|
import type { IncludedDependencies, PackageVulnerabilityAudit } from '@pnpm/types';
|
|
7
|
-
export type InstallDepsOptions = Pick<Config, 'autoInstallPeers' | 'bail' | 'bin' | 'catalogs' | 'catalogMode' | 'cleanupUnusedCatalogs' | 'dedupePeerDependents' | 'dedupePeers' | 'depth' | 'dev' | 'enableGlobalVirtualStore' | 'virtualStoreOnly' | 'engineStrict' | 'excludeLinksFromLockfile' | 'global' | 'globalPnpmfile' | 'ignoreCurrentSpecifiers' | 'ignorePnpmfile' | 'ignoreScripts' | 'optimisticRepeatInstall' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'pnprServer' | 'production' | 'preferWorkspacePackages' | 'registries' | 'runtime' | 'runtimeOnFail' | 'save' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'scriptsPrependNodePath' | 'scriptShell' | 'sideEffectsCache' | 'sideEffectsCacheReadonly' | 'sort' | 'sharedWorkspaceLockfile' | 'shellEmulator' | 'tag' | 'trustLockfile' | 'allowBuilds' | 'optional' | 'workspaceConcurrency' | 'workspaceDir' | 'workspacePackagePatterns' | 'extraEnv' | 'ignoreWorkspaceCycles' | 'disallowWorkspaceCycles' | 'configDependencies' | 'packageExtensions' | 'updateConfig' | 'virtualStoreDirMaxLength'> & Pick<ConfigContext, 'allProjects' | 'allProjectsGraph' | 'cliOptions' | 'hooks' | 'rootProjectManifestDir' | 'rootProjectManifest' | 'selectedProjectsGraph'> & Partial<Pick<Config, 'ci'>> & CreateStoreControllerOptions & {
|
|
7
|
+
export type InstallDepsOptions = Pick<Config, 'autoInstallPeers' | 'bail' | 'bin' | 'catalogs' | 'catalogMode' | 'cleanupUnusedCatalogs' | 'dedupePeerDependents' | 'dedupePeers' | 'depth' | 'dev' | 'enableGlobalVirtualStore' | 'virtualStoreOnly' | 'engineStrict' | 'excludeLinksFromLockfile' | 'global' | 'globalPnpmfile' | 'ignoreCurrentSpecifiers' | 'ignorePnpmfile' | 'ignoreScripts' | 'optimisticRepeatInstall' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'pnprServer' | 'production' | 'preferWorkspacePackages' | 'registries' | 'runtime' | 'runtimeOnFail' | 'save' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'scriptsPrependNodePath' | 'scriptShell' | 'sideEffectsCache' | 'sideEffectsCacheReadonly' | 'sort' | 'sharedWorkspaceLockfile' | 'shellEmulator' | 'tag' | 'trustLockfile' | 'allowBuilds' | 'optional' | 'workspaceConcurrency' | 'workspaceDir' | 'workspacePackagePatterns' | 'extraEnv' | 'ignoreWorkspace' | 'ignoreWorkspaceCycles' | 'disallowWorkspaceCycles' | 'configDependencies' | 'packageExtensions' | 'updateConfig' | 'virtualStoreDirMaxLength'> & Pick<ConfigContext, 'allProjects' | 'allProjectsGraph' | 'cliOptions' | 'hooks' | 'rootProjectManifestDir' | 'rootProjectManifest' | 'selectedProjectsGraph'> & Partial<Pick<Config, 'ci'>> & CreateStoreControllerOptions & {
|
|
8
8
|
argv: {
|
|
9
9
|
cooked?: string[];
|
|
10
10
|
original: string[];
|
|
@@ -48,5 +48,5 @@ export type InstallDepsOptions = Pick<Config, 'autoInstallPeers' | 'bail' | 'bin
|
|
|
48
48
|
* subcommand — see `runPacquet.ts`'s `noRuntime` opt.
|
|
49
49
|
*/
|
|
50
50
|
isInstallCommand?: boolean;
|
|
51
|
-
} & Partial<Pick<Config, 'pnpmHomeDir' | 'strictDepBuilds' | 'useLockfile' | 'useGitBranchLockfile'>>;
|
|
52
|
-
export declare function installDeps(opts: InstallDepsOptions, params: string[]): Promise<
|
|
51
|
+
} & Partial<Pick<Config, 'dryRun' | 'pnpmHomeDir' | 'strictDepBuilds' | 'useLockfile' | 'useGitBranchLockfile' | 'mergeGitBranchLockfiles'>>;
|
|
52
|
+
export declare function installDeps(opts: InstallDepsOptions, params: string[]): Promise<DryRunInstallResult | undefined>;
|
package/lib/installDeps.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { buildProjects } from '@pnpm/building.after-install';
|
|
3
|
+
import { mergeCatalogs } from '@pnpm/catalogs.config';
|
|
3
4
|
import { readProjectManifestOnly, tryReadProjectManifest, } from '@pnpm/cli.utils';
|
|
4
5
|
import { checkDepsStatus } from '@pnpm/deps.status';
|
|
5
6
|
import { PnpmError } from '@pnpm/error';
|
|
@@ -32,6 +33,7 @@ export async function installDeps(opts, params) {
|
|
|
32
33
|
const { upToDate, wantedLockfileToRestore } = await checkDepsStatus({
|
|
33
34
|
...opts,
|
|
34
35
|
ignoreFilteredInstallCache: true,
|
|
36
|
+
treatLocalFileDepsAsOutdated: true,
|
|
35
37
|
});
|
|
36
38
|
if (upToDate && await restoreWantedLockfileIfMissing(wantedLockfileToRestore, opts)) {
|
|
37
39
|
if (opts.hooks?.customResolvers?.some(r => r.shouldRefreshResolution)) {
|
|
@@ -131,7 +133,7 @@ export async function installDeps(opts, params) {
|
|
|
131
133
|
const allProjectsGraph = opts.allProjectsGraph ?? createProjectsGraph(allProjects, {
|
|
132
134
|
linkWorkspacePackages: Boolean(opts.linkWorkspacePackages),
|
|
133
135
|
}).graph;
|
|
134
|
-
|
|
136
|
+
return recursiveInstallThenUpdateWorkspaceState(allProjects, params, {
|
|
135
137
|
...opts,
|
|
136
138
|
preferredVersions: opts.packageVulnerabilityAudit ? preferNonvulnerablePackageVersions(opts.packageVulnerabilityAudit) : undefined,
|
|
137
139
|
allProjectsGraph,
|
|
@@ -140,7 +142,6 @@ export async function installDeps(opts, params) {
|
|
|
140
142
|
workspaceDir: opts.workspaceDir,
|
|
141
143
|
runPacquet,
|
|
142
144
|
}, opts.update ? 'update' : (params.length === 0 ? 'install' : 'add'));
|
|
143
|
-
return;
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
// `pnpm install ""` is going to be just `pnpm install`
|
|
@@ -241,8 +242,8 @@ export async function installDeps(opts, params) {
|
|
|
241
242
|
rootDir: opts.dir,
|
|
242
243
|
targetDependenciesField: getSaveType(opts),
|
|
243
244
|
};
|
|
244
|
-
const { updatedCatalogs, updatedProject, ignoredBuilds, resolutionPolicyViolations } = await mutateModulesInSingleProject(mutatedProject, installOpts);
|
|
245
|
-
if (opts.save !== false) {
|
|
245
|
+
const { updatedCatalogs, updatedProject, ignoredBuilds, resolutionPolicyViolations, dryRunResult } = await mutateModulesInSingleProject(mutatedProject, installOpts);
|
|
246
|
+
if (opts.save !== false && !opts.dryRun) {
|
|
246
247
|
// Only pick entries when we'll actually persist. Otherwise the
|
|
247
248
|
// info log would claim we added entries the workspace manifest
|
|
248
249
|
// never saw, and the next install would re-prompt or fail
|
|
@@ -261,7 +262,7 @@ export async function installDeps(opts, params) {
|
|
|
261
262
|
if (!opts.lockfileOnly) {
|
|
262
263
|
await updateWorkspaceState({
|
|
263
264
|
allProjects,
|
|
264
|
-
settings: opts,
|
|
265
|
+
settings: withUpdatedCatalogs(opts, updatedCatalogs),
|
|
265
266
|
workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
|
|
266
267
|
pnpmfiles: opts.pnpmfile,
|
|
267
268
|
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
|
@@ -269,9 +270,9 @@ export async function installDeps(opts, params) {
|
|
|
269
270
|
});
|
|
270
271
|
}
|
|
271
272
|
await handleIgnoredBuilds(opts, ignoredBuilds);
|
|
272
|
-
return;
|
|
273
|
+
return dryRunResult;
|
|
273
274
|
}
|
|
274
|
-
const { updatedCatalogs, updatedManifest, ignoredBuilds, resolutionPolicyViolations } = await install(manifest, {
|
|
275
|
+
const { updatedCatalogs, updatedManifest, ignoredBuilds, resolutionPolicyViolations, dryRunResult } = await install(manifest, {
|
|
275
276
|
...installOpts,
|
|
276
277
|
updatePackageManifest,
|
|
277
278
|
updateMatching,
|
|
@@ -280,7 +281,7 @@ export async function installDeps(opts, params) {
|
|
|
280
281
|
// from this install" — both package.json and the workspace manifest.
|
|
281
282
|
// Skip the pick so the info log doesn't claim entries were added that
|
|
282
283
|
// were never written; the next install will resurface them.
|
|
283
|
-
if (opts.save !== false) {
|
|
284
|
+
if (opts.save !== false && !opts.dryRun) {
|
|
284
285
|
const policyUpdates = policyHandlers?.pickManifestUpdates(resolutionPolicyViolations);
|
|
285
286
|
if (opts.update === true) {
|
|
286
287
|
await Promise.all([
|
|
@@ -319,7 +320,7 @@ export async function installDeps(opts, params) {
|
|
|
319
320
|
selectedProjectsGraph,
|
|
320
321
|
workspaceDir: opts.workspaceDir, // Otherwise TypeScript doesn't understand that is not undefined
|
|
321
322
|
runPacquet,
|
|
322
|
-
}, 'install');
|
|
323
|
+
}, 'install', updatedCatalogs);
|
|
323
324
|
if (opts.ignoreScripts)
|
|
324
325
|
return;
|
|
325
326
|
await buildProjects([
|
|
@@ -340,7 +341,7 @@ export async function installDeps(opts, params) {
|
|
|
340
341
|
if (!opts.lockfileOnly) {
|
|
341
342
|
await updateWorkspaceState({
|
|
342
343
|
allProjects,
|
|
343
|
-
settings: opts,
|
|
344
|
+
settings: withUpdatedCatalogs(opts, updatedCatalogs),
|
|
344
345
|
workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
|
|
345
346
|
pnpmfiles: opts.pnpmfile,
|
|
346
347
|
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
|
@@ -348,6 +349,7 @@ export async function installDeps(opts, params) {
|
|
|
348
349
|
});
|
|
349
350
|
}
|
|
350
351
|
}
|
|
352
|
+
return dryRunResult;
|
|
351
353
|
}
|
|
352
354
|
function selectProjectByDir(projects, searchedDir) {
|
|
353
355
|
const project = projects.find(({ rootDir }) => path.relative(rootDir, searchedDir) === '');
|
|
@@ -355,19 +357,31 @@ function selectProjectByDir(projects, searchedDir) {
|
|
|
355
357
|
return undefined;
|
|
356
358
|
return { [project.rootDir]: { dependencies: [], package: project } };
|
|
357
359
|
}
|
|
358
|
-
async function recursiveInstallThenUpdateWorkspaceState(allProjects, params, opts, cmdFullName) {
|
|
360
|
+
async function recursiveInstallThenUpdateWorkspaceState(allProjects, params, opts, cmdFullName, updatedCatalogs) {
|
|
359
361
|
const recursiveResult = await recursive(allProjects, params, opts, cmdFullName);
|
|
360
362
|
if (!opts.lockfileOnly) {
|
|
361
363
|
await updateWorkspaceState({
|
|
362
364
|
allProjects,
|
|
363
|
-
settings: opts,
|
|
365
|
+
settings: withUpdatedCatalogs(opts, updatedCatalogs, recursiveResult.updatedCatalogs),
|
|
364
366
|
workspaceDir: opts.workspaceDir,
|
|
365
367
|
pnpmfiles: opts.pnpmfile,
|
|
366
368
|
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
|
367
369
|
configDependencies: opts.configDependencies,
|
|
368
370
|
});
|
|
369
371
|
}
|
|
370
|
-
return recursiveResult;
|
|
372
|
+
return recursiveResult.dryRunResult;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Folds the catalog entries written to `pnpm-workspace.yaml` during this
|
|
376
|
+
* install into the catalogs read at startup. The workspace state cache records
|
|
377
|
+
* these so a later install detects when a catalog entry was reverted; without
|
|
378
|
+
* this, the cache would keep the stale pre-install catalogs and report
|
|
379
|
+
* "Already up to date" even though the manifest changed.
|
|
380
|
+
*/
|
|
381
|
+
function withUpdatedCatalogs(settings, ...updatedCatalogs) {
|
|
382
|
+
if (updatedCatalogs.every((catalogs) => catalogs == null))
|
|
383
|
+
return settings;
|
|
384
|
+
return { ...settings, catalogs: mergeCatalogs(settings.catalogs, ...updatedCatalogs) };
|
|
371
385
|
}
|
|
372
386
|
function severityStringToNumber(severity) {
|
|
373
387
|
switch (severity) {
|
package/lib/policyHandlers.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import { mergePackageVersionSpecs } from '@pnpm/config.version-policy';
|
|
2
3
|
import { PnpmError } from '@pnpm/error';
|
|
3
4
|
import { globalInfo } from '@pnpm/logger';
|
|
4
5
|
import { MINIMUM_RELEASE_AGE_VIOLATION_CODE } from '@pnpm/resolving.npm-resolver';
|
|
@@ -120,7 +121,12 @@ function pickImmatureEntries(violations, promptRequired) {
|
|
|
120
121
|
const immature = filterImmatureViolations(violations);
|
|
121
122
|
if (immature.length === 0)
|
|
122
123
|
return undefined;
|
|
123
|
-
|
|
124
|
+
// Combine into the canonical per-package form the workspace writer
|
|
125
|
+
// persists (`name@v1 || v2`), so the logged count and list match the
|
|
126
|
+
// entries that actually land in pnpm-workspace.yaml even when multiple
|
|
127
|
+
// immature versions belong to the same package. The pre-sort keeps the
|
|
128
|
+
// cross-package order stable regardless of resolution order.
|
|
129
|
+
const entries = mergePackageVersionSpecs(immature.map((v) => `${v.name}@${v.version}`).sort());
|
|
124
130
|
// Strict-mode picks already passed through the approval prompt, so
|
|
125
131
|
// the log here only confirms what was persisted. Loose-mode picks
|
|
126
132
|
// haven't been announced anywhere else, so the same log doubles as
|
|
@@ -128,9 +134,9 @@ function pickImmatureEntries(violations, promptRequired) {
|
|
|
128
134
|
const reason = promptRequired
|
|
129
135
|
? '(approved at the prompt)'
|
|
130
136
|
: '(set minimumReleaseAgeStrict to true to gate these updates with a prompt)';
|
|
131
|
-
globalInfo(`Added ${
|
|
132
|
-
`${reason}:\n ${
|
|
133
|
-
return
|
|
137
|
+
globalInfo(`Added ${entries.length} ${entries.length === 1 ? 'entry' : 'entries'} to minimumReleaseAgeExclude in pnpm-workspace.yaml ` +
|
|
138
|
+
`${reason}:\n ${entries.join('\n ')}`);
|
|
139
|
+
return entries;
|
|
134
140
|
}
|
|
135
141
|
function failOnImmature(immature) {
|
|
136
142
|
const sorted = [...immature].sort((a, b) => `${a.name}@${a.version}`.localeCompare(`${b.name}@${b.version}`));
|
package/lib/prune.js
CHANGED
package/lib/recursive.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import type { Catalogs } from '@pnpm/catalogs.types';
|
|
1
2
|
import type { CommandHandler } from '@pnpm/cli.command';
|
|
2
3
|
import { type Config, type ConfigContext } from '@pnpm/config.reader';
|
|
3
|
-
import { type UpdateMatchingFunction } from '@pnpm/installing.deps-installer';
|
|
4
|
+
import { type DryRunInstallResult, type UpdateMatchingFunction } from '@pnpm/installing.deps-installer';
|
|
4
5
|
import type { PreferredVersions } from '@pnpm/resolving.resolver-base';
|
|
5
6
|
import type { ResolutionVerifier } from '@pnpm/resolving.resolver-base';
|
|
6
7
|
import { type CreateStoreControllerOptions } from '@pnpm/store.connection-manager';
|
|
7
8
|
import type { StoreController } from '@pnpm/store.controller';
|
|
8
9
|
import type { IncludedDependencies, Project, ProjectManifest, ProjectsGraph } from '@pnpm/types';
|
|
9
|
-
export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config, 'bail' | 'configDependencies' | 'dedupePeerDependents' | 'dedupePeers' | 'depth' | 'globalPnpmfile' | 'hoistPattern' | 'hoistingLimits' | 'ignorePnpmfile' | 'ignoreScripts' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'modulesDir' | 'pnprServer' | 'allowBuilds' | 'registries' | 'runtime' | 'save' | 'saveCatalogName' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'sharedWorkspaceLockfile' | 'tag' | 'trustLockfile' | 'cleanupUnusedCatalogs' | 'packageConfigs' | 'updateConfig'> & Pick<ConfigContext, 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir'> & {
|
|
10
|
+
export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config, 'bail' | 'configDependencies' | 'dedupePeerDependents' | 'dedupePeers' | 'depth' | 'dryRun' | 'globalPnpmfile' | 'hoistPattern' | 'hoistingLimits' | 'ignorePnpmfile' | 'ignoreScripts' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'modulesDir' | 'pnprServer' | 'allowBuilds' | 'registries' | 'runtime' | 'save' | 'saveCatalogName' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'sharedWorkspaceLockfile' | 'tag' | 'trustLockfile' | 'cleanupUnusedCatalogs' | 'packageConfigs' | 'updateConfig'> & Pick<ConfigContext, 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir'> & {
|
|
10
11
|
rebuildHandler?: CommandHandler;
|
|
11
12
|
include?: IncludedDependencies;
|
|
12
13
|
includeDirect?: IncludedDependencies;
|
|
@@ -45,7 +46,21 @@ export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config, 'bail
|
|
|
45
46
|
};
|
|
46
47
|
} & Partial<Pick<Config, 'ci' | 'sort' | 'strictDepBuilds' | 'workspaceConcurrency'>> & Required<Pick<Config, 'workspaceDir'>>;
|
|
47
48
|
export type CommandFullName = 'install' | 'add' | 'remove' | 'update' | 'import';
|
|
48
|
-
export
|
|
49
|
+
export interface RecursiveResult {
|
|
50
|
+
passed: boolean | string;
|
|
51
|
+
/**
|
|
52
|
+
* Catalog entries written to `pnpm-workspace.yaml` during this install.
|
|
53
|
+
* The caller folds these into the catalogs recorded in the workspace state
|
|
54
|
+
* cache so that reverting a catalog entry is detected as an outdated state.
|
|
55
|
+
*/
|
|
56
|
+
updatedCatalogs?: Catalogs;
|
|
57
|
+
/**
|
|
58
|
+
* Present only for a `dryRun` install over a shared workspace lockfile:
|
|
59
|
+
* the before/after wanted lockfiles for the caller to diff.
|
|
60
|
+
*/
|
|
61
|
+
dryRunResult?: DryRunInstallResult;
|
|
62
|
+
}
|
|
63
|
+
export declare function recursive(allProjects: Project[], params: string[], opts: RecursiveOptions, cmdFullName: CommandFullName): Promise<RecursiveResult>;
|
|
49
64
|
export declare function matchDependencies(match: (input: string) => string | null, manifest: ProjectManifest, include: IncludedDependencies): string[];
|
|
50
65
|
export type UpdateDepsMatcher = (input: string) => string | null;
|
|
51
66
|
export declare function createMatcher(params: string[]): UpdateDepsMatcher;
|
package/lib/recursive.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { mergeCatalogs } from '@pnpm/catalogs.config';
|
|
3
4
|
import { throwOnCommandFail, } from '@pnpm/cli.utils';
|
|
4
5
|
import { createMatcherWithIndex } from '@pnpm/config.matcher';
|
|
5
6
|
import { createProjectConfigRecord, getWorkspaceConcurrency, } from '@pnpm/config.reader';
|
|
@@ -23,11 +24,11 @@ import { createWorkspaceSpecs, updateToWorkspacePackagesFromManifest } from './u
|
|
|
23
24
|
export async function recursive(allProjects, params, opts, cmdFullName) {
|
|
24
25
|
if (allProjects.length === 0) {
|
|
25
26
|
// It might make sense to throw an exception in this case
|
|
26
|
-
return false;
|
|
27
|
+
return { passed: false };
|
|
27
28
|
}
|
|
28
29
|
const pkgs = Object.values(opts.selectedProjectsGraph).map((wsPkg) => wsPkg.package);
|
|
29
30
|
if (pkgs.length === 0) {
|
|
30
|
-
return false;
|
|
31
|
+
return { passed: false };
|
|
31
32
|
}
|
|
32
33
|
const manifestsByPath = getManifestsByPath(allProjects);
|
|
33
34
|
const throwOnFail = throwOnCommandFail.bind(null, `pnpm recursive ${cmdFullName}`);
|
|
@@ -88,7 +89,7 @@ export async function recursive(allProjects, params, opts, cmdFullName) {
|
|
|
88
89
|
const isFromWorkspace = isSubdir.bind(null, calculatedRepositoryRoot);
|
|
89
90
|
importers = await pFilter(importers, async ({ rootDirRealPath }) => isFromWorkspace(rootDirRealPath));
|
|
90
91
|
if (importers.length === 0)
|
|
91
|
-
return true;
|
|
92
|
+
return { passed: true };
|
|
92
93
|
let mutation;
|
|
93
94
|
switch (cmdFullName) {
|
|
94
95
|
case 'remove':
|
|
@@ -176,12 +177,12 @@ export async function recursive(allProjects, params, opts, cmdFullName) {
|
|
|
176
177
|
if ((mutatedImporters.length === 0) && cmdFullName === 'update' && opts.depth === 0) {
|
|
177
178
|
throw new PnpmError('NO_PACKAGE_IN_DEPENDENCIES', 'None of the specified packages were found in the dependencies of any of the projects.');
|
|
178
179
|
}
|
|
179
|
-
const { updatedCatalogs, updatedProjects: mutatedPkgs, ignoredBuilds, resolutionPolicyViolations, } = await mutateModules(mutatedImporters, {
|
|
180
|
+
const { updatedCatalogs, updatedProjects: mutatedPkgs, ignoredBuilds, resolutionPolicyViolations, dryRunResult, } = await mutateModules(mutatedImporters, {
|
|
180
181
|
...installOpts,
|
|
181
182
|
storeController: store.ctrl,
|
|
182
183
|
resolutionVerifiers: store.resolutionVerifiers,
|
|
183
184
|
});
|
|
184
|
-
if (opts.save !== false) {
|
|
185
|
+
if (opts.save !== false && !opts.dryRun) {
|
|
185
186
|
// Only pick entries when we'll actually persist. Otherwise the
|
|
186
187
|
// info log would claim entries were added that the workspace
|
|
187
188
|
// manifest never saw, and the next install would re-prompt or
|
|
@@ -199,7 +200,7 @@ export async function recursive(allProjects, params, opts, cmdFullName) {
|
|
|
199
200
|
await Promise.all(promises);
|
|
200
201
|
}
|
|
201
202
|
await handleIgnoredBuilds(opts, ignoredBuilds);
|
|
202
|
-
return true;
|
|
203
|
+
return { passed: true, updatedCatalogs, dryRunResult };
|
|
203
204
|
}
|
|
204
205
|
const pkgPaths = Object.keys(opts.selectedProjectsGraph).sort();
|
|
205
206
|
let updatedCatalogs;
|
|
@@ -289,8 +290,10 @@ export async function recursive(allProjects, params, opts, cmdFullName) {
|
|
|
289
290
|
if (opts.save !== false) {
|
|
290
291
|
await writeProjectManifest(newManifest);
|
|
291
292
|
if (newCatalogsAddition) {
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
// Per-project additions are partial maps keyed by catalog name then
|
|
294
|
+
// dependency. Merge at the dependency level so two projects updating
|
|
295
|
+
// different entries of the same catalog don't clobber each other.
|
|
296
|
+
updatedCatalogs = mergeCatalogs(updatedCatalogs, newCatalogsAddition);
|
|
294
297
|
}
|
|
295
298
|
}
|
|
296
299
|
if (ignoredBuilds?.size) {
|
|
@@ -346,7 +349,7 @@ export async function recursive(allProjects, params, opts, cmdFullName) {
|
|
|
346
349
|
if (!Object.values(result).filter(({ status }) => status === 'passed').length && cmdFullName === 'update' && opts.depth === 0) {
|
|
347
350
|
throw new PnpmError('NO_PACKAGE_IN_DEPENDENCIES', 'None of the specified packages were found in the dependencies of any of the projects.');
|
|
348
351
|
}
|
|
349
|
-
return true;
|
|
352
|
+
return { passed: true, updatedCatalogs };
|
|
350
353
|
}
|
|
351
354
|
function calculateRepositoryRoot(workspaceDir, projectDirs) {
|
|
352
355
|
// assume repo root is workspace dir
|
package/lib/remove.js
CHANGED
|
@@ -39,6 +39,8 @@ export function rcOptionsTypes() {
|
|
|
39
39
|
'lockfile-dir',
|
|
40
40
|
'lockfile-only',
|
|
41
41
|
'lockfile',
|
|
42
|
+
'node-experimental-package-map',
|
|
43
|
+
'node-package-map-type',
|
|
42
44
|
'node-linker',
|
|
43
45
|
'package-import-method',
|
|
44
46
|
'pnpmfile',
|
|
@@ -137,6 +139,9 @@ export async function handler(opts, params) {
|
|
|
137
139
|
storeDir: store.dir,
|
|
138
140
|
resolutionVerifiers: store.resolutionVerifiers,
|
|
139
141
|
include,
|
|
142
|
+
// `--dry-run` is an `install`-only preview; never let a config-level
|
|
143
|
+
// `dry-run` turn `remove` into a no-op check.
|
|
144
|
+
dryRun: false,
|
|
140
145
|
});
|
|
141
146
|
const allProjects = opts.allProjects ?? (opts.workspaceDir
|
|
142
147
|
? await findWorkspaceProjects(opts.workspaceDir, { ...opts, patterns: opts.workspacePackagePatterns })
|
package/lib/update/index.js
CHANGED
|
@@ -38,6 +38,8 @@ export function rcOptionsTypes() {
|
|
|
38
38
|
'lockfile',
|
|
39
39
|
'lockfile-include-tarball-url',
|
|
40
40
|
'network-concurrency',
|
|
41
|
+
'node-experimental-package-map',
|
|
42
|
+
'node-package-map-type',
|
|
41
43
|
'noproxy',
|
|
42
44
|
'npm-path',
|
|
43
45
|
'offline',
|
|
@@ -135,6 +137,10 @@ dependencies is not found inside the workspace',
|
|
|
135
137
|
name: '--interactive',
|
|
136
138
|
shortAlias: '-i',
|
|
137
139
|
},
|
|
140
|
+
{
|
|
141
|
+
description: 'Don\'t update the ranges in package.json.',
|
|
142
|
+
name: '--no-save',
|
|
143
|
+
},
|
|
138
144
|
OPTIONS.globalDir,
|
|
139
145
|
...UNIVERSAL_OPTIONS,
|
|
140
146
|
],
|
|
@@ -276,7 +282,7 @@ async function update(dependencies, opts, rebuildHandler) {
|
|
|
276
282
|
else if ((dependencies.length > 0) && dependencies.every(dep => !dep.substring(1).includes('@')) && depth > 0 && !opts.latest) {
|
|
277
283
|
updateMatching = createMatcher(dependencies);
|
|
278
284
|
}
|
|
279
|
-
|
|
285
|
+
await installDeps({
|
|
280
286
|
...opts,
|
|
281
287
|
rebuildHandler,
|
|
282
288
|
allowNew: false,
|
|
@@ -289,6 +295,9 @@ async function update(dependencies, opts, rebuildHandler) {
|
|
|
289
295
|
updateMatching,
|
|
290
296
|
updatePackageManifest: opts.save !== false,
|
|
291
297
|
resolutionMode: opts.save === false ? 'highest' : opts.resolutionMode,
|
|
298
|
+
// `--dry-run` is an `install`-only preview; never let a config-level
|
|
299
|
+
// `dry-run` turn `update` into a no-op check.
|
|
300
|
+
dryRun: false,
|
|
292
301
|
}, dependencies);
|
|
293
302
|
}
|
|
294
303
|
function makeIncludeDependenciesFromCLI(opts) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/installing.commands",
|
|
3
|
-
"version": "1100.
|
|
3
|
+
"version": "1100.10.1",
|
|
4
4
|
"description": "Commands for installation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"funding": "https://opencollective.com/pnpm",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/pnpm/pnpm/tree/main/installing/commands"
|
|
13
|
+
"url": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/commands"
|
|
14
14
|
},
|
|
15
|
-
"homepage": "https://github.com/pnpm/pnpm/tree/main/installing/commands#readme",
|
|
15
|
+
"homepage": "https://github.com/pnpm/pnpm/tree/main/pnpm11/installing/commands#readme",
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/pnpm/pnpm/issues"
|
|
18
18
|
},
|
|
@@ -33,14 +33,13 @@
|
|
|
33
33
|
"@pnpm/util.lex-comparator": "^4.0.1",
|
|
34
34
|
"@yarnpkg/core": "4.8.0",
|
|
35
35
|
"@yarnpkg/lockfile": "^1.1.0",
|
|
36
|
-
"@yarnpkg/parsers": "3.0.3",
|
|
37
36
|
"@zkochan/rimraf": "^4.0.0",
|
|
38
37
|
"@zkochan/table": "^2.0.1",
|
|
39
38
|
"chalk": "^5.6.2",
|
|
40
39
|
"ci-info": "^4.4.0",
|
|
41
40
|
"detect-libc": "^2.1.2",
|
|
42
|
-
"get-npm-tarball-url": "^2.1.0",
|
|
43
41
|
"is-subdir": "^2.0.0",
|
|
42
|
+
"js-yaml": "npm:@zkochan/js-yaml@0.0.11",
|
|
44
43
|
"load-json-file": "^7.0.1",
|
|
45
44
|
"normalize-path": "^3.0.0",
|
|
46
45
|
"p-filter": "^4.1.0",
|
|
@@ -48,57 +47,61 @@
|
|
|
48
47
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
49
48
|
"render-help": "^2.0.0",
|
|
50
49
|
"version-selector-type": "^3.0.0",
|
|
51
|
-
"@pnpm/building.
|
|
52
|
-
"@pnpm/building.policy": "1100.0.10",
|
|
50
|
+
"@pnpm/building.policy": "1100.0.11",
|
|
53
51
|
"@pnpm/catalogs.types": "1100.0.0",
|
|
54
|
-
"@pnpm/
|
|
55
|
-
"@pnpm/cli.common-cli-options-help": "1100.0.2",
|
|
52
|
+
"@pnpm/catalogs.config": "1100.0.2",
|
|
56
53
|
"@pnpm/cli.command": "1100.0.1",
|
|
57
|
-
"@pnpm/
|
|
54
|
+
"@pnpm/cli.utils": "1101.0.13",
|
|
58
55
|
"@pnpm/config.pick-registry-for-package": "1100.0.9",
|
|
59
|
-
"@pnpm/
|
|
60
|
-
"@pnpm/config.
|
|
56
|
+
"@pnpm/cli.common-cli-options-help": "1100.0.2",
|
|
57
|
+
"@pnpm/config.reader": "1101.10.1",
|
|
58
|
+
"@pnpm/building.after-install": "1102.0.2",
|
|
59
|
+
"@pnpm/config.writer": "1100.0.14",
|
|
61
60
|
"@pnpm/constants": "1100.0.0",
|
|
62
|
-
"@pnpm/
|
|
61
|
+
"@pnpm/config.version-policy": "1100.1.6",
|
|
62
|
+
"@pnpm/deps.inspection.outdated": "1100.1.10",
|
|
63
|
+
"@pnpm/config.matcher": "1100.0.1",
|
|
63
64
|
"@pnpm/deps.path": "1100.0.8",
|
|
64
|
-
"@pnpm/
|
|
65
|
-
"@pnpm/deps.
|
|
66
|
-
"@pnpm/error": "1100.0.0",
|
|
67
|
-
"@pnpm/fs.read-modules-dir": "1100.0.1",
|
|
65
|
+
"@pnpm/error": "1100.0.1",
|
|
66
|
+
"@pnpm/deps.security.signatures": "1101.2.3",
|
|
68
67
|
"@pnpm/fs.graceful-fs": "1100.1.0",
|
|
69
|
-
"@pnpm/global.commands": "1100.0.
|
|
70
|
-
"@pnpm/
|
|
71
|
-
"@pnpm/
|
|
72
|
-
"@pnpm/installing.context": "1100.0.
|
|
73
|
-
"@pnpm/installing.
|
|
74
|
-
"@pnpm/
|
|
75
|
-
"@pnpm/installing.
|
|
76
|
-
"@pnpm/
|
|
77
|
-
"@pnpm/lockfile.fs": "1100.1.
|
|
78
|
-
"@pnpm/network.
|
|
79
|
-
"@pnpm/
|
|
80
|
-
"@pnpm/
|
|
68
|
+
"@pnpm/global.commands": "1100.0.30",
|
|
69
|
+
"@pnpm/deps.status": "1100.1.3",
|
|
70
|
+
"@pnpm/hooks.pnpmfile": "1100.0.16",
|
|
71
|
+
"@pnpm/installing.context": "1100.0.20",
|
|
72
|
+
"@pnpm/installing.dedupe.check": "1100.1.1",
|
|
73
|
+
"@pnpm/installing.deps-installer": "1102.1.1",
|
|
74
|
+
"@pnpm/installing.dedupe.issues-renderer": "1100.0.1",
|
|
75
|
+
"@pnpm/lockfile.types": "1100.0.12",
|
|
76
|
+
"@pnpm/lockfile.fs": "1100.1.7",
|
|
77
|
+
"@pnpm/network.fetch": "1100.1.4",
|
|
78
|
+
"@pnpm/network.auth-header": "1101.1.3",
|
|
79
|
+
"@pnpm/pkg-manifest.reader": "1100.0.9",
|
|
80
|
+
"@pnpm/installing.env-installer": "1102.0.2",
|
|
81
|
+
"@pnpm/pkg-manifest.utils": "1100.2.6",
|
|
81
82
|
"@pnpm/resolving.parse-wanted-dependency": "1100.0.1",
|
|
82
|
-
"@pnpm/
|
|
83
|
-
"@pnpm/
|
|
84
|
-
"@pnpm/
|
|
85
|
-
"@pnpm/
|
|
83
|
+
"@pnpm/store.controller": "1102.0.2",
|
|
84
|
+
"@pnpm/resolving.npm-resolver": "1102.1.0",
|
|
85
|
+
"@pnpm/store.connection-manager": "1100.3.2",
|
|
86
|
+
"@pnpm/resolving.resolver-base": "1100.5.0",
|
|
86
87
|
"@pnpm/types": "1101.3.2",
|
|
87
|
-
"@pnpm/
|
|
88
|
+
"@pnpm/fs.read-modules-dir": "1100.0.1",
|
|
88
89
|
"@pnpm/workspace.project-manifest-writer": "1100.0.8",
|
|
89
|
-
"@pnpm/workspace.projects-filter": "1100.0.
|
|
90
|
-
"@pnpm/workspace.
|
|
91
|
-
"@pnpm/workspace.projects-
|
|
90
|
+
"@pnpm/workspace.projects-filter": "1100.0.23",
|
|
91
|
+
"@pnpm/workspace.project-manifest-reader": "1100.0.14",
|
|
92
|
+
"@pnpm/workspace.projects-reader": "1101.0.13",
|
|
93
|
+
"@pnpm/workspace.projects-graph": "1100.0.20",
|
|
94
|
+
"@pnpm/workspace.state": "1100.0.24",
|
|
92
95
|
"@pnpm/workspace.projects-sorter": "1100.0.7",
|
|
93
|
-
"@pnpm/workspace.root-finder": "1100.0.
|
|
94
|
-
"@pnpm/workspace.
|
|
95
|
-
"@pnpm/workspace.workspace-manifest-writer": "1100.0.13"
|
|
96
|
+
"@pnpm/workspace.root-finder": "1100.0.3",
|
|
97
|
+
"@pnpm/workspace.workspace-manifest-writer": "1100.0.14"
|
|
96
98
|
},
|
|
97
99
|
"peerDependencies": {
|
|
98
100
|
"@pnpm/logger": "^1100.0.0"
|
|
99
101
|
},
|
|
100
102
|
"devDependencies": {
|
|
101
103
|
"@jest/globals": "30.4.1",
|
|
104
|
+
"@types/js-yaml": "^4.0.9",
|
|
102
105
|
"@types/normalize-path": "^3.0.2",
|
|
103
106
|
"@types/proxyquire": "^1.3.31",
|
|
104
107
|
"@types/ramda": "0.31.1",
|
|
@@ -114,19 +117,19 @@
|
|
|
114
117
|
"write-json-file": "^7.0.0",
|
|
115
118
|
"write-package": "7.2.0",
|
|
116
119
|
"write-yaml-file": "^6.0.0",
|
|
117
|
-
"@pnpm/installing.commands": "1100.9.0",
|
|
118
|
-
"@pnpm/assert-project": "1100.0.16",
|
|
119
120
|
"@pnpm/installing.modules-yaml": "1100.0.9",
|
|
121
|
+
"@pnpm/installing.commands": "1100.10.1",
|
|
122
|
+
"@pnpm/assert-project": "1100.0.17",
|
|
123
|
+
"@pnpm/store.index": "1100.2.1",
|
|
120
124
|
"@pnpm/logger": "1100.0.0",
|
|
121
|
-
"@pnpm/prepare": "1100.0.
|
|
125
|
+
"@pnpm/prepare": "1100.0.17",
|
|
122
126
|
"@pnpm/test-fixtures": "1100.0.0",
|
|
123
127
|
"@pnpm/test-ipc-server": "1100.0.0",
|
|
124
|
-
"@pnpm/testing.
|
|
125
|
-
"@pnpm/testing.mock
|
|
126
|
-
"@pnpm/testing.
|
|
127
|
-
"@pnpm/
|
|
128
|
-
"@pnpm/worker": "1100.2.
|
|
129
|
-
"@pnpm/workspace.projects-filter": "1100.0.21"
|
|
128
|
+
"@pnpm/testing.mock-agent": "1101.0.4",
|
|
129
|
+
"@pnpm/testing.registry-mock": "1100.0.7",
|
|
130
|
+
"@pnpm/testing.command-defaults": "1100.0.7",
|
|
131
|
+
"@pnpm/workspace.projects-filter": "1100.0.23",
|
|
132
|
+
"@pnpm/worker": "1100.2.2"
|
|
130
133
|
},
|
|
131
134
|
"engines": {
|
|
132
135
|
"node": ">=22.13"
|