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 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