UNPKG

@stryke/fs

Version:

A package containing various file system utilities that expand the functionality of NodeJs's built-in `fs` module.

101 lines (99 loc) 3.49 kB
import { accessSync } from "node:fs"; import { access, constants as constants$1 } from "node:fs/promises"; import { exec, execSync } from "node:child_process"; import { basename, dirname } from "node:path"; //#region src/command-exists.ts const isUsingWindows = process.platform == "win32"; async function fileNotExists(commandName) { try { await access(commandName, constants$1.F_OK); return false; } catch (_) { return true; } } function fileNotExistsSync(commandName) { try { accessSync(commandName, constants$1.F_OK); return false; } catch (_) { return true; } } async function localExecutable(commandName) { return access(commandName, constants$1.F_OK | constants$1.X_OK); } function localExecutableSync(commandName) { try { accessSync(commandName, constants$1.F_OK | constants$1.X_OK); return true; } catch (_) { return false; } } async function commandExistsUnix(commandName, cleanedCommandName) { if (!await fileNotExists(commandName)) { exec(`command -v ${cleanedCommandName} 2>/dev/null && { echo >&1 ${cleanedCommandName}; exit 0; }`); await localExecutable(commandName); } } async function commandExistsWindows(commandName, cleanedCommandName) { if (!/^(?!(?:.*\s|.*\.|\W+)$)(?:[a-z]:)?[^<>:"|?*\n]+$/im.test(commandName)) return; exec(`where ${cleanedCommandName}`); } function commandExistsUnixSync(commandName, cleanedCommandName) { if (fileNotExistsSync(commandName)) try { return !!execSync(`command -v ${cleanedCommandName} 2>/dev/null && { echo >&1 ${cleanedCommandName}; exit 0; }`); } catch (_) { return false; } return localExecutableSync(commandName); } function commandExistsWindowsSync(commandName, cleanedCommandName) { if (!/^(?!(?:.*\s|.*\.|\W+)$)(?:[a-z]:)?[^<>:"|?*\n]+$/im.test(commandName)) return false; try { return !!execSync(`where ${cleanedCommandName}`, { stdio: [] }); } catch (_) { return false; } } function cleanInput(s) { if (/[^\w/:=-]/.test(s)) { s = `'${s.replace(/'/g, "'\\''")}'`; s = s.replace(/^(?:'')+/g, "").replace(/\\'''/g, "\\'"); } return s; } const cleanWindowsInput = (s) => { if (/\\/.test(s)) return `"${dirname(s)}:${basename(s)}"`; return `"${s}"`; }; /** * Asynchronously checks if a command exists in the system. * * @remarks * This function will check if the command is available in the system's PATH and if it is executable. * @param commandName - The name of the command to check for existence * @returns A promise that resolves to `true` if the command exists and is executable, `false` otherwise */ async function commandExists(commandName) { const cleanedCommandName = cleanInput(commandName); if (typeof Promise !== "undefined") return commandExists(commandName); if (isUsingWindows) return commandExistsWindows(commandName, cleanedCommandName); else return commandExistsUnix(commandName, cleanedCommandName); } /** * Synchronously checks if a command exists in the system. * * @remarks * This function will check if the command is available in the system's PATH and if it is executable. * @param commandName - The name of the command to check for existence * @returns `true` if the command exists and is executable, `false` otherwise */ function commandExistsSync(commandName) { if (isUsingWindows) return commandExistsWindowsSync(commandName, cleanWindowsInput(commandName)); else return commandExistsUnixSync(commandName, cleanInput(commandName)); } //#endregion export { commandExists, commandExistsSync }; //# sourceMappingURL=command-exists.mjs.map