/** * PowerShell executable resolution, dependency-free so non-package consumers * (the repository's coverage-gate probe in `vitest.config.ts`) can share the * ONE resolution definition with the executor and its suites — a probe that * resolved differently from the code under test could exempt a file whose * suites actually run. * * @module @deepseek-ai/dsh-pwsh-local/resolve */ import { existsSync } from 'node:fs' import { join } from 'node:path' /** * Well-known Windows PowerShell install locations plus PATH entries, newest * first. Explicitly parameterized (env) so resolution is a pure function of * its inputs on every platform. * @param env - the environment to probe; defaults to the process environment. * @returns candidate `pwsh` executable paths in resolution order. */ export function candidatePwshPaths(env: NodeJS.ProcessEnv = process.env): string[] { const programFiles = env.ProgramFiles ?? 'C:\\Program Files' const systemRoot = env.SystemRoot ?? 'C:\\Windows' const candidates = [ join(programFiles, 'PowerShell', '7', 'pwsh.exe'), ] // Microsoft Store installs (and any user-added location) live on PATH; // entries may carry surrounding quotes from `setx`-style definitions. for (const entry of (env.PATH ?? '').split(';')) { const trimmed = entry.trim().replace(/^"|"$/g, '') if (trimmed.length === 0) continue candidates.push(join(trimmed, 'pwsh.exe')) } // Windows PowerShell 5.1 remains the last-resort fallback on legacy hosts. candidates.push(join(systemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe')) return candidates } /** * Resolve the pwsh executable this executor spawns. * @param configured - an explicit `pwshPath` config value, trusted as-is. * @param env - the environment to probe on Windows; defaults to the process environment. * @param platform - the platform to resolve for; defaults to the process platform. * @returns the first existing well-known location on Windows (PowerShell 7 * install, a PATH entry such as the Microsoft Store install, then Windows * PowerShell 5.1), else `pwsh` for PATH resolution. */ export function resolvePwshPath( configured?: string, env: NodeJS.ProcessEnv = process.env, platform: NodeJS.Platform = process.platform, ): string { if (configured !== undefined && configured.length > 0) return configured if (platform === 'win32') { for (const candidate of candidatePwshPaths(env)) { if (existsSync(candidate)) return candidate } } return 'pwsh' }