@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.
- package/CHANGELOG.md +21 -0
- package/README.md +174 -7
- package/dist/EsiClient.d.ts +5 -0
- package/dist/EsiClient.d.ts.map +1 -1
- package/dist/EsiClient.js +13 -0
- package/dist/core/ApiClient.d.ts +4 -0
- package/dist/core/ApiClient.d.ts.map +1 -1
- package/dist/core/ApiClient.js +7 -0
- package/dist/core/ApiRequestHandler.d.ts +3 -1
- package/dist/core/ApiRequestHandler.d.ts.map +1 -1
- package/dist/core/ApiRequestHandler.js +106 -40
- package/dist/core/BatchRequestHandler.d.ts +12 -0
- package/dist/core/BatchRequestHandler.d.ts.map +1 -0
- package/dist/core/BatchRequestHandler.js +66 -0
- package/dist/core/constants.d.ts +2 -2
- package/dist/core/constants.js +1 -1
- package/dist/core/endpoints/createClient.d.ts.map +1 -1
- package/dist/core/endpoints/createClient.js +14 -2
- package/dist/core/endpoints/esi-cache-ttls.generated.d.ts +2 -0
- package/dist/core/endpoints/esi-cache-ttls.generated.d.ts.map +1 -0
- package/dist/core/endpoints/esi-cache-ttls.generated.js +126 -0
- package/dist/core/endpoints/esi-rate-limit-groups.generated.d.ts +7 -0
- package/dist/core/endpoints/esi-rate-limit-groups.generated.d.ts.map +1 -0
- package/dist/core/endpoints/esi-rate-limit-groups.generated.js +153 -0
- package/dist/core/pagination/PaginationHandler.d.ts +1 -1
- package/dist/core/pagination/PaginationHandler.d.ts.map +1 -1
- package/dist/core/pagination/PaginationHandler.js +2 -2
- package/dist/core/rateLimiter/IRateLimiter.d.ts +13 -3
- package/dist/core/rateLimiter/IRateLimiter.d.ts.map +1 -1
- package/dist/core/rateLimiter/RateLimiter.d.ts +24 -51
- package/dist/core/rateLimiter/RateLimiter.d.ts.map +1 -1
- package/dist/core/rateLimiter/RateLimiter.js +208 -98
- package/dist/core/util/error.d.ts +5 -1
- package/dist/core/util/error.d.ts.map +1 -1
- package/dist/core/util/error.js +11 -2
- package/dist/core/util/retry.d.ts +8 -0
- package/dist/core/util/retry.d.ts.map +1 -0
- package/dist/core/util/retry.js +9 -0
- package/dist/core/util/stringUtil.d.ts +2 -0
- package/dist/core/util/stringUtil.d.ts.map +1 -0
- package/dist/core/util/stringUtil.js +6 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/types/api-responses.d.ts +1 -0
- package/dist/types/api-responses.d.ts.map +1 -1
- package/dist/types/api-responses.js +24 -0
- package/dist/types/common.d.ts +9 -0
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/generated/esi-spec.generated.d.ts +1763 -0
- package/dist/types/generated/esi-spec.generated.d.ts.map +1 -0
- package/dist/types/generated/esi-spec.generated.js +6 -0
- 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.
|
|
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
|
-
|
|
64
|
+
createBucketForGroup(groupName) {
|
|
45
65
|
return {
|
|
46
|
-
|
|
66
|
+
group: groupName,
|
|
67
|
+
remaining: -1,
|
|
47
68
|
limit: 0,
|
|
48
69
|
used: 0,
|
|
49
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
64
|
-
const
|
|
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
|
-
|
|
131
|
+
bucket.remaining = parseInt(headers['x-ratelimit-remaining'], 10);
|
|
67
132
|
}
|
|
68
133
|
if ('x-ratelimit-limit' in headers) {
|
|
69
|
-
|
|
134
|
+
bucket.limit = parseInt(headers['x-ratelimit-limit'], 10);
|
|
70
135
|
}
|
|
71
136
|
if ('x-ratelimit-used' in headers) {
|
|
72
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
91
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
117
|
-
this.rateLimitInfo.blockedUntil = 0;
|
|
118
|
-
this.rateLimitInfo.retryAfter = null;
|
|
169
|
+
bucket.blockedUntil = 0;
|
|
119
170
|
return;
|
|
120
171
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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.
|
|
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
|
-
|
|
133
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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.
|
|
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
|
|
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,
|
|
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"}
|
package/dist/core/util/error.js
CHANGED
|
@@ -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
|
|
97
|
+
return error instanceof TimeoutError;
|
|
89
98
|
}
|
|
90
99
|
function isRetryable(error) {
|
|
91
100
|
return error instanceof EsiError && error.retryable;
|
|
@@ -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 @@
|
|
|
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"}
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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.
|
|
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; } });
|
|
@@ -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"));
|
package/dist/types/common.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|