@upyo/ses 0.5.0-dev.164 → 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
@@ -139,17 +139,18 @@ var SesHttpClient = class {
139
139
  for (const [key, value] of Object.entries(this.config.headers)) signedHeaders.set(key, value);
140
140
  const controller = new AbortController();
141
141
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
142
- const signal = options.signal == null ? controller.signal : AbortSignal.any([controller.signal, options.signal]);
142
+ const combinedSignal = combineSignals(controller.signal, options.signal);
143
143
  try {
144
144
  return await globalThis.fetch(url, {
145
145
  ...options,
146
146
  headers: this.headersToRecord(signedHeaders),
147
- signal
147
+ signal: combinedSignal.signal
148
148
  });
149
149
  } catch (error) {
150
150
  if (isAbortError$1(error) && controller.signal.aborted && !options.signal?.aborted) throw new Error(`SES API request timed out after ${this.config.timeout} ms.`);
151
151
  throw error;
152
152
  } finally {
153
+ combinedSignal.cleanup();
153
154
  clearTimeout(timeoutId);
154
155
  }
155
156
  }
@@ -239,12 +240,12 @@ function isAbortError$1(error) {
239
240
  return error instanceof Error && error.name === "AbortError";
240
241
  }
241
242
  function sleep(milliseconds, signal) {
242
- if (signal?.aborted) return Promise.reject(createAbortError());
243
+ if (signal?.aborted) return Promise.reject(createAbortError(signal));
243
244
  return new Promise((resolve, reject) => {
244
245
  function abort() {
245
246
  clearTimeout(timeoutId);
246
247
  signal?.removeEventListener("abort", abort);
247
- reject(createAbortError());
248
+ reject(createAbortError(signal));
248
249
  }
249
250
  const timeoutId = setTimeout(() => {
250
251
  signal?.removeEventListener("abort", abort);
@@ -253,8 +254,41 @@ function sleep(milliseconds, signal) {
253
254
  signal?.addEventListener("abort", abort, { once: true });
254
255
  });
255
256
  }
256
- function createAbortError() {
257
- return new DOMException("The operation was aborted.", "AbortError");
257
+ function createAbortError(signal) {
258
+ return signal?.reason ?? new DOMException("The operation was aborted.", "AbortError");
259
+ }
260
+ function combineSignals(timeoutSignal, externalSignal) {
261
+ if (externalSignal == null) return {
262
+ signal: timeoutSignal,
263
+ cleanup: () => {}
264
+ };
265
+ if (typeof AbortSignal.any === "function") return {
266
+ signal: AbortSignal.any([timeoutSignal, externalSignal]),
267
+ cleanup: () => {}
268
+ };
269
+ const controller = new AbortController();
270
+ const cleanup = () => {
271
+ timeoutSignal.removeEventListener("abort", abortFromTimeout);
272
+ externalSignal.removeEventListener("abort", abortFromExternal);
273
+ };
274
+ const abortFromTimeout = () => {
275
+ cleanup();
276
+ controller.abort(timeoutSignal.reason);
277
+ };
278
+ const abortFromExternal = () => {
279
+ cleanup();
280
+ controller.abort(externalSignal.reason);
281
+ };
282
+ if (timeoutSignal.aborted) controller.abort(timeoutSignal.reason);
283
+ else if (externalSignal.aborted) controller.abort(externalSignal.reason);
284
+ else {
285
+ timeoutSignal.addEventListener("abort", abortFromTimeout, { once: true });
286
+ externalSignal.addEventListener("abort", abortFromExternal, { once: true });
287
+ }
288
+ return {
289
+ signal: controller.signal,
290
+ cleanup
291
+ };
258
292
  }
259
293
  var SesApiError = class extends Error {
260
294
  statusCode;
@@ -435,7 +469,7 @@ var SesTransport = class {
435
469
  provider: "ses"
436
470
  };
437
471
  } catch (error) {
438
- if (isAbortError(error) && options?.signal?.aborted) throw error;
472
+ if (isCallerAbort(error, options?.signal)) throw error;
439
473
  const errorMessage = error instanceof Error ? error.message : String(error);
440
474
  return createSesFailure(errorMessage, error);
441
475
  }
@@ -510,6 +544,9 @@ function createSesFailure(message, error) {
510
544
  });
511
545
  return (0, __upyo_core.createFailedReceipt)(message, { provider: "ses" });
512
546
  }
547
+ function isCallerAbort(error, signal) {
548
+ return signal?.aborted === true && (isAbortError(error) || error === signal.reason);
549
+ }
513
550
  function isAbortError(error) {
514
551
  return error instanceof Error && error.name === "AbortError";
515
552
  }
package/dist/index.js CHANGED
@@ -116,17 +116,18 @@ var SesHttpClient = class {
116
116
  for (const [key, value] of Object.entries(this.config.headers)) signedHeaders.set(key, value);
117
117
  const controller = new AbortController();
118
118
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
119
- const signal = options.signal == null ? controller.signal : AbortSignal.any([controller.signal, options.signal]);
119
+ const combinedSignal = combineSignals(controller.signal, options.signal);
120
120
  try {
121
121
  return await globalThis.fetch(url, {
122
122
  ...options,
123
123
  headers: this.headersToRecord(signedHeaders),
124
- signal
124
+ signal: combinedSignal.signal
125
125
  });
126
126
  } catch (error) {
127
127
  if (isAbortError$1(error) && controller.signal.aborted && !options.signal?.aborted) throw new Error(`SES API request timed out after ${this.config.timeout} ms.`);
128
128
  throw error;
129
129
  } finally {
130
+ combinedSignal.cleanup();
130
131
  clearTimeout(timeoutId);
131
132
  }
132
133
  }
@@ -216,12 +217,12 @@ function isAbortError$1(error) {
216
217
  return error instanceof Error && error.name === "AbortError";
217
218
  }
218
219
  function sleep(milliseconds, signal) {
219
- if (signal?.aborted) return Promise.reject(createAbortError());
220
+ if (signal?.aborted) return Promise.reject(createAbortError(signal));
220
221
  return new Promise((resolve, reject) => {
221
222
  function abort() {
222
223
  clearTimeout(timeoutId);
223
224
  signal?.removeEventListener("abort", abort);
224
- reject(createAbortError());
225
+ reject(createAbortError(signal));
225
226
  }
226
227
  const timeoutId = setTimeout(() => {
227
228
  signal?.removeEventListener("abort", abort);
@@ -230,8 +231,41 @@ function sleep(milliseconds, signal) {
230
231
  signal?.addEventListener("abort", abort, { once: true });
231
232
  });
232
233
  }
233
- function createAbortError() {
234
- return new DOMException("The operation was aborted.", "AbortError");
234
+ function createAbortError(signal) {
235
+ return signal?.reason ?? new DOMException("The operation was aborted.", "AbortError");
236
+ }
237
+ function combineSignals(timeoutSignal, externalSignal) {
238
+ if (externalSignal == null) return {
239
+ signal: timeoutSignal,
240
+ cleanup: () => {}
241
+ };
242
+ if (typeof AbortSignal.any === "function") return {
243
+ signal: AbortSignal.any([timeoutSignal, externalSignal]),
244
+ cleanup: () => {}
245
+ };
246
+ const controller = new AbortController();
247
+ const cleanup = () => {
248
+ timeoutSignal.removeEventListener("abort", abortFromTimeout);
249
+ externalSignal.removeEventListener("abort", abortFromExternal);
250
+ };
251
+ const abortFromTimeout = () => {
252
+ cleanup();
253
+ controller.abort(timeoutSignal.reason);
254
+ };
255
+ const abortFromExternal = () => {
256
+ cleanup();
257
+ controller.abort(externalSignal.reason);
258
+ };
259
+ if (timeoutSignal.aborted) controller.abort(timeoutSignal.reason);
260
+ else if (externalSignal.aborted) controller.abort(externalSignal.reason);
261
+ else {
262
+ timeoutSignal.addEventListener("abort", abortFromTimeout, { once: true });
263
+ externalSignal.addEventListener("abort", abortFromExternal, { once: true });
264
+ }
265
+ return {
266
+ signal: controller.signal,
267
+ cleanup
268
+ };
235
269
  }
236
270
  var SesApiError = class extends Error {
237
271
  statusCode;
@@ -412,7 +446,7 @@ var SesTransport = class {
412
446
  provider: "ses"
413
447
  };
414
448
  } catch (error) {
415
- if (isAbortError(error) && options?.signal?.aborted) throw error;
449
+ if (isCallerAbort(error, options?.signal)) throw error;
416
450
  const errorMessage = error instanceof Error ? error.message : String(error);
417
451
  return createSesFailure(errorMessage, error);
418
452
  }
@@ -487,6 +521,9 @@ function createSesFailure(message, error) {
487
521
  });
488
522
  return createFailedReceipt(message, { provider: "ses" });
489
523
  }
524
+ function isCallerAbort(error, signal) {
525
+ return signal?.aborted === true && (isAbortError(error) || error === signal.reason);
526
+ }
490
527
  function isAbortError(error) {
491
528
  return error instanceof Error && error.name === "AbortError";
492
529
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upyo/ses",
3
- "version": "0.5.0-dev.164",
3
+ "version": "0.5.0-dev.168",
4
4
  "description": "Amazon SES transport for Upyo email library",
5
5
  "keywords": [
6
6
  "email",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "sideEffects": false,
57
57
  "peerDependencies": {
58
- "@upyo/core": "0.5.0-dev.164+5e283c64"
58
+ "@upyo/core": "0.5.0-dev.168+1e808a3a"
59
59
  },
60
60
  "devDependencies": {
61
61
  "tsdown": "^0.12.7",