import type { RemoteObject } from "../types"; export function asRecord(value: unknown): RemoteObject { return value && typeof value === "object" && !Array.isArray(value) ? (value as RemoteObject) : {}; } export function isObjectRecord(value: unknown): value is RemoteObject { return Boolean(value) && typeof value === "object" && !Array.isArray(value); } export function firstString(source: RemoteObject, keys: string[], fallback = ""): string { for (const key of keys) { const value = source[key]; if (typeof value === "string" && value.trim()) { return value; } if (typeof value === "number") { return String(value); } } return fallback; } export function findStringDeep(value: unknown, keys: string[], depth = 0): string { if (depth > 3) { return ""; } if (typeof value === "string") { return value; } if (!isObjectRecord(value)) { return ""; } for (const key of keys) { const direct = value[key]; if (typeof direct === "string" && direct.trim()) { return direct; } if (isObjectRecord(direct)) { const nested = findStringDeep(direct, keys, depth + 1); if (nested) { return nested; } } } for (const nestedValue of Object.values(value)) { if (Array.isArray(nestedValue)) { continue; } const nested = findStringDeep(nestedValue, keys, depth + 1); if (nested) { return nested; } } return ""; } export function extractObjectPath(value: unknown): string { if (typeof value === "string") { return value; } return findStringDeep(value, [ "objectPath", "ObjectPath", "path", "Path", "actorPath", "ActorPath", "softObjectPath", "SoftObjectPath", "name", "Name", ]); } export function nestedString(source: RemoteObject, keys: string[], fallback = ""): string { for (const key of keys) { const value = source[key]; if (typeof value === "string" && value.trim()) { return value; } const nested = asRecord(value); const nestedValue = firstString(nested, ["Name", "name", "Path", "path", "ObjectPath", "objectPath"]); if (nestedValue) { return nestedValue; } } return fallback; } export function basename(path: string): string { const clean = path.replace(/["']/g, ""); const colonName = clean.split(":").pop() ?? clean; const dotName = colonName.split(".").pop() ?? colonName; const slashName = dotName.split("/").pop() ?? dotName; return slashName || clean || "Actor"; } export function cleanObjectName(name: string): string { return name .replace(/^Default__/, "") .replace(/^UEDPIE_\d+_/, "") .replace(/_\d+$/, (suffix) => (suffix === "_0" ? "_0" : suffix)); } export function deriveLevelNameFromPath(path: string): string { if (!path) { return ""; } const clean = path.replace(/["']/g, ""); const packagePath = clean.includes(":") ? clean.split(":")[0] : clean; const objectName = packagePath.split(".").pop() ?? packagePath; return cleanObjectName(basename(objectName)); } export function extractReturnValue(payload: unknown): unknown[] { if (Array.isArray(payload)) { return payload; } const record = asRecord(payload); const returnValue = record.ReturnValue ?? record.returnValue ?? record.Result ?? record.result; if (Array.isArray(returnValue)) { return returnValue; } const nested = asRecord(returnValue); for (const value of Object.values(nested)) { if (Array.isArray(value)) { return value; } } return []; } export function extractFirstReturnString(payload: unknown): string { const record = asRecord(payload); const returnValue = record.ReturnValue ?? record.returnValue ?? record.Result ?? record.result; if (typeof returnValue === "string") { return returnValue; } if (typeof returnValue === "number") { return String(returnValue); } return firstString(asRecord(returnValue), ["Name", "name", "Label", "label", "DisplayName", "displayName"]); }