halo-infinite-api 13.0.0 → 14.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.
Files changed (78) hide show
  1. package/coverage/lcov-report/authentication/halo-authentication-client.ts.html +8 -5
  2. package/coverage/lcov-report/authentication/index.html +7 -7
  3. package/coverage/lcov-report/authentication/xbox-authentication-client.ts.html +38 -11
  4. package/coverage/lcov-report/core/halo-infinite-client.ts.html +82 -31
  5. package/coverage/lcov-report/core/index.html +19 -19
  6. package/coverage/lcov-report/core/request-policy.ts.html +1 -1
  7. package/coverage/lcov-report/core/token-persisters/in-memory-token-persister.ts.html +1 -1
  8. package/coverage/lcov-report/core/token-persisters/index.html +1 -1
  9. package/coverage/lcov-report/core/token-persisters/local-storage-token-persister.ts.html +1 -1
  10. package/coverage/lcov-report/core/token-persisters/node-fs-token-persister.ts.html +1 -1
  11. package/coverage/lcov-report/core/token-persisters/token-persister.ts.html +1 -1
  12. package/coverage/lcov-report/core/token-providers/auto-token-provider.ts.html +22 -49
  13. package/coverage/lcov-report/core/token-providers/index.html +37 -7
  14. package/coverage/lcov-report/core/token-providers/spartan-token-provider.ts.html +106 -0
  15. package/coverage/lcov-report/core/token-providers/{spartan-token-providers/static-xsts-ticket-token-spartan-token-provider.ts.html → static-xsts-ticket-token-spartan-token-provider.ts.html} +25 -52
  16. package/coverage/lcov-report/core/token-providers/xbox-token-provider.ts.html +1 -1
  17. package/coverage/lcov-report/core/xbox-client.ts.html +1 -1
  18. package/coverage/lcov-report/endpoints/halo-core-endpoints.ts.html +1 -1
  19. package/coverage/lcov-report/endpoints/index.html +1 -1
  20. package/coverage/lcov-report/index.html +32 -47
  21. package/coverage/lcov-report/models/halo-infinite/api-formatted-date.ts.html +1 -1
  22. package/coverage/lcov-report/models/halo-infinite/asset-kind.ts.html +1 -1
  23. package/coverage/lcov-report/models/halo-infinite/asset-version-link.ts.html +1 -1
  24. package/coverage/lcov-report/models/halo-infinite/asset.ts.html +1 -1
  25. package/coverage/lcov-report/models/halo-infinite/ban-summary.ts.html +1 -1
  26. package/coverage/lcov-report/models/halo-infinite/game-variant-category.ts.html +1 -1
  27. package/coverage/lcov-report/models/halo-infinite/index.html +23 -8
  28. package/coverage/lcov-report/models/halo-infinite/match-info.ts.html +1 -1
  29. package/coverage/lcov-report/models/halo-infinite/match-outcome.ts.html +1 -1
  30. package/coverage/lcov-report/models/halo-infinite/match-skill.ts.html +1 -1
  31. package/coverage/lcov-report/models/halo-infinite/match-stats.ts.html +1 -1
  32. package/coverage/lcov-report/models/halo-infinite/match-type.ts.html +1 -1
  33. package/coverage/lcov-report/models/halo-infinite/matches-privacy.ts.html +1 -1
  34. package/coverage/lcov-report/models/halo-infinite/medals-metadata-file.ts.html +1 -1
  35. package/coverage/lcov-report/models/halo-infinite/player-match-history.ts.html +1 -1
  36. package/coverage/lcov-report/models/halo-infinite/playlist-csr-container.ts.html +1 -1
  37. package/coverage/lcov-report/models/halo-infinite/playlist-csr.ts.html +1 -1
  38. package/coverage/lcov-report/models/halo-infinite/playlist-experience.ts.html +1 -1
  39. package/coverage/lcov-report/models/halo-infinite/playlist.ts.html +1 -1
  40. package/coverage/lcov-report/models/halo-infinite/progression-file.ts.html +1 -1
  41. package/coverage/lcov-report/models/halo-infinite/season.ts.html +1 -1
  42. package/coverage/lcov-report/models/halo-infinite/service-record.ts.html +1 -1
  43. package/coverage/lcov-report/models/halo-infinite/settings.ts.html +205 -0
  44. package/coverage/lcov-report/models/halo-infinite/skill-result.ts.html +1 -1
  45. package/coverage/lcov-report/models/halo-infinite/stats.ts.html +1 -1
  46. package/coverage/lcov-report/models/halo-infinite/user-info.ts.html +1 -1
  47. package/coverage/lcov-report/models/index.html +1 -1
  48. package/coverage/lcov-report/models/spartan-token-proof.ts.html +1 -1
  49. package/coverage/lcov-report/models/spartan-token-request.ts.html +1 -1
  50. package/coverage/lcov-report/models/spartan-token.ts.html +1 -1
  51. package/coverage/lcov-report/models/xbox-ticket.ts.html +1 -1
  52. package/coverage/lcov-report/util/date-time.ts.html +1 -1
  53. package/coverage/lcov-report/util/expiry-token-cache.ts.html +1 -1
  54. package/coverage/lcov-report/util/fetch-function.ts.html +1 -1
  55. package/coverage/lcov-report/util/global-contants.ts.html +1 -1
  56. package/coverage/lcov-report/util/index.html +1 -1
  57. package/coverage/lcov-report/util/keyed-expiry-token-cache.ts.html +1 -1
  58. package/coverage/lcov-report/util/request-error.ts.html +1 -1
  59. package/coverage/lcov-report/util/resolvable-promise.ts.html +29 -29
  60. package/coverage/lcov-report/util/xuid.ts.html +1 -1
  61. package/coverage/lcov.info +324 -244
  62. package/dist/index.cjs +56 -58
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +47 -17
  65. package/dist/index.d.ts +47 -17
  66. package/dist/index.js +56 -58
  67. package/dist/index.js.map +1 -1
  68. package/package.json +1 -1
  69. package/src/authentication/halo-authentication-client.ts +2 -1
  70. package/src/authentication/xbox-authentication-client.ts +16 -7
  71. package/src/core/halo-infinite-client.test.ts +18 -9
  72. package/src/core/halo-infinite-client.ts +35 -18
  73. package/src/core/token-providers/auto-token-provider.ts +17 -26
  74. package/src/core/token-providers/{spartan-token-providers/static-xsts-ticket-token-spartan-token-provider.ts → static-xsts-ticket-token-spartan-token-provider.ts} +12 -21
  75. package/src/index.ts +2 -2
  76. package/src/models/halo-infinite/settings.ts +40 -0
  77. package/coverage/lcov-report/core/token-providers/spartan-token-providers/index.html +0 -116
  78. /package/src/core/token-providers/{spartan-token-providers/index.ts → spartan-token-provider.ts} +0 -0
