Skip to content

fix(cli-kit): respect package manager when installNodeModules adds specific packages#7299

Open
andromia3 wants to merge 1 commit intoShopify:mainfrom
andromia3:fix/install-node-modules-subcommand
Open

fix(cli-kit): respect package manager when installNodeModules adds specific packages#7299
andromia3 wants to merge 1 commit intoShopify:mainfrom
andromia3:fix/install-node-modules-subcommand

Conversation

@andromia3
Copy link
Copy Markdown

WHY are these changes introduced?

Fixes #7042.

`installNodeModules()` in `packages/cli-kit/src/public/node/node-package-manager.ts` always ran ` install `, but `yarn`, `pnpm`, and `bun` all require the `add` subcommand to install a specific package with a version specifier — their `install` subcommand installs from the lockfile.

So a call like
```ts
installNodeModules({packageManager: 'yarn', args: ['@shopify/hydrogen@2025.7.1']})
```
produced `yarn install @shopify/hydrogen@2025.7.1`, which yarn rejects. Same for pnpm. Hydrogen PR #3462 worked around this by bypassing `installNodeModules()` with a direct `exec()` call that mapped the subcommand per package manager; this upstream fix lets that workaround be removed (@kdaviduik's original suggestion).

WHAT is this pull request doing?

Rather than silently change the meaning of `args` — which would break `packages/app/src/cli/services/init/template/npm.ts`, the only other call site, which uses `args` for flags like `['--network-concurrency', '1']` — added a new optional `packages?: string[]` field to `InstallNodeModulesOptions`.

When `packages` is provided:

  • `npm` keeps using `install` (no change, and npm supports both).
  • `yarn`, `pnpm`, and `bun` use `add`, matching the existing internal helpers `argumentsToAddDependenciesWith{Yarn,PNPM,Bun}` further down the same file.

When `packages` is omitted the function behaves identically to before, so every existing call site is unaffected.

```diff

  • let args = ['install']
  • const hasPackages = Boolean(options.packages?.length)
  • const usesAddSubcommand =
  • hasPackages &&
  • (options.packageManager === 'yarn' ||
  •  options.packageManager === 'pnpm' ||
    
  •  options.packageManager === 'bun')
    
  • let args = [usesAddSubcommand ? 'add' : 'install']
  • if (options.packages) {
  • args = args.concat(options.packages)
  • }
    if (options.args) {
    args = args.concat(options.args)
    }
    ```

Full-path trace

  • `installNodeModules` is used from two files inside this repo: `packages/app/src/cli/services/init/template/npm.ts` (passes `args` as flags, not packages) and `packages/app/src/cli/services/generate/extension.ts` (calls without `args` — pure lockfile install). Neither is affected by this change.
  • External consumers (Hydrogen's `upgrade` command, among others) previously worked around the bug; they can migrate to the new `packages` field when they want to drop the workaround.
  • The existing internal helpers `addNPMDependencies` / `argumentsToAddDependenciesWith{Yarn,PNPM,Bun}` already use `add` for yarn/pnpm/bun — this fix brings `installNodeModules` in line with the same convention when it's used to add specific packages.
  • The `homebrew` and `unknown` `PackageManager` variants keep the existing `install` behaviour (`homebrew install ` isn't reachable in practice — `addNPMDependencies` throws for it — and `unknown` is an error state).

How to test your changes?

Six new tests in `packages/cli-kit/src/public/node/node-package-manager.test.ts`:

  1. `uses `install` when packages are provided for npm`
  2. `uses `add` when packages are provided for yarn`
  3. `uses `add` when packages are provided for pnpm`
  4. `uses `add` when packages are provided for bun`
  5. `appends `args` after `packages`` — verifies ordering when both are passed
  6. `uses `install` (unchanged) when no packages are provided, even for yarn` — regression guard for the existing `init/template/npm.ts` call path

Run locally:
```bash
pnpm --filter @shopify/cli-kit test node-package-manager
```

Post-release steps

None in this repo. Downstream note: Hydrogen's `upgrade.ts` workaround can be removed once this change ships in a `@shopify/cli-kit` release and a matching Hydrogen PR is opened.

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows) — no OS-specific code
  • I've considered possible documentation changes — the new option has a JSDoc block explaining when to use it
  • I've considered analytics changes to measure impact — N/A
  • The change is user-facing, so I've added a changelog entry with `pnpm changeset add` — `.changeset/fix-install-node-modules-subcommand.md`, patch bump for `@shopify/cli-kit`

…ecific packages (Shopify#7042)

`installNodeModules()` always ran `<pm> install <args>`, but `yarn`,
`pnpm`, and `bun` all require the `add` subcommand to install a
specific package with a version specifier — their `install` subcommand
installs from the lockfile. So a call like

    installNodeModules({packageManager: 'yarn', args: ['@shopify/hydrogen@2025.7.1']})

produced `yarn install @shopify/hydrogen@2025.7.1`, which yarn rejects.
The same applied to pnpm. Hydrogen PR Shopify#3462 worked around this by
bypassing `installNodeModules()` with a direct `exec()` call that
mapped the subcommand per package manager; this upstream fix lets
that workaround be removed.

Rather than silently change the meaning of `args` (which breaks
`init/template/npm.ts`, which uses it for flags like
`['--network-concurrency', '1']`), added a new optional
`packages?: string[]` field to `InstallNodeModulesOptions`. When
`packages` is provided:

- `npm` keeps using `install` (no change, and npm supports both).
- `yarn`, `pnpm`, and `bun` use `add`, matching the existing internal
  helpers `argumentsToAddDependenciesWith{Yarn,PNPM,Bun}` further
  down the same file.

When `packages` is omitted the function behaves identically to the
old implementation, so every existing call site is unaffected.

Added six new tests in `node-package-manager.test.ts` covering:
- npm with packages (`install`)
- yarn with packages (`add`)
- pnpm with packages (`add`)
- bun with packages (`add`)
- packages + args ordering (packages first, then flags)
- yarn with `args` only (no packages) — unchanged `install` behaviour

Fixes Shopify#7042.
@andromia3 andromia3 requested review from a team as code owners April 14, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

installNodeModules() uses wrong subcommand for yarn/pnpm when adding specific packages

1 participant