barsa d6f7c50e7b Refactor Salesforce request handling and improve logging
- Moved metrics tracking and logging from the queueing phase to the execution phase in SalesforceRequestQueueService for better accuracy.
- Updated CSRF token generation in CsrfController to accept parameters in a more flexible manner.
- Enhanced CacheService to handle immediate expiry requests without leaking stale values.
- Improved error handling and re-authentication logic in SalesforceConnection for better resilience during session expiration.
- Refactored logout functionality in AuthFacade to handle optional userId and improve logging during token revocation.
- Updated AuthController to apply rate limit headers and improved type handling in various request contexts.
- Streamlined imports and improved overall code organization across multiple modules for better maintainability.
2025-11-05 15:47:06 +09:00

104 lines
3.3 KiB
TypeScript

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<void> {
// 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<string, unknown>) => ["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<string, unknown>) => ["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<string, unknown>) =>
["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;