@@ -25,7 +25,7 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">0% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>0/102</span>
28
+ <span class='fraction'>0/103</span>
29
29
  </div>
30
30
 
31
31
 
@@ -46,7 +46,7 @@
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">0% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>0/102</span>
49
+ <span class='fraction'>0/103</span>
50
50
  </div>
51
51
 
52
52
 
@@ -165,7 +165,9 @@
165
165
  <a name='L100'></a><a href='#L100'>100</a>
166
166
  <a name='L101'></a><a href='#L101'>101</a>
167
167
  <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
170
+ <span class="cline-any cline-no">&nbsp;</span>
169
171
  <span class="cline-any cline-no">&nbsp;</span>
170
172
  <span class="cline-any cline-no">&nbsp;</span>
171
173
  <span class="cline-any cline-no">&nbsp;</span>
@@ -276,13 +278,14 @@
276
278
  <span class="cstat-no" title="statement not covered" >import { RequestError } from "../util/request-error";</span>
277
279
  <span class="cstat-no" title="statement not covered" >import { unauthorizedRetryPolicy } from "../core/request-policy";</span>
278
280
  <span class="cstat-no" title="statement not covered" >import { HaloCoreEndpoints } from "../endpoints/halo-core-endpoints";</span>
281
+ <span class="cstat-no" title="statement not covered" >import { SpartanTokenProvider } from "..";</span>
279
282
  <span class="cstat-no" title="statement not covered" ></span>
280
283
  <span class="cstat-no" title="statement not covered" >export interface Token {</span>
281
284
  <span class="cstat-no" title="statement not covered" > token: string;</span>
282
285
  <span class="cstat-no" title="statement not covered" > expiresAt: DateTime;</span>
283
286
  <span class="cstat-no" title="statement not covered" >}</span>
284
287
  <span class="cstat-no" title="statement not covered" ></span>
