UNPKG

pmpn

Version:

A typosafe wrapper for pnpm

252 lines (250 loc) 7.51 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const child_process_1 = require("child_process"); const process_1 = require("process"); // Constants const PNPM_NAME = "pnpm"; const FRAME_TIME = 100; // milliseconds between frames // Get terminal width function getTermWidth() { try { return process_1.stdout.columns || 80; } catch { return 80; // Default if can't detect } } // Animation frames for the car (using multiline template literals) const carFrames = [ // Frame 0 (Normal position) ` ______________ /| |\\ / |____________| \\ /__|____________|__\\ | __ __ | | |__| |__| | | ____P_M_P_N____ | \\_/ \\ / \\_/ \\__/ \\__/`, // Frame 1 (Rising) ` ______________ /| |\\ / |____________| \\ /__|____________|__\\ | __ __ | | |__| |__| | | ____P_M_P_N____ | \\_/_||_____x___||_\\_/ / \\ / \\ \\__/ \\__/`, // Frame 2 (Highest position) ` ______________ /| |\\ / |____________| \\ /__|____________|__\\ | __ __ | | |__| |__| | | ____P_M_P_N____ | \\_/ || || \\_/ \\_||_____x___||_/ / \\ / \\ \\__/ \\__/`, // Frame 3 (Tilted Left - mild) ` ______ _______/ |\\ /| ______| \\ / |_____/ _____|__\\ /__|______/ __ | | __ |__| | | |__| P_N____ | | ____P_M/____||_\\_/ \\_/ \\ / \\ \\__/ \\__/`, // Frame 4 (Tilted Left - max) ` ___ ____/ |\\ ____/ ___| \\ /| ____/ __|__\\ / |___/ ____/ __ | /__|____/ |__| | | __ N____ | | |__| M_P/ || \\_/ | ____P/_x____||_/ \\_/ \\ / \\ \\__/ \\__/`, // Frame 5 (Tilted Right - mild) ` ______ /| \\_______ / |______ |\\ /__|_____ \\_____| \\ | __ \\______|__\\ | |__| __ | | ____P_M |__| | \\_/__||_____\\P_N____ | / \\ / \\_/ \\__/ \\__/`, // Frame 6 (Tilted Right - max) ` ____ /| \\_____ / |____ \\___ /__|___ \\____ |\\ | __ \\____ \\__| \\ | |__| \\___|__\\ | ____P __ | \\_/ || \\M_P |__| | \\_||_____x_\\N____ | / \\ / \\_/ \\__/ \\__/`, ]; /** * Gets the number of lines in the first animation frame. */ function getFrameLines() { return carFrames[0].split("\n"); } /** * Gets the width of the widest line in the first animation frame. */ function getCarWidth() { const lines = getFrameLines(); return Math.max(...lines.map((line) => line.length)); } /** * Clear the console and move cursor to top */ function clearAndMoveCursorToTop() { // Move cursor up by the number of lines in our animation const numLines = getFrameLines().length; process.stdout.write(`\x1B[${numLines}A`); } /** * Clear the animation area */ function clearAnimationArea() { clearAndMoveCursorToTop(); const numLines = getFrameLines().length; const termWidth = getTermWidth(); for (let i = 0; i < numLines; i++) { console.log(" ".repeat(termWidth)); } clearAndMoveCursorToTop(); // Move cursor back to top after clearing } /** * Draws a single frame of the animation */ function drawFrame(frameIndex, xPosition) { const frame = carFrames[frameIndex]; const termWidth = getTermWidth(); const frameLines = frame.split("\n"); // Clear the entire animation area first clearAnimationArea(); // Draw current frame frameLines.forEach((line) => { if (xPosition < 0) { // Calculate how much of the line to show when partially off-screen const visiblePart = line.substring(Math.min(Math.abs(xPosition), line.length)); const padding = ""; // No padding needed as we're off-screen to the left console.log(padding + (visiblePart || "")); } else { // Line with padding when car is on-screen const padding = " ".repeat(Math.min(xPosition, termWidth)); console.log(padding + line); } }); } /** * Run the bouncing car animation */ async function animateCar() { const termWidth = getTermWidth(); const frameLines = getFrameLines(); // Get lines of the first frame const carWidth = getCarWidth(); // Get the actual width of the car art // Add initial empty lines for animation space console.log("\n".repeat(frameLines.length)); // Animation sequence // First move from left to center const centerPosition = Math.floor(termWidth / 2) - Math.floor(carWidth / 2); // Start at position 0 (left edge of screen) const startPosition = 0; // Calculate endpoint - either travel 24 spaces or go to center if center is closer const maxAnimationDistance = 24; const endPosition = Math.min(startPosition + maxAnimationDistance, centerPosition); // 1. Slide in from the left (exactly like it does now) for (let x = startPosition; x <= endPosition; x += 3) { drawFrame(0, x); await new Promise((resolve) => setTimeout(resolve, FRAME_TIME)); } // At this point, we're at the end position with frame 0 (normal position) // Frames for the bounce animation sequences const bounceSequence = [ { frame: 1 }, { frame: 2 }, { frame: 1 }, { frame: 0 }, ]; const bounceLeftSequence = [ { frame: 3 }, { frame: 4 }, { frame: 3 }, { frame: 0 }, ]; const bounceRightSequence = [ { frame: 5 }, { frame: 6 }, { frame: 5 }, { frame: 0 }, { frame: 0 }, ]; for (const { frame } of [...bounceSequence, ...bounceLeftSequence, ...bounceRightSequence]) { drawFrame(frame, endPosition); await new Promise((resolve) => setTimeout(resolve, FRAME_TIME)); } // Clear the animation clearAnimationArea(); } /** * Main function */ async function main() { try { // Run the car animation await animateCar(); // Get the arguments to pass to pnpm const args = process.argv.slice(2); // Execute pnpm with arguments try { (0, child_process_1.execSync)(`${PNPM_NAME} ${args.join(" ")}`, { stdio: "inherit" }); } catch (error) { // If pnpm fails, pass its error code if (error instanceof Error && "status" in error && typeof error.status === "number") { process.exit(error.status); } else { process.exit(1); } } } catch (error) { console.error("Animation error:", error); // Try to run pnpm anyway try { (0, child_process_1.execSync)(`${PNPM_NAME} ${process.argv.slice(2).join(" ")}`, { stdio: "inherit", }); } catch (cmdError) { process.exit(1); } } } // Start the program main();