UNPKG

@ordino.ai/cli

Version:
321 lines (289 loc) • 11.7 kB
import { execSync } from "child_process"; import { printMessage } from "./printMessage.util"; import { getVersionRequirements, getVersionRequirementsAsStrings } from "../config/version-requirements"; import fs from "fs"; import path from "path"; interface VersionInfo { major: number; minor: number; patch: number; } interface NodeVersionCheckResult { compatible: boolean; version: VersionInfo; error?: string; } interface NpmVersionCheckResult { compatible: boolean; version: VersionInfo; error?: string; } interface BrowserInfo { name: string; installLocation: string; } function parseVersion(versionString: string): VersionInfo { const match = versionString.match(/^v?(\d+)\.(\d+)\.(\d+)/); if (!match) { throw new Error(`Invalid version format: ${versionString}`); } return { major: parseInt(match[1], 10), minor: parseInt(match[2], 10), patch: parseInt(match[3], 10) }; } function compareVersions(required: VersionInfo, actual: VersionInfo): boolean { if (actual.major > required.major) return true; if (actual.major < required.major) return false; if (actual.minor > required.minor) return true; if (actual.minor < required.minor) return false; return actual.patch >= required.patch; } function getNodeVersion(): VersionInfo { try { const nodeVersion = execSync("node --version", { encoding: "utf8" }).trim(); return parseVersion(nodeVersion); } catch (error) { throw new Error("Failed to get Node.js version. Please ensure Node.js is installed and accessible."); } } function getNpmVersion(): VersionInfo { try { const npmVersion = execSync("npm --version", { encoding: "utf8" }).trim(); return parseVersion(npmVersion); } catch (error) { throw new Error("Failed to get npm version. Please ensure npm is installed and accessible."); } } export function checkNodeVersion(): NodeVersionCheckResult { const requiredVersions = getVersionRequirements(); const result: NodeVersionCheckResult = { compatible: false, version: { major: 0, minor: 0, patch: 0 } }; try { result.version = getNodeVersion(); result.compatible = compareVersions(requiredVersions.node, result.version); } catch (error) { result.error = error instanceof Error ? error.message : "Unknown error checking Node.js version"; } return result; } export function checkNpmVersion(): NpmVersionCheckResult { const requiredVersions = getVersionRequirements(); const result: NpmVersionCheckResult = { compatible: false, version: { major: 0, minor: 0, patch: 0 } }; try { result.version = getNpmVersion(); result.compatible = compareVersions(requiredVersions.npm, result.version); } catch (error) { result.error = error instanceof Error ? error.message : "Unknown error checking npm version"; } return result; } export function checkNodeVersionOnly(): boolean { const nodeCheck = checkNodeVersion(); const requiredVersionsStrings = getVersionRequirementsAsStrings(); printMessage("\nšŸ” Checking Node.js version...", "36", true); printMessage(`Current: ${nodeCheck.version.major}.${nodeCheck.version.minor}.${nodeCheck.version.patch}`, nodeCheck.compatible ? "32" : "31", false); printMessage(`Required: ${requiredVersionsStrings.node}`, "33", false); if (nodeCheck.error) { printMessage(`āŒ Error checking Node.js version: ${nodeCheck.error}`, "31", true); return false; } if (nodeCheck.compatible) { printMessage("āœ… Node.js version is compatible!", "32", true); return true; } else { printMessage("āŒ Node.js version is not compatible:", "31", true); printMessage(" • Download from: https://nodejs.org/", "36", false); printMessage(" • Or use Node Version Manager (nvm):", "36", false); printMessage(" - Windows: nvm install latest", "36", false); printMessage(" - macOS/Linux: nvm install node", "36", false); printMessage(" • Or use package manager:", "36", false); printMessage(" - Windows (Chocolatey): choco install nodejs", "36", false); printMessage(" - macOS (Homebrew): brew install node", "36", false); printMessage(" - Linux (apt): sudo apt update && sudo apt install nodejs", "36", false); return false; } } export function checkNpmVersionOnly(): boolean { const npmCheck = checkNpmVersion(); const requiredVersionsStrings = getVersionRequirementsAsStrings(); printMessage("\nšŸ” Checking npm version...", "36", true); printMessage(`Current: ${npmCheck.version.major}.${npmCheck.version.minor}.${npmCheck.version.patch}`, npmCheck.compatible ? "32" : "31", false); printMessage(`Required: ${requiredVersionsStrings.npm}`, "33", false); if (npmCheck.error) { printMessage(`āŒ Error checking npm version: ${npmCheck.error}`, "31", true); return false; } if (npmCheck.compatible) { printMessage("āœ… npm version is compatible!", "32", true); return true; } else { printMessage("āŒ npm version is not compatible:", "31", true); printMessage(" • Update npm globally: npm install -g npm@latest", "36", false); printMessage(" • Or use Node Version Manager (nvm):", "36", false); printMessage(" - nvm install-latest-npm", "36", false); printMessage(" • Or reinstall Node.js (includes latest npm):", "36", false); printMessage(" - Download from: https://nodejs.org/", "36", false); return false; } } export function displayVersionCheck(): boolean { const nodeCompatible = checkNodeVersionOnly(); const npmCompatible = checkNpmVersionOnly(); return nodeCompatible && npmCompatible; } function checkConfigFile(): boolean { const currentDir = process.cwd(); const configPath = path.join(currentDir, "ordino.config.ts"); const configExists = fs.existsSync(configPath); printMessage(`ordino.config.ts: ${configExists ? "āœ… Found" : "āŒ Not found"}`, configExists ? "32" : "31", false); return configExists; } function checkInitializeFile(): boolean { const currentDir = process.cwd(); const initializePath = path.join(currentDir, "ordino.initialize.js"); const initializeExists = fs.existsSync(initializePath); printMessage(`ordino.initialize.js: ${initializeExists ? "āœ… Found" : "āŒ Not found"}`, initializeExists ? "32" : "31", false); return initializeExists; } function parsePlaywrightDryRunOutput(output: string): BrowserInfo[] { const browsers: BrowserInfo[] = []; const lines = output.split('\n'); let currentBrowser: Partial<BrowserInfo> = {}; for (const line of lines) { const trimmedLine = line.trim(); const browserMatch = trimmedLine.match(/^browser:\s+(\S+)/); if (browserMatch) { if (currentBrowser.name && currentBrowser.installLocation) { browsers.push(currentBrowser as BrowserInfo); } currentBrowser = { name: browserMatch[1] }; continue; } const locationMatch = trimmedLine.match(/^Install location:\s+(.+)/); if (locationMatch && currentBrowser.name) { currentBrowser.installLocation = locationMatch[1].trim(); } } if (currentBrowser.name && currentBrowser.installLocation) { browsers.push(currentBrowser as BrowserInfo); } return browsers; } function extractBrowserVersionFromPath(installLocation: string): string | null { const match = installLocation.match(/[\\\/]([^\\\/]+)-(\d+)$/); if (match) { return match[2]; } return null; } export function checkPlaywrightBrowsers(cwd?: string): boolean { try { const playwrightVersion = execSync("npx playwright --version", { encoding: "utf8", stdio: "pipe", timeout: 10000, cwd: cwd }).trim(); let dryRunOutput = execSync("npx playwright install --dry-run", { encoding: "utf8", stdio: "pipe", timeout: 15000, cwd: cwd }); const browsers = parsePlaywrightDryRunOutput(dryRunOutput); const platform = process.platform; let playwrightDir = ''; if (platform === 'win32') { const userHome = process.env.USERPROFILE || ''; playwrightDir = path.join(userHome, 'AppData', 'Local', 'ms-playwright'); } else if (platform === 'darwin') { const userHome = process.env.HOME || ''; playwrightDir = path.join(userHome, 'Library', 'Caches', 'ms-playwright'); } else if (platform === 'linux') { const userHome = process.env.HOME || ''; playwrightDir = path.join(userHome, '.cache', 'ms-playwright'); } else { printMessage(`Playwright browser binaries: āŒ Not installed (${playwrightVersion}) - Unsupported platform`, "31", false); return false; } if (!fs.existsSync(playwrightDir)) { printMessage(`Playwright browser binaries: āŒ Not installed (${playwrightVersion})`, "31", false); printMessage(" • Run: npx playwright install", "36", false); return false; } const chromiumRelatedBrowsers = browsers.filter(browser => browser.name === 'chromium' || browser.name === 'chrome' || browser.name === 'msedge' || browser.name.includes('chromium') ); if (chromiumRelatedBrowsers.length === 0) { printMessage(`Playwright browser binaries: āŒ No chromium-related browsers found in dry-run (${playwrightVersion})`, "31", false); printMessage(" • Run: npx playwright install chromium", "36", false); return false; } const missingBrowsers: string[] = []; const availableBrowsers: string[] = []; chromiumRelatedBrowsers.forEach(browser => { if (fs.existsSync(browser.installLocation)) { const version = extractBrowserVersionFromPath(browser.installLocation); const browserVersion = version ? `${browser.name}-${version}` : browser.name; availableBrowsers.push(browserVersion); } else { missingBrowsers.push(browser.name); } }); if (missingBrowsers.length > 0) { printMessage(`Playwright browser binaries: āŒ Some chromium-related binaries missing (${playwrightVersion})`, "31", false); printMessage(` • Missing: ${missingBrowsers.join(', ')}`, "31", false); if (availableBrowsers.length > 0) { printMessage(` • Available: ${availableBrowsers.join(', ')}`, "36", false); } printMessage(" • Run: npx playwright install", "36", false); return false; } printMessage(`Playwright browser binaries: āœ… All chromium-related browsers installed (${playwrightVersion})`, "32", false); availableBrowsers.forEach(browserVersion => { printMessage(` • Found: ${browserVersion}`, "36", false); }); return true; } catch (error) { printMessage("Playwright browser binaries: āŒ Not installed", "31", false); printMessage(" • Run: npx playwright install", "36", false); return false; } } export function checkCypressFiles(): boolean { printMessage("\nšŸ” Checking Cypress configuration files...", "36", true); const configExists = checkConfigFile(); const initializeExists = checkInitializeFile(); if (configExists && initializeExists) { printMessage("āœ… All Cypress configuration files are present!", "32", true); return true; } return false; } export function checkPlaywrightFiles(): boolean { printMessage("\nšŸ” Checking Playwright configuration files...", "36", true); const configExists = checkConfigFile(); const initializeExists = checkInitializeFile(); const browsersInstalled = checkPlaywrightBrowsers(); if (configExists && initializeExists && browsersInstalled) { printMessage("āœ… All Playwright configuration files and browsers are present!", "32", true); return true; } return false; }