const MAX_RAW_LEN = 8000; export interface KavenegarNormalized { httpLikeStatus?: number; message?: string; raw: string; } export function safeJsonStringify(value: unknown): string { try { const s = JSON.stringify(value); return s.length > MAX_RAW_LEN ? `${s.slice(0, MAX_RAW_LEN)}...[truncated]` : s; } catch { return String(value); } } /** * Kavenegar REST responses use `{ return: { status, message }, ... }`. * Transport failures may yield non-JSON strings or malformed bodies. */ export function normalizeKavenegarBody(body: unknown): KavenegarNormalized { if (typeof body === "string") { try { return normalizeKavenegarBody(JSON.parse(body) as unknown); } catch { const raw = body.length > MAX_RAW_LEN ? `${body.slice(0, MAX_RAW_LEN)}...[truncated]` : body; return { raw }; } } let httpLikeStatus: number | undefined; let message: string | undefined; if (body && typeof body === "object" && !Array.isArray(body)) { const ret = (body as { return?: { status?: unknown; message?: unknown } }) .return; if (ret && typeof ret === "object") { if (typeof ret.status === "number" && Number.isFinite(ret.status)) { httpLikeStatus = ret.status; } if (typeof ret.message === "string") { message = ret.message; } } } return { httpLikeStatus, message, raw: safeJsonStringify(body), }; } /** Kavenegar uses `return.status === 200` for a successful API call. */ export function isKavenegarSuccess(body: unknown): boolean { return normalizeKavenegarBody(body).httpLikeStatus === 200; } /** The nest client sometimes rejects with a JSON string `{ "error": "..." }`. */ export function unwrapKavenegarTransportError(err: unknown): unknown { if (typeof err === "string") { try { return JSON.parse(err) as unknown; } catch { return { transportMessage: err }; } } if (err instanceof Error) { return { name: err.name, message: err.message }; } return err; }