@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
JavaScript
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