Skip to content

Instantly share code, notes, and snippets.

@WomB0ComB0
Created April 23, 2025 02:53
Show Gist options
  • Save WomB0ComB0/a11c50b0bbd6354a961dcb49dc5e2711 to your computer and use it in GitHub Desktop.
Save WomB0ComB0/a11c50b0bbd6354a961dcb49dc5e2711 to your computer and use it in GitHub Desktop.
bun-shell-case.ts and related files - with AI-generated descriptions
import { $ } from 'bun';
import { platform as osPlatform } from 'node:os';
// Removed unused 'exec' import
/**
* Enum representing the detected operating system platform.
*/
export enum Platform {
Windows = 'windows',
Mac = 'mac',
Linux = 'linux',
Unknown = 'unknown',
}
/**
* Interface describing the detected platform information.
*/
export interface IPlatformInfo {
/** The detected operating system platform. */
platform: Platform;
/** True if the platform is Windows. */
isWindows: boolean;
/** True if the platform is macOS. */
isMac: boolean;
/** True if the platform is Linux. */
isLinux: boolean;
/** True if running under Windows Subsystem for Linux. */
isWsl: boolean;
/** True if running under WSL version 2. */
isWsl2: boolean;
}
function determinePlatformInfo(): IPlatformInfo {
const os = osPlatform();
const isWindows = os === 'win32';
const isMac = os === 'darwin';
const isLinux = os === 'linux';
const isWsl = process.env.WSL_DISTRO_NAME !== undefined;
const isWsl2 = isWsl && process.env.WSL_INTEROP !== undefined;
let platform: Platform;
if (isWindows) platform = Platform.Windows;
else if (isMac) platform = Platform.Mac;
else if (isLinux) platform = Platform.Linux;
else platform = Platform.Unknown;
return Object.freeze({
platform,
isWindows,
isMac,
isLinux,
isWsl,
isWsl2,
});
}
/**
* Singleton instance containing information about the current platform.
* Uses Object.freeze for immutability.
*/
export const platformInfo: IPlatformInfo = determinePlatformInfo();
// --- Package Manager Detection ---
interface PackageManagerInfo {
name: string;
command: string;
}
const nodePackageManagers: ReadonlyArray<PackageManagerInfo> = [
{ name: 'bun', command: 'bun --version' },
{ name: 'pnpm', command: 'pnpm --version' },
{ name: 'yarn', command: 'yarn --version' },
{ name: 'npm', command: 'npm --version' },
];
function getSystemPackageManagers(): ReadonlyArray<PackageManagerInfo> {
switch (platformInfo.platform) {
case Platform.Mac:
return [{ name: 'brew', command: 'brew --version' }];
case Platform.Windows:
return [
{ name: 'winget', command: 'winget --version' },
{ name: 'scoop', command: 'scoop --version' },
{ name: 'choco', command: 'choco --version' },
];
case Platform.Linux:
return [
{ name: 'apt', command: 'apt --version' }, // Common on Debian/Ubuntu
{ name: 'dnf', command: 'dnf --version' }, // Fedora, RHEL 8+
{ name: 'pacman', command: 'pacman --version' }, // Arch
{ name: 'paru', command: 'paru --version' }, // Arch AUR Helper (often installed with pacman)
{ name: 'yum', command: 'yum --version' }, // CentOS/RHEL 7
];
default:
return [];
}
}
const systemPackageManagers = getSystemPackageManagers();
const allKnownPackageManagers = [...nodePackageManagers, ...systemPackageManagers];
/**
* Checks if a command exists and runs successfully.
* @param pmInfo - The package manager info { name, command }.
* @returns The name of the package manager if found, otherwise null.
*/
async function checkPackageManager(pmInfo: PackageManagerInfo): Promise<string | null> {
try {
const result = await $`${pmInfo.command}`.nothrow();
if (result.exitCode === 0) {
console.debug(`Detected package manager: ${pmInfo.name}`);
return pmInfo.name;
}
} catch (error: any) {
if (error?.code !== 'ENOENT' && !error.message?.includes('command not found')) {
console.debug(`Error checking for ${pmInfo.name} (${pmInfo.command}): ${error.message}`);
}
}
return null;
}
/**
* Detects the first available Node.js package manager (npm, yarn, pnpm, bun).
* @returns Promise resolving to the name of the first detected Node.js package manager, or null if none are found.
*/
export async function detectNodePackageManager(): Promise<string | null> {
console.debug('Detecting Node.js package managers...');
for (const pm of nodePackageManagers) {
const found = await checkPackageManager(pm);
if (found) return found;
}
console.debug('No standard Node.js package manager detected.');
return null;
}
/**
* Detects the first available *system* package manager (apt, brew, winget, etc.).
* Useful for installing system-level software like Node.js itself.
* @returns Promise resolving to the name of the first detected system package manager, or null if none are found.
*/
export async function detectSystemPackageManager(): Promise<string | null> {
console.debug('Detecting system package managers...');
if (systemPackageManagers.length === 0) {
console.debug('No system package managers configured for this platform:', platformInfo.platform);
return null;
}
for (const pm of systemPackageManagers) {
const found = await checkPackageManager(pm);
if (found) return found;
}
console.debug('No supported system package manager detected.');
return null;
}
/**
* Installs Node.js using a specified *system* package manager.
* Note: This function requires appropriate permissions (e.g., sudo on Linux/Mac).
* It relies on Bun's `$` which handles shell execution.
*
* @param systemPackageManager - The system package manager to use (e.g., 'apt', 'brew', 'winget').
* @returns Promise that resolves when installation command completes, or rejects on error.
* @throws Error if the package manager is unsupported or the command fails.
*/
export async function installNodeJS(systemPackageManager: string): Promise<void> {
const commands: { [key: string]: string | undefined } = {
// Linux
'apt': 'sudo apt update && sudo apt install -y nodejs',
'dnf': 'sudo dnf install -y nodejs', // Might need nodejs-npm package separately on some distros
'yum': 'sudo yum install -y nodejs', // Older RHEL/CentOS
'pacman': 'sudo pacman -Syu --noconfirm nodejs npm', // Often need npm explicitly
'paru': 'paru -Syu --noconfirm nodejs npm', // Assumes paru is set up for non-interactive use
// macOS
'brew': 'brew install node',
// Windows
'winget': 'winget install -e --id Node.js.Nodejs', // ID might vary slightly, check with `winget search Node.js`
'choco': 'choco install nodejs --yes', // Use --yes for non-interactive
'scoop': 'scoop install nodejs',
};
const command = commands[systemPackageManager];
if (!command) {
throw new Error(`Unsupported package manager for Node.js installation: ${systemPackageManager}`);
}
console.log(`Attempting to install Node.js using ${systemPackageManager}...`);
console.log(`Executing: ${command}`);
try {
const result = await $`${command}`;
if (result.exitCode !== 0) {
throw new Error(`Node.js installation command failed with exit code ${result.exitCode}.`);
}
console.log(`Node.js installation command via ${systemPackageManager} completed successfully.`);
} catch (error: any) {
console.error(`Error installing Node.js using ${systemPackageManager}: ${error.message}`);
throw error;
}
}
// --- Example Usage / Diagnostic Script ---
// This block runs only when the script is executed directly (e.g., `bun run platform.ts`)
if (require.main === module) {
async function runDiagnostic(): Promise<void> {
console.log('--- Platform Information ---');
console.log(`Platform: ${platformInfo.platform}`);
console.log(`Is Windows: ${platformInfo.isWindows}`);
console.log(`Is Mac: ${platformInfo.isMac}`);
console.log(`Is Linux: ${platformInfo.isLinux}`);
console.log(`Is WSL: ${platformInfo.isWsl} (WSL2: ${platformInfo.isWsl2})`);
console.log('--------------------------\n');
console.log('--- Package Manager Detection ---');
const nodePM = await detectNodePackageManager();
console.log(`Detected Node.js PM: ${nodePM ?? 'None'}`);
const systemPM = await detectSystemPackageManager();
console.log(`Detected System PM: ${systemPM ?? 'None'}`);
console.log('-------------------------------\n');
// Example: Try installing Node.js if a system PM was found
// Uncomment carefully! This will attempt to install Node.js.
/*
if (systemPM) {
try {
console.log(`Attempting Node.js installation using ${systemPM}...`);
await installNodeJS(systemPM);
console.log("Node.js installation initiated successfully.");
} catch (error) {
console.error("Node.js installation failed:", error.message);
}
} else {
console.log("Cannot attempt Node.js installation: No supported system package manager detected.");
}
*/
}
runDiagnostic().catch(error => {
console.error("Diagnostic script failed:", error);
process.exit(1);
});
}

