jiren 3.1.0 → 3.3.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.
Files changed (34) hide show
  1. package/README.md +1 -9
  2. package/components/client-node-native.ts +150 -292
  3. package/components/client.ts +385 -286
  4. package/components/index.ts +0 -2
  5. package/components/native-cache-node.ts +0 -3
  6. package/components/native-cache.ts +0 -8
  7. package/components/native-node.ts +142 -4
  8. package/components/native.ts +33 -65
  9. package/components/types.ts +25 -41
  10. package/dist/components/client-node-native.d.ts +0 -1
  11. package/dist/components/client-node-native.d.ts.map +1 -1
  12. package/dist/components/client-node-native.js +84 -202
  13. package/dist/components/client-node-native.js.map +1 -1
  14. package/dist/components/native-cache-node.d.ts.map +1 -1
  15. package/dist/components/native-cache-node.js +0 -1
  16. package/dist/components/native-cache-node.js.map +1 -1
  17. package/dist/components/native-node.d.ts +78 -0
  18. package/dist/components/native-node.d.ts.map +1 -1
  19. package/dist/components/native-node.js +125 -2
  20. package/dist/components/native-node.js.map +1 -1
  21. package/dist/components/types.d.ts +5 -13
  22. package/dist/components/types.d.ts.map +1 -1
  23. package/lib/libhttpclient.dylib +0 -0
  24. package/package.json +3 -3
  25. package/components/cache.ts +0 -451
  26. package/components/native-json.ts +0 -195
  27. package/components/persistent-worker.ts +0 -67
  28. package/components/subprocess-worker.ts +0 -60
  29. package/components/worker-pool.ts +0 -153
  30. package/components/worker.ts +0 -154
  31. package/dist/components/cache.d.ts +0 -32
  32. package/dist/components/cache.d.ts.map +0 -1
  33. package/dist/components/cache.js +0 -374
  34. package/dist/components/cache.js.map +0 -1
