@pnpm/installing.commands 1100.8.0 → 1100.10.0
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/import/index.js +15 -3
- package/lib/install.d.ts +2 -2
- package/lib/install.js +69 -1
- package/lib/installDeps.d.ts +4 -4
- package/lib/installDeps.js +29 -14
- package/lib/link.js +1 -0
- package/lib/prune.js +1 -1
- package/lib/recursive.d.ts +28 -7
- package/lib/recursive.js +12 -9
- package/lib/remove.js +5 -0
- package/lib/runPacquet.d.ts +54 -16
- package/lib/runPacquet.js +87 -12
- package/lib/update/index.js +15 -1
- package/lib/verifyPacquetIdentity.js +2 -1
- package/package.json +60 -56
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
|
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'));
|
|
@@ -230,7 +242,7 @@ function selectProjectByDir(projects, searchedDir) {
|
|
|
230
242
|
const project = projects.find(({ rootDir }) => path.relative(rootDir, searchedDir) === '');
|
|
231
243
|
if (project == null)
|
|
232
244
|
return undefined;
|
|
233
|
-
return { [
|
|
245
|
+
return { [project.rootDir]: { dependencies: [], package: project } };
|
|
234
246
|
}
|
|
235
247
|
function getYarnLockfileType(lockFileContents) {
|
|
236
248
|
return lockFileContents.includes('__metadata')
|
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',
|
|
@@ -71,6 +75,7 @@ export function rcOptionsTypes() {
|
|
|
71
75
|
'optional',
|
|
72
76
|
'unsafe-perm',
|
|
73
77
|
'verify-store-integrity',
|
|
78
|
+
'frozen-store',
|
|
74
79
|
'virtual-store-dir',
|
|
75
80
|
'virtual-store-only',
|
|
76
81
|
], allTypes);
|
|
@@ -78,6 +83,7 @@ export function rcOptionsTypes() {
|
|
|
78
83
|
export const cliOptionsTypes = () => ({
|
|
79
84
|
...rcOptionsTypes(),
|
|
80
85
|
...pick(['force'], allTypes),
|
|
86
|
+
'dry-run': Boolean,
|
|
81
87
|
'fix-lockfile': Boolean,
|
|
82
88
|
'update-checksums': Boolean,
|
|
83
89
|
'resolution-only': Boolean,
|
|
@@ -127,6 +133,10 @@ For options that may be used with `-r`, see "pnpm help recursive"',
|
|
|
127
133
|
description: 'Skip reinstall if the workspace state is up-to-date',
|
|
128
134
|
name: '--optimistic-repeat-install',
|
|
129
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
|
+
},
|
|
130
140
|
{
|
|
131
141
|
description: '`optionalDependencies` are not installed',
|
|
132
142
|
name: '--no-optional',
|
|
@@ -211,6 +221,10 @@ by any dependencies, so it is an emulation of a flat node_modules',
|
|
|
211
221
|
description: 'If false, skips store integrity checks. These checks detect accidental corruption, not tampering by untrusted users with write access to the store',
|
|
212
222
|
name: '--[no-]verify-store-integrity',
|
|
213
223
|
},
|
|
224
|
+
{
|
|
225
|
+
description: 'Open the package store read-only (immutable) and skip all store writes. For installs against a store on a read-only filesystem (e.g. a Nix store); pair with --offline --frozen-lockfile. Incompatible with --force',
|
|
226
|
+
name: '--frozen-store',
|
|
227
|
+
},
|
|
214
228
|
{
|
|
215
229
|
description: 'Fail on missing or invalid peer dependencies',
|
|
216
230
|
name: '--strict-peer-dependencies',
|
|
@@ -265,6 +279,18 @@ Install all optionalDependencies even when they don\'t satisfy the current envir
|
|
|
265
279
|
description: 'Re-runs resolution: useful for printing out peer dependency issues',
|
|
266
280
|
name: '--resolution-only',
|
|
267
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
|
+
},
|
|
268
294
|
...UNIVERSAL_OPTIONS,
|
|
269
295
|
],
|
|
270
296
|
},
|
|
@@ -299,6 +325,48 @@ export async function handler(opts, _params, commands) {
|
|
|
299
325
|
installDepsOptions.lockfileOnly = true;
|
|
300
326
|
installDepsOptions.forceFullResolution = true;
|
|
301
327
|
}
|
|
302
|
-
|
|
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');
|
|
303
371
|
}
|
|
304
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'> & 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' | '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)) {
|
|
@@ -95,6 +97,7 @@ export async function installDeps(opts, params) {
|
|
|
95
97
|
packageName: pacquetConfigDepName,
|
|
96
98
|
argv: { original: opts.argv.original, remain: opts.argv.remain ?? [] },
|
|
97
99
|
isInstallCommand: opts.isInstallCommand === true,
|
|
100
|
+
virtualStoreDirMaxLength: opts.virtualStoreDirMaxLength,
|
|
98
101
|
})
|
|
99
102
|
: undefined;
|
|
100
103
|
const includeDirect = opts.includeDirect ?? {
|
|
@@ -130,7 +133,7 @@ export async function installDeps(opts, params) {
|
|
|
130
133
|
const allProjectsGraph = opts.allProjectsGraph ?? createProjectsGraph(allProjects, {
|
|
131
134
|
linkWorkspacePackages: Boolean(opts.linkWorkspacePackages),
|
|
132
135
|
}).graph;
|
|
133
|
-
|
|
136
|
+
return recursiveInstallThenUpdateWorkspaceState(allProjects, params, {
|
|
134
137
|
...opts,
|
|
135
138
|
preferredVersions: opts.packageVulnerabilityAudit ? preferNonvulnerablePackageVersions(opts.packageVulnerabilityAudit) : undefined,
|
|
136
139
|
allProjectsGraph,
|
|
@@ -139,7 +142,6 @@ export async function installDeps(opts, params) {
|
|
|
139
142
|
workspaceDir: opts.workspaceDir,
|
|
140
143
|
runPacquet,
|
|
141
144
|
}, opts.update ? 'update' : (params.length === 0 ? 'install' : 'add'));
|
|
142
|
-
return;
|
|
143
145
|
}
|
|
144
146
|
}
|
|
145
147
|
// `pnpm install ""` is going to be just `pnpm install`
|
|
@@ -240,8 +242,8 @@ export async function installDeps(opts, params) {
|
|
|
240
242
|
rootDir: opts.dir,
|
|
241
243
|
targetDependenciesField: getSaveType(opts),
|
|
242
244
|
};
|
|
243
|
-
const { updatedCatalogs, updatedProject, ignoredBuilds, resolutionPolicyViolations } = await mutateModulesInSingleProject(mutatedProject, installOpts);
|
|
244
|
-
if (opts.save !== false) {
|
|
245
|
+
const { updatedCatalogs, updatedProject, ignoredBuilds, resolutionPolicyViolations, dryRunResult } = await mutateModulesInSingleProject(mutatedProject, installOpts);
|
|
246
|
+
if (opts.save !== false && !opts.dryRun) {
|
|
245
247
|
// Only pick entries when we'll actually persist. Otherwise the
|
|
246
248
|
// info log would claim we added entries the workspace manifest
|
|
247
249
|
// never saw, and the next install would re-prompt or fail
|
|
@@ -260,7 +262,7 @@ export async function installDeps(opts, params) {
|
|
|
260
262
|
if (!opts.lockfileOnly) {
|
|
261
263
|
await updateWorkspaceState({
|
|
262
264
|
allProjects,
|
|
263
|
-
settings: opts,
|
|
265
|
+
settings: withUpdatedCatalogs(opts, updatedCatalogs),
|
|
264
266
|
workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
|
|
265
267
|
pnpmfiles: opts.pnpmfile,
|
|
266
268
|
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
|
@@ -268,9 +270,9 @@ export async function installDeps(opts, params) {
|
|
|
268
270
|
});
|
|
269
271
|
}
|
|
270
272
|
await handleIgnoredBuilds(opts, ignoredBuilds);
|
|
271
|
-
return;
|
|
273
|
+
return dryRunResult;
|
|
272
274
|
}
|
|
273
|
-
const { updatedCatalogs, updatedManifest, ignoredBuilds, resolutionPolicyViolations } = await install(manifest, {
|
|
275
|
+
const { updatedCatalogs, updatedManifest, ignoredBuilds, resolutionPolicyViolations, dryRunResult } = await install(manifest, {
|
|
274
276
|
...installOpts,
|
|
275
277
|
updatePackageManifest,
|
|
276
278
|
updateMatching,
|
|
@@ -279,7 +281,7 @@ export async function installDeps(opts, params) {
|
|
|
279
281
|
// from this install" — both package.json and the workspace manifest.
|
|
280
282
|
// Skip the pick so the info log doesn't claim entries were added that
|
|
281
283
|
// were never written; the next install will resurface them.
|
|
282
|
-
if (opts.save !== false) {
|
|
284
|
+
if (opts.save !== false && !opts.dryRun) {
|
|
283
285
|
const policyUpdates = policyHandlers?.pickManifestUpdates(resolutionPolicyViolations);
|
|
284
286
|
if (opts.update === true) {
|
|
285
287
|
await Promise.all([
|
|
@@ -318,7 +320,7 @@ export async function installDeps(opts, params) {
|
|
|
318
320
|
selectedProjectsGraph,
|
|
319
321
|
workspaceDir: opts.workspaceDir, // Otherwise TypeScript doesn't understand that is not undefined
|
|
320
322
|
runPacquet,
|
|
321
|
-
}, 'install');
|
|
323
|
+
}, 'install', updatedCatalogs);
|
|
322
324
|
if (opts.ignoreScripts)
|
|
323
325
|
return;
|
|
324
326
|
await buildProjects([
|
|
@@ -339,7 +341,7 @@ export async function installDeps(opts, params) {
|
|
|
339
341
|
if (!opts.lockfileOnly) {
|
|
340
342
|
await updateWorkspaceState({
|
|
341
343
|
allProjects,
|
|
342
|
-
settings: opts,
|
|
344
|
+
settings: withUpdatedCatalogs(opts, updatedCatalogs),
|
|
343
345
|
workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
|
|
344
346
|
pnpmfiles: opts.pnpmfile,
|
|
345
347
|
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
|
@@ -347,26 +349,39 @@ export async function installDeps(opts, params) {
|
|
|
347
349
|
});
|
|
348
350
|
}
|
|
349
351
|
}
|
|
352
|
+
return dryRunResult;
|
|
350
353
|
}
|
|
351
354
|
function selectProjectByDir(projects, searchedDir) {
|
|
352
355
|
const project = projects.find(({ rootDir }) => path.relative(rootDir, searchedDir) === '');
|
|
353
356
|
if (project == null)
|
|
354
357
|
return undefined;
|
|
355
|
-
return { [
|
|
358
|
+
return { [project.rootDir]: { dependencies: [], package: project } };
|
|
356
359
|
}
|
|
357
|
-
async function recursiveInstallThenUpdateWorkspaceState(allProjects, params, opts, cmdFullName) {
|
|
360
|
+
async function recursiveInstallThenUpdateWorkspaceState(allProjects, params, opts, cmdFullName, updatedCatalogs) {
|
|
358
361
|
const recursiveResult = await recursive(allProjects, params, opts, cmdFullName);
|
|
359
362
|
if (!opts.lockfileOnly) {
|
|
360
363
|
await updateWorkspaceState({
|
|
361
364
|
allProjects,
|
|
362
|
-
settings: opts,
|
|
365
|
+
settings: withUpdatedCatalogs(opts, updatedCatalogs, recursiveResult.updatedCatalogs),
|
|
363
366
|
workspaceDir: opts.workspaceDir,
|
|
364
367
|
pnpmfiles: opts.pnpmfile,
|
|
365
368
|
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
|
366
369
|
configDependencies: opts.configDependencies,
|
|
367
370
|
});
|
|
368
371
|
}
|
|
369
|
-
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) };
|
|
370
385
|
}
|
|
371
386
|
function severityStringToNumber(severity) {
|
|
372
387
|
switch (severity) {
|
package/lib/link.js
CHANGED
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;
|
|
@@ -32,14 +33,34 @@ export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config, 'bail
|
|
|
32
33
|
pnpmfile: string[];
|
|
33
34
|
/**
|
|
34
35
|
* Alternative install engine (today: pacquet) the deps-installer
|
|
35
|
-
* delegates the
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* delegates the install to. Built in `installDeps` when
|
|
37
|
+
* `configDependencies.pacquet` is declared, threaded through here so
|
|
38
|
+
* the recursive workspace path picks it up too.
|
|
38
39
|
*/
|
|
39
|
-
runPacquet?:
|
|
40
|
+
runPacquet?: {
|
|
41
|
+
supportsResolution: boolean;
|
|
42
|
+
run: (opts?: {
|
|
43
|
+
filterResolvedProgress?: boolean;
|
|
44
|
+
resolve?: boolean;
|
|
45
|
+
}) => Promise<void>;
|
|
46
|
+
};
|
|
40
47
|
} & Partial<Pick<Config, 'ci' | 'sort' | 'strictDepBuilds' | 'workspaceConcurrency'>> & Required<Pick<Config, 'workspaceDir'>>;
|
|
41
48
|
export type CommandFullName = 'install' | 'add' | 'remove' | 'update' | 'import';
|
|
42
|
-
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>;
|
|
43
64
|
export declare function matchDependencies(match: (input: string) => string | null, manifest: ProjectManifest, include: IncludedDependencies): string[];
|
|
44
65
|
export type UpdateDepsMatcher = (input: string) => string | null;
|
|
45
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/runPacquet.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export interface MakeRunPacquetOpts {
|
|
2
2
|
lockfileDir: string;
|
|
3
|
+
/**
|
|
4
|
+
* Effective pnpm config value. Forwarded through `PNPM_CONFIG_*` so
|
|
5
|
+
* pacquet writes the same `.modules.yaml` and virtual-store paths as
|
|
6
|
+
* the pnpm process that delegated to it, including Windows' shorter
|
|
7
|
+
* default.
|
|
8
|
+
*/
|
|
9
|
+
virtualStoreDirMaxLength: number;
|
|
3
10
|
/**
|
|
4
11
|
* Which `configDependencies` entry installed pacquet: either the
|
|
5
12
|
* original unscoped `pacquet` or the official scoped
|
|
@@ -32,21 +39,6 @@ export interface MakeRunPacquetOpts {
|
|
|
32
39
|
*/
|
|
33
40
|
isInstallCommand: boolean;
|
|
34
41
|
}
|
|
35
|
-
/**
|
|
36
|
-
* Build the install-engine callback `mutateModules` invokes when
|
|
37
|
-
* `configDependencies` declares pacquet.
|
|
38
|
-
*
|
|
39
|
-
* The callback spawns the pacquet binary installed under
|
|
40
|
-
* `node_modules/.pnpm-config/pacquet`. From `pnpm install`/`pnpm i` it
|
|
41
|
-
* forwards the user's own pnpm CLI flags to pacquet's `install`
|
|
42
|
-
* subcommand; from `add`/`update`/`dedupe` it doesn't forward (warning
|
|
43
|
-
* instead). Pacquet's NDJSON stderr is parsed line-by-line and the
|
|
44
|
-
* valid JSON records are re-emitted on pnpm's global `streamParser` so
|
|
45
|
-
* `@pnpm/cli.default-reporter` renders pacquet's events the same way it
|
|
46
|
-
* renders pnpm's own. Non-JSON stderr lines (panic backtraces,
|
|
47
|
-
* unexpected diagnostics) are forwarded to the real stderr verbatim so
|
|
48
|
-
* they reach the user.
|
|
49
|
-
*/
|
|
50
42
|
/** Args the deps-installer passes per pacquet invocation. */
|
|
51
43
|
export interface RunPacquetCallOpts {
|
|
52
44
|
/**
|
|
@@ -60,5 +52,51 @@ export interface RunPacquetCallOpts {
|
|
|
60
52
|
* source.
|
|
61
53
|
*/
|
|
62
54
|
filterResolvedProgress?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* `true` to let pacquet perform the resolution itself rather than
|
|
57
|
+
* materialize an already-resolved lockfile. Drops the injected
|
|
58
|
+
* `--frozen-lockfile`, so pacquet resolves the manifests, writes
|
|
59
|
+
* `pnpm-lock.yaml`, and materializes in a single pass. Only valid
|
|
60
|
+
* when {@link PacquetEngine.supportsResolution} is `true` (pacquet
|
|
61
|
+
* >= 0.11.7).
|
|
62
|
+
*/
|
|
63
|
+
resolve?: boolean;
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Handle to the pacquet install engine: its capabilities plus the
|
|
67
|
+
* callback `mutateModules` invokes to run it.
|
|
68
|
+
*/
|
|
69
|
+
export interface PacquetEngine {
|
|
70
|
+
/**
|
|
71
|
+
* `true` when the installed pacquet is new enough (>= 0.11.7) to
|
|
72
|
+
* perform dependency resolution itself. When `false`, pacquet can
|
|
73
|
+
* only materialize an already-resolved lockfile, so the deps-installer
|
|
74
|
+
* runs its own resolve pass first and hands the written lockfile to
|
|
75
|
+
* pacquet.
|
|
76
|
+
*/
|
|
77
|
+
supportsResolution: boolean;
|
|
78
|
+
run: (callOpts?: RunPacquetCallOpts) => Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Build the pacquet install engine `mutateModules` delegates to when
|
|
82
|
+
* `configDependencies` declares pacquet.
|
|
83
|
+
*
|
|
84
|
+
* `run` spawns the pacquet binary installed under
|
|
85
|
+
* `node_modules/.pnpm-config/pacquet`. From `pnpm install`/`pnpm i` it
|
|
86
|
+
* forwards the user's own pnpm CLI flags to pacquet's `install`
|
|
87
|
+
* subcommand; from `add`/`update`/`dedupe` it doesn't forward (warning
|
|
88
|
+
* instead). Pacquet's NDJSON stderr is parsed line-by-line and the
|
|
89
|
+
* valid JSON records are re-emitted on pnpm's global `streamParser` so
|
|
90
|
+
* `@pnpm/cli.default-reporter` renders pacquet's events the same way it
|
|
91
|
+
* renders pnpm's own. Non-JSON stderr lines (panic backtraces,
|
|
92
|
+
* unexpected diagnostics) are forwarded to the real stderr verbatim so
|
|
93
|
+
* they reach the user.
|
|
94
|
+
*/
|
|
95
|
+
export declare function makeRunPacquet(opts: MakeRunPacquetOpts): PacquetEngine;
|
|
96
|
+
/**
|
|
97
|
+
* Name of the `@pacquet/<platform>-<arch>[-musl]` package that holds the
|
|
98
|
+
* native pacquet binary for the host. On linux the binary packages are
|
|
99
|
+
* split by libc and only the matching one is installed, so spawning and
|
|
100
|
+
* signature verification must agree on this exact name.
|
|
101
|
+
*/
|
|
102
|
+
export declare function pacquetPlatformPkgName(): string;
|
package/lib/runPacquet.js
CHANGED
|
@@ -6,12 +6,34 @@ import readline from 'node:readline';
|
|
|
6
6
|
import { PnpmError } from '@pnpm/error';
|
|
7
7
|
import { logger, streamParser } from '@pnpm/logger';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
|
+
import { familySync as getLibcFamilySync, MUSL } from 'detect-libc';
|
|
9
10
|
// The runtime `streamParser` is a `Transform` stream (split2 + JSON.parse).
|
|
10
11
|
// Its public typing only exposes `on`/`removeListener`, so we narrow to the
|
|
11
12
|
// writable side here to feed pacquet's NDJSON lines back through the same
|
|
12
13
|
// parser that `@pnpm/cli.default-reporter` listens on.
|
|
13
14
|
const streamParserWritable = streamParser;
|
|
15
|
+
/**
|
|
16
|
+
* Build the pacquet install engine `mutateModules` delegates to when
|
|
17
|
+
* `configDependencies` declares pacquet.
|
|
18
|
+
*
|
|
19
|
+
* `run` spawns the pacquet binary installed under
|
|
20
|
+
* `node_modules/.pnpm-config/pacquet`. From `pnpm install`/`pnpm i` it
|
|
21
|
+
* forwards the user's own pnpm CLI flags to pacquet's `install`
|
|
22
|
+
* subcommand; from `add`/`update`/`dedupe` it doesn't forward (warning
|
|
23
|
+
* instead). Pacquet's NDJSON stderr is parsed line-by-line and the
|
|
24
|
+
* valid JSON records are re-emitted on pnpm's global `streamParser` so
|
|
25
|
+
* `@pnpm/cli.default-reporter` renders pacquet's events the same way it
|
|
26
|
+
* renders pnpm's own. Non-JSON stderr lines (panic backtraces,
|
|
27
|
+
* unexpected diagnostics) are forwarded to the real stderr verbatim so
|
|
28
|
+
* they reach the user.
|
|
29
|
+
*/
|
|
14
30
|
export function makeRunPacquet(opts) {
|
|
31
|
+
return {
|
|
32
|
+
supportsResolution: pacquetSupportsResolution(resolvePacquetVersion(opts.lockfileDir, opts.packageName)),
|
|
33
|
+
run: makeRun(opts),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function makeRun(opts) {
|
|
15
37
|
return async (callOpts) => {
|
|
16
38
|
const pacquetBin = resolvePacquetBin(opts.lockfileDir, opts.packageName);
|
|
17
39
|
// From `pnpm install`/`pnpm i` we forward the user's flags through to
|
|
@@ -19,21 +41,23 @@ export function makeRunPacquet(opts) {
|
|
|
19
41
|
// surface closely enough on that command that they're safe to pass
|
|
20
42
|
// along. From `add`/`update`/`dedupe` we don't forward anything: those
|
|
21
43
|
// commands carry flags pacquet's `install` doesn't recognize
|
|
22
|
-
// (`--save-dev`, `--save-peer`, etc.) which clap would reject.
|
|
23
|
-
// way pacquet picks up the settings users care about from
|
|
24
|
-
// `pnpm-workspace.yaml` / `.npmrc` on its own, so a non-install
|
|
25
|
-
// delegation isn't broken by the omission.
|
|
44
|
+
// (`--save-dev`, `--save-peer`, etc.) which clap would reject.
|
|
26
45
|
const forwardedFlags = opts.isInstallCommand ? collectForwardedFlags(opts.argv) : [];
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
46
|
+
// In resolve mode pacquet does the resolution itself, so it must not
|
|
47
|
+
// be pinned to the existing lockfile — drop both injected flags.
|
|
48
|
+
//
|
|
49
|
+
// Otherwise (frozen materialization) inject `--frozen-lockfile` plus
|
|
50
|
+
// `--ignore-manifest-check`. The latter tells pacquet to skip its
|
|
51
|
+
// per-importer `package.json` ↔ `pnpm-lock.yaml` freshness gate:
|
|
52
|
+
// pnpm just resolved and wrote the lockfile itself; on `pnpm up` /
|
|
53
|
+
// `add` / `remove` the manifest on disk is still the pre-mutation
|
|
54
|
+
// copy (pnpm writes it after `mutateModules` returns), so pacquet's
|
|
55
|
+
// own check would always fire here. See
|
|
33
56
|
// https://github.com/pnpm/pnpm/issues/11797. The flag is narrow
|
|
34
57
|
// (only the manifest check); settings drift like `overrides` is
|
|
35
58
|
// still enforced and was already re-validated by pnpm.
|
|
36
|
-
const
|
|
59
|
+
const frozenArgs = callOpts?.resolve === true ? [] : ['--frozen-lockfile', '--ignore-manifest-check'];
|
|
60
|
+
const args = ['--reporter=ndjson', 'install', ...frozenArgs, ...forwardedFlags];
|
|
37
61
|
const droppedFlags = opts.isInstallCommand ? [] : collectDroppedFlags(opts.argv);
|
|
38
62
|
if (droppedFlags.length > 0) {
|
|
39
63
|
logger.warn({
|
|
@@ -53,6 +77,7 @@ export function makeRunPacquet(opts) {
|
|
|
53
77
|
logger.info({ message: banner, prefix: opts.lockfileDir });
|
|
54
78
|
const child = spawn(pacquetBin, args, {
|
|
55
79
|
cwd: opts.lockfileDir,
|
|
80
|
+
env: makePacquetEnv(opts),
|
|
56
81
|
stdio: ['ignore', 'inherit', 'pipe'],
|
|
57
82
|
});
|
|
58
83
|
const filterResolved = callOpts?.filterResolvedProgress === true;
|
|
@@ -89,6 +114,16 @@ export function makeRunPacquet(opts) {
|
|
|
89
114
|
});
|
|
90
115
|
};
|
|
91
116
|
}
|
|
117
|
+
function makePacquetEnv(opts) {
|
|
118
|
+
const env = { ...process.env };
|
|
119
|
+
for (const key of Object.keys(env)) {
|
|
120
|
+
if (key.toLowerCase() === 'pnpm_config_virtual_store_dir_max_length') {
|
|
121
|
+
delete env[key];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
env.PNPM_CONFIG_VIRTUAL_STORE_DIR_MAX_LENGTH = String(opts.virtualStoreDirMaxLength);
|
|
125
|
+
return env;
|
|
126
|
+
}
|
|
92
127
|
/**
|
|
93
128
|
* Path of the platform-specific native pacquet binary for the host. The
|
|
94
129
|
* pacquet npm package ships a Node wrapper at `bin/pacquet` that uses
|
|
@@ -108,7 +143,47 @@ export function makeRunPacquet(opts) {
|
|
|
108
143
|
function resolvePacquetBin(lockfileDir, packageName) {
|
|
109
144
|
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
110
145
|
const pacquetPkg = fs.realpathSync(path.join(lockfileDir, 'node_modules/.pnpm-config', packageName, 'package.json'));
|
|
111
|
-
return createRequire(pacquetPkg).resolve(
|
|
146
|
+
return createRequire(pacquetPkg).resolve(`${pacquetPlatformPkgName()}/pacquet${ext}`);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Name of the `@pacquet/<platform>-<arch>[-musl]` package that holds the
|
|
150
|
+
* native pacquet binary for the host. On linux the binary packages are
|
|
151
|
+
* split by libc and only the matching one is installed, so spawning and
|
|
152
|
+
* signature verification must agree on this exact name.
|
|
153
|
+
*/
|
|
154
|
+
export function pacquetPlatformPkgName() {
|
|
155
|
+
const libc = process.platform === 'linux' && getLibcFamilySync() === MUSL ? '-musl' : '';
|
|
156
|
+
return `@pacquet/${process.platform}-${process.arch}${libc}`;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Read the installed pacquet's version from its `package.json` under
|
|
160
|
+
* `node_modules/.pnpm-config/<packageName>`. Returns `undefined` if it
|
|
161
|
+
* can't be read — callers treat that as "assume the older,
|
|
162
|
+
* materialization-only pacquet" so a missing/garbled manifest degrades
|
|
163
|
+
* to the safe path rather than failing the install.
|
|
164
|
+
*/
|
|
165
|
+
function resolvePacquetVersion(lockfileDir, packageName) {
|
|
166
|
+
try {
|
|
167
|
+
const pacquetPkg = fs.realpathSync(path.join(lockfileDir, 'node_modules/.pnpm-config', packageName, 'package.json'));
|
|
168
|
+
const { version } = JSON.parse(fs.readFileSync(pacquetPkg, 'utf8'));
|
|
169
|
+
return version;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* pacquet gained full resolving installs in 0.11.7; earlier releases
|
|
177
|
+
* stay on pnpm's resolve-then-materialize path. Pre-release builds of
|
|
178
|
+
* 0.11.7 (e.g. `0.11.7-rc.1`) count as supporting it.
|
|
179
|
+
*/
|
|
180
|
+
function pacquetSupportsResolution(version) {
|
|
181
|
+
if (version == null)
|
|
182
|
+
return false;
|
|
183
|
+
const [major, minor, patch] = version.split('.', 3).map((part) => parseInt(part, 10));
|
|
184
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch))
|
|
185
|
+
return false;
|
|
186
|
+
return major > 0 || (major === 0 && (minor > 11 || (minor === 11 && patch >= 7)));
|
|
112
187
|
}
|
|
113
188
|
/**
|
|
114
189
|
* From `pnpm install`/`pnpm i`, return everything in argv that should
|
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
|
],
|
|
@@ -205,6 +211,11 @@ async function interactiveUpdate(input, opts, rebuildHandler) {
|
|
|
205
211
|
flatChoices.push({
|
|
206
212
|
name: choice.message,
|
|
207
213
|
value: choice.value,
|
|
214
|
+
// `name` is the rendered table row (label + versions + workspace + url)
|
|
215
|
+
// that lays out a single choice during selection. After submission
|
|
216
|
+
// @inquirer/prompts comma-joins each choice's `short`, which without
|
|
217
|
+
// this defaults to `name` and dumps the whole table back to stdout.
|
|
218
|
+
short: choice.value,
|
|
208
219
|
});
|
|
209
220
|
}
|
|
210
221
|
}
|
|
@@ -271,7 +282,7 @@ async function update(dependencies, opts, rebuildHandler) {
|
|
|
271
282
|
else if ((dependencies.length > 0) && dependencies.every(dep => !dep.substring(1).includes('@')) && depth > 0 && !opts.latest) {
|
|
272
283
|
updateMatching = createMatcher(dependencies);
|
|
273
284
|
}
|
|
274
|
-
|
|
285
|
+
await installDeps({
|
|
275
286
|
...opts,
|
|
276
287
|
rebuildHandler,
|
|
277
288
|
allowNew: false,
|
|
@@ -284,6 +295,9 @@ async function update(dependencies, opts, rebuildHandler) {
|
|
|
284
295
|
updateMatching,
|
|
285
296
|
updatePackageManifest: opts.save !== false,
|
|
286
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,
|
|
287
301
|
}, dependencies);
|
|
288
302
|
}
|
|
289
303
|
function makeIncludeDependenciesFromCLI(opts) {
|
|
@@ -4,6 +4,7 @@ import { PnpmError } from '@pnpm/error';
|
|
|
4
4
|
import { readEnvLockfile } from '@pnpm/lockfile.fs';
|
|
5
5
|
import { logger } from '@pnpm/logger';
|
|
6
6
|
import { createGetAuthHeaderByURI } from '@pnpm/network.auth-header';
|
|
7
|
+
import { pacquetPlatformPkgName } from './runPacquet.js';
|
|
7
8
|
/**
|
|
8
9
|
* Decides whether pnpm may spawn the pacquet binary installed under
|
|
9
10
|
* `node_modules/.pnpm-config/<packageName>` as an install engine.
|
|
@@ -60,7 +61,7 @@ async function collectPacquetPackagesToVerify(packageName, rootDir, registries)
|
|
|
60
61
|
return undefined;
|
|
61
62
|
// Only the host's platform binary is ever spawned, so that's the one whose
|
|
62
63
|
// identity matters. If it isn't in the lockfile, pacquet couldn't run here.
|
|
63
|
-
const platformPkgName =
|
|
64
|
+
const platformPkgName = pacquetPlatformPkgName();
|
|
64
65
|
const platformVersion = envLockfile.snapshots[shimKey]?.optionalDependencies?.[platformPkgName];
|
|
65
66
|
if (platformVersion == null)
|
|
66
67
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/installing.commands",
|
|
3
|
-
"version": "1100.
|
|
3
|
+
"version": "1100.10.0",
|
|
4
4
|
"description": "Commands for installation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -30,16 +30,17 @@
|
|
|
30
30
|
"@inquirer/prompts": "^8.4.3",
|
|
31
31
|
"@pnpm/colorize-semver-diff": "^2.0.0",
|
|
32
32
|
"@pnpm/semver-diff": "^2.0.0",
|
|
33
|
-
"@pnpm/util.lex-comparator": "^
|
|
34
|
-
"@yarnpkg/core": "4.
|
|
33
|
+
"@pnpm/util.lex-comparator": "^4.0.1",
|
|
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",
|
|
40
|
+
"detect-libc": "^2.1.2",
|
|
41
41
|
"get-npm-tarball-url": "^2.1.0",
|
|
42
42
|
"is-subdir": "^2.0.0",
|
|
43
|
+
"js-yaml": "npm:@zkochan/js-yaml@0.0.11",
|
|
43
44
|
"load-json-file": "^7.0.1",
|
|
44
45
|
"normalize-path": "^3.0.0",
|
|
45
46
|
"p-filter": "^4.1.0",
|
|
@@ -47,62 +48,65 @@
|
|
|
47
48
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
48
49
|
"render-help": "^2.0.0",
|
|
49
50
|
"version-selector-type": "^3.0.0",
|
|
50
|
-
"@pnpm/building.after-install": "
|
|
51
|
+
"@pnpm/building.after-install": "1102.0.1",
|
|
52
|
+
"@pnpm/building.policy": "1100.0.10",
|
|
53
|
+
"@pnpm/catalogs.config": "1100.0.1",
|
|
51
54
|
"@pnpm/cli.command": "1100.0.1",
|
|
52
|
-
"@pnpm/catalogs.types": "1100.0.0",
|
|
53
55
|
"@pnpm/cli.common-cli-options-help": "1100.0.2",
|
|
56
|
+
"@pnpm/cli.utils": "1101.0.12",
|
|
54
57
|
"@pnpm/config.matcher": "1100.0.1",
|
|
55
|
-
"@pnpm/
|
|
56
|
-
"@pnpm/config.
|
|
58
|
+
"@pnpm/config.pick-registry-for-package": "1100.0.9",
|
|
59
|
+
"@pnpm/config.reader": "1101.10.0",
|
|
60
|
+
"@pnpm/config.writer": "1100.0.13",
|
|
57
61
|
"@pnpm/constants": "1100.0.0",
|
|
58
|
-
"@pnpm/
|
|
59
|
-
"@pnpm/deps.
|
|
60
|
-
"@pnpm/
|
|
61
|
-
"@pnpm/deps.
|
|
62
|
-
"@pnpm/
|
|
62
|
+
"@pnpm/deps.inspection.outdated": "1100.1.9",
|
|
63
|
+
"@pnpm/deps.path": "1100.0.8",
|
|
64
|
+
"@pnpm/deps.status": "1100.1.2",
|
|
65
|
+
"@pnpm/deps.security.signatures": "1101.2.2",
|
|
66
|
+
"@pnpm/catalogs.types": "1100.0.0",
|
|
67
|
+
"@pnpm/fs.read-modules-dir": "1100.0.1",
|
|
63
68
|
"@pnpm/error": "1100.0.0",
|
|
64
|
-
"@pnpm/
|
|
69
|
+
"@pnpm/global.commands": "1100.0.29",
|
|
65
70
|
"@pnpm/fs.graceful-fs": "1100.1.0",
|
|
66
|
-
"@pnpm/
|
|
67
|
-
"@pnpm/
|
|
68
|
-
"@pnpm/installing.
|
|
69
|
-
"@pnpm/installing.
|
|
70
|
-
"@pnpm/
|
|
71
|
-
"@pnpm/
|
|
72
|
-
"@pnpm/lockfile.
|
|
73
|
-
"@pnpm/
|
|
74
|
-
"@pnpm/
|
|
75
|
-
"@pnpm/pkg-manifest.
|
|
76
|
-
"@pnpm/
|
|
77
|
-
"@pnpm/installing.deps-installer": "1101.9.0",
|
|
71
|
+
"@pnpm/hooks.pnpmfile": "1100.0.15",
|
|
72
|
+
"@pnpm/installing.dedupe.check": "1100.1.0",
|
|
73
|
+
"@pnpm/installing.dedupe.issues-renderer": "1100.0.1",
|
|
74
|
+
"@pnpm/installing.deps-installer": "1102.1.0",
|
|
75
|
+
"@pnpm/installing.context": "1100.0.19",
|
|
76
|
+
"@pnpm/lockfile.fs": "1100.1.6",
|
|
77
|
+
"@pnpm/lockfile.types": "1100.0.11",
|
|
78
|
+
"@pnpm/installing.env-installer": "1102.0.1",
|
|
79
|
+
"@pnpm/network.fetch": "1100.1.3",
|
|
80
|
+
"@pnpm/pkg-manifest.reader": "1100.0.8",
|
|
81
|
+
"@pnpm/network.auth-header": "1101.1.2",
|
|
78
82
|
"@pnpm/resolving.parse-wanted-dependency": "1100.0.1",
|
|
79
|
-
"@pnpm/resolving.resolver
|
|
80
|
-
"@pnpm/store.connection-manager": "1100.
|
|
81
|
-
"@pnpm/
|
|
82
|
-
"@pnpm/
|
|
83
|
-
"@pnpm/
|
|
84
|
-
"@pnpm/
|
|
85
|
-
"@pnpm/workspace.project-manifest-writer": "1100.0.
|
|
86
|
-
"@pnpm/workspace.projects-
|
|
87
|
-
"@pnpm/workspace.projects-
|
|
88
|
-
"@pnpm/workspace.projects-
|
|
89
|
-
"@pnpm/workspace.
|
|
90
|
-
"@pnpm/workspace.
|
|
91
|
-
"@pnpm/workspace.
|
|
92
|
-
"@pnpm/
|
|
93
|
-
"@pnpm/
|
|
94
|
-
"@pnpm/lockfile.types": "1100.0.10"
|
|
83
|
+
"@pnpm/resolving.npm-resolver": "1102.0.1",
|
|
84
|
+
"@pnpm/store.connection-manager": "1100.3.1",
|
|
85
|
+
"@pnpm/resolving.resolver-base": "1100.4.2",
|
|
86
|
+
"@pnpm/workspace.project-manifest-reader": "1100.0.13",
|
|
87
|
+
"@pnpm/pkg-manifest.utils": "1100.2.5",
|
|
88
|
+
"@pnpm/types": "1101.3.2",
|
|
89
|
+
"@pnpm/workspace.project-manifest-writer": "1100.0.8",
|
|
90
|
+
"@pnpm/workspace.projects-sorter": "1100.0.7",
|
|
91
|
+
"@pnpm/workspace.projects-graph": "1100.0.19",
|
|
92
|
+
"@pnpm/workspace.projects-reader": "1101.0.12",
|
|
93
|
+
"@pnpm/workspace.state": "1100.0.23",
|
|
94
|
+
"@pnpm/workspace.projects-filter": "1100.0.22",
|
|
95
|
+
"@pnpm/workspace.root-finder": "1100.0.2",
|
|
96
|
+
"@pnpm/store.controller": "1102.0.1",
|
|
97
|
+
"@pnpm/workspace.workspace-manifest-writer": "1100.0.13"
|
|
95
98
|
},
|
|
96
99
|
"peerDependencies": {
|
|
97
|
-
"@pnpm/logger": "^
|
|
100
|
+
"@pnpm/logger": "^1100.0.0"
|
|
98
101
|
},
|
|
99
102
|
"devDependencies": {
|
|
100
|
-
"@jest/globals": "30.
|
|
103
|
+
"@jest/globals": "30.4.1",
|
|
104
|
+
"@types/js-yaml": "^4.0.9",
|
|
101
105
|
"@types/normalize-path": "^3.0.2",
|
|
102
106
|
"@types/proxyquire": "^1.3.31",
|
|
103
107
|
"@types/ramda": "0.31.1",
|
|
104
108
|
"@types/yarnpkg__lockfile": "^1.1.9",
|
|
105
|
-
"@types/zkochan__table": "npm:@types/table@6.
|
|
109
|
+
"@types/zkochan__table": "npm:@types/table@6.3.2",
|
|
106
110
|
"delay": "^7.0.0",
|
|
107
111
|
"jest-diff": "^30.4.1",
|
|
108
112
|
"path-name": "^1.0.0",
|
|
@@ -113,19 +117,19 @@
|
|
|
113
117
|
"write-json-file": "^7.0.0",
|
|
114
118
|
"write-package": "7.2.0",
|
|
115
119
|
"write-yaml-file": "^6.0.0",
|
|
116
|
-
"@pnpm/
|
|
117
|
-
"@pnpm/installing.
|
|
120
|
+
"@pnpm/installing.commands": "1100.10.0",
|
|
121
|
+
"@pnpm/installing.modules-yaml": "1100.0.9",
|
|
118
122
|
"@pnpm/logger": "1100.0.0",
|
|
119
|
-
"@pnpm/
|
|
120
|
-
"@pnpm/store.index": "1100.
|
|
121
|
-
"@pnpm/prepare": "1100.0.15",
|
|
122
|
-
"@pnpm/test-fixtures": "1100.0.0",
|
|
123
|
+
"@pnpm/assert-project": "1100.0.16",
|
|
124
|
+
"@pnpm/store.index": "1100.2.0",
|
|
123
125
|
"@pnpm/test-ipc-server": "1100.0.0",
|
|
124
|
-
"@pnpm/
|
|
125
|
-
"@pnpm/testing.
|
|
126
|
-
"@pnpm/
|
|
127
|
-
"@pnpm/
|
|
128
|
-
"@pnpm/
|
|
126
|
+
"@pnpm/prepare": "1100.0.16",
|
|
127
|
+
"@pnpm/testing.registry-mock": "1100.0.6",
|
|
128
|
+
"@pnpm/testing.command-defaults": "1100.0.6",
|
|
129
|
+
"@pnpm/testing.mock-agent": "1101.0.3",
|
|
130
|
+
"@pnpm/test-fixtures": "1100.0.0",
|
|
131
|
+
"@pnpm/worker": "1100.2.1",
|
|
132
|
+
"@pnpm/workspace.projects-filter": "1100.0.22"
|
|
129
133
|
},
|
|
130
134
|
"engines": {
|
|
131
135
|
"node": ">=22.13"
|