@timmsy/riftjs 3.0.1 → 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,205 +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`, `dotenv`, and TypeScript, 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 `src/endpoints/` for easy extension.
18
- - **TypeScript Types**: The package ships with declaration files for typed usage in TS projects.
19
+ The package is authored in TypeScript and published as compiled CommonJS with `.d.ts` types.
19
20
 
20
- ## Installation
21
-
22
- Install RiftJS via npm:
21
+ ## Install
23
22
 
24
23
  ```bash
25
24
  npm install @timmsy/riftjs
26
25
  ```
27
26
 
28
- You’ll also need a Riot Games API key from [developer.riotgames.com](https://developer.riotgames.com/).
29
-
30
- ## Setup
27
+ You need a Riot developer key:
28
+ - https://developer.riotgames.com/
31
29
 
32
- 1. **Install Dependencies**:
33
- Ensure you have Node.js installed, then run the install command above.
30
+ ## Quick Start
34
31
 
35
- 2. **Configure Environment**:
36
- Create a `.env` file in your project root with your API key and region:
32
+ ### 1. Configure environment
37
33
 
38
- ```env
39
- RIOT_API_KEY=RGAPI-your-api-key-here
40
- REGION=EUW1
41
- TEST_RIOT_ID=YourRiotName
42
- TEST_TAG_LINE=EUW
43
- ```
34
+ Create a `.env` file in your app:
44
35
 
45
- - Replace `RGAPI-your-api-key-here` with your API key.
46
- - Use a short region code (e.g., `EUW1`, `NA1`). See [Region Mapping](#region-mapping) for details.
47
- - `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
+ ```
48
40
 
49
- ## Usage
41
+ Notes:
42
+ - `RIOT_API_KEY` is required for `RiotAPI`.
43
+ - `REGION` is optional. Default is `EUW1`.
50
44
 
51
- Here’s a basic example to get started:
45
+ ### 2. Basic usage (JavaScript / CommonJS)
52
46
 
53
47
  ```js
54
48
  const { RiotAPI, DataDragon } = require('@timmsy/riftjs');
55
49
 
56
- // Initialize RiotAPI
57
- 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 });
58
55
 
59
- // Fetch account, summoner, and match data
60
- async function fetchPlayerData() {
61
- try {
62
- const account = await riot.getAccountByRiotId('Timmsy#BRUV');
63
- 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
+ }
64
63
 
65
- const summoner = await riot.getSummonerByPuuid(account.puuid);
66
- console.log('Summoner:', summoner);
64
+ main().catch((err) => {
65
+ console.error(err.message);
66
+ process.exitCode = 1;
67
+ });
68
+ ```
67
69
 
68
- const matchlist = await riot.getMatchlistByPuuid(account.puuid, { start: 0, count: 5 });
69
- console.log('Matchlist:', matchlist);
70
+ ### 3. Basic usage (TypeScript)
70
71
 
71
- const match = await riot.getMatchById(matchlist[0]);
72
- console.log('Match:', match);
73
- } catch (error) {
74
- console.error('Error:', error.message);
75
- }
76
- }
72
+ ```ts
73
+ import { RiotAPI, DataDragon } from '@timmsy/riftjs';
77
74
 
78
- // Initialize DataDragon
79
- 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 || ''));
80
79
 
81
- async function fetchStaticData() {
82
- try {
83
- const champions = await dd.getChampions();
84
- console.log('Champions:', champions.data);
80
+ console.log('Solo queue:', rank.solo);
81
+ console.log('Flex queue:', rank.flex);
85
82
 
86
- const items = await dd.getItems();
87
- console.log('Items:', items.data);
88
- } catch (error) {
89
- console.error('Error:', error.message);
90
- }
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);
91
86
  }
92
87
 
93
- // Run the examples
94
- fetchPlayerData();
95
- 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
+ });
96
93
  ```
97
94
 
98
95
  ## API Reference
99
96
 
100
- ### 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?)
101
144
 
102
- - `getAccountByRiotId(riotId, [tagLine], [region])`: Fetch account by Riot ID (e.g., `Timmsy#BRUV`).
103
- - `getSummonerByPuuid(puuid, [region])`: Get summoner data by PUUID.
104
- - `getRankEntriesByPuuid(puuid, [region])`: Get all League-V4 rank entries for a player PUUID.
105
- - `getRankByPuuid(puuid, [region])`: Get rank split by Solo and Flex queues from a PUUID.
106
- - `getMatchlistByPuuid(puuid, [options], [region])`: Get match history (options: `{ start, count }`).
107
- - `getMatchById(matchId, [region])`: Get full match payload (`metadata` + `info`) by match ID.
108
- - `getMatchTimelineById(matchId, [region])`: Get timeline payload by match ID.
109
- - `getMatchlistByPuuidAll(puuid, [options], [region], [pacing])`: Fetch all match IDs in pages of 100.
110
- - `getMatchesWithDetailsByPuuid(puuid, [options], [region], [pacing])`: Fetch all match IDs and their match payloads.
145
+ - Input:
146
+ - `puuid: string`
147
+ - `options?: MatchlistOptions`
148
+ - `region?: RegionCode`
149
+ - Output: `string[]` of match IDs
111
150
 
