|
<# |
|
.SYNOPSIS |
|
Cross-platform development environment setup module for PowerShell Core. |
|
|
|
.DESCRIPTION |
|
This module provides functions to install and configure a complete development |
|
environment on Windows, macOS, and Linux. It requires PowerShell Core (7+). |
|
|
|
.NOTES |
|
This module is designed to be imported by setup-core.ps1 and should only run |
|
on PowerShell Core, not Windows PowerShell 5.1. |
|
#> |
|
|
|
#Requires -Version 7.0 |
|
|
|
# ============================================================================ |
|
# PLATFORM DETECTION |
|
# ============================================================================ |
|
|
|
function Get-Platform { |
|
<# |
|
.SYNOPSIS |
|
Detects the current operating system platform. |
|
.OUTPUTS |
|
String: 'Windows', 'macOS', or 'Linux' |
|
#> |
|
if ($IsWindows) { return 'Windows' } |
|
if ($IsMacOS) { return 'macOS' } |
|
if ($IsLinux) { return 'Linux' } |
|
throw "Unknown platform" |
|
} |
|
|
|
function Get-PackageManager { |
|
<# |
|
.SYNOPSIS |
|
Returns the appropriate package manager for the current platform. |
|
#> |
|
switch (Get-Platform) { |
|
'Windows' { return 'winget' } |
|
'macOS' { return 'brew' } |
|
'Linux' { return 'apt' } # Default to apt, can be extended |
|
} |
|
} |
|
|
|
# ============================================================================ |
|
# LOGGING |
|
# ============================================================================ |
|
|
|
$script:LogFile = $null |
|
|
|
function Initialize-Logging { |
|
param([string]$LogDirectory = $null) |
|
|
|
if (-not $LogDirectory) { |
|
$LogDirectory = if ($IsWindows) { $env:TEMP } else { "/tmp" } |
|
} |
|
|
|
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss' |
|
$script:LogFile = Join-Path $LogDirectory "setup-core_$timestamp.log" |
|
|
|
Write-Info "Log file: $script:LogFile" |
|
} |
|
|
|
function Write-Info { |
|
param([string]$Message) |
|
$timestamp = Get-Date -Format 'HH:mm:ss' |
|
$line = "[$timestamp] [INFO] $Message" |
|
Write-Host $line -ForegroundColor Cyan |
|
if ($script:LogFile) { Add-Content -Path $script:LogFile -Value $line -ErrorAction SilentlyContinue } |
|
} |
|
|
|
function Write-Success { |
|
param([string]$Message) |
|
$timestamp = Get-Date -Format 'HH:mm:ss' |
|
$line = "[$timestamp] [OK] $Message" |
|
Write-Host $line -ForegroundColor Green |
|
if ($script:LogFile) { Add-Content -Path $script:LogFile -Value $line -ErrorAction SilentlyContinue } |
|
} |
|
|
|
function Write-Warn { |
|
param([string]$Message) |
|
$timestamp = Get-Date -Format 'HH:mm:ss' |
|
$line = "[$timestamp] [WARN] $Message" |
|
Write-Host $line -ForegroundColor Yellow |
|
if ($script:LogFile) { Add-Content -Path $script:LogFile -Value $line -ErrorAction SilentlyContinue } |
|
} |
|
|
|
function Write-Err { |
|
param([string]$Message) |
|
$timestamp = Get-Date -Format 'HH:mm:ss' |
|
$line = "[$timestamp] [ERROR] $Message" |
|
Write-Host $line -ForegroundColor Red |
|
if ($script:LogFile) { Add-Content -Path $script:LogFile -Value $line -ErrorAction SilentlyContinue } |
|
} |
|
|
|
# ============================================================================ |
|
# PACKAGE INSTALLATION - CROSS PLATFORM |
|
# ============================================================================ |
|
|
|
function Install-WithWinget { |
|
<# |
|
.SYNOPSIS |
|
Installs a package using winget (Windows only). |
|
#> |
|
param( |
|
[Parameter(Mandatory)][string]$Id, |
|
[string]$Name = $Id, |
|
[string[]]$ExtraArgs = @() |
|
) |
|
|
|
# Check if already installed |
|
$installed = $false |
|
try { |
|
$list = winget list --id $Id --exact --source winget 2>$null |
|
if ($list -match [Regex]::Escape($Id)) { $installed = $true } |
|
} catch { } |
|
|
|
if ($installed) { |
|
Write-Info "$Name is already installed." |
|
return $true |
|
} |
|
|
|
Write-Info "Installing $Name via winget..." |
|
$args = @('install', '--id', $Id, '-e', '--source', 'winget', '--accept-package-agreements', '--accept-source-agreements') + $ExtraArgs |
|
|
|
try { |
|
& winget @args |
|
if ($LASTEXITCODE -eq 0) { |
|
Write-Success "$Name installed successfully." |
|
return $true |
|
} else { |
|
Write-Warn "$Name installation returned exit code $LASTEXITCODE" |
|
return $false |
|
} |
|
} catch { |
|
Write-Err "Failed to install ${Name}: $($_.Exception.Message)" |
|
return $false |
|
} |
|
} |
|
|
|
function Install-WithBrew { |
|
<# |
|
.SYNOPSIS |
|
Installs a package using Homebrew (macOS/Linux). |
|
#> |
|
param( |
|
[Parameter(Mandatory)][string]$Formula, |
|
[string]$Name = $Formula, |
|
[switch]$Cask |
|
) |
|
|
|
# Check if already installed |
|
$installed = $false |
|
try { |
|
if ($Cask) { |
|
$list = brew list --cask 2>$null |
|
} else { |
|
$list = brew list --formula 2>$null |
|
} |
|
if ($list -contains $Formula) { $installed = $true } |
|
} catch { } |
|
|
|
if ($installed) { |
|
Write-Info "$Name is already installed." |
|
return $true |
|
} |
|
|
|
Write-Info "Installing $Name via Homebrew..." |
|
try { |
|
if ($Cask) { |
|
brew install --cask $Formula |
|
} else { |
|
brew install $Formula |
|
} |
|
|
|
if ($LASTEXITCODE -eq 0) { |
|
Write-Success "$Name installed successfully." |
|
return $true |
|
} else { |
|
Write-Warn "$Name installation returned exit code $LASTEXITCODE" |
|
return $false |
|
} |
|
} catch { |
|
Write-Err "Failed to install ${Name}: $($_.Exception.Message)" |
|
return $false |
|
} |
|
} |
|
|
|
function Install-WithApt { |
|
<# |
|
.SYNOPSIS |
|
Installs a package using apt (Debian/Ubuntu Linux). |
|
#> |
|
param( |
|
[Parameter(Mandatory)][string]$Package, |
|
[string]$Name = $Package |
|
) |
|
|
|
# Check if already installed |
|
$installed = $false |
|
try { |
|
$result = dpkg -l $Package 2>$null | grep "^ii" |
|
if ($result) { $installed = $true } |
|
} catch { } |
|
|
|
if ($installed) { |
|
Write-Info "$Name is already installed." |
|
return $true |
|
} |
|
|
|
Write-Info "Installing $Name via apt..." |
|
try { |
|
sudo apt-get install -y $Package |
|
if ($LASTEXITCODE -eq 0) { |
|
Write-Success "$Name installed successfully." |
|
return $true |
|
} else { |
|
Write-Warn "$Name installation returned exit code $LASTEXITCODE" |
|
return $false |
|
} |
|
} catch { |
|
Write-Err "Failed to install ${Name}: $($_.Exception.Message)" |
|
return $false |
|
} |
|
} |
|
|
|
# ============================================================================ |
|
# CROSS-PLATFORM PACKAGE INSTALLATION |
|
# ============================================================================ |
|
|
|
function Install-Package { |
|
<# |
|
.SYNOPSIS |
|
Cross-platform package installation wrapper. |
|
#> |
|
param( |
|
[string]$WingetId, |
|
[string]$BrewFormula, |
|
[string]$BrewCask, |
|
[string]$AptPackage, |
|
[string]$Name |
|
) |
|
|
|
$platform = Get-Platform |
|
$displayName = if ($Name) { $Name } else { $WingetId ?? $BrewFormula ?? $BrewCask ?? $AptPackage } |
|
|
|
switch ($platform) { |
|
'Windows' { |
|
if ($WingetId) { |
|
return Install-WithWinget -Id $WingetId -Name $displayName |
|
} |
|
} |
|
'macOS' { |
|
if ($BrewCask) { |
|
return Install-WithBrew -Formula $BrewCask -Name $displayName -Cask |
|
} elseif ($BrewFormula) { |
|
return Install-WithBrew -Formula $BrewFormula -Name $displayName |
|
} |
|
} |
|
'Linux' { |
|
if ($AptPackage) { |
|
return Install-WithApt -Package $AptPackage -Name $displayName |
|
} |
|
} |
|
} |
|
|
|
Write-Warn "No package definition for $displayName on $platform" |
|
return $false |
|
} |
|
|
|
# ============================================================================ |
|
# CORE TOOL INSTALLATION |
|
# ============================================================================ |
|
|
|
function Install-Git { |
|
Write-Info "Checking Git..." |
|
Install-Package -WingetId 'Git.Git' -BrewFormula 'git' -AptPackage 'git' -Name 'Git' |
|
} |
|
|
|
function Install-VSCode { |
|
Write-Info "Checking Visual Studio Code..." |
|
Install-Package -WingetId 'Microsoft.VisualStudioCode' -BrewCask 'visual-studio-code' -Name 'Visual Studio Code' |
|
# Note: On Linux, VS Code is typically installed via .deb or snap - handled separately |
|
} |
|
|
|
function Install-WindowsTerminal { |
|
if (-not $IsWindows) { return } |
|
Write-Info "Checking Windows Terminal..." |
|
Install-WithWinget -Id 'Microsoft.WindowsTerminal' -Name 'Windows Terminal' |
|
} |
|
|
|
function Install-PowerToys { |
|
if (-not $IsWindows) { return } |
|
Write-Info "Checking PowerToys..." |
|
Install-WithWinget -Id 'Microsoft.PowerToys' -Name 'PowerToys' |
|
} |
|
|
|
function Install-WindowsApp { |
|
<# |
|
.SYNOPSIS |
|
Installs Windows App (formerly Remote Desktop) for connecting to Dev Boxes and Azure Virtual Desktop. |
|
#> |
|
if (-not $IsWindows) { return } |
|
Write-Info "Checking Windows App (for Dev Boxes)..." |
|
Install-WithWinget -Id 'Microsoft.WindowsApp' -Name 'Windows App' |
|
} |
|
|
|
function Install-Python { |
|
Write-Info "Checking Python..." |
|
Install-Package -WingetId 'Python.Python.3.12' -BrewFormula 'python@3.12' -AptPackage 'python3' -Name 'Python' |
|
} |
|
|
|
function Install-GitHubCLI { |
|
Write-Info "Checking GitHub CLI..." |
|
Install-Package -WingetId 'GitHub.cli' -BrewFormula 'gh' -AptPackage 'gh' -Name 'GitHub CLI' |
|
} |
|
|
|
function Install-AzureCLI { |
|
Write-Info "Checking Azure CLI..." |
|
Install-Package -WingetId 'Microsoft.AzureCLI' -BrewFormula 'azure-cli' -Name 'Azure CLI' |
|
} |
|
|
|
function Install-AzureDeveloperCLI { |
|
Write-Info "Checking Azure Developer CLI..." |
|
if ($IsMacOS) { |
|
# azd requires a tap on macOS |
|
try { |
|
brew tap azure/azd 2>$null |
|
} catch { } |
|
} |
|
Install-Package -WingetId 'Microsoft.Azd' -BrewFormula 'azd' -Name 'Azure Developer CLI' |
|
} |
|
|
|
function Install-DotNetSDK { |
|
Write-Info "Checking .NET SDKs..." |
|
|
|
if ($IsWindows) { |
|
Install-WithWinget -Id 'Microsoft.DotNet.SDK.8' -Name '.NET SDK 8' |
|
Install-WithWinget -Id 'Microsoft.DotNet.SDK.9' -Name '.NET SDK 9' |
|
} elseif ($IsMacOS) { |
|
Install-WithBrew -Formula 'dotnet@8' -Name '.NET SDK 8' |
|
# .NET 9 may need --cask dotnet-sdk |
|
} elseif ($IsLinux) { |
|
# Linux needs Microsoft repo setup - handled in bootstrap or separately |
|
Install-WithApt -Package 'dotnet-sdk-8.0' -Name '.NET SDK 8' |
|
} |
|
} |
|
|
|
function Install-NodeJS { |
|
Write-Info "Checking Node.js (via nvm)..." |
|
|
|
if ($IsWindows) { |
|
Install-WithWinget -Id 'CoreyButler.NVMforWindows' -Name 'NVM for Windows' |
|
Write-Info "After setup, run 'nvm install lts' and 'nvm use lts' in a new terminal." |
|
} else { |
|
# Install nvm for macOS/Linux |
|
$nvmDir = Join-Path $HOME ".nvm" |
|
if (-not (Test-Path $nvmDir)) { |
|
Write-Info "Installing nvm..." |
|
try { |
|
bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash' |
|
Write-Success "nvm installed. Run 'nvm install --lts' after restarting your shell." |
|
} catch { |
|
Write-Warn "Failed to install nvm: $($_.Exception.Message)" |
|
} |
|
} else { |
|
Write-Info "nvm is already installed." |
|
} |
|
} |
|
} |
|
|
|
function Install-ContainerEngine { |
|
<# |
|
.SYNOPSIS |
|
Installs the appropriate container engine for the platform. |
|
- Windows: Podman |
|
- macOS: OrbStack (preferred) or Podman |
|
- Linux: Podman |
|
#> |
|
param( |
|
[ValidateSet('podman', 'orbstack', 'auto')] |
|
[string]$Engine = 'auto' |
|
) |
|
|
|
$platform = Get-Platform |
|
|
|
# Auto-select engine |
|
if ($Engine -eq 'auto') { |
|
$Engine = if ($platform -eq 'macOS') { 'orbstack' } else { 'podman' } |
|
} |
|
|
|
Write-Info "Installing container engine: $Engine..." |
|
|
|
switch ($Engine) { |
|
'orbstack' { |
|
if ($platform -ne 'macOS') { |
|
Write-Warn "OrbStack is only available on macOS. Falling back to Podman." |
|
Install-ContainerEngine -Engine 'podman' |
|
return |
|
} |
|
Install-WithBrew -Formula 'orbstack' -Name 'OrbStack' -Cask |
|
} |
|
'podman' { |
|
if ($IsWindows) { |
|
Install-WithWinget -Id 'RedHat.Podman' -Name 'Podman CLI' |
|
Install-WithWinget -Id 'RedHat.Podman-Desktop' -Name 'Podman Desktop' |
|
} elseif ($IsMacOS) { |
|
Install-WithBrew -Formula 'podman' -Name 'Podman' |
|
Install-WithBrew -Formula 'podman-desktop' -Name 'Podman Desktop' -Cask |
|
} else { |
|
Install-WithApt -Package 'podman' -Name 'Podman' |
|
} |
|
} |
|
} |
|
} |
|
|
|
function Install-WSL { |
|
<# |
|
.SYNOPSIS |
|
Installs WSL with Ubuntu on Windows. |
|
#> |
|
if (-not $IsWindows) { return } |
|
|
|
Write-Info "Checking WSL..." |
|
|
|
# Check if WSL is installed |
|
$wslInstalled = $false |
|
try { |
|
$wslVersion = wsl --version 2>$null |
|
if ($wslVersion) { $wslInstalled = $true } |
|
} catch { } |
|
|
|
if (-not $wslInstalled) { |
|
Write-Info "Installing WSL..." |
|
Install-WithWinget -Id 'Microsoft.WSL' -Name 'Windows Subsystem for Linux' |
|
} else { |
|
Write-Info "WSL is already installed." |
|
} |
|
|
|
# Check for Ubuntu |
|
$distros = wsl --list --quiet 2>$null |
|
if ($distros -notmatch 'Ubuntu') { |
|
Write-Info "Installing Ubuntu distribution..." |
|
try { |
|
wsl --install -d Ubuntu --no-launch |
|
Write-Success "Ubuntu installed. Please restart your computer, then run 'wsl' to complete Ubuntu setup." |
|
} catch { |
|
Write-Warn "Failed to install Ubuntu: $($_.Exception.Message)" |
|
Write-Info "You can manually install Ubuntu from the Microsoft Store or run 'wsl --install -d Ubuntu'" |
|
} |
|
} else { |
|
Write-Info "Ubuntu is already installed in WSL." |
|
} |
|
} |
|
|
|
# ============================================================================ |
|
# VS CODE EXTENSIONS |
|
# ============================================================================ |
|
|
|
function Install-VSCodeExtensions { |
|
Write-Info "Installing VS Code extensions..." |
|
|
|
$extensions = @( |
|
# Python |
|
'ms-python.python', |
|
'ms-python.vscode-pylance', |
|
'ms-python.debugpy', |
|
|
|
# Remote Development |
|
'ms-vscode.remote-containers', |
|
'ms-vscode-remote.remote-ssh', |
|
'ms-vscode-remote.remote-wsl', |
|
|
|
# GitHub & Live Share |
|
'ms-vsliveshare.vsliveshare', |
|
'GitHub.copilot', |
|
'GitHub.copilot-chat', |
|
|
|
# PowerShell & YAML |
|
'ms-vscode.PowerShell', |
|
'redhat.vscode-yaml', |
|
|
|
# Kubernetes |
|
'ms-kubernetes-tools.vscode-kubernetes-tools', |
|
|
|
# Azure |
|
'ms-azuretools.vscode-azurefunctions', |
|
'ms-azuretools.vscode-azureresourcegroups', |
|
'ms-azuretools.vscode-azureappservice', |
|
'ms-azuretools.vscode-azurestorage', |
|
'ms-azuretools.vscode-cosmosdb', |
|
|
|
# .NET / C# |
|
'ms-dotnettools.csharp', |
|
'ms-dotnettools.csdevkit', |
|
'ms-dotnettools.vscode-dotnet-runtime', |
|
'ms-semantic-kernel.semantic-kernel', |
|
|
|
# Git |
|
'eamodio.gitlens', |
|
'mhutchie.git-graph', |
|
|
|
# Utilities |
|
'usernamehw.errorlens', |
|
'esbenp.prettier-vscode', |
|
'dbaeumer.vscode-eslint', |
|
'ms-vscode.makefile-tools', |
|
'tamasfe.even-better-toml', |
|
|
|
# Additional Languages |
|
'golang.go', |
|
'rust-lang.rust-analyzer' |
|
) |
|
|
|
# Find VS Code CLI |
|
$codeCmd = Get-Command code -ErrorAction SilentlyContinue |
|
if (-not $codeCmd) { |
|
if ($IsWindows) { |
|
$codePath = Join-Path $env:LOCALAPPDATA 'Programs\Microsoft VS Code\bin\code.cmd' |
|
if (Test-Path $codePath) { $codeCmd = $codePath } |
|
} elseif ($IsMacOS) { |
|
$codePath = '/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code' |
|
if (Test-Path $codePath) { $codeCmd = $codePath } |
|
} |
|
} |
|
|
|
if (-not $codeCmd) { |
|
Write-Warn "VS Code CLI not found. Please open VS Code once to enable the 'code' command." |
|
return |
|
} |
|
|
|
# Get installed extensions |
|
try { |
|
$installedExtensions = & $codeCmd --list-extensions 2>$null |
|
} catch { |
|
$installedExtensions = @() |
|
} |
|
|
|
foreach ($ext in $extensions) { |
|
if ($installedExtensions -contains $ext) { |
|
Write-Info "Extension already installed: $ext" |
|
} else { |
|
Write-Info "Installing extension: $ext" |
|
try { |
|
& $codeCmd --install-extension $ext --force 2>&1 | Out-Null |
|
} catch { |
|
Write-Warn "Failed to install extension: $ext" |
|
} |
|
} |
|
} |
|
|
|
Write-Success "VS Code extensions installation complete." |
|
} |
|
|
|
# ============================================================================ |
|
# GIT CONFIGURATION |
|
# ============================================================================ |
|
|
|
function Set-GitConfiguration { |
|
param( |
|
[Parameter(Mandatory)][string]$Username, |
|
[Parameter(Mandatory)][string]$Email |
|
) |
|
|
|
Write-Info "Configuring Git..." |
|
|
|
try { |
|
git config --global user.name "$Username" |
|
git config --global user.email "$Email" |
|
git config --global core.editor "code --wait" |
|
git config --global init.defaultBranch "main" |
|
git config --global pull.rebase false |
|
|
|
if ($IsWindows) { |
|
git config --global core.autocrlf true |
|
} else { |
|
git config --global core.autocrlf input |
|
} |
|
|
|
Write-Success "Git configured for: $Username <$Email>" |
|
} catch { |
|
Write-Err "Failed to configure Git: $($_.Exception.Message)" |
|
} |
|
} |
|
|
|
function Set-GitAliases { |
|
Write-Info "Setting up Git aliases..." |
|
|
|
try { |
|
git config --global alias.co "checkout" |
|
git config --global alias.br "branch" |
|
git config --global alias.ci "commit" |
|
git config --global alias.st "status" |
|
git config --global alias.lg "log --oneline --graph --decorate" |
|
git config --global alias.last "log -1 HEAD" |
|
git config --global alias.unstage "reset HEAD --" |
|
|
|
Write-Success "Git aliases configured." |
|
} catch { |
|
Write-Warn "Failed to configure some Git aliases." |
|
} |
|
} |
|
|
|
# ============================================================================ |
|
# SHELL & TERMINAL CONFIGURATION |
|
# ============================================================================ |
|
|
|
function Install-NerdFont { |
|
Write-Info "Checking Nerd Fonts..." |
|
|
|
if ($IsWindows) { |
|
# Try different winget IDs for Nerd Fonts |
|
$fontIds = @( |
|
'NerdFonts.CascadiaCode', |
|
'NerdFonts.CaskaydiaCove' |
|
) |
|
foreach ($fontId in $fontIds) { |
|
$result = Install-WithWinget -Id $fontId -Name 'CaskaydiaCove Nerd Font' |
|
if ($result) { break } |
|
} |
|
} elseif ($IsMacOS) { |
|
try { |
|
brew tap homebrew/cask-fonts 2>$null |
|
} catch { } |
|
Install-WithBrew -Formula 'font-caskaydia-cove-nerd-font' -Name 'CaskaydiaCove Nerd Font' -Cask |
|
} |
|
} |
|
|
|
function Install-OhMyPosh { |
|
Write-Info "Checking Oh My Posh..." |
|
|
|
if ($IsWindows) { |
|
Install-WithWinget -Id 'JanDeDobbeleer.OhMyPosh' -Name 'Oh My Posh' |
|
} elseif ($IsMacOS) { |
|
Install-WithBrew -Formula 'oh-my-posh' -Name 'Oh My Posh' |
|
} |
|
|
|
# Add to PowerShell profile |
|
$profileContent = @" |
|
|
|
# Oh My Posh prompt |
|
if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) { |
|
oh-my-posh init pwsh --config `"`$env:POSH_THEMES_PATH/agnoster.omp.json`" | Invoke-Expression |
|
} |
|
"@ |
|
|
|
$profilePath = $PROFILE.CurrentUserAllHosts |
|
$profileDir = Split-Path $profilePath -Parent |
|
|
|
if (-not (Test-Path $profileDir)) { |
|
New-Item -ItemType Directory -Path $profileDir -Force | Out-Null |
|
} |
|
|
|
if (-not (Test-Path $profilePath)) { |
|
New-Item -ItemType File -Path $profilePath -Force | Out-Null |
|
} |
|
|
|
$existingProfile = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue |
|
if ($existingProfile -notmatch 'oh-my-posh') { |
|
Add-Content -Path $profilePath -Value $profileContent |
|
Write-Success "Oh My Posh added to PowerShell profile." |
|
} |
|
} |
|
|
|
function Install-ZshSetup { |
|
<# |
|
.SYNOPSIS |
|
Installs Zsh, Oh My Zsh, and Powerlevel10k on macOS/Linux. |
|
#> |
|
if ($IsWindows) { return } |
|
|
|
Write-Info "Setting up Zsh environment..." |
|
|
|
# Install Zsh if not present |
|
if (-not (Get-Command zsh -ErrorAction SilentlyContinue)) { |
|
if ($IsMacOS) { |
|
Write-Info "Zsh should be pre-installed on macOS." |
|
} else { |
|
Install-WithApt -Package 'zsh' -Name 'Zsh' |
|
} |
|
} |
|
|
|
# Install Oh My Zsh |
|
$omzDir = Join-Path $HOME ".oh-my-zsh" |
|
if (-not (Test-Path $omzDir)) { |
|
Write-Info "Installing Oh My Zsh..." |
|
try { |
|
bash -c 'RUNZSH=no CHSH=no KEEP_ZSHRC=yes sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"' |
|
Write-Success "Oh My Zsh installed." |
|
} catch { |
|
Write-Warn "Failed to install Oh My Zsh: $($_.Exception.Message)" |
|
} |
|
} else { |
|
Write-Info "Oh My Zsh is already installed." |
|
} |
|
|
|
# Install Powerlevel10k theme |
|
$p10kDir = Join-Path $HOME ".oh-my-zsh/custom/themes/powerlevel10k" |
|
if (-not (Test-Path $p10kDir)) { |
|
Write-Info "Installing Powerlevel10k theme..." |
|
try { |
|
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git $p10kDir |
|
Write-Success "Powerlevel10k installed." |
|
} catch { |
|
Write-Warn "Failed to install Powerlevel10k: $($_.Exception.Message)" |
|
} |
|
} |
|
} |
|
|
|
# ============================================================================ |
|
# DOTNET GLOBAL TOOLS |
|
# ============================================================================ |
|
|
|
function Install-DotNetGlobalTools { |
|
Write-Info "Installing .NET global tools..." |
|
|
|
if (-not (Get-Command dotnet -ErrorAction SilentlyContinue)) { |
|
Write-Warn ".NET SDK not found. Skipping global tools installation." |
|
return |
|
} |
|
|
|
$tools = @('dotnet-ef', 'dotnet-format') |
|
|
|
foreach ($tool in $tools) { |
|
try { |
|
dotnet tool update --global $tool 2>$null |
|
if ($LASTEXITCODE -ne 0) { |
|
dotnet tool install --global $tool |
|
} |
|
Write-Success "$tool installed/updated." |
|
} catch { |
|
Write-Warn "Failed to install $tool" |
|
} |
|
} |
|
} |
|
|
|
# ============================================================================ |
|
# EXPORTS |
|
# ============================================================================ |
|
|
|
Export-ModuleMember -Function @( |
|
# Platform detection |
|
'Get-Platform', |
|
'Get-PackageManager', |
|
|
|
# Logging |
|
'Initialize-Logging', |
|
'Write-Info', |
|
'Write-Success', |
|
'Write-Warn', |
|
'Write-Err', |
|
|
|
# Package installation |
|
'Install-Package', |
|
'Install-WithWinget', |
|
'Install-WithBrew', |
|
'Install-WithApt', |
|
|
|
# Core tools |
|
'Install-Git', |
|
'Install-VSCode', |
|
'Install-WindowsTerminal', |
|
'Install-PowerToys', |
|
'Install-Python', |
|
'Install-GitHubCLI', |
|
'Install-AzureCLI', |
|
'Install-AzureDeveloperCLI', |
|
'Install-DotNetSDK', |
|
'Install-NodeJS', |
|
'Install-ContainerEngine', |
|
'Install-WSL', |
|
|
|
# VS Code |
|
'Install-VSCodeExtensions', |
|
|
|
# Git |
|
'Set-GitConfiguration', |
|
'Set-GitAliases', |
|
|
|
# Shell & Terminal |
|
'Install-NerdFont', |
|
'Install-OhMyPosh', |
|
'Install-ZshSetup', |
|
|
|
# Windows-specific |
|
'Install-WindowsApp', |
|
|
|
# .NET |
|
'Install-DotNetGlobalTools' |
|
) |