@@ -1,60 +0,0 @@
1
- import { CString, type Pointer } from "bun:ffi";
2
- import { lib } from "./native";
3
-
4
- const decoder = new TextDecoder();
5
- let inputBuffer = "";
6
-
7
- const ptr: Pointer | null = lib.symbols.zclient_new();
8
- if (!ptr) {
9
- console.error(
10
- JSON.stringify({ success: false, error: "Failed to create client" })
11
- );
12
- process.exit(1);
13
- }
14
-
15
- lib.symbols.zclient_set_benchmark_mode(ptr, true);
16
-
17
- const url = process.argv[2];
18
- const method = process.argv[3] || "GET";
19
-
20
- if (!url) {
21
- console.error(JSON.stringify({ success: false, error: "No URL provided" }));
22
- process.exit(1);
23
- }
24
-
25
- try {
26
- const methodBuffer = Buffer.from(method + "\0");
27
- const urlBuffer = Buffer.from(url + "\0");
28
-
29
- const respPtr = lib.symbols.zclient_request_full(
30
- ptr,
31
- methodBuffer,
32
- urlBuffer,
33
- null,
34
- null,
35
- 5,
36
- false
37
- );
38
-
39
- if (!respPtr) throw new Error("Native request failed");
40
-
41
- const status = lib.symbols.zfull_response_status(respPtr);
42
- const bodyLen = Number(lib.symbols.zfull_response_body_len(respPtr));
43
- const bodyPtr = lib.symbols.zfull_response_body(respPtr);
44
-
45
- let bodyString = "";
46
- if (bodyLen > 0 && bodyPtr) {
47
- bodyString = new CString(bodyPtr).toString();
48
- }
49
-
50
- lib.symbols.zclient_response_full_free(respPtr);
51
- lib.symbols.zclient_free(ptr);
52
-
53
- console.log(
54
- JSON.stringify({ success: true, status, bodyLen: bodyString.length })
55
- );
56
- } catch (err: any) {
57
- console.log(JSON.stringify({ success: false, error: err.message }));
58
- lib.symbols.zclient_free(ptr);
59
- process.exit(1);
60
- }
@@ -1,153 +0,0 @@
1
- import { Worker } from "worker_threads";
2
- import { join } from "path";
3
- import type { RequestOptions } from "./types";
4
-
5
- interface WorkerTask {
6
- id: number;
7
- url: string;
8
- options: RequestOptions;
9
- resolve: (value: any) => void;
10
- reject: (error: any) => void;
11
- }
12
-
13
- interface WorkerWrapper {
14
- worker: Worker;
15
- busy: boolean;
16
- taskQueue: WorkerTask[];
17
- }
18
-
19
- export class WorkerPool {
20
- private workers: WorkerWrapper[] = [];
21
- private taskId = 0;
22
- private pendingTasks = new Map<number, WorkerTask>();
23
- private ready: Promise<void>;
24
- private closed = false;
25
-
26
- constructor(poolSize: number = 4) {
27
- const workerPath = join(import.meta.dir, "worker.ts");
28
-
29
- const readyPromises: Promise<void>[] = [];
30
-
31
- for (let i = 0; i < poolSize; i++) {
32
- const worker = new Worker(workerPath);
33
- const wrapper: WorkerWrapper = {
34
- worker,
35
- busy: false,
36
- taskQueue: [],
37
- };
38
-
39
- worker.on("message", (msg: any) => {
40
- if (msg.type === "prefetch_done") {
41
- return;
42
- }
43
-
44
- const task = this.pendingTasks.get(msg.id);
45
- if (task) {
46
- this.pendingTasks.delete(msg.id);
47
- wrapper.busy = false;
48
-
49
- if (msg.success) {
50
- task.resolve(msg.response);
51
- } else {
52
- task.reject(new Error(msg.error));
53
- }
54
-
55
- // Process next task in queue
56
- this.processQueue(wrapper);
57
- }
58
- });
59
-
60
- worker.on("error", (err) => {
61
- console.error("Worker error:", err);
62
- });
63
-
64
- this.workers.push(wrapper);
65
- }
66
-
67
- this.ready = Promise.resolve();
68
- }
69
-
70
- async waitReady(): Promise<void> {
71
- return this.ready;
72
- }
73
-
74
- async request(url: string, options: RequestOptions = {}): Promise<any> {
75
- if (this.closed) {
76
- throw new Error("Worker pool is closed");
77
- }
78
-
79
- return new Promise((resolve, reject) => {
80
- const task: WorkerTask = {
81
- id: this.taskId++,
82
- url,
83
- options,
84
- resolve,
85
- reject,
86
- };
87
-
88
- // Find the least busy worker
89
- if (this.workers.length === 0) {
90
- throw new Error("Worker pool has no workers");
91
- }
92
- let leastBusy = this.workers[0]!;
93
- for (const w of this.workers) {
94
- if (!w.busy && w.taskQueue.length === 0) {
95
- leastBusy = w;
96
- break;
97
- }
98
- if (w.taskQueue.length < leastBusy.taskQueue.length) {
99
- leastBusy = w;
100
- }
101
- }
102
-
103
- leastBusy.taskQueue.push(task);
104
- this.processQueue(leastBusy);
105
- });
106
- }
107
-
108
- private processQueue(wrapper: WorkerWrapper): void {
109
- if (wrapper.busy || wrapper.taskQueue.length === 0) {
110
- return;
111
- }
112
-
113
- const task = wrapper.taskQueue.shift()!;
114
- wrapper.busy = true;
115
- this.pendingTasks.set(task.id, task);
116
-
117
- wrapper.worker.postMessage({
118
- id: task.id,
119
- url: task.url,
120
- options: task.options,
121
- });
122
- }
123
-
124
- async prefetch(urls: string[]): Promise<void> {
125
- const promises = this.workers.map(
126
- (w) =>
127
- new Promise<void>((resolve) => {
128
- const handler = (msg: any) => {
129
- if (msg.type === "prefetch_done") {
130
- w.worker.off("message", handler);
131
- resolve();
132
- }
133
- };
134
- w.worker.on("message", handler);
135
- w.worker.postMessage({ type: "prefetch", url: urls });
136
- })
137
- );
138
- await Promise.all(promises);
139
- }
140
-
141
- async close(): Promise<void> {
142
- this.closed = true;
143
- const closePromises = this.workers.map(
144
- (w) =>
145
- new Promise<void>((resolve) => {
146
- w.worker.once("exit", () => resolve());
147
- w.worker.postMessage({ type: "close" });
148
- })
149
- );
150
- await Promise.all(closePromises);
151
- this.workers = [];
152
- }
153
- }
@@ -1,154 +0,0 @@
1
- import { parentPort } from "worker_threads";
2
- import { CString, type Pointer } from "bun:ffi";
3
- import { lib } from "./native";
4
- import type { RequestOptions } from "./types";
5
-
6
- let ptr: Pointer | null = null;
7
-
8
- function ensureClient(): Pointer {
9
- if (!ptr) {
10
- ptr = lib.symbols.zclient_new();
11
- if (!ptr) {
12
- throw new Error("Failed to create native client instance in worker");
13
- }
14
- lib.symbols.zclient_set_benchmark_mode(ptr, true);
15
- }
16
- return ptr;
17
- }
18
-
19
- process.on("exit", () => {
20
- if (ptr) {
21
- lib.symbols.zclient_free(ptr);
22
- ptr = null;
23
- }
24
- });
25
-
26
- if (parentPort) {
27
- parentPort.on(
28
- "message",
29
- (msg: {
30
- id: number;
31
- url: string;
32
- options: RequestOptions;
33
- type?: string;
34
- }) => {
35
- if (msg.type === "close") {
36
- if (ptr) {
37
- lib.symbols.zclient_free(ptr);
38
- ptr = null;
39
- }
40
- process.exit(0);
41
- return;
42
- }
43
-
44
- if (msg.type === "prefetch") {
45
- try {
46
- const client = ensureClient();
47
- const urls = msg.url as unknown as string[];
48
- for (const url of urls) {
49
- const urlBuffer = Buffer.from(url + "\0");
50
- lib.symbols.zclient_prefetch(client, urlBuffer);
51
- }
52
- parentPort?.postMessage({ type: "prefetch_done" });
53
- } catch (err: any) {
54
- parentPort?.postMessage({
55
- type: "prefetch_done",
56
- error: err.message,
57
- });
58
- }
59
- return;
60
- }
61
-
62
- const { id, url, options } = msg;
63
-
64
- try {
65
- const client = ensureClient();
66
-
67
- const method = options.method || "GET";
68
- const methodBuffer = Buffer.from(method + "\0");
69
- const urlBuffer = Buffer.from(url + "\0");
70
-
71
- let headersBuffer: Buffer | null = null;
72
- if (options.headers) {
73
- const headerStr = Object.entries(options.headers)
74
- .map(([k, v]) => `${k.toLowerCase()}: ${v}`)
75
- .join("\r\n");
76
- if (headerStr.length > 0) {
77
- headersBuffer = Buffer.from(headerStr + "\0");
78
- }
79
- }
80
-
81
- let bodyBuffer: Buffer | null = null;
82
- if (options.body) {
83
- const bodyStr =
84
- typeof options.body === "string"
85
- ? options.body
86
- : JSON.stringify(options.body);
87
- bodyBuffer = Buffer.from(bodyStr + "\0");
88
- }
89
-
90
- const maxRedirects = options.maxRedirects ?? 5;
91
- const antibot = options.antibot ?? false;
92
-
93
- // Use the full request API for complete response
94
- const respPtr = lib.symbols.zclient_request_full(
95
- client,
96
- methodBuffer,
97
- urlBuffer,
98
- headersBuffer,
99
- bodyBuffer,
100
- maxRedirects,
101
- antibot
102
- );
103
-
104
- if (!respPtr) throw new Error("Native request failed");
105
-
106
- const status = lib.symbols.zfull_response_status(respPtr);
107
- const bodyLen = Number(lib.symbols.zfull_response_body_len(respPtr));
108
- const bodyPtr = lib.symbols.zfull_response_body(respPtr);
109
- const headersLen = Number(
110
- lib.symbols.zfull_response_headers_len(respPtr)
111
- );
112
- const headersRawPtr = lib.symbols.zfull_response_headers(respPtr);
113
-
114
- let bodyString = "";
115
- if (bodyLen > 0 && bodyPtr) {
116
- bodyString = new CString(bodyPtr).toString();
117
- }
118
-
119
- const headers: Record<string, string> = {};
120
- if (headersLen > 0 && headersRawPtr) {
121
- const headersStr = new CString(headersRawPtr).toString();
122
- const lines = headersStr.split("\r\n");
123
- for (const line of lines) {
124
- if (!line) continue;
125
- const colonIdx = line.indexOf(":");
126
- if (colonIdx !== -1) {
127
- const key = line.substring(0, colonIdx).trim().toLowerCase();
128
- const val = line.substring(colonIdx + 1).trim();
129
- headers[key] = val;
130
- }
131
- }
132
- }
133
-
134
- lib.symbols.zclient_response_full_free(respPtr);
135
-
136
- parentPort?.postMessage({
137
- id,
138
- success: true,
139
- response: {
140
- status,
141
- body: bodyString,
142
- headers,
143
- },
144
- });
145
- } catch (err: any) {
146
- parentPort?.postMessage({
147
- id,
148
- success: false,
149
- error: err.message,
150
- });
151
- }
152
- }
153
- );
154
- }
@@ -1,32 +0,0 @@
1
- import type { JirenResponse } from "./types.js";
2
- export declare class ResponseCache {
3
- private l1;
4
- private cacheDir;
5
- private maxDiskSize;
6
- constructor(l1Capacity?: number, cacheDir?: string, maxDiskSize?: number);
7
- private generateKey;
8
- private getCacheFilePath;
9
- preloadL1(url: string, path?: string, options?: any): boolean;
10
- get(url: string, path?: string, options?: any): JirenResponse | null;
11
- private getFromDisk;
12
- set(url: string, response: JirenResponse, ttl: number, path?: string, options?: any): void;
13
- private setToDisk;
14
- clear(url?: string): void;
15
- private clearAllDisk;
16
- stats(): {
17
- l1: {
18
- size: number;
19
- capacity: number;
20
- hits: number;
21
- misses: number;
22
- hitRate: string;
23
- };
24
- l2: {
25
- size: number;
26
- maxSize: number;
27
- cacheDir: string;
28
- totalSizeKB: string;
29
- };
30
- };
31
- }
32
- //# sourceMappingURL=cache.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../components/cache.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,aAAa,EAId,MAAM,YAAY,CAAC;AAqLpB,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;gBAEhB,UAAU,SAAM,EAAE,QAAQ,SAAiB,EAAE,WAAW,SAAM;IAW1E,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,gBAAgB;IAIxB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO;IAkB7D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,aAAa,GAAG,IAAI;IAoBpE,OAAO,CAAC,WAAW;IAkDnB,GAAG,CACD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,GAAG,GACZ,IAAI;YAgBO,SAAS;IAuDvB,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAezB,OAAO,CAAC,YAAY;IAapB,KAAK;;;;;;;;;;;;;;;CA6BN"}