@valoranchi/riot-client 0.3.0 → 0.5.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.
Files changed (261) hide show
  1. package/README.md +20 -1
  2. package/dist/RiotClient.d.ts +8 -1
  3. package/dist/RiotClient.d.ts.map +1 -1
  4. package/dist/RiotClient.js +18 -3
  5. package/dist/RiotClient.js.map +1 -1
  6. package/dist/analysis/collectionValue.d.ts +4 -0
  7. package/dist/analysis/collectionValue.d.ts.map +1 -0
  8. package/dist/analysis/collectionValue.js +119 -0
  9. package/dist/analysis/collectionValue.js.map +1 -0
  10. package/dist/analysis/loadoutDiff.d.ts +6 -0
  11. package/dist/analysis/loadoutDiff.d.ts.map +1 -0
  12. package/dist/analysis/loadoutDiff.js +258 -0
  13. package/dist/analysis/loadoutDiff.js.map +1 -0
  14. package/dist/analysis/matchSync.d.ts +8 -0
  15. package/dist/analysis/matchSync.d.ts.map +1 -0
  16. package/dist/analysis/matchSync.js +66 -0
  17. package/dist/analysis/matchSync.js.map +1 -0
  18. package/dist/analysis/performanceSummary.d.ts +4 -0
  19. package/dist/analysis/performanceSummary.d.ts.map +1 -0
  20. package/dist/analysis/performanceSummary.js +184 -0
  21. package/dist/analysis/performanceSummary.js.map +1 -0
  22. package/dist/analysis/playerAssessment.d.ts +10 -0
  23. package/dist/analysis/playerAssessment.d.ts.map +1 -0
  24. package/dist/analysis/playerAssessment.js +47 -0
  25. package/dist/analysis/playerAssessment.js.map +1 -0
  26. package/dist/analysis/ratingTrend.d.ts +5 -0
  27. package/dist/analysis/ratingTrend.d.ts.map +1 -0
  28. package/dist/analysis/ratingTrend.js +70 -0
  29. package/dist/analysis/ratingTrend.js.map +1 -0
  30. package/dist/analysis/storeHistory.d.ts +6 -0
  31. package/dist/analysis/storeHistory.d.ts.map +1 -0
  32. package/dist/analysis/storeHistory.js +74 -0
  33. package/dist/analysis/storeHistory.js.map +1 -0
  34. package/dist/analysis/wishlist.d.ts +5 -0
  35. package/dist/analysis/wishlist.d.ts.map +1 -0
  36. package/dist/analysis/wishlist.js +122 -0
  37. package/dist/analysis/wishlist.js.map +1 -0
  38. package/dist/bin.js +3 -1
  39. package/dist/bin.js.map +1 -1
  40. package/dist/catalogue/Catalogue.d.ts +1 -0
  41. package/dist/catalogue/Catalogue.d.ts.map +1 -1
  42. package/dist/catalogue/Catalogue.js +11 -0
  43. package/dist/catalogue/Catalogue.js.map +1 -1
  44. package/dist/catalogue/ValorantApi.d.ts.map +1 -1
  45. package/dist/catalogue/ValorantApi.js +1 -1
  46. package/dist/catalogue/ValorantApi.js.map +1 -1
  47. package/dist/cli.d.ts +15 -9
  48. package/dist/cli.d.ts.map +1 -1
  49. package/dist/cli.js +371 -46
  50. package/dist/cli.js.map +1 -1
  51. package/dist/client/AccountService.d.ts +6 -1
  52. package/dist/client/AccountService.d.ts.map +1 -1
  53. package/dist/client/AccountService.js +39 -4
  54. package/dist/client/AccountService.js.map +1 -1
  55. package/dist/client/AccountValidator.d.ts.map +1 -1
  56. package/dist/client/AccountValidator.js +9 -3
  57. package/dist/client/AccountValidator.js.map +1 -1
  58. package/dist/client/ChatValidator.d.ts.map +1 -1
  59. package/dist/client/ChatValidator.js +2 -4
  60. package/dist/client/ChatValidator.js.map +1 -1
  61. package/dist/client/ClientContext.d.ts +5 -0
  62. package/dist/client/ClientContext.d.ts.map +1 -1
  63. package/dist/client/ClientContext.js.map +1 -1
  64. package/dist/client/LiveMatchService.d.ts +1 -1
  65. package/dist/client/LiveMatchService.d.ts.map +1 -1
  66. package/dist/client/LiveMatchService.js +30 -20
  67. package/dist/client/LiveMatchService.js.map +1 -1
  68. package/dist/client/LoadoutValidator.d.ts.map +1 -1
  69. package/dist/client/LoadoutValidator.js +1 -3
  70. package/dist/client/LoadoutValidator.js.map +1 -1
  71. package/dist/client/MatchService.d.ts +17 -1
  72. package/dist/client/MatchService.d.ts.map +1 -1
  73. package/dist/client/MatchService.js +123 -2
  74. package/dist/client/MatchService.js.map +1 -1
  75. package/dist/client/MatchValidator.d.ts.map +1 -1
  76. package/dist/client/MatchValidator.js.map +1 -1
  77. package/dist/client/OfficialService.d.ts +35 -0
  78. package/dist/client/OfficialService.d.ts.map +1 -0
  79. package/dist/client/OfficialService.js +141 -0
  80. package/dist/client/OfficialService.js.map +1 -0
  81. package/dist/client/PartyService.d.ts.map +1 -1
  82. package/dist/client/PartyService.js +3 -1
  83. package/dist/client/PartyService.js.map +1 -1
  84. package/dist/client/PartyValidator.d.ts.map +1 -1
  85. package/dist/client/PartyValidator.js +1 -2
  86. package/dist/client/PartyValidator.js.map +1 -1
  87. package/dist/client/SocialService.d.ts.map +1 -1
  88. package/dist/client/SocialService.js +4 -5
  89. package/dist/client/SocialService.js.map +1 -1
  90. package/dist/client/StoreService.d.ts +9 -1
  91. package/dist/client/StoreService.d.ts.map +1 -1
  92. package/dist/client/StoreService.js +90 -2
  93. package/dist/client/StoreService.js.map +1 -1
  94. package/dist/client/StoreValidator.d.ts.map +1 -1
  95. package/dist/client/StoreValidator.js +4 -2
  96. package/dist/client/StoreValidator.js.map +1 -1
  97. package/dist/client/api.d.ts +55 -1
  98. package/dist/client/api.d.ts.map +1 -1
  99. package/dist/collection/CustomGameConfigsBuilder.d.ts.map +1 -1
  100. package/dist/collection/CustomGameConfigsBuilder.js.map +1 -1
  101. package/dist/collection/LiveMatchBuilder.d.ts +2 -2
  102. package/dist/collection/LiveMatchBuilder.d.ts.map +1 -1
  103. package/dist/collection/LiveMatchBuilder.js +10 -8
  104. package/dist/collection/LiveMatchBuilder.js.map +1 -1
  105. package/dist/collection/LoadoutBuilder.d.ts.map +1 -1
  106. package/dist/collection/LoadoutBuilder.js +1 -1
  107. package/dist/collection/LoadoutBuilder.js.map +1 -1
  108. package/dist/collection/LoadoutWriter.d.ts.map +1 -1
  109. package/dist/collection/LoadoutWriter.js +0 -1
  110. package/dist/collection/LoadoutWriter.js.map +1 -1
  111. package/dist/collection/MmrBuilder.d.ts +1 -1
  112. package/dist/collection/MmrBuilder.d.ts.map +1 -1
  113. package/dist/collection/MmrBuilder.js +5 -2
  114. package/dist/collection/MmrBuilder.js.map +1 -1
  115. package/dist/collection/PlayerSettingsBuilder.d.ts.map +1 -1
  116. package/dist/collection/PlayerSettingsBuilder.js +1 -3
  117. package/dist/collection/PlayerSettingsBuilder.js.map +1 -1
  118. package/dist/collection/RankFit.d.ts +11 -0
  119. package/dist/collection/RankFit.d.ts.map +1 -0
  120. package/dist/collection/RankFit.js +56 -0
  121. package/dist/collection/RankFit.js.map +1 -0
  122. package/dist/errors.d.ts +5 -1
  123. package/dist/errors.d.ts.map +1 -1
  124. package/dist/errors.js +8 -1
  125. package/dist/errors.js.map +1 -1
  126. package/dist/formatError.d.ts +10 -0
  127. package/dist/formatError.d.ts.map +1 -0
  128. package/dist/formatError.js +29 -0
  129. package/dist/formatError.js.map +1 -0
  130. package/dist/index.d.ts +15 -4
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +13 -2
  133. package/dist/index.js.map +1 -1
  134. package/dist/local/ChatApi.d.ts.map +1 -1
  135. package/dist/local/ChatApi.js +3 -1
  136. package/dist/local/ChatApi.js.map +1 -1
  137. package/dist/local/RiotSocket.d.ts.map +1 -1
  138. package/dist/local/RiotSocket.js.map +1 -1
  139. package/dist/mcp/McpServer.d.ts +21 -0
  140. package/dist/mcp/McpServer.d.ts.map +1 -0
  141. package/dist/mcp/McpServer.js +135 -0
  142. package/dist/mcp/McpServer.js.map +1 -0
  143. package/dist/mcp/index.d.ts +4 -0
  144. package/dist/mcp/index.d.ts.map +1 -0
  145. package/dist/mcp/index.js +3 -0
  146. package/dist/mcp/index.js.map +1 -0
  147. package/dist/mcp/tools.d.ts +9 -0
  148. package/dist/mcp/tools.d.ts.map +1 -0
  149. package/dist/mcp/tools.js +83 -0
  150. package/dist/mcp/tools.js.map +1 -0
  151. package/dist/mcp/types.d.ts +46 -0
  152. package/dist/mcp/types.d.ts.map +1 -0
  153. package/dist/mcp/types.js +2 -0
  154. package/dist/mcp/types.js.map +1 -0
  155. package/dist/model/index.d.ts +201 -0
  156. package/dist/model/index.d.ts.map +1 -1
  157. package/dist/official/OfficialApi.d.ts +35 -0
  158. package/dist/official/OfficialApi.d.ts.map +1 -0
  159. package/dist/official/OfficialApi.js +148 -0
  160. package/dist/official/OfficialApi.js.map +1 -0
  161. package/dist/official/OfficialMatchAdapter.d.ts +11 -0
  162. package/dist/official/OfficialMatchAdapter.d.ts.map +1 -0
  163. package/dist/official/OfficialMatchAdapter.js +157 -0
  164. package/dist/official/OfficialMatchAdapter.js.map +1 -0
  165. package/dist/official/RateLimiter.d.ts +20 -0
  166. package/dist/official/RateLimiter.d.ts.map +1 -0
  167. package/dist/official/RateLimiter.js +56 -0
  168. package/dist/official/RateLimiter.js.map +1 -0
  169. package/dist/official/types.d.ts +214 -0
  170. package/dist/official/types.d.ts.map +1 -0
  171. package/dist/official/types.js +2 -0
  172. package/dist/official/types.js.map +1 -0
  173. package/dist/raw.d.ts +4 -0
  174. package/dist/raw.d.ts.map +1 -1
  175. package/dist/raw.js +4 -0
  176. package/dist/raw.js.map +1 -1
  177. package/dist/riot/HttpGateway.d.ts.map +1 -1
  178. package/dist/riot/HttpGateway.js +9 -2
  179. package/dist/riot/HttpGateway.js.map +1 -1
  180. package/dist/riot/ResponseCache.d.ts +2 -0
  181. package/dist/riot/ResponseCache.d.ts.map +1 -1
  182. package/dist/riot/ResponseCache.js +9 -5
  183. package/dist/riot/ResponseCache.js.map +1 -1
  184. package/dist/riot/RiotApi.d.ts.map +1 -1
  185. package/dist/riot/RiotApi.js.map +1 -1
  186. package/dist/riot/types.d.ts.map +1 -1
  187. package/dist/serve/index.d.ts +7 -0
  188. package/dist/serve/index.d.ts.map +1 -0
  189. package/dist/serve/index.js +6 -0
  190. package/dist/serve/index.js.map +1 -0
  191. package/dist/serve/indexHtml.d.ts +2 -0
  192. package/dist/serve/indexHtml.d.ts.map +1 -0
  193. package/dist/serve/indexHtml.js +36 -0
  194. package/dist/serve/indexHtml.js.map +1 -0
  195. package/dist/serve/openapi.d.ts +2 -0
  196. package/dist/serve/openapi.d.ts.map +1 -0
  197. package/dist/serve/openapi.js +125 -0
  198. package/dist/serve/openapi.js.map +1 -0
  199. package/dist/serve/routes.d.ts +9 -0
  200. package/dist/serve/routes.d.ts.map +1 -0
  201. package/dist/serve/routes.js +1631 -0
  202. package/dist/serve/routes.js.map +1 -0
  203. package/dist/serve/server.d.ts +6 -0
  204. package/dist/serve/server.d.ts.map +1 -0
  205. package/dist/serve/server.js +149 -0
  206. package/dist/serve/server.js.map +1 -0
  207. package/dist/serve/sse.d.ts +4 -0
  208. package/dist/serve/sse.d.ts.map +1 -0
  209. package/dist/serve/sse.js +89 -0
  210. package/dist/serve/sse.js.map +1 -0
  211. package/dist/serve/types.d.ts +32 -0
  212. package/dist/serve/types.d.ts.map +1 -0
  213. package/dist/serve/types.js +2 -0
  214. package/dist/serve/types.js.map +1 -0
  215. package/dist/version.d.ts +2 -0
  216. package/dist/version.d.ts.map +1 -0
  217. package/dist/version.js +12 -0
  218. package/dist/version.js.map +1 -0
  219. package/dist/watch/AsyncQueue.d.ts +13 -0
  220. package/dist/watch/AsyncQueue.d.ts.map +1 -0
  221. package/dist/watch/AsyncQueue.js +50 -0
  222. package/dist/watch/AsyncQueue.js.map +1 -0
  223. package/dist/watch/FriendsWatcher.d.ts +26 -0
  224. package/dist/watch/FriendsWatcher.d.ts.map +1 -0
  225. package/dist/watch/FriendsWatcher.js +152 -0
  226. package/dist/watch/FriendsWatcher.js.map +1 -0
  227. package/dist/watch/MatchWatcher.d.ts +44 -0
  228. package/dist/watch/MatchWatcher.d.ts.map +1 -0
  229. package/dist/watch/MatchWatcher.js +272 -0
  230. package/dist/watch/MatchWatcher.js.map +1 -0
  231. package/dist/watch/StoreWatcher.d.ts +27 -0
  232. package/dist/watch/StoreWatcher.d.ts.map +1 -0
  233. package/dist/watch/StoreWatcher.js +116 -0
  234. package/dist/watch/StoreWatcher.js.map +1 -0
  235. package/dist/watch/WebhookNotifier.d.ts +8 -0
  236. package/dist/watch/WebhookNotifier.d.ts.map +1 -0
  237. package/dist/watch/WebhookNotifier.js +42 -0
  238. package/dist/watch/WebhookNotifier.js.map +1 -0
  239. package/dist/watch/index.d.ts +26 -0
  240. package/dist/watch/index.d.ts.map +1 -0
  241. package/dist/watch/index.js +31 -0
  242. package/dist/watch/index.js.map +1 -0
  243. package/dist/watch/types.d.ts +114 -0
  244. package/dist/watch/types.d.ts.map +1 -0
  245. package/dist/watch/types.js +2 -0
  246. package/dist/watch/types.js.map +1 -0
  247. package/package.json +17 -5
  248. package/schema/CollectionValue.json +153 -0
  249. package/schema/LiveMatch.json +8 -1
  250. package/schema/LoadoutDiff.json +73 -0
  251. package/schema/MatchSyncResult.json +54 -0
  252. package/schema/Mmr.json +38 -1
  253. package/schema/OfficialAccount.json +25 -0
  254. package/schema/OfficialProfile.json +354 -0
  255. package/schema/PerformanceSummary.json +284 -0
  256. package/schema/PlayerAssessment.json +48 -0
  257. package/schema/RatingTrend.json +107 -0
  258. package/schema/StoreHistory.json +61 -0
  259. package/schema/Wishlist.json +35 -0
  260. package/schema/WishlistCheck.json +67 -0
  261. package/schema/WishlistHit.json +51 -0
