perf(kit): reduce duplication between findPath and resolvePath (#30682)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Daniel Roe 2025-01-21 11:33:12 +00:00 committed by GitHub
parent 0f897a056e
commit 83d2361e86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,4 +1,4 @@
import { existsSync, promises as fsp } from 'node:fs' import { promises as fsp } from 'node:fs'
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
import { basename, dirname, isAbsolute, join, normalize, resolve } from 'pathe' import { basename, dirname, isAbsolute, join, normalize, resolve } from 'pathe'
import { globby } from 'globby' import { globby } from 'globby'
@ -38,97 +38,30 @@ export interface ResolvePathOptions {
* If path could not be resolved, normalized input path will be returned * If path could not be resolved, normalized input path will be returned
*/ */
export async function resolvePath (path: string, opts: ResolvePathOptions = {}): Promise<string> { export async function resolvePath (path: string, opts: ResolvePathOptions = {}): Promise<string> {
// Always normalize input const res = await _resolvePathGranularly(path, opts)
const _path = path
path = normalize(path)
// Fast return if the path exists if (res.type === 'file') {
if (isAbsolute(path)) { return res.path
if (opts?.virtual && existsInVFS(path)) {
return path
}
if (existsSync(path) && !(await isDirectory(path))) {
return path
}
}
// Use current nuxt options
const nuxt = tryUseNuxt()
const cwd = opts.cwd || (nuxt ? nuxt.options.rootDir : process.cwd())
const extensions = opts.extensions || (nuxt ? nuxt.options.extensions : ['.ts', '.mjs', '.cjs', '.json'])
const modulesDir = nuxt ? nuxt.options.modulesDir : []
// Resolve aliases
path = resolveAlias(path)
// Resolve relative to cwd
if (!isAbsolute(path)) {
path = resolve(cwd, path)
}
// Check if resolvedPath is a file
if (opts?.virtual && existsInVFS(path, nuxt)) {
return path
}
let _isDir = false
if (existsSync(path)) {
_isDir = await isDirectory(path)
if (!_isDir) {
return path
}
}
// Check possible extensions
for (const ext of extensions) {
// path.[ext]
const pathWithExt = path + ext
if (opts?.virtual && existsInVFS(pathWithExt, nuxt)) {
return pathWithExt
}
if (existsSync(pathWithExt)) {
return pathWithExt
}
// path/index.[ext]
const pathWithIndex = join(path, 'index' + ext)
if (opts?.virtual && existsInVFS(pathWithIndex, nuxt)) {
return pathWithIndex
}
if (_isDir && existsSync(pathWithIndex)) {
return pathWithIndex
}
}
// Try to resolve as module id
const resolveModulePath = await _resolvePath(_path, { url: [cwd, ...modulesDir] }).catch(() => null)
if (resolveModulePath) {
return resolveModulePath
} }
// Return normalized input // Return normalized input
return opts.fallbackToOriginal ? _path : path return opts.fallbackToOriginal ? path : res.path
} }
/** /**
* Try to resolve first existing file in paths * Try to resolve first existing file in paths
*/ */
export async function findPath (paths: string | string[], opts?: ResolvePathOptions, pathType: 'file' | 'dir' = 'file'): Promise<string | null> { export async function findPath (paths: string | string[], opts?: ResolvePathOptions, pathType: 'file' | 'dir' = 'file'): Promise<string | null> {
const nuxt = opts?.virtual ? tryUseNuxt() : undefined
for (const path of toArray(paths)) { for (const path of toArray(paths)) {
const rPath = await resolvePath(path, opts) const res = await _resolvePathGranularly(path, opts)
// Check VFS if (!res.type || (pathType && res.type !== pathType)) {
if (opts?.virtual && existsInVFS(rPath, nuxt)) { continue
return rPath
} }
// Check file system // Check file system
if (await existsSensitive(rPath)) { if (res.virtual || await existsSensitive(res.path)) {
const _isDir = await isDirectory(rPath) return res.path
if (!pathType || (pathType === 'file' && !_isDir) || (pathType === 'dir' && _isDir)) {
return rPath
}
} }
} }
return null return null
@ -186,15 +119,106 @@ export async function resolveNuxtModule (base: string, paths: string[]): Promise
// --- Internal --- // --- Internal ---
async function existsSensitive (path: string) { interface PathResolution {
if (!existsSync(path)) { return false } path: string
const dirFiles = await fsp.readdir(dirname(path)) type?: 'file' | 'dir'
return dirFiles.includes(basename(path)) virtual?: boolean
} }
// Usage note: We assume path existence is already ensured async function _resolvePathType (path: string, opts: ResolvePathOptions = {}, skipFs = false): Promise<PathResolution | undefined> {
async function isDirectory (path: string) { if (opts?.virtual && existsInVFS(path)) {
return (await fsp.lstat(path)).isDirectory() return {
path,
type: 'file',
virtual: true,
}
}
if (skipFs) {
return
}
const fd = await fsp.open(path, 'r').catch(() => null)
try {
const stats = await fd?.stat()
if (stats) {
return {
path,
type: stats.isFile() ? 'file' : 'dir',
virtual: false,
}
}
} finally {
fd?.close()
}
}
async function _resolvePathGranularly (path: string, opts: ResolvePathOptions = {}): Promise<PathResolution> {
// Always normalize input
const _path = path
path = normalize(path)
// Fast return if the path exists
if (isAbsolute(path)) {
const res = await _resolvePathType(path, opts)
if (res && res.type === 'file') {
return res
}
}
// Use current nuxt options
const nuxt = tryUseNuxt()
const cwd = opts.cwd || (nuxt ? nuxt.options.rootDir : process.cwd())
const extensions = opts.extensions || (nuxt ? nuxt.options.extensions : ['.ts', '.mjs', '.cjs', '.json'])
const modulesDir = nuxt ? nuxt.options.modulesDir : []
// Resolve aliases
path = resolveAlias(path)
// Resolve relative to cwd
if (!isAbsolute(path)) {
path = resolve(cwd, path)
}
const res = await _resolvePathType(path, opts)
if (res && res.type === 'file') {
return res
}
// Check possible extensions
for (const ext of extensions) {
// path.[ext]
const extPath = await _resolvePathType(path + ext, opts)
if (extPath && extPath.type === 'file') {
return extPath
}
// path/index.[ext]
const indexPath = await _resolvePathType(join(path, 'index' + ext), opts, res?.type !== 'dir' /* skip checking if parent is not a directory */)
if (indexPath && indexPath.type === 'file') {
return indexPath
}
}
// Try to resolve as module id
const resolvedModulePath = await _resolvePath(_path, { url: [cwd, ...modulesDir] }).catch(() => null)
if (resolvedModulePath) {
return {
path: resolvedModulePath,
type: 'file',
virtual: false,
}
}
// Return normalized input
return {
path,
}
}
async function existsSensitive (path: string) {
const dirFiles = await fsp.readdir(dirname(path)).catch(() => null)
return dirFiles && dirFiles.includes(basename(path))
} }
function existsInVFS (path: string, nuxt = tryUseNuxt()) { function existsInVFS (path: string, nuxt = tryUseNuxt()) {