// This module is only meant to be used in Server Components in the app/ directory // It cannot be imported in Client Components or pages/ directory import { redirect } from 'next/navigation'; import { CustomerResponse, CustomerStats } from './api-client'; // Dynamically import cookies to prevent build errors let cookiesModule: any; try { // This will only work in server components cookiesModule = require('next/headers'); } catch (error) { console.warn('Warning: next/headers only works in Server Components in the app/ directory'); } /** * Constructs a server-side API URL for backend requests * Used in Server Components and API routes to directly access the backend API * * @param endpoint The API endpoint path * @returns A complete URL to the backend API */ function getServerApiUrl(endpoint: string): string { const apiUrl = process.env.SERVER_API_URL || 'https://internal-api.inboxi.ng/api'; const cleanEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint; return apiUrl.endsWith('/') ? `${apiUrl}${cleanEndpoint}` : `${apiUrl}/${cleanEndpoint}`; } /** * Server-side fetch wrapper with authentication. * Used in Server Components to make authenticated API requests to the backend. * This uses the SERVER_API_URL environment variable and is different from client-side fetching. * * @throws Error if used outside of a Server Component in the app/ directory */ export async function fetchServer( endpoint: string, options: RequestInit = {} ): Promise { // Check if we're in a server component context if (!cookiesModule?.cookies) { throw new Error( "fetchServer can only be used in Server Components in the app/ directory. " + "For client components, use clientFetch or fetchClient instead." ); } // Get auth token from cookies const cookieStore = await cookiesModule.cookies(); const authToken = cookieStore.get('Authorization')?.value; // Redirect to login if not authenticated if (!authToken) redirect('/login'); try { // Get the complete backend URL using the utility function const url = getServerApiUrl(endpoint); // Make the request with proper auth headers const res = await fetch(url, { ...options, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${authToken}`, ...options.headers, }, cache: 'no-store', // Always fetch fresh data }); // Handle auth failures if (res.status === 401) redirect('/login'); // Handle other errors if (!res.ok) { const errorData = await res.json().catch(() => ({})); const errorMessage = errorData.message || errorData.error || `Request failed: ${res.status} ${res.statusText}`; throw new Error(errorMessage); } // Handle 204 No Content responses if (res.status === 204) { return {} as T; } return await res.json(); } catch (error) { console.error(`Server request to ${endpoint} failed:`, error); throw error; } } // =========== SERVER API SERVICES =========== /** * Get a paginated list of customers (server-side) * @param page Page number (starting from 1) * @param limit Number of items per page * @returns Promise with customers data and total count */ export const getCustomersServer = async (page: number = 1, limit: number = 25): Promise => { return fetchServer(`/customers?page=${page}&limit=${limit}`); }; /** * Get detailed stats for a specific customer (server-side) * @param userId The customer's user ID * @returns Promise with detailed customer stats */ export const getCustomerDetailsServer = async (userId: string): Promise => { return fetchServer(`/customers/${userId}`); }; // Server-side platform stats function export async function getPlatformStatsServer(): Promise { try { return fetchServer('/stats/platform'); } catch (error) { console.error('Error fetching platform stats (server):', error); // Return default stats to prevent UI breakage return { totalProducts: 0, totalVendors: 0, totalOrders: 0, totalCustomers: 0, gmv: 0 }; } }