export { createClient, resolveBaseUrl } from "./runtime/client"; export type { ApiClient, AuthHeaderResolver, CreateClientOptions, QueryParams, PathParams, } from "./runtime/client"; export { ApiError, isApiError } from "./runtime/client"; // Re-export API helpers export * from "./response-helpers"; // Import createClient for internal use import { createClient, ApiError } from "./runtime/client"; import { logger } from "@/lib/logger"; /** * Global error handler for API client * Handles authentication errors and triggers logout when needed */ async function handleApiError(response: Response): Promise { // Don't import useAuthStore at module level to avoid circular dependencies // We'll handle auth errors by dispatching a custom event that the auth system can listen to if (response.status === 401) { logger.warn("Received 401 Unauthorized response - triggering logout"); // Dispatch a custom event that the auth system will listen to if (typeof window !== "undefined") { window.dispatchEvent(new CustomEvent("auth:unauthorized", { detail: { url: response.url, status: response.status } })); } } // Still throw the error so the calling code can handle it let body: unknown; let message = response.statusText || `Request failed with status ${response.status}`; try { const cloned = response.clone(); const contentType = cloned.headers.get("content-type"); if (contentType?.includes("application/json")) { body = await cloned.json(); if (body && typeof body === "object" && "message" in body) { const maybeMessage = (body as { message?: unknown }).message; if (typeof maybeMessage === "string") { message = maybeMessage; } } } } catch { // Ignore body parse errors } throw new ApiError(message, response, body); } export const apiClient = createClient({ handleError: handleApiError, }); // Query keys for React Query - matching the expected structure export const queryKeys = { auth: { me: () => ["auth", "me"] as const, session: () => ["auth", "session"] as const, }, billing: { invoices: (params?: Record) => ["billing", "invoices", params] as const, invoice: (id: string) => ["billing", "invoice", id] as const, paymentMethods: () => ["billing", "payment-methods"] as const, }, subscriptions: { all: () => ["subscriptions"] as const, list: (params?: Record) => ["subscriptions", "list", params] as const, active: () => ["subscriptions", "active"] as const, stats: () => ["subscriptions", "stats"] as const, detail: (id: string) => ["subscriptions", "detail", id] as const, invoices: (id: number, params?: Record) => ["subscriptions", "invoices", id, params] as const, }, dashboard: { summary: () => ["dashboard", "summary"] as const, }, catalog: { products: () => ["catalog", "products"] as const, internet: { combined: () => ["catalog", "internet", "combined"] as const, }, sim: { combined: () => ["catalog", "sim", "combined"] as const, }, vpn: { combined: () => ["catalog", "vpn", "combined"] as const, }, }, orders: { list: () => ["orders", "list"] as const, detail: (id: string | number) => ["orders", "detail", String(id)] as const, }, } as const;