Twisted Node.js Wrapper for Riot Games API

repository·master·Indexed 41 days ago

https://github.com/justadev-afk/twisted

A fully-typed Node.js wrapper for the Riot Games API, covering League of Legends, Teamfight Tactics, Riot Account, and Data Dragon. Version 1.83.0 features native fetch, automatic rate-limit retries, and concurrency control. It provides specialized service classes like LolApi and a comprehensive set of Data Transfer Objects (DTOs) for type-safe API responses.

Tokens
14K
Snippets
49
Records
63
Agent score
99%

What's inside Twisted

  1. Overview of available Twisted examples

    master

    The examples are organized by Riot API category:

    FolderCategoryExamplesHighlights
    riot/Riot Account (Account-V1)2Resolve Riot ID ↔ PUUID; routed by regionGroup.
    lol/League of Legends19Summoner, League/ranked, Champion mastery, Match-V5, Spectator-V5, Challenges, Status.
    lol/*.DataDragon.tsData Dragon (static CDN)12Champions, runes, maps, queues, versions (no API key/rate limits required).
    lol/deprecated/LoL (deprecated)11Older endpoints (Match-V4, Spectator-V4, etc.). Use current versions instead.
    tft/Teamfight Tactics9Summoner, league by tier, Match-V1, Spectator, static files.
    clash/Clash2List tournaments and fetch by ID.
  2. Distinguish between Regions and Region Groups

    master

    Twisted uses TypeScript to enforce correct routing at the type level. You must use the correct constant type depending on the endpoint:

    ConceptTypeExamplesUsed by
    Platform regionRegionsNA1, EUW1, KRSummoner, League, Champion Mastery, Spectator, Status
    Region groupRegionGroupsAMERICAS, ASIA, EUROPE, SEAMatch-V5, TFT Match
    Account routingAccountAPIRegionGroupsAMERICAS, ASIA, EUROPEAccount-V1

    Use the Constants object to access these values.

    import { Constants } from 'twisted'
    
    Constants.Regions.EU_WEST        // 'EUW1'  — platform region
    Constants.RegionGroups.EUROPE    // 'EUROPE' — routing value
  3. Understand the ApiResponseDTO response shape

    master

    Most API methods resolve to an ApiResponseDTO<T> object. This structure provides both the requested data and the rate limit metadata returned by Riot's headers.

    {
      response: T          // the parsed payload
      rateLimits: {
        AppRateLimit, AppRateLimitCount,
        MethodRateLimit, MethodRatelimitCount,
        RetryAfter, Type, EdgeTraceId
      }
    }
    // Example of accessing the response
    const { response, rateLimits } = await api.Summoner.getByPUUID(puuid, Constants.Regions.KOREA);
  4. Handle Rate Limiting and Retries

    master

    Twisted automatically handles 429 Too Many Requests and 503 Service Unavailable responses by waiting for the duration specified in Riot's Retry-After header and re-issuing the request.

    • Retry Logic: Controlled by rateLimitRetry (boolean) and rateLimitRetryAttempts (number).
    • Concurrency Control: You can cap parallel requests per service using the concurrency option to avoid hitting limits too quickly.
    // Limit to 10 concurrent requests per service
    const api = new LolApi({ key, concurrency: 10 })
  5. Understand Regions vs Region Groups in Twisted

    master

    Twisted distinguishes between two Riot routing concepts, and the library's types enforce which one is required for specific endpoints:

    • Regions: Platform-specific routing (e.g., EUW1, KR, NA1) used by most League of Legends and Teamfight Tactics endpoints.
    • RegionGroups: Larger routing groups (e.g., AMERICAS, ASIA, EUROPE, SEA) used by the Account API, Match-V5, and TFT-Match.

    Refer to config/config.ts for the specific implementations used in the examples.

  6. Install Twisted

    master

    Install the twisted package using your preferred package manager.

    Requirements: Node.js ≥ 18 is required because the library uses the native fetch API.

    npm install twisted
    # or
    yarn add twisted
    # or
    pnpm add twisted
  7. Run Twisted examples

    master

    The example directory contains runnable examples for almost every Riot API endpoint wrapped by twisted. Each example is a self-contained async function that performs a call and logs a summary.

    To run these examples, you must provide a Riot API key via the RIOT_API_KEY environment variable.

    Note: The examples use demo Riot IDs defined in config/config.ts. You should edit config/config.ts with your own summonerName, tagLine, region, or regionGroup to ensure the examples work with your own account data.

    # Run every example
    RIOT_API_KEY=RGAPI-xxxx yarn example
    
    # Run a single example by name (case-insensitive substring match)
    RIOT_API_KEY=RGAPI-xxxx yarn example account
    RIOT_API_KEY=RGAPI-xxxx yarn example datadragon
  8. Quick start with Twisted APIs

    master

    Twisted provides three main entry points depending on the service you are accessing:

    • RiotApi: For Riot Account services.
    • LolApi: For League of Legends services.
    • TftApi: For Teamfight Tactics services.

    Every API call (except Data Dragon) returns an object containing { response, rateLimits }. Your actual data is located in the response property.

    import { RiotApi, LolApi, TftApi, Constants } from 'twisted'
    
    // Riot Account Example
    const riotApi = new RiotApi({ key: 'RGAPI-xxxxxxxx' })
    const { response } = await riotApi.Account.getByRiotId('Hide on bush', 'KR1', Constants.RegionGroups.ASIA)
    
    // League of Legends Example
    const lolApi = new LolApi({ key: 'RGAPI-xxxxxxxx' })
    const summoner = (await lolApi.Summoner.getByPUUID(puuid, Constants.Regions.KOREA)).response
    
    // Teamfight Tactics Example
    const tftApi = new TftApi({ key: 'RGAPI-xxxxxxxx' })
    const { response: tftSummoner } = await tftApi.Summoner.getByPUUID(puuid, Constants.Regions.AMERICA_NORTH)
  9. Understand how query parameters are serialized

    master

    Twisted uses a specific serialization logic for query parameters to ensure compatibility with the Riot Games API. When passing parameters:

    1. Null/Undefined values: null and undefined values are skipped and will not appear in the query string.
    2. Arrays: Arrays are expanded into repeated keys. For example, { queue: [420, 440] } is serialized as queue=420&queue=440. This is the specific format required by Riot's endpoints.
    3. Standard values: Strings and numbers are converted to their string representations.
    // Example of expected serialization behavior:
    // Input: { queue: [420, 440], name: 'player', empty: null }
    // Output: "queue=420&queue=440&name=player"
  10. Configure the Twisted API client

    master

    You can pass an options object to the API constructors to configure behavior such as rate limiting, concurrency, and debugging.

    import { LolApi } from 'twisted'
    
    const api = new LolApi({
      key: 'RGAPI-xxxxxxxx',
      rateLimitRetry: true,
      rateLimitRetryAttempts: 1,
      concurrency: 10,
      debug: {
        logTime: false,
        logUrls: false,
        logRatelimits: false
      }
    })
  11. Run Twisted examples using Docker Compose

    master

    You can run the provided examples in a containerized environment using Docker Compose. The setup builds an image from examples.Dockerfile and mounts the current directory to /app inside the container.

    To make the examples functional, you must provide your Riot Games API key via the RIOT_API_KEY environment variable.

    services:
      app:
        build:
          dockerfile: examples.Dockerfile
          context: .
        container_name: riotApiExamples
        volumes:
          - .:/app
        environment:
          RIOT_API_KEY: YOUR_API_KEY_HERE
  12. Use Data Dragon for static assets

    master

    Data Dragon provides access to static game assets (champions, items, runes, versions, etc.). Unlike other endpoints, Data Dragon hits the public CDN directly.

    Key differences:

    • No API key required.
    • No rate limiting.
    • Returns raw payload (does not wrap results in an ApiResponseDTO).
    const api = new LolApi()
    
    const versions = await api.DataDragon.getVersions()                 // ['15.x.1', ...]
    const champs   = await api.DataDragon.getChampionList()             // all champions
    const aatrox   = await api.DataDragon.getChampion(Constants.Champions.AATROX)
    const items    = await api.DataDragon.getItemList()                 // all items
    const runes    = await api.DataDragon.getRunesReforged()