jiren 1.5.5 โ†’ 1.6.5

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 (45) hide show
  1. package/README.md +123 -313
  2. package/components/cache.ts +1 -1
  3. package/components/client-node-native.ts +602 -159
  4. package/components/client.ts +51 -29
  5. package/components/metrics.ts +1 -4
  6. package/components/native-node.ts +48 -3
  7. package/components/native.ts +29 -0
  8. package/components/persistent-worker.ts +73 -0
  9. package/components/subprocess-worker.ts +65 -0
  10. package/components/types.ts +2 -0
  11. package/components/worker-pool.ts +169 -0
  12. package/components/worker.ts +39 -23
  13. package/dist/components/cache.d.ts +76 -0
  14. package/dist/components/cache.d.ts.map +1 -0
  15. package/dist/components/cache.js +439 -0
  16. package/dist/components/cache.js.map +1 -0
  17. package/dist/components/client-node-native.d.ts +134 -0
  18. package/dist/components/client-node-native.d.ts.map +1 -0
  19. package/dist/components/client-node-native.js +811 -0
  20. package/dist/components/client-node-native.js.map +1 -0
  21. package/dist/components/metrics.d.ts +104 -0
  22. package/dist/components/metrics.d.ts.map +1 -0
  23. package/dist/components/metrics.js +296 -0
  24. package/dist/components/metrics.js.map +1 -0
  25. package/dist/components/native-node.d.ts +67 -0
  26. package/dist/components/native-node.d.ts.map +1 -0
  27. package/dist/components/native-node.js +137 -0
  28. package/dist/components/native-node.js.map +1 -0
  29. package/dist/components/types.d.ts +252 -0
  30. package/dist/components/types.d.ts.map +1 -0
  31. package/dist/components/types.js +5 -0
  32. package/dist/components/types.js.map +1 -0
  33. package/dist/index-node.d.ts +10 -0
  34. package/dist/index-node.d.ts.map +1 -0
  35. package/dist/index-node.js +12 -0
  36. package/dist/index-node.js.map +1 -0
  37. package/dist/types/index.d.ts +63 -0
  38. package/dist/types/index.d.ts.map +1 -0
  39. package/dist/types/index.js +6 -0
  40. package/dist/types/index.js.map +1 -0
  41. package/index-node.ts +6 -6
  42. package/index.ts +4 -3
  43. package/lib/libhttpclient.dylib +0 -0
  44. package/package.json +15 -8
  45. package/types/index.ts +0 -68
package/README.md CHANGED
@@ -1,22 +1,54 @@
1
1
  # Jiren ๐Ÿš€
2
2
 
