@e-mc/request 0.11.7 → 0.12.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/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
3
2
  const path = require("node:path");
4
3
  const fs = require("node:fs");
5
4
  const crypto = require("node:crypto");
@@ -20,22 +19,7 @@ const module_1 = require("@e-mc/module");
20
19
  const util_1 = require("@e-mc/request/util");
21
20
  const host_1 = require("@e-mc/request/http/host");
22
21
  const adapter_1 = require("@e-mc/request/http/adapter");
23
- const kSession = Symbol('session');
24
- const kHttpVersion = Symbol('httpVersion');
25
- const kIpVersion = Symbol('ipVersion');
26
- const kAgentTimeout = Symbol('agentTimeout');
27
- const kHeaders = Symbol('headers');
28
- const kCerts = Symbol('certs');
29
- const kBaseURL = Symbol('baseURL');
30
- const kDownloading = Symbol('downloading');
31
- const kSingleton = Symbol('singleton');
32
- const kHostInfo = Symbol('hostInfo');
33
- const kConnectDns = Symbol('connectDns');
34
- const kPendingDns = Symbol('pendingDns');
35
- const kConnectHttp = Symbol('connectHttp');
36
- const kStatusOn = Symbol('statusOn');
37
- const kHeadersOn = Symbol('headersOn');
38
- const kAdapter = Symbol('adapter');
22
+ const kRequest = Symbol.for('request:constructor');
39
23
  const SUPPORTED_NODE20 = (0, types_1.supported)(20);
40
24
  const SUPPORTED_ZSTD = (0, types_1.supported)(23, 8) && typeof zlib.createZstdDecompress === 'function';
41
25
  const REGEXP_PEMCERT = /^-{3,}[ \t]*BEGIN[ \t].+\n-{3,}[ \t]*END[ \t][^-]+-{3,}$/s;
@@ -75,8 +59,46 @@ const ARIA2 = {
75
59
  LOWEST_SPEED_LIMIT: null,
76
60
  ALWAYS_RESUME: false,
77
61
  FILE_ALLOCATION: 'none',
62
+ PROXY: {},
63
+ NO_PROXY: '',
78
64
  CONF_PATH: ''
79
65
  };
66
+ const RCLONE = {
67
+ BIN: which.sync(module_1.PLATFORM_WIN32 ? 'rclone.exe' : 'rclone', { nothrow: true }) || '',
68
+ EXEC_UID: undefined,
69
+ EXEC_GID: undefined,
70
+ CHECK_FIRST: false,
71
+ CHECKSUM: false,
72
+ CUTOFF_MODE: '',
73
+ IGNORE_CASE_SYNC: false,
74
+ IGNORE_CHECKSUM: false,
75
+ IGNORE_EXISTING: false,
76
+ IGNORE_SIZE: false,
77
+ IGNORE_TIMES: false,
78
+ IMMUTABLE: false,
79
+ INPLACE: false,
80
+ MAX_BACKLOG: 0,
81
+ MAX_DURATION: '',
82
+ MAX_TRANSFER: '',
83
+ METADATA: false,
84
+ MODIFY_WINDOW: '',
85
+ MULTI_THREAD_CHUNK_SIZE: '',
86
+ MULTI_THREAD_CUTOFF: '',
87
+ MULTI_THREAD_STREAMS: 0,
88
+ MULTI_THREAD_WRITE_BUFFER_SIZE: '',
89
+ NO_CHECK_DEST: false,
90
+ NO_TRAVERSE: false,
91
+ NO_UPDATE_DIR_MODTIME: false,
92
+ REFRESH_TIMES: false,
93
+ SIZE_ONLY: false,
94
+ UPDATE: false,
95
+ FAST_LIST: false,
96
+ BIND: '',
97
+ CONTIMEOUT: '',
98
+ DISABLE_HTTP2: false,
99
+ TIMEOUT: '',
100
+ CONFIG: ''
101
+ };
80
102
  let HTTP_ADAPTER = adapter_1;
81
103
  let KEEP_ALIVE = null;
82
104
  let ACCEPT_ENCODING = false;
@@ -335,15 +357,6 @@ function decompressEncoding(value, chunkSize) {
335
357
  break;
336
358
  }
337
359
  }
338
- function abortHeaders(href, request, options, statusCode = '', message) {
339
- const reason = (0, types_1.errorMessage)(statusCode, message || "Aborted by client", href);
340
- const outAbort = options.outAbort;
341
- if (outAbort) {
342
- outAbort.abort(reason);
343
- this[kDownloading].delete(outAbort);
344
- }
345
- request.destroy(reason);
346
- }
347
360
  function resetAria2() {
348
361
  clearInterval(ARIA2.PID_TIMER);
349
362
  ARIA2.PID_TIMER = null;
@@ -363,27 +376,187 @@ function failedDns(err, pending) {
363
376
  }
364
377
  pending.length = 0;
365
378
  }
