payload-plugin-newsletter 0.25.9 → 0.25.12

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.
@@ -741,25 +741,8 @@ var createEmailSafeFeatures = (additionalBlocks) => {
741
741
  ItalicFeature(),
742
742
  UnderlineFeature(),
743
743
  StrikethroughFeature(),
744
- // Links with enhanced configuration
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 with enhanced configuration
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:", error);
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
  }
@@ -1779,70 +1745,88 @@ var createTestBroadcastEndpoint = (config, collectionSlug) => {
1779
1745
  };
1780
1746
  };
1781
1747
 
1782
- // src/endpoints/broadcasts/preview.ts
1748
+ // src/utils/mediaPopulation.ts
1783
1749
  async function populateMediaFields(content, payload, config) {
1784
1750
  if (!content || typeof content !== "object") return content;
1785
- if (content.root?.children) {
1786
- for (const child of content.root.children) {
1751
+ const typedContent = content;
1752
+ if (typedContent.root?.children) {
1753
+ for (const child of typedContent.root.children) {
1787
1754
  await populateBlockMediaFields(child, payload, config);
1788
1755
  }
1789
1756
  }
1790
1757
  return content;
1791
1758
  }
1792
1759
  async function populateBlockMediaFields(node, payload, config) {
1793
- if (node.type === "block" && node.fields) {
1794
- const blockType = node.fields.blockType || node.fields.blockName;
1760
+ if (!node || typeof node !== "object") return;
1761
+ const typedNode = node;
1762
+ if (typedNode.type === "block" && typedNode.fields) {
1763
+ const blockType = typedNode.fields.blockType || typedNode.fields.blockName;
1795
1764
  const customBlocks = config.customizations?.broadcasts?.customBlocks || [];
1796
1765
  const blockConfig = customBlocks.find((b) => b.slug === blockType);
1797
1766
  if (blockConfig && blockConfig.fields) {
1798
1767
  for (const field of blockConfig.fields) {
1799
- if (field.type === "upload" && field.relationTo && node.fields[field.name]) {
1800
- const fieldValue = node.fields[field.name];
1768
+ if (field.type === "upload" && field.relationTo && typedNode.fields[field.name]) {
1769
+ const fieldValue = typedNode.fields[field.name];
1770
+ const collectionName = Array.isArray(field.relationTo) ? field.relationTo[0] : field.relationTo;
1801
1771
  if (typeof fieldValue === "string" && fieldValue.match(/^[a-f0-9]{24}$/i)) {
1802
1772
  try {
1803
1773
  const media = await payload.findByID({
1804
- collection: field.relationTo,
1774
+ collection: collectionName,
1805
1775
  id: fieldValue,
1806
1776
  depth: 0
1807
1777
  });
1808
1778
  if (media) {
1809
- node.fields[field.name] = media;
1810
- payload.logger?.info(`Populated ${field.name} for block ${blockType}:`, {
1811
- mediaId: fieldValue,
1812
- mediaUrl: media.url,
1813
- filename: media.filename
1814
- });
1779
+ typedNode.fields[field.name] = media;
1780
+ payload.logger?.info(
1781
+ {
1782
+ mediaId: fieldValue,
1783
+ mediaUrl: media.url,
1784
+ filename: media.filename
1785
+ },
1786
+ `Populated ${field.name} for block ${blockType}`
1787
+ );
1815
1788
  }
1816
1789
  } catch (error) {
1817
- payload.logger?.error(`Failed to populate ${field.name} for block ${blockType}:`, error);
1790
+ payload.logger?.error(
1791
+ { error: String(error) },
1792
+ `Failed to populate ${field.name} for block ${blockType}`
1793
+ );
1818
1794
  }
1819
1795
  }
1820
1796
  }
1821
1797
  if (field.type === "array" && field.fields) {
1822
- const arrayValue = node.fields[field.name];
1798
+ const arrayValue = typedNode.fields[field.name];
1823
1799
  if (Array.isArray(arrayValue)) {
1824
1800
  for (const arrayItem of arrayValue) {
1825
1801
  if (arrayItem && typeof arrayItem === "object") {
1802
+ const typedArrayItem = arrayItem;
1826
1803
  for (const arrayField of field.fields) {
1827
- if (arrayField.type === "upload" && arrayField.relationTo && arrayItem[arrayField.name]) {
1828
- const arrayFieldValue = arrayItem[arrayField.name];
1804
+ if (arrayField.type === "upload" && arrayField.relationTo && typedArrayItem[arrayField.name]) {
1805
+ const arrayFieldValue = typedArrayItem[arrayField.name];
1806
+ const arrayCollectionName = Array.isArray(arrayField.relationTo) ? arrayField.relationTo[0] : arrayField.relationTo;
1829
1807
  if (typeof arrayFieldValue === "string" && arrayFieldValue.match(/^[a-f0-9]{24}$/i)) {
1830
1808
  try {
1831
1809
  const media = await payload.findByID({
1832
- collection: arrayField.relationTo,
1810
+ collection: arrayCollectionName,
1833
1811
  id: arrayFieldValue,
1834
1812
  depth: 0
1835
1813
  });
1836
1814
  if (media) {
1837
- arrayItem[arrayField.name] = media;
1838
- payload.logger?.info(`Populated array ${arrayField.name} for block ${blockType}:`, {
1839
- mediaId: arrayFieldValue,
1840
- mediaUrl: media.url,
1841
- filename: media.filename
1842
- });
1815
+ typedArrayItem[arrayField.name] = media;
1816
+ payload.logger?.info(
1817
+ {
1818
+ mediaId: arrayFieldValue,
1819
+ mediaUrl: media.url,
1820
+ filename: media.filename
1821
+ },
1822
+ `Populated array ${arrayField.name} for block ${blockType}`
1823
+ );
1843
1824
  }
1844
1825
  } catch (error) {
1845
- payload.logger?.error(`Failed to populate array ${arrayField.name} for block ${blockType}:`, error);
1826
+ payload.logger?.error(
1827
+ { error: String(error) },
1828
+ `Failed to populate array ${arrayField.name} for block ${blockType}`
1829
+ );
1846
1830
  }
1847
1831
  }
1848
1832
  }
@@ -1851,23 +1835,24 @@ async function populateBlockMediaFields(node, payload, config) {
1851
1835
  }
1852
1836
  }
1853
1837
  }
1854
- if (field.type === "richText" && node.fields[field.name]) {
1855
- await populateRichTextUploads(node.fields[field.name], payload);
1838
+ if (field.type === "richText" && typedNode.fields[field.name]) {
1839
+ await populateRichTextUploads(typedNode.fields[field.name], payload);
1856
1840
  payload.logger?.info(`Processed rich text field ${field.name} for upload nodes`);
1857
1841
  }
1858
1842
  }
1859
1843
  }
1860
1844
  }
1861
- if (node.children) {
1862
- for (const child of node.children) {
1845
+ if (typedNode.children) {
1846
+ for (const child of typedNode.children) {
1863
1847
  await populateBlockMediaFields(child, payload, config);
1864
1848
  }
1865
1849
  }
1866
1850
  }
1867
1851
  async function populateRichTextUploads(content, payload) {
1868
1852
  if (!content || typeof content !== "object") return;
1869
- if (content.root?.children) {
1870
- await processNodeArray(content.root.children);
1853
+ const typedContent = content;
1854
+ if (typedContent.root?.children) {
1855
+ await processNodeArray(typedContent.root.children);
1871
1856
  }
1872
1857
  if (Array.isArray(content)) {
1873
1858
  await processNodeArray(content);
@@ -1877,33 +1862,42 @@ async function populateRichTextUploads(content, payload) {
1877
1862
  }
1878
1863
  async function processNode(node) {
1879
1864
  if (!node || typeof node !== "object") return;
1880
- if (node.type === "upload" && node.relationTo === "media" && typeof node.value === "string" && node.value.match(/^[a-f0-9]{24}$/i)) {
1865
+ const typedNode = node;
1866
+ if (typedNode.type === "upload" && typedNode.relationTo === "media" && typeof typedNode.value === "string" && typedNode.value.match(/^[a-f0-9]{24}$/i)) {
1881
1867
  try {
1882
1868
  const media = await payload.findByID({
1883
1869
  collection: "media",
1884
- id: node.value,
1870
+ id: typedNode.value,
1885
1871
  depth: 0
1886
1872
  });
1887
1873
  if (media) {
1888
- node.value = media;
1889
- payload.logger?.info(`Populated rich text upload node:`, {
1890
- mediaId: node.value,
1891
- mediaUrl: media.url,
1892
- filename: media.filename
1893
- });
1874
+ typedNode.value = media;
1875
+ payload.logger?.info(
1876
+ {
1877
+ mediaId: typedNode.value,
1878
+ mediaUrl: media.url,
1879
+ filename: media.filename
1880
+ },
1881
+ "Populated rich text upload node"
1882
+ );
1894
1883
  }
1895
1884
  } catch (error) {
1896
- payload.logger?.error(`Failed to populate rich text upload ${node.value}:`, error);
1885
+ payload.logger?.error(
1886
+ { error: String(error) },
1887
+ `Failed to populate rich text upload ${typedNode.value}`
1888
+ );
1897
1889
  }
1898
1890
  }
1899
- if (node.children && Array.isArray(node.children)) {
1900
- await processNodeArray(node.children);
1891
+ if (typedNode.children && Array.isArray(typedNode.children)) {
1892
+ await processNodeArray(typedNode.children);
1901
1893
  }
1902
- if (node.root?.children && Array.isArray(node.root.children)) {
1903
- await processNodeArray(node.root.children);
1894
+ if (typedNode.root?.children && Array.isArray(typedNode.root.children)) {
1895
+ await processNodeArray(typedNode.root.children);
1904
1896
  }
1905
1897
  }
1906
1898
  }
1899
+
1900
+ // src/endpoints/broadcasts/preview.ts
1907
1901
  var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
1908
1902
  return {
1909
1903
  path: "/preview",
@@ -2297,7 +2291,7 @@ var createBroadcastsCollection = (pluginConfig) => {
2297
2291
  return doc;
2298
2292
  }
2299
2293
  if (operation === "update") {
2300
- req.payload.logger.info("Broadcast afterChange update hook triggered", {
2294
+ req.payload.logger.info({
2301
2295
  operation,
2302
2296
  hasProviderId: !!doc.providerId,
2303
2297
  hasExternalId: !!doc.externalId,
@@ -2305,7 +2299,7 @@ var createBroadcastsCollection = (pluginConfig) => {
2305
2299
  publishStatus: doc._status,
2306
2300
  hasSubject: !!doc.subject,
2307
2301
  hasContent: !!doc.contentSection?.content
2308
- });
2302
+ }, "Broadcast afterChange update hook triggered");
2309
2303
  try {
2310
2304
  const providerConfig = await getBroadcastConfig(req, pluginConfig);
2311
2305
  if (!providerConfig || !providerConfig.token) {
@@ -2392,10 +2386,10 @@ var createBroadcastsCollection = (pluginConfig) => {
2392
2386
  if (JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds)) {
2393
2387
  updates.audienceIds = doc.audienceIds?.map((a) => a.audienceId);
2394
2388
  }
2395
- req.payload.logger.info("Syncing broadcast updates to provider", {
2389
+ req.payload.logger.info({
2396
2390
  providerId: doc.providerId,
2397
2391
  updates
2398
- });
2392
+ }, "Syncing broadcast updates to provider");
2399
2393
  await provider.update(doc.providerId, updates);
2400
2394
  req.payload.logger.info(`Broadcast ${doc.id} synced to provider successfully`);
2401
2395
  } else {
@@ -2417,18 +2411,18 @@ var createBroadcastsCollection = (pluginConfig) => {
2417
2411
  ...error.statusText
2418
2412
  });
2419
2413
  } else if (typeof error === "string") {
2420
- req.payload.logger.error("Error is a string:", error);
2414
+ req.payload.logger.error({ errorValue: error }, "Error is a string");
2421
2415
  } else if (error && typeof error === "object") {
2422
- req.payload.logger.error("Error is an object:", JSON.stringify(error, null, 2));
2416
+ req.payload.logger.error({ errorValue: JSON.stringify(error, null, 2) }, "Error is an object");
2423
2417
  } else {
2424
- req.payload.logger.error("Unknown error type:", typeof error);
2418
+ req.payload.logger.error({ errorType: typeof error }, "Unknown error type");
2425
2419
  }
2426
- req.payload.logger.error("Failed broadcast document (update operation):", {
2420
+ req.payload.logger.error({
2427
2421
  id: doc.id,
2428
2422
  subject: doc.subject,
2429
2423
  hasContent: !!doc.contentSection?.content,
2430
2424
  contentType: doc.contentSection?.content ? typeof doc.contentSection.content : "none"
2431
- });
2425
+ }, "Failed broadcast document (update operation)");
2432
2426
  }
2433
2427
  }
2434
2428
  return doc;
@@ -2474,7 +2468,7 @@ var createBroadcastsCollection = (pluginConfig) => {
2474
2468
  ...error.details
2475
2469
  });
2476
2470
  } else {
2477
- req.payload.logger.error(`Failed to send broadcast ${doc.id}:`, error);
2471
+ req.payload.logger.error({ error: String(error) }, `Failed to send broadcast ${doc.id}`);
2478
2472
  }
2479
2473
  await req.payload.update({
2480
2474
  collection: "broadcasts",
@@ -2517,7 +2511,7 @@ var createBroadcastsCollection = (pluginConfig) => {
2517
2511
  ...error.details
2518
2512
  });
2519
2513
  } else {
2520
- req.payload.logger.error("Failed to delete broadcast from provider:", error);
2514
+ req.payload.logger.error({ error: String(error) }, "Failed to delete broadcast from provider");
2521
2515
  }
2522
2516
  }
2523
2517
  return doc;