Skip to content

Auto-activate package.json packageManager via Corepack in nodejs plugin - #2845

Merged
mikeland73 merged 11 commits into
mainfrom
mikeland73/nodejs-corepack-pkgmgr-autodetect
Jun 7, 2026
Merged

Auto-activate package.json packageManager via Corepack in nodejs plugin#2845
mikeland73 merged 11 commits into
mainfrom
mikeland73/nodejs-corepack-pkgmgr-autodetect

Conversation

@mikeland73

Copy link
Copy Markdown
Collaborator

Summary

When Corepack is enabled (DEVBOX_COREPACK_ENABLED=1), the nodejs plugin now reads the packageManager field from the project's package.json and runs corepack prepare --activate so the pinned package manager (pnpm, yarn, or npm) is ready in the shell. The behavior is generalized to any package manager and enabled by default; set DEVBOX_DISABLE_NODEJS_PACKAGE_MANAGER_AUTODETECT=1 to disable it.

How was it tested?

Validated that plugins/nodejs.json still parses as valid JSON and that the new init_hook entry renders the expected shell. The hook is guarded so it only runs when Corepack is enabled, the disable flag is unset, and a package.json exists, and it emits nothing when no packageManager field is present.

Community Contribution License

All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.

By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.

When Corepack is enabled, the nodejs plugin now reads the `packageManager`
field from the project's package.json and runs `corepack prepare --activate`
so the pinned package manager (pnpm, yarn, or npm) is available in the shell.
This is generalized to any package manager and enabled by default. Set
DEVBOX_DISABLE_NODEJS_PACKAGE_MANAGER_AUTODETECT=1 to disable it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CopilotAI review requested due to automatic review settings June 2, 2026 21:46
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the built-in nodejs plugin so that, when Corepack is enabled, Devbox automatically reads the project’s package.json#packageManager field and runs corepack prepare --activate to make the pinned package manager available in the shell (with an opt-out via DEVBOX_DISABLE_NODEJS_PACKAGE_MANAGER_AUTODETECT=1).

Changes:

  • Update the nodejs plugin README text to document automatic package manager activation and the disable flag.
  • Add an init_hook step that detects packageManager from package.json and activates it via Corepack when enabled.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadplugins/nodejs.json Outdated
Comment threadplugins/nodejs.json Outdated
mikeland73and others added 2 commits June 2, 2026 14:51
Assert the Corepack-activated pnpm version matches the pinned
packageManager field, exercising the nodejs plugin autodetect.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Quote the DEVBOX_COREPACK_ENABLED guards so they behave reliably when the
var is unset, and build the package.json path from
process.env.DEVBOX_PROJECT_ROOT inside Node instead of interpolating the
shell variable into the JS source (which could break on paths containing
quotes or backslashes).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mikeland73and others added 7 commits June 5, 2026 14:25
Cover the two no-op cases for the nodejs plugin's autodetect init_hook:
package.json missing, and package.json present without a packageManager
field. Both must leave shell init working without error.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the inline shell + node -e one-liner with a dedicated
activate-package-manager.js shipped via create_files and invoked from the
init_hook. This is easier to read and maintain than the escaped one-liner.
The corepack enable / PATH export lines stay in shell since exporting PATH
must mutate the parent shell environment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the three init_hook shell commands into a single
`eval "$(node setup-corepack.js <corepack-bin-dir>)"`. The script now
enables Corepack, activates the pinned packageManager, and prints the
`export PATH=...` line for the shell to eval (a child process can't mutate
the parent shell's PATH, so the export is emitted and eval'd).
Renamed activate-package-manager.js -> setup-corepack.js to reflect its
broader responsibility.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The script now early-exits unless DEVBOX_COREPACK_ENABLED is set, so the
init_hook no longer needs the shell-side guard and is a single
eval "$(node setup-corepack.js <corepack-bin-dir>)". When disabled the
script emits nothing, so the eval is a no-op.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Declare the corepack-bin dir in the plugin's env block (and add it to PATH,
matching the ruby plugin's pattern), so setup-corepack.js no longer needs to
emit an export for the shell to eval. The init_hook is now simply
`node <virtenv>/bin/setup-corepack.js`, and the script reads the bin dir
from DEVBOX_COREPACK_BIN_DIR. Bumped plugin version to regenerate the
shipped script.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump nodejs plugin_version to 0.0.3 in the example lockfiles.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mikeland73
mikeland73 merged commit 6235efa into mainJun 7, 2026
6 checks passed
@mikeland73
mikeland73 deleted the mikeland73/nodejs-corepack-pkgmgr-autodetect branch June 7, 2026 18:41
mikeland73 added a commit that referenced this pull request Jun 22, 2026
## Summary
Fixes#2856.
The Corepack setup script introduced in #2845 (`setup-corepack.js`) is
written in CommonJS and uses `require()`. The nodejs plugin runs it as
the shell `init_hook`:
```
node "{{ .Virtenv }}/bin/setup-corepack.js"
```
When a project's root `package.json` sets `"type": "module"`, Node
treats **every** `.js` file in the directory tree — including this one
inside `.devbox/virtenv` — as an ES module. The script then crashes on
its first `require()`, taking the whole shell down:
```
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension
and '.../package.json' contains "type": "module".
```
As a result, `devbox shell` no longer starts for any nodejs project
whose `package.json` declares `"type": "module"`.
## Fix
Rewrite the script as a native **ES module** and name it
**`setup-corepack.mjs`**. The `.mjs` extension forces Node to treat the
file as ESM regardless of the surrounding `package.json` `type`, so it
works for both `"type": "module"` projects and default/CommonJS
projects. (A plain `.js` ESM file would break the inverse case — Node
parses `.js` as CommonJS when `type` is absent or `commonjs`.)
Changes:
- Rename `plugins/nodejs/setup-corepack.js` →
`plugins/nodejs/setup-corepack.mjs`.
- `require()` → `import` for `node:child_process` and `node:path`.
- Read `package.json` via `readFileSync` + `JSON.parse` instead of
`require()`, since JSON module import syntax differs across Node
versions.
- Update the plugin's `init_hook` and `create_files` references in
`plugins/nodejs.json`.
- Add a regression test case (`"type": "module"` in `package.json`) to
`testscripts/plugin/nodejs_corepack_autodetect.test.txt`.
## How was it tested?
- `node --check` on the `.mjs` file (valid ESM syntax).
- Ran the script directly in scratch dirs and confirmed it exits 0 (no
crash, shell init never breaks) in all of:
- `package.json` with `{"type":"module"}` — previously the reported
`ReferenceError`.
- default/CommonJS `package.json`.
- `package.json` with a pinned `packageManager` (`pnpm@9.0.0`) —
autodetect path activates correctly.
- Added `Case 3` to the corepack autodetect testscript to guard against
regression.
cc @AdaptivChris (issue reporter)
---
_Generated by [Claude
Code](https://claude.ai/code/session_01DmRVmUmym8zb2jqRdwnVvZ)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@mikeland73@mohsenari