Skip to content

Commit 6221c66

Browse files
committed
docs: document minimumReleaseAge
1 parent e9394fc commit 6221c66

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed

blog/releases/10.16.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
title: pnpm 10.16
3+
authors: zkochan
4+
tags: [release]
5+
date: 2025-09-12
6+
---
7+
8+
## Minor Changes
9+
10+
### New setting for delayed dependency updates
11+
12+
There have been several incidents recently where popular packages were successfully attacked. To reduce the risk of installing a compromised version, we are introducing a new setting that delays the installation of newly released dependencies. In most cases, such attacks are discovered quickly and the malicious versions are removed from the registry within an hour.
13+
14+
The new setting is called `minimumReleaseAge`. It specifies the number of minutes that must pass after a version is published before pnpm will install it. For example, setting `minimumReleaseAge: 1440` ensures that only packages released at least one day ago can be installed.
15+
16+
If you set `minimumReleaseAge` but need to disable this restriction for certain dependencies, you can list them under the `minimumReleaseAgeExclude` setting. For instance, with the following configuration pnpm will always install the latest version of webpack, regardless of its release time:
17+
18+
```yaml
19+
minimumReleaseAgeExclude:
20+
- webpack
21+
```
22+
23+
Related issue: [#9921](https://github.com/pnpm/pnpm/issues/9921).
24+
25+
### Advanced dependency filtering with finder functions
26+
27+
Added support for `finders` [#9946](https://github.com/pnpm/pnpm/pull/9946).
28+
29+
In the past, `pnpm list` and `pnpm why` could only search for dependencies by **name** (and optionally version). For example:
30+
31+
```
32+
pnpm why minimist
33+
```
34+
35+
prints the chain of dependencies to any installed instance of `minimist`:
36+
37+
```
38+
verdaccio 5.20.1
39+
├─┬ handlebars 4.7.7
40+
│ └── minimist 1.2.8
41+
└─┬ mv 2.1.1
42+
└─┬ mkdirp 0.5.6
43+
└── minimist 1.2.8
44+
```
45+
46+
What if we want to search by **other properties** of a dependency, not just its name? For instance, find all packages that have `react@17` in their peer dependencies?
47+
48+
This is now possible with "finder functions". Finder functions can be declared in `.pnpmfile.cjs` and invoked with the `--find-by=<function name>` flag when running `pnpm list` or `pnpm why`.
49+
50+
Let's say we want to find any dependencies that have React 17 in peer dependencies. We can add this finder to our `.pnpmfile.cjs`:
51+
52+
```js
53+
module.exports = {
54+
finders: {
55+
react17: (ctx) => {
56+
return ctx.readManifest().peerDependencies?.react === "^17.0.0";
57+
},
58+
},
59+
};
60+
```
61+
62+
Now we can use this finder function by running:
63+
64+
```
65+
pnpm why --find-by=react17
66+
```
67+
68+
pnpm will find all dependencies that have this React in peer dependencies and print their exact locations in the dependency graph.
69+
70+
```
71+
@apollo/client 4.0.4
72+
├── @graphql-typed-document-node/core 3.2.0
73+
└── graphql-tag 2.12.6
74+
```
75+
76+
It is also possible to print out some additional information in the output by returning a string from the finder. For example, with the following finder:
77+
78+
```js
79+
module.exports = {
80+
finders: {
81+
react17: (ctx) => {
82+
const manifest = ctx.readManifest();
83+
if (manifest.peerDependencies?.react === "^17.0.0") {
84+
return `license: ${manifest.license}`;
85+
}
86+
return false;
87+
},
88+
},
89+
};
90+
```
91+
92+
Every matched package will also print out the license from its `package.json`:
93+
94+
```
95+
@apollo/client 4.0.4
96+
├── @graphql-typed-document-node/core 3.2.0
97+
│ license: MIT
98+
└── graphql-tag 2.12.6
99+
license: MIT
100+
```
101+
102+
### Patch Changes
103+
104+
- Fix deprecation warning printed when executing pnpm with Node.js 24 [#9529](https://github.com/pnpm/pnpm/issues/9529).
105+
- Throw an error if `nodeVersion` is not set to an exact semver version [#9934](https://github.com/pnpm/pnpm/issues/9934).
106+
- `pnpm publish` should be able to publish a `.tar.gz` file [#9927](https://github.com/pnpm/pnpm/pull/9927).
107+
- Canceling a running process with Ctrl-C should make `pnpm run` return a non-zero exit code [#9626](https://github.com/pnpm/pnpm/issues/9626).

docs/settings.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,43 @@ ignoredOptionalDependencies:
196196
- "@esbuild/*"
197197
```
198198

199+
### minimumReleaseAge
200+
201+
Added in: v10.16.0
202+
203+
* Default: **0**
204+
* Type: **number (minutes)**
205+
206+
To reduce the risk of installing compromised packages, you can delay the installation of newly published versions. In most cases, malicious releases are discovered and removed from the registry within an hour.
207+
208+
`minimumReleaseAge` defines the minimum number of minutes that must pass after a version is published before pnpm will install it. This applies to **all dependencies**, including transitive ones.
209+
210+
For example, the following setting ensures that only packages released at least one day ago can be installed:
211+
212+
```yaml
213+
minimumReleaseAge: 1440
214+
```
215+
216+
### minimumReleaseAgeExclude
217+
218+
Added in: v10.16.0
219+
220+
* Default: **undefined**
221+
* Type: **string[]**
222+
223+
If you set `minimumReleaseAge` but need certain dependencies to always install the newest version immediately, you can list them under `minimumReleaseAgeExclude`. The exclusion works by **package name** and applies to all versions of that package.
224+
225+
Example:
226+
227+
```yaml
228+
minimumReleaseAge: 1440
229+
minimumReleaseAgeExclude:
230+
- webpack
231+
- react
232+
```
233+
234+
In this case, all dependencies must be at least a day old, except `webpack` and `react`, which are installed immediately upon release.
235+
199236
## Dependency Hoisting Settings
200237

201238
### hoist

0 commit comments

Comments
 (0)