zipfetch 1.0.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/README.md +328 -0
- package/dist/cache.d.ts +14 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +41 -0
- package/dist/cache.js.map +1 -0
- package/dist/client.d.ts +50 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +299 -0
- package/dist/client.js.map +1 -0
- package/dist/error.d.ts +15 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +32 -0
- package/dist/error.js.map +1 -0
- package/dist/index.d.ts +129 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +393 -0
- package/dist/index.js.map +1 -0
- package/dist/rate-limiter.d.ts +14 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +34 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* zipfetch - Ultra-fast, lightweight HTTP client built on native fetch
|
|
3
|
+
* Features: retries, interceptors, caching, rate limiting, timeout
|
|
4
|
+
*/
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Error Class
|
|
7
|
+
// ============================================================================
|
|
8
|
+
export class ZipError extends Error {
|
|
9
|
+
config;
|
|
10
|
+
response;
|
|
11
|
+
status;
|
|
12
|
+
code;
|
|
13
|
+
constructor(message, config, response) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'ZipError';
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.response = response;
|
|
18
|
+
this.status = response?.status;
|
|
19
|
+
}
|
|
20
|
+
static timeout(config) {
|
|
21
|
+
const error = new ZipError('Request timeout', config);
|
|
22
|
+
error.code = 'TIMEOUT';
|
|
23
|
+
return error;
|
|
24
|
+
}
|
|
25
|
+
static network(config, originalError) {
|
|
26
|
+
const error = new ZipError(`Network error: ${originalError.message}`, config);
|
|
27
|
+
error.code = 'NETWORK';
|
|
28
|
+
return error;
|
|
29
|
+
}
|
|
30
|
+
static abort(config) {
|
|
31
|
+
const error = new ZipError('Request aborted', config);
|
|
32
|
+
error.code = 'ABORT';
|
|
33
|
+
return error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
class ResponseCache {
|
|
37
|
+
cache = new Map();
|
|
38
|
+
generateKey(url, config) {
|
|
39
|
+
const params = config.params ? JSON.stringify(config.params) : '';
|
|
40
|
+
const headers = config.headers ? JSON.stringify(config.headers) : '';
|
|
41
|
+
return `${config.method || 'GET'}:${url}:${params}:${headers}`;
|
|
42
|
+
}
|
|
43
|
+
get(url, config) {
|
|
44
|
+
const key = this.generateKey(url, config);
|
|
45
|
+
const entry = this.cache.get(key);
|
|
46
|
+
if (!entry)
|
|
47
|
+
return null;
|
|
48
|
+
if (Date.now() - entry.timestamp > entry.ttl) {
|
|
49
|
+
this.cache.delete(key);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return entry.data;
|
|
53
|
+
}
|
|
54
|
+
set(url, config, response, ttl) {
|
|
55
|
+
const key = this.generateKey(url, config);
|
|
56
|
+
this.cache.set(key, {
|
|
57
|
+
data: response,
|
|
58
|
+
timestamp: Date.now(),
|
|
59
|
+
ttl,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
clear() {
|
|
63
|
+
this.cache.clear();
|
|
64
|
+
}
|
|
65
|
+
delete(url, config) {
|
|
66
|
+
const key = this.generateKey(url, config);
|
|
67
|
+
return this.cache.delete(key);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Rate Limiter Implementation
|
|
72
|
+
// ============================================================================
|
|
73
|
+
class RateLimiter {
|
|
74
|
+
timestamps = [];
|
|
75
|
+
config;
|
|
76
|
+
constructor(config) {
|
|
77
|
+
this.config = config;
|
|
78
|
+
}
|
|
79
|
+
async acquire() {
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
// Remove timestamps outside the interval window
|
|
82
|
+
this.timestamps = this.timestamps.filter((t) => now - t < this.config.interval);
|
|
83
|
+
if (this.timestamps.length >= this.config.requests) {
|
|
84
|
+
// Wait until the oldest request expires
|
|
85
|
+
const oldestTimestamp = this.timestamps[0];
|
|
86
|
+
const waitTime = this.config.interval - (now - oldestTimestamp);
|
|
87
|
+
await this.sleep(waitTime);
|
|
88
|
+
return this.acquire();
|
|
89
|
+
}
|
|
90
|
+
this.timestamps.push(now);
|
|
91
|
+
}
|
|
92
|
+
sleep(ms) {
|
|
93
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Main ZipFetch Class
|
|
98
|
+
// ============================================================================
|
|
99
|
+
class ZipFetch {
|
|
100
|
+
config;
|
|
101
|
+
cache;
|
|
102
|
+
rateLimiter;
|
|
103
|
+
requestInterceptors = [];
|
|
104
|
+
responseInterceptors = [];
|
|
105
|
+
errorInterceptors = [];
|
|
106
|
+
constructor(config = {}) {
|
|
107
|
+
this.config = {
|
|
108
|
+
timeout: 30000,
|
|
109
|
+
retry: { attempts: 0 },
|
|
110
|
+
cache: { enabled: false, ttl: 60000, methods: ['GET'] },
|
|
111
|
+
...config,
|
|
112
|
+
};
|
|
113
|
+
this.cache = new ResponseCache();
|
|
114
|
+
if (config.rateLimit) {
|
|
115
|
+
this.rateLimiter = new RateLimiter(config.rateLimit);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Interceptors
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
interceptors = {
|
|
122
|
+
request: {
|
|
123
|
+
use: (interceptor) => {
|
|
124
|
+
this.requestInterceptors.push(interceptor);
|
|
125
|
+
return this.requestInterceptors.length - 1;
|
|
126
|
+
},
|
|
127
|
+
eject: (index) => {
|
|
128
|
+
this.requestInterceptors.splice(index, 1);
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
response: {
|
|
132
|
+
use: (interceptor) => {
|
|
133
|
+
this.responseInterceptors.push(interceptor);
|
|
134
|
+
return this.responseInterceptors.length - 1;
|
|
135
|
+
},
|
|
136
|
+
eject: (index) => {
|
|
137
|
+
this.responseInterceptors.splice(index, 1);
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
error: {
|
|
141
|
+
use: (interceptor) => {
|
|
142
|
+
this.errorInterceptors.push(interceptor);
|
|
143
|
+
return this.errorInterceptors.length - 1;
|
|
144
|
+
},
|
|
145
|
+
eject: (index) => {
|
|
146
|
+
this.errorInterceptors.splice(index, 1);
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Core Request Method
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
async request(config) {
|
|
154
|
+
// Apply request interceptors
|
|
155
|
+
let finalConfig = { ...config };
|
|
156
|
+
for (const interceptor of this.requestInterceptors) {
|
|
157
|
+
finalConfig = await interceptor(finalConfig);
|
|
158
|
+
}
|
|
159
|
+
// Build URL
|
|
160
|
+
const baseURL = finalConfig.baseURL || this.config.baseURL || '';
|
|
161
|
+
let url = finalConfig.url || '';
|
|
162
|
+
if (baseURL && !url.startsWith('http')) {
|
|
163
|
+
url = `${baseURL.replace(/\/$/, '')}/${url.replace(/^\//, '')}`;
|
|
164
|
+
}
|
|
165
|
+
// Add query params
|
|
166
|
+
if (finalConfig.params) {
|
|
167
|
+
const searchParams = new URLSearchParams();
|
|
168
|
+
for (const [key, value] of Object.entries(finalConfig.params)) {
|
|
169
|
+
if (value !== undefined) {
|
|
170
|
+
searchParams.append(key, String(value));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const queryString = searchParams.toString();
|
|
174
|
+
if (queryString) {
|
|
175
|
+
url += (url.includes('?') ? '&' : '?') + queryString;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Check cache
|
|
179
|
+
const method = (finalConfig.method?.toUpperCase() || 'GET');
|
|
180
|
+
const cacheEnabled = finalConfig.useCache !== false &&
|
|
181
|
+
this.config.cache?.enabled &&
|
|
182
|
+
this.config.cache.methods?.includes(method);
|
|
183
|
+
if (cacheEnabled) {
|
|
184
|
+
const cached = this.cache.get(url, finalConfig);
|
|
185
|
+
if (cached)
|
|
186
|
+
return cached;
|
|
187
|
+
}
|
|
188
|
+
// Rate limiting
|
|
189
|
+
if (this.rateLimiter) {
|
|
190
|
+
await this.rateLimiter.acquire();
|
|
191
|
+
}
|
|
192
|
+
// Execute request with retry
|
|
193
|
+
const retryConfig = finalConfig.retry || this.config.retry || { attempts: 0 };
|
|
194
|
+
const maxAttempts = (retryConfig.attempts || 0) + 1;
|
|
195
|
+
let lastError = null;
|
|
196
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
197
|
+
try {
|
|
198
|
+
const response = await this.executeRequest(url, finalConfig);
|
|
199
|
+
// Check if should retry based on response
|
|
200
|
+
if (attempt < maxAttempts && this.shouldRetry(response, retryConfig)) {
|
|
201
|
+
await this.delay(attempt, retryConfig);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
// Cache successful response
|
|
205
|
+
if (cacheEnabled && response.status >= 200 && response.status < 300) {
|
|
206
|
+
this.cache.set(url, finalConfig, response, this.config.cache?.ttl || 60000);
|
|
207
|
+
}
|
|
208
|
+
// Apply response interceptors
|
|
209
|
+
let finalResponse = response;
|
|
210
|
+
for (const interceptor of this.responseInterceptors) {
|
|
211
|
+
finalResponse = await interceptor(finalResponse);
|
|
212
|
+
}
|
|
213
|
+
return finalResponse;
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
lastError = error instanceof ZipError
|
|
217
|
+
? error
|
|
218
|
+
: ZipError.network(finalConfig, error);
|
|
219
|
+
if (attempt < maxAttempts) {
|
|
220
|
+
await this.delay(attempt, retryConfig);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Apply error interceptors
|
|
226
|
+
for (const interceptor of this.errorInterceptors) {
|
|
227
|
+
lastError = await interceptor(lastError);
|
|
228
|
+
}
|
|
229
|
+
throw lastError;
|
|
230
|
+
}
|
|
231
|
+
async executeRequest(url, config) {
|
|
232
|
+
const timeout = config.timeout || this.config.timeout || 30000;
|
|
233
|
+
const controller = new AbortController();
|
|
234
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
235
|
+
try {
|
|
236
|
+
// Merge headers
|
|
237
|
+
const headers = new Headers({
|
|
238
|
+
'Content-Type': 'application/json',
|
|
239
|
+
...this.config.headers,
|
|
240
|
+
...config.headers,
|
|
241
|
+
});
|
|
242
|
+
// Prepare body
|
|
243
|
+
let body;
|
|
244
|
+
if (config.data !== undefined) {
|
|
245
|
+
if (config.data instanceof FormData ||
|
|
246
|
+
config.data instanceof URLSearchParams ||
|
|
247
|
+
config.data instanceof Blob ||
|
|
248
|
+
config.data instanceof ArrayBuffer ||
|
|
249
|
+
typeof config.data === 'string') {
|
|
250
|
+
body = config.data;
|
|
251
|
+
// Remove Content-Type for FormData to let browser set it
|
|
252
|
+
if (config.data instanceof FormData) {
|
|
253
|
+
headers.delete('Content-Type');
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
body = JSON.stringify(config.data);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const request = new Request(url, {
|
|
261
|
+
method: config.method || 'GET',
|
|
262
|
+
headers,
|
|
263
|
+
body,
|
|
264
|
+
signal: controller.signal,
|
|
265
|
+
credentials: config.credentials,
|
|
266
|
+
mode: config.mode,
|
|
267
|
+
redirect: config.redirect,
|
|
268
|
+
referrer: config.referrer,
|
|
269
|
+
referrerPolicy: config.referrerPolicy,
|
|
270
|
+
integrity: config.integrity,
|
|
271
|
+
});
|
|
272
|
+
const response = await fetch(request);
|
|
273
|
+
clearTimeout(timeoutId);
|
|
274
|
+
// Parse response
|
|
275
|
+
let data;
|
|
276
|
+
const contentType = response.headers.get('content-type');
|
|
277
|
+
if (contentType?.includes('application/json')) {
|
|
278
|
+
data = await response.json();
|
|
279
|
+
}
|
|
280
|
+
else if (contentType?.includes('text/')) {
|
|
281
|
+
data = await response.text();
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
data = await response.blob();
|
|
285
|
+
}
|
|
286
|
+
const zipResponse = {
|
|
287
|
+
data,
|
|
288
|
+
status: response.status,
|
|
289
|
+
statusText: response.statusText,
|
|
290
|
+
headers: response.headers,
|
|
291
|
+
config,
|
|
292
|
+
request,
|
|
293
|
+
};
|
|
294
|
+
// Throw on error status codes
|
|
295
|
+
if (!response.ok) {
|
|
296
|
+
throw new ZipError(`Request failed with status ${response.status}`, config, zipResponse);
|
|
297
|
+
}
|
|
298
|
+
return zipResponse;
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
clearTimeout(timeoutId);
|
|
302
|
+
if (error instanceof ZipError) {
|
|
303
|
+
throw error;
|
|
304
|
+
}
|
|
305
|
+
if (error.name === 'AbortError') {
|
|
306
|
+
throw ZipError.timeout(config);
|
|
307
|
+
}
|
|
308
|
+
throw ZipError.network(config, error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
shouldRetry(response, config) {
|
|
312
|
+
if (!config.retryOn) {
|
|
313
|
+
return response.status >= 500;
|
|
314
|
+
}
|
|
315
|
+
if (Array.isArray(config.retryOn)) {
|
|
316
|
+
return config.retryOn.includes(response.status);
|
|
317
|
+
}
|
|
318
|
+
// response interceptor was already applied, so we need the original Response
|
|
319
|
+
// For now, just use status check
|
|
320
|
+
return response.status >= 500;
|
|
321
|
+
}
|
|
322
|
+
async delay(attempt, config) {
|
|
323
|
+
const baseDelay = config.delay || 1000;
|
|
324
|
+
let delay;
|
|
325
|
+
if (config.backoff === 'exponential') {
|
|
326
|
+
delay = baseDelay * Math.pow(2, attempt - 1);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
delay = baseDelay * attempt;
|
|
330
|
+
}
|
|
331
|
+
// Add jitter (±10%)
|
|
332
|
+
const jitter = delay * 0.1 * (Math.random() * 2 - 1);
|
|
333
|
+
delay += jitter;
|
|
334
|
+
return new Promise((resolve) => setTimeout(resolve, delay));
|
|
335
|
+
}
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
// HTTP Method Shortcuts
|
|
338
|
+
// ---------------------------------------------------------------------------
|
|
339
|
+
get(url, config) {
|
|
340
|
+
return this.request({ ...config, url, method: 'GET' });
|
|
341
|
+
}
|
|
342
|
+
post(url, data, config) {
|
|
343
|
+
return this.request({ ...config, url, method: 'POST', data });
|
|
344
|
+
}
|
|
345
|
+
put(url, data, config) {
|
|
346
|
+
return this.request({ ...config, url, method: 'PUT', data });
|
|
347
|
+
}
|
|
348
|
+
patch(url, data, config) {
|
|
349
|
+
return this.request({ ...config, url, method: 'PATCH', data });
|
|
350
|
+
}
|
|
351
|
+
delete(url, config) {
|
|
352
|
+
return this.request({ ...config, url, method: 'DELETE' });
|
|
353
|
+
}
|
|
354
|
+
head(url, config) {
|
|
355
|
+
return this.request({ ...config, url, method: 'HEAD' });
|
|
356
|
+
}
|
|
357
|
+
options(url, config) {
|
|
358
|
+
return this.request({ ...config, url, method: 'OPTIONS' });
|
|
359
|
+
}
|
|
360
|
+
// ---------------------------------------------------------------------------
|
|
361
|
+
// Utility Methods
|
|
362
|
+
// ---------------------------------------------------------------------------
|
|
363
|
+
clearCache() {
|
|
364
|
+
this.cache.clear();
|
|
365
|
+
}
|
|
366
|
+
create(config) {
|
|
367
|
+
return new ZipFetch({ ...this.config, ...config });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// ============================================================================
|
|
371
|
+
// Default Instance & Exports
|
|
372
|
+
// ============================================================================
|
|
373
|
+
const zipfetch = new ZipFetch();
|
|
374
|
+
// Export default instance methods
|
|
375
|
+
export const request = zipfetch.request.bind(zipfetch);
|
|
376
|
+
export const get = zipfetch.get.bind(zipfetch);
|
|
377
|
+
export const post = zipfetch.post.bind(zipfetch);
|
|
378
|
+
export const put = zipfetch.put.bind(zipfetch);
|
|
379
|
+
export const patch = zipfetch.patch.bind(zipfetch);
|
|
380
|
+
export const del = zipfetch.delete.bind(zipfetch);
|
|
381
|
+
export const head = zipfetch.head.bind(zipfetch);
|
|
382
|
+
export const options = zipfetch.options.bind(zipfetch);
|
|
383
|
+
export const interceptors = zipfetch.interceptors;
|
|
384
|
+
export const clearCache = zipfetch.clearCache.bind(zipfetch);
|
|
385
|
+
// Factory function
|
|
386
|
+
export function create(config) {
|
|
387
|
+
return new ZipFetch(config);
|
|
388
|
+
}
|
|
389
|
+
// Export class
|
|
390
|
+
export { ZipFetch };
|
|
391
|
+
// Default export
|
|
392
|
+
export default zipfetch;
|
|
393
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate limiting implementation
|
|
3
|
+
*/
|
|
4
|
+
import type { RateLimitConfig } from './types.js';
|
|
5
|
+
export declare class RateLimiter {
|
|
6
|
+
private timestamps;
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config: RateLimitConfig);
|
|
9
|
+
acquire(): Promise<void>;
|
|
10
|
+
private sleep;
|
|
11
|
+
reset(): void;
|
|
12
|
+
pending(): number;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,EAAE,eAAe;IAI7B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB9B,OAAO,CAAC,KAAK;IAIb,KAAK,IAAI,IAAI;IAIb,OAAO,IAAI,MAAM;CAIlB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate limiting implementation
|
|
3
|
+
*/
|
|
4
|
+
export class RateLimiter {
|
|
5
|
+
timestamps = [];
|
|
6
|
+
config;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
}
|
|
10
|
+
async acquire() {
|
|
11
|
+
const now = Date.now();
|
|
12
|
+
// Remove timestamps outside the interval window
|
|
13
|
+
this.timestamps = this.timestamps.filter((t) => now - t < this.config.interval);
|
|
14
|
+
if (this.timestamps.length >= this.config.requests) {
|
|
15
|
+
// Wait until the oldest request expires
|
|
16
|
+
const oldestTimestamp = this.timestamps[0];
|
|
17
|
+
const waitTime = this.config.interval - (now - oldestTimestamp);
|
|
18
|
+
await this.sleep(waitTime);
|
|
19
|
+
return this.acquire();
|
|
20
|
+
}
|
|
21
|
+
this.timestamps.push(now);
|
|
22
|
+
}
|
|
23
|
+
sleep(ms) {
|
|
24
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
25
|
+
}
|
|
26
|
+
reset() {
|
|
27
|
+
this.timestamps = [];
|
|
28
|
+
}
|
|
29
|
+
pending() {
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
return this.timestamps.filter((t) => now - t < this.config.interval).length;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,OAAO,WAAW;IACd,UAAU,GAAa,EAAE,CAAC;IAC1B,MAAM,CAAkB;IAEhC,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,gDAAgD;QAChD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CACtC,CAAC;QAEF,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnD,wCAAwC;YACxC,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC;YAChE,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC3B,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;IACvB,CAAC;IAED,OAAO;QACL,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IAC9E,CAAC;CACF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for zipfetch
|
|
3
|
+
*/
|
|
4
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
5
|
+
export interface ZipFetchConfig {
|
|
6
|
+
baseURL?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
retry?: RetryConfig;
|
|
10
|
+
cache?: CacheConfig;
|
|
11
|
+
rateLimit?: RateLimitConfig;
|
|
12
|
+
}
|
|
13
|
+
export interface RetryConfig {
|
|
14
|
+
attempts?: number;
|
|
15
|
+
delay?: number;
|
|
16
|
+
backoff?: 'linear' | 'exponential';
|
|
17
|
+
retryOn?: number[] | ((response: Response) => boolean);
|
|
18
|
+
}
|
|
19
|
+
export interface CacheConfig {
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
ttl?: number;
|
|
22
|
+
methods?: HttpMethod[];
|
|
23
|
+
}
|
|
24
|
+
export interface RateLimitConfig {
|
|
25
|
+
requests: number;
|
|
26
|
+
interval: number;
|
|
27
|
+
}
|
|
28
|
+
export interface RequestConfig extends Omit<RequestInit, 'body' | 'cache'> {
|
|
29
|
+
url?: string;
|
|
30
|
+
baseURL?: string;
|
|
31
|
+
params?: Record<string, string | number | boolean | undefined>;
|
|
32
|
+
data?: unknown;
|
|
33
|
+
timeout?: number;
|
|
34
|
+
retry?: RetryConfig;
|
|
35
|
+
useCache?: boolean;
|
|
36
|
+
onUploadProgress?: (progress: ProgressEvent) => void;
|
|
37
|
+
onDownloadProgress?: (progress: ProgressEvent) => void;
|
|
38
|
+
}
|
|
39
|
+
export interface ZipResponse<T = unknown> {
|
|
40
|
+
data: T;
|
|
41
|
+
status: number;
|
|
42
|
+
statusText: string;
|
|
43
|
+
headers: Headers;
|
|
44
|
+
config: RequestConfig;
|
|
45
|
+
request: Request;
|
|
46
|
+
}
|
|
47
|
+
export interface ProgressEvent {
|
|
48
|
+
loaded: number;
|
|
49
|
+
total: number;
|
|
50
|
+
percent: number;
|
|
51
|
+
}
|
|
52
|
+
export type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;
|
|
53
|
+
export type ResponseInterceptor<T = unknown> = (response: ZipResponse<T>) => ZipResponse<T> | Promise<ZipResponse<T>>;
|
|
54
|
+
export type ErrorInterceptor = (error: ZipError) => ZipError | Promise<ZipError>;
|
|
55
|
+
import type { ZipError } from './error.js';
|
|
56
|
+
export type { ZipError };
|
|
57
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1F,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IAC/D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACrD,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,aAAa,KAAK,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AACnG,MAAM,MAAM,mBAAmB,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AACtH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAGjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zipfetch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Ultra-fast, lightweight HTTP client built on native fetch - retries, interceptors, caching, rate limiting",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"dev": "tsx src/index.ts",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"clean": "rm -rf dist"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"fetch",
|
|
28
|
+
"http",
|
|
29
|
+
"https",
|
|
30
|
+
"request",
|
|
31
|
+
"client",
|
|
32
|
+
"api",
|
|
33
|
+
"rest",
|
|
34
|
+
"ajax",
|
|
35
|
+
"axios",
|
|
36
|
+
"got",
|
|
37
|
+
"node-fetch",
|
|
38
|
+
"retry",
|
|
39
|
+
"interceptor",
|
|
40
|
+
"cache",
|
|
41
|
+
"rate-limit",
|
|
42
|
+
"lightweight",
|
|
43
|
+
"fast",
|
|
44
|
+
"typescript"
|
|
45
|
+
],
|
|
46
|
+
"author": "",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/willzhangfly/zipfetch.git"
|
|
51
|
+
},
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/willzhangfly/zipfetch/issues"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/willzhangfly/zipfetch#readme",
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=18.0.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"typescript": "^5.3.0",
|
|
61
|
+
"@types/node": "^20.11.0",
|
|
62
|
+
"tsx": "^4.7.0"
|
|
63
|
+
},
|
|
64
|
+
"sideEffects": false
|
|
65
|
+
}
|