bun-shell-case.ts Description

File Type: ts

Generated Description:

bun-shell-case.ts Analysis

This TypeScript file provides functionality to detect the operating system and identify available package managers (both Node.js-specific and system-level) on the system. It's designed to be platform-agnostic and works across Windows, macOS, and Linux, including WSL environments.

Summary

The file aims to determine the current operating system, identify which package manager(s) (e.g., npm, yarn, bun, brew, apt, choco) are installed and available on the system. This information is crucial for scripts that need to interact with the system's package management capabilities, such as installing dependencies or other software.

Key Components and Functions

  • Platform enum: Defines an enum for representing different operating systems (Windows, macOS, Linux, Unknown).
  • IPlatformInfo interface: Defines an interface to structure information about the detected platform, including boolean flags for various platform-specific characteristics (e.g., isWsl, isWsl2).
  • **determinePlatformInfo(): ** This function detects the operating system and returns an IPlatformInfo object containing the details. It leverages os.platform() and environment variables (WSL_DISTRO_NAME, WSL_INTEROP) to accurately identify WSL environments.
  • **platformInfo: ** A singleton, immutable (Object.freeze) instance of IPlatformInfo, providing readily available platform details.
  • PackageManagerInfo interface: Defines the structure for package manager information (name and command).
  • nodePackageManagers & systemPackageManagers: Arrays of PackageManagerInfo objects listing common Node.js package managers and system package managers, respectively. systemPackageManagers is dynamically generated based on the detected platform.
  • **getSystemPackageManagers(): ** Returns an array of PackageManagerInfo based on the operating system detected. This uses a switch statement for platform-specific handling.
  • allKnownPackageManagers: Combines nodePackageManagers and systemPackageManagers into a single list.
  • checkPackageManager(pmInfo): Asynchronously checks if a given package manager is installed and functional by attempting to execute its version command. It uses Bun's $ tagged template literal for command execution and handles potential errors gracefully.
  • **detectNodePackageManager(): ** Asynchronously detects the first available Node.js package manager.
  • **detectSystemPackageManager(): ** Asynchronously detects the first available system package manager.

