UNPKG

nvenv

Version:

Python venv-like Node.js environment manager - project-local Node.js installation without global environment pollution

84 lines (72 loc) 2.57 kB
const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const { log, isWindows } = require('./utils'); /** * Extract archive file to destination directory * @param {string} archivePath - Path to archive file (.tar.gz or .zip) * @param {string} destDir - Destination directory * @param {object} options - Options { silent: boolean } * @returns {Promise<void>} */ async function extractArchive(archivePath, destDir, options = {}) { if (!fs.existsSync(archivePath)) { throw new Error(`Archive file not found: ${archivePath}`); } // Create destination directory if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } const ext = path.extname(archivePath); log(`Extracting archive: ${archivePath}`, options); log(`Destination: ${destDir}`, options); try { if (ext === '.gz' || archivePath.endsWith('.tar.gz')) { // Extract tar.gz using tar command execSync(`tar -xzf "${archivePath}" -C "${destDir}"`, { stdio: 'inherit' }); } else if (ext === '.zip') { // Extract zip using unzip command (Unix) or PowerShell (Windows) if (isWindows()) { // Windows: use PowerShell with LiteralPath and Force flags execSync( `powershell.exe -NoProfile -Command "Expand-Archive -LiteralPath '${archivePath}' -DestinationPath '${destDir}' -Force"`, { stdio: 'inherit' } ); } else { // Unix: use unzip execSync(`unzip -q "${archivePath}" -d "${destDir}"`, { stdio: 'inherit' }); } } else { throw new Error(`Unsupported archive format: ${ext}`); } log('Extraction completed!', options); } catch (error) { throw new Error(`Failed to extract archive: ${error.message}`); } } /** * Find the extracted Node.js directory * Handles cases where archive extracts to a subdirectory * @param {string} extractDir - Directory where archive was extracted * @returns {string} Path to Node.js installation directory */ function findNodeDirectory(extractDir) { const entries = fs.readdirSync(extractDir); // Look for directory matching pattern: node-v* const nodeDir = entries.find(entry => { const fullPath = path.join(extractDir, entry); return fs.statSync(fullPath).isDirectory() && entry.startsWith('node-v'); }); if (!nodeDir) { throw new Error(`Could not find Node.js directory in ${extractDir}`); } return path.join(extractDir, nodeDir); } module.exports = { extractArchive, findNodeDirectory };