@mavogel/awscdk-rootmail 0.1.14 → 0.1.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.
Files changed (168) hide show
  1. package/.jsii +10 -10
  2. package/lib/rootmail.js +1 -1
  3. package/lib/ses-receive.js +1 -1
  4. package/node_modules/@aws-sdk/checksums/package.json +3 -3
  5. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-cjs/index.js +23 -1
  6. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-es/models/CloudWatchLogsServiceException.js +1 -0
  7. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-es/models/errors.js +21 -0
  8. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/models/CloudWatchLogsServiceException.d.ts +1 -0
  9. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/models/errors.d.ts +21 -0
  10. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/ts3.4/models/CloudWatchLogsServiceException.d.ts +1 -0
  11. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/ts3.4/models/errors.d.ts +21 -0
  12. package/node_modules/@aws-sdk/client-cloudwatch-logs/package.json +4 -4
  13. package/node_modules/@aws-sdk/client-route-53/dist-cjs/index.js +71 -1
  14. package/node_modules/@aws-sdk/client-route-53/dist-es/models/Route53ServiceException.js +1 -0
  15. package/node_modules/@aws-sdk/client-route-53/dist-es/models/errors.js +69 -0
  16. package/node_modules/@aws-sdk/client-route-53/dist-types/models/Route53ServiceException.d.ts +1 -0
  17. package/node_modules/@aws-sdk/client-route-53/dist-types/models/errors.d.ts +69 -0
  18. package/node_modules/@aws-sdk/client-route-53/dist-types/ts3.4/models/Route53ServiceException.d.ts +1 -0
  19. package/node_modules/@aws-sdk/client-route-53/dist-types/ts3.4/models/errors.d.ts +69 -0
  20. package/node_modules/@aws-sdk/client-route-53/package.json +4 -4
  21. package/node_modules/@aws-sdk/client-s3/dist-cjs/index.js +23 -1
  22. package/node_modules/@aws-sdk/client-s3/dist-es/models/S3ServiceException.js +1 -0
  23. package/node_modules/@aws-sdk/client-s3/dist-es/models/errors.js +21 -0
  24. package/node_modules/@aws-sdk/client-s3/dist-types/models/S3ServiceException.d.ts +1 -0
  25. package/node_modules/@aws-sdk/client-s3/dist-types/models/errors.d.ts +21 -0
  26. package/node_modules/@aws-sdk/client-s3/dist-types/ts3.4/models/S3ServiceException.d.ts +1 -0
  27. package/node_modules/@aws-sdk/client-s3/dist-types/ts3.4/models/errors.d.ts +21 -0
  28. package/node_modules/@aws-sdk/client-s3/package.json +8 -8
  29. package/node_modules/@aws-sdk/client-ses/dist-cjs/index.js +36 -1
  30. package/node_modules/@aws-sdk/client-ses/dist-es/models/SESServiceException.js +1 -0
  31. package/node_modules/@aws-sdk/client-ses/dist-es/models/errors.js +34 -0
  32. package/node_modules/@aws-sdk/client-ses/dist-types/models/SESServiceException.d.ts +1 -0
  33. package/node_modules/@aws-sdk/client-ses/dist-types/models/errors.d.ts +34 -0
  34. package/node_modules/@aws-sdk/client-ses/dist-types/ts3.4/models/SESServiceException.d.ts +1 -0
  35. package/node_modules/@aws-sdk/client-ses/dist-types/ts3.4/models/errors.d.ts +34 -0
  36. package/node_modules/@aws-sdk/client-ses/package.json +4 -4
  37. package/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js +142 -1
  38. package/node_modules/@aws-sdk/client-ssm/dist-es/models/SSMServiceException.js +1 -0
  39. package/node_modules/@aws-sdk/client-ssm/dist-es/models/errors.js +140 -0
  40. package/node_modules/@aws-sdk/client-ssm/dist-types/models/SSMServiceException.d.ts +1 -0
  41. package/node_modules/@aws-sdk/client-ssm/dist-types/models/errors.d.ts +140 -0
  42. package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/SSMServiceException.d.ts +1 -0
  43. package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/errors.d.ts +140 -0
  44. package/node_modules/@aws-sdk/client-ssm/package.json +4 -4
  45. package/node_modules/@aws-sdk/core/package.json +3 -3
  46. package/node_modules/@aws-sdk/credential-provider-env/package.json +3 -3
  47. package/node_modules/@aws-sdk/credential-provider-http/package.json +3 -3
  48. package/node_modules/@aws-sdk/credential-provider-ini/package.json +10 -10
  49. package/node_modules/@aws-sdk/credential-provider-login/package.json +4 -4
  50. package/node_modules/@aws-sdk/credential-provider-node/package.json +8 -8
  51. package/node_modules/@aws-sdk/credential-provider-process/package.json +3 -3
  52. package/node_modules/@aws-sdk/credential-provider-sso/package.json +5 -5
  53. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +4 -4
  54. package/node_modules/@aws-sdk/middleware-sdk-s3/package.json +4 -4
  55. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +11 -1
  56. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +6 -1
  57. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +6 -1
  58. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +13 -1
  59. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +9 -1
  60. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/models/CognitoIdentityServiceException.js +1 -0
  61. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/models/errors.js +9 -0
  62. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/models/SigninServiceException.js +1 -0
  63. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/signin/models/errors.js +4 -0
  64. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/models/SSOServiceException.js +1 -0
  65. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso/models/errors.js +4 -0
  66. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/models/SSOOIDCServiceException.js +1 -0
  67. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sso-oidc/models/errors.js +11 -0
  68. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/models/STSServiceException.js +1 -0
  69. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/sts/models/errors.js +7 -0
  70. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/models/CognitoIdentityServiceException.d.ts +1 -0
  71. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/models/errors.d.ts +9 -0
  72. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/signin/models/SigninServiceException.d.ts +1 -0
  73. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/signin/models/errors.d.ts +4 -0
  74. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso/models/SSOServiceException.d.ts +1 -0
  75. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso/models/errors.d.ts +4 -0
  76. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso-oidc/models/SSOOIDCServiceException.d.ts +1 -0
  77. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso-oidc/models/errors.d.ts +11 -0
  78. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sts/models/STSServiceException.d.ts +1 -0
  79. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sts/models/errors.d.ts +7 -0
  80. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/cognito-identity/models/CognitoIdentityServiceException.d.ts +1 -0
  81. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/cognito-identity/models/errors.d.ts +9 -0
  82. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/signin/models/SigninServiceException.d.ts +1 -0
  83. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/signin/models/errors.d.ts +4 -0
  84. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso/models/SSOServiceException.d.ts +1 -0
  85. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso/models/errors.d.ts +4 -0
  86. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso-oidc/models/SSOOIDCServiceException.d.ts +1 -0
  87. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sso-oidc/models/errors.d.ts +11 -0
  88. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sts/models/STSServiceException.d.ts +1 -0
  89. package/node_modules/@aws-sdk/nested-clients/dist-types/ts3.4/submodules/sts/models/errors.d.ts +7 -0
  90. package/node_modules/@aws-sdk/nested-clients/package.json +4 -4
  91. package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +2 -2
  92. package/node_modules/@aws-sdk/token-providers/package.json +4 -4
  93. package/node_modules/@smithy/core/dist-cjs/submodules/client/index.js +33 -11
  94. package/node_modules/@smithy/core/dist-cjs/submodules/endpoints/index.browser.js +2 -1
  95. package/node_modules/@smithy/core/dist-cjs/submodules/endpoints/index.js +2 -1
  96. package/node_modules/@smithy/core/dist-cjs/submodules/schema/index.js +3 -0
  97. package/node_modules/@smithy/core/dist-es/submodules/client/smithy-client/exceptions.js +33 -11
  98. package/node_modules/@smithy/core/dist-es/submodules/endpoints/util-endpoints/cache/EndpointCache.js +2 -1
  99. package/node_modules/@smithy/core/dist-es/submodules/schema/TypeRegistry.js +3 -0
  100. package/node_modules/@smithy/core/dist-types/submodules/client/smithy-client/exceptions.d.ts +1 -0
  101. package/node_modules/@smithy/core/dist-types/ts3.4/submodules/client/smithy-client/exceptions.d.ts +1 -0
  102. package/node_modules/@smithy/core/package.json +1 -1
  103. package/node_modules/@smithy/signature-v4/dist-cjs/index.js +4 -1
  104. package/node_modules/@smithy/signature-v4/dist-es/getCanonicalHeaders.js +4 -1
  105. package/node_modules/@smithy/signature-v4/package.json +3 -3
  106. package/node_modules/mailparser/.release-please-manifest.json +1 -1
  107. package/node_modules/mailparser/CHANGELOG.md +7 -0
  108. package/node_modules/mailparser/package.json +2 -2
  109. package/node_modules/nodemailer/CHANGELOG.md +27 -0
  110. package/node_modules/nodemailer/dist/cjs/base64/index.d.ts +3 -0
  111. package/node_modules/nodemailer/dist/cjs/base64/index.js +80 -41
  112. package/node_modules/nodemailer/dist/cjs/dkim/index.js +43 -29
  113. package/node_modules/nodemailer/dist/cjs/dkim/message-parser.js +2 -2
  114. package/node_modules/nodemailer/dist/cjs/errors.d.ts +17 -0
  115. package/node_modules/nodemailer/dist/cjs/errors.js +12 -1
  116. package/node_modules/nodemailer/dist/cjs/fetch/index.js +23 -3
  117. package/node_modules/nodemailer/dist/cjs/mailer/index.js +23 -7
  118. package/node_modules/nodemailer/dist/cjs/mailer/mail-message.d.ts +5 -0
  119. package/node_modules/nodemailer/dist/cjs/mailer/mail-message.js +20 -0
  120. package/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +1 -1
  121. package/node_modules/nodemailer/dist/cjs/mime-node/index.js +165 -105
  122. package/node_modules/nodemailer/dist/cjs/nodemailer.js +12 -9
  123. package/node_modules/nodemailer/dist/cjs/package-info.d.ts +1 -1
  124. package/node_modules/nodemailer/dist/cjs/package-info.js +1 -1
  125. package/node_modules/nodemailer/dist/cjs/qp/index.d.ts +2 -0
  126. package/node_modules/nodemailer/dist/cjs/qp/index.js +103 -33
  127. package/node_modules/nodemailer/dist/cjs/sendmail-transport/index.js +54 -14
  128. package/node_modules/nodemailer/dist/cjs/shared/index.d.ts +32 -1
  129. package/node_modules/nodemailer/dist/cjs/shared/index.js +212 -115
  130. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.d.ts +3 -1
  131. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +88 -68
  132. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +7 -1
  133. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +348 -136
  134. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +3 -0
  135. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +7 -1
  136. package/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +106 -17
  137. package/node_modules/nodemailer/dist/cjs/smtp-transport/index.js +8 -2
  138. package/node_modules/nodemailer/dist/esm/base64/index.d.ts +3 -0
  139. package/node_modules/nodemailer/dist/esm/base64/index.js +80 -41
  140. package/node_modules/nodemailer/dist/esm/dkim/index.js +43 -29
  141. package/node_modules/nodemailer/dist/esm/dkim/message-parser.js +2 -2
  142. package/node_modules/nodemailer/dist/esm/errors.d.ts +17 -0
  143. package/node_modules/nodemailer/dist/esm/errors.js +10 -0
  144. package/node_modules/nodemailer/dist/esm/fetch/index.js +23 -3
  145. package/node_modules/nodemailer/dist/esm/mailer/index.js +23 -7
  146. package/node_modules/nodemailer/dist/esm/mailer/mail-message.d.ts +5 -0
  147. package/node_modules/nodemailer/dist/esm/mailer/mail-message.js +20 -0
  148. package/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +1 -1
  149. package/node_modules/nodemailer/dist/esm/mime-node/index.js +166 -106
  150. package/node_modules/nodemailer/dist/esm/nodemailer.js +12 -9
  151. package/node_modules/nodemailer/dist/esm/package-info.d.ts +1 -1
  152. package/node_modules/nodemailer/dist/esm/package-info.js +1 -1
  153. package/node_modules/nodemailer/dist/esm/qp/index.d.ts +2 -0
  154. package/node_modules/nodemailer/dist/esm/qp/index.js +103 -33
  155. package/node_modules/nodemailer/dist/esm/sendmail-transport/index.js +54 -14
  156. package/node_modules/nodemailer/dist/esm/shared/index.d.ts +32 -1
  157. package/node_modules/nodemailer/dist/esm/shared/index.js +207 -115
  158. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.d.ts +3 -1
  159. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +88 -68
  160. package/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +7 -1
  161. package/node_modules/nodemailer/dist/esm/smtp-connection/index.js +348 -136
  162. package/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +3 -0
  163. package/node_modules/nodemailer/dist/esm/smtp-pool/index.js +7 -1
  164. package/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.js +106 -17
  165. package/node_modules/nodemailer/dist/esm/smtp-transport/index.js +8 -2
  166. package/node_modules/nodemailer/package.json +1 -1
  167. package/node_modules/uuid/package.json +17 -17
  168. package/package.json +9 -9
