rsnext/packages/next/server/lib/find-page-file.ts
Jan Potoms cefbcadf45
Make page path case sensitive in dev (#8848)
URL paths are case sensitive, MacOS file system is case insensitive. This PR makes sure development mode doesn't find pages that don't have the casing as specified in the URL.

Will clean up and write a test when agreed on this approach.

Fixes https://github.com/zeit/next.js/issues/8825
Fixes https://github.com/zeit/next.js/issues/8847
Fixes https://github.com/zeit/next.js/issues/9080
2020-05-26 12:50:28 +00:00

73 lines
2.2 KiB
TypeScript

import { join, sep as pathSeparator, normalize } from 'path'
import chalk from 'next/dist/compiled/chalk'
import { isWriteable } from '../../build/is-writeable'
import { warn } from '../../build/output/log'
import fs from 'fs'
import { promisify } from 'util'
const readdir = promisify(fs.readdir)
async function isTrueCasePagePath(pagePath: string, pagesDir: string) {
const pageSegments = normalize(pagePath).split(pathSeparator).filter(Boolean)
const segmentExistsPromises = pageSegments.map(async (segment, i) => {
const segmentParentDir = join(pagesDir, ...pageSegments.slice(0, i))
const parentDirEntries = await readdir(segmentParentDir)
return parentDirEntries.includes(segment)
})
return (await Promise.all(segmentExistsPromises)).every(Boolean)
}
export async function findPageFile(
rootDir: string,
normalizedPagePath: string,
pageExtensions: string[]
): Promise<string | null> {
let foundPagePaths: string[] = []
for (const extension of pageExtensions) {
const relativePagePath = `${normalizedPagePath}.${extension}`
const pagePath = join(rootDir, relativePagePath)
// only /index and /sub/index when /sub/index/index.js is allowed
// see test/integration/route-indexes for expected index handling
if (
normalizedPagePath.startsWith('/index') ||
!normalizedPagePath.endsWith('/index')
) {
if (await isWriteable(pagePath)) {
foundPagePaths.push(relativePagePath)
}
}
const relativePagePathWithIndex = join(
normalizedPagePath,
`index.${extension}`
)
const pagePathWithIndex = join(rootDir, relativePagePathWithIndex)
if (await isWriteable(pagePathWithIndex)) {
foundPagePaths.push(relativePagePathWithIndex)
}
}
if (foundPagePaths.length < 1) {
return null
}
if (!(await isTrueCasePagePath(foundPagePaths[0], rootDir))) {
return null
}
if (foundPagePaths.length > 1) {
warn(
`Duplicate page detected. ${chalk.cyan(
join('pages', foundPagePaths[0])
)} and ${chalk.cyan(
join('pages', foundPagePaths[1])
)} both resolve to ${chalk.cyan(normalizedPagePath)}.`
)
}
return foundPagePaths[0]
}