@pnpm/exec.commands 1100.2.5 → 1100.3.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/dlx.js CHANGED
@@ -8,10 +8,11 @@ import { OUTPUT_OPTIONS } from '@pnpm/cli.common-cli-options-help';
8
8
  import { docsUrl, readProjectManifestOnly } from '@pnpm/cli.utils';
9
9
  import { types } from '@pnpm/config.reader';
10
10
  import { getPublishedByPolicy } from '@pnpm/config.version-policy';
11
- import { createHexHash } from '@pnpm/crypto.hash';
11
+ import { createShortHash } from '@pnpm/crypto.hash';
12
12
  import { PnpmError } from '@pnpm/error';
13
13
  import { createResolver, makeResolutionStrict } from '@pnpm/installing.client';
14
14
  import { add } from '@pnpm/installing.commands';
15
+ import { logger } from '@pnpm/logger';
15
16
  import { readPackageJsonFromDir } from '@pnpm/pkg-manifest.reader';
16
17
  import { parseWantedDependency } from '@pnpm/resolving.parse-wanted-dependency';
17
18
  import { lexCompare } from '@pnpm/util.lex-comparator';
@@ -186,8 +187,23 @@ export async function handler(opts, [command, ...args], commands) {
186
187
  }
187
188
  else {
188
189
  // Drop the partially-populated cache so a subsequent dlx run starts
189
- // clean instead of reusing a broken install.
190
- await fs.promises.rm(cachedDir, { recursive: true, force: true });
190
+ // clean instead of reusing a broken install. This is best-effort: on
191
+ // Windows the just-run install scripts (or antivirus) can briefly hold
192
+ // handles on freshly written files, so retry with backoff. A cleanup
193
+ // failure must never mask the original install error, which is the one
194
+ // worth surfacing — log it and rethrow err. A leftover prepare dir is
195
+ // harmless: it has a unique name and findCache only trusts the `pkg`
196
+ // symlink.
197
+ try {
198
+ await fs.promises.rm(cachedDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
199
+ }
200
+ catch (cleanupErr) {
201
+ logger.warn({
202
+ error: cleanupErr,
203
+ message: `Failed to clean up the dlx cache directory at "${cachedDir}"`,
204
+ prefix: cachedDir,
205
+ });
206
+ }
191
207
  throw err;
192
208
  }
193
209
  }
@@ -353,7 +369,12 @@ export function createCacheKey(opts) {
353
369
  }
354
370
  }
355
371
  const hashStr = JSON.stringify(args);
356
- return createHexHash(hashStr);
372
+ // A short (truncated) hash keeps the dlx cache path short. The full
373
+ // virtual-store path below it (`<key>/<prepare>/node_modules/.pnpm/<pkgId>/
374
+ // node_modules/<pkg>`) can otherwise blow past Windows' MAX_PATH (260) and
375
+ // make lifecycle scripts fail with a `spawn cmd.exe ENOENT` (the cwd no
376
+ // longer resolves). 128 bits is ample collision resistance for a cache key.
377
+ return createShortHash(hashStr);
357
378
  }