package/dist/cli.js CHANGED
@@ -1,12 +1,16 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { parseArgs } from "node:util";
3
3
  import { RiotClientError, ValidationError } from "./errors.js";
4
+ import { PACKAGE_VERSION } from "./version.js";
5
+ import { formatError } from "./formatError.js";
6
+ import { McpServer } from "./mcp/index.js";
4
7
  import { RiotClient } from "./RiotClient.js";
5
8
  export const USAGE = `Usage: riotclient <command> [options]
6
9
 
7
10
  Account:
8
11
  whoami Print signed-in player profile and region
9
12
  owned-items Print owned inventory items
13
+ collection-value Calculate estimated VP and Radianite value of owned collection
10
14
  loadout Print currently equipped loadout
11
15
  wallet Print VP, Radianite, and Kingdom Credits balances
12
16
  xp Print account level, XP progression and recent match XP history
@@ -21,6 +25,9 @@ Account:
21
25
  settings-save Save player settings from JSON file (<file.json>, requires --yes --confirm)
22
26
  equip Equip skins, buddies, sprays, card, title, border, flex (dry-run, --yes to apply)
23
27
  equip-collection Equip a collection of skins (<skinUuid,...>) (dry-run, --yes to apply)
28
+ loadout-export Export current loadout as a preset JSON
29
+ loadout-diff Compare current loadout against preset JSON file (<preset.json>)
30
+ loadout-apply Apply loadout preset from JSON file (<preset.json>, dry-run, --yes to apply)
24
31
  contract-activate Activate an agent contract (<uuid>) (dry-run, --yes to apply)
25
32
  favourite-add Add skin to favourites (<skin>) (dry-run, --yes to apply)
26
33
  favourite-remove Remove skin from favourites (<skin>) (dry-run, --yes to apply)
@@ -44,13 +51,17 @@ Social:
44
51
 
45
52
  Store:
46
53
  store Print storefront (daily, night market, bundles, accessories)
54
+ store-history Print recorded daily store rotations [--days <n>]
55
+ store-seen Print when a skin was last seen in daily store (<skin>)
47
56
  offers Print full item offers catalog and pricing
48
57
  order <id> Print store order details
49
58
  night-market-reveal Reveal night market offers (dry-run, --yes to apply)
50
59
  buy Purchase offer or bundle (--offer <id> | --bundle <id>, requires --yes --confirm)
60
+ wishlist Print skin wishlist or manage items (add <skin>, remove <skin>, check)
51
61
 
52
62
  Matches:
53
63
  matches Print recent match history summaries
64
+ matches-sync Synchronize match history to local cache [--pages <n>]
54
65
  match <id> Print full match details by ID
55
66
  mmr Print current rank, rating, and MMR breakdown
56
67
  rank-history Print competitive rating adjustments and tier changes
@@ -61,6 +72,9 @@ Matches:
61
72
  leaderboard Print competitive leaderboard [--season] [--start] [--size] [--query]
62
73
  content Print active act, episode and live events
63
74
  premier Print premier eligibility, roster, and season info
75
+ trend Print competitive rating streak, net RR gains, and climbing pace
76
+ summary Print player performance summary across recent matches [--count n] [--queue q]
77
+ assess [puuid] Assess player rank anomalies, streaks, and warning flags
64
78
  agent-select Select an agent in pregame (<uuid|name>) (dry-run, --yes to apply)
65
79
  agent-lock Lock in an agent in pregame (<uuid|name>) (dry-run, --yes to apply)
66
80
  dodge Dodge pregame agent select (requires --yes --confirm)
@@ -102,6 +116,22 @@ Raw (unsupported):
102
116
 
103
117
  Events:
104
118
  watch Stream real-time events as JSON lines until interrupted
119
+ watch store Stream store wishlist rotation hits until interrupted [--webhook <url>] [--interval <min>]
120
+ watch-match Stream match lifecycle events until interrupted
121
+ watch-friends Stream friend activity and presence events until interrupted
122
+
123
+ Server:
124
+ serve Start local HTTP server with SSE events and OpenAPI docs [--port 47800] [--host 127.0.0.1] [--allow-remote]
125
+ mcp Start Model Context Protocol (MCP) server over stdio for AI assistants
126
+
127
+ Official:
128
+ official account <name#tag> Print player PUUID and active shard
129
+ official matches <name#tag> Print player match history [--queue <q>] [--count <n>]
130
+ official match <id> Print full match details (--shard <shard> [--self <puuid>])
131
+ official leaderboard Print competitive leaderboard (--shard <shard> [--act <id>] [--start <n>] [--size <n>])
132
+ official status Print platform status and maintenance alerts (--shard <shard>)
133
+ official summary <name#tag> Print player performance summary [--queue <q>] [--count <n>]
134
+ official profile <name#tag> Print player scouting profile [--count <n>]
105
135
 
106
136
  Options:
107
137
  --yes Execute write command (default is dry-run)
@@ -138,19 +168,29 @@ Options:
138
168
  --only <events> Comma-separated list of event names to print
139
169
  --raw Include raw client event frames or unformatted settings
140
170
  --cid <id> Conversation ID for filtering messages or participants
171
+ --api-key <key> Riot Developer API key (or RIOT_API_KEY env)
172
+ --shard <shard> Riot shard (na, latam, br, eu, ap, kr)
173
+ --self <puuid> Player PUUID for self perspective in official match
174
+ --act <uuid> Act or season UUID for official leaderboard
141
175
  --language <lang> Catalogue language (default: en-US)
142
176
  --cache <seconds> Reuse Riot responses younger than this many seconds
177
+ --no-official-cache Disable official match disk cache
178
+ --webhook <url> Webhook URL for store alerts (Discord or generic)
179
+ --interval <min> Check interval in minutes for store watcher
180
+ --port <n> Port to bind HTTP server (default: 47800)
181
+ --host <ip> Host address to bind HTTP server (default: 127.0.0.1)
182
+ --allow-remote Allow binding HTTP server to non-loopback address
143
183
  --pretty Pretty-print JSON output
144
184
  --help Show usage instructions
145
185
  --version Show version number
146
186
  `;
