65 lines
3.0 KiB
PowerShell
65 lines
3.0 KiB
PowerShell
$ErrorActionPreference = 'Stop'
|
|
|
|
$root = Split-Path -Parent $PSScriptRoot
|
|
$documents = @(Get-ChildItem -LiteralPath $root -File -Filter '*.openapi.json')
|
|
if ($documents.Count -ne 1) { throw 'Exactly one current OpenAPI JSON export is required at the repository root' }
|
|
$documentPath = $documents[0].FullName
|
|
$document = Get-Content -Raw -Encoding UTF8 -LiteralPath $documentPath | ConvertFrom-Json
|
|
|
|
function Get-Operation {
|
|
param([string]$Path, [string]$Method)
|
|
$pathProperty = $document.paths.PSObject.Properties[$Path]
|
|
if (-not $pathProperty) { throw "Missing lineage path: $Path" }
|
|
$operation = $pathProperty.Value.PSObject.Properties[$Method]
|
|
if (-not $operation) { throw "Missing lineage operation: $Method $Path" }
|
|
return $operation.Value
|
|
}
|
|
|
|
function Assert-ClientHeader {
|
|
param([object]$Operation, [string]$Label)
|
|
$clientId = @($Operation.parameters | Where-Object { $_.in -eq 'header' -and $_.name -eq 'clientid' -and $_.required -eq $true })
|
|
if ($clientId.Count -ne 1) { throw "$Label must require the clientid header" }
|
|
$hasSaToken = @($Operation.security | Where-Object { $_.PSObject.Properties.Name -contains 'SaToken' }).Count -gt 0
|
|
if (-not $hasSaToken) { throw "$Label must require SaToken" }
|
|
}
|
|
|
|
$listPath = '/genealogy/app/genealogies/{genealogyId}/lineage/persons'
|
|
$detailPath = '/genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}'
|
|
$pagePath = '/genealogy/app/genealogies/{genealogyId}/lineage/persons/page'
|
|
|
|
foreach ($target in @(
|
|
@{ Path = $listPath; Method = 'get' },
|
|
@{ Path = $listPath; Method = 'post' },
|
|
@{ Path = $detailPath; Method = 'get' },
|
|
@{ Path = $detailPath; Method = 'put' },
|
|
@{ Path = $pagePath; Method = 'get' }
|
|
)) {
|
|
$operation = Get-Operation -Path $target.Path -Method $target.Method
|
|
Assert-ClientHeader -Operation $operation -Label "$($target.Method.ToUpper()) $($target.Path)"
|
|
}
|
|
|
|
$create = Get-Operation -Path $listPath -Method 'post'
|
|
$requestSchema = $create.requestBody.content.'application/json'.schema
|
|
if ($requestSchema.'$ref' -ne '#/components/schemas/LineagePersonBody') {
|
|
throw 'Lineage person create must consume LineagePersonBody'
|
|
}
|
|
|
|
$body = $document.components.schemas.LineagePersonBody
|
|
if (@($body.required) -notcontains 'name') { throw 'LineagePersonBody must require name' }
|
|
foreach ($field in @('name', 'generation', 'appUserId', 'fatherId', 'motherId', 'avatarOssId', 'birthLunar', 'deathLunar', 'personStatus')) {
|
|
if (-not $body.properties.PSObject.Properties[$field]) { throw "LineagePersonBody is missing $field" }
|
|
}
|
|
|
|
$avatar = $body.properties.avatarOssId
|
|
if (($avatar.type -join ',') -ne 'string,null' -or $avatar.pattern -ne '^[1-9][0-9]*$') {
|
|
throw 'LineagePersonBody.avatarOssId must use the decimal string OSS ID contract'
|
|
}
|
|
|
|
foreach ($field in @('birthLunar', 'deathLunar', 'personStatus', 'sex')) {
|
|
$schema = $body.properties.$field
|
|
if ($schema.type -ne 'string') { throw "LineagePersonBody.$field must be a dictionary string" }
|
|
if ($schema.enum) { throw "LineagePersonBody.$field enum changed; update the T-series selector contract" }
|
|
}
|
|
|
|
Write-Output 'LINEAGE-OPENAPI-CONTRACT PASS'
|