@lgriffin/esi.ts 10.0.0 → 10.2.1

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 (260) hide show
  1. package/CHANGELOG.md +158 -0
  2. package/README.md +14 -5
  3. package/dist/EsiClient.d.mts +140 -0
  4. package/dist/EsiClientBuilder.d.mts +75 -0
  5. package/dist/auth/EsiTokenManager.d.mts +200 -0
  6. package/dist/auth/EveSsoClient.d.mts +88 -0
  7. package/dist/auth/errors.d.mts +42 -0
  8. package/dist/auth/index.d.mts +14 -0
  9. package/dist/auth/jwt.d.mts +43 -0
  10. package/dist/auth/pkce.d.mts +21 -0
  11. package/dist/auth/storage/FileTokenStorage.d.mts +44 -0
  12. package/dist/auth/storage/MemoryTokenStorage.d.mts +18 -0
  13. package/dist/auth/types.d.mts +42 -0
  14. package/dist/{chunk-7A72QFDF.mjs → chunk-4W66ONJI.mjs} +4 -7
  15. package/dist/chunk-4W66ONJI.mjs.map +1 -0
  16. package/dist/{chunk-HPSACXX3.js → chunk-N3B65VLB.js} +4 -7
  17. package/dist/chunk-N3B65VLB.js.map +1 -0
  18. package/dist/clients/AccessListsClient.d.mts +25 -0
  19. package/dist/clients/AllianceClient.d.mts +59 -0
  20. package/dist/clients/AssetsClient.d.mts +65 -0
  21. package/dist/clients/BaseEsiClient.d.mts +19 -0
  22. package/dist/clients/CalendarClient.d.mts +48 -0
  23. package/dist/clients/CharacterClient.d.mts +134 -0
  24. package/dist/clients/ClonesClient.d.mts +27 -0
  25. package/dist/clients/ContactsClient.d.mts +96 -0
  26. package/dist/clients/ContractsClient.d.mts +91 -0
  27. package/dist/clients/CorporationProjectsClient.d.mts +54 -0
  28. package/dist/clients/CorporationsClient.d.mts +219 -0
  29. package/dist/clients/CosmeticsClient.d.mts +11 -0
  30. package/dist/clients/DogmaClient.d.mts +42 -0
  31. package/dist/clients/FactionClient.d.mts +60 -0
  32. package/dist/clients/FittingsClient.d.mts +38 -0
  33. package/dist/clients/FleetClient.d.mts +134 -0
  34. package/dist/clients/FreelanceJobsClient.d.mts +61 -0
  35. package/dist/clients/IncursionsClient.d.mts +14 -0
  36. package/dist/clients/IndustryClient.d.mts +86 -0
  37. package/dist/clients/InsuranceClient.d.mts +14 -0
  38. package/dist/clients/KillmailsClient.d.mts +37 -0
  39. package/dist/clients/LocationClient.d.mts +32 -0
  40. package/dist/clients/LoyaltyClient.d.mts +28 -0
  41. package/dist/clients/MailClient.d.mts +104 -0
  42. package/dist/clients/MarketClient.d.mts +102 -0
  43. package/dist/clients/MercenaryClient.d.mts +42 -0
  44. package/dist/clients/MetaClient.d.mts +45 -0
  45. package/dist/clients/MilitaryCampaignsClient.d.mts +53 -0
  46. package/dist/clients/ParagonHubClient.d.mts +13 -0
  47. package/dist/clients/PiClient.d.mts +45 -0
  48. package/dist/clients/RouteClient.d.mts +25 -0
  49. package/dist/clients/SearchClient.d.mts +17 -0
  50. package/dist/clients/SkillsClient.d.mts +39 -0
  51. package/dist/clients/SkyhooksClient.d.mts +48 -0
  52. package/dist/clients/SovereigntyClient.d.mts +20 -0
  53. package/dist/clients/StatusClient.d.mts +14 -0
  54. package/dist/clients/UiClient.d.mts +44 -0
  55. package/dist/clients/UniverseClient.d.mts +212 -0
  56. package/dist/clients/WalletClient.d.mts +70 -0
  57. package/dist/clients/WarsClient.d.mts +33 -0
  58. package/dist/core/ApiClient.d.mts +73 -0
  59. package/dist/core/ApiClientBuilder.d.mts +24 -0
  60. package/dist/core/ApiRequestHandler.d.ts.map +1 -1
  61. package/dist/core/BatchRequestHandler.d.mts +12 -0
  62. package/dist/core/ClientRegistry.d.mts +45 -0
  63. package/dist/core/EsiDiagnostics.d.mts +35 -0
  64. package/dist/core/IDeduplicator.d.mts +22 -0
  65. package/dist/core/IDeduplicator.d.ts +16 -0
  66. package/dist/core/IDeduplicator.d.ts.map +1 -1
  67. package/dist/core/IRetryStrategy.d.mts +5 -0
  68. package/dist/core/RequestDeduplicator.d.mts +21 -0
  69. package/dist/core/RequestDeduplicator.d.ts +11 -0
  70. package/dist/core/RequestDeduplicator.d.ts.map +1 -1
  71. package/dist/core/RetryStrategy.d.mts +21 -0
  72. package/dist/core/cache/ETagCacheManager.d.mts +75 -0
  73. package/dist/core/cache/ICache.d.mts +27 -0
  74. package/dist/core/cache/cacheKey.d.ts +11 -0
  75. package/dist/core/cache/cacheKey.d.ts.map +1 -1
  76. package/dist/core/circuitBreaker/CircuitBreaker.d.mts +52 -0
  77. package/dist/core/circuitBreaker/CircuitBreaker.d.ts.map +1 -1
  78. package/dist/core/circuitBreaker/ICircuitBreaker.d.mts +23 -0
  79. package/dist/core/configureApiClient.d.mts +18 -0
  80. package/dist/core/constants.d.ts +2 -2
  81. package/dist/core/endpoints/EndpointDefinition.d.mts +63 -0
  82. package/dist/core/endpoints/accessListEndpoints.d.mts +34 -0
  83. package/dist/core/endpoints/allianceEndpoints.d.mts +43 -0
  84. package/dist/core/endpoints/assetEndpoints.d.mts +76 -0
  85. package/dist/core/endpoints/buildEndpointPath.d.mts +7 -0
  86. package/dist/core/endpoints/calendarEndpoints.d.mts +54 -0
  87. package/dist/core/endpoints/characterEndpoints.d.mts +185 -0
  88. package/dist/core/endpoints/cloneEndpoints.d.mts +32 -0
  89. package/dist/core/endpoints/contactEndpoints.d.mts +106 -0
  90. package/dist/core/endpoints/contractEndpoints.d.mts +168 -0
  91. package/dist/core/endpoints/corporationEndpoints.d.mts +324 -0
  92. package/dist/core/endpoints/corporationProjectEndpoints.d.mts +102 -0
  93. package/dist/core/endpoints/cosmeticsEndpoints.d.mts +52 -0
  94. package/dist/core/endpoints/createClient.d.mts +69 -0
  95. package/dist/core/endpoints/dogmaEndpoints.d.mts +89 -0
  96. package/dist/core/endpoints/esi-cache-ttls.generated.d.ts.map +1 -1
  97. package/dist/core/endpoints/esi-rate-limit-groups.generated.d.mts +7 -0
  98. package/dist/core/endpoints/esi-rate-limit-groups.generated.d.ts.map +1 -1
  99. package/dist/core/endpoints/esi-scopes.generated.d.mts +3 -0
  100. package/dist/core/endpoints/esi-scopes.generated.d.ts.map +1 -1
  101. package/dist/core/endpoints/factionEndpoints.d.mts +194 -0
  102. package/dist/core/endpoints/fittingEndpoints.d.mts +34 -0
  103. package/dist/core/endpoints/fleetEndpoints.d.mts +137 -0
  104. package/dist/core/endpoints/freelanceJobsEndpoints.d.mts +181 -0
  105. package/dist/core/endpoints/incursionEndpoints.d.mts +19 -0
  106. package/dist/core/endpoints/industryEndpoints.d.mts +138 -0
  107. package/dist/core/endpoints/insuranceEndpoints.d.mts +17 -0
  108. package/dist/core/endpoints/killmailEndpoints.d.mts +62 -0
  109. package/dist/core/endpoints/locationEndpoints.d.mts +37 -0
  110. package/dist/core/endpoints/loyaltyEndpoints.d.mts +32 -0
  111. package/dist/core/endpoints/mailEndpoints.d.mts +111 -0
  112. package/dist/core/endpoints/marketEndpoints.d.mts +191 -0
  113. package/dist/core/endpoints/mercenaryEndpoints.d.mts +79 -0
  114. package/dist/core/endpoints/metaEndpoints.d.mts +50 -0
  115. package/dist/core/endpoints/militaryCampaignEndpoints.d.mts +87 -0
  116. package/dist/core/endpoints/paragonHubEndpoints.d.mts +163 -0
  117. package/dist/core/endpoints/piEndpoints.d.mts +101 -0
  118. package/dist/core/endpoints/routeEndpoints.d.mts +14 -0
  119. package/dist/core/endpoints/searchEndpoints.d.mts +26 -0
  120. package/dist/core/endpoints/skillEndpoints.d.mts +52 -0
  121. package/dist/core/endpoints/skyhookEndpoints.d.mts +111 -0
  122. package/dist/core/endpoints/sovereigntyEndpoints.d.mts +59 -0
  123. package/dist/core/endpoints/statusEndpoints.d.mts +14 -0
  124. package/dist/core/endpoints/uiEndpoints.d.mts +43 -0
  125. package/dist/core/endpoints/universeEndpoints.d.mts +456 -0
  126. package/dist/core/endpoints/walletEndpoints.d.mts +98 -0
  127. package/dist/core/endpoints/warEndpoints.d.mts +51 -0
  128. package/dist/core/logger/DefaultLogger.d.mts +31 -0
  129. package/dist/core/logger/ILogger.d.mts +17 -0
  130. package/dist/core/logger/NoopLogger.d.mts +7 -0
  131. package/dist/core/logger/loggerUtil.d.mts +11 -0
  132. package/dist/core/logger/resolveLogger.d.ts +3 -3
  133. package/dist/core/logger/resolveLogger.d.ts.map +1 -1
  134. package/dist/core/middleware/Middleware.d.mts +30 -0
  135. package/dist/core/pagination/AsyncPaginationIterator.d.mts +12 -0
  136. package/dist/core/pagination/AsyncPaginationIterator.d.ts.map +1 -1
  137. package/dist/core/pagination/CursorPaginationHandler.d.mts +68 -0
  138. package/dist/core/pagination/CursorPaginationHandler.d.ts.map +1 -1
  139. package/dist/core/rateLimiter/IRateLimiter.d.mts +27 -0
  140. package/dist/core/rateLimiter/RateLimiter.d.mts +62 -0
  141. package/dist/core/rateLimiter/RateLimiter.d.ts.map +1 -1
  142. package/dist/core/requestPipeline/cachePolicy.d.ts +11 -1
  143. package/dist/core/requestPipeline/cachePolicy.d.ts.map +1 -1
  144. package/dist/core/requestPipeline/fetchExecution.d.ts.map +1 -1
  145. package/dist/core/requestPipeline/index.d.ts +1 -1
  146. package/dist/core/requestPipeline/index.d.ts.map +1 -1
  147. package/dist/core/requestPipeline/paginationOrchestration.d.ts +1 -1
  148. package/dist/core/requestPipeline/paginationOrchestration.d.ts.map +1 -1
  149. package/dist/core/requestPipeline/statusHandling.d.ts +6 -0
  150. package/dist/core/requestPipeline/statusHandling.d.ts.map +1 -1
  151. package/dist/core/util/concurrency.d.ts.map +1 -1
  152. package/dist/core/util/error.d.mts +37 -0
  153. package/dist/core/util/retry.d.mts +8 -0
  154. package/dist/core/util/retry.d.ts.map +1 -1
  155. package/dist/errors.d.mts +5 -0
  156. package/dist/errors.js +2 -2
  157. package/dist/errors.mjs +1 -1
  158. package/dist/index.d.mts +81 -0
  159. package/dist/index.js +374 -197
  160. package/dist/index.js.map +1 -1
  161. package/dist/index.mjs +267 -90
  162. package/dist/index.mjs.map +1 -1
  163. package/dist/schemas/access-lists.d.mts +16 -0
  164. package/dist/schemas/alliance.d.mts +26 -0
  165. package/dist/schemas/assets.d.mts +24 -0
  166. package/dist/schemas/calendar.d.mts +27 -0
  167. package/dist/schemas/character.d.mts +109 -0
  168. package/dist/schemas/clones.d.mts +17 -0
  169. package/dist/schemas/common.d.mts +74 -0
  170. package/dist/schemas/contacts.d.mts +14 -0
  171. package/dist/schemas/contracts.d.mts +104 -0
  172. package/dist/schemas/corporation-projects.d.mts +104 -0
  173. package/dist/schemas/corporation.d.mts +193 -0
  174. package/dist/schemas/cosmetics.d.mts +58 -0
  175. package/dist/schemas/dogma.d.mts +57 -0
  176. package/dist/schemas/esiEnum.d.mts +3 -0
  177. package/dist/schemas/faction-warfare.d.mts +203 -0
  178. package/dist/schemas/fittings.d.mts +13 -0
  179. package/dist/schemas/fleet.d.mts +37 -0
  180. package/dist/schemas/freelance-jobs.d.mts +171 -0
  181. package/dist/schemas/incursions.d.mts +12 -0
  182. package/dist/schemas/index.d.mts +39 -0
  183. package/dist/schemas/industry.d.mts +99 -0
  184. package/dist/schemas/insurance.d.mts +10 -0
  185. package/dist/schemas/killmails.d.mts +38 -0
  186. package/dist/schemas/location.d.mts +18 -0
  187. package/dist/schemas/loyalty.d.mts +18 -0
  188. package/dist/schemas/mail.d.mts +53 -0
  189. package/dist/schemas/market.d.mts +123 -0
  190. package/dist/schemas/mercenary.d.mts +74 -0
  191. package/dist/schemas/meta.d.mts +36 -0
  192. package/dist/schemas/military-campaigns.d.mts +26 -0
  193. package/dist/schemas/paragon-hub.d.mts +96 -0
  194. package/dist/schemas/pi.d.mts +71 -0
  195. package/dist/schemas/skills.d.mts +28 -0
  196. package/dist/schemas/skyhooks.d.mts +129 -0
  197. package/dist/schemas/sovereignty.d.mts +56 -0
  198. package/dist/schemas/status.d.mts +8 -0
  199. package/dist/schemas/universe.d.mts +285 -0
  200. package/dist/schemas/wallet.d.mts +45 -0
  201. package/dist/schemas/wars.d.mts +27 -0
  202. package/dist/sde/IStaticDataProvider.d.mts +106 -0
  203. package/dist/sde/MemorySdeProvider.d.mts +167 -0
  204. package/dist/sde/SdeDataProvider.d.mts +119 -0
  205. package/dist/sde/SdeTestDataFactory.d.mts +33 -0
  206. package/dist/sde/errors.d.mts +23 -0
  207. package/dist/sde/index.d.mts +9 -0
  208. package/dist/sde/memory.d.mts +8 -0
  209. package/dist/sde/types.d.mts +1039 -0
  210. package/dist/sde/version.d.mts +7 -0
  211. package/dist/testing/TestDataFactory.d.mts +172 -0
  212. package/dist/testing/index.d.mts +2 -0
  213. package/dist/testing/index.js +2 -2
  214. package/dist/testing/index.mjs +1 -1
  215. package/dist/types/access-lists.d.mts +5 -0
  216. package/dist/types/alliance.d.mts +7 -0
  217. package/dist/types/api-responses.d.mts +40 -0
  218. package/dist/types/assets.d.mts +6 -0
  219. package/dist/types/branded.d.mts +23 -0
  220. package/dist/types/calendar.d.mts +6 -0
  221. package/dist/types/character.d.mts +17 -0
  222. package/dist/types/clones.d.mts +4 -0
  223. package/dist/types/common.d.mts +19 -0
  224. package/dist/types/contacts.d.mts +5 -0
  225. package/dist/types/contracts.d.mts +9 -0
  226. package/dist/types/corporation-projects.d.mts +10 -0
  227. package/dist/types/corporation.d.mts +19 -0
  228. package/dist/types/cosmetics.d.mts +8 -0
  229. package/dist/types/dogma.d.mts +6 -0
  230. package/dist/types/faction-warfare.d.mts +17 -0
  231. package/dist/types/fittings.d.mts +4 -0
  232. package/dist/types/fleet.d.mts +7 -0
  233. package/dist/types/freelance-jobs.d.mts +12 -0
  234. package/dist/types/generated/esi-spec.generated.d.mts +2136 -0
  235. package/dist/types/generated/esi-spec.generated.d.ts +164 -16
  236. package/dist/types/generated/esi-spec.generated.d.ts.map +1 -1
  237. package/dist/types/generated/spec-alignment.check.d.ts +2 -2
  238. package/dist/types/incursions.d.mts +4 -0
  239. package/dist/types/industry.d.mts +11 -0
  240. package/dist/types/insurance.d.mts +4 -0
  241. package/dist/types/killmails.d.mts +5 -0
  242. package/dist/types/location.d.mts +6 -0
  243. package/dist/types/loyalty.d.mts +5 -0
  244. package/dist/types/mail.d.mts +6 -0
  245. package/dist/types/market.d.mts +12 -0
  246. package/dist/types/mercenary.d.mts +7 -0
  247. package/dist/types/meta.d.mts +9 -0
  248. package/dist/types/military-campaigns.d.mts +6 -0
  249. package/dist/types/paragon-hub.d.mts +8 -0
  250. package/dist/types/pi.d.mts +6 -0
  251. package/dist/types/skills.d.mts +5 -0
  252. package/dist/types/skyhooks.d.mts +8 -0
  253. package/dist/types/sovereignty.d.mts +6 -0
  254. package/dist/types/status.d.mts +4 -0
  255. package/dist/types/universe.d.mts +27 -0
  256. package/dist/types/wallet.d.mts +6 -0
  257. package/dist/types/wars.d.mts +4 -0
  258. package/package.json +92 -24
  259. package/dist/chunk-7A72QFDF.mjs.map +0 -1
  260. package/dist/chunk-HPSACXX3.js.map +0 -1
package/dist/index.mjs CHANGED
@@ -9,39 +9,6 @@ import {
9
9
  isSsoError,
10
10
  isTokenRevoked
11
11
  } from "./chunk-R7D7M2LQ.mjs";
12
- import {
13
- CircuitBreaker,
14
- CircuitOpenError,
15
- EsiError,
16
- EsiValidationError,
17
- TimeoutError,
18
- buildError,
19
- createDefaultLogger,
20
- getLogger,
21
- isCircuitOpen,
22
- isEsiError,
23
- isForbidden,
24
- isNotFound,
25
- isRateLimited,
26
- isRetryable,
27
- isServerError,
28
- isTimeout,
29
- isUnauthorized,
30
- isValidationError,
31
- logDebug,
32
- logDebug2,
33
- logError,
34
- logError2,
35
- logFatal,
36
- logInfo,
37
- logInfo2,
38
- logTrace,
39
- logWarn,
40
- logWarn2,
41
- sanitizeUrl,
42
- setLogger,
43
- toPinoLogger
44
- } from "./chunk-7A72QFDF.mjs";
45
12
  import {
46
13
  AccessListSchema,
47
14
  AgentResearchSchema,
@@ -207,6 +174,39 @@ import {
207
174
  WarSchema,
208
175
  schemas_exports
209
176
  } from "./chunk-VZS32UQ3.mjs";
177
+ import {
178
+ CircuitBreaker,
179
+ CircuitOpenError,
180
+ EsiError,
181
+ EsiValidationError,
182
+ TimeoutError,
183
+ buildError,
184
+ createDefaultLogger,
185
+ getLogger,
186
+ isCircuitOpen,
187
+ isEsiError,
188
+ isForbidden,
189
+ isNotFound,
190
+ isRateLimited,
191
+ isRetryable,
192
+ isServerError,
193
+ isTimeout,
194
+ isUnauthorized,
195
+ isValidationError,
196
+ logDebug,
197
+ logDebug2,
198
+ logError,
199
+ logError2,
200
+ logFatal,
201
+ logInfo,
202
+ logInfo2,
203
+ logTrace,
204
+ logWarn,
205
+ logWarn2,
206
+ sanitizeUrl,
207
+ setLogger,
208
+ toPinoLogger
209
+ } from "./chunk-4W66ONJI.mjs";
210
210
  import "./chunk-JIW4BXLP.mjs";
211
211
 
212
212
  // src/core/middleware/Middleware.ts
@@ -428,17 +428,23 @@ var ApiClient = class {
428
428
 
429
429
  // src/core/cache/cacheKey.ts
430
430
  import { createHash } from "crypto";
431
- function buildCacheKey(url, client, requiresAuth = false) {
432
- if (!requiresAuth) return url;
431
+ function scopeToIdentity(key, client, requiresAuth) {
432
+ if (!requiresAuth) return key;
433
433
  const authHeader = client.getAuthorizationHeader();
434
- if (!authHeader) return url;
434
+ if (!authHeader) return key;
435
435
  const hash = createHash("sha256").update(authHeader).digest("hex").slice(0, 16);
436
- return `${hash}:${url}`;
436
+ return `${hash}:${key}`;
437
+ }
438
+ function buildCacheKey(url, client, requiresAuth = false) {
439
+ return scopeToIdentity(url, client, requiresAuth);
440
+ }
441
+ function buildDedupeKey(endpoint, client, requiresAuth = false) {
442
+ return scopeToIdentity(endpoint, client, requiresAuth);
437
443
  }
438
444
 
439
445
  // src/core/constants.ts
440
446
  var PACKAGE_NAME = "esi.ts";
441
- var PACKAGE_VERSION = "10.0.0";
447
+ var PACKAGE_VERSION = "10.2.1";
442
448
  var USER_AGENT = `${PACKAGE_NAME}/${PACKAGE_VERSION}`;
443
449
  var COMPATIBILITY_DATE = "2026-05-19";
444
450
 
@@ -503,6 +509,8 @@ var esiCacheTtls = {
503
509
  "GET:alliances/{alliance_id}/contacts/labels": 300,
504
510
  "GET:alliances/{alliance_id}/corporations": 3600,
505
511
  "GET:characters/{character_id}": 86400,
512
+ "GET:characters/{character_id}/access-lists": 300,
513
+ "GET:characters/{character_id}/access-lists/{access_list_id}": 300,
506
514
  "GET:characters/{character_id}/agents_research": 3600,
507
515
  "GET:characters/{character_id}/assets": 3600,
508
516
  "GET:characters/{character_id}/attributes": 120,
@@ -533,6 +541,8 @@ var esiCacheTtls = {
533
541
  "GET:characters/{character_id}/mail/labels": 30,
534
542
  "GET:characters/{character_id}/mail/lists": 120,
535
543
  "GET:characters/{character_id}/medals": 3600,
544
+ "GET:characters/{character_id}/mercenary-tactical-operations": 300,
545
+ "GET:characters/{character_id}/mercenary-tactical-operations/{operation_id}": 300,
536
546
  "GET:characters/{character_id}/mining": 600,
537
547
  "GET:characters/{character_id}/notifications": 600,
538
548
  "GET:characters/{character_id}/notifications/contacts": 600,
@@ -547,6 +557,8 @@ var esiCacheTtls = {
547
557
  "GET:characters/{character_id}/skillqueue": 60,
548
558
  "GET:characters/{character_id}/skills": 60,
549
559
  "GET:characters/{character_id}/standings": 3600,
560
+ "GET:characters/{character_id}/structures/mercenary-dens": 3600,
561
+ "GET:characters/{character_id}/structures/mercenary-dens/{mercenary_den_id}": 3600,
550
562
  "GET:characters/{character_id}/titles": 3600,
551
563
  "GET:characters/{character_id}/wallet": 120,
552
564
  "GET:characters/{character_id}/wallet/journal": 3600,
@@ -591,6 +603,10 @@ var esiCacheTtls = {
591
603
  "GET:corporations/{corporation_id}/starbases": 3600,
592
604
  "GET:corporations/{corporation_id}/starbases/{starbase_id}": 3600,
593
605
  "GET:corporations/{corporation_id}/structures": 3600,
606
+ "GET:corporations/{corporation_id}/structures/skyhooks": 3600,
607
+ "GET:corporations/{corporation_id}/structures/skyhooks/{skyhook_id}": 3600,
608
+ "GET:corporations/{corporation_id}/structures/sovereignty-hubs": 3600,
609
+ "GET:corporations/{corporation_id}/structures/sovereignty-hubs/{sovereignty_hub_id}": 3600,
594
610
  "GET:corporations/{corporation_id}/titles": 3600,
595
611
  "GET:corporations/{corporation_id}/wallets": 300,
596
612
  "GET:corporations/{corporation_id}/wallets/{division}/journal": 3600,
@@ -611,9 +627,9 @@ var esiCacheTtls = {
611
627
  "GET:markets/structures/{structure_id}": 300,
612
628
  "GET:meta/changelog": 600,
613
629
  "GET:meta/compatibility-dates": 600,
630
+ "GET:skyhooks/raidable": 300,
614
631
  "GET:sovereignty/campaigns": 5,
615
- "GET:sovereignty/map": 3600,
616
- "GET:sovereignty/structures": 120,
632
+ "GET:sovereignty/systems": 300,
617
633
  "GET:status": 30,
618
634
  "GET:universe/schematics/{schematic_id}": 3600,
619
635
  "GET:universe/structures": 3600,
@@ -662,6 +678,10 @@ function trySpecAwareCacheHit(client, url, method, templatePath, resolveCache2,
662
678
  }
663
679
  return null;
664
680
  }
681
+ function hasCachedEntry(client, url, resolveCache2, requiresAuth = false) {
682
+ const cache = resolveCache2(client);
683
+ return !!cache && cache.has(buildCacheKey(url, client, requiresAuth));
684
+ }
665
685
  function tryStaleCacheResponse(client, url, parsed, resolveCache2, requiresAuth = false) {
666
686
  const cache = resolveCache2(client);
667
687
  if (!cache) return null;
@@ -677,10 +697,40 @@ function tryStaleCacheResponse(client, url, parsed, resolveCache2, requiresAuth
677
697
  cacheHitType: "stale-on-error"
678
698
  };
679
699
  }
680
- function cacheResponse(client, url, method, endpoint, parsed, data, useETag, resolveCache2, templatePath, requiresAuth = false) {
700
+ var RECENT_WRITES = 64;
701
+ var writeLogs = /* @__PURE__ */ new WeakMap();
702
+ function writeLogFor(cache) {
703
+ let log = writeLogs.get(cache);
704
+ if (!log) {
705
+ log = { generation: 0, recent: [] };
706
+ writeLogs.set(cache, log);
707
+ }
708
+ return log;
709
+ }
710
+ function currentWriteGeneration(client, resolveCache2) {
711
+ const cache = resolveCache2(client);
712
+ return cache ? writeLogFor(cache).generation : 0;
713
+ }
714
+ function invalidatedSince(cache, generation, key) {
715
+ const log = writeLogFor(cache);
716
+ if (log.generation === generation) return false;
717
+ if (log.generation - generation > log.recent.length) return true;
718
+ return log.recent.some(
719
+ (write) => write.generation > generation && key.includes(write.path)
720
+ );
721
+ }
722
+ function cacheResponse(client, url, method, endpoint, parsed, data, useETag, resolveCache2, templatePath, requiresAuth = false, sentAtWriteGeneration) {
681
723
  const cache = resolveCache2(client);
682
724
  if (useETag && method === "GET" && cache && parsed.etag) {
683
725
  const key = buildCacheKey(url, client, requiresAuth);
726
+ if (sentAtWriteGeneration !== void 0 && invalidatedSince(cache, sentAtWriteGeneration, key)) {
727
+ logDebug2(
728
+ client,
729
+ `Not caching ${url}: a write invalidated it while the request was in flight`,
730
+ { method }
731
+ );
732
+ return;
733
+ }
684
734
  const headerTtl = parseCacheControlTtl(parsed.raw);
685
735
  const specTtlMs = templatePath ? lookupSpecTtl(method, templatePath) : void 0;
686
736
  const freshnessTtl = specTtlMs ?? headerTtl;
@@ -710,9 +760,16 @@ function evictRejectedResponse(client, endpoint, requiresAuth, resolveCache2) {
710
760
  }
711
761
  }
712
762
  function invalidateAfterWrite(client, method, endpoint, resolveCache2) {
763
+ if (method === "GET") return;
764
+ const path2 = endpoint.split("?")[0];
765
+ client.getDeduplicator()?.detachByPath?.(path2);
713
766
  const cache = resolveCache2(client);
714
- if (method !== "GET" && cache) {
715
- cache.deleteByPath(endpoint.split("?")[0]);
767
+ if (cache) {
768
+ cache.deleteByPath(path2);
769
+ const log = writeLogFor(cache);
770
+ log.generation += 1;
771
+ log.recent.push({ generation: log.generation, path: path2 });
772
+ if (log.recent.length > RECENT_WRITES) log.recent.shift();
716
773
  }
717
774
  }
718
775
 
@@ -729,10 +786,14 @@ var STATUS_MESSAGES = {
729
786
  422: "Unprocessable Entity",
730
787
  429: "Too many requests",
731
788
  500: "Internal server error",
789
+ 502: "Bad Gateway",
732
790
  503: "Service Unavailable",
733
791
  504: "Gateway Timeout",
734
792
  520: "Internal server error, did the request terminate too soon?"
735
793
  };
794
+ function statusMessage(response) {
795
+ return STATUS_MESSAGES[response.status] || response.statusText || `HTTP ${response.status}`;
796
+ }
736
797
  function handleEarlyStatus(client, status, url, parsed, useETag, resolveCache2, requiresAuth = false) {
737
798
  if (status === 201) {
738
799
  return { headers: parsed.raw, body: void 0, status: 201 };
@@ -751,7 +812,11 @@ function handleEarlyStatus(client, status, url, parsed, useETag, resolveCache2,
751
812
  status,
752
813
  cacheHitType: "etag-304"
753
814
  });
754
- const headers = { ...cachedEntry.headers, ...parsed.raw };
815
+ const headers = {
816
+ ...cachedEntry.headers,
817
+ ...parsed.raw
818
+ };
819
+ if ("etag" in parsed.raw) headers["etag"] = cachedEntry.etag;
755
820
  cache.set(
756
821
  key,
757
822
  cachedEntry.etag,
@@ -790,8 +855,8 @@ async function readEsiErrorReason(response) {
790
855
  }
791
856
  }
792
857
  function handleErrorResponse(client, response, url, parsed, useETag, resolveCache2, requiresAuth = false, esiReason) {
793
- const statusMessage = STATUS_MESSAGES[response.status] || response.statusText;
794
- const errorMessage = esiReason ? `${statusMessage}: ${esiReason}` : statusMessage;
858
+ const text = statusMessage(response);
859
+ const errorMessage = esiReason ? `${text}: ${esiReason}` : text;
795
860
  if (response.status >= 500 && useETag) {
796
861
  const staleResult = tryStaleCacheResponse(
797
862
  client,
@@ -839,7 +904,7 @@ function wrapError(error, client) {
839
904
 
840
905
  // src/core/util/retry.ts
841
906
  function retryDelay(attempt, baseMs, maxMs) {
842
- const exponential = baseMs * Math.pow(2, attempt);
907
+ const exponential = baseMs === 0 ? 0 : baseMs * Math.pow(2, attempt);
843
908
  const jitter = exponential * (0.75 + Math.random() * 0.5);
844
909
  return Math.min(jitter, maxMs);
845
910
  }
@@ -1045,7 +1110,7 @@ function handleCursorPagination(parsed, data) {
1045
1110
  };
1046
1111
  return { headers: parsed.raw, body: data, status: 200, cursors };
1047
1112
  }
1048
- async function handleOffsetPagination(client, endpoint, method, requiresAuth, parsed, data, body, url, useETag, pageFetch, resolveCache2, templatePath) {
1113
+ async function handleOffsetPagination(client, endpoint, method, requiresAuth, parsed, data, body, url, useETag, pageFetch, resolveCache2, templatePath, sentAtWriteGeneration) {
1049
1114
  const totalPages = parsed.xPages;
1050
1115
  if (totalPages <= 1) {
1051
1116
  return { headers: parsed.raw, body: data, status: 200 };
@@ -1081,7 +1146,9 @@ async function handleOffsetPagination(client, endpoint, method, requiresAuth, pa
1081
1146
  allData,
1082
1147
  useETag,
1083
1148
  resolveCache2,
1084
- templatePath
1149
+ templatePath,
1150
+ requiresAuth,
1151
+ sentAtWriteGeneration
1085
1152
  );
1086
1153
  return { headers: parsed.raw, body: allData, status: 200 };
1087
1154
  } catch (paginationError) {
@@ -1186,6 +1253,17 @@ function networkError(err, url) {
1186
1253
  { cause: err }
1187
1254
  );
1188
1255
  }
1256
+ async function bufferBody(response) {
1257
+ if (typeof response.text !== "function") return;
1258
+ const text = await response.text();
1259
+ Object.defineProperties(response, {
1260
+ text: { value: () => Promise.resolve(text), configurable: true },
1261
+ json: {
1262
+ value: () => Promise.resolve(text).then((t) => JSON.parse(t)),
1263
+ configurable: true
1264
+ }
1265
+ });
1266
+ }
1189
1267
  async function executeSingleFetch(client, endpoint, method, body, requiresAuth, useETag, resolveCache2, resolveRateLimiter2, resolveCircuitBreaker2, requestTimeout, templatePath) {
1190
1268
  const rawUrl = `${client.getLink()}/${endpoint}`;
1191
1269
  const builtHeaders = buildRequestHeaders(
@@ -1226,6 +1304,7 @@ async function executeSingleFetch(client, endpoint, method, body, requiresAuth,
1226
1304
  let response;
1227
1305
  try {
1228
1306
  response = await client.getFetch()(url, options);
1307
+ await bufferBody(response);
1229
1308
  } catch (err) {
1230
1309
  clearTimeout(timer);
1231
1310
  if (cb) {
@@ -1295,11 +1374,11 @@ async function fetchOnePage(client, endpoint, method, body, requiresAuth, useETa
1295
1374
  templatePath
1296
1375
  );
1297
1376
  if (!response.ok) {
1298
- const statusMessage = STATUS_MESSAGES[response.status] || response.statusText;
1377
+ const text = statusMessage(response);
1299
1378
  const reason = await readEsiErrorReason(response);
1300
1379
  throw new EsiError(
1301
1380
  response.status,
1302
- reason ? `${statusMessage}: ${reason}` : statusMessage,
1381
+ reason ? `${text}: ${reason}` : text,
1303
1382
  url,
1304
1383
  parsed.requestId ?? void 0
1305
1384
  );
@@ -1324,6 +1403,13 @@ var executeRequest = async (client, endpoint, method, body, requiresAuth = false
1324
1403
  );
1325
1404
  };
1326
1405
  try {
1406
+ const writeGeneration = currentWriteGeneration(client, resolveCache);
1407
+ const revalidating = useETag && method === "GET" && hasCachedEntry(
1408
+ client,
1409
+ `${client.getLink()}/${endpoint}`,
1410
+ resolveCache,
1411
+ requiresAuth
1412
+ );
1327
1413
  const { response, parsed, url } = await executeSingleFetch(
1328
1414
  client,
1329
1415
  endpoint,
@@ -1349,6 +1435,18 @@ var executeRequest = async (client, endpoint, method, body, requiresAuth = false
1349
1435
  }
1350
1436
  return finish({ headers: parsed.raw, body: data2, status: 201 });
1351
1437
  }
1438
+ if (response.status === 304 && revalidating && !hasCachedEntry(client, url, resolveCache, requiresAuth)) {
1439
+ return await executeRequest(
1440
+ client,
1441
+ endpoint,
1442
+ method,
1443
+ body,
1444
+ requiresAuth,
1445
+ useETag,
1446
+ requestTimeout,
1447
+ templatePath
1448
+ );
1449
+ }
1352
1450
  const earlyResult = handleEarlyStatus(
1353
1451
  client,
1354
1452
  response.status,
@@ -1373,18 +1471,21 @@ var executeRequest = async (client, endpoint, method, body, requiresAuth = false
1373
1471
  return finish(staleOrThrow);
1374
1472
  }
1375
1473
  const data = await parseJsonBody(client, response, url);
1376
- cacheResponse(
1377
- client,
1378
- url,
1379
- method,
1380
- endpoint,
1381
- parsed,
1382
- data,
1383
- useETag,
1384
- resolveCache,
1385
- templatePath,
1386
- requiresAuth
1387
- );
1474
+ if (parsed.xPages <= 1 || parsed.hasCursorPagination) {
1475
+ cacheResponse(
1476
+ client,
1477
+ url,
1478
+ method,
1479
+ endpoint,
1480
+ parsed,
1481
+ data,
1482
+ useETag,
1483
+ resolveCache,
1484
+ templatePath,
1485
+ requiresAuth,
1486
+ writeGeneration
1487
+ );
1488
+ }
1388
1489
  const cursorResult = handleCursorPagination(parsed, data);
1389
1490
  if (cursorResult) return finish(cursorResult);
1390
1491
  const pageFetch = async (paginatedEndpoint) => {
@@ -1415,7 +1516,8 @@ var executeRequest = async (client, endpoint, method, body, requiresAuth = false
1415
1516
  useETag,
1416
1517
  pageFetch,
1417
1518
  resolveCache,
1418
- templatePath
1519
+ templatePath,
1520
+ writeGeneration
1419
1521
  );
1420
1522
  return finish(paginatedResult);
1421
1523
  } catch (error) {
@@ -1452,24 +1554,26 @@ var handleSinglePageRequest = async (client, endpoint, method, body, requiresAut
1452
1554
  var handleRequest = async (client, endpoint, method, body, requiresAuth = false, useETag = true, templatePath, requestTimeout) => {
1453
1555
  const rawUrl = `${client.getLink()}/${endpoint}`;
1454
1556
  const startTime = Date.now();
1455
- const specHit = trySpecAwareCacheHit(
1456
- client,
1457
- rawUrl,
1458
- method,
1459
- templatePath,
1460
- resolveCache,
1461
- requiresAuth
1462
- );
1463
- if (specHit) {
1464
- return applyResponseInterceptors(
1557
+ const specCacheHit = () => {
1558
+ const hit = trySpecAwareCacheHit(
1465
1559
  client,
1466
- specHit,
1560
+ rawUrl,
1561
+ method,
1562
+ templatePath,
1563
+ resolveCache,
1564
+ requiresAuth
1565
+ );
1566
+ return hit ? applyResponseInterceptors(
1567
+ client,
1568
+ hit,
1467
1569
  rawUrl,
1468
1570
  endpoint,
1469
1571
  method,
1470
1572
  startTime
1471
- );
1472
- }
1573
+ ) : null;
1574
+ };
1575
+ const specHit = specCacheHit();
1576
+ if (specHit) return specHit;
1473
1577
  const doExecute = () => executeRequest(
1474
1578
  client,
1475
1579
  endpoint,
@@ -1482,7 +1586,16 @@ var handleRequest = async (client, endpoint, method, body, requiresAuth = false,
1482
1586
  );
1483
1587
  const dedup = client.getDeduplicator();
1484
1588
  const canDedup = dedup && method === "GET" && !body;
1485
- const operation = () => canDedup ? dedup.dedupe(endpoint, doExecute) : doExecute();
1589
+ let attempted = false;
1590
+ const operation = () => {
1591
+ const retryHit = attempted ? specCacheHit() : null;
1592
+ attempted = true;
1593
+ if (retryHit) return retryHit;
1594
+ return canDedup ? dedup.dedupe(
1595
+ buildDedupeKey(endpoint, client, requiresAuth),
1596
+ doExecute
1597
+ ) : doExecute();
1598
+ };
1486
1599
  const retryStrategy = resolveRetryStrategy(client);
1487
1600
  return retryStrategy.execute(operation, {
1488
1601
  client,
@@ -1831,7 +1944,6 @@ async function fetchAllPages(client, endpoint, method, requiresAuth = false, bod
1831
1944
  );
1832
1945
  const totalPages = parseInt(firstResponse.headers["x-pages"] || "1", 10);
1833
1946
  const result = extractArray(firstBody);
1834
- if (totalPages <= 1) return result;
1835
1947
  const remaining = Array.from({ length: totalPages - 1 }, (_, i) => i + 2);
1836
1948
  for (let i = 0; i < remaining.length; i += concurrency) {
1837
1949
  const batch = remaining.slice(i, i + concurrency);
@@ -7680,6 +7792,8 @@ var ETagCacheManager = class {
7680
7792
  var esiRateLimitGroups = {
7681
7793
  "GET:alliances/{alliance_id}/contacts": { group: "alliance-social", maxTokens: 300, windowSizeMs: 9e5 },
7682
7794
  "GET:alliances/{alliance_id}/contacts/labels": { group: "alliance-social", maxTokens: 300, windowSizeMs: 9e5 },
7795
+ "GET:characters/{character_id}/access-lists": { group: "char-access", maxTokens: 600, windowSizeMs: 9e5 },
7796
+ "GET:characters/{character_id}/access-lists/{access_list_id}": { group: "char-access", maxTokens: 600, windowSizeMs: 9e5 },
7683
7797
  "GET:characters/{character_id}/agents_research": { group: "char-industry", maxTokens: 600, windowSizeMs: 9e5 },
7684
7798
  "GET:characters/{character_id}/assets": { group: "char-asset", maxTokens: 1800, windowSizeMs: 9e5 },
7685
7799
  "POST:characters/{character_id}/assets/locations": { group: "char-asset", maxTokens: 1800, windowSizeMs: 9e5 },
@@ -7723,6 +7837,8 @@ var esiRateLimitGroups = {
7723
7837
  "DELETE:characters/{character_id}/mail/labels/{label_id}": { group: "char-social", maxTokens: 600, windowSizeMs: 9e5 },
7724
7838
  "GET:characters/{character_id}/mail/lists": { group: "char-social", maxTokens: 600, windowSizeMs: 9e5 },
7725
7839
  "GET:characters/{character_id}/medals": { group: "char-detail", maxTokens: 600, windowSizeMs: 9e5 },
7840
+ "GET:characters/{character_id}/mercenary-tactical-operations": { group: "char-activity", maxTokens: 150, windowSizeMs: 9e5 },
7841
+ "GET:characters/{character_id}/mercenary-tactical-operations/{operation_id}": { group: "char-activity", maxTokens: 150, windowSizeMs: 9e5 },
7726
7842
  "GET:characters/{character_id}/mining": { group: "char-industry", maxTokens: 600, windowSizeMs: 9e5 },
7727
7843
  "GET:characters/{character_id}/notifications": { group: "char-notification", maxTokens: 15, windowSizeMs: 9e5 },
7728
7844
  "GET:characters/{character_id}/notifications/contacts": { group: "char-social", maxTokens: 600, windowSizeMs: 9e5 },
@@ -7735,6 +7851,8 @@ var esiRateLimitGroups = {
7735
7851
  "GET:characters/{character_id}/skillqueue": { group: "char-detail", maxTokens: 600, windowSizeMs: 9e5 },
7736
7852
  "GET:characters/{character_id}/skills": { group: "char-detail", maxTokens: 600, windowSizeMs: 9e5 },
7737
7853
  "GET:characters/{character_id}/standings": { group: "char-social", maxTokens: 600, windowSizeMs: 9e5 },
7854
+ "GET:characters/{character_id}/structures/mercenary-dens": { group: "char-structure", maxTokens: 30, windowSizeMs: 9e5 },
7855
+ "GET:characters/{character_id}/structures/mercenary-dens/{mercenary_den_id}": { group: "char-structure", maxTokens: 30, windowSizeMs: 9e5 },
7738
7856
  "GET:characters/{character_id}/titles": { group: "char-detail", maxTokens: 600, windowSizeMs: 9e5 },
7739
7857
  "GET:characters/{character_id}/wallet": { group: "char-wallet", maxTokens: 150, windowSizeMs: 9e5 },
7740
7858
  "GET:characters/{character_id}/wallet/journal": { group: "char-wallet", maxTokens: 150, windowSizeMs: 9e5 },
@@ -7777,6 +7895,10 @@ var esiRateLimitGroups = {
7777
7895
  "GET:corporations/{corporation_id}/starbases": { group: "corp-structure", maxTokens: 300, windowSizeMs: 9e5 },
7778
7896
  "GET:corporations/{corporation_id}/starbases/{starbase_id}": { group: "corp-structure", maxTokens: 300, windowSizeMs: 9e5 },
7779
7897
  "GET:corporations/{corporation_id}/structures": { group: "corp-structure", maxTokens: 300, windowSizeMs: 9e5 },
7898
+ "GET:corporations/{corporation_id}/structures/skyhooks": { group: "corp-structure", maxTokens: 300, windowSizeMs: 9e5 },
7899
+ "GET:corporations/{corporation_id}/structures/skyhooks/{skyhook_id}": { group: "corp-structure", maxTokens: 300, windowSizeMs: 9e5 },
7900
+ "GET:corporations/{corporation_id}/structures/sovereignty-hubs": { group: "corp-structure", maxTokens: 300, windowSizeMs: 9e5 },
7901
+ "GET:corporations/{corporation_id}/structures/sovereignty-hubs/{sovereignty_hub_id}": { group: "corp-structure", maxTokens: 300, windowSizeMs: 9e5 },
7780
7902
  "GET:corporations/{corporation_id}/titles": { group: "corp-detail", maxTokens: 300, windowSizeMs: 9e5 },
7781
7903
  "GET:corporations/{corporation_id}/wallets": { group: "corp-wallet", maxTokens: 300, windowSizeMs: 9e5 },
7782
7904
  "GET:corporations/{corporation_id}/wallets/{division}/journal": { group: "corp-wallet", maxTokens: 300, windowSizeMs: 9e5 },
@@ -7812,9 +7934,9 @@ var esiRateLimitGroups = {
7812
7934
  "GET:meta/compatibility-dates": { group: "meta", maxTokens: 150, windowSizeMs: 9e5 },
7813
7935
  "GET:meta/status": { group: "meta", maxTokens: 150, windowSizeMs: 9e5 },
7814
7936
  "POST:route/{origin_system_id}/{destination_system_id}": { group: "routes", maxTokens: 3600, windowSizeMs: 9e5 },
7937
+ "GET:skyhooks/raidable": { group: "activity", maxTokens: 30, windowSizeMs: 9e5 },
7815
7938
  "GET:sovereignty/campaigns": { group: "sovereignty", maxTokens: 600, windowSizeMs: 9e5 },
7816
- "GET:sovereignty/map": { group: "sovereignty", maxTokens: 600, windowSizeMs: 9e5 },
7817
- "GET:sovereignty/structures": { group: "sovereignty", maxTokens: 600, windowSizeMs: 9e5 },
7939
+ "GET:sovereignty/systems": { group: "sovereignty", maxTokens: 600, windowSizeMs: 9e5 },
7818
7940
  "GET:status": { group: "status", maxTokens: 600, windowSizeMs: 9e5 },
7819
7941
  "POST:ui/autopilot/waypoint": { group: "ui", maxTokens: 900, windowSizeMs: 9e5 },
7820
7942
  "POST:ui/openwindow/contract": { group: "ui", maxTokens: 900, windowSizeMs: 9e5 },
@@ -7834,8 +7956,19 @@ function getTokenCost(statusCode) {
7834
7956
  if (statusCode >= 500 && statusCode < 600) return 0;
7835
7957
  return 2;
7836
7958
  }
7959
+ function retryAfterDeadline(value, now) {
7960
+ const trimmed = value.trim();
7961
+ if (/^\d+$/.test(trimmed)) return now + parseInt(trimmed, 10) * 1e3;
7962
+ if (!/[A-Za-z]/.test(trimmed)) return void 0;
7963
+ const date = Date.parse(trimmed);
7964
+ return Number.isNaN(date) ? void 0 : date;
7965
+ }
7837
7966
  var DEFAULT_WINDOW_MS = 9e5;
7838
- var DEFAULT_ERROR_LIMIT = { remain: 100, reset: 0 };
7967
+ var DEFAULT_ERROR_LIMIT = {
7968
+ remain: 100,
7969
+ reset: 0,
7970
+ exhaustedUntil: 0
7971
+ };
7839
7972
  var RateLimiter = class _RateLimiter {
7840
7973
  minDelayMs;
7841
7974
  decelerationThreshold;
@@ -7957,6 +8090,7 @@ var RateLimiter = class _RateLimiter {
7957
8090
  }
7958
8091
  updateFromResponse(headers, statusCode, templatePath, method, requestHeaders) {
7959
8092
  if (this.isTestMode) return;
8093
+ const now = Date.now();
7960
8094
  const responseGroup = headers["x-ratelimit-group"] || void 0;
7961
8095
  const bucket = this.getBucket(
7962
8096
  templatePath,
@@ -7973,23 +8107,30 @@ var RateLimiter = class _RateLimiter {
7973
8107
  if ("x-ratelimit-used" in headers) {
7974
8108
  bucket.used = parseInt(headers["x-ratelimit-used"], 10);
7975
8109
  }
7976
- bucket.lastUpdated = Date.now();
8110
+ bucket.lastUpdated = now;
7977
8111
  if ("retry-after" in headers) {
7978
- const retrySeconds = parseInt(headers["retry-after"], 10);
7979
- bucket.blockedUntil = Date.now() + retrySeconds * 1e3;
8112
+ const until = retryAfterDeadline(headers["retry-after"], now);
8113
+ if (until !== void 0) bucket.blockedUntil = until;
7980
8114
  }
7981
8115
  if (statusCode === 420 || statusCode === 429) {
7982
- if (bucket.blockedUntil <= Date.now()) {
7983
- bucket.blockedUntil = Date.now() + 6e4;
8116
+ if (bucket.blockedUntil <= now) {
8117
+ bucket.blockedUntil = now + 6e4;
7984
8118
  }
7985
8119
  }
7986
8120
  const errorLimit = this.resolveErrorLimit(requestHeaders);
7987
- if ("x-esi-error-limit-remain" in headers) {
7988
- errorLimit.remain = parseInt(headers["x-esi-error-limit-remain"], 10);
8121
+ const reportedRemain = "x-esi-error-limit-remain" in headers ? parseInt(headers["x-esi-error-limit-remain"], 10) : void 0;
8122
+ if (reportedRemain !== void 0 && reportedRemain > 0 && errorLimit.remain <= 0 && now < errorLimit.exhaustedUntil) {
8123
+ return;
8124
+ }
8125
+ if (reportedRemain !== void 0) {
8126
+ errorLimit.remain = reportedRemain;
7989
8127
  }
7990
8128
  if ("x-esi-error-limit-reset" in headers) {
7991
8129
  errorLimit.reset = parseInt(headers["x-esi-error-limit-reset"], 10);
7992
8130
  }
8131
+ if (reportedRemain !== void 0 && reportedRemain <= 0) {
8132
+ errorLimit.exhaustedUntil = now + errorLimit.reset * 1e3;
8133
+ }
7993
8134
  }
7994
8135
  updateRateLimitInfo(headers) {
7995
8136
  this.updateFromResponse(headers, 200);
@@ -8203,6 +8344,32 @@ var RequestDeduplicator = class {
8203
8344
  this.inflight.set(key, promise);
8204
8345
  return promise;
8205
8346
  }
8347
+ /**
8348
+ * Drop the in-flight entries whose key contains `pathSegment`, so a call
8349
+ * made after a write cannot join a request sent before it.
8350
+ *
8351
+ * The requests themselves keep running and whoever already joined them still
8352
+ * gets their answer. Only the map entry goes, which is what new callers look
8353
+ * in. Matching is `includes`, the same rule ETagCacheManager.deleteByPath
8354
+ * uses, so one written path invalidates the cache and detaches the reads of
8355
+ * it by the same test.
8356
+ */
8357
+ detachByPath(pathSegment) {
8358
+ let count = 0;
8359
+ for (const key of this.inflight.keys()) {
8360
+ if (key.includes(pathSegment)) {
8361
+ this.inflight.delete(key);
8362
+ count += 1;
8363
+ }
8364
+ }
8365
+ if (count > 0 && this.client) {
8366
+ logDebug2(
8367
+ this.client,
8368
+ `[Dedup] Detached ${count} in-flight request(s) matching ${pathSegment} after a write`
8369
+ );
8370
+ }
8371
+ return count;
8372
+ }
8206
8373
  get pending() {
8207
8374
  return this.inflight.size;
8208
8375
  }
@@ -8852,6 +9019,8 @@ var ApiClientBuilder = class {
8852
9019
  var esiEndpointScopes = {
8853
9020
  "GET:alliances/{alliance_id}/contacts": ["esi-alliances.read_contacts.v1"],
8854
9021
  "GET:alliances/{alliance_id}/contacts/labels": ["esi-alliances.read_contacts.v1"],
9022
+ "GET:characters/{character_id}/access-lists": ["esi-access.read_lists.v1"],
9023
+ "GET:characters/{character_id}/access-lists/{access_list_id}": ["esi-access.read_lists.v1"],
8855
9024
  "GET:characters/{character_id}/agents_research": ["esi-characters.read_agents_research.v1"],
8856
9025
  "GET:characters/{character_id}/assets": ["esi-assets.read_assets.v1"],
8857
9026
  "POST:characters/{character_id}/assets/locations": ["esi-assets.read_assets.v1"],
@@ -8895,6 +9064,8 @@ var esiEndpointScopes = {
8895
9064
  "DELETE:characters/{character_id}/mail/labels/{label_id}": ["esi-mail.organize_mail.v1"],
8896
9065
  "GET:characters/{character_id}/mail/lists": ["esi-mail.read_mail.v1"],
8897
9066
  "GET:characters/{character_id}/medals": ["esi-characters.read_medals.v1"],
9067
+ "GET:characters/{character_id}/mercenary-tactical-operations": ["esi-activities.read_character.v1"],
9068
+ "GET:characters/{character_id}/mercenary-tactical-operations/{operation_id}": ["esi-activities.read_character.v1"],
8898
9069
  "GET:characters/{character_id}/mining": ["esi-industry.read_character_mining.v1"],
8899
9070
  "GET:characters/{character_id}/notifications": ["esi-characters.read_notifications.v1"],
8900
9071
  "GET:characters/{character_id}/notifications/contacts": ["esi-characters.read_notifications.v1"],
@@ -8909,6 +9080,8 @@ var esiEndpointScopes = {
8909
9080
  "GET:characters/{character_id}/skillqueue": ["esi-skills.read_skillqueue.v1"],
8910
9081
  "GET:characters/{character_id}/skills": ["esi-skills.read_skills.v1"],
8911
9082
  "GET:characters/{character_id}/standings": ["esi-characters.read_standings.v1"],
9083
+ "GET:characters/{character_id}/structures/mercenary-dens": ["esi-structures.read_character.v1"],
9084
+ "GET:characters/{character_id}/structures/mercenary-dens/{mercenary_den_id}": ["esi-structures.read_character.v1"],
8912
9085
  "GET:characters/{character_id}/titles": ["esi-characters.read_titles.v1"],
8913
9086
  "GET:characters/{character_id}/wallet": ["esi-wallet.read_character_wallet.v1"],
8914
9087
  "GET:characters/{character_id}/wallet/journal": ["esi-wallet.read_character_wallet.v1"],
@@ -8953,6 +9126,10 @@ var esiEndpointScopes = {
8953
9126
  "GET:corporations/{corporation_id}/starbases": ["esi-corporations.read_starbases.v1"],
8954
9127
  "GET:corporations/{corporation_id}/starbases/{starbase_id}": ["esi-corporations.read_starbases.v1"],
8955
9128
  "GET:corporations/{corporation_id}/structures": ["esi-corporations.read_structures.v1"],
9129
+ "GET:corporations/{corporation_id}/structures/skyhooks": ["esi-structures.read_corporation.v1"],
9130
+ "GET:corporations/{corporation_id}/structures/skyhooks/{skyhook_id}": ["esi-structures.read_corporation.v1"],
9131
+ "GET:corporations/{corporation_id}/structures/sovereignty-hubs": ["esi-structures.read_corporation.v1"],
9132
+ "GET:corporations/{corporation_id}/structures/sovereignty-hubs/{sovereignty_hub_id}": ["esi-structures.read_corporation.v1"],
8956
9133
  "GET:corporations/{corporation_id}/titles": ["esi-corporations.read_titles.v1"],
8957
9134
  "GET:corporations/{corporation_id}/wallets": ["esi-wallet.read_corporation_wallets.v1"],
8958
9135
  "GET:corporations/{corporation_id}/wallets/{division}/journal": ["esi-wallet.read_corporation_wallets.v1"],
@@ -9189,7 +9366,7 @@ function resolveLimit(requested) {
9189
9366
  }
9190
9367
  async function runWithConcurrency(items, worker, options = {}) {
9191
9368
  const limit = resolveLimit(options.concurrency);
9192
- const results = new Array(items.length);
9369
+ const results = [];
9193
9370
  let nextIndex = 0;
9194
9371
  let completed = 0;
9195
9372
  async function runOne() {