@@ -37,11 +37,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  const node_child_process_1 = require("node:child_process");
40
+ const node_stream_1 = require("node:stream");
40
41
  const packageData = __importStar(require("../package-info.js"));
41
42
  const shared = __importStar(require("../shared/index.js"));
42
43
  const errors = __importStar(require("../errors.js"));
43
44
  const le_windows_js_1 = __importDefault(require("../mime-node/le-windows.js"));
44
45
  const le_unix_js_1 = __importDefault(require("../mime-node/le-unix.js"));
46
+ // how long an stdin error waits for the exit code of the process before it is reported
47
+ const STDIN_ERROR_EXIT_WAIT = 1000;
45
48
  /**
46
49
  * Generates a Transport object for Sendmail
47
50
  *
@@ -139,37 +142,75 @@ class SendmailTransport {
139
142
  return callback(E);
140
143
  }
141
144
  if (sendmail) {
145
+ let stream;
146
+ // ended once the whole message was handed to stdin
147
+ const messageWritten = () => !!stream && stream.readableEnded;
148
+ // an EPIPE says less than the exit code that usually follows it, so it is only
149
+ // reported when the process exits without one
150
+ let stdinError = null;
151
+ // releases whatever the message is still being read from
152
+ const release = () => {
153
+ if (stream && !messageWritten()) {
154
+ stream.destroy();
155
+ }
156
+ };
157
+ const fail = (err) => {
158
+ release();
159
+ callback(err);
160
+ };
142
161
  sendmail.on('error', err => {
143
162
  this.logger.error({
144
163
  err,
145
164
  tnx: 'spawn',
146
165
  messageId
147
166
  }, 'Error occurred when sending message %s. %s', messageId, err.message);
148
- callback(err);
167
+ fail(err);
149
168
  });
150
- sendmail.once('exit', code => {
151
- if (!code) {
169
+ // 'close' follows 'exit' with the same arguments, it is only listened to in case the
170
+ // process ends without an 'exit' event
171
+ const onExit = (code, signal) => {
172
+ let err = null;
173
+ if (code) {
174
+ err = new Error(code === 127 ? 'Sendmail command not found, process exited with code ' + code : 'Sendmail exited with code ' + code);
175
+ }
176
+ else if (signal) {
177
+ err = new Error('Sendmail was terminated by ' + signal);
178
+ }
179
+ else if (!messageWritten()) {
180
+ // exiting with 0 before the message was written does not mean it was queued
181
+ err = new Error('Sendmail exited before the message was written');
182
+ }
183
+ else if (stdinError) {
184
+ err = stdinError;
185
+ }
186
+ if (!err) {
152
187
  return callback();
153
188
  }
154
- const err = new Error(code === 127 ? 'Sendmail command not found, process exited with code ' + code : 'Sendmail exited with code ' + code);
155
- err.code = errors.ESENDMAIL;
189
+ err.code = err.code || errors.ESENDMAIL;
156
190
  this.logger.error({
157
191
  err,
158
192
  tnx: 'stdin',
159
193
  messageId
160
194
  }, 'Error sending message %s to sendmail. %s', messageId, err.message);
161
- callback(err);
162
- });
163
- // the close listener is handed the exit code as its first argument, so a non-zero
164
- // code reaching it before the exit listener did counts as the error value
165
- sendmail.once('close', callback);
195
+ fail(err);
196
+ };
197
+ sendmail.once('exit', onExit);
198
+ sendmail.once('close', onExit);
166
199
  sendmail.stdin.on('error', err => {
167
200
  this.logger.error({
168
201
  err,
169
202
  tnx: 'stdin',
170
203
  messageId
171
204
  }, 'Error occurred when piping message %s to sendmail. %s', messageId, err.message);
172
- callback(err);
205
+ if (stdinError) {
206
+ return;
207
+ }
208
+ stdinError = err;
209
+ release();
210
+ // a process that closed its stdin normally exits right after, with a code that
211
+ // tells more than the EPIPE. Report the EPIPE if it does not
212
+ const exitTimer = setTimeout(() => fail(err), STDIN_ERROR_EXIT_WAIT);
213
+ sendmail.once('exit', () => clearTimeout(exitTimer));
173
214
  });
174
215
  const recipients = [].concat(envelope.to || []);
175
216
  if (recipients.length > 3) {
@@ -180,12 +221,11 @@ class SendmailTransport {
180
221
  messageId
181
222
  }, 'Sending message %s to <%s>', messageId, recipients.join(', '));
182
223
  const sourceStream = mail.message.createReadStream();
183
- let stream = sourceStream;
224
+ stream = sourceStream;
184
225
  if (this.options.newline) {
185
226
  // apply the transport-level line ending transform; the message-level
186
227
  // `newline` option is handled by MimeNode in createReadStream()
187
- stream = sourceStream.pipe(this.winbreak ? new le_windows_js_1.default() : new le_unix_js_1.default());
188
- sourceStream.once('error', err => stream.emit('error', err));
228
+ stream = (0, node_stream_1.pipeline)(sourceStream, this.winbreak ? new le_windows_js_1.default() : new le_unix_js_1.default(), () => false);
189
229
  }
190
230
  stream.once('error', err => {
191
231
  this.logger.error({
@@ -1,6 +1,7 @@
1
+ import type { NodemailerError } from '../errors.js';
1
2
  import { isProtoKey, copyOwnKeys } from './objects.js';
2
3
  import os from 'node:os';
3
- import type { Readable } from 'node:stream';
4
+ import { type Readable } from 'node:stream';
4
5
  import type { OutgoingHttpHeaders } from 'node:http';
5
6
  export { isProtoKey, copyOwnKeys };
6
7
  /**
@@ -258,3 +259,33 @@ export declare const assign: (...args: ({
258
259
  [key: string]: any;
259
260
  };
260
261
  export declare const encodeXText: (str: string) => string;
262
+ /**
263
+ * Keeps the first error a content stream emits before it is read, so the error is reported
264
+ * when the stream is read instead of being thrown as unhandled. The listener stays attached
265
+ * for good, a stream that emits 'error' more than once never throws the later ones either
266
+ *
267
+ * @param stream Readable stream
268
+ */
269
+ export declare function recordStreamErrors(stream: Readable): void;
270
+ /**
271
+ * Destroys a value if it is a readable stream that was not destroyed yet
272
+ *
273
+ * @param value Any content value
274
+ */
275
+ export declare function destroyStream(value: unknown): void;
276
+ /**
277
+ * Tells why a stream can not be read from start to end anymore. A stream that ended or was
278
+ * destroyed before anyone read it would never emit 'end' to a new reader, or, when piped, would
279
+ * end the destination right away and turn into an empty value without any error
280
+ *
281
+ * @param stream Readable stream
282
+ * @returns The error the stream failed with, an ESTREAM error, or null when it can be read
283
+ */
284
+ export declare function unreadableStreamError(stream: Readable): NodemailerError | null;
285
+ /**
286
+ * Streams a stream value into a Buffer
287
+ *
288
+ * @param stream Readable stream
289
+ * @param callback Callback function with (err, value)
290
+ */
291
+ export declare function resolveStream(stream: Readable, callback: (err: Error | null, value?: Buffer) => void): void;
@@ -37,8 +37,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
38
  };
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.encodeXText = exports.assign = exports.parseDataURI = exports.callbackPromise = exports.getLogger = exports._logFunc = exports.parseConnectionUrl = exports.resolveHostname = exports.dnsCache = exports.networkInterfaces = exports._resetCacheCleanup = exports._lastCacheCleanup = exports.copyOwnKeys = exports.isProtoKey = void 0;
40
+ exports.encodeXText = exports.assign = exports.parseDataURI = exports.callbackPromise = exports.getLogger = exports._logFunc = exports.parseConnectionUrl = exports.resolveHostname = exports.dnsCache = exports._readNetworkInterfaces = exports.networkInterfaces = exports._resetCacheCleanup = exports._lastCacheCleanup = exports.copyOwnKeys = exports.isProtoKey = void 0;
41
41
  exports.resolveContent = resolveContent;
