2021-04-02 11:47:01 +00:00
|
|
|
import { existsSync, lstatSync } from 'fs'
|
|
|
|
import { resolve, join } from 'upath'
|
2020-07-02 13:02:35 +00:00
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
export interface ResolveOptions {
|
|
|
|
base?: string
|
|
|
|
alias?: Record<string, string>
|
|
|
|
extensions?: string[]
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
function resolvePath (path: string, opts: ResolveOptions = {}) {
|
|
|
|
// Fast return in case of path exists
|
|
|
|
if (existsSync(path)) {
|
|
|
|
return path
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
let resolvedPath: string
|
2020-07-02 13:02:35 +00:00
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
// Resolve alias
|
|
|
|
if (opts.alias) {
|
|
|
|
resolvedPath = resolveAlias(path, opts.alias)
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
// Resolve relative to base or cwd
|
|
|
|
resolvedPath = resolve(opts.base || '.', resolvedPath)
|
2020-07-02 13:02:35 +00:00
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
// Check if resolvedPath is a file
|
|
|
|
let isDirectory = false
|
|
|
|
if (existsSync(resolvedPath)) {
|
|
|
|
isDirectory = lstatSync(resolvedPath).isDirectory()
|
|
|
|
if (!isDirectory) {
|
|
|
|
return resolvedPath
|
|
|
|
}
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
// Check possible extensions
|
|
|
|
for (const ext of opts.extensions) {
|
|
|
|
// resolvedPath.[ext]
|
|
|
|
const resolvedPathwithExt = resolvedPath + ext
|
|
|
|
if (!isDirectory && existsSync(resolvedPathwithExt)) {
|
|
|
|
return resolvedPathwithExt
|
|
|
|
}
|
|
|
|
// resolvedPath/index.[ext]
|
|
|
|
const resolvedPathwithIndex = join(resolvedPath, 'index' + ext)
|
|
|
|
if (isDirectory && existsSync(resolvedPathwithIndex)) {
|
|
|
|
return resolvedPathwithIndex
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
// If extension check fails and resolvedPath is a valid directory, return it
|
|
|
|
if (isDirectory) {
|
|
|
|
return resolvedPath
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
// Give up if it is neither a directory
|
|
|
|
throw new Error(`Cannot resolve "${path}" from "${resolvedPath}"`)
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
export function resolveAlias (path: string, alias: ResolveOptions['alias']) {
|
|
|
|
for (const key in alias) {
|
|
|
|
if (path.startsWith(key)) {
|
|
|
|
path = alias[key] + path.substr(key.length)
|
|
|
|
}
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
2021-04-02 11:47:01 +00:00
|
|
|
return path
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
export function tryResolvePath (path: string, opts: ResolveOptions = {}) {
|
|
|
|
try {
|
|
|
|
return resolvePath(path, opts)
|
|
|
|
} catch (e) {
|
|
|
|
}
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|