website refactor
This commit is contained in:
@@ -3,8 +3,6 @@
|
||||
*/
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { ApiError } from './ApiError';
|
||||
import { CircuitBreakerRegistry } from './RetryHandler';
|
||||
|
||||
export type ConnectionStatus = 'connected' | 'disconnected' | 'degraded' | 'checking';
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ export class BaseApiClient {
|
||||
/**
|
||||
* Get developer-friendly hint for troubleshooting
|
||||
*/
|
||||
private getDeveloperHint(error: Error, path: string, method: string): string {
|
||||
private getDeveloperHint(error: Error, _path: string, _method: string): string {
|
||||
if (error.message.includes('fetch failed') || error.message.includes('Failed to fetch')) {
|
||||
return 'Check if API server is running and CORS is configured correctly';
|
||||
}
|
||||
@@ -183,7 +183,7 @@ export class BaseApiClient {
|
||||
/**
|
||||
* Get troubleshooting context for network errors
|
||||
*/
|
||||
private getTroubleshootingContext(error: Error, path: string): string {
|
||||
private getTroubleshootingContext(error: Error, _path: string): string {
|
||||
if (typeof window !== 'undefined') {
|
||||
const baseUrl = this.baseUrl;
|
||||
const currentOrigin = window.location.origin;
|
||||
|
||||
@@ -37,7 +37,7 @@ export interface CacheEntry<T> {
|
||||
* Simple in-memory cache for API responses
|
||||
*/
|
||||
class ResponseCache {
|
||||
private cache = new Map<string, CacheEntry<any>>();
|
||||
private cache = new Map<string, CacheEntry<unknown>>();
|
||||
|
||||
/**
|
||||
* Get cached data if not expired
|
||||
@@ -46,20 +46,20 @@ class ResponseCache {
|
||||
const entry = this.cache.get(key);
|
||||
if (!entry) return null;
|
||||
|
||||
if (new Date() > entry.expiry) {
|
||||
if (new globalThis.Date() > entry.expiry) {
|
||||
this.cache.delete(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return entry.data;
|
||||
return entry.data as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cached data with expiry
|
||||
*/
|
||||
set<T>(key: string, data: T, ttlMs: number = 300000): void {
|
||||
const now = new Date();
|
||||
const expiry = new Date(now.getTime() + ttlMs);
|
||||
const now = new globalThis.Date();
|
||||
const expiry = new globalThis.Date(now.getTime() + ttlMs);
|
||||
|
||||
this.cache.set(key, {
|
||||
data,
|
||||
@@ -133,7 +133,7 @@ export async function withGracefulDegradation<T>(
|
||||
'API unavailable and no fallback provided',
|
||||
'NETWORK_ERROR',
|
||||
{
|
||||
timestamp: new Date().toISOString(),
|
||||
timestamp: new globalThis.Date().toISOString(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Retry logic and circuit breaker for API requests
|
||||
*/
|
||||
|
||||
import { ApiError, ApiErrorType } from './ApiError';
|
||||
import { ApiError } from './ApiError';
|
||||
|
||||
export interface RetryConfig {
|
||||
maxRetries: number;
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import { LeaguesApiClient } from './leagues/LeaguesApiClient';
|
||||
import { RacesApiClient } from './races/RacesApiClient';
|
||||
import { DriversApiClient } from './drivers/DriversApiClient';
|
||||
import { TeamsApiClient } from './teams/TeamsApiClient';
|
||||
import { SponsorsApiClient } from './sponsors/SponsorsApiClient';
|
||||
import { MediaApiClient } from './media/MediaApiClient';
|
||||
import { AnalyticsApiClient } from './analytics/AnalyticsApiClient';
|
||||
import { AuthApiClient } from './auth/AuthApiClient';
|
||||
import { PaymentsApiClient } from './payments/PaymentsApiClient';
|
||||
import { DashboardApiClient } from './dashboard/DashboardApiClient';
|
||||
import { PenaltiesApiClient } from './penalties/PenaltiesApiClient';
|
||||
import { ProtestsApiClient } from './protests/ProtestsApiClient';
|
||||
import { AdminApiClient } from './admin/AdminApiClient';
|
||||
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
|
||||
import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
|
||||
|
||||
/**
|
||||
* Main API Client
|
||||
*
|
||||
* Orchestrates all domain-specific API clients with consistent configuration.
|
||||
*/
|
||||
export class ApiClient {
|
||||
public readonly leagues: LeaguesApiClient;
|
||||
public readonly races: RacesApiClient;
|
||||
public readonly drivers: DriversApiClient;
|
||||
public readonly teams: TeamsApiClient;
|
||||
public readonly sponsors: SponsorsApiClient;
|
||||
public readonly media: MediaApiClient;
|
||||
public readonly analytics: AnalyticsApiClient;
|
||||
public readonly auth: AuthApiClient;
|
||||
public readonly payments: PaymentsApiClient;
|
||||
public readonly dashboard: DashboardApiClient;
|
||||
public readonly penalties: PenaltiesApiClient;
|
||||
public readonly protests: ProtestsApiClient;
|
||||
public readonly admin: AdminApiClient;
|
||||
|
||||
constructor(baseUrl: string) {
|
||||
const logger = new ConsoleLogger();
|
||||
const errorReporter = new EnhancedErrorReporter(logger, {
|
||||
showUserNotifications: true,
|
||||
logToConsole: true,
|
||||
reportToExternal: process.env.NODE_ENV === 'production',
|
||||
});
|
||||
|
||||
this.leagues = new LeaguesApiClient(baseUrl, errorReporter, logger);
|
||||
this.races = new RacesApiClient(baseUrl, errorReporter, logger);
|
||||
this.drivers = new DriversApiClient(baseUrl, errorReporter, logger);
|
||||
this.teams = new TeamsApiClient(baseUrl, errorReporter, logger);
|
||||
this.sponsors = new SponsorsApiClient(baseUrl, errorReporter, logger);
|
||||
this.media = new MediaApiClient(baseUrl, errorReporter, logger);
|
||||
this.analytics = new AnalyticsApiClient(baseUrl, errorReporter, logger);
|
||||
this.auth = new AuthApiClient(baseUrl, errorReporter, logger);
|
||||
this.payments = new PaymentsApiClient(baseUrl, errorReporter, logger);
|
||||
this.dashboard = new DashboardApiClient(baseUrl, errorReporter, logger);
|
||||
this.penalties = new PenaltiesApiClient(baseUrl, errorReporter, logger);
|
||||
this.protests = new ProtestsApiClient(baseUrl, errorReporter, logger);
|
||||
this.admin = new AdminApiClient(baseUrl, errorReporter, logger);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Singleton Instance
|
||||
// ============================================================================
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001';
|
||||
|
||||
export const api = new ApiClient(API_BASE_URL);
|
||||
@@ -134,7 +134,7 @@ export class LeaguesApiClient extends BaseApiClient {
|
||||
seasonId: string,
|
||||
input: CreateLeagueScheduleRaceInputDTO,
|
||||
): Promise<CreateLeagueScheduleRaceOutputDTO> {
|
||||
const { example: _example, ...payload } = input;
|
||||
const { example: _, ...payload } = input;
|
||||
return this.post<CreateLeagueScheduleRaceOutputDTO>(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races`, payload);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ export class LeaguesApiClient extends BaseApiClient {
|
||||
raceId: string,
|
||||
input: UpdateLeagueScheduleRaceInputDTO,
|
||||
): Promise<LeagueScheduleRaceMutationSuccessDTO> {
|
||||
const { example: _example, ...payload } = input;
|
||||
const { example: _, ...payload } = input;
|
||||
return this.patch<LeagueScheduleRaceMutationSuccessDTO>(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races/${raceId}`, payload);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ type UpdateMemberPaymentInputDto = {
|
||||
paidAt?: Date | string;
|
||||
};
|
||||
type UpdateMemberPaymentOutputDto = { payment: MemberPaymentDTO };
|
||||
type GetWalletTransactionsOutputDto = { transactions: TransactionDTO[] };
|
||||
type UpdatePaymentStatusOutputDto = { payment: PaymentDTO };
|
||||
type UpsertMembershipFeeInputDto = {
|
||||
leagueId: string;
|
||||
@@ -70,7 +69,6 @@ type AwardPrizeInputDto = {
|
||||
driverId: string;
|
||||
};
|
||||
type AwardPrizeOutputDto = { prize: PrizeDTO };
|
||||
type DeletePrizeInputDto = { prizeId: string };
|
||||
type DeletePrizeOutputDto = { success: boolean };
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,8 +12,6 @@ import type { RaceDetailEntryDTO } from '../../types/generated/RaceDetailEntryDT
|
||||
import type { RaceDetailRegistrationDTO } from '../../types/generated/RaceDetailRegistrationDTO';
|
||||
import type { RaceDetailUserResultDTO } from '../../types/generated/RaceDetailUserResultDTO';
|
||||
import type { FileProtestCommandDTO } from '../../types/generated/FileProtestCommandDTO';
|
||||
import type { AllRacesPageDTO } from '../../types/generated/AllRacesPageDTO';
|
||||
import type { FilteredRacesPageDataDTO } from '../../types/tbd/FilteredRacesPageDataDTO';
|
||||
|
||||
// Define missing types
|
||||
export type RacesPageDataDTO = { races: RacesPageDataRaceDTO[] };
|
||||
|
||||
@@ -66,22 +66,29 @@ export class SponsorsApiClient extends BaseApiClient {
|
||||
|
||||
/** Get sponsor billing information */
|
||||
getBilling(sponsorId: string): Promise<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
paymentMethods: any[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
invoices: any[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
stats: any;
|
||||
}> {
|
||||
return this.get(`/sponsors/billing/${sponsorId}`);
|
||||
}
|
||||
|
||||
/** Get available leagues for sponsorship */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getAvailableLeagues(): Promise<any[]> {
|
||||
return this.get('/sponsors/leagues/available');
|
||||
}
|
||||
|
||||
/** Get detailed league information */
|
||||
getLeagueDetail(leagueId: string): Promise<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
league: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
drivers: any[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
races: any[];
|
||||
}> {
|
||||
return this.get(`/sponsors/leagues/${leagueId}/detail`);
|
||||
@@ -89,14 +96,18 @@ export class SponsorsApiClient extends BaseApiClient {
|
||||
|
||||
/** Get sponsor settings */
|
||||
getSettings(sponsorId: string): Promise<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
profile: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
notifications: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
privacy: any;
|
||||
}> {
|
||||
return this.get(`/sponsors/settings/${sponsorId}`);
|
||||
}
|
||||
|
||||
/** Update sponsor settings */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
updateSettings(sponsorId: string, input: any): Promise<void> {
|
||||
return this.put(`/sponsors/settings/${sponsorId}`, input);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { LeagueMemberDTO } from '@/lib/types/generated/LeagueMemberDTO';
|
||||
import type { GetAllTeamsOutputDTO } from '@/lib/types/generated/GetAllTeamsOutputDTO';
|
||||
import type { GetTeamDetailsOutputDTO } from '@/lib/types/generated/GetTeamDetailsOutputDTO';
|
||||
import type { GetTeamMembersOutputDTO } from '@/lib/types/generated/GetTeamMembersOutputDTO';
|
||||
|
||||
Reference in New Issue
Block a user