internal/sdk/runtime.ps1
|
function Import-BapSdk { [CmdletBinding()] param () if ('D365Bap.Tools.PowerPlatformSdk.SdkClient' -as [type]) { return } $sdkRoot = Join-Path $script:ModuleRoot 'bin/PowerPlatformSdk' $bridge = Join-Path $sdkRoot 'D365Bap.Tools.PowerPlatformSdk.dll' if (-not (Test-Path -LiteralPath $bridge)) { throw 'The bundled Power Platform SDK is missing. Run build/Build-PowerPlatformSdk.ps1 before importing the source module.' } $null = [Reflection.Assembly]::LoadFrom((Join-Path $sdkRoot 'Microsoft.Kiota.Abstractions.dll')) $null = [Reflection.Assembly]::LoadFrom((Join-Path $sdkRoot 'Microsoft.Kiota.Serialization.Json.dll')) $null = [Reflection.Assembly]::LoadFrom((Join-Path $sdkRoot 'Microsoft.Kiota.Http.HttpClientLibrary.dll')) $null = [Reflection.Assembly]::LoadFrom((Join-Path $sdkRoot 'Microsoft.PowerPlatform.Management.dll')) $null = [Reflection.Assembly]::LoadFrom($bridge) } function Get-BapSdkParameter { [CmdletBinding()] param ($Resource, [string] $Method) $builder = $Resource.Builder -as [type] $bodyParameter = $builder.GetMethod($Method).GetParameters() | Where-Object { $_.Name -eq 'body' } if (-not $bodyParameter) { return } foreach ($property in $bodyParameter.ParameterType.GetProperties()) { if ($property.Name -eq 'AdditionalData') { continue } $type = $property.PropertyType $collection = $type.IsGenericType -and $type.GetGenericTypeDefinition() -eq [Collections.Generic.List``1] if ($collection) { $type = $type.GetGenericArguments()[0] } $underlying = [Nullable]::GetUnderlyingType($type) if ($underlying) { $type = $underlying } if (-not $type.IsEnum) { throw "The SDK generator does not yet support request property $($property.Name) of type $type." } $name = $property.Name if ($Resource.ParameterPrefix -and $name.StartsWith($Resource.ParameterPrefix)) { $name = $name.Substring($Resource.ParameterPrefix.Length) } [pscustomobject]@{ Name = $name Property = $property Type = $type Collection = $collection Values = [Enum]::GetNames($type) ResponseProperty = $property.Name -replace '^Updated', '' BodyType = $bodyParameter.ParameterType } } } function Invoke-BapSdkRequest { [CmdletBinding()] param ($Resource, [string] $Method, [string] $EnvironmentId, $Body, [string] $Token, [string] $RequestUrl) $json = [D365Bap.Tools.PowerPlatformSdk.SdkClient]::Execute( $Resource.Builder, $Method, $EnvironmentId, $script:BapSdkApiVersion, $Body, $Token, $RequestUrl) if ($json) { $json | ConvertFrom-Json } } function Invoke-BapSdkCommand { [CmdletBinding()] param ([string] $CommandName, [Collections.IDictionary] $BoundParameters) $operation = $script:BapSdkCommands[$CommandName] $environmentId = $null $environmentName = $null if ($operation.Resource.Scope -eq 'Environment') { $inputEnvironment = $BoundParameters['EnvironmentId'] if ([guid]::TryParse($inputEnvironment, [ref]([guid]::Empty))) { $environmentId = $inputEnvironment $environmentName = $inputEnvironment } else { if ([Management.Automation.WildcardPattern]::ContainsWildcardCharacters($inputEnvironment)) { throw 'EnvironmentId must be an exact environment name or GUID.' } $environments = @(Get-BapEnvironment -EnvironmentId $inputEnvironment -ErrorAction Stop) if ($environments.Count -ne 1) { throw "Expected one environment named '$inputEnvironment'; found $($environments.Count)." } $environmentId = $environments[0].PpacEnvId $environmentName = $environments[0].EnvName } } $secureToken = Get-BapAccessToken -ResourceUrl 'https://api.powerplatform.com' $token = [Net.NetworkCredential]::new('', $secureToken).Password $body = $null if ($operation.Parameters.Count) { $current = Invoke-BapSdkRequest -Resource $operation.Resource -Method $operation.Resource.Methods.Get -EnvironmentId $environmentId -Token $token $body = [Activator]::CreateInstance($operation.Parameters[0].BodyType) foreach ($parameter in $operation.Parameters) { $value = if ($BoundParameters.ContainsKey($parameter.Name)) { $BoundParameters[$parameter.Name] } else { $current.($parameter.ResponseProperty) } if ($null -eq $value) { throw "The current value for $($parameter.Name) was absent. Specify it explicitly." } if ($parameter.Collection) { $converted = [Activator]::CreateInstance($parameter.Property.PropertyType) foreach ($item in $value) { $converted.Add([Enum]::Parse($parameter.Type, $item, $true)) } } else { $converted = [Enum]::Parse($parameter.Type, $value, $true) } $parameter.Property.SetValue($body, $converted) } } $request = @{ Resource = $operation.Resource Method = $operation.Method EnvironmentId = $environmentId Body = $body Token = $token ErrorAction = 'Stop' } $result = Invoke-BapSdkRequest @request if ($operation.Resource.CollectionProperty) { $items = [Collections.Generic.List[object]]::new() $visited = [Collections.Generic.HashSet[string]]::new() do { foreach ($item in $result.($operation.Resource.CollectionProperty)) { $items.Add($item) } $nextLink = $result.($operation.Resource.NextLinkProperty) if ($nextLink) { if (-not $visited.Add($nextLink)) { throw 'The API returned a repeated continuation URL.' } $result = Invoke-BapSdkRequest @request -RequestUrl $nextLink } } while ($nextLink) $name = if ($BoundParameters.ContainsKey('Name')) { $BoundParameters['Name'] } else { '*' } $filtered = foreach ($item in $items) { foreach ($property in $operation.Resource.FilterProperties) { if ($item.$property -like $name -or $item.$property -eq $name) { $item break } } } $output = @($filtered | Sort-Object -Property $operation.Resource.SortProperty | Select-PSFObject -TypeName $operation.Resource.TypeName -Property $operation.Resource.Properties) if ($BoundParameters['AsExcelOutput']) { if ($output.Count) { $output | Export-Excel -WorksheetName $operation.Resource.WorksheetName } return } return $output } if ($null -ne $result) { $result.PSObject.TypeNames.Insert(0, ('D365Bap.Tools.' + $operation.Resource.Noun)) foreach ($parameter in @(Get-BapSdkParameter -Resource $operation.Resource -Method $operation.Resource.Methods.Set)) { $result | Add-Member -NotePropertyName $parameter.Name -NotePropertyValue $result.($parameter.ResponseProperty) } $result | Add-Member -NotePropertyName EnvironmentId -NotePropertyValue $environmentId $result | Add-Member -NotePropertyName EnvironmentName -NotePropertyValue $environmentName $result | Add-Member -NotePropertyName PpacEnvId -NotePropertyValue $environmentId $result | Add-Member -NotePropertyName PpacEnvName -NotePropertyValue $environmentName $result } } |