Public/Update-PSGalleryStats.ps1

function Update-PSGalleryStats {
    [CmdletBinding()]
    param(
        [string]$Path
    )

    $filePath = Join-Path (Get-SnapshotPath) 'Modules.txt'
    if (-not (Test-Path -LiteralPath $filePath)) {
        Write-Warning "No modules registered. Use Register-PSGalleryModule to add modules."
        return
    }

    $modules = @(Get-Content -LiteralPath $filePath | Where-Object { $_ -match '\S' })
    if ($modules.Count -eq 0) {
        Write-Warning "No modules registered. Use Register-PSGalleryModule to add modules."
        return
    }

    if ([string]::IsNullOrWhiteSpace($Path)) {
        $dir = Get-SnapshotPath
        $Path = Join-Path $dir 'PSGalleryDownloads.csv'
    }

    if (-not (Test-Path -LiteralPath $Path)) {
        Set-Content -LiteralPath $Path -Value 'Date,ModuleName,LatestVersion,TotalDownloads' -Encoding utf8BOM
    }

    foreach ($name in $modules) {
        Write-Verbose "Fetching stats for '$name'..."

        $entries = Invoke-GalleryAPI -ModuleName $name

        if ($entries.Count -eq 0) {
            Write-Warning "Module '$name' not found on PowerShell Gallery."
            continue
        }

        $stable = @($entries | Where-Object { -not $_.IsPrerelease })
        $latest = $stable | Where-Object { $_.IsLatestVersion } | Select-Object -First 1
        if ($null -eq $latest) {
            $latest = $stable | Sort-Object { [version]($_.Version -replace '-.*') } -Descending |
                      Select-Object -First 1
        }
        if ($null -eq $latest) {
            Write-Warning "Module '$name' has no stable versions."
            continue
        }

        $date = [datetime]::UtcNow.ToString('yyyy-MM-dd')
        Add-Content -LiteralPath $Path -Value "$date,$($latest.Id),$($latest.Version),$($latest.DownloadCount)" -Encoding utf8BOM

        [PSCustomObject]@{
            Date           = $date
            ModuleName     = $latest.Id
            LatestVersion  = $latest.Version
            TotalDownloads = $latest.DownloadCount
        }
    }
}