runtimeidentifier.ps1

param(
    [parameter(Mandatory = $true)]
    [psobject]
    $Exported
)

Try {
    $Exported | Add-Member `
        -MemberType NoteProperty `
        -Name Runtime `
        -Value ([System.Runtime.InteropServices.RuntimeInformation]::RuntimeIdentifier.ToString())
} Catch {

    # The C# Architecture Enum should cover all architectures listed in Microsoft.NETCore.Platforms
    # - see: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=net-7.0
    $arch = Try {
        [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString()
    } Catch {
        Try {
            [System.Runtime.InteropServices.RuntimeInformation, mscorlib]::OSArchitecture.ToString()
        } Catch {}
    }
    $os_releases_file = Get-Content -Path "/etc/os-release" -ErrorAction SilentlyContinue
    $os_checks = @{
        # Standard Linux Checks
        @(
            "alpine", "arch", "centos", "debian", "exherbo", "fedora",
            "gentoo", "linuxmint", "manjaro", "miraclelinux", "ol",
            "opensuse", "rhel", "rocky", "sles", "tizen", "ubuntu"
        ) = { param( $OS ); Try { $os_releases_file -match "ID\=[`"']?$OS" } Catch { $false } }
        
        # Unsupported OS Checks
        @(
            "android", # Android currently requires Xamarin/.NET MAUI to run, and PowerShell only supports .NET Core and .NET Framework
            "browser", # While Blazor Web Assembly technically has limited capability to run .NET Core, there is no current implementation of PowerShell for it
            "illumos", "omnios", "openindiana", "smartos", "solaris", # Solaris systems are not supported by PowerShell
            "ios", "iossimulator", "tvos", "tvossimulator", # iOS currently requires Xamarin/.NET MAUI to run, and PowerShell only supports .NET Core and .NET Framework
            "maccatalyst", # While maccatalyst supports .NET core, there is no current implementation of PowerShell for it
            "freebsd" # FreeBSD does not yet support .NET Core
        ) = { $false }

        # Built-in Checks
        @( "osx", "linux" ) = { param( $OS ); [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::"$OS") }
        "win" = { [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Windows) }
        "unix" = {
            [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::Linux) -or `
            [System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform([System.Runtime.InteropServices.OSPlatform]::OSX)
        }
    }

    $oses = $os_checks.GetEnumerator() | ForEach-Object {
        $os_array = $_.Key
        $os_check = $_.Value
        $os_array | Where-Object {
            $os_check.Invoke( $_ )
        }
    } | Where-Object { $_ }
    
    $rids = if( $oses.Count ){
        $global:version_ammendments = @(
            @(
                @(
                    "alpine", "centos", "debian", "fedora", "linuxmint",
                    "miraclelinux", "ol", "opensuse", "rhel", "rocky",
                    "sles", "tizen", "ubuntu"
                ),
                { param( $OS ); ($os_releases_file | Where-Object { $_ -match "VERSION_ID" }).Split("=")[1].Trim("`"' ") },
                { param( $OS, $Version ); "$OS.$Version" }
            ),
            # Currently unsupported systems that do have version checks
            # "android", "freebsd", "ios", "iossimulator"
            # "maccatalyst", "omnios", "smartos", "solaris"
            # "tvos", "tvossimulator"
            @(
                "osx",
                {
                    param( $OS )
                    $v = $(sw_vers -productVersion)
                    $maj = $v.Split(".")[0]
                    $min = $v.Split(".")[1]
                    if( $maj -eq "10" ){
                        "$maj.$min"
                    } else {
                        $maj
                    }
                },
                { param( $OS, $Version ); "$OS.$Version" }
            ),
            @(
                "win",
                {
                    param( $OS )
                    $version = [System.Environment]::OSVersion.Version

                    switch -Wildcard ($version.ToString()) 
                    {
                        "10.0*" { "10" }
                        "6.3*"  { "81" }
                        "6.2*"  { "8" }
                        "6.1*"  { "7" }
                        default { "" }
                    }
                },
                { param( $OS, $Version ); "$($OS)$($Version)" }
            )
        )
        $oses = $oses | ForEach-Object {
            $os = $_
            $version_ammendment = $version_ammendments | Where-Object { $_[0] -contains $os }
            $ammended = if( $version_ammendment.Count ){
                $version_ammendment[2].Invoke( $os, $version_ammendment[1].Invoke( $os ) )
            } else {
                $os
            }
            $ammended
        }
        $oses | ForEach-Object {
            $os = $_
            (@( $os, $arch.ToLower() ) | Where-Object { $_ }) -join "-"
        }
    } else {
        (@( "any", $arch.ToLower() ) | Where-Object { $_ }) -join "-"
    }

    # aot checks are not required for PowerShell

    # need to check the RID graph for the top most RID in the list of detected RIDs
    # I think I will create a set of graphs for each RID, then check which RID only occurs in one set of graphs

    $graphs = @{}
    $rids | ForEach-Object {
        $graphs[$_] = [System.Collections.ArrayList]::new()
        $graphs[$_].add( [System.Collections.ArrayList]::new() ) | Out-Null

        & $grapher $_ $graphs[$_][0] $graphs[$_]
    }

    $rid = $rids | ForEach-Object {
        # iterate through the other graph sets and count how many of the sets contain the current RID
        $output = @{
            "rid" = $_
            "tally" = 0
        }

        If( $graphs.Keys.Count -ne 1 ){
            $graphs.Keys | Where-Object { $_ -ne $output.rid } | ForEach-Object {
                $graph = $graphs[$_]
                $graph | Where-Object { $_.Contains( $output.rid ) } | ForEach-Object { $output.tally += 1 }
            }
        }

        $output
    } | Where-Object { $_.tally -eq 0 } | ForEach-Object { $_.rid } | Select-Object -First 1

    if( $rid.Count -ne 1 ){
        Write-Host "Unable to determine the correct RID for this system."
        Write-Host "Possible RID Count: $($rid.Count)"
        Write-Host "Possible RIDs: $($rid -join ", ")"
        Write-Host "All RIDs Detected: $($rids -join ", ")"
    }

    $Exported | Add-Member `
        -MemberType NoteProperty `
        -Name Runtime `
        -Value $rid

    $Exported
}