import "server-only"; export function normalizeFalCredentials(apiKey: string) { const normalized = String(apiKey || "") .replace(/\u00a0/g, " ") .replace(/\u3000/g, " ") .replace(/:/g, ":") .trim(); const stripped = normalized.replace(/^bearer\s+/i, "").replace(/^key\s+/i, ""); const kvMatch = stripped.match(/^(?:fal[_-]?key|api[_-]?key|token)\s*[::]\s*(.+)$/i); if (kvMatch?.[1]) { return kvMatch[1].trim(); } return stripped; } export function collectFalImageUrls(payload: any): string[] { const urls = new Set(); const isLikelyImageUrl = (value: string) => /^https?:\/\//i.test(value) && (/\.(png|jpg|jpeg|webp|gif)(\?|$)/i.test(value) || value.includes("image") || value.includes("img") || value.includes("fal.media")); const walk = (value: any, parentKey = "") => { if (typeof value === "string") { if (isLikelyImageUrl(value)) { urls.add(value); } return; } if (Array.isArray(value)) { for (const item of value) { walk(item, parentKey); } return; } if (value && typeof value === "object") { for (const [key, nestedValue] of Object.entries(value)) { if (key === "url" && typeof nestedValue === "string" && /^https?:\/\//i.test(nestedValue)) { if (/image|img|file|output|result|artifact/i.test(parentKey) || isLikelyImageUrl(nestedValue)) { urls.add(nestedValue); } } walk(nestedValue, key); } } }; walk(payload); return Array.from(urls); }