@upyo/plunk 0.5.0-dev.86 → 0.5.0
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 +111 -31
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +89 -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,
|
|
@@ -60,18 +118,18 @@ var PlunkHttpClient = class {
|
|
|
60
118
|
const response = await this.makeRequest(url, emailData, signal);
|
|
61
119
|
return await this.parseResponse(response);
|
|
62
120
|
} catch (error) {
|
|
121
|
+
if (isCallerAbort$1(error, signal)) throw error;
|
|
63
122
|
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
|
-
}
|
|
123
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
124
|
+
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
125
|
if (attempt === this.config.retries) break;
|
|
69
126
|
const delay = Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
70
127
|
await this.sleep(delay);
|
|
71
128
|
}
|
|
72
129
|
}
|
|
73
130
|
const errorMessage = lastError?.message ?? "Unknown error occurred";
|
|
74
|
-
throw this.
|
|
131
|
+
if (lastError instanceof PlunkApiError) throw new PlunkApiError(lastError.message, lastError.statusCode, lastError.retryAfterMilliseconds, this.config.retries + 1);
|
|
132
|
+
throw new PlunkApiError(errorMessage, void 0, void 0, this.config.retries + 1);
|
|
75
133
|
}
|
|
76
134
|
/**
|
|
77
135
|
* Makes an HTTP request to the Plunk API.
|
|
@@ -87,13 +145,24 @@ var PlunkHttpClient = class {
|
|
|
87
145
|
"Content-Type": "application/json",
|
|
88
146
|
...this.config.headers
|
|
89
147
|
};
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
148
|
+
const timeoutController = new AbortController();
|
|
149
|
+
const timeoutId = this.config.timeout > 0 ? setTimeout(() => timeoutController.abort(), this.config.timeout) : void 0;
|
|
150
|
+
const combinedSignal = (0, __upyo_core.combineSignals)(timeoutController.signal, signal);
|
|
151
|
+
let response;
|
|
152
|
+
try {
|
|
153
|
+
response = await fetch(url, {
|
|
154
|
+
method: "POST",
|
|
155
|
+
headers,
|
|
156
|
+
body: JSON.stringify(emailData),
|
|
157
|
+
signal: combinedSignal.signal
|
|
158
|
+
});
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (isAbortError$1(error) && timeoutController.signal.aborted && !signal?.aborted) throw new Error(`Plunk API request timed out after ${this.config.timeout} ms.`);
|
|
161
|
+
throw error;
|
|
162
|
+
} finally {
|
|
163
|
+
combinedSignal.cleanup();
|
|
164
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
165
|
+
}
|
|
97
166
|
if (!response.ok) {
|
|
98
167
|
let errorBody;
|
|
99
168
|
try {
|
|
@@ -101,7 +170,7 @@ var PlunkHttpClient = class {
|
|
|
101
170
|
} catch {
|
|
102
171
|
errorBody = "Failed to read error response";
|
|
103
172
|
}
|
|
104
|
-
throw new
|
|
173
|
+
throw new PlunkApiError(`HTTP ${response.status}: ${response.statusText}. ${truncateErrorBody(errorBody)}`, response.status, (0, __upyo_core.parseRetryAfter)(response.headers.get("Retry-After")));
|
|
105
174
|
}
|
|
106
175
|
return response;
|
|
107
176
|
}
|
|
@@ -124,19 +193,6 @@ var PlunkHttpClient = class {
|
|
|
124
193
|
}
|
|
125
194
|
}
|
|
126
195
|
/**
|
|
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
196
|
* Sleeps for the specified number of milliseconds.
|
|
141
197
|
*
|
|
142
198
|
* @param ms - Milliseconds to sleep
|
|
@@ -146,6 +202,15 @@ var PlunkHttpClient = class {
|
|
|
146
202
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
147
203
|
}
|
|
148
204
|
};
|
|
205
|
+
function isAbortError$1(error) {
|
|
206
|
+
return error instanceof Error && error.name === "AbortError";
|
|
207
|
+
}
|
|
208
|
+
function isCallerAbort$1(error, signal) {
|
|
209
|
+
return signal?.aborted === true && (isAbortError$1(error) || error === signal.reason);
|
|
210
|
+
}
|
|
211
|
+
function truncateErrorBody(text) {
|
|
212
|
+
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
213
|
+
}
|
|
149
214
|
|
|
150
215
|
//#endregion
|
|
151
216
|
//#region src/message-converter.ts
|
|
@@ -277,6 +342,7 @@ function arrayBufferToBase64(buffer) {
|
|
|
277
342
|
* ```
|
|
278
343
|
*/
|
|
279
344
|
var PlunkTransport = class {
|
|
345
|
+
id = "plunk";
|
|
280
346
|
/**
|
|
281
347
|
* The resolved Plunk configuration used by this transport.
|
|
282
348
|
*/
|
|
@@ -333,14 +399,13 @@ var PlunkTransport = class {
|
|
|
333
399
|
const messageId = this.extractMessageId(response, message);
|
|
334
400
|
return {
|
|
335
401
|
successful: true,
|
|
336
|
-
messageId
|
|
402
|
+
messageId,
|
|
403
|
+
provider: "plunk"
|
|
337
404
|
};
|
|
338
405
|
} catch (error) {
|
|
406
|
+
if (isCallerAbort(error, options?.signal)) throw error;
|
|
339
407
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
340
|
-
return
|
|
341
|
-
successful: false,
|
|
342
|
-
errorMessages: [errorMessage]
|
|
343
|
-
};
|
|
408
|
+
return createPlunkFailure(errorMessage, error);
|
|
344
409
|
}
|
|
345
410
|
}
|
|
346
411
|
/**
|
|
@@ -429,6 +494,21 @@ var PlunkTransport = class {
|
|
|
429
494
|
return `plunk-${timestamp}-${recipientHash}-${random}`;
|
|
430
495
|
}
|
|
431
496
|
};
|
|
497
|
+
function createPlunkFailure(message, error) {
|
|
498
|
+
if (error instanceof PlunkApiError) return (0, __upyo_core.createFailedReceipt)(message, {
|
|
499
|
+
provider: "plunk",
|
|
500
|
+
statusCode: error.statusCode,
|
|
501
|
+
retryAfterMilliseconds: error.retryAfterMilliseconds,
|
|
502
|
+
attempts: error.attempts
|
|
503
|
+
});
|
|
504
|
+
return (0, __upyo_core.createFailedReceipt)(message, { provider: "plunk" });
|
|
505
|
+
}
|
|
506
|
+
function isAbortError(error) {
|
|
507
|
+
return error instanceof Error && error.name === "AbortError";
|
|
508
|
+
}
|
|
509
|
+
function isCallerAbort(error, signal) {
|
|
510
|
+
return signal?.aborted === true && (isAbortError(error) || error === signal.reason);
|
|
511
|
+
}
|
|
432
512
|
|
|
433
513
|
//#endregion
|
|
434
514
|
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 { combineSignals, 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,
|
|
@@ -59,18 +95,18 @@ var PlunkHttpClient = class {
|
|
|
59
95
|
const response = await this.makeRequest(url, emailData, signal);
|
|
60
96
|
return await this.parseResponse(response);
|
|
61
97
|
} catch (error) {
|
|
98
|
+
if (isCallerAbort$1(error, signal)) throw error;
|
|
62
99
|
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
|
-
}
|
|
100
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
101
|
+
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
102
|
if (attempt === this.config.retries) break;
|
|
68
103
|
const delay = Math.min(1e3 * Math.pow(2, attempt), 1e4);
|
|
69
104
|
await this.sleep(delay);
|
|
70
105
|
}
|
|
71
106
|
}
|
|
72
107
|
const errorMessage = lastError?.message ?? "Unknown error occurred";
|
|
73
|
-
throw this.
|
|
108
|
+
if (lastError instanceof PlunkApiError) throw new PlunkApiError(lastError.message, lastError.statusCode, lastError.retryAfterMilliseconds, this.config.retries + 1);
|
|
109
|
+
throw new PlunkApiError(errorMessage, void 0, void 0, this.config.retries + 1);
|
|
74
110
|
}
|
|
75
111
|
/**
|
|
76
112
|
* Makes an HTTP request to the Plunk API.
|
|
@@ -86,13 +122,24 @@ var PlunkHttpClient = class {
|
|
|
86
122
|
"Content-Type": "application/json",
|
|
87
123
|
...this.config.headers
|
|
88
124
|
};
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
125
|
+
const timeoutController = new AbortController();
|
|
126
|
+
const timeoutId = this.config.timeout > 0 ? setTimeout(() => timeoutController.abort(), this.config.timeout) : void 0;
|
|
127
|
+
const combinedSignal = combineSignals(timeoutController.signal, signal);
|
|
128
|
+
let response;
|
|
129
|
+
try {
|
|
130
|
+
response = await fetch(url, {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers,
|
|
133
|
+
body: JSON.stringify(emailData),
|
|
134
|
+
signal: combinedSignal.signal
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (isAbortError$1(error) && timeoutController.signal.aborted && !signal?.aborted) throw new Error(`Plunk API request timed out after ${this.config.timeout} ms.`);
|
|
138
|
+
throw error;
|
|
139
|
+
} finally {
|
|
140
|
+
combinedSignal.cleanup();
|
|
141
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
142
|
+
}
|
|
96
143
|
if (!response.ok) {
|
|
97
144
|
let errorBody;
|
|
98
145
|
try {
|
|
@@ -100,7 +147,7 @@ var PlunkHttpClient = class {
|
|
|
100
147
|
} catch {
|
|
101
148
|
errorBody = "Failed to read error response";
|
|
102
149
|
}
|
|
103
|
-
throw new
|
|
150
|
+
throw new PlunkApiError(`HTTP ${response.status}: ${response.statusText}. ${truncateErrorBody(errorBody)}`, response.status, parseRetryAfter(response.headers.get("Retry-After")));
|
|
104
151
|
}
|
|
105
152
|
return response;
|
|
106
153
|
}
|
|
@@ -123,19 +170,6 @@ var PlunkHttpClient = class {
|
|
|
123
170
|
}
|
|
124
171
|
}
|
|
125
172
|
/**
|
|
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
173
|
* Sleeps for the specified number of milliseconds.
|
|
140
174
|
*
|
|
141
175
|
* @param ms - Milliseconds to sleep
|
|
@@ -145,6 +179,15 @@ var PlunkHttpClient = class {
|
|
|
145
179
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
146
180
|
}
|
|
147
181
|
};
|
|
182
|
+
function isAbortError$1(error) {
|
|
183
|
+
return error instanceof Error && error.name === "AbortError";
|
|
184
|
+
}
|
|
185
|
+
function isCallerAbort$1(error, signal) {
|
|
186
|
+
return signal?.aborted === true && (isAbortError$1(error) || error === signal.reason);
|
|
187
|
+
}
|
|
188
|
+
function truncateErrorBody(text) {
|
|
189
|
+
return text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
190
|
+
}
|
|
148
191
|
|
|
149
192
|
//#endregion
|
|
150
193
|
//#region src/message-converter.ts
|
|
@@ -276,6 +319,7 @@ function arrayBufferToBase64(buffer) {
|
|
|
276
319
|
* ```
|
|
277
320
|
*/
|
|
278
321
|
var PlunkTransport = class {
|
|
322
|
+
id = "plunk";
|
|
279
323
|
/**
|
|
280
324
|
* The resolved Plunk configuration used by this transport.
|
|
281
325
|
*/
|
|
@@ -332,14 +376,13 @@ var PlunkTransport = class {
|
|
|
332
376
|
const messageId = this.extractMessageId(response, message);
|
|
333
377
|
return {
|
|
334
378
|
successful: true,
|
|
335
|
-
messageId
|
|
379
|
+
messageId,
|
|
380
|
+
provider: "plunk"
|
|
336
381
|
};
|
|
337
382
|
} catch (error) {
|
|
383
|
+
if (isCallerAbort(error, options?.signal)) throw error;
|
|
338
384
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
339
|
-
return
|
|
340
|
-
successful: false,
|
|
341
|
-
errorMessages: [errorMessage]
|
|
342
|
-
};
|
|
385
|
+
return createPlunkFailure(errorMessage, error);
|
|
343
386
|
}
|
|
344
387
|
}
|
|
345
388
|
/**
|
|
@@ -428,6 +471,21 @@ var PlunkTransport = class {
|
|
|
428
471
|
return `plunk-${timestamp}-${recipientHash}-${random}`;
|
|
429
472
|
}
|
|
430
473
|
};
|
|
474
|
+
function createPlunkFailure(message, error) {
|
|
475
|
+
if (error instanceof PlunkApiError) return createFailedReceipt(message, {
|
|
476
|
+
provider: "plunk",
|
|
477
|
+
statusCode: error.statusCode,
|
|
478
|
+
retryAfterMilliseconds: error.retryAfterMilliseconds,
|
|
479
|
+
attempts: error.attempts
|
|
480
|
+
});
|
|
481
|
+
return createFailedReceipt(message, { provider: "plunk" });
|
|
482
|
+
}
|
|
483
|
+
function isAbortError(error) {
|
|
484
|
+
return error instanceof Error && error.name === "AbortError";
|
|
485
|
+
}
|
|
486
|
+
function isCallerAbort(error, signal) {
|
|
487
|
+
return signal?.aborted === true && (isAbortError(error) || error === signal.reason);
|
|
488
|
+
}
|
|
431
489
|
|
|
432
490
|
//#endregion
|
|
433
491
|
export { PlunkTransport };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upyo/plunk",
|
|
3
|
-
"version": "0.5.0
|
|
3
|
+
"version": "0.5.0",
|
|
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
|
|
56
|
+
"@upyo/core": "0.5.0"
|
|
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
|
}
|