@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 +217 -130
- package/dist/endpoints/datadragon.d.ts +4 -0
- package/dist/endpoints/datadragon.js +40 -0
- package/dist/endpoints/riot.d.ts +2 -0
- package/dist/endpoints/riot.js +169 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +106 -0
- package/dist/test-endpoints.d.ts +1 -0
- package/{test-endpoints.js → dist/test-endpoints.js} +29 -39
- package/dist/types.d.ts +60 -0
- package/dist/types.js +2 -0
- package/package.json +23 -3
- package/.github/workflows/publish.yml +0 -52
- package/endpoints/datadragon.js +0 -40
- package/endpoints/riot.js +0 -217
- package/index.js +0 -88
package/README.md
CHANGED
|
@@ -1,198 +1,285 @@
|
|
|
1
1
|
# RiftJS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript-first Riot Games API wrapper for Node.js, with built-in Data Dragon support.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@timmsy/riftjs)
|
|
6
6
|

|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## What this package does
|
|
9
9
|
|
|
10
|
-
RiftJS
|
|
10
|
+
RiftJS wraps common Riot API and Data Dragon use cases in a small API:
|
|
11
11
|
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
|
28
|
-
|
|
29
|
-
## Setup
|
|
27
|
+
You need a Riot developer key:
|
|
28
|
+
- https://developer.riotgames.com/
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
Ensure you have Node.js installed, then run the install command above.
|
|
30
|
+
## Quick Start
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
Create a `.env` file in your project root with your API key and region:
|
|
32
|
+
### 1. Configure environment
|
|
36
33
|
|
|
37
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
```env
|
|
37
|
+
RIOT_API_KEY=RGAPI-your-key-here
|
|
38
|
+
REGION=EUW1
|
|
39
|
+
```
|
|
47
40
|
|
|
48
|
-
|
|
41
|
+
Notes:
|
|
42
|
+
- `RIOT_API_KEY` is required for `RiotAPI`.
|
|
43
|
+
- `REGION` is optional. Default is `EUW1`.
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
### 2. Basic usage (JavaScript / CommonJS)
|
|
51
46
|
|
|
52
47
|
```js
|
|
53
48
|
const { RiotAPI, DataDragon } = require('@timmsy/riftjs');
|
|
54
49
|
|
|
55
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
65
|
-
|
|
64
|
+
main().catch((err) => {
|
|
65
|
+
console.error(err.message);
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
});
|
|
68
|
+
```
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
console.log('Matchlist:', matchlist);
|
|
70
|
+
### 3. Basic usage (TypeScript)
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
} catch (error) {
|
|
73
|
-
console.error('Error:', error.message);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
72
|
+
```ts
|
|
73
|
+
import { RiotAPI, DataDragon } from '@timmsy/riftjs';
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
const
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
102
|
-
- `
|
|
103
|
-
- `
|
|
104
|
-
- `
|
|
105
|
-
- `
|
|
106
|
-
- `
|
|
107
|
-
- `
|
|
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
|
-
|
|
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
|
-
|
|
120
|
-
- `
|
|
121
|
-
- `
|
|
161
|
+
- Input:
|
|
162
|
+
- `matchId: string` (example `EUW1_1234567890`)
|
|
163
|
+
- `region?: RegionCode`
|
|
164
|
+
- Output: Match V5 payload (`metadata` + `info`)
|
|
122
165
|
|
|
123
|
-
|
|
124
|
-
- Solo Queue: `RANKED_SOLO_5x5`
|
|
125
|
-
- Flex Queue: `RANKED_FLEX_SR`
|
|
166
|
+
### getMatchTimelineById(matchId, region?)
|
|
126
167
|
|
|
127
|
-
|
|
168
|
+
- Input:
|
|
169
|
+
- `matchId: string`
|
|
170
|
+
- `region?: RegionCode`
|
|
171
|
+
- Output: Match timeline payload
|
|
128
172
|
|
|
129
|
-
|
|
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
|
-
|
|
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
|
-
|
|
183
|
+
### getMatchesWithDetailsByPuuid(puuid, options?, region?, pacing?)
|
|
137
184
|
|
|
138
|
-
-
|
|
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
|
-
|
|
141
|
-
- `NA1` → `na1.api.riotgames.com`
|
|
195
|
+
## DataDragon
|
|
142
196
|
|
|
143
|
-
|
|
197
|
+
### new DataDragon(version?, locale?)
|
|
144
198
|
|
|
145
|
-
|
|
146
|
-
-
|
|
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
|
-
|
|
205
|
+
### getChampions()
|
|
149
206
|
|
|
150
|
-
|
|
207
|
+
- Output: Data Dragon champion payload (`champion.json`)
|
|
151
208
|
|
|
152
|
-
|
|
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
|
-
|
|
211
|
+
- Output: Data Dragon item payload (`item.json`)
|
|
164
212
|
|
|
165
|
-
|
|
213
|
+
## Supported regions
|
|
166
214
|
|
|
167
|
-
|
|
215
|
+
Supported `REGION` / `region` values:
|
|
168
216
|
|
|
169
|
-
|
|
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
|
-
|
|
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
|
-
|
|
177
|
-
npm install
|
|
178
|
-
```
|
|
223
|
+
## Error behavior
|
|
179
224
|
|
|
180
|
-
|
|
181
|
-
4. Run endpoint checks:
|
|
225
|
+
RiftJS normalizes errors to plain `Error` objects with readable messages:
|
|
182
226
|
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
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)
|
|
279
|
+
MIT License © 2025 James Timms. See [LICENSE](LICENSE).
|
|
193
280
|
|
|
194
281
|
## Links
|
|
195
282
|
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
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,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,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
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|