@e-mc/request 0.12.14 → 0.12.16

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
@@ -9,7 +9,7 @@
9
9
 
10
10
  ## Interface
11
11
 
12
- * [View Source](https://www.unpkg.com/@e-mc/types@0.12.14/lib/index.d.ts)
12
+ * [View Source](https://www.unpkg.com/@e-mc/types@0.12.16/lib/index.d.ts)
13
13
 
14
14
  ```typescript
15
15
  import type { IModule, ModuleConstructor } from "./index";
@@ -45,6 +45,7 @@ interface IRequest extends IModule {
45
45
  rclone(uri: string | URL, pathname: string | URL): Promise<string[]>;
46
46
  rclone(uri: string | URL, options?: RcloneOptions): Promise<string[]>;
47
47
  json(uri: string | URL, options?: OpenOptions): Promise<object | null>;
48
+ blob(uri: string | URL, options?: OpenOptions): Promise<Blob | null>;
48
49
  pipe(uri: string | URL, to: Writable, options?: OpenOptions): Promise<null>;
49
50
  opts(url: string | URL, options?: OpenOptions): HostConfig;
50
51
  open(uri: string | URL, options: OpenOptions): HttpRequestClient;
@@ -255,9 +256,9 @@ instance.get("http://hostname/path/config.yml", options).then(data => {
255
256
 
256
257
  ## References
257
258
 
258
- - https://www.unpkg.com/@e-mc/types@0.12.14/lib/http.d.ts
259
- - https://www.unpkg.com/@e-mc/types@0.12.14/lib/request.d.ts
260
- - https://www.unpkg.com/@e-mc/types@0.12.14/lib/settings.d.ts
259
+ - https://www.unpkg.com/@e-mc/types@0.12.16/lib/http.d.ts
260
+ - https://www.unpkg.com/@e-mc/types@0.12.16/lib/request.d.ts
261
+ - https://www.unpkg.com/@e-mc/types@0.12.16/lib/settings.d.ts
261
262
 
262
263
  * https://www.npmjs.com/package/@types/node
263
264
 
@@ -243,6 +243,9 @@ class HttpAdapter {
243
243
  if ('outFilename' in opts) {
244
244
  opts.outFilename = (0, util_1.parseHeader)(headers, 'content-disposition');
245
245
  }
246
+ if ('outContentType' in opts) {
247
+ opts.outContentType = headers['content-type'];
248
+ }
246
249
  const pipeline = this.pipeTo ? !(0, types_1.isString)(this.pipeTo) : false;
247
250
  const enabled = opts.connected?.call(this.client, headers) !== false && !pipeline;
248
251
  const maxBufferSize = opts.maxBufferSize ? (0, types_1.alignSize)(opts.maxBufferSize) : 0;
@@ -349,7 +352,12 @@ class HttpAdapter {
349
352
  result = new (require(packageName = 'fast-xml-parser').XMLParser)(parser).parse(buffer);
350
353
  break;
351
354
  case 'toml':
352
- result = require(packageName = 'toml').parse(buffer);
355
+ try {
356
+ result = require('smol-toml').parse(buffer, parser);
357
+ }
358
+ catch {
359
+ result = require(packageName = 'toml').parse(buffer);
360
+ }
353
361
  break;
354
362
  default:
355
363
  result = JSON.parse(buffer);
@@ -367,6 +375,9 @@ class HttpAdapter {
367
375
  }
368
376
  }
369
377
  }
378
+ else if (opts.outFormat) {
379
+ opts.outFormat = undefined;
380
+ }
370
381
  if (result === undefined) {
371
382
  result = buffer;
372
383
  }
package/index.js CHANGED
@@ -23,6 +23,7 @@ const adapter_1 = require("@e-mc/request/http/adapter");
23
23
  const kRequest = Symbol.for('request:constructor');
24
24
  const SUPPORTED_NODE20 = (0, types_1.supported)(20);
25
25
  const SUPPORTED_ZSTD = (0, types_1.supported)(23, 8) || (0, types_1.supported)(22, 15, 0, true);
26
+ const SUPPORTED_FILE = (0, types_1.supported)(19, 2) || (0, types_1.supported)(18, 13, true);
26
27
  const REGEXP_PEMCERT = /^-{3,}[ \t]*BEGIN[ \t].+\n-{3,}[ \t]*END[ \t][^-]+-{3,}$/s;
27
28
  const REGEXP_GLOBWITHIN = /\\\?|(?:(?<!\\)(?:\*|\[!?[^!\]]+\]|\{(?:[^,]+,)+[^}]+\}|[!?+*@]\((?:[^|]+\|)*[^)]+\)|\?.*\?|\?$))/;
28
29
  const REGEXP_RCLONE = /^rclone:\?/i;
@@ -33,8 +34,8 @@ const HTTP = {
33
34
  PROXY: null
34
35
  };
35
36
  const TLS = {
36
- TEXT: {},
37
- FILE: {}
37
+ TEXT: Object.create(null),
38
+ FILE: Object.create(null)
38
39
  };
39
40
  const DNS = {
40
41
  CACHE: Object.create(null),
@@ -61,7 +62,7 @@ const ARIA2 = {
61
62
  LOWEST_SPEED_LIMIT: null,
62
63
  ALWAYS_RESUME: false,
63
64
  FILE_ALLOCATION: 'none',
64
- PROXY: {},
65
+ PROXY: Object.create(null),
65
66
  NO_PROXY: '',
66
67
  CONF_PATH: ''
67
68
  };
@@ -116,21 +117,6 @@ try {
116
117
  }
117
118
  catch {
118
119
  }
119
- function getBaseHeaders(uri, headers) {
120
- let result;
121
- uri = (0, util_1.trimPath)(uri);
122
- for (const pathname in headers) {
123
- if (pathname === uri || uri.startsWith(pathname + '/')) {
124
- (result ||= []).push([pathname, headers[pathname]]);
125
- }
126
- }
127
- if (result) {
128
- if (result.length > 1) {
129
- result.sort((a, b) => b[0].length - a[0].length);
130
- }
131
- return result[0][1];
132
- }
133
- }
134
120
  function setDnsCache(hostname, value, expires) {
135
121
  expires ??= DNS.EXPIRES;
136
122
  if (expires > 0 && !DNS.CACHE[hostname]) {
@@ -175,11 +161,9 @@ function getProxySettings(request, agentTimeout) {
175
161
  return null;
176
162
  }
177
163
  function closeTorrent(pid) {
178
- if (typeof pid === 'number') {
179
- const index = ARIA2.PID_QUEUE.findIndex(value => pid === value[0]);
180
- if (index !== -1) {
181
- ARIA2.PID_QUEUE.splice(index, 1);
182
- }
164
+ const index = ARIA2.PID_QUEUE.findIndex(value => value[0] === pid);
165
+ if (index !== -1) {
166
+ ARIA2.PID_QUEUE.splice(index, 1);
183
167
  }
184
168
  }
185
169
  function clearDnsLookup() {
@@ -201,7 +185,7 @@ function resetHttpHost(version) {
201
185
  const host = HTTP.HOST[origin];
202
186
  if (host.secure && host.version === 1) {
203
187
  const failed = host.failed(2, true);
204
- if (failed === 0 && host.failed(2, true) < 10 || failed < 3 && host.success(2, true) > 0) {
188
+ if (failed === 0 && host.error(2, true) < 10 || failed < 3 && host.success(2, true) > 0) {
205
189
  host.version = version;
206
190
  }
207
191
  }
@@ -362,8 +346,10 @@ function decompressEncoding(value, chunkSize) {
362
346
  }
363
347
  }
364
348
  function resetAria2() {
365
- clearInterval(ARIA2.PID_TIMER);
366
- ARIA2.PID_TIMER = null;
349
+ if (ARIA2.PID_TIMER) {
350
+ clearInterval(ARIA2.PID_TIMER);
351
+ ARIA2.PID_TIMER = null;
352
+ }
367
353
  }
368
354
  function escapeShellQuote(value) {
369
355
  value = value.replace(/(?<!\\)"/g, '\\"');
@@ -846,9 +832,9 @@ class Request extends module_1 {
846
832
  };
847
833
  #singleton = false;
848
834
  #httpVersion = null;
835
+ #headers = null;
849
836
  #ipVersion;
850
837
  #agentTimeout;
851
- #headers = null;
852
838
  #baseUrl = null;
853
839
  #connectDns = Object.create(null);
854
840
  #pendingDns = Object.create(null);
@@ -858,7 +844,7 @@ class Request extends module_1 {
858
844
  #adapter = HTTP_ADAPTER;
859
845
  #certs = null;
860
846
  #downloading = new Set();
861
- #hostInfo = {};
847
+ #hostInfo = Object.create(null);
862
848
  #session = [Object.create(null)];
863
849
  constructor(data) {
864
850
  super();
@@ -884,9 +870,7 @@ class Request extends module_1 {
884
870
  if (proxy) {
885
871
  this.proxy = proxy;
886
872
  }
887
- if ((0, types_1.isObject)(headers)) {
888
- setOutgoingHeaders(this.#headers = {}, headers);
889
- }
873
+ this.parseHeaders(headers);
890
874
  if ((0, types_1.isObject)(certs)) {
891
875
  this.#certs = validateCerts(certs);
892
876
  }
@@ -994,9 +978,7 @@ class Request extends module_1 {
994
978
  init(config) {
995
979
  if (config) {
996
980
  const { headers, httpVersion, ipVersion, readTimeout } = config;
997
- if ((0, types_1.isObject)(headers)) {
998
- setOutgoingHeaders(this.#headers ||= {}, headers);
999
- }
981
+ this.parseHeaders(headers);
1000
982
  if (httpVersion !== undefined) {
1001
983
  this.httpVersion = httpVersion;
1002
984
  }
@@ -1220,8 +1202,7 @@ class Request extends module_1 {
1220
1202
  }
1221
1203
  }
1222
1204
  headersOf(uri) {
1223
- const headers = this.#headers;
1224
- return headers && getBaseHeaders(uri, headers) || (this.host ? getBaseHeaders(uri, HTTP.HEADERS) : undefined);
1205
+ return this.findHeadersByUri(uri) || (this.host ? this.findHeadersByUri(uri, HTTP.HEADERS) : undefined);
1225
1206
  }
1226
1207
  async aria2c(uri, options = {}) {
1227
1208
  if (!ARIA2.BIN) {
@@ -1238,15 +1219,10 @@ class Request extends module_1 {
1238
1219
  ({ signal, silent } = options);
1239
1220
  ({ pathname, headers, binOpts } = this.parseBinOpts(options, ['--daemon'], ['--input-file'], options.shellExpansion));
1240
1221
  }
1241
- try {
1242
- if (typeof uri === 'string' && module_1.isURL(uri)) {
1243
- uri = new URL(uri);
1244
- }
1245
- pathname = checkBinTarget(this, "aria2", uri, pathname, 'aria2', binOpts);
1246
- }
1247
- catch (err) {
1248
- return Promise.reject(err);
1222
+ if ((0, types_1.isString)(uri) && module_1.isURL(uri)) {
1223
+ uri = new URL(uri);
1249
1224
  }
1225
+ pathname = checkBinTarget(this, "aria2", uri, pathname, 'aria2', binOpts);
1250
1226
  silent ??= this.#singleton;
1251
1227
  return new Promise((resolve, reject) => {
1252
1228
  let protocol, origin, username, password;
@@ -1511,12 +1487,7 @@ class Request extends module_1 {
1511
1487
  default:
1512
1488
  return Promise.reject((0, types_1.errorMessage)("rclone", "Invalid command", command || uri));
1513
1489
  }
1514
- try {
1515
- pathname = checkBinTarget(this, "rclone", uri, pathname, command, binOpts);
1516
- }
1517
- catch (err) {
1518
- return Promise.reject(err);
1519
- }
1490
+ pathname = checkBinTarget(this, "rclone", uri, pathname, command, binOpts);
1520
1491
  silent ??= this.#singleton;
1521
1492
  return new Promise((resolve, reject) => {
1522
1493
  const init = [
@@ -1710,6 +1681,21 @@ class Request extends module_1 {
1710
1681
  options.format = 'json';
1711
1682
  return this.get(uri, options);
1712
1683
  }
1684
+ async blob(uri, options = {}) {
1685
+ options.outContentType = undefined;
1686
+ options.outFilename = undefined;
1687
+ options.outBlob = true;
1688
+ const data = await this.get(uri, options);
1689
+ if (!data) {
1690
+ return null;
1691
+ }
1692
+ const format = options.outFormat?.out;
1693
+ const type = { type: format ? 'application/' + format : options.outContentType || (typeof data === 'string' ? 'text/plain' : undefined) };
1694
+ if (SUPPORTED_FILE && options.outFilename) {
1695
+ return new File([Buffer.from(data)], path.basename(options.outFilename), type);
1696
+ }
1697
+ return new Blob([Buffer.from(data)], type);
1698
+ }
1713
1699
  async pipe(uri, to, options = {}) {
1714
1700
  options.pipeTo = to;
1715
1701
  return this.get(uri, options);
@@ -1777,7 +1763,9 @@ class Request extends module_1 {
1777
1763
  }
1778
1764
  headers.accept += ', text/plain';
1779
1765
  options.encoding = (0, types_1.getEncoding)(encoding);
1780
- options.outFormat = { out: format, parser };
1766
+ if (!options.outBlob) {
1767
+ options.outFormat = { out: format, parser };
1768
+ }
1781
1769
  }
1782
1770
  if (typeof uri !== 'string') {
1783
1771
  url = uri;
@@ -1942,7 +1930,7 @@ class Request extends module_1 {
1942
1930
  try {
1943
1931
  keepAlive ??= proxy.keepAlive;
1944
1932
  agentTimeout ??= proxy.agentTimeout;
1945
- const proxyHeaders = this.#headers && getBaseHeaders(proxy.host.href, this.#headers) || getBaseHeaders(proxy.host.href, HTTP.HEADERS);
1933
+ const proxyHeaders = this.findHeadersByUri(proxy.host.href) || this.findHeadersByUri(proxy.host.href, HTTP.HEADERS);
1946
1934
  agent = require(pkg)(proxy.host, (typeof keepAlive === 'boolean' || agentTimeout > 0) && agentTimeout !== 0 ? { keepAlive: keepAlive ?? true, timeout: agentTimeout, headers: proxyHeaders } : { headers: proxyHeaders });
1947
1935
  }
1948
1936
  catch (err) {
@@ -2391,7 +2379,7 @@ class Request extends module_1 {
2391
2379
  }
2392
2380
  if ((0, types_1.isArray)(options.binOpts)) {
2393
2381
  let next = false;
2394
- binOpts = options.binOpts.filter((opt) => !((0, types_1.isString)(opt) && /^-[a-z].*$/i.test(opt.trim()))).map((opt) => {
2382
+ binOpts = options.binOpts.filter((opt) => !((0, types_1.isString)(opt) && /^-[a-z].*$/i.test(opt))).map((opt) => {
2395
2383
  if (next) {
2396
2384
  if (!module_1.asString(opt).startsWith('--')) {
2397
2385
  return [];
@@ -2441,6 +2429,26 @@ class Request extends module_1 {
2441
2429
  }
2442
2430
  return { pathname, headers: (0, util_1.parseOutgoingHeaders)(options.headers), binOpts };
2443
2431
  }
2432
+ parseHeaders(outgoing) {
2433
+ if ((0, types_1.isObject)(outgoing)) {
2434
+ setOutgoingHeaders(this.#headers ||= {}, outgoing);
2435
+ }
2436
+ }
2437
+ findHeadersByUri(uri, outgoing = this.#headers) {
2438
+ if (outgoing) {
2439
+ const result = [];
2440
+ uri = (0, util_1.trimPath)(uri);
2441
+ for (const pathname in outgoing) {
2442
+ if (pathname === uri || uri.startsWith(pathname + '/')) {
2443
+ result.push([pathname, outgoing[pathname]]);
2444
+ }
2445
+ }
2446
+ if (result.length > 0) {
2447
+ result.sort((a, b) => b[0].length - a[0].length);
2448
+ return result[0][1];
2449
+ }
2450
+ }
2451
+ }
2444
2452
  set adapter(value) {
2445
2453
  if (isConstructor(value) && value.prototype instanceof adapter_1) {
2446
2454
  this.#adapter = value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/request",
3
- "version": "0.12.14",
3
+ "version": "0.12.16",
4
4
  "description": "Request constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -19,11 +19,11 @@
19
19
  "license": "BSD-3-Clause",
20
20
  "homepage": "https://github.com/anpham6/e-mc#readme",
21
21
  "dependencies": {
22
- "@e-mc/module": "0.12.14",
23
- "@e-mc/types": "0.12.14",
22
+ "@e-mc/module": "0.12.16",
23
+ "@e-mc/types": "0.12.16",
24
24
  "combined-stream": "^1.0.8",
25
25
  "js-yaml": "^4.1.1",
26
- "picomatch": "^4.0.3",
26
+ "picomatch": "^4.0.4",
27
27
  "which": "^4.0.0"
28
28
  }
29
29
  }
package/util.d.ts CHANGED
@@ -13,8 +13,8 @@ declare namespace util {
13
13
  function hasBasicAuth(value: string): boolean;
14
14
  function checkRetryable(err: unknown): boolean;
15
15
  function isRetryable(value: number, timeout?: boolean): boolean;
16
- function parseHttpProxy(value?: string): HttpProxySettings | undefined;
17
- function trimPath(value: string): string;
16
+ function parseHttpProxy(value?: string, ignoreEnv?: boolean): HttpProxySettings | undefined;
17
+ function trimPath(value: string, char?: string): string;
18
18
  function asInt(value: unknown): number;
19
19
  function asFloat(value: unknown): number;
20
20
  function fromSeconds(value: unknown): number;
package/util.js CHANGED
@@ -182,9 +182,11 @@ function parseHttpProxy(value, ignoreEnv) {
182
182
  }
183
183
  }
184
184
  }
185
- function trimPath(value) {
186
- const length = value.length - 1;
187
- return value[length] === '/' ? value.substring(0, length) : value;
185
+ function trimPath(value, char = '/') {
186
+ while (value.at(-1) === char) {
187
+ value = value.slice(0, -1);
188
+ }
189
+ return value;
188
190
  }
189
191
  function asInt(value) {
190
192
  switch (typeof value) {