Universal.psm1

[UniversalAutomation.AssemblyResolver]::Bind()
function Resolve-Variable {
    [CmdletBinding()]
    param($Name)

    $PSCmdlet.GetVariableValue($Name)
}

function Start-PSUServer {
    [CmdletBinding()]
    param(
        [Parameter()]
        [string]$ExecutablePath,
        [Parameter()]
        [string]$ListenAddress,
        [Parameter()]
        [int]$Port, 
        [Parameter()]
        [ScriptBlock]$Configuration
    )

    if ([UniversalAutomation.RemoteCommand]::Configuration)
    {
        & $Configuration
        return
    }

    if (-not $PSBoundParameters.ContainsKey("ExecutablePath"))
    {
        $ExecutablePath = "Universal.Server"
        if ($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows)
        {
            $ExecutablePath = "Universal.Server.exe"
        }
    }

    $Command = Get-Command $ExecutablePath -ErrorAction SilentlyContinue
    if ($null -eq $Command)
    {
        $ExecutablePath = Join-Path $PSScriptRoot $ExecutablePath
        $Command = Get-Command $ExecutablePath -ErrorAction SilentlyContinue
        if ($null -eq $Command)
        {
            throw 'Unable to locate the Universal Server executable. You can use Install-PSUServer the server for your platform. Use the -AddToPath parameter to add the installation directory the the PATH.'
        }
    }

    if ($PSVersionTable.PSEdition -ne 'Desktop' -and -not $IsWindows)
    {
        try 
        {
            chmod +x $ExecutablePath
        }
        catch 
        {
            Write-Warning "Failed to set executable flag. You may have to run 'chmod +x' yourself on $ExecutablePath. $_"
        }
    }

    if ($ListenAddress)
    {
        $Env:Kestrel__Endpoints__HTTP__Url = $ListenAddress
    }
    elseif ($PSBoundParameters.ContainsKey("Port"))
    {
        $Env:Kestrel__Endpoints__HTTP__Url = "http://localhost:$port"
    }

    if ($Configuration)
    {
        $scriptName = (Get-PSCallStack | Select-Object -Last 1).ScriptName
        if (-not $scriptName)
        {
            $scriptName = (Get-PSCallStack | Select-Object -Last 1 -Skip 1).ScriptName
        }
        $Env:Data__ConfigurationScript = $scriptName
    }

    $Process = Start-Process -FilePath $ExecutablePath -PassThru

    $Process
}

function Install-PSUServer {
    [CmdletBinding(DefaultParameterSetName = "Version")]
    param(
        [Parameter()]
        [string]$Path,
        [Parameter()]
        [Switch]$AddToPath,
        [Parameter(ParameterSetName = "Version")]
        [string]$Version = (Get-Module Universal).Version,
        [Parameter(ParameterSetName = "Latest")]
        [Switch]$LatestVersion
    )

    if ([UniversalAutomation.RemoteCommand]::Configuration)
    {
        return
    }

    $platform = "win7-x64";
    $folder = 'CommonApplicationData'
    if ($PSVersionTable.PSEdition -eq 'Core')
    {
        if ($IsLinux)
        {
            $platform = "linux-x64"
        }
        elseif ($IsMacOS)
        {
            $folder = 'ApplicationData'
            $platform = "osx-x64"
        }
    }

    if (-not $Path) {
        $ProgramData = [System.Environment]::GetFolderPath($folder)
        $Path = [System.IO.Path]::Combine($ProgramData, "PowerShellUniversal", "Server")
    }

    if ($LatestVersion)
    {
        $Version = (Invoke-WebRequest https://imsreleases.blob.core.windows.net/universal/production/version.txt).Content
    }

    $Temp= [System.IO.Path]::GetTempPath()
    $Zip = (Join-Path $Temp "Universal.$Version.$platform.zip")

    Invoke-WebRequest "https://imsreleases.blob.core.windows.net/universal/production/$version/Universal.$platform.$Version.zip" -OutFile $Zip
    Expand-Archive -Path $Zip -DestinationPath $Path -Force
    Remove-Item $Zip -Force

    if ($IsWindows)
    {
        Get-ChildItem $Path -Recurse | Unblock-File
    }
    
    if ($AddToPath)
    {
        $PathSeparator = ";" 
        $Scope = 'User'
        if ($platform -eq 'win7-x64' -and ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
        {
            $Scope = 'Machine'
        }

        if ($IsWindows)
        {
            $envPath = [Environment]::GetEnvironmentVariable('PATH', $Scope)
            $newpath = $envPath + $PathSeparator + $Path
            [Environment]::SetEnvironmentVariable("PATH", $newpath, $Scope)
        }
        else 
        {
            $PathSeparator = ":"
            Write-Warning "You may need to set your `$PATH environment variable manually. PowerShell Universal is installed to $Path"
            $envPath = [Environment]::GetEnvironmentVariable('PATH')
            $newpath = $envPath + $PathSeparator + $Path
            [Environment]::SetEnvironmentVariable("PATH", $newpath)
        }
        
        $Env:PATH += $PathSeparator + $Path
    }

    if ($IsMacOS)
    {
        $ServerPath = Join-Path $Path "Universal.Server"
        /bin/chmod +x $ServerPath
    }
}