payload-plugin-newsletter 0.25.1 → 0.25.2
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 +6 -0
- package/dist/collections.cjs +33 -129
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +33 -129
- package/dist/collections.js.map +1 -1
- package/dist/server.js +49 -145
- package/package.json +1 -1
- package/plugin-api-key-recommendations.md +0 -117
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [0.25.2] - 2025-08-15
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
- Fixed issue where editing draft broadcasts created duplicate entries in the provider instead of updating the existing broadcast
|
|
5
|
+
- Broadcasts now immediately sync to provider on creation with minimal data to establish the association
|
|
6
|
+
|
|
1
7
|
## [0.25.1] - 2025-08-09
|
|
2
8
|
|
|
3
9
|
### Fixed
|
package/dist/collections.cjs
CHANGED
|
@@ -1514,7 +1514,7 @@ var createSendBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1514
1514
|
return {
|
|
1515
1515
|
path: "/:id/send",
|
|
1516
1516
|
method: "post",
|
|
1517
|
-
handler: async (req) => {
|
|
1517
|
+
handler: (async (req) => {
|
|
1518
1518
|
try {
|
|
1519
1519
|
const auth = await requireAdmin(req, config);
|
|
1520
1520
|
if (!auth.authorized) {
|
|
@@ -1588,7 +1588,7 @@ var createSendBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1588
1588
|
error: "Failed to send broadcast"
|
|
1589
1589
|
}, { status: 500 });
|
|
1590
1590
|
}
|
|
1591
|
-
}
|
|
1591
|
+
})
|
|
1592
1592
|
};
|
|
1593
1593
|
};
|
|
1594
1594
|
|
|
@@ -1598,7 +1598,7 @@ var createScheduleBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1598
1598
|
return {
|
|
1599
1599
|
path: "/:id/schedule",
|
|
1600
1600
|
method: "post",
|
|
1601
|
-
handler: async (req) => {
|
|
1601
|
+
handler: (async (req) => {
|
|
1602
1602
|
try {
|
|
1603
1603
|
const auth = await requireAdmin(req, config);
|
|
1604
1604
|
if (!auth.authorized) {
|
|
@@ -1692,7 +1692,7 @@ var createScheduleBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1692
1692
|
error: "Failed to schedule broadcast"
|
|
1693
1693
|
}, { status: 500 });
|
|
1694
1694
|
}
|
|
1695
|
-
}
|
|
1695
|
+
})
|
|
1696
1696
|
};
|
|
1697
1697
|
};
|
|
1698
1698
|
|
|
@@ -1701,7 +1701,7 @@ var createTestBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1701
1701
|
return {
|
|
1702
1702
|
path: "/:id/test",
|
|
1703
1703
|
method: "post",
|
|
1704
|
-
handler: async (req) => {
|
|
1704
|
+
handler: (async (req) => {
|
|
1705
1705
|
try {
|
|
1706
1706
|
const auth = await requireAdmin(req, config);
|
|
1707
1707
|
if (!auth.authorized) {
|
|
@@ -1775,7 +1775,7 @@ var createTestBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1775
1775
|
error: "Failed to send test email"
|
|
1776
1776
|
}, { status: 500 });
|
|
1777
1777
|
}
|
|
1778
|
-
}
|
|
1778
|
+
})
|
|
1779
1779
|
};
|
|
1780
1780
|
};
|
|
1781
1781
|
|
|
@@ -1864,7 +1864,7 @@ var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
|
|
|
1864
1864
|
return {
|
|
1865
1865
|
path: "/preview",
|
|
1866
1866
|
method: "post",
|
|
1867
|
-
handler: async (req) => {
|
|
1867
|
+
handler: (async (req) => {
|
|
1868
1868
|
try {
|
|
1869
1869
|
const data = await (req.json?.() || Promise.resolve({}));
|
|
1870
1870
|
const { content, preheader, subject, documentData } = data;
|
|
@@ -1904,7 +1904,7 @@ var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
|
|
|
1904
1904
|
error: "Failed to generate email preview"
|
|
1905
1905
|
}, { status: 500 });
|
|
1906
1906
|
}
|
|
1907
|
-
}
|
|
1907
|
+
})
|
|
1908
1908
|
};
|
|
1909
1909
|
};
|
|
1910
1910
|
|
|
@@ -2249,10 +2249,6 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2249
2249
|
async ({ doc, operation, req, previousDoc }) => {
|
|
2250
2250
|
if (!hasProviders) return doc;
|
|
2251
2251
|
if (operation === "create") {
|
|
2252
|
-
if (!doc.subject || !doc.contentSection?.content) {
|
|
2253
|
-
req.payload.logger.info("Skipping provider sync - broadcast has no subject or content yet");
|
|
2254
|
-
return doc;
|
|
2255
|
-
}
|
|
2256
2252
|
try {
|
|
2257
2253
|
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
2258
2254
|
if (!providerConfig || !providerConfig.token) {
|
|
@@ -2261,45 +2257,32 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2261
2257
|
}
|
|
2262
2258
|
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
2263
2259
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
2264
|
-
|
|
2265
|
-
const
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
if (!htmlContent || htmlContent.trim() === "") {
|
|
2277
|
-
req.payload.logger.info("Skipping provider sync - content is empty after conversion");
|
|
2278
|
-
return doc;
|
|
2279
|
-
}
|
|
2260
|
+
const subject = doc.subject || `Draft Broadcast ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
2261
|
+
const htmlContent = doc.contentSection?.content ? await convertToEmailSafeHtml(
|
|
2262
|
+
await populateMediaFields(doc.contentSection.content, req.payload, pluginConfig),
|
|
2263
|
+
{
|
|
2264
|
+
wrapInTemplate: pluginConfig.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,
|
|
2265
|
+
customWrapper: pluginConfig.customizations?.broadcasts?.emailPreview?.customWrapper,
|
|
2266
|
+
preheader: doc.contentSection?.preheader,
|
|
2267
|
+
subject,
|
|
2268
|
+
documentData: doc,
|
|
2269
|
+
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2270
|
+
}
|
|
2271
|
+
) : "<p>Draft content - to be updated</p>";
|
|
2280
2272
|
const createData = {
|
|
2281
|
-
name:
|
|
2282
|
-
// Use subject as name
|
|
2283
|
-
subject
|
|
2284
|
-
preheader: doc.contentSection?.preheader,
|
|
2273
|
+
name: subject,
|
|
2274
|
+
// Use subject as name
|
|
2275
|
+
subject,
|
|
2276
|
+
preheader: doc.contentSection?.preheader || "",
|
|
2285
2277
|
content: htmlContent,
|
|
2286
|
-
trackOpens: doc.settings?.trackOpens,
|
|
2287
|
-
trackClicks: doc.settings?.trackClicks,
|
|
2278
|
+
trackOpens: doc.settings?.trackOpens ?? true,
|
|
2279
|
+
trackClicks: doc.settings?.trackClicks ?? true,
|
|
2288
2280
|
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
2289
|
-
audienceIds: doc.audienceIds?.map((a) => a.audienceId)
|
|
2281
|
+
audienceIds: doc.audienceIds?.map((a) => a.audienceId) || []
|
|
2290
2282
|
};
|
|
2291
|
-
req.payload.logger.info("Creating broadcast with data
|
|
2292
|
-
name: createData.name,
|
|
2283
|
+
req.payload.logger.info("Creating broadcast in provider with minimal data to establish association", {
|
|
2293
2284
|
subject: createData.subject,
|
|
2294
|
-
|
|
2295
|
-
contentLength: htmlContent ? htmlContent.length : 0,
|
|
2296
|
-
contentPreview: htmlContent ? htmlContent.substring(0, 100) + "..." : "EMPTY",
|
|
2297
|
-
trackOpens: createData.trackOpens,
|
|
2298
|
-
trackClicks: createData.trackClicks,
|
|
2299
|
-
replyTo: createData.replyTo,
|
|
2300
|
-
audienceIds: createData.audienceIds || [],
|
|
2301
|
-
apiUrl: providerConfig.apiUrl,
|
|
2302
|
-
hasToken: !!providerConfig.token
|
|
2285
|
+
hasActualContent: !!doc.contentSection?.content
|
|
2303
2286
|
});
|
|
2304
2287
|
const providerBroadcast = await provider.create(createData);
|
|
2305
2288
|
await req.payload.update({
|
|
@@ -2311,40 +2294,14 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2311
2294
|
},
|
|
2312
2295
|
req
|
|
2313
2296
|
});
|
|
2297
|
+
req.payload.logger.info(`Broadcast ${doc.id} created in provider with ID ${providerBroadcast.id}`);
|
|
2314
2298
|
return {
|
|
2315
2299
|
...doc,
|
|
2316
2300
|
providerId: providerBroadcast.id,
|
|
2317
2301
|
providerData: providerBroadcast.providerData
|
|
2318
2302
|
};
|
|
2319
2303
|
} catch (error) {
|
|
2320
|
-
req.payload.logger.error("
|
|
2321
|
-
req.payload.logger.error(error);
|
|
2322
|
-
if (error instanceof Error) {
|
|
2323
|
-
req.payload.logger.error("Error is instance of Error:", {
|
|
2324
|
-
message: error.message,
|
|
2325
|
-
stack: error.stack,
|
|
2326
|
-
name: error.name,
|
|
2327
|
-
// If it's a BroadcastProviderError, it might have additional details
|
|
2328
|
-
...error.details,
|
|
2329
|
-
// Check if it's a fetch response error
|
|
2330
|
-
...error.response,
|
|
2331
|
-
...error.data,
|
|
2332
|
-
...error.status,
|
|
2333
|
-
...error.statusText
|
|
2334
|
-
});
|
|
2335
|
-
} else if (typeof error === "string") {
|
|
2336
|
-
req.payload.logger.error("Error is a string:", error);
|
|
2337
|
-
} else if (error && typeof error === "object") {
|
|
2338
|
-
req.payload.logger.error("Error is an object:", JSON.stringify(error, null, 2));
|
|
2339
|
-
} else {
|
|
2340
|
-
req.payload.logger.error("Unknown error type:", typeof error);
|
|
2341
|
-
}
|
|
2342
|
-
req.payload.logger.error("Failed broadcast document:", {
|
|
2343
|
-
id: doc.id,
|
|
2344
|
-
subject: doc.subject,
|
|
2345
|
-
hasContent: !!doc.contentSection?.content,
|
|
2346
|
-
contentType: doc.contentSection?.content ? typeof doc.contentSection.content : "none"
|
|
2347
|
-
});
|
|
2304
|
+
req.payload.logger.error("Failed to create broadcast in provider during initial creation:", error);
|
|
2348
2305
|
return doc;
|
|
2349
2306
|
}
|
|
2350
2307
|
}
|
|
@@ -2364,61 +2321,8 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2364
2321
|
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
2365
2322
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
2366
2323
|
if (!doc.providerId) {
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
return doc;
|
|
2370
|
-
}
|
|
2371
|
-
req.payload.logger.info("Creating broadcast in provider (deferred from initial create)...");
|
|
2372
|
-
const populatedContent = await populateMediaFields(doc.contentSection?.content, req.payload, pluginConfig);
|
|
2373
|
-
const emailPreviewConfig = pluginConfig.customizations?.broadcasts?.emailPreview;
|
|
2374
|
-
const htmlContent = await convertToEmailSafeHtml(populatedContent, {
|
|
2375
|
-
wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,
|
|
2376
|
-
customWrapper: emailPreviewConfig?.customWrapper,
|
|
2377
|
-
preheader: doc.contentSection?.preheader,
|
|
2378
|
-
subject: doc.subject,
|
|
2379
|
-
documentData: doc,
|
|
2380
|
-
// Pass entire document
|
|
2381
|
-
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2382
|
-
});
|
|
2383
|
-
if (!htmlContent || htmlContent.trim() === "") {
|
|
2384
|
-
req.payload.logger.info("Skipping provider sync - content is empty after conversion");
|
|
2385
|
-
return doc;
|
|
2386
|
-
}
|
|
2387
|
-
const createData = {
|
|
2388
|
-
name: doc.subject,
|
|
2389
|
-
subject: doc.subject,
|
|
2390
|
-
preheader: doc.contentSection?.preheader,
|
|
2391
|
-
content: htmlContent,
|
|
2392
|
-
trackOpens: doc.settings?.trackOpens,
|
|
2393
|
-
trackClicks: doc.settings?.trackClicks,
|
|
2394
|
-
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
2395
|
-
audienceIds: doc.audienceIds?.map((a) => a.audienceId)
|
|
2396
|
-
};
|
|
2397
|
-
req.payload.logger.info("Creating broadcast with data:", {
|
|
2398
|
-
name: createData.name,
|
|
2399
|
-
subject: createData.subject,
|
|
2400
|
-
preheader: createData.preheader || "NONE",
|
|
2401
|
-
contentLength: htmlContent ? htmlContent.length : 0,
|
|
2402
|
-
contentPreview: htmlContent ? htmlContent.substring(0, 100) + "..." : "EMPTY",
|
|
2403
|
-
apiUrl: providerConfig.apiUrl,
|
|
2404
|
-
hasToken: !!providerConfig.token
|
|
2405
|
-
});
|
|
2406
|
-
const providerBroadcast = await provider.create(createData);
|
|
2407
|
-
await req.payload.update({
|
|
2408
|
-
collection: "broadcasts",
|
|
2409
|
-
id: doc.id,
|
|
2410
|
-
data: {
|
|
2411
|
-
providerId: providerBroadcast.id,
|
|
2412
|
-
providerData: providerBroadcast.providerData
|
|
2413
|
-
},
|
|
2414
|
-
req
|
|
2415
|
-
});
|
|
2416
|
-
req.payload.logger.info(`Broadcast ${doc.id} created in provider successfully (deferred)`);
|
|
2417
|
-
return {
|
|
2418
|
-
...doc,
|
|
2419
|
-
providerId: providerBroadcast.id,
|
|
2420
|
-
providerData: providerBroadcast.providerData
|
|
2421
|
-
};
|
|
2324
|
+
req.payload.logger.warn(`Broadcast ${doc.id} has no providerId - provider sync skipped. This shouldn't happen with immediate creation.`);
|
|
2325
|
+
return doc;
|
|
2422
2326
|
}
|
|
2423
2327
|
if (doc.providerId) {
|
|
2424
2328
|
const capabilities = provider.getCapabilities();
|