payload-plugin-newsletter 0.25.8 → 0.25.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/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## [0.25.9] - 2025-08-19
2
+
3
+ ### Fixed
4
+ - Fixed providerId/externalId not being saved during broadcast creation
5
+ - Moved provider creation from create to update operation
6
+ - Provider broadcast is now created on first update when subject and content are present
7
+ - Ensures IDs are properly persisted to the database
8
+ - Prevents issues with Payload's create operation not persisting afterChange modifications
9
+
10
+ ### Changed
11
+ - Broadcasts are now created in Payload first, then synced to provider on first meaningful update
12
+ - More robust approach that works with Payload's hook lifecycle
13
+
1
14
  ## [0.25.8] - 2025-08-19
2
15
 
3
16
  ### Fixed
@@ -2306,92 +2306,18 @@ var createBroadcastsCollection = (pluginConfig) => {
2306
2306
  async ({ doc, operation, req, previousDoc }) => {
2307
2307
  if (!hasProviders) return doc;
2308
2308
  if (operation === "create") {
2309
- try {
2310
- req.payload.logger.info("Broadcast afterChange CREATE hook (sync) - doc info:", {
2311
- docId: doc.id,
2312
- docIdType: typeof doc.id,
2313
- hasDoc: !!doc,
2314
- operation,
2315
- status: doc._status,
2316
- hasExternalId: !!doc.externalId,
2317
- hasProviderId: !!doc.providerId
2318
- });
2319
- if (doc.externalId || doc.providerId) {
2320
- req.payload.logger.info("Broadcast already has provider IDs, skipping creation", {
2321
- externalId: doc.externalId,
2322
- providerId: doc.providerId
2323
- });
2324
- return doc;
2325
- }
2326
- const providerConfig = await getBroadcastConfig(req, pluginConfig);
2327
- if (!providerConfig || !providerConfig.token) {
2328
- req.payload.logger.error("Broadcast provider not configured in Newsletter Settings or environment variables");
2329
- return doc;
2330
- }
2331
- const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
2332
- const provider = new BroadcastApiProvider2(providerConfig);
2333
- const subject = doc.subject || `Draft Broadcast ${(/* @__PURE__ */ new Date()).toISOString()}`;
2334
- const htmlContent = doc.contentSection?.content ? await convertToEmailSafeHtml(
2335
- await populateMediaFields(doc.contentSection.content, req.payload, pluginConfig),
2336
- {
2337
- wrapInTemplate: pluginConfig.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,
2338
- customWrapper: pluginConfig.customizations?.broadcasts?.emailPreview?.customWrapper,
2339
- preheader: doc.contentSection?.preheader,
2340
- subject,
2341
- documentData: doc,
2342
- customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
2343
- }
2344
- ) : "<p>Draft content - to be updated</p>";
2345
- const createData = {
2346
- name: subject,
2347
- // Use subject as name
2348
- subject,
2349
- preheader: doc.contentSection?.preheader || "",
2350
- content: htmlContent,
2351
- trackOpens: doc.settings?.trackOpens ?? true,
2352
- trackClicks: doc.settings?.trackClicks ?? true,
2353
- replyTo: doc.settings?.replyTo || providerConfig.replyTo,
2354
- audienceIds: doc.audienceIds?.map((a) => a.audienceId) || []
2355
- };
2356
- req.payload.logger.info("Creating broadcast in provider with minimal data to establish association", {
2357
- subject: createData.subject,
2358
- hasActualContent: !!doc.contentSection?.content
2359
- });
2360
- const providerBroadcast = await provider.create(createData);
2361
- req.payload.logger.info("Provider broadcast created:", {
2362
- providerBroadcastId: providerBroadcast.id,
2363
- providerBroadcastIdType: typeof providerBroadcast.id,
2364
- docId: doc.id,
2365
- docIdType: typeof doc.id
2366
- });
2367
- req.payload.logger.info(`Broadcast ${doc.id} created in provider with ID ${providerBroadcast.id}`);
2368
- return {
2369
- ...doc,
2370
- providerId: providerBroadcast.id,
2371
- externalId: providerBroadcast.id,
2372
- // Include externalId in return value
2373
- providerData: providerBroadcast.providerData
2374
- };
2375
- } catch (error) {
2376
- req.payload.logger.error("Failed to create broadcast in provider during initial creation:");
2377
- if (error instanceof Error) {
2378
- req.payload.logger.error("Error details:", {
2379
- message: error.message,
2380
- stack: error.stack,
2381
- name: error.name
2382
- });
2383
- } else {
2384
- req.payload.logger.error("Raw error:", error);
2385
- }
2386
- return doc;
2387
- }
2309
+ req.payload.logger.info("Broadcast created in Payload, provider sync will happen on first update with content");
2310
+ return doc;
2388
2311
  }
2389
2312
  if (operation === "update") {
2390
2313
  req.payload.logger.info("Broadcast afterChange update hook triggered", {
2391
2314
  operation,
2392
2315
  hasProviderId: !!doc.providerId,
2316
+ hasExternalId: !!doc.externalId,
2393
2317
  sendStatus: doc.sendStatus,
2394
- publishStatus: doc._status
2318
+ publishStatus: doc._status,
2319
+ hasSubject: !!doc.subject,
2320
+ hasContent: !!doc.contentSection?.content
2395
2321
  });
2396
2322
  try {
2397
2323
  const providerConfig = await getBroadcastConfig(req, pluginConfig);
@@ -2401,8 +2327,40 @@ var createBroadcastsCollection = (pluginConfig) => {
2401
2327
  }
2402
2328
  const { BroadcastApiProvider: BroadcastApiProvider2 } = await Promise.resolve().then(() => (init_broadcast2(), broadcast_exports));
2403
2329
  const provider = new BroadcastApiProvider2(providerConfig);
2330
+ if (!doc.providerId && !doc.externalId && doc.subject && doc.contentSection?.content) {
2331
+ req.payload.logger.info("Creating broadcast in provider on first update with content");
2332
+ const htmlContent = await convertToEmailSafeHtml(
2333
+ await populateMediaFields(doc.contentSection.content, req.payload, pluginConfig),
2334
+ {
2335
+ wrapInTemplate: pluginConfig.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,
2336
+ customWrapper: pluginConfig.customizations?.broadcasts?.emailPreview?.customWrapper,
2337
+ preheader: doc.contentSection?.preheader,
2338
+ subject: doc.subject,
2339
+ documentData: doc,
2340
+ customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter
2341
+ }
2342
+ );
2343
+ const createData = {
2344
+ name: doc.subject,
2345
+ subject: doc.subject,
2346
+ preheader: doc.contentSection?.preheader || "",
2347
+ content: htmlContent,
2348
+ trackOpens: doc.settings?.trackOpens ?? true,
2349
+ trackClicks: doc.settings?.trackClicks ?? true,
2350
+ replyTo: doc.settings?.replyTo || providerConfig.replyTo,
2351
+ audienceIds: doc.audienceIds?.map((a) => a.audienceId) || []
2352
+ };
2353
+ const providerBroadcast = await provider.create(createData);
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
+ providerData: providerBroadcast.providerData
2360
+ };
2361
+ }
2404
2362
  if (!doc.providerId) {
2405
- req.payload.logger.warn(`Broadcast ${doc.id} has no providerId - provider sync skipped. This shouldn't happen with immediate creation.`);
2363
+ req.payload.logger.info(`Broadcast ${doc.id} has no providerId and insufficient content for creation - skipping sync`);
2406
2364
  return doc;
2407
2365
  }
2408
2366
  if (doc.providerId) {