tangerine 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +3 -7
  2. package/index.js +17 -4
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -176,7 +176,7 @@ import Tangerine from 'tangerine';
176
176
  const tangerine = new Tangerine();
177
177
  // or `const resolver = new Tangerine()`
178
178
 
179
- tangerine.resolve('forwardemail.net', 'A').then(console.log);
179
+ tangerine.resolve('forwardemail.net').then(console.log);
180
180
  ```
181
181
 
182
182
  ### CommonJS (CJS)
@@ -189,7 +189,7 @@ const Tangerine = require('tangerine');
189
189
  const tangerine = new Tangerine();
190
190
  // or `const resolver = new Tangerine()`
191
191
 
192
- tangerine.resolve('forwardemail.net', 'A').then(console.log);
192
+ tangerine.resolve('forwardemail.net').then(console.log);
193
193
  ```
194
194
 
195
195
 
@@ -211,8 +211,7 @@ tangerine.resolve('forwardemail.net', 'A').then(console.log);
211
211
  retry: {
212
212
  limit: 0
213
213
  }
214
- },
215
- requestTimeout: (ms) => ({ timeout: { request: ms } })
214
+ }
216
215
  },
217
216
  got
218
217
  );
@@ -223,8 +222,6 @@ tangerine.resolve('forwardemail.net', 'A').then(console.log);
223
222
  * The `body` property returned should be either a `Buffer` or `Stream`.
224
223
 
225
224
  * Specify default request options based off the library under `requestOptions` below
