$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $api = Get-Content -LiteralPath (Join-Path $root 'utils/api.js') -Raw -Encoding UTF8 $t04 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t04-add-relative.vue') -Raw -Encoding UTF8 $t05 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t05-edit-member.vue') -Raw -Encoding UTF8 foreach ($required in @( 'const normalizeLineageWritePayload = (payload) =>', "const lineageRelationPath = Object.freeze({", "FATHER: 'parents'", "SPOUSE: 'spouses'", "SIBLING: 'siblings'", "SON: 'children'", 'async createRelatedPerson(genealogyId, personId, relationType, payload, requestOptions = {})', 'async updatePerson(genealogyId, personId, payload, requestOptions = {})', "'bindingMode',", "['NONE', 'SELF', 'SPECIFIED']", 'method: ''PUT''', 'requestStrict({' )) { if (-not $api.Contains($required)) { throw "Lineage Apifox write contract missing: $required" } } foreach ($forbidden in @('relationType: relationType.value', 'sex: addForm.gender')) { if ($t04.Contains($forbidden)) { throw "T04 must not guess unsupported wire field: $forbidden" } } foreach ($source in @($t04, $t05)) { if ($source.Contains('birthClock') -or $source.Contains('deathClock') -or $source.Contains('toDateTime(')) { throw 'Lineage birth/death dates must send the documented yyyy-MM-dd value, without a client-added time component' } } foreach ($required in @( 'v-model="addForm.personNo"', 'v-model="addForm.aliasName"', 'v-model="addForm.generation"', 'v-model="addForm.generationName"', 'v-model="addForm.birthPlace"', 'v-model="addForm.deathPlace"', 'v-model="addForm.burialPlace"', 'v-model="addForm.biography"', 'v-model="addForm.remark"', 'v-model="addForm.sortOrder"', 'v-model="addForm.relationName"', 'personNo: addForm.personNo', 'sex: addForm.sex', 'avatarOssId: addForm.avatarOssId', 'personStatus: addForm.personStatus', 'sortOrder: addForm.sortOrder', 'aliasName: addForm.aliasName', 'generationName: addForm.generationName', 'biography: addForm.biography', 'remark: addForm.remark', '? { generation: 1, relationName: addForm.relationName }', 'const sexOptions = Object.freeze([', 'const lunarOptions = Object.freeze([', 'const personStatusOptions = Object.freeze([', 'personOptionLabels', 'appApi.getLineagePersonOptions(', 'const personOptionsRequestController = createRequestController();', 'requestController: personOptionsRequestController', 'const bindingModeOptions = Object.freeze([', 'bindingMode: addForm.bindingMode', 'addForm.bindingMode === "SPECIFIED"', 'pickAndUploadImage(' )) { if (-not $t04.Contains($required)) { throw "T04 safe optional field missing: $required" } } foreach ($required in @( 'v-model="editForm.personNo"', 'v-model="editForm.generation"', 'v-model="editForm.sortOrder"', 'v-model="editForm.relationName"', 'personNo: editForm.personNo', 'sex: editForm.sex', 'avatarOssId: editForm.avatarOssId', 'personStatus: editForm.personStatus', 'sortOrder: editForm.sortOrder', 'const sexOptions = Object.freeze([', 'const lunarOptions = Object.freeze([', 'const personStatusOptions = Object.freeze([', 'personOptionLabels', 'appApi.getLineagePersonOptions(', 'const personOptionsRequestController = createRequestController();', 'requestController: personOptionsRequestController', 'const bindingModeOptions = Object.freeze([', 'bindingMode: editForm.bindingMode', 'editForm.bindingMode === "SPECIFIED"', 'pickAndUploadImage(' )) { if (-not $t05.Contains($required)) { throw "T05 LineagePersonBody field missing: $required" } } foreach ($forbidden in @( 'v-model="addForm.appUserId"', 'v-model="addForm.fatherId"', 'v-model="addForm.motherId"', 'v-model="addForm.avatarOssId"', 'v-model="editForm.appUserId"', 'v-model="editForm.fatherId"', 'v-model="editForm.motherId"', 'v-model="editForm.avatarOssId"' )) { if ($t04.Contains($forbidden) -or $t05.Contains($forbidden)) { throw "Lineage ID or OSS field must not be a raw input: $forbidden" } } foreach ($source in @($t04, $t05)) { if ($source.Contains('getProfile({ requestController: profileRequestController })')) { throw 'Lineage identity binding must not fetch and submit the current appUserId for NONE or SELF' } } foreach ($required in @('appApi.createRelatedPerson(', 'appApi.createPerson(', 'appApi.updatePerson(', 'failedAction.value = "save"')) { $source = if ($required -eq 'appApi.updatePerson(' -or $required -eq 'failedAction.value = "save"') { $t05 } else { $t04 } if (-not $source.Contains($required)) { throw "Lineage write page missing: $required" } } Write-Output 'LINEAGE-WRITE-APIFOX-CONTRACT PASS'