Add robust dev fetch logging

Improve ApiDevTools to log fetch errors with stack traces during development, fix UUID generation fallback for environments lacking crypto.randomUUID, and ensure errors are surfaced in the browser console for easier debugging. Includes fallback generateUUID and preserved patching with proper catch blocks.

X-Lovable-Edit-ID: edt-83e14dbc-6e2d-4ff9-9d17-d881d62d7da6
This commit is contained in:
gpt-engineer-app[bot]
2026-01-11 06:16:04 +00:00
+37 -17
View File
@@ -46,6 +46,20 @@ function clearLogs() {
notifyListeners(); notifyListeners();
} }
// Fallback UUID generator for environments where crypto.randomUUID is unavailable
function generateUUID(): string {
try {
return crypto.randomUUID();
} catch {
// Fallback implementation
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
}
// Intercept fetch (dev only) // Intercept fetch (dev only)
const isDev = import.meta.env.DEV; const isDev = import.meta.env.DEV;
const originalFetch = window.fetch; const originalFetch = window.fetch;
@@ -55,23 +69,24 @@ const globalAny = window as unknown as { __gatehouseFetchPatched?: boolean };
if (isDev && !globalAny.__gatehouseFetchPatched) { if (isDev && !globalAny.__gatehouseFetchPatched) {
globalAny.__gatehouseFetchPatched = true; globalAny.__gatehouseFetchPatched = true;
window.fetch = async function (input, init) { try {
const url = window.fetch = async function (input, init) {
typeof input === "string" ? input : input instanceof URL ? input.href : input.url; const url =
typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
// Log calls that look like our backend API (support both absolute + relative base URLs) // Log calls that look like our backend API (support both absolute + relative base URLs)
const shouldLog = const shouldLog =
url.includes("/api/") || url.includes("/api/") ||
url.includes("/api/v1") || url.includes("/api/v1") ||
url.includes("/auth/") || url.includes("/auth/") ||
url.includes("/users/") || url.includes("/users/") ||
url.includes("/org/"); url.includes("/org/");
if (!shouldLog) { if (!shouldLog) {
return originalFetch.apply(this, [input, init]); return originalFetch.apply(this, [input, init]);
} }
const id = crypto.randomUUID(); const id = generateUUID();
const method = init?.method || "GET"; const method = init?.method || "GET";
let requestBody: unknown; let requestBody: unknown;
@@ -147,10 +162,15 @@ if (isDev && !globalAny.__gatehouseFetchPatched) {
}); });
throw err; throw err;
} }
}; };
} catch (patchError) {
// Log any errors during fetch patching with full stack trace
console.error("[Gatehouse DevTools] Failed to patch fetch:", patchError);
if (patchError instanceof Error) {
console.error("[Gatehouse DevTools] Stack trace:", patchError.stack);
}
}
} }
// isDev is already declared at module level for the fetch patch
export default function ApiDevTools() { export default function ApiDevTools() {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [logs, setLogs] = useState<ApiLog[]>([...apiLogs]); const [logs, setLogs] = useState<ApiLog[]>([...apiLogs]);