/** * WHMCS Custom Field Utilities (domain-internal) */ const isObject = (value: unknown): value is Record => typeof value === "object" && value !== null; const normalizeCustomFieldEntries = (value: unknown): Array> => { if (Array.isArray(value)) return value.filter(isObject); if (isObject(value) && "customfield" in value) { const custom = (value as { customfield?: unknown }).customfield; if (Array.isArray(custom)) return custom.filter(isObject); if (isObject(custom)) return [custom]; return []; } return []; }; /** * Build a lightweight map of WHMCS custom field identifiers to values. * Accepts the documented WHMCS response shapes (array or { customfield }). */ export function getCustomFieldsMap(customFields: unknown): Record { if (!customFields) return {}; if (isObject(customFields) && !Array.isArray(customFields) && !("customfield" in customFields)) { return Object.entries(customFields).reduce>((acc, [key, value]) => { if (typeof value === "string") { const trimmedKey = key.trim(); if (trimmedKey) acc[trimmedKey] = value; } return acc; }, {}); } const map: Record = {}; for (const entry of normalizeCustomFieldEntries(customFields)) { const idRaw = "id" in entry ? entry["id"] : undefined; const id = typeof idRaw === "string" ? idRaw.trim() : typeof idRaw === "number" ? String(idRaw) : undefined; const nameRaw = "name" in entry ? entry["name"] : undefined; const name = typeof nameRaw === "string" ? nameRaw.trim() : undefined; const rawValue = "value" in entry ? entry["value"] : undefined; if (rawValue === undefined || rawValue === null) continue; const value = typeof rawValue === "string" ? rawValue : typeof rawValue === "number" || typeof rawValue === "boolean" ? String(rawValue) : undefined; if (!value) continue; if (id) map[id] = value; if (name) map[name] = value; } return map; } /** * Retrieve a custom field value by numeric id or name. */ export function getCustomFieldValue( customFields: unknown, key: string | number ): string | undefined { if (key === undefined || key === null) return undefined; const map = getCustomFieldsMap(customFields); const primary = map[String(key)]; if (primary !== undefined) return primary; if (typeof key === "string") { const numeric = Number.parseInt(key, 10); if (!Number.isNaN(numeric)) { const numericValue = map[String(numeric)]; if (numericValue !== undefined) return numericValue; } } return undefined; }