@pnpm/installing.commands 1100.4.1 → 1100.5.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 CHANGED
@@ -74,6 +74,7 @@ export function rcOptionsTypes() {
74
74
  'side-effects-cache',
75
75
  'store-dir',
76
76
  'strict-peer-dependencies',
77
+ 'trust-lockfile',
77
78
  'trust-policy',
78
79
  'trust-policy-exclude',
79
80
  'trust-policy-ignore-after',
package/lib/install.d.ts CHANGED
@@ -7,9 +7,11 @@ 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' | 'publicHoistPattern' | 'ignorePnpmfile' | 'ignoreScripts' | 'injectWorkspacePackages' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'modulesDir' | 'nodeLinker' | 'patchedDependencies' | 'preferFrozenLockfile' | 'preferWorkspacePackages' | 'production' | 'registries' | 'save' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveCatalogName' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'sideEffectsCache' | 'sideEffectsCacheReadonly' | 'sort' | 'sharedWorkspaceLockfile' | 'tag' | 'allowBuilds' | 'optional' | 'virtualStoreDir' | 'workspaceConcurrency' | 'workspaceDir' | 'workspacePackagePatterns' | 'extraEnv' | 'resolutionMode' | 'ignoreWorkspaceCycles' | 'disallowWorkspaceCycles' | 'updateConfig' | 'overrides' | 'packageExtensions' | 'agent' | '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' | 'enableGlobalVirtualStore' | 'engineStrict' | 'excludeLinksFromLockfile' | 'frozenLockfile' | 'global' | 'globalPnpmfile' | 'hoistPattern' | 'publicHoistPattern' | 'ignorePnpmfile' | 'ignoreScripts' | 'injectWorkspacePackages' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | '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' | 'agent' | 'supportedArchitectures' | 'packageConfigs'> & Pick<ConfigContext, 'allProjects' | 'cliOptions' | 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'allProjectsGraph' | 'selectedProjectsGraph'> & CreateStoreControllerOptions & Partial<Pick<Config, 'globalPkgDir'>> & {
11
11
  argv: {
12
+ cooked?: string[];
12
13
  original: string[];
14
+ remain?: string[];
13
15
  };
14
16
  fixLockfile?: boolean;
15
17
  frozenLockfileIfExists?: boolean;
package/lib/install.js CHANGED
@@ -61,6 +61,7 @@ export function rcOptionsTypes() {
61
61
  'side-effects-cache',
62
62
  'store-dir',
63
63
  'strict-peer-dependencies',
64
+ 'trust-lockfile',
64
65
  'trust-policy',
65
66
  'trust-policy-exclude',
66
67
  'trust-policy-ignore-after',
@@ -220,6 +221,10 @@ by any dependencies, so it is an emulation of a flat node_modules',
220
221
  description: 'Ignore trust downgrades for packages published more than specified minutes ago',
221
222
  name: '--trust-policy-ignore-after <minutes>',
222
223
  },
224
+ {
225
+ description: 'Trust the lockfile and skip the supply-chain verification step that re-applies minimumReleaseAge / trustPolicy to each lockfile entry. Use only when the lockfile is part of the trusted base (closed-source projects, CI runs against an already-verified lockfile)',
226
+ name: '--trust-lockfile',
227
+ },
223
228
  {
224
229
  description: 'Clones/hardlinks or copies packages. The selected method depends from the file system',
225
230
  name: '--package-import-method auto',
@@ -282,6 +287,7 @@ export async function handler(opts, _params, commands) {
282
287
  include,
283
288
  includeDirect: include,
284
289
  fetchFullMetadata: getFetchFullMetadata(opts),
290
+ isInstallCommand: true,
285
291
  };
286
292
  if (opts.resolutionOnly) {
287
293
  installDepsOptions.lockfileOnly = true;
@@ -4,9 +4,11 @@ import { 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' | 'agent' | 'production' | 'preferWorkspacePackages' | 'registries' | 'runtime' | 'runtimeOnFail' | 'save' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'scriptsPrependNodePath' | 'scriptShell' | 'sideEffectsCache' | 'sideEffectsCacheReadonly' | 'sort' | 'sharedWorkspaceLockfile' | 'shellEmulator' | 'tag' | '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' | 'agent' | '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 & {
8
8
  argv: {
9
+ cooked?: string[];
9
10
  original: string[];
11
+ remain?: string[];
10
12
  };
11
13
  allowNew?: boolean;
12
14
  forceFullResolution?: boolean;
@@ -39,5 +41,12 @@ export type InstallDepsOptions = Pick<Config, 'autoInstallPeers' | 'bail' | 'bin
39
41
  rebuildHandler?: CommandHandler;
40
42
  pnpmfile: string[];
41
43
  packageVulnerabilityAudit?: PackageVulnerabilityAudit;
44
+ /**
45
+ * `true` when this call originated from `pnpm install` (or `pnpm i`),
46
+ * `false`/`undefined` for `add`, `update`, `dedupe`, etc. Used to gate
47
+ * which pnpm CLI flags are safe to forward to pacquet's `install`
48
+ * subcommand — see `runPacquet.ts`'s `noRuntime` opt.
49
+ */
50
+ isInstallCommand?: boolean;
42
51
  } & Partial<Pick<Config, 'pnpmHomeDir' | 'strictDepBuilds'>>;
43
52
  export declare function installDeps(opts: InstallDepsOptions, params: string[]): Promise<void>;
@@ -76,7 +76,8 @@ export async function installDeps(opts, params) {
76
76
  ? makeRunPacquet({
77
77
  lockfileDir: opts.lockfileDir ?? opts.dir,
78
78
  packageName: pacquetConfigDepName,
79
- argv: opts.argv.original,
79
+ argv: { original: opts.argv.original, remain: opts.argv.remain ?? [] },
80
+ isInstallCommand: opts.isInstallCommand === true,
80
81
  })
81
82
  : undefined;
82
83
  const includeDirect = opts.includeDirect ?? {
@@ -6,7 +6,7 @@ import type { ResolutionVerifier } from '@pnpm/resolving.resolver-base';
6
6
  import { type CreateStoreControllerOptions } from '@pnpm/store.connection-manager';
7
7
  import type { StoreController } from '@pnpm/store.controller';
8
8
  import type { IncludedDependencies, Project, ProjectManifest, ProjectsGraph } from '@pnpm/types';
9
- export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config, 'bail' | 'configDependencies' | 'dedupePeerDependents' | 'dedupePeers' | 'depth' | 'globalPnpmfile' | 'hoistPattern' | 'ignorePnpmfile' | 'ignoreScripts' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'modulesDir' | 'agent' | 'allowBuilds' | 'registries' | 'runtime' | 'save' | 'saveCatalogName' | 'saveDev' | 'saveExact' | 'saveOptional' | 'savePeer' | 'savePrefix' | 'saveProd' | 'saveWorkspaceProtocol' | 'lockfileIncludeTarballUrl' | 'sharedWorkspaceLockfile' | 'tag' | 'cleanupUnusedCatalogs' | 'packageConfigs' | 'updateConfig'> & Pick<ConfigContext, 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir'> & {
9
+ export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config, 'bail' | 'configDependencies' | 'dedupePeerDependents' | 'dedupePeers' | 'depth' | 'globalPnpmfile' | 'hoistPattern' | 'ignorePnpmfile' | 'ignoreScripts' | 'linkWorkspacePackages' | 'lockfileDir' | 'lockfileOnly' | 'modulesDir' | 'agent' | '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
10
  rebuildHandler?: CommandHandler;
11
11
  include?: IncludedDependencies;
12
12
  includeDirect?: IncludedDependencies;
package/lib/remove.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare const cliOptionsTypes: () => Record<string, unknown>;
6
6
  export declare function help(): string;
7
7
  export declare const commandNames: string[];
8
8
  export declare const completion: CompletionFunc;
9
- export declare function handler(opts: CreateStoreControllerOptions & Pick<Config, 'bail' | 'bin' | 'configDependencies' | 'dev' | 'engineStrict' | 'globalPnpmfile' | 'ignorePnpmfile' | 'linkWorkspacePackages' | 'lockfileDir' | 'optional' | 'production' | 'registries' | 'saveDev' | 'saveOptional' | 'saveProd' | 'workspaceDir' | 'workspacePackagePatterns' | 'sharedWorkspaceLockfile' | 'cleanupUnusedCatalogs'> & Pick<ConfigContext, 'allProjects' | 'allProjectsGraph' | 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'selectedProjectsGraph'> & {
9
+ export declare function handler(opts: CreateStoreControllerOptions & Pick<Config, 'bail' | 'bin' | 'configDependencies' | 'dev' | 'engineStrict' | 'globalPnpmfile' | 'ignorePnpmfile' | 'linkWorkspacePackages' | 'lockfileDir' | 'optional' | 'production' | 'registries' | 'saveDev' | 'saveOptional' | 'saveProd' | 'workspaceDir' | 'workspacePackagePatterns' | 'sharedWorkspaceLockfile' | 'cleanupUnusedCatalogs' | 'trustLockfile'> & Pick<ConfigContext, 'allProjects' | 'allProjectsGraph' | 'hooks' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'selectedProjectsGraph'> & {
10
10
  recursive?: boolean;
11
11
  pnpmfile: string[];
12
12
  } & Partial<Pick<Config, 'global' | 'globalPkgDir'>>, params: string[]): Promise<void>;
@@ -10,26 +10,42 @@ export interface MakeRunPacquetOpts {
10
10
  */
11
11
  packageName: 'pacquet' | '@pnpm/pacquet';
12
12
  /**
13
- * The user's original `pnpm` argv (`process.argv.slice(2)`). Not
14
- * forwarded to pacquet we only inspect it to warn about flags
13
+ * The parsed pnpm argv from `@pnpm/cli.parse-cli-args` `original`
14
+ * preserves the user's exact tokens (so `--key=value` stays joined,
15
+ * which pacquet's `--config.<key>=<value>` parser requires), and
16
+ * `remain` lists the positionals (the `install`/`i` command token
17
+ * among them). When `isInstallCommand` is true we forward
18
+ * `original` minus positionals to pacquet's own `install`
19
+ * subcommand; otherwise we only inspect it to warn about flags
15
20
  * pacquet won't see.
16
21
  */
17
- argv: string[];
22
+ argv: {
23
+ original: string[];
24
+ remain: string[];
25
+ };
26
+ /**
27
+ * `true` when the user invoked `pnpm install` (or `pnpm i`). Gates
28
+ * flag forwarding: pacquet's `install` subcommand mirrors pnpm's
29
+ * surface closely enough that the user's flags are safe to pass
30
+ * along on that command, but not from `add`/`update`/`dedupe` (whose
31
+ * own flag surface doesn't line up with pacquet's `install`).
32
+ */
33
+ isInstallCommand: boolean;
18
34
  }
19
35
  /**
20
36
  * Build the install-engine callback `mutateModules` invokes when
21
- * `configDependencies` declares pacquet. Returns `undefined` when no
22
- * pacquet binary is on disk — the caller falls back to the JS path in
23
- * that case.
37
+ * `configDependencies` declares pacquet.
24
38
  *
25
39
  * The callback spawns the pacquet binary installed under
26
- * `node_modules/.pnpm-config/pacquet` and forwards the user's own
27
- * pnpm CLI flags. Pacquet's NDJSON stderr is parsed line-by-line and
28
- * the valid JSON records are re-emitted on pnpm's global
29
- * `streamParser` so `@pnpm/cli.default-reporter` renders pacquet's
30
- * events the same way it renders pnpm's own. Non-JSON stderr lines
31
- * (panic backtraces, unexpected diagnostics) are forwarded to the
32
- * real stderr verbatim so they reach the user.
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.
33
49
  */
34
50
  /** Args the deps-installer passes per pacquet invocation. */
35
51
  export interface RunPacquetCallOpts {
package/lib/runPacquet.js CHANGED
@@ -14,15 +14,27 @@ const streamParserWritable = streamParser;
14
14
  export function makeRunPacquet(opts) {
15
15
  return async (callOpts) => {
16
16
  const pacquetBin = resolvePacquetBin(opts.lockfileDir, opts.packageName);
17
- // Always the same fixed args. We don't forward pnpm's CLI flags
18
- // even though pacquet's `install` subcommand mirrors most of them:
19
- // pnpm has commands like `add` and `update` that carry flags
20
- // pacquet's `install` doesn't recognize (e.g., `--save-dev`,
21
- // `--save-peer`), and clap would reject them. The settings users
22
- // care about live in `pnpm-workspace.yaml` / `.npmrc`, which
23
- // pacquet reads on its own.
24
- const args = ['--reporter=ndjson', 'install', '--frozen-lockfile'];
25
- const droppedFlags = collectDroppedFlags(opts.argv);
17
+ // From `pnpm install`/`pnpm i` we forward the user's flags through to
18
+ // pacquet's own `install` subcommand verbatim pacquet mirrors pnpm's
19
+ // surface closely enough on that command that they're safe to pass
20
+ // along. From `add`/`update`/`dedupe` we don't forward anything: those
21
+ // commands carry flags pacquet's `install` doesn't recognize
22
+ // (`--save-dev`, `--save-peer`, etc.) which clap would reject. Either
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.
26
+ const forwardedFlags = opts.isInstallCommand ? collectForwardedFlags(opts.argv) : [];
27
+ // `--ignore-manifest-check` tells pacquet to skip its per-importer
28
+ // `package.json` ↔ `pnpm-lock.yaml` freshness gate. pnpm just
29
+ // resolved and wrote the lockfile itself; on `pnpm up` / `add` /
30
+ // `remove` the manifest on disk is still the pre-mutation copy
31
+ // (pnpm writes it after `mutateModules` returns), so pacquet's own
32
+ // check would always fire here. See
33
+ // https://github.com/pnpm/pnpm/issues/11797. The flag is narrow
34
+ // (only the manifest check); settings drift like `overrides` is
35
+ // still enforced and was already re-validated by pnpm.
36
+ const args = ['--reporter=ndjson', 'install', '--frozen-lockfile', '--ignore-manifest-check', ...forwardedFlags];
37
+ const droppedFlags = opts.isInstallCommand ? [] : collectDroppedFlags(opts.argv);
26
38
  if (droppedFlags.length > 0) {
27
39
  logger.warn({
28
40
  message: `The following CLI flags are not forwarded to pacquet and may not be honored: ${droppedFlags.join(' ')}. Move the equivalent settings into pnpm-workspace.yaml (or .npmrc for auth/registry) if pacquet needs them.`,
@@ -99,28 +111,103 @@ function resolvePacquetBin(lockfileDir, packageName) {
99
111
  return createRequire(pacquetPkg).resolve(`@pacquet/${process.platform}-${process.arch}/pacquet${ext}`);
100
112
  }
101
113
  /**
102
- * Pull the CLI flags out of pnpm's argv so we can warn about them
103
- * before pacquet runs. We don't forward any of them — pacquet always
104
- * gets `install --frozen-lockfile --reporter=ndjson` but most are
105
- * handled by pnpm itself before delegation (`--save-dev` rewrites
106
- * `package.json`, `--filter` selects projects, etc.) so listing them
107
- * to the user makes the "not forwarded" surface concrete.
114
+ * From `pnpm install`/`pnpm i`, return everything in argv that should
115
+ * ride along to pacquet's own `install` subcommand. Drops the
116
+ * positionals nopt classified (`install` / `i`, plus anything users
117
+ * typed positionally) since pacquet's `install` doesn't accept any —
118
+ * leaving them in produces `error: unexpected argument 'install'
119
+ * found`. Pacquet's clap parser walks the same `--prod`, `--dev`,
120
+ * `--no-optional`, `--no-runtime`, `--node-linker`, `--offline`,
121
+ * `--prefer-offline`, `--cpu`, `--os`, `--libc`, `--frozen-lockfile`
122
+ * surface pnpm itself accepts on `install`, so the flags don't need
123
+ * reshaping.
108
124
  *
109
- * Flags we explicitly emit ourselves (`--frozen-lockfile`,
110
- * `--reporter=ndjson`) are filtered out: they're honored, so warning
111
- * about them would be misleading. `--config.*` is filtered too —
112
- * those configure pnpm's runtime and aren't intended for the install
113
- * engine.
125
+ * Flags we always inject ourselves (`--frozen-lockfile`,
126
+ * `--ignore-manifest-check`) are dropped in every form the user can
127
+ * type them positive (`--frozen-lockfile`), negated
128
+ * (`--no-frozen-lockfile`), and any `=value` form. Pacquet's clap
129
+ * defines these as plain `#[clap(long)] bool` flags, so a duplicate
130
+ * `--frozen-lockfile` or a conflicting `--no-frozen-lockfile`
131
+ * crashes the parser with "used multiple times" / "unexpected
132
+ * argument". The user's `--no-frozen-lockfile` intent is already
133
+ * honored upstream (pnpm did a fresh resolve before delegating);
134
+ * pacquet's role here is just lockfile-driven materialization.
135
+ *
136
+ * `--reporter` is stripped in any form (`--reporter=foo`,
137
+ * `--reporter foo`): pacquet's `reporter` is a clap value option
138
+ * with last-value-wins semantics, so a user-supplied value would
139
+ * override our `--reporter=ndjson` and break the
140
+ * NDJSON-to-streamParser plumbing the default reporter relies on.
141
+ */
142
+ function collectForwardedFlags(argv) {
143
+ const result = [];
144
+ // `argv.remain` is the ordered subsequence of positionals nopt
145
+ // extracted from `original`. Match by index rather than by value so
146
+ // an option's value that happens to equal a positional (e.g.
147
+ // `--node-linker install`) isn't mistaken for the positional itself.
148
+ let positionalIdx = 0;
149
+ for (let i = 0; i < argv.original.length; i++) {
150
+ const arg = argv.original[i];
151
+ if (positionalIdx < argv.remain.length && arg === argv.remain[positionalIdx]) {
152
+ positionalIdx++;
153
+ continue;
154
+ }
155
+ if (isAlwaysInjected(arg))
156
+ continue;
157
+ if (arg.startsWith('--reporter='))
158
+ continue;
159
+ if (arg === '--reporter') {
160
+ // Consume the next token as the reporter value (`--reporter foo`).
161
+ i++;
162
+ continue;
163
+ }
164
+ result.push(arg);
165
+ }
166
+ return result;
167
+ }
168
+ const ALWAYS_INJECTED_FLAGS = ['frozen-lockfile', 'ignore-manifest-check'];
169
+ function isAlwaysInjected(arg) {
170
+ for (const name of ALWAYS_INJECTED_FLAGS) {
171
+ if (arg === `--${name}` || arg === `--no-${name}`)
172
+ return true;
173
+ if (arg.startsWith(`--${name}=`) || arg.startsWith(`--no-${name}=`))
174
+ return true;
175
+ }
176
+ return false;
177
+ }
178
+ /**
179
+ * From a non-install command (`add`, `update`, `dedupe`, ...), pull the
180
+ * CLI flags out of pnpm's argv so we can warn that pacquet won't see
181
+ * them. They're still handled by pnpm itself before delegation
182
+ * (`--save-dev` rewrites `package.json`, `--filter` selects projects,
183
+ * etc.) so listing them to the user makes the "not forwarded" surface
184
+ * concrete.
185
+ *
186
+ * Flags pnpm itself honors before delegation are filtered out —
187
+ * warning about them would be misleading: `--frozen-lockfile` and
188
+ * `--ignore-manifest-check` in every shape (positive / negated /
189
+ * `=value`); `--reporter` in every shape (`--reporter=foo`,
190
+ * `--reporter foo`); and `--config.*` (configures pnpm's runtime,
191
+ * not the install engine).
114
192
  */
115
193
  function collectDroppedFlags(argv) {
116
- return argv.filter((arg) => {
194
+ const result = [];
195
+ for (let i = 0; i < argv.original.length; i++) {
196
+ const arg = argv.original[i];
117
197
  if (!arg.startsWith('-'))
118
- return false;
119
- if (arg === '--frozen-lockfile' || arg === '--reporter=ndjson')
120
- return false;
198
+ continue;
199
+ if (isAlwaysInjected(arg))
200
+ continue;
121
201
  if (arg.startsWith('--config.'))
122
- return false;
123
- return true;
124
- });
202
+ continue;
203
+ if (arg.startsWith('--reporter='))
204
+ continue;
205
+ if (arg === '--reporter') {
206
+ i++;
207
+ continue;
208
+ }
209
+ result.push(arg);
210
+ }
211
+ return result;
125
212
  }
126
213
  //# sourceMappingURL=runPacquet.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/installing.commands",
3
- "version": "1100.4.1",
3
+ "version": "1100.5.0",
4
4
  "description": "Commands for installation",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -44,46 +44,46 @@
44
44
  "ramda": "npm:@pnpm/ramda@0.28.1",
45
45
  "render-help": "^2.0.0",
46
46
  "version-selector-type": "^3.0.0",
47
- "@pnpm/building.after-install": "1101.0.15",
47
+ "@pnpm/building.after-install": "1101.0.16",
48
48
  "@pnpm/catalogs.types": "1100.0.0",
49
49
  "@pnpm/cli.command": "1100.0.1",
50
+ "@pnpm/cli.utils": "1101.0.7",
50
51
  "@pnpm/cli.common-cli-options-help": "1100.0.1",
51
- "@pnpm/cli.utils": "1101.0.6",
52
52
  "@pnpm/config.matcher": "1100.0.1",
53
53
  "@pnpm/config.pick-registry-for-package": "1100.0.5",
54
- "@pnpm/config.reader": "1101.3.3",
55
- "@pnpm/config.writer": "1100.0.9",
56
- "@pnpm/deps.inspection.outdated": "1100.1.1",
54
+ "@pnpm/config.reader": "1101.4.0",
57
55
  "@pnpm/constants": "1100.0.0",
58
- "@pnpm/deps.path": "1100.0.4",
56
+ "@pnpm/config.writer": "1100.0.9",
59
57
  "@pnpm/error": "1100.0.0",
58
+ "@pnpm/deps.inspection.outdated": "1100.1.2",
60
59
  "@pnpm/fs.graceful-fs": "1100.1.0",
61
- "@pnpm/deps.status": "1100.0.17",
62
60
  "@pnpm/fs.read-modules-dir": "1100.0.1",
63
- "@pnpm/global.commands": "1100.0.20",
61
+ "@pnpm/global.commands": "1100.0.21",
62
+ "@pnpm/deps.status": "1100.0.18",
64
63
  "@pnpm/hooks.pnpmfile": "1100.0.10",
64
+ "@pnpm/deps.path": "1100.0.4",
65
65
  "@pnpm/installing.context": "1100.0.12",
66
66
  "@pnpm/installing.dedupe.check": "1100.0.7",
67
- "@pnpm/installing.deps-installer": "1101.3.1",
67
+ "@pnpm/installing.deps-installer": "1101.4.0",
68
+ "@pnpm/installing.env-installer": "1101.1.2",
68
69
  "@pnpm/lockfile.types": "1100.0.7",
69
- "@pnpm/installing.env-installer": "1101.1.1",
70
70
  "@pnpm/pkg-manifest.reader": "1100.0.4",
71
71
  "@pnpm/pkg-manifest.utils": "1100.2.0",
72
- "@pnpm/resolving.npm-resolver": "1101.3.1",
72
+ "@pnpm/resolving.npm-resolver": "1101.3.2",
73
73
  "@pnpm/resolving.parse-wanted-dependency": "1100.0.1",
74
74
  "@pnpm/resolving.resolver-base": "1100.3.0",
75
- "@pnpm/store.connection-manager": "1100.2.2",
75
+ "@pnpm/store.connection-manager": "1100.2.3",
76
76
  "@pnpm/store.controller": "1101.0.8",
77
77
  "@pnpm/types": "1101.1.1",
78
- "@pnpm/workspace.project-manifest-reader": "1100.0.7",
78
+ "@pnpm/workspace.project-manifest-reader": "1100.0.8",
79
79
  "@pnpm/workspace.project-manifest-writer": "1100.0.4",
80
- "@pnpm/workspace.projects-filter": "1100.0.14",
81
- "@pnpm/workspace.projects-graph": "1100.0.11",
82
- "@pnpm/workspace.projects-reader": "1101.0.6",
80
+ "@pnpm/workspace.projects-filter": "1100.0.15",
81
+ "@pnpm/workspace.projects-reader": "1101.0.7",
83
82
  "@pnpm/workspace.projects-sorter": "1100.0.3",
84
- "@pnpm/workspace.root-finder": "1100.0.1",
85
- "@pnpm/workspace.state": "1100.0.14",
86
- "@pnpm/workspace.workspace-manifest-writer": "1100.0.9"
83
+ "@pnpm/workspace.projects-graph": "1100.0.12",
84
+ "@pnpm/workspace.state": "1100.0.15",
85
+ "@pnpm/workspace.workspace-manifest-writer": "1100.0.9",
86
+ "@pnpm/workspace.root-finder": "1100.0.1"
87
87
  },
88
88
  "peerDependencies": {
89
89
  "@pnpm/logger": ">=1001.0.0 <1002.0.0"
@@ -107,7 +107,7 @@
107
107
  "write-package": "7.2.0",
108
108
  "write-yaml-file": "^6.0.0",
109
109
  "@pnpm/assert-project": "1100.0.10",
110
- "@pnpm/installing.commands": "1100.4.1",
110
+ "@pnpm/installing.commands": "1100.5.0",
111
111
  "@pnpm/logger": "1100.0.0",
112
112
  "@pnpm/prepare": "1100.0.10",
113
113
  "@pnpm/installing.modules-yaml": "1100.0.5",
@@ -117,7 +117,7 @@
117
117
  "@pnpm/testing.command-defaults": "1100.0.1",
118
118
  "@pnpm/testing.mock-agent": "1100.0.6",
119
119
  "@pnpm/worker": "1100.1.7",
120
- "@pnpm/workspace.projects-filter": "1100.0.14"
120
+ "@pnpm/workspace.projects-filter": "1100.0.15"
121
121
  },
122
122
  "engines": {
123
123
  "node": ">=22.13"