226
-
227
- * See `requestTimeout` function below, as it is required to be set properly if you are using a custom HTTP library function.
228
225
  * Instance methods of [dns.promises.Resolver](https://nodejs.org/api/dns.html) are mirrored to :tangerine: Tangerine.
229
226
  * Resolver methods accept an optional `abortController` argument, which is an instance of [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). Note that :tangerine: Tangerine manages `AbortController` usage internally – so you most likely won't need to pass your own (see [index.js](https://github.com/forwardemail/tangerine/blob/main/index.js) for more insight).
230
227
  * See the complete list of [Options](#options) below.
@@ -287,7 +284,6 @@ Similar to the `options` argument from `new dns.promises.Resolver(options)` invo
287
284
  | `requestOptions` | `Object` | Defaults to an Object with `requestOptions.method` and `requestOptions.headers` properties and values below | Default options to pass to [undici](https://github.com/nodejs/undici) (or your custom HTTP library function passed as `request`). |
288
285
  | `requestOptions.method` | `String` | Defaults to `"GET"` (must be either `"GET"` or `"POST"`, case-insensitive depending on library you use). | Default HTTP method to use for DNS over HTTP ("DoH") requests. |
289
286
  | `requestOptions.headers` | `Object` | Defaults to `{ 'content-type': 'application/dns-message', 'user-agent': pkg.name + "/" + pkg.version, accept: 'application/dns-message', bodyTimeout: timeout }`. | Default HTTP headers to use for DNS over HTTP ("DoH") requests. |
290
- | `requestTimeout` | `Function` | Defaults to `(ms) => ({ bodyTimeout })` for setting undici timeout properly. | This function accepts an argument `ms` which is the number of milliseconds to wait for the request to timeout (since we use a back-off strategy that mirrors the Node.js DNS module). This function is required to be passed and customized if you are using a custom HTTP library. If you're using a custom HTTP library such as `got`, you'd set this to `requestTimeout: (ms) => ({ timeout: { request: ms } })` |
291
287
  | `protocol` | `String` | Defaults to `"https"`. | Default HTTP protocol to use for DNS over HTTPS ("DoH") requests. |
292
288
  | `dnsOrder` | `String` | Defaults to `"verbatim"` for Node.js v17.0.0+ and `"ipv4first"` for older versions. | Sets the default result order of `lookup` invocations (see [dns.setDefaultResultOrder](https://nodejs.org/api/dns.html#dnssetdefaultresultorderorder) for more insight). |
293
289
  | `logger` | `Object` | `false` | This is the default logger. We recommend using [Cabin](https://github.com/cabinjs) instead of using `console` as your default logger. Set this value to `false` to disable logging entirely (uses noop function). |
package/index.js CHANGED
@@ -12,6 +12,7 @@ const getStream = require('get-stream');
12
12
  const ipaddr = require('ipaddr.js');
13
13
  const mergeOptions = require('merge-options');
14
14
  const pMap = require('p-map');
15
+ const pTimeout = require('p-timeout');
15
16
  const pWaitFor = require('p-wait-for');
16
17
  const packet = require('dns-packet');
17
18
  const semver = require('semver');
@@ -69,6 +70,8 @@ class Tangerine extends dns.promises.Resolver {
69
70
  let err;
70
71
  if (errors.length === 1) {
71
72
  err = errors[0];
73
+ } else if (errors.every((e) => e instanceof pTimeout.TimeoutError)) {
74
+ err = errors[0];
72
75
  } else {
73
76
  err = new Error(
74
77
  [...new Set(errors.map((e) => e.message).filter(Boolean))].join('; ')
@@ -76,6 +79,14 @@ class Tangerine extends dns.promises.Resolver {
76
79
  err.stack = [...new Set(errors.map((e) => e.stack).filter(Boolean))].join(
77
80
  '\n\n'
78
81
  );
82
+
83
+ // if all errors had `name` and they were all the same then preserve it
84
+ if (
85
+ typeof errors[0].name !== 'undefined' &&
86
+ errors.every((e) => e.name === errors[0].name)
87
+ )
88
+ err.name = errors[0].name;
89
+
79
90
  // if all errors had `code` and they were all the same then preserve it
80
91
  if (
81
92
  typeof errors[0].code !== 'undefined' &&
@@ -251,7 +262,6 @@ class Tangerine extends dns.promises.Resolver {
251
262
  accept: 'application/dns-message'
252
263
  }
253
264
  },
254
- requestTimeout: (ms) => ({ bodyTimeout: ms }),
255
265
  //
256
266
  // NOTE: we set the default to "get" since it is faster from `benchmark` results
257
267
  //
@@ -756,7 +766,6 @@ class Tangerine extends dns.promises.Resolver {
756
766
 
757
767
  const options = {
758
768
  ...this.options.requestOptions,
759
- ...this.options.requestTimeout(timeout), // returns `{ bodyTimeout: requestTimeout }`
760
769
  signal: abortController.signal
761
770
  };
762
771
 
@@ -772,7 +781,9 @@ class Tangerine extends dns.promises.Resolver {
772
781
  }
773
782
 
774
783
  debug('request', { url, options });
775
- const response = await this.request(url, options);
784
+ const response = await pTimeout(this.request(url, options), timeout, {
785
+ signal: abortController.signal
786
+ });
776
787
  return response;
777
788
  }
778
789
 
@@ -901,7 +912,9 @@ class Tangerine extends dns.promises.Resolver {
901
912
  const err = this.constructor.createError(
902
913
  name,
903
914
  rrtype,
904
- _err.code,
915
+ _err instanceof pTimeout.TimeoutError || _err.name === 'TimeoutError'
916
+ ? dns.TIMEOUT
917
+ : _err.code,
905
918
  _err.errno
906
919
  );
907
920
  // then map it to dns.CONNREFUSED
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tangerine",
3
3
  "description": "Tangerine is the best Node.js drop-in replacement for dns.promises.Resolver using DNS over HTTPS (\"DoH\") via undici with built-in retries, timeouts, smart server rotation, AbortControllers, and caching support for multiple backends via Keyv.",
4
- "version": "1.2.0",
4
+ "version": "1.2.2",
5
5
  "author": "Forward Email (https://forwardemail.net)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/forwardemail/tangerine/issues"
@@ -17,6 +17,7 @@
17
17
  "keyv": "^4.5.2",
18
18
  "merge-options": "3.0.4",
19
19
  "p-map": "4",
20
+ "p-timeout": "4",
20
21
  "p-wait-for": "3",
21
22
  "port-numbers": "^6.0.1",
22
23
  "semver": "^7.3.8"