import { realpathSync } from "node:fs"; import type { PathFlavor } from "#src/path/path-flavor"; /** * Resolve symlinks in an absolute path, best-effort. * * Splits the path into components and tries `realpathSync` from the full path * down to `/`, re-appending the non-existent tail to the first ancestor that * resolves. Returns the input unchanged when no ancestor resolves (unreachable * in practice since `/` always exists) or when a non-ENOENT/ENOTDIR error is * encountered (e.g. `EACCES`, `ELOOP`), so callers fall back to lexical * containment for paths that cannot be resolved. */ export function canonicalizePath( absolutePath: string, flavor: PathFlavor, ): string { if (!absolutePath) return absolutePath; const { impl } = flavor; const root = impl.parse(absolutePath).root; const rest = absolutePath.slice(root.length); const parts = rest.split(impl.sep).filter(Boolean); for (let i = parts.length; i >= 0; i--) { const candidate = root + parts.slice(0, i).join(impl.sep); try { const real = realpathSync(candidate); const tail = parts.slice(i); return tail.length === 0 ? real : impl.join(real, ...tail); } catch (error) { const code = (error as NodeJS.ErrnoException).code; if (code !== "ENOENT" && code !== "ENOTDIR") return absolutePath; } } return absolutePath; }