285
- <span class="cstat-no" title="statement not covered" >export class HaloAuthenticationClient {</span>
288
+ <span class="cstat-no" title="statement not covered" >export class HaloAuthenticationClient implements SpartanTokenProvider {</span>
286
289
  <span class="cstat-no" title="statement not covered" > private spartanTokenCache = new ExpiryTokenCache(</span>
287
290
  <span class="cstat-no" title="statement not covered" > async () =&gt; {</span>
288
291
  <span class="cstat-no" title="statement not covered" > const failureHandler = unauthorizedRetryPolicy.onFailure(</span>
@@ -376,7 +379,7 @@
376
379
  <div class='footer quiet pad2 space-top1 center small'>
377
380
  Code coverage generated by
378
381
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
379
- at 2025-11-19T04:39:38.927Z
382
+ at 2025-12-08T18:28:58.806Z
380
383
  </div>
381
384
  <script src="../prettify.js"></script>
382
385
  <script>
@@ -25,7 +25,7 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">0% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>0/263</span>
28
+ <span class='fraction'>0/273</span>
29
29
  </div>
30
30
 
31
31
 
@@ -46,7 +46,7 @@
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">0% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>0/263</span>
49
+ <span class='fraction'>0/273</span>
50
50
  </div>
51
51
 
52
52
 
@@ -84,13 +84,13 @@
84
84
  <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
85
85
  </td>
86
86
  <td data-value="0" class="pct low">0%</td>
87
- <td data-value="102" class="abs low">0/102</td>
87
+ <td data-value="103" class="abs low">0/103</td>
88
88
  <td data-value="0" class="pct low">0%</td>
89
89
  <td data-value="1" class="abs low">0/1</td>
90
90
  <td data-value="0" class="pct low">0%</td>
91
91
  <td data-value="1" class="abs low">0/1</td>
92
92
  <td data-value="0" class="pct low">0%</td>
93
- <td data-value="102" class="abs low">0/102</td>
93
+ <td data-value="103" class="abs low">0/103</td>
94
94
  </tr>
95
95
 
96
96
  <tr>
@@ -99,13 +99,13 @@
99
99
  <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
100
100
  </td>
101
101
  <td data-value="0" class="pct low">0%</td>
102
- <td data-value="161" class="abs low">0/161</td>
102
+ <td data-value="170" class="abs low">0/170</td>
103
103
  <td data-value="0" class="pct low">0%</td>
104
104
  <td data-value="1" class="abs low">0/1</td>
105
105
  <td data-value="0" class="pct low">0%</td>
106
106
  <td data-value="1" class="abs low">0/1</td>
107
107
  <td data-value="0" class="pct low">0%</td>
108
- <td data-value="161" class="abs low">0/161</td>
108
+ <td data-value="170" class="abs low">0/170</td>
109
109
  </tr>
110
110
 
111
111
  </tbody>
@@ -116,7 +116,7 @@
116
116
  <div class='footer quiet pad2 space-top1 center small'>
117
117
  Code coverage generated by
118
118
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
119
- at 2025-11-19T04:39:38.927Z
119
+ at 2025-12-08T18:28:58.806Z
120
120
  </div>
121
121
  <script src="../prettify.js"></script>
122
122
  <script>
@@ -25,7 +25,7 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">0% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>0/161</span>
28
+ <span class='fraction'>0/170</span>
29
29
  </div>
30
30
 
31
31
 
@@ -46,7 +46,7 @@
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">0% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>0/161</span>
49
+ <span class='fraction'>0/170</span>
50
50
  </div>
51
51
 
52
52
 
@@ -224,7 +224,25 @@
224
224
  <a name='L159'></a><a href='#L159'>159</a>
225
225
  <a name='L160'></a><a href='#L160'>160</a>
226
226
  <a name='L161'></a><a href='#L161'>161</a>
227
- <a name='L162'></a><a href='#L162'>162</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
237
+ <span class="cline-any cline-no">&nbsp;</span>
238
+ <span class="cline-any cline-no">&nbsp;</span>
239
+ <span class="cline-any cline-no">&nbsp;</span>
240
+ <span class="cline-any cline-no">&nbsp;</span>
241
+ <span class="cline-any cline-no">&nbsp;</span>
242
+ <span class="cline-any cline-no">&nbsp;</span>
243
+ <span class="cline-any cline-no">&nbsp;</span>
244
+ <span class="cline-any cline-no">&nbsp;</span>
245
+ <span class="cline-any cline-no">&nbsp;</span>
228
246
  <span class="cline-any cline-no">&nbsp;</span>
229
247
  <span class="cline-any cline-no">&nbsp;</span>
230
248
  <span class="cline-any cline-no">&nbsp;</span>
@@ -406,6 +424,10 @@
406
424
  <span class="cstat-no" title="statement not covered" >}</span>
407
425
  <span class="cstat-no" title="statement not covered" ></span>
408
426
  <span class="cstat-no" title="statement not covered" >export class XboxAuthenticationClient {</span>
427
+ <span class="cstat-no" title="statement not covered" > static readonly userTokenName = "xbox.userToken";</span>
428
+ <span class="cstat-no" title="statement not covered" > static readonly xstsTicketName = (relyingParty: RelyingParty) =&gt;</span>
429
+ <span class="cstat-no" title="statement not covered" > `xbox.xstsTicket.${relyingParty}`;</span>
430
+ <span class="cstat-no" title="statement not covered" ></span>
409
431
  <span class="cstat-no" title="statement not covered" > private userTokenCache = new ExpiryTokenCache(</span>
410
432
  <span class="cstat-no" title="statement not covered" > async (accessToken: string) =&gt; {</span>
411
433
  <span class="cstat-no" title="statement not covered" > const url = "https://user.auth.xboxlive.com/user/authenticate";</span>
@@ -446,7 +468,7 @@
446
468
  <span class="cstat-no" title="statement not covered" > const tokenPersister = await this.tokenPersisterOrPromise;</span>
447
469
  <span class="cstat-no" title="statement not covered" > return (</span>
448
470
  <span class="cstat-no" title="statement not covered" > (await tokenPersister?.load&lt;XboxTicket &amp; { expiresAt: unknown }&gt;(</span>
449
- <span class="cstat-no" title="statement not covered" > "xbox.userToken"</span>
471
+ <span class="cstat-no" title="statement not covered" > XboxAuthenticationClient.userTokenName</span>
450
472
  <span class="cstat-no" title="statement not covered" > )) ?? null</span>
451
473
  <span class="cstat-no" title="statement not covered" > );</span>
452
474
  <span class="cstat-no" title="statement not covered" > }</span>
@@ -480,7 +502,7 @@
480
502
  <span class="cstat-no" title="statement not covered" > };</span>
481
503
  <span class="cstat-no" title="statement not covered" > await (</span>
482
504
  <span class="cstat-no" title="statement not covered" > await this.tokenPersisterOrPromise</span>
483
- <span class="cstat-no" title="statement not covered" > )?.save("xbox.xstsTicket." + relyingParty, token);</span>
505
+ <span class="cstat-no" title="statement not covered" > )?.save(XboxAuthenticationClient.xstsTicketName(relyingParty), token);</span>
484
506
  <span class="cstat-no" title="statement not covered" > return token;</span>
485
507
  <span class="cstat-no" title="statement not covered" > } else {</span>
486
508
  <span class="cstat-no" title="statement not covered" > throw new RequestError(url, response);</span>
@@ -495,16 +517,14 @@
495
517
  <span class="cstat-no" title="statement not covered" > );</span>
496
518
  <span class="cstat-no" title="statement not covered" ></span>
497
519
  <span class="cstat-no" title="statement not covered" > constructor(</span>
520
+ <span class="cstat-no" title="statement not covered" > private readonly getOauth2AccessToken: () =&gt; Promise&lt;string&gt;,</span>
498
521
  <span class="cstat-no" title="statement not covered" > private readonly tokenPersisterOrPromise?:</span>
499
522
  <span class="cstat-no" title="statement not covered" > | TokenPersister</span>
500
523
  <span class="cstat-no" title="statement not covered" > | Promise&lt;TokenPersister&gt;,</span>
501
524
  <span class="cstat-no" title="statement not covered" > private readonly fetchFn: FetchFunction = defaultFetch</span>
502
525
  <span class="cstat-no" title="statement not covered" > ) {}</span>
503
526
  <span class="cstat-no" title="statement not covered" ></span>
504
- <span class="cstat-no" title="statement not covered" > public async getXstsTicket(</span>
505
- <span class="cstat-no" title="statement not covered" > getOauth2AccessToken: () =&gt; Promise&lt;string&gt;,</span>
506
- <span class="cstat-no" title="statement not covered" > relyingParty: RelyingParty</span>
507
- <span class="cstat-no" title="statement not covered" > ) {</span>
527
+ <span class="cstat-no" title="statement not covered" > public async getXstsTicket(relyingParty: RelyingParty) {</span>
508
528
  <span class="cstat-no" title="statement not covered" > let xstsTicket = await this.xstsTicketCache.getExistingToken(relyingParty);</span>
509
529
  <span class="cstat-no" title="statement not covered" > if (!xstsTicket) {</span>
510
530
  <span class="cstat-no" title="statement not covered" > let userToken = await this.userTokenCache.getExistingToken();</span>
@@ -524,7 +544,7 @@
524
544
  <span class="cstat-no" title="statement not covered" > if (!userToken) {</span>
525
545
  <span class="cstat-no" title="statement not covered" > // Ouath2 token depends on nothing, so we can fetch it without</span>
526
546
  <span class="cstat-no" title="statement not covered" > // worrying if it is expired.</span>
527
- <span class="cstat-no" title="statement not covered" > const oauthToken = await getOauth2AccessToken();</span>
547
+ <span class="cstat-no" title="statement not covered" > const oauthToken = await this.getOauth2AccessToken();</span>
528
548
  <span class="cstat-no" title="statement not covered" > userToken = await this.userTokenCache.getToken(oauthToken);</span>
529
549
  <span class="cstat-no" title="statement not covered" > }</span>
530
550
  <span class="cstat-no" title="statement not covered" > return this.xstsTicketCache.getToken(relyingParty, userToken.Token);</span>
@@ -545,6 +565,13 @@
545
565
  <span class="cstat-no" title="statement not covered" ></span>
546
566
  <span class="cstat-no" title="statement not covered" > public getXboxLiveV3Token = (xboxTicket: XboxTicket) =&gt;</span>
547
567
  <span class="cstat-no" title="statement not covered" > `XBL3.0 x=${xboxTicket.DisplayClaims.xui[0].uhs};${xboxTicket.Token}`;</span>
568
+ <span class="cstat-no" title="statement not covered" ></span>
569
+ <span class="cstat-no" title="statement not covered" > public clearXboxUserToken = async () =&gt; {</span>
570
+ <span class="cstat-no" title="statement not covered" > // Clear from memory</span>
571
+ <span class="cstat-no" title="statement not covered" > this.userTokenCache.clearToken();</span>
572
+ <span class="cstat-no" title="statement not covered" > // Clear from storage</span>
573
+ <span class="cstat-no" title="statement not covered" > (await this.tokenPersisterOrPromise)?.clear("xbox.userToken");</span>
574
+ <span class="cstat-no" title="statement not covered" > };</span>
548
575
  <span class="cstat-no" title="statement not covered" >}</span>
549
576
  &nbsp;</pre></td></tr></table></pre>
550
577
 
@@ -553,7 +580,7 @@
553
580
  <div class='footer quiet pad2 space-top1 center small'>
554
581
  Code coverage generated by
555
582
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
556
- at 2025-11-19T04:39:38.927Z
583
+ at 2025-12-08T18:28:58.806Z
557
584
  </div>
558
585
  <script src="../prettify.js"></script>
559
586
  <script>
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">44.72% </span>
26
+ <span class="strong">45.2% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>216/483</span>
28
+ <span class='fraction'>226/500</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">72.72% </span>
33
+ <span class="strong">88.88% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>8/11</span>
35
+ <span class='fraction'>8/9</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">20.83% </span>
40
+ <span class="strong">20% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>5/24</span>
42
+ <span class='fraction'>5/25</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">44.72% </span>
47
+ <span class="strong">45.2% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>216/483</span>
49
+ <span class='fraction'>226/500</span>
50
50
  </div>
51
51
 
52
52
 
@@ -546,7 +546,24 @@
546
546
  <a name='L481'></a><a href='#L481'>481</a>
547
547
  <a name='L482'></a><a href='#L482'>482</a>
548
548
  <a name='L483'></a><a href='#L483'>483</a>
549
- <a name='L484'></a><a href='#L484'>484</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
550
567
  <span class="cline-any cline-yes">1x</span>
551
568
  <span class="cline-any cline-yes">1x</span>
552
569
  <span class="cline-any cline-yes">1x</span>
@@ -621,6 +638,8 @@
621
638
  <span class="cline-any cline-yes">1x</span>
622
639
  <span class="cline-any cline-yes">1x</span>
623
640
  <span class="cline-any cline-yes">1x</span>
641
+ <span class="cline-any cline-yes">1x</span>
642
+ <span class="cline-any cline-no">&nbsp;</span>
624
643
  <span class="cline-any cline-no">&nbsp;</span>
625
644
  <span class="cline-any cline-no">&nbsp;</span>
626
645
  <span class="cline-any cline-no">&nbsp;</span>
@@ -659,9 +678,6 @@
659
678
  <span class="cline-any cline-yes">1x</span>
660
679
  <span class="cline-any cline-yes">1x</span>
661
680
  <span class="cline-any cline-yes">1x</span>
662
- <span class="cline-any cline-no">&nbsp;</span>
663
- <span class="cline-any cline-no">&nbsp;</span>
664
- <span class="cline-any cline-no">&nbsp;</span>
665
681
  <span class="cline-any cline-yes">1x</span>
666
682
  <span class="cline-any cline-yes">1x</span>
667
683
  <span class="cline-any cline-yes">1x</span>
@@ -686,6 +702,12 @@
686
702
  <span class="cline-any cline-yes">2x</span>
687
703
  <span class="cline-any cline-yes">2x</span>
688
704
  <span class="cline-any cline-yes">2x</span>
705
+ <span class="cline-any cline-yes">2x</span>
706
+ <span class="cline-any cline-yes">2x</span>
707
+ <span class="cline-any cline-yes">1x</span>
708
+ <span class="cline-any cline-yes">1x</span>
709
+ <span class="cline-any cline-yes">1x</span>
710
+ <span class="cline-any cline-yes">1x</span>
689
711
  <span class="cline-any cline-yes">1x</span>
690
712
  <span class="cline-any cline-yes">1x</span>
691
713
  <span class="cline-any cline-yes">1x</span>
@@ -1029,6 +1051,18 @@
1029
1051
  <span class="cline-any cline-no">&nbsp;</span>
1030
1052
  <span class="cline-any cline-yes">1x</span>
1031
1053
  <span class="cline-any cline-yes">1x</span>
1054
+ <span class="cline-any cline-yes">1x</span>
1055
+ <span class="cline-any cline-no">&nbsp;</span>
1056
+ <span class="cline-any cline-no">&nbsp;</span>
1057
+ <span class="cline-any cline-no">&nbsp;</span>
1058
+ <span class="cline-any cline-no">&nbsp;</span>
1059
+ <span class="cline-any cline-no">&nbsp;</span>
1060
+ <span class="cline-any cline-no">&nbsp;</span>
1061
+ <span class="cline-any cline-no">&nbsp;</span>
1062
+ <span class="cline-any cline-no">&nbsp;</span>
1063
+ <span class="cline-any cline-no">&nbsp;</span>
1064
+ <span class="cline-any cline-yes">1x</span>
1065
+ <span class="cline-any cline-yes">1x</span>
1032
1066
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { FetchFunction, defaultFetch } from "../util/fetch-function";
1033
1067
  import { HaloCoreEndpoints } from "../endpoints/halo-core-endpoints";
1034
1068
  import {
@@ -1047,7 +1081,7 @@ import { PlaylistCsrContainer } from "../models/halo-infinite/playlist-csr-conta
1047
1081
  import { ServiceRecord } from "../models/halo-infinite/service-record";
1048
1082
  import { UserInfo } from "../models/halo-infinite/user-info";
1049
1083
  import { GlobalConstants } from "../util/global-contants";
1050
- import { SpartanTokenProvider } from "./token-providers/spartan-token-providers";
1084
+ import { SpartanTokenProvider } from "./token-providers/spartan-token-provider";
1051
1085
  import { RequestError } from "../util/request-error";
1052
1086
  import { MatchesPrivacy } from "../models/halo-infinite/matches-privacy";
1053
1087
  import { MedalsMetadataFile } from "../models/halo-infinite/medals-metadata-file";
@@ -1061,6 +1095,7 @@ import { KeyedExpiryTokenCache } from "../util/keyed-expiry-token-cache";
1061
1095
  import { DateTime } from "luxon";
1062
1096
  import { wrapPlayerId, unwrapPlayerId } from "../util/xuid";
1063
1097
  import { SeasonCalendarContainer } from "../models/halo-infinite/season";
1098
+ import { Settings } from "../models/halo-infinite/settings";
1064
1099
  &nbsp;
1065
1100
  export interface ResultContainer&lt;TValue&gt; {
1066
1101
  Id: string;
@@ -1111,7 +1146,8 @@ export class HaloInfiniteClient {
1111
1146
  <span class="cstat-no" title="statement not covered" > }/oban/flight-configurations/titles/hi/audiences/retail/players/${wrapPlayerId(</span>
1112
1147
  <span class="cstat-no" title="statement not covered" > xuid</span>
1113
1148
  <span class="cstat-no" title="statement not covered" > )}/active`,</span>
1114
- <span class="cstat-no" title="statement not covered" > { method: "get" }</span>
1149
+ <span class="cstat-no" title="statement not covered" > { method: "get" },</span>
1150
+ <span class="cstat-no" title="statement not covered" > false</span>
1115
1151
  <span class="cstat-no" title="statement not covered" > );</span>
1116
1152
  <span class="cstat-no" title="statement not covered" > const {</span>
1117
1153
  <span class="cstat-no" title="statement not covered" > FlightConfigurationId,</span>
@@ -1131,20 +1167,17 @@ export class HaloInfiniteClient {
1131
1167
  &nbsp;
1132
1168
  constructor(
1133
1169
  private readonly spartanTokenProvider: SpartanTokenProvider,
1134
- private readonly clearXstsToken: () =&gt; Promise&lt;void&gt;,
1135
1170
  private readonly fetchFn: FetchFunction = defaultFetch
1136
1171
  ) {}
1137
1172
  &nbsp;
1138
- private async executeRequest(url: string, init: RequestInit) {
1173
+ protected async executeRequest(
1174
+ url: string,
1175
+ init: RequestInit,
1176
+ skipAuth: boolean
1177
+ ) {
1139
1178
  const failureHandler = unauthorizedRetryPolicy.onFailure(
1140
1179
  async ({ handled }) =&gt; {
1141
1180
  if (handled) {
1142
- const expiration =
1143
- await this.spartanTokenProvider.getCurrentExpiration();
1144
- if (expiration<span class="branch-0 cbranch-no" title="branch not covered" > &amp;&amp; expiration &gt; DateTime.now().plus({ minutes: 1 }))</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1145
- <span class="cstat-no" title="statement not covered" > // Token should still be valid, but was rejected. That means the xsts is likely invalid.</span>
1146
- <span class="cstat-no" title="statement not covered" > await this.clearXstsToken();</span>
1147
- <span class="cstat-no" title="statement not covered" > }</span>
1148
1181
  await this.spartanTokenProvider.clearSpartanToken();
1149
1182
  }
1150
1183
  }
@@ -1158,10 +1191,12 @@ export class HaloInfiniteClient {
1158
1191
  if (!headers.has("Accept")) {
1159
1192
  headers.set("Accept", "application/json");
1160
1193
  }
1161
- headers.set(
1162
- "x-343-authorization-spartan",
1163
- await this.spartanTokenProvider.getSpartanToken()
1164
- );
1194
+ if (!skipAuth) {
1195
+ headers.set(
1196
+ "x-343-authorization-spartan",
1197
+ await this.spartanTokenProvider.getSpartanToken()
1198
+ );
1199
+ }
1165
1200
  &nbsp;
1166
1201
  const response = await this.fetchFn(url, {
1167
1202
  ...init,
@@ -1179,8 +1214,12 @@ export class HaloInfiniteClient {
1179
1214
  }
1180
1215
  }
1181
1216
  &nbsp;
1182
- private async executeJsonRequest&lt;T&gt;(url: string, init: RequestInit) {
1183
- const response = await this.executeRequest(url, init);
1217
+ protected async executeJsonRequest&lt;T&gt;(
1218
+ url: string,
1219
+ init: RequestInit,
1220
+ skipAuth?: boolean
1221
+ ) {
1222
+ const response = await this.executeRequest(url, init, skipAuth ?? false);
1184
1223
  &nbsp;
1185
1224
  if (response.status &gt;= 200 &amp;&amp; response.status &lt; 300) {
1186
1225
  return (await response.json()) as T;
@@ -1189,7 +1228,7 @@ export class HaloInfiniteClient {
1189
1228
  <span class="cstat-no" title="statement not covered" > }</span>
1190
1229
  }
1191
1230
  &nbsp;
1192
- private <span class="fstat-no" title="function not covered" >async executeResultsRequest&lt;T&gt;(</span>
1231
+ protected <span class="fstat-no" title="function not covered" >async executeResultsRequest&lt;T&gt;(</span>
1193
1232
  <span class="cstat-no" title="statement not covered" > ...args: Parameters&lt;HaloInfiniteClient["executeJsonRequest"]&gt;</span>
1194
1233
  <span class="cstat-no" title="statement not covered" > ) {</span>
1195
1234
  <span class="cstat-no" title="statement not covered" > let resultsContainer: ResultsContainer&lt;T&gt;;</span>
@@ -1211,7 +1250,7 @@ export class HaloInfiniteClient {
1211
1250
  <span class="cstat-no" title="statement not covered" > return resultsContainer.Value;</span>
1212
1251
  <span class="cstat-no" title="statement not covered" > }</span>
1213
1252
  &nbsp;
1214
- private <span class="fstat-no" title="function not covered" >async executePaginationRequest&lt;T&gt;(</span>
1253
+ protected <span class="fstat-no" title="function not covered" >async executePaginationRequest&lt;T&gt;(</span>
1215
1254
  <span class="cstat-no" title="statement not covered" > count: number,</span>
1216
1255
  <span class="cstat-no" title="statement not covered" > start: number,</span>
1217
1256
  <span class="cstat-no" title="statement not covered" > queryParameters: Record&lt;string, string&gt;,</span>
@@ -1511,6 +1550,18 @@ export class HaloInfiniteClient {
1511
1550
  <span class="cstat-no" title="statement not covered" > method: "get",</span>
1512
1551
  <span class="cstat-no" title="statement not covered" > }</span>
1513
1552
  );
1553
+ &nbsp;
1554
+ public getSettings = <span class="fstat-no" title="function not covered" >(</span>
1555
+ <span class="cstat-no" title="statement not covered" > init?: Omit&lt;RequestInit, "body" | "method"&gt;</span>
1556
+ <span class="cstat-no" title="statement not covered" > ): Promise&lt;Settings&gt; =&gt;</span>
1557
+ <span class="cstat-no" title="statement not covered" > this.executeJsonRequest(</span>
1558
+ <span class="cstat-no" title="statement not covered" > `https://${HaloCoreEndpoints.SettingsOrigin}.${HaloCoreEndpoints.ServiceDomain}/settings/hipc/e2a0a7c6-6efe-42af-9283-c2ab73250c48`,</span>
1559
+ <span class="cstat-no" title="statement not covered" > {</span>
1560
+ <span class="cstat-no" title="statement not covered" > ...init,</span>
1561
+ <span class="cstat-no" title="statement not covered" > method: "get",</span>
1562
+ <span class="cstat-no" title="statement not covered" > },</span>
1563
+ <span class="cstat-no" title="statement not covered" > true</span>
1564
+ );
1514
1565
  }
1515
1566
  &nbsp;</pre></td></tr></table></pre>
1516
1567
 
@@ -1519,7 +1570,7 @@ export class HaloInfiniteClient {
1519
1570
  <div class='footer quiet pad2 space-top1 center small'>
1520
1571
  Code coverage generated by
1521
1572
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1522
- at 2025-11-19T04:39:38.927Z
1573
+ at 2025-12-08T18:28:58.806Z
1523
1574
  </div>
1524
1575
  <script src="../prettify.js"></script>
1525
1576
  <script>
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">37.54% </span>
26
+ <span class="strong">38.13% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>223/594</span>
28
+ <span class='fraction'>233/611</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">69.23% </span>
33
+ <span class="strong">81.81% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>9/13</span>
35
+ <span class='fraction'>9/11</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">20% </span>
40
+ <span class="strong">19.23% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>5/25</span>
42
+ <span class='fraction'>5/26</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">37.54% </span>
47
+ <span class="strong">38.13% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>223/594</span>
49
+ <span class='fraction'>233/611</span>
50
50
  </div>
51
51
 
52
52
 
@@ -80,17 +80,17 @@
80
80
  </thead>
81
81
  <tbody><tr>
82
82
  <td class="file low" data-value="halo-infinite-client.ts"><a href="halo-infinite-client.ts.html">halo-infinite-client.ts</a></td>
83
- <td data-value="44.72" class="pic low">
84
- <div class="chart"><div class="cover-fill" style="width: 44%"></div><div class="cover-empty" style="width: 56%"></div></div>
83
+ <td data-value="45.2" class="pic low">
84
+ <div class="chart"><div class="cover-fill" style="width: 45%"></div><div class="cover-empty" style="width: 55%"></div></div>
85
85
  </td>
86
- <td data-value="44.72" class="pct low">44.72%</td>
87
- <td data-value="483" class="abs low">216/483</td>
88
- <td data-value="72.72" class="pct medium">72.72%</td>
89
- <td data-value="11" class="abs medium">8/11</td>
90
- <td data-value="20.83" class="pct low">20.83%</td>
91
- <td data-value="24" class="abs low">5/24</td>
92
- <td data-value="44.72" class="pct low">44.72%</td>
93
- <td data-value="483" class="abs low">216/483</td>
86
+ <td data-value="45.2" class="pct low">45.2%</td>
87
+ <td data-value="500" class="abs low">226/500</td>
88
+ <td data-value="88.88" class="pct high">88.88%</td>
89
+ <td data-value="9" class="abs high">8/9</td>
90
+ <td data-value="20" class="pct low">20%</td>
91
+ <td data-value="25" class="abs low">5/25</td>
92
+ <td data-value="45.2" class="pct low">45.2%</td>
93
+ <td data-value="500" class="abs low">226/500</td>
94
94
  </tr>
95
95
 
96
96
  <tr>
@@ -131,7 +131,7 @@
131
131
  <div class='footer quiet pad2 space-top1 center small'>
132
132
  Code coverage generated by
133
133
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
134
- at 2025-11-19T04:39:38.927Z
134
+ at 2025-12-08T18:28:58.806Z
135
135
  </div>
136
136
  <script src="../prettify.js"></script>
137
137
  <script>
@@ -91,7 +91,7 @@ export const unauthorizedRetryPolicy = retry(
91
91
  <div class='footer quiet pad2 space-top1 center small'>
92
92
  Code coverage generated by
93
93
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
94
- at 2025-11-19T04:39:38.927Z
94
+ at 2025-12-08T18:28:58.806Z
95
95
  </div>
96
96
  <script src="../prettify.js"></script>
97
97
  <script>
@@ -115,7 +115,7 @@ export const inMemoryTokenPersister: TokenPersister = {
115
115
  <div class='footer quiet pad2 space-top1 center small'>
116
116
  Code coverage generated by
117
117
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
118
- at 2025-11-19T04:39:38.927Z
118
+ at 2025-12-08T18:28:58.806Z
119
119
  </div>
120
120
  <script src="../../prettify.js"></script>
121
121
  <script>
@@ -146,7 +146,7 @@
146
146
  <div class='footer quiet pad2 space-top1 center small'>
147
147
  Code coverage generated by
148
148
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
149
- at 2025-11-19T04:39:38.927Z
149
+ at 2025-12-08T18:28:58.806Z
150
150
  </div>
151
151
  <script src="../../prettify.js"></script>
152
152
  <script>
@@ -124,7 +124,7 @@
124
124
  <div class='footer quiet pad2 space-top1 center small'>
125
125
  Code coverage generated by
126
126
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
127
- at 2025-11-19T04:39:38.927Z
127
+ at 2025-12-08T18:28:58.806Z
128
128
  </div>
129
129
  <script src="../../prettify.js"></script>
130
130
  <script>
@@ -184,7 +184,7 @@ export const nodeFsTokenPersister: TokenPersister = {
184
184
  <div class='footer quiet pad2 space-top1 center small'>
185
185
  Code coverage generated by
186
186
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
187
- at 2025-11-19T04:39:38.927Z
187
+ at 2025-12-08T18:28:58.806Z
188
188
  </div>
189
189
  <script src="../../prettify.js"></script>
190
190
  <script>
@@ -85,7 +85,7 @@
85
85
  <div class='footer quiet pad2 space-top1 center small'>
86
86
  Code coverage generated by
87
87
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
88
- at 2025-11-19T04:39:38.927Z
88
+ at 2025-12-08T18:28:58.806Z
89
89
  </div>
90
90
  <script src="../../prettify.js"></script>
91
91
  <script>