oob.psm1

function Start-OOB {
    [CmdletBinding()]
    param (
        [int]   $Port    = 8000,
        [string]$Name    = 'oob',
        [int]   $Timeout = 15
    )

    # 0. Node check
    Import-Module Node -ErrorAction Stop; Assert-NodeInstalled
    Write-Host "ℹ️ Using Node at: $(Get-NodePath)"

    # 1. Cloudflared
    Import-Module cloudflared -ErrorAction Stop

    # 2. Paths
    $moduleRoot = Split-Path (Join-Path $PSScriptRoot 'oob-server.js') -Parent
    $jsPath     = Join-Path $moduleRoot 'oob-server.js'
    if (-not (Test-Path $jsPath)) { throw "Missing: $jsPath" }

    # 3. Launch JS listener
    if (-not $script:__oobProc -or $script:__oobProc.HasExited) {
        $script:__oobProc = Start-Process node `
            -ArgumentList @("`"$jsPath`"", $Port, $Name) `
            -WorkingDirectory $moduleRoot `
            -WindowStyle Normal `
            -PassThru
        Start-Sleep 1
    }

    # 4. Start Cloudflare tunnel
    $tName               = "${Name}_$(Get-Random -Minimum 1000 -Maximum 9999)"
    $script:__oobTunnel  = Start-TempTunnel -Name $tName -Url "http://localhost:$Port" -TimeoutSeconds $Timeout
    Write-Host "🌐 Tunnel URL: $($script:__oobTunnel.Url)"

    # 5. Tail the latest log without checks
    $jsLog = Get-ChildItem (Join-Path $moduleRoot 'logs') -Filter "${Name}_*.log" -File |
             Sort-Object LastWriteTime -Descending |
             Select-Object -First 1

    if ($jsLog) {
        $script:__logJob = Start-Job -Name "OOBLog_$Name" -ScriptBlock {
            param($path)
            Get-Content -Path $path -Wait -Tail 0 |
            ForEach-Object { Write-Host "[OOB]" $_ }
        } -ArgumentList $jsLog.FullName
    }

    return $script:__oobTunnel.Url
}

function Stop-OOB {
    [CmdletBinding()]
    param()

    if ($script:__oobTunnel) {
        Stop-TempTunnel -Name $script:__oobTunnel.Name -ErrorAction SilentlyContinue
        $script:__oobTunnel = $null
    }
    if ($script:__oobProc -and -not $script:__oobProc.HasExited) {
        Stop-Process -Id $script:__oobProc.Id -ErrorAction SilentlyContinue
        $script:__oobProc = $null
    }
    if ($script:__logJob) {
        Stop-Job -Job $script:__logJob -Force -ErrorAction SilentlyContinue
        Remove-Job -Job $script:__logJob -Force -ErrorAction SilentlyContinue
        $script:__logJob = $null
    }

    Write-Host "🛑 OOB listener, tunnel, and log tail stopped."
}

Export-ModuleMember -Function Start-OOB, Stop-OOB