@timmsy/riftjs 2.1.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,198 +1,285 @@
1
1
  # RiftJS
2
2
 
3
- A lightweight Node.js wrapper for the Riot Games API, providing easy access to League of Legends game data.
3
+ TypeScript-first Riot Games API wrapper for Node.js, with built-in Data Dragon support.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/@timmsy%2Friftjs.svg)](https://www.npmjs.com/package/@timmsy/riftjs)
6
6
  ![GitHub license](https://img.shields.io/github/license/timmsy1998/RiftJS)
7
7
 
8
- ## Overview
8
+ ## What this package does
9
9
 
10
- RiftJS simplifies interaction with the Riot Games API and DataDragon static data. It supports fetching account details, summoner info, match history, and game data using a modular endpoint structure. Built with `axios` and `dotenv`, it’s designed for developers building League of Legends tools or applications.
10
+ RiftJS wraps common Riot API and Data Dragon use cases in a small API:
11
11
 
12
- ## Features
12
+ - Resolve account details from Riot ID
13
+ - Get summoner details from PUUID
14
+ - Get rank entries and queue-split rank summaries
15
+ - Get match IDs, match details, and match timelines
16
+ - Fetch all match IDs with paging and optional pacing
17
+ - Fetch Data Dragon champion and item static data
13
18
 
14
- - **RiotAPI**: Fetch account data by Riot ID, summoner data by PUUID, match history, and match details.
15
- - **DataDragon**: Access static game data like champions and items.
16
- - **Region Support**: Handles platform (e.g., `EUW1`) and shard (e.g., `europe`) routing.
17
- - **Modular Design**: Endpoints are organized in an `/endpoints/` directory for easy extension.
19
+ The package is authored in TypeScript and published as compiled CommonJS with `.d.ts` types.
18
20
 
19
- ## Installation
20
-
21
- Install RiftJS via npm:
21
+ ## Install
22
22
 
23
23
  ```bash
24
24
  npm install @timmsy/riftjs
25
25
  ```
26
26
 
27
- You’ll also need a Riot Games API key from [developer.riotgames.com](https://developer.riotgames.com/).
28
-
29
- ## Setup
27
+ You need a Riot developer key:
28
+ - https://developer.riotgames.com/
30
29
 
31
- 1. **Install Dependencies**:
32
- Ensure you have Node.js installed, then run the install command above.
30
+ ## Quick Start
33
31
 
34
- 2. **Configure Environment**:
35
- Create a `.env` file in your project root with your API key and region:
32
+ ### 1. Configure environment
36
33
 
37
- ```env
38
- RIOT_API_KEY=RGAPI-your-api-key-here
39
- REGION=EUW1
40
- TEST_RIOT_ID=YourRiotName
41
- TEST_TAG_LINE=EUW
42
- ```
34
+ Create a `.env` file in your app:
43
35
 
44
- - Replace `RGAPI-your-api-key-here` with your API key.
45
- - Use a short region code (e.g., `EUW1`, `NA1`). See [Region Mapping](#region-mapping) for details.
46
- - `TEST_RIOT_ID` and `TEST_TAG_LINE` are used by the endpoint test script.
36
+ ```env
37
+ RIOT_API_KEY=RGAPI-your-key-here
38
+ REGION=EUW1
39
+ ```
47
40
 
48
- ## Usage
41
+ Notes:
42
+ - `RIOT_API_KEY` is required for `RiotAPI`.
43
+ - `REGION` is optional. Default is `EUW1`.
49
44
 
50
- Here’s a basic example to get started:
45
+ ### 2. Basic usage (JavaScript / CommonJS)
51
46
 
52
47
  ```js
53
48
  const { RiotAPI, DataDragon } = require('@timmsy/riftjs');
54
49
 
55
- // Initialize RiotAPI
56
- const riot = new RiotAPI();
50
+ async function main() {
51
+ const riot = new RiotAPI();
52
+ const account = await riot.getAccountByRiotId('PlayerName#EUW');
53
+ const summoner = await riot.getSummonerByPuuid(account.puuid);
54
+ const matchIds = await riot.getMatchlistByPuuid(account.puuid, { start: 0, count: 5 });
57
55
 
58
- // Fetch account, summoner, and match data
59
- async function fetchPlayerData() {
60
- try {
61
- const account = await riot.getAccountByRiotId('Timmsy#BRUV');
62
- console.log('Account:', account);
56
+ console.log('Summoner level:', summoner.summonerLevel);
57
+ console.log('Recent matches:', matchIds);
58
+
59
+ const dd = new DataDragon();
60
+ const champions = await dd.getChampions();
61
+ console.log('Champion count:', Object.keys(champions.data || {}).length);
62
+ }
63
63
 
64
- const summoner = await riot.getSummonerByPuuid(account.puuid);
65
- console.log('Summoner:', summoner);
64
+ main().catch((err) => {
65
+ console.error(err.message);
66
+ process.exitCode = 1;
67
+ });
68
+ ```
66
69
 
67
- const matchlist = await riot.getMatchlistByPuuid(account.puuid, { start: 0, count: 5 });
68
- console.log('Matchlist:', matchlist);
70
+ ### 3. Basic usage (TypeScript)
69
71
 
70
- const match = await riot.getMatchById(matchlist[0]);
71
- console.log('Match:', match);
72
- } catch (error) {
73
- console.error('Error:', error.message);
74
- }
75
- }
72
+ ```ts
73
+ import { RiotAPI, DataDragon } from '@timmsy/riftjs';
76
74
 
77
- // Initialize DataDragon
78
- const dd = new DataDragon();
75
+ async function main(): Promise<void> {
76
+ const riot = new RiotAPI();
77
+ const account = await riot.getAccountByRiotId('PlayerName#EUW');
78
+ const rank = await riot.getRankByPuuid(String(account.puuid || ''));
79
79
 
80
- async function fetchStaticData() {
81
- try {
82
- const champions = await dd.getChampions();
83
- console.log('Champions:', champions.data);
80
+ console.log('Solo queue:', rank.solo);
81
+ console.log('Flex queue:', rank.flex);
84
82
 
85
- const items = await dd.getItems();
86
- console.log('Items:', items.data);
87
- } catch (error) {
88
- console.error('Error:', error.message);
89
- }
83
+ const dd = new DataDragon();
84
+ const items = await dd.getItems();
85
+ console.log('Item count:', Object.keys((items.data as Record<string, unknown>) || {}).length);
90
86
  }
91
87
 
92
- // Run the examples
93
- fetchPlayerData();
94
- fetchStaticData();
88
+ main().catch((err: unknown) => {
89
+ const message = err instanceof Error ? err.message : 'Unknown error';
90
+ console.error(message);
91
+ process.exitCode = 1;
92
+ });
95
93
  ```
96
94
 
97
95
  ## API Reference
98
96
 
99
- ### RiotAPI
97
+ ## RiotAPI
98
+
99
+ `new RiotAPI()` reads:
100
+ - `RIOT_API_KEY` from environment
101
+ - `REGION` from environment (default `EUW1`)
102
+
103
+ ### getAccountByRiotId(riotId, tagLine?, region?)
104
+
105
+ - Input:
106
+ - `riotId: string` (`"Name#Tag"` format, or name-only with `tagLine`)
107
+ - `tagLine?: string | null`
108
+ - `region?: RegionCode`
109
+ - Output: account payload (includes `puuid`)
110
+ - Example:
111
+ ```ts
112
+ const account = await riot.getAccountByRiotId('Timmsy#BRUV');
113
+ ```
114
+
115
+ ### getSummonerByPuuid(puuid, region?)
116
+
117
+ - Input:
118
+ - `puuid: string`
119
+ - `region?: RegionCode`
120
+ - Output: Summoner V4 payload
121
+
122
+ ### getRankEntriesByPuuid(puuid, region?)
123
+
124
+ - Input:
125
+ - `puuid: string`
126
+ - `region?: RegionCode`
127
+ - Output: League V4 rank entries array
128
+
129
+ ### getRankByPuuid(puuid, region?)
130
+
131
+ - Input:
132
+ - `puuid: string`
133
+ - `region?: RegionCode`
134
+ - Output:
135
+ - `solo`: solo queue entry with computed `winRate` (or `null`)
136
+ - `flex`: flex queue entry with computed `winRate` (or `null`)
137
+ - `entries`: original rank entries
138
+
139
+ Queue constants used internally:
140
+ - `RANKED_SOLO_5x5`
141
+ - `RANKED_FLEX_SR`
142
+
143
+ ### getMatchlistByPuuid(puuid, options?, region?)
144
+
145
+ - Input:
146
+ - `puuid: string`
147
+ - `options?: MatchlistOptions`
148
+ - `region?: RegionCode`
149
+ - Output: `string[]` of match IDs
100
150
 
101
- - `getAccountByRiotId(riotId, [tagLine], [region])`: Fetch account by Riot ID (e.g., `Timmsy#BRUV`).
102
- - `getSummonerByPuuid(puuid, [region])`: Get summoner data by PUUID.
103
- - `getRankEntriesByPuuid(puuid, [region])`: Get all League-V4 rank entries for a player PUUID.
104
- - `getRankByPuuid(puuid, [region])`: Get rank split by Solo and Flex queues from a PUUID.
105
- - `getMatchlistByPuuid(puuid, [options], [region])`: Get match history (options: `{ start, count }`).
106
- - `getMatchById(matchId, [region])`: Get full match payload (`metadata` + `info`) by match ID.
107
- - `getMatchTimelineById(matchId, [region])`: Get timeline payload by match ID.
108
- - `getMatchlistByPuuidAll(puuid, [options], [region], [pacing])`: Fetch all match IDs in pages of 100.
109
- - `getMatchesWithDetailsByPuuid(puuid, [options], [region], [pacing])`: Fetch all match IDs and their match payloads.
151
+ `MatchlistOptions`:
152
+ - `startTime?: number` (epoch seconds)
153
+ - `endTime?: number` (epoch seconds)
154
+ - `queue?: number`
155
+ - `type?: string`
156
+ - `start?: number`
157
+ - `count?: number` (Riot max is 100 for this endpoint)
110
158
 
111
- `options` supports Riot Match-V5 query params:
112
- - `startTime` (epoch seconds)
113
- - `endTime` (epoch seconds)
114
- - `queue` (int)
115
- - `type` (string)
116
- - `start` (int, default `0`)
117
- - `count` (int, `0-100`, single-page method only)
159
+ ### getMatchById(matchId, region?)
118
160
 
119
- `pacing` helps respect rate limits on multi-request methods:
120
- - `getMatchlistByPuuidAll`: `{ delayMs, maxMatches }`
121
- - `getMatchesWithDetailsByPuuid`: `{ pageDelayMs, detailDelayMs, maxMatches }`
161
+ - Input:
162
+ - `matchId: string` (example `EUW1_1234567890`)
163
+ - `region?: RegionCode`
164
+ - Output: Match V5 payload (`metadata` + `info`)
122
165
 
123
- Rank queue mapping used by helper methods:
124
- - Solo Queue: `RANKED_SOLO_5x5`
125
- - Flex Queue: `RANKED_FLEX_SR`
166
+ ### getMatchTimelineById(matchId, region?)
126
167
 
127
- ### DataDragon
168
+ - Input:
169
+ - `matchId: string`
170
+ - `region?: RegionCode`
171
+ - Output: Match timeline payload
128
172
 
129
- - `getChampions()`: Fetch all champion data.
130
- - `getItems()`: Fetch all item data.
131
- - `new DataDragon()` resolves the latest Data Dragon patch automatically.
132
- - `new DataDragon('x.y.z')` pins requests to an explicit patch version.
173
+ ### getMatchlistByPuuidAll(puuid, options?, region?, pacing?)
133
174
 
134
- ## Region Mapping
175
+ - Purpose: fetches all match IDs in pages of up to 100.
176
+ - Input:
177
+ - `puuid: string`
178
+ - `options?: MatchlistOptions` (filters + optional start offset)
179
+ - `region?: RegionCode`
180
+ - `pacing?: { delayMs?: number; maxMatches?: number | null }`
181
+ - Output: `string[]` of aggregated match IDs
135
182
 
136
- RiftJS uses a region map to route requests correctly:
183
+ ### getMatchesWithDetailsByPuuid(puuid, options?, region?, pacing?)
137
184
 
138
- - **Platform Routing** (e.g., Summoner V4):
185
+ - Purpose: fetches match IDs, then fetches each match payload.
186
+ - Input:
187
+ - `puuid: string`
188
+ - `options?: MatchlistOptions`
189
+ - `region?: RegionCode`
190
+ - `pacing?: { pageDelayMs?: number; detailDelayMs?: number; maxMatches?: number | null }`
191
+ - Output:
192
+ - `matchIds: string[]`
193
+ - `matches: object[]`
139
194
 
140
- - `EUW1` → `euw1.api.riotgames.com`
141
- - `NA1` → `na1.api.riotgames.com`
195
+ ## DataDragon
142
196
 
143
- - **Shard Routing** (e.g., Account V1, Match V5):
197
+ ### new DataDragon(version?, locale?)
144
198
 
145
- - `EUW1` `europe.api.riotgames.com`
146
- - `NA1` `americas.api.riotgames.com`
199
+ - `version?: string | null`
200
+ - Omit to auto-resolve the latest Data Dragon version
201
+ - Pass a version like `15.4.1` to pin
202
+ - `locale?: string`
203
+ - Defaults to `en_US`
147
204
 
148
- Supported regions: `BR1`, `EUN1`, `EUW1`, `JP1`, `KR`, `LA1`, `LA2`, `NA1`, `OC1`, `TR1`, `RU`, `PH2`, `SG2`, `TH2`, `TW2`, `VN2`.
205
+ ### getChampions()
149
206
 
150
- ## Keywords
207
+ - Output: Data Dragon champion payload (`champion.json`)
151
208
 
152
- - riot-api
153
- - league-of-legends
154
- - lol-api
155
- - datadragon
156
- - summoner
157
- - match-history
158
- - game-data
159
- - node-js
160
- - javascript
161
- - api-wrapper
209
+ ### getItems()
162
210
 
163
- ## Development
211
+ - Output: Data Dragon item payload (`item.json`)
164
212
 
165
- To contribute or run locally:
213
+ ## Supported regions
166
214
 
167
- 1. Clone the repo:
215
+ Supported `REGION` / `region` values:
168
216
 
169
- ```bash
170
- git clone https://github.com/timmsy1998/RiftJS.git
171
- cd RiftJS
172
- ```
217
+ `BR1`, `EUN1`, `EUW1`, `JP1`, `KR`, `LA1`, `LA2`, `NA1`, `OC1`, `TR1`, `RU`, `PH2`, `SG2`, `TH2`, `TW2`, `VN2`
173
218
 
174
- 2. Install dependencies:
219
+ Routing behavior:
220
+ - Platform APIs (example Summoner V4) use platform hosts like `euw1.api.riotgames.com`.
221
+ - Regional APIs (example Match V5 / Account V1) use shard hosts like `europe.api.riotgames.com`.
175
222
 
176
- ```bash
177
- npm install
178
- ```
223
+ ## Error behavior
179
224
 
180
- 3. Create a `.env` file (see [Setup](#setup)).
181
- 4. Run endpoint checks:
225
+ RiftJS normalizes errors to plain `Error` objects with readable messages:
182
226
 
183
- ```bash
184
- npm test
185
- ```
227
+ - HTTP response errors: `API error <status>: <message>`
228
+ - No response from Riot: `No response received from the server`
229
+ - Request setup/other errors: `Request error: <message>`
230
+ - Data Dragon wrapper errors: `DataDragon error: <message>`
231
+
232
+ ## Local development
233
+
234
+ ### Run locally
235
+
236
+ ```bash
237
+ git clone https://github.com/timmsy1998/RiftJS.git
238
+ cd RiftJS
239
+ npm install
240
+ npm run build
241
+ ```
242
+
243
+ ### Run endpoint checks
244
+
245
+ ```bash
246
+ npm test
247
+ ```
248
+
249
+ Test script behavior:
250
+ - Riot endpoint checks run only when `RIOT_API_KEY` and `TEST_RIOT_ID` are set.
251
+ - Data Dragon checks always run.
252
+
253
+ Optional `.env` values for tests:
254
+
255
+ ```env
256
+ TEST_RIOT_ID=YourRiotName
257
+ TEST_TAG_LINE=EUW
258
+ ```
259
+
260
+ Maintainer notes:
261
+ - See `MAINTAINER_NOTES.md` for project conventions and release checklist.
262
+
263
+ ## Package output
264
+
265
+ Published entry points:
266
+ - `main`: `dist/index.js`
267
+ - `types`: `dist/index.d.ts`
268
+
269
+ Build command:
270
+
271
+ ```bash
272
+ npm run build
273
+ ```
186
274
 
187
- - Riot API calls run when `TEST_RIOT_ID` is set.
188
- - Data Dragon calls always run.
275
+ Compiled output is written to `dist/`.
189
276
 
190
277
  ## License
191
278
 
192
- MIT License © 2025 James Timms. See [LICENSE](LICENSE) for details.
279
+ MIT License © 2025 James Timms. See [LICENSE](LICENSE).
193
280
 
194
281
  ## Links
195
282
 
196
- - **npm Registry**: [https://www.npmjs.com/package/@timmsy/riftjs](https://www.npmjs.com/package/@timmsy/riftjs)
197
- - **GitHub Repository**: [https://github.com/timmsy1998/RiftJS](https://github.com/timmsy1998/RiftJS)
198
- - **Riot Developer Portal**: [https://developer.riotgames.com/](https://developer.riotgames.com/)
283
+ - npm: https://www.npmjs.com/package/@timmsy/riftjs
284
+ - GitHub: https://github.com/timmsy1998/RiftJS
285
+ - Riot Developer Portal: https://developer.riotgames.com/
@@ -0,0 +1,4 @@
1
+ import type { DataDragonEndpointMethods } from '../types';
2
+ type BaseURLResolver = string | (() => string | Promise<string>);
3
+ export default function dataDragonEndpoints(baseURLOrResolver: BaseURLResolver): DataDragonEndpointMethods;
4
+ export {};
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = dataDragonEndpoints;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ function dataDragonEndpoints(baseURLOrResolver) {
9
+ const resolveBaseURL = async () => {
10
+ // Maintainer note (Timmsy): allow either a fixed URL or lazy resolver so callers can choose version strategy.
11
+ if (typeof baseURLOrResolver === 'function') {
12
+ return baseURLOrResolver();
13
+ }
14
+ return baseURLOrResolver;
15
+ };
16
+ return {
17
+ async getChampions() {
18
+ try {
19
+ const baseURL = await resolveBaseURL();
20
+ const response = await axios_1.default.get(`${baseURL}/champion.json`);
21
+ return response.data;
22
+ }
23
+ catch (error) {
24
+ const message = error instanceof Error ? error.message : 'Unknown DataDragon error';
25
+ throw new Error(`DataDragon error: ${message}`);
26
+ }
27
+ },
28
+ async getItems() {
29
+ try {
30
+ const baseURL = await resolveBaseURL();
31
+ const response = await axios_1.default.get(`${baseURL}/item.json`);
32
+ return response.data;
33
+ }
34
+ catch (error) {
35
+ const message = error instanceof Error ? error.message : 'Unknown DataDragon error';
36
+ throw new Error(`DataDragon error: ${message}`);
37
+ }
38
+ },
39
+ };
40
+ }
@@ -0,0 +1,2 @@
1
+ import type { RiotEndpointMethods, RiotEndpointsFactoryArgs } from '../types';
2
+ export default function riotEndpoints({ client, defaultRegion, regionMap, handleError, }: RiotEndpointsFactoryArgs): RiotEndpointMethods;
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = riotEndpoints;
4
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5
+ const SOLO_QUEUE = 'RANKED_SOLO_5x5';
6
+ const FLEX_QUEUE = 'RANKED_FLEX_SR';
7
+ const withRankMetrics = (entry) => {
8
+ if (!entry)
9
+ return null;
10
+ const wins = Number(entry.wins) || 0;
11
+ const losses = Number(entry.losses) || 0;
12
+ const gamesPlayed = wins + losses;
13
+ const winRate = gamesPlayed > 0 ? Number(((wins / gamesPlayed) * 100).toFixed(2)) : 0;
14
+ return { ...entry, winRate };
15
+ };
16
+ const coerceRegion = (region, regionMap) => {
17
+ // Maintainer note (Timmsy): region overrides are accepted per-call, but must always match our known map.
18
+ const upper = region.toUpperCase();
19
+ if (!regionMap[upper])
20
+ throw new Error(`Invalid region: ${region}`);
21
+ return upper;
22
+ };
23
+ function riotEndpoints({ client, defaultRegion, regionMap, handleError, }) {
24
+ const getAccountByRiotId = async (riotId, tagLine = null, region = defaultRegion) => {
25
+ const resolvedRegion = coerceRegion(region, regionMap);
26
+ let gameName;
27
+ let tag;
28
+ if (riotId.includes('#')) {
29
+ [gameName, tag] = riotId.split('#');
30
+ }
31
+ else {
32
+ gameName = riotId;
33
+ tag = tagLine || '';
34
+ }
35
+ if (!tag)
36
+ throw new Error('TagLine is required for getAccountByRiotId');
37
+ const shard = regionMap[resolvedRegion].shard;
38
+ try {
39
+ const response = await client.get(`/riot/account/v1/accounts/by-riot-id/${encodeURIComponent(gameName)}/${encodeURIComponent(tag)}`, { baseURL: `https://${shard}` });
40
+ return response.data;
41
+ }
42
+ catch (error) {
43
+ throw handleError(error);
44
+ }
45
+ };
46
+ const getSummonerByPuuid = async (puuid, region = defaultRegion) => {
47
+ const resolvedRegion = coerceRegion(region, regionMap);
48
+ const platform = regionMap[resolvedRegion].platform;
49
+ try {
50
+ const response = await client.get(`/lol/summoner/v4/summoners/by-puuid/${encodeURIComponent(puuid)}`, { baseURL: `https://${platform}` });
51
+ return response.data;
52
+ }
53
+ catch (error) {
54
+ throw handleError(error);
55
+ }
56
+ };
57
+ const getRankEntriesByPuuid = async (puuid, region = defaultRegion) => {
58
+ const resolvedRegion = coerceRegion(region, regionMap);
59
+ const platform = regionMap[resolvedRegion].platform;
60
+ try {
61
+ const response = await client.get(`/lol/league/v4/entries/by-puuid/${encodeURIComponent(puuid)}`, {
62
+ baseURL: `https://${platform}`,
63
+ });
64
+ return response.data;
65
+ }
66
+ catch (error) {
67
+ throw handleError(error);
68
+ }
69
+ };
70
+ const getRankByPuuid = async (puuid, region = defaultRegion) => {
71
+ const entries = await getRankEntriesByPuuid(puuid, region);
72
+ const solo = withRankMetrics(entries.find((entry) => entry.queueType === SOLO_QUEUE) || null);
73
+ const flex = withRankMetrics(entries.find((entry) => entry.queueType === FLEX_QUEUE) || null);
74
+ return { solo, flex, entries };
75
+ };
76
+ const getMatchlistByPuuid = async (puuid, options = {}, region = defaultRegion) => {
77
+ const resolvedRegion = coerceRegion(region, regionMap);
78
+ const shard = regionMap[resolvedRegion].shard;
79
+ try {
80
+ const response = await client.get(`/lol/match/v5/matches/by-puuid/${encodeURIComponent(puuid)}/ids`, {
81
+ baseURL: `https://${shard}`,
82
+ params: options,
83
+ });
84
+ return response.data;
85
+ }
86
+ catch (error) {
87
+ throw handleError(error);
88
+ }
89
+ };
90
+ const getMatchById = async (matchId, region = defaultRegion) => {
91
+ const resolvedRegion = coerceRegion(region, regionMap);
92
+ const shard = regionMap[resolvedRegion].shard;
93
+ try {
94
+ const response = await client.get(`/lol/match/v5/matches/${matchId}`, {
95
+ baseURL: `https://${shard}`,
96
+ });
97
+ return response.data;
98
+ }
99
+ catch (error) {
100
+ throw handleError(error);
101
+ }
102
+ };
103
+ const getMatchTimelineById = async (matchId, region = defaultRegion) => {
104
+ const resolvedRegion = coerceRegion(region, regionMap);
105
+ const shard = regionMap[resolvedRegion].shard;
106
+ try {
107
+ const response = await client.get(`/lol/match/v5/matches/${matchId}/timeline`, {
108
+ baseURL: `https://${shard}`,
109
+ });
110
+ return response.data;
111
+ }
112
+ catch (error) {
113
+ throw handleError(error);
114
+ }
115
+ };
116
+ const getMatchlistByPuuidAll = async (puuid, options = {}, region = defaultRegion, pacing = {}) => {
117
+ // Maintainer note (Timmsy): defaults are intentionally conservative to reduce accidental rate-limit spikes.
118
+ const baseStart = Number.isInteger(options.start) ? options.start : 0;
119
+ const pageDelayMs = Number.isInteger(pacing.delayMs) ? pacing.delayMs : 1250;
120
+ const maxMatches = Number.isInteger(pacing.maxMatches) && Number(pacing.maxMatches) >= 0 ? Number(pacing.maxMatches) : null;
121
+ const filters = {
122
+ startTime: options.startTime,
123
+ endTime: options.endTime,
124
+ queue: options.queue,
125
+ type: options.type,
126
+ };
127
+ let start = baseStart;
128
+ const allMatchIds = [];
129
+ while (true) {
130
+ const remaining = maxMatches === null ? 100 : Math.min(100, maxMatches - allMatchIds.length);
131
+ if (remaining <= 0)
132
+ break;
133
+ const page = await getMatchlistByPuuid(puuid, { ...filters, start, count: remaining }, region);
134
+ allMatchIds.push(...page);
135
+ if (page.length < remaining)
136
+ break;
137
+ start += page.length;
138
+ if (pageDelayMs > 0)
139
+ await sleep(pageDelayMs);
140
+ }
141
+ return allMatchIds;
142
+ };
143
+ const getMatchesWithDetailsByPuuid = async (puuid, options = {}, region = defaultRegion, pacing = {}) => {
144
+ // Maintainer note (Timmsy): details are fetched sequentially on purpose for predictable pacing.
145
+ const pageDelayMs = Number.isInteger(pacing.pageDelayMs) ? pacing.pageDelayMs : 1250;
146
+ const detailDelayMs = Number.isInteger(pacing.detailDelayMs) ? pacing.detailDelayMs : 1250;
147
+ const maxMatches = Number.isInteger(pacing.maxMatches) && Number(pacing.maxMatches) >= 0 ? Number(pacing.maxMatches) : null;
148
+ const matchIds = await getMatchlistByPuuidAll(puuid, options, region, { delayMs: pageDelayMs, maxMatches });
149
+ const matches = [];
150
+ for (let i = 0; i < matchIds.length; i += 1) {
151
+ matches.push(await getMatchById(matchIds[i], region));
152
+ if (detailDelayMs > 0 && i < matchIds.length - 1) {
153
+ await sleep(detailDelayMs);
154
+ }
155
+ }
156
+ return { matchIds, matches };
157
+ };
158
+ return {
159
+ getAccountByRiotId,
160
+ getSummonerByPuuid,
161
+ getRankEntriesByPuuid,
162
+ getRankByPuuid,
163
+ getMatchlistByPuuid,
164
+ getMatchById,
165
+ getMatchTimelineById,
166
+ getMatchlistByPuuidAll,
167
+ getMatchesWithDetailsByPuuid,
168
+ };
169
+ }
@@ -0,0 +1,28 @@
1
+ import 'dotenv/config';
2
+ import type { DataDragonEndpointMethods, RegionCode, RiotEndpointMethods } from './types';
3
+ export declare class RiotAPI implements RiotEndpointMethods {
4
+ readonly apiKey: string;
5
+ readonly region: RegionCode;
6
+ private readonly client;
7
+ getAccountByRiotId: RiotEndpointMethods['getAccountByRiotId'];
8
+ getSummonerByPuuid: RiotEndpointMethods['getSummonerByPuuid'];
9
+ getRankEntriesByPuuid: RiotEndpointMethods['getRankEntriesByPuuid'];
10
+ getRankByPuuid: RiotEndpointMethods['getRankByPuuid'];
11
+ getMatchlistByPuuid: RiotEndpointMethods['getMatchlistByPuuid'];
12
+ getMatchById: RiotEndpointMethods['getMatchById'];
13
+ getMatchTimelineById: RiotEndpointMethods['getMatchTimelineById'];
14
+ getMatchlistByPuuidAll: RiotEndpointMethods['getMatchlistByPuuidAll'];
15
+ getMatchesWithDetailsByPuuid: RiotEndpointMethods['getMatchesWithDetailsByPuuid'];
16
+ constructor();
17
+ private _handleError;
18
+ }
19
+ export declare class DataDragon implements DataDragonEndpointMethods {
20
+ version: string | null;
21
+ locale: string;
22
+ private baseURL;
23
+ private baseURLPromise;
24
+ getChampions: DataDragonEndpointMethods['getChampions'];
25
+ getItems: DataDragonEndpointMethods['getItems'];
26
+ constructor(version?: string | null, locale?: string);
27
+ private resolveBaseURL;
28
+ }