366
- function successDns(instance, value, pending, connected) {
367
- instance[kConnectDns][value] = connected;
368
- setDnsCache(value, connected, null);
369
- if (SUPPORTED_NODE20) {
370
- for (const cb of pending) {
371
- cb(null, connected);
379
+ function setBinExec(settings, target) {
380
+ let { bin, exec } = settings;
381
+ if (bin === false) {
382
+ target.BIN = '';
383
+ }
384
+ else if (bin && module_1.isPath(bin = path.resolve(bin), true)) {
385
+ target.BIN = bin;
386
+ }
387
+ if ((0, types_1.isPlainObject)(exec)) {
388
+ let { uid, gid } = exec;
389
+ target.EXEC_UID = (uid = (0, util_1.asInt)(uid)) >= 0 ? uid : undefined;
390
+ target.EXEC_GID = (gid = (0, util_1.asInt)(gid)) >= 0 ? gid : undefined;
391
+ }
392
+ }
393
+ function parseBinOpts(instance, options, ignore, skip) {
394
+ let pathname = options.pathname, binOpts;
395
+ if (!(0, types_1.isString)(pathname)) {
396
+ if (!instance.host) {
397
+ return [];
398
+ }
399
+ pathname = process.cwd();
400
+ }
401
+ if ((0, types_1.isArray)(options.binOpts)) {
402
+ let next = false;
403
+ binOpts = options.binOpts.filter(opt => !((0, types_1.isString)(opt) && /^-[a-z].*$/i.test(opt.trim()))).map((opt) => {
404
+ if (next) {
405
+ if (!module_1.asString(opt).startsWith('--')) {
406
+ return [];
407
+ }
408
+ next = false;
409
+ }
410
+ switch (typeof opt) {
411
+ case 'string': {
412
+ const value = opt.trim();
413
+ if (value.startsWith('--')) {
414
+ const match = /^(--[a-z]+[a-z0-9-]*)(=)?\s*(.*)$/s.exec(value);
415
+ if (match) {
416
+ if (ignore.includes(match[1])) {
417
+ return [];
418
+ }
419
+ if (skip.includes(match[1])) {
420
+ if (!match[2]) {
421
+ next = true;
422
+ }
423
+ return [];
424
+ }
425
+ switch (match[1]) {
426
+ case '--version':
427
+ case '--help':
428
+ return [];
429
+ default:
430
+ return match[3] ? [match[1], (0, types_1.sanitizeArgs)(match[3])] : [match[1]];
431
+ }
432
+ }
433
+ }
434
+ else if (value) {
435
+ return [(0, types_1.sanitizeArgs)(value)];
436
+ }
437
+ break;
438
+ }
439
+ case 'number':
440
+ case 'boolean':
441
+ return [opt.toString()];
442
+ default:
443
+ if ((0, types_1.isArray)(opt)) {
444
+ return opt.filter(item => (0, types_1.isString)(item)).map(item => (0, types_1.sanitizeArgs)(item));
445
+ }
446
+ break;
447
+ }
448
+ return [];
449
+ }).flat();
450
+ }
451
+ return [pathname, (0, util_1.parseOutgoingHeaders)(options.headers), binOpts];
452
+ }
453
+ function checkBinTarget(instance, name, uri, pathname, command, binOpts) {
454
+ if (!(0, types_1.isString)(pathname)) {
455
+ throw (0, types_1.errorMessage)(name, "Invalid parameters", 'pathname');
456
+ }
457
+ pathname = path.resolve(pathname);
458
+ if ((instance.host || instance.hasPermission('fs') || process.permission) && !instance.canWrite(pathname)) {
459
+ throw (0, types_1.errorMessage)(name, "Unsupported access", pathname);
460
+ }
461
+ let target;
462
+ switch (command) {
463
+ case 'copyurl':
464
+ if (module_1.isDir(pathname) || isDirEnd(pathname)) {
465
+ target = pathname;
466
+ if (!binOpts || !binOpts.includes('--auto-filename') && !binOpts.includes('--header-filename')) {
467
+ pathname = path.join(pathname, path.basename(new URL(uri).pathname));
468
+ }
469
+ break;
470
+ }
471
+ case 'copyto':
472
+ target = isDirEnd(pathname) ? pathname : path.dirname(pathname);
473
+ break;
474
+ default:
475
+ target = pathname;
476
+ break;
477
+ }
478
+ if (!module_1.createDir(target)) {
479
+ throw (0, types_1.errorMessage)(name, "Path is not a directory", target);
480
+ }
481
+ return pathname;
482
+ }
483
+ function checkBinOpts(init, binOpts) {
484
+ if ((0, types_1.isArray)(binOpts)) {
485
+ for (let i = 0; i < binOpts.length; ++i) {
486
+ const leading = binOpts[i] + '=';
487
+ for (const arg of init) {
488
+ if (arg.startsWith(leading)) {
489
+ const items = [];
490
+ for (let k = i + 1; k < binOpts.length; ++k) {
491
+ const next = binOpts[k];
492
+ if (next.startsWith('--')) {
493
+ break;
494
+ }
495
+ items.push(next);
496
+ }
497
+ const l = items.length + 1;
498
+ binOpts.splice(i, l);
499
+ i += l;
500
+ break;
501
+ }
502
+ }
372
503
  }
373
504
  }
374
- else {
375
- const { address, family } = connected[0];
376
- for (const cb of pending) {
377
- cb(null, address, family);
505
+ }
506
+ function setBinHeaders(args, headers) {
507
+ for (const name in headers) {
508
+ let items = headers[name];
509
+ if (!Array.isArray(items)) {
510
+ items = [items.toString()];
378
511
  }
512
+ args.push(...items.map(value => `--header="${name}: ${escapeShellQuote(value)}"`));
513
+ }
514
+ }
515
+ function finalizeBinArgs(instance, name, bin, args, opts, binOpts, cmd = []) {
516
+ if ((0, types_1.isArray)(binOpts)) {
517
+ for (const leading of binOpts) {
518
+ if (leading.startsWith('-')) {
519
+ const pattern = new RegExp(`^${leading}(?:=|$)`);
520
+ for (let i = 0; i < opts.length; ++i) {
521
+ if (pattern.test(opts[i])) {
522
+ opts.splice(i--, i);
523
+ break;
524
+ }
525
+ }
526
+ }
527
+ }
528
+ args = binOpts.concat(args);
529
+ }
530
+ if (args.length > 0) {
531
+ if (module_1.hasLogType(32768)) {
532
+ instance.formatMessage(32768, name.toUpperCase(), [bin].concat(cmd).join(' '), args.join(' '), { ...module_1.LOG_STYLE_WARN });
533
+ }
534
+ else {
535
+ instance.addLog(types_1.STATUS_TYPE.INFO, path.basename(bin) + ' ' + args.join(' '), name);
536
+ }
537
+ }
538
+ return args;
539
+ }
540
+ function addAria2Proxy(args, protocol, host) {
541
+ const { origin, username, password } = host;
542
+ args.push(`--${protocol}-proxy="${origin}"`);
543
+ if (username) {
544
+ args.push(`--${protocol}-proxy-user="${escapeShellQuote(decodeURIComponent(username))}"`);
545
+ }
546
+ if (password) {
547
+ args.push(`--${protocol}-proxy-passwd="${escapeShellQuote(decodeURIComponent(password))}"`);
379
548
  }
380
- pending.length = 0;
381
549
  }
382
- const isFunction = (value) => typeof value === 'function';
550
+ const isConstructor = (value) => typeof value === 'function';
551
+ const isDirEnd = (value) => value.endsWith('/') || value.endsWith(path.sep);
552
+ const trimCharEnd = (value) => value.substring(0, value.length - 1);
383
553
  const configureDns = (family, options) => family === 0 ? options : { family, hints: family === 6 ? dns.V4MAPPED : 0 };
384
- const ignoreOpt = (opts, ...values) => !opts?.some(item => values.includes(item));
554
+ const ignoreOpt = (opts, ...values) => !opts?.some(opt => values.some(value => opt === value || opt.startsWith(value + '=')));
385
555
  const escapeQuote = (value) => value.replace(/[\\"]/g, capture => '\\' + capture);
556
+ const rcloneSize = (value) => (0, types_1.isString)(value) ? /^\d+(?:B|K|M|G|T|P)$/.exec(value)?.[0] : undefined;
557
+ const rcloneDuration = (value) => (0, types_1.isString)(value) ? /^\d+(?:h|m|s|ms|ns)$/.exec(value)?.[0] : undefined;
386
558
  class Request extends module_1 {
559
+ static [kRequest] = true;
387
560
  static async purgeMemory(percent = 1, limit = 0, parent) {
388
561
  if (percent >= 1) {
389
562
  resetHttpHost(0);
@@ -403,18 +576,8 @@ class Request extends module_1 {
403
576
  }
404
577
  const { request, download } = settings;
405
578
  if (download?.aria2) {
406
- let { bin, exec, update_status, max_concurrent_downloads, max_connection_per_server, check_integrity, bt_stop_timeout, bt_tracker_connect_timeout, bt_tracker_timeout, min_split_size, disk_cache, lowest_speed_limit, always_resume, file_allocation, conf_path } = download.aria2;
407
- if (bin === false) {
408
- ARIA2.BIN = '';
409
- }
410
- else if (bin && this.isPath(bin = path.resolve(bin), true)) {
411
- ARIA2.BIN = bin;
412
- }
413
- if ((0, types_1.isPlainObject)(exec)) {
414
- let { uid, gid } = exec;
415
- ARIA2.EXEC_UID = (uid = (0, util_1.asInt)(uid)) >= 0 ? uid : undefined;
416
- ARIA2.EXEC_GID = (gid = (0, util_1.asInt)(gid)) >= 0 ? gid : undefined;
417
- }
579
+ let { update_status, max_concurrent_downloads, max_connection_per_server, check_integrity, bt_stop_timeout, bt_tracker_connect_timeout, bt_tracker_timeout, min_split_size, disk_cache, lowest_speed_limit, always_resume, file_allocation, proxy, no_proxy, conf_path } = download.aria2;
580
+ setBinExec(download.aria2, ARIA2);
418
581
  if ((0, types_1.isPlainObject)(update_status)) {
419
582
  const { interval, broadcast_only } = update_status;
420
583
  if (typeof broadcast_only === 'boolean') {
@@ -425,12 +588,12 @@ class Request extends module_1 {
425
588
  if ((update_status = (0, util_1.asInt)(update_status)) >= 0) {
426
589
  ARIA2.UPDATE_STATUS = update_status;
427
590
  }
428
- if ((max_concurrent_downloads = (0, util_1.asInt)(max_concurrent_downloads)) > 0) {
429
- ARIA2.MAX_CONCURRENT_DOWNLOADS = max_concurrent_downloads;
430
- }
431
591
  if (typeof check_integrity === 'boolean') {
432
592
  ARIA2.CHECK_INTEGRITY = check_integrity;
433
593
  }
594
+ if ((max_concurrent_downloads = (0, util_1.asInt)(max_concurrent_downloads)) > 0) {
595
+ ARIA2.MAX_CONCURRENT_DOWNLOADS = max_concurrent_downloads;
596
+ }
434
597
  if ((max_connection_per_server = (0, util_1.asInt)(max_connection_per_server)) > 0) {
435
598
  ARIA2.MAX_CONNECTION_PER_SERVER = max_connection_per_server;
436
599
  }
@@ -466,10 +629,130 @@ class Request extends module_1 {
466
629
  break;
467
630
  }
468
631
  }
632
+ if (proxy) {
633
+ try {
634
+ for (const uri in proxy) {
635
+ const host = new URL(uri);
636
+ ARIA2.PROXY[trimCharEnd(host.protocol)] = { host };
637
+ }
638
+ }
639
+ catch {
640
+ }
641
+ }
642
+ else if (proxy === false) {
643
+ ARIA2.PROXY = {};
644
+ }
645
+ if (no_proxy === '' || (0, types_1.isString)(no_proxy)) {
646
+ ARIA2.NO_PROXY = no_proxy;
647
+ }
469
648
  if (conf_path === '' || (0, types_1.isString)(conf_path) && this.isPath(conf_path = path.resolve(conf_path))) {
470
649
  ARIA2.CONF_PATH = conf_path;
471
650
  }
472
651
  }
652
+ if (download?.rclone) {
653
+ let { check_first, checksum, cutoff_mode, ignore_case_sync, ignore_checksum, ignore_existing, ignore_size, ignore_times, immutable, inplace, max_backlog, max_duration, max_transfer, metadata, modify_window, multi_thread_chunk_size, multi_thread_cutoff, multi_thread_streams, multi_thread_write_buffer_size, no_check_dest, no_traverse, no_update_dir_modtime, refresh_times, size_only, update, fast_list, bind, contimeout, disable_http2, timeout, config } = download.rclone;
654
+ setBinExec(download.rclone, RCLONE);
655
+ if (typeof check_first === 'boolean') {
656
+ RCLONE.CHECK_FIRST = check_first;
657
+ }
658
+ if (typeof checksum === 'boolean') {
659
+ RCLONE.CHECKSUM = checksum;
660
+ }
661
+ if ((0, types_1.isString)(cutoff_mode)) {
662
+ const value = cutoff_mode.toUpperCase();
663
+ switch (value) {
664
+ case 'HARD':
665
+ case 'SOFT':
666
+ case 'CAUTIOUS':
667
+ RCLONE.CUTOFF_MODE = value;
668
+ break;
669
+ }
670
+ }
671
+ if (typeof ignore_case_sync === 'boolean') {
672
+ RCLONE.IGNORE_CASE_SYNC = ignore_case_sync;
673
+ }
674
+ if (typeof ignore_checksum === 'boolean') {
675
+ RCLONE.IGNORE_CHECKSUM = ignore_checksum;
676
+ }
677
+ if (typeof ignore_existing === 'boolean') {
678
+ RCLONE.IGNORE_EXISTING = ignore_existing;
679
+ }
680
+ if (typeof ignore_size === 'boolean') {
681
+ RCLONE.IGNORE_SIZE = ignore_size;
682
+ }
683
+ if (typeof ignore_times === 'boolean') {
684
+ RCLONE.IGNORE_TIMES = ignore_times;
685
+ }
686
+ if (typeof immutable === 'boolean') {
687
+ RCLONE.IMMUTABLE = immutable;
688
+ }
689
+ if (typeof inplace === 'boolean') {
690
+ RCLONE.INPLACE = inplace;
691
+ }
692
+ if ((max_backlog = (0, util_1.asInt)(max_backlog)) > 0) {
693
+ RCLONE.MAX_BACKLOG = max_backlog;
694
+ }
695
+ if (max_duration = rcloneDuration(max_duration)) {
696
+ RCLONE.MAX_DURATION = max_duration;
697
+ }
698
+ if (max_transfer = rcloneSize(max_transfer)) {
699
+ RCLONE.MAX_TRANSFER = max_transfer;
700
+ }
701
+ if (typeof metadata === 'boolean') {
702
+ RCLONE.METADATA = metadata;
703
+ }
704
+ if (modify_window = rcloneDuration(modify_window)) {
705
+ RCLONE.MODIFY_WINDOW = modify_window;
706
+ }
707
+ if (multi_thread_chunk_size = rcloneSize(multi_thread_chunk_size)) {
708
+ RCLONE.MULTI_THREAD_CHUNK_SIZE = multi_thread_chunk_size;
709
+ }
710
+ if (multi_thread_cutoff = rcloneSize(multi_thread_cutoff)) {
711
+ RCLONE.MULTI_THREAD_CUTOFF = multi_thread_cutoff;
712
+ }
713
+ if ((multi_thread_streams = (0, util_1.asInt)(multi_thread_streams)) > 0) {
714
+ RCLONE.MULTI_THREAD_STREAMS = multi_thread_streams;
715
+ }
716
+ if (multi_thread_write_buffer_size = rcloneSize(multi_thread_write_buffer_size)) {
717
+ RCLONE.MULTI_THREAD_WRITE_BUFFER_SIZE = multi_thread_write_buffer_size;
718
+ }
719
+ if (typeof no_check_dest === 'boolean') {
720
+ RCLONE.NO_CHECK_DEST = no_check_dest;
721
+ }
722
+ if (typeof no_traverse === 'boolean') {
723
+ RCLONE.NO_TRAVERSE = no_traverse;
724
+ }
725
+ if (typeof no_update_dir_modtime === 'boolean') {
726
+ RCLONE.NO_UPDATE_DIR_MODTIME = no_update_dir_modtime;
727
+ }
728
+ if (typeof refresh_times === 'boolean') {
729
+ RCLONE.REFRESH_TIMES = refresh_times;
730
+ }
731
+ if (typeof size_only === 'boolean') {
732
+ RCLONE.SIZE_ONLY = size_only;
733
+ }
734
+ if (typeof update === 'boolean') {
735
+ RCLONE.UPDATE = update;
736
+ }
737
+ if (typeof fast_list === 'boolean') {
738
+ RCLONE.FAST_LIST = fast_list;
739
+ }
740
+ if (contimeout = rcloneDuration(contimeout)) {
741
+ RCLONE.CONTIMEOUT = contimeout;
742
+ }
743
+ if (typeof bind === 'string') {
744
+ RCLONE.BIND = bind;
745
+ }
746
+ if (typeof disable_http2 === 'boolean') {
747
+ RCLONE.DISABLE_HTTP2 = disable_http2;
748
+ }
749
+ if (timeout = rcloneDuration(timeout)) {
750
+ RCLONE.TIMEOUT = timeout;
751
+ }
752
+ if (config === '' || (0, types_1.isString)(config) && this.isPath(config = path.resolve(config), true)) {
753
+ RCLONE.CONFIG = config;
754
+ }
755
+ }
473
756
  if (request) {
474
757
  let { read_timeout, agent, use, headers, certs } = request, agent_timeout;
475
758
  if ((read_timeout = (0, util_1.fromSeconds)(read_timeout)) >= 0) {
@@ -585,42 +868,51 @@ class Request extends module_1 {
585
868
  }
586
869
  }
587
870
  static defineHttpAdapter(module) {
588
- if (isFunction(module) && module.prototype instanceof adapter_1) {
871
+ if (isConstructor(module) && module.prototype instanceof adapter_1) {
589
872
  HTTP_ADAPTER = module;
590
873
  }
591
874
  }
592
875
  static getAria2Path() {
593
876
  return ARIA2.BIN;
594
877
  }
878
+ static getRclonePath() {
879
+ return RCLONE.BIN;
880
+ }
881
+ startTime = Date.now();
882
+ acceptEncoding;
883
+ keepAlive;
884
+ readExpect = 'none';
885
+ readTimeout;
886
+ proxy = null;
887
+ module;
888
+ _moduleName = "request";
889
+ _threadable = true;
890
+ _config = {
891
+ timeout: 60000,
892
+ connectTimeout: 20 * 1000,
893
+ redirectLimit: 10,
894
+ retryWait: 1000,
895
+ retryAfter: 30 * 1000,
896
+ retryLimit: 5
897
+ };
898
+ #singleton = false;
899
+ #httpVersion = null;
900
+ #ipVersion;
901
+ #agentTimeout;
902
+ #headers = null;
903
+ #certs = null;
904
+ #baseUrl = null;
905
+ #connectDns = Object.create(null);
906
+ #pendingDns = Object.create(null);
907
+ #connectHttp = [{}, {}];
908
+ #statusOn = null;
909
+ #headersOn = null;
910
+ #adapter = HTTP_ADAPTER;
911
+ #downloading = new Set();
912
+ #hostInfo = {};
913
+ #session = [Object.create(null)];
595
914
  constructor(data) {
596
915
  super();
597
- this.startTime = Date.now();
598
- this.readExpect = 'none';
599
- this.proxy = null;
600
- this._moduleName = "request";
601
- this._threadable = true;
602
- this._config = {
603
- timeout: 60000,
604
- connectTimeout: 20 * 1000,
605
- redirectLimit: 10,
606
- retryWait: 1000,
607
- retryAfter: 30 * 1000,
608
- retryLimit: 5
609
- };
610
- this[_a] = false;
611
- this[_b] = null;
612
- this[_c] = null;
613
- this[_d] = null;
614
- this[_e] = null;
615
- this[_f] = Object.create(null);
616
- this[_g] = Object.create(null);
617
- this[_h] = [{}, {}];
618
- this[_j] = null;
619
- this[_k] = null;
620
- this[_l] = HTTP_ADAPTER;
621
- this[_m] = new Set();
622
- this[_o] = {};
623
- this[_p] = [Object.create(null)];
624
916
  if ((0, types_1.isPlainObject)(data)) {
625
917
  const { headers, read_timeout, agent, use, connect, certs } = data;
626
918
  const timeout = (0, util_1.fromSeconds)(data.timeout);
@@ -629,14 +921,14 @@ class Request extends module_1 {
629
921
  this.keepAlive = typeof (value = agent?.keep_alive) === 'boolean' ? value : KEEP_ALIVE;
630
922
  this.acceptEncoding = typeof (value = use?.accept_encoding) === 'boolean' ? value : ACCEPT_ENCODING;
631
923
  if ((value = (0, util_1.asInt)(use?.http_version)) === 1 || value === 2) {
632
- this[kHttpVersion] = value;
924
+ this.#httpVersion = value;
633
925
  }
634
- this[kIpVersion] = (value = (0, util_1.asInt)(data.dns?.family)) && (value === 4 || value === 6) ? value : 0;
926
+ this.#ipVersion = (value = (0, util_1.asInt)(data.dns?.family)) && (value === 4 || value === 6) ? value : 0;
635
927
  if ((value = (0, util_1.fromSeconds)(agent?.timeout)) >= 0) {
636
- this[kAgentTimeout] = value;
928
+ this.#agentTimeout = value;
637
929
  }
638
930
  else {
639
- this[kAgentTimeout] = AGENT_TIMEOUT;
931
+ this.#agentTimeout = AGENT_TIMEOUT;
640
932
  value = undefined;
641
933
  }
642
934
  const proxy = getProxySettings(data, value);
@@ -644,10 +936,10 @@ class Request extends module_1 {
644
936
  this.proxy = proxy;
645
937
  }
646
938
  if ((0, types_1.isObject)(headers)) {
647
- setOutgoingHeaders(this[kHeaders] = {}, headers);
939
+ setOutgoingHeaders(this.#headers = {}, headers);
648
940
  }
649
941
  if ((0, types_1.isObject)(certs)) {
650
- this[kCerts] = validateCerts(certs);
942
+ this.#certs = validateCerts(certs);
651
943
  }
652
944
  if ((0, types_1.isObject)(connect)) {
653
945
  this.apply({ client: {
@@ -668,21 +960,21 @@ class Request extends module_1 {
668
960
  this.readTimeout = READ_TIMEOUT;
669
961
  this.keepAlive = KEEP_ALIVE;
670
962
  this.acceptEncoding = ACCEPT_ENCODING;
671
- this[kAgentTimeout] = AGENT_TIMEOUT;
672
- this[kIpVersion] = DNS.FAMILY;
963
+ this.#agentTimeout = AGENT_TIMEOUT;
964
+ this.#ipVersion = DNS.FAMILY;
673
965
  }
674
966
  this.module = data;
675
967
  }
676
968
  flushLog() {
677
969
  const log = this._logQueued;
678
- if (this[kSingleton]) {
970
+ if (this.#singleton) {
679
971
  log.length = 0;
680
972
  }
681
973
  else {
682
974
  if (log.length > 0 && !this.host?.aborted) {
683
975
  const output = [];
684
976
  let count = 0;
685
- this[kConnectHttp].forEach((protocol, index) => {
977
+ this.#connectHttp.forEach((protocol, index) => {
686
978
  const title = 'HTTP' + (index + 1);
687
979
  for (const origin in protocol) {
688
980
  const value = protocol[origin];
@@ -731,22 +1023,22 @@ class Request extends module_1 {
731
1023
  }
732
1024
  super.flushLog();
733
1025
  }
734
- this[kConnectHttp] = [{}, {}];
1026
+ this.#connectHttp = [{}, {}];
735
1027
  }
736
1028
  detach(singleton) {
737
1029
  if (typeof singleton === 'boolean') {
738
- this[kSingleton] = singleton;
1030
+ this.#singleton = singleton;
739
1031
  }
740
1032
  if (singleton !== false) {
741
1033
  super.detach();
742
1034
  }
743
1035
  }
744
1036
  abort(reason) {
745
- for (const item of this[kDownloading]) {
1037
+ for (const item of this.#downloading) {
746
1038
  item.abort(reason);
747
1039
  }
748
1040
  this.close();
749
- if (!this[kSingleton]) {
1041
+ if (!this.#singleton) {
750
1042
  super.abort(reason);
751
1043
  }
752
1044
  }
@@ -754,7 +1046,7 @@ class Request extends module_1 {
754
1046
  if (config) {
755
1047
  const { headers, httpVersion, ipVersion, readTimeout } = config;
756
1048
  if ((0, types_1.isObject)(headers)) {
757
- setOutgoingHeaders(this[kHeaders] ||= {}, headers);
1049
+ setOutgoingHeaders(this.#headers ||= {}, headers);
758
1050
  }
759
1051
  if (httpVersion !== undefined) {
760
1052
  this.httpVersion = httpVersion;
@@ -841,10 +1133,10 @@ class Request extends module_1 {
841
1133
  }
842
1134
  break;
843
1135
  }
844
- setDnsCache(hostname, this[kConnectDns][hostname] = [{ address, family }], timeout);
1136
+ setDnsCache(hostname, this.#connectDns[hostname] = [{ address, family }], timeout);
845
1137
  }
846
1138
  lookupDns(hostname) {
847
- const resolved = this[kConnectDns][hostname] || DNS.CACHE[hostname];
1139
+ const resolved = this.#connectDns[hostname] || DNS.CACHE[hostname];
848
1140
  if (resolved) {
849
1141
  return (...args) => {
850
1142
  if (SUPPORTED_NODE20) {
@@ -855,13 +1147,29 @@ class Request extends module_1 {
855
1147
  }
856
1148
  };
857
1149
  }
858
- const pending = this[kPendingDns][hostname] ||= [];
1150
+ const pending = this.#pendingDns[hostname] ||= [];
1151
+ const successDns = (value, connected) => {
1152
+ this.#connectDns[value] = connected;
1153
+ setDnsCache(value, connected, null);
1154
+ if (SUPPORTED_NODE20) {
1155
+ for (const cb of pending) {
1156
+ cb(null, connected);
1157
+ }
1158
+ }
1159
+ else {
1160
+ const { address, family } = connected[0];
1161
+ for (const cb of pending) {
1162
+ cb(null, address, family);
1163
+ }
1164
+ }
1165
+ pending.length = 0;
1166
+ };
859
1167
  return (value, options, callback) => {
860
1168
  if (pending.push(callback) === 1) {
861
1169
  let ipVersion = this.ipVersion;
862
1170
  dns.lookup(value, configureDns(ipVersion, options), (err, address, family) => {
863
1171
  if (!err) {
864
- successDns(this, value, pending, typeof address === 'string' ? [{ address, family }] : address);
1172
+ successDns(value, typeof address === 'string' ? [{ address, family }] : address);
865
1173
  return;
866
1174
  }
867
1175
  switch (err.code) {
@@ -886,7 +1194,7 @@ class Request extends module_1 {
886
1194
  }
887
1195
  dns.lookup(value, configureDns(ipVersion, options), (err, address, family) => {
888
1196
  if (!err) {
889
- successDns(this, value, pending, typeof address === 'string' ? [{ address, family }] : address);
1197
+ successDns(value, typeof address === 'string' ? [{ address, family }] : address);
890
1198
  }
891
1199
  else {
892
1200
  failedDns(err, pending);
@@ -932,7 +1240,7 @@ class Request extends module_1 {
932
1240
  globUrl = '*';
933
1241
  }
934
1242
  if ((0, types_1.isString)(globUrl) && typeof callback === 'function') {
935
- const on = this[kStatusOn] ||= new Map();
1243
+ const on = this.#statusOn ||= new Map();
936
1244
  for (const item of !Array.isArray(code) ? [code] : code) {
937
1245
  let status = on.get(item);
938
1246
  if (!status) {
@@ -948,7 +1256,7 @@ class Request extends module_1 {
948
1256
  globUrl = '*';
949
1257
  }
950
1258
  if ((0, types_1.isString)(globUrl) && typeof callback === 'function') {
951
- const on = this[kHeadersOn] ||= new Map();
1259
+ const on = this.#headersOn ||= new Map();
952
1260
  for (const item of !Array.isArray(name) ? [name] : name) {
953
1261
  let headers = on.get(item);
954
1262
  if (!headers) {
@@ -959,86 +1267,31 @@ class Request extends module_1 {
959
1267
  }
960
1268
  }
961
1269
  headersOf(uri) {
962
- const headers = this[kHeaders];
1270
+ const headers = this.#headers;
963
1271
  return headers && getBaseHeaders(uri, headers) || (this.host ? getBaseHeaders(uri, HTTP.HEADERS) : undefined);
964
1272
  }
965
- async aria2c(uri, options) {
1273
+ async aria2c(uri, options = {}) {
966
1274
  if (!ARIA2.BIN) {
967
1275
  return Promise.reject((0, types_1.errorMessage)("aria2", "Binary not found"));
968
1276
  }
969
- if (typeof uri === 'string' && module_1.isURL(uri)) {
970
- uri = new URL(uri);
971
- }
972
1277
  let pathname, headers, binOpts, signal, silent;
973
- if (options) {
974
- if (typeof options === 'string') {
975
- pathname = options;
976
- }
977
- else {
978
- ({ pathname, binOpts, signal, silent } = options);
979
- headers = (0, util_1.parseOutgoingHeaders)(options.headers);
980
- if ((0, types_1.isArray)(binOpts)) {
981
- let next = false;
982
- binOpts = binOpts.filter(opt => !((0, types_1.isString)(opt) && /^-[a-z].*$/i.test(opt.trim()))).map((opt) => {
983
- if (next) {
984
- if (!module_1.asString(opt).startsWith('--')) {
985
- return [];
986
- }
987
- next = false;
988
- }
989
- switch (typeof opt) {
990
- case 'string': {
991
- const value = opt.trim();
992
- if (value.startsWith('--')) {
993
- const match = /^(--[a-z]+[a-z0-9-]*)(=)?\s*(.*)$/s.exec(value);
994
- if (match) {
995
- switch (match[1]) {
996
- case '--daemon':
997
- case '--version':
998
- case '--help':
999
- break;
1000
- case '--input-file':
1001
- if (!match[2]) {
1002
- next = true;
1003
- }
1004
- break;
1005
- default:
1006
- return match[3] ? [match[1], module_1.sanitizeArgs(match[3])] : [match[1]];
1007
- }
1008
- }
1009
- }
1010
- else if (value) {
1011
- return [module_1.sanitizeArgs(value)];
1012
- }
1013
- break;
1014
- }
1015
- case 'number':
1016
- case 'boolean':
1017
- return [opt.toString()];
1018
- default:
1019
- if ((0, types_1.isArray)(opt)) {
1020
- return opt.filter(item => (0, types_1.isString)(item)).map(item => module_1.sanitizeArgs(item));
1021
- }
1022
- break;
1023
- }
1024
- return [];
1025
- }).flat();
1026
- }
1027
- }
1278
+ if ((0, types_1.isString)(options)) {
1279
+ pathname = options;
1028
1280
  }
1029
- if (!pathname) {
1030
- if (this.host) {
1031
- return Promise.reject((0, types_1.errorMessage)("aria2", "Invalid parameters", 'pathname'));
1032
- }
1033
- pathname = process.cwd();
1281
+ else {
1282
+ ({ signal, silent } = options);
1283
+ [pathname, headers, binOpts] = parseBinOpts(this, options, ['--daemon'], ['--input-file']);
1034
1284
  }
1035
- if ((this.host || this.hasOwnPermission()) && !this.canWrite(pathname = path.resolve(pathname.trim()))) {
1036
- return Promise.reject((0, types_1.errorMessage)("aria2", "Unsupported access", pathname));
1285
+ try {
1286
+ if (typeof uri === 'string' && module_1.isURL(uri)) {
1287
+ uri = new URL(uri);
1288
+ }
1289
+ pathname = checkBinTarget(this, "aria2", uri, pathname, 'aria2', binOpts);
1037
1290
  }
1038
- if (!module_1.createDir(pathname)) {
1039
- return Promise.reject((0, types_1.errorMessage)("aria2", "Path is not a directory", pathname));
1291
+ catch (err) {
1292
+ return Promise.reject(err);
1040
1293
  }
1041
- silent ??= this[kSingleton];
1294
+ silent ??= this.#singleton;
1042
1295
  return new Promise((resolve, reject) => {
1043
1296
  let protocol, origin, username, password;
1044
1297
  if (uri instanceof URL) {
@@ -1059,31 +1312,7 @@ class Request extends module_1 {
1059
1312
  '--stderr=false',
1060
1313
  '--log=""'
1061
1314
  ];
1062
- let args = [];
1063
- if ((0, types_1.isArray)(binOpts)) {
1064
- for (let i = 0; i < binOpts.length; ++i) {
1065
- const leading = binOpts[i] + '=';
1066
- for (const arg of init) {
1067
- if (arg.startsWith(leading)) {
1068
- const items = [];
1069
- for (let k = i + 1; k < binOpts.length; ++k) {
1070
- const next = binOpts[k];
1071
- if (next.startsWith('--')) {
1072
- break;
1073
- }
1074
- items.push(next);
1075
- }
1076
- const l = items.length + 1;
1077
- binOpts.splice(i, l);
1078
- i += l;
1079
- break;
1080
- }
1081
- }
1082
- }
1083
- }
1084
- else {
1085
- binOpts = undefined;
1086
- }
1315
+ checkBinOpts(init, binOpts);
1087
1316
  const { connectTimeout, timeout, retryWait, retryLimit } = this._config;
1088
1317
  const opts = [
1089
1318
  '--log-level=warn',
@@ -1093,6 +1322,7 @@ class Request extends module_1 {
1093
1322
  '--file-allocation=' + ARIA2.FILE_ALLOCATION,
1094
1323
  '--max-tries=' + (retryLimit + 1)
1095
1324
  ];
1325
+ let args = [];
1096
1326
  if (ARIA2.MAX_CONCURRENT_DOWNLOADS) {
1097
1327
  opts.push('--max-concurrent-downloads=' + ARIA2.MAX_CONCURRENT_DOWNLOADS);
1098
1328
  }
@@ -1126,6 +1356,10 @@ class Request extends module_1 {
1126
1356
  if (retryWait > 0) {
1127
1357
  opts.push('--retry-wait=' + Math.min(Math.ceil(retryWait / 1000), 600));
1128
1358
  }
1359
+ if (ARIA2.NO_PROXY) {
1360
+ opts.push(`--no-proxy="${ARIA2.NO_PROXY}"`);
1361
+ }
1362
+ let proxy;
1129
1363
  if (protocol) {
1130
1364
  if (this.agentTimeout === 0) {
1131
1365
  opts.push('--enable-http-keep-alive=false');
@@ -1135,16 +1369,10 @@ class Request extends module_1 {
1135
1369
  if (baseHeaders) {
1136
1370
  headers = headers ? { ...baseHeaders, ...headers } : baseHeaders;
1137
1371
  }
1138
- for (const name in headers) {
1139
- let items = headers[name];
1140
- if (!Array.isArray(items)) {
1141
- items = [items.toString()];
1142
- }
1143
- args.push(...items.map(value => `--header="${name}: ${escapeShellQuote(value)}"`));
1144
- }
1372
+ setBinHeaders(args, headers);
1145
1373
  }
1146
1374
  if (origin) {
1147
- const secure = this[kCerts]?.[1][origin] || this.host && TLS.FILE[origin];
1375
+ const secure = this.#certs?.[1][origin] || this.host && TLS.FILE[origin];
1148
1376
  if (secure) {
1149
1377
  if (secure.ca && ignoreOpt(binOpts, '--ca-certificate')) {
1150
1378
  args.push(`--ca-certificate="${escapeShellQuote(secure.ca)}"`);
@@ -1157,7 +1385,7 @@ class Request extends module_1 {
1157
1385
  }
1158
1386
  }
1159
1387
  }
1160
- switch (protocol = protocol.substring(0, protocol.length - 1)) {
1388
+ switch (protocol = trimCharEnd(protocol)) {
1161
1389
  case 'http':
1162
1390
  case 'https':
1163
1391
  if (ignoreOpt(binOpts, '--http-no-cache')) {
@@ -1173,54 +1401,33 @@ class Request extends module_1 {
1173
1401
  args.push(`--${prefix}-passwd="${escapeShellQuote(decodeURIComponent(password))}"`);
1174
1402
  }
1175
1403
  }
1176
- const proxy = this.proxyOf(uri);
1177
- if (proxy && ignoreOpt(binOpts, `--${protocol}-proxy-user`, `--${protocol}-proxy-passwd`)) {
1178
- ({ origin, username, password } = proxy.host);
1179
- if (ignoreOpt(binOpts, `--${protocol}-proxy`)) {
1180
- args.push(`--${protocol}-proxy="${origin}"`);
1181
- }
1182
- if (username) {
1183
- args.push(`--${protocol}-proxy-user="${escapeShellQuote(decodeURIComponent(username))}"`);
1184
- }
1185
- if (password) {
1186
- args.push(`--${protocol}-proxy-passwd="${escapeShellQuote(decodeURIComponent(password))}"`);
1187
- }
1404
+ if (ignoreOpt(binOpts, `--${protocol}-proxy`, `--${protocol}-proxy-user`, `--${protocol}-proxy-passwd`)) {
1405
+ proxy = this.proxyOf(uri) || ARIA2.PROXY[protocol];
1188
1406
  }
1189
1407
  break;
1190
1408
  }
1191
1409
  }
1192
1410
  }
1193
- if (binOpts) {
1194
- for (const leading of binOpts) {
1195
- if (leading.startsWith('-')) {
1196
- const pattern = new RegExp(`^${leading}(?:=|$)`);
1197
- for (let i = 0; i < opts.length; ++i) {
1198
- if (pattern.test(opts[i])) {
1199
- opts.splice(i--, i);
1200
- break;
1201
- }
1202
- }
1203
- }
1204
- }
1205
- args = binOpts.concat(args);
1411
+ if (proxy) {
1412
+ addAria2Proxy(args, protocol, proxy.host);
1206
1413
  }
1207
- if (args.length > 0) {
1208
- if (module_1.hasLogType(32768)) {
1209
- this.formatMessage(32768, 'ARIA2', ARIA2.BIN, args.join(' '), { ...module_1.LOG_STYLE_WARN });
1210
- }
1211
- else {
1212
- this.addLog(types_1.STATUS_TYPE.INFO, path.basename(ARIA2.BIN) + ' ' + args.join(' '), "aria2");
1213
- }
1414
+ else if (ARIA2.PROXY.all) {
1415
+ addAria2Proxy(opts, 'all', ARIA2.PROXY.all.host);
1214
1416
  }
1417
+ args = finalizeBinArgs(this, "aria2", ARIA2.BIN, args, opts, binOpts);
1215
1418
  opts.push(`"${escapeShellQuote(uri)}"`);
1216
1419
  args = args.concat(init, opts);
1217
1420
  const startTime = Date.now();
1218
1421
  let out = '', message = '';
1422
+ const commitLog = (type, msg) => {
1423
+ const timeStamp = Date.now();
1424
+ this.addLog(type, msg, { timeStamp, duration: timeStamp - startTime, from: "aria2", source: uri });
1425
+ };
1219
1426
  const errorResponse = (pid, err) => {
1220
1427
  closeTorrent(pid);
1221
1428
  reject(err);
1222
1429
  };
1223
- const { pid, stdout, stderr } = child_process.spawn(module_1.sanitizeCmd(ARIA2.BIN), args, { cwd: pathname, shell: true, signal: this.signal, uid: ARIA2.EXEC_UID, gid: ARIA2.EXEC_GID })
1430
+ const { pid, stdout, stderr } = child_process.spawn((0, types_1.sanitizeCmd)(ARIA2.BIN), args, { cwd: pathname, shell: true, signal: signal || this.signal, uid: ARIA2.EXEC_UID, gid: ARIA2.EXEC_GID })
1224
1431
  .on('exit', code => {
1225
1432
  closeTorrent(pid);
1226
1433
  if (this.aborted) {
@@ -1231,7 +1438,6 @@ class Request extends module_1 {
1231
1438
  reject((0, types_1.errorValue)(message || "Unknown", 'Exit status: ' + code));
1232
1439
  return;
1233
1440
  }
1234
- const currentTime = Date.now();
1235
1441
  const result = [];
1236
1442
  let messageUnit;
1237
1443
  for (const match of out.matchAll(/\|(OK|ERR|INPR)\s*\|\s*([^|]+)\|\s*(\d+)\|([^\n]+)/g)) {
@@ -1250,7 +1456,7 @@ class Request extends module_1 {
1250
1456
  }
1251
1457
  case 'ERR':
1252
1458
  fs.unlink(file, err => {
1253
- if (err && !silent && !this[kSingleton]) {
1459
+ if (err && !silent && !this.#singleton) {
1254
1460
  this.writeFail(["Unable to delete file", path.basename(file)], err, { type: 32, fatal: false });
1255
1461
  }
1256
1462
  });
@@ -1262,18 +1468,18 @@ class Request extends module_1 {
1262
1468
  if (!silent && LOG_HTTP && LOG_TIMEPROCESS) {
1263
1469
  this.writeTimeProcess("aria2", uri, startTime, { type: 1024, queue: true, messageUnit, messageUnitMinWidth: 9, bypassLog: true });
1264
1470
  }
1265
- this.addLog(types_1.STATUS_TYPE.INFO, out, currentTime, currentTime - startTime, "aria2", uri);
1471
+ commitLog(types_1.STATUS_TYPE.INFO, out);
1266
1472
  }
1267
1473
  else {
1268
- this.addLog(types_1.STATUS_TYPE.ERROR, "No files were successfully downloaded", currentTime, currentTime - startTime, "aria2", uri);
1474
+ commitLog(types_1.STATUS_TYPE.ERROR, "No files were successfully downloaded");
1269
1475
  }
1270
1476
  resolve(result);
1271
1477
  })
1272
1478
  .on('error', err => {
1273
1479
  errorResponse(pid, err);
1274
1480
  });
1275
- stdout.setEncoding('utf-8').on('data', (value) => out += value);
1276
- stderr.setEncoding('utf-8').on('data', (value) => message += value);
1481
+ stdout.setEncoding('utf8').on('data', (value) => out += value);
1482
+ stderr.setEncoding('utf8').on('data', (value) => message += value);
1277
1483
  if (pid !== undefined && module_1.isFile(uri, 'torrent')) {
1278
1484
  if (!ARIA2.PID_TIMER) {
1279
1485
  ARIA2.PID_TIMER = setInterval(() => {
@@ -1320,6 +1526,231 @@ class Request extends module_1 {
1320
1526
  }
1321
1527
  });
1322
1528
  }
1529
+ async rclone(uri, options = {}) {
1530
+ if (!RCLONE.BIN) {
1531
+ return Promise.reject((0, types_1.errorMessage)("rclone", "Binary not found"));
1532
+ }
1533
+ let pathname, headers, binOpts, silent;
1534
+ if ((0, types_1.isString)(options)) {
1535
+ pathname = options;
1536
+ options = {};
1537
+ }
1538
+ else {
1539
+ silent = options.silent;
1540
+ [pathname, headers, binOpts] = parseBinOpts(this, options, ['--interactive', '--dry-run'], ['--partial-suffix', '--verbose']);
1541
+ }
1542
+ const command = options.command || 'copy';
1543
+ let source;
1544
+ switch (command) {
1545
+ case 'copy':
1546
+ case 'copyto':
1547
+ if (module_1.isURL(source = uri.replace(/^rclone:\?/i, ''))) {
1548
+ return Promise.reject((0, types_1.errorMessage)("rclone", "Unsupported protocol", uri));
1549
+ }
1550
+ break;
1551
+ case 'copyurl':
1552
+ if (!module_1.isURL(source = uri)) {
1553
+ return Promise.reject((0, types_1.errorMessage)("rclone", "Unsupported protocol", uri));
1554
+ }
1555
+ break;
1556
+ default:
1557
+ return Promise.reject((0, types_1.errorMessage)("rclone", "Invalid command", command || uri));
1558
+ }
1559
+ try {
1560
+ pathname = checkBinTarget(this, "rclone", uri, pathname, command, binOpts);
1561
+ }
1562
+ catch (err) {
1563
+ return Promise.reject(err);
1564
+ }
1565
+ silent ??= this.#singleton;
1566
+ return new Promise((resolve, reject) => {
1567
+ const init = [
1568
+ '--links=false',
1569
+ '--delete-excluded=false',
1570
+ '--interactive=false',
1571
+ '--dry-run=false',
1572
+ '--log-level=INFO',
1573
+ '--use-json-log'
1574
+ ];
1575
+ const opts = [];
1576
+ let args = [];
1577
+ if (typeof options.update === 'boolean') {
1578
+ init.push('--update=' + options.update.toString());
1579
+ checkBinOpts(init, binOpts);
1580
+ }
1581
+ else {
1582
+ checkBinOpts(init, binOpts);
1583
+ if (RCLONE.UPDATE) {
1584
+ opts.push('--update');
1585
+ }
1586
+ }
1587
+ if (RCLONE.CHECK_FIRST) {
1588
+ opts.push('--check-first');
1589
+ }
1590
+ if (RCLONE.CHECKSUM) {
1591
+ opts.push('--checksum');
1592
+ }
1593
+ if (RCLONE.CUTOFF_MODE) {
1594
+ opts.push('--cutoff-mode=' + RCLONE.CUTOFF_MODE);
1595
+ }
1596
+ if (RCLONE.IGNORE_CASE_SYNC) {
1597
+ opts.push('--ignore-case-sync');
1598
+ }
1599
+ if (RCLONE.IGNORE_CHECKSUM) {
1600
+ opts.push('--ignore-checksum');
1601
+ }
1602
+ if (RCLONE.IGNORE_EXISTING) {
1603
+ opts.push('--ignore-existing');
1604
+ }
1605
+ if (RCLONE.IGNORE_SIZE) {
1606
+ opts.push('--ignore-size');
1607
+ }
1608
+ if (RCLONE.IGNORE_TIMES) {
1609
+ opts.push('--ignore-times');
1610
+ }
1611
+ if (RCLONE.IMMUTABLE) {
1612
+ opts.push('--immutable');
1613
+ }
1614
+ if (RCLONE.INPLACE) {
1615
+ opts.push('--inplace');
1616
+ }
1617
+ if (RCLONE.MAX_BACKLOG > 0) {
1618
+ opts.push('--max-backlog=' + RCLONE.MAX_BACKLOG);
1619
+ }
1620
+ if (RCLONE.MAX_DURATION) {
1621
+ opts.push('--max-duration=' + RCLONE.MAX_DURATION);
1622
+ }
1623
+ if (RCLONE.MAX_TRANSFER) {
1624
+ opts.push('--max-transfer=' + RCLONE.MAX_TRANSFER);
1625
+ }
1626
+ if (RCLONE.METADATA) {
1627
+ opts.push('--metadata');
1628
+ }
1629
+ if (RCLONE.MODIFY_WINDOW) {
1630
+ opts.push('--modify-window=' + RCLONE.MODIFY_WINDOW);
1631
+ }
1632
+ if (RCLONE.MULTI_THREAD_CHUNK_SIZE) {
1633
+ opts.push('--multi-thread-chunk-size=' + RCLONE.MULTI_THREAD_CHUNK_SIZE);
1634
+ }
1635
+ if (RCLONE.MULTI_THREAD_CUTOFF) {
1636
+ opts.push('--multi-thread-chunk-size=' + RCLONE.MULTI_THREAD_CUTOFF);
1637
+ }
1638
+ if (RCLONE.MULTI_THREAD_STREAMS) {
1639
+ opts.push('--multi-thread-streams=' + RCLONE.MULTI_THREAD_STREAMS);
1640
+ }
1641
+ if (RCLONE.MULTI_THREAD_WRITE_BUFFER_SIZE) {
1642
+ opts.push('--multi-thread-buffer-size=' + RCLONE.MULTI_THREAD_WRITE_BUFFER_SIZE);
1643
+ }
1644
+ if (RCLONE.NO_CHECK_DEST) {
1645
+ opts.push('--no-check-dest');
1646
+ }
1647
+ if (RCLONE.NO_TRAVERSE) {
1648
+ opts.push('--no-traverse');
1649
+ }
1650
+ if (RCLONE.NO_UPDATE_DIR_MODTIME) {
1651
+ opts.push('--no-update-dir-modtime');
1652
+ }
1653
+ if (RCLONE.REFRESH_TIMES) {
1654
+ opts.push('--refresh-times');
1655
+ }
1656
+ if (RCLONE.SIZE_ONLY) {
1657
+ opts.push('--size-only');
1658
+ }
1659
+ if (RCLONE.FAST_LIST) {
1660
+ opts.push('--fast-list');
1661
+ }
1662
+ if (RCLONE.BIND) {
1663
+ opts.push('--bind=' + RCLONE.BIND);
1664
+ }
1665
+ if (RCLONE.CONTIMEOUT) {
1666
+ opts.push('--contimeout=' + RCLONE.CONTIMEOUT);
1667
+ }
1668
+ else if (this._config.connectTimeout > 0) {
1669
+ opts.push(`--contimeout=${this._config.connectTimeout}ms`);
1670
+ }
1671
+ if (RCLONE.DISABLE_HTTP2) {
1672
+ opts.push('--disable-http2');
1673
+ }
1674
+ if (RCLONE.TIMEOUT) {
1675
+ opts.push('--timeout=' + RCLONE.TIMEOUT);
1676
+ }
1677
+ else if (this._config.timeout > 0) {
1678
+ opts.push(`--timeout=${this._config.timeout}ms`);
1679
+ }
1680
+ if (RCLONE.CONFIG) {
1681
+ opts.push(`--config="${escapeShellQuote(RCLONE.CONFIG)}"`);
1682
+ }
1683
+ setBinHeaders(args, headers);
1684
+ const cwd = module_1.isDir(pathname) ? pathname : path.dirname(pathname);
1685
+ const cmd = [source, pathname];
1686
+ args = finalizeBinArgs(this, "rclone", RCLONE.BIN, args, opts, binOpts, cmd).concat(init, opts);
1687
+ args.push(...cmd.map(value => (0, types_1.sanitizeCmd)(value)));
1688
+ args.unshift(command);
1689
+ const startTime = Date.now();
1690
+ const out = [];
1691
+ const commitLog = (type, msg) => {
1692
+ const timeStamp = Date.now();
1693
+ this.addLog(type, msg, { timeStamp, duration: timeStamp - startTime, from: "rclone", source });
1694
+ };
1695
+ const parseOutput = (value) => {
1696
+ try {
1697
+ const data = JSON.parse(value);
1698
+ if ((0, types_1.isPlainObject)(data)) {
1699
+ switch (data.level) {
1700
+ case 'info':
1701
+ if (data.size > 0 && (0, types_1.isString)(data.object)) {
1702
+ out.push(data);
1703
+ }
1704
+ else if ((0, types_1.isPlainObject)(data.stats)) {
1705
+ if (data.stats.fatalError) {
1706
+ commitLog(types_1.STATUS_TYPE.ERROR, data.msg);
1707
+ }
1708
+ else {
1709
+ if (command === 'copyurl' && data.stats.totalTransfers > 0) {
1710
+ data.object = module_1.isPath(pathname, true) ? pathname : '';
1711
+ out.push(data);
1712
+ }
1713
+ commitLog(types_1.STATUS_TYPE.INFO, data.msg);
1714
+ }
1715
+ }
1716
+ break;
1717
+ case 'error':
1718
+ commitLog(types_1.STATUS_TYPE.ERROR, data.msg);
1719
+ break;
1720
+ }
1721
+ }
1722
+ }
1723
+ catch (err) {
1724
+ commitLog(types_1.STATUS_TYPE.ERROR, err);
1725
+ }
1726
+ };
1727
+ const { stdout, stderr } = child_process.spawn((0, types_1.sanitizeCmd)(RCLONE.BIN), args, { cwd, shell: true, signal: this.signal, uid: RCLONE.EXEC_UID, gid: RCLONE.EXEC_GID })
1728
+ .on('exit', code => {
1729
+ if (options.signal || this.aborted) {
1730
+ reject((0, types_1.createAbortError)());
1731
+ return;
1732
+ }
1733
+ if (code) {
1734
+ reject((0, types_1.errorValue)("Unknown", 'Exit status: ' + code));
1735
+ return;
1736
+ }
1737
+ if (out.length > 0 && !silent && LOG_HTTP && LOG_TIMEPROCESS) {
1738
+ this.writeTimeProcess("rclone", source, startTime, { type: 1024, queue: true, bypassLog: true });
1739
+ }
1740
+ const result = out.map(item => command === 'copyurl' ? item.object : path.join(cwd, item.object));
1741
+ if (out.length > 0) {
1742
+ commitLog(types_1.STATUS_TYPE.INFO, result);
1743
+ }
1744
+ else {
1745
+ commitLog(types_1.STATUS_TYPE.ERROR, "No files were successfully downloaded");
1746
+ }
1747
+ resolve(result);
1748
+ })
1749
+ .on('error', reject);
1750
+ stdout.setEncoding('utf8').on('data', parseOutput);
1751
+ stderr.setEncoding('utf8').on('data', parseOutput);
1752
+ });
1753
+ }
1323
1754
  async json(uri, options = {}) {
1324
1755
  options.format = 'json';
1325
1756
  return this.get(uri, options);
@@ -1329,7 +1760,7 @@ class Request extends module_1 {
1329
1760
  return this.get(uri, options);
1330
1761
  }
1331
1762
  opts(url, options) {
1332
- const base = this[kBaseURL];
1763
+ const base = this.#baseUrl;
1333
1764
  if (base) {
1334
1765
  if (typeof url === 'string') {
1335
1766
  url = new URL(url, base[0]);
@@ -1346,7 +1777,7 @@ class Request extends module_1 {
1346
1777
  host = HTTP.HOST[url.origin] ||= new host_1(url, HTTP.VERSION);
1347
1778
  }
1348
1779
  else {
1349
- host = this[kHostInfo][url.origin] ||= new host_1(url, this.httpVersion || 1);
1780
+ host = this.#hostInfo[url.origin] ||= new host_1(url, this.httpVersion || 1);
1350
1781
  }
1351
1782
  return { ...options, host, url };
1352
1783
  }
@@ -1397,7 +1828,7 @@ class Request extends module_1 {
1397
1828
  url = uri;
1398
1829
  uri = url.toString();
1399
1830
  }
1400
- const base = this[kBaseURL];
1831
+ const base = this.#baseUrl;
1401
1832
  if (!host) {
1402
1833
  ({ host, url } = this.opts(url || uri, { base: options.base }));
1403
1834
  options.host = host;
@@ -1416,7 +1847,7 @@ class Request extends module_1 {
1416
1847
  options.url = url;
1417
1848
  }
1418
1849
  if (options.base) {
1419
- this[kBaseURL] = [url, httpVersion, headers];
1850
+ this.#baseUrl = [url, httpVersion, headers];
1420
1851
  }
1421
1852
  else if (base) {
1422
1853
  httpVersion ??= base[1];
@@ -1458,13 +1889,13 @@ class Request extends module_1 {
1458
1889
  expectContinue = false;
1459
1890
  }
1460
1891
  if (secure) {
1461
- const certs = this[kCerts]?.[0][origin] || this.host && TLS.TEXT[origin];
1892
+ const certs = this.#certs?.[0][origin] || this.host && TLS.TEXT[origin];
1462
1893
  if (certs) {
1463
1894
  ({ ca, cert, key, ciphers, version: minVersion } = certs);
1464
1895
  }
1465
1896
  }
1466
1897
  if (!proxy && httpVersion !== 1 && ((httpVersion || host.version) === 2 && version !== 1 || secure && version === 2 && host.failed(2, true) === 0)) {
1467
- request = (this[kSession][0][origin] ||= http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, ciphers, minVersion, settings: host.localhost ? { maxFrameSize: 16777215, enablePush: false } : { enablePush: false } })).request({ ...baseHeaders, ...host_1.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
1898
+ request = (this.#session[0][origin] ||= http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, ciphers, minVersion, settings: host.localhost ? { maxFrameSize: 16777215, enablePush: false } : { enablePush: false } })).request({ ...baseHeaders, ...host_1.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
1468
1899
  if (getting) {
1469
1900
  const listenerMap = {};
1470
1901
  const onEvent = request.on.bind(request);
@@ -1473,7 +1904,7 @@ class Request extends module_1 {
1473
1904
  request.on('response', response => {
1474
1905
  const statusCode = response[':status'];
1475
1906
  if (expectContinue) {
1476
- abortHeaders.call(this, url.href, request, options, statusCode, "Did not receive continue acknowledgment");
1907
+ this.abortHeaders(url.href, request, options, statusCode, "Did not receive continue acknowledgment");
1477
1908
  return;
1478
1909
  }
1479
1910
  connected = true;
@@ -1502,7 +1933,7 @@ class Request extends module_1 {
1502
1933
  }
1503
1934
  }
1504
1935
  if (LOG_HTTP) {
1505
- this[kConnectHttp][1][origin] = (this[kConnectHttp][1][origin] || 0) + 1;
1936
+ this.#connectHttp[1][origin] = (this.#connectHttp[1][origin] || 0) + 1;
1506
1937
  }
1507
1938
  }
1508
1939
  this.matchHeaders(url, response, request, options);
@@ -1556,7 +1987,7 @@ class Request extends module_1 {
1556
1987
  try {
1557
1988
  keepAlive ??= proxy.keepAlive;
1558
1989
  agentTimeout ??= proxy.agentTimeout;
1559
- const proxyHeaders = this[kHeaders] && getBaseHeaders(proxy.host.href, this[kHeaders]) || getBaseHeaders(proxy.host.href, HTTP.HEADERS);
1990
+ const proxyHeaders = this.#headers && getBaseHeaders(proxy.host.href, this.#headers) || getBaseHeaders(proxy.host.href, HTTP.HEADERS);
1560
1991
  agent = require(pkg)(proxy.host, (typeof keepAlive === 'boolean' || agentTimeout > 0) && agentTimeout !== 0 ? { keepAlive: keepAlive ?? true, timeout: agentTimeout, headers: proxyHeaders } : { headers: proxyHeaders });
1561
1992
  }
1562
1993
  catch (err) {
@@ -1652,7 +2083,7 @@ class Request extends module_1 {
1652
2083
  }
1653
2084
  }
1654
2085
  if (LOG_HTTP) {
1655
- this[kConnectHttp][0][origin] = (this[kConnectHttp][0][origin] || 0) + 1;
2086
+ this.#connectHttp[0][origin] = (this.#connectHttp[0][origin] || 0) + 1;
1656
2087
  }
1657
2088
  }
1658
2089
  else {
@@ -1667,7 +2098,7 @@ class Request extends module_1 {
1667
2098
  request.emit('end');
1668
2099
  });
1669
2100
  if (expectContinue) {
1670
- abortHeaders.call(this, url.href, request, options, statusCode, "Did not receive continue acknowledgment");
2101
+ this.abortHeaders(url.href, request, options, statusCode, "Did not receive continue acknowledgment");
1671
2102
  return;
1672
2103
  }
1673
2104
  }
@@ -1685,7 +2116,7 @@ class Request extends module_1 {
1685
2116
  }
1686
2117
  if (getting || posting) {
1687
2118
  const ac = new AbortController();
1688
- this[kDownloading].add(options.outAbort = ac);
2119
+ this.#downloading.add(options.outAbort = ac);
1689
2120
  stream.addAbortSignal(ac.signal, request);
1690
2121
  if (options.signal) {
1691
2122
  stream.addAbortSignal(options.signal, request);
@@ -1885,11 +2316,11 @@ class Request extends module_1 {
1885
2316
  return this.get(uri, options);
1886
2317
  }
1887
2318
  async get(uri, options) {
1888
- const opts = (typeof options === 'string' ? { format: options, encoding: 'utf-8' } : options || {});
2319
+ const opts = (typeof options === 'string' ? { format: options, encoding: 'utf8' } : options || {});
1889
2320
  if (this.readExpect === 'string') {
1890
2321
  opts.encoding = (0, types_1.getEncoding)(opts.encoding);
1891
2322
  }
1892
- const singleton = this[kSingleton];
2323
+ const singleton = this.#singleton;
1893
2324
  const verbose = !opts.silent && !singleton || opts.silent === false;
1894
2325
  const log = verbose && LOG_HTTP && LOG_TIMEPROCESS;
1895
2326
  const state = Object.freeze({
@@ -1898,7 +2329,7 @@ class Request extends module_1 {
1898
2329
  singleton,
1899
2330
  config: this._config
1900
2331
  });
1901
- return new this[kAdapter](this, state, uri, opts).start();
2332
+ return new this.#adapter(this, state, uri, opts).start();
1902
2333
  }
1903
2334
  reset(adapter) {
1904
2335
  if (adapter) {
@@ -1908,26 +2339,26 @@ class Request extends module_1 {
1908
2339
  }
1909
2340
  const ac = adapter.abortController;
1910
2341
  if (ac) {
1911
- this[kDownloading].delete(ac);
2342
+ this.#downloading.delete(ac);
1912
2343
  adapter.abortController = null;
1913
2344
  }
1914
2345
  return;
1915
2346
  }
1916
- this[kPendingDns] = Object.create(null);
1917
- this[kDownloading].clear();
2347
+ this.#pendingDns = Object.create(null);
2348
+ this.#downloading.clear();
1918
2349
  }
1919
2350
  close() {
1920
- const session = this[kSession];
2351
+ const session = this.#session;
1921
2352
  session.forEach((protocol, index) => {
1922
2353
  for (const host in protocol) {
1923
2354
  protocol[host].close();
1924
2355
  }
1925
2356
  session[index] = Object.create(null);
1926
2357
  });
1927
- this[kDownloading].clear();
2358
+ this.#downloading.clear();
1928
2359
  }
1929
2360
  matchStatus(code, url, headers, request, options) {
1930
- const status = this[kStatusOn]?.get(code);
2361
+ const status = this.#statusOn?.get(code);
1931
2362
  if (status) {
1932
2363
  const href = url.href;
1933
2364
  const called = new Set();
@@ -1939,7 +2370,7 @@ class Request extends module_1 {
1939
2370
  for (const callback of called) {
1940
2371
  try {
1941
2372
  if (callback(code, headers, url) === true) {
1942
- abortHeaders.call(this, href, request, options, code);
2373
+ this.abortHeaders(href, request, options, code);
1943
2374
  return false;
1944
2375
  }
1945
2376
  }
@@ -1951,7 +2382,7 @@ class Request extends module_1 {
1951
2382
  return true;
1952
2383
  }
1953
2384
  matchHeaders(url, headers, request, options) {
1954
- const on = this[kHeadersOn];
2385
+ const on = this.#headersOn;
1955
2386
  if (on?.size) {
1956
2387
  const href = url.href;
1957
2388
  const called = new Map();
@@ -1971,7 +2402,7 @@ class Request extends module_1 {
1971
2402
  for (const [callback, data] of called) {
1972
2403
  try {
1973
2404
  if (callback(data, url) === true) {
1974
- abortHeaders.call(this, href, request, options);
2405
+ this.abortHeaders(href, request, options);
1975
2406
  return false;
1976
2407
  }
1977
2408
  }
@@ -1982,50 +2413,58 @@ class Request extends module_1 {
1982
2413
  }
1983
2414
  return true;
1984
2415
  }
2416
+ abortHeaders(href, request, options, statusCode = '', message = "Aborted by client") {
2417
+ const reason = (0, types_1.errorMessage)(statusCode, message, href);
2418
+ const outAbort = options.outAbort;
2419
+ if (outAbort) {
2420
+ outAbort.abort(reason);
2421
+ this.#downloading.delete(outAbort);
2422
+ }
2423
+ request.destroy(reason);
2424
+ }
1985
2425
  set adapter(value) {
1986
- if (isFunction(value) && value.prototype instanceof adapter_1) {
1987
- this[kAdapter] = value;
2426
+ if (isConstructor(value) && value.prototype instanceof adapter_1) {
2427
+ this.#adapter = value;
1988
2428
  }
1989
2429
  }
1990
2430
  set agentTimeout(value) {
1991
2431
  if (value > 0) {
1992
- this[kAgentTimeout] = value;
2432
+ this.#agentTimeout = value;
1993
2433
  this.keepAlive ??= true;
1994
2434
  }
1995
2435
  else {
1996
- this[kAgentTimeout] = 0;
2436
+ this.#agentTimeout = 0;
1997
2437
  this.keepAlive ??= false;
1998
2438
  }
1999
2439
  }
2000
2440
  get agentTimeout() {
2001
- return this[kAgentTimeout];
2441
+ return this.#agentTimeout;
2002
2442
  }
2003
2443
  set httpVersion(value) {
2004
2444
  switch (value) {
2005
2445
  case 1:
2006
2446
  case 2:
2007
- this[kHttpVersion] = value;
2447
+ this.#httpVersion = value;
2008
2448
  break;
2009
2449
  }
2010
2450
  }
2011
2451
  get httpVersion() {
2012
- return this[kHttpVersion];
2452
+ return this.#httpVersion;
2013
2453
  }
2014
2454
  set ipVersion(value) {
2015
2455
  switch (value) {
2016
2456
  case 0:
2017
2457
  case 4:
2018
2458
  case 6:
2019
- this[kIpVersion] = value;
2459
+ this.#ipVersion = value;
2020
2460
  break;
2021
2461
  }
2022
2462
  }
2023
2463
  get ipVersion() {
2024
- return this[kIpVersion];
2464
+ return this.#ipVersion;
2025
2465
  }
2026
2466
  get settings() {
2027
2467
  return this.module.settings ||= {};
2028
2468
  }
2029
2469
  }
2030
- _a = kSingleton, _b = kHttpVersion, _c = kHeaders, _d = kCerts, _e = kBaseURL, _f = kConnectDns, _g = kPendingDns, _h = kConnectHttp, _j = kStatusOn, _k = kHeadersOn, _l = kAdapter, _m = kDownloading, _o = kHostInfo, _p = kSession;
2031
2470
  module.exports = Request;