Skip to content

Commit 18f6257

Browse files
Fix workspace root selection with parent lockfiles
1 parent 5b99d26 commit 18f6257

2 files changed

Lines changed: 55 additions & 4 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises'
2+
import { tmpdir } from 'node:os'
3+
import { join } from 'node:path'
4+
import { findRootDirAndLockFiles, warnDuplicatedLockFiles } from './find-root'
5+
6+
describe('findRootDirAndLockFiles()', () => {
7+
it('prefers the nearest lockfile over stray parent lockfiles', async () => {
8+
const rootDir = await mkdtemp(join(tmpdir(), 'nextjs-find-root-'))
9+
10+
try {
11+
const appDir = join(rootDir, 'app')
12+
const parentLockfile = join(rootDir, 'package-lock.json')
13+
const appLockfile = join(appDir, 'package-lock.json')
14+
15+
await mkdir(appDir)
16+
await writeFile(parentLockfile, '{}')
17+
await writeFile(appLockfile, '{}')
18+
19+
const result = findRootDirAndLockFiles(appDir)
20+
21+
expect(result.rootDir).toBe(appDir)
22+
expect(result.lockFiles).toEqual([appLockfile, parentLockfile])
23+
} finally {
24+
await rm(rootDir, { recursive: true, force: true })
25+
}
26+
})
27+
})
28+
29+
describe('warnDuplicatedLockFiles()', () => {
30+
it('reports the nearest lockfile as the selected root marker', () => {
31+
const appLockfile = '/repo/app/package-lock.json'
32+
const parentLockfile = '/repo/package-lock.json'
33+
const warn = jest.spyOn(console, 'warn').mockImplementation(() => {})
34+
35+
try {
36+
warnDuplicatedLockFiles([appLockfile, parentLockfile])
37+
38+
const message = String(warn.mock.calls[0][0])
39+
40+
expect(message).toContain(
41+
`selected the directory of ${appLockfile} as the root directory`
42+
)
43+
expect(message).toContain(`* ${parentLockfile}`)
44+
expect(message).not.toContain(
45+
`selected the directory of ${parentLockfile} as the root directory`
46+
)
47+
} finally {
48+
warn.mockRestore()
49+
}
50+
})
51+
})

packages/next/src/lib/find-root.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,21 @@ export function findRootDirAndLockFiles(cwd: string): {
6060

6161
return {
6262
lockFiles,
63-
rootDir: dirname(lockFiles[lockFiles.length - 1]),
63+
rootDir: dirname(lockFiles[0]),
6464
}
6565
}
6666

6767
export function warnDuplicatedLockFiles(lockFiles: string[]) {
6868
if (lockFiles.length > 1) {
6969
const additionalLockFiles = lockFiles
70-
.slice(0, -1)
70+
.slice(1)
7171
.map((str) => `\n * ${str}`)
7272
.join('')
7373

7474
if (process.env.TURBOPACK) {
7575
Log.warnOnce(
7676
`Warning: Next.js inferred your workspace root, but it may not be correct.\n` +
77-
` We detected multiple lockfiles and selected the directory of ${lockFiles[lockFiles.length - 1]} as the root directory.\n` +
77+
` We detected multiple lockfiles and selected the directory of ${lockFiles[0]} as the root directory.\n` +
7878
` To silence this warning, set \`turbopack.root\` in your Next.js config, or consider ` +
7979
`removing one of the lockfiles if it's not needed.\n` +
8080
` See https://nextjs.org/docs/app/api-reference/config/next-config-js/turbopack#root-directory for more information.\n` +
@@ -83,7 +83,7 @@ export function warnDuplicatedLockFiles(lockFiles: string[]) {
8383
} else {
8484
Log.warnOnce(
8585
`Warning: Next.js inferred your workspace root, but it may not be correct.\n` +
86-
` We detected multiple lockfiles and selected the directory of ${lockFiles[lockFiles.length - 1]} as the root directory.\n` +
86+
` We detected multiple lockfiles and selected the directory of ${lockFiles[0]} as the root directory.\n` +
8787
` To silence this warning, set \`outputFileTracingRoot\` in your Next.js config, or consider ` +
8888
`removing one of the lockfiles if it's not needed.\n` +
8989
` See https://nextjs.org/docs/app/api-reference/config/next-config-js/output#caveats for more information.\n` +

0 commit comments

Comments
 (0)