diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..1078f5a --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,84 @@ +name: Generate and Deploy Documentation + +on: + push: + branches: [ main ] + paths: + - 'docs-config.json' + - 'scripts/Generate-Docs.ps1' + - '.github/workflows/docs.yml' + schedule: + # Run weekly to pick up new package versions + - cron: '0 2 * * 0' + workflow_dispatch: + inputs: + force_rebuild: + description: 'Force complete rebuild' + required: false + default: 'false' + type: boolean + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + generate-docs: + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.x' + + - name: Setup NuGet + uses: NuGet/setup-nuget@v2 + + - name: Install DocFX + run: dotnet tool install -g docfx + + - name: Setup Pages + uses: actions/configure-pages@v4 + + - name: Cache NuGet packages + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('docs-config.json') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: Generate Documentation + shell: pwsh + run: | + $cleanFlag = if ("${{ github.event.inputs.force_rebuild }}" -eq "true") { "-Clean" } else { "" } + & "./scripts/Generate-Docs.ps1" -ConfigFile "docs-config.json" -OutputPath "docs" $cleanFlag + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/_site + + deploy: + needs: generate-docs + runs-on: ubuntu-latest + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 7b7da96..c9b1ffc 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,10 @@ Microsoft.VisualStudio.Glass /Iris/Programs/*.pdb /Iris/ic/Properties/launchSettings.json /Iris/xplat-package/Properties/launchSettings.json + +# DocFX +docs/_site/ +docs/api/ +docs/docfx.json +docs/filterConfig.yml +*.tmp diff --git a/DOCFX_USAGE.md b/DOCFX_USAGE.md new file mode 100644 index 0000000..719d8c3 --- /dev/null +++ b/DOCFX_USAGE.md @@ -0,0 +1,204 @@ +# DocFX Documentation Generation System + +This repository contains a complete solution for generating and hosting API documentation from NuGet packages using DocFX. + +## 🚀 Quick Start + +### Prerequisites +- PowerShell 5.1 or later +- .NET SDK 8.0 or later +- NuGet CLI (optional, for package version updates) +- DocFX (installed automatically by scripts) + +### Generate Documentation Locally + +```powershell +# Option 1: Generate and serve locally in one command +.\scripts\Serve-Docs-Local.ps1 + +# Option 2: Generate only +.\scripts\Generate-Docs.ps1 -ConfigFile docs-config.json -OutputPath docs + +# Option 3: Generate with clean rebuild +.\scripts\Generate-Docs.ps1 -ConfigFile docs-config.json -OutputPath docs -Clean +``` + +After running, the documentation will be available at: `http://localhost:8080` + +## 📦 Configuration + +Edit `docs-config.json` to configure which NuGet packages to document: + +```json +{ + "packages": [ + { + "id": "Microsoft.VisualStudio.Debugger.Engine", + "version": "17.14.1051801", + "description": "Visual Studio Debugger Engine APIs and interfaces", + "framework": "net472" + } + ], + "docfx": { + "siteName": "Visual Studio Debugger Engine Documentation", + "siteDescription": "API documentation for Visual Studio Debugger Engine extensibility interfaces", + "baseUrl": "https://microsoft.github.io/ConcordExtensibilitySamples/" + } +} +``` + +### Package Configuration Options +- **id**: NuGet package ID +- **version**: Specific version to document +- **description**: Human-readable description for the documentation +- **framework**: Target framework (e.g., "net472", "netstandard2.0") + +## 🔄 Automatic Updates + +### GitHub Actions +The repository includes a GitHub Action (`.github/workflows/docs.yml`) that: +- Runs automatically on pushes to main branch +- Runs weekly to pick up new package versions +- Can be triggered manually with force rebuild option +- Deploys to GitHub Pages automatically + +### Package Version Updates +```powershell +# Check for updates (preview mode) +.\scripts\Update-PackageVersions.ps1 -Preview + +# Update configuration file with latest versions +.\scripts\Update-PackageVersions.ps1 +``` + +## 📁 Generated Structure + +``` +docs/ +├── _site/ # Generated static website +├── api/ # Generated API reference (YAML files) +├── docfx.json # DocFX configuration (auto-generated) +├── index.md # Documentation homepage +└── toc.yml # Table of contents +``` + +## 🌐 GitHub Pages Deployment + +The documentation is automatically deployed to GitHub Pages at: +**https://microsoft.github.io/ConcordExtensibilitySamples/** + +### Manual Deployment Setup +1. Go to repository Settings > Pages +2. Set Source to "GitHub Actions" +3. The workflow will handle the rest automatically + +## 🛠️ Troubleshooting + +### Common Issues + +1. **DocFX not found** + ```powershell + dotnet tool install -g docfx + ``` + +2. **NuGet package download fails** + - Check package ID and version in `docs-config.json` + - Ensure internet connectivity + - Verify package exists on nuget.org + +3. **Documentation generation fails** + - Check that assemblies were extracted successfully + - Verify .NET target framework compatibility + - Review DocFX logs for specific errors + +4. **GitHub Actions fails** + - Check workflow permissions (Pages deployment requires write permissions) + - Verify repository has GitHub Pages enabled + - Review action logs for specific errors + +### Debug Mode +Run scripts with verbose output: +```powershell +$VerbosePreference = "Continue" +.\scripts\Generate-Docs.ps1 -ConfigFile docs-config.json -Verbose +``` + +## 📋 Script Reference + +### Generate-Docs.ps1 +Main documentation generation script. + +**Parameters:** +- `-ConfigFile`: Path to configuration JSON file (required) +- `-OutputPath`: Output directory for generated docs (default: "docs") +- `-Clean`: Remove existing files before generation + +### Update-PackageVersions.ps1 +Updates package versions in configuration to latest available. + +**Parameters:** +- `-ConfigFile`: Path to configuration JSON file (default: "docs-config.json") +- `-Preview`: Show available updates without applying them + +### Serve-Docs-Local.ps1 +Generates and serves documentation locally for development. + +**Parameters:** +- `-ConfigFile`: Path to configuration JSON file (default: "docs-config.json") +- `-Port`: Port for local web server (default: 8080) + +## 🔧 Advanced Configuration + +### Custom DocFX Templates +Modify the `template` array in the generated `docfx.json` to use custom templates: + +```json +{ + "build": { + "template": ["default", "modern", "custom-template-path"] + } +} +``` + +### Multiple Package Sources +Add multiple packages to document different APIs: + +```json +{ + "packages": [ + { + "id": "Microsoft.VisualStudio.Debugger.Engine", + "version": "17.14.1051801", + "description": "Visual Studio Debugger Engine APIs", + "framework": "net472" + }, + { + "id": "Microsoft.VisualStudio.Shell.Framework", + "version": "17.0.31902.203", + "description": "Visual Studio Shell Framework", + "framework": "net472" + } + ] +} +``` + +### Custom Metadata +Add custom metadata to generated documentation: + +```json +{ + "docfx": { + "siteName": "My API Docs", + "siteDescription": "Documentation for my APIs", + "baseUrl": "https://myorg.github.io/myrepo/", + "customMetadata": { + "_appFooter": "Copyright © 2025 My Organization", + "_appLogoPath": "images/logo.png" + } + } +} +``` + +## 📝 License + +This documentation system is part of the ConcordExtensibilitySamples repository and follows the same licensing terms. diff --git a/README.md b/README.md index 5c5ae50..a49773c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ -## ConcordExtensibilitySamples +# ConcordExtensibilitySamples + Visual Studio Debug Engine Extensibility Samples +## Documentation + +📚 **[View API Documentation](https://microsoft.github.io/ConcordExtensibilitySamples/)** - Complete API documentation for Visual Studio Debugger Engine extensibility interfaces + ### What are "Concord Extensibility Samples"? -[Concord](https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/Overview) is the code name for Visual Studio's new debug engine that first shipped in Visual Studio 2012. Concord was designed to be extensible and this repo contains samples of these extensions. +[Concord](https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/Overview) is the code name for Visual Studio's new debug engine that first shipped in Visual Studio 2012. Concord was designed to be extensible and this repo contains samples of these extensions. The samples in this repo currently target Visual Studio 2022 (version 17.0). For older versions of these samples, please see the [VS16 branch](https://github.com/Microsoft/ConcordExtensibilitySamples/tree/VS16). @@ -17,4 +22,27 @@ If you want to dive right into some code for extending the debug engine, take a * [Managed Expression Evaluator](https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/Managed-Expression-Evaluator-Sample) * [C++ Custom Visualizer](https://github.com/Microsoft/ConcordExtensibilitySamples/wiki/Cpp-Custom-Visualizer-Sample) +## Documentation Generation + +This repository automatically generates and hosts API documentation for Visual Studio extensibility interfaces using DocFX. The documentation is built from NuGet packages and deployed to GitHub Pages. + +### Local Development + +To generate and serve documentation locally: + +```powershell +# Generate and serve docs locally +.\scripts\Serve-Docs-Local.ps1 + +# Update package versions +.\scripts\Update-PackageVersions.ps1 + +# Generate docs only +.\scripts\Generate-Docs.ps1 -ConfigFile docs-config.json +``` + +### Configuration + +Edit [`docs-config.json`](docs-config.json) to configure which NuGet packages to document. + This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/docs-config.json b/docs-config.json new file mode 100644 index 0000000..418769e --- /dev/null +++ b/docs-config.json @@ -0,0 +1,15 @@ +{ + "packages": [ + { + "id": "Microsoft.VisualStudio.Debugger.Engine", + "version": "17.14.1051801", + "description": "Visual Studio Debugger Engine APIs and interfaces", + "framework": "netstandard2.0" + } + ], + "docfx": { + "siteName": "Visual Studio Debugger Engine Documentation", + "siteDescription": "API documentation for Visual Studio Debugger Engine extensibility interfaces", + "baseUrl": "https://microsoft.github.io/ConcordExtensibilitySamples/" + } +} diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..5430540 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,18 @@ +# Visual Studio Debugger Engine Documentation + +API documentation for Visual Studio Debugger Engine extensibility interfaces + +## API Documentation + +This documentation covers the following packages: + +- **Microsoft.VisualStudio.Debugger.Engine** v17.14.1051801 - Visual Studio Debugger Engine APIs and interfaces + + +## API Reference + +Browse the [API Reference](api/) for detailed documentation of all types and members. + +--- + +*Generated on 2025-07-21 23:25:11 UTC from NuGet packages* diff --git a/docs/toc.yml b/docs/toc.yml new file mode 100644 index 0000000..db5f212 --- /dev/null +++ b/docs/toc.yml @@ -0,0 +1,4 @@ +- name: Home + href: index.md +- name: API Reference + href: api/ diff --git a/scripts/Generate-Docs.ps1 b/scripts/Generate-Docs.ps1 new file mode 100644 index 0000000..63a89d9 --- /dev/null +++ b/scripts/Generate-Docs.ps1 @@ -0,0 +1,330 @@ +<# +.SYNOPSIS + Generates DocFX documentation from NuGet packages +.DESCRIPTION + This script downloads specified NuGet packages, extracts assemblies, and generates DocFX documentation +.PARAMETER ConfigFile + Path to the configuration JSON file +.PARAMETER OutputPath + Output path for generated documentation +.PARAMETER Clean + Clean existing files before generation +#> + +param( + [Parameter(Mandatory = $true)] + [string]$ConfigFile, + + [Parameter(Mandatory = $false)] + [string]$OutputPath = "docs", + + [Parameter(Mandatory = $false)] + [switch]$Clean +) + +# Set error action preference +$ErrorActionPreference = "Stop" + +# Function to write colored output +function Write-ColorOutput { + param([string]$Message, [string]$Color = "Green") + Write-Host $Message -ForegroundColor $Color +} + +# Function to ensure directory exists +function Ensure-Directory { + param([string]$Path) + if (!(Test-Path $Path)) { + New-Item -ItemType Directory -Path $Path -Force | Out-Null + } +} + +# Main script +try { + Write-ColorOutput "Starting DocFX documentation generation..." "Cyan" + + # Load configuration + if (!(Test-Path $ConfigFile)) { + throw "Configuration file not found: $ConfigFile" + } + + $config = Get-Content $ConfigFile | ConvertFrom-Json + Write-ColorOutput "Loaded configuration with $($config.packages.Count) packages" + + # Setup directories + $tempDir = Join-Path $env:TEMP "docfx-nuget-$(Get-Date -Format 'yyyyMMdd-HHmmss')" + $packagesDir = Join-Path $tempDir "packages" + $assembliesDir = Join-Path $tempDir "assemblies" + + Ensure-Directory $tempDir + Ensure-Directory $packagesDir + Ensure-Directory $assembliesDir + Ensure-Directory $OutputPath + + Write-ColorOutput "Working directory: $tempDir" "Yellow" + + # Clean output if requested + if ($Clean) { + Write-ColorOutput "Cleaning existing documentation..." "Yellow" + Remove-Item (Join-Path $OutputPath "*") -Recurse -Force -ErrorAction SilentlyContinue + } + + # Download and extract packages + Write-ColorOutput "Downloading NuGet packages..." "Cyan" + + $assemblies = @() + foreach ($package in $config.packages) { + Write-ColorOutput "Processing package: $($package.id) v$($package.version)" + + # First check if package is already in global cache + $globalPackagePath = Join-Path $env:USERPROFILE ".nuget\packages\$($package.id.ToLower())\$($package.version)" + $packageDir = $null + + if (Test-Path $globalPackagePath) { + Write-ColorOutput " Found in global NuGet cache: $globalPackagePath" "Gray" + $packageDir = $globalPackagePath + } else { + # Download package using nuget install + $nugetArgs = @( + "install", $package.id, + "-Version", $package.version, + "-OutputDirectory", $packagesDir, + "-NoCache", + "-NonInteractive" + ) + + & nuget @nugetArgs + if ($LASTEXITCODE -ne 0) { + throw "Failed to download package: $($package.id)" + } + + $packageDir = Join-Path $packagesDir "$($package.id).$($package.version)" + } + + if (!(Test-Path $packageDir)) { + throw "Package directory not found: $packageDir" + } + + + # Find and copy assemblies from lib or ref folders + $libDir = Join-Path $packageDir "lib" + $refDir = Join-Path $packageDir "ref" + + # Try lib folder first, then ref folder + $searchDirs = @() + if (Test-Path $libDir) { $searchDirs += $libDir } + if (Test-Path $refDir) { $searchDirs += $refDir } + + if ($searchDirs.Count -eq 0) { + Write-ColorOutput " Warning: No lib or ref directories found in package" "Yellow" + continue + } + + foreach ($searchDir in $searchDirs) { + Write-ColorOutput " Searching in: $searchDir" "Gray" + + # Find appropriate framework folder + $frameworkDir = $null + if ($package.framework) { + $frameworkDir = Join-Path $searchDir $package.framework + # Also try common variations + if (!(Test-Path $frameworkDir)) { + $variations = @("netstandard2.0", "net462", "net472", "net48") + foreach ($variation in $variations) { + $testPath = Join-Path $searchDir $variation + if (Test-Path $testPath) { + $frameworkDir = $testPath + break + } + } + } + } + + if (!$frameworkDir -or !(Test-Path $frameworkDir)) { + # Find the best available framework + $availableFrameworks = Get-ChildItem $searchDir -Directory | Sort-Object Name -Descending + if ($availableFrameworks.Count -gt 0) { + $frameworkDir = $availableFrameworks[0].FullName + } + } + + if ($frameworkDir -and (Test-Path $frameworkDir)) { + Write-ColorOutput " Using framework directory: $frameworkDir" "Gray" + + # Copy DLL files + $dllFiles = Get-ChildItem $frameworkDir -Filter "*.dll" + foreach ($dll in $dllFiles) { + $destPath = Join-Path $assembliesDir $dll.Name + Copy-Item $dll.FullName $destPath -Force + $assemblies += $destPath + Write-ColorOutput " Copied: $($dll.Name)" "Gray" + + # Copy corresponding XML documentation file if it exists + $xmlName = [System.IO.Path]::ChangeExtension($dll.Name, ".xml") + $xmlPath = Join-Path $frameworkDir $xmlName + if (Test-Path $xmlPath) { + $xmlDestPath = Join-Path $assembliesDir $xmlName + Copy-Item $xmlPath $xmlDestPath -Force + Write-ColorOutput " Copied: $xmlName" "Gray" + } + } + break # Found assemblies, no need to check other directories + } + } + } + + if ($assemblies.Count -eq 0) { + throw "No assemblies found in downloaded packages" + } + + Write-ColorOutput "Found $($assemblies.Count) assemblies to document" "Green" + + # Generate DocFX configuration + Write-ColorOutput "Generating DocFX configuration..." "Cyan" + + $docfxConfig = @{ + metadata = @( + @{ + src = @( + @{ + files = $assemblies | ForEach-Object { [System.IO.Path]::GetFileName($_) } + src = $assembliesDir + } + ) + dest = "api" + includePrivateMembers = $false + disableGitFeatures = $false + disableDefaultFilter = $false + allowCompilationErrors = $true + properties = @{ + TargetFramework = "netstandard2.0" + } + filter = "filterConfig.yml" + } + ) + build = @{ + content = @( + @{ + files = @( + "api/**.yml", + "api/index.md" + ) + }, + @{ + files = @( + "articles/**.md", + "articles/**/toc.yml", + "toc.yml", + "*.md" + ) + } + ) + resource = @( + @{ + files = @("images/**") + } + ) + output = "_site" + template = @("default", "modern") + globalMetadata = @{ + "_appName" = $config.docfx.siteName + "_appTitle" = $config.docfx.siteDescription + "_enableSearch" = $true + "_gitContribute" = @{ + repo = "https://github.com/microsoft/ConcordExtensibilitySamples" + branch = "main" + } + "_gitUrlPattern" = "github" + } + } + } + + $docfxConfigPath = Join-Path $OutputPath "docfx.json" + $docfxConfig | ConvertTo-Json -Depth 10 | Set-Content $docfxConfigPath + + # Create a filter configuration to include all public APIs + $filterConfig = @" +apiRules: +- exclude: + uidRegex: ^System\. + type: Namespace +- exclude: + uidRegex: ^Microsoft\.VisualStudio\..*\.Internal + type: Namespace +- include: + uidRegex: .* + type: Type +- include: + uidRegex: .* + type: Member +"@ + + Set-Content (Join-Path $OutputPath "filterConfig.yml") $filterConfig + + # Create index page + $indexContent = @" +# $($config.docfx.siteName) + +$($config.docfx.siteDescription) + +## API Documentation + +This documentation covers the following packages: + +$($config.packages | ForEach-Object { "- **$($_.id)** v$($_.version) - $($_.description)" } | Out-String) + +## API Reference + +Browse the [API Reference](api/) for detailed documentation of all types and members. + +--- + +*Generated on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss UTC') from NuGet packages* +"@ + + Set-Content (Join-Path $OutputPath "index.md") $indexContent + + # Create table of contents + $tocContent = @" +- name: Home + href: index.md +- name: API Reference + href: api/ +"@ + + Set-Content (Join-Path $OutputPath "toc.yml") $tocContent + + # Create articles directory and basic content + $articlesDir = Join-Path $OutputPath "articles" + Ensure-Directory $articlesDir + + # Generate documentation + Write-ColorOutput "Generating documentation with DocFX..." "Cyan" + + Push-Location $OutputPath + try { + & docfx docfx.json + if ($LASTEXITCODE -ne 0) { + throw "DocFX generation failed" + } + + Write-ColorOutput "Documentation generated successfully!" "Green" + Write-ColorOutput "Output directory: $(Join-Path (Get-Location) '_site')" "Yellow" + } + finally { + Pop-Location + } + + # Cleanup + Write-ColorOutput "Cleaning up temporary files..." "Yellow" + Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue + + Write-ColorOutput "Documentation generation completed successfully!" "Green" +} +catch { + Write-ColorOutput "Error: $($_.Exception.Message)" "Red" + if ($tempDir -and (Test-Path $tempDir)) { + Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue + } + exit 1 +} diff --git a/scripts/Serve-Docs-Local.ps1 b/scripts/Serve-Docs-Local.ps1 new file mode 100644 index 0000000..263c92f --- /dev/null +++ b/scripts/Serve-Docs-Local.ps1 @@ -0,0 +1,34 @@ +<# +.SYNOPSIS + Generates and serves documentation locally for development +#> + +param( + [Parameter(Mandatory = $false)] + [string]$ConfigFile = "docs-config.json", + + [Parameter(Mandatory = $false)] + [int]$Port = 8080 +) + +$ErrorActionPreference = "Stop" + +Write-Host "Starting local documentation server..." -ForegroundColor Cyan + +try { + # Generate docs + & "./scripts/Generate-Docs.ps1" -ConfigFile $ConfigFile -OutputPath "docs" -Clean + + # Serve locally + Push-Location "docs" + Write-Host "Serving documentation at http://localhost:$Port" -ForegroundColor Green + Write-Host "Press Ctrl+C to stop the server" -ForegroundColor Yellow + + & docfx serve _site --port $Port +} +catch { + Write-Error "Error: $($_.Exception.Message)" +} +finally { + Pop-Location +} diff --git a/scripts/Update-PackageVersions.ps1 b/scripts/Update-PackageVersions.ps1 new file mode 100644 index 0000000..3ff66b1 --- /dev/null +++ b/scripts/Update-PackageVersions.ps1 @@ -0,0 +1,70 @@ +<# +.SYNOPSIS + Updates package versions in docs-config.json to latest available versions +.DESCRIPTION + This script checks NuGet for the latest versions of configured packages and updates the configuration file +#> + +param( + [Parameter(Mandatory = $false)] + [string]$ConfigFile = "docs-config.json", + + [Parameter(Mandatory = $false)] + [switch]$Preview +) + +$ErrorActionPreference = "Stop" + +function Get-LatestPackageVersion { + param([string]$PackageId) + + try { + $nugetCmd = "nuget list $PackageId -NonInteractive" + $result = Invoke-Expression $nugetCmd + $line = $result | Where-Object { $_ -match "^$PackageId " } | Select-Object -First 1 + if ($line -match "$PackageId\s+(\d+\.\d+\.\d+(?:\.\d+)?)") { + return $matches[1] + } + } + catch { + Write-Warning "Could not get latest version for $PackageId" + } + return $null +} + +try { + Write-Host "Checking for package updates..." -ForegroundColor Cyan + + if (!(Test-Path $ConfigFile)) { + throw "Configuration file not found: $ConfigFile" + } + + $config = Get-Content $ConfigFile | ConvertFrom-Json + $updated = $false + + foreach ($package in $config.packages) { + Write-Host "Checking $($package.id)..." -ForegroundColor Yellow + $latestVersion = Get-LatestPackageVersion $package.id + + if ($latestVersion -and $latestVersion -ne $package.version) { + Write-Host " Update available: $($package.version) -> $latestVersion" -ForegroundColor Green + if (!$Preview) { + $package.version = $latestVersion + $updated = $true + } + } else { + Write-Host " Current version $($package.version) is up to date" -ForegroundColor Gray + } + } + + if ($updated) { + $config | ConvertTo-Json -Depth 10 | Set-Content $ConfigFile + Write-Host "Configuration updated!" -ForegroundColor Green + } elseif (!$Preview) { + Write-Host "No updates needed" -ForegroundColor Gray + } +} +catch { + Write-Error "Error: $($_.Exception.Message)" + exit 1 +}