@upyo/plunk 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 +103 -31
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +81 -31
- 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,6 +49,40 @@ function createPlunkConfig(config) {
|
|
|
25
49
|
//#endregion
|
|
26
50
|
//#region src/http-client.ts
|
|
27
51
|
/**
|
|
52
|
+
* Error thrown when a Plunk API request fails.
|
|
53
|
+
*
|
|
54
|
+
* @since 0.5.0
|
|
55
|
+
*/
|
|
56
|
+
var PlunkApiError = class extends Error {
|
|
57
|
+
/**
|
|
58
|
+
* HTTP status code returned by Plunk, if the request reached the API.
|
|
59
|
+
*/
|
|
60
|
+
statusCode;
|
|
61
|
+
/**
|
|
62
|
+
* Retry delay from Plunk'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 Plunk API error.
|
|
71
|
+
*
|
|
72
|
+
* @param message Error message.
|
|
73
|
+
* @param statusCode HTTP status code returned by Plunk.
|
|
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) {
|
|
78
|
+
super(message);
|
|
79
|
+
this.name = "PlunkApiError";
|
|
80
|
+
this.statusCode = statusCode;
|
|
81
|
+
this.retryAfterMilliseconds = retryAfterMilliseconds;
|
|
82
|
+
this.attempts = attempts;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
28
86
|
* HTTP client wrapper for Plunk API requests.
|
|
29
87
|
*
|
|
30
88
|
* This class handles authentication, request formatting, error handling,
|
|
@@ -61,17 +119,16 @@ var PlunkHttpClient = class {
|
|
|
61
119
|
return await this.parseResponse(response);
|
|
62
120
|
} catch (error) {
|
|
63
121
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
64
|
-
if (error instanceof Error)
|
|
65
|
-
|
|
66
|
-
if (error.message.includes("status: 4")) throw this.createPlunkError(error.message, 400);
|
|
67
|
-
}
|
|
122
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
123
|
+
if (error instanceof PlunkApiError && error.statusCode !== void 0 && error.statusCode >= 400 && error.statusCode < 500) throw new PlunkApiError(error.message, error.statusCode, error.retryAfterMilliseconds, attempt + 1);
|
|
68
124
|
if (attempt === this.config.retries) break;
|
|
69
125
|
const delay = Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
70
126
|
await this.sleep(delay);
|
|
71
127
|
}
|
|
72
128
|
}
|
|
73
129
|
const errorMessage = lastError?.message ?? "Unknown error occurred";
|
|
74
|
-
throw this.
|
|
130
|
+
if (lastError instanceof PlunkApiError) throw new PlunkApiError(lastError.message, lastError.statusCode, lastError.retryAfterMilliseconds, this.config.retries + 1);
|
|
131
|
+
throw new PlunkApiError(errorMessage, void 0, void 0, this.config.retries + 1);
|
|
75
132
|
}
|
|
76
133
|
/**
|
|
77
134
|
* Makes an HTTP request to the Plunk API.
|
|
@@ -87,13 +144,23 @@ var PlunkHttpClient = class {
|
|
|
87
144
|
"Content-Type": "application/json",
|
|
88
145
|
...this.config.headers
|
|
89
146
|
};
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
147
|
+
const timeoutController = new AbortController();
|
|
148
|
+
const timeoutId = this.config.timeout > 0 ? setTimeout(() => timeoutController.abort(), this.config.timeout) : void 0;
|
|
149
|
+
const requestSignal = signal == null ? timeoutController.signal : AbortSignal.any([timeoutController.signal, signal]);
|
|
150
|
+
let response;
|
|
151
|
+
try {
|
|
152
|
+
response = await fetch(url, {
|
|
153
|
+
method: "POST",
|
|
154
|
+
headers,
|
|
155
|
+
body: JSON.stringify(emailData),
|
|
156
|
+
signal: requestSignal
|
|
157
|
+
});
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (isAbortError$1(error) && timeoutController.signal.aborted && !signal?.aborted) throw new Error(`Plunk API request timed out after ${this.config.timeout} ms.`);
|
|
160
|
+
throw error;
|
|
161
|
+
} finally {
|
|
162
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
163
|
+
}
|
|
97
164
|
if (!response.ok) {
|
|
98
165
|
let errorBody;
|
|
99
166
|
try {
|
|
@@ -101,7 +168,7 @@ var PlunkHttpClient = class {
|
|
|
101
168
|
} catch {
|
|
102
169
|
errorBody = "Failed to read error response";
|
|
103
170
|
}
|
|
104
|
-
throw new
|
|
171
|
+
throw new PlunkApiError(`HTTP ${response.status}: ${response.statusText}. ${truncateErrorBody(errorBody)}`, response.status, (0, __upyo_core.parseRetryAfter)(response.headers.get("Retry-After")));
|
|
105
172
|
}
|
|
106
173
|
return response;
|
|
107
174
|
}
|
|
@@ -124,19 +191,6 @@ var PlunkHttpClient = class {
|
|
|
124
191
|
}
|
|
125
192
|
}
|
|
126
193
|
/**
|
|
127
|
-
* Creates a PlunkError from an error message and optional status code.
|
|
128
|
-
*
|
|
129
|
-
* @param message - The error message
|
|
130
|
-
* @param statusCode - Optional HTTP status code
|
|
131
|
-
* @returns PlunkError instance
|
|
132
|
-
*/
|
|
133
|
-
createPlunkError(message, statusCode) {
|
|
134
|
-
return {
|
|
135
|
-
message,
|
|
136
|
-
statusCode
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
194
|
* Sleeps for the specified number of milliseconds.
|
|
141
195
|
*
|
|
142
196
|
* @param ms - Milliseconds to sleep
|
|
@@ -146,6 +200,12 @@ var PlunkHttpClient = class {
|
|
|
146
200
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
147
201
|
}
|
|
148
202
|
};
|
|
203
|
+
function isAbortError$1(error) {
|
|
204
|
+
return error instanceof Error && error.name === "AbortError";
|
|
205
|
+
}
|
|
206
|
+
function truncateErrorBody(text) {
|
|
207
|
+
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
208
|
+
}
|
|
149
209
|
|
|
150
210
|
//#endregion
|
|
151
211
|
//#region src/message-converter.ts
|
|
@@ -277,6 +337,7 @@ function arrayBufferToBase64(buffer) {
|
|
|
277
337
|
* ```
|
|
278
338
|
*/
|
|
279
339
|
var PlunkTransport = class {
|
|
340
|
+
id = "plunk";
|
|
280
341
|
/**
|
|
281
342
|
* The resolved Plunk configuration used by this transport.
|
|
282
343
|
*/
|
|
@@ -333,14 +394,13 @@ var PlunkTransport = class {
|
|
|
333
394
|
const messageId = this.extractMessageId(response, message);
|
|
334
395
|
return {
|
|
335
396
|
successful: true,
|
|
336
|
-
messageId
|
|
397
|
+
messageId,
|
|
398
|
+
provider: "plunk"
|
|
337
399
|
};
|
|
338
400
|
} catch (error) {
|
|
401
|
+
if (isAbortError(error) && options?.signal?.aborted) throw error;
|
|
339
402
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
340
|
-
return
|
|
341
|
-
successful: false,
|
|
342
|
-
errorMessages: [errorMessage]
|
|
343
|
-
};
|
|
403
|
+
return createPlunkFailure(errorMessage, error);
|
|
344
404
|
}
|
|
345
405
|
}
|
|
346
406
|
/**
|
|
@@ -429,6 +489,18 @@ var PlunkTransport = class {
|
|
|
429
489
|
return `plunk-${timestamp}-${recipientHash}-${random}`;
|
|
430
490
|
}
|
|
431
491
|
};
|
|
492
|
+
function createPlunkFailure(message, error) {
|
|
493
|
+
if (error instanceof PlunkApiError) return (0, __upyo_core.createFailedReceipt)(message, {
|
|
494
|
+
provider: "plunk",
|
|
495
|
+
statusCode: error.statusCode,
|
|
496
|
+
retryAfterMilliseconds: error.retryAfterMilliseconds,
|
|
497
|
+
attempts: error.attempts
|
|
498
|
+
});
|
|
499
|
+
return (0, __upyo_core.createFailedReceipt)(message, { provider: "plunk" });
|
|
500
|
+
}
|
|
501
|
+
function isAbortError(error) {
|
|
502
|
+
return error instanceof Error && error.name === "AbortError";
|
|
503
|
+
}
|
|
432
504
|
|
|
433
505
|
//#endregion
|
|
434
506
|
exports.PlunkTransport = PlunkTransport;
|
package/dist/index.d.cts
CHANGED
|
@@ -106,7 +106,8 @@ type ResolvedPlunkConfig = Required<PlunkConfig>;
|
|
|
106
106
|
* }
|
|
107
107
|
* ```
|
|
108
108
|
*/
|
|
109
|
-
declare class PlunkTransport implements Transport {
|
|
109
|
+
declare class PlunkTransport implements Transport<"plunk"> {
|
|
110
|
+
readonly id = "plunk";
|
|
110
111
|
/**
|
|
111
112
|
* The resolved Plunk configuration used by this transport.
|
|
112
113
|
*/
|
|
@@ -151,7 +152,7 @@ declare class PlunkTransport implements Transport {
|
|
|
151
152
|
* @returns A promise that resolves to a receipt indicating success or
|
|
152
153
|
* failure.
|
|
153
154
|
*/
|
|
154
|
-
send(message: Message, options?: TransportOptions): Promise<Receipt
|
|
155
|
+
send(message: Message, options?: TransportOptions): Promise<Receipt<"plunk">>;
|
|
155
156
|
/**
|
|
156
157
|
* Sends multiple email messages efficiently via Plunk API.
|
|
157
158
|
*
|
|
@@ -204,7 +205,7 @@ declare class PlunkTransport implements Transport {
|
|
|
204
205
|
* cancellation.
|
|
205
206
|
* @returns An async iterable of receipts, one for each message.
|
|
206
207
|
*/
|
|
207
|
-
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt
|
|
208
|
+
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt<"plunk">>;
|
|
208
209
|
/**
|
|
209
210
|
* Extracts or generates a message ID from the Plunk response.
|
|
210
211
|
*
|
|
@@ -260,10 +261,9 @@ interface PlunkError {
|
|
|
260
261
|
readonly details?: unknown;
|
|
261
262
|
}
|
|
262
263
|
/**
|
|
263
|
-
*
|
|
264
|
+
* Error thrown when a Plunk API request fails.
|
|
264
265
|
*
|
|
265
|
-
*
|
|
266
|
-
* and retry logic for the Plunk HTTP API.
|
|
266
|
+
* @since 0.5.0
|
|
267
267
|
*/
|
|
268
268
|
//#endregion
|
|
269
269
|
export { PlunkConfig, PlunkError, PlunkResponse, PlunkTransport, ResolvedPlunkConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -106,7 +106,8 @@ type ResolvedPlunkConfig = Required<PlunkConfig>;
|
|
|
106
106
|
* }
|
|
107
107
|
* ```
|
|
108
108
|
*/
|
|
109
|
-
declare class PlunkTransport implements Transport {
|
|
109
|
+
declare class PlunkTransport implements Transport<"plunk"> {
|
|
110
|
+
readonly id = "plunk";
|
|
110
111
|
/**
|
|
111
112
|
* The resolved Plunk configuration used by this transport.
|
|
112
113
|
*/
|
|
@@ -151,7 +152,7 @@ declare class PlunkTransport implements Transport {
|
|
|
151
152
|
* @returns A promise that resolves to a receipt indicating success or
|
|
152
153
|
* failure.
|
|
153
154
|
*/
|
|
154
|
-
send(message: Message, options?: TransportOptions): Promise<Receipt
|
|
155
|
+
send(message: Message, options?: TransportOptions): Promise<Receipt<"plunk">>;
|
|
155
156
|
/**
|
|
156
157
|
* Sends multiple email messages efficiently via Plunk API.
|
|
157
158
|
*
|
|
@@ -204,7 +205,7 @@ declare class PlunkTransport implements Transport {
|
|
|
204
205
|
* cancellation.
|
|
205
206
|
* @returns An async iterable of receipts, one for each message.
|
|
206
207
|
*/
|
|
207
|
-
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt
|
|
208
|
+
sendMany(messages: Iterable<Message> | AsyncIterable<Message>, options?: TransportOptions): AsyncIterable<Receipt<"plunk">>;
|
|
208
209
|
/**
|
|
209
210
|
* Extracts or generates a message ID from the Plunk response.
|
|
210
211
|
*
|
|
@@ -260,10 +261,9 @@ interface PlunkError {
|
|
|
260
261
|
readonly details?: unknown;
|
|
261
262
|
}
|
|
262
263
|
/**
|
|
263
|
-
*
|
|
264
|
+
* Error thrown when a Plunk API request fails.
|
|
264
265
|
*
|
|
265
|
-
*
|
|
266
|
-
* and retry logic for the Plunk HTTP API.
|
|
266
|
+
* @since 0.5.0
|
|
267
267
|
*/
|
|
268
268
|
//#endregion
|
|
269
269
|
export { PlunkConfig, PlunkError, PlunkResponse, PlunkTransport, ResolvedPlunkConfig };
|
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 Plunk configuration by applying default values to optional fields.
|
|
@@ -24,6 +26,40 @@ function createPlunkConfig(config) {
|
|
|
24
26
|
//#endregion
|
|
25
27
|
//#region src/http-client.ts
|
|
26
28
|
/**
|
|
29
|
+
* Error thrown when a Plunk API request fails.
|
|
30
|
+
*
|
|
31
|
+
* @since 0.5.0
|
|
32
|
+
*/
|
|
33
|
+
var PlunkApiError = class extends Error {
|
|
34
|
+
/**
|
|
35
|
+
* HTTP status code returned by Plunk, if the request reached the API.
|
|
36
|
+
*/
|
|
37
|
+
statusCode;
|
|
38
|
+
/**
|
|
39
|
+
* Retry delay from Plunk'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 Plunk API error.
|
|
48
|
+
*
|
|
49
|
+
* @param message Error message.
|
|
50
|
+
* @param statusCode HTTP status code returned by Plunk.
|
|
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) {
|
|
55
|
+
super(message);
|
|
56
|
+
this.name = "PlunkApiError";
|
|
57
|
+
this.statusCode = statusCode;
|
|
58
|
+
this.retryAfterMilliseconds = retryAfterMilliseconds;
|
|
59
|
+
this.attempts = attempts;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
27
63
|
* HTTP client wrapper for Plunk API requests.
|
|
28
64
|
*
|
|
29
65
|
* This class handles authentication, request formatting, error handling,
|
|
@@ -60,17 +96,16 @@ var PlunkHttpClient = class {
|
|
|
60
96
|
return await this.parseResponse(response);
|
|
61
97
|
} catch (error) {
|
|
62
98
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
63
|
-
if (error instanceof Error)
|
|
64
|
-
|
|
65
|
-
if (error.message.includes("status: 4")) throw this.createPlunkError(error.message, 400);
|
|
66
|
-
}
|
|
99
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
100
|
+
if (error instanceof PlunkApiError && error.statusCode !== void 0 && error.statusCode >= 400 && error.statusCode < 500) throw new PlunkApiError(error.message, error.statusCode, error.retryAfterMilliseconds, attempt + 1);
|
|
67
101
|
if (attempt === this.config.retries) break;
|
|
68
102
|
const delay = Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
69
103
|
await this.sleep(delay);
|
|
70
104
|
}
|
|
71
105
|
}
|
|
72
106
|
const errorMessage = lastError?.message ?? "Unknown error occurred";
|
|
73
|
-
throw this.
|
|
107
|
+
if (lastError instanceof PlunkApiError) throw new PlunkApiError(lastError.message, lastError.statusCode, lastError.retryAfterMilliseconds, this.config.retries + 1);
|
|
108
|
+
throw new PlunkApiError(errorMessage, void 0, void 0, this.config.retries + 1);
|
|
74
109
|
}
|
|
75
110
|
/**
|
|
76
111
|
* Makes an HTTP request to the Plunk API.
|
|
@@ -86,13 +121,23 @@ var PlunkHttpClient = class {
|
|
|
86
121
|
"Content-Type": "application/json",
|
|
87
122
|
...this.config.headers
|
|
88
123
|
};
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
124
|
+
const timeoutController = new AbortController();
|
|
125
|
+
const timeoutId = this.config.timeout > 0 ? setTimeout(() => timeoutController.abort(), this.config.timeout) : void 0;
|
|
126
|
+
const requestSignal = signal == null ? timeoutController.signal : AbortSignal.any([timeoutController.signal, signal]);
|
|
127
|
+
let response;
|
|
128
|
+
try {
|
|
129
|
+
response = await fetch(url, {
|
|
130
|
+
method: "POST",
|
|
131
|
+
headers,
|
|
132
|
+
body: JSON.stringify(emailData),
|
|
133
|
+
signal: requestSignal
|
|
134
|
+
});
|
|
135
|
+
} catch (error) {
|
|
136
|
+
if (isAbortError$1(error) && timeoutController.signal.aborted && !signal?.aborted) throw new Error(`Plunk API request timed out after ${this.config.timeout} ms.`);
|
|
137
|
+
throw error;
|
|
138
|
+
} finally {
|
|
139
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
140
|
+
}
|
|
96
141
|
if (!response.ok) {
|
|
97
142
|
let errorBody;
|
|
98
143
|
try {
|
|
@@ -100,7 +145,7 @@ var PlunkHttpClient = class {
|
|
|
100
145
|
} catch {
|
|
101
146
|
errorBody = "Failed to read error response";
|
|
102
147
|
}
|
|
103
|
-
throw new
|
|
148
|
+
throw new PlunkApiError(`HTTP ${response.status}: ${response.statusText}. ${truncateErrorBody(errorBody)}`, response.status, parseRetryAfter(response.headers.get("Retry-After")));
|
|
104
149
|
}
|
|
105
150
|
return response;
|
|
106
151
|
}
|
|
@@ -123,19 +168,6 @@ var PlunkHttpClient = class {
|
|
|
123
168
|
}
|
|
124
169
|
}
|
|
125
170
|
/**
|
|
126
|
-
* Creates a PlunkError from an error message and optional status code.
|
|
127
|
-
*
|
|
128
|
-
* @param message - The error message
|
|
129
|
-
* @param statusCode - Optional HTTP status code
|
|
130
|
-
* @returns PlunkError instance
|
|
131
|
-
*/
|
|
132
|
-
createPlunkError(message, statusCode) {
|
|
133
|
-
return {
|
|
134
|
-
message,
|
|
135
|
-
statusCode
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
171
|
* Sleeps for the specified number of milliseconds.
|
|
140
172
|
*
|
|
141
173
|
* @param ms - Milliseconds to sleep
|
|
@@ -145,6 +177,12 @@ var PlunkHttpClient = class {
|
|
|
145
177
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
146
178
|
}
|
|
147
179
|
};
|
|
180
|
+
function isAbortError$1(error) {
|
|
181
|
+
return error instanceof Error && error.name === "AbortError";
|
|
182
|
+
}
|
|
183
|
+
function truncateErrorBody(text) {
|
|
184
|
+
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
185
|
+
}
|
|
148
186
|
|
|
149
187
|
//#endregion
|
|
150
188
|
//#region src/message-converter.ts
|
|
@@ -276,6 +314,7 @@ function arrayBufferToBase64(buffer) {
|
|
|
276
314
|
* ```
|
|
277
315
|
*/
|
|
278
316
|
var PlunkTransport = class {
|
|
317
|
+
id = "plunk";
|
|
279
318
|
/**
|
|
280
319
|
* The resolved Plunk configuration used by this transport.
|
|
281
320
|
*/
|
|
@@ -332,14 +371,13 @@ var PlunkTransport = class {
|
|
|
332
371
|
const messageId = this.extractMessageId(response, message);
|
|
333
372
|
return {
|
|
334
373
|
successful: true,
|
|
335
|
-
messageId
|
|
374
|
+
messageId,
|
|
375
|
+
provider: "plunk"
|
|
336
376
|
};
|
|
337
377
|
} catch (error) {
|
|
378
|
+
if (isAbortError(error) && options?.signal?.aborted) throw error;
|
|
338
379
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
339
|
-
return
|
|
340
|
-
successful: false,
|
|
341
|
-
errorMessages: [errorMessage]
|
|
342
|
-
};
|
|
380
|
+
return createPlunkFailure(errorMessage, error);
|
|
343
381
|
}
|
|
344
382
|
}
|
|
345
383
|
/**
|
|
@@ -428,6 +466,18 @@ var PlunkTransport = class {
|
|
|
428
466
|
return `plunk-${timestamp}-${recipientHash}-${random}`;
|
|
429
467
|
}
|
|
430
468
|
};
|
|
469
|
+
function createPlunkFailure(message, error) {
|
|
470
|
+
if (error instanceof PlunkApiError) return createFailedReceipt(message, {
|
|
471
|
+
provider: "plunk",
|
|
472
|
+
statusCode: error.statusCode,
|
|
473
|
+
retryAfterMilliseconds: error.retryAfterMilliseconds,
|
|
474
|
+
attempts: error.attempts
|
|
475
|
+
});
|
|
476
|
+
return createFailedReceipt(message, { provider: "plunk" });
|
|
477
|
+
}
|
|
478
|
+
function isAbortError(error) {
|
|
479
|
+
return error instanceof Error && error.name === "AbortError";
|
|
480
|
+
}
|
|
431
481
|
|
|
432
482
|
//#endregion
|
|
433
483
|
export { PlunkTransport };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upyo/plunk",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.154",
|
|
4
4
|
"description": "Plunk 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
|
}
|