teams-cli 0.2.3

A Microsoft Teams CLI and TUI designed equally for humans and agents
Documentation
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
try {
    Add-Type -AssemblyName System.Security
    $request = [Console]::In.ReadToEnd() | ConvertFrom-Json
    if ($request.id -cnotmatch '^[a-f0-9]{64}$') { throw 'invalid request' }
    $root = Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) 'teams-cli\credentials'
    $path = Join-Path $root ($request.id + '.dpapi')
    $scope = [System.Security.Cryptography.DataProtectionScope]::CurrentUser
    $result = @{ status = 'ok'; secret = '' }
    switch ($request.action) {
        'get' {
            if (![IO.File]::Exists($path)) { $result.status = 'missing'; break }
            $encrypted = [IO.File]::ReadAllBytes($path)
            $plain = [System.Security.Cryptography.ProtectedData]::Unprotect($encrypted, $null, $scope)
            $result.secret = [Convert]::ToBase64String($plain)
        }
        'set' {
            $plain = [Convert]::FromBase64String($request.secret)
            $encrypted = [System.Security.Cryptography.ProtectedData]::Protect($plain, $null, $scope)
            [IO.Directory]::CreateDirectory($root) | Out-Null
            $temporary = Join-Path $root ([Guid]::NewGuid().ToString() + '.tmp')
            try {
                [IO.File]::WriteAllBytes($temporary, $encrypted)
                if ([IO.File]::Exists($path)) {
                    # PowerShell coerces $null to an empty string for string
                    # parameters; File.Replace needs an actual null backup path.
                    [IO.File]::Replace($temporary, $path, [System.Management.Automation.Language.NullString]::Value)
                } else {
                    [IO.File]::Move($temporary, $path)
                }
            } finally {
                if ([IO.File]::Exists($temporary)) { [IO.File]::Delete($temporary) }
            }
        }
        'delete' {
            if ([IO.File]::Exists($path)) { [IO.File]::Delete($path) }
            else { $result.status = 'missing' }
        }
        default { throw 'invalid action' }
    }
    [Console]::Out.Write(($result | ConvertTo-Json -Compress))
} catch {
    [Console]::Out.Write('{"status":"error"}')
    exit 1
}