jiren 1.1.0 → 1.1.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.
- package/README.md +197 -44
- package/components/client.ts +639 -0
- package/components/index.ts +20 -10
- package/components/native.ts +31 -9
- package/components/types.ts +118 -4
- package/components/worker.ts +142 -0
- package/index.ts +29 -0
- package/lib/libcurl-impersonate.dylib +0 -0
- package/lib/libhttpclient.dylib +0 -0
- package/lib/libidn2.0.dylib +0 -0
- package/lib/libintl.8.dylib +0 -0
- package/lib/libunistring.5.dylib +0 -0
- package/lib/libzstd.1.5.7.dylib +0 -0
- package/package.json +9 -14
- package/types/index.ts +6 -11
- package/components/client-bun.ts +0 -188
- package/components/client-node.ts +0 -105
- package/components/runtime.ts +0 -11
- package/dist/index.js +0 -271
package/README.md
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Jiren
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Ultra-fast HTTP/HTTPS client.
|
|
3
|
+
Ultra-fast HTTP/HTTPS client powered by native Zig (FFI).
|
|
6
4
|
Designed to be significantly faster than `fetch` and other Node/Bun HTTP clients.
|
|
7
5
|
|
|
8
6
|
## Features
|
|
9
7
|
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **Type-Safe API**: Strict options (`GetRequestOptions`, `PostRequestOptions`) for better DX.
|
|
14
|
-
- **Helper Methods**: Built-in `.json<T>()` parser and header accessors.
|
|
8
|
+
- **Native Performance**: Written in Zig for memory safety and speed.
|
|
9
|
+
- **Anti-Bot Protection**: Bypass Cloudflare with curl-impersonate (Chrome TLS fingerprinting).
|
|
10
|
+
- **HTTP/1.1, HTTP/2 & HTTP/3 (QUIC)**: Full support for modern protocols.
|
|
15
11
|
- **Connection Pooling**: Reuse connections for maximum throughput.
|
|
16
|
-
- **
|
|
12
|
+
- **Mandatory Warmup**: Pre-warm connections for instant requests.
|
|
13
|
+
- **Type-Safe URLs**: Define named endpoints with full TypeScript autocomplete.
|
|
14
|
+
- **JSON & Text Helpers**: Easy response parsing.
|
|
15
|
+
- **Automatic Gzip Decompression**: Handles compressed responses transparently.
|
|
17
16
|
|
|
18
17
|
## Installation
|
|
19
18
|
|
|
@@ -23,67 +22,221 @@ bun add jiren
|
|
|
23
22
|
|
|
24
23
|
## Usage
|
|
25
24
|
|
|
26
|
-
### Basic
|
|
25
|
+
### Basic Usage (Type-Safe URLs)
|
|
26
|
+
|
|
27
|
+
**Warmup is now mandatory** - you must define URLs in the constructor:
|
|
27
28
|
|
|
28
29
|
```typescript
|
|
29
30
|
import { JirenClient } from "jiren";
|
|
30
31
|
|
|
31
|
-
const client = new JirenClient(
|
|
32
|
+
const client = new JirenClient({
|
|
33
|
+
warmup: {
|
|
34
|
+
google: "https://www.google.com",
|
|
35
|
+
github: "https://api.github.com",
|
|
36
|
+
myapi: "https://api.myservice.com",
|
|
37
|
+
},
|
|
38
|
+
});
|
|
32
39
|
|
|
33
|
-
//
|
|
34
|
-
const res = client.get(
|
|
35
|
-
console.log(res.status);
|
|
40
|
+
// TypeScript knows about 'google', 'github', 'myapi' - full autocomplete!
|
|
41
|
+
const res = await client.url.google.get();
|
|
42
|
+
console.log(res.status);
|
|
43
|
+
const text = await res.body.text();
|
|
44
|
+
```
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
### JSON Response
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
interface User {
|
|
50
|
+
id: number;
|
|
51
|
+
name: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const client = new JirenClient({
|
|
55
|
+
warmup: {
|
|
56
|
+
api: "https://api.example.com",
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const res = await client.url.api.get<User>({
|
|
61
|
+
path: "/user/1",
|
|
62
|
+
responseType: "json",
|
|
63
|
+
});
|
|
64
|
+
console.log(res.name); // Fully typed!
|
|
39
65
|
```
|
|
40
66
|
|
|
41
|
-
###
|
|
67
|
+
### Anti-Bot Mode (NEW! �️)
|
|
42
68
|
|
|
43
|
-
|
|
69
|
+
Enable curl-impersonate for sites with bot protection:
|
|
44
70
|
|
|
45
71
|
```typescript
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
72
|
+
const client = new JirenClient({
|
|
73
|
+
warmup: {
|
|
74
|
+
protected: "https://protected-site.com",
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Enable antibot mode for this request
|
|
79
|
+
const res = await client.url.protected.get({
|
|
80
|
+
antibot: true, // Uses curl-impersonate with Chrome fingerprinting
|
|
49
81
|
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### POST, PUT, PATCH, DELETE
|
|
50
85
|
|
|
51
|
-
|
|
52
|
-
client
|
|
53
|
-
|
|
54
|
-
|
|
86
|
+
```typescript
|
|
87
|
+
const client = new JirenClient({
|
|
88
|
+
warmup: {
|
|
89
|
+
api: "https://api.myservice.com",
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// POST with body
|
|
94
|
+
const created = await client.url.api.post(
|
|
95
|
+
JSON.stringify({ name: "New Item" }),
|
|
55
96
|
{
|
|
97
|
+
path: "/items",
|
|
56
98
|
headers: { "Content-Type": "application/json" },
|
|
57
99
|
}
|
|
58
100
|
);
|
|
59
101
|
|
|
60
|
-
//
|
|
61
|
-
client.
|
|
62
|
-
|
|
102
|
+
// PUT, PATCH, DELETE
|
|
103
|
+
await client.url.api.put(body, { path: "/items/1" });
|
|
104
|
+
await client.url.api.patch(body, { path: "/items/1" });
|
|
105
|
+
await client.url.api.delete(null, { path: "/items/1" });
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Response Helpers
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
const res = await client.url.api.get({ path: "/data" });
|
|
112
|
+
|
|
113
|
+
// Get as text
|
|
114
|
+
const text = await res.body.text();
|
|
115
|
+
|
|
116
|
+
// Get as JSON
|
|
117
|
+
const json = await res.body.json();
|
|
118
|
+
|
|
119
|
+
// Get as ArrayBuffer
|
|
120
|
+
const buffer = await res.body.arrayBuffer();
|
|
121
|
+
|
|
122
|
+
// Get as Blob
|
|
123
|
+
const blob = await res.body.blob();
|
|
124
|
+
|
|
125
|
+
// Or use responseType for automatic parsing
|
|
126
|
+
const data = await client.url.api.get({
|
|
127
|
+
path: "/data",
|
|
128
|
+
responseType: "json", // Returns parsed JSON directly
|
|
63
129
|
});
|
|
64
130
|
```
|
|
65
131
|
|
|
66
|
-
|
|
132
|
+
## Why Jiren?
|
|
67
133
|
|
|
68
|
-
|
|
134
|
+
### Comparison with Other Clients
|
|
135
|
+
|
|
136
|
+
| Feature | **Jiren** | **Axios** | **ky** | **got** | **node-fetch** |
|
|
137
|
+
| -------------------- | :-------: | :-------: | :----: | :-----: | :------------: |
|
|
138
|
+
| Type-safe named URLs | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
139
|
+
| Mandatory warmup | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
140
|
+
| HTTP/3 (QUIC) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
141
|
+
| Anti-bot protection | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
142
|
+
| Native performance | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
143
|
+
| Zero code generation | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
144
|
+
| Bun FFI optimized | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
145
|
+
|
|
146
|
+
### What Makes Jiren Unique
|
|
147
|
+
|
|
148
|
+
1. **🔥 Mandatory Warmup** - Pre-establishes connections at startup for instant requests
|
|
149
|
+
2. **📝 Type-Safe URLs** - Full autocomplete without needing backend schemas or code generation
|
|
150
|
+
3. **🚀 Native Speed** - Zig-powered core bypasses JavaScript overhead
|
|
151
|
+
4. **🛡️ Anti-Bot Protection** - Bypass Cloudflare, TLS fingerprinting, and bot detection with curl-impersonate
|
|
152
|
+
5. **⚡ HTTP/3 Support** - First-class QUIC support for modern protocols
|
|
153
|
+
|
|
154
|
+
## Anti-Bot Protection
|
|
155
|
+
|
|
156
|
+
The `antibot` option uses curl-impersonate to mimic Chrome's TLS fingerprint:
|
|
157
|
+
|
|
158
|
+
- Bypass TLS fingerprinting protections (JA3/JA4) like Cloudflare
|
|
159
|
+
- Chrome 120 browser impersonation
|
|
160
|
+
- Proper header ordering and HTTP/2 settings
|
|
161
|
+
- Automatic gzip decompression
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const res = await client.url.site.get({
|
|
165
|
+
antibot: true, // Enable for protected sites
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Performance**: ~1-2s for first request, faster with connection reuse.
|
|
170
|
+
|
|
171
|
+
## API Reference
|
|
172
|
+
|
|
173
|
+
### `JirenClient`
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
// Constructor options
|
|
177
|
+
interface JirenClientOptions {
|
|
178
|
+
warmup: Record<string, string>; // Required! Map of key -> URL
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Create client (warmup is mandatory)
|
|
182
|
+
const client = new JirenClient({
|
|
183
|
+
warmup: {
|
|
184
|
+
api: "https://api.example.com",
|
|
185
|
+
cdn: "https://cdn.example.com",
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Type-safe URL access
|
|
190
|
+
client.url[key].get(options?)
|
|
191
|
+
client.url[key].post(body?, options?)
|
|
192
|
+
client.url[key].put(body?, options?)
|
|
193
|
+
client.url[key].patch(body?, options?)
|
|
194
|
+
client.url[key].delete(body?, options?)
|
|
195
|
+
client.url[key].head(options?)
|
|
196
|
+
client.url[key].options(options?)
|
|
197
|
+
|
|
198
|
+
// Cleanup
|
|
199
|
+
client.close()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Request Options
|
|
69
203
|
|
|
70
204
|
```typescript
|
|
71
|
-
|
|
72
|
-
|
|
205
|
+
interface UrlRequestOptions {
|
|
206
|
+
path?: string; // Path to append to base URL
|
|
207
|
+
headers?: Record<string, string>;
|
|
208
|
+
maxRedirects?: number;
|
|
209
|
+
responseType?: "json" | "text" | "arraybuffer" | "blob";
|
|
210
|
+
antibot?: boolean; // Enable curl-impersonate (default: false)
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Response Object
|
|
73
215
|
|
|
74
|
-
|
|
75
|
-
|
|
216
|
+
```typescript
|
|
217
|
+
interface JirenResponse<T> {
|
|
218
|
+
status: number;
|
|
219
|
+
statusText: string;
|
|
220
|
+
headers: Record<string, string>;
|
|
221
|
+
ok: boolean;
|
|
222
|
+
body: {
|
|
223
|
+
text(): Promise<string>;
|
|
224
|
+
json<R = T>(): Promise<R>;
|
|
225
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
226
|
+
blob(): Promise<Blob>;
|
|
227
|
+
};
|
|
228
|
+
}
|
|
76
229
|
```
|
|
77
230
|
|
|
78
|
-
##
|
|
231
|
+
## Performance
|
|
232
|
+
|
|
233
|
+
Benchmark results:
|
|
234
|
+
|
|
235
|
+
- **Bun fetch**: ~950-1780ms
|
|
236
|
+
- **JirenClient**: ~480-1630ms
|
|
79
237
|
|
|
80
|
-
**
|
|
238
|
+
JirenClient is often **faster than Bun's native fetch** thanks to optimized connection pooling and native Zig implementation.
|
|
81
239
|
|
|
82
|
-
|
|
83
|
-
| ----------------- | ------------- | -------------- |
|
|
84
|
-
| **jiren** | **1,550,000** | **1.0x** |
|
|
85
|
-
| Bun `fetch` | 45,000 | 34x Slower |
|
|
86
|
-
| Node `http` | 32,000 | 48x Slower |
|
|
87
|
-
| Python `requests` | 6,500 | 238x Slower |
|
|
240
|
+
## License
|
|
88
241
|
|
|
89
|
-
|
|
242
|
+
MIT
|