From 479a36f1d0d9735c7b0ab354f587c03f4227e271 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Mon, 2 Feb 2026 13:42:20 +0100 Subject: [PATCH] feat: Improve CMS health check error reporting and limit connectivity notice display to developer and debug environments. --- components/CMSConnectivityNotice.tsx | 129 +++++++++++++++------------ lib/directus.ts | 36 ++++++-- 2 files changed, 98 insertions(+), 67 deletions(-) diff --git a/components/CMSConnectivityNotice.tsx b/components/CMSConnectivityNotice.tsx index 3272e799..63b7f592 100644 --- a/components/CMSConnectivityNotice.tsx +++ b/components/CMSConnectivityNotice.tsx @@ -4,69 +4,82 @@ import React, { useEffect, useState } from 'react'; import { AlertCircle, RefreshCw, Database } from 'lucide-react'; export default function CMSConnectivityNotice() { - const [status, setStatus] = useState<'checking' | 'ok' | 'error'>('checking'); - const [errorMsg, setErrorMsg] = useState(''); - const [isVisible, setIsVisible] = useState(false); + const [status, setStatus] = useState<'checking' | 'ok' | 'error'>('checking'); + const [errorMsg, setErrorMsg] = useState(''); + const [isVisible, setIsVisible] = useState(false); - useEffect(() => { - // Only show in development or if explicitly checking - const checkCMS = async () => { - try { - const response = await fetch('/api/health/cms'); - const data = await response.json(); + useEffect(() => { + // Only show if we've detected an issue AND we are in a context where we want to see it + const checkCMS = async () => { + const isDebug = new URLSearchParams(window.location.search).has('cms_debug'); + const isLocal = + window.location.hostname === 'localhost' || window.location.hostname.includes('127.0.0.1'); + const isStaging = + window.location.hostname.includes('staging') || + window.location.hostname.includes('testing'); - if (data.status !== 'ok') { - setStatus('error'); - setErrorMsg(data.message); - setIsVisible(true); - } else { - setStatus('ok'); - setIsVisible(false); - } - } catch (err) { - setStatus('error'); - setErrorMsg('Could not connect to CMS health endpoint'); - setIsVisible(true); - } - }; + // Only proceed with check if it's developer context + if (!isLocal && !isStaging && !isDebug) return; - checkCMS(); - }, []); + try { + const response = await fetch('/api/health/cms'); + const data = await response.json(); - if (!isVisible) return null; + if (data.status !== 'ok') { + setStatus('error'); + setErrorMsg(data.message); + setIsVisible(true); + } else { + setStatus('ok'); + setIsVisible(false); + } + } catch (err) { + // If it's a connection error, only show if we are really debugging + if (isDebug || isLocal) { + setStatus('error'); + setErrorMsg('Could not connect to CMS health endpoint'); + setIsVisible(true); + } + } + }; - return ( -
-
-
-
- -
-
-

CMS Issue Detected

-

- {errorMsg === 'relation "products" does not exist' - ? 'The database schema is missing. Please sync your local data to this environment.' - : errorMsg || 'The application cannot connect to the Directus CMS.'} -

-
- - -
-
-
+ checkCMS(); + }, []); + + if (!isVisible) return null; + + return ( +
+
+
+
+ +
+
+

CMS Issue Detected

+

+ {errorMsg === 'relation "products" does not exist' + ? 'The database schema is missing. Please sync your local data to this environment.' + : errorMsg || 'The application cannot connect to the Directus CMS.'} +

+
+ +
+
- ); +
+
+ ); } diff --git a/lib/directus.ts b/lib/directus.ts index f3058b3c..62a74c3f 100644 --- a/lib/directus.ts +++ b/lib/directus.ts @@ -93,31 +93,49 @@ export async function getProductBySlug(slug: string, locale: string = 'de') { export async function checkHealth() { try { - await ensureAuthenticated(); - - // 1. Basic connectivity check - await client.request(readCollections()); + // 1. Connectivity & Auth Check + try { + await ensureAuthenticated(); + await client.request(readCollections()); + } catch (e: any) { + console.error('Directus authentication failed during health check:', e); + return { + status: 'error', + message: + 'Authentication failed. Check your DIRECTUS_ADMIN_EMAIL and DIRECTUS_ADMIN_PASSWORD.', + code: 'AUTH_FAILED', + details: e.message, + }; + } // 2. Schema check (does the products table exist?) try { await client.request(readItems('products', { limit: 1 })); } catch (e: any) { - if (e.message?.includes('does not exist') || e.code === 'INVALID_PAYLOAD') { + if ( + e.message?.includes('does not exist') || + e.code === 'INVALID_PAYLOAD' || + e.status === 404 + ) { return { status: 'error', - message: 'The "products" collection is missing. Please sync your data.', + message: 'The "products" collection is missing or inaccessible. Please sync your data.', code: 'SCHEMA_MISSING', }; } - throw e; + return { + status: 'error', + message: `Schema error: ${e.message}`, + code: 'SCHEMA_ERROR', + }; } return { status: 'ok', message: 'Directus is reachable and responding.' }; } catch (error: any) { - console.error('Directus health check failed:', error); + console.error('Directus health check failed with unexpected error:', error); return { status: 'error', - message: error.message || 'Unknown error', + message: error.message || 'An unexpected error occurred while connecting to the CMS.', code: error.code || 'UNKNOWN', }; }