← Files Power BI DesktopARCHIVED FILE

scripts/New-PowerBITomWritePlan.ps1

2.57 KB · Oct 2, 2026 · 00:32 UTC

↓ Download file

param(
    [ValidateSet('AddMeasure','UpdateMeasure','AddRelationship','AddRole','AddCalculationGroup','RunTmsl')]
    [string]$Operation = 'AddMeasure',
    [string]$TableName,
    [string]$ObjectName,
    [string]$Expression,
    [string]$ConnectionString,
    [string]$OutputPath,
    [switch]$AllowWrite,
    [switch]$Json
)

$ErrorActionPreference = 'Stop'

$safetyGates = @(
    [pscustomobject]@{ gate = 'Dry run default'; passed = (-not $AllowWrite); detail = 'No write is performed unless AllowWrite is explicitly set.' },
    [pscustomobject]@{ gate = 'Connection explicit'; passed = [bool]$ConnectionString; detail = 'A TOM/TMSL write path must target an explicit local or service endpoint.' },
    [pscustomobject]@{ gate = 'Backup required'; passed = $false; detail = 'Export PBIP/TMDL or model.bim before any write.' },
    [pscustomobject]@{ gate = 'Diff required'; passed = $false; detail = 'Review before/after TMDL/TMSL diff before apply.' },
    [pscustomobject]@{ gate = 'Rollback required'; passed = $false; detail = 'Define rollback script or source-control revert before apply.' }
)

$draft = switch ($Operation) {
    'AddMeasure' { "CREATE OR REPLACE MEASURE '$TableName'[$ObjectName] = $Expression" }
    'UpdateMeasure' { "ALTER MEASURE '$TableName'[$ObjectName] = $Expression" }
    'AddRelationship' { "CREATE RELATIONSHIP $ObjectName" }
    'AddRole' { "CREATE ROLE $ObjectName" }
    'AddCalculationGroup' { "CREATE CALCULATION GROUP $ObjectName" }
    default { $Expression }
}

$result = [pscustomobject]@{
    schema = 'codex.powerbi.tomWritePlan.v1'
    generated = (Get-Date).ToString('s')
    operation = $Operation
    tableName = $TableName
    objectName = $ObjectName
    dryRun = (-not $AllowWrite)
    connectionStringProvided = [bool]$ConnectionString
    safetyGates = $safetyGates
    draftCommand = $draft
    writeStatus = if ($AllowWrite) { 'BlockedUntilBackupDiffRollbackConfirmed' } else { 'DryRunOnly' }
}

if ($Json) {
    $text = $result | ConvertTo-Json -Depth 8
    if ($OutputPath) { Set-Content -LiteralPath $OutputPath -Value $text -Encoding UTF8 }
    $text
    return
}

$lines = @('# TOM/TMSL Write Plan', '', "Operation: $Operation", "Dry run: $($result.dryRun)", '', '## Safety Gates') +
    @($safetyGates | ForEach-Object { "- [$($_.gate)] Passed=$($_.passed): $($_.detail)" }) +
    @('', '## Draft Command', '', '```text', $draft, '```')
$content = ($lines -join [Environment]::NewLine) + [Environment]::NewLine
if ($OutputPath) { Set-Content -LiteralPath $OutputPath -Value $content -Encoding UTF8 }
$content

SHA-256: f5c1dc25aba653df14ee2b84bd7a8b84e5376fb9e3612869a8c65873164e1210