init project

This commit is contained in:
root
2026-07-31 13:12:54 -04:00
parent 0da92d5e02
commit f3863f760c
7215 changed files with 1860260 additions and 1 deletions
+170
View File
@@ -0,0 +1,170 @@
import fs from 'node:fs';
import fsPromises from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
const isWindows = process.platform === 'win32';
// A command containing a directory separator is treated as a path and looked up directly, instead of being searched for in `PATH`. Backslash only counts as a separator on Windows, since it's a valid filename character on other platforms.
const separatorPattern = isWindows ? /[\/\\]/v : /\//v;
// The standard Windows executable extensions, used when `PATHEXT` is not set.
const defaultPathExt = '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC';
function resolveOptions(command, options) {
if (typeof command !== 'string' || command.length === 0) {
throw new TypeError('Expected a non-empty string.');
}
const {
cwd = process.cwd(),
// On Windows, `process.env.PATH` can be undefined in some contexts (for example, worker threads), where it's only exposed as `Path`.
path: searchPath = process.env.PATH ?? (isWindows ? process.env.Path : undefined) ?? '',
// `||` (not `??`) so an empty `PATHEXT` falls back to the default instead of disabling all lookup on Windows.
pathExt = process.env.PATHEXT || defaultPathExt,
} = options;
return {cwd, searchPath, pathExt};
}
function windowsExtensions(command, pathExt) {
const extensions = pathExt.split(path.delimiter).filter(Boolean);
const commandExtension = path.extname(command).toLowerCase();
// If the command already ends with a known executable extension, also try it verbatim.
if (commandExtension !== '' && extensions.some(extension => extension.toLowerCase() === commandExtension)) {
return ['', ...extensions];
}
return extensions;
}
function * candidatePaths(command, {cwd, searchPath, pathExt}) {
const extensions = isWindows ? windowsExtensions(command, pathExt) : [''];
if (separatorPattern.test(command)) {
const base = path.resolve(cwd, command);
for (const extension of extensions) {
yield base + extension;
}
return;
}
const directories = [
// Windows searches the current directory before `PATH`.
...(isWindows ? [cwd] : []),
...searchPath.split(path.delimiter),
];
for (const directory of directories) {
// `PATH` entries can be wrapped in double quotes on Windows.
const unquoted = isWindows && directory.length > 1 && directory.startsWith('"') && directory.endsWith('"') ? directory.slice(1, -1) : directory;
// Skip empty entries. Unlike a POSIX shell, an empty entry is not treated as the current directory, since implicitly searching the current directory is a security risk. Checked after unquoting so a quoted-empty entry (`""`) is skipped too.
if (unquoted === '') {
continue;
}
const base = path.resolve(cwd, unquoted, command);
for (const extension of extensions) {
yield base + extension;
}
}
}
async function isExecutable(filePath) {
let stats;
try {
stats = await fsPromises.stat(filePath);
} catch (error) {
// Windows App Execution Aliases (in `WindowsApps`) throw `EACCES` on `stat`, but are valid, launchable executables.
return isWindows && error.code === 'EACCES';
}
// A directory can have the executable bit set, but it's not a command.
if (!stats.isFile()) {
return false;
}
// On Windows, executability is determined by the file extension, which is already validated against `PATHEXT`.
if (isWindows) {
return true;
}
try {
await fsPromises.access(filePath, fs.constants.X_OK);
return true;
} catch {
return false;
}
}
function isExecutableSync(filePath) {
let stats;
try {
stats = fs.statSync(filePath);
} catch (error) {
return isWindows && error.code === 'EACCES';
}
if (!stats.isFile()) {
return false;
}
if (isWindows) {
return true;
}
try {
fs.accessSync(filePath, fs.constants.X_OK);
return true;
} catch {
return false;
}
}
export async function whichCommand(command, options = {}) {
const resolved = resolveOptions(command, options);
for (const candidate of candidatePaths(command, resolved)) {
// Checked sequentially so the first match in `PATH` order wins and the search can short-circuit.
if (await isExecutable(candidate)) { // eslint-disable-line no-await-in-loop
return candidate;
}
}
return undefined;
}
export function whichCommandSync(command, options = {}) {
const resolved = resolveOptions(command, options);
for (const candidate of candidatePaths(command, resolved)) {
if (isExecutableSync(candidate)) {
return candidate;
}
}
return undefined;
}
export async function whichCommandAll(command, options = {}) {
const resolved = resolveOptions(command, options);
const candidates = [...candidatePaths(command, resolved)];
const matches = await Promise.all(candidates.map(async candidate => (await isExecutable(candidate)) ? candidate : undefined));
return [...new Set(matches.filter(Boolean))];
}
export function whichCommandAllSync(command, options = {}) {
const resolved = resolveOptions(command, options);
const found = [];
for (const candidate of candidatePaths(command, resolved)) {
if (isExecutableSync(candidate)) {
found.push(candidate);
}
}
return [...new Set(found)];
}