358
379
  function getValidCacheDir(cacheLink, dlxCacheMaxAge) {
359
380
  let stats;
@@ -379,7 +400,10 @@ function getValidCacheDir(cacheLink, dlxCacheMaxAge) {
379
400
  return isValid ? target : undefined;
380
401
  }
381
402
  function getPrepareDir(cachePath) {
382
- const name = `${new Date().getTime().toString(16)}-${process.pid.toString(16)}`;
403
+ // base36 (vs hex) keeps this segment short — see createCacheKey for why dlx
404
+ // path length matters on Windows. time+pid stays unique across concurrent
405
+ // dlx processes and across a process's own retries of a failed install.
406
+ const name = `${Date.now().toString(36)}-${process.pid.toString(36)}`;
383
407
  return path.join(cachePath, name);
384
408
  }
385
409
  function resolveCatalogProtocol(catalogResolver, alias, bareSpecifier) {
package/lib/exec.d.ts CHANGED
@@ -28,7 +28,7 @@ export type ExecOpts = Required<Pick<ConfigContext, 'selectedProjectsGraph'>> &
28
28
  resumeFrom?: string;
29
29
  reportSummary?: boolean;
30
30
  implicitlyFellbackFromRun?: boolean;
31
- } & Pick<Config, 'bin' | 'dir' | 'extraBinPaths' | 'extraEnv' | 'lockfileDir' | 'modulesDir' | 'nodeOptions' | 'pnpmHomeDir' | 'recursive' | 'reporter' | 'reporterHidePrefix' | 'userAgent' | 'verifyDepsBeforeRun' | 'workspaceDir'> & Pick<ConfigContext, 'cliOptions'> & CheckDepsStatusOptions;
31
+ } & Pick<Config, 'bin' | 'dir' | 'extraBinPaths' | 'extraEnv' | 'lockfileDir' | 'modulesDir' | 'nodeOptions' | 'nodeExperimentalPackageMap' | 'pnpmHomeDir' | 'recursive' | 'reporter' | 'reporterHidePrefix' | 'userAgent' | 'verifyDepsBeforeRun' | 'workspaceDir'> & Pick<ConfigContext, 'cliOptions'> & CheckDepsStatusOptions;
32
32
  export declare function handler(opts: ExecOpts, params: string[]): Promise<{
33
33
  exitCode: number;
34
34
  }>;
package/lib/exec.js CHANGED
@@ -4,7 +4,7 @@ import { docsUrl, readProjectManifestOnly, throwOnCommandFail } from '@pnpm/cli.
4
4
  import { getWorkspaceConcurrency, types } from '@pnpm/config.reader';
5
5
  import { lifecycleLogger } from '@pnpm/core-loggers';
6
6
  import { PnpmError } from '@pnpm/error';
7
- import { makeNodeRequireOption } from '@pnpm/exec.lifecycle';
7
+ import { makeNodePackageMapOption, makeNodeRequireOption } from '@pnpm/exec.lifecycle';
8
8
  import { logger } from '@pnpm/logger';
9
9
  import { prependDirsToPath } from '@pnpm/shell.path';
10
10
  import { tryReadProjectManifest } from '@pnpm/workspace.project-manifest-reader';
@@ -33,6 +33,8 @@ export function rcOptionsTypes() {
33
33
  'unsafe-perm',
34
34
  'workspace-concurrency',
35
35
  'reporter-hide-prefix',
36
+ 'node-experimental-package-map',
37
+ 'node-package-map-type',
36
38
  ], types),
37
39
  'shell-mode': Boolean,
38
40
  'resume-from': String,
