Skip to content

Commit 64da71c

Browse files
fix: lib/helpers/install.ts to better support pnpm and properly respect root argument (#64418)
This fixes and improves the `lib/helpers/install.ts` file (`install()`) method to better support pnpm and properly respect the `root` argument. I encountered an issue where by running `next <command> <project-dir>`, and the `<command>` involved installing missing dependencies (like `lint` or my upcoming `experimental-test`), it was not executing pnpm in my `<project-dir>` because pnpm doesn't have a `--cwd` flag. Closes NEXT-3092 Co-authored-by: Zack Tanner <[email protected]>
1 parent 03b7a0f commit 64da71c

File tree

1 file changed

+36
-66
lines changed

1 file changed

+36
-66
lines changed

packages/next/src/lib/helpers/install.ts

Lines changed: 36 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { yellow } from '../picocolors'
22
import spawn from 'next/dist/compiled/cross-spawn'
3-
4-
export type PackageManager = 'npm' | 'pnpm' | 'yarn'
3+
import type { PackageManager } from './get-pkg-manager'
54

65
interface InstallArgs {
76
/**
8-
* Indicate whether to install packages using npm, pnpm or Yarn.
7+
* Indicate whether to install packages using npm, pnpm, or yarn.
98
*/
109
packageManager: PackageManager
1110
/**
12-
* Indicate whether there is an active Internet connection.
11+
* Indicate whether there is an active internet connection.
1312
*/
1413
isOnline: boolean
1514
/**
@@ -19,81 +18,52 @@ interface InstallArgs {
1918
}
2019

2120
/**
22-
* Spawn a package manager installation with either Yarn or NPM.
21+
* Spawn a package manager installation with either npm, pnpm, or yarn.
2322
*
2423
* @returns A Promise that resolves once the installation is finished.
2524
*/
2625
export function install(
2726
root: string,
28-
dependencies: string[] | null,
27+
dependencies: string[],
2928
{ packageManager, isOnline, devDependencies }: InstallArgs
3029
): Promise<void> {
31-
/**
32-
* (p)npm-specific command-line flags.
33-
*/
34-
const npmFlags: string[] = []
35-
/**
36-
* Yarn-specific command-line flags.
37-
*/
38-
const yarnFlags: string[] = []
39-
/**
40-
* Return a Promise that resolves once the installation is finished.
41-
*/
42-
return new Promise((resolve, reject) => {
43-
let args: string[]
44-
let command = packageManager
45-
const useYarn = packageManager === 'yarn'
30+
let args: string[] = []
4631

47-
if (dependencies && dependencies.length) {
48-
/**
49-
* If there are dependencies, run a variation of `{packageManager} add`.
50-
*/
51-
if (useYarn) {
52-
/**
53-
* Call `yarn add --exact (--offline)? (-D)? ...`.
54-
*/
55-
args = ['add', '--exact']
56-
if (!isOnline) args.push('--offline')
57-
args.push('--cwd', root)
58-
if (devDependencies) args.push('--dev')
59-
args.push(...dependencies)
60-
} else {
61-
/**
62-
* Call `(p)npm install [--save|--save-dev] ...`.
63-
*/
64-
args = ['install', '--save-exact']
65-
args.push(devDependencies ? '--save-dev' : '--save')
66-
args.push(...dependencies)
67-
}
32+
if (dependencies.length > 0) {
33+
if (packageManager === 'yarn') {
34+
args = ['add', '--exact']
35+
if (devDependencies) args.push('--dev')
36+
} else if (packageManager === 'pnpm') {
37+
args = ['add', '--save-exact']
38+
args.push(devDependencies ? '--save-dev' : '--save-prod')
6839
} else {
69-
/**
70-
* If there are no dependencies, run a variation of `{packageManager}
71-
* install`.
72-
*/
73-
args = ['install']
74-
if (!isOnline) {
75-
console.log(yellow('You appear to be offline.'))
76-
if (useYarn) {
77-
console.log(yellow('Falling back to the local Yarn cache.'))
78-
console.log()
79-
args.push('--offline')
80-
} else {
81-
console.log()
82-
}
83-
}
40+
// npm
41+
args = ['install', '--save-exact']
42+
args.push(devDependencies ? '--save-dev' : '--save')
8443
}
85-
/**
86-
* Add any package manager-specific flags.
87-
*/
88-
if (useYarn) {
89-
args.push(...yarnFlags)
90-
} else {
91-
args.push(...npmFlags)
44+
45+
args.push(...dependencies)
46+
} else {
47+
args = ['install'] // npm, pnpm, and yarn all support `install`
48+
49+
if (!isOnline) {
50+
args.push('--offline')
51+
console.log(yellow('You appear to be offline.'))
52+
if (packageManager !== 'npm') {
53+
console.log(
54+
yellow(`Falling back to the local ${packageManager} cache.`)
55+
)
56+
}
57+
console.log()
9258
}
59+
}
60+
61+
return new Promise((resolve, reject) => {
9362
/**
9463
* Spawn the installation process.
9564
*/
96-
const child = spawn(command, args, {
65+
const child = spawn(packageManager, args, {
66+
cwd: root,
9767
stdio: 'inherit',
9868
env: {
9969
...process.env,
@@ -106,7 +76,7 @@ export function install(
10676
})
10777
child.on('close', (code) => {
10878
if (code !== 0) {
109-
reject({ command: `${command} ${args.join(' ')}` })
79+
reject({ command: `${packageManager} ${args.join(' ')}` })
11080
return
11181
}
11282
resolve()

0 commit comments

Comments
 (0)