@upyo/mailgun 0.5.0-dev.158 → 0.5.0-dev.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -129,7 +129,7 @@ var MailgunHttpClient = class {
129
129
  throw new MailgunApiError(lastError.message, void 0, void 0, attempt + 1);
130
130
  }
131
131
  const delay = Math.pow(2, attempt) * 1e3;
132
- await new Promise((resolve) => setTimeout(resolve, delay));
132
+ await sleep(delay, options.signal);
133
133
  }
134
134
  throw lastError || /* @__PURE__ */ new Error("Request failed after all retries");
135
135
  }
@@ -149,18 +149,18 @@ var MailgunHttpClient = class {
149
149
  for (const [key, value] of Object.entries(this.config.headers)) headers.set(key, value);
150
150
  const controller = new AbortController();
151
151
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
152
- let signal = controller.signal;
153
- if (options.signal) signal = AbortSignal.any([controller.signal, options.signal]);
152
+ const combinedSignal = combineSignals(controller.signal, options.signal);
154
153
  try {
155
154
  return await globalThis.fetch(url, {
156
155
  ...options,
157
156
  headers,
158
- signal
157
+ signal: combinedSignal.signal
159
158
  });
160
159
  } catch (error) {
161
160
  if (isAbortError$1(error) && controller.signal.aborted && !options.signal?.aborted) throw new Error(`Mailgun API request timed out after ${this.config.timeout} ms.`);
162
161
  throw error;
163
162
  } finally {
163
+ combinedSignal.cleanup();
164
164
  clearTimeout(timeoutId);
165
165
  }
166
166
  }
@@ -202,6 +202,57 @@ var MailgunApiError = class extends Error {
202
202
  function isAbortError$1(error) {
203
203
  return error instanceof Error && error.name === "AbortError";
204
204
  }
205
+ function sleep(milliseconds, signal) {
206
+ if (signal?.aborted) return Promise.reject(createAbortError(signal));
207
+ return new Promise((resolve, reject) => {
208
+ function abort() {
209
+ clearTimeout(timeoutId);
210
+ signal?.removeEventListener("abort", abort);
211
+ reject(createAbortError(signal));
212
+ }
213
+ const timeoutId = setTimeout(() => {
214
+ signal?.removeEventListener("abort", abort);
215
+ resolve();
216
+ }, milliseconds);
217
+ signal?.addEventListener("abort", abort, { once: true });
218
+ });
219
+ }
220
+ function createAbortError(signal) {
221
+ return signal?.reason ?? new DOMException("The operation was aborted.", "AbortError");
222
+ }
223
+ function combineSignals(timeoutSignal, externalSignal) {
224
+ if (externalSignal == null) return {
225
+ signal: timeoutSignal,
226
+ cleanup: () => {}
227
+ };
228
+ if (typeof AbortSignal.any === "function") return {
229
+ signal: AbortSignal.any([timeoutSignal, externalSignal]),
230
+ cleanup: () => {}
231
+ };
232
+ const controller = new AbortController();
233
+ const cleanup = () => {
234
+ timeoutSignal.removeEventListener("abort", abortFromTimeout);
235
+ externalSignal.removeEventListener("abort", abortFromExternal);
236
+ };
237
+ const abortFromTimeout = () => {
238
+ cleanup();
239
+ controller.abort(timeoutSignal.reason);
240
+ };
241
+ const abortFromExternal = () => {
242
+ cleanup();
243
+ controller.abort(externalSignal.reason);
244
+ };
245
+ if (timeoutSignal.aborted) controller.abort(timeoutSignal.reason);
246
+ else if (externalSignal.aborted) controller.abort(externalSignal.reason);
247
+ else {
248
+ timeoutSignal.addEventListener("abort", abortFromTimeout, { once: true });
249
+ externalSignal.addEventListener("abort", abortFromExternal, { once: true });
250
+ }
251
+ return {
252
+ signal: controller.signal,
253
+ cleanup
254
+ };
255
+ }
205
256
  function truncateErrorBody(text) {
206
257
  return text.length > 500 ? `${text.slice(0, 500)}...` : text;
207
258
  }
@@ -391,7 +442,7 @@ var MailgunTransport = class {
391
442
  provider: "mailgun"
392
443
  };
393
444
  } catch (error) {
394
- if (isAbortError(error) && options?.signal?.aborted) throw error;
445
+ if (isCallerAbort(error, options?.signal)) throw error;
395
446
  const errorMessage = error instanceof Error ? error.message : String(error);
396
447
  return createMailgunFailure(errorMessage, error);
397
448
  }
@@ -470,6 +521,9 @@ function createMailgunFailure(message, error) {
470
521
  });
471
522
  return (0, __upyo_core.createFailedReceipt)(message, { provider: "mailgun" });
472
523
  }
524
+ function isCallerAbort(error, signal) {
525
+ return signal?.aborted === true && (isAbortError(error) || error === signal.reason);
526
+ }
473
527
  function isAbortError(error) {
474
528
  return error instanceof Error && error.name === "AbortError";
475
529
  }
package/dist/index.js CHANGED
@@ -106,7 +106,7 @@ var MailgunHttpClient = class {
106
106
  throw new MailgunApiError(lastError.message, void 0, void 0, attempt + 1);
107
107
  }
