├── docs
├── .gitignore
├── .vitepress
│ ├── cache
│ │ └── deps
│ │ │ ├── package.json
│ │ │ ├── vue.js.map
│ │ │ ├── _metadata.json
│ │ │ └── vue.js
│ ├── theme
│ │ ├── index.ts
│ │ └── style.css
│ └── config.mts
├── package.json
├── api
│ ├── car-class.md
│ ├── team.md
│ ├── car.md
│ ├── time-attack.md
│ ├── track.md
│ ├── how-to-use.md
│ ├── constants.md
│ ├── hosted.md
│ ├── lookup.md
│ ├── series.md
│ ├── season.md
│ ├── member.md
│ ├── results.md
│ ├── league.md
│ └── stats.md
├── index.md
└── getting-started.md
├── .gitignore
├── packages
└── iracing-api
│ ├── .gitignore
│ ├── .prettierrc
│ ├── src
│ ├── helpers.ts
│ ├── consts.ts
│ ├── types
│ │ ├── time-attack.ts
│ │ ├── constants.ts
│ │ ├── car-class.ts
│ │ ├── index.ts
│ │ ├── lookup.ts
│ │ ├── team.ts
│ │ ├── season.ts
│ │ ├── track.ts
│ │ ├── car.ts
│ │ ├── hosted.ts
│ │ ├── common.ts
│ │ ├── league.ts
│ │ ├── series.ts
│ │ ├── stats.ts
│ │ └── member.ts
│ ├── logger.ts
│ ├── api
│ │ ├── car-class.ts
│ │ ├── track.ts
│ │ ├── car.ts
│ │ ├── team.ts
│ │ ├── time-attack.ts
│ │ ├── constants.ts
│ │ ├── hosted.ts
│ │ ├── lookup.ts
│ │ ├── series.ts
│ │ ├── season.ts
│ │ ├── api.ts
│ │ ├── member.ts
│ │ ├── league.ts
│ │ ├── stats.ts
│ │ └── results.ts
│ ├── rate-limiter.ts
│ └── index.ts
│ ├── .eslintrc.json
│ ├── tsconfig.json
│ ├── package.json
│ └── README.md
├── pnpm-workspace.yaml
├── package.json
├── README.md
└── TODO.md
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | .vitepress/cache
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .idea
3 | .vscode
--------------------------------------------------------------------------------
/packages/iracing-api/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /lib
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/*'
3 | - 'docs'
--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/iracing-api/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 4,
4 | "semi": false,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/vue.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "sources": [],
4 | "sourcesContent": [],
5 | "mappings": "",
6 | "names": []
7 | }
8 |
--------------------------------------------------------------------------------
/packages/iracing-api/src/helpers.ts:
--------------------------------------------------------------------------------
1 | import CryptoJS from 'crypto-js'
2 |
3 | export const encryptPassword = (email: string, password: string) =>
4 | CryptoJS.enc.Base64.stringify(
5 | CryptoJS.SHA256(password + email.toLowerCase())
6 | )
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iracing-api-root",
3 | "private": true,
4 | "scripts": {
5 | "docs:dev": "pnpm --filter iracing-api-docs dev",
6 | "docs:build": "pnpm --filter iracing-api-docs build",
7 | "docs:serve": "pnpm --filter iracing-api-docs serve"
8 | }
9 | }
--------------------------------------------------------------------------------
/packages/iracing-api/src/consts.ts:
--------------------------------------------------------------------------------
1 | export const API_URL = 'https://members-ng.iracing.com/'
2 |
3 | export const DEFAULT_RATE_LIMIT_PADDING = 5
4 | export const DEFAULT_OPTIONS = {
5 | logger: false,
6 | manageRateLimit: false,
7 | rateLimitPadding: DEFAULT_RATE_LIMIT_PADDING,
8 | }
9 |
--------------------------------------------------------------------------------
/packages/iracing-api/src/types/time-attack.ts:
--------------------------------------------------------------------------------
1 | import { z } from 'zod'
2 |
3 | // Params
4 | //
5 | export const GetTimeAttackSeasonParamsSchema = z.object({
6 | seasonId: z.number(),
7 | })
8 | export type GetTimeAttackSeasonParams = z.infer<
9 | typeof GetTimeAttackSeasonParamsSchema
10 | >
11 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iracing-api-docs",
3 | "version": "1.0.0",
4 | "devDependencies": {
5 | "vitepress": "^1.0.2",
6 | "vue": "^3.4.21"
7 | },
8 | "scripts": {
9 | "dev": "vitepress dev",
10 | "build": "vitepress build",
11 | "preview": "vitepress preview"
12 | }
13 | }
--------------------------------------------------------------------------------
/docs/api/car-class.md:
--------------------------------------------------------------------------------
1 | # Car Class API
2 |
3 | All methods in the `Car Class` API are available through the `carClass` property of the `iRacingAPI` instance.
4 |
5 | ## Car Classes
6 |
7 | Get the car classes.
8 |
9 | ```ts
10 | const carClasses = await ir.carClass.getCarClasses();
11 | ```
12 | https://members-ng.iracing.com/data/carclass/get
--------------------------------------------------------------------------------
/packages/iracing-api/src/logger.ts:
--------------------------------------------------------------------------------
1 | import { Options } from './types'
2 |
3 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
4 | export let logger = (..._args: unknown[]) => {}
5 |
6 | export const createLogger = (options: Options) => {
7 | if (options.logger) {
8 | logger = (...args: unknown[]) =>
9 | console.log(`\x1b[34m[iracing-api]\x1b[0m`, ...args)
10 | } else {
11 | logger = () => {}
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.ts:
--------------------------------------------------------------------------------
1 | // https://vitepress.dev/guide/custom-theme
2 | import { h } from 'vue'
3 | import type { Theme } from 'vitepress'
4 | import DefaultTheme from 'vitepress/theme'
5 | import './style.css'
6 |
7 | export default {
8 | extends: DefaultTheme,
9 | Layout: () => {
10 | return h(DefaultTheme.Layout, null, {
11 | // https://vitepress.dev/guide/extending-default-theme#layout-slots
12 | })
13 | },
14 | enhanceApp({ app, router, siteData }) {
15 | // ...
16 | }
17 | } satisfies Theme
18 |
--------------------------------------------------------------------------------
/docs/api/team.md:
--------------------------------------------------------------------------------
1 | # Team API
2 |
3 | All methods in the `Team` API are available through the `team` property of the `iRacingAPI` instance.
4 |
5 | ## Data
6 |
7 | Get the team data.
8 |
9 | ```ts
10 | const teamData = await ir.team.getTeamData(params);
11 | ```
12 |
13 | Available parameters:
14 | * `teamId: number` - The team ID of the team to get the data for.
15 | * `includeMembers?: boolean` - Include the members in the data.
16 | * For faster responses, only request when necessary.
17 |
18 | https://members-ng.iracing.com/data/team/get
--------------------------------------------------------------------------------
/packages/iracing-api/src/api/car-class.ts:
--------------------------------------------------------------------------------
1 | import { CarClass } from '../types/car-class'
2 | import { API } from './api'
3 |
4 | /**
5 | * Provides methods for interacting with car class endpoints.
6 | */
7 | export class CarClassAPI extends API {
8 | /**
9 | * Get a list of all available car classes.
10 | *
11 | * @returns A promise resolving to an array of car class objects, or undefined on error.
12 | */
13 | getCarClasses = async () => {
14 | return await this._getData('data/carclass/get')
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docs/api/car.md:
--------------------------------------------------------------------------------
1 | # Car API
2 |
3 | All methods in the `Car` API are available through the `car` property of the `iRacingAPI` instance.
4 |
5 | ## Cars
6 |
7 | Get the cars.
8 |
9 | ```ts
10 | const cars = await ir.car.getCars();
11 | ```
12 | https://members-ng.iracing.com/data/car/get
13 |
14 | ## Car Assets
15 |
16 | Get the car assets.
17 |
18 | * Image paths are relative to https://images-static.iracing.com/
19 |
20 | ```ts
21 | const carAssets = await ir.car.getCarAssets();
22 | ```
23 | https://members-ng.iracing.com/data/car/assets
24 |
25 |
--------------------------------------------------------------------------------
/docs/api/time-attack.md:
--------------------------------------------------------------------------------
1 | # Time Attack API
2 |
3 | All methods in the `Time Attack` API are available through the `timeAttack` property of the `iRacingAPI` instance.
4 |
5 | ## Season Results
6 |
7 | Get the time attack season results.
8 |
9 | * Results for the authenticated member, if any.
10 |
11 | ```ts
12 | const seasonResults = await ir.timeAttack.getTimeAttackSeasonResults(params);
13 | ```
14 |
15 | Available parameters:
16 | * `seasonId: number` - The season ID to get the results for.
17 |
18 | https://members-ng.iracing.com/data/time_attack/member_season_results
--------------------------------------------------------------------------------
/docs/api/track.md:
--------------------------------------------------------------------------------
1 | # Track API
2 |
3 | All methods in the `Track` API are available through the `track` property of the `iRacingAPI` instance.
4 |
5 | ## Assets
6 |
7 | Get the track assets.
8 |
9 | * Image paths are relative to https://images-static.iracing.com/
10 |
11 | ```ts
12 | const trackAssets = await ir.track.getTrackAssets();
13 | ```
14 | https://members-ng.iracing.com/data/track/assets
15 |
16 | ## Tracks
17 |
18 | Get the tracks.
19 |
20 | ```ts
21 | const tracks = await ir.track.getTracks();
22 | ```
23 | https://members-ng.iracing.com/data/track/get
--------------------------------------------------------------------------------
/packages/iracing-api/src/types/constants.ts:
--------------------------------------------------------------------------------
1 | import * as z from 'zod'
2 |
3 | export const ConstantCategorySchema = z.object({
4 | label: z.string(),
5 | value: z.number(),
6 | })
7 | export type Category = z.infer
8 |
9 | export const DivisionSchema = z.object({
10 | label: z.string(),
11 | value: z.number(),
12 | })
13 | export type Division = z.infer
14 |
15 | export const EventSchema = z.object({
16 | label: z.string(),
17 | value: z.number(),
18 | })
19 | export type Event = z.infer
20 |
--------------------------------------------------------------------------------
/packages/iracing-api/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true
5 | },
6 | "extends": [
7 | "eslint:recommended",
8 | "plugin:@typescript-eslint/eslint-recommended",
9 | "plugin:@typescript-eslint/recommended"
10 | ],
11 | "parser": "@typescript-eslint/parser",
12 | "parserOptions": {
13 | "ecmaVersion": "latest",
14 | "sourceType": "module"
15 | },
16 | "plugins": ["@typescript-eslint"],
17 | "root": true,
18 | "rules": {
19 | "@typescript-eslint/no-explicit-any": "warn"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/iracing-api/src/types/car-class.ts:
--------------------------------------------------------------------------------
1 | import * as z from 'zod'
2 |
3 | export const CarsInClassSchema = z.object({
4 | carDirpath: z.string(),
5 | carId: z.number(),
6 | rainEnabled: z.boolean(),
7 | retired: z.boolean(),
8 | })
9 | export type CarsInClass = z.infer
10 |
11 | export const CarClassSchema = z.object({
12 | carClassId: z.number(),
13 | carsInClass: z.array(CarsInClassSchema),
14 | custId: z.number(),
15 | name: z.string(),
16 | rainEnabled: z.boolean(),
17 | relativeSpeed: z.number(),
18 | shortName: z.string(),
19 | })
20 | export type CarClass = z.infer
21 |
--------------------------------------------------------------------------------
/docs/api/how-to-use.md:
--------------------------------------------------------------------------------
1 | # How to use
2 |
3 | ## API Client
4 |
5 | ```ts
6 | import { iRacingAPI } from 'iracing-api';
7 |
8 | const ir = new iRacingAPI(options);
9 | ```
10 |
11 | ### Options
12 |
13 | * logger: `boolean` - Enable logging of requests and responses. Default is `false`.
14 | * manageRateLimits: `boolean` - Enable rate limit management. Default is `false`.
15 | * rateLimitPadding: `number` - Add a padding to the rate limit to avoid hitting the limit. Default is `5`.
16 |
17 | ### Login
18 |
19 | ```ts
20 | const email = 'email@domain.com';
21 | const password = 'password';
22 |
23 | await ir.login(email, password);
24 | ```
25 |
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # iRacing API
2 |
3 | ## Installation
4 |
5 | ```bash
6 | npm install iracing-api
7 | yarn add iracing-api
8 | pnpm i iracing-api
9 | bun i iracing-api
10 | ```
11 |
12 | ## Basic Usage
13 |
14 |
15 | ```typescript
16 | import IracingAPI from 'iracing-api'
17 |
18 | const irUser = 'FOO@gmail.com'
19 | const irPass = 'BAR'
20 |
21 | const main = async () => {
22 | const ir = new IracingAPI()
23 |
24 | // First you have to login to iracing using your credentials to be able to use the API.
25 | await ir.login(irUser, irPass)
26 |
27 | // Now you can use any endpoint, e.g. getCars
28 | const cars = await ir.car.getCars()
29 |
30 | console.log(cars)
31 | }
32 |
33 | main().then(() => 'Done')
34 | ```
35 |
36 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | # https://vitepress.dev/reference/default-theme-home-page
3 | layout: home
4 |
5 | hero:
6 | name: "iRacing API"
7 | text: "A wrapper for iRacing API"
8 | # tagline: My great project tagline
9 | actions:
10 | - theme: brand
11 | text: Get Started
12 | link: /getting-started
13 | - theme: alt
14 | text: View on GitHub
15 | link: https://github.com/themich4/iracing-api
16 |
17 | features:
18 | - title: Type safe
19 | details: Responses are typed using TypeScript.
20 | - title: Handle rate limits
21 | details: Rate limits are handled automatically, so you don't have to worry about them.
22 | - title: Easy to use
23 | details: The API is designed to be easy to use and understand.
24 | ---
25 |
26 |
--------------------------------------------------------------------------------
/docs/api/constants.md:
--------------------------------------------------------------------------------
1 | # Constants API
2 |
3 | All methods in the `Constants` API are available through the `constants` property of the `iRacingAPI` instance.
4 |
5 | ## Categories
6 |
7 | Get the categories.
8 |
9 | ```ts
10 | const categories = await ir.constants.getCategories();
11 | ```
12 | https://members-ng.iracing.com/data/constants/categories
13 |
14 | ## Divisions
15 |
16 | Get the divisions.
17 |
18 | ```ts
19 | const divisions = await ir.constants.getDivisions();
20 | ```
21 | https://members-ng.iracing.com/data/constants/divisions
22 |
23 | ## Event Types
24 |
25 | Get the event types.
26 |
27 | ```ts
28 | const eventTypes = await ir.constants.getEventTypes();
29 | ```
30 | https://members-ng.iracing.com/data/constants/eventtypes
--------------------------------------------------------------------------------
/packages/iracing-api/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './car'
2 | export * from './car-class'
3 | export * from './common'
4 | export * from './constants'
5 | export * from './hosted'
6 | export * from './league'
7 | export * from './lookup'
8 | export * from './member'
9 | export * from './results'
10 | export * from './season'
11 | export * from './series'
12 | export * from './stats'
13 | export * from './team'
14 | export * from './time-attack'
15 | export * from './track'
16 |
17 | export interface FetchCookie {
18 | (
19 | input: RequestInfo | URL,
20 | init?: RequestInit | undefined
21 | ): Promise
22 | }
23 |
24 | export interface Options {
25 | logger?: boolean
26 | manageRateLimit?: boolean
27 | rateLimitPadding?: number
28 | }
29 |
30 | export interface RateLimit {
31 | limit: number
32 | remaining: number
33 | reset: Date
34 | }
35 |
--------------------------------------------------------------------------------
/packages/iracing-api/src/api/track.ts:
--------------------------------------------------------------------------------
1 | import { API } from './api'
2 | import { Track, TrackAssets } from '../types'
3 |
4 | /**
5 | * Provides methods for interacting with track-related endpoints.
6 | */
7 | export class TrackAPI extends API {
8 | /**
9 | * Get assets for all tracks (logos, images, map layers, etc.).
10 | *
11 | * Note: Image paths are relative to `https://images-static.iracing.com/`.
12 | *
13 | * @returns A promise resolving to the track assets data, or undefined on error.
14 | */
15 | getTrackAssets = async () =>
16 | await this._getData('data/track/assets')
17 | /**
18 | * Get a list of all available tracks and their configurations.
19 | *
20 | * @returns A promise resolving to an array of track objects, or undefined on error.
21 | */
22 | getTracks = async () => await this._getData