payload-plugin-newsletter 0.16.6 → 0.16.8
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/CHANGELOG.md +39 -0
- package/dist/collections.cjs +79 -19
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +79 -19
- package/dist/collections.js.map +1 -1
- package/dist/components.cjs +3 -0
- package/dist/components.cjs.map +1 -1
- package/dist/components.js +3 -0
- package/dist/components.js.map +1 -1
- package/dist/index.cjs +79 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +79 -19
- package/dist/index.js.map +1 -1
- package/dist/utils.cjs +3 -0
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +3 -0
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,42 @@
|
|
|
1
|
+
## [0.16.8] - 2025-01-29
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
- **Handle Empty Content When Creating Broadcasts** - Fixed error when creating broadcasts without content
|
|
5
|
+
- Added null/undefined check in convertToEmailSafeHtml function
|
|
6
|
+
- Skip provider sync when subject or content is missing on create
|
|
7
|
+
- Skip provider sync when content is empty after conversion
|
|
8
|
+
- Prevents "Cannot destructure property 'root' of 'editorState'" error
|
|
9
|
+
- Broadcasts can now be created empty and synced later when content is added
|
|
10
|
+
|
|
11
|
+
### Technical
|
|
12
|
+
- Updated convertToEmailSafeHtml to accept undefined/null editorState
|
|
13
|
+
- Added pre-sync validation in afterChange hook for create operations
|
|
14
|
+
- Empty broadcasts are saved in Payload but not synced to provider until content is added
|
|
15
|
+
|
|
16
|
+
## [0.16.7] - 2025-07-29
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- **Comprehensive Diagnostic Logging** - Added extensive logging to diagnose broadcast sync issues
|
|
20
|
+
- Logs the HTML content conversion process
|
|
21
|
+
- Shows exactly what data is being sent to the Broadcast API (with preview)
|
|
22
|
+
- Displays request URL, method, and body structure
|
|
23
|
+
- Shows API response status and headers
|
|
24
|
+
- Captures and logs all error types (Error objects, strings, JSON responses)
|
|
25
|
+
- Logs raw errors to identify unexpected error formats
|
|
26
|
+
|
|
27
|
+
### Improved
|
|
28
|
+
- **Better Error Visibility** - Enhanced error handling to capture more details
|
|
29
|
+
- Raw error logging to see the actual error structure
|
|
30
|
+
- Multiple error format handlers (Error, string, object, unknown)
|
|
31
|
+
- Response body parsing for API errors
|
|
32
|
+
- Document context logging when errors occur
|
|
33
|
+
- API request/response details in provider logs
|
|
34
|
+
|
|
35
|
+
### Technical
|
|
36
|
+
- Added pre-API call logging in afterChange hook
|
|
37
|
+
- Added comprehensive error logging in BroadcastApiProvider
|
|
38
|
+
- Logs help identify if issues are with content, API format, or authentication
|
|
39
|
+
|
|
1
40
|
## [0.16.6] - 2025-07-29
|
|
2
41
|
|
|
3
42
|
### Fixed
|
package/dist/collections.cjs
CHANGED
|
@@ -252,29 +252,46 @@ var init_broadcast2 = __esm({
|
|
|
252
252
|
async create(data) {
|
|
253
253
|
try {
|
|
254
254
|
this.validateRequiredFields(data, ["name", "subject", "content"]);
|
|
255
|
+
const requestBody = {
|
|
256
|
+
broadcast: {
|
|
257
|
+
name: data.name,
|
|
258
|
+
subject: data.subject,
|
|
259
|
+
preheader: data.preheader,
|
|
260
|
+
body: data.content,
|
|
261
|
+
html_body: true,
|
|
262
|
+
track_opens: data.trackOpens ?? true,
|
|
263
|
+
track_clicks: data.trackClicks ?? true,
|
|
264
|
+
reply_to: data.replyTo,
|
|
265
|
+
segment_ids: data.audienceIds
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
console.log("[BroadcastApiProvider] Creating broadcast:", {
|
|
269
|
+
url: `${this.apiUrl}/api/v1/broadcasts`,
|
|
270
|
+
method: "POST",
|
|
271
|
+
hasToken: !!this.token,
|
|
272
|
+
tokenLength: this.token?.length,
|
|
273
|
+
body: JSON.stringify(requestBody, null, 2)
|
|
274
|
+
});
|
|
255
275
|
const response = await fetch(`${this.apiUrl}/api/v1/broadcasts`, {
|
|
256
276
|
method: "POST",
|
|
257
277
|
headers: {
|
|
258
278
|
"Authorization": `Bearer ${this.token}`,
|
|
259
279
|
"Content-Type": "application/json"
|
|
260
280
|
},
|
|
261
|
-
body: JSON.stringify(
|
|
262
|
-
broadcast: {
|
|
263
|
-
name: data.name,
|
|
264
|
-
subject: data.subject,
|
|
265
|
-
preheader: data.preheader,
|
|
266
|
-
body: data.content,
|
|
267
|
-
html_body: true,
|
|
268
|
-
track_opens: data.trackOpens ?? true,
|
|
269
|
-
track_clicks: data.trackClicks ?? true,
|
|
270
|
-
reply_to: data.replyTo,
|
|
271
|
-
segment_ids: data.audienceIds
|
|
272
|
-
}
|
|
273
|
-
})
|
|
281
|
+
body: JSON.stringify(requestBody)
|
|
274
282
|
});
|
|
283
|
+
console.log("[BroadcastApiProvider] Response status:", response.status);
|
|
284
|
+
console.log("[BroadcastApiProvider] Response headers:", Object.fromEntries(response.headers.entries()));
|
|
275
285
|
if (!response.ok) {
|
|
276
|
-
const
|
|
277
|
-
|
|
286
|
+
const errorText = await response.text();
|
|
287
|
+
console.error("[BroadcastApiProvider] Error response body:", errorText);
|
|
288
|
+
let errorDetails;
|
|
289
|
+
try {
|
|
290
|
+
errorDetails = JSON.parse(errorText);
|
|
291
|
+
console.error("[BroadcastApiProvider] Parsed error:", errorDetails);
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
294
|
+
throw new Error(`Broadcast API error: ${response.status} - ${errorText}`);
|
|
278
295
|
}
|
|
279
296
|
const result = await response.json();
|
|
280
297
|
return this.get(result.id.toString());
|
|
@@ -943,6 +960,9 @@ var EMAIL_SAFE_CONFIG = {
|
|
|
943
960
|
FORBID_ATTR: ["class", "id", "onclick", "onload", "onerror"]
|
|
944
961
|
};
|
|
945
962
|
async function convertToEmailSafeHtml(editorState, options) {
|
|
963
|
+
if (!editorState) {
|
|
964
|
+
return "";
|
|
965
|
+
}
|
|
946
966
|
const rawHtml = await lexicalToEmailHtml(editorState, options?.mediaUrl);
|
|
947
967
|
const sanitizedHtml = import_isomorphic_dompurify.default.sanitize(rawHtml, EMAIL_SAFE_CONFIG);
|
|
948
968
|
if (options?.wrapInTemplate) {
|
|
@@ -1440,6 +1460,10 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1440
1460
|
async ({ doc, operation, req, previousDoc }) => {
|
|
1441
1461
|
if (!hasProviders) return doc;
|
|
1442
1462
|
if (operation === "create") {
|
|
1463
|
+
if (!doc.subject || !doc.contentSection?.content) {
|
|
1464
|
+
req.payload.logger.info("Skipping provider sync - broadcast has no subject or content yet");
|
|
1465
|
+
return doc;
|
|
1466
|
+
}
|
|
1443
1467
|
try {
|
|
1444
1468
|
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
1445
1469
|
if (!providerConfig || !providerConfig.token) {
|
|
@@ -1448,8 +1472,13 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1448
1472
|
}
|
|
1449
1473
|
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
1450
1474
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
1475
|
+
req.payload.logger.info("Converting content to HTML...");
|
|
1451
1476
|
const htmlContent = await convertToEmailSafeHtml(doc.contentSection?.content);
|
|
1452
|
-
|
|
1477
|
+
if (!htmlContent || htmlContent.trim() === "") {
|
|
1478
|
+
req.payload.logger.info("Skipping provider sync - content is empty after conversion");
|
|
1479
|
+
return doc;
|
|
1480
|
+
}
|
|
1481
|
+
const createData = {
|
|
1453
1482
|
name: doc.subject,
|
|
1454
1483
|
// Use subject as name since we removed the name field
|
|
1455
1484
|
subject: doc.subject,
|
|
@@ -1459,7 +1488,21 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1459
1488
|
trackClicks: doc.settings?.trackClicks,
|
|
1460
1489
|
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
1461
1490
|
audienceIds: doc.audienceIds?.map((a) => a.audienceId)
|
|
1491
|
+
};
|
|
1492
|
+
req.payload.logger.info("Creating broadcast with data:", {
|
|
1493
|
+
name: createData.name,
|
|
1494
|
+
subject: createData.subject,
|
|
1495
|
+
preheader: createData.preheader || "NONE",
|
|
1496
|
+
contentLength: htmlContent ? htmlContent.length : 0,
|
|
1497
|
+
contentPreview: htmlContent ? htmlContent.substring(0, 100) + "..." : "EMPTY",
|
|
1498
|
+
trackOpens: createData.trackOpens,
|
|
1499
|
+
trackClicks: createData.trackClicks,
|
|
1500
|
+
replyTo: createData.replyTo,
|
|
1501
|
+
audienceIds: createData.audienceIds || [],
|
|
1502
|
+
apiUrl: providerConfig.apiUrl,
|
|
1503
|
+
hasToken: !!providerConfig.token
|
|
1462
1504
|
});
|
|
1505
|
+
const providerBroadcast = await provider.create(createData);
|
|
1463
1506
|
await req.payload.update({
|
|
1464
1507
|
collection: "broadcasts",
|
|
1465
1508
|
id: doc.id,
|
|
@@ -1475,17 +1518,34 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1475
1518
|
providerData: providerBroadcast.providerData
|
|
1476
1519
|
};
|
|
1477
1520
|
} catch (error) {
|
|
1521
|
+
req.payload.logger.error("Raw error from broadcast provider:");
|
|
1522
|
+
req.payload.logger.error(error);
|
|
1478
1523
|
if (error instanceof Error) {
|
|
1479
|
-
req.payload.logger.error("
|
|
1524
|
+
req.payload.logger.error("Error is instance of Error:", {
|
|
1480
1525
|
message: error.message,
|
|
1481
1526
|
stack: error.stack,
|
|
1482
1527
|
name: error.name,
|
|
1483
1528
|
// If it's a BroadcastProviderError, it might have additional details
|
|
1484
|
-
...error.details
|
|
1529
|
+
...error.details,
|
|
1530
|
+
// Check if it's a fetch response error
|
|
1531
|
+
...error.response,
|
|
1532
|
+
...error.data,
|
|
1533
|
+
...error.status,
|
|
1534
|
+
...error.statusText
|
|
1485
1535
|
});
|
|
1536
|
+
} else if (typeof error === "string") {
|
|
1537
|
+
req.payload.logger.error("Error is a string:", error);
|
|
1538
|
+
} else if (error && typeof error === "object") {
|
|
1539
|
+
req.payload.logger.error("Error is an object:", JSON.stringify(error, null, 2));
|
|
1486
1540
|
} else {
|
|
1487
|
-
req.payload.logger.error("
|
|
1541
|
+
req.payload.logger.error("Unknown error type:", typeof error);
|
|
1488
1542
|
}
|
|
1543
|
+
req.payload.logger.error("Failed broadcast document:", {
|
|
1544
|
+
id: doc.id,
|
|
1545
|
+
subject: doc.subject,
|
|
1546
|
+
hasContent: !!doc.contentSection?.content,
|
|
1547
|
+
contentType: doc.contentSection?.content ? typeof doc.contentSection.content : "none"
|
|
1548
|
+
});
|
|
1489
1549
|
return doc;
|
|
1490
1550
|
}
|
|
1491
1551
|
}
|