@@ -156,6 +158,8 @@ export async function handler(opts, params) {
156
158
  const result = createEmptyRecursiveSummary(chunks);
157
159
  const existsPnp = existsInDir.bind(null, '.pnp.cjs');
158
160
  const workspacePnpPath = opts.workspaceDir && existsPnp(opts.workspaceDir);
161
+ const existsPackageMap = existsInDir.bind(null, path.join(opts.modulesDir ?? 'node_modules', '.package-map.json'));
162
+ const workspacePackageMapPath = opts.nodeExperimentalPackageMap && opts.workspaceDir && existsPackageMap(opts.workspaceDir);
159
163
  let exitCode = 0;
160
164
  const prependPaths = [
161
165
  './node_modules/.bin',
@@ -169,15 +173,21 @@ export async function handler(opts, params) {
169
173
  const startTime = process.hrtime();
170
174
  try {
171
175
  const pnpPath = workspacePnpPath ?? existsPnp(prefix);
176
+ const packageMapPath = workspacePackageMapPath || (opts.nodeExperimentalPackageMap && existsPackageMap(prefix));
172
177
  const extraEnv = {
173
178
  ...opts.extraEnv,
174
- ...(pnpPath ? makeNodeRequireOption(pnpPath) : {}),
179
+ ...(opts.nodeOptions ? { NODE_OPTIONS: opts.nodeOptions } : {}),
175
180
  };
181
+ if (pnpPath) {
182
+ Object.assign(extraEnv, makeNodeRequireOption(pnpPath, extraEnv));
183
+ }
184
+ if (packageMapPath) {
185
+ Object.assign(extraEnv, makeNodePackageMapOption(packageMapPath, extraEnv));
186
+ }
176
187
  const env = makeEnv({
177
188
  extraEnv: {
178
189
  ...extraEnv,
179
190
  PNPM_PACKAGE_NAME: opts.selectedProjectsGraph[prefix]?.package.manifest.name,
180
- ...(opts.nodeOptions ? { NODE_OPTIONS: opts.nodeOptions } : {}),
181
191
  },
182
192
  prependPaths,
183
193
  userAgent: opts.userAgent,
package/lib/run.d.ts CHANGED
@@ -24,7 +24,7 @@ export declare const commandNames: string[];
24
24
  export declare function help(): string;
25
25
  export type RunOpts = Omit<RecursiveRunOpts, 'allProjects' | 'selectedProjectsGraph' | 'workspaceDir'> & {
26
26
  recursive?: boolean;
27
- } & Pick<Config, 'bin' | 'verifyDepsBeforeRun' | 'dir' | 'enablePrePostScripts' | 'engineStrict' | 'extraBinPaths' | 'extraEnv' | 'nodeOptions' | 'pnpmHomeDir' | 'reporter' | 'scriptShell' | 'scriptsPrependNodePath' | 'shellEmulator' | 'syncInjectedDepsAfterScripts' | 'userAgent'> & Pick<ConfigContext, 'cliOptions'> & (({
27
+ } & Pick<Config, 'bin' | 'verifyDepsBeforeRun' | 'dir' | 'enablePrePostScripts' | 'engineStrict' | 'extraBinPaths' | 'extraEnv' | 'nodeOptions' | 'nodeExperimentalPackageMap' | 'pnpmHomeDir' | 'reporter' | 'scriptShell' | 'scriptsPrependNodePath' | 'shellEmulator' | 'syncInjectedDepsAfterScripts' | 'userAgent'> & Pick<ConfigContext, 'cliOptions'> & (({
28
28
  recursive?: false;
29
29
  } & Partial<Pick<ConfigContext, 'allProjects' | 'selectedProjectsGraph'> & Pick<Config, 'workspaceDir'>>) | ({
30
30
  recursive: true;
package/lib/run.js CHANGED
@@ -3,7 +3,7 @@ import { FILTERING, UNIVERSAL_OPTIONS } from '@pnpm/cli.common-cli-options-help'
3
3
  import { docsUrl, readProjectManifestOnly, tryReadProjectManifest, } from '@pnpm/cli.utils';
4
4
  import { getWorkspaceConcurrency, types as allTypes } from '@pnpm/config.reader';
5
5
  import { PnpmError } from '@pnpm/error';
6
- import { makeNodeRequireOption, runLifecycleHook, } from '@pnpm/exec.lifecycle';
6
+ import { makeNodePackageMapOption, makeNodeRequireOption, runLifecycleHook, } from '@pnpm/exec.lifecycle';
7
7
  import { syncInjectedDeps } from '@pnpm/workspace.injected-deps-syncer';
8
8
  import pLimit from 'p-limit';
9
9
  import { pick } from 'ramda';
@@ -60,6 +60,8 @@ export function rcOptionsTypes() {
60
60
  return {
61
61
  ...pick([
62
62
  'npm-path',
63
+ 'node-experimental-package-map',
64
+ 'node-package-map-type',
63
65
  ], allTypes),
64
66
  };
65
67
  }
@@ -104,7 +106,7 @@ For options that may be used with `-r`, see "pnpm help recursive"',
104
106
  shortAlias: '-r',
105
107
  },
106
108
  {
107
- description: 'The command will exit with a 0 exit code even if the script fails',
109
+ description: 'Continue running the remaining scripts even if one of them fails, instead of aborting on the first failure. The command still exits with a non-zero exit code if any script failed',
108
110
  name: '--no-bail',
109
111
  },
110
112
  IF_PRESENT_OPTION_HELP,
@@ -214,22 +216,40 @@ so you may run "pnpm -w run ${scriptName}"`,
214
216
  if (pnpPath) {
215
217
  lifecycleOpts.extraEnv = {
216
218
  ...lifecycleOpts.extraEnv,
217
- ...makeNodeRequireOption(pnpPath),
219
+ ...makeNodeRequireOption(pnpPath, lifecycleOpts.extraEnv),
218
220
  };
219
221
  }
220
- try {
221
- const limitRun = pLimit(concurrency);
222
- const runScriptOptions = {
223
- enablePrePostScripts: opts.enablePrePostScripts ?? false,
224
- syncInjectedDepsAfterScripts: opts.syncInjectedDepsAfterScripts,
225
- workspaceDir: opts.workspaceDir,
222
+ const existsPackageMap = existsInDir.bind(null, path.join(opts.modulesDir ?? 'node_modules', '.package-map.json'));
223
+ const packageMapPath = opts.nodeExperimentalPackageMap
224
+ ? (opts.workspaceDir && existsPackageMap(opts.workspaceDir)) ?? existsPackageMap(dir)
225
+ : undefined;
226
+ if (packageMapPath) {
227
+ lifecycleOpts.extraEnv = {
228
+ ...lifecycleOpts.extraEnv,
229
+ ...makeNodePackageMapOption(packageMapPath, lifecycleOpts.extraEnv),
226
230
  };
227
- const _runScript = runScript.bind(null, { manifest, lifecycleOpts, runScriptOptions, passedThruArgs });
231
+ }
232
+ const limitRun = pLimit(concurrency);
233
+ const runScriptOptions = {
234
+ enablePrePostScripts: opts.enablePrePostScripts ?? false,
235
+ syncInjectedDepsAfterScripts: opts.syncInjectedDepsAfterScripts,
236
+ workspaceDir: opts.workspaceDir,
237
+ };
238
+ const _runScript = runScript.bind(null, { manifest, lifecycleOpts, runScriptOptions, passedThruArgs });
239
+ if (opts.bail !== false) {
228
240
  await Promise.all(specifiedScripts.map(script => limitRun(() => _runScript(script))));
229
241
  }
230
- catch (err) {
231
- if (opts.bail !== false) {
232
- throw err;
242
+ else {
243
+ const results = await Promise.allSettled(specifiedScripts.map(script => limitRun(() => _runScript(script))));
244
+ const failures = results
245
+ .map((result, index) => ({ result, script: specifiedScripts[index] }))
246
+ .filter((entry) => entry.result.status === 'rejected');
247
+ if (failures.length > 0) {
248
+ throw new PnpmError('RUN_FAILED', `Some scripts failed: ${failures.length} of ${specifiedScripts.length}`, {
249
+ hint: failures
250
+ .map(({ script, result }) => `${script}: ${result.reason?.message ?? String(result.reason)}`)
251
+ .join('\n'),
252
+ });
233
253
  }
234
254
  }
235
255
  return undefined;
@@ -1,6 +1,6 @@
1
1
  import { type Config, type ConfigContext } from '@pnpm/config.reader';
2
2
  import type { PackageScripts } from '@pnpm/types';
3
- export type RecursiveRunOpts = Pick<Config, 'bin' | 'enablePrePostScripts' | 'unsafePerm' | 'pnpmHomeDir' | 'requiredScripts' | 'userAgent' | 'scriptsPrependNodePath' | 'scriptShell' | 'shellEmulator' | 'stream' | 'syncInjectedDepsAfterScripts' | 'workspaceDir'> & Pick<ConfigContext, 'rootProjectManifest'> & Required<Pick<ConfigContext, 'allProjects' | 'selectedProjectsGraph'> & Pick<Config, 'workspaceDir' | 'dir'>> & Partial<Pick<Config, 'extraBinPaths' | 'extraEnv' | 'bail' | 'reporter' | 'reverse' | 'sort' | 'workspaceConcurrency'>> & {
3
+ export type RecursiveRunOpts = Pick<Config, 'bin' | 'enablePrePostScripts' | 'unsafePerm' | 'pnpmHomeDir' | 'requiredScripts' | 'userAgent' | 'scriptsPrependNodePath' | 'scriptShell' | 'shellEmulator' | 'stream' | 'syncInjectedDepsAfterScripts' | 'workspaceDir' | 'nodeExperimentalPackageMap' | 'modulesDir'> & Pick<ConfigContext, 'rootProjectManifest'> & Required<Pick<ConfigContext, 'allProjects' | 'selectedProjectsGraph'> & Pick<Config, 'workspaceDir' | 'dir'>> & Partial<Pick<Config, 'extraBinPaths' | 'extraEnv' | 'bail' | 'reporter' | 'reverse' | 'sort' | 'workspaceConcurrency'>> & {
4
4
  ifPresent?: boolean;
5
5
  resumeFrom?: string;
6
6
  reportSummary?: boolean;
@@ -4,7 +4,7 @@ import util from 'node:util';
4
4
  import { throwOnCommandFail } from '@pnpm/cli.utils';
5
5
  import { getWorkspaceConcurrency } from '@pnpm/config.reader';
6
6
  import { PnpmError } from '@pnpm/error';
7
- import { makeNodeRequireOption, } from '@pnpm/exec.lifecycle';
7
+ import { makeNodePackageMapOption, makeNodeRequireOption, } from '@pnpm/exec.lifecycle';
8
8
  import { groupStart } from '@pnpm/log.group';
9
9
  import { sortProjects } from '@pnpm/workspace.projects-sorter';
10
10
  import pLimit from 'p-limit';
@@ -39,6 +39,8 @@ export async function runRecursive(params, opts) {
39
39
  : 'pipe';
40
40
  const existsPnp = existsInDir.bind(null, '.pnp.cjs');
41
41
  const workspacePnpPath = opts.workspaceDir && existsPnp(opts.workspaceDir);
42
+ const existsPackageMap = existsInDir.bind(null, path.join(opts.modulesDir ?? 'node_modules', '.package-map.json'));
43
+ const workspacePackageMapPath = opts.nodeExperimentalPackageMap && opts.workspaceDir && existsPackageMap(opts.workspaceDir);
42
44
  const requiredScripts = opts.requiredScripts ?? [];
43
45
  if (requiredScripts.includes(scriptName)) {
44
46
  const missingScriptPackages = packageChunks
@@ -93,7 +95,14 @@ export async function runRecursive(params, opts) {
93
95
  if (pnpPath) {
94
96
  lifecycleOpts.extraEnv = {
95
97
  ...lifecycleOpts.extraEnv,
96
- ...makeNodeRequireOption(pnpPath),
98
+ ...makeNodeRequireOption(pnpPath, lifecycleOpts.extraEnv),
99
+ };
100
+ }
101
+ const packageMapPath = workspacePackageMapPath || (opts.nodeExperimentalPackageMap && existsPackageMap(prefix));
102
+ if (packageMapPath) {
103
+ lifecycleOpts.extraEnv = {
104
+ ...lifecycleOpts.extraEnv,
105
+ ...makeNodePackageMapOption(packageMapPath, lifecycleOpts.extraEnv),
97
106
  };
98
107
  }
99
108
  const runScriptOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/exec.commands",
3
- "version": "1100.2.5",
3
+ "version": "1100.3.1",
4
4
  "description": "Commands for running scripts",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -11,9 +11,9 @@
11
11
  "funding": "https://opencollective.com/pnpm",
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "https://github.com/pnpm/pnpm/tree/main/exec/commands"
14
+ "url": "https://github.com/pnpm/pnpm/tree/main/pnpm11/exec/commands"
15
15
  },
16
- "homepage": "https://github.com/pnpm/pnpm/tree/main/exec/commands#readme",
16
+ "homepage": "https://github.com/pnpm/pnpm/tree/main/pnpm11/exec/commands#readme",
17
17
  "bugs": {
18
18
  "url": "https://github.com/pnpm/pnpm/issues"
19
19
  },
@@ -41,31 +41,31 @@
41
41
  "symlink-dir": "^10.0.1",
42
42
  "which": "npm:@pnpm/which@^3.0.1",
43
43
  "write-json-file": "^7.0.0",
44
+ "@pnpm/building.commands": "1100.1.7",
44
45
  "@pnpm/bins.resolver": "1100.0.8",
45
46
  "@pnpm/cli.command": "1100.0.1",
46
- "@pnpm/cli.utils": "1101.0.12",
47
- "@pnpm/config.reader": "1101.9.0",
48
- "@pnpm/config.version-policy": "1100.1.5",
49
- "@pnpm/building.commands": "1100.1.5",
47
+ "@pnpm/cli.common-cli-options-help": "1100.0.2",
48
+ "@pnpm/cli.utils": "1101.0.13",
49
+ "@pnpm/config.reader": "1101.10.1",
50
50
  "@pnpm/catalogs.resolver": "1100.0.0",
51
- "@pnpm/deps.status": "1100.1.1",
52
- "@pnpm/engine.runtime.commands": "1100.1.5",
53
- "@pnpm/error": "1100.0.0",
51
+ "@pnpm/config.version-policy": "1100.1.6",
54
52
  "@pnpm/core-loggers": "1100.2.1",
55
53
  "@pnpm/crypto.hash": "1100.0.1",
56
- "@pnpm/exec.lifecycle": "1100.0.18",
57
- "@pnpm/installing.commands": "1100.9.0",
58
- "@pnpm/installing.client": "1100.2.8",
54
+ "@pnpm/deps.status": "1100.1.3",
55
+ "@pnpm/engine.runtime.commands": "1100.1.7",
56
+ "@pnpm/error": "1100.0.1",
57
+ "@pnpm/exec.lifecycle": "1100.1.1",
58
+ "@pnpm/installing.commands": "1100.10.1",
59
59
  "@pnpm/exec.pnpm-cli-runner": "1100.0.1",
60
- "@pnpm/pkg-manifest.reader": "1100.0.8",
61
- "@pnpm/shell.path": "1100.0.1",
62
- "@pnpm/store.path": "1100.0.1",
60
+ "@pnpm/installing.client": "1100.2.10",
63
61
  "@pnpm/resolving.parse-wanted-dependency": "1100.0.1",
62
+ "@pnpm/shell.path": "1100.0.1",
64
63
  "@pnpm/types": "1101.3.2",
65
- "@pnpm/workspace.projects-sorter": "1100.0.7",
66
- "@pnpm/cli.common-cli-options-help": "1100.0.2",
67
- "@pnpm/workspace.injected-deps-syncer": "1100.0.19",
68
- "@pnpm/workspace.project-manifest-reader": "1100.0.13"
64
+ "@pnpm/workspace.injected-deps-syncer": "1100.0.21",
65
+ "@pnpm/store.path": "1100.0.2",
66
+ "@pnpm/pkg-manifest.reader": "1100.0.9",
67
+ "@pnpm/workspace.project-manifest-reader": "1100.0.14",
68
+ "@pnpm/workspace.projects-sorter": "1100.0.7"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@pnpm/logger": "^1100.0.0"
@@ -77,13 +77,13 @@
77
77
  "@types/which": "^3.0.4",
78
78
  "is-windows": "^1.0.2",
79
79
  "write-yaml-file": "^6.0.0",
80
+ "@pnpm/exec.commands": "1100.3.1",
80
81
  "@pnpm/engine.runtime.system-version": "1100.0.3",
81
- "@pnpm/exec.commands": "1100.2.5",
82
- "@pnpm/prepare": "1100.0.16",
82
+ "@pnpm/logger": "1100.0.0",
83
+ "@pnpm/prepare": "1100.0.17",
83
84
  "@pnpm/test-ipc-server": "1100.0.0",
84
- "@pnpm/testing.command-defaults": "1100.0.6",
85
- "@pnpm/workspace.projects-filter": "1100.0.21",
86
- "@pnpm/logger": "1100.0.0"
85
+ "@pnpm/workspace.projects-filter": "1100.0.23",
86
+ "@pnpm/testing.command-defaults": "1100.0.7"
87
87
  },
88
88
  "engines": {
89
89
  "node": ">=22.13"