import { version } from "../constants"; import { LdbClientV2 } from "./LdbClientV2"; import { LocationReferenceClientV2 } from "./LocationReferenceClientV2"; import { MiscClientV2 } from "./MiscClientV2"; import { PisClientV2 } from "./PisClientV2"; import { TrainClientV2 } from "./TrainClientV2"; import { UserClientV2 } from "./UserClientV2"; import { ApiError, NetworkError } from "../errors"; export class BaseOwlBoardClient { protected baseUrl: string; protected apiKey: string; protected headers: Record; constructor(baseUrl: string, apiKey: string) { this.baseUrl = baseUrl; this.apiKey = apiKey; this.headers = { "Content-Type": "application/json", "Accept": "application/json", "User-Agent": `OwlBoardTS/v${version}`, "uuid": this.apiKey, }; } async makeRequest(method: string, path: string, body?: any): Promise { const url = `${this.baseUrl}${path}`; const options: RequestInit = { method, headers: this.headers, body: body ? JSON.stringify(body) : undefined, }; let attempt = 0; const retries = 3; const delay = 500; const retryableStatusCodes = [408, 500, 502, 503, 504]; while (attempt < retries) { try { const response = await fetch(url, options); if (!response.ok) { const responseBody = await response.text(); const apiError = new ApiError("API Request Failed", response.status, responseBody); if (retryableStatusCodes.includes(response.status)) { attempt++; if (attempt >= retries) { // Max attempts reached throw apiError; } // Wait before retrying await new Promise(res => setTimeout(res, delay)); continue; // Retry } else { // Non-retryable status codes throw apiError; } } return (await response.json()) as T; } catch (error) { if (error instanceof TypeError) { // Indicates network errors with fetch if (attempt < retries) { attempt ++; await new Promise(res => setTimeout(res, delay)); continue; } // Throw network error if max tries reached handling TypeError throw new NetworkError("Network request failed"); }; throw error; // Rethrow any other error }; } // This code should never be reached. throw new Error("Unexpected error after multiple retries.") } } export class OwlBoardClientV2 extends BaseOwlBoardClient { pis: PisClientV2; train: TrainClientV2; user: UserClientV2; locationReference: LocationReferenceClientV2; misc: MiscClientV2; ldb: LdbClientV2; constructor(baseUrl: string, apiKey: string) { super(baseUrl, apiKey); this.pis = new PisClientV2(this); this.train = new TrainClientV2(this); this.user = new UserClientV2(this); this.locationReference = new LocationReferenceClientV2(this); this.misc = new MiscClientV2(this); this.ldb = new LdbClientV2(this); } }