3
- **The fastest HTTP client for JavaScript** - Simple, type-safe, and blazingly fast.
3
+ **The fastest HTTP client for JavaScript** โ€” Native Zig core, type-safe, batteries included.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/jiren.svg)](https://www.npmjs.com/package/jiren)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
8
  ---
9
9
 
10
+ ## โšก Performance
11
+
12
+ Jiren beats every major HTTP client โ€” **52% faster than Bun Fetch**.
13
+
14
+ ### Concurrent Benchmark (mitata)
15
+
16
+ | Client | Avg Latency | Req/sec | vs Jiren |
17
+ | ---------- | ----------- | ------------ | -------------- |
18
+ | **Jiren** | **20.9 ยตs** | **47,800/s** | ๐Ÿ† **Fastest** |
19
+ | Bun Fetch | 31.7 ยตs | 31,500/s | 52% slower |
20
+ | Node-Fetch | 29.4 ยตs | 34,000/s | 41% slower |
21
+ | Undici | 37.1 ยตs | 27,000/s | 77% slower |
22
+ | Ky | 36.5 ยตs | 27,400/s | 75% slower |
23
+ | Axios | 59.5 ยตs | 16,800/s | 185% slower |
24
+ | Got | 61.3 ยตs | 16,300/s | 193% slower |
25
+
26
+ ### Sequential Benchmark
27
+
28
+ | Client | Avg Latency | Req/sec | vs Jiren |
29
+ | ---------- | ----------- | ------------ | -------------- |
30
+ | **Jiren** | **20.7 ยตs** | **48,300/s** | ๐Ÿ† **Fastest** |
31
+ | Bun Fetch | 27.9 ยตs | 35,800/s | 35% slower |
32
+ | Node-Fetch | 29.8 ยตs | 33,600/s | 44% slower |
33
+ | Undici | 30.6 ยตs | 32,700/s | 48% slower |
34
+ | Ky | 35.6 ยตs | 28,100/s | 72% slower |
35
+ | Axios | 56.6 ยตs | 17,700/s | 173% slower |
36
+ | Got | 59.9 ยตs | 16,700/s | 189% slower |
37
+
38
+ > Benchmarked on Apple M4, Bun 1.3.0
39
+
40
+ ---
41
+
10
42
  ## โœจ Why Jiren?
11
43
 
12
- | Feature | Benefit |
13
- | ------------------------ | ------------------------------------------------- |
14
- | โšก **Blazing Fast** | 2-3x faster than native `fetch` |
15
- | ๏ฟฝ **HTTP/3 Support** | Automatic protocol upgrade for faster connections |
16
- | ๏ฟฝ๐Ÿ’พ **Built-in Caching** | Automatic response caching with zero config |
17
- | ๐Ÿ“ **Type-Safe** | Full TypeScript support with autocomplete |
18
- | ๐Ÿ”’ **Anti-Bot Ready** | Bypass common bot protections easily |
19
- | ๐Ÿ“Š **Built-in Metrics** | Track performance out of the box |
44
+ - โšก **52% Faster Than Bun** โ€” Native Zig core, zero overhead
45
+ - ๐Ÿ”„ **HTTP/2 & HTTP/3** โ€” Automatic protocol upgrade
46
+ - ๐Ÿ’พ **Smart Caching** โ€” L1 memory + L2 disk, 100x faster repeat requests
47
+ - ๐Ÿ“ **Type-Safe** โ€” Full TypeScript with autocomplete
48
+ - ๐Ÿ”’ **Anti-Bot Mode** โ€” Bypass Cloudflare & bot protections
49
+ - ๐Ÿ“Š **Built-in Metrics** โ€” Track latency, cache hits, and more
50
+ - ๐Ÿ”Œ **Interceptors** โ€” Add auth, logging, error handling
51
+ - ๐ŸŽฏ **Zero Config** โ€” Just works out of the box
20
52
 
21
53
  ---
22
54
 
@@ -24,11 +56,27 @@
24
56
 
25
57
  ```bash
26
58
  bun add jiren
59
+ # or
60
+ npm install jiren
27
61
  ```
28
62
 
29
63
  ---
30
64
 
31
- ## ๐Ÿš€ Quick Start
65
+ ## ๏ฟฝ Table of Contents
66
+
67
+ 1. [Quick Start](#-quick-start)
68
+ 2. [Making Requests](#-making-requests)
69
+ 3. [Response Handling](#-response-handling)
70
+ 4. [Caching](#-caching)
71
+ 5. [Anti-Bot Protection](#-anti-bot-protection)
72
+ 6. [Interceptors](#-interceptors)
73
+ 7. [Metrics](#-metrics)
74
+ 8. [TypeScript Support](#-typescript-support)
75
+ 9. [Framework Integration](#-framework-integration)
76
+
77
+ ---
78
+
79
+ ## ๏ฟฝ๐Ÿš€ Quick Start
32
80
 
33
81
  ### Step 1: Create Your Client
34
82
 
@@ -36,7 +84,7 @@ bun add jiren
36
84
  import { JirenClient } from "jiren";
37
85
 
38
86
  const client = new JirenClient({
39
- warmup: {
87
+ targets: {
40
88
  api: "https://api.example.com",
41
89
  github: "https://api.github.com",
42
90
  },
@@ -61,19 +109,6 @@ That's it! ๐ŸŽ‰
61
109
 
62
110
  ---
63
111
 
64
- ## ๐Ÿ“– Table of Contents
65
-
66
- 1. [Making Requests](#-making-requests)
67
- 2. [Response Handling](#-response-handling)
68
- 3. [Caching](#-caching)
69
- 4. [Anti-Bot Protection](#-anti-bot-protection)
70
- 5. [Interceptors](#-interceptors)
71
- 6. [Metrics](#-metrics)
72
- 7. [TypeScript Support](#-typescript-support)
73
- 8. [API Reference](#-api-reference)
74
-
75
- ---
76
-
77
112
  ## ๐ŸŒ Making Requests
78
113
 
79
114
  ### GET Requests
@@ -136,13 +171,11 @@ const buffer = await response.body.arrayBuffer();
136
171
 
137
172
  ### Auto-Parse (Recommended)
138
173
 
139
- Let Jiren parse the response automatically:
140
-
141
174
  ```typescript
142
- // Auto-parse JSON
143
- const users = await client.url.api.get({
175
+ // Auto-parse JSON - returns parsed data directly!
176
+ const users = await client.url.api.get<User[]>({
144
177
  path: "/users",
145
- responseType: "json", // โ† Returns parsed data directly!
178
+ responseType: "json",
146
179
  });
147
180
 
148
181
  // Auto-parse text
@@ -165,104 +198,92 @@ console.log(response.redirected); // false
165
198
 
166
199
  ---
167
200
 
168
- ## ๐Ÿ’พ Caching
201
+ ## ๏ฟฝ TypeScript Support
202
+
203
+ ### Type-Safe Responses
169
204
 
170
- Enable caching for instant responses on repeated requests:
205
+ ```typescript
206
+ // Define your types
207
+ interface User {
208
+ id: number;
209
+ name: string;
210
+ email: string;
211
+ }
171
212
 
172
- ### Enable Caching
213
+ // Get typed responses
214
+ const users = await client.url.api.get<User[]>({
215
+ path: "/users",
216
+ responseType: "json",
217
+ });
218
+
219
+ // users is typed as User[]!
220
+ users.forEach((user) => console.log(user.name));
221
+ ```
222
+
223
+ ### Type-Safe Target URLs
173
224
 
174
225
  ```typescript
226
+ import { JirenClient } from "jiren";
227
+
228
+ // Use object targets for typed URL endpoints
175
229
  const client = new JirenClient({
176
- warmup: {
177
- api: {
178
- url: "https://api.example.com",
179
- cache: true, // โ† Enable caching (60s default)
180
- },
230
+ targets: {
231
+ api: "https://api.example.com",
232
+ github: "https://api.github.com",
233
+ stripe: "https://api.stripe.com",
181
234
  },
182
235
  });
236
+
237
+ // All targets are typed and autocomplete-enabled!
238
+ await client.url.api.get({ path: "/users" });
239
+ await client.url.github.get({ path: "/repos" });
240
+ await client.url.stripe.post(body, { path: "/charges" });
183
241
  ```
184
242
 
185
- ### Custom Cache Duration
243
+ ## ๐Ÿ’พ Caching
186
244
 
187
245
  ```typescript
188
246
  const client = new JirenClient({
189
- warmup: {
247
+ targets: {
190
248
  api: {
191
249
  url: "https://api.example.com",
192
- cache: { ttl: 300000 }, // 5 minutes
193
- },
194
- cdn: {
195
- url: "https://cdn.example.com",
196
- cache: { ttl: 3600000 }, // 1 hour
250
+ cache: true, // Enable (60s default)
251
+ // cache: { ttl: 300000 }, // Custom TTL (5 min)
197
252
  },
198
253
  },
199
254
  });
200
- ```
201
-
202
- ### Cache Performance
203
-
204
- | Request Type | Speed | Improvement |
205
- | -------------- | ------ | ------------------ |
206
- | First request | ~150ms | - |
207
- | Cached request | ~1-2ms | **100x faster** โšก |
208
-
209
- ### Refresh Cache
210
255
 
211
- ```typescript
212
- // Force refresh cached data
213
- await client.url.api.prefetch({ path: "/users" });
256
+ // First request: ~100ms
257
+ // Cached request: ~1ms (100x faster!)
214
258
  ```
215
259
 
216
- > ๐Ÿ’ก **Tip:** Add `.cache/` to your `.gitignore`
217
-
218
260
  ---
219
261
 
220
262
  ## ๐Ÿ”’ Anti-Bot Protection
221
263
 
222
- Bypass Cloudflare and other bot protections:
223
-
224
264
  ```typescript
225
265
  const client = new JirenClient({
226
- warmup: {
266
+ targets: {
227
267
  protected: "https://protected-site.com",
228
268
  },
229
269
  antibot: true,
230
270
  });
231
-
232
- const response = await client.url.protected.get();
233
271
  ```
234
272
 
235
273
  ---
236
274
 
237
275
  ## ๐Ÿ”„ Interceptors
238
276
 
239
- Add middleware to modify requests/responses:
240
-
241
- ### Add Authentication
242
-
243
277
  ```typescript
244
278
  const client = new JirenClient({
245
- warmup: { api: "https://api.example.com" },
279
+ targets: { api: "https://api.example.com" },
246
280
  interceptors: {
247
281
  request: [
248
282
  (ctx) => ({
249
283
  ...ctx,
250
- headers: {
251
- ...ctx.headers,
252
- Authorization: `Bearer ${getToken()}`,
253
- },
284
+ headers: { ...ctx.headers, Authorization: `Bearer ${token}` },
254
285
  }),
255
286
  ],
256
- },
257
- });
258
- ```
259
-
260
- ### Log Responses
261
-
262
- ```typescript
263
- const client = new JirenClient({
264
- warmup: { api: "https://api.example.com" },
265
- interceptors: {
266
287
  response: [
267
288
  (ctx) => {
268
289
  console.log(`${ctx.response.status} ${ctx.request.url}`);
@@ -273,239 +294,41 @@ const client = new JirenClient({
273
294
  });
274
295
  ```
275
296
 
276
- ### Handle Errors
277
-
278
- ```typescript
279
- const client = new JirenClient({
280
- warmup: { api: "https://api.example.com" },
281
- interceptors: {
282
- error: [
283
- (error, ctx) => {
284
- console.error(`Request failed: ${ctx.url}`);
285
- },
286
- ],
287
- },
288
- });
289
- ```
290
-
291
- ### Add Interceptors Later
292
-
293
- ```typescript
294
- client.use({
295
- request: [
296
- (ctx) => ({ ...ctx, headers: { ...ctx.headers, "X-Custom": "value" } }),
297
- ],
298
- });
299
- ```
300
-
301
297
  ---
302
298
 
303
299
  ## ๐Ÿ“Š Metrics
304
300
 
305
- Track performance and cache efficiency:
306
-
307
- ### Get Endpoint Metrics
308
-
309
301
  ```typescript
310
302
  const metrics = client.metrics.get("api");
311
-
312
- console.log(metrics.requests.total); // Total requests made
313
- console.log(metrics.timing.avgMs); // Average response time
314
- console.log(metrics.cache.hitRate); // Cache hit percentage
315
- ```
316
-
317
- ### Get Global Metrics
318
-
319
- ```typescript
320
- const global = client.metrics.getGlobal();
321
-
322
- console.log(global.totalRequests); // All requests
323
- console.log(global.avgResponseTimeMs); // Average across all endpoints
324
- console.log(global.overallCacheHitRate); // Overall cache performance
325
- ```
326
-
327
- ### Export & Reset
328
-
329
- ```typescript
330
- // Export as JSON
331
- const json = client.metrics.export();
332
-
333
- // Reset metrics
334
- client.metrics.reset();
303
+ console.log(metrics.requests.total);
304
+ console.log(metrics.timing.avgMs);
305
+ console.log(metrics.cache.hitRate);
335
306
  ```
336
307
 
337
308
  ---
338
309
 
339
- ## ๐Ÿ”ท TypeScript Support
340
-
341
- ### Type-Safe Responses
342
-
343
- ```typescript
344
- interface User {
345
- id: number;
346
- name: string;
347
- email: string;
348
- }
349
-
350
- // TypeScript knows the response type!
351
- const user = await client.url.api.get<User>({
352
- path: "/users/123",
353
- responseType: "json",
354
- });
355
-
356
- console.log(user.name); // โœ… Autocomplete works!
357
- ```
310
+ ## ๐Ÿ—๏ธ Framework Integration
358
311
 
359
- ### Typed URL Keys
312
+ ### Next.js
360
313
 
361
314
  ```typescript
362
- const client = new JirenClient({
363
- warmup: {
364
- api: "https://api.example.com",
365
- cdn: "https://cdn.example.com",
366
- },
367
- });
368
-
369
- client.url.api.get(); // โœ… Valid
370
- client.url.cdn.get(); // โœ… Valid
371
- client.url.foo.get(); // โŒ TypeScript error!
315
+ // next.config.ts
316
+ const nextConfig = {
317
+ serverExternalPackages: ["jiren", "koffi"],
318
+ };
372
319
  ```
373
320
 
374
- ---
375
-
376
- ## ๐Ÿ“š API Reference
377
-
378
- ### Creating a Client
379
-
380
321
  ```typescript
381
- new JirenClient({
382
- warmup: {
383
- // Simple URL
384
- api: "https://api.example.com",
385
-
386
- // With caching
387
- cdn: {
388
- url: "https://cdn.example.com",
389
- cache: true, // or { ttl: 60000 }
390
- },
391
- },
392
-
393
- // Optional settings
394
- antibot: false, // Enable anti-bot protection
395
- benchmark: false, // Benchmark mode
396
- interceptors: {}, // Request/response interceptors
397
- });
398
- ```
399
-
400
- ### Request Methods
401
-
402
- | Method | Signature |
403
- | ------------ | -------------------------------------------------- |
404
- | `get()` | `get<T>(options?): Promise<Response<T>>` |
405
- | `post()` | `post<T>(body?, options?): Promise<Response<T>>` |
406
- | `put()` | `put<T>(body?, options?): Promise<Response<T>>` |
407
- | `patch()` | `patch<T>(body?, options?): Promise<Response<T>>` |
408
- | `delete()` | `delete<T>(body?, options?): Promise<Response<T>>` |
409
- | `head()` | `head(options?): Promise<Response>` |
410
- | `options()` | `options(options?): Promise<Response>` |
411
- | `prefetch()` | `prefetch(options?): Promise<void>` |
412
-
413
- ### Request Options
414
-
415
- ```typescript
416
- {
417
- path?: string; // URL path to append
418
- headers?: Record<string, string>; // Request headers
419
- responseType?: "json" | "text"; // Auto-parse response
420
- maxRedirects?: number; // Max redirects (default: 5)
421
- }
422
- ```
423
-
424
- ### Response Object
425
-
426
- ```typescript
427
- {
428
- url: string;
429
- status: number;
430
- statusText: string;
431
- headers: Record<string, string>;
432
- ok: boolean;
433
- redirected: boolean;
434
- body: {
435
- json<T>(): Promise<T>;
436
- text(): Promise<string>;
437
- arrayBuffer(): Promise<ArrayBuffer>;
438
- blob(): Promise<Blob>;
439
- };
440
- }
441
- ```
442
-
443
- ---
444
-
445
- ## ๐Ÿ’ก Examples
446
-
447
- ### API Client Pattern
448
-
449
- ```typescript
450
- // lib/api.ts
322
+ // app/api/data/route.ts
451
323
  import { JirenClient } from "jiren";
452
324
 
453
- export const api = new JirenClient({
454
- warmup: {
455
- backend: {
456
- url: process.env.API_URL!,
457
- cache: { ttl: 30000 },
458
- },
459
- },
460
- interceptors: {
461
- request: [
462
- (ctx) => ({
463
- ...ctx,
464
- headers: {
465
- ...ctx.headers,
466
- Authorization: `Bearer ${getSession()?.token}`,
467
- },
468
- }),
469
- ],
470
- },
471
- });
472
-
473
- // Usage anywhere
474
- import { api } from "@/lib/api";
475
- const users = await api.url.backend.get({
476
- path: "/users",
477
- responseType: "json",
325
+ const client = new JirenClient({
326
+ targets: { api: "https://api.example.com" },
478
327
  });
479
- ```
480
-
481
- ### React/Next.js Hook
482
-
483
- ```typescript
484
- function useApi<T>(path: string) {
485
- const [data, setData] = useState<T | null>(null);
486
- const [loading, setLoading] = useState(true);
487
-
488
- useEffect(() => {
489
- api.url.backend
490
- .get<T>({ path, responseType: "json" })
491
- .then(setData)
492
- .finally(() => setLoading(false));
493
- }, [path]);
494
-
495
- return { data, loading };
496
- }
497
328
 
498
- // Usage
499
- function UserList() {
500
- const { data: users, loading } = useApi<User[]>("/users");
501
- if (loading) return <Spinner />;
502
- return (
503
- <ul>
504
- {users?.map((u) => (
505
- <li key={u.id}>{u.name}</li>
506
- ))}
507
- </ul>
508
- );
329
+ export async function GET() {
330
+ const res = await client.url.api.get({ path: "/users" });
331
+ return Response.json(await res.body.json());
509
332
  }
510
333
  ```
511
334
 
@@ -513,30 +336,17 @@ function UserList() {
513
336
 
514
337
  ## ๐Ÿ“‹ Requirements
515
338
 
516
- - **Bun** v1.0.0+
339
+ - **Bun** v1.0+ or **Node.js** v18+
340
+ - **macOS** (ARM64/x64) or **Linux** (x64)
517
341
 
518
342
  ---
519
343
 
520
344
  ## ๐Ÿ“„ License
521
345
 
522
- MIT ยฉ Vikash Khati
523
-
524
- ---
525
-
526
- ## ๐Ÿค Contributing
527
-
528
- Contributions welcome! Please open an issue or submit a pull request.
529
-
530
- ---
531
-
532
- ## ๐Ÿ†˜ Support
533
-
534
- - ๐Ÿ“– [Documentation](https://github.com/vikashkhati007/jiren)
535
- - ๐Ÿ› [Issue Tracker](https://github.com/vikashkhati007/jiren/issues)
536
- - ๐Ÿ’ฌ [Discussions](https://github.com/vikashkhati007/jiren/discussions)
346
+ MIT ยฉ VK
537
347
 
538
348
  ---
539
349
 
540
350
  <p align="center">
541
- <strong>Made with โšก by Vikash Khati</strong>
351
+ <strong>Made with โšก by VK</strong>
542
352
  </p>
@@ -10,7 +10,7 @@ import {
10
10
  import { gzipSync, gunzipSync } from "zlib";
11
11
  import { createHash } from "crypto";
12
12
  import { join } from "path";
13
- import type { JirenResponse, JirenResponseBody } from "./types";
13
+ import type { JirenResponse, JirenResponseBody } from "./types.js";
14
14
 
15
15
  /**
16
16
  * Serializable cache entry - stores raw body data for reconstruction