fix(bootstrap): harden Windows PowerShell & shell scripts against download hangs and version conflicts
This commit is contained in:
1 parent
739c1c2909
commit
611d1a0947
4 files changed
+299
-69
No files matched your search
+143
-33
@@ -26,6 +26,11 @@ param(
|
|||||||
$ErrorActionPreference = "Continue"
|
$ErrorActionPreference = "Continue"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
|
# Ensure modern TLS protocols are enabled for downloads (GitHub releases, nodejs.org, Google repositories)
|
||||||
|
try {
|
||||||
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
|
||||||
|
} catch {}
|
||||||
|
|
||||||
Write-Host "======================================================" -ForegroundColor Cyan
|
Write-Host "======================================================" -ForegroundColor Cyan
|
||||||
Write-Host " 🚀 Artemis - Windows Smart Installer " -ForegroundColor Cyan
|
Write-Host " 🚀 Artemis - Windows Smart Installer " -ForegroundColor Cyan
|
||||||
Write-Host "======================================================" -ForegroundColor Cyan
|
Write-Host "======================================================" -ForegroundColor Cyan
|
||||||
@@ -38,34 +43,50 @@ Set-Location $RootDir
|
|||||||
function Update-EnvironmentPath {
|
function Update-EnvironmentPath {
|
||||||
$standardDirs = @(
|
$standardDirs = @(
|
||||||
"$env:LOCALAPPDATA\Microsoft\WinGet\Links",
|
"$env:LOCALAPPDATA\Microsoft\WinGet\Links",
|
||||||
|
"$env:LOCALAPPDATA\Programs\node",
|
||||||
|
"$env:USERPROFILE\.local\share\node",
|
||||||
|
"$env:LOCALAPPDATA\Programs\scrcpy",
|
||||||
|
"$env:USERPROFILE\.local\share\scrcpy",
|
||||||
|
"$env:LOCALAPPDATA\Programs\platform-tools",
|
||||||
|
"$env:USERPROFILE\.local\share\platform-tools",
|
||||||
|
"$env:LOCALAPPDATA\Programs\uv",
|
||||||
|
"$env:LOCALAPPDATA\uv",
|
||||||
|
"$env:APPDATA\uv",
|
||||||
|
"$env:USERPROFILE\.cargo\bin",
|
||||||
|
"$env:USERPROFILE\.local\bin",
|
||||||
|
"$env:USERPROFILE\scoop\shims",
|
||||||
|
"C:\ProgramData\chocolatey\bin",
|
||||||
"$env:LOCALAPPDATA\Android\Sdk\platform-tools",
|
"$env:LOCALAPPDATA\Android\Sdk\platform-tools",
|
||||||
"$env:LOCALAPPDATA\Android\android-sdk\platform-tools",
|
"$env:LOCALAPPDATA\Android\android-sdk\platform-tools",
|
||||||
"$env:ProgramFiles\Android\platform-tools",
|
"$env:ProgramFiles\Android\platform-tools",
|
||||||
"${env:ProgramFiles(x86)}\Android\android-sdk\platform-tools",
|
"${env:ProgramFiles(x86)}\Android\android-sdk\platform-tools",
|
||||||
"$env:ProgramFiles\nodejs",
|
"$env:ProgramFiles\nodejs",
|
||||||
"${env:ProgramFiles(x86)}\nodejs",
|
"${env:ProgramFiles(x86)}\nodejs",
|
||||||
"$env:APPDATA\npm",
|
"$env:APPDATA\npm"
|
||||||
"$env:LOCALAPPDATA\Programs\platform-tools",
|
|
||||||
"$env:LOCALAPPDATA\Programs\scrcpy",
|
|
||||||
"$env:LOCALAPPDATA\Programs\node",
|
|
||||||
"$env:USERPROFILE\.local\share\platform-tools",
|
|
||||||
"$env:USERPROFILE\.local\share\scrcpy",
|
|
||||||
"$env:USERPROFILE\.local\share\node",
|
|
||||||
"$env:LOCALAPPDATA\nvm",
|
|
||||||
"$env:ProgramData\nvm",
|
|
||||||
"C:\ProgramData\chocolatey\bin",
|
|
||||||
"$env:USERPROFILE\scoop\shims",
|
|
||||||
"$env:USERPROFILE\.local\bin",
|
|
||||||
"$env:USERPROFILE\.cargo\bin"
|
|
||||||
)
|
)
|
||||||
|
if ($env:CARGO_HOME) { $standardDirs = @("$env:CARGO_HOME\bin") + $standardDirs }
|
||||||
if ($env:ANDROID_HOME) { $standardDirs += "$env:ANDROID_HOME\platform-tools" }
|
if ($env:ANDROID_HOME) { $standardDirs += "$env:ANDROID_HOME\platform-tools" }
|
||||||
if ($env:ANDROID_SDK_ROOT) { $standardDirs += "$env:ANDROID_SDK_ROOT\platform-tools" }
|
if ($env:ANDROID_SDK_ROOT) { $standardDirs += "$env:ANDROID_SDK_ROOT\platform-tools" }
|
||||||
if ($env:NVM_HOME) { $standardDirs += $env:NVM_HOME }
|
if ($env:NVM_SYMLINK) { $standardDirs = @($env:NVM_SYMLINK) + $standardDirs }
|
||||||
if ($env:NVM_SYMLINK) { $standardDirs += $env:NVM_SYMLINK }
|
if ($env:NVM_HOME) { $standardDirs = @($env:NVM_HOME) + $standardDirs }
|
||||||
|
|
||||||
$regPath = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
|
$regPath = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||||
$currentPaths = ($env:PATH -split ";") + ($regPath -split ";") + $standardDirs | Where-Object { [string]::IsNullOrWhiteSpace($_) -eq $false -and (Test-Path $_) } | Select-Object -Unique
|
$currentPaths = ($env:PATH -split ";") + ($regPath -split ";") + $standardDirs | Where-Object { [string]::IsNullOrWhiteSpace($_) -eq $false -and (Test-Path $_) } | Select-Object -Unique
|
||||||
$env:PATH = $currentPaths -join ";"
|
$env:PATH = $currentPaths -join ";"
|
||||||
|
|
||||||
|
# Ensure user-space portable tools take absolute priority over system-level outdated versions
|
||||||
|
$portableNode = "$env:LOCALAPPDATA\Programs\node"
|
||||||
|
if (Test-Path "$portableNode\node.exe") {
|
||||||
|
$env:PATH = "$portableNode;$env:PATH"
|
||||||
|
}
|
||||||
|
$portableScrcpy = "$env:LOCALAPPDATA\Programs\scrcpy"
|
||||||
|
if (Test-Path "$portableScrcpy\scrcpy.exe") {
|
||||||
|
$env:PATH = "$portableScrcpy;$env:PATH"
|
||||||
|
}
|
||||||
|
$portablePt = "$env:LOCALAPPDATA\Programs\platform-tools"
|
||||||
|
if (Test-Path "$portablePt\adb.exe") {
|
||||||
|
$env:PATH = "$portablePt;$env:PATH"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Start-LocalAdbServer {
|
function Start-LocalAdbServer {
|
||||||
@@ -85,6 +106,48 @@ function Test-CommandExists {
|
|||||||
return ($null -ne $res)
|
return ($null -ne $res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Invoke-DownloadFile {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][string]$Uri,
|
||||||
|
[Parameter(Mandatory=$true)][string]$OutFile,
|
||||||
|
[int]$TimeoutSec = 45
|
||||||
|
)
|
||||||
|
if (Test-Path $OutFile) {
|
||||||
|
Remove-Item -Path $OutFile -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. Try Windows built-in curl.exe first (available in Win 10 1803+ and Win 11)
|
||||||
|
if (Test-CommandExists "curl.exe") {
|
||||||
|
try {
|
||||||
|
& curl.exe -f -sSL --connect-timeout 5 --max-time $TimeoutSec "$Uri" -o "$OutFile" 2>$null
|
||||||
|
if ($LASTEXITCODE -eq 0 -and (Test-Path $OutFile) -and ((Get-Item $OutFile).Length -gt 0)) {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
if (Test-Path $OutFile) {
|
||||||
|
Remove-Item -Path $OutFile -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 2. Fallback to Invoke-WebRequest (suppressing progress bar to eliminate PowerShell buffer hangs)
|
||||||
|
try {
|
||||||
|
$prevProgress = $ProgressPreference
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
Invoke-WebRequest -Uri $Uri -OutFile $OutFile -TimeoutSec $TimeoutSec -UseBasicParsing -ErrorAction Stop
|
||||||
|
$ProgressPreference = $prevProgress
|
||||||
|
if ((Test-Path $OutFile) -and ((Get-Item $OutFile).Length -gt 0)) {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$ProgressPreference = $prevProgress
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $OutFile) {
|
||||||
|
Remove-Item -Path $OutFile -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
function Install-PortablePlatformTools {
|
function Install-PortablePlatformTools {
|
||||||
$ptDir = "$env:LOCALAPPDATA\Programs\platform-tools"
|
$ptDir = "$env:LOCALAPPDATA\Programs\platform-tools"
|
||||||
if (Test-Path "$ptDir\adb.exe") {
|
if (Test-Path "$ptDir\adb.exe") {
|
||||||
@@ -94,7 +157,7 @@ function Install-PortablePlatformTools {
|
|||||||
Write-Host " [INFO] Installing Android platform-tools (adb) in user space..." -ForegroundColor Cyan
|
Write-Host " [INFO] Installing Android platform-tools (adb) in user space..." -ForegroundColor Cyan
|
||||||
try {
|
try {
|
||||||
$zipPath = "$env:TEMP\platform-tools-windows.zip"
|
$zipPath = "$env:TEMP\platform-tools-windows.zip"
|
||||||
Invoke-WebRequest -Uri "https://dl.google.com/android/repository/platform-tools-latest-windows.zip" -OutFile $zipPath -UseBasicParsing
|
if (Invoke-DownloadFile -Uri "https://dl.google.com/android/repository/platform-tools-latest-windows.zip" -OutFile $zipPath -TimeoutSec 60) {
|
||||||
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
||||||
Expand-Archive -Path $zipPath -DestinationPath "$env:LOCALAPPDATA\Programs" -Force
|
Expand-Archive -Path $zipPath -DestinationPath "$env:LOCALAPPDATA\Programs" -Force
|
||||||
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
||||||
@@ -103,6 +166,7 @@ function Install-PortablePlatformTools {
|
|||||||
Write-Host " ✔ adb installed in user space." -ForegroundColor Green
|
Write-Host " ✔ adb installed in user space." -ForegroundColor Green
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " ⚠ Failed to install portable platform-tools: $_" -ForegroundColor DarkYellow
|
Write-Host " ⚠ Failed to install portable platform-tools: $_" -ForegroundColor DarkYellow
|
||||||
}
|
}
|
||||||
@@ -115,19 +179,31 @@ function Install-PortableScrcpy {
|
|||||||
$env:PATH = "$scrcpyDir;$env:PATH"
|
$env:PATH = "$scrcpyDir;$env:PATH"
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
# Check if nested from an earlier run and heal
|
||||||
|
$nested = Get-ChildItem -Path $scrcpyDir -Directory -Filter "scrcpy*" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($nested -and (Test-Path "$($nested.FullName)\scrcpy.exe")) {
|
||||||
|
Copy-Item -Path "$($nested.FullName)\*" -Destination $scrcpyDir -Recurse -Force
|
||||||
|
Remove-Item -Path $nested.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
if (Test-Path "$scrcpyDir\scrcpy.exe") {
|
||||||
|
$env:PATH = "$scrcpyDir;$env:PATH"
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan
|
Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan
|
||||||
try {
|
try {
|
||||||
$zipPath = "$env:TEMP\scrcpy-win64.zip"
|
$zipPath = "$env:TEMP\scrcpy-win64.zip"
|
||||||
Invoke-WebRequest -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -UseBasicParsing
|
if (Invoke-DownloadFile -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -TimeoutSec 60) {
|
||||||
$extractDir = "$env:TEMP\scrcpy_extract"
|
$extractDir = "$env:TEMP\scrcpy_extract"
|
||||||
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
||||||
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
||||||
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
||||||
if ($extractedFolder) {
|
if ($extractedFolder) {
|
||||||
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
if (-not (Test-Path $scrcpyDir)) {
|
||||||
if (Test-Path $scrcpyDir) { Remove-Item $scrcpyDir -Recurse -Force -ErrorAction SilentlyContinue }
|
New-Item -ItemType Directory -Path $scrcpyDir -Force | Out-Null
|
||||||
Move-Item -Path $extractedFolder.FullName -Destination $scrcpyDir -Force
|
}
|
||||||
|
Copy-Item -Path "$($extractedFolder.FullName)\*" -Destination $scrcpyDir -Recurse -Force
|
||||||
}
|
}
|
||||||
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
||||||
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
@@ -136,6 +212,7 @@ function Install-PortableScrcpy {
|
|||||||
Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green
|
Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow
|
Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow
|
||||||
}
|
}
|
||||||
@@ -143,7 +220,7 @@ function Install-PortableScrcpy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Test-NodeCompatible {
|
function Test-NodeCompatible {
|
||||||
if (-not (Test-CommandExists "node") -or -not (Test-CommandExists "npm")) { return $false }
|
if (-not (Test-CommandExists "node") -or (-not (Test-CommandExists "npm") -and -not (Test-CommandExists "npm.cmd"))) { return $false }
|
||||||
try {
|
try {
|
||||||
$verRaw = (& node -v 2>$null)
|
$verRaw = (& node -v 2>$null)
|
||||||
if (-not $verRaw) { return $false }
|
if (-not $verRaw) { return $false }
|
||||||
@@ -153,8 +230,8 @@ function Test-NodeCompatible {
|
|||||||
$major = [int]$parts[0]
|
$major = [int]$parts[0]
|
||||||
$minor = [int]$parts[1]
|
$minor = [int]$parts[1]
|
||||||
if ($major -ge 26) { return $true }
|
if ($major -ge 26) { return $true }
|
||||||
if ($major -ge 24 -and $minor -ge 15) { return $true }
|
if ($major -eq 24 -and $minor -ge 15) { return $true }
|
||||||
if ($major -ge 22 -and $minor -ge 22) { return $true }
|
if ($major -eq 22 -and $minor -ge 22) { return $true }
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return $false
|
return $false
|
||||||
@@ -170,6 +247,19 @@ function Install-PortableNode {
|
|||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# Check if nested from an earlier run and heal
|
||||||
|
$nested = Get-ChildItem -Path $nodeDir -Directory -Filter "node-*" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($nested -and (Test-Path "$($nested.FullName)\node.exe")) {
|
||||||
|
Copy-Item -Path "$($nested.FullName)\*" -Destination $nodeDir -Recurse -Force
|
||||||
|
Remove-Item -Path $nested.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
if (Test-Path "$nodeDir\node.exe") {
|
||||||
|
$env:PATH = "$nodeDir;$env:PATH"
|
||||||
|
if (Test-NodeCompatible) {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host " [INFO] Installing portable Node.js LTS (v22.23.2) in user space..." -ForegroundColor Cyan
|
Write-Host " [INFO] Installing portable Node.js LTS (v22.23.2) in user space..." -ForegroundColor Cyan
|
||||||
try {
|
try {
|
||||||
$nodeVer = "v22.23.2"
|
$nodeVer = "v22.23.2"
|
||||||
@@ -177,16 +267,17 @@ function Install-PortableNode {
|
|||||||
if ($env:PROCESSOR_ARCHITECTURE -match "ARM64") { "arm64" } else { "x64" }
|
if ($env:PROCESSOR_ARCHITECTURE -match "ARM64") { "arm64" } else { "x64" }
|
||||||
} else { "x64" }
|
} else { "x64" }
|
||||||
$zipPath = "$env:TEMP\node-$nodeVer-win-$arch.zip"
|
$zipPath = "$env:TEMP\node-$nodeVer-win-$arch.zip"
|
||||||
Invoke-WebRequest -Uri "https://nodejs.org/dist/$nodeVer/node-$nodeVer-win-$arch.zip" -OutFile $zipPath -UseBasicParsing
|
if (Invoke-DownloadFile -Uri "https://nodejs.org/dist/$nodeVer/node-$nodeVer-win-$arch.zip" -OutFile $zipPath -TimeoutSec 60) {
|
||||||
$extractDir = "$env:TEMP\node_extract"
|
$extractDir = "$env:TEMP\node_extract"
|
||||||
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
||||||
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
||||||
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
||||||
if ($extractedFolder) {
|
if ($extractedFolder) {
|
||||||
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
if (-not (Test-Path $nodeDir)) {
|
||||||
if (Test-Path $nodeDir) { Remove-Item $nodeDir -Recurse -Force -ErrorAction SilentlyContinue }
|
New-Item -ItemType Directory -Path $nodeDir -Force | Out-Null
|
||||||
Move-Item -Path $extractedFolder.FullName -Destination $nodeDir -Force
|
}
|
||||||
|
Copy-Item -Path "$($extractedFolder.FullName)\*" -Destination $nodeDir -Recurse -Force
|
||||||
}
|
}
|
||||||
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
||||||
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
@@ -195,6 +286,7 @@ function Install-PortableNode {
|
|||||||
Write-Host " ✔ Portable Node.js $nodeVer installed in user space." -ForegroundColor Green
|
Write-Host " ✔ Portable Node.js $nodeVer installed in user space." -ForegroundColor Green
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " ⚠ Failed to install portable Node.js: $_" -ForegroundColor DarkYellow
|
Write-Host " ⚠ Failed to install portable Node.js: $_" -ForegroundColor DarkYellow
|
||||||
}
|
}
|
||||||
@@ -357,13 +449,26 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1))
|
|||||||
Write-Host " 🎨 Compiling Angular Showcase UI..." -ForegroundColor Cyan
|
Write-Host " 🎨 Compiling Angular Showcase UI..." -ForegroundColor Cyan
|
||||||
Push-Location "$RootDir\apps\showcase_ui"
|
Push-Location "$RootDir\apps\showcase_ui"
|
||||||
try {
|
try {
|
||||||
npm install --silent
|
$npmExec = if (Test-CommandExists "npm.cmd") { "npm.cmd" } else { "npm" }
|
||||||
|
Write-Host " 📦 Installing frontend npm dependencies..." -ForegroundColor Cyan
|
||||||
|
& $npmExec install --no-audit --no-fund --loglevel=error
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host " ⚠ npm install returned exit code $LASTEXITCODE. Trying silent install..." -ForegroundColor DarkYellow
|
||||||
|
& $npmExec install --silent
|
||||||
|
}
|
||||||
$cliNodeVersion = "$RootDir\apps\showcase_ui\node_modules\@angular\cli\src\utilities\node-version.js"
|
$cliNodeVersion = "$RootDir\apps\showcase_ui\node_modules\@angular\cli\src\utilities\node-version.js"
|
||||||
if (Test-Path $cliNodeVersion) {
|
if (Test-Path $cliNodeVersion) {
|
||||||
(Get-Content $cliNodeVersion) -replace '22\.22\.3', '22.22.0' | Set-Content $cliNodeVersion
|
(Get-Content $cliNodeVersion) -replace '22\.22\.3', '22.22.0' | Set-Content $cliNodeVersion
|
||||||
}
|
}
|
||||||
npm run build
|
Write-Host " ⚙ Building Angular frontend application..." -ForegroundColor Cyan
|
||||||
|
& $npmExec run build
|
||||||
|
if (Test-Path $ShowcaseIndex) {
|
||||||
Write-Host " ✔ Showcase UI compiled successfully." -ForegroundColor Green
|
Write-Host " ✔ Showcase UI compiled successfully." -ForegroundColor Green
|
||||||
|
} elseif (Test-Path $ShowcaseIndexAlt1) {
|
||||||
|
Write-Host " ✔ Showcase UI compiled successfully." -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host " ⚠ Showcase UI build finished but index.html was not found in expected dist directory." -ForegroundColor DarkYellow
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " ⚠ Failed to build Showcase UI: $_" -ForegroundColor DarkYellow
|
Write-Host " ⚠ Failed to build Showcase UI: $_" -ForegroundColor DarkYellow
|
||||||
} finally {
|
} finally {
|
||||||
@@ -380,8 +485,13 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1))
|
|||||||
Write-Host "`n6. Toolchain Readiness Summary:" -ForegroundColor Yellow
|
Write-Host "`n6. Toolchain Readiness Summary:" -ForegroundColor Yellow
|
||||||
$tools = @("adb", "ffmpeg", "scrcpy", "uv", "npm")
|
$tools = @("adb", "ffmpeg", "scrcpy", "uv", "npm")
|
||||||
foreach ($t in $tools) {
|
foreach ($t in $tools) {
|
||||||
if (Test-CommandExists $t) {
|
$hasCmd = Test-CommandExists $t
|
||||||
$p = (Get-Command $t).Source
|
if (-not $hasCmd -and $t -eq "npm") {
|
||||||
|
$hasCmd = Test-CommandExists "npm.cmd"
|
||||||
|
}
|
||||||
|
if ($hasCmd) {
|
||||||
|
$targetName = if ($t -eq "npm" -and -not (Test-CommandExists "npm") -and (Test-CommandExists "npm.cmd")) { "npm.cmd" } else { $t }
|
||||||
|
$p = (Get-Command $targetName).Source
|
||||||
if ($t -eq "npm" -and (Test-CommandExists "node")) {
|
if ($t -eq "npm" -and (Test-CommandExists "node")) {
|
||||||
$nVer = (& node -v 2>$null)
|
$nVer = (& node -v 2>$null)
|
||||||
Write-Host " ✔ $t ($nVer) -> $p" -ForegroundColor Green
|
Write-Host " ✔ $t ($nVer) -> $p" -ForegroundColor Green
|
||||||
@@ -401,10 +511,10 @@ Write-Host "======================================================" -ForegroundC
|
|||||||
if ($Launch -or $Open) {
|
if ($Launch -or $Open) {
|
||||||
Start-LocalAdbServer
|
Start-LocalAdbServer
|
||||||
Write-Host "🚀 Launching Showcase UI..." -ForegroundColor Green
|
Write-Host "🚀 Launching Showcase UI..." -ForegroundColor Green
|
||||||
uv run artemis ui --open
|
uv run python -m artemis ui --open
|
||||||
} else {
|
} else {
|
||||||
Write-Host "To start the Showcase UI and interactive onboarding:" -ForegroundColor White
|
Write-Host "To start the Showcase UI and interactive onboarding:" -ForegroundColor White
|
||||||
Write-Host " 👉 .\start.bat (or: uv run artemis ui)" -ForegroundColor Cyan
|
Write-Host " 👉 .\start.bat (or: uv run python -m artemis ui)" -ForegroundColor Cyan
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ install_system_packages() {
|
|||||||
if [ ! -x "${PT_DIR}/adb" ]; then
|
if [ ! -x "${PT_DIR}/adb" ]; then
|
||||||
echo -e " ${CYAN}📦 Installing Android platform-tools (adb) in user space...${NC}"
|
echo -e " ${CYAN}📦 Installing Android platform-tools (adb) in user space...${NC}"
|
||||||
local TEMP_ZIP="/tmp/platform-tools-$$.zip"
|
local TEMP_ZIP="/tmp/platform-tools-$$.zip"
|
||||||
if curl -fsSL "https://dl.google.com/android/repository/platform-tools-latest-linux.zip" -o "${TEMP_ZIP}" 2>/dev/null; then
|
if curl -fsSL --connect-timeout 5 --max-time 30 "https://dl.google.com/android/repository/platform-tools-latest-linux.zip" -o "${TEMP_ZIP}" 2>/dev/null; then
|
||||||
mkdir -p "${HOME}/.local/share" "${HOME}/.local/bin"
|
mkdir -p "${HOME}/.local/share" "${HOME}/.local/bin"
|
||||||
if has_cmd unzip; then
|
if has_cmd unzip; then
|
||||||
unzip -q -o "${TEMP_ZIP}" -d "${HOME}/.local/share" 2>/dev/null || true
|
unzip -q -o "${TEMP_ZIP}" -d "${HOME}/.local/share" 2>/dev/null || true
|
||||||
@@ -425,10 +425,10 @@ setup_showcase_ui() {
|
|||||||
if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
|
if [ "$(id -u)" -ne 0 ]; then SUDO_PREFIX="sudo"; fi
|
||||||
if has_cmd apt-get; then
|
if has_cmd apt-get; then
|
||||||
echo -e " ${CYAN}📦 Configuring NodeSource Node.js 22 LTS repository...${NC}"
|
echo -e " ${CYAN}📦 Configuring NodeSource Node.js 22 LTS repository...${NC}"
|
||||||
curl -fsSL https://deb.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
|
curl -fsSL --connect-timeout 5 --max-time 30 https://deb.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
|
||||||
${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=5 install -y -qq nodejs 2>/dev/null || true
|
${SUDO_PREFIX} apt-get -o DPkg::Lock::Timeout=5 install -y -qq nodejs 2>/dev/null || true
|
||||||
elif has_cmd dnf; then
|
elif has_cmd dnf; then
|
||||||
curl -fsSL https://rpm.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
|
curl -fsSL --connect-timeout 5 --max-time 30 https://rpm.nodesource.com/setup_22.x | ${SUDO_PREFIX} bash - >/dev/null 2>&1 || true
|
||||||
${SUDO_PREFIX} dnf install -y nodejs || true
|
${SUDO_PREFIX} dnf install -y nodejs || true
|
||||||
elif has_cmd pacman; then
|
elif has_cmd pacman; then
|
||||||
${SUDO_PREFIX} pacman -S --noconfirm nodejs npm || true
|
${SUDO_PREFIX} pacman -S --noconfirm nodejs npm || true
|
||||||
@@ -451,7 +451,7 @@ setup_showcase_ui() {
|
|||||||
echo -e " ${CYAN}📦 Installing portable Node.js ${NODE_VER} in user space (~/.local)...${NC}"
|
echo -e " ${CYAN}📦 Installing portable Node.js ${NODE_VER} in user space (~/.local)...${NC}"
|
||||||
rm -rf "${NODE_DIR}"
|
rm -rf "${NODE_DIR}"
|
||||||
mkdir -p "${NODE_DIR}" "${HOME}/.local/bin"
|
mkdir -p "${NODE_DIR}" "${HOME}/.local/bin"
|
||||||
if curl -fsSL "https://nodejs.org/dist/${NODE_VER}/node-${NODE_VER}-${OS_SYS}-${NODE_ARCH}.tar.gz" | tar -xz -C "${NODE_DIR}" --strip-components=1 2>/dev/null; then
|
if curl -fsSL --connect-timeout 5 --max-time 60 "https://nodejs.org/dist/${NODE_VER}/node-${NODE_VER}-${OS_SYS}-${NODE_ARCH}.tar.gz" | tar -xz -C "${NODE_DIR}" --strip-components=1 2>/dev/null; then
|
||||||
ln -sf "${NODE_DIR}/bin/node" "${HOME}/.local/bin/node"
|
ln -sf "${NODE_DIR}/bin/node" "${HOME}/.local/bin/node"
|
||||||
ln -sf "${NODE_DIR}/bin/npm" "${HOME}/.local/bin/npm"
|
ln -sf "${NODE_DIR}/bin/npm" "${HOME}/.local/bin/npm"
|
||||||
ln -sf "${NODE_DIR}/bin/npx" "${HOME}/.local/bin/npx"
|
ln -sf "${NODE_DIR}/bin/npx" "${HOME}/.local/bin/npx"
|
||||||
|
|||||||
+150
-30
@@ -21,6 +21,11 @@ param(
|
|||||||
$ErrorActionPreference = "Continue"
|
$ErrorActionPreference = "Continue"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
|
# Ensure modern TLS protocols are enabled for downloads (GitHub releases, nodejs.org, Google repositories)
|
||||||
|
try {
|
||||||
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
|
||||||
|
} catch {}
|
||||||
|
|
||||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
$RootDir = Split-Path -Parent $ScriptDir
|
$RootDir = Split-Path -Parent $ScriptDir
|
||||||
Set-Location $RootDir
|
Set-Location $RootDir
|
||||||
@@ -33,34 +38,50 @@ Write-Host ""
|
|||||||
function Update-EnvironmentPath {
|
function Update-EnvironmentPath {
|
||||||
$standardDirs = @(
|
$standardDirs = @(
|
||||||
"$env:LOCALAPPDATA\Microsoft\WinGet\Links",
|
"$env:LOCALAPPDATA\Microsoft\WinGet\Links",
|
||||||
|
"$env:LOCALAPPDATA\Programs\node",
|
||||||
|
"$env:USERPROFILE\.local\share\node",
|
||||||
|
"$env:LOCALAPPDATA\Programs\scrcpy",
|
||||||
|
"$env:USERPROFILE\.local\share\scrcpy",
|
||||||
|
"$env:LOCALAPPDATA\Programs\platform-tools",
|
||||||
|
"$env:USERPROFILE\.local\share\platform-tools",
|
||||||
|
"$env:LOCALAPPDATA\Programs\uv",
|
||||||
|
"$env:LOCALAPPDATA\uv",
|
||||||
|
"$env:APPDATA\uv",
|
||||||
|
"$env:USERPROFILE\.cargo\bin",
|
||||||
|
"$env:USERPROFILE\.local\bin",
|
||||||
|
"$env:USERPROFILE\scoop\shims",
|
||||||
|
"C:\ProgramData\chocolatey\bin",
|
||||||
"$env:LOCALAPPDATA\Android\Sdk\platform-tools",
|
"$env:LOCALAPPDATA\Android\Sdk\platform-tools",
|
||||||
"$env:LOCALAPPDATA\Android\android-sdk\platform-tools",
|
"$env:LOCALAPPDATA\Android\android-sdk\platform-tools",
|
||||||
"$env:ProgramFiles\Android\platform-tools",
|
"$env:ProgramFiles\Android\platform-tools",
|
||||||
"${env:ProgramFiles(x86)}\Android\android-sdk\platform-tools",
|
"${env:ProgramFiles(x86)}\Android\android-sdk\platform-tools",
|
||||||
"$env:ProgramFiles\nodejs",
|
"$env:ProgramFiles\nodejs",
|
||||||
"${env:ProgramFiles(x86)}\nodejs",
|
"${env:ProgramFiles(x86)}\nodejs",
|
||||||
"$env:APPDATA\npm",
|
"$env:APPDATA\npm"
|
||||||
"$env:LOCALAPPDATA\Programs\platform-tools",
|
|
||||||
"$env:LOCALAPPDATA\Programs\scrcpy",
|
|
||||||
"$env:LOCALAPPDATA\Programs\node",
|
|
||||||
"$env:USERPROFILE\.local\share\platform-tools",
|
|
||||||
"$env:USERPROFILE\.local\share\scrcpy",
|
|
||||||
"$env:USERPROFILE\.local\share\node",
|
|
||||||
"$env:LOCALAPPDATA\nvm",
|
|
||||||
"$env:ProgramData\nvm",
|
|
||||||
"C:\ProgramData\chocolatey\bin",
|
|
||||||
"$env:USERPROFILE\scoop\shims",
|
|
||||||
"$env:USERPROFILE\.local\bin",
|
|
||||||
"$env:USERPROFILE\.cargo\bin"
|
|
||||||
)
|
)
|
||||||
|
if ($env:CARGO_HOME) { $standardDirs = @("$env:CARGO_HOME\bin") + $standardDirs }
|
||||||
if ($env:ANDROID_HOME) { $standardDirs += "$env:ANDROID_HOME\platform-tools" }
|
if ($env:ANDROID_HOME) { $standardDirs += "$env:ANDROID_HOME\platform-tools" }
|
||||||
if ($env:ANDROID_SDK_ROOT) { $standardDirs += "$env:ANDROID_SDK_ROOT\platform-tools" }
|
if ($env:ANDROID_SDK_ROOT) { $standardDirs += "$env:ANDROID_SDK_ROOT\platform-tools" }
|
||||||
if ($env:NVM_HOME) { $standardDirs += $env:NVM_HOME }
|
if ($env:NVM_SYMLINK) { $standardDirs = @($env:NVM_SYMLINK) + $standardDirs }
|
||||||
if ($env:NVM_SYMLINK) { $standardDirs += $env:NVM_SYMLINK }
|
if ($env:NVM_HOME) { $standardDirs = @($env:NVM_HOME) + $standardDirs }
|
||||||
|
|
||||||
$regPath = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
|
$regPath = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||||
$currentPaths = ($env:PATH -split ";") + ($regPath -split ";") + $standardDirs | Where-Object { [string]::IsNullOrWhiteSpace($_) -eq $false -and (Test-Path $_) } | Select-Object -Unique
|
$currentPaths = ($env:PATH -split ";") + ($regPath -split ";") + $standardDirs | Where-Object { [string]::IsNullOrWhiteSpace($_) -eq $false -and (Test-Path $_) } | Select-Object -Unique
|
||||||
$env:PATH = $currentPaths -join ";"
|
$env:PATH = $currentPaths -join ";"
|
||||||
|
|
||||||
|
# Ensure user-space portable tools take absolute priority over system-level outdated versions
|
||||||
|
$portableNode = "$env:LOCALAPPDATA\Programs\node"
|
||||||
|
if (Test-Path "$portableNode\node.exe") {
|
||||||
|
$env:PATH = "$portableNode;$env:PATH"
|
||||||
|
}
|
||||||
|
$portableScrcpy = "$env:LOCALAPPDATA\Programs\scrcpy"
|
||||||
|
if (Test-Path "$portableScrcpy\scrcpy.exe") {
|
||||||
|
$env:PATH = "$portableScrcpy;$env:PATH"
|
||||||
|
}
|
||||||
|
$portablePt = "$env:LOCALAPPDATA\Programs\platform-tools"
|
||||||
|
if (Test-Path "$portablePt\adb.exe") {
|
||||||
|
$env:PATH = "$portablePt;$env:PATH"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Start-LocalAdbServer {
|
function Start-LocalAdbServer {
|
||||||
@@ -80,6 +101,48 @@ function Test-CommandExists {
|
|||||||
return ($null -ne $res)
|
return ($null -ne $res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Invoke-DownloadFile {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][string]$Uri,
|
||||||
|
[Parameter(Mandatory=$true)][string]$OutFile,
|
||||||
|
[int]$TimeoutSec = 45
|
||||||
|
)
|
||||||
|
if (Test-Path $OutFile) {
|
||||||
|
Remove-Item -Path $OutFile -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. Try Windows built-in curl.exe first (available in Win 10 1803+ and Win 11)
|
||||||
|
if (Test-CommandExists "curl.exe") {
|
||||||
|
try {
|
||||||
|
& curl.exe -f -sSL --connect-timeout 5 --max-time $TimeoutSec "$Uri" -o "$OutFile" 2>$null
|
||||||
|
if ($LASTEXITCODE -eq 0 -and (Test-Path $OutFile) -and ((Get-Item $OutFile).Length -gt 0)) {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
if (Test-Path $OutFile) {
|
||||||
|
Remove-Item -Path $OutFile -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 2. Fallback to Invoke-WebRequest (suppressing progress bar to eliminate PowerShell buffer hangs)
|
||||||
|
try {
|
||||||
|
$prevProgress = $ProgressPreference
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
Invoke-WebRequest -Uri $Uri -OutFile $OutFile -TimeoutSec $TimeoutSec -UseBasicParsing -ErrorAction Stop
|
||||||
|
$ProgressPreference = $prevProgress
|
||||||
|
if ((Test-Path $OutFile) -and ((Get-Item $OutFile).Length -gt 0)) {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$ProgressPreference = $prevProgress
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $OutFile) {
|
||||||
|
Remove-Item -Path $OutFile -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
function Install-PortablePlatformTools {
|
function Install-PortablePlatformTools {
|
||||||
$ptDir = "$env:LOCALAPPDATA\Programs\platform-tools"
|
$ptDir = "$env:LOCALAPPDATA\Programs\platform-tools"
|
||||||
if (Test-Path "$ptDir\adb.exe") {
|
if (Test-Path "$ptDir\adb.exe") {
|
||||||
@@ -89,7 +152,7 @@ function Install-PortablePlatformTools {
|
|||||||
Write-Host " [INFO] Installing Android platform-tools (adb) in user space..." -ForegroundColor Cyan
|
Write-Host " [INFO] Installing Android platform-tools (adb) in user space..." -ForegroundColor Cyan
|
||||||
try {
|
try {
|
||||||
$zipPath = "$env:TEMP\platform-tools-windows.zip"
|
$zipPath = "$env:TEMP\platform-tools-windows.zip"
|
||||||
Invoke-WebRequest -Uri "https://dl.google.com/android/repository/platform-tools-latest-windows.zip" -OutFile $zipPath -UseBasicParsing
|
if (Invoke-DownloadFile -Uri "https://dl.google.com/android/repository/platform-tools-latest-windows.zip" -OutFile $zipPath -TimeoutSec 60) {
|
||||||
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
||||||
Expand-Archive -Path $zipPath -DestinationPath "$env:LOCALAPPDATA\Programs" -Force
|
Expand-Archive -Path $zipPath -DestinationPath "$env:LOCALAPPDATA\Programs" -Force
|
||||||
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
||||||
@@ -98,6 +161,7 @@ function Install-PortablePlatformTools {
|
|||||||
Write-Host " [OK] adb installed in user space." -ForegroundColor Green
|
Write-Host " [OK] adb installed in user space." -ForegroundColor Green
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " [WARN] Failed to install portable platform-tools: $_" -ForegroundColor DarkYellow
|
Write-Host " [WARN] Failed to install portable platform-tools: $_" -ForegroundColor DarkYellow
|
||||||
}
|
}
|
||||||
@@ -110,19 +174,31 @@ function Install-PortableScrcpy {
|
|||||||
$env:PATH = "$scrcpyDir;$env:PATH"
|
$env:PATH = "$scrcpyDir;$env:PATH"
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
# Check if nested from an earlier run and heal
|
||||||
|
$nested = Get-ChildItem -Path $scrcpyDir -Directory -Filter "scrcpy*" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($nested -and (Test-Path "$($nested.FullName)\scrcpy.exe")) {
|
||||||
|
Copy-Item -Path "$($nested.FullName)\*" -Destination $scrcpyDir -Recurse -Force
|
||||||
|
Remove-Item -Path $nested.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
if (Test-Path "$scrcpyDir\scrcpy.exe") {
|
||||||
|
$env:PATH = "$scrcpyDir;$env:PATH"
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan
|
Write-Host " [INFO] Installing portable scrcpy in user space..." -ForegroundColor Cyan
|
||||||
try {
|
try {
|
||||||
$zipPath = "$env:TEMP\scrcpy-win64.zip"
|
$zipPath = "$env:TEMP\scrcpy-win64.zip"
|
||||||
Invoke-WebRequest -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -UseBasicParsing
|
if (Invoke-DownloadFile -Uri "https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-win64-v4.1.zip" -OutFile $zipPath -TimeoutSec 60) {
|
||||||
$extractDir = "$env:TEMP\scrcpy_extract"
|
$extractDir = "$env:TEMP\scrcpy_extract"
|
||||||
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
||||||
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
||||||
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
||||||
if ($extractedFolder) {
|
if ($extractedFolder) {
|
||||||
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
if (-not (Test-Path $scrcpyDir)) {
|
||||||
if (Test-Path $scrcpyDir) { Remove-Item $scrcpyDir -Recurse -Force -ErrorAction SilentlyContinue }
|
New-Item -ItemType Directory -Path $scrcpyDir -Force | Out-Null
|
||||||
Move-Item -Path $extractedFolder.FullName -Destination $scrcpyDir -Force
|
}
|
||||||
|
Copy-Item -Path "$($extractedFolder.FullName)\*" -Destination $scrcpyDir -Recurse -Force
|
||||||
}
|
}
|
||||||
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
||||||
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
@@ -131,6 +207,7 @@ function Install-PortableScrcpy {
|
|||||||
Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green
|
Write-Host " ✔ Portable scrcpy installed in user space." -ForegroundColor Green
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow
|
Write-Host " ⚠ Failed to install portable scrcpy: $_" -ForegroundColor DarkYellow
|
||||||
}
|
}
|
||||||
@@ -138,7 +215,7 @@ function Install-PortableScrcpy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Test-NodeCompatible {
|
function Test-NodeCompatible {
|
||||||
if (-not (Test-CommandExists "node") -or -not (Test-CommandExists "npm")) { return $false }
|
if (-not (Test-CommandExists "node") -or (-not (Test-CommandExists "npm") -and -not (Test-CommandExists "npm.cmd"))) { return $false }
|
||||||
try {
|
try {
|
||||||
$verRaw = (& node -v 2>$null)
|
$verRaw = (& node -v 2>$null)
|
||||||
if (-not $verRaw) { return $false }
|
if (-not $verRaw) { return $false }
|
||||||
@@ -148,8 +225,8 @@ function Test-NodeCompatible {
|
|||||||
$major = [int]$parts[0]
|
$major = [int]$parts[0]
|
||||||
$minor = [int]$parts[1]
|
$minor = [int]$parts[1]
|
||||||
if ($major -ge 26) { return $true }
|
if ($major -ge 26) { return $true }
|
||||||
if ($major -ge 24 -and $minor -ge 15) { return $true }
|
if ($major -eq 24 -and $minor -ge 15) { return $true }
|
||||||
if ($major -ge 22 -and $minor -ge 22) { return $true }
|
if ($major -eq 22 -and $minor -ge 22) { return $true }
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return $false
|
return $false
|
||||||
@@ -165,6 +242,19 @@ function Install-PortableNode {
|
|||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# Check if nested from an earlier run and heal
|
||||||
|
$nested = Get-ChildItem -Path $nodeDir -Directory -Filter "node-*" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($nested -and (Test-Path "$($nested.FullName)\node.exe")) {
|
||||||
|
Copy-Item -Path "$($nested.FullName)\*" -Destination $nodeDir -Recurse -Force
|
||||||
|
Remove-Item -Path $nested.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
if (Test-Path "$nodeDir\node.exe") {
|
||||||
|
$env:PATH = "$nodeDir;$env:PATH"
|
||||||
|
if (Test-NodeCompatible) {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host " [INFO] Installing portable Node.js LTS (v22.23.2) in user space..." -ForegroundColor Cyan
|
Write-Host " [INFO] Installing portable Node.js LTS (v22.23.2) in user space..." -ForegroundColor Cyan
|
||||||
try {
|
try {
|
||||||
$nodeVer = "v22.23.2"
|
$nodeVer = "v22.23.2"
|
||||||
@@ -172,16 +262,17 @@ function Install-PortableNode {
|
|||||||
if ($env:PROCESSOR_ARCHITECTURE -match "ARM64") { "arm64" } else { "x64" }
|
if ($env:PROCESSOR_ARCHITECTURE -match "ARM64") { "arm64" } else { "x64" }
|
||||||
} else { "x64" }
|
} else { "x64" }
|
||||||
$zipPath = "$env:TEMP\node-$nodeVer-win-$arch.zip"
|
$zipPath = "$env:TEMP\node-$nodeVer-win-$arch.zip"
|
||||||
Invoke-WebRequest -Uri "https://nodejs.org/dist/$nodeVer/node-$nodeVer-win-$arch.zip" -OutFile $zipPath -UseBasicParsing
|
if (Invoke-DownloadFile -Uri "https://nodejs.org/dist/$nodeVer/node-$nodeVer-win-$arch.zip" -OutFile $zipPath -TimeoutSec 60) {
|
||||||
$extractDir = "$env:TEMP\node_extract"
|
$extractDir = "$env:TEMP\node_extract"
|
||||||
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
|
||||||
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force
|
||||||
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
$extractedFolder = Get-ChildItem -Path $extractDir -Directory | Select-Object -First 1
|
||||||
if ($extractedFolder) {
|
if ($extractedFolder) {
|
||||||
New-Item -ItemType Directory -Path "$env:LOCALAPPDATA\Programs" -Force | Out-Null
|
if (-not (Test-Path $nodeDir)) {
|
||||||
if (Test-Path $nodeDir) { Remove-Item $nodeDir -Recurse -Force -ErrorAction SilentlyContinue }
|
New-Item -ItemType Directory -Path $nodeDir -Force | Out-Null
|
||||||
Move-Item -Path $extractedFolder.FullName -Destination $nodeDir -Force
|
}
|
||||||
|
Copy-Item -Path "$($extractedFolder.FullName)\*" -Destination $nodeDir -Recurse -Force
|
||||||
}
|
}
|
||||||
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
|
||||||
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
@@ -190,6 +281,7 @@ function Install-PortableNode {
|
|||||||
Write-Host " [OK] Portable Node.js $nodeVer installed in user space." -ForegroundColor Green
|
Write-Host " [OK] Portable Node.js $nodeVer installed in user space." -ForegroundColor Green
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " [WARN] Failed to install portable Node.js: $_" -ForegroundColor DarkYellow
|
Write-Host " [WARN] Failed to install portable Node.js: $_" -ForegroundColor DarkYellow
|
||||||
}
|
}
|
||||||
@@ -202,10 +294,21 @@ Update-EnvironmentPath
|
|||||||
# 2. Check or install uv
|
# 2. Check or install uv
|
||||||
if (-not (Test-CommandExists "uv")) {
|
if (-not (Test-CommandExists "uv")) {
|
||||||
Write-Host " [INFO] uv not found. Installing Astral uv..." -ForegroundColor Yellow
|
Write-Host " [INFO] uv not found. Installing Astral uv..." -ForegroundColor Yellow
|
||||||
|
try {
|
||||||
|
Invoke-Expression (Invoke-RestMethod -Uri "https://astral.sh/uv/install.ps1")
|
||||||
|
} catch {
|
||||||
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
||||||
|
}
|
||||||
Update-EnvironmentPath
|
Update-EnvironmentPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not (Test-CommandExists "uv")) {
|
||||||
|
Write-Host " [ERROR] Astral 'uv' package manager could not be installed or found in PATH." -ForegroundColor Red
|
||||||
|
Write-Host " Please install uv manually from https://astral.sh/ or run:" -ForegroundColor Yellow
|
||||||
|
Write-Host " powershell -c ""irm https://astral.sh/uv/install.ps1 | iex""" -ForegroundColor Cyan
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# 3. Check and try installing missing system toolchains (ADB, FFmpeg, scrcpy)
|
# 3. Check and try installing missing system toolchains (ADB, FFmpeg, scrcpy)
|
||||||
$missingCore = @()
|
$missingCore = @()
|
||||||
if (-not (Test-CommandExists "adb")) { $missingCore += "adb" }
|
if (-not (Test-CommandExists "adb")) { $missingCore += "adb" }
|
||||||
@@ -321,13 +424,26 @@ if ((-not (Test-Path $ShowcaseIndex)) -and (-not (Test-Path $ShowcaseIndexAlt1))
|
|||||||
Write-Host " [INFO] Showcase UI build not found. Compiling Angular Showcase UI..." -ForegroundColor Yellow
|
Write-Host " [INFO] Showcase UI build not found. Compiling Angular Showcase UI..." -ForegroundColor Yellow
|
||||||
Push-Location "$RootDir\apps\showcase_ui"
|
Push-Location "$RootDir\apps\showcase_ui"
|
||||||
try {
|
try {
|
||||||
npm install --silent
|
$npmExec = if (Test-CommandExists "npm.cmd") { "npm.cmd" } else { "npm" }
|
||||||
|
Write-Host " [INFO] Installing frontend npm dependencies..." -ForegroundColor Cyan
|
||||||
|
& $npmExec install --no-audit --no-fund --loglevel=error
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host " [WARN] npm install returned exit code $LASTEXITCODE. Trying silent install..." -ForegroundColor DarkYellow
|
||||||
|
& $npmExec install --silent
|
||||||
|
}
|
||||||
$cliNodeVersion = "$RootDir\apps\showcase_ui\node_modules\@angular\cli\src\utilities\node-version.js"
|
$cliNodeVersion = "$RootDir\apps\showcase_ui\node_modules\@angular\cli\src\utilities\node-version.js"
|
||||||
if (Test-Path $cliNodeVersion) {
|
if (Test-Path $cliNodeVersion) {
|
||||||
(Get-Content $cliNodeVersion) -replace '22\.22\.3', '22.22.0' | Set-Content $cliNodeVersion
|
(Get-Content $cliNodeVersion) -replace '22\.22\.3', '22.22.0' | Set-Content $cliNodeVersion
|
||||||
}
|
}
|
||||||
npm run build
|
Write-Host " [INFO] Building Angular frontend application..." -ForegroundColor Cyan
|
||||||
|
& $npmExec run build
|
||||||
|
if (Test-Path $ShowcaseIndex) {
|
||||||
Write-Host " [OK] Showcase UI compiled successfully." -ForegroundColor Green
|
Write-Host " [OK] Showcase UI compiled successfully." -ForegroundColor Green
|
||||||
|
} elseif (Test-Path $ShowcaseIndexAlt1) {
|
||||||
|
Write-Host " [OK] Showcase UI compiled successfully." -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host " [WARN] Showcase UI build finished but index.html was not found in expected dist directory." -ForegroundColor DarkYellow
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host " [WARN] Failed to build Showcase UI: $_" -ForegroundColor DarkYellow
|
Write-Host " [WARN] Failed to build Showcase UI: $_" -ForegroundColor DarkYellow
|
||||||
} finally {
|
} finally {
|
||||||
@@ -354,7 +470,7 @@ if ([Console]::IsInputRedirected -eq $false) {
|
|||||||
|
|
||||||
if ($installMcp -match "^[Yy]") {
|
if ($installMcp -match "^[Yy]") {
|
||||||
Write-Host " Installing MCP server configuration & testing rules..." -ForegroundColor Cyan
|
Write-Host " Installing MCP server configuration & testing rules..." -ForegroundColor Cyan
|
||||||
uv run artemis mcp --install all
|
uv run python -m artemis mcp --install all
|
||||||
if ($LASTEXITCODE -eq 0) {
|
if ($LASTEXITCODE -eq 0) {
|
||||||
Write-Host " [OK] MCP configuration and rules installed successfully." -ForegroundColor Green
|
Write-Host " [OK] MCP configuration and rules installed successfully." -ForegroundColor Green
|
||||||
Write-Host " [TIP] You can update or re-install anytime with: uv run artemis mcp --install all" -ForegroundColor Cyan
|
Write-Host " [TIP] You can update or re-install anytime with: uv run artemis mcp --install all" -ForegroundColor Cyan
|
||||||
@@ -378,3 +494,7 @@ if ($NoOpen) {
|
|||||||
} else {
|
} else {
|
||||||
uv run python -m artemis ui --port $Port --open
|
uv run python -m artemis ui --port $Port --open
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
@@ -221,7 +221,7 @@ if [ ${#MISSING_CORE[@]} -gt 0 ]; then
|
|||||||
if [ ! -x "${PT_DIR}/adb" ]; then
|
if [ ! -x "${PT_DIR}/adb" ]; then
|
||||||
echo -e " ${CYAN}📦 Installing Android platform-tools (adb) in user space...${NC}"
|
echo -e " ${CYAN}📦 Installing Android platform-tools (adb) in user space...${NC}"
|
||||||
TEMP_ZIP="/tmp/platform-tools-$$.zip"
|
TEMP_ZIP="/tmp/platform-tools-$$.zip"
|
||||||
if curl -fsSL "https://dl.google.com/android/repository/platform-tools-latest-linux.zip" -o "${TEMP_ZIP}" 2>/dev/null; then
|
if curl -fsSL --connect-timeout 5 --max-time 30 "https://dl.google.com/android/repository/platform-tools-latest-linux.zip" -o "${TEMP_ZIP}" 2>/dev/null; then
|
||||||
mkdir -p "${HOME}/.local/share" "${HOME}/.local/bin"
|
mkdir -p "${HOME}/.local/share" "${HOME}/.local/bin"
|
||||||
if command -v unzip >/dev/null 2>&1; then
|
if command -v unzip >/dev/null 2>&1; then
|
||||||
unzip -q -o "${TEMP_ZIP}" -d "${HOME}/.local/share" 2>/dev/null || true
|
unzip -q -o "${TEMP_ZIP}" -d "${HOME}/.local/share" 2>/dev/null || true
|
||||||
@@ -333,7 +333,7 @@ if [ ! -f "${SHOWCASE_INDEX}" ] && [ ! -f "${SHOWCASE_INDEX_ALT1}" ] && [ ! -f "
|
|||||||
echo -e " ${CYAN}📦 Installing portable Node.js ${NODE_VER} in user space (~/.local)...${NC}"
|
echo -e " ${CYAN}📦 Installing portable Node.js ${NODE_VER} in user space (~/.local)...${NC}"
|
||||||
rm -rf "${NODE_DIR}"
|
rm -rf "${NODE_DIR}"
|
||||||
mkdir -p "${NODE_DIR}" "${HOME}/.local/bin"
|
mkdir -p "${NODE_DIR}" "${HOME}/.local/bin"
|
||||||
if curl -fsSL "https://nodejs.org/dist/${NODE_VER}/node-${NODE_VER}-${OS_SYS}-${NODE_ARCH}.tar.gz" | tar -xz -C "${NODE_DIR}" --strip-components=1 2>/dev/null; then
|
if curl -fsSL --connect-timeout 5 --max-time 60 "https://nodejs.org/dist/${NODE_VER}/node-${NODE_VER}-${OS_SYS}-${NODE_ARCH}.tar.gz" | tar -xz -C "${NODE_DIR}" --strip-components=1 2>/dev/null; then
|
||||||
ln -sf "${NODE_DIR}/bin/node" "${HOME}/.local/bin/node"
|
ln -sf "${NODE_DIR}/bin/node" "${HOME}/.local/bin/node"
|
||||||
ln -sf "${NODE_DIR}/bin/npm" "${HOME}/.local/bin/npm"
|
ln -sf "${NODE_DIR}/bin/npm" "${HOME}/.local/bin/npm"
|
||||||
ln -sf "${NODE_DIR}/bin/npx" "${HOME}/.local/bin/npx"
|
ln -sf "${NODE_DIR}/bin/npx" "${HOME}/.local/bin/npx"
|
||||||
|
|||||||
Reference in new issue
Block a user