jiren 1.0.11 → 1.0.13

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
@@ -1,5 +1,7 @@
1
1
  # jiren
2
2
 
3
+ > **⚠️ BUN ONLY**: This package requires [Bun](https://bun.sh) runtime. Node.js is not supported.
4
+
3
5
  Ultra-fast HTTP/HTTPS client.
4
6
  Designed to be significantly faster than `fetch` and other Node/Bun HTTP clients.
5
7
 
@@ -1,4 +1,5 @@
1
- import { lib, readCString } from "./native";
1
+ import { CString, type Pointer } from "bun:ffi";
2
+ import { lib } from "./native";
2
3
  import type {
3
4
  RequestOptions,
4
5
  GetRequestOptions,
@@ -6,10 +7,8 @@ import type {
6
7
  HttpResponse,
7
8
  } from "../types";
8
9
 
9
- // Runtime-agnostic pointer type
10
- type Pointer = any;
11
10
  export class JirenClient {
12
- private ptr: unknown | null;
11
+ private ptr: Pointer | null;
13
12
 
14
13
  constructor() {
15
14
  this.ptr = lib.symbols.zclient_new();
@@ -22,7 +21,7 @@ export class JirenClient {
22
21
  */
23
22
  public close(): void {
24
23
  if (this.ptr) {
25
- lib.symbols.zclient_free(this.ptr as Pointer);
24
+ lib.symbols.zclient_free(this.ptr);
26
25
  this.ptr = null;
27
26
  }
28
27
  }
@@ -60,7 +59,7 @@ export class JirenClient {
60
59
  }
61
60
 
62
61
  const respPtr = lib.symbols.zclient_request(
63
- this.ptr as Pointer,
62
+ this.ptr,
64
63
  methodBuffer,
65
64
  urlBuffer,
66
65
  headersBuffer,
@@ -133,7 +132,7 @@ export class JirenClient {
133
132
 
134
133
  for (const url of urls) {
135
134
  const urlBuffer = Buffer.from(url + "\0");
136
- lib.symbols.zclient_prefetch(this.ptr as Pointer, urlBuffer);
135
+ lib.symbols.zclient_prefetch(this.ptr, urlBuffer);
137
136
  }
138
137
  }
139
138
 
@@ -152,12 +151,15 @@ export class JirenClient {
152
151
 
153
152
  let bodyString = "";
154
153
  if (bodyLen > 0 && bodyPtr) {
155
- bodyString = readCString(bodyPtr);
154
+ // CString uses the full length if not null-terminated or we can just read the ptr
155
+ // Since we know the length, we can be more precise, but CString assumes null-terminated
156
+ // for now we trust it is null terminated from Zig
157
+ bodyString = new CString(bodyPtr).toString();
156
158
  }
157
159
 
158
160
  const headers: Record<string, string> = {};
159
161
  if (headersLen > 0 && headersPtr) {
160
- const headersStr = readCString(headersPtr);
162
+ const headersStr = new CString(headersPtr).toString();
161
163
  const lines = headersStr.split("\r\n");
162
164
  for (const line of lines) {
163
165
  if (!line) continue;
@@ -174,10 +176,6 @@ export class JirenClient {
174
176
  status,
175
177
  body: bodyString,
176
178
  headers,
177
- get ok() {
178
- return status >= 200 && status < 300;
179
- },
180
- text: async () => bodyString,
181
179
  json: <T = any>() => {
182
180
  if (!bodyString) return null as T;
183
181
  return JSON.parse(bodyString) as T;
@@ -1,182 +1,64 @@
1
- import { isBun } from "./runtime";
2
- import { join, dirname } from "path";
3
- import { fileURLToPath } from "url";
1
+ import { dlopen, FFIType, suffix } from "bun:ffi";
2
+ import { join } from "path";
4
3
 
5
- // Helper to get library path
6
- function getLibPath(): string {
7
- const platform = process.platform;
8
- const ext =
9
- platform === "darwin" ? "dylib" : platform === "win32" ? "dll" : "so";
4
+ // Resolve library path relative to this module
5
+ const libPath = join(import.meta.dir, `../lib/libhttpclient.${suffix}`);
10
6
 
11
- if (isBun) {
12
- // @ts-ignore - Bun-specific
13
- return join(import.meta.dir, `../lib/libhttpclient.${ext}`);
14
- } else {
15
- // Node.js
16
- const __filename = fileURLToPath(import.meta.url);
17
- const __dirname = dirname(__filename);
18
- return join(__dirname, `../lib/libhttpclient.${ext}`);
19
- }
20
- }
7
+ export const ffiDef = {
8
+ zclient_new: {
9
+ args: [],
10
+ returns: FFIType.ptr,
11
+ },
12
+ zclient_free: {
13
+ args: [FFIType.ptr],
14
+ returns: FFIType.void,
15
+ },
16
+ zclient_get: {
17
+ args: [FFIType.ptr, FFIType.cstring],
18
+ returns: FFIType.ptr,
19
+ },
20
+ zclient_post: {
21
+ args: [FFIType.ptr, FFIType.cstring, FFIType.cstring],
22
+ returns: FFIType.ptr,
23
+ },
24
+ zclient_prefetch: {
25
+ args: [FFIType.ptr, FFIType.cstring],
26
+ returns: FFIType.void,
27
+ },
28
+ zclient_response_status: {
29
+ args: [FFIType.ptr],
30
+ returns: FFIType.u16,
31
+ },
32
+ zclient_response_body: {
33
+ args: [FFIType.ptr],
34
+ returns: FFIType.ptr,
35
+ },
36
+ zclient_response_body_len: {
37
+ args: [FFIType.ptr],
38
+ returns: FFIType.u64,
39
+ },
40
+ zclient_response_headers: {
41
+ args: [FFIType.ptr],
42
+ returns: FFIType.ptr,
43
+ },
44
+ zclient_response_headers_len: {
45
+ args: [FFIType.ptr],
46
+ returns: FFIType.u64,
47
+ },
48
+ zclient_response_free: {
49
+ args: [FFIType.ptr],
50
+ returns: FFIType.void,
51
+ },
52
+ zclient_request: {
53
+ args: [
54
+ FFIType.ptr, // client
55
+ FFIType.cstring, // method
56
+ FFIType.cstring, // url
57
+ FFIType.cstring, // headers (nullable)
58
+ FFIType.cstring, // body (nullable)
59
+ ],
60
+ returns: FFIType.ptr,
61
+ },
62
+ } as const;
21
63
 
22
- // Type definitions for our FFI symbols
23
- export type NativeLib = {
24
- symbols: {
25
- zclient_new: () => any;
26
- zclient_free: (ptr: any) => void;
27
- zclient_get: (client: any, url: any) => any;
28
- zclient_post: (client: any, url: any, body: any) => any;
29
- zclient_prefetch: (client: any, url: any) => void;
30
- zclient_response_status: (resp: any) => number;
31
- zclient_response_body: (resp: any) => any;
32
- zclient_response_body_len: (resp: any) => bigint | number;
33
- zclient_response_headers: (resp: any) => any;
34
- zclient_response_headers_len: (resp: any) => bigint | number;
35
- zclient_response_free: (resp: any) => void;
36
- zclient_request: (
37
- client: any,
38
- method: any,
39
- url: any,
40
- headers: any,
41
- body: any
42
- ) => any;
43
- };
44
- };
45
-
46
- // Load the appropriate FFI library
47
- async function loadLibrary(): Promise<NativeLib> {
48
- const libPath = getLibPath();
49
-
50
- if (isBun) {
51
- // Use Bun FFI
52
- const { dlopen, FFIType } = await import("bun:ffi");
53
-
54
- const ffiDef = {
55
- zclient_new: { args: [], returns: FFIType.ptr },
56
- zclient_free: { args: [FFIType.ptr], returns: FFIType.void },
57
- zclient_get: {
58
- args: [FFIType.ptr, FFIType.cstring],
59
- returns: FFIType.ptr,
60
- },
61
- zclient_post: {
62
- args: [FFIType.ptr, FFIType.cstring, FFIType.cstring],
63
- returns: FFIType.ptr,
64
- },
65
- zclient_prefetch: {
66
- args: [FFIType.ptr, FFIType.cstring],
67
- returns: FFIType.void,
68
- },
69
- zclient_response_status: { args: [FFIType.ptr], returns: FFIType.u16 },
70
- zclient_response_body: { args: [FFIType.ptr], returns: FFIType.ptr },
71
- zclient_response_body_len: { args: [FFIType.ptr], returns: FFIType.u64 },
72
- zclient_response_headers: { args: [FFIType.ptr], returns: FFIType.ptr },
73
- zclient_response_headers_len: {
74
- args: [FFIType.ptr],
75
- returns: FFIType.u64,
76
- },
77
- zclient_response_free: { args: [FFIType.ptr], returns: FFIType.void },
78
- zclient_request: {
79
- args: [
80
- FFIType.ptr,
81
- FFIType.cstring,
82
- FFIType.cstring,
83
- FFIType.cstring,
84
- FFIType.cstring,
85
- ],
86
- returns: FFIType.ptr,
87
- },
88
- };
89
-
90
- return dlopen(libPath, ffiDef) as NativeLib;
91
- } else {
92
- // Use koffi for Node.js
93
- const koffi = await import("koffi");
94
-
95
- const nativeLib = koffi.load(libPath);
96
-
97
- return {
98
- symbols: {
99
- zclient_new: nativeLib.func("zclient_new", "void*", []),
100
- zclient_free: nativeLib.func("zclient_free", "void", ["void*"]),
101
- zclient_get: nativeLib.func("zclient_get", "void*", ["void*", "str"]),
102
- zclient_post: nativeLib.func("zclient_post", "void*", [
103
- "void*",
104
- "str",
105
- "str",
106
- ]),
107
- zclient_prefetch: nativeLib.func("zclient_prefetch", "void", [
108
- "void*",
109
- "str",
110
- ]),
111
- zclient_response_status: nativeLib.func(
112
- "zclient_response_status",
113
- "uint16",
114
- ["void*"]
115
- ),
116
- zclient_response_body: nativeLib.func(
117
- "zclient_response_body",
118
- "void*",
119
- ["void*"]
120
- ),
121
- zclient_response_body_len: nativeLib.func(
122
- "zclient_response_body_len",
123
- "uint64",
124
- ["void*"]
125
- ),
126
- zclient_response_headers: nativeLib.func(
127
- "zclient_response_headers",
128
- "void*",
129
- ["void*"]
130
- ),
131
- zclient_response_headers_len: nativeLib.func(
132
- "zclient_response_headers_len",
133
- "uint64",
134
- ["void*"]
135
- ),
136
- zclient_response_free: nativeLib.func("zclient_response_free", "void", [
137
- "void*",
138
- ]),
139
- zclient_request: nativeLib.func("zclient_request", "void*", [
140
- "void*",
141
- "str",
142
- "str",
143
- "str",
144
- "str",
145
- ]),
146
- },
147
- };
148
- }
149
- }
150
-
151
- // Export the loaded library (initialized on first import)
152
- export const lib: NativeLib = await loadLibrary();
153
-
154
- // Helper to read C string from pointer (runtime-agnostic)
155
- export function readCString(ptr: any): string {
156
- if (!ptr) return "";
157
-
158
- if (isBun) {
159
- // For Bun, we need to dynamically get CString
160
- // Use a simple approach: read bytes until null terminator
161
- const view = new DataView(new ArrayBuffer(0));
162
- try {
163
- // In Bun, pointers can be read as buffers
164
- // @ts-ignore - Bun specific
165
- const buf = Buffer.from(ptr as any);
166
- const nullIdx = buf.indexOf(0);
167
- return buf.toString("utf8", 0, nullIdx >= 0 ? nullIdx : undefined);
168
- } catch {
169
- // Fallback: try to read as string directly
170
- return String(ptr);
171
- }
172
- } else {
173
- // Node.js with koffi
174
- try {
175
- const koffi = require("koffi");
176
- return koffi.decode(ptr, "string");
177
- } catch (e) {
178
- console.error("Failed to decode C string:", e);
179
- return "";
180
- }
181
- }
182
- }
64
+ export const lib = dlopen(libPath, ffiDef);
@@ -21,7 +21,9 @@
21
21
  *
22
22
  * @packageDocumentation
23
23
  */
24
+
24
25
  // Main client
25
26
  export { JirenClient } from "./components";
27
+
26
28
  // Types
27
29
  export * from "./types";
Binary file
package/package.json CHANGED
@@ -1,16 +1,11 @@
1
1
  {
2
2
  "name": "jiren",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "author": "",
5
- "main": "index.js",
6
- "module": "index.js",
7
- "types": "index.d.ts",
8
- "dependencies": {},
9
- "optionalDependencies": {
10
- "koffi": "^2.9.0"
11
- },
5
+ "main": "index.ts",
6
+ "module": "index.ts",
7
+ "types": "index.ts",
12
8
  "devDependencies": {
13
- "typescript": "^5",
14
9
  "@types/bun": "^1.3.4"
15
10
  },
16
11
  "peerDependencies": {
@@ -18,8 +13,7 @@
18
13
  },
19
14
  "description": "Jiren is a high-performance HTTP/HTTPS client, Faster than any other HTTP/HTTPS client.",
20
15
  "files": [
21
- "index.js",
22
- "index.d.ts",
16
+ "index.ts",
23
17
  "types",
24
18
  "lib",
25
19
  "components"
@@ -38,13 +32,10 @@
38
32
  ],
39
33
  "license": "MIT",
40
34
  "scripts": {
41
- "build": "tsc",
42
35
  "build:zig": "cd .. && zig build --release=fast",
43
- "test": "bun run examples/basic.ts",
44
- "prepublishOnly": "npm run build"
36
+ "test": "bun run examples/basic.ts"
45
37
  },
46
38
  "engines": {
47
- "node": ">=18.0.0",
48
39
  "bun": ">=1.1.0"
49
40
  },
50
41
  "type": "module"
package/types/index.ts CHANGED
@@ -52,10 +52,6 @@ export interface HttpResponse {
52
52
  body: string;
53
53
  /** Response headers */
54
54
  headers?: Record<string, string>;
55
- /** True if status is 2xx */
56
- ok: boolean;
57
- /** Helper to get body as string (Promise for Fetch compatibility) */
58
- text: () => Promise<string>;
59
55
  /** Helper to parse JSON body */
60
56
  json: <T = any>() => T;
61
57
  }
@@ -1,29 +0,0 @@
1
- import type { RequestOptions, GetRequestOptions, PostRequestOptions, HttpResponse } from "../types";
2
- export declare class JirenClient {
3
- private ptr;
4
- constructor();
5
- /**
6
- * Free the native client resources.
7
- * Must be called when the client is no longer needed.
8
- */
9
- close(): void;
10
- /**
11
- * Perform a HTTP request.
12
- * @param url - The URL to request
13
- * @param options - Request options (method, headers, body)
14
- * @returns Response object
15
- */
16
- request(url: string, options?: RequestOptions): HttpResponse;
17
- get(url: string, options?: GetRequestOptions): HttpResponse;
18
- post(url: string, body: string | object, options?: PostRequestOptions): HttpResponse;
19
- put(url: string, body: string | object, options?: PostRequestOptions): HttpResponse;
20
- delete(url: string, options?: GetRequestOptions): HttpResponse;
21
- patch(url: string, body: string | object, options?: PostRequestOptions): HttpResponse;
22
- head(url: string, options?: GetRequestOptions): HttpResponse;
23
- /**
24
- * Prefetch URLs to warm up connections (resolve DNS & Handshake).
25
- * @param urls - List of URLs to prefetch
26
- */
27
- prefetch(urls: string[]): void;
28
- private parseResponse;
29
- }
@@ -1,140 +0,0 @@
1
- import { lib, readCString } from "./native";
2
- export class JirenClient {
3
- ptr;
4
- constructor() {
5
- this.ptr = lib.symbols.zclient_new();
6
- if (!this.ptr)
7
- throw new Error("Failed to create native client instance");
8
- }
9
- /**
10
- * Free the native client resources.
11
- * Must be called when the client is no longer needed.
12
- */
13
- close() {
14
- if (this.ptr) {
15
- lib.symbols.zclient_free(this.ptr);
16
- this.ptr = null;
17
- }
18
- }
19
- /**
20
- * Perform a HTTP request.
21
- * @param url - The URL to request
22
- * @param options - Request options (method, headers, body)
23
- * @returns Response object
24
- */
25
- request(url, options = {}) {
26
- if (!this.ptr)
27
- throw new Error("Client is closed");
28
- const method = options.method || "GET";
29
- const methodBuffer = Buffer.from(method + "\0");
30
- const urlBuffer = Buffer.from(url + "\0");
31
- let headersBuffer = null;
32
- if (options.headers) {
33
- const headerStr = Object.entries(options.headers)
34
- .map(([k, v]) => `${k.toLowerCase()}: ${v}`)
35
- .join("\r\n");
36
- if (headerStr.length > 0) {
37
- headersBuffer = Buffer.from(headerStr + "\0");
38
- }
39
- }
40
- let bodyBuffer = null;
41
- if (options.body) {
42
- const bodyStr = typeof options.body === "string"
43
- ? options.body
44
- : JSON.stringify(options.body);
45
- bodyBuffer = Buffer.from(bodyStr + "\0");
46
- }
47
- const respPtr = lib.symbols.zclient_request(this.ptr, methodBuffer, urlBuffer, headersBuffer, bodyBuffer);
48
- const response = this.parseResponse(respPtr);
49
- // Handle Redirects
50
- if (options.maxRedirects &&
51
- options.maxRedirects > 0 &&
52
- response.status >= 300 &&
53
- response.status < 400 &&
54
- response.headers &&
55
- response.headers["location"]) {
56
- const location = response.headers["location"];
57
- const newUrl = new URL(location, url).toString(); // Resolve relative URLs
58
- const newOptions = { ...options, maxRedirects: options.maxRedirects - 1 };
59
- return this.request(newUrl, newOptions);
60
- }
61
- return response;
62
- }
63
- get(url, options = {}) {
64
- return this.request(url, { ...options, method: "GET" });
65
- }
66
- post(url, body, options = {}) {
67
- return this.request(url, { ...options, method: "POST", body });
68
- }
69
- put(url, body, options = {}) {
70
- return this.request(url, { ...options, method: "PUT", body });
71
- }
72
- delete(url, options = {}) {
73
- return this.request(url, { ...options, method: "DELETE" });
74
- }
75
- patch(url, body, options = {}) {
76
- return this.request(url, { ...options, method: "PATCH", body });
77
- }
78
- head(url, options = {}) {
79
- return this.request(url, { ...options, method: "HEAD" });
80
- }
81
- /**
82
- * Prefetch URLs to warm up connections (resolve DNS & Handshake).
83
- * @param urls - List of URLs to prefetch
84
- */
85
- prefetch(urls) {
86
- if (!this.ptr)
87
- throw new Error("Client is closed");
88
- for (const url of urls) {
89
- const urlBuffer = Buffer.from(url + "\0");
90
- lib.symbols.zclient_prefetch(this.ptr, urlBuffer);
91
- }
92
- }
93
- parseResponse(respPtr) {
94
- if (!respPtr)
95
- throw new Error("Native request failed (returned null pointer)");
96
- try {
97
- const status = lib.symbols.zclient_response_status(respPtr);
98
- const bodyLen = Number(lib.symbols.zclient_response_body_len(respPtr));
99
- const bodyPtr = lib.symbols.zclient_response_body(respPtr);
100
- const headersLen = Number(lib.symbols.zclient_response_headers_len(respPtr));
101
- const headersPtr = lib.symbols.zclient_response_headers(respPtr);
102
- let bodyString = "";
103
- if (bodyLen > 0 && bodyPtr) {
104
- bodyString = readCString(bodyPtr);
105
- }
106
- const headers = {};
107
- if (headersLen > 0 && headersPtr) {
108
- const headersStr = readCString(headersPtr);
109
- const lines = headersStr.split("\r\n");
110
- for (const line of lines) {
111
- if (!line)
112
- continue;
113
- const colonIdx = line.indexOf(":");
114
- if (colonIdx !== -1) {
115
- const key = line.substring(0, colonIdx).trim().toLowerCase();
116
- const val = line.substring(colonIdx + 1).trim();
117
- headers[key] = val;
118
- }
119
- }
120
- }
121
- return {
122
- status,
123
- body: bodyString,
124
- headers,
125
- get ok() {
126
- return status >= 200 && status < 300;
127
- },
128
- text: async () => bodyString,
129
- json: () => {
130
- if (!bodyString)
131
- return null;
132
- return JSON.parse(bodyString);
133
- },
134
- };
135
- }
136
- finally {
137
- lib.symbols.zclient_response_free(respPtr);
138
- }
139
- }
140
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * flous - Ultra-fast HTTP/HTTPS client powered by native Zig
3
- *
4
- * @packageDocumentation
5
- */
6
- export { JirenClient } from "./client";
7
- export type { JirenHttpConfig, ParsedUrl } from "../types/index";
@@ -1,8 +0,0 @@
1
- /**
2
- * flous - Ultra-fast HTTP/HTTPS client powered by native Zig
3
- *
4
- * @packageDocumentation
5
- */
6
- // Main client
7
- export { JirenClient } from "./client";
8
- // Remove broken exports
@@ -1,18 +0,0 @@
1
- export type NativeLib = {
2
- symbols: {
3
- zclient_new: () => any;
4
- zclient_free: (ptr: any) => void;
5
- zclient_get: (client: any, url: any) => any;
6
- zclient_post: (client: any, url: any, body: any) => any;
7
- zclient_prefetch: (client: any, url: any) => void;
8
- zclient_response_status: (resp: any) => number;
9
- zclient_response_body: (resp: any) => any;
10
- zclient_response_body_len: (resp: any) => bigint | number;
11
- zclient_response_headers: (resp: any) => any;
12
- zclient_response_headers_len: (resp: any) => bigint | number;
13
- zclient_response_free: (resp: any) => void;
14
- zclient_request: (client: any, method: any, url: any, headers: any, body: any) => any;
15
- };
16
- };
17
- export declare const lib: NativeLib;
18
- export declare function readCString(ptr: any): string;
@@ -1,132 +0,0 @@
1
- import { isBun } from "./runtime";
2
- import { join, dirname } from "path";
3
- import { fileURLToPath } from "url";
4
- // Helper to get library path
5
- function getLibPath() {
6
- const platform = process.platform;
7
- const ext = platform === "darwin" ? "dylib" : platform === "win32" ? "dll" : "so";
8
- if (isBun) {
9
- // @ts-ignore - Bun-specific
10
- return join(import.meta.dir, `../lib/libhttpclient.${ext}`);
11
- }
12
- else {
13
- // Node.js
14
- const __filename = fileURLToPath(import.meta.url);
15
- const __dirname = dirname(__filename);
16
- return join(__dirname, `../lib/libhttpclient.${ext}`);
17
- }
18
- }
19
- // Load the appropriate FFI library
20
- async function loadLibrary() {
21
- const libPath = getLibPath();
22
- if (isBun) {
23
- // Use Bun FFI
24
- const { dlopen, FFIType } = await import("bun:ffi");
25
- const ffiDef = {
26
- zclient_new: { args: [], returns: FFIType.ptr },
27
- zclient_free: { args: [FFIType.ptr], returns: FFIType.void },
28
- zclient_get: {
29
- args: [FFIType.ptr, FFIType.cstring],
30
- returns: FFIType.ptr,
31
- },
32
- zclient_post: {
33
- args: [FFIType.ptr, FFIType.cstring, FFIType.cstring],
34
- returns: FFIType.ptr,
35
- },
36
- zclient_prefetch: {
37
- args: [FFIType.ptr, FFIType.cstring],
38
- returns: FFIType.void,
39
- },
40
- zclient_response_status: { args: [FFIType.ptr], returns: FFIType.u16 },
41
- zclient_response_body: { args: [FFIType.ptr], returns: FFIType.ptr },
42
- zclient_response_body_len: { args: [FFIType.ptr], returns: FFIType.u64 },
43
- zclient_response_headers: { args: [FFIType.ptr], returns: FFIType.ptr },
44
- zclient_response_headers_len: {
45
- args: [FFIType.ptr],
46
- returns: FFIType.u64,
47
- },
48
- zclient_response_free: { args: [FFIType.ptr], returns: FFIType.void },
49
- zclient_request: {
50
- args: [
51
- FFIType.ptr,
52
- FFIType.cstring,
53
- FFIType.cstring,
54
- FFIType.cstring,
55
- FFIType.cstring,
56
- ],
57
- returns: FFIType.ptr,
58
- },
59
- };
60
- return dlopen(libPath, ffiDef);
61
- }
62
- else {
63
- // Use koffi for Node.js
64
- const koffi = await import("koffi");
65
- const nativeLib = koffi.load(libPath);
66
- return {
67
- symbols: {
68
- zclient_new: nativeLib.func("zclient_new", "void*", []),
69
- zclient_free: nativeLib.func("zclient_free", "void", ["void*"]),
70
- zclient_get: nativeLib.func("zclient_get", "void*", ["void*", "str"]),
71
- zclient_post: nativeLib.func("zclient_post", "void*", [
72
- "void*",
73
- "str",
74
- "str",
75
- ]),
76
- zclient_prefetch: nativeLib.func("zclient_prefetch", "void", [
77
- "void*",
78
- "str",
79
- ]),
80
- zclient_response_status: nativeLib.func("zclient_response_status", "uint16", ["void*"]),
81
- zclient_response_body: nativeLib.func("zclient_response_body", "void*", ["void*"]),
82
- zclient_response_body_len: nativeLib.func("zclient_response_body_len", "uint64", ["void*"]),
83
- zclient_response_headers: nativeLib.func("zclient_response_headers", "void*", ["void*"]),
84
- zclient_response_headers_len: nativeLib.func("zclient_response_headers_len", "uint64", ["void*"]),
85
- zclient_response_free: nativeLib.func("zclient_response_free", "void", [
86
- "void*",
87
- ]),
88
- zclient_request: nativeLib.func("zclient_request", "void*", [
89
- "void*",
90
- "str",
91
- "str",
92
- "str",
93
- "str",
94
- ]),
95
- },
96
- };
97
- }
98
- }
99
- // Export the loaded library (initialized on first import)
100
- export const lib = await loadLibrary();
101
- // Helper to read C string from pointer (runtime-agnostic)
102
- export function readCString(ptr) {
103
- if (!ptr)
104
- return "";
105
- if (isBun) {
106
- // For Bun, we need to dynamically get CString
107
- // Use a simple approach: read bytes until null terminator
108
- const view = new DataView(new ArrayBuffer(0));
109
- try {
110
- // In Bun, pointers can be read as buffers
111
- // @ts-ignore - Bun specific
112
- const buf = Buffer.from(ptr);
113
- const nullIdx = buf.indexOf(0);
114
- return buf.toString("utf8", 0, nullIdx >= 0 ? nullIdx : undefined);
115
- }
116
- catch {
117
- // Fallback: try to read as string directly
118
- return String(ptr);
119
- }
120
- }
121
- else {
122
- // Node.js with koffi
123
- try {
124
- const koffi = require("koffi");
125
- return koffi.decode(ptr, "string");
126
- }
127
- catch (e) {
128
- console.error("Failed to decode C string:", e);
129
- return "";
130
- }
131
- }
132
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Runtime detection utility for Jiren
3
- * Detects whether we're running in Bun or Node.js
4
- */
5
- export declare const isBun: boolean;
6
- export declare const isNode: string | false;
7
- export declare function getRuntime(): "bun" | "node" | "unknown";
@@ -1,16 +0,0 @@
1
- /**
2
- * Runtime detection utility for Jiren
3
- * Detects whether we're running in Bun or Node.js
4
- */
5
- export const isBun = typeof Bun !== "undefined";
6
- export const isNode = !isBun &&
7
- typeof process !== "undefined" &&
8
- process.versions &&
9
- process.versions.node;
10
- export function getRuntime() {
11
- if (isBun)
12
- return "bun";
13
- if (isNode)
14
- return "node";
15
- return "unknown";
16
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Runtime detection utility for Jiren
3
- * Detects whether we're running in Bun or Node.js
4
- */
5
-
6
- export const isBun = typeof Bun !== "undefined";
7
- export const isNode =
8
- !isBun &&
9
- typeof process !== "undefined" &&
10
- process.versions &&
11
- process.versions.node;
12
-
13
- export function getRuntime(): "bun" | "node" | "unknown" {
14
- if (isBun) return "bun";
15
- if (isNode) return "node";
16
- return "unknown";
17
- }
@@ -1,55 +0,0 @@
1
- /**
2
- * pow - Ultra-fast HTTP/HTTPS client powered by native Zigr than any other HTTP/HTTPS client
3
- */
4
- /** Options for batch HTTP requests */
5
- export interface BatchOptions {
6
- /** Number of requests to send (default: 1000) */
7
- count?: number;
8
- /** Number of concurrent threads (default: 100) */
9
- threads?: number;
10
- }
11
- /** Result of a batch request operation */
12
- export interface BatchResult {
13
- /** Number of successful requests */
14
- success: number;
15
- /** Total requests attempted */
16
- total: number;
17
- /** Duration in seconds */
18
- duration: number;
19
- /** Requests per second */
20
- requestsPerSecond: number;
21
- }
22
- /** Options for single HTTP requests */
23
- export interface RequestOptions {
24
- /** HTTP method (default: GET) */
25
- method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD";
26
- /** Request headers */
27
- headers?: Record<string, string>;
28
- /** Request body (for POST, PUT, PATCH) */
29
- body?: string | object;
30
- /** Request timeout in milliseconds */
31
- timeout?: number;
32
- }
33
- /** HTTP Response */
34
- export interface HttpResponse {
35
- /** HTTP status code */
36
- status: number;
37
- /** Response body as string */
38
- body: string;
39
- /** Response headers */
40
- headers?: Record<string, string>;
41
- }
42
- /** Configuration for JirenHttpClient */
43
- export interface JirenHttpConfig {
44
- /** Default number of threads for batch operations */
45
- defaultThreads?: number;
46
- /** Base URL prefix for all requests */
47
- baseUrl?: string;
48
- }
49
- /** Parsed URL components */
50
- export interface ParsedUrl {
51
- protocol: "http" | "https";
52
- host: string;
53
- port: number;
54
- path: string;
55
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * pow - Ultra-fast HTTP/HTTPS client powered by native Zigr than any other HTTP/HTTPS client
3
- */
4
- export {};
package/index.d.ts DELETED
@@ -1,25 +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
- export { JirenClient } from "./components";
25
- export * from "./types";
package/types/index.d.ts DELETED
@@ -1,69 +0,0 @@
1
- /**
2
- * jiren - Ultra-fast HTTP/HTTPS Client Types
3
- * 56% faster than llhttp
4
- */
5
- /** Options for batch HTTP requests */
6
- export interface BatchOptions {
7
- /** Number of requests to send (default: 1000) */
8
- count?: number;
9
- /** Number of concurrent threads (default: 100) */
10
- threads?: number;
11
- }
12
- /** Result of a batch request operation */
13
- export interface BatchResult {
14
- /** Number of successful requests */
15
- success: number;
16
- /** Total requests attempted */
17
- total: number;
18
- /** Duration in seconds */
19
- duration: number;
20
- /** Requests per second */
21
- requestsPerSecond: number;
22
- }
23
- /** Options for single HTTP requests */
24
- /** Options for single HTTP requests */
25
- export interface RequestOptions {
26
- /** HTTP method (default: GET) */
27
- method?: string;
28
- /** Request headers */
29
- headers?: Record<string, string>;
30
- /** Request body (for POST, PUT, PATCH) */
31
- body?: string | object;
32
- /** Request timeout in milliseconds */
33
- timeout?: number;
34
- /** Maximum number of redirects to follow (default: 0) */
35
- maxRedirects?: number;
36
- }
37
- /** Options for requests without a body (GET, DELETE, HEAD) */
38
- export type GetRequestOptions = Omit<RequestOptions, "method" | "body">;
39
- /** Options for requests with a body (POST, PUT, PATCH) where body is a separate argument */
40
- export type PostRequestOptions = Omit<RequestOptions, "method" | "body">;
41
- /** HTTP Response */
42
- export interface HttpResponse {
43
- /** HTTP status code */
44
- status: number;
45
- /** Response body as string */
46
- body: string;
47
- /** Response headers */
48
- headers?: Record<string, string>;
49
- /** True if status is 2xx */
50
- ok: boolean;
51
- /** Helper to get body as string (Promise for Fetch compatibility) */
52
- text: () => Promise<string>;
53
- /** Helper to parse JSON body */
54
- json: <T = any>() => T;
55
- }
56
- /** Configuration for JirenHttpClient */
57
- export interface JirenHttpConfig {
58
- /** Default number of threads for batch operations */
59
- defaultThreads?: number;
60
- /** Base URL prefix for all requests */
61
- baseUrl?: string;
62
- }
63
- /** Parsed URL components */
64
- export interface ParsedUrl {
65
- protocol: "http" | "https";
66
- host: string;
67
- port: number;
68
- path: string;
69
- }
package/types/index.js DELETED
@@ -1,5 +0,0 @@
1
- /**
2
- * jiren - Ultra-fast HTTP/HTTPS Client Types
3
- * 56% faster than llhttp
4
- */
5
- export {};