Modules/businessdev.ALbuild.Containers/Public/Get-BcContainerWebClientUrl.ps1

function Get-BcContainerWebClientUrl {
    <#
    .SYNOPSIS
        Resolves the reachable Web Client URL of a Business Central container.
 
    .DESCRIPTION
        Returns the URL an external browser (e.g. the OpenClaw Playwright agent on another host) can
        use to open the container's Web Client, together with the protocol, IP and port. The URL is
        built IP-based (not DNS/name-based) so it resolves from any host on the LAN - a container on a
        transparent Docker network has its own DHCP LAN IP, and even a default (NAT) container's IP is
        stable on the Docker host.
 
        The container IP is read via 'docker inspect' (the same pattern as Publish-BcContainerApp). The
        protocol is taken from -Protocol if given (the caller created the container and knows it),
        otherwise from the 'albuild.protocol' label stamped by New-BcContainer, defaulting to https
        (the BC generic image's default). Default Web Client ports (80 http / 443 https) are omitted
        from the URL.
 
    .PARAMETER Name
        Container name.
 
    .PARAMETER Protocol
        'http' or 'https'. Empty = read the 'albuild.protocol' label, else default to 'https'.
 
    .PARAMETER ServerInstance
        BC server instance (the Web Client path segment). Default 'BC' (the generic image default).
 
    .PARAMETER DockerExecutable
        The Docker executable to use (default 'docker').
 
    .OUTPUTS
        PSCustomObject with Url, Protocol, Ip, Port - or $null when no container IP could be resolved
        (e.g. the container is not running yet).
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [Alias('ContainerName')] [string] $Name,
        [ValidateSet('', 'http', 'https')] [string] $Protocol = '',
        [string] $ServerInstance = 'BC',
        [string] $DockerExecutable = 'docker'
    )

    # Protocol precedence: explicit -Protocol > the 'albuild.protocol' label > 'https' (image default).
    if (-not $Protocol) {
        $lbl = Invoke-BcDocker -DockerExecutable $DockerExecutable -Quiet -PassThru `
            -Arguments @('inspect', '-f', '{{index .Config.Labels "albuild.protocol"}}', $Name)
        if ($lbl.Success) {
            $p = "$($lbl.StdOut)".Trim()
            if ($p -eq 'http' -or $p -eq 'https') { $Protocol = $p }
        }
        if (-not $Protocol) { $Protocol = 'https' }
    }

    # Container IP: on a transparent network this is the DHCP-assigned LAN IP; on the default NAT
    # network it is the internal Docker IP. Concatenated across networks (a container has one here).
    $ipResult = Invoke-BcDocker -DockerExecutable $DockerExecutable -Quiet -PassThru `
        -Arguments @('inspect', '-f', '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}', $Name)
    $ip = if ($ipResult.Success) { "$($ipResult.StdOut)".Trim() } else { '' }
    if ([string]::IsNullOrWhiteSpace($ip)) { return $null }

    $port = if ($Protocol -eq 'https') { 443 } else { 80 }
    [PSCustomObject]@{
        Url      = "$Protocol`://$ip/$ServerInstance/"
        Protocol = $Protocol
        Ip       = $ip
        Port     = $port
    }
}