# Installs the aphrody-labs/bun runtime from its GitHub releases. # # irm https://raw.githubusercontent.com/aphrody-labs/bun/main/scripts/aphrody/install.ps1 | iex # & ([scriptblock]::Create((irm .../install.ps1))) -Version 1.4.3 # newest aphrody.N build of base 1.4.3 # & ([scriptblock]::Create((irm .../install.ps1))) -Version aphrody-v1.4.3-aphrody.1 # # BUN_INSTALL (default ~\.bun) receives bin\bun.exe and bin\bunx.exe. -NoPathUpdate skips the user PATH. # APHRODY_BUN_REPO overrides the repository, GITHUB_TOKEN (or GH_TOKEN) authenticates the release lookup. param( [String]$Version = "latest", [Switch]$DebugInfo = $false, [Switch]$NoPathUpdate = $false ) $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" $Repo = if ($env:APHRODY_BUN_REPO) { $env:APHRODY_BUN_REPO } else { "aphrody-labs/bun" } $Token = if ($env:GITHUB_TOKEN) { $env:GITHUB_TOKEN } else { $env:GH_TOKEN } $Headers = @{ Accept = "application/vnd.github+json" } if ($Token) { $Headers.Authorization = "Bearer $Token" } $Arch = (Get-CimInstance Win32_OperatingSystem).OSArchitecture $BunArch = if ($Arch -match "ARM") { "aarch64" } else { "x64" } $Target = if ($DebugInfo) { "bun-windows-$BunArch-profile" } else { "bun-windows-$BunArch" } $Exe = if ($DebugInfo) { "bun-profile.exe" } else { "bun.exe" } $Tag = switch -Regex ($Version) { # The repository also publishes other releases (tools, n2b): the newest runtime release, not GitHub's "latest". "^latest$" { (Invoke-RestMethod -Headers $Headers "https://api.github.com/repos/$Repo/releases?per_page=100") | Where-Object { -not $_.draft -and -not $_.prerelease -and $_.tag_name -match '^(bun-v\d+\.\d+\.\d+|aphrody-v\d+\.\d+\.\d+-aphrody\.\d+)$' } | Select-Object -First 1 -ExpandProperty tag_name } "^aphrody-v" { $Version } "^bun-v\d+\.\d+\.\d+$" { $Version } "^(bun-)?v?(\d+\.\d+\.\d+)$" { $Base = $Matches[2] $Releases = Invoke-RestMethod -Headers $Headers "https://api.github.com/repos/$Repo/releases?per_page=100" $Stable = $Releases | Where-Object { -not $_.draft -and -not $_.prerelease -and $_.tag_name -eq "bun-v$Base" } if ($Stable) { "bun-v$Base" } else { $Releases | Where-Object { -not $_.draft -and -not $_.prerelease } | Select-Object -ExpandProperty tag_name | Where-Object { $_ -match "^aphrody-v$([regex]::Escape($Base))-aphrody\.(\d+)$" } | Sort-Object { [int]($_ -replace '^.*\.', '') } | Select-Object -Last 1 } } default { throw "Version must be latest, X.Y.Z or aphrody-vX.Y.Z-aphrody.N" } } if (-not $Tag) { throw "no $Repo release for $Version" } $BaseUrl = "https://github.com/$Repo/releases/download/$Tag" $Tmp = Join-Path ([System.IO.Path]::GetTempPath()) "aphrody-bun-$([guid]::NewGuid())" New-Item -ItemType Directory -Force $Tmp | Out-Null try { $Zip = Join-Path $Tmp "$Target.zip" Invoke-WebRequest "$BaseUrl/$Target.zip" -OutFile $Zip $SumsFile = Join-Path $Tmp "SHA256SUMS.txt" try { Invoke-WebRequest "$BaseUrl/SHA256SUMS.txt" -OutFile $SumsFile; $Sums = Get-Content $SumsFile } catch { $Sums = $null } if ($Sums) { $Want = ($Sums | Where-Object { $_ -match " $Target\.zip\s*$" } | Select-Object -First 1) -replace '\s.*$', '' $Got = (Get-FileHash -Algorithm SHA256 $Zip).Hash.ToLower() if (-not $Want -or $Want.ToLower() -ne $Got) { throw "checksum mismatch for $Target.zip" } } Expand-Archive -Force $Zip $Tmp $Root = if ($env:BUN_INSTALL) { $env:BUN_INSTALL } else { Join-Path $HOME ".bun" } $Bin = Join-Path $Root "bin" New-Item -ItemType Directory -Force $Bin | Out-Null $Bun = Join-Path $Bin "bun.exe" Move-Item -Force (Join-Path $Tmp "$Target\$Exe") $Bun $env:IS_BUN_AUTO_UPDATE = "1" & $Bun completions *> $null $env:IS_BUN_AUTO_UPDATE = $null # bun picks its mode from argv0; existing node/npm/npx aliases are relinked so they never keep an older build. foreach ($Alias in "bunx.exe", "node.exe", "npm.exe", "npx.exe") { $Link = Join-Path $Bin $Alias if ($Alias -ne "bunx.exe" -and -not (Test-Path $Link)) { continue } if (Test-Path $Link) { $Old = "$Link.old" Remove-Item -Force $Old -ErrorAction SilentlyContinue Move-Item -Force $Link $Old Remove-Item -Force $Old -ErrorAction SilentlyContinue } New-Item -ItemType HardLink -Path $Link -Target $Bun | Out-Null } Write-Output "Installed $Tag ($(& $Bun --revision)) to $Bun" if (-not $NoPathUpdate) { $UserPath = [Environment]::GetEnvironmentVariable("Path", "User") if (-not (($UserPath -split ";") -contains $Bin)) { [Environment]::SetEnvironmentVariable("Path", "$Bin;$UserPath", "User") Write-Output "Added $Bin to the user PATH (open a new terminal)" } } } finally { Remove-Item -Recurse -Force $Tmp -ErrorAction SilentlyContinue }