payload-plugin-newsletter 0.25.8 → 0.25.11
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 +22 -0
- package/dist/collections.cjs +68 -142
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +68 -142
- package/dist/collections.js.map +1 -1
- package/dist/fields.cjs +4 -38
- package/dist/fields.cjs.map +1 -1
- package/dist/fields.js +4 -38
- package/dist/fields.js.map +1 -1
- package/dist/server.js +68 -142
- package/dist/utils.cjs +2 -2
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.js +2 -2
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/collections.js
CHANGED
|
@@ -741,25 +741,8 @@ var createEmailSafeFeatures = (additionalBlocks) => {
|
|
|
741
741
|
ItalicFeature(),
|
|
742
742
|
UnderlineFeature(),
|
|
743
743
|
StrikethroughFeature(),
|
|
744
|
-
// Links
|
|
745
|
-
LinkFeature(
|
|
746
|
-
fields: [
|
|
747
|
-
{
|
|
748
|
-
name: "url",
|
|
749
|
-
type: "text",
|
|
750
|
-
required: true,
|
|
751
|
-
admin: {
|
|
752
|
-
description: "Enter the full URL (including https://)"
|
|
753
|
-
}
|
|
754
|
-
},
|
|
755
|
-
{
|
|
756
|
-
name: "newTab",
|
|
757
|
-
type: "checkbox",
|
|
758
|
-
label: "Open in new tab",
|
|
759
|
-
defaultValue: false
|
|
760
|
-
}
|
|
761
|
-
]
|
|
762
|
-
}),
|
|
744
|
+
// Links - use default fields to ensure drawer UI works correctly
|
|
745
|
+
LinkFeature(),
|
|
763
746
|
// Lists
|
|
764
747
|
OrderedListFeature(),
|
|
765
748
|
UnorderedListFeature(),
|
|
@@ -815,25 +798,8 @@ var createEmailLexicalEditor = (customBlocks = []) => {
|
|
|
815
798
|
ItalicFeature(),
|
|
816
799
|
UnderlineFeature(),
|
|
817
800
|
StrikethroughFeature(),
|
|
818
|
-
// Links
|
|
819
|
-
LinkFeature(
|
|
820
|
-
fields: [
|
|
821
|
-
{
|
|
822
|
-
name: "url",
|
|
823
|
-
type: "text",
|
|
824
|
-
required: true,
|
|
825
|
-
admin: {
|
|
826
|
-
description: "Enter the full URL (including https://)"
|
|
827
|
-
}
|
|
828
|
-
},
|
|
829
|
-
{
|
|
830
|
-
name: "newTab",
|
|
831
|
-
type: "checkbox",
|
|
832
|
-
label: "Open in new tab",
|
|
833
|
-
defaultValue: false
|
|
834
|
-
}
|
|
835
|
-
]
|
|
836
|
-
}),
|
|
801
|
+
// Links - use default fields to ensure drawer UI works correctly
|
|
802
|
+
LinkFeature(),
|
|
837
803
|
// Lists
|
|
838
804
|
OrderedListFeature(),
|
|
839
805
|
UnorderedListFeature(),
|
|
@@ -1401,7 +1367,7 @@ async function getBroadcastConfig(req, pluginConfig) {
|
|
|
1401
1367
|
}
|
|
1402
1368
|
return pluginConfig.providers?.broadcast || null;
|
|
1403
1369
|
} catch (error) {
|
|
1404
|
-
req.payload.logger.error("Failed to get broadcast config from settings
|
|
1370
|
+
req.payload.logger.error({ error: String(error) }, "Failed to get broadcast config from settings");
|
|
1405
1371
|
return pluginConfig.providers?.broadcast || null;
|
|
1406
1372
|
}
|
|
1407
1373
|
}
|
|
@@ -1798,23 +1764,24 @@ async function populateBlockMediaFields(node, payload, config) {
|
|
|
1798
1764
|
for (const field of blockConfig.fields) {
|
|
1799
1765
|
if (field.type === "upload" && field.relationTo && node.fields[field.name]) {
|
|
1800
1766
|
const fieldValue = node.fields[field.name];
|
|
1767
|
+
const collectionName = Array.isArray(field.relationTo) ? field.relationTo[0] : field.relationTo;
|
|
1801
1768
|
if (typeof fieldValue === "string" && fieldValue.match(/^[a-f0-9]{24}$/i)) {
|
|
1802
1769
|
try {
|
|
1803
1770
|
const media = await payload.findByID({
|
|
1804
|
-
collection:
|
|
1771
|
+
collection: collectionName,
|
|
1805
1772
|
id: fieldValue,
|
|
1806
1773
|
depth: 0
|
|
1807
1774
|
});
|
|
1808
1775
|
if (media) {
|
|
1809
1776
|
node.fields[field.name] = media;
|
|
1810
|
-
payload.logger?.info(
|
|
1777
|
+
payload.logger?.info({
|
|
1811
1778
|
mediaId: fieldValue,
|
|
1812
1779
|
mediaUrl: media.url,
|
|
1813
1780
|
filename: media.filename
|
|
1814
|
-
});
|
|
1781
|
+
}, `Populated ${field.name} for block ${blockType}`);
|
|
1815
1782
|
}
|
|
1816
1783
|
} catch (error) {
|
|
1817
|
-
payload.logger?.error(`Failed to populate ${field.name} for block ${blockType}
|
|
1784
|
+
payload.logger?.error({ error: String(error) }, `Failed to populate ${field.name} for block ${blockType}`);
|
|
1818
1785
|
}
|
|
1819
1786
|
}
|
|
1820
1787
|
}
|
|
@@ -1826,23 +1793,24 @@ async function populateBlockMediaFields(node, payload, config) {
|
|
|
1826
1793
|
for (const arrayField of field.fields) {
|
|
1827
1794
|
if (arrayField.type === "upload" && arrayField.relationTo && arrayItem[arrayField.name]) {
|
|
1828
1795
|
const arrayFieldValue = arrayItem[arrayField.name];
|
|
1796
|
+
const arrayCollectionName = Array.isArray(arrayField.relationTo) ? arrayField.relationTo[0] : arrayField.relationTo;
|
|
1829
1797
|
if (typeof arrayFieldValue === "string" && arrayFieldValue.match(/^[a-f0-9]{24}$/i)) {
|
|
1830
1798
|
try {
|
|
1831
1799
|
const media = await payload.findByID({
|
|
1832
|
-
collection:
|
|
1800
|
+
collection: arrayCollectionName,
|
|
1833
1801
|
id: arrayFieldValue,
|
|
1834
1802
|
depth: 0
|
|
1835
1803
|
});
|
|
1836
1804
|
if (media) {
|
|
1837
1805
|
arrayItem[arrayField.name] = media;
|
|
1838
|
-
payload.logger?.info(
|
|
1806
|
+
payload.logger?.info({
|
|
1839
1807
|
mediaId: arrayFieldValue,
|
|
1840
1808
|
mediaUrl: media.url,
|
|
1841
1809
|
filename: media.filename
|
|
1842
|
-
});
|
|
1810
|
+
}, `Populated array ${arrayField.name} for block ${blockType}`);
|
|
1843
1811
|
}
|
|
1844
1812
|
} catch (error) {
|
|
1845
|
-
payload.logger?.error(`Failed to populate array ${arrayField.name} for block ${blockType}
|
|
1813
|
+
payload.logger?.error({ error: String(error) }, `Failed to populate array ${arrayField.name} for block ${blockType}`);
|
|
1846
1814
|
}
|
|
1847
1815
|
}
|
|
1848
1816
|
}
|
|
@@ -1886,14 +1854,14 @@ async function populateRichTextUploads(content, payload) {
|
|
|
1886
1854
|
});
|
|
1887
1855
|
if (media) {
|
|
1888
1856
|
node.value = media;
|
|
1889
|
-
payload.logger?.info(
|
|
1857
|
+
payload.logger?.info({
|
|
1890
1858
|
mediaId: node.value,
|
|
1891
1859
|
mediaUrl: media.url,
|
|
1892
1860
|
filename: media.filename
|
|
1893
|
-
});
|
|
1861
|
+
}, "Populated rich text upload node");
|
|
1894
1862
|
}
|
|
1895
1863
|
} catch (error) {
|
|
1896
|
-
payload.logger?.error(`Failed to populate rich text upload ${node.value}
|
|
1864
|
+
payload.logger?.error({ error: String(error) }, `Failed to populate rich text upload ${node.value}`);
|
|
1897
1865
|
}
|
|
1898
1866
|
}
|
|
1899
1867
|
if (node.children && Array.isArray(node.children)) {
|
|
@@ -2293,93 +2261,19 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2293
2261
|
async ({ doc, operation, req, previousDoc }) => {
|
|
2294
2262
|
if (!hasProviders) return doc;
|
|
2295
2263
|
if (operation === "create") {
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
docId: doc.id,
|
|
2299
|
-
docIdType: typeof doc.id,
|
|
2300
|
-
hasDoc: !!doc,
|
|
2301
|
-
operation,
|
|
2302
|
-
status: doc._status,
|
|
2303
|
-
hasExternalId: !!doc.externalId,
|
|
2304
|
-
hasProviderId: !!doc.providerId
|
|
2305
|
-
});
|
|
2306
|
-
if (doc.externalId || doc.providerId) {
|
|
2307
|
-
req.payload.logger.info("Broadcast already has provider IDs, skipping creation", {
|
|
2308
|
-
externalId: doc.externalId,
|
|
2309
|
-
providerId: doc.providerId
|
|
2310
|
-
});
|
|
2311
|
-
return doc;
|
|
2312
|
-
}
|
|
2313
|
-
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
2314
|
-
if (!providerConfig || !providerConfig.token) {
|
|
2315
|
-
req.payload.logger.error("Broadcast provider not configured in Newsletter Settings or environment variables");
|
|
2316
|
-
return doc;
|
|
2317
|
-
}
|
|
2318
|
-
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
2319
|
-
const provider = new BroadcastApiProvider2(providerConfig);
|
|
2320
|
-
const subject = doc.subject || `Draft Broadcast ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
2321
|
-
const htmlContent = doc.contentSection?.content ? await convertToEmailSafeHtml(
|
|
2322
|
-
await populateMediaFields(doc.contentSection.content, req.payload, pluginConfig),
|
|
2323
|
-
{
|
|
2324
|
-
wrapInTemplate: pluginConfig.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,
|
|
2325
|
-
customWrapper: pluginConfig.customizations?.broadcasts?.emailPreview?.customWrapper,
|
|
2326
|
-
preheader: doc.contentSection?.preheader,
|
|
2327
|
-
subject,
|
|
2328
|
-
documentData: doc,
|
|
2329
|
-
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2330
|
-
}
|
|
2331
|
-
) : "<p>Draft content - to be updated</p>";
|
|
2332
|
-
const createData = {
|
|
2333
|
-
name: subject,
|
|
2334
|
-
// Use subject as name
|
|
2335
|
-
subject,
|
|
2336
|
-
preheader: doc.contentSection?.preheader || "",
|
|
2337
|
-
content: htmlContent,
|
|
2338
|
-
trackOpens: doc.settings?.trackOpens ?? true,
|
|
2339
|
-
trackClicks: doc.settings?.trackClicks ?? true,
|
|
2340
|
-
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
2341
|
-
audienceIds: doc.audienceIds?.map((a) => a.audienceId) || []
|
|
2342
|
-
};
|
|
2343
|
-
req.payload.logger.info("Creating broadcast in provider with minimal data to establish association", {
|
|
2344
|
-
subject: createData.subject,
|
|
2345
|
-
hasActualContent: !!doc.contentSection?.content
|
|
2346
|
-
});
|
|
2347
|
-
const providerBroadcast = await provider.create(createData);
|
|
2348
|
-
req.payload.logger.info("Provider broadcast created:", {
|
|
2349
|
-
providerBroadcastId: providerBroadcast.id,
|
|
2350
|
-
providerBroadcastIdType: typeof providerBroadcast.id,
|
|
2351
|
-
docId: doc.id,
|
|
2352
|
-
docIdType: typeof doc.id
|
|
2353
|
-
});
|
|
2354
|
-
req.payload.logger.info(`Broadcast ${doc.id} created in provider with ID ${providerBroadcast.id}`);
|
|
2355
|
-
return {
|
|
2356
|
-
...doc,
|
|
2357
|
-
providerId: providerBroadcast.id,
|
|
2358
|
-
externalId: providerBroadcast.id,
|
|
2359
|
-
// Include externalId in return value
|
|
2360
|
-
providerData: providerBroadcast.providerData
|
|
2361
|
-
};
|
|
2362
|
-
} catch (error) {
|
|
2363
|
-
req.payload.logger.error("Failed to create broadcast in provider during initial creation:");
|
|
2364
|
-
if (error instanceof Error) {
|
|
2365
|
-
req.payload.logger.error("Error details:", {
|
|
2366
|
-
message: error.message,
|
|
2367
|
-
stack: error.stack,
|
|
2368
|
-
name: error.name
|
|
2369
|
-
});
|
|
2370
|
-
} else {
|
|
2371
|
-
req.payload.logger.error("Raw error:", error);
|
|
2372
|
-
}
|
|
2373
|
-
return doc;
|
|
2374
|
-
}
|
|
2264
|
+
req.payload.logger.info("Broadcast created in Payload, provider sync will happen on first update with content");
|
|
2265
|
+
return doc;
|
|
2375
2266
|
}
|
|
2376
2267
|
if (operation === "update") {
|
|
2377
|
-
req.payload.logger.info(
|
|
2268
|
+
req.payload.logger.info({
|
|
2378
2269
|
operation,
|
|
2379
2270
|
hasProviderId: !!doc.providerId,
|
|
2271
|
+
hasExternalId: !!doc.externalId,
|
|
2380
2272
|
sendStatus: doc.sendStatus,
|
|
2381
|
-
publishStatus: doc._status
|
|
2382
|
-
|
|
2273
|
+
publishStatus: doc._status,
|
|
2274
|
+
hasSubject: !!doc.subject,
|
|
2275
|
+
hasContent: !!doc.contentSection?.content
|
|
2276
|
+
}, "Broadcast afterChange update hook triggered");
|
|
2383
2277
|
try {
|
|
2384
2278
|
const providerConfig = await getBroadcastConfig(req, pluginConfig);
|
|
2385
2279
|
if (!providerConfig || !providerConfig.token) {
|
|
@@ -2388,8 +2282,40 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2388
2282
|
}
|
|
2389
2283
|
const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
|
|
2390
2284
|
const provider = new BroadcastApiProvider2(providerConfig);
|
|
2285
|
+
if (!doc.providerId && !doc.externalId && doc.subject && doc.contentSection?.content) {
|
|
2286
|
+
req.payload.logger.info("Creating broadcast in provider on first update with content");
|
|
2287
|
+
const htmlContent = await convertToEmailSafeHtml(
|
|
2288
|
+
await populateMediaFields(doc.contentSection.content, req.payload, pluginConfig),
|
|
2289
|
+
{
|
|
2290
|
+
wrapInTemplate: pluginConfig.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,
|
|
2291
|
+
customWrapper: pluginConfig.customizations?.broadcasts?.emailPreview?.customWrapper,
|
|
2292
|
+
preheader: doc.contentSection?.preheader,
|
|
2293
|
+
subject: doc.subject,
|
|
2294
|
+
documentData: doc,
|
|
2295
|
+
customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
|
|
2296
|
+
}
|
|
2297
|
+
);
|
|
2298
|
+
const createData = {
|
|
2299
|
+
name: doc.subject,
|
|
2300
|
+
subject: doc.subject,
|
|
2301
|
+
preheader: doc.contentSection?.preheader || "",
|
|
2302
|
+
content: htmlContent,
|
|
2303
|
+
trackOpens: doc.settings?.trackOpens ?? true,
|
|
2304
|
+
trackClicks: doc.settings?.trackClicks ?? true,
|
|
2305
|
+
replyTo: doc.settings?.replyTo || providerConfig.replyTo,
|
|
2306
|
+
audienceIds: doc.audienceIds?.map((a) => a.audienceId) || []
|
|
2307
|
+
};
|
|
2308
|
+
const providerBroadcast = await provider.create(createData);
|
|
2309
|
+
req.payload.logger.info(`Broadcast ${doc.id} created in provider with ID ${providerBroadcast.id}`);
|
|
2310
|
+
return {
|
|
2311
|
+
...doc,
|
|
2312
|
+
providerId: providerBroadcast.id,
|
|
2313
|
+
externalId: providerBroadcast.id,
|
|
2314
|
+
providerData: providerBroadcast.providerData
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2391
2317
|
if (!doc.providerId) {
|
|
2392
|
-
req.payload.logger.
|
|
2318
|
+
req.payload.logger.info(`Broadcast ${doc.id} has no providerId and insufficient content for creation - skipping sync`);
|
|
2393
2319
|
return doc;
|
|
2394
2320
|
}
|
|
2395
2321
|
if (doc.providerId) {
|
|
@@ -2434,10 +2360,10 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2434
2360
|
if (JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds)) {
|
|
2435
2361
|
updates.audienceIds = doc.audienceIds?.map((a) => a.audienceId);
|
|
2436
2362
|
}
|
|
2437
|
-
req.payload.logger.info(
|
|
2363
|
+
req.payload.logger.info({
|
|
2438
2364
|
providerId: doc.providerId,
|
|
2439
2365
|
updates
|
|
2440
|
-
});
|
|
2366
|
+
}, "Syncing broadcast updates to provider");
|
|
2441
2367
|
await provider.update(doc.providerId, updates);
|
|
2442
2368
|
req.payload.logger.info(`Broadcast ${doc.id} synced to provider successfully`);
|
|
2443
2369
|
} else {
|
|
@@ -2459,18 +2385,18 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2459
2385
|
...error.statusText
|
|
2460
2386
|
});
|
|
2461
2387
|
} else if (typeof error === "string") {
|
|
2462
|
-
req.payload.logger.error("Error is a string
|
|
2388
|
+
req.payload.logger.error({ errorValue: error }, "Error is a string");
|
|
2463
2389
|
} else if (error && typeof error === "object") {
|
|
2464
|
-
req.payload.logger.error(
|
|
2390
|
+
req.payload.logger.error({ errorValue: JSON.stringify(error, null, 2) }, "Error is an object");
|
|
2465
2391
|
} else {
|
|
2466
|
-
req.payload.logger.error("Unknown error type
|
|
2392
|
+
req.payload.logger.error({ errorType: typeof error }, "Unknown error type");
|
|
2467
2393
|
}
|
|
2468
|
-
req.payload.logger.error(
|
|
2394
|
+
req.payload.logger.error({
|
|
2469
2395
|
id: doc.id,
|
|
2470
2396
|
subject: doc.subject,
|
|
2471
2397
|
hasContent: !!doc.contentSection?.content,
|
|
2472
2398
|
contentType: doc.contentSection?.content ? typeof doc.contentSection.content : "none"
|
|
2473
|
-
});
|
|
2399
|
+
}, "Failed broadcast document (update operation)");
|
|
2474
2400
|
}
|
|
2475
2401
|
}
|
|
2476
2402
|
return doc;
|
|
@@ -2516,7 +2442,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2516
2442
|
...error.details
|
|
2517
2443
|
});
|
|
2518
2444
|
} else {
|
|
2519
|
-
req.payload.logger.error(`Failed to send broadcast ${doc.id}
|
|
2445
|
+
req.payload.logger.error({ error: String(error) }, `Failed to send broadcast ${doc.id}`);
|
|
2520
2446
|
}
|
|
2521
2447
|
await req.payload.update({
|
|
2522
2448
|
collection: "broadcasts",
|
|
@@ -2559,7 +2485,7 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2559
2485
|
...error.details
|
|
2560
2486
|
});
|
|
2561
2487
|
} else {
|
|
2562
|
-
req.payload.logger.error("Failed to delete broadcast from provider
|
|
2488
|
+
req.payload.logger.error({ error: String(error) }, "Failed to delete broadcast from provider");
|
|
2563
2489
|
}
|
|
2564
2490
|
}
|
|
2565
2491
|
return doc;
|