UNPKG

snow-flow

Version:

Snow-Flow - AI-powered ServiceNow development CLI with 410+ MCP tools

188 lines (158 loc) 5.68 kB
#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const os = require('os'); const https = require('https'); const { execSync } = require('child_process'); const zlib = require('zlib'); const platform = os.platform() === 'win32' ? 'windows' : os.platform(); const arch = os.arch() === 'arm64' ? 'arm64' : 'x64'; const binaryName = platform === 'windows' ? 'snow-code.exe' : 'snow-code'; const packageDir = __dirname; const binDir = path.join(packageDir, 'bin'); const binaryPath = path.join(binDir, binaryName); const distDir = path.join(packageDir, 'dist'); const mcpDir = path.join(distDir, 'mcp'); const mcpIndexPath = path.join(mcpDir, 'enterprise-proxy', 'index.js'); // Get version from package.json function getVersion() { try { const pkg = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8')); return pkg.version; } catch { return null; } } // Get version from installed binary function getBinaryVersion() { try { if (!fs.existsSync(binaryPath)) return null; const result = execSync(`"${binaryPath}" --version`, { encoding: 'utf8', stdio: 'pipe' }); return result.trim(); } catch { return null; } } // Follow redirects and download file function download(url) { return new Promise((resolve, reject) => { const request = https.get(url, { headers: { 'User-Agent': 'snow-flow-installer' } }, (response) => { if (response.statusCode === 302 || response.statusCode === 301) { download(response.headers.location).then(resolve).catch(reject); return; } if (response.statusCode !== 200) { reject(new Error(`Failed to download: HTTP ${response.statusCode}`)); return; } const chunks = []; response.on('data', chunk => chunks.push(chunk)); response.on('end', () => resolve(Buffer.concat(chunks))); response.on('error', reject); }); request.on('error', reject); }); } async function downloadBinary() { const version = getVersion(); if (!version) { console.log('Could not determine version, skipping binary download'); return false; } const assetName = `snow-flow-${platform}-${arch}`; const tarballName = `${assetName}.tar.gz`; const releaseUrl = `https://github.com/groeimetai/snow-flow/releases/download/v${version}/${tarballName}`; console.log(`Downloading snow-flow binary for ${platform}-${arch}...`); console.log(`URL: ${releaseUrl}`); try { // Download the tarball const tarballData = await download(releaseUrl); // Create temp file const tmpDir = os.tmpdir(); const tarballPath = path.join(tmpDir, tarballName); fs.writeFileSync(tarballPath, tarballData); // Ensure bin directory exists if (!fs.existsSync(binDir)) { fs.mkdirSync(binDir, { recursive: true }); } // Extract using tar command console.log('Extracting binary...'); execSync(`tar -xzf "${tarballPath}" -C "${binDir}" --strip-components=1`, { stdio: 'pipe' }); // Clean up fs.unlinkSync(tarballPath); // Make executable on non-Windows if (platform !== 'windows' && fs.existsSync(binaryPath)) { fs.chmodSync(binaryPath, 0o755); } console.log('✅ Binary installed successfully!'); return true; } catch (error) { console.log(`Note: Could not download pre-built binary (${error.message})`); console.log('You may need to build from source or check your network connection.'); return false; } } async function downloadMcpServers() { const version = getVersion(); if (!version) { console.log('Could not determine version, skipping MCP download'); return false; } const tarballName = 'snow-flow-mcp.tar.gz'; const releaseUrl = `https://github.com/groeimetai/snow-flow/releases/download/v${version}/${tarballName}`; console.log('Downloading MCP servers...'); try { // Download the tarball const tarballData = await download(releaseUrl); // Create temp file const tmpDir = os.tmpdir(); const tarballPath = path.join(tmpDir, tarballName); fs.writeFileSync(tarballPath, tarballData); // Ensure dist directory exists if (!fs.existsSync(distDir)) { fs.mkdirSync(distDir, { recursive: true }); } // Extract MCP servers console.log('Extracting MCP servers...'); execSync(`tar -xzf "${tarballPath}" -C "${distDir}"`, { stdio: 'pipe' }); // Clean up fs.unlinkSync(tarballPath); console.log('✅ MCP servers installed successfully!'); return true; } catch (error) { console.log(`Note: Could not download MCP servers (${error.message})`); console.log('Enterprise features may not be available.'); return false; } } async function main() { const packageVersion = getVersion(); const binaryVersion = getBinaryVersion(); // Download binary if missing or version mismatch if (!fs.existsSync(binaryPath)) { console.log('Binary not found, downloading...'); await downloadBinary(); } else if (packageVersion && binaryVersion && packageVersion !== binaryVersion) { console.log(`Version mismatch: binary is ${binaryVersion}, package is ${packageVersion}`); console.log('Downloading correct version...'); // Remove old binary first try { fs.unlinkSync(binaryPath); } catch {} await downloadBinary(); } else { // Make sure it's executable if (platform !== 'windows') { try { fs.chmodSync(binaryPath, 0o755); } catch {} } } // Download MCP servers if needed if (!fs.existsSync(mcpIndexPath)) { await downloadMcpServers(); } } main().catch(err => { console.log(`Postinstall failed: ${err.message}`); });