UNPKG

iracing-api

Version:

Javascript client for iracing API

95 lines (94 loc) 4.32 kB
import { API_URL } from '../consts'; import { logger } from '../logger'; import { RateLimiter } from '../rate-limiter'; import humps from 'humps'; const { camelizeKeys } = humps; /** * Base class for iRacing API endpoints. * Provides common functionality for making requests, handling rate limits, and processing responses. * @internal */ export class API { /** * Initializes the base API class. * @param fetchCookie - The fetch instance with cookie support. * @param options - Client configuration options. */ constructor(fetchCookie, options) { /** * Internal method to fetch data from a specified API endpoint. * Handles rate limiting, URL construction, and optionally fetching data from a returned link. * * @template Data - The expected type of the primary data payload. * @template Parameters - The type of the query parameters object. * @param endpoint - The specific API endpoint path (e.g., 'data/car/get'). * @param [params] - Optional query parameters for the request. * @param [getLinkData=true] - If true and the response contains a 'link', fetch data from that link. * @returns A promise resolving to the fetched data (type Data) or undefined if an error occurs or no data is found. * @internal */ this._getData = async (endpoint, params, getLinkData = true) => { try { const canProceed = this.rateLimiter.checkRateLimit(); if (!canProceed) { await this.rateLimiter.waitForReset(); } const parsedParams = `[${Object.entries(params !== null && params !== void 0 ? params : {}) .map(([key, value]) => `${key}=${value}`) .join(', ')}]`; logger(`Getting data from '${endpoint}'`, parsedParams); const url = this._getUrl(endpoint, params); const response = await this.fetchCookie(url, { cache: 'no-cache', credentials: 'include', }); this.rateLimiter.updateRateLimit(response); const data = await response.json(); if ((data === null || data === void 0 ? void 0 : data.link) && getLinkData) { return await this._getLinkData(data === null || data === void 0 ? void 0 : data.link); } return data; } catch (error) { logger(`Error getting data from '${endpoint}'`); return undefined; } }; /** * Internal method to fetch data from a secondary URL (often an S3 link) provided in an initial API response. * Converts keys in the fetched JSON data to camelCase. * * @template Data - The expected type of the data payload from the link. * @param link - The URL to fetch data from. * @returns A promise resolving to the fetched and camelCased data (type Data) or undefined if the link is invalid or fetching fails. * @internal */ this._getLinkData = async (link) => { if (!link) return undefined; const response = await fetch(link); const data = await response.json(); if (!data) return undefined; return camelizeKeys(data); }; /** * Internal method to construct the full API URL including the base path and query parameters. * * @template Parameters - The type of the query parameters object. * @param endpoint - The specific API endpoint path. * @param [params] - Optional query parameters. * @returns The fully constructed URL string. * @internal */ this._getUrl = (endpoint, params) => { // Filter out empty values const searchParams = params && new URLSearchParams(JSON.parse(JSON.stringify(params))).toString(); return `${API_URL}${endpoint}${searchParams ? `?${searchParams}` : ''}`; }; this.fetchCookie = fetchCookie; this.options = options; this.rateLimiter = new RateLimiter(options); } }