Public/Core/Import-ModuleSafe.ps1

function Import-ModuleSafe {
    <#
    .SYNOPSIS
        Imports a module, installing it (CurrentUser scope) first if it isn't present.
 
    .DESCRIPTION
        Guards an Import-Module call so a missing module doesn't break profile startup:
          1. If the module isn't already available, install it with Install-PSResource
             into the CurrentUser scope.
          2. Import the module.
          3. If an initialization script block was supplied, run it after the import.
 
        Any failure to install or import is reported as a warning and swallowed so the rest
        of profile initialization continues; the initialization script is only run once the
        module has imported successfully.
 
    .PARAMETER Name
        Name of the module to ensure and import.
 
    .PARAMETER Initialize
        Optional script block run after the module is imported (e.g. setting module-specific
        environment variables or options).
 
    .PARAMETER Repair
        Optional recovery script block run when the import fails. After it runs the import is
        retried once, and a warning is only reported if that retry also fails. Use it to clean up
        state that wedges a module's import (e.g. Repair-TerminalIconsCache, which purges a
        corrupted Terminal-Icons theme cache so the re-import can regenerate it). With no -Repair
        an import failure is reported as a warning immediately, as before.
 
    .PARAMETER Scope
        Scope to install into when the module is missing. Defaults to 'CurrentUser'.
 
    .PARAMETER Repository
        Repository to install from when the module is missing. Defaults to 'PSGallery'.
 
    .EXAMPLE
        Import-ModuleSafe Terminal-Icons
 
    .EXAMPLE
        Import-ModuleSafe posh-git -Initialize { $env:POSH_GIT_ENABLED = $true }
 
    .EXAMPLE
        Import-ModuleSafe Terminal-Icons -Repair { Repair-TerminalIconsCache }
 
        Import Terminal-Icons; if it fails (e.g. a corrupted theme cache), run the repair and retry
        once before warning.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory, Position = 0)]
        [string]$Name,

        [Parameter(Position = 1)]
        [scriptblock]$Initialize,

        [Parameter()]
        [scriptblock]$Repair,

        [Parameter()]
        [ValidateSet('CurrentUser', 'AllUsers')]
        [string]$Scope = 'CurrentUser',

        [Parameter()]
        [string]$Repository = 'PSGallery'
    )

    if (-not (Get-Module -ListAvailable -Name $Name)) {
        try {
            Install-PSResource -Name $Name -Repository $Repository -Scope $Scope -TrustRepository -ErrorAction Stop
        }
        catch {
            Write-Warning "Import-ModuleSafe: could not install '$Name' from '$Repository': $($_.Exception.Message)"
            return
        }
    }

    try {
        Import-Module $Name -ErrorAction Stop
    }
    catch {
        if ($Repair) {
            # Best-effort recovery, then one retry; only warn if the retry also fails.
            & $Repair
            try {
                Import-Module $Name -ErrorAction Stop
            }
            catch {
                Write-Warning "Import-ModuleSafe: could not import '$Name': $($_.Exception.Message)"
                return
            }
        }
        else {
            Write-Warning "Import-ModuleSafe: could not import '$Name': $($_.Exception.Message)"
            return
        }
    }

    if ($Initialize) {
        & $Initialize
    }
}