Private/Invoke-RaidinessModuleScript.ps1

<#
    The one place a local module script is started from. Invoke-RaidinessModule
    and the -Modules loop in Invoke-Raidiness both come through here, so tests
    mock this single boundary and the four scripts never run without a tenant.

    Each script declares its own parameters (sharepoint-admin takes -TenantName,
    the others -TenantId; teams has no -HashUpns). Rather than remembering that
    per name, the parameter block is read from the script with Get-Command —
    which parses, and does not execute — and only the parameters a script
    declares are passed.
#>

# psrunner-lint allow: New-Item — creates the local output directory for the module result; never a tenant object
function Invoke-RaidinessModuleScript {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $Name,
        [string] $TenantId,
        [string] $TenantName,
        [string] $OutputPath = './raidiness-data',
        [switch] $HashUpns,
        [string] $LogPath
    )

    $ErrorActionPreference = 'Stop'

    $script = Join-Path $PSScriptRoot '..' 'scripts' 'local' "$Name.ps1"
    if (-not (Test-Path $script)) {
        throw "Module script not found: $script"
    }
    $parameters = (Get-Command -Name $script).Parameters

    New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
    $result = Join-Path $OutputPath "raidiness-$Name.json"

    # The scripts predate the module and identify runs by an id; locally one
    # collection round is one run.
    $arguments = @{
        RunId      = "local-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
        OutputPath = $result
    }
    if ($parameters.ContainsKey('TenantName')) {
        if (-not $TenantName) {
            throw "The $Name module needs the tenant name (the 'contoso' in contoso-admin.sharepoint.com); pass -TenantId contoso.onmicrosoft.com or -TenantName contoso."
        }
        $arguments.TenantName = $TenantName
    }
    else {
        if (-not $TenantId) {
            throw "The $Name module needs a -TenantId (tenant id or default domain) for its sign-in."
        }
        $arguments.TenantId = $TenantId
    }
    if ($HashUpns -and $parameters.ContainsKey('HashUpns')) {
        $arguments.HashUpns = $true
    }
    # A script that can log, does. The same introspection that keeps
    # -TenantName off the scripts that do not take it applies here.
    if ($LogPath -and $parameters.ContainsKey('LogPath')) {
        $arguments.LogPath = $LogPath
    }

    & $script @arguments

    Write-Host "Module result written to $result — Export-RaidinessReport will pick it up." -ForegroundColor Green
}