jiren 1.0.13 → 1.0.15
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/dist/index.js +182 -0
- package/package.json +11 -8
- package/index.ts +0 -29
package/dist/index.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// components/client.ts
|
|
3
|
+
import { CString } from "bun:ffi";
|
|
4
|
+
|
|
5
|
+
// components/native.ts
|
|
6
|
+
import { dlopen, FFIType, suffix } from "bun:ffi";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
var libPath = join(import.meta.dir, `../lib/libhttpclient.${suffix}`);
|
|
9
|
+
var ffiDef = {
|
|
10
|
+
zclient_new: {
|
|
11
|
+
args: [],
|
|
12
|
+
returns: FFIType.ptr
|
|
13
|
+
},
|
|
14
|
+
zclient_free: {
|
|
15
|
+
args: [FFIType.ptr],
|
|
16
|
+
returns: FFIType.void
|
|
17
|
+
},
|
|
18
|
+
zclient_get: {
|
|
19
|
+
args: [FFIType.ptr, FFIType.cstring],
|
|
20
|
+
returns: FFIType.ptr
|
|
21
|
+
},
|
|
22
|
+
zclient_post: {
|
|
23
|
+
args: [FFIType.ptr, FFIType.cstring, FFIType.cstring],
|
|
24
|
+
returns: FFIType.ptr
|
|
25
|
+
},
|
|
26
|
+
zclient_prefetch: {
|
|
27
|
+
args: [FFIType.ptr, FFIType.cstring],
|
|
28
|
+
returns: FFIType.void
|
|
29
|
+
},
|
|
30
|
+
zclient_response_status: {
|
|
31
|
+
args: [FFIType.ptr],
|
|
32
|
+
returns: FFIType.u16
|
|
33
|
+
},
|
|
34
|
+
zclient_response_body: {
|
|
35
|
+
args: [FFIType.ptr],
|
|
36
|
+
returns: FFIType.ptr
|
|
37
|
+
},
|
|
38
|
+
zclient_response_body_len: {
|
|
39
|
+
args: [FFIType.ptr],
|
|
40
|
+
returns: FFIType.u64
|
|
41
|
+
},
|
|
42
|
+
zclient_response_headers: {
|
|
43
|
+
args: [FFIType.ptr],
|
|
44
|
+
returns: FFIType.ptr
|
|
45
|
+
},
|
|
46
|
+
zclient_response_headers_len: {
|
|
47
|
+
args: [FFIType.ptr],
|
|
48
|
+
returns: FFIType.u64
|
|
49
|
+
},
|
|
50
|
+
zclient_response_free: {
|
|
51
|
+
args: [FFIType.ptr],
|
|
52
|
+
returns: FFIType.void
|
|
53
|
+
},
|
|
54
|
+
zclient_request: {
|
|
55
|
+
args: [
|
|
56
|
+
FFIType.ptr,
|
|
57
|
+
FFIType.cstring,
|
|
58
|
+
FFIType.cstring,
|
|
59
|
+
FFIType.cstring,
|
|
60
|
+
FFIType.cstring
|
|
61
|
+
],
|
|
62
|
+
returns: FFIType.ptr
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var lib = dlopen(libPath, ffiDef);
|
|
66
|
+
|
|
67
|
+
// components/client.ts
|
|
68
|
+
class JirenClient {
|
|
69
|
+
ptr;
|
|
70
|
+
constructor() {
|
|
71
|
+
this.ptr = lib.symbols.zclient_new();
|
|
72
|
+
if (!this.ptr)
|
|
73
|
+
throw new Error("Failed to create native client instance");
|
|
74
|
+
}
|
|
75
|
+
close() {
|
|
76
|
+
if (this.ptr) {
|
|
77
|
+
lib.symbols.zclient_free(this.ptr);
|
|
78
|
+
this.ptr = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
request(url, options = {}) {
|
|
82
|
+
if (!this.ptr)
|
|
83
|
+
throw new Error("Client is closed");
|
|
84
|
+
const method = options.method || "GET";
|
|
85
|
+
const methodBuffer = Buffer.from(method + "\x00");
|
|
86
|
+
const urlBuffer = Buffer.from(url + "\x00");
|
|
87
|
+
let headersBuffer = null;
|
|
88
|
+
if (options.headers) {
|
|
89
|
+
const headerStr = Object.entries(options.headers).map(([k, v]) => `${k.toLowerCase()}: ${v}`).join(`\r
|
|
90
|
+
`);
|
|
91
|
+
if (headerStr.length > 0) {
|
|
92
|
+
headersBuffer = Buffer.from(headerStr + "\x00");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
let bodyBuffer = null;
|
|
96
|
+
if (options.body) {
|
|
97
|
+
const bodyStr = typeof options.body === "string" ? options.body : JSON.stringify(options.body);
|
|
98
|
+
bodyBuffer = Buffer.from(bodyStr + "\x00");
|
|
99
|
+
}
|
|
100
|
+
const respPtr = lib.symbols.zclient_request(this.ptr, methodBuffer, urlBuffer, headersBuffer, bodyBuffer);
|
|
101
|
+
const response = this.parseResponse(respPtr);
|
|
102
|
+
if (options.maxRedirects && options.maxRedirects > 0 && response.status >= 300 && response.status < 400 && response.headers && response.headers["location"]) {
|
|
103
|
+
const location = response.headers["location"];
|
|
104
|
+
const newUrl = new URL(location, url).toString();
|
|
105
|
+
const newOptions = { ...options, maxRedirects: options.maxRedirects - 1 };
|
|
106
|
+
return this.request(newUrl, newOptions);
|
|
107
|
+
}
|
|
108
|
+
return response;
|
|
109
|
+
}
|
|
110
|
+
get(url, options = {}) {
|
|
111
|
+
return this.request(url, { ...options, method: "GET" });
|
|
112
|
+
}
|
|
113
|
+
post(url, body, options = {}) {
|
|
114
|
+
return this.request(url, { ...options, method: "POST", body });
|
|
115
|
+
}
|
|
116
|
+
put(url, body, options = {}) {
|
|
117
|
+
return this.request(url, { ...options, method: "PUT", body });
|
|
118
|
+
}
|
|
119
|
+
delete(url, options = {}) {
|
|
120
|
+
return this.request(url, { ...options, method: "DELETE" });
|
|
121
|
+
}
|
|
122
|
+
patch(url, body, options = {}) {
|
|
123
|
+
return this.request(url, { ...options, method: "PATCH", body });
|
|
124
|
+
}
|
|
125
|
+
head(url, options = {}) {
|
|
126
|
+
return this.request(url, { ...options, method: "HEAD" });
|
|
127
|
+
}
|
|
128
|
+
prefetch(urls) {
|
|
129
|
+
if (!this.ptr)
|
|
130
|
+
throw new Error("Client is closed");
|
|
131
|
+
for (const url of urls) {
|
|
132
|
+
const urlBuffer = Buffer.from(url + "\x00");
|
|
133
|
+
lib.symbols.zclient_prefetch(this.ptr, urlBuffer);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
parseResponse(respPtr) {
|
|
137
|
+
if (!respPtr)
|
|
138
|
+
throw new Error("Native request failed (returned null pointer)");
|
|
139
|
+
try {
|
|
140
|
+
const status = lib.symbols.zclient_response_status(respPtr);
|
|
141
|
+
const bodyLen = Number(lib.symbols.zclient_response_body_len(respPtr));
|
|
142
|
+
const bodyPtr = lib.symbols.zclient_response_body(respPtr);
|
|
143
|
+
const headersLen = Number(lib.symbols.zclient_response_headers_len(respPtr));
|
|
144
|
+
const headersPtr = lib.symbols.zclient_response_headers(respPtr);
|
|
145
|
+
let bodyString = "";
|
|
146
|
+
if (bodyLen > 0 && bodyPtr) {
|
|
147
|
+
bodyString = new CString(bodyPtr).toString();
|
|
148
|
+
}
|
|
149
|
+
const headers = {};
|
|
150
|
+
if (headersLen > 0 && headersPtr) {
|
|
151
|
+
const headersStr = new CString(headersPtr).toString();
|
|
152
|
+
const lines = headersStr.split(`\r
|
|
153
|
+
`);
|
|
154
|
+
for (const line of lines) {
|
|
155
|
+
if (!line)
|
|
156
|
+
continue;
|
|
157
|
+
const colonIdx = line.indexOf(":");
|
|
158
|
+
if (colonIdx !== -1) {
|
|
159
|
+
const key = line.substring(0, colonIdx).trim().toLowerCase();
|
|
160
|
+
const val = line.substring(colonIdx + 1).trim();
|
|
161
|
+
headers[key] = val;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
status,
|
|
167
|
+
body: bodyString,
|
|
168
|
+
headers,
|
|
169
|
+
json: () => {
|
|
170
|
+
if (!bodyString)
|
|
171
|
+
return null;
|
|
172
|
+
return JSON.parse(bodyString);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
} finally {
|
|
176
|
+
lib.symbols.zclient_response_free(respPtr);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
export {
|
|
181
|
+
JirenClient
|
|
182
|
+
};
|
package/package.json
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jiren",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"author": "",
|
|
5
|
-
"main": "index.
|
|
6
|
-
"module": "index.
|
|
7
|
-
"types": "index.ts",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "types/index.ts",
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"@types/bun": "^1.3.4"
|
|
9
|
+
"@types/bun": "^1.3.4",
|
|
10
|
+
"bun-types": "^1.3.4"
|
|
10
11
|
},
|
|
11
12
|
"peerDependencies": {
|
|
12
13
|
"typescript": "^5"
|
|
13
14
|
},
|
|
14
15
|
"description": "Jiren is a high-performance HTTP/HTTPS client, Faster than any other HTTP/HTTPS client.",
|
|
15
16
|
"files": [
|
|
16
|
-
"
|
|
17
|
-
"types",
|
|
17
|
+
"dist",
|
|
18
18
|
"lib",
|
|
19
|
-
"components"
|
|
19
|
+
"components",
|
|
20
|
+
"types"
|
|
20
21
|
],
|
|
21
22
|
"keywords": [
|
|
22
23
|
"http",
|
|
@@ -33,6 +34,8 @@
|
|
|
33
34
|
"license": "MIT",
|
|
34
35
|
"scripts": {
|
|
35
36
|
"build:zig": "cd .. && zig build --release=fast",
|
|
37
|
+
"build": "bun build ./index.ts --outdir dist --target bun",
|
|
38
|
+
"prepare": "bun run build",
|
|
36
39
|
"test": "bun run examples/basic.ts"
|
|
37
40
|
},
|
|
38
41
|
"engines": {
|
package/index.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* jiren - Ultra-fast HTTP/HTTPS client powered by native Zig
|
|
3
|
-
*
|
|
4
|
-
* Faster than any other HTTP/HTTPS client | 1.5M+ requests/sec
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```typescript
|
|
8
|
-
* import { JirenClient } from 'jiren';
|
|
9
|
-
*
|
|
10
|
-
* const client = new JirenClient();
|
|
11
|
-
*
|
|
12
|
-
* // High-performance batch requests
|
|
13
|
-
* const result = client.batch('http://localhost:3000/', {
|
|
14
|
-
* count: 10000,
|
|
15
|
-
* threads: 100
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* console.log(`Success: ${result.success}/${result.total}`);
|
|
19
|
-
* console.log(`Speed: ${result.requestsPerSecond.toFixed(0)} req/sec`);
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* @packageDocumentation
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
// Main client
|
|
26
|
-
export { JirenClient } from "./components";
|
|
27
|
-
|
|
28
|
-
// Types
|
|
29
|
-
export * from "./types";
|