jiren 1.4.0 → 1.5.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 +220 -3
- package/components/cache.ts +398 -41
- package/components/client-node-native.ts +45 -12
- package/components/client.ts +524 -99
- package/components/index.ts +9 -0
- package/components/metrics.ts +420 -0
- package/components/native-cache.ts +181 -0
- package/components/native-node.ts +26 -0
- package/components/native.ts +92 -0
- package/components/types.ts +105 -5
- package/lib/libhttpclient.dylib +0 -0
- package/package.json +1 -1
- package/components/client-node.ts +0 -440
package/README.md
CHANGED
|
@@ -46,6 +46,8 @@ console.log(users);
|
|
|
46
46
|
- [Basic Usage](#basic-usage)
|
|
47
47
|
- [Response Caching](#response-caching)
|
|
48
48
|
- [Anti-Bot Protection](#anti-bot-protection)
|
|
49
|
+
- [Request Interceptors](#request-interceptors)
|
|
50
|
+
- [Metrics & Observability](#metrics--observability)
|
|
49
51
|
- [Advanced Features](#advanced-features)
|
|
50
52
|
- [Performance](#performance)
|
|
51
53
|
- [API Reference](#api-reference)
|
|
@@ -225,13 +227,12 @@ Bypass Cloudflare and other bot protection using Chrome TLS fingerprinting:
|
|
|
225
227
|
const client = new JirenClient({
|
|
226
228
|
warmup: {
|
|
227
229
|
protected: "https://cloudflare-protected-site.com",
|
|
230
|
+
antibot: true,
|
|
228
231
|
},
|
|
229
232
|
});
|
|
230
233
|
|
|
231
234
|
// Enable anti-bot mode for this request
|
|
232
|
-
const response = await client.url.protected.get(
|
|
233
|
-
antibot: true, // Uses curl-impersonate with Chrome 120 fingerprint
|
|
234
|
-
});
|
|
235
|
+
const response = await client.url.protected.get();
|
|
235
236
|
```
|
|
236
237
|
|
|
237
238
|
**How it works:**
|
|
@@ -242,6 +243,222 @@ const response = await client.url.protected.get({
|
|
|
242
243
|
|
|
243
244
|
---
|
|
244
245
|
|
|
246
|
+
## Request Interceptors
|
|
247
|
+
|
|
248
|
+
Add middleware to intercept requests and responses for logging, auth injection, and more:
|
|
249
|
+
|
|
250
|
+
### Basic Interceptors
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const client = new JirenClient({
|
|
254
|
+
warmup: { api: "https://api.example.com" },
|
|
255
|
+
interceptors: {
|
|
256
|
+
// Modify requests before sending
|
|
257
|
+
request: [
|
|
258
|
+
(ctx) => ({
|
|
259
|
+
...ctx,
|
|
260
|
+
headers: { ...ctx.headers, Authorization: `Bearer ${getToken()}` },
|
|
261
|
+
}),
|
|
262
|
+
],
|
|
263
|
+
// Transform responses after receiving
|
|
264
|
+
response: [
|
|
265
|
+
(ctx) => {
|
|
266
|
+
console.log(`[${ctx.response.status}] ${ctx.request.url}`);
|
|
267
|
+
return ctx;
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
// Handle errors
|
|
271
|
+
error: [(err, ctx) => console.error(`Failed: ${ctx.url}`, err)],
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Dynamic Interceptors with `use()`
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
// Add interceptors after client creation
|
|
280
|
+
client.use({
|
|
281
|
+
request: [
|
|
282
|
+
(ctx) => ({ ...ctx, headers: { ...ctx.headers, "X-Custom": "value" } }),
|
|
283
|
+
],
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Interceptor Types
|
|
288
|
+
|
|
289
|
+
| Type | Purpose | Context |
|
|
290
|
+
| ---------- | ------------------------------------------------ | -------------------------------- |
|
|
291
|
+
| `request` | Modify method, URL, headers, body before sending | `{ method, url, headers, body }` |
|
|
292
|
+
| `response` | Transform response after receiving | `{ request, response }` |
|
|
293
|
+
| `error` | Handle errors centrally | `(error, requestContext)` |
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Metrics & Observability
|
|
298
|
+
|
|
299
|
+
Track performance, cache efficiency, and request statistics with built-in metrics collection:
|
|
300
|
+
|
|
301
|
+
### Basic Metrics
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
const client = new JirenClient({
|
|
305
|
+
warmup: {
|
|
306
|
+
api: {
|
|
307
|
+
url: "https://api.example.com",
|
|
308
|
+
cache: true,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Make some requests
|
|
314
|
+
await client.url.api.get({ path: "/users" });
|
|
315
|
+
await client.url.api.get({ path: "/users" }); // Cache hit
|
|
316
|
+
|
|
317
|
+
// Get endpoint metrics
|
|
318
|
+
const metrics = client.metrics.get("api");
|
|
319
|
+
console.log(metrics);
|
|
320
|
+
/*
|
|
321
|
+
{
|
|
322
|
+
endpoint: "api",
|
|
323
|
+
requests: {
|
|
324
|
+
total: 2,
|
|
325
|
+
success: 2,
|
|
326
|
+
failed: 0
|
|
327
|
+
},
|
|
328
|
+
statusCodes: { 200: 2 },
|
|
329
|
+
timing: {
|
|
330
|
+
avgMs: 50.5,
|
|
331
|
+
minMs: 0.01,
|
|
332
|
+
maxMs: 101,
|
|
333
|
+
p50Ms: 50.5,
|
|
334
|
+
p95Ms: 101,
|
|
335
|
+
p99Ms: 101
|
|
336
|
+
},
|
|
337
|
+
cache: {
|
|
338
|
+
l1Hits: 1,
|
|
339
|
+
l1Misses: 1,
|
|
340
|
+
l2Hits: 0,
|
|
341
|
+
l2Misses: 1,
|
|
342
|
+
hitRate: "50.00%"
|
|
343
|
+
},
|
|
344
|
+
deduplication: {
|
|
345
|
+
hits: 0,
|
|
346
|
+
misses: 2,
|
|
347
|
+
hitRate: "0.00%"
|
|
348
|
+
},
|
|
349
|
+
bytes: {
|
|
350
|
+
sent: 0,
|
|
351
|
+
received: 0
|
|
352
|
+
},
|
|
353
|
+
errors: {},
|
|
354
|
+
lastRequestAt: 1234567890000
|
|
355
|
+
}
|
|
356
|
+
*/
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Global Metrics
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// Get aggregated metrics across all endpoints
|
|
363
|
+
const global = client.metrics.getGlobal();
|
|
364
|
+
console.log(global);
|
|
365
|
+
/*
|
|
366
|
+
{
|
|
367
|
+
totalRequests: 8,
|
|
368
|
+
totalSuccess: 8,
|
|
369
|
+
totalFailed: 0,
|
|
370
|
+
avgResponseTimeMs: 125.5,
|
|
371
|
+
totalBytesSent: 1024,
|
|
372
|
+
totalBytesReceived: 4096,
|
|
373
|
+
overallCacheHitRate: "62.50%",
|
|
374
|
+
overallDeduplicationRate: "25.00%",
|
|
375
|
+
endpoints: 2,
|
|
376
|
+
uptime: 60000
|
|
377
|
+
}
|
|
378
|
+
*/
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### All Endpoints
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
// Get metrics for all endpoints
|
|
385
|
+
const allMetrics = client.metrics.getAll();
|
|
386
|
+
for (const [endpoint, metrics] of Object.entries(allMetrics)) {
|
|
387
|
+
console.log(`${endpoint}: ${metrics.cache.hitRate} cache hit rate`);
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Export Metrics
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
// Export all metrics as JSON
|
|
395
|
+
const json = client.metrics.export();
|
|
396
|
+
console.log(json); // Pretty-printed JSON string
|
|
397
|
+
|
|
398
|
+
// Save to file or send to monitoring service
|
|
399
|
+
await Bun.write("metrics.json", json);
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Reset Metrics
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
// Reset specific endpoint
|
|
406
|
+
client.metrics.reset("api");
|
|
407
|
+
|
|
408
|
+
// Reset all metrics
|
|
409
|
+
client.metrics.reset();
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Tracked Metrics
|
|
413
|
+
|
|
414
|
+
| Category | Metrics |
|
|
415
|
+
| ------------ | ---------------------------------------------------------- |
|
|
416
|
+
| **Requests** | Total, success, failed, status code distribution |
|
|
417
|
+
| **Timing** | Average, min, max, P50, P95, P99 response times |
|
|
418
|
+
| **Cache** | L1/L2 hits & misses, overall hit rate |
|
|
419
|
+
| **Dedupe** | Deduplication hits/misses for identical in-flight requests |
|
|
420
|
+
| **Bytes** | Total sent/received |
|
|
421
|
+
| **Errors** | Error counts by type |
|
|
422
|
+
| **Other** | Last request timestamp, client uptime |
|
|
423
|
+
|
|
424
|
+
### Use Cases
|
|
425
|
+
|
|
426
|
+
**Performance Monitoring:**
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
// Track P99 latency
|
|
430
|
+
setInterval(() => {
|
|
431
|
+
const metrics = client.metrics.getGlobal();
|
|
432
|
+
if (metrics.avgResponseTimeMs > 1000) {
|
|
433
|
+
console.warn("High latency detected!");
|
|
434
|
+
}
|
|
435
|
+
}, 60000);
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
**Cache Optimization:**
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// Monitor cache effectiveness
|
|
442
|
+
const metrics = client.metrics.get("api");
|
|
443
|
+
console.log(`Cache hit rate: ${metrics.cache.hitRate}`);
|
|
444
|
+
if (parseFloat(metrics.cache.hitRate) < 50) {
|
|
445
|
+
console.log("Consider increasing cache TTL");
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Debugging:**
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
// Export metrics for debugging
|
|
453
|
+
if (process.env.DEBUG) {
|
|
454
|
+
process.on("exit", () => {
|
|
455
|
+
console.log(client.metrics.export());
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
245
462
|
## Advanced Features
|
|
246
463
|
|
|
247
464
|
### TypeScript Generics
|