@upyo/resend 0.5.0-dev.128 → 0.5.0-dev.154
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 +99 -17
- package/dist/index.d.cts +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.js +77 -17
- package/package.json +3 -8
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
const __upyo_core = __toESM(require("@upyo/core"));
|
|
1
25
|
|
|
2
26
|
//#region src/config.ts
|
|
3
27
|
/**
|
|
@@ -25,14 +49,37 @@ function createResendConfig(config) {
|
|
|
25
49
|
//#endregion
|
|
26
50
|
//#region src/http-client.ts
|
|
27
51
|
/**
|
|
28
|
-
*
|
|
52
|
+
* Error thrown when a Resend API request fails.
|
|
53
|
+
*
|
|
54
|
+
* @since 0.5.0
|
|
29
55
|
*/
|
|
30
56
|
var ResendApiError = class extends Error {
|
|
57
|
+
/**
|
|
58
|
+
* HTTP status code returned by Resend, if the request reached the API.
|
|
59
|
+
*/
|
|
31
60
|
statusCode;
|
|
32
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Retry delay from Resend's `Retry-After` response header.
|
|
63
|
+
*/
|
|
64
|
+
retryAfterMilliseconds;
|
|
65
|
+
/**
|
|
66
|
+
* Number of attempts made before this error was produced.
|
|
67
|
+
*/
|
|
68
|
+
attempts;
|
|
69
|
+
/**
|
|
70
|
+
* Creates a Resend API error.
|
|
71
|
+
*
|
|
72
|
+
* @param message Error message.
|
|
73
|
+
* @param statusCode HTTP status code returned by Resend.
|
|
74
|
+
* @param retryAfterMilliseconds Retry delay from the response.
|
|
75
|
+
* @param attempts Number of attempts made before this error.
|
|
76
|
+
*/
|
|
77
|
+
constructor(message, statusCode, retryAfterMilliseconds, attempts) {
|
|
33
78
|
super(message);
|
|
34
79
|
this.name = "ResendApiError";
|
|
35
80
|
this.statusCode = statusCode;
|
|
81
|
+
this.retryAfterMilliseconds = retryAfterMilliseconds;
|
|
82
|
+
this.attempts = attempts;
|
|
36
83
|
}
|
|
37
84
|
};
|
|
38
85
|
/**
|
|
@@ -102,7 +149,10 @@ var ResendHttpClient = class {
|
|
|
102
149
|
const errorBody = JSON.parse(text);
|
|
103
150
|
errorMessage = errorBody.message;
|
|
104
151
|
} catch {}
|
|
105
|
-
|
|
152
|
+
const parsedErrorMessage = errorMessage === "" ? void 0 : errorMessage;
|
|
153
|
+
const responseMessage = truncateErrorBody(text);
|
|
154
|
+
const fallbackMessage = responseMessage === "" ? void 0 : responseMessage;
|
|
155
|
+
throw new ResendApiError(parsedErrorMessage ?? fallbackMessage ?? `HTTP ${response.status}`, response.status, (0, __upyo_core.parseRetryAfter)(response.headers.get("Retry-After")), attempt + 1);
|
|
106
156
|
}
|
|
107
157
|
try {
|
|
108
158
|
return JSON.parse(text);
|
|
@@ -111,9 +161,12 @@ var ResendHttpClient = class {
|
|
|
111
161
|
}
|
|
112
162
|
} catch (error) {
|
|
113
163
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
114
|
-
if (error instanceof ResendApiError && error.statusCode >= 400 && error.statusCode < 500) throw error;
|
|
164
|
+
if (error instanceof ResendApiError && error.statusCode !== void 0 && error.statusCode >= 400 && error.statusCode < 500) throw error;
|
|
115
165
|
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
116
|
-
if (attempt === this.config.retries)
|
|
166
|
+
if (attempt === this.config.retries) {
|
|
167
|
+
if (lastError instanceof ResendApiError) throw lastError;
|
|
168
|
+
throw new ResendApiError(lastError.message, void 0, void 0, attempt + 1);
|
|
169
|
+
}
|
|
117
170
|
const backoffMs = Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
118
171
|
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
119
172
|
}
|
|
@@ -133,11 +186,19 @@ var ResendHttpClient = class {
|
|
|
133
186
|
const controller = new AbortController();
|
|
134
187
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
135
188
|
let signal;
|
|
189
|
+
let cleanup = () => {};
|
|
136
190
|
if (options.signal) {
|
|
137
191
|
const combinedController = new AbortController();
|
|
138
192
|
const onAbort = () => combinedController.abort();
|
|
139
|
-
options.signal.
|
|
140
|
-
|
|
193
|
+
if (options.signal.aborted || controller.signal.aborted) combinedController.abort();
|
|
194
|
+
else {
|
|
195
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
196
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
197
|
+
}
|
|
198
|
+
cleanup = () => {
|
|
199
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
200
|
+
controller.signal.removeEventListener("abort", onAbort);
|
|
201
|
+
};
|
|
141
202
|
signal = combinedController.signal;
|
|
142
203
|
} else signal = controller.signal;
|
|
143
204
|
try {
|
|
@@ -147,11 +208,21 @@ var ResendHttpClient = class {
|
|
|
147
208
|
signal
|
|
148
209
|
});
|
|
149
210
|
return response;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
if (isAbortError$1(error) && controller.signal.aborted && !options.signal?.aborted) throw new Error(`Resend API request timed out after ${this.config.timeout} ms.`);
|
|
213
|
+
throw error;
|
|
150
214
|
} finally {
|
|
215
|
+
cleanup();
|
|
151
216
|
clearTimeout(timeoutId);
|
|
152
217
|
}
|
|
153
218
|
}
|
|
154
219
|
};
|
|
220
|
+
function isAbortError$1(error) {
|
|
221
|
+
return error instanceof Error && error.name === "AbortError";
|
|
222
|
+
}
|
|
223
|
+
function truncateErrorBody(text) {
|
|
224
|
+
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
225
|
+
}
|
|
155
226
|
|
|
156
227
|
//#endregion
|
|
157
228
|
//#region src/message-converter.ts
|
|
@@ -339,6 +410,7 @@ function generateIdempotencyKey() {
|
|
|
339
410
|
* ```
|
|
340
411
|
*/
|
|
341
412
|
var ResendTransport = class {
|
|
413
|
+
id = "resend";
|
|
342
414
|
/**
|
|
343
415
|
* The resolved Resend configuration used by this transport.
|
|
344
416
|
*/
|
|
@@ -396,14 +468,13 @@ var ResendTransport = class {
|
|
|
396
468
|
const response = await this.httpClient.sendMessage(emailData, options?.signal, idempotencyKey);
|
|
397
469
|
return {
|
|
398
470
|
successful: true,
|
|
399
|
-
messageId: response.id
|
|
471
|
+
messageId: response.id,
|
|
472
|
+
provider: "resend"
|
|
400
473
|
};
|
|
401
474
|
} catch (error) {
|
|
475
|
+
if (isAbortError(error) && options?.signal?.aborted) throw error;
|
|
402
476
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
403
|
-
return
|
|
404
|
-
successful: false,
|
|
405
|
-
errorMessages: [errorMessage]
|
|
406
|
-
};
|
|
477
|
+
return createResendFailure(errorMessage, error);
|
|
407
478
|
}
|
|
408
479
|
}
|
|
409
480
|
/**
|
|
@@ -512,14 +583,13 @@ var ResendTransport = class {
|
|
|
512
583
|
const response = await this.httpClient.sendBatch(batchData, options?.signal, idempotencyKey);
|
|
513
584
|
for (const result of response.data) yield {
|
|
514
585
|
successful: true,
|
|
515
|
-
messageId: result.id
|
|
586
|
+
messageId: result.id,
|
|
587
|
+
provider: "resend"
|
|
516
588
|
};
|
|
517
589
|
} catch (error) {
|
|
590
|
+
if (isAbortError(error) && options?.signal?.aborted) throw error;
|
|
518
591
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
519
|
-
for (let i = 0; i < messages.length; i++) yield
|
|
520
|
-
successful: false,
|
|
521
|
-
errorMessages: [errorMessage]
|
|
522
|
-
};
|
|
592
|
+
for (let i = 0; i < messages.length; i++) yield createResendFailure(errorMessage, error);
|
|
523
593
|
}
|
|
524
594
|
}
|
|
525
595
|
/**
|
|
@@ -549,6 +619,18 @@ var ResendTransport = class {
|
|
|
549
619
|
return chunks;
|
|
550
620
|
}
|
|
551
621
|
};
|
|
622
|
+
function createResendFailure(message, error) {
|
|
623
|
+
if (error instanceof ResendApiError) return (0, __upyo_core.createFailedReceipt)(message, {
|
|
624
|
+
provider: "resend",
|
|
625
|
+
statusCode: error.statusCode,
|
|
626
|
+
retryAfterMilliseconds: error.retryAfterMilliseconds,
|
|
627
|
+
attempts: error.attempts
|
|
628
|
+
});
|
|
629
|
+
return (0, __upyo_core.createFailedReceipt)(message, { provider: "resend" });
|
|
630
|
+
}
|
|
631
|
+
function isAbortError(error) {
|
|
632
|
+
return error instanceof Error && error.name === "AbortError";
|
|
633
|
+
}
|
|
552
634
|
|
|
553
635
|
//#endregion
|
|
554
636
|
exports.ResendTransport = ResendTransport;
|
package/dist/index.d.cts
CHANGED
|
@@ -99,7 +99,8 @@ type ResolvedResendConfig = Required<ResendConfig>;
|
|
|
99
99
|
* }
|
|
100
100
|
* ```
|
|
101
101
|
*/
|
|
102
|
-
declare class ResendTransport implements Transport {
|
|
102
|
+
declare class ResendTransport implements Transport<"resend"> {
|
|
103
|
+
readonly id = "resend";
|
|
103
104
|
/**
|
|
104
105
|
* The resolved Resend configuration used by this transport.
|
|
105
106
|
*/
|
|
@@ -145,7 +146,7 @@ declare class ResendTransport implements Transport {
|
|
|
145
146
|
* @returns A promise that resolves to a receipt indicating success or
|
|
146
147
|
* failure.
|
|
147
148
|
*/
|
|
148
|
-
send(message: Message, options?: TransportOptions): Promise<Receipt
|
|
149
|
+
send(message: Message, options?: TransportOptions): Promise<Receipt<"resend">>;
|
|
149
150
|
/**
|
|
150
151
|
* Sends multiple email messages efficiently via Resend API.
|
|
151
152
|
*
|
|
@@ -200,7 +201,7 @@ declare class ResendTransport implements Transport {
|
|
|
200
201
|
* cancellation.
|
|
201
202
|
* @returns An async iterable of receipts, one for each message.
|
|
202
203
|
*/
|
|
203
|
-
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt
|
|
204
|
+
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt<"resend">>;
|
|
204
205
|
/**
|
|
205
206
|
* Optimized batch sending that chooses the best strategy based on message features.
|
|
206
207
|
*
|
|
@@ -274,11 +275,32 @@ interface ResendError {
|
|
|
274
275
|
name?: string;
|
|
275
276
|
}
|
|
276
277
|
/**
|
|
277
|
-
*
|
|
278
|
+
* Error thrown when a Resend API request fails.
|
|
279
|
+
*
|
|
280
|
+
* @since 0.5.0
|
|
278
281
|
*/
|
|
279
282
|
declare class ResendApiError extends Error {
|
|
280
|
-
|
|
281
|
-
|
|
283
|
+
/**
|
|
284
|
+
* HTTP status code returned by Resend, if the request reached the API.
|
|
285
|
+
*/
|
|
286
|
+
readonly statusCode?: number;
|
|
287
|
+
/**
|
|
288
|
+
* Retry delay from Resend's `Retry-After` response header.
|
|
289
|
+
*/
|
|
290
|
+
readonly retryAfterMilliseconds?: number;
|
|
291
|
+
/**
|
|
292
|
+
* Number of attempts made before this error was produced.
|
|
293
|
+
*/
|
|
294
|
+
readonly attempts?: number;
|
|
295
|
+
/**
|
|
296
|
+
* Creates a Resend API error.
|
|
297
|
+
*
|
|
298
|
+
* @param message Error message.
|
|
299
|
+
* @param statusCode HTTP status code returned by Resend.
|
|
300
|
+
* @param retryAfterMilliseconds Retry delay from the response.
|
|
301
|
+
* @param attempts Number of attempts made before this error.
|
|
302
|
+
*/
|
|
303
|
+
constructor(message: string, statusCode?: number, retryAfterMilliseconds?: number, attempts?: number);
|
|
282
304
|
}
|
|
283
305
|
/**
|
|
284
306
|
* HTTP client wrapper for Resend API requests.
|
package/dist/index.d.ts
CHANGED
|
@@ -99,7 +99,8 @@ type ResolvedResendConfig = Required<ResendConfig>;
|
|
|
99
99
|
* }
|
|
100
100
|
* ```
|
|
101
101
|
*/
|
|
102
|
-
declare class ResendTransport implements Transport {
|
|
102
|
+
declare class ResendTransport implements Transport<"resend"> {
|
|
103
|
+
readonly id = "resend";
|
|
103
104
|
/**
|
|
104
105
|
* The resolved Resend configuration used by this transport.
|
|
105
106
|
*/
|
|
@@ -145,7 +146,7 @@ declare class ResendTransport implements Transport {
|
|
|
145
146
|
* @returns A promise that resolves to a receipt indicating success or
|
|
146
147
|
* failure.
|
|
147
148
|
*/
|
|
148
|
-
send(message: Message, options?: TransportOptions): Promise<Receipt
|
|
149
|
+
send(message: Message, options?: TransportOptions): Promise<Receipt<"resend">>;
|
|
149
150
|
/**
|
|
150
151
|
* Sends multiple email messages efficiently via Resend API.
|
|
151
152
|
*
|
|
@@ -200,7 +201,7 @@ declare class ResendTransport implements Transport {
|
|
|
200
201
|
* cancellation.
|
|
201
202
|
* @returns An async iterable of receipts, one for each message.
|
|
202
203
|
*/
|
|
203
|
-
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt
|
|
204
|
+
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt<"resend">>;
|
|
204
205
|
/**
|
|
205
206
|
* Optimized batch sending that chooses the best strategy based on message features.
|
|
206
207
|
*
|
|
@@ -274,11 +275,32 @@ interface ResendError {
|
|
|
274
275
|
name?: string;
|
|
275
276
|
}
|
|
276
277
|
/**
|
|
277
|
-
*
|
|
278
|
+
* Error thrown when a Resend API request fails.
|
|
279
|
+
*
|
|
280
|
+
* @since 0.5.0
|
|
278
281
|
*/
|
|
279
282
|
declare class ResendApiError extends Error {
|
|
280
|
-
|
|
281
|
-
|
|
283
|
+
/**
|
|
284
|
+
* HTTP status code returned by Resend, if the request reached the API.
|
|
285
|
+
*/
|
|
286
|
+
readonly statusCode?: number;
|
|
287
|
+
/**
|
|
288
|
+
* Retry delay from Resend's `Retry-After` response header.
|
|
289
|
+
*/
|
|
290
|
+
readonly retryAfterMilliseconds?: number;
|
|
291
|
+
/**
|
|
292
|
+
* Number of attempts made before this error was produced.
|
|
293
|
+
*/
|
|
294
|
+
readonly attempts?: number;
|
|
295
|
+
/**
|
|
296
|
+
* Creates a Resend API error.
|
|
297
|
+
*
|
|
298
|
+
* @param message Error message.
|
|
299
|
+
* @param statusCode HTTP status code returned by Resend.
|
|
300
|
+
* @param retryAfterMilliseconds Retry delay from the response.
|
|
301
|
+
* @param attempts Number of attempts made before this error.
|
|
302
|
+
*/
|
|
303
|
+
constructor(message: string, statusCode?: number, retryAfterMilliseconds?: number, attempts?: number);
|
|
282
304
|
}
|
|
283
305
|
/**
|
|
284
306
|
* HTTP client wrapper for Resend API requests.
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createFailedReceipt, parseRetryAfter } from "@upyo/core";
|
|
2
|
+
|
|
1
3
|
//#region src/config.ts
|
|
2
4
|
/**
|
|
3
5
|
* Creates a resolved Resend configuration by applying default values to optional fields.
|
|
@@ -24,14 +26,37 @@ function createResendConfig(config) {
|
|
|
24
26
|
//#endregion
|
|
25
27
|
//#region src/http-client.ts
|
|
26
28
|
/**
|
|
27
|
-
*
|
|
29
|
+
* Error thrown when a Resend API request fails.
|
|
30
|
+
*
|
|
31
|
+
* @since 0.5.0
|
|
28
32
|
*/
|
|
29
33
|
var ResendApiError = class extends Error {
|
|
34
|
+
/**
|
|
35
|
+
* HTTP status code returned by Resend, if the request reached the API.
|
|
36
|
+
*/
|
|
30
37
|
statusCode;
|
|
31
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Retry delay from Resend's `Retry-After` response header.
|
|
40
|
+
*/
|
|
41
|
+
retryAfterMilliseconds;
|
|
42
|
+
/**
|
|
43
|
+
* Number of attempts made before this error was produced.
|
|
44
|
+
*/
|
|
45
|
+
attempts;
|
|
46
|
+
/**
|
|
47
|
+
* Creates a Resend API error.
|
|
48
|
+
*
|
|
49
|
+
* @param message Error message.
|
|
50
|
+
* @param statusCode HTTP status code returned by Resend.
|
|
51
|
+
* @param retryAfterMilliseconds Retry delay from the response.
|
|
52
|
+
* @param attempts Number of attempts made before this error.
|
|
53
|
+
*/
|
|
54
|
+
constructor(message, statusCode, retryAfterMilliseconds, attempts) {
|
|
32
55
|
super(message);
|
|
33
56
|
this.name = "ResendApiError";
|
|
34
57
|
this.statusCode = statusCode;
|
|
58
|
+
this.retryAfterMilliseconds = retryAfterMilliseconds;
|
|
59
|
+
this.attempts = attempts;
|
|
35
60
|
}
|
|
36
61
|
};
|
|
37
62
|
/**
|
|
@@ -101,7 +126,10 @@ var ResendHttpClient = class {
|
|
|
101
126
|
const errorBody = JSON.parse(text);
|
|
102
127
|
errorMessage = errorBody.message;
|
|
103
128
|
} catch {}
|
|
104
|
-
|
|
129
|
+
const parsedErrorMessage = errorMessage === "" ? void 0 : errorMessage;
|
|
130
|
+
const responseMessage = truncateErrorBody(text);
|
|
131
|
+
const fallbackMessage = responseMessage === "" ? void 0 : responseMessage;
|
|
132
|
+
throw new ResendApiError(parsedErrorMessage ?? fallbackMessage ?? `HTTP ${response.status}`, response.status, parseRetryAfter(response.headers.get("Retry-After")), attempt + 1);
|
|
105
133
|
}
|
|
106
134
|
try {
|
|
107
135
|
return JSON.parse(text);
|
|
@@ -110,9 +138,12 @@ var ResendHttpClient = class {
|
|
|
110
138
|
}
|
|
111
139
|
} catch (error) {
|
|
112
140
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
113
|
-
if (error instanceof ResendApiError && error.statusCode >= 400 && error.statusCode < 500) throw error;
|
|
141
|
+
if (error instanceof ResendApiError && error.statusCode !== void 0 && error.statusCode >= 400 && error.statusCode < 500) throw error;
|
|
114
142
|
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
115
|
-
if (attempt === this.config.retries)
|
|
143
|
+
if (attempt === this.config.retries) {
|
|
144
|
+
if (lastError instanceof ResendApiError) throw lastError;
|
|
145
|
+
throw new ResendApiError(lastError.message, void 0, void 0, attempt + 1);
|
|
146
|
+
}
|
|
116
147
|
const backoffMs = Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
117
148
|
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
118
149
|
}
|
|
@@ -132,11 +163,19 @@ var ResendHttpClient = class {
|
|
|
132
163
|
const controller = new AbortController();
|
|
133
164
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
134
165
|
let signal;
|
|
166
|
+
let cleanup = () => {};
|
|
135
167
|
if (options.signal) {
|
|
136
168
|
const combinedController = new AbortController();
|
|
137
169
|
const onAbort = () => combinedController.abort();
|
|
138
|
-
options.signal.
|
|
139
|
-
|
|
170
|
+
if (options.signal.aborted || controller.signal.aborted) combinedController.abort();
|
|
171
|
+
else {
|
|
172
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
173
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
174
|
+
}
|
|
175
|
+
cleanup = () => {
|
|
176
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
177
|
+
controller.signal.removeEventListener("abort", onAbort);
|
|
178
|
+
};
|
|
140
179
|
signal = combinedController.signal;
|
|
141
180
|
} else signal = controller.signal;
|
|
142
181
|
try {
|
|
@@ -146,11 +185,21 @@ var ResendHttpClient = class {
|
|
|
146
185
|
signal
|
|
147
186
|
});
|
|
148
187
|
return response;
|
|
188
|
+
} catch (error) {
|
|
189
|
+
if (isAbortError$1(error) && controller.signal.aborted && !options.signal?.aborted) throw new Error(`Resend API request timed out after ${this.config.timeout} ms.`);
|
|
190
|
+
throw error;
|
|
149
191
|
} finally {
|
|
192
|
+
cleanup();
|
|
150
193
|
clearTimeout(timeoutId);
|
|
151
194
|
}
|
|
152
195
|
}
|
|
153
196
|
};
|
|
197
|
+
function isAbortError$1(error) {
|
|
198
|
+
return error instanceof Error && error.name === "AbortError";
|
|
199
|
+
}
|
|
200
|
+
function truncateErrorBody(text) {
|
|
201
|
+
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
202
|
+
}
|
|
154
203
|
|
|
155
204
|
//#endregion
|
|
156
205
|
//#region src/message-converter.ts
|
|
@@ -338,6 +387,7 @@ function generateIdempotencyKey() {
|
|
|
338
387
|
* ```
|
|
339
388
|
*/
|
|
340
389
|
var ResendTransport = class {
|
|
390
|
+
id = "resend";
|
|
341
391
|
/**
|
|
342
392
|
* The resolved Resend configuration used by this transport.
|
|
343
393
|
*/
|
|
@@ -395,14 +445,13 @@ var ResendTransport = class {
|
|
|
395
445
|
const response = await this.httpClient.sendMessage(emailData, options?.signal, idempotencyKey);
|
|
396
446
|
return {
|
|
397
447
|
successful: true,
|
|
398
|
-
messageId: response.id
|
|
448
|
+
messageId: response.id,
|
|
449
|
+
provider: "resend"
|
|
399
450
|
};
|
|
400
451
|
} catch (error) {
|
|
452
|
+
if (isAbortError(error) && options?.signal?.aborted) throw error;
|
|
401
453
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
402
|
-
return
|
|
403
|
-
successful: false,
|
|
404
|
-
errorMessages: [errorMessage]
|
|
405
|
-
};
|
|
454
|
+
return createResendFailure(errorMessage, error);
|
|
406
455
|
}
|
|
407
456
|
}
|
|
408
457
|
/**
|
|
@@ -511,14 +560,13 @@ var ResendTransport = class {
|
|
|
511
560
|
const response = await this.httpClient.sendBatch(batchData, options?.signal, idempotencyKey);
|
|
512
561
|
for (const result of response.data) yield {
|
|
513
562
|
successful: true,
|
|
514
|
-
messageId: result.id
|
|
563
|
+
messageId: result.id,
|
|
564
|
+
provider: "resend"
|
|
515
565
|
};
|
|
516
566
|
} catch (error) {
|
|
567
|
+
if (isAbortError(error) && options?.signal?.aborted) throw error;
|
|
517
568
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
518
|
-
for (let i = 0; i < messages.length; i++) yield
|
|
519
|
-
successful: false,
|
|
520
|
-
errorMessages: [errorMessage]
|
|
521
|
-
};
|
|
569
|
+
for (let i = 0; i < messages.length; i++) yield createResendFailure(errorMessage, error);
|
|
522
570
|
}
|
|
523
571
|
}
|
|
524
572
|
/**
|
|
@@ -548,6 +596,18 @@ var ResendTransport = class {
|
|
|
548
596
|
return chunks;
|
|
549
597
|
}
|
|
550
598
|
};
|
|
599
|
+
function createResendFailure(message, error) {
|
|
600
|
+
if (error instanceof ResendApiError) return createFailedReceipt(message, {
|
|
601
|
+
provider: "resend",
|
|
602
|
+
statusCode: error.statusCode,
|
|
603
|
+
retryAfterMilliseconds: error.retryAfterMilliseconds,
|
|
604
|
+
attempts: error.attempts
|
|
605
|
+
});
|
|
606
|
+
return createFailedReceipt(message, { provider: "resend" });
|
|
607
|
+
}
|
|
608
|
+
function isAbortError(error) {
|
|
609
|
+
return error instanceof Error && error.name === "AbortError";
|
|
610
|
+
}
|
|
551
611
|
|
|
552
612
|
//#endregion
|
|
553
613
|
export { ResendTransport };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upyo/resend",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.154",
|
|
4
4
|
"description": "Resend transport for Upyo email library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"email",
|
|
@@ -53,18 +53,13 @@
|
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@upyo/core": "0.5.0-dev.
|
|
56
|
+
"@upyo/core": "0.5.0-dev.154+2f72d353"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@dotenvx/dotenvx": "^1.47.3",
|
|
60
59
|
"tsdown": "^0.12.7",
|
|
61
60
|
"typescript": "5.8.3"
|
|
62
61
|
},
|
|
63
62
|
"scripts": {
|
|
64
|
-
"
|
|
65
|
-
"prepublish": "tsdown",
|
|
66
|
-
"test": "tsdown && dotenvx run --ignore=MISSING_ENV_FILE -- node --experimental-transform-types --test",
|
|
67
|
-
"test:bun": "tsdown && bun test --timeout=30000 --env-file=.env",
|
|
68
|
-
"test:deno": "deno test --allow-env --allow-net --env-file=.env"
|
|
63
|
+
"prepublish": "mise run --no-deps :build"
|
|
69
64
|
}
|
|
70
65
|
}
|