UNPKG

navflow-browser-server

Version:

Standalone Playwright browser server for NavFlow - enables browser automation with API key authentication, workspace device management, session sync, and requires Node.js v22+

180 lines 7.54 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UpdateService = void 0; const axios_1 = __importDefault(require("axios")); const child_process_1 = require("child_process"); const util_1 = require("util"); const execAsync = (0, util_1.promisify)(child_process_1.exec); class UpdateService { constructor(packageName = 'navflow-browser-server', currentVersion, onShutdown) { this.packageName = packageName; this.currentVersion = currentVersion; this.onShutdown = onShutdown; } /** * Check the latest version available on npm */ async getLatestVersion() { try { console.log(`🔍 Checking latest version for ${this.packageName}...`); const response = await axios_1.default.get(`https://registry.npmjs.org/${this.packageName}`, { timeout: 10000, headers: { 'Accept': 'application/json' } }); const latestVersion = response.data['dist-tags'].latest; console.log(`📦 Latest version on npm: ${latestVersion}`); return latestVersion; } catch (error) { console.error('❌ Failed to check latest version from npm:', error.message); return null; } } /** * Compare version strings (semver-like comparison) */ compareVersions(version1, version2) { const v1parts = version1.split('.').map(Number); const v2parts = version2.split('.').map(Number); for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) { const v1part = v1parts[i] || 0; const v2part = v2parts[i] || 0; if (v1part < v2part) return -1; if (v1part > v2part) return 1; } return 0; } /** * Check if an update is available */ async isUpdateAvailable() { const latestVersion = await this.getLatestVersion(); if (!latestVersion) { return { available: false }; } const comparison = this.compareVersions(this.currentVersion, latestVersion); const available = comparison < 0; // Current version is older than latest if (available) { console.log(`🆙 Update available: ${this.currentVersion}${latestVersion}`); } else { console.log(`✅ Already running latest version: ${this.currentVersion}`); } return { available, latestVersion: available ? latestVersion : undefined }; } /** * Perform the update by restarting with the latest version */ async performUpdate() { try { console.log('🚀 Starting auto-update process...'); // Debug: Show process arguments console.log('🔍 Process info:'); console.log(' - argv[0]:', process.argv[0]); console.log(' - argv[1]:', process.argv[1]); console.log(' - npm_execpath:', process.env.npm_execpath); console.log(' - npm_command:', process.env.npm_command); // Check if we're running via npx const isNpx = process.argv[0].includes('npx') || process.env.npm_execpath || process.env.npm_command === 'exec' || process.argv[1]?.includes('navflow-browser-server'); console.log('🔧 NPX detection result:', isNpx); if (!isNpx) { console.warn('⚠️ Auto-update only supported when running via npx'); console.log('💡 To enable auto-updates, run: npx navflow-browser-server@latest'); console.log('📋 Current execution method appears to be direct node execution'); return false; } console.log('🔄 Restarting with latest version...'); console.log('📋 Command: npx --yes navflow-browser-server@latest'); // Get current process arguments (excluding node and script path) const args = process.argv.slice(2); const argsString = args.length > 0 ? ` ${args.join(' ')}` : ''; // Execute the update command // Note: This will terminate the current process and start a new one const updateCommand = `npx --yes navflow-browser-server@latest${argsString}`; console.log(`🎯 Executing: ${updateCommand}`); console.log('👋 Current process will terminate...'); // Method 1: Try direct spawn approach try { const child = (0, child_process_1.spawn)('npx', ['--yes', 'navflow-browser-server@latest', ...args], { detached: true, stdio: 'inherit', shell: true }); child.unref(); console.log(`✅ New process spawned (PID: ${child.pid})`); // Give the new process time to start setTimeout(async () => { console.log('🔄 Shutting down current process...'); // Call shutdown handler if provided if (this.onShutdown) { await this.onShutdown(); } process.exit(0); }, 2000); return true; } catch (spawnError) { console.warn('⚠️ Spawn method failed, trying exec method...', spawnError); // Method 2: Fallback to exec with shell (0, child_process_1.exec)(updateCommand, (error, stdout, stderr) => { if (error) { console.error('❌ Exec method also failed:', error.message); } }); setTimeout(async () => { console.log('🔄 Shutting down current process (exec method)...'); // Call shutdown handler if provided if (this.onShutdown) { await this.onShutdown(); } process.exit(0); }, 2000); return true; } return true; } catch (error) { console.error('❌ Auto-update failed:', error.message); return false; } } /** * Schedule automatic update check */ scheduleUpdateCheck(intervalMinutes = 60) { console.log(`⏰ Scheduling update checks every ${intervalMinutes} minutes`); return setInterval(async () => { try { const { available, latestVersion } = await this.isUpdateAvailable(); if (available && latestVersion) { console.log(`🔔 New version ${latestVersion} is available!`); console.log('💡 Update will be applied automatically when no flows are running'); } } catch (error) { console.warn('⚠️ Scheduled update check failed:', error); } }, intervalMinutes * 60 * 1000); } /** * Get current version */ getCurrentVersion() { return this.currentVersion; } } exports.UpdateService = UpdateService; //# sourceMappingURL=UpdateService.js.map