112
- `options` supports Riot Match-V5 query params:
113
- - `startTime` (epoch seconds)
114
- - `endTime` (epoch seconds)
115
- - `queue` (int)
116
- - `type` (string)
117
- - `start` (int, default `0`)
118
- - `count` (int, `0-100`, single-page method only)
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)
119
158
 
120
- `pacing` helps respect rate limits on multi-request methods:
121
- - `getMatchlistByPuuidAll`: `{ delayMs, maxMatches }`
122
- - `getMatchesWithDetailsByPuuid`: `{ pageDelayMs, detailDelayMs, maxMatches }`
159
+ ### getMatchById(matchId, region?)
123
160
 
124
- Rank queue mapping used by helper methods:
125
- - Solo Queue: `RANKED_SOLO_5x5`
126
- - Flex Queue: `RANKED_FLEX_SR`
161
+ - Input:
162
+ - `matchId: string` (example `EUW1_1234567890`)
163
+ - `region?: RegionCode`
164
+ - Output: Match V5 payload (`metadata` + `info`)
127
165
 
128
- ### DataDragon
166
+ ### getMatchTimelineById(matchId, region?)
129
167
 
130
- - `getChampions()`: Fetch all champion data.
131
- - `getItems()`: Fetch all item data.
132
- - `new DataDragon()` resolves the latest Data Dragon patch automatically.
133
- - `new DataDragon('x.y.z')` pins requests to an explicit patch version.
168
+ - Input:
169
+ - `matchId: string`
170
+ - `region?: RegionCode`
171
+ - Output: Match timeline payload
134
172
 
135
- ## Region Mapping
173
+ ### getMatchlistByPuuidAll(puuid, options?, region?, pacing?)
136
174
 
137
- RiftJS uses a region map to route requests correctly:
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
138
182
 
139
- - **Platform Routing** (e.g., Summoner V4):
183
+ ### getMatchesWithDetailsByPuuid(puuid, options?, region?, pacing?)
140
184
 
141
- - `EUW1` `euw1.api.riotgames.com`
142
- - `NA1` → `na1.api.riotgames.com`
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[]`
143
194
 
144
- - **Shard Routing** (e.g., Account V1, Match V5):
195
+ ## DataDragon
145
196
 
146
- - `EUW1` `europe.api.riotgames.com`
147
- - `NA1` → `americas.api.riotgames.com`
197
+ ### new DataDragon(version?, locale?)
148
198
 
149
- Supported regions: `BR1`, `EUN1`, `EUW1`, `JP1`, `KR`, `LA1`, `LA2`, `NA1`, `OC1`, `TR1`, `RU`, `PH2`, `SG2`, `TH2`, `TW2`, `VN2`.
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`
150
204
 
151
- ## Keywords
205
+ ### getChampions()
152
206
 
153
- - riot-api
154
- - league-of-legends
155
- - lol-api
156
- - datadragon
157
- - summoner
158
- - match-history
159
- - game-data
160
- - node-js
161
- - javascript
162
- - api-wrapper
207
+ - Output: Data Dragon champion payload (`champion.json`)
163
208
 
164
- ## Development
209
+ ### getItems()
165
210
 
166
- To contribute or run locally:
211
+ - Output: Data Dragon item payload (`item.json`)
167
212
 
168
- 1. Clone the repo:
213
+ ## Supported regions
169
214
 
170
- ```bash
171
- git clone https://github.com/timmsy1998/RiftJS.git
172
- cd RiftJS
173
- ```
215
+ Supported `REGION` / `region` values:
174
216
 
175
- 2. Install dependencies:
217
+ `BR1`, `EUN1`, `EUW1`, `JP1`, `KR`, `LA1`, `LA2`, `NA1`, `OC1`, `TR1`, `RU`, `PH2`, `SG2`, `TH2`, `TW2`, `VN2`
176
218
 
177
- ```bash
178
- npm install
179
- ```
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`.
180
222
 
181
- 3. Create a `.env` file (see [Setup](#setup)).
182
- 4. Build the package:
223
+ ## Error behavior
183
224
 
184
- ```bash
185
- npm run build
186
- ```
225
+ RiftJS normalizes errors to plain `Error` objects with readable messages:
187
226
 
188
- 5. Run endpoint checks:
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>`
189
231
 