42
+ exports.recordStreamErrors = recordStreamErrors;
43
+ exports.destroyStream = destroyStream;
44
+ exports.unreadableStreamError = unreadableStreamError;
45
+ exports.resolveStream = resolveStream;
42
46
  const urllib = __importStar(require("./url.js"));
43
47
  const node_util_1 = __importDefault(require("node:util"));
44
48
  const node_fs_1 = __importDefault(require("node:fs"));
@@ -50,6 +54,7 @@ Object.defineProperty(exports, "copyOwnKeys", { enumerable: true, get: function
50
54
  const node_dns_1 = __importDefault(require("node:dns"));
51
55
  const node_net_1 = __importDefault(require("node:net"));
52
56
  const node_os_1 = __importDefault(require("node:os"));
57
+ const node_stream_1 = require("node:stream");
53
58
  const DNS_TTL = 5 * 60 * 1000;
54
59
  const CACHE_CLEANUP_INTERVAL = 30 * 1000; // Minimum 30 seconds between cleanups
55
60
  const MAX_CACHE_SIZE = 1000; // Maximum number of entries in cache
@@ -62,14 +67,25 @@ const _resetCacheCleanup = () => {
62
67
  lastCacheCleanup = 0;
63
68
  };
64
69
  exports._resetCacheCleanup = _resetCacheCleanup;
65
- try {
66
- exports.networkInterfaces = node_os_1.default.networkInterfaces();
67
- }
68
- catch (_err) {
69
- // fails on some systems
70
- }
70
+ let networkInterfacesRead = false;
71
+ // Read on first use rather than at load, so that importing the module does not ask for
72
+ // the interface table (Deno prompts for --allow-sys on it)
73
+ /** @internal */
74
+ const _readNetworkInterfaces = () => {
75
+ if (!networkInterfacesRead) {
76
+ networkInterfacesRead = true;
77
+ try {
78
+ exports.networkInterfaces = node_os_1.default.networkInterfaces();
79
+ }
80
+ catch (_err) {
81
+ // fails on some systems
82
+ }
83
+ }
84
+ return exports.networkInterfaces;
85
+ };
86
+ exports._readNetworkInterfaces = _readNetworkInterfaces;
71
87
  const isFamilySupported = (family, allowInternal) => {
72
- const addresses = Object.values(exports.networkInterfaces || {}).flat();
88
+ const addresses = Object.values((0, exports._readNetworkInterfaces)() || {}).flat();
73
89
  if (!addresses.length) {
74
90
  // hope for the best. Runtimes without an interface table (Cloudflare
75
91
  // Workers) report an empty object rather than throwing
@@ -80,7 +96,8 @@ const isFamilySupported = (family, allowInternal) => {
80
96
  const resolve = (family, hostname, options, callback) => {
81
97
  options = options || {};
82
98
  if (!isFamilySupported(family, options.allowInternalNetworkInterfaces)) {
83
- return callback(null, []);
99
+ callback(null, []);
100
+ return null;
84
101
  }
85
102
  const dnsResolver = node_dns_1.default.Resolver ? new node_dns_1.default.Resolver(options) : node_dns_1.default;
86
103
  dnsResolver['resolve' + family](hostname, (err, addresses) => {
@@ -99,6 +116,7 @@ const resolve = (family, hostname, options, callback) => {
99
116
  }
100
117
  return callback(null, Array.isArray(addresses) ? addresses : [].concat(addresses || []));
101
118
  });
119
+ return node_dns_1.default.Resolver ? dnsResolver : null;
102
120
  };
103
121
  exports.dnsCache = new Map();
104
122
  const formatDNSValue = (value, extra) => {
@@ -162,115 +180,139 @@ const resolveHostname = (options, callback) => {
162
180
  }));
163
181
  }
164
182
  }
165
- // Resolve both IPv4 and IPv6 addresses for fallback support
183
+ // The timeout limits the lookup as a whole. It is also handed to the resolver, but there
184
+ // it applies to every query attempt on its own, and the resolver retries a few times
185
+ let responded = false;
186
+ let deadline;
187
+ const respond = (err, result) => {
188
+ if (responded) {
189
+ return;
190
+ }
191
+ responded = true;
192
+ clearTimeout(deadline);
193
+ callback(err, result);
194
+ };
195
+ // a stale cached value is still better than no value at all
196
+ const respondCached = (error) => {
197
+ if (!cached) {
198
+ return false;
199
+ }
200
+ exports.dnsCache.set(host, {
201
+ value: cached.value,
202
+ expires: Date.now() + (options.dnsTtl || DNS_TTL)
203
+ });
204
+ respond(null, formatDNSValue(cached.value, {
205
+ servername,
206
+ cached: true,
207
+ error
208
+ }));
209
+ return true;
210
+ };
211
+ const resolvers = [];
212
+ const timeout = Number(options.timeout) || 0;
213
+ if (timeout > 0) {
214
+ deadline = setTimeout(() => {
215
+ for (const resolver of resolvers) {
216
+ if (typeof resolver.cancel === 'function') {
217
+ resolver.cancel();
218
+ }
219
+ }
220
+ const err = new Error('DNS lookup for ' + host + ' timed out');
221
+ err.code = node_dns_1.default.TIMEOUT;
222
+ if (!respondCached(err)) {
223
+ respond(err);
224
+ }
225
+ }, timeout);
226
+ }
227
+ // Resolve both IPv4 and IPv6 addresses for fallback support, at the same time
166
228
  let ipv4Addresses = [];
167
229
  let ipv6Addresses = [];
168
230
  let ipv4Error = null;
169
231
  let ipv6Error = null;
170
- resolve(4, options.host, options, (err, addresses) => {
171
- if (err) {
172
- ipv4Error = err;
232
+ let pending = 2;
233
+ const onResolved = () => {
234
+ if (--pending || responded) {
235
+ return;
173
236
  }
174
- else {
175
- ipv4Addresses = addresses || [];
237
+ // Combine addresses: IPv4 first, then IPv6
238
+ const allAddresses = ipv4Addresses.concat(ipv6Addresses);
239
+ if (allAddresses.length) {
240
+ const value = {
241
+ addresses: allAddresses
242
+ };
243
+ exports.dnsCache.set(host, {
244
+ value,
245
+ expires: Date.now() + (options.dnsTtl || DNS_TTL)
246
+ });
247
+ return respond(null, formatDNSValue(value, {
248
+ servername,
249
+ cached: false
250
+ }));
176
251
  }
177
- resolve(6, host, options, (err, addresses) => {
178
- if (err) {
179
- ipv6Error = err;
180
- }
181
- else {
182
- ipv6Addresses = addresses || [];
183
- }
184
- // Combine addresses: IPv4 first, then IPv6
185
- const allAddresses = ipv4Addresses.concat(ipv6Addresses);
186
- if (allAddresses.length) {
252
+ // No addresses from resolve4/resolve6, try dns.lookup as fallback
253
+ if (ipv4Error && ipv6Error && respondCached(ipv4Error)) {
254
+ // Both resolvers had errors
255
+ return;
256
+ }
257
+ try {
258
+ node_dns_1.default.lookup(host, { all: true }, (err, addresses) => {
259
+ if (err) {
260
+ if (respondCached(err)) {
261
+ return;
262
+ }
263
+ return respond(err);
264
+ }
265
+ // Get all supported addresses from dns.lookup
266
+ const supportedAddresses = addresses
267
+ ? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
268
+ : [];
269
+ if (addresses && addresses.length && !supportedAddresses.length) {
270
+ // there are addresses but none can be used
271
+ console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
272
+ }
273
+ if (!supportedAddresses.length && cached) {
274
+ // nothing was found, fallback to cached value
275
+ return respond(null, formatDNSValue(cached.value, {
276
+ servername,
277
+ cached: true
278
+ }));
279
+ }
187
280
  const value = {
188
- addresses: allAddresses
281
+ addresses: supportedAddresses.length ? supportedAddresses : [host]
189
282
  };
190
283
  exports.dnsCache.set(host, {
191
284
  value,
192
285
  expires: Date.now() + (options.dnsTtl || DNS_TTL)
193
286
  });
194
- return callback(null, formatDNSValue(value, {
287
+ return respond(null, formatDNSValue(value, {
195
288
  servername,
196
289
  cached: false
197
290
  }));
291
+ });
292
+ }
293
+ catch (lookupErr) {
294
+ if (respondCached(lookupErr)) {
295
+ return;
198
296
  }
199
- // No addresses from resolve4/resolve6, try dns.lookup as fallback
200
- if (ipv4Error && ipv6Error) {
201
- // Both resolvers had errors
202
- if (cached) {
203
- exports.dnsCache.set(host, {
204
- value: cached.value,
205
- expires: Date.now() + (options.dnsTtl || DNS_TTL)
206
- });
207
- return callback(null, formatDNSValue(cached.value, {
208
- servername,
209
- cached: true,
210
- error: ipv4Error
211
- }));
212
- }
213
- }
214
- try {
215
- node_dns_1.default.lookup(host, { all: true }, (err, addresses) => {
216
- if (err) {
217
- if (cached) {
218
- exports.dnsCache.set(host, {
219
- value: cached.value,
220
- expires: Date.now() + (options.dnsTtl || DNS_TTL)
221
- });
222
- return callback(null, formatDNSValue(cached.value, {
223
- servername,
224
- cached: true,
225
- error: err
226
- }));
227
- }
228
- return callback(err);
229
- }
230
- // Get all supported addresses from dns.lookup
231
- const supportedAddresses = addresses
232
- ? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
233
- : [];
234
- if (addresses && addresses.length && !supportedAddresses.length) {
235
- // there are addresses but none can be used
236
- console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
237
- }
238
- if (!supportedAddresses.length && cached) {
239
- // nothing was found, fallback to cached value
240
- return callback(null, formatDNSValue(cached.value, {
241
- servername,
242
- cached: true
243
- }));
244
- }
245
- const value = {
246
- addresses: supportedAddresses.length ? supportedAddresses : [host]
247
- };
248
- exports.dnsCache.set(host, {
249
- value,
250
- expires: Date.now() + (options.dnsTtl || DNS_TTL)
251
- });
252
- return callback(null, formatDNSValue(value, {
253
- servername,
254
- cached: false
255
- }));
256
- });
297
+ return respond(ipv4Error || ipv6Error || lookupErr);
298
+ }
299
+ };
300
+ for (const family of [4, 6]) {
301
+ const resolver = resolve(family, host, options, (err, addresses) => {
302
+ if (family === 4) {
303
+ ipv4Error = err;
304
+ ipv4Addresses = addresses || [];
257
305
  }
258
- catch (lookupErr) {
259
- if (cached) {
260
- exports.dnsCache.set(host, {
261
- value: cached.value,
262
- expires: Date.now() + (options.dnsTtl || DNS_TTL)
263
- });
264
- return callback(null, formatDNSValue(cached.value, {
265
- servername,
266
- cached: true,
267
- error: lookupErr
268
- }));
269
- }
270
- return callback(ipv4Error || ipv6Error || lookupErr);
306
+ else {
307
+ ipv6Error = err;
308
+ ipv6Addresses = addresses || [];
271
309
  }
310
+ onResolved();
272
311
  });
273
- });
312
+ if (resolver) {
313
+ resolvers.push(resolver);
314
+ }
315
+ }
274
316
  };
275
317
  exports.resolveHostname = resolveHostname;
276
318
  /**
@@ -597,6 +639,53 @@ const encodeXText = (str) => {
597
639
  return result;
598
640
  };
599
641
  exports.encodeXText = encodeXText;
642
+ // The first error a stream emitted, see recordStreamErrors
643
+ const streamErrors = new WeakMap();
644
+ /**
645
+ * Keeps the first error a content stream emits before it is read, so the error is reported
646
+ * when the stream is read instead of being thrown as unhandled. The listener stays attached
647
+ * for good, a stream that emits 'error' more than once never throws the later ones either
648
+ *
649
+ * @param stream Readable stream
650
+ */
651
+ function recordStreamErrors(stream) {
652
+ stream.on('error', err => {
653
+ if (!streamErrors.has(stream)) {
654
+ streamErrors.set(stream, err);
655
+ }
656
+ });
657
+ }
658
+ /**
659
+ * Destroys a value if it is a readable stream that was not destroyed yet
660
+ *
661
+ * @param value Any content value
662
+ */
663
+ function destroyStream(value) {
664
+ const stream = value;
665
+ if (stream && typeof stream.pipe === 'function' && typeof stream.destroy === 'function' && !stream.destroyed) {
666
+ stream.destroy();
667
+ }
668
+ }
669
+ /**
670
+ * Tells why a stream can not be read from start to end anymore. A stream that ended or was
671
+ * destroyed before anyone read it would never emit 'end' to a new reader, or, when piped, would
672
+ * end the destination right away and turn into an empty value without any error
673
+ *
674
+ * @param stream Readable stream
675
+ * @returns The error the stream failed with, an ESTREAM error, or null when it can be read
676
+ */
677
+ function unreadableStreamError(stream) {
678
+ const err = streamErrors.get(stream) || stream.errored;
679
+ if (err) {
680
+ return err;
681
+ }
682
+ if (stream.readableEnded || stream.destroyed) {
683
+ const unreadable = new Error('Content stream was already read or destroyed');
684
+ unreadable.code = errors.ESTREAM;
685
+ return unreadable;
686
+ }
687
+ return null;
688
+ }
600
689
  /**
601
690
  * Streams a stream value into a Buffer
602
691
  *
@@ -605,35 +694,43 @@ exports.encodeXText = encodeXText;
605
694
  */
606
695
  function resolveStream(stream, callback) {
607
696
  let responded = false;
608
- const chunks = [];
609
- let chunklen = 0;
610
- stream.on('error', err => {
697
+ const respond = (err, value) => {
611
698
  if (responded) {
612
699
  return;
613
700
  }
614
701
  responded = true;
615
- callback(err);
616
- });
617
- stream.on('readable', () => {
618
- let chunk;
619
- while ((chunk = stream.read()) !== null) {
620
- chunks.push(chunk);
621
- chunklen += chunk.length;
702
+ callback(err, value);
703
+ };
704
+ const unreadable = unreadableStreamError(stream);
705
+ if (unreadable) {
706
+ // absorbs a later 'error' from the stream, there is nobody left to report it to
707
+ stream.on('error', () => false);
708
+ setImmediate(() => respond(unreadable));
709
+ return;
710
+ }
711
+ const chunks = [];
712
+ let chunklen = 0;
713
+ stream.on('data', (chunk) => {
714
+ if (typeof chunk === 'string') {
715
+ chunk = Buffer.from(chunk);
622
716
  }
717
+ chunks.push(chunk);
718
+ chunklen += chunk.length;
623
719
  });
624
- stream.on('end', () => {
625
- if (responded) {
626
- return;
720
+ // finished() also reports a stream that is destroyed before 'end', which would otherwise
721
+ // leave the callback waiting forever
722
+ (0, node_stream_1.finished)(stream, { writable: false }, err => {
723
+ if (err) {
724
+ return respond(err);
627
725
  }
628
- responded = true;
629
726
  let value;
630
727
  try {
631
728
  value = Buffer.concat(chunks, chunklen);
632
729
  }
633
730
  catch (E) {
634
- return callback(E);
731
+ return respond(E);
635
732
  }
636
- callback(null, value);
733
+ respond(null, value);
637
734
  });
638
735
  }
639
736
  /**
@@ -9,6 +9,8 @@ import type { Callback } from '../errors.js';
9
9
  export interface HttpProxyClientOptions {
10
10
  /** Set to false to accept a proxy certificate that fails validation (e.g. self-signed) */
11
11
  rejectUnauthorized?: boolean | undefined;
12
+ /** Time in milliseconds the CONNECT handshake may take, defaults to httpProxyClient.timeout or 30 seconds */
13
+ timeout?: number | undefined;
12
14
  }
13
15
  /**
14
16
  * Receives the proxied socket once the CONNECT handshake has succeeded, or the error that prevented it
@@ -38,7 +40,7 @@ declare function httpProxyClient(proxyUrl: string, destinationPort: number | str
38
40
  */
39
41
  declare function httpProxyClient(proxyUrl: string, destinationPort: number | string, destinationHost: string, tlsOptions: HttpProxyClientOptions | undefined, callback: HttpProxyClientCallback): void;
40
42
  /**
41
- * Socket timeout in milliseconds while the CONNECT handshake is in progress, defaults to 30 seconds.
43
+ * Time in milliseconds the CONNECT handshake may take when the call does not set one, defaults to 30 seconds.
42
44
  * Settable on the function itself, the same way the CommonJS module exposed it.
43
45
  */
44
46
  declare namespace httpProxyClient {