Modules/businessdev.ALbuild.Feeds/Private/Get-BcNuspecIdentity.ps1

function Get-BcNuspecIdentity {
    <#
    .SYNOPSIS
        Reads the package id and version from a .nupkg's embedded .nuspec.
 
    .DESCRIPTION
        Internal helper. A .nupkg is an OPC zip; this opens it and parses the <id> and <version> from
        the root .nuspec entry. Reading the manifest is more reliable than parsing the file name,
        because package ids themselves contain dots.
 
    .PARAMETER PackagePath
        Path to the .nupkg.
 
    .OUTPUTS
        Hashtable with Id and Version.
    #>

    [CmdletBinding()]
    [OutputType([hashtable])]
    param(
        [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $PackagePath
    )

    if (-not (Test-Path -LiteralPath $PackagePath)) { throw "Package not found: '$PackagePath'." }

    Add-Type -AssemblyName System.IO.Compression -ErrorAction SilentlyContinue
    Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction SilentlyContinue

    $zip = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path -LiteralPath $PackagePath).ProviderPath)
    try {
        $entry = $zip.Entries | Where-Object { $_.FullName -notlike '*/*' -and $_.Name -like '*.nuspec' } | Select-Object -First 1
        if (-not $entry) { throw "No .nuspec found in '$PackagePath'." }
        $reader = [System.IO.StreamReader]::new($entry.Open())
        try { $nuspecXml = $reader.ReadToEnd() } finally { $reader.Dispose() }
    }
    finally { $zip.Dispose() }

    $xml = [xml] $nuspecXml
    $metadata = $xml.package.metadata
    $id = "$($metadata.id)"
    $version = "$($metadata.version)"
    if (-not $id -or -not $version) { throw "Could not read id/version from the .nuspec in '$PackagePath'." }

    return @{ Id = $id; Version = $version }
}