190
- ```bash
191
- npm test
192
- ```
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
+ ```
193
274
 
194
- - Riot API calls run when `TEST_RIOT_ID` is set.
195
- - Data Dragon calls always run.
275
+ Compiled output is written to `dist/`.
196
276
 
197
277
  ## License
198
278
 
199
- MIT License © 2025 James Timms. See [LICENSE](LICENSE) for details.
279
+ MIT License © 2025 James Timms. See [LICENSE](LICENSE).
200
280
 
201
281
  ## Links
202
282
 
203
- - **npm Registry**: [https://www.npmjs.com/package/@timmsy/riftjs](https://www.npmjs.com/package/@timmsy/riftjs)
204
- - **GitHub Repository**: [https://github.com/timmsy1998/RiftJS](https://github.com/timmsy1998/RiftJS)
205
- - **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/
@@ -7,6 +7,7 @@ exports.default = dataDragonEndpoints;
7
7
  const axios_1 = __importDefault(require("axios"));
8
8
  function dataDragonEndpoints(baseURLOrResolver) {
9
9
  const resolveBaseURL = async () => {
10
+ // Maintainer note (Timmsy): allow either a fixed URL or lazy resolver so callers can choose version strategy.
10
11
  if (typeof baseURLOrResolver === 'function') {
11
12
  return baseURLOrResolver();
12
13
  }
@@ -14,6 +14,7 @@ const withRankMetrics = (entry) => {
14
14
  return { ...entry, winRate };
15
15
  };
16
16
  const coerceRegion = (region, regionMap) => {
17
+ // Maintainer note (Timmsy): region overrides are accepted per-call, but must always match our known map.
17
18
  const upper = region.toUpperCase();
18
19
  if (!regionMap[upper])
19
20
  throw new Error(`Invalid region: ${region}`);
@@ -113,6 +114,7 @@ function riotEndpoints({ client, defaultRegion, regionMap, handleError, }) {
113
114
  }
114
115
  };
115
116
  const getMatchlistByPuuidAll = async (puuid, options = {}, region = defaultRegion, pacing = {}) => {
117
+ // Maintainer note (Timmsy): defaults are intentionally conservative to reduce accidental rate-limit spikes.
116
118
  const baseStart = Number.isInteger(options.start) ? options.start : 0;
117
119
  const pageDelayMs = Number.isInteger(pacing.delayMs) ? pacing.delayMs : 1250;
118
120
  const maxMatches = Number.isInteger(pacing.maxMatches) && Number(pacing.maxMatches) >= 0 ? Number(pacing.maxMatches) : null;
@@ -139,6 +141,7 @@ function riotEndpoints({ client, defaultRegion, regionMap, handleError, }) {
139
141
  return allMatchIds;
140
142
  };
141
143
  const getMatchesWithDetailsByPuuid = async (puuid, options = {}, region = defaultRegion, pacing = {}) => {
144
+ // Maintainer note (Timmsy): details are fetched sequentially on purpose for predictable pacing.
142
145
  const pageDelayMs = Number.isInteger(pacing.pageDelayMs) ? pacing.pageDelayMs : 1250;
143
146
  const detailDelayMs = Number.isInteger(pacing.detailDelayMs) ? pacing.detailDelayMs : 1250;
144
147
  const maxMatches = Number.isInteger(pacing.maxMatches) && Number(pacing.maxMatches) >= 0 ? Number(pacing.maxMatches) : null;
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ const regionMap = {
27
27
  VN2: { platform: 'vn2.api.riotgames.com', shard: 'sea.api.riotgames.com' },
28
28
  };
29
29
  const parseRegion = (region) => {
30
+ // Maintainer note (Timmsy): fail fast on bad region input so routing bugs are obvious immediately.
30
31
  const upper = region.toUpperCase();
31
32
  if (!regionMap[upper])
32
33
  throw new Error(`Invalid region: ${region}`);
@@ -58,6 +59,7 @@ class RiotAPI {
58
59
  this.client = axios_1.default.create({
59
60
  headers: { 'X-Riot-Token': this.apiKey },
60
61
  });
62
+ // Maintainer note (Timmsy): keep endpoint methods attached here so the class API stays flat for consumers.
61
63
  Object.assign(this, (0, riot_1.default)({
62
64
  client: this.client,
63
65
  defaultRegion: this.region,
@@ -80,6 +82,7 @@ class DataDragon {
80
82
  return this.baseURL;
81
83
  if (this.baseURLPromise)
82
84
  return this.baseURLPromise;
85
+ // Maintainer note (Timmsy): share one in-flight resolver to avoid duplicate version requests under concurrency.
83
86
  this.baseURLPromise = (async () => {
84
87
  if (!this.version) {
85
88
  const response = await axios_1.default.get('https://ddragon.leagueoflegends.com/api/versions.json');
@@ -38,6 +38,7 @@ async function run() {
38
38
  console.log('[PASS] getMatchesWithDetailsByPuuid:', withDetails.matches.length, 'matches');
39
39
  }
40
40
  else {
41
+ // Maintainer note (Timmsy): no-match accounts are valid, so keep this as a skip rather than a failure.
41
42
  console.log('[SKIP] Match-by-id/timeline/all/details checks: no matches returned');
42
43
  }
43
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timmsy/riftjs",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
@@ -19,7 +19,7 @@
19
19
  "build": "tsc -p tsconfig.json",
20
20
  "test": "npm run test:endpoints",
21
21
  "test:endpoints": "npm run build && node dist/test-endpoints.js",
22
- "prepublishOnly": "npm run build"
22
+ "prepack": "npm run build"
23
23
  },
24
24
  "dependencies": {
25
25
  "axios": "^1.7.7",