2021-05-10 10:39:18 +02:00
|
|
|
import { fileExists } from '../../lib/file-exists'
|
2022-04-30 13:19:27 +02:00
|
|
|
import { getPagePaths } from '../../shared/lib/page-path/get-page-paths'
|
|
|
|
import { nonNullable } from '../../lib/non-nullable'
|
|
|
|
import { join, sep, normalize } from 'path'
|
|
|
|
import { promises } from 'fs'
|
|
|
|
import { warn } from '../../build/output/log'
|
|
|
|
import chalk from '../../lib/chalk'
|
2020-05-26 14:50:28 +02:00
|
|
|
|
2022-08-15 16:29:51 +02:00
|
|
|
async function isTrueCasePagePath(pagePath: string, pagesDir: string) {
|
|
|
|
const pageSegments = normalize(pagePath).split(sep).filter(Boolean)
|
|
|
|
const segmentExistsPromises = pageSegments.map(async (segment, i) => {
|
|
|
|
const segmentParentDir = join(pagesDir, ...pageSegments.slice(0, i))
|
|
|
|
const parentDirEntries = await promises.readdir(segmentParentDir)
|
|
|
|
return parentDirEntries.includes(segment)
|
|
|
|
})
|
|
|
|
|
|
|
|
return (await Promise.all(segmentExistsPromises)).every(Boolean)
|
|
|
|
}
|
|
|
|
|
2022-04-30 13:19:27 +02:00
|
|
|
/**
|
|
|
|
* Finds a page file with the given parameters. If the page is duplicated with
|
|
|
|
* multiple extensions it will throw, otherwise it will return the *relative*
|
|
|
|
* path to the page file or null if it is not found.
|
|
|
|
*
|
|
|
|
* @param pagesDir Absolute path to the pages folder with trailing `/pages`.
|
|
|
|
* @param normalizedPagePath The page normalized (it will be denormalized).
|
|
|
|
* @param pageExtensions Array of page extensions.
|
|
|
|
*/
|
2019-05-29 13:57:26 +02:00
|
|
|
export async function findPageFile(
|
2022-04-30 13:19:27 +02:00
|
|
|
pagesDir: string,
|
2019-05-29 13:57:26 +02:00
|
|
|
normalizedPagePath: string,
|
2022-09-03 02:13:47 +02:00
|
|
|
pageExtensions: string[],
|
|
|
|
isAppDir: boolean
|
2019-05-29 13:57:26 +02:00
|
|
|
): Promise<string | null> {
|
2022-09-03 02:13:47 +02:00
|
|
|
const pagePaths = getPagePaths(normalizedPagePath, pageExtensions, isAppDir)
|
2022-04-30 13:19:27 +02:00
|
|
|
const [existingPath, ...others] = (
|
|
|
|
await Promise.all(
|
2022-09-03 02:13:47 +02:00
|
|
|
pagePaths.map(async (path) => {
|
|
|
|
const filePath = join(pagesDir, path)
|
|
|
|
return (await fileExists(filePath)) ? path : null
|
|
|
|
})
|
2022-04-30 13:19:27 +02:00
|
|
|
)
|
|
|
|
).filter(nonNullable)
|
2019-02-24 22:08:35 +01:00
|
|
|
|
2022-04-30 13:19:27 +02:00
|
|
|
if (!existingPath) {
|
2019-09-11 20:26:10 +02:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2022-04-30 13:19:27 +02:00
|
|
|
if (!(await isTrueCasePagePath(existingPath, pagesDir))) {
|
2020-05-26 14:50:28 +02:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2022-04-30 13:19:27 +02:00
|
|
|
if (others.length > 0) {
|
2019-09-11 20:26:10 +02:00
|
|
|
warn(
|
|
|
|
`Duplicate page detected. ${chalk.cyan(
|
2022-04-30 13:19:27 +02:00
|
|
|
join('pages', existingPath)
|
2019-09-11 20:26:10 +02:00
|
|
|
)} and ${chalk.cyan(
|
2022-04-30 13:19:27 +02:00
|
|
|
join('pages', others[0])
|
2019-09-11 20:26:10 +02:00
|
|
|
)} both resolve to ${chalk.cyan(normalizedPagePath)}.`
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-04-30 13:19:27 +02:00
|
|
|
return existingPath
|
|
|
|
}
|
2022-08-26 20:21:53 +02:00
|
|
|
|
|
|
|
// Determine if the file is leaf node page file under layouts,
|
|
|
|
// The filename should start with 'page', it can be either shared,
|
|
|
|
// client, or server components with allowed page file extension.
|
|
|
|
// e.g. page.js, page.server.js, page.client.tsx, etc.
|
|
|
|
export function isLayoutsLeafPage(filePath: string) {
|
|
|
|
return /[\\/]?page\.((server|client)\.?)?[jt]sx?$/.test(filePath)
|
|
|
|
}
|