private/specs/Get-SpecsPropertyAsParameter.ps1
<# .SYNOPSIS Get the given API Specs property as a flat parameter with its attributes in a list together with any nested & also resolved property .DESCRIPTION Get the given API Specs property as a flat parameter with its attributes in a list together with any nested & also resolved property .PARAMETER JSONFilePath Mandatory. The path to the API Specs JSON file hosting the data .PARAMETER SpecificationData Mandatory. The specification data contain in the given API Specs file .PARAMETER RequiredParametersOnLevel Optional. A list of required parameters for the current level. If the current parameter is part of that list it will have a 'required' attribute .PARAMETER Parameter Mandatory. The parameter reference of the API Specs file to process .PARAMETER Name Mandatory. The name of the parameter to process .PARAMETER Parent Opional. The parent parameter of the currently process parameter. For example 'properties' for the most properties parameters - and '' (empty) if on root .PARAMETER Level Mandatory. The current 'tab' level. For example, root equals to 0, properties to 1 etc. .PARAMETER SkipLevel Optional. For this parameter, do not create a 'container' parameter, that is, a parameter that just exist to host other parameters. Only required in rare cases where a `ref` only contains further `ref` attributes and no properties. .EXAMPLE Get-SpecsPropertyAsParameter -JSONFilePath '(...)/resource-manager/Microsoft.KeyVault/stable/2022-07-01/keyvault.json' -SpecificationData @{ paths = @{(..)}; definititions = @{(..)}; (..) } -RequiredParametersOnLevel @('param1', 'param2') -Parameter @{ '$ref' = (..); description = '..' } -Name 'Param1' -Parent 'Param0' -Level 0 Process the given parameter. Converted in JSON the output may look like [ { "required": false, "Parent": "properties", "description": "The blob service properties for blob restore policy", "level": 1, "name": "restorePolicy", "type": "object" }, { "required": false, "Parent": "restorePolicy", "description": "Blob restore is enabled if set to true.", "level": 2, "name": "enabled", "type": "boolean" }, { "name": "days", "maxValue": 365, "type": "integer", "level": 2, "required": false, "description": "how long this blob can be restored. It should be great than zero and less than DeleteRetentionPolicy.days.", "minValue": 1, "Parent": "restorePolicy" } ] Which is equivalent to the following structure: restorePolicy:object enabled:boolean days:integer #> function Get-SpecsPropertyAsParameter { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $JSONFilePath, [Parameter(Mandatory = $true)] [hashtable] $SpecificationData, [Parameter(Mandatory = $false)] [array] $RequiredParametersOnLevel = @(), [Parameter(Mandatory = $true)] [hashtable] $Parameter, [Parameter(Mandatory = $true)] [string] $Name, [Parameter(Mandatory = $false)] [string] $Parent = '', [Parameter(Mandatory = $true)] [int] $Level, [Parameter(Mandatory = $false)] [boolean] $SkipLevel = $false ) $refObjects = @() if ($Parameter.readOnly) { return @() } if ($Parameter.Keys -contains '$ref') { # Parameter contains a reference to another specification $inputObject = @{ JSONFilePath = $JSONFilePath SpecificationData = $SpecificationData Parameter = $Parameter } $resolvedReference = Resolve-SpecPropertyReference @inputObject $parameter = $resolvedReference.parameter $specificationData = $resolvedReference.SpecificationData if ($Parameter.Keys -contains 'properties') { # Parameter is an object if (-not $SkipLevel) { $parameterObject = @{ level = $Level name = $Name type = 'object' description = $Parameter.description required = $RequiredParametersOnLevel -contains $Name Parent = $Parent } $refObjects += Set-OptionalParameter -SourceParameterObject $Parameter -TargetObject $parameterObject } foreach ($property in $Parameter['properties'].Keys) { $recursiveInputObject = @{ JSONFilePath = $JSONFilePath SpecificationData = $SpecificationData Parameter = $Parameter['properties'][$property] RequiredParametersOnLevel = $RequiredParametersOnLevel Level = $SkipLevel ? $Level : $Level + 1 Parent = $Name Name = $property } $refObjects += Get-SpecsPropertyAsParameter @recursiveInputObject } } else { $recursiveInputObject = @{ JSONFilePath = $JSONFilePath SpecificationData = $SpecificationData Parameter = $Parameter RequiredParametersOnLevel = $RequiredParametersOnLevel Level = $Level Parent = $Parent Name = $Name } $refObjects += Get-SpecsPropertyAsParameter @recursiveInputObject } } elseif ($Parameter.Keys -contains 'items') { # Parameter is an array if ($Parameter.items.Keys -contains '$ref') { # Each item is an object/array $parameterObject = @{ level = $Level name = $Name type = 'array' description = $Parameter.description required = $RequiredParametersOnLevel -contains $Name Parent = $Parent } $refObjects += Set-OptionalParameter -SourceParameterObject $Parameter -TargetObject $parameterObject $recursiveInputObject = @{ JSONFilePath = $JSONFilePath SpecificationData = $SpecificationData Parameter = $Parameter['items'] RequiredParametersOnLevel = $RequiredParametersOnLevel Level = $Level + 1 Parent = $Name Name = $property SkipLevel = $true } $refObjects += Get-SpecsPropertyAsParameter @recursiveInputObject } else { # Each item has a primitive type $parameterObject = @{ level = $Level name = $Name type = 'array' description = $Parameter.description required = $RequiredParametersOnLevel -contains $Name Parent = $Parent } $refObjects += Set-OptionalParameter -SourceParameterObject $Parameter -TargetObject $parameterObject } } elseif ($parameter.Keys -contains 'properties') { # The case if a definition reference should have been created, but the RP implemented it another way. # Example "TableServiceProperties": { "properties": { "properties": { "properties": { "cors": {...}}}}} $parameterObject = @{ level = $Level name = $Name type = 'object' description = $Parameter.description required = $RequiredParametersOnLevel -contains $Name Parent = $Parent } $refObjects += Set-OptionalParameter -SourceParameterObject $Parameter -TargetObject $parameterObject foreach ($property in $Parameter['properties'].Keys) { $recursiveInputObject = @{ JSONFilePath = $JSONFilePath SpecificationData = $SpecificationData Parameter = $Parameter['properties'][$property] RequiredParametersOnLevel = $RequiredParametersOnLevel Level = $SkipLevel ? $Level : $Level + 1 Parent = $Name Name = $property } $refObjects += Get-SpecsPropertyAsParameter @recursiveInputObject } } else { # Parameter is a 'simple' leaf - that is, not an object/array and does not reference any other specification if ($parameter.readOnly) { return @() } $parameterObject = @{ level = $Level name = $Name type = $Parameter.keys -contains 'type' ? $Parameter.type : 'object' description = $Parameter.description required = $RequiredParametersOnLevel -contains $Name Parent = $Parent } $refObjects += Set-OptionalParameter -SourceParameterObject $Parameter -TargetObject $parameterObject } return $refObjects } |