Files
pnpm/exec/plugin-commands-script-runners/src/buildCommandNotFoundHint.ts
2024-04-13 00:18:14 +02:00

62 lines
1.8 KiB
TypeScript

import { type PackageScripts } from '@pnpm/types'
import didYouMean, { ReturnTypeEnums } from 'didyoumean2'
import { readdirSync } from 'fs'
import path from 'path'
export function getNearestProgram ({
dir,
modulesDir,
programName,
workspaceDir,
}: {
dir: string
modulesDir: string
programName: string
workspaceDir: string | undefined
}): string | null {
try {
const binDir = path.join(dir, modulesDir, '.bin')
const programList = readProgramsFromDir(binDir)
if (workspaceDir && workspaceDir !== dir) {
const workspaceBinDir = path.join(workspaceDir, modulesDir, '.bin')
programList.push(...readProgramsFromDir(workspaceBinDir))
}
return getNearest(programName, programList)
} catch {
return null
}
}
function readProgramsFromDir (binDir: string): string[] {
const files = readdirSync(binDir)
if (process.platform !== 'win32') return files
const executableExtensions = ['.cmd', '.bat', '.ps1', '.exe', '.com']
return files.map((fullName) => {
const { name, ext } = path.parse(fullName)
return executableExtensions.includes(ext.toLowerCase()) ? name : fullName
})
}
export function buildCommandNotFoundHint (scriptName: string, scripts?: PackageScripts | undefined): string {
let hint = `Command "${scriptName}" not found.`
const nearestCommand = getNearestScript(scriptName, scripts)
if (nearestCommand) {
hint += ` Did you mean "pnpm run ${nearestCommand}"?`
}
return hint
}
export function getNearestScript (scriptName: string, scripts?: PackageScripts | undefined): string | null {
return getNearest(scriptName, Object.keys(scripts ?? []))
}
export function getNearest (name: string, list: readonly string[]): string | null {
if (list == null || list.length === 0) return null
return didYouMean(name, list, {
returnType: ReturnTypeEnums.FIRST_CLOSEST_MATCH,
})
}