src/_Install-CciModuleFromBlob.ps1

function _Install-CciModuleFromBlob {
<#
.SYNOPSIS
    Installs a module (and its RequiredModules, recursively) from the tenant
    distribution store.
.DESCRIPTION
    The feed path gets dependency resolution for free from PSResourceGet; the
    store path has to do it explicitly, by reading RequiredModules from the
    installed manifest and fetching each dependency that is not already
    available. $Seen guards against cycles and repeat work.
#>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$Name,
        [Parameter(Mandatory)]$Feed,
        [Parameter(Mandatory)]$Context,
        [Parameter(Mandatory)]$Index,
        [string]$Version,
        [ValidateSet('CurrentUser','AllUsers')][string]$Scope = 'CurrentUser',
        [switch]$Reinstall,
        [System.Collections.Generic.HashSet[string]]$Seen
    )

    if (-not $Seen) { $Seen = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) }
    if (-not $Seen.Add($Name)) { return }

    $entry = $Index.modules.PSObject.Properties[$Name]
    if (-not $entry) {
        throw "cciget: '$Name' is not present in the tenant distribution store index."
    }
    if (-not $Version) { $Version = $entry.Value.latest }

    $root   = _Get-CciModulesRoot -Scope $Scope
    $target = Join-Path (Join-Path $root $Name) $Version
    if ((Test-Path $target) -and -not $Reinstall) {
        Write-Host "cciget: $Name $Version already installed."
    }
    else {
        New-Item -ItemType Directory -Path $target -Force | Out-Null
        $prefix = "$($Feed.blobPrefix)/$Name/$Version/"
        $blobs  = @(Get-AzStorageBlob -Context $Context -Container $Feed.blobContainer -Prefix $prefix -ErrorAction Stop)
        if (-not $blobs) { throw "cciget: no content under '$prefix' in the distribution store." }
        Write-Host "cciget: downloading $Name $Version ($($blobs.Count) files) from the tenant distribution store..."
        foreach ($b in $blobs) {
            $rel = $b.Name.Substring($prefix.Length)
            if (-not $rel) { continue }
            $dest = Join-Path $target ($rel -replace '/', '\')
            $dir  = Split-Path $dest -Parent
            if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
            $null = Get-AzStorageBlobContent -Context $Context -Container $Feed.blobContainer `
                -Blob $b.Name -Destination $dest -Force -ErrorAction Stop
        }
        Write-Host "cciget: installed $Name $Version -> $target"
    }

    $psd1 = Get-ChildItem $target -Filter '*.psd1' | Select-Object -First 1
    if ($psd1) {
        $manifest = Import-PowerShellDataFile $psd1.FullName
        foreach ($dep in @($manifest.RequiredModules)) {
            if (-not $dep) { continue }
            $depName = if ($dep -is [hashtable]) { $dep.ModuleName } else { "$dep" }
            if (-not $depName) { continue }
            if (Get-Module -ListAvailable -Name $depName) {
                Write-Verbose "cciget: dependency $depName already available."
                continue
            }
            Write-Host "cciget: resolving dependency $depName..."
            _Install-CciModuleFromBlob -Name $depName -Feed $Feed -Context $Context -Index $Index `
                -Scope $Scope -Reinstall:$Reinstall -Seen $Seen
        }
    }
}