payload-plugin-newsletter 0.16.3 → 0.16.6
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 +62 -0
- package/dist/collections.cjs +148 -115
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +148 -115
- package/dist/collections.js.map +1 -1
- package/dist/index.cjs +152 -119
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +152 -119
- package/dist/index.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/plugin-api-key-recommendations.md +117 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,65 @@
|
|
|
1
|
+
## [0.16.6] - 2025-07-29
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
- **Critical: Update Sync Now Works** - Fixed the afterChange hook that was blocking update operations
|
|
5
|
+
- Removed the `operation !== 'create'` check that prevented the afterChange hook from running on updates
|
|
6
|
+
- Moved update sync logic from beforeChange to afterChange for proper architectural pattern
|
|
7
|
+
- Updates are now synced AFTER they're saved to Payload, ensuring consistency
|
|
8
|
+
- Provider sync failures no longer block Payload updates
|
|
9
|
+
|
|
10
|
+
### Improved
|
|
11
|
+
- **Better Hook Architecture** - Sync operations now happen in the correct lifecycle stage
|
|
12
|
+
- beforeChange was architecturally wrong - if provider sync failed, data would be inconsistent
|
|
13
|
+
- afterChange ensures Payload data is saved first, then syncs to provider
|
|
14
|
+
- More resilient to network failures and API errors
|
|
15
|
+
|
|
16
|
+
### Technical
|
|
17
|
+
- Consolidated create and update logic in a single afterChange hook
|
|
18
|
+
- Added comprehensive content change detection before syncing
|
|
19
|
+
- Enhanced logging for update sync operations
|
|
20
|
+
- Removed redundant beforeChange hook logic
|
|
21
|
+
|
|
22
|
+
## [0.16.5] - 2025-07-29
|
|
23
|
+
|
|
24
|
+
### Breaking Changes
|
|
25
|
+
- **Field Renaming** - Renamed `status` field to `sendStatus` throughout the codebase
|
|
26
|
+
- This avoids confusion with Payload's built-in `_status` field (draft/published)
|
|
27
|
+
- Database field is now `sendStatus` for email send status (draft, scheduled, sending, sent, etc.)
|
|
28
|
+
- All references in providers, endpoints, and types have been updated
|
|
29
|
+
- If you have existing broadcast data with a `status` field, you'll need to migrate it to `sendStatus`
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- **Update Sync** - Fixed issue where broadcast updates made in Payload weren't syncing to the Broadcast provider
|
|
33
|
+
- The update hook now correctly checks `sendStatus` instead of the non-existent `status` field
|
|
34
|
+
- Provider can now properly determine if a broadcast is editable based on its send status
|
|
35
|
+
|
|
36
|
+
### Technical
|
|
37
|
+
- Updated `Broadcast` type interface to use `sendStatus` property
|
|
38
|
+
- Updated all provider implementations (Broadcast and Resend) to use `sendStatus`
|
|
39
|
+
- Updated send and schedule endpoints to set `sendStatus` field
|
|
40
|
+
- All TypeScript errors resolved
|
|
41
|
+
|
|
42
|
+
## [0.16.4] - 2025-07-27
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
- **Access Control for Broadcasts** - Added proper access control to the Broadcasts collection
|
|
46
|
+
- Public read access for all users
|
|
47
|
+
- Create, update, and delete operations require authenticated users
|
|
48
|
+
- Prevents unauthorized modifications to broadcast content
|
|
49
|
+
- Follows Payload's standard access control patterns
|
|
50
|
+
|
|
51
|
+
### Improved
|
|
52
|
+
- **Enhanced Update Sync Debugging** - Added detailed logging for broadcast update synchronization
|
|
53
|
+
- Logs when update hooks are triggered with operation details
|
|
54
|
+
- Shows what fields are being synced to the provider
|
|
55
|
+
- Helps diagnose why updates might not be syncing
|
|
56
|
+
- Added info logging for skipped updates due to status restrictions
|
|
57
|
+
- **Clearer Field Naming** - Renamed `status` field to `sendStatus` to avoid confusion with Payload's `_status`
|
|
58
|
+
- Database field is now `sendStatus` (draft, scheduled, sending, sent, etc.)
|
|
59
|
+
- Payload's versioning field remains `_status` (draft, published)
|
|
60
|
+
- Added virtual `status` field for API backward compatibility
|
|
61
|
+
- Makes it clear which status controls email sending vs content publishing
|
|
62
|
+
|
|
1
63
|
## [0.16.3] - 2025-07-27
|
|
2
64
|
|
|
3
65
|
### Improved
|
package/dist/collections.cjs
CHANGED
|
@@ -291,9 +291,9 @@ var init_broadcast2 = __esm({
|
|
|
291
291
|
async update(id, data) {
|
|
292
292
|
try {
|
|
293
293
|
const existing = await this.get(id);
|
|
294
|
-
if (!this.canEditInStatus(existing.
|
|
294
|
+
if (!this.canEditInStatus(existing.sendStatus)) {
|
|
295
295
|
throw new BroadcastProviderError(
|
|
296
|
-
`Cannot update broadcast in status: ${existing.
|
|
296
|
+
`Cannot update broadcast in status: ${existing.sendStatus}`,
|
|
297
297
|
"INVALID_STATUS" /* INVALID_STATUS */,
|
|
298
298
|
this.name
|
|
299
299
|
);
|
|
@@ -336,9 +336,9 @@ var init_broadcast2 = __esm({
|
|
|
336
336
|
async delete(id) {
|
|
337
337
|
try {
|
|
338
338
|
const existing = await this.get(id);
|
|
339
|
-
if (!this.canEditInStatus(existing.
|
|
339
|
+
if (!this.canEditInStatus(existing.sendStatus)) {
|
|
340
340
|
throw new BroadcastProviderError(
|
|
341
|
-
`Cannot delete broadcast in status: ${existing.
|
|
341
|
+
`Cannot delete broadcast in status: ${existing.sendStatus}`,
|
|
342
342
|
"INVALID_STATUS" /* INVALID_STATUS */,
|
|
343
343
|
this.name
|
|
344
344
|
);
|
|
@@ -497,7 +497,7 @@ var init_broadcast2 = __esm({
|
|
|
497
497
|
subject: broadcast.subject,
|
|
498
498
|
preheader: broadcast.preheader,
|
|
499
499
|
content: broadcast.body,
|
|
500
|
-
|
|
500
|
+
sendStatus: this.mapBroadcastStatus(broadcast.status),
|
|
501
501
|
trackOpens: broadcast.track_opens,
|
|
502
502
|
trackClicks: broadcast.track_clicks,
|
|
503
503
|
replyTo: broadcast.reply_to,
|
|
@@ -1191,6 +1191,19 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1191
1191
|
const customizations = pluginConfig.customizations?.broadcasts;
|
|
1192
1192
|
return {
|
|
1193
1193
|
slug: "broadcasts",
|
|
1194
|
+
access: {
|
|
1195
|
+
read: () => true,
|
|
1196
|
+
// Public read access
|
|
1197
|
+
create: ({ req: { user } }) => {
|
|
1198
|
+
return Boolean(user);
|
|
1199
|
+
},
|
|
1200
|
+
update: ({ req: { user } }) => {
|
|
1201
|
+
return Boolean(user);
|
|
1202
|
+
},
|
|
1203
|
+
delete: ({ req: { user } }) => {
|
|
1204
|
+
return Boolean(user);
|
|
1205
|
+
}
|
|
1206
|
+
},
|
|
1194
1207
|
versions: {
|
|
1195
1208
|
drafts: {
|
|
1196
1209
|
autosave: true,
|
|
@@ -1204,7 +1217,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1204
1217
|
admin: {
|
|
1205
1218
|
useAsTitle: "subject",
|
|
1206
1219
|
description: "Individual email campaigns sent to subscribers",
|
|
1207
|
-
defaultColumns: ["subject", "_status", "
|
|
1220
|
+
defaultColumns: ["subject", "_status", "sendStatus", "sentAt", "recipientCount"]
|
|
1208
1221
|
},
|
|
1209
1222
|
fields: [
|
|
1210
1223
|
{
|
|
@@ -1264,8 +1277,9 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1264
1277
|
]
|
|
1265
1278
|
},
|
|
1266
1279
|
{
|
|
1267
|
-
name: "
|
|
1280
|
+
name: "sendStatus",
|
|
1268
1281
|
type: "select",
|
|
1282
|
+
label: "Send Status",
|
|
1269
1283
|
required: true,
|
|
1270
1284
|
defaultValue: "draft" /* DRAFT */,
|
|
1271
1285
|
options: [
|
|
@@ -1279,6 +1293,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1279
1293
|
],
|
|
1280
1294
|
admin: {
|
|
1281
1295
|
readOnly: true,
|
|
1296
|
+
description: "The status of the email send operation",
|
|
1282
1297
|
components: {
|
|
1283
1298
|
Cell: "payload-plugin-newsletter/components#StatusBadge"
|
|
1284
1299
|
}
|
|
@@ -1335,7 +1350,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1335
1350
|
type: "group",
|
|
1336
1351
|
admin: {
|
|
1337
1352
|
readOnly: true,
|
|
1338
|
-
condition: (data) => data?.
|
|
1353
|
+
condition: (data) => data?.sendStatus === "sent" /* SENT */
|
|
1339
1354
|
},
|
|
1340
1355
|
fields: [
|
|
1341
1356
|
{
|
|
@@ -1394,7 +1409,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1394
1409
|
name: "scheduledAt",
|
|
1395
1410
|
type: "date",
|
|
1396
1411
|
admin: {
|
|
1397
|
-
condition: (data) => data?.
|
|
1412
|
+
condition: (data) => data?.sendStatus === "scheduled" /* SCHEDULED */,
|
|
1398
1413
|
date: {
|
|
1399
1414
|
displayFormat: "MMM d, yyyy h:mm a"
|
|
1400
1415
|
}
|
|
@@ -1420,58 +1435,130 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1420
1435
|
}
|
|
1421
1436
|
],
|
|
1422
1437
|
hooks: {
|
|
1423
|
-
// Sync with provider on create
|
|
1438
|
+
// Sync with provider on create and update
|
|
1424
1439
|
afterChange: [
|
|
1425
|
-
async ({ doc, operation, req }) => {
|
|
1426
|
-
if (!hasProviders
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1440
|
+
async ({ doc, operation, req, previousDoc }) => {
|
|
1441
|
+
if (!hasProviders) return doc;
|
|
1442
|
+
if (operation === "create") {
|
|
1443
|
+
try {
|
|
1444
|
+
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
1445
|
+
if (!providerConfig || !providerConfig.token) {
|
|
1446
|
+
req.payload.logger.error("Broadcast provider not configured in Newsletter Settings or environment variables");
|
|
1447
|
+
return doc;
|
|
1448
|
+
}
|
|
1449
|
+
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
1450
|
+
const provider = new BroadcastApiProvider2(providerConfig);
|
|
1451
|
+
const htmlContent = await convertToEmailSafeHtml(doc.contentSection?.content);
|
|
1452
|
+
const providerBroadcast = await provider.create({
|
|
1453
|
+
name: doc.subject,
|
|
1454
|
+
// Use subject as name since we removed the name field
|
|
1455
|
+
subject: doc.subject,
|
|
1456
|
+
preheader: doc.contentSection?.preheader,
|
|
1457
|
+
content: htmlContent,
|
|
1458
|
+
trackOpens: doc.settings?.trackOpens,
|
|
1459
|
+
trackClicks: doc.settings?.trackClicks,
|
|
1460
|
+
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
1461
|
+
audienceIds: doc.audienceIds?.map((a) => a.audienceId)
|
|
1462
|
+
});
|
|
1463
|
+
await req.payload.update({
|
|
1464
|
+
collection: "broadcasts",
|
|
1465
|
+
id: doc.id,
|
|
1466
|
+
data: {
|
|
1467
|
+
providerId: providerBroadcast.id,
|
|
1468
|
+
providerData: providerBroadcast.providerData
|
|
1469
|
+
},
|
|
1470
|
+
req
|
|
1471
|
+
});
|
|
1472
|
+
return {
|
|
1473
|
+
...doc,
|
|
1451
1474
|
providerId: providerBroadcast.id,
|
|
1452
1475
|
providerData: providerBroadcast.providerData
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1476
|
+
};
|
|
1477
|
+
} catch (error) {
|
|
1478
|
+
if (error instanceof Error) {
|
|
1479
|
+
req.payload.logger.error("Failed to create broadcast in provider:", {
|
|
1480
|
+
message: error.message,
|
|
1481
|
+
stack: error.stack,
|
|
1482
|
+
name: error.name,
|
|
1483
|
+
// If it's a BroadcastProviderError, it might have additional details
|
|
1484
|
+
...error.details
|
|
1485
|
+
});
|
|
1486
|
+
} else {
|
|
1487
|
+
req.payload.logger.error("Failed to create broadcast in provider:", error);
|
|
1488
|
+
}
|
|
1489
|
+
return doc;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
if (operation === "update" && doc.providerId) {
|
|
1493
|
+
req.payload.logger.info("Broadcast afterChange update hook triggered", {
|
|
1494
|
+
operation,
|
|
1495
|
+
hasProviderId: !!doc.providerId,
|
|
1496
|
+
sendStatus: doc.sendStatus,
|
|
1497
|
+
publishStatus: doc._status
|
|
1455
1498
|
});
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1499
|
+
try {
|
|
1500
|
+
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
1501
|
+
if (!providerConfig || !providerConfig.token) {
|
|
1502
|
+
req.payload.logger.error("Broadcast provider not configured in Newsletter Settings or environment variables");
|
|
1503
|
+
return doc;
|
|
1504
|
+
}
|
|
1505
|
+
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
1506
|
+
const provider = new BroadcastApiProvider2(providerConfig);
|
|
1507
|
+
const capabilities = provider.getCapabilities();
|
|
1508
|
+
const sendStatus = doc.sendStatus || "draft" /* DRAFT */;
|
|
1509
|
+
if (!capabilities.editableStatuses.includes(sendStatus)) {
|
|
1510
|
+
req.payload.logger.info(`Skipping sync for broadcast in status: ${sendStatus}`);
|
|
1511
|
+
return doc;
|
|
1512
|
+
}
|
|
1513
|
+
const contentChanged = doc.subject !== previousDoc?.subject || doc.contentSection?.preheader !== previousDoc?.contentSection?.preheader || JSON.stringify(doc.contentSection?.content) !== JSON.stringify(previousDoc?.contentSection?.content) || doc.settings?.trackOpens !== previousDoc?.settings?.trackOpens || doc.settings?.trackClicks !== previousDoc?.settings?.trackClicks || doc.settings?.replyTo !== previousDoc?.settings?.replyTo || JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds);
|
|
1514
|
+
if (contentChanged) {
|
|
1515
|
+
const updates = {};
|
|
1516
|
+
if (doc.subject !== previousDoc?.subject) {
|
|
1517
|
+
updates.name = doc.subject;
|
|
1518
|
+
updates.subject = doc.subject;
|
|
1519
|
+
}
|
|
1520
|
+
if (doc.contentSection?.preheader !== previousDoc?.contentSection?.preheader) {
|
|
1521
|
+
updates.preheader = doc.contentSection?.preheader;
|
|
1522
|
+
}
|
|
1523
|
+
if (JSON.stringify(doc.contentSection?.content) !== JSON.stringify(previousDoc?.contentSection?.content)) {
|
|
1524
|
+
updates.content = await convertToEmailSafeHtml(doc.contentSection?.content);
|
|
1525
|
+
}
|
|
1526
|
+
if (doc.settings?.trackOpens !== previousDoc?.settings?.trackOpens) {
|
|
1527
|
+
updates.trackOpens = doc.settings.trackOpens;
|
|
1528
|
+
}
|
|
1529
|
+
if (doc.settings?.trackClicks !== previousDoc?.settings?.trackClicks) {
|
|
1530
|
+
updates.trackClicks = doc.settings.trackClicks;
|
|
1531
|
+
}
|
|
1532
|
+
if (doc.settings?.replyTo !== previousDoc?.settings?.replyTo) {
|
|
1533
|
+
updates.replyTo = doc.settings.replyTo || providerConfig.replyTo;
|
|
1534
|
+
}
|
|
1535
|
+
if (JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds)) {
|
|
1536
|
+
updates.audienceIds = doc.audienceIds?.map((a) => a.audienceId);
|
|
1537
|
+
}
|
|
1538
|
+
req.payload.logger.info("Syncing broadcast updates to provider", {
|
|
1539
|
+
providerId: doc.providerId,
|
|
1540
|
+
updates
|
|
1541
|
+
});
|
|
1542
|
+
await provider.update(doc.providerId, updates);
|
|
1543
|
+
req.payload.logger.info(`Broadcast ${doc.id} synced to provider successfully`);
|
|
1544
|
+
} else {
|
|
1545
|
+
req.payload.logger.info("No content changes to sync to provider");
|
|
1546
|
+
}
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
if (error instanceof Error) {
|
|
1549
|
+
req.payload.logger.error("Failed to sync broadcast update to provider:", {
|
|
1550
|
+
message: error.message,
|
|
1551
|
+
stack: error.stack,
|
|
1552
|
+
name: error.name,
|
|
1553
|
+
// If it's a BroadcastProviderError, it might have additional details
|
|
1554
|
+
...error.details
|
|
1555
|
+
});
|
|
1556
|
+
} else {
|
|
1557
|
+
req.payload.logger.error("Failed to sync broadcast update to provider:", error);
|
|
1558
|
+
}
|
|
1472
1559
|
}
|
|
1473
|
-
return doc;
|
|
1474
1560
|
}
|
|
1561
|
+
return doc;
|
|
1475
1562
|
},
|
|
1476
1563
|
// Hook to send when published
|
|
1477
1564
|
async ({ doc, operation, previousDoc, req }) => {
|
|
@@ -1479,7 +1566,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1479
1566
|
const wasUnpublished = !previousDoc?._status || previousDoc._status === "draft";
|
|
1480
1567
|
const isNowPublished = doc._status === "published";
|
|
1481
1568
|
if (wasUnpublished && isNowPublished && doc.providerId) {
|
|
1482
|
-
if (doc.
|
|
1569
|
+
if (doc.sendStatus === "sent" /* SENT */ || doc.sendStatus === "sending" /* SENDING */) {
|
|
1483
1570
|
return doc;
|
|
1484
1571
|
}
|
|
1485
1572
|
try {
|
|
@@ -1498,7 +1585,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1498
1585
|
collection: "broadcasts",
|
|
1499
1586
|
id: doc.id,
|
|
1500
1587
|
data: {
|
|
1501
|
-
|
|
1588
|
+
sendStatus: "sending" /* SENDING */,
|
|
1502
1589
|
sentAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1503
1590
|
},
|
|
1504
1591
|
req
|
|
@@ -1520,7 +1607,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1520
1607
|
collection: "broadcasts",
|
|
1521
1608
|
id: doc.id,
|
|
1522
1609
|
data: {
|
|
1523
|
-
|
|
1610
|
+
sendStatus: "failed" /* FAILED */
|
|
1524
1611
|
},
|
|
1525
1612
|
req
|
|
1526
1613
|
});
|
|
@@ -1529,62 +1616,8 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1529
1616
|
return doc;
|
|
1530
1617
|
}
|
|
1531
1618
|
],
|
|
1532
|
-
//
|
|
1533
|
-
beforeChange: [
|
|
1534
|
-
async ({ data, originalDoc, operation, req }) => {
|
|
1535
|
-
if (!hasProviders || !originalDoc?.providerId || operation !== "update") return data;
|
|
1536
|
-
try {
|
|
1537
|
-
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
1538
|
-
if (!providerConfig || !providerConfig.token) {
|
|
1539
|
-
req.payload.logger.error("Broadcast provider not configured in Newsletter Settings or environment variables");
|
|
1540
|
-
return data;
|
|
1541
|
-
}
|
|
1542
|
-
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
1543
|
-
const provider = new BroadcastApiProvider2(providerConfig);
|
|
1544
|
-
const capabilities = provider.getCapabilities();
|
|
1545
|
-
if (!capabilities.editableStatuses.includes(originalDoc.status)) {
|
|
1546
|
-
return data;
|
|
1547
|
-
}
|
|
1548
|
-
const updates = {};
|
|
1549
|
-
if (data.subject !== originalDoc.subject) {
|
|
1550
|
-
updates.name = data.subject;
|
|
1551
|
-
updates.subject = data.subject;
|
|
1552
|
-
}
|
|
1553
|
-
if (data.contentSection?.preheader !== originalDoc.contentSection?.preheader) updates.preheader = data.contentSection?.preheader;
|
|
1554
|
-
if (data.contentSection?.content !== originalDoc.contentSection?.content) {
|
|
1555
|
-
updates.content = await convertToEmailSafeHtml(data.contentSection?.content);
|
|
1556
|
-
}
|
|
1557
|
-
if (data.settings?.trackOpens !== originalDoc.settings?.trackOpens) {
|
|
1558
|
-
updates.trackOpens = data.settings.trackOpens;
|
|
1559
|
-
}
|
|
1560
|
-
if (data.settings?.trackClicks !== originalDoc.settings?.trackClicks) {
|
|
1561
|
-
updates.trackClicks = data.settings.trackClicks;
|
|
1562
|
-
}
|
|
1563
|
-
if (data.settings?.replyTo !== originalDoc.settings?.replyTo) {
|
|
1564
|
-
updates.replyTo = data.settings.replyTo || providerConfig.replyTo;
|
|
1565
|
-
}
|
|
1566
|
-
if (JSON.stringify(data.audienceIds) !== JSON.stringify(originalDoc.audienceIds)) {
|
|
1567
|
-
updates.audienceIds = data.audienceIds?.map((a) => a.audienceId);
|
|
1568
|
-
}
|
|
1569
|
-
if (Object.keys(updates).length > 0) {
|
|
1570
|
-
await provider.update(originalDoc.providerId, updates);
|
|
1571
|
-
}
|
|
1572
|
-
} catch (error) {
|
|
1573
|
-
if (error instanceof Error) {
|
|
1574
|
-
req.payload.logger.error("Failed to update broadcast in provider:", {
|
|
1575
|
-
message: error.message,
|
|
1576
|
-
stack: error.stack,
|
|
1577
|
-
name: error.name,
|
|
1578
|
-
// If it's a BroadcastProviderError, it might have additional details
|
|
1579
|
-
...error.details
|
|
1580
|
-
});
|
|
1581
|
-
} else {
|
|
1582
|
-
req.payload.logger.error("Failed to update broadcast in provider:", error);
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
return data;
|
|
1586
|
-
}
|
|
1587
|
-
],
|
|
1619
|
+
// beforeChange hooks can be added here if needed
|
|
1620
|
+
beforeChange: [],
|
|
1588
1621
|
// Handle deletion
|
|
1589
1622
|
afterDelete: [
|
|
1590
1623
|
async ({ doc, req }) => {
|
|
@@ -1598,7 +1631,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
1598
1631
|
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
1599
1632
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
1600
1633
|
const capabilities = provider.getCapabilities();
|
|
1601
|
-
if (capabilities.editableStatuses.includes(doc.
|
|
1634
|
+
if (capabilities.editableStatuses.includes(doc.sendStatus)) {
|
|
1602
1635
|
await provider.delete(doc.providerId);
|
|
1603
1636
|
}
|
|
1604
1637
|
} catch (error) {
|