payload-plugin-newsletter 0.16.7 → 0.16.9

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/dist/index.cjs CHANGED
@@ -3188,6 +3188,9 @@ var EMAIL_SAFE_CONFIG = {
3188
3188
  FORBID_ATTR: ["class", "id", "onclick", "onload", "onerror"]
3189
3189
  };
3190
3190
  async function convertToEmailSafeHtml(editorState, options) {
3191
+ if (!editorState) {
3192
+ return "";
3193
+ }
3191
3194
  const rawHtml = await lexicalToEmailHtml(editorState, options?.mediaUrl);
3192
3195
  const sanitizedHtml = import_isomorphic_dompurify2.default.sanitize(rawHtml, EMAIL_SAFE_CONFIG);
3193
3196
  if (options?.wrapInTemplate) {
@@ -4394,6 +4397,10 @@ var createBroadcastsCollection = (pluginConfig) => {
4394
4397
  async ({ doc, operation, req, previousDoc }) => {
4395
4398
  if (!hasProviders) return doc;
4396
4399
  if (operation === "create") {
4400
+ if (!doc.subject || !doc.contentSection?.content) {
4401
+ req.payload.logger.info("Skipping provider sync - broadcast has no subject or content yet");
4402
+ return doc;
4403
+ }
4397
4404
  try {
4398
4405
  const providerConfig = await getBroadcastConfig(req, pluginConfig);
4399
4406
  if (!providerConfig || !providerConfig.token) {
@@ -4404,6 +4411,10 @@ var createBroadcastsCollection = (pluginConfig) => {
4404
4411
  const provider = new BroadcastApiProvider2(providerConfig);
4405
4412
  req.payload.logger.info("Converting content to HTML...");
4406
4413
  const htmlContent = await convertToEmailSafeHtml(doc.contentSection?.content);
4414
+ if (!htmlContent || htmlContent.trim() === "") {
4415
+ req.payload.logger.info("Skipping provider sync - content is empty after conversion");
4416
+ return doc;
4417
+ }
4407
4418
  const createData = {
4408
4419
  name: doc.subject,
4409
4420
  // Use subject as name since we removed the name field
@@ -4475,7 +4486,7 @@ var createBroadcastsCollection = (pluginConfig) => {
4475
4486
  return doc;
4476
4487
  }
4477
4488
  }
4478
- if (operation === "update" && doc.providerId) {
4489
+ if (operation === "update") {
4479
4490
  req.payload.logger.info("Broadcast afterChange update hook triggered", {
4480
4491
  operation,
4481
4492
  hasProviderId: !!doc.providerId,
@@ -4490,57 +4501,135 @@ var createBroadcastsCollection = (pluginConfig) => {
4490
4501
  }
4491
4502
  const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
4492
4503
  const provider = new BroadcastApiProvider2(providerConfig);
4493
- const capabilities = provider.getCapabilities();
4494
- const sendStatus = doc.sendStatus || "draft" /* DRAFT */;
4495
- if (!capabilities.editableStatuses.includes(sendStatus)) {
4496
- req.payload.logger.info(`Skipping sync for broadcast in status: ${sendStatus}`);
4497
- return doc;
4498
- }
4499
- 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);
4500
- if (contentChanged) {
4501
- const updates = {};
4502
- if (doc.subject !== previousDoc?.subject) {
4503
- updates.name = doc.subject;
4504
- updates.subject = doc.subject;
4505
- }
4506
- if (doc.contentSection?.preheader !== previousDoc?.contentSection?.preheader) {
4507
- updates.preheader = doc.contentSection?.preheader;
4504
+ if (!doc.providerId) {
4505
+ if (!doc.subject || !doc.contentSection?.content) {
4506
+ req.payload.logger.info("Still missing required fields for provider sync");
4507
+ return doc;
4508
4508
  }
4509
- if (JSON.stringify(doc.contentSection?.content) !== JSON.stringify(previousDoc?.contentSection?.content)) {
4510
- updates.content = await convertToEmailSafeHtml(doc.contentSection?.content);
4511
- }
4512
- if (doc.settings?.trackOpens !== previousDoc?.settings?.trackOpens) {
4513
- updates.trackOpens = doc.settings.trackOpens;
4514
- }
4515
- if (doc.settings?.trackClicks !== previousDoc?.settings?.trackClicks) {
4516
- updates.trackClicks = doc.settings.trackClicks;
4509
+ try {
4510
+ req.payload.logger.info("Creating broadcast in provider (deferred from initial create)...");
4511
+ const htmlContent = await convertToEmailSafeHtml(doc.contentSection?.content);
4512
+ if (!htmlContent || htmlContent.trim() === "") {
4513
+ req.payload.logger.info("Skipping provider sync - content is empty after conversion");
4514
+ return doc;
4515
+ }
4516
+ const createData = {
4517
+ name: doc.subject,
4518
+ subject: doc.subject,
4519
+ preheader: doc.contentSection?.preheader,
4520
+ content: htmlContent,
4521
+ trackOpens: doc.settings?.trackOpens,
4522
+ trackClicks: doc.settings?.trackClicks,
4523
+ replyTo: doc.settings?.replyTo || providerConfig.replyTo,
4524
+ audienceIds: doc.audienceIds?.map((a) => a.audienceId)
4525
+ };
4526
+ req.payload.logger.info("Creating broadcast with data:", {
4527
+ name: createData.name,
4528
+ subject: createData.subject,
4529
+ preheader: createData.preheader || "NONE",
4530
+ contentLength: htmlContent ? htmlContent.length : 0,
4531
+ contentPreview: htmlContent ? htmlContent.substring(0, 100) + "..." : "EMPTY",
4532
+ apiUrl: providerConfig.apiUrl,
4533
+ hasToken: !!providerConfig.token
4534
+ });
4535
+ const providerBroadcast = await provider.create(createData);
4536
+ await req.payload.update({
4537
+ collection: "broadcasts",
4538
+ id: doc.id,
4539
+ data: {
4540
+ providerId: providerBroadcast.id,
4541
+ providerData: providerBroadcast.providerData
4542
+ },
4543
+ req
4544
+ });
4545
+ req.payload.logger.info(`Broadcast ${doc.id} created in provider successfully (deferred)`);
4546
+ return {
4547
+ ...doc,
4548
+ providerId: providerBroadcast.id,
4549
+ providerData: providerBroadcast.providerData
4550
+ };
4551
+ } catch (error) {
4552
+ req.payload.logger.error("Raw error from broadcast provider (deferred create):");
4553
+ req.payload.logger.error(error);
4554
+ if (error instanceof Error) {
4555
+ req.payload.logger.error("Error is instance of Error:", {
4556
+ message: error.message,
4557
+ stack: error.stack,
4558
+ name: error.name,
4559
+ ...error.details,
4560
+ ...error.response,
4561
+ ...error.data,
4562
+ ...error.status,
4563
+ ...error.statusText
4564
+ });
4565
+ } else if (typeof error === "string") {
4566
+ req.payload.logger.error("Error is a string:", error);
4567
+ } else if (error && typeof error === "object") {
4568
+ req.payload.logger.error("Error is an object:", JSON.stringify(error, null, 2));
4569
+ } else {
4570
+ req.payload.logger.error("Unknown error type:", typeof error);
4571
+ }
4572
+ req.payload.logger.error("Failed broadcast document (deferred create):", {
4573
+ id: doc.id,
4574
+ subject: doc.subject,
4575
+ hasContent: !!doc.contentSection?.content,
4576
+ contentType: doc.contentSection?.content ? typeof doc.contentSection.content : "none"
4577
+ });
4578
+ return doc;
4517
4579
  }
4518
- if (doc.settings?.replyTo !== previousDoc?.settings?.replyTo) {
4519
- updates.replyTo = doc.settings.replyTo || providerConfig.replyTo;
4580
+ }
4581
+ if (doc.providerId) {
4582
+ const capabilities = provider.getCapabilities();
4583
+ const sendStatus = doc.sendStatus || "draft" /* DRAFT */;
4584
+ if (!capabilities.editableStatuses.includes(sendStatus)) {
4585
+ req.payload.logger.info(`Skipping sync for broadcast in status: ${sendStatus}`);
4586
+ return doc;
4520
4587
  }
4521
- if (JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds)) {
4522
- updates.audienceIds = doc.audienceIds?.map((a) => a.audienceId);
4588
+ 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);
4589
+ if (contentChanged) {
4590
+ const updates = {};
4591
+ if (doc.subject !== previousDoc?.subject) {
4592
+ updates.name = doc.subject;
4593
+ updates.subject = doc.subject;
4594
+ }
4595
+ if (doc.contentSection?.preheader !== previousDoc?.contentSection?.preheader) {
4596
+ updates.preheader = doc.contentSection?.preheader;
4597
+ }
4598
+ if (JSON.stringify(doc.contentSection?.content) !== JSON.stringify(previousDoc?.contentSection?.content)) {
4599
+ updates.content = await convertToEmailSafeHtml(doc.contentSection?.content);
4600
+ }
4601
+ if (doc.settings?.trackOpens !== previousDoc?.settings?.trackOpens) {
4602
+ updates.trackOpens = doc.settings.trackOpens;
4603
+ }
4604
+ if (doc.settings?.trackClicks !== previousDoc?.settings?.trackClicks) {
4605
+ updates.trackClicks = doc.settings.trackClicks;
4606
+ }
4607
+ if (doc.settings?.replyTo !== previousDoc?.settings?.replyTo) {
4608
+ updates.replyTo = doc.settings.replyTo || providerConfig.replyTo;
4609
+ }
4610
+ if (JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds)) {
4611
+ updates.audienceIds = doc.audienceIds?.map((a) => a.audienceId);
4612
+ }
4613
+ req.payload.logger.info("Syncing broadcast updates to provider", {
4614
+ providerId: doc.providerId,
4615
+ updates
4616
+ });
4617
+ await provider.update(doc.providerId, updates);
4618
+ req.payload.logger.info(`Broadcast ${doc.id} synced to provider successfully`);
4619
+ } else {
4620
+ req.payload.logger.info("No content changes to sync to provider");
4523
4621
  }
4524
- req.payload.logger.info("Syncing broadcast updates to provider", {
4525
- providerId: doc.providerId,
4526
- updates
4527
- });
4528
- await provider.update(doc.providerId, updates);
4529
- req.payload.logger.info(`Broadcast ${doc.id} synced to provider successfully`);
4530
- } else {
4531
- req.payload.logger.info("No content changes to sync to provider");
4532
4622
  }
4533
4623
  } catch (error) {
4534
4624
  if (error instanceof Error) {
4535
- req.payload.logger.error("Failed to sync broadcast update to provider:", {
4625
+ req.payload.logger.error("Failed to handle broadcast update operation:", {
4536
4626
  message: error.message,
4537
4627
  stack: error.stack,
4538
4628
  name: error.name,
4539
- // If it's a BroadcastProviderError, it might have additional details
4540
4629
  ...error.details
4541
4630
  });
4542
4631
  } else {
4543
- req.payload.logger.error("Failed to sync broadcast update to provider:", error);
4632
+ req.payload.logger.error("Failed to handle broadcast update operation:", error);
4544
4633
  }
4545
4634
  }
4546
4635
  }