* Resolves every existing prefix through realpath and appends only missing * path segments. This detects an existing symlink that redirects a future * output outside its declared root without creating any directory first.
(path: string)
| 211 | * output outside its declared root without creating any directory first. |
| 212 | */ |
| 213 | async function canonicalFuturePath(path: string): Promise<string> { |
| 214 | const missing: string[] = []; |
| 215 | let existing = path; |
| 216 | let canonicalExisting: string | undefined; |
| 217 | while (canonicalExisting === undefined) { |
| 218 | try { |
| 219 | canonicalExisting = await realpath(existing); |
| 220 | } catch (error: unknown) { |
| 221 | if (!isMissingPathError(error)) throw error; |
| 222 | const parent = dirname(existing); |
| 223 | if (parent === existing) throw error; |
| 224 | missing.push(basename(existing)); |
| 225 | existing = parent; |
| 226 | } |
| 227 | } |
| 228 | if (missing.length > 0) { |
| 229 | const existingStats = await stat(canonicalExisting); |
| 230 | if (!existingStats.isDirectory()) throw new Error(`An output path ancestor is not a directory: ${existing}`); |
| 231 | } |
| 232 | return resolve(canonicalExisting, ...missing.reverse()); |
| 233 | } |
| 234 | |
| 235 | function isMissingPathError(error: unknown): error is NodeJS.ErrnoException { |
| 236 | return error instanceof Error && 'code' in error && error.code === 'ENOENT'; |
no test coverage detected