export function validatePayload(payload, type, rootKey, requiredIdKeyByType) { if (typeof payload !== "object" || payload === null || Array.isArray(payload)) { return "Payload must be an object"; } if (typeof payload.schemaVersion !== "number") { return "schemaVersion must be a number"; } const allowedTopLevel = new Set(["schemaVersion", rootKey]); const unknownTopLevel = Object.keys(payload).filter((key) => !allowedTopLevel.has(key)); if (unknownTopLevel.length > 0) { return `Unsupported top-level keys for ${type}: ${unknownTopLevel.join(", ")}`; } if (!Array.isArray(payload[rootKey])) { return `Missing array root: ${rootKey}`; } const idKey = requiredIdKeyByType[type]; if (!idKey) { return null; } const list = payload[rootKey]; for (let index = 0; index < list.length; index += 1) { const entry = list[index]; if (!entry || typeof entry !== "object" || Array.isArray(entry)) { return `${rootKey}[${index}] must be an object`; } const idValue = String(entry[idKey] ?? "").trim(); if (!idValue) { return `${rootKey}[${index}] is missing required key: ${idKey}`; } } return null; } export function validateCatalogMetaPayload(payload, frozenCatalogKeys) { if (typeof payload !== "object" || payload === null || Array.isArray(payload)) { return "Catalog payload must be an object"; } if (typeof payload.schemaVersion !== "number") { return "schemaVersion must be a number"; } const allowedTopLevel = new Set(["schemaVersion", ...frozenCatalogKeys]); const unknownTopLevel = Object.keys(payload).filter((key) => !allowedTopLevel.has(key)); if (unknownTopLevel.length > 0) { return `Unsupported catalog keys: ${unknownTopLevel.join(", ")}`; } for (const key of frozenCatalogKeys) { if (!Array.isArray(payload[key])) { return `${key} must be an array`; } } return null; }