147
- const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
148
187
  const ERROR_EXIT_CODES = {
149
188
  RIOT_CLIENT_NOT_RUNNING: 2,
150
189
  RIOT_CLIENT_NOT_READY: 3,
151
190
  REGION_UNKNOWN: 4,
152
191
  RIOT_API_ERROR: 5,
153
192
  VALIDATION: 6,
193
+ OFFICIAL_API_KEY_MISSING: 7,
154
194
  };
155
195
  export function exitCodeForError(error) {
156
196
  if (error instanceof RiotClientError) {
@@ -158,33 +198,7 @@ export function exitCodeForError(error) {
158
198
  }
159
199
  return 1;
160
200
  }
161
- export function formatError(error) {
162
- if (error instanceof ValidationError) {
163
- return {
164
- error: {
165
- code: error.code,
166
- reason: error.reason,
167
- message: error.message,
168
- details: error.details,
169
- },
170
- };
171
- }
172
- if (error instanceof RiotClientError) {
173
- return {
174
- error: {
175
- code: error.code,
176
- message: error.message,
177
- },
178
- };
179
- }
180
- const message = error instanceof Error ? error.message : String(error);
181
- return {
182
- error: {
183
- code: "UNKNOWN_ERROR",
184
- message,
185
- },
186
- };
187
- }
201
+ export { formatError };
188
202
  export function formatWatchLine(event, data, at = new Date().toISOString()) {
189
203
  return JSON.stringify({
190
204
  event,
@@ -240,6 +254,111 @@ export async function runWatch(client, options = {}) {
240
254
  await client.close();
241
255
  return 0;
242
256
  }
257
+ export async function runWatchMatch(client) {
258
+ const watcher = client.watch.match();
259
+ const onSignal = () => {
260
+ process.off("SIGINT", onSignal);
261
+ process.off("SIGTERM", onSignal);
262
+ watcher.stop();
263
+ };
264
+ process.on("SIGINT", onSignal);
265
+ process.on("SIGTERM", onSignal);
266
+ try {
267
+ for await (const item of watcher) {
268
+ process.stdout.write(`${JSON.stringify(item)}\n`);
269
+ }
270
+ }
271
+ finally {
272
+ process.off("SIGINT", onSignal);
273
+ process.off("SIGTERM", onSignal);
274
+ watcher.stop();
275
+ await client.close();
276
+ }
277
+ return 0;
278
+ }
279
+ export async function runWatchFriends(client) {
280
+ const watcher = client.watch.friends();
281
+ const onSignal = () => {
282
+ process.off("SIGINT", onSignal);
283
+ process.off("SIGTERM", onSignal);
284
+ watcher.stop();
285
+ };
286
+ process.on("SIGINT", onSignal);
287
+ process.on("SIGTERM", onSignal);
288
+ try {
289
+ for await (const item of watcher) {
290
+ process.stdout.write(`${JSON.stringify(item)}\n`);
291
+ }
292
+ }
293
+ finally {
294
+ process.off("SIGINT", onSignal);
295
+ process.off("SIGTERM", onSignal);
296
+ watcher.stop();
297
+ await client.close();
298
+ }
299
+ return 0;
300
+ }
301
+ export async function runWatchStore(client, options = {}) {
302
+ const intervalMs = options.intervalMinutes && options.intervalMinutes > 0
303
+ ? options.intervalMinutes * 60 * 1000
304
+ : undefined;
305
+ const watcher = client.watch.store({
306
+ webhook: options.webhook,
307
+ intervalMs,
308
+ });
309
+ const onSignal = () => {
310
+ process.off("SIGINT", onSignal);
311
+ process.off("SIGTERM", onSignal);
312
+ watcher.stop();
313
+ };
314
+ process.on("SIGINT", onSignal);
315
+ process.on("SIGTERM", onSignal);
316
+ try {
317
+ for await (const item of watcher) {
318
+ process.stdout.write(`${JSON.stringify(item)}\n`);
319
+ }
320
+ }
321
+ finally {
322
+ process.off("SIGINT", onSignal);
323
+ process.off("SIGTERM", onSignal);
324
+ watcher.stop();
325
+ await client.close();
326
+ }
327
+ return 0;
328
+ }
329
+ export async function runServe(client, options = {}) {
330
+ const server = await client.serve(options);
331
+ process.stdout.write(`Riot Client HTTP server listening on ${server.url}\n`);
332
+ await new Promise((resolve) => {
333
+ const onSignal = () => {
334
+ process.off("SIGINT", onSignal);
335
+ process.off("SIGTERM", onSignal);
336
+ resolve();
337
+ };
338
+ process.on("SIGINT", onSignal);
339
+ process.on("SIGTERM", onSignal);
340
+ });
341
+ await server.close();
342
+ await client.close();
343
+ return 0;
344
+ }
345
+ export async function runMcp(client) {
346
+ const server = new McpServer(client);
347
+ const onSignal = () => {
348
+ server.close();
349
+ };
350
+ process.on("SIGINT", onSignal);
351
+ process.on("SIGTERM", onSignal);
352
+ try {
353
+ await server.start();
354
+ }
355
+ finally {
356
+ process.off("SIGINT", onSignal);
357
+ process.off("SIGTERM", onSignal);
358
+ await client.close();
359
+ }
360
+ return 0;
361
+ }
243
362
  const UNKNOWN_COMMAND = Symbol("UNKNOWN_COMMAND");
244
363
  function parseTarget(to) {
245
364
  if (to.includes("#"))
@@ -347,6 +466,8 @@ async function executeStandardCommand(client, command, options) {
347
466
  return client.account.whoami();
348
467
  case "owned-items":
349
468
  return client.account.ownedItems({ language: options?.language });
469
+ case "collection-value":
470
+ return client.account.collectionValue();
350
471
  case "loadout":
351
472
  return client.account.loadout();
352
473
  case "wallet":
@@ -377,10 +498,34 @@ async function executeStandardCommand(client, command, options) {
377
498
  return client.social.messages(options?.cid);
378
499
  case "store":
379
500
  return client.store.current({ language: options?.language });
501
+ case "store-history":
502
+ return client.store.history({ days: options?.days });
503
+ case "store-seen": {
504
+ const skin = requirePositional(pos, 1, "Usage: riotclient store-seen <skin>");
505
+ return client.store.seen(skin);
506
+ }
380
507
  case "offers":
381
508
  return client.store.offers();
382
509
  case "order":
383
510
  return client.store.order(requirePositional(pos, 1, "Usage: riotclient order <id>"));
511
+ case "wishlist": {
512
+ const action = pos[1];
513
+ if (!action || action === "list") {
514
+ return client.store.wishlist();
515
+ }
516
+ if (action === "add") {
517
+ const skin = requirePositional(pos, 2, "Usage: riotclient wishlist add <skin>");
518
+ return client.store.wishlistAdd(skin);
519
+ }
520
+ if (action === "remove") {
521
+ const skin = requirePositional(pos, 2, "Usage: riotclient wishlist remove <skin>");
522
+ return client.store.wishlistRemove(skin);
523
+ }
524
+ if (action === "check") {
525
+ return client.store.wishlistCheck();
526
+ }
527
+ throw new ValidationError("unknown-command", `Unknown wishlist action: ${action}`);
528
+ }
384
529
  case "client":
385
530
  return client.account.client();
386
531
  case "participants":
@@ -399,6 +544,8 @@ async function executeGameCommand(client, command, options) {
399
544
  switch (command) {
400
545
  case "matches":
401
546
  return client.matches.list({ count: options?.count, queue: options?.queue });
547
+ case "matches-sync":
548
+ return client.matches.sync({ maxPages: options?.pages });
402
549
  case "match":
403
550
  if (!options?.matchId)
404
551
  throw new Error("Missing match ID: riotclient match <id>");
@@ -426,6 +573,12 @@ async function executeGameCommand(client, command, options) {
426
573
  return client.matches.content();
427
574
  case "premier":
428
575
  return client.matches.premier();
576
+ case "trend":
577
+ return client.matches.trend({ count: options?.count });
578
+ case "summary":
579
+ return client.matches.summary({ count: options?.count, queue: options?.queue });
580
+ case "assess":
581
+ return client.matches.assess(pos[1]);
429
582
  case "party":
430
583
  return client.party.current();
431
584
  case "queues":
@@ -445,23 +598,33 @@ async function executeSocialWriteCommand(client, command, yes, pos, vals) {
445
598
  throw new ValidationError("invalid-argument", "Usage: riotclient send --to <puuid|name#tag|cid> --text <message>");
446
599
  }
447
600
  const target = parseTarget(to);
448
- return yes ? client.social.sendMessage(target, text) : client.social.validateSendMessage(target, text);
601
+ return yes
602
+ ? client.social.sendMessage(target, text)
603
+ : client.social.validateSendMessage(target, text);
449
604
  }
450
605
  case "friend-request": {
451
606
  const riotId = requirePositional(pos, 1, "Usage: riotclient friend-request <name#tag>");
452
- return yes ? client.social.sendFriendRequest(riotId) : client.social.validateSendFriendRequest(riotId);
607
+ return yes
608
+ ? client.social.sendFriendRequest(riotId)
609
+ : client.social.validateSendFriendRequest(riotId);
453
610
  }
454
611
  case "friend-accept": {
455
612
  const puuid = requirePositional(pos, 1, "Usage: riotclient friend-accept <puuid>");
456
- return yes ? client.social.acceptFriendRequest(puuid) : client.social.validateAcceptFriendRequest(puuid);
613
+ return yes
614
+ ? client.social.acceptFriendRequest(puuid)
615
+ : client.social.validateAcceptFriendRequest(puuid);
457
616
  }
458
617
  case "friend-decline": {
459
618
  const puuid = requirePositional(pos, 1, "Usage: riotclient friend-decline <puuid>");
460
- return yes ? client.social.declineFriendRequest(puuid) : client.social.validateDeclineFriendRequest(puuid);
619
+ return yes
620
+ ? client.social.declineFriendRequest(puuid)
621
+ : client.social.validateDeclineFriendRequest(puuid);
461
622
  }
462
623
  case "friend-cancel": {
463
624
  const puuid = requirePositional(pos, 1, "Usage: riotclient friend-cancel <puuid>");
464
- return yes ? client.social.cancelFriendRequest(puuid) : client.social.validateCancelFriendRequest(puuid);
625
+ return yes
626
+ ? client.social.cancelFriendRequest(puuid)
627
+ : client.social.validateCancelFriendRequest(puuid);
465
628
  }
466
629
  case "friend-remove": {
467
630
  const puuid = requirePositional(pos, 1, "Usage: riotclient friend-remove <puuid>");
@@ -506,15 +669,36 @@ async function executeAccountWriteCommand(client, command, yes, pos, vals) {
506
669
  }
507
670
  case "equip-collection": {
508
671
  const raw = pos.slice(1).join(",");
509
- const skinUuids = raw.split(",").map((s) => s.trim()).filter(Boolean);
672
+ const skinUuids = raw
673
+ .split(",")
674
+ .map((s) => s.trim())
675
+ .filter(Boolean);
510
676
  if (skinUuids.length === 0) {
511
677
  throw new ValidationError("invalid-argument", "Usage: riotclient equip-collection <skinUuid,...>");
512
678
  }
513
- return yes ? client.account.equipCollection(skinUuids) : client.account.validateEquipCollection(skinUuids);
679
+ return yes
680
+ ? client.account.equipCollection(skinUuids)
681
+ : client.account.validateEquipCollection(skinUuids);
682
+ }
683
+ case "loadout-export":
684
+ return client.account.exportLoadout();
685
+ case "loadout-diff": {
686
+ const file = requirePositional(pos, 1, "Usage: riotclient loadout-diff <preset.json>");
687
+ const content = JSON.parse(readFileSync(file, "utf-8"));
688
+ return client.account.diffLoadout(content);
689
+ }
690
+ case "loadout-apply": {
691
+ const file = requirePositional(pos, 1, "Usage: riotclient loadout-apply <preset.json> [--yes]");
692
+ const content = JSON.parse(readFileSync(file, "utf-8"));
693
+ return yes
694
+ ? client.account.equipPreset(content)
695
+ : client.account.validateEquipPreset(content);
514
696
  }
515
697
  case "contract-activate": {
516
698
  const uuid = requirePositional(pos, 1, "Usage: riotclient contract-activate <uuid>");
517
- return yes ? client.account.activateContract(uuid) : client.account.validateActivateContract(uuid);
699
+ return yes
700
+ ? client.account.activateContract(uuid)
701
+ : client.account.validateActivateContract(uuid);
518
702
  }
519
703
  case "favourite-add": {
520
704
  const skin = requirePositional(pos, 1, "Usage: riotclient favourite-add <skin>");
@@ -522,7 +706,9 @@ async function executeAccountWriteCommand(client, command, yes, pos, vals) {
522
706
  }
523
707
  case "favourite-remove": {
524
708
  const skin = requirePositional(pos, 1, "Usage: riotclient favourite-remove <skin>");
525
- return yes ? client.account.removeFavourite(skin) : client.account.validateRemoveFavourite(skin);
709
+ return yes
710
+ ? client.account.removeFavourite(skin)
711
+ : client.account.validateRemoveFavourite(skin);
526
712
  }
527
713
  case "privacy":
528
714
  return executePrivacyCommand(client, yes, vals);
@@ -574,8 +760,12 @@ async function executePartyCommand(client, command, options) {
574
760
  }
575
761
  case "party-code":
576
762
  return vals.revoke
577
- ? (yes ? client.party.revokeInviteCode() : client.party.validateRevokeInviteCode())
578
- : (yes ? client.party.createInviteCode() : client.party.validateCreateInviteCode());
763
+ ? yes
764
+ ? client.party.revokeInviteCode()
765
+ : client.party.validateRevokeInviteCode()
766
+ : yes
767
+ ? client.party.createInviteCode()
768
+ : client.party.validateCreateInviteCode();
579
769
  case "party-join": {
580
770
  const target = requirePositional(pos, 1, "Usage: riotclient party-join <partyId|code>");
581
771
  const isPartyId = target.includes("-") || target.length >= 32;
@@ -586,7 +776,9 @@ async function executePartyCommand(client, command, options) {
586
776
  }
587
777
  case "party-ready": {
588
778
  const ready = parseBooleanFlag("ready", requirePositional(pos, 1, "Usage: riotclient party-ready on|off"));
589
- return yes ? client.party.setReady(Boolean(ready)) : client.party.validateSetReady(Boolean(ready));
779
+ return yes
780
+ ? client.party.setReady(Boolean(ready))
781
+ : client.party.validateSetReady(Boolean(ready));
590
782
  }
591
783
  case "party-queue": {
592
784
  const queue = requirePositional(pos, 1, "Usage: riotclient party-queue <queue>");
@@ -597,7 +789,9 @@ async function executePartyCommand(client, command, options) {
597
789
  if (access !== "open" && access !== "closed") {
598
790
  throw new ValidationError("invalid-argument", "Usage: riotclient party-access open|closed");
599
791
  }
600
- return yes ? client.party.setAccessibility(access) : client.party.validateSetAccessibility(access);
792
+ return yes
793
+ ? client.party.setAccessibility(access)
794
+ : client.party.validateSetAccessibility(access);
601
795
  }
602
796
  case "party-start":
603
797
  return yes ? client.party.startMatchmaking() : client.party.validateStartMatchmaking();
@@ -645,13 +839,20 @@ async function executePartyExtraCommand(client, command, yes, pos) {
645
839
  }
646
840
  case "party-servers": {
647
841
  const raw = requirePositional(pos, 1, "Usage: riotclient party-servers <id,...>");
648
- const ids = raw.split(",").map((s) => s.trim()).filter(Boolean);
649
- return yes ? client.party.setPreferredServers(ids) : client.party.validateSetPreferredServers(ids);
842
+ const ids = raw
843
+ .split(",")
844
+ .map((s) => s.trim())
845
+ .filter(Boolean);
846
+ return yes
847
+ ? client.party.setPreferredServers(ids)
848
+ : client.party.validateSetPreferredServers(ids);
650
849
  }
651
850
  case "party-moderator": {
652
851
  const puuid = requirePositional(pos, 1, "Usage: riotclient party-moderator <puuid> on|off");
653
852
  const mod = parseBooleanFlag("moderator", requirePositional(pos, 2, "Usage: riotclient party-moderator <puuid> on|off"));
654
- return yes ? client.party.setModerator(puuid, Boolean(mod)) : client.party.validateSetModerator(puuid, Boolean(mod));
853
+ return yes
854
+ ? client.party.setModerator(puuid, Boolean(mod))
855
+ : client.party.validateSetModerator(puuid, Boolean(mod));
655
856
  }
656
857
  case "party-refresh":
657
858
  return yes ? client.party.refresh() : client.party.validateRefresh();
@@ -660,7 +861,11 @@ async function executePartyExtraCommand(client, command, yes, pos) {
660
861
  }
661
862
  }
662
863
  function parseCustomGameRules(vals) {
663
- const ruleList = Array.isArray(vals.rule) ? vals.rule : vals.rule ? [String(vals.rule)] : [];
864
+ const ruleList = Array.isArray(vals.rule)
865
+ ? vals.rule
866
+ : vals.rule
867
+ ? [String(vals.rule)]
868
+ : [];
664
869
  const rules = {};
665
870
  for (const r of ruleList) {
666
871
  const idx = r.indexOf("=");
@@ -778,10 +983,85 @@ async function executeRawCommand(client, command, pos, vals) {
778
983
  throw new ValidationError("invalid-argument", `Unknown HTTP method: ${method}. Expected get, post, put, or delete`);
779
984
  }
780
985
  }
986
+ async function executeOfficialCommand(client, command, pos, vals) {
987
+ if (command !== "official") {
988
+ return UNKNOWN_COMMAND;
989
+ }
990
+ const sub = pos[1];
991
+ switch (sub) {
992
+ case "account": {
993
+ const riotId = pos[2];
994
+ if (!riotId) {
995
+ throw new ValidationError("missing-riot-id", "Riot ID required (e.g. Name#Tag)");
996
+ }
997
+ return client.official.account(riotId);
998
+ }
999
+ case "matches": {
1000
+ const riotId = pos[2];
1001
+ if (!riotId) {
1002
+ throw new ValidationError("missing-riot-id", "Riot ID required (e.g. Name#Tag)");
1003
+ }
1004
+ const count = vals.count !== undefined ? Number(vals.count) : undefined;
1005
+ const queue = vals.queue !== undefined ? String(vals.queue) : undefined;
1006
+ return client.official.matches(riotId, { count, queue });
1007
+ }
1008
+ case "match": {
1009
+ const matchId = pos[2];
1010
+ if (!matchId) {
1011
+ throw new ValidationError("missing-match-id", "Match ID required");
1012
+ }
1013
+ const shard = vals.shard !== undefined ? String(vals.shard) : undefined;
1014
+ if (!shard) {
1015
+ throw new ValidationError("missing-shard", "Shard required (--shard <shard>)");
1016
+ }
1017
+ const self = vals.self !== undefined ? String(vals.self) : undefined;
1018
+ return client.official.match(matchId, { shard, self });
1019
+ }
1020
+ case "leaderboard": {
1021
+ const shard = vals.shard !== undefined ? String(vals.shard) : undefined;
1022
+ if (!shard) {
1023
+ throw new ValidationError("missing-shard", "Shard required (--shard <shard>)");
1024
+ }
1025
+ const act = vals.act !== undefined ? String(vals.act) : undefined;
1026
+ const start = vals.start !== undefined ? Number(vals.start) : undefined;
1027
+ const size = vals.size !== undefined ? Number(vals.size) : undefined;
1028
+ return client.official.leaderboard({ shard, act, start, size });
1029
+ }
1030
+ case "status": {
1031
+ const shard = vals.shard !== undefined ? String(vals.shard) : undefined;
1032
+ if (!shard) {
1033
+ throw new ValidationError("missing-shard", "Shard required (--shard <shard>)");
1034
+ }
1035
+ return client.official.status(shard);
1036
+ }
1037
+ case "summary": {
1038
+ const riotId = pos[2];
1039
+ if (!riotId) {
1040
+ throw new ValidationError("missing-riot-id", "Riot ID required (e.g. Name#Tag)");
1041
+ }
1042
+ const count = vals.count !== undefined ? Number(vals.count) : undefined;
1043
+ const queue = vals.queue !== undefined ? String(vals.queue) : undefined;
1044
+ return client.official.summary(riotId, { count, queue });
1045
+ }
1046
+ case "profile": {
1047
+ const riotId = pos[2];
1048
+ if (!riotId) {
1049
+ throw new ValidationError("missing-riot-id", "Riot ID required (e.g. Name#Tag)");
1050
+ }
1051
+ const count = vals.count !== undefined ? Number(vals.count) : undefined;
1052
+ return client.official.profile(riotId, { count });
1053
+ }
1054
+ default:
1055
+ return UNKNOWN_COMMAND;
1056
+ }
1057
+ }
781
1058
  async function executeCommand(client, command, options) {
782
1059
  const pos = options?.positionals ?? [];
783
1060
  const vals = options?.rawValues ?? {};
784
1061
  const yes = Boolean(options?.yes);
1062
+ const official = await executeOfficialCommand(client, command, pos, vals);
1063
+ if (official !== UNKNOWN_COMMAND)
1064
+ return official;
785
1065
  const std = await executeStandardCommand(client, command, options);
786
1066
  if (std !== UNKNOWN_COMMAND)
787
1067
  return std;
@@ -854,11 +1134,23 @@ export async function runCli(args) {
854
1134
  server: { type: "string" },
855
1135
  rule: { type: "string", multiple: true },
856
1136
  body: { type: "string" },
1137
+ days: { type: "string" },
1138
+ pages: { type: "string" },
1139
+ port: { type: "string" },
1140
+ host: { type: "string" },
1141
+ "allow-remote": { type: "boolean", default: false },
1142
+ "api-key": { type: "string" },
1143
+ shard: { type: "string" },
1144
+ self: { type: "string" },
1145
+ act: { type: "string" },
1146
+ "no-official-cache": { type: "boolean", default: false },
1147
+ webhook: { type: "string" },
1148
+ interval: { type: "string" },
857
1149
  },
858
1150
  allowPositionals: true,
859
1151
  });
860
1152
  if (parsed.values.version) {
861
- process.stdout.write(`${packageJson.version}\n`);
1153
+ process.stdout.write(`${PACKAGE_VERSION}\n`);
862
1154
  return 0;
863
1155
  }
864
1156
  if (parsed.values.help || parsed.positionals.length === 0) {
@@ -867,17 +1159,48 @@ export async function runCli(args) {
867
1159
  }
868
1160
  const command = parsed.positionals[0];
869
1161
  const cacheSeconds = Number(parsed.values.cache ?? 0);
1162
+ const apiKey = parsed.values["api-key"]
1163
+ ? String(parsed.values["api-key"])
1164
+ : process.env.RIOT_API_KEY;
1165
+ const officialCache = parsed.values["no-official-cache"] ? false : undefined;
870
1166
  const client = new RiotClient({
871
1167
  language: parsed.values.language,
872
1168
  responseCache: cacheSeconds > 0 ? { ttlMs: cacheSeconds * 1000 } : undefined,
1169
+ officialApiKey: apiKey,
1170
+ officialCache,
873
1171
  });
874
1172
  try {
875
1173
  if (command === "watch") {
1174
+ if (parsed.positionals[1] === "store") {
1175
+ const intervalMinutes = parsed.values.interval ? Number(parsed.values.interval) : undefined;
1176
+ const webhook = parsed.values.webhook ? String(parsed.values.webhook) : undefined;
1177
+ return await runWatchStore(client, { webhook, intervalMinutes });
1178
+ }
876
1179
  return await runWatch(client, {
877
1180
  only: parsed.values.only,
878
1181
  raw: parsed.values.raw,
879
1182
  });
880
1183
  }
1184
+ if (command === "watch-store") {
1185
+ const intervalMinutes = parsed.values.interval ? Number(parsed.values.interval) : undefined;
1186
+ const webhook = parsed.values.webhook ? String(parsed.values.webhook) : undefined;
1187
+ return await runWatchStore(client, { webhook, intervalMinutes });
1188
+ }
1189
+ if (command === "watch-match") {
1190
+ return await runWatchMatch(client);
1191
+ }
1192
+ if (command === "watch-friends") {
1193
+ return await runWatchFriends(client);
1194
+ }
1195
+ if (command === "serve") {
1196
+ const port = parsed.values.port ? Number(parsed.values.port) : undefined;
1197
+ const host = parsed.values.host;
1198
+ const allowRemote = Boolean(parsed.values["allow-remote"]);
1199
+ return await runServe(client, { port, host, allowRemote });
1200
+ }
1201
+ if (command === "mcp") {
1202
+ return await runMcp(client);
1203
+ }
881
1204
  const count = parsed.values.count ? Number(parsed.values.count) : undefined;
882
1205
  const loadouts = parsed.values["no-loadouts"] ? false : (parsed.values.loadouts ?? true);
883
1206
  const result = await executeCommand(client, command, {
@@ -889,6 +1212,8 @@ export async function runCli(args) {
889
1212
  loadouts,
890
1213
  matchId: command === "match" ? parsed.positionals[1] : undefined,
891
1214
  yes: Boolean(parsed.values.yes),
1215
+ days: parsed.values.days ? Number(parsed.values.days) : undefined,
1216
+ pages: parsed.values.pages ? Number(parsed.values.pages) : undefined,
892
1217
  positionals: parsed.positionals,
893
1218
  rawValues: parsed.values,
894
1219
  });