@upyo/ses 0.5.0-dev.158 → 0.5.0-dev.164

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
@@ -80,6 +80,16 @@ var SesHttpClient = class {
80
80
  signal
81
81
  });
82
82
  }
83
+ /**
84
+ * Makes an HTTP request to the SES API with retry logic.
85
+ *
86
+ * @param url The URL to make the request to.
87
+ * @param options Fetch options.
88
+ * @returns Promise that resolves to the parsed response.
89
+ * @throws {DOMException} If the caller aborts the request.
90
+ * @throws {SesApiError} If SES returns a client error or all retry attempts
91
+ * are exhausted.
92
+ */
83
93
  async makeRequest(url, options) {
84
94
  let lastError = null;
85
95
  for (let attempt = 0; attempt <= this.config.retries; attempt++) try {
@@ -106,10 +116,19 @@ var SesHttpClient = class {
106
116
  throw new SesApiError(lastError.message, void 0, void 0, void 0, attempt + 1);
107
117
  }
108
118
  const delay = Math.pow(2, attempt) * 1e3;
109
- await new Promise((resolve) => setTimeout(resolve, delay));
119
+ await sleep(delay, options.signal);
110
120
  }
111
121
  throw lastError || /* @__PURE__ */ new Error("Request failed after all retries");
112
122
  }
123
+ /**
124
+ * Makes a signed fetch request to the SES API.
125
+ *
126
+ * @param url The URL to make the request to.
127
+ * @param options Fetch options.
128
+ * @returns Promise that resolves to the fetch response.
129
+ * @throws {Error} If the configured request timeout is reached.
130
+ * @throws {DOMException} If the caller aborts the request.
131
+ */
113
132
  async fetchWithAuth(url, options) {
114
133
  const credentials = await this.getCredentials();
115
134
  const headers = new Headers(options.headers);
@@ -219,6 +238,24 @@ var SesHttpClient = class {
219
238
  function isAbortError$1(error) {
220
239
  return error instanceof Error && error.name === "AbortError";
221
240
  }
241
+ function sleep(milliseconds, signal) {
242
+ if (signal?.aborted) return Promise.reject(createAbortError());
243
+ return new Promise((resolve, reject) => {
244
+ function abort() {
245
+ clearTimeout(timeoutId);
246
+ signal?.removeEventListener("abort", abort);
247
+ reject(createAbortError());
248
+ }
249
+ const timeoutId = setTimeout(() => {
250
+ signal?.removeEventListener("abort", abort);
251
+ resolve();
252
+ }, milliseconds);
253
+ signal?.addEventListener("abort", abort, { once: true });
254
+ });
255
+ }
256
+ function createAbortError() {
257
+ return new DOMException("The operation was aborted.", "AbortError");
258
+ }
222
259
  var SesApiError = class extends Error {
223
260
  statusCode;
224
261
  errors;
package/dist/index.js CHANGED
@@ -57,6 +57,16 @@ var SesHttpClient = class {
57
57
  signal
58
58
  });
59
59
  }
60
+ /**
61
+ * Makes an HTTP request to the SES API with retry logic.
62
+ *
63
+ * @param url The URL to make the request to.
64
+ * @param options Fetch options.
65
+ * @returns Promise that resolves to the parsed response.
66
+ * @throws {DOMException} If the caller aborts the request.
67
+ * @throws {SesApiError} If SES returns a client error or all retry attempts
68
+ * are exhausted.
69
+ */
60
70
  async makeRequest(url, options) {
61
71
  let lastError = null;
62
72
  for (let attempt = 0; attempt <= this.config.retries; attempt++) try {
@@ -83,10 +93,19 @@ var SesHttpClient = class {
83
93
  throw new SesApiError(lastError.message, void 0, void 0, void 0, attempt + 1);
84
94
  }
85
95
  const delay = Math.pow(2, attempt) * 1e3;
86
- await new Promise((resolve) => setTimeout(resolve, delay));
96
+ await sleep(delay, options.signal);
87
97
  }
88
98
  throw lastError || /* @__PURE__ */ new Error("Request failed after all retries");
89
99
  }
100
+ /**
101
+ * Makes a signed fetch request to the SES API.
102
+ *
103
+ * @param url The URL to make the request to.
104
+ * @param options Fetch options.
105
+ * @returns Promise that resolves to the fetch response.
106
+ * @throws {Error} If the configured request timeout is reached.
107
+ * @throws {DOMException} If the caller aborts the request.
108
+ */
90
109
  async fetchWithAuth(url, options) {
91
110
  const credentials = await this.getCredentials();
92
111
  const headers = new Headers(options.headers);
@@ -196,6 +215,24 @@ var SesHttpClient = class {
196
215
  function isAbortError$1(error) {
197
216
  return error instanceof Error && error.name === "AbortError";
198
217
  }
218
+ function sleep(milliseconds, signal) {
219
+ if (signal?.aborted) return Promise.reject(createAbortError());
220
+ return new Promise((resolve, reject) => {
221
+ function abort() {
222
+ clearTimeout(timeoutId);
223
+ signal?.removeEventListener("abort", abort);
224
+ reject(createAbortError());
225
+ }
226
+ const timeoutId = setTimeout(() => {
227
+ signal?.removeEventListener("abort", abort);
228
+ resolve();
229
+ }, milliseconds);
230
+ signal?.addEventListener("abort", abort, { once: true });
231
+ });
232
+ }
233
+ function createAbortError() {
234
+ return new DOMException("The operation was aborted.", "AbortError");
235
+ }
199
236
  var SesApiError = class extends Error {
200
237
  statusCode;
201
238
  errors;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upyo/ses",
3
- "version": "0.5.0-dev.158",
3
+ "version": "0.5.0-dev.164",
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.158+468b767c"
58
+ "@upyo/core": "0.5.0-dev.164+5e283c64"
59
59
  },
60
60
  "devDependencies": {
61
61
  "tsdown": "^0.12.7",