Download and extract Node.js binary
()
| 68 | |
| 69 | |
| 70 | def download_and_extract_node(): |
| 71 | """Download and extract Node.js binary""" |
| 72 | url, filename, is_zip = get_node_download_info() |
| 73 | download_path = TOOLS_DIR / filename |
| 74 | |
| 75 | # Get architecture for extraction path |
| 76 | machine = platform.machine().lower() |
| 77 | if machine in ["x86_64", "amd64"]: |
| 78 | arch = "x64" |
| 79 | elif machine in ["aarch64", "arm64"]: |
| 80 | arch = "arm64" |
| 81 | else: |
| 82 | raise ValueError(f"Unsupported architecture: {machine}") |
| 83 | |
| 84 | print(f"Downloading Node.js v{NODE_VERSION}...") |
| 85 | TOOLS_DIR.mkdir(exist_ok=True) |
| 86 | NODE_DIR.mkdir(exist_ok=True) |
| 87 | |
| 88 | if not download_path.exists(): |
| 89 | print(f"Downloading from: {url}") |
| 90 | with httpx.stream("GET", url, follow_redirects=True) as response: |
| 91 | response.raise_for_status() |
| 92 | with open(download_path, "wb") as f: |
| 93 | for chunk in response.iter_bytes(chunk_size=8192): |
| 94 | f.write(chunk) |
| 95 | print(f"SUCCESS: Downloaded {filename}") |
| 96 | |
| 97 | # Extract Node.js |
| 98 | if platform.system() == "Windows": |
| 99 | node_exe = NODE_DIR / "node.exe" |
| 100 | else: |
| 101 | node_exe = NODE_DIR / "bin" / "node" |
| 102 | |
| 103 | if not node_exe.exists(): |
| 104 | print("Extracting Node.js...") |
| 105 | |
| 106 | if is_zip: |
| 107 | with zipfile.ZipFile(download_path, "r") as zip_ref: |
| 108 | zip_ref.extractall(NODE_DIR) |
| 109 | # Move contents from nested folder to NODE_DIR |
| 110 | nested_dir = NODE_DIR / f"node-v{NODE_VERSION}-win-{arch}" |
| 111 | if nested_dir.exists(): |
| 112 | for item in nested_dir.iterdir(): |
| 113 | if item.is_dir(): |
| 114 | # For directories, move contents recursively |
| 115 | target_dir = NODE_DIR / item.name |
| 116 | if target_dir.exists(): |
| 117 | shutil.rmtree(target_dir) |
| 118 | shutil.move(str(item), str(target_dir)) |
| 119 | else: |
| 120 | # For files, move directly |
| 121 | target_file = NODE_DIR / item.name |
| 122 | if target_file.exists(): |
| 123 | target_file.unlink() |
| 124 | item.rename(target_file) |
| 125 | nested_dir.rmdir() |
| 126 | else: |
| 127 | with tarfile.open(download_path, "r:*") as tar_ref: |