Notable Patterns and Techniques

  • Immutability: The platformInfo object is frozen using Object.freeze() to ensure its values cannot be modified after initialization, enhancing data integrity.
  • Singleton Pattern: The platformInfo is implemented as a singleton, ensuring only one instance exists throughout the application's lifecycle.
  • Asynchronous Operations: Package manager detection is done asynchronously using async/await, preventing blocking while waiting for external commands to finish.
  • Error Handling: The checkPackageManager function includes robust error handling using try...catch, specifically checking for ENOENT (file not found) errors and filtering out irrelevant errors.
  • Platform-Specific Logic: The use of a switch statement in getSystemPackageManagers demonstrates a clear way to handle platform-specific logic.
  • Functional Programming Principles: The code tends to favor pure functions and immutability, enhancing readability and testability.

Potential Use Cases

  • CLI tools: To determine which package manager to use for installing dependencies or other tasks.
  • Build scripts: To automate tasks that require platform-specific commands.
  • Installer scripts: To determine how to install Node.js (or other dependencies) based on the system and available package managers.
  • Cross-platform applications: To adapt the behavior or logic of an application to the underlying operating system.
  • Testing frameworks: To conditionally run tests based on the available platform and package managers.

The code is well-structured, robust, and clearly demonstrates best practices for asynchronous operations, error handling, and platform-specific logic. The use of Bun's $ simplifies command execution, and the overall design facilitates maintainability and reusability.

Description generated on 4/22/2025, 10:53:30 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment