@lgriffin/esi.ts 5.1.0 → 5.2.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 (53) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +174 -7
  3. package/dist/EsiClient.d.ts +5 -0
  4. package/dist/EsiClient.d.ts.map +1 -1
  5. package/dist/EsiClient.js +13 -0
  6. package/dist/core/ApiClient.d.ts +4 -0
  7. package/dist/core/ApiClient.d.ts.map +1 -1
  8. package/dist/core/ApiClient.js +7 -0
  9. package/dist/core/ApiRequestHandler.d.ts +3 -1
  10. package/dist/core/ApiRequestHandler.d.ts.map +1 -1
  11. package/dist/core/ApiRequestHandler.js +106 -40
  12. package/dist/core/BatchRequestHandler.d.ts +12 -0
  13. package/dist/core/BatchRequestHandler.d.ts.map +1 -0
  14. package/dist/core/BatchRequestHandler.js +66 -0
  15. package/dist/core/constants.d.ts +2 -2
  16. package/dist/core/constants.js +1 -1
  17. package/dist/core/endpoints/createClient.d.ts.map +1 -1
  18. package/dist/core/endpoints/createClient.js +14 -2
  19. package/dist/core/endpoints/esi-cache-ttls.generated.d.ts +2 -0
  20. package/dist/core/endpoints/esi-cache-ttls.generated.d.ts.map +1 -0
  21. package/dist/core/endpoints/esi-cache-ttls.generated.js +126 -0
  22. package/dist/core/endpoints/esi-rate-limit-groups.generated.d.ts +7 -0
  23. package/dist/core/endpoints/esi-rate-limit-groups.generated.d.ts.map +1 -0
  24. package/dist/core/endpoints/esi-rate-limit-groups.generated.js +153 -0
  25. package/dist/core/pagination/PaginationHandler.d.ts +1 -1
  26. package/dist/core/pagination/PaginationHandler.d.ts.map +1 -1
  27. package/dist/core/pagination/PaginationHandler.js +2 -2
  28. package/dist/core/rateLimiter/IRateLimiter.d.ts +13 -3
  29. package/dist/core/rateLimiter/IRateLimiter.d.ts.map +1 -1
  30. package/dist/core/rateLimiter/RateLimiter.d.ts +24 -51
  31. package/dist/core/rateLimiter/RateLimiter.d.ts.map +1 -1
  32. package/dist/core/rateLimiter/RateLimiter.js +208 -98
  33. package/dist/core/util/error.d.ts +5 -1
  34. package/dist/core/util/error.d.ts.map +1 -1
  35. package/dist/core/util/error.js +11 -2
  36. package/dist/core/util/retry.d.ts +8 -0
  37. package/dist/core/util/retry.d.ts.map +1 -0
  38. package/dist/core/util/retry.js +9 -0
  39. package/dist/core/util/stringUtil.d.ts +2 -0
  40. package/dist/core/util/stringUtil.d.ts.map +1 -0
  41. package/dist/core/util/stringUtil.js +6 -0
  42. package/dist/index.d.ts +5 -2
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +7 -2
  45. package/dist/types/api-responses.d.ts +1 -0
  46. package/dist/types/api-responses.d.ts.map +1 -1
  47. package/dist/types/api-responses.js +24 -0
  48. package/dist/types/common.d.ts +9 -0
  49. package/dist/types/common.d.ts.map +1 -1
  50. package/dist/types/generated/esi-spec.generated.d.ts +1763 -0
  51. package/dist/types/generated/esi-spec.generated.d.ts.map +1 -0
  52. package/dist/types/generated/esi-spec.generated.js +6 -0
  53. package/package.json +4 -2
@@ -1,24 +1,10 @@
1
1
  "use strict";
2
- /**
3
- * Rate Limiter for ESI API calls
4
- *
5
- * Implements both the new floating-window rate limiting system and the legacy
6
- * error-limit system per the official ESI documentation:
7
- *
8
- * New system (X-Ratelimit-* headers):
9
- * - Floating window with token bucket per IP+route group
10
- * - Token costs: 2xx = 2 tokens, 3xx = 1 token, 4xx = 5 tokens, 5xx = 0 tokens
11
- * - Returns 429 when bucket is empty, with Retry-After header
12
- *
13
- * Legacy system (x-esi-error-limit-* headers):
14
- * - 100 non-2xx/3xx errors per minute
15
- * - Returns 420 when limit exceeded, with Retry-After header
16
- */
17
2
  Object.defineProperty(exports, "__esModule", { value: true });
18
3
  exports.RateLimiter = void 0;
4
+ const esi_rate_limit_groups_generated_1 = require("../endpoints/esi-rate-limit-groups.generated");
5
+ const stringUtil_1 = require("../util/stringUtil");
19
6
  const loggerUtil_1 = require("../logger/loggerUtil");
20
7
  const sleep_1 = require("../util/sleep");
21
- /** Token costs per HTTP status code range, per ESI docs */
22
8
  function getTokenCost(statusCode) {
23
9
  if (statusCode >= 200 && statusCode < 300)
24
10
  return 2;
@@ -30,136 +16,189 @@ function getTokenCost(statusCode) {
30
16
  return 0;
31
17
  return 2;
32
18
  }
19
+ const DEFAULT_WINDOW_MS = 900_000;
33
20
  class RateLimiter {
34
- rateLimitInfo;
35
- lastRequestTime = 0;
36
21
  minDelayMs;
37
- isTestMode = false;
38
22
  decelerationThreshold;
23
+ userKeyExtractor;
24
+ lastRequestTime = 0;
25
+ isTestMode = false;
26
+ errorLimitRemain = 100;
27
+ errorLimitReset = 0;
28
+ defaultBuckets = new Map();
29
+ userBuckets = null;
30
+ fallbackBucket;
31
+ lastCleanup = 0;
32
+ static CLEANUP_INTERVAL_MS = 60_000;
39
33
  constructor(config) {
40
34
  this.minDelayMs = config?.minDelayMs ?? 50;
41
35
  this.decelerationThreshold = config?.decelerationThreshold ?? 0.2;
42
- this.rateLimitInfo = this.defaultInfo();
36
+ this.userKeyExtractor = config?.userKeyExtractor;
37
+ if (this.userKeyExtractor) {
38
+ this.userBuckets = new Map();
39
+ }
40
+ this.fallbackBucket = this.createFallbackBucket();
41
+ }
42
+ createFallbackBucket() {
43
+ return {
44
+ group: '__fallback__',
45
+ remaining: -1,
46
+ limit: 0,
47
+ used: 0,
48
+ windowSizeMs: DEFAULT_WINDOW_MS,
49
+ blockedUntil: 0,
50
+ lastUpdated: 0,
51
+ };
52
+ }
53
+ createBucketFromSpec(spec) {
54
+ return {
55
+ group: spec.group,
56
+ remaining: spec.maxTokens,
57
+ limit: spec.maxTokens,
58
+ used: 0,
59
+ windowSizeMs: spec.windowSizeMs,
60
+ blockedUntil: 0,
61
+ lastUpdated: 0,
62
+ };
43
63
  }
44
- defaultInfo() {
64
+ createBucketForGroup(groupName) {
45
65
  return {
46
- remaining: -1, // -1 means "no data yet"
66
+ group: groupName,
67
+ remaining: -1,
47
68
  limit: 0,
48
69
  used: 0,
49
- group: null,
50
- errorLimitRemain: 100,
51
- errorLimitReset: 0,
52
- retryAfter: null,
70
+ windowSizeMs: DEFAULT_WINDOW_MS,
53
71
  blockedUntil: 0,
72
+ lastUpdated: 0,
54
73
  };
55
74
  }
56
- /**
57
- * Update rate limit information from response headers and status code.
58
- * Must be called on EVERY response, not just 2xx.
59
- */
60
- updateFromResponse(headers, statusCode) {
75
+ lookupGroupSpec(method, templatePath) {
76
+ if (!templatePath || !method)
77
+ return undefined;
78
+ const normalized = templatePath
79
+ .replace(/\/$/, '')
80
+ .replace(/\{(\w+)\}/g, (_, name) => `{${(0, stringUtil_1.camelToSnake)(name)}}`);
81
+ const key = `${method}:${normalized}`;
82
+ return esi_rate_limit_groups_generated_1.esiRateLimitGroups[key];
83
+ }
84
+ resolveBucketMap(requestHeaders) {
85
+ if (!this.userBuckets || !this.userKeyExtractor || !requestHeaders) {
86
+ return this.defaultBuckets;
87
+ }
88
+ const userKey = this.userKeyExtractor(requestHeaders);
89
+ let userSet = this.userBuckets.get(userKey);
90
+ if (!userSet) {
91
+ userSet = { groups: new Map(), lastAccessed: Date.now() };
92
+ this.userBuckets.set(userKey, userSet);
93
+ }
94
+ userSet.lastAccessed = Date.now();
95
+ return userSet.groups;
96
+ }
97
+ getBucket(templatePath, method, requestHeaders, groupNameOverride) {
98
+ const bucketMap = this.resolveBucketMap(requestHeaders);
99
+ const spec = this.lookupGroupSpec(method, templatePath);
100
+ const groupName = groupNameOverride ?? spec?.group;
101
+ if (!groupName)
102
+ return this.fallbackBucket;
103
+ let bucket = bucketMap.get(groupName);
104
+ if (!bucket) {
105
+ bucket = spec
106
+ ? this.createBucketFromSpec(spec)
107
+ : this.createBucketForGroup(groupName);
108
+ bucketMap.set(groupName, bucket);
109
+ }
110
+ return bucket;
111
+ }
112
+ cleanupStaleUsers() {
113
+ if (!this.userBuckets)
114
+ return;
115
+ const now = Date.now();
116
+ if (now - this.lastCleanup < RateLimiter.CLEANUP_INTERVAL_MS)
117
+ return;
118
+ this.lastCleanup = now;
119
+ for (const [userKey, userSet] of this.userBuckets) {
120
+ if (now - userSet.lastAccessed > DEFAULT_WINDOW_MS) {
121
+ this.userBuckets.delete(userKey);
122
+ }
123
+ }
124
+ }
125
+ updateFromResponse(headers, statusCode, templatePath, method, requestHeaders) {
61
126
  if (this.isTestMode)
62
127
  return;
63
- // New rate limit headers (preferred)
64
- const group = headers['x-ratelimit-group'] || null;
128
+ const responseGroup = headers['x-ratelimit-group'] || undefined;
129
+ const bucket = this.getBucket(templatePath, method, requestHeaders, responseGroup);
65
130
  if ('x-ratelimit-remaining' in headers) {
66
- this.rateLimitInfo.remaining = parseInt(headers['x-ratelimit-remaining'], 10);
131
+ bucket.remaining = parseInt(headers['x-ratelimit-remaining'], 10);
67
132
  }
68
133
  if ('x-ratelimit-limit' in headers) {
69
- this.rateLimitInfo.limit = parseInt(headers['x-ratelimit-limit'], 10);
134
+ bucket.limit = parseInt(headers['x-ratelimit-limit'], 10);
70
135
  }
71
136
  if ('x-ratelimit-used' in headers) {
72
- this.rateLimitInfo.used = parseInt(headers['x-ratelimit-used'], 10);
73
- }
74
- this.rateLimitInfo.group = group;
75
- // Legacy error limit headers
76
- if ('x-esi-error-limit-remain' in headers) {
77
- this.rateLimitInfo.errorLimitRemain = parseInt(headers['x-esi-error-limit-remain'], 10);
137
+ bucket.used = parseInt(headers['x-ratelimit-used'], 10);
78
138
  }
79
- if ('x-esi-error-limit-reset' in headers) {
80
- this.rateLimitInfo.errorLimitReset = parseInt(headers['x-esi-error-limit-reset'], 10);
81
- }
82
- // Retry-After (present on 420 and 429 responses)
139
+ bucket.lastUpdated = Date.now();
83
140
  if ('retry-after' in headers) {
84
141
  const retrySeconds = parseInt(headers['retry-after'], 10);
85
- this.rateLimitInfo.retryAfter = retrySeconds;
86
- this.rateLimitInfo.blockedUntil = Date.now() + retrySeconds * 1000;
142
+ bucket.blockedUntil = Date.now() + retrySeconds * 1000;
87
143
  }
88
- // Handle 420 (legacy error limited) and 429 (new rate limited)
89
144
  if (statusCode === 420 || statusCode === 429) {
90
- if (!this.rateLimitInfo.retryAfter) {
91
- // No Retry-After header — default to 60 seconds for safety
92
- this.rateLimitInfo.blockedUntil = Date.now() + 60_000;
145
+ if (bucket.blockedUntil <= Date.now()) {
146
+ bucket.blockedUntil = Date.now() + 60_000;
93
147
  }
94
148
  }
149
+ if ('x-esi-error-limit-remain' in headers) {
150
+ this.errorLimitRemain = parseInt(headers['x-esi-error-limit-remain'], 10);
151
+ }
152
+ if ('x-esi-error-limit-reset' in headers) {
153
+ this.errorLimitReset = parseInt(headers['x-esi-error-limit-reset'], 10);
154
+ }
95
155
  }
96
- /**
97
- * Legacy method — kept for backwards compatibility.
98
- * Prefer updateFromResponse() which also accepts status code.
99
- */
100
156
  updateRateLimitInfo(headers) {
101
157
  this.updateFromResponse(headers, 200);
102
158
  }
103
- /**
104
- * Check if we should wait before making the next request.
105
- * Enforces hard blocks (420/429), proactive deceleration, and minimum delay.
106
- */
107
- async checkRateLimit() {
159
+ async checkRateLimit(templatePath, method, requestHeaders) {
108
160
  if (this.isTestMode)
109
161
  return;
162
+ this.cleanupStaleUsers();
163
+ const bucket = this.getBucket(templatePath, method, requestHeaders);
110
164
  const now = Date.now();
111
- // Hard block: we received a 420/429 and must wait
112
- if (this.rateLimitInfo.blockedUntil > now) {
113
- const waitTime = this.rateLimitInfo.blockedUntil - now;
114
- (0, loggerUtil_1.logWarn)(`[ESI Rate Limit] Blocked for ${Math.ceil(waitTime / 1000)}s (420/429 received)`);
165
+ if (bucket.blockedUntil > now) {
166
+ const waitTime = bucket.blockedUntil - now;
167
+ (0, loggerUtil_1.logWarn)(`[ESI Rate Limit] Group '${bucket.group}' blocked for ${Math.ceil(waitTime / 1000)}s (420/429 received)`);
115
168
  await (0, sleep_1.sleep)(waitTime);
116
- // Clear the block after waiting
117
- this.rateLimitInfo.blockedUntil = 0;
118
- this.rateLimitInfo.retryAfter = null;
169
+ bucket.blockedUntil = 0;
119
170
  return;
120
171
  }
121
- // Legacy error limit: if remaining errors are very low, slow down
122
- if (this.rateLimitInfo.errorLimitRemain <= 10 &&
123
- this.rateLimitInfo.errorLimitRemain > 0) {
124
- const resetMs = this.rateLimitInfo.errorLimitReset * 1000;
125
- const delay = Math.min(resetMs, 5000); // cap at 5s
172
+ if (this.errorLimitRemain <= 10 && this.errorLimitRemain > 0) {
173
+ const resetMs = this.errorLimitReset * 1000;
174
+ const delay = Math.min(resetMs, 5000);
126
175
  if (delay > 0) {
127
- (0, loggerUtil_1.logWarn)(`[ESI Rate Limit] Legacy error limit low (${this.rateLimitInfo.errorLimitRemain}), waiting ${delay}ms`);
176
+ (0, loggerUtil_1.logWarn)(`[ESI Rate Limit] Legacy error limit low (${this.errorLimitRemain}), waiting ${delay}ms`);
128
177
  await (0, sleep_1.sleep)(delay);
129
178
  return;
130
179
  }
131
180
  }
132
- // Legacy error limit: completely exhausted
133
- if (this.rateLimitInfo.errorLimitRemain <= 0 &&
134
- this.rateLimitInfo.errorLimitReset > 0) {
135
- const waitTime = this.rateLimitInfo.errorLimitReset * 1000;
181
+ if (this.errorLimitRemain <= 0 && this.errorLimitReset > 0) {
182
+ const waitTime = this.errorLimitReset * 1000;
136
183
  (0, loggerUtil_1.logWarn)(`[ESI Rate Limit] Legacy error limit exhausted, waiting ${Math.ceil(waitTime / 1000)}s`);
137
184
  await (0, sleep_1.sleep)(waitTime);
138
185
  return;
139
186
  }
140
- // Proactive deceleration: if new-system remaining is known and getting low
141
- if (this.rateLimitInfo.remaining >= 0 && this.rateLimitInfo.limit > 0) {
142
- const ratio = this.rateLimitInfo.remaining / this.rateLimitInfo.limit;
143
- if (this.rateLimitInfo.remaining <= 0) {
144
- // Bucket empty — wait before next request
145
- (0, loggerUtil_1.logWarn)('[ESI Rate Limit] Token bucket empty, waiting 1s');
187
+ if (bucket.remaining >= 0 && bucket.limit > 0) {
188
+ const ratio = bucket.remaining / bucket.limit;
189
+ if (bucket.remaining <= 0) {
190
+ (0, loggerUtil_1.logWarn)(`[ESI Rate Limit] Group '${bucket.group}' token bucket empty, waiting 1s`);
146
191
  await (0, sleep_1.sleep)(1000);
147
192
  return;
148
193
  }
149
194
  if (ratio <= this.decelerationThreshold) {
150
- // Linearly increase delay as remaining approaches 0
151
- // At 20% remaining: ~50ms extra, at 1% remaining: ~1000ms extra
152
195
  const extraDelay = Math.ceil((1 - ratio / this.decelerationThreshold) * 1000);
153
196
  await (0, sleep_1.sleep)(extraDelay);
154
197
  return;
155
198
  }
156
199
  }
157
- // Minimum delay between requests
158
200
  await this.enforceMinDelay();
159
201
  }
160
- /**
161
- * Enforce minimum delay between requests
162
- */
163
202
  async enforceMinDelay() {
164
203
  if (this.isTestMode) {
165
204
  this.lastRequestTime = Date.now();
@@ -172,26 +211,97 @@ class RateLimiter {
172
211
  }
173
212
  this.lastRequestTime = Date.now();
174
213
  }
175
- /** Get current rate limit status */
176
214
  getStatus() {
177
- return { ...this.rateLimitInfo };
215
+ let worstBucket = this.fallbackBucket;
216
+ let worstRatio = Infinity;
217
+ const checkBucket = (bucket) => {
218
+ if (bucket.limit > 0) {
219
+ const ratio = bucket.remaining / bucket.limit;
220
+ if (ratio < worstRatio) {
221
+ worstRatio = ratio;
222
+ worstBucket = bucket;
223
+ }
224
+ }
225
+ };
226
+ for (const bucket of this.defaultBuckets.values()) {
227
+ checkBucket(bucket);
228
+ }
229
+ if (this.userBuckets) {
230
+ for (const userSet of this.userBuckets.values()) {
231
+ for (const bucket of userSet.groups.values()) {
232
+ checkBucket(bucket);
233
+ }
234
+ }
235
+ }
236
+ return {
237
+ remaining: worstBucket.remaining,
238
+ limit: worstBucket.limit,
239
+ used: worstBucket.used,
240
+ group: worstBucket.group === '__fallback__' ? null : worstBucket.group,
241
+ errorLimitRemain: this.errorLimitRemain,
242
+ errorLimitReset: this.errorLimitReset,
243
+ retryAfter: worstBucket.blockedUntil > Date.now()
244
+ ? Math.ceil((worstBucket.blockedUntil - Date.now()) / 1000)
245
+ : null,
246
+ blockedUntil: worstBucket.blockedUntil,
247
+ };
248
+ }
249
+ getGroupStatus(group) {
250
+ const bucket = this.defaultBuckets.get(group);
251
+ if (!bucket)
252
+ return undefined;
253
+ return {
254
+ group: bucket.group,
255
+ remaining: bucket.remaining,
256
+ limit: bucket.limit,
257
+ used: bucket.used,
258
+ windowSizeMs: bucket.windowSizeMs,
259
+ blockedUntil: bucket.blockedUntil,
260
+ };
261
+ }
262
+ getAllGroupStatuses() {
263
+ const result = new Map();
264
+ for (const [name, bucket] of this.defaultBuckets) {
265
+ result.set(name, {
266
+ group: bucket.group,
267
+ remaining: bucket.remaining,
268
+ limit: bucket.limit,
269
+ used: bucket.used,
270
+ windowSizeMs: bucket.windowSizeMs,
271
+ blockedUntil: bucket.blockedUntil,
272
+ });
273
+ }
274
+ return result;
178
275
  }
179
- /** Get token cost for a given status code */
180
276
  static getTokenCost(statusCode) {
181
277
  return getTokenCost(statusCode);
182
278
  }
183
- /** Check if currently blocked (420/429 backoff active) */
184
- isBlocked() {
185
- return this.rateLimitInfo.blockedUntil > Date.now();
279
+ isBlocked(group) {
280
+ const now = Date.now();
281
+ if (group) {
282
+ const bucket = this.defaultBuckets.get(group);
283
+ return bucket ? bucket.blockedUntil > now : false;
284
+ }
285
+ if (this.fallbackBucket.blockedUntil > now)
286
+ return true;
287
+ for (const bucket of this.defaultBuckets.values()) {
288
+ if (bucket.blockedUntil > now)
289
+ return true;
290
+ }
291
+ return false;
186
292
  }
187
- /** Set test mode (disables all delays) */
188
293
  setTestMode(enabled) {
189
294
  this.isTestMode = enabled;
190
295
  }
191
- /** Reset rate limiter state */
192
296
  reset() {
193
- this.rateLimitInfo = this.defaultInfo();
297
+ this.defaultBuckets.clear();
298
+ if (this.userBuckets)
299
+ this.userBuckets.clear();
300
+ this.fallbackBucket = this.createFallbackBucket();
301
+ this.errorLimitRemain = 100;
302
+ this.errorLimitReset = 0;
194
303
  this.lastRequestTime = 0;
304
+ this.lastCleanup = 0;
195
305
  }
196
306
  }
197
307
  exports.RateLimiter = RateLimiter;
@@ -17,7 +17,11 @@ export declare function isNotFound(error: unknown): error is EsiError;
17
17
  export declare function isUnauthorized(error: unknown): error is EsiError;
18
18
  export declare function isForbidden(error: unknown): error is EsiError;
19
19
  export declare function isServerError(error: unknown): error is EsiError;
20
- export declare function isTimeout(error: unknown): error is EsiError;
20
+ export declare class TimeoutError extends EsiError {
21
+ readonly timeoutMs: number;
22
+ constructor(timeoutMs: number, url?: string, requestId?: string);
23
+ }
24
+ export declare function isTimeout(error: unknown): error is TimeoutError;
21
25
  export declare function isRetryable(error: unknown): error is EsiError;
22
26
  export declare const buildError: (message: string, type?: string, url?: string) => Error;
23
27
  //# sourceMappingURL=error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/core/util/error.ts"],"names":[],"mappings":"AAiBA,qBAAa,QAAS,SAAQ,KAAK;aAIf,UAAU,EAAE,MAAM;aAGlB,SAAS,CAAC,EAAE,MAAM;IANpC,SAAgB,GAAG,CAAC,EAAE,MAAM,CAAC;gBAGX,UAAU,EAAE,MAAM,EAClC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,EACI,SAAS,CAAC,EAAE,MAAM,YAAA;IAOpC,aAAa,IAAI,OAAO;IAIxB,UAAU,IAAI,OAAO;IAIrB,cAAc,IAAI,OAAO;IAIzB,WAAW,IAAI,OAAO;IAItB,aAAa,IAAI,OAAO;IAIxB,SAAS,IAAI,OAAO;IAIpB,IAAI,SAAS,IAAI,OAAO,CASvB;CACF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE/D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAEhE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE7D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE/D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE7D;AAED,eAAO,MAAM,UAAU,GACrB,SAAS,MAAM,EACf,OAAM,MAAgB,EACtB,MAAM,MAAM,KACX,KAMF,CAAC"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/core/util/error.ts"],"names":[],"mappings":"AAiBA,qBAAa,QAAS,SAAQ,KAAK;aAIf,UAAU,EAAE,MAAM;aAGlB,SAAS,CAAC,EAAE,MAAM;IANpC,SAAgB,GAAG,CAAC,EAAE,MAAM,CAAC;gBAGX,UAAU,EAAE,MAAM,EAClC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,EACI,SAAS,CAAC,EAAE,MAAM,YAAA;IAOpC,aAAa,IAAI,OAAO;IAIxB,UAAU,IAAI,OAAO;IAIrB,cAAc,IAAI,OAAO;IAIzB,WAAW,IAAI,OAAO;IAItB,aAAa,IAAI,OAAO;IAIxB,SAAS,IAAI,OAAO;IAIpB,IAAI,SAAS,IAAI,OAAO,CASvB;CACF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE/D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAEhE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE7D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE/D;AAED,qBAAa,YAAa,SAAQ,QAAQ;aAEtB,SAAS,EAAE,MAAM;gBAAjB,SAAS,EAAE,MAAM,EACjC,GAAG,CAAC,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM;CAKrB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAE/D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE7D;AAED,eAAO,MAAM,UAAU,GACrB,SAAS,MAAM,EACf,OAAM,MAAgB,EACtB,MAAM,MAAM,KACX,KAMF,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildError = exports.EsiError = void 0;
3
+ exports.buildError = exports.TimeoutError = exports.EsiError = void 0;
4
4
  exports.isEsiError = isEsiError;
5
5
  exports.isRateLimited = isRateLimited;
6
6
  exports.isNotFound = isNotFound;
@@ -84,8 +84,17 @@ function isForbidden(error) {
84
84
  function isServerError(error) {
85
85
  return error instanceof EsiError && error.isServerError();
86
86
  }
87
+ class TimeoutError extends EsiError {
88
+ timeoutMs;
89
+ constructor(timeoutMs, url, requestId) {
90
+ super(0, `Request timed out after ${timeoutMs}ms`, url, requestId);
91
+ this.timeoutMs = timeoutMs;
92
+ this.name = 'TimeoutError';
93
+ }
94
+ }
95
+ exports.TimeoutError = TimeoutError;
87
96
  function isTimeout(error) {
88
- return error instanceof EsiError && error.isTimeout();
97
+ return error instanceof TimeoutError;
89
98
  }
90
99
  function isRetryable(error) {
91
100
  return error instanceof EsiError && error.retryable;
@@ -0,0 +1,8 @@
1
+ export interface RetryConfig {
2
+ maxRetries?: number;
3
+ baseDelayMs?: number;
4
+ maxDelayMs?: number;
5
+ retryMutations?: boolean;
6
+ }
7
+ export declare function retryDelay(attempt: number, baseMs: number, maxMs: number): number;
8
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../../src/core/util/retry.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,CAKR"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.retryDelay = retryDelay;
4
+ function retryDelay(attempt, baseMs, maxMs) {
5
+ const exponential = baseMs * Math.pow(2, attempt);
6
+ // eslint-disable-next-line sonarjs/pseudo-random
7
+ const jitter = exponential * (0.75 + Math.random() * 0.5);
8
+ return Math.min(jitter, maxMs);
9
+ }
@@ -0,0 +1,2 @@
1
+ export declare function camelToSnake(s: string): string;
2
+ //# sourceMappingURL=stringUtil.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringUtil.d.ts","sourceRoot":"","sources":["../../../src/core/util/stringUtil.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.camelToSnake = camelToSnake;
4
+ function camelToSnake(s) {
5
+ return s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
6
+ }
package/dist/index.d.ts CHANGED
@@ -42,17 +42,20 @@ export { MercenaryClient } from './clients/MercenaryClient';
42
42
  export { AccessListsClient } from './clients/AccessListsClient';
43
43
  export { CursorOptions, CursorResult, CreateClientOptions, WithMetadata, fetchAllCursorPages, } from './core/endpoints/createClient';
44
44
  export { CursorTokens } from './core/pagination/CursorPaginationHandler';
45
- export { EsiError, isEsiError, isRateLimited, isNotFound, isUnauthorized, isForbidden, isServerError, isTimeout, isRetryable, } from './core/util/error';
45
+ export { EsiError, TimeoutError, isEsiError, isRateLimited, isNotFound, isUnauthorized, isForbidden, isServerError, isTimeout, isRetryable, } from './core/util/error';
46
46
  export { DeprecationInfo } from './core/endpoints/EndpointDefinition';
47
47
  export { RequestInterceptor, ResponseInterceptor, RequestContext, ResponseContext, } from './core/middleware/Middleware';
48
48
  export { CircuitBreaker, CircuitBreakerConfig, CircuitState, CircuitOpenError, } from './core/circuitBreaker/CircuitBreaker';
49
49
  export { RateLimiter, RateLimitInfo, RateLimiterConfig, } from './core/rateLimiter/RateLimiter';
50
50
  export { ETagCacheManager, ETagCacheConfig, } from './core/cache/ETagCacheManager';
51
+ export { RetryConfig } from './core/util/retry';
51
52
  export { RequestDeduplicator } from './core/RequestDeduplicator';
53
+ export { batchFetch, batchPost, BatchOptions, BatchResult, } from './core/BatchRequestHandler';
52
54
  export { EsiDiagnostics, CacheStats, CircuitBreakerStats, } from './core/EsiDiagnostics';
53
55
  export { fetchPages, PageResult, } from './core/pagination/AsyncPaginationIterator';
54
56
  export { ICache } from './core/cache/ICache';
55
- export { IRateLimiter } from './core/rateLimiter/IRateLimiter';
57
+ export { IRateLimiter, RateLimitGroupStatus, } from './core/rateLimiter/IRateLimiter';
58
+ export { RateLimitGroupSpec } from './core/endpoints/esi-rate-limit-groups.generated';
56
59
  export { ILogger } from './core/logger/ILogger';
57
60
  export { setLogger } from './core/logger/loggerUtil';
58
61
  export * from './types/api-responses';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.isForbidden = exports.isUnauthorized = exports.isNotFound = exports.isRateLimited = exports.isEsiError = exports.EsiError = exports.fetchAllCursorPages = exports.AccessListsClient = exports.MercenaryClient = exports.SkyhooksClient = exports.FreelanceJobsClient = exports.MetaClient = exports.WarsClient = exports.WalletClient = exports.UniverseClient = exports.UiClient = exports.StatusClient = exports.SovereigntyClient = exports.CharacterSkillsClient = exports.SearchClient = exports.RouteClient = exports.PiClient = exports.MarketClient = exports.MailClient = exports.LoyaltyClient = exports.LocationClient = exports.KillmailsClient = exports.InsuranceClient = exports.IndustryClient = exports.IncursionsClient = exports.FleetClient = exports.FittingsClient = exports.FactionClient = exports.DogmaClient = exports.CorporationsClient = exports.ContractsClient = exports.ContactsClient = exports.ClonesClient = exports.CharacterClient = exports.CalendarClient = exports.AssetsClient = exports.AllianceClient = exports.BaseEsiClient = exports.ApiClientBuilder = exports.ApiClient = exports.EsiApiFactory = exports.EsiClientBuilder = exports.CustomEsiClient = exports.getDefaultClient = exports.EsiClient = void 0;
18
- exports.setLogger = exports.fetchPages = exports.EsiDiagnostics = exports.RequestDeduplicator = exports.ETagCacheManager = exports.RateLimiter = exports.CircuitOpenError = exports.CircuitBreaker = exports.isRetryable = exports.isTimeout = exports.isServerError = void 0;
17
+ exports.isUnauthorized = exports.isNotFound = exports.isRateLimited = exports.isEsiError = exports.TimeoutError = exports.EsiError = exports.fetchAllCursorPages = exports.AccessListsClient = exports.MercenaryClient = exports.SkyhooksClient = exports.FreelanceJobsClient = exports.MetaClient = exports.WarsClient = exports.WalletClient = exports.UniverseClient = exports.UiClient = exports.StatusClient = exports.SovereigntyClient = exports.CharacterSkillsClient = exports.SearchClient = exports.RouteClient = exports.PiClient = exports.MarketClient = exports.MailClient = exports.LoyaltyClient = exports.LocationClient = exports.KillmailsClient = exports.InsuranceClient = exports.IndustryClient = exports.IncursionsClient = exports.FleetClient = exports.FittingsClient = exports.FactionClient = exports.DogmaClient = exports.CorporationsClient = exports.ContractsClient = exports.ContactsClient = exports.ClonesClient = exports.CharacterClient = exports.CalendarClient = exports.AssetsClient = exports.AllianceClient = exports.BaseEsiClient = exports.ApiClientBuilder = exports.ApiClient = exports.EsiApiFactory = exports.EsiClientBuilder = exports.CustomEsiClient = exports.getDefaultClient = exports.EsiClient = void 0;
18
+ exports.setLogger = exports.fetchPages = exports.EsiDiagnostics = exports.batchPost = exports.batchFetch = exports.RequestDeduplicator = exports.ETagCacheManager = exports.RateLimiter = exports.CircuitOpenError = exports.CircuitBreaker = exports.isRetryable = exports.isTimeout = exports.isServerError = exports.isForbidden = void 0;
19
19
  // Main client
20
20
  var EsiClient_1 = require("./EsiClient");
21
21
  Object.defineProperty(exports, "EsiClient", { enumerable: true, get: function () { return EsiClient_1.EsiClient; } });
@@ -111,6 +111,7 @@ Object.defineProperty(exports, "fetchAllCursorPages", { enumerable: true, get: f
111
111
  // Error class & type guards
112
112
  var error_1 = require("./core/util/error");
113
113
  Object.defineProperty(exports, "EsiError", { enumerable: true, get: function () { return error_1.EsiError; } });
114
+ Object.defineProperty(exports, "TimeoutError", { enumerable: true, get: function () { return error_1.TimeoutError; } });
114
115
  Object.defineProperty(exports, "isEsiError", { enumerable: true, get: function () { return error_1.isEsiError; } });
115
116
  Object.defineProperty(exports, "isRateLimited", { enumerable: true, get: function () { return error_1.isRateLimited; } });
116
117
  Object.defineProperty(exports, "isNotFound", { enumerable: true, get: function () { return error_1.isNotFound; } });
@@ -131,6 +132,10 @@ Object.defineProperty(exports, "ETagCacheManager", { enumerable: true, get: func
131
132
  // Request deduplication
132
133
  var RequestDeduplicator_1 = require("./core/RequestDeduplicator");
133
134
  Object.defineProperty(exports, "RequestDeduplicator", { enumerable: true, get: function () { return RequestDeduplicator_1.RequestDeduplicator; } });
135
+ // Batch operations
136
+ var BatchRequestHandler_1 = require("./core/BatchRequestHandler");
137
+ Object.defineProperty(exports, "batchFetch", { enumerable: true, get: function () { return BatchRequestHandler_1.batchFetch; } });
138
+ Object.defineProperty(exports, "batchPost", { enumerable: true, get: function () { return BatchRequestHandler_1.batchPost; } });
134
139
  // Diagnostics
135
140
  var EsiDiagnostics_1 = require("./core/EsiDiagnostics");
136
141
  Object.defineProperty(exports, "EsiDiagnostics", { enumerable: true, get: function () { return EsiDiagnostics_1.EsiDiagnostics; } });
@@ -30,4 +30,5 @@ export * from './freelance-jobs';
30
30
  export * from './skyhooks';
31
31
  export * from './mercenary';
32
32
  export * from './access-lists';
33
+ export * as EsiSpec from './generated/esi-spec.generated';
33
34
  //# sourceMappingURL=api-responses.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-responses.d.ts","sourceRoot":"","sources":["../../src/types/api-responses.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,MAAM,CAAC;AACrB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"api-responses.d.ts","sourceRoot":"","sources":["../../src/types/api-responses.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,MAAM,CAAC;AACrB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,KAAK,OAAO,MAAM,gCAAgC,CAAC"}
@@ -10,10 +10,33 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
13
18
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
20
  };
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
16
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.EsiSpec = void 0;
17
40
  __exportStar(require("./common"), exports);
18
41
  __exportStar(require("./alliance"), exports);
19
42
  __exportStar(require("./character"), exports);
@@ -46,3 +69,4 @@ __exportStar(require("./freelance-jobs"), exports);
46
69
  __exportStar(require("./skyhooks"), exports);
47
70
  __exportStar(require("./mercenary"), exports);
48
71
  __exportStar(require("./access-lists"), exports);
72
+ exports.EsiSpec = __importStar(require("./generated/esi-spec.generated"));
@@ -1,7 +1,14 @@
1
+ export interface RateLimitMeta {
2
+ remaining: number;
3
+ limit: number;
4
+ used: number;
5
+ group: string | null;
6
+ }
1
7
  export interface EsiResponseMeta {
2
8
  headers: Record<string, string>;
3
9
  fromCache: boolean;
4
10
  stale: boolean;
11
+ cacheHitType?: 'spec-ttl' | 'etag-304' | 'stale-on-error';
5
12
  warning?: {
6
13
  code: number;
7
14
  message: string;
@@ -9,6 +16,8 @@ export interface EsiResponseMeta {
9
16
  requestId?: string;
10
17
  date?: string;
11
18
  contentLanguage?: string;
19
+ rateLimit?: RateLimitMeta;
20
+ responseTimeMs?: number;
12
21
  }
13
22
  export interface EsiResponse<T> {
14
23
  data: T;
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/types/common.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,eAAe,CAAC;CACvB"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/types/common.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IAC1D,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,eAAe,CAAC;CACvB"}