jiren 1.3.1 → 1.4.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.
package/dist/index.js DELETED
@@ -1,712 +0,0 @@
1
- // @bun
2
- var __require = import.meta.require;
3
-
4
- // components/client.ts
5
- import { toArrayBuffer } from "bun:ffi";
6
-
7
- // components/native.ts
8
- import { dlopen, FFIType, suffix } from "bun:ffi";
9
- import { join } from "path";
10
- var libPath = join(import.meta.dir, `../lib/libhttpclient.${suffix}`);
11
- var ffiDef = {
12
- zclient_new: {
13
- args: [],
14
- returns: FFIType.ptr
15
- },
16
- zclient_free: {
17
- args: [FFIType.ptr],
18
- returns: FFIType.void
19
- },
20
- zclient_get: {
21
- args: [FFIType.ptr, FFIType.cstring],
22
- returns: FFIType.ptr
23
- },
24
- zclient_post: {
25
- args: [FFIType.ptr, FFIType.cstring, FFIType.cstring],
26
- returns: FFIType.ptr
27
- },
28
- zclient_request: {
29
- args: [
30
- FFIType.ptr,
31
- FFIType.cstring,
32
- FFIType.cstring,
33
- FFIType.cstring,
34
- FFIType.cstring,
35
- FFIType.u8,
36
- FFIType.bool
37
- ],
38
- returns: FFIType.ptr
39
- },
40
- zclient_prefetch: {
41
- args: [FFIType.ptr, FFIType.cstring],
42
- returns: FFIType.void
43
- },
44
- zclient_response_status: {
45
- args: [FFIType.ptr],
46
- returns: FFIType.u16
47
- },
48
- zclient_response_body: {
49
- args: [FFIType.ptr],
50
- returns: FFIType.ptr
51
- },
52
- zclient_response_body_len: {
53
- args: [FFIType.ptr],
54
- returns: FFIType.u64
55
- },
56
- zclient_response_headers: {
57
- args: [FFIType.ptr],
58
- returns: FFIType.ptr
59
- },
60
- zclient_response_headers_len: {
61
- args: [FFIType.ptr],
62
- returns: FFIType.u64
63
- },
64
- zclient_response_parse_header_offsets: {
65
- args: [FFIType.ptr],
66
- returns: FFIType.ptr
67
- },
68
- zclient_header_offsets_free: {
69
- args: [FFIType.ptr],
70
- returns: FFIType.void
71
- },
72
- z_find_header_value: {
73
- args: [FFIType.ptr, FFIType.u64, FFIType.cstring],
74
- returns: FFIType.ptr
75
- },
76
- zclient_header_value_free: {
77
- args: [FFIType.ptr],
78
- returns: FFIType.void
79
- },
80
- zclient_response_free: {
81
- args: [FFIType.ptr],
82
- returns: FFIType.void
83
- },
84
- zclient_set_benchmark_mode: {
85
- args: [FFIType.ptr, FFIType.bool],
86
- returns: FFIType.void
87
- }
88
- };
89
- var lib = dlopen(libPath, ffiDef);
90
-
91
- // components/cache.ts
92
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
93
- import { gzipSync, gunzipSync } from "zlib";
94
- import { createHash } from "crypto";
95
- import { join as join2 } from "path";
96
-
97
- class ResponseCache {
98
- cacheDir;
99
- maxSize;
100
- constructor(maxSize = 100, cacheDir = ".cache/jiren") {
101
- this.maxSize = maxSize;
102
- this.cacheDir = cacheDir;
103
- if (!existsSync(this.cacheDir)) {
104
- mkdirSync(this.cacheDir, { recursive: true });
105
- }
106
- }
107
- generateKey(url, path, options) {
108
- const fullUrl = path ? `${url}${path}` : url;
109
- const method = options?.method || "GET";
110
- const headers = JSON.stringify(options?.headers || {});
111
- const key = `${method}:${fullUrl}:${headers}`;
112
- return createHash("md5").update(key).digest("hex");
113
- }
114
- getCacheFilePath(key) {
115
- return join2(this.cacheDir, `${key}.json.gz`);
116
- }
117
- get(url, path, options) {
118
- const key = this.generateKey(url, path, options);
119
- const filePath = this.getCacheFilePath(key);
120
- if (!existsSync(filePath))
121
- return null;
122
- try {
123
- const compressed = readFileSync(filePath);
124
- const decompressed = gunzipSync(compressed);
125
- const data = decompressed.toString("utf-8");
126
- const entry = JSON.parse(data);
127
- const now = Date.now();
128
- if (now - entry.timestamp > entry.ttl) {
129
- try {
130
- __require("fs").unlinkSync(filePath);
131
- } catch {}
132
- return null;
133
- }
134
- return entry.response;
135
- } catch (error) {
136
- try {
137
- __require("fs").unlinkSync(filePath);
138
- } catch {}
139
- return null;
140
- }
141
- }
142
- set(url, response, ttl, path, options) {
143
- const key = this.generateKey(url, path, options);
144
- const filePath = this.getCacheFilePath(key);
145
- const entry = {
146
- response,
147
- timestamp: Date.now(),
148
- ttl
149
- };
150
- try {
151
- const json = JSON.stringify(entry);
152
- const compressed = gzipSync(json);
153
- writeFileSync(filePath, compressed);
154
- } catch (error) {
155
- console.warn("Failed to write cache:", error);
156
- }
157
- }
158
- clear(url) {
159
- if (url) {
160
- this.clearAll();
161
- } else {
162
- this.clearAll();
163
- }
164
- }
165
- clearAll() {
166
- try {
167
- const fs = __require("fs");
168
- const files = fs.readdirSync(this.cacheDir);
169
- for (const file of files) {
170
- if (file.endsWith(".json.gz")) {
171
- fs.unlinkSync(join2(this.cacheDir, file));
172
- }
173
- }
174
- } catch (error) {}
175
- }
176
- stats() {
177
- try {
178
- const fs = __require("fs");
179
- const files = fs.readdirSync(this.cacheDir);
180
- const cacheFiles = files.filter((f) => f.endsWith(".json.gz"));
181
- let totalSize = 0;
182
- for (const file of cacheFiles) {
183
- const stats = fs.statSync(join2(this.cacheDir, file));
184
- totalSize += stats.size;
185
- }
186
- return {
187
- size: cacheFiles.length,
188
- maxSize: this.maxSize,
189
- cacheDir: this.cacheDir,
190
- totalSizeKB: (totalSize / 1024).toFixed(2)
191
- };
192
- } catch {
193
- return {
194
- size: 0,
195
- maxSize: this.maxSize,
196
- cacheDir: this.cacheDir,
197
- totalSizeKB: "0"
198
- };
199
- }
200
- }
201
- }
202
-
203
- // components/client.ts
204
- var STATUS_TEXT = {
205
- 200: "OK",
206
- 201: "Created",
207
- 204: "No Content",
208
- 301: "Moved Permanently",
209
- 302: "Found",
210
- 400: "Bad Request",
211
- 401: "Unauthorized",
212
- 403: "Forbidden",
213
- 404: "Not Found",
214
- 500: "Internal Server Error",
215
- 502: "Bad Gateway",
216
- 503: "Service Unavailable"
217
- };
218
- class JirenClient {
219
- ptr;
220
- urlMap = new Map;
221
- cacheConfig = new Map;
222
- cache;
223
- inflightRequests = new Map;
224
- globalRetry;
225
- url;
226
- constructor(options) {
227
- this.ptr = lib.symbols.zclient_new();
228
- if (!this.ptr)
229
- throw new Error("Failed to create native client instance");
230
- this.cache = new ResponseCache(100);
231
- if (options?.benchmark) {
232
- lib.symbols.zclient_set_benchmark_mode(this.ptr, true);
233
- }
234
- if (options?.warmup) {
235
- const urls = [];
236
- const warmup = options.warmup;
237
- if (Array.isArray(warmup)) {
238
- for (const item of warmup) {
239
- if (typeof item === "string") {
240
- urls.push(item);
241
- } else {
242
- const config = item;
243
- urls.push(config.url);
244
- this.urlMap.set(config.key, config.url);
245
- if (config.cache) {
246
- const cacheConfig = typeof config.cache === "boolean" ? { enabled: true, ttl: 60000 } : { enabled: true, ttl: config.cache.ttl || 60000 };
247
- this.cacheConfig.set(config.key, cacheConfig);
248
- }
249
- }
250
- }
251
- } else {
252
- for (const [key, urlConfig] of Object.entries(warmup)) {
253
- if (typeof urlConfig === "string") {
254
- urls.push(urlConfig);
255
- this.urlMap.set(key, urlConfig);
256
- } else {
257
- urls.push(urlConfig.url);
258
- this.urlMap.set(key, urlConfig.url);
259
- if (urlConfig.cache) {
260
- const cacheConfig = typeof urlConfig.cache === "boolean" ? { enabled: true, ttl: 60000 } : { enabled: true, ttl: urlConfig.cache.ttl || 60000 };
261
- this.cacheConfig.set(key, cacheConfig);
262
- }
263
- }
264
- }
265
- }
266
- if (urls.length > 0) {
267
- this.warmup(urls);
268
- }
269
- }
270
- this.url = this.createUrlAccessor();
271
- if (options?.retry) {
272
- this.globalRetry = typeof options.retry === "number" ? { count: options.retry, delay: 100, backoff: 2 } : options.retry;
273
- }
274
- }
275
- async waitFor(ms) {
276
- return new Promise((resolve) => setTimeout(resolve, ms));
277
- }
278
- createUrlAccessor() {
279
- const self = this;
280
- return new Proxy({}, {
281
- get(_target, prop) {
282
- const baseUrl = self.urlMap.get(prop);
283
- if (!baseUrl) {
284
- throw new Error(`URL key "${prop}" not found. Available keys: ${Array.from(self.urlMap.keys()).join(", ")}`);
285
- }
286
- const buildUrl = (path) => path ? `${baseUrl.replace(/\/$/, "")}/${path.replace(/^\//, "")}` : baseUrl;
287
- return {
288
- get: async (options) => {
289
- const cacheConfig = self.cacheConfig.get(prop);
290
- if (cacheConfig?.enabled) {
291
- const cached = self.cache.get(baseUrl, options?.path, options);
292
- if (cached) {
293
- return self.rehydrateResponse(cached);
294
- }
295
- }
296
- const dedupKey = `GET:${buildUrl(options?.path)}:${JSON.stringify(options?.headers || {})}`;
297
- if (self.inflightRequests.has(dedupKey)) {
298
- return self.inflightRequests.get(dedupKey);
299
- }
300
- const requestPromise = (async () => {
301
- try {
302
- const response = await self.request("GET", buildUrl(options?.path), null, {
303
- headers: options?.headers,
304
- maxRedirects: options?.maxRedirects,
305
- responseType: options?.responseType,
306
- antibot: options?.antibot
307
- });
308
- if (cacheConfig?.enabled && typeof response === "object" && "status" in response) {
309
- self.cache.set(baseUrl, response, cacheConfig.ttl, options?.path, options);
310
- }
311
- return response;
312
- } finally {
313
- self.inflightRequests.delete(dedupKey);
314
- }
315
- })();
316
- self.inflightRequests.set(dedupKey, requestPromise);
317
- return requestPromise;
318
- },
319
- post: async (options) => {
320
- const { headers, serializedBody } = self.prepareBody(options?.body, options?.headers);
321
- return self.request("POST", buildUrl(options?.path), serializedBody, {
322
- headers,
323
- maxRedirects: options?.maxRedirects,
324
- responseType: options?.responseType
325
- });
326
- },
327
- put: async (options) => {
328
- const { headers, serializedBody } = self.prepareBody(options?.body, options?.headers);
329
- return self.request("PUT", buildUrl(options?.path), serializedBody, {
330
- headers,
331
- maxRedirects: options?.maxRedirects,
332
- responseType: options?.responseType
333
- });
334
- },
335
- patch: async (options) => {
336
- const { headers, serializedBody } = self.prepareBody(options?.body, options?.headers);
337
- return self.request("PATCH", buildUrl(options?.path), serializedBody, {
338
- headers,
339
- maxRedirects: options?.maxRedirects,
340
- responseType: options?.responseType
341
- });
342
- },
343
- delete: async (options) => {
344
- const { headers, serializedBody } = self.prepareBody(options?.body, options?.headers);
345
- return self.request("DELETE", buildUrl(options?.path), serializedBody, {
346
- headers,
347
- maxRedirects: options?.maxRedirects,
348
- responseType: options?.responseType
349
- });
350
- },
351
- head: async (options) => {
352
- return self.request("HEAD", buildUrl(options?.path), null, {
353
- headers: options?.headers,
354
- maxRedirects: options?.maxRedirects,
355
- antibot: options?.antibot
356
- });
357
- },
358
- options: async (options) => {
359
- return self.request("OPTIONS", buildUrl(options?.path), null, {
360
- headers: options?.headers,
361
- maxRedirects: options?.maxRedirects,
362
- antibot: options?.antibot
363
- });
364
- },
365
- prefetch: async (options) => {
366
- self.cache.clear(baseUrl);
367
- const cacheConfig = self.cacheConfig.get(prop);
368
- if (cacheConfig?.enabled) {
369
- await self.request("GET", buildUrl(options?.path), null, {
370
- headers: options?.headers,
371
- maxRedirects: options?.maxRedirects,
372
- antibot: options?.antibot
373
- });
374
- }
375
- }
376
- };
377
- }
378
- });
379
- }
380
- close() {
381
- if (this.ptr) {
382
- lib.symbols.zclient_free(this.ptr);
383
- this.ptr = null;
384
- }
385
- }
386
- async warmup(urls) {
387
- if (!this.ptr)
388
- throw new Error("Client is closed");
389
- await Promise.all(urls.map((url) => new Promise((resolve) => {
390
- const urlBuffer = Buffer.from(url + "\x00");
391
- lib.symbols.zclient_prefetch(this.ptr, urlBuffer);
392
- resolve();
393
- })));
394
- }
395
- prefetch(urls) {
396
- this.warmup(urls);
397
- }
398
- async request(method, url, body, options) {
399
- if (!this.ptr)
400
- throw new Error("Client is closed");
401
- let headers = {};
402
- let maxRedirects = 5;
403
- let responseType;
404
- let antibot = false;
405
- if (options) {
406
- if ("maxRedirects" in options || "headers" in options || "responseType" in options || "method" in options || "timeout" in options || "antibot" in options) {
407
- const opts = options;
408
- if (opts.headers)
409
- headers = opts.headers;
410
- if (opts.maxRedirects !== undefined)
411
- maxRedirects = opts.maxRedirects;
412
- if (opts.responseType)
413
- responseType = opts.responseType;
414
- if (opts.antibot !== undefined)
415
- antibot = opts.antibot;
416
- } else {
417
- headers = options;
418
- }
419
- }
420
- const methodBuffer = Buffer.from(method + "\x00");
421
- const urlBuffer = Buffer.from(url + "\x00");
422
- let bodyBuffer = null;
423
- if (body) {
424
- bodyBuffer = Buffer.from(body + "\x00");
425
- }
426
- let headersBuffer = null;
427
- const defaultHeaders = {
428
- "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
429
- accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
430
- "accept-encoding": "gzip",
431
- "accept-language": "en-US,en;q=0.9",
432
- "sec-ch-ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
433
- "sec-ch-ua-mobile": "?0",
434
- "sec-ch-ua-platform": '"macOS"',
435
- "sec-fetch-dest": "document",
436
- "sec-fetch-mode": "navigate",
437
- "sec-fetch-site": "none",
438
- "sec-fetch-user": "?1",
439
- "upgrade-insecure-requests": "1"
440
- };
441
- const finalHeaders = { ...defaultHeaders, ...headers };
442
- const orderedHeaders = {};
443
- const keys = [
444
- "sec-ch-ua",
445
- "sec-ch-ua-mobile",
446
- "sec-ch-ua-platform",
447
- "upgrade-insecure-requests",
448
- "user-agent",
449
- "accept",
450
- "sec-fetch-site",
451
- "sec-fetch-mode",
452
- "sec-fetch-user",
453
- "sec-fetch-dest",
454
- "accept-encoding",
455
- "accept-language"
456
- ];
457
- for (const key of keys) {
458
- if (finalHeaders[key]) {
459
- orderedHeaders[key] = finalHeaders[key];
460
- delete finalHeaders[key];
461
- }
462
- }
463
- for (const [key, value] of Object.entries(finalHeaders)) {
464
- orderedHeaders[key] = value;
465
- }
466
- const headerStr = Object.entries(orderedHeaders).map(([k, v]) => `${k.toLowerCase()}: ${v}`).join(`\r
467
- `);
468
- if (headerStr.length > 0) {
469
- headersBuffer = Buffer.from(headerStr + "\x00");
470
- }
471
- let retryConfig = this.globalRetry;
472
- if (options && typeof options === "object" && "retry" in options) {
473
- const userRetry = options.retry;
474
- if (typeof userRetry === "number") {
475
- retryConfig = { count: userRetry, delay: 100, backoff: 2 };
476
- } else if (typeof userRetry === "object") {
477
- retryConfig = userRetry;
478
- }
479
- }
480
- let attempts = 0;
481
- const maxAttempts = (retryConfig?.count || 0) + 1;
482
- let currentDelay = retryConfig?.delay || 100;
483
- const backoff = retryConfig?.backoff || 2;
484
- let lastError;
485
- while (attempts < maxAttempts) {
486
- attempts++;
487
- try {
488
- const respPtr = lib.symbols.zclient_request(this.ptr, methodBuffer, urlBuffer, headersBuffer, bodyBuffer, maxRedirects, antibot);
489
- if (!respPtr) {
490
- throw new Error("Native request failed (returned null pointer)");
491
- }
492
- const response = this.parseResponse(respPtr, url);
493
- if (responseType) {
494
- if (responseType === "json")
495
- return response.body.json();
496
- if (responseType === "text")
497
- return response.body.text();
498
- if (responseType === "arraybuffer")
499
- return response.body.arrayBuffer();
500
- if (responseType === "blob")
501
- return response.body.blob();
502
- }
503
- return response;
504
- } catch (err) {
505
- lastError = err;
506
- if (attempts < maxAttempts) {
507
- await this.waitFor(currentDelay);
508
- currentDelay *= backoff;
509
- }
510
- }
511
- }
512
- throw lastError || new Error("Request failed after retries");
513
- }
514
- parseResponse(respPtr, url) {
515
- if (!respPtr)
516
- throw new Error("Native request failed (returned null pointer)");
517
- try {
518
- const status = lib.symbols.zclient_response_status(respPtr);
519
- const len = Number(lib.symbols.zclient_response_body_len(respPtr));
520
- const bodyPtr = lib.symbols.zclient_response_body(respPtr);
521
- const headersLen = Number(lib.symbols.zclient_response_headers_len(respPtr));
522
- let headersObj = {};
523
- if (headersLen > 0) {
524
- const rawHeadersPtr = lib.symbols.zclient_response_headers(respPtr);
525
- if (rawHeadersPtr) {
526
- const rawSrc = toArrayBuffer(rawHeadersPtr, 0, headersLen);
527
- const raw = new Uint8Array(rawSrc.slice(0));
528
- headersObj = new NativeHeaders(raw);
529
- }
530
- }
531
- const headersProxy = new Proxy(headersObj instanceof NativeHeaders ? headersObj : {}, {
532
- get(target, prop) {
533
- if (target instanceof NativeHeaders && typeof prop === "string") {
534
- if (prop === "toJSON")
535
- return () => target.toJSON();
536
- const val = target.get(prop);
537
- if (val !== null)
538
- return val;
539
- }
540
- return Reflect.get(target, prop);
541
- }
542
- });
543
- let buffer = new ArrayBuffer(0);
544
- if (len > 0 && bodyPtr) {
545
- buffer = toArrayBuffer(bodyPtr, 0, len).slice(0);
546
- }
547
- let base64Data = "";
548
- try {
549
- base64Data = Buffer.from(buffer).toString("base64");
550
- } catch (e) {}
551
- let bodyUsed = false;
552
- const consumeBody = () => {
553
- if (bodyUsed) {}
554
- bodyUsed = true;
555
- };
556
- const bodyObj = {
557
- bodyUsed: false,
558
- _raw: base64Data,
559
- arrayBuffer: async () => {
560
- consumeBody();
561
- if (Buffer.isBuffer(buffer)) {
562
- const buf = buffer;
563
- return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
564
- }
565
- return buffer;
566
- },
567
- blob: async () => {
568
- consumeBody();
569
- return new Blob([buffer]);
570
- },
571
- text: async () => {
572
- consumeBody();
573
- return new TextDecoder().decode(buffer);
574
- },
575
- json: async () => {
576
- consumeBody();
577
- const text = new TextDecoder().decode(buffer);
578
- return JSON.parse(text);
579
- }
580
- };
581
- Object.defineProperty(bodyObj, "bodyUsed", {
582
- get: () => bodyUsed
583
- });
584
- return {
585
- url,
586
- status,
587
- statusText: STATUS_TEXT[status] || "",
588
- headers: headersProxy,
589
- ok: status >= 200 && status < 300,
590
- redirected: false,
591
- type: "basic",
592
- body: bodyObj
593
- };
594
- } finally {
595
- lib.symbols.zclient_response_free(respPtr);
596
- }
597
- }
598
- prepareBody(body, userHeaders) {
599
- let serializedBody = null;
600
- const headers = { ...userHeaders };
601
- if (body !== null && body !== undefined) {
602
- if (typeof body === "object") {
603
- serializedBody = JSON.stringify(body);
604
- const hasContentType = Object.keys(headers).some((k) => k.toLowerCase() === "content-type");
605
- if (!hasContentType) {
606
- headers["Content-Type"] = "application/json";
607
- }
608
- } else {
609
- serializedBody = String(body);
610
- }
611
- }
612
- return { headers, serializedBody };
613
- }
614
- rehydrateResponse(cached) {
615
- if (typeof cached.body.text === "function")
616
- return cached;
617
- const rawData = cached.body._raw;
618
- let buffer;
619
- if (rawData) {
620
- buffer = Buffer.from(rawData, "base64");
621
- } else {
622
- buffer = Buffer.from("");
623
- }
624
- let bodyUsed = cached.body.bodyUsed || false;
625
- const consumeBody = () => {
626
- bodyUsed = true;
627
- };
628
- const bodyObj = {
629
- _raw: rawData,
630
- bodyUsed,
631
- arrayBuffer: async () => {
632
- consumeBody();
633
- return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
634
- },
635
- blob: async () => {
636
- consumeBody();
637
- return new Blob([buffer]);
638
- },
639
- text: async () => {
640
- consumeBody();
641
- return new TextDecoder().decode(buffer);
642
- },
643
- json: async () => {
644
- consumeBody();
645
- const text = new TextDecoder().decode(buffer);
646
- return JSON.parse(text);
647
- }
648
- };
649
- Object.defineProperty(bodyObj, "bodyUsed", {
650
- get: () => bodyUsed
651
- });
652
- return {
653
- ...cached,
654
- body: bodyObj
655
- };
656
- }
657
- }
658
-
659
- class NativeHeaders {
660
- raw;
661
- len;
662
- decoder = new TextDecoder;
663
- cache = new Map;
664
- constructor(raw) {
665
- this.raw = raw;
666
- this.len = raw.byteLength;
667
- }
668
- get(name) {
669
- const target = name.toLowerCase();
670
- if (this.cache.has(target))
671
- return this.cache.get(target);
672
- const keyBuf = Buffer.from(target + "\x00");
673
- const resPtr = lib.symbols.z_find_header_value(this.raw, this.len, keyBuf);
674
- if (!resPtr)
675
- return null;
676
- try {
677
- const view = new DataView(toArrayBuffer(resPtr, 0, 16));
678
- const valPtr = view.getBigUint64(0, true);
679
- const valLen = Number(view.getBigUint64(8, true));
680
- if (valLen === 0) {
681
- this.cache.set(target, "");
682
- return "";
683
- }
684
- const valBytes = toArrayBuffer(Number(valPtr), 0, valLen);
685
- const val = this.decoder.decode(valBytes);
686
- this.cache.set(target, val);
687
- return val;
688
- } finally {
689
- lib.symbols.zclient_header_value_free(resPtr);
690
- }
691
- }
692
- toJSON() {
693
- const obj = {};
694
- const text = this.decoder.decode(this.raw);
695
- const lines = text.split(`\r
696
- `);
697
- for (const line of lines) {
698
- if (!line)
699
- continue;
700
- const colon = line.indexOf(":");
701
- if (colon === -1)
702
- continue;
703
- const key = line.substring(0, colon).trim().toLowerCase();
704
- const val = line.substring(colon + 1).trim();
705
- obj[key] = val;
706
- }
707
- return obj;
708
- }
709
- }
710
- export {
711
- JirenClient
712
- };
Binary file