pnpm
pnpm copied to clipboard
Check that dependencies are install before running scripts
Contribution
- [ ] I'd be willing to implement this feature (contributing guide)
Describe the user story
It's easy to begin development with the wrong dependencies installed. Here's some examples:
- Switch branches, where the new branch has different dependencies
- Pull the repo for the first time
Describe the solution you'd like
Normally you'd have to remember to run pnpm i in these scenarios. I'd like pnpm to "remember" for me.
Before I run a script in the "scripts" field of the package.json (or pnpm test, etc.), I'd like pnpm to check that the correct dependencies are installed then either:
- Error out, notifying me that I should run
pnpm i - Automatically install the dependencies for me (i.e., run
pnpm iin the background).
Describe the drawbacks of your solution
- This will increase the latency of every command. It may be possible to utilize caching to speed this up for subsequent pnpm invocations.
- Automatically running
pnpm ican pose security risks (becausepostinstallscripts can run arbitrary code), so doing this should be opt-in on the developer-level in my opinion.
Describe alternatives you've considered
Keep the status quo.
Since automatically install dependencies could pose security risks, how about just check if the lockfile is up-to-date?
If the lockfile is out-of-date (either because it doesn't match package.json or it is different from node_modules/.pnpm/lock.yaml), pnpm would print an error to remind you to run pnpm install before running a script. This should be sufficient to prevent users from running scripts with outdated packages.
What do you think?
That's good enough for me.
The issue with this is that pnpm run has already a slow startup and this will make it even slower. Unless you come up with some really smart caching mechanics to avoid reading and parsing the whole lockfile every time, which is usually a large file.
Unless you come up with some really smart caching mechanics to avoid reading and parsing the whole lockfile every time, which is usually a large file.
I plan to only run this validation on the very first pnpm run by setting an environment variable named pnpm_run_skip_deps_check (is this a good name?). This way, only pnpm run issued directly by the user will check the lockfile settings. Nested pnpm run will not do so.
Furthermore, this feature will be disabled by default.
It isn't enough to check if the lockfile is up-to-date. You also need to check if node_modules is up to date, which can be done by comparing node_modules/.pnpm/lock.yaml to pnpm-lock.yaml.
During install I would store somewhere the modification times of package.json files and lockfiles and then during run I guess you could consider everything up to date if the modification times didn't change. Hopefully this would be fast enough as you'd only need to read attributes instead of reading and parsing big files. Although in a big workspace you'd need to read attributes of many package.json files in many workspace projects.
With all the above optimizations that I suggested one expensive operation remains: searching for all the workspace projects in the filesystem. To verify that the lockfile is up to date we check if the set of workspace projects remains the same.
I didn't expect that this feature would be so complex. But the PR is done.
Hi, the release notes didn't say what the default value of verify-deps-before-run is (when it's not defined).
If you can amend the notes to show the default value, that will be great 🙂
EDIT: Saw here in the docs that the default is false.
Also, dumb question, but where is this verify-deps-before-run supposed to be added? I tried package.json but it didn't do anything:
{
// ...
// ❌ Does not work:
"verify-deps-before-run": "install", // or "warn",
"dependencies": { ... },
// ...
"packageManager": "[email protected]"
}
I didn't get any installation logs or warnings when running scripts pnpm script-name but running plain install pnpm i does show packages being updated (to match new lockfile). I have also tried verifyDepsBeforeRun to no avail.
EDIT: Apparently, this is a CLI option: ✅ pnpm --verify-deps-before-run=install script-name. A bit disappointing that we cannot just set it in package.json or in another way. (Is there another way to set a default?)
EDIT again: We can set it in the developer environment (globally or per user):
# ✅ Works:
# set globally
pnpm config -g set verify-deps-before-run=install
# or per user
pnpm config set verify-deps-before-run=install
But we cannot set it per project using package.json.
But we cannot set it per project using
package.json.
You can use .npmrc to set it per project. According to the docs:
pnpm gets its configuration from the command line, environment variables, and
.npmrcfiles.
Hello, I am pnpm to install deps even when using npx in my CI. I don't want to install pnpm or install depencencies and just want to run npx directly without pnpm. However, [email protected] is always installing dependencies it seems.