108
108
  const delay = Math.pow(2, attempt) * 1e3;
109
- await new Promise((resolve) => setTimeout(resolve, delay));
109
+ await sleep(delay, options.signal);
110
110
  }
111
111
  throw lastError || /* @__PURE__ */ new Error("Request failed after all retries");
112
112
  }
@@ -126,18 +126,18 @@ var MailgunHttpClient = class {
126
126
  for (const [key, value] of Object.entries(this.config.headers)) headers.set(key, value);
127
127
  const controller = new AbortController();
128
128
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
129
- let signal = controller.signal;
130
- if (options.signal) signal = AbortSignal.any([controller.signal, options.signal]);
129
+ const combinedSignal = combineSignals(controller.signal, options.signal);
131
130
  try {
132
131
  return await globalThis.fetch(url, {
133
132
  ...options,
134
133
  headers,
135
- signal
134
+ signal: combinedSignal.signal
136
135
  });
137
136
  } catch (error) {
138
137
  if (isAbortError$1(error) && controller.signal.aborted && !options.signal?.aborted) throw new Error(`Mailgun API request timed out after ${this.config.timeout} ms.`);
139
138
  throw error;
140
139
  } finally {
140
+ combinedSignal.cleanup();
141
141
  clearTimeout(timeoutId);
142
142
  }
143
143
  }
@@ -179,6 +179,57 @@ var MailgunApiError = class extends Error {
179
179
  function isAbortError$1(error) {
180
180
  return error instanceof Error && error.name === "AbortError";
181
181
  }
182
+ function sleep(milliseconds, signal) {
183
+ if (signal?.aborted) return Promise.reject(createAbortError(signal));
184
+ return new Promise((resolve, reject) => {
185
+ function abort() {
186
+ clearTimeout(timeoutId);
187
+ signal?.removeEventListener("abort", abort);
188
+ reject(createAbortError(signal));
189
+ }
190
+ const timeoutId = setTimeout(() => {
191
+ signal?.removeEventListener("abort", abort);
192
+ resolve();
193
+ }, milliseconds);
194
+ signal?.addEventListener("abort", abort, { once: true });
195
+ });
196
+ }
197
+ function createAbortError(signal) {
198
+ return signal?.reason ?? new DOMException("The operation was aborted.", "AbortError");
199
+ }
200
+ function combineSignals(timeoutSignal, externalSignal) {
201
+ if (externalSignal == null) return {
202
+ signal: timeoutSignal,
203
+ cleanup: () => {}
204
+ };
205
+ if (typeof AbortSignal.any === "function") return {
206
+ signal: AbortSignal.any([timeoutSignal, externalSignal]),
207
+ cleanup: () => {}
208
+ };
209
+ const controller = new AbortController();
210
+ const cleanup = () => {
211
+ timeoutSignal.removeEventListener("abort", abortFromTimeout);
212
+ externalSignal.removeEventListener("abort", abortFromExternal);
213
+ };
214
+ const abortFromTimeout = () => {
215
+ cleanup();
216
+ controller.abort(timeoutSignal.reason);
217
+ };
218
+ const abortFromExternal = () => {
219
+ cleanup();
220
+ controller.abort(externalSignal.reason);
221
+ };
222
+ if (timeoutSignal.aborted) controller.abort(timeoutSignal.reason);
223
+ else if (externalSignal.aborted) controller.abort(externalSignal.reason);
224
+ else {
225
+ timeoutSignal.addEventListener("abort", abortFromTimeout, { once: true });
226
+ externalSignal.addEventListener("abort", abortFromExternal, { once: true });
227
+ }
228
+ return {
229
+ signal: controller.signal,
230
+ cleanup
231
+ };
232
+ }
182
233
  function truncateErrorBody(text) {
183
234
  return text.length > 500 ? `${text.slice(0, 500)}...` : text;
184
235
  }
@@ -368,7 +419,7 @@ var MailgunTransport = class {
368
419
  provider: "mailgun"
369
420
  };
370
421
  } catch (error) {
371
- if (isAbortError(error) && options?.signal?.aborted) throw error;
422
+ if (isCallerAbort(error, options?.signal)) throw error;
372
423
  const errorMessage = error instanceof Error ? error.message : String(error);
373
424
  return createMailgunFailure(errorMessage, error);
374
425
  }
@@ -447,6 +498,9 @@ function createMailgunFailure(message, error) {
447
498
  });
448
499
  return createFailedReceipt(message, { provider: "mailgun" });
449
500
  }
501
+ function isCallerAbort(error, signal) {
502
+ return signal?.aborted === true && (isAbortError(error) || error === signal.reason);
503
+ }
450
504
  function isAbortError(error) {
451
505
  return error instanceof Error && error.name === "AbortError";
452
506
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upyo/mailgun",
3
- "version": "0.5.0-dev.158",
3
+ "version": "0.5.0-dev.168",
4
4
  "description": "Mailgun transport for Upyo email library",
5
5
  "keywords": [
6
6
  "email",
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "sideEffects": false,
55
55
  "peerDependencies": {
56
- "@upyo/core": "0.5.0-dev.158+468b767c"
56
+ "@upyo/core": "0.5.0-dev.168+1e808a3a"
57
57
  },
58
58
  "devDependencies": {
59
59
  "tsdown": "^0.12.7",