payload-plugin-newsletter 0.25.1 → 0.25.3
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 +15 -0
- package/dist/collections.cjs +77 -129
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +77 -129
- package/dist/collections.js.map +1 -1
- package/dist/server.js +93 -145
- package/package.json +1 -1
- package/plugin-api-key-recommendations.md +0 -117
package/dist/collections.js
CHANGED
|
@@ -1501,7 +1501,7 @@ var createSendBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1501
1501
|
return {
|
|
1502
1502
|
path: "/:id/send",
|
|
1503
1503
|
method: "post",
|
|
1504
|
-
handler: async (req) => {
|
|
1504
|
+
handler: (async (req) => {
|
|
1505
1505
|
try {
|
|
1506
1506
|
const auth = await requireAdmin(req, config);
|
|
1507
1507
|
if (!auth.authorized) {
|
|
@@ -1575,7 +1575,7 @@ var createSendBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1575
1575
|
error: "Failed to send broadcast"
|
|
1576
1576
|
}, { status: 500 });
|
|
1577
1577
|
}
|
|
1578
|
-
}
|
|
1578
|
+
})
|
|
1579
1579
|
};
|
|
1580
1580
|
};
|
|
1581
1581
|
|
|
@@ -1585,7 +1585,7 @@ var createScheduleBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1585
1585
|
return {
|
|
1586
1586
|
path: "/:id/schedule",
|
|
1587
1587
|
method: "post",
|
|
1588
|
-
handler: async (req) => {
|
|
1588
|
+
handler: (async (req) => {
|
|
1589
1589
|
try {
|
|
1590
1590
|
const auth = await requireAdmin(req, config);
|
|
1591
1591
|
if (!auth.authorized) {
|
|
@@ -1679,7 +1679,7 @@ var createScheduleBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1679
1679
|
error: "Failed to schedule broadcast"
|
|
1680
1680
|
}, { status: 500 });
|
|
1681
1681
|
}
|
|
1682
|
-
}
|
|
1682
|
+
})
|
|
1683
1683
|
};
|
|
1684
1684
|
};
|
|
1685
1685
|
|
|
@@ -1688,7 +1688,7 @@ var createTestBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1688
1688
|
return {
|
|
1689
1689
|
path: "/:id/test",
|
|
1690
1690
|
method: "post",
|
|
1691
|
-
handler: async (req) => {
|
|
1691
|
+
handler: (async (req) => {
|
|
1692
1692
|
try {
|
|
1693
1693
|
const auth = await requireAdmin(req, config);
|
|
1694
1694
|
if (!auth.authorized) {
|
|
@@ -1762,7 +1762,7 @@ var createTestBroadcastEndpoint = (config, collectionSlug) => {
|
|
|
1762
1762
|
error: "Failed to send test email"
|
|
1763
1763
|
}, { status: 500 });
|
|
1764
1764
|
}
|
|
1765
|
-
}
|
|
1765
|
+
})
|
|
1766
1766
|
};
|
|
1767
1767
|
};
|
|
1768
1768
|
|
|
@@ -1838,6 +1838,10 @@ async function populateBlockMediaFields(node, payload, config) {
|
|
|
1838
1838
|
}
|
|
1839
1839
|
}
|
|
1840
1840
|
}
|
|
1841
|
+
if (field.type === "richText" && node.fields[field.name]) {
|
|
1842
|
+
await populateRichTextUploads(node.fields[field.name], payload);
|
|
1843
|
+
payload.logger?.info(`Processed rich text field ${field.name} for upload nodes`);
|
|
1844
|
+
}
|
|
1841
1845
|
}
|
|
1842
1846
|
}
|
|
1843
1847
|
}
|
|
@@ -1847,11 +1851,51 @@ async function populateBlockMediaFields(node, payload, config) {
|
|
|
1847
1851
|
}
|
|
1848
1852
|
}
|
|
1849
1853
|
}
|
|
1854
|
+
async function populateRichTextUploads(content, payload) {
|
|
1855
|
+
if (!content || typeof content !== "object") return;
|
|
1856
|
+
if (content.root?.children) {
|
|
1857
|
+
await processNodeArray(content.root.children);
|
|
1858
|
+
}
|
|
1859
|
+
if (Array.isArray(content)) {
|
|
1860
|
+
await processNodeArray(content);
|
|
1861
|
+
}
|
|
1862
|
+
async function processNodeArray(nodes) {
|
|
1863
|
+
await Promise.all(nodes.map(processNode));
|
|
1864
|
+
}
|
|
1865
|
+
async function processNode(node) {
|
|
1866
|
+
if (!node || typeof node !== "object") return;
|
|
1867
|
+
if (node.type === "upload" && node.relationTo === "media" && typeof node.value === "string" && node.value.match(/^[a-f0-9]{24}$/i)) {
|
|
1868
|
+
try {
|
|
1869
|
+
const media = await payload.findByID({
|
|
1870
|
+
collection: "media",
|
|
1871
|
+
id: node.value,
|
|
1872
|
+
depth: 0
|
|
1873
|
+
});
|
|
1874
|
+
if (media) {
|
|
1875
|
+
node.value = media;
|
|
1876
|
+
payload.logger?.info(`Populated rich text upload node:`, {
|
|
1877
|
+
mediaId: node.value,
|
|
1878
|
+
mediaUrl: media.url,
|
|
1879
|
+
filename: media.filename
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
} catch (error) {
|
|
1883
|
+
payload.logger?.error(`Failed to populate rich text upload ${node.value}:`, error);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
if (node.children && Array.isArray(node.children)) {
|
|
1887
|
+
await processNodeArray(node.children);
|
|
1888
|
+
}
|
|
1889
|
+
if (node.root?.children && Array.isArray(node.root.children)) {
|
|
1890
|
+
await processNodeArray(node.root.children);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1850
1894
|
var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
|
|
1851
1895
|
return {
|
|
1852
1896
|
path: "/preview",
|
|
1853
1897
|
method: "post",
|
|
1854
|
-
handler: async (req) => {
|
|
1898
|
+
handler: (async (req) => {
|
|
1855
1899
|
try {
|
|
1856
1900
|
const data = await (req.json?.() || Promise.resolve({}));
|
|
1857
1901
|
const { content, preheader, subject, documentData } = data;
|
|
@@ -1891,7 +1935,7 @@ var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
|
|
|
1891
1935
|
error: "Failed to generate email preview"
|
|
1892
1936
|
}, { status: 500 });
|
|
1893
1937
|
}
|
|
1894
|
-
}
|
|
1938
|
+
})
|
|
1895
1939
|
};
|
|
1896
1940
|
};
|
|
1897
1941
|
|
|
@@ -2236,10 +2280,6 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2236
2280
|
async ({ doc, operation, req, previousDoc }) => {
|
|
2237
2281
|
if (!hasProviders) return doc;
|
|
2238
2282
|
if (operation === "create") {
|
|
2239
|
-
if (!doc.subject || !doc.contentSection?.content) {
|
|
2240
|
-
req.payload.logger.info("Skipping provider sync - broadcast has no subject or content yet");
|
|
2241
|
-
return doc;
|
|
2242
|
-
}
|
|
2243
2283
|
try {
|
|
2244
2284
|
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
2245
2285
|
if (!providerConfig || !providerConfig.token) {
|
|
@@ -2248,45 +2288,32 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2248
2288
|
}
|
|
2249
2289
|
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
2250
2290
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
2251
|
-
|
|
2252
|
-
const
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
if (!htmlContent || htmlContent.trim() === "") {
|
|
2264
|
-
req.payload.logger.info("Skipping provider sync - content is empty after conversion");
|
|
2265
|
-
return doc;
|
|
2266
|
-
}
|
|
2291
|
+
const subject = doc.subject || `Draft Broadcast ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
2292
|
+
const htmlContent = doc.contentSection?.content ? await convertToEmailSafeHtml(
|
|
2293
|
+
await populateMediaFields(doc.contentSection.content, req.payload, pluginConfig),
|
|
2294
|
+
{
|
|
2295
|
+
wrapInTemplate: pluginConfig.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,
|
|
2296
|
+
customWrapper: pluginConfig.customizations?.broadcasts?.emailPreview?.customWrapper,
|
|
2297
|
+
preheader: doc.contentSection?.preheader,
|
|
2298
|
+
subject,
|
|
2299
|
+
documentData: doc,
|
|
2300
|
+
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2301
|
+
}
|
|
2302
|
+
) : "<p>Draft content - to be updated</p>";
|
|
2267
2303
|
const createData = {
|
|
2268
|
-
name:
|
|
2269
|
-
// Use subject as name
|
|
2270
|
-
subject
|
|
2271
|
-
preheader: doc.contentSection?.preheader,
|
|
2304
|
+
name: subject,
|
|
2305
|
+
// Use subject as name
|
|
2306
|
+
subject,
|
|
2307
|
+
preheader: doc.contentSection?.preheader || "",
|
|
2272
2308
|
content: htmlContent,
|
|
2273
|
-
trackOpens: doc.settings?.trackOpens,
|
|
2274
|
-
trackClicks: doc.settings?.trackClicks,
|
|
2309
|
+
trackOpens: doc.settings?.trackOpens ?? true,
|
|
2310
|
+
trackClicks: doc.settings?.trackClicks ?? true,
|
|
2275
2311
|
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
2276
|
-
audienceIds: doc.audienceIds?.map((a) => a.audienceId)
|
|
2312
|
+
audienceIds: doc.audienceIds?.map((a) => a.audienceId) || []
|
|
2277
2313
|
};
|
|
2278
|
-
req.payload.logger.info("Creating broadcast with data
|
|
2279
|
-
name: createData.name,
|
|
2314
|
+
req.payload.logger.info("Creating broadcast in provider with minimal data to establish association", {
|
|
2280
2315
|
subject: createData.subject,
|
|
2281
|
-
|
|
2282
|
-
contentLength: htmlContent ? htmlContent.length : 0,
|
|
2283
|
-
contentPreview: htmlContent ? htmlContent.substring(0, 100) + "..." : "EMPTY",
|
|
2284
|
-
trackOpens: createData.trackOpens,
|
|
2285
|
-
trackClicks: createData.trackClicks,
|
|
2286
|
-
replyTo: createData.replyTo,
|
|
2287
|
-
audienceIds: createData.audienceIds || [],
|
|
2288
|
-
apiUrl: providerConfig.apiUrl,
|
|
2289
|
-
hasToken: !!providerConfig.token
|
|
2316
|
+
hasActualContent: !!doc.contentSection?.content
|
|
2290
2317
|
});
|
|
2291
2318
|
const providerBroadcast = await provider.create(createData);
|
|
2292
2319
|
await req.payload.update({
|
|
@@ -2298,40 +2325,14 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2298
2325
|
},
|
|
2299
2326
|
req
|
|
2300
2327
|
});
|
|
2328
|
+
req.payload.logger.info(`Broadcast ${doc.id} created in provider with ID ${providerBroadcast.id}`);
|
|
2301
2329
|
return {
|
|
2302
2330
|
...doc,
|
|
2303
2331
|
providerId: providerBroadcast.id,
|
|
2304
2332
|
providerData: providerBroadcast.providerData
|
|
2305
2333
|
};
|
|
2306
2334
|
} catch (error) {
|
|
2307
|
-
req.payload.logger.error("
|
|
2308
|
-
req.payload.logger.error(error);
|
|
2309
|
-
if (error instanceof Error) {
|
|
2310
|
-
req.payload.logger.error("Error is instance of Error:", {
|
|
2311
|
-
message: error.message,
|
|
2312
|
-
stack: error.stack,
|
|
2313
|
-
name: error.name,
|
|
2314
|
-
// If it's a BroadcastProviderError, it might have additional details
|
|
2315
|
-
...error.details,
|
|
2316
|
-
// Check if it's a fetch response error
|
|
2317
|
-
...error.response,
|
|
2318
|
-
...error.data,
|
|
2319
|
-
...error.status,
|
|
2320
|
-
...error.statusText
|
|
2321
|
-
});
|
|
2322
|
-
} else if (typeof error === "string") {
|
|
2323
|
-
req.payload.logger.error("Error is a string:", error);
|
|
2324
|
-
} else if (error && typeof error === "object") {
|
|
2325
|
-
req.payload.logger.error("Error is an object:", JSON.stringify(error, null, 2));
|
|
2326
|
-
} else {
|
|
2327
|
-
req.payload.logger.error("Unknown error type:", typeof error);
|
|
2328
|
-
}
|
|
2329
|
-
req.payload.logger.error("Failed broadcast document:", {
|
|
2330
|
-
id: doc.id,
|
|
2331
|
-
subject: doc.subject,
|
|
2332
|
-
hasContent: !!doc.contentSection?.content,
|
|
2333
|
-
contentType: doc.contentSection?.content ? typeof doc.contentSection.content : "none"
|
|
2334
|
-
});
|
|
2335
|
+
req.payload.logger.error("Failed to create broadcast in provider during initial creation:", error);
|
|
2335
2336
|
return doc;
|
|
2336
2337
|
}
|
|
2337
2338
|
}
|
|
@@ -2351,61 +2352,8 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2351
2352
|
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
2352
2353
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
2353
2354
|
if (!doc.providerId) {
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
return doc;
|
|
2357
|
-
}
|
|
2358
|
-
req.payload.logger.info("Creating broadcast in provider (deferred from initial create)...");
|
|
2359
|
-
const populatedContent = await populateMediaFields(doc.contentSection?.content, req.payload, pluginConfig);
|
|
2360
|
-
const emailPreviewConfig = pluginConfig.customizations?.broadcasts?.emailPreview;
|
|
2361
|
-
const htmlContent = await convertToEmailSafeHtml(populatedContent, {
|
|
2362
|
-
wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,
|
|
2363
|
-
customWrapper: emailPreviewConfig?.customWrapper,
|
|
2364
|
-
preheader: doc.contentSection?.preheader,
|
|
2365
|
-
subject: doc.subject,
|
|
2366
|
-
documentData: doc,
|
|
2367
|
-
// Pass entire document
|
|
2368
|
-
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2369
|
-
});
|
|
2370
|
-
if (!htmlContent || htmlContent.trim() === "") {
|
|
2371
|
-
req.payload.logger.info("Skipping provider sync - content is empty after conversion");
|
|
2372
|
-
return doc;
|
|
2373
|
-
}
|
|
2374
|
-
const createData = {
|
|
2375
|
-
name: doc.subject,
|
|
2376
|
-
subject: doc.subject,
|
|
2377
|
-
preheader: doc.contentSection?.preheader,
|
|
2378
|
-
content: htmlContent,
|
|
2379
|
-
trackOpens: doc.settings?.trackOpens,
|
|
2380
|
-
trackClicks: doc.settings?.trackClicks,
|
|
2381
|
-
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
2382
|
-
audienceIds: doc.audienceIds?.map((a) => a.audienceId)
|
|
2383
|
-
};
|
|
2384
|
-
req.payload.logger.info("Creating broadcast with data:", {
|
|
2385
|
-
name: createData.name,
|
|
2386
|
-
subject: createData.subject,
|
|
2387
|
-
preheader: createData.preheader || "NONE",
|
|
2388
|
-
contentLength: htmlContent ? htmlContent.length : 0,
|
|
2389
|
-
contentPreview: htmlContent ? htmlContent.substring(0, 100) + "..." : "EMPTY",
|
|
2390
|
-
apiUrl: providerConfig.apiUrl,
|
|
2391
|
-
hasToken: !!providerConfig.token
|
|
2392
|
-
});
|
|
2393
|
-
const providerBroadcast = await provider.create(createData);
|
|
2394
|
-
await req.payload.update({
|
|
2395
|
-
collection: "broadcasts",
|
|
2396
|
-
id: doc.id,
|
|
2397
|
-
data: {
|
|
2398
|
-
providerId: providerBroadcast.id,
|
|
2399
|
-
providerData: providerBroadcast.providerData
|
|
2400
|
-
},
|
|
2401
|
-
req
|
|
2402
|
-
});
|
|
2403
|
-
req.payload.logger.info(`Broadcast ${doc.id} created in provider successfully (deferred)`);
|
|
2404
|
-
return {
|
|
2405
|
-
...doc,
|
|
2406
|
-
providerId: providerBroadcast.id,
|
|
2407
|
-
providerData: providerBroadcast.providerData
|
|
2408
|
-
};
|
|
2355
|
+
req.payload.logger.warn(`Broadcast ${doc.id} has no providerId - provider sync skipped. This shouldn't happen with immediate creation.`);
|
|
2356
|
+
return doc;
|
|
2409
2357
|
}
|
|
2410
2358
|
if (doc.providerId) {
|
|
2411
2359
|
const capabilities = provider.getCapabilities();
|