UNPKG

iracing-data-sdk

Version:

A comprehensive TypeScript SDK for the iRacing Data API with support for all documented endpoints

1,261 lines (1,257 loc) 60.2 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { ApiEndpoints: () => ApiEndpoints, AuthRequestSchema: () => AuthRequestSchema, AuthResponseSchema: () => AuthResponseSchema, EventLogParamsSchema: () => EventLogParamsSchema, HostedCombinedSessionsParamsSchema: () => HostedCombinedSessionsParamsSchema, LapChartDataParamsSchema: () => LapChartDataParamsSchema, LapDataParamsSchema: () => LapDataParamsSchema, LeagueCustLeagueSessionsParamsSchema: () => LeagueCustLeagueSessionsParamsSchema, LeagueDirectoryParamsSchema: () => LeagueDirectoryParamsSchema, LeagueGetParamsSchema: () => LeagueGetParamsSchema, LeagueMembershipParamsSchema: () => LeagueMembershipParamsSchema, LeaguePointsSystemsParamsSchema: () => LeaguePointsSystemsParamsSchema, LeagueRosterParamsSchema: () => LeagueRosterParamsSchema, LeagueSeasonSessionsParamsSchema: () => LeagueSeasonSessionsParamsSchema, LeagueSeasonStandingsParamsSchema: () => LeagueSeasonStandingsParamsSchema, LeagueSeasonsParamsSchema: () => LeagueSeasonsParamsSchema, LookupDriversParamsSchema: () => LookupDriversParamsSchema, MemberAwardInstancesParamsSchema: () => MemberAwardInstancesParamsSchema, MemberAwardsParamsSchema: () => MemberAwardsParamsSchema, MemberChartDataParamsSchema: () => MemberChartDataParamsSchema, MemberGetParamsSchema: () => MemberGetParamsSchema, MemberProfileParamsSchema: () => MemberProfileParamsSchema, ResultsGetParamsSchema: () => ResultsGetParamsSchema, ResultsSearchHostedParamsSchema: () => ResultsSearchHostedParamsSchema, ResultsSearchSeriesParamsSchema: () => ResultsSearchSeriesParamsSchema, SeasonListParamsSchema: () => SeasonListParamsSchema, SeasonRaceGuideParamsSchema: () => SeasonRaceGuideParamsSchema, SeasonResultsParamsSchema: () => SeasonResultsParamsSchema, SeasonSpectatorSubsessionIdsDetailParamsSchema: () => SeasonSpectatorSubsessionIdsDetailParamsSchema, SeasonSpectatorSubsessionIdsParamsSchema: () => SeasonSpectatorSubsessionIdsParamsSchema, SeriesPastSeasonsParamsSchema: () => SeriesPastSeasonsParamsSchema, SeriesSeasonListParamsSchema: () => SeriesSeasonListParamsSchema, SeriesSeasonScheduleParamsSchema: () => SeriesSeasonScheduleParamsSchema, SeriesSeasonsParamsSchema: () => SeriesSeasonsParamsSchema, StatsMemberBestsParamsSchema: () => StatsMemberBestsParamsSchema, StatsMemberCareerParamsSchema: () => StatsMemberCareerParamsSchema, StatsMemberDivisionParamsSchema: () => StatsMemberDivisionParamsSchema, StatsMemberRecapParamsSchema: () => StatsMemberRecapParamsSchema, StatsMemberRecentRacesParamsSchema: () => StatsMemberRecentRacesParamsSchema, StatsMemberSummaryParamsSchema: () => StatsMemberSummaryParamsSchema, StatsMemberYearlyParamsSchema: () => StatsMemberYearlyParamsSchema, StatsSeasonDriverStandingsParamsSchema: () => StatsSeasonDriverStandingsParamsSchema, StatsSeasonQualifyResultsParamsSchema: () => StatsSeasonQualifyResultsParamsSchema, StatsSeasonSupersessionStandingsParamsSchema: () => StatsSeasonSupersessionStandingsParamsSchema, StatsSeasonTTResultsParamsSchema: () => StatsSeasonTTResultsParamsSchema, StatsSeasonTTStandingsParamsSchema: () => StatsSeasonTTStandingsParamsSchema, StatsSeasonTeamStandingsParamsSchema: () => StatsSeasonTeamStandingsParamsSchema, StatsWorldRecordsParamsSchema: () => StatsWorldRecordsParamsSchema, TeamGetParamsSchema: () => TeamGetParamsSchema, TimeAttackMemberSeasonResultsParamsSchema: () => TimeAttackMemberSeasonResultsParamsSchema, default: () => iRacingSDK, iRacingSDK: () => iRacingSDK }); module.exports = __toCommonJS(src_exports); // src/types.ts var import_zod = require("zod"); var AuthRequestSchema = import_zod.z.object({ email: import_zod.z.string().email(), password: import_zod.z.string() }); var AuthResponseSchema = import_zod.z.object({ authcode: import_zod.z.string(), ssoCookieValue: import_zod.z.string(), custId: import_zod.z.number(), email: import_zod.z.string().email() }); var HostedCombinedSessionsParamsSchema = import_zod.z.object({ package_id: import_zod.z.number().optional() }); var LeagueCustLeagueSessionsParamsSchema = import_zod.z.object({ mine: import_zod.z.boolean().optional(), package_id: import_zod.z.number().optional() }); var LeagueDirectoryParamsSchema = import_zod.z.object({ search: import_zod.z.string().optional(), tag: import_zod.z.string().optional(), restrict_to_member: import_zod.z.boolean().optional(), restrict_to_recruiting: import_zod.z.boolean().optional(), restrict_to_friends: import_zod.z.boolean().optional(), restrict_to_watched: import_zod.z.boolean().optional(), minimum_roster_count: import_zod.z.number().optional(), maximum_roster_count: import_zod.z.number().optional(), lowerbound: import_zod.z.number().optional(), upperbound: import_zod.z.number().optional(), sort: import_zod.z.string().optional(), order: import_zod.z.string().optional() }); var LeagueGetParamsSchema = import_zod.z.object({ league_id: import_zod.z.number(), include_licenses: import_zod.z.boolean().optional() }); var LeaguePointsSystemsParamsSchema = import_zod.z.object({ league_id: import_zod.z.number(), season_id: import_zod.z.number().optional() }); var LeagueMembershipParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional(), include_league: import_zod.z.boolean().optional() }); var LeagueRosterParamsSchema = import_zod.z.object({ league_id: import_zod.z.number(), include_licenses: import_zod.z.boolean().optional() }); var LeagueSeasonsParamsSchema = import_zod.z.object({ league_id: import_zod.z.number(), retired: import_zod.z.boolean().optional() }); var LeagueSeasonStandingsParamsSchema = import_zod.z.object({ league_id: import_zod.z.number(), season_id: import_zod.z.number(), car_class_id: import_zod.z.number().optional(), car_id: import_zod.z.number().optional() }); var LeagueSeasonSessionsParamsSchema = import_zod.z.object({ league_id: import_zod.z.number(), season_id: import_zod.z.number(), results_only: import_zod.z.boolean().optional() }); var LookupDriversParamsSchema = import_zod.z.object({ search_term: import_zod.z.string(), league_id: import_zod.z.number().optional() }); var MemberGetParamsSchema = import_zod.z.object({ cust_ids: import_zod.z.array(import_zod.z.number()).transform((arr) => arr.join(",")), include_licenses: import_zod.z.boolean().optional() }); var MemberAwardsParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional() }); var MemberAwardInstancesParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional(), award_id: import_zod.z.number() }); var MemberChartDataParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional(), category_id: import_zod.z.number(), chart_type: import_zod.z.number() }); var MemberProfileParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional() }); var ResultsGetParamsSchema = import_zod.z.object({ subsession_id: import_zod.z.number(), include_licenses: import_zod.z.boolean().optional() }); var EventLogParamsSchema = import_zod.z.object({ subsession_id: import_zod.z.number(), simsession_number: import_zod.z.number() }); var LapChartDataParamsSchema = import_zod.z.object({ subsession_id: import_zod.z.number(), simsession_number: import_zod.z.number() }); var LapDataParamsSchema = import_zod.z.object({ subsession_id: import_zod.z.number(), simsession_number: import_zod.z.number(), cust_id: import_zod.z.number().optional(), team_id: import_zod.z.number().optional() }); var ResultsSearchHostedParamsSchema = import_zod.z.object({ start_range_begin: import_zod.z.string().optional(), start_range_end: import_zod.z.string().optional(), finish_range_begin: import_zod.z.string().optional(), finish_range_end: import_zod.z.string().optional(), cust_id: import_zod.z.number().optional(), team_id: import_zod.z.number().optional(), host_cust_id: import_zod.z.number().optional(), session_name: import_zod.z.string().optional(), league_id: import_zod.z.number().optional(), league_season_id: import_zod.z.number().optional(), car_id: import_zod.z.number().optional(), track_id: import_zod.z.number().optional(), category_ids: import_zod.z.array(import_zod.z.number()).transform((arr) => arr.join(",")).optional() }); var ResultsSearchSeriesParamsSchema = import_zod.z.object({ season_year: import_zod.z.number().optional(), season_quarter: import_zod.z.number().optional(), start_range_begin: import_zod.z.string().optional(), start_range_end: import_zod.z.string().optional(), finish_range_begin: import_zod.z.string().optional(), finish_range_end: import_zod.z.string().optional(), cust_id: import_zod.z.number().optional(), team_id: import_zod.z.number().optional(), series_id: import_zod.z.number().optional(), race_week_num: import_zod.z.number().optional(), official_only: import_zod.z.boolean().optional(), event_types: import_zod.z.array(import_zod.z.number()).transform((arr) => arr.join(",")).optional(), category_ids: import_zod.z.array(import_zod.z.number()).transform((arr) => arr.join(",")).optional() }); var SeasonResultsParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), event_type: import_zod.z.number().optional(), race_week_num: import_zod.z.number().optional() }); var SeasonListParamsSchema = import_zod.z.object({ season_year: import_zod.z.number(), season_quarter: import_zod.z.number() }); var SeasonRaceGuideParamsSchema = import_zod.z.object({ from: import_zod.z.string().optional(), include_end_after_from: import_zod.z.boolean().optional() }); var SeasonSpectatorSubsessionIdsParamsSchema = import_zod.z.object({ event_types: import_zod.z.array(import_zod.z.number()).transform((arr) => arr.join(",")).optional() }); var SeasonSpectatorSubsessionIdsDetailParamsSchema = import_zod.z.object({ event_types: import_zod.z.array(import_zod.z.number()).transform((arr) => arr.join(",")).optional(), season_ids: import_zod.z.array(import_zod.z.number()).transform((arr) => arr.join(",")).optional() }); var SeriesPastSeasonsParamsSchema = import_zod.z.object({ series_id: import_zod.z.number() }); var SeriesSeasonsParamsSchema = import_zod.z.object({ include_series: import_zod.z.boolean().optional(), season_year: import_zod.z.number().optional(), season_quarter: import_zod.z.number().optional() }); var SeriesSeasonListParamsSchema = import_zod.z.object({ include_series: import_zod.z.boolean().optional(), season_year: import_zod.z.number().optional(), season_quarter: import_zod.z.number().optional() }); var SeriesSeasonScheduleParamsSchema = import_zod.z.object({ season_id: import_zod.z.number() }); var StatsMemberBestsParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional(), car_id: import_zod.z.number().optional() }); var StatsMemberCareerParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional() }); var StatsMemberDivisionParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), event_type: import_zod.z.number() }); var StatsMemberRecapParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional(), year: import_zod.z.number().optional(), season: import_zod.z.number().optional() }); var StatsMemberRecentRacesParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional() }); var StatsMemberSummaryParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional() }); var StatsMemberYearlyParamsSchema = import_zod.z.object({ cust_id: import_zod.z.number().optional() }); var StatsSeasonDriverStandingsParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), car_class_id: import_zod.z.number(), division: import_zod.z.number().optional(), race_week_num: import_zod.z.number().optional() }); var StatsSeasonSupersessionStandingsParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), car_class_id: import_zod.z.number(), division: import_zod.z.number().optional(), race_week_num: import_zod.z.number().optional() }); var StatsSeasonTeamStandingsParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), car_class_id: import_zod.z.number(), race_week_num: import_zod.z.number().optional() }); var StatsSeasonTTStandingsParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), car_class_id: import_zod.z.number(), division: import_zod.z.number().optional(), race_week_num: import_zod.z.number().optional() }); var StatsSeasonTTResultsParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), car_class_id: import_zod.z.number(), race_week_num: import_zod.z.number(), division: import_zod.z.number().optional() }); var StatsSeasonQualifyResultsParamsSchema = import_zod.z.object({ season_id: import_zod.z.number(), car_class_id: import_zod.z.number(), race_week_num: import_zod.z.number(), division: import_zod.z.number().optional() }); var StatsWorldRecordsParamsSchema = import_zod.z.object({ car_id: import_zod.z.number(), track_id: import_zod.z.number(), season_year: import_zod.z.number().optional(), season_quarter: import_zod.z.number().optional() }); var TeamGetParamsSchema = import_zod.z.object({ team_id: import_zod.z.number(), include_licenses: import_zod.z.boolean().optional() }); var TimeAttackMemberSeasonResultsParamsSchema = import_zod.z.object({ ta_comp_season_id: import_zod.z.number() }); // src/endpoints.ts var ApiEndpoints = /* @__PURE__ */ ((ApiEndpoints2) => { ApiEndpoints2["AUTH"] = "/auth"; ApiEndpoints2["CAR_ASSETS"] = "/data/car/assets"; ApiEndpoints2["CAR_GET"] = "/data/car/get"; ApiEndpoints2["CARCLASS_GET"] = "/data/carclass/get"; ApiEndpoints2["CONSTANTS_CATEGORIES"] = "/data/constants/categories"; ApiEndpoints2["CONSTANTS_DIVISIONS"] = "/data/constants/divisions"; ApiEndpoints2["CONSTANTS_EVENT_TYPES"] = "/data/constants/event_types"; ApiEndpoints2["DRIVER_STATS_OVAL"] = "/data/driver_stats_by_category/oval"; ApiEndpoints2["DRIVER_STATS_SPORTS_CAR"] = "/data/driver_stats_by_category/sports_car"; ApiEndpoints2["DRIVER_STATS_FORMULA_CAR"] = "/data/driver_stats_by_category/formula_car"; ApiEndpoints2["DRIVER_STATS_ROAD"] = "/data/driver_stats_by_category/road"; ApiEndpoints2["DRIVER_STATS_DIRT_OVAL"] = "/data/driver_stats_by_category/dirt_oval"; ApiEndpoints2["DRIVER_STATS_DIRT_ROAD"] = "/data/driver_stats_by_category/dirt_road"; ApiEndpoints2["HOSTED_COMBINED_SESSIONS"] = "/data/hosted/combined_sessions"; ApiEndpoints2["HOSTED_SESSIONS"] = "/data/hosted/sessions"; ApiEndpoints2["LEAGUE_CUST_LEAGUE_SESSIONS"] = "/data/league/cust_league_sessions"; ApiEndpoints2["LEAGUE_DIRECTORY"] = "/data/league/directory"; ApiEndpoints2["LEAGUE_GET"] = "/data/league/get"; ApiEndpoints2["LEAGUE_GET_POINTS_SYSTEMS"] = "/data/league/get_points_systems"; ApiEndpoints2["LEAGUE_MEMBERSHIP"] = "/data/league/membership"; ApiEndpoints2["LEAGUE_ROSTER"] = "/data/league/roster"; ApiEndpoints2["LEAGUE_SEASONS"] = "/data/league/seasons"; ApiEndpoints2["LEAGUE_SEASON_STANDINGS"] = "/data/league/season_standings"; ApiEndpoints2["LEAGUE_SEASON_SESSIONS"] = "/data/league/season_sessions"; ApiEndpoints2["LOOKUP_COUNTRIES"] = "/data/lookup/countries"; ApiEndpoints2["LOOKUP_DRIVERS"] = "/data/lookup/drivers"; ApiEndpoints2["LOOKUP_FLAIRS"] = "/data/lookup/flairs"; ApiEndpoints2["LOOKUP_GET"] = "/data/lookup/get"; ApiEndpoints2["LOOKUP_LICENSES"] = "/data/lookup/licenses"; ApiEndpoints2["MEMBER_AWARDS"] = "/data/member/awards"; ApiEndpoints2["MEMBER_AWARD_INSTANCES"] = "/data/member/award_instances"; ApiEndpoints2["MEMBER_CHART_DATA"] = "/data/member/chart_data"; ApiEndpoints2["MEMBER_GET"] = "/data/member/get"; ApiEndpoints2["MEMBER_INFO"] = "/data/member/info"; ApiEndpoints2["MEMBER_PARTICIPATION_CREDITS"] = "/data/member/participation_credits"; ApiEndpoints2["MEMBER_PROFILE"] = "/data/member/profile"; ApiEndpoints2["RESULTS_GET"] = "/data/results/get"; ApiEndpoints2["RESULTS_EVENT_LOG"] = "/data/results/event_log"; ApiEndpoints2["RESULTS_LAP_CHART_DATA"] = "/data/results/lap_chart_data"; ApiEndpoints2["RESULTS_LAP_DATA"] = "/data/results/lap_data"; ApiEndpoints2["RESULTS_SEARCH_HOSTED"] = "/data/results/search_hosted"; ApiEndpoints2["RESULTS_SEARCH_SERIES"] = "/data/results/search_series"; ApiEndpoints2["RESULTS_SEASON_RESULTS"] = "/data/results/season_results"; ApiEndpoints2["SEASON_LIST"] = "/data/season/list"; ApiEndpoints2["SEASON_RACE_GUIDE"] = "/data/season/race_guide"; ApiEndpoints2["SEASON_SPECTATOR_SUBSESSIONIDS"] = "/data/season/spectator_subsessionids"; ApiEndpoints2["SEASON_SPECTATOR_SUBSESSIONIDS_DETAIL"] = "/data/season/spectator_subsessionids_detail"; ApiEndpoints2["SERIES_ASSETS"] = "/data/series/assets"; ApiEndpoints2["SERIES_GET"] = "/data/series/get"; ApiEndpoints2["SERIES_PAST_SEASONS"] = "/data/series/past_seasons"; ApiEndpoints2["SERIES_SEASONS"] = "/data/series/seasons"; ApiEndpoints2["SERIES_SEASON_LIST"] = "/data/series/season_list"; ApiEndpoints2["SERIES_SEASON_SCHEDULE"] = "/data/series/season_schedule"; ApiEndpoints2["SERIES_STATS_SERIES"] = "/data/series/stats_series"; ApiEndpoints2["STATS_MEMBER_BESTS"] = "/data/stats/member_bests"; ApiEndpoints2["STATS_MEMBER_CAREER"] = "/data/stats/member_career"; ApiEndpoints2["STATS_MEMBER_DIVISION"] = "/data/stats/member_division"; ApiEndpoints2["STATS_MEMBER_RECAP"] = "/data/stats/member_recap"; ApiEndpoints2["STATS_MEMBER_RECENT_RACES"] = "/data/stats/member_recent_races"; ApiEndpoints2["STATS_MEMBER_SUMMARY"] = "/data/stats/member_summary"; ApiEndpoints2["STATS_MEMBER_YEARLY"] = "/data/stats/member_yearly"; ApiEndpoints2["STATS_SEASON_DRIVER_STANDINGS"] = "/data/stats/season_driver_standings"; ApiEndpoints2["STATS_SEASON_SUPERSESSION_STANDINGS"] = "/data/stats/season_supersession_standings"; ApiEndpoints2["STATS_SEASON_TEAM_STANDINGS"] = "/data/stats/season_team_standings"; ApiEndpoints2["STATS_SEASON_TT_STANDINGS"] = "/data/stats/season_tt_standings"; ApiEndpoints2["STATS_SEASON_TT_RESULTS"] = "/data/stats/season_tt_results"; ApiEndpoints2["STATS_SEASON_QUALIFY_RESULTS"] = "/data/stats/season_qualify_results"; ApiEndpoints2["STATS_WORLD_RECORDS"] = "/data/stats/world_records"; ApiEndpoints2["TEAM_GET"] = "/data/team/get"; ApiEndpoints2["TIME_ATTACK_MEMBER_SEASON_RESULTS"] = "/data/time_attack/member_season_results"; ApiEndpoints2["TRACK_ASSETS"] = "/data/track/assets"; ApiEndpoints2["TRACK_GET"] = "/data/track/get"; return ApiEndpoints2; })(ApiEndpoints || {}); // src/iracingApi.ts var import_node_fetch = __toESM(require("node-fetch")); var import_fetch_cookie = __toESM(require("fetch-cookie")); var import_tough_cookie = require("tough-cookie"); var iRacingSDK = class { /** * Creates a new iRacing SDK instance * * @param options - Configuration options for the SDK */ constructor(options = {}) { this.baseUrl = options.baseUrl || "https://members-ng.iracing.com"; this.cookieJar = new import_tough_cookie.CookieJar(); this.fetchImpl = options.fetchImpl || (0, import_fetch_cookie.default)(import_node_fetch.default, this.cookieJar); this.autoHandleChunkedResponses = options.autoHandleChunkedResponses !== false; } /** * Internal request helper that handles authentication, rate limiting, and error handling * * @param path - API endpoint path * @param options - Fetch options * @param query - Query parameters * @returns Promise resolving to the API response */ async request(path, options = {}, query) { let url = this.baseUrl + path; if (query && Object.keys(query).length > 0) { const params = new URLSearchParams(); for (const [key, value] of Object.entries(query)) { if (value !== void 0) params.append(key, String(value)); } url += `?${params.toString()}`; } console.log(`Requesting: ${url}`); let baseHeaders = { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" }; if (options.headers) { if (options.headers instanceof Headers) { options.headers.forEach((value, key) => { baseHeaders[key] = value; }); } else if (Array.isArray(options.headers)) { for (const [key, value] of options.headers) baseHeaders[key] = value; } else { baseHeaders = { ...baseHeaders, ...options.headers }; } } const res = await this.fetchImpl(url, { ...options, headers: baseHeaders, credentials: "include" }); const limit = res.headers.get("x-ratelimit-limit"); const remaining = res.headers.get("x-ratelimit-remaining"); const reset = res.headers.get("x-ratelimit-reset"); if (limit || remaining || reset) { console.log("[iRacing Rate Limit]", { limit, remaining, reset, resetDate: reset ? new Date(Number(reset) * 1e3).toISOString() : void 0 }); } if (remaining !== null && reset && Number(remaining) <= 1) { const now = Date.now(); const resetMs = Number(reset) * 1e3; const waitMs = resetMs - now; if (waitMs > 0) { console.warn(`[iRacingSDK] Rate limit reached. Waiting ${(waitMs / 1e3).toFixed(1)} seconds until reset...`); await new Promise((res2) => setTimeout(res2, waitMs)); } } if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`); return res.json(); } /** * Authenticate with iRacing and store session cookies * * @param req - Authentication request with email and password * @returns Promise resolving to authentication response */ async authenticate(req) { const parsed = AuthRequestSchema.safeParse(req); if (!parsed.success) throw parsed.error; const email = req.email.toLowerCase(); const passwordConcat = `${req.password}${email}`; let hashBase64; if (typeof window !== "undefined" && window.crypto && window.crypto.subtle) { const hashBuffer = await window.crypto.subtle.digest("SHA-256", new TextEncoder().encode(passwordConcat)); const hashArray = new Uint8Array(hashBuffer); const hashString = Array.from(hashArray).map((b) => String.fromCharCode(b)).join(""); hashBase64 = btoa(hashString); } else if (typeof global !== "undefined" && global.crypto && global.crypto.subtle) { const hashBuffer = await global.crypto.subtle.digest("SHA-256", new TextEncoder().encode(passwordConcat)); hashBase64 = Buffer.from(hashBuffer).toString("base64"); } else { const { createHash } = await import("crypto"); const hashBuffer = createHash("sha256").update(passwordConcat).digest(); hashBase64 = hashBuffer.toString("base64"); } const res = await this.fetchImpl(this.baseUrl + "/auth" /* AUTH */, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password: hashBase64 }), credentials: "include" }); if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`); const response = await res.json(); console.log("Authentication response:", JSON.stringify(response, null, 2)); if (response.ssoCookieValue) { this.ssoCookieValue = response.ssoCookieValue; if (response.authcode) { this.authcode = response.authcode; } } else { const setCookie = res.headers.get("set-cookie"); if (setCookie) { const match = setCookie.match(/irsso_membersv2=([^;]+)/); if (match) { this.ssoCookieValue = match[1]; } } if (response.authcode) { this.authcode = response.authcode; } } return response; } /** * Handle chunked responses by fetching data from S3 * * @param response - Response containing chunk_info * @returns Promise resolving to combined chunked data */ async handleChunkedResponse(response) { if (response.link && !response.chunk_info) { console.log(`[iRacingSDK] Processing direct link response: ${response.link}`); const linkResponse = await this.fetchImpl(response.link); if (!linkResponse.ok) { throw new Error(`Failed to fetch linked data: ${linkResponse.status}`); } const contentType = linkResponse.headers.get("content-type"); if (contentType && contentType.includes("text/csv")) { console.log(`[iRacingSDK] Processing CSV response`); const csvText = await linkResponse.text(); return csvText; } const linkData = await linkResponse.json(); console.log(`[iRacingSDK] Successfully fetched linked data`); return linkData; } if (response.data && response.data.chunk_info) { const nestedData = response.data; if (nestedData.chunk_info.num_chunks === 0 || nestedData.chunk_info.rows === 0) { console.log(`[iRacingSDK] No chunks needed (${nestedData.chunk_info.rows} rows)`); return nestedData; } if (nestedData.chunk_info.chunk_file_names && nestedData.chunk_info.chunk_file_names.length > 0) { console.log(`[iRacingSDK] Processing ${nestedData.chunk_info.num_chunks} chunks from nested response`); const chunks2 = []; for (const chunkFileName of nestedData.chunk_info.chunk_file_names) { const chunkUrl = `${nestedData.chunk_info.base_download_url}${chunkFileName}`; console.log(`[iRacingSDK] Fetching chunk: ${chunkUrl}`); const chunkResponse = await this.fetchImpl(chunkUrl); if (!chunkResponse.ok) { throw new Error(`Failed to fetch chunk: ${chunkResponse.status}`); } const chunkData = await chunkResponse.json(); chunks2.push(...chunkData); await new Promise((resolve) => setTimeout(resolve, 100)); } console.log(`[iRacingSDK] Combined ${chunks2.length} records from ${nestedData.chunk_info.num_chunks} chunks`); return { ...nestedData, data: chunks2, chunk_info: nestedData.chunk_info }; } return nestedData; } if (!response.chunk_info) { return response; } const chunkInfo = response.chunk_info; const chunks = []; console.log(`[iRacingSDK] Processing chunked response with ${chunkInfo.total_chunks} chunks`); if (chunkInfo.chunk_file_name && chunkInfo.total_chunks === 1) { const chunkUrl = `${chunkInfo.base_download_url}${chunkInfo.chunk_file_name}`; console.log(`[iRacingSDK] Fetching single chunk: ${chunkUrl}`); const chunkResponse = await this.fetchImpl(chunkUrl); if (!chunkResponse.ok) { throw new Error(`Failed to fetch chunk: ${chunkResponse.status}`); } const chunkData = await chunkResponse.json(); chunks.push(...chunkData); } else if (chunkInfo.chunk_file_names && chunkInfo.chunk_file_names.length > 0) { for (const chunkFileName of chunkInfo.chunk_file_names) { const chunkUrl = `${chunkInfo.base_download_url}${chunkFileName}`; console.log(`[iRacingSDK] Fetching chunk: ${chunkUrl}`); const chunkResponse = await this.fetchImpl(chunkUrl); if (!chunkResponse.ok) { throw new Error(`Failed to fetch chunk: ${chunkResponse.status}`); } const chunkData = await chunkResponse.json(); chunks.push(...chunkData); await new Promise((resolve) => setTimeout(resolve, 100)); } } else { for (let i = 0; i < chunkInfo.total_chunks; i++) { const chunkFileName = `${chunkInfo.chunk_file_name.replace(/\.\w+$/, "")}_${i}.json`; const chunkUrl = `${chunkInfo.base_download_url}${chunkFileName}`; console.log(`[iRacingSDK] Fetching chunk ${i + 1}/${chunkInfo.total_chunks}: ${chunkUrl}`); try { const chunkResponse = await this.fetchImpl(chunkUrl); if (!chunkResponse.ok) { console.warn(`[iRacingSDK] Failed to fetch chunk ${i}: ${chunkResponse.status}`); continue; } const chunkData = await chunkResponse.json(); chunks.push(...chunkData); await new Promise((resolve) => setTimeout(resolve, 100)); } catch (error) { console.warn(`[iRacingSDK] Error fetching chunk ${i}: ${error}`); } } } console.log(`[iRacingSDK] Combined ${chunks.length} records from ${chunkInfo.total_chunks} chunks`); return { ...response, data: chunks, chunk_info: chunkInfo }; } /** * Enhanced request method that handles both regular and chunked responses * * @param path - API endpoint path * @param options - Fetch options * @param query - Query parameters * @param handleChunks - Whether to automatically handle chunked responses * @returns Promise resolving to the API response */ async requestWithChunking(path, options = {}, query, handleChunks) { const response = await this.request(path, options, query); const shouldHandleChunks = handleChunks !== void 0 ? handleChunks : this.autoHandleChunkedResponses; if (shouldHandleChunks && (response.chunk_info || response.link)) { return this.handleChunkedResponse(response); } return response; } // === Car Data === /** * Get car assets including images and logos * Image paths are relative to https://images-static.iracing.com/ * * @returns Promise resolving to car assets data */ async getCarAssets() { return this.requestWithChunking("/data/car/assets" /* CAR_ASSETS */); } /** * Get all available cars * * @returns Promise resolving to car data */ async getCars() { return this.requestWithChunking("/data/car/get" /* CAR_GET */); } // === Car Class Data === /** * Get all car classes * * @returns Promise resolving to car class data */ async getCarClasses() { return this.requestWithChunking("/data/carclass/get" /* CARCLASS_GET */); } // === Constants === /** * Get track categories (constant data) * * @returns Promise resolving to category data */ async getCategories() { return this.request("/data/constants/categories" /* CONSTANTS_CATEGORIES */); } /** * Get divisions (constant data) * * @returns Promise resolving to division data */ async getDivisions() { return this.request("/data/constants/divisions" /* CONSTANTS_DIVISIONS */); } /** * Get event types (constant data) * * @returns Promise resolving to event type data */ async getEventTypes() { return this.request("/data/constants/event_types" /* CONSTANTS_EVENT_TYPES */); } // === Driver Stats by Category === /** * Get driver stats for oval category * * @returns Promise resolving to oval driver stats */ async getDriverStatsOval() { return this.requestWithChunking("/data/driver_stats_by_category/oval" /* DRIVER_STATS_OVAL */); } /** * Get driver stats for sports car category * * @returns Promise resolving to sports car driver stats */ async getDriverStatsSportsCar() { return this.requestWithChunking("/data/driver_stats_by_category/sports_car" /* DRIVER_STATS_SPORTS_CAR */); } /** * Get driver stats for formula car category * * @returns Promise resolving to formula car driver stats */ async getDriverStatsFormulaCar() { return this.requestWithChunking("/data/driver_stats_by_category/formula_car" /* DRIVER_STATS_FORMULA_CAR */); } /** * Get driver stats for road category * * @returns Promise resolving to road driver stats */ async getDriverStatsRoad() { return this.requestWithChunking("/data/driver_stats_by_category/road" /* DRIVER_STATS_ROAD */); } /** * Get driver stats for dirt oval category * * @returns Promise resolving to dirt oval driver stats */ async getDriverStatsDirtOval() { return this.requestWithChunking("/data/driver_stats_by_category/dirt_oval" /* DRIVER_STATS_DIRT_OVAL */); } /** * Get driver stats for dirt road category * * @returns Promise resolving to dirt road driver stats */ async getDriverStatsDirtRoad() { return this.requestWithChunking("/data/driver_stats_by_category/dirt_road" /* DRIVER_STATS_DIRT_ROAD */); } // === Hosted Sessions === /** * Get hosted sessions that can be joined as driver or spectator * Also includes non-league pending sessions for the user * * @param params - Optional parameters to filter sessions * @returns Promise resolving to hosted session data */ async getHostedCombinedSessions(params) { if (params) { const parsed = HostedCombinedSessionsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.requestWithChunking("/data/hosted/combined_sessions" /* HOSTED_COMBINED_SESSIONS */, {}, params); } /** * Get hosted sessions that can be joined as driver * Without spectator and non-league pending sessions * * @returns Promise resolving to hosted session data */ async getHostedSessions() { return this.requestWithChunking("/data/hosted/sessions" /* HOSTED_SESSIONS */); } // === League Data === /** * Get customer league sessions * * @param params - Optional parameters to filter sessions * @returns Promise resolving to league session data */ async getLeagueCustSessions(params) { if (params) { const parsed = LeagueCustLeagueSessionsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.request("/data/league/cust_league_sessions" /* LEAGUE_CUST_LEAGUE_SESSIONS */, {}, params); } /** * Search league directory * * @param params - Optional search parameters * @returns Promise resolving to league directory data */ async getLeagueDirectory(params) { if (params) { const parsed = LeagueDirectoryParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.requestWithChunking("/data/league/directory" /* LEAGUE_DIRECTORY */, {}, params); } /** * Get league information * * @param params - League parameters including league ID * @returns Promise resolving to league data */ async getLeague(params) { const parsed = LeagueGetParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/league/get" /* LEAGUE_GET */, {}, params); } /** * Get league points systems * * @param params - Parameters including league ID * @returns Promise resolving to points system data */ async getLeaguePointsSystems(params) { const parsed = LeaguePointsSystemsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/league/get_points_systems" /* LEAGUE_GET_POINTS_SYSTEMS */, {}, params); } /** * Get league membership information * * @param params - Optional membership parameters * @returns Promise resolving to membership data */ async getLeagueMembership(params) { if (params) { const parsed = LeagueMembershipParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.request("/data/league/membership" /* LEAGUE_MEMBERSHIP */, {}, params); } /** * Get league roster * * @param params - Parameters including league ID * @returns Promise resolving to roster data */ async getLeagueRoster(params) { const parsed = LeagueRosterParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/league/roster" /* LEAGUE_ROSTER */, {}, params); } /** * Get league seasons * * @param params - Parameters including league ID * @returns Promise resolving to season data */ async getLeagueSeasons(params) { const parsed = LeagueSeasonsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/league/seasons" /* LEAGUE_SEASONS */, {}, params); } /** * Get league season standings * * @param params - Parameters including league and season IDs * @returns Promise resolving to standings data */ async getLeagueSeasonStandings(params) { const parsed = LeagueSeasonStandingsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.requestWithChunking("/data/league/season_standings" /* LEAGUE_SEASON_STANDINGS */, {}, params); } /** * Get league season sessions * * @param params - Parameters including league and season IDs * @returns Promise resolving to session data */ async getLeagueSeasonSessions(params) { const parsed = LeagueSeasonSessionsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/league/season_sessions" /* LEAGUE_SEASON_SESSIONS */, {}, params); } // === Lookup Data === /** * Get countries lookup data * * @returns Promise resolving to country data */ async getLookupCountries() { return this.requestWithChunking("/data/lookup/countries" /* LOOKUP_COUNTRIES */); } /** * Search for drivers * * @param params - Search parameters including search term * @returns Promise resolving to driver search results */ async getLookupDrivers(params) { const parsed = LookupDriversParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.requestWithChunking("/data/lookup/drivers" /* LOOKUP_DRIVERS */, {}, params); } /** * Get flairs lookup data * Icons are from https://github.com/lipis/flag-icons/ * * @returns Promise resolving to flair data */ async getLookupFlairs() { return this.requestWithChunking("/data/lookup/flairs" /* LOOKUP_FLAIRS */); } /** * Get general lookup data * * @returns Promise resolving to lookup data */ async getLookupGet() { return this.requestWithChunking("/data/lookup/get" /* LOOKUP_GET */); } /** * Get licenses lookup data * * @returns Promise resolving to license data */ async getLookupLicenses() { return this.requestWithChunking("/data/lookup/licenses" /* LOOKUP_LICENSES */); } // === Member Data === /** * Get member awards * * @param params - Optional parameters including customer ID * @returns Promise resolving to award data */ async getMemberAwards(params) { if (params) { const parsed = MemberAwardsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.request("/data/member/awards" /* MEMBER_AWARDS */, {}, params); } /** * Get member award instances * * @param params - Parameters including award ID * @returns Promise resolving to award instance data */ async getMemberAwardInstances(params) { const parsed = MemberAwardInstancesParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/member/award_instances" /* MEMBER_AWARD_INSTANCES */, {}, params); } /** * Get member chart data * * @param params - Parameters including category and chart type * @returns Promise resolving to chart data */ async getMemberChartData(params) { const parsed = MemberChartDataParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/member/chart_data" /* MEMBER_CHART_DATA */, {}, params); } /** * Get member information by customer IDs * * @param params - Parameters including customer IDs * @returns Promise resolving to member data */ async getMembers(params) { const parsed = MemberGetParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.requestWithChunking("/data/member/get" /* MEMBER_GET */, {}, params); } /** * Get authenticated member information * * @returns Promise resolving to member info */ async getMemberInfo() { return this.requestWithChunking("/data/member/info" /* MEMBER_INFO */); } /** * Get member participation credits * * @returns Promise resolving to participation credit data */ async getMemberParticipationCredits() { return this.request("/data/member/participation_credits" /* MEMBER_PARTICIPATION_CREDITS */); } /** * Get member profile * * @param params - Optional parameters including customer ID * @returns Promise resolving to profile data */ async getMemberProfile(params) { if (params) { const parsed = MemberProfileParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.requestWithChunking("/data/member/profile" /* MEMBER_PROFILE */, {}, params); } // === Results Data === /** * Get results for a subsession * * @param params - Parameters including subsession ID * @returns Promise resolving to result data */ async getResults(params) { const parsed = ResultsGetParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/results/get" /* RESULTS_GET */, {}, params); } /** * Get event log for a subsession * * @param params - Parameters including subsession and session number * @returns Promise resolving to event log data */ async getResultsEventLog(params) { const parsed = EventLogParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/results/event_log" /* RESULTS_EVENT_LOG */, {}, params); } /** * Get lap chart data for a subsession * * @param params - Parameters including subsession and session number * @returns Promise resolving to lap chart data */ async getResultsLapChartData(params) { const parsed = LapChartDataParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/results/lap_chart_data" /* RESULTS_LAP_CHART_DATA */, {}, params); } /** * Get lap data for a subsession * * @param params - Parameters including subsession and session number * @returns Promise resolving to lap data */ async getResultsLapData(params) { const parsed = LapDataParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/results/lap_data" /* RESULTS_LAP_DATA */, {}, params); } /** * Search hosted and league session results * Maximum time frame of 90 days * * @param params - Search parameters * @returns Promise resolving to hosted session results */ async getResultsSearchHosted(params) { const parsed = ResultsSearchHostedParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.requestWithChunking("/data/results/search_hosted" /* RESULTS_SEARCH_HOSTED */, {}, params); } /** * Search official series results * Maximum time frame of 90 days * * @param params - Search parameters * @returns Promise resolving to series results */ async getResultsSearchSeries(params) { const parsed = ResultsSearchSeriesParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.requestWithChunking("/data/results/search_series" /* RESULTS_SEARCH_SERIES */, {}, params); } /** * Get season results * * @param params - Parameters including season ID * @returns Promise resolving to season results */ async getResultsSeasonResults(params) { const parsed = SeasonResultsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.requestWithChunking("/data/results/season_results" /* RESULTS_SEASON_RESULTS */, {}, params); } // === Season Data === /** * Get season list * * @param params - Parameters including season year and quarter * @returns Promise resolving to season list */ async getSeasonList(params) { const parsed = SeasonListParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.requestWithChunking("/data/season/list" /* SEASON_LIST */, {}, params); } /** * Get season race guide * * @param params - Optional parameters for filtering * @returns Promise resolving to race guide data */ async getSeasonRaceGuide(params) { if (params) { const parsed = SeasonRaceGuideParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.requestWithChunking("/data/season/race_guide" /* SEASON_RACE_GUIDE */, {}, params); } /** * Get spectator subsession IDs * * @param params - Optional parameters for filtering * @returns Promise resolving to spectator subsession IDs */ async getSeasonSpectatorSubsessionIds(params) { if (params) { const parsed = SeasonSpectatorSubsessionIdsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.request("/data/season/spectator_subsessionids" /* SEASON_SPECTATOR_SUBSESSIONIDS */, {}, params); } /** * Get detailed spectator subsession information * * @param params - Optional parameters for filtering * @returns Promise resolving to detailed spectator subsession data */ async getSeasonSpectatorSubsessionIdsDetail(params) { if (params) { const parsed = SeasonSpectatorSubsessionIdsDetailParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.request("/data/season/spectator_subsessionids_detail" /* SEASON_SPECTATOR_SUBSESSIONIDS_DETAIL */, {}, params); } // === Series Data === /** * Get series assets including images and logos * Image paths are relative to https://images-static.iracing.com/ * * @returns Promise resolving to series assets */ async getSeriesAssets() { return this.requestWithChunking("/data/series/assets" /* SERIES_ASSETS */); } /** * Get all series * * @returns Promise resolving to series data */ async getSeries() { return this.requestWithChunking("/data/series/get" /* SERIES_GET */); } /** * Get all seasons for a series * Filter by official:true for seasons with standings * * @param params - Parameters including series ID * @returns Promise resolving to past seasons data */ async getSeriesPastSeasons(params) { const parsed = SeriesPastSeasonsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/series/past_seasons" /* SERIES_PAST_SEASONS */, {}, params); } /** * Get series seasons * * @param params - Optional parameters for filtering * @returns Promise resolving to series seasons */ async getSeriesSeasons(params) { if (params) { const parsed = SeriesSeasonsParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.requestWithChunking("/data/series/seasons" /* SERIES_SEASONS */, {}, params); } /** * Get series season list * * @param params - Optional parameters for filtering * @returns Promise resolving to series season list */ async getSeriesSeasonList(params) { if (params) { const parsed = SeriesSeasonListParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; } return this.requestWithChunking("/data/series/season_list" /* SERIES_SEASON_LIST */, {}, params); } /** * Get series season schedule * * @param params - Parameters including season ID * @returns Promise resolving to season schedule */ async getSeriesSeasonSchedule(params) { const parsed = SeriesSeasonScheduleParamsSchema.safeParse(params); if (!parsed.success) throw parsed.error; return this.request("/data/series/season_schedule" /* SERIES_SEASON_SCHEDULE */, {}, params); } /** * Get series stats * Filter by official:true for series with standings * * @returns Promise resolving to series stats */ async getSeriesStats() { return this.requestWithChunking("/data/series/stats_series" /* SERIES_STATS_SERIES */); } // === Stats Data === /** * Get member best times * * @para