{"version":3,"sources":["../src/types/newsletter.ts","../src/types/broadcast.ts","../src/types/providers.ts","../src/types/index.ts","../src/providers/broadcast/broadcast.ts","../src/exports/collections.ts","../src/collections/Broadcasts.ts","../src/fields/emailContent.ts","../src/utils/blockValidation.ts","../src/fields/broadcastInlinePreview.ts","../src/fields/broadcastSchedule.ts","../src/utils/emailSafeHtml.ts","../src/utils/getBroadcastConfig.ts","../src/utils/getProvider.ts","../src/utils/mediaPopulation.ts","../src/endpoints/broadcasts/preview.ts","../src/utils/getErrorMessage.ts","../src/utils/broadcast-sync.ts","../src/utils/scheduling-state.ts","../src/utils/idempotency.ts","../src/endpoints/broadcasts/send.ts","../src/utils/access.ts","../src/utils/auth.ts","../src/endpoints/broadcasts/schedule.ts","../src/endpoints/broadcasts/retry-sync.ts","../src/endpoints/broadcasts/test.ts","../src/emails/render.tsx","../src/emails/MagicLink.tsx","../src/emails/styles.ts","../src/emails/Welcome.tsx","../src/emails/SignIn.tsx","../src/collections/Subscribers.ts"],"sourcesContent":["/**\n * Core types for newsletter management functionality\n */\n\n/**\n * Represents a newsletter/broadcast in the system\n */\nexport interface Newsletter {\n  id: string;\n  name: string;\n  subject: string;\n  preheader?: string;\n  content: string; // HTML content\n  status: NewsletterStatus;\n  trackOpens: boolean;\n  trackClicks: boolean;\n  replyTo?: string;\n  recipientCount?: number;\n  sentAt?: Date;\n  scheduledAt?: Date;\n  createdAt: Date;\n  updatedAt: Date;\n  // Provider-specific data stored here\n  providerData?: Record<string, any>;\n  // Provider information\n  providerId?: string;\n  providerType?: 'broadcast' | 'resend';\n}\n\n/**\n * Possible statuses for a newsletter\n */\nexport enum NewsletterStatus {\n  DRAFT = 'draft',\n  SCHEDULED = 'scheduled',\n  SENDING = 'sending',\n  SENT = 'sent',\n  FAILED = 'failed',\n  PAUSED = 'paused',\n  CANCELED = 'canceled'\n}\n\n/**\n * Options for listing newsletters\n */\nexport interface ListNewsletterOptions {\n  limit?: number;\n  offset?: number;\n  status?: NewsletterStatus;\n  sortBy?: 'createdAt' | 'updatedAt' | 'sentAt' | 'name';\n  sortOrder?: 'asc' | 'desc';\n}\n\n/**\n * Response from listing newsletters\n */\nexport interface ListNewsletterResponse<T = Newsletter> {\n  items: T[];\n  total: number;\n  limit: number;\n  offset: number;\n  hasMore: boolean;\n}\n\n/**\n * Input for creating a new newsletter\n */\nexport interface CreateNewsletterInput {\n  name: string;\n  subject: string;\n  preheader?: string;\n  content: string;\n  trackOpens?: boolean;\n  trackClicks?: boolean;\n  replyTo?: string;\n  audienceIds?: string[]; // Maps to segments/audiences\n}\n\n/**\n * Input for updating an existing newsletter\n */\nexport interface UpdateNewsletterInput {\n  name?: string;\n  subject?: string;\n  preheader?: string;\n  content?: string;\n  trackOpens?: boolean;\n  trackClicks?: boolean;\n  replyTo?: string;\n  audienceIds?: string[];\n}\n\n/**\n * Options for sending a newsletter\n */\nexport interface SendNewsletterOptions {\n  audienceIds?: string[]; // Target specific audiences\n  testMode?: boolean; // Send test email\n  testRecipients?: string[]; // Email addresses for test send\n}\n\n/**\n * Analytics data for a newsletter\n */\nexport interface NewsletterAnalytics {\n  sent: number;\n  delivered: number;\n  opened: number;\n  clicked: number;\n  bounced: number;\n  complained: number;\n  unsubscribed: number;\n  deliveryRate?: number;\n  openRate?: number;\n  clickRate?: number;\n  bounceRate?: number;\n}\n\n/**\n * Capabilities that a newsletter provider supports\n */\nexport interface NewsletterProviderCapabilities {\n  supportsScheduling: boolean;\n  supportsSegmentation: boolean;\n  supportsAnalytics: boolean;\n  supportsABTesting: boolean;\n  supportsTemplates: boolean;\n  supportsPersonalization: boolean;\n  maxRecipientsPerSend?: number;\n  editableStatuses: NewsletterStatus[];\n  supportedContentTypes: ('html' | 'text' | 'react')[];\n}\n\n/**\n * Error types specific to newsletter operations\n */\nexport class NewsletterProviderError extends Error {\n  constructor(\n    message: string,\n    public code: NewsletterErrorCode,\n    public provider: string,\n    public details?: any\n  ) {\n    super(message);\n    this.name = 'NewsletterProviderError';\n  }\n}\n\nexport enum NewsletterErrorCode {\n  NOT_SUPPORTED = 'NOT_SUPPORTED',\n  INVALID_STATUS = 'INVALID_STATUS',\n  PROVIDER_ERROR = 'PROVIDER_ERROR',\n  VALIDATION_ERROR = 'VALIDATION_ERROR',\n  NOT_FOUND = 'NOT_FOUND',\n  PERMISSION_DENIED = 'PERMISSION_DENIED',\n  RATE_LIMITED = 'RATE_LIMITED',\n  CONFIGURATION_ERROR = 'CONFIGURATION_ERROR'\n}\n\n/**\n * Newsletter template for reusable content\n */\nexport interface NewsletterTemplate {\n  id: string;\n  name: string;\n  description?: string;\n  content: string;\n  variables?: NewsletterTemplateVariable[];\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport interface NewsletterTemplateVariable {\n  name: string;\n  type: 'text' | 'html' | 'image' | 'url';\n  defaultValue?: string;\n  required?: boolean;\n}","/**\n * Core types for broadcast management functionality\n */\n\n/**\n * Represents a broadcast (individual email campaign) in the system\n */\nexport interface Broadcast {\n  id: string;\n  name: string;\n  subject: string;\n  preheader?: string;\n  content: string; // HTML content\n  sendStatus: BroadcastStatus;\n  trackOpens: boolean;\n  trackClicks: boolean;\n  replyTo?: string;\n  recipientCount?: number;\n  sentAt?: Date;\n  scheduledAt?: Date;\n  createdAt: Date;\n  updatedAt: Date;\n  // Provider-specific data stored here\n  providerData?: Record<string, any>;\n  // Provider information\n  providerId?: string;\n  providerType?: 'broadcast' | 'resend';\n}\n\n/**\n * Possible statuses for a broadcast\n */\nexport enum BroadcastStatus {\n  DRAFT = 'draft',\n  SCHEDULED = 'scheduled',\n  SENDING = 'sending',\n  SENT = 'sent',\n  FAILED = 'failed',\n  PAUSED = 'paused',\n  CANCELED = 'canceled'\n}\n\n/**\n * Options for listing broadcasts\n */\nexport interface ListBroadcastOptions {\n  limit?: number;\n  offset?: number;\n  status?: BroadcastStatus;\n  sortBy?: 'createdAt' | 'updatedAt' | 'sentAt' | 'name';\n  sortOrder?: 'asc' | 'desc';\n}\n\n/**\n * Response from listing broadcasts\n */\nexport interface ListBroadcastResponse<T = Broadcast> {\n  items: T[];\n  total: number;\n  limit: number;\n  offset: number;\n  hasMore: boolean;\n}\n\n/**\n * Input for creating a new broadcast\n */\nexport interface CreateBroadcastInput {\n  name: string;\n  subject: string;\n  preheader?: string;\n  content: string;\n  trackOpens?: boolean;\n  trackClicks?: boolean;\n  replyTo?: string;\n  audienceIds?: string[]; // Maps to segments/audiences\n}\n\n/**\n * Input for updating an existing broadcast\n */\nexport interface UpdateBroadcastInput {\n  name?: string;\n  subject?: string;\n  preheader?: string;\n  content?: string;\n  trackOpens?: boolean;\n  trackClicks?: boolean;\n  replyTo?: string;\n  audienceIds?: string[];\n}\n\n/**\n * Options for sending a broadcast\n */\nexport interface SendBroadcastOptions {\n  audienceIds?: string[]; // Target specific audiences\n  testMode?: boolean; // Send test email\n  testRecipients?: string[]; // Email addresses for test send\n}\n\n/**\n * Analytics data for a broadcast\n */\nexport interface BroadcastAnalytics {\n  sent: number;\n  delivered: number;\n  opened: number;\n  clicked: number;\n  bounced: number;\n  complained: number;\n  unsubscribed: number;\n  deliveryRate?: number;\n  openRate?: number;\n  clickRate?: number;\n  bounceRate?: number;\n}\n\n/**\n * Capabilities that a broadcast provider supports\n */\nexport interface BroadcastProviderCapabilities {\n  supportsScheduling: boolean;\n  supportsSegmentation: boolean;\n  supportsAnalytics: boolean;\n  supportsABTesting: boolean;\n  supportsTemplates: boolean;\n  supportsPersonalization: boolean;\n  maxRecipientsPerSend?: number;\n  editableStatuses: BroadcastStatus[];\n  supportedContentTypes: ('html' | 'text' | 'react')[];\n  supportsMultipleChannels: boolean;\n  supportsChannelSegmentation: boolean;\n}\n\n/**\n * Error types specific to broadcast operations\n */\nexport class BroadcastProviderError extends Error {\n  constructor(\n    message: string,\n    public code: BroadcastErrorCode,\n    public provider: string,\n    public details?: any\n  ) {\n    super(message);\n    this.name = 'BroadcastProviderError';\n  }\n}\n\nexport enum BroadcastErrorCode {\n  NOT_SUPPORTED = 'NOT_SUPPORTED',\n  INVALID_STATUS = 'INVALID_STATUS',\n  PROVIDER_ERROR = 'PROVIDER_ERROR',\n  VALIDATION_ERROR = 'VALIDATION_ERROR',\n  NOT_FOUND = 'NOT_FOUND',\n  PERMISSION_DENIED = 'PERMISSION_DENIED',\n  RATE_LIMITED = 'RATE_LIMITED',\n  CONFIGURATION_ERROR = 'CONFIGURATION_ERROR'\n}\n\n/**\n * Broadcast template for reusable content\n */\nexport interface BroadcastTemplate {\n  id: string;\n  name: string;\n  description?: string;\n  content: string;\n  variables?: BroadcastTemplateVariable[];\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport interface BroadcastTemplateVariable {\n  name: string;\n  type: 'text' | 'html' | 'image' | 'url';\n  defaultValue?: string;\n  required?: boolean;\n}\n\n/**\n * Audience ID field structure used in broadcast documents\n */\nexport interface AudienceIdField {\n  audienceId: string;\n}\n\n/**\n * Data required for creating a broadcast in the provider\n */\nexport interface ProviderCreateData {\n  name: string;\n  subject: string;\n  preheader: string;\n  content: string;\n  trackOpens: boolean;\n  trackClicks: boolean;\n  replyTo?: string;\n  audienceIds: string[];\n}\n\n/**\n * Result from syncing a broadcast to the provider (discriminated union)\n */\nexport type ProviderSyncResult = {\n  success: true;\n  providerId: string;\n  externalId: string;\n  providerData: unknown;\n} | {\n  success: false;\n  error: string;\n}\n\n/**\n * Document shape for broadcast in afterChange hook\n */\nexport interface BroadcastDocument {\n  id: string;\n  subject?: string | null;\n  contentSection?: {\n    content?: unknown;\n    preheader?: string;\n  } | null;\n  settings?: {\n    trackOpens?: boolean;\n    trackClicks?: boolean;\n    replyTo?: string;\n  };\n  audienceIds?: AudienceIdField[];\n  providerId?: string | null;\n  externalId?: string | null;\n  providerData?: unknown;\n  providerSyncStatus?: 'pending' | 'synced' | 'failed';\n  providerSyncError?: string | null;\n}\n\n// Re-export newsletter types with deprecation notice for backwards compatibility\nexport {\n  NewsletterStatus,\n  type ListNewsletterOptions,\n  type ListNewsletterResponse,\n  type CreateNewsletterInput,\n  type UpdateNewsletterInput,\n  type SendNewsletterOptions,\n  type NewsletterAnalytics,\n  type NewsletterProviderCapabilities,\n  NewsletterProviderError,\n  NewsletterErrorCode,\n  type NewsletterTemplate,\n  type NewsletterTemplateVariable\n} from './newsletter';","/**\n * Provider interfaces for broadcast management\n */\n\n// Import broadcast types\nimport type {\n  Broadcast,\n  BroadcastStatus,\n  ListBroadcastOptions,\n  ListBroadcastResponse,\n  CreateBroadcastInput,\n  UpdateBroadcastInput,\n  SendBroadcastOptions,\n  BroadcastAnalytics,\n  BroadcastProviderCapabilities\n} from './broadcast'\n\nimport {\n  BroadcastProviderError,\n  BroadcastErrorCode\n} from './broadcast'\n\n\n// Import legacy newsletter types for backwards compatibility\nimport type {\n  Newsletter,\n  NewsletterStatus,\n  ListNewsletterOptions,\n  ListNewsletterResponse,\n  CreateNewsletterInput,\n  UpdateNewsletterInput,\n  SendNewsletterOptions,\n  NewsletterAnalytics,\n  NewsletterProviderCapabilities\n} from './newsletter'\n\nimport {\n  NewsletterProviderError,\n  NewsletterErrorCode\n} from './newsletter'\n\n/**\n * Main interface for broadcast providers\n */\nexport interface BroadcastProvider {\n  /**\n   * Get the provider name\n   */\n  readonly name: string;\n\n  // Broadcast management methods\n  /**\n   * List broadcasts with pagination\n   */\n  list(options?: ListBroadcastOptions): Promise<ListBroadcastResponse<Broadcast>>;\n  \n  /**\n   * Get a specific broadcast by ID\n   */\n  get(id: string): Promise<Broadcast>;\n  \n  /**\n   * Create a new broadcast\n   */\n  create(data: CreateBroadcastInput): Promise<Broadcast>;\n  \n  /**\n   * Update an existing broadcast\n   */\n  update(id: string, data: UpdateBroadcastInput): Promise<Broadcast>;\n  \n  /**\n   * Delete a broadcast\n   */\n  delete(id: string): Promise<void>;\n  \n  /**\n   * Send a broadcast immediately or to test recipients\n   */\n  send(id: string, options?: SendBroadcastOptions): Promise<Broadcast>;\n  \n  /**\n   * Schedule a broadcast for future sending\n   */\n  schedule(id: string, scheduledAt: Date): Promise<Broadcast>;\n  \n  /**\n   * Cancel a scheduled broadcast\n   */\n  cancelSchedule(id: string): Promise<Broadcast>;\n  \n  /**\n   * Get analytics for a broadcast\n   */\n  getAnalytics(id: string): Promise<BroadcastAnalytics>;\n  \n  /**\n   * Get provider capabilities\n   */\n  getCapabilities(): BroadcastProviderCapabilities;\n  \n  /**\n   * Validate that the provider is properly configured\n   */\n  validateConfiguration(): Promise<boolean>;\n}\n\n/**\n * Legacy newsletter provider interface for backwards compatibility\n * @deprecated Use BroadcastProvider instead\n */\nexport interface NewsletterProvider {\n  /**\n   * Get the provider name\n   */\n  readonly name: string;\n\n  /**\n   * List newsletters with pagination\n   */\n  list(options?: ListNewsletterOptions): Promise<ListNewsletterResponse<Newsletter>>;\n  \n  /**\n   * Get a specific newsletter by ID\n   */\n  get(id: string): Promise<Newsletter>;\n  \n  /**\n   * Create a new newsletter\n   */\n  create(data: CreateNewsletterInput): Promise<Newsletter>;\n  \n  /**\n   * Update an existing newsletter\n   */\n  update(id: string, data: UpdateNewsletterInput): Promise<Newsletter>;\n  \n  /**\n   * Delete a newsletter\n   */\n  delete(id: string): Promise<void>;\n  \n  /**\n   * Send a newsletter immediately or to test recipients\n   */\n  send(id: string, options?: SendNewsletterOptions): Promise<Newsletter>;\n  \n  /**\n   * Schedule a newsletter for future sending\n   */\n  schedule(id: string, scheduledAt: Date): Promise<Newsletter>;\n  \n  /**\n   * Cancel a scheduled newsletter\n   */\n  cancelSchedule(id: string): Promise<Newsletter>;\n  \n  /**\n   * Get analytics for a newsletter\n   */\n  getAnalytics(id: string): Promise<NewsletterAnalytics>;\n  \n  /**\n   * Get provider capabilities\n   */\n  getCapabilities(): NewsletterProviderCapabilities;\n  \n  /**\n   * Validate that the provider is properly configured\n   */\n  validateConfiguration(): Promise<boolean>;\n}\n\n/**\n * Base abstract class for broadcast providers\n */\nexport abstract class BaseBroadcastProvider implements BroadcastProvider {\n  abstract readonly name: string;\n  \n  constructor(protected config: any) {}\n  \n  // Broadcast management - abstract methods\n  abstract list(options?: ListBroadcastOptions): Promise<ListBroadcastResponse<Broadcast>>;\n  abstract get(id: string): Promise<Broadcast>;\n  abstract create(data: CreateBroadcastInput): Promise<Broadcast>;\n  abstract update(id: string, data: UpdateBroadcastInput): Promise<Broadcast>;\n  abstract delete(id: string): Promise<void>;\n  abstract send(id: string, options?: SendBroadcastOptions): Promise<Broadcast>;\n  abstract getCapabilities(): BroadcastProviderCapabilities;\n  abstract validateConfiguration(): Promise<boolean>;\n  \n  /**\n   * Schedule a broadcast - default implementation throws not supported\n   */\n  async schedule(_id: string, _scheduledAt: Date): Promise<Broadcast> {\n    const capabilities = this.getCapabilities();\n    if (!capabilities.supportsScheduling) {\n      throw new BroadcastProviderError(\n        'Scheduling is not supported by this provider',\n        BroadcastErrorCode.NOT_SUPPORTED,\n        this.name\n      );\n    }\n    throw new Error('Method not implemented');\n  }\n  \n  /**\n   * Cancel scheduled broadcast - default implementation throws not supported\n   */\n  async cancelSchedule(_id: string): Promise<Broadcast> {\n    const capabilities = this.getCapabilities();\n    if (!capabilities.supportsScheduling) {\n      throw new BroadcastProviderError(\n        'Scheduling is not supported by this provider',\n        BroadcastErrorCode.NOT_SUPPORTED,\n        this.name\n      );\n    }\n    throw new Error('Method not implemented');\n  }\n  \n  /**\n   * Get analytics - default implementation returns zeros\n   */\n  async getAnalytics(_id: string): Promise<BroadcastAnalytics> {\n    const capabilities = this.getCapabilities();\n    if (!capabilities.supportsAnalytics) {\n      throw new BroadcastProviderError(\n        'Analytics are not supported by this provider',\n        BroadcastErrorCode.NOT_SUPPORTED,\n        this.name\n      );\n    }\n    \n    return {\n      sent: 0,\n      delivered: 0,\n      opened: 0,\n      clicked: 0,\n      bounced: 0,\n      complained: 0,\n      unsubscribed: 0\n    };\n  }\n  \n  /**\n   * Helper method to validate required fields\n   */\n  protected validateRequiredFields(data: any, fields: string[]): void {\n    const missing = fields.filter(field => !data[field]);\n    if (missing.length > 0) {\n      throw new BroadcastProviderError(\n        `Missing required fields: ${missing.join(', ')}`,\n        BroadcastErrorCode.VALIDATION_ERROR,\n        this.name\n      );\n    }\n  }\n  \n  /**\n   * Helper method to check if a status transition is allowed\n   */\n  protected canEditInStatus(status: BroadcastStatus): boolean {\n    const capabilities = this.getCapabilities();\n    return capabilities.editableStatuses.includes(status);\n  }\n  \n  /**\n   * Helper to build pagination response\n   */\n  protected buildListResponse<T>(\n    items: T[],\n    total: number,\n    options: ListBroadcastOptions = {}\n  ): ListBroadcastResponse<T> {\n    const limit = options.limit || 20;\n    const offset = options.offset || 0;\n    \n    return {\n      items,\n      total,\n      limit,\n      offset,\n      hasMore: offset + items.length < total\n    };\n  }\n}\n\n/**\n * Base abstract class for newsletter providers\n * @deprecated Use BaseBroadcastProvider instead\n */\nexport abstract class BaseNewsletterProvider implements NewsletterProvider {\n  abstract readonly name: string;\n  \n  constructor(protected config: any) {}\n  \n  abstract list(options?: ListNewsletterOptions): Promise<ListNewsletterResponse<Newsletter>>;\n  abstract get(id: string): Promise<Newsletter>;\n  abstract create(data: CreateNewsletterInput): Promise<Newsletter>;\n  abstract update(id: string, data: UpdateNewsletterInput): Promise<Newsletter>;\n  abstract delete(id: string): Promise<void>;\n  abstract send(id: string, options?: SendNewsletterOptions): Promise<Newsletter>;\n  abstract getCapabilities(): NewsletterProviderCapabilities;\n  abstract validateConfiguration(): Promise<boolean>;\n  \n  /**\n   * Schedule a newsletter - default implementation throws not supported\n   */\n  async schedule(_id: string, _scheduledAt: Date): Promise<Newsletter> {\n    const capabilities = this.getCapabilities();\n    if (!capabilities.supportsScheduling) {\n      throw new NewsletterProviderError(\n        'Scheduling is not supported by this provider',\n        NewsletterErrorCode.NOT_SUPPORTED,\n        this.name\n      );\n    }\n    throw new Error('Method not implemented');\n  }\n  \n  /**\n   * Cancel scheduled newsletter - default implementation throws not supported\n   */\n  async cancelSchedule(_id: string): Promise<Newsletter> {\n    const capabilities = this.getCapabilities();\n    if (!capabilities.supportsScheduling) {\n      throw new NewsletterProviderError(\n        'Scheduling is not supported by this provider',\n        NewsletterErrorCode.NOT_SUPPORTED,\n        this.name\n      );\n    }\n    throw new Error('Method not implemented');\n  }\n  \n  /**\n   * Get analytics - default implementation returns zeros\n   */\n  async getAnalytics(_id: string): Promise<NewsletterAnalytics> {\n    const capabilities = this.getCapabilities();\n    if (!capabilities.supportsAnalytics) {\n      throw new NewsletterProviderError(\n        'Analytics are not supported by this provider',\n        NewsletterErrorCode.NOT_SUPPORTED,\n        this.name\n      );\n    }\n    \n    return {\n      sent: 0,\n      delivered: 0,\n      opened: 0,\n      clicked: 0,\n      bounced: 0,\n      complained: 0,\n      unsubscribed: 0\n    };\n  }\n  \n  /**\n   * Helper method to validate required fields\n   */\n  protected validateRequiredFields(data: any, fields: string[]): void {\n    const missing = fields.filter(field => !data[field]);\n    if (missing.length > 0) {\n      throw new NewsletterProviderError(\n        `Missing required fields: ${missing.join(', ')}`,\n        NewsletterErrorCode.VALIDATION_ERROR,\n        this.name\n      );\n    }\n  }\n  \n  /**\n   * Helper method to check if a status transition is allowed\n   */\n  protected canEditInStatus(status: NewsletterStatus): boolean {\n    const capabilities = this.getCapabilities();\n    return capabilities.editableStatuses.includes(status);\n  }\n  \n  /**\n   * Helper to build pagination response\n   */\n  protected buildListResponse<T>(\n    items: T[],\n    total: number,\n    options: ListNewsletterOptions = {}\n  ): ListNewsletterResponse<T> {\n    const limit = options.limit || 20;\n    const offset = options.offset || 0;\n    \n    return {\n      items,\n      total,\n      limit,\n      offset,\n      hasMore: offset + items.length < total\n    };\n  }\n}","import type { Field, Block, RichTextField } from 'payload'\nimport type { BroadcastProvider } from './providers'\n\n// Export broadcast types\nexport * from './broadcast'\nexport * from './providers'\n// Export legacy newsletter types for backwards compatibility\nexport * from './newsletter'\n\n// Email wrapper options interface\nexport interface EmailWrapperOptions {\n  preheader?: string\n  subject?: string\n  documentData?: Record<string, any> // Generic document data\n}\n\n// Re-export for convenience\nexport type CustomEmailWrapper = (\n  content: string, \n  options?: EmailWrapperOptions\n) => string | Promise<string>\n\n// Add new interface for broadcast customizations\nexport interface BroadcastCustomizations {\n  additionalFields?: Field[]\n  customBlocks?: Block[]\n  fieldOverrides?: {\n    content?: (defaultField: RichTextField) => RichTextField\n  }\n  /**\n   * Custom block email converter\n   * @param node - The block node from Lexical editor state\n   * @param mediaUrl - Base URL for media files\n   * @returns Promise<string> - The email-safe HTML for the block\n   */\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n  \n  /**\n   * Fields to populate in custom blocks before email conversion\n   * Can be an array of field names or a function that returns field names based on block type\n   * This is useful for upload fields that need to be populated with full media objects\n   * \n   * @example\n   * // Array of field names to always populate\n   * populateFields: ['bannerImage', 'sponsorLogo']\n   * \n   * @example\n   * // Function to return fields based on block type\n   * populateFields: (blockType) => {\n   *   if (blockType === 'newsletter-hero') return ['bannerImage', 'sponsorLogo']\n   *   if (blockType === 'content-section') return ['featuredImage']\n   *   return []\n   * }\n   */\n  populateFields?: string[] | ((blockType: string) => string[])\n  \n  /**\n   * Email preview customization options\n   */\n  emailPreview?: {\n    /**\n     * Whether to wrap preview content in default email template\n     * @default true\n     */\n    wrapInTemplate?: boolean\n    \n    /**\n     * Custom wrapper function for preview content\n     * Receives the converted HTML and should return wrapped HTML\n     */\n    customWrapper?: (content: string, options?: EmailWrapperOptions) => string | Promise<string>\n    \n    /**\n     * Custom preview component to replace the default one entirely\n     * If provided, this component will be used instead of the default EmailPreview\n     */\n    customPreviewComponent?: string // Path to custom component for import map\n  }\n}\n\nexport interface NewsletterPluginConfig {\n  /**\n   * Enable or disable the plugin\n   * @default true\n   */\n  enabled?: boolean\n\n  /**\n   * Slug for the subscribers collection\n   * @default 'subscribers'\n   */\n  subscribersSlug?: string\n  \n  /**\n   * Slug for the newsletter settings global\n   * @default 'newsletter-settings'\n   */\n  settingsSlug?: string\n\n  /**\n   * Authentication configuration for magic links\n   */\n  auth?: {\n    /**\n     * Enable magic link authentication\n     * @default true\n     */\n    enabled?: boolean\n    \n    /**\n     * Token expiration time\n     * @default '7d'\n     */\n    tokenExpiration?: string\n    \n    /**\n     * Path where magic link redirects\n     * @default '/newsletter/verify'\n     */\n    magicLinkPath?: string\n    \n    /**\n     * Allow unsubscribed users to sign in\n     * @default false\n     */\n    allowUnsubscribedSignin?: boolean\n    \n    /**\n     * Allow unsubscribed users to resubscribe\n     * @default false\n     */\n    allowResubscribe?: boolean\n  }\n\n  /**\n   * Access control configuration\n   */\n  access?: {\n    /**\n     * Custom function to determine if a user is an admin\n     * @param user - The authenticated user object\n     * @returns true if the user should have admin access\n     */\n    isAdmin?: (user: any) => boolean\n  }\n\n  /**\n   * Email provider configuration\n   */\n  providers: {\n    /**\n     * Default provider to use\n     */\n    default: 'resend' | 'broadcast' | string\n    \n    /**\n     * Resend provider configuration\n     */\n    resend?: ResendProviderConfig\n    \n    /**\n     * Broadcast provider configuration\n     */\n    broadcast?: BroadcastProviderConfig\n  }\n\n  /**\n   * Field customization options\n   */\n  fields?: {\n    /**\n     * Override default fields\n     */\n    overrides?: (args: { defaultFields: Field[] }) => Field[]\n    \n    /**\n     * Additional custom fields\n     */\n    additional?: Field[]\n  }\n\n  /**\n   * Email template components\n   */\n  templates?: {\n    /**\n     * Welcome email template\n     */\n    welcome?: React.ComponentType<WelcomeEmailProps>\n    \n    /**\n     * Magic link email template\n     */\n    magicLink?: React.ComponentType<MagicLinkEmailProps>\n  }\n\n  /**\n   * Plugin hooks\n   */\n  hooks?: {\n    beforeSubscribe?: (args: BeforeSubscribeArgs) => void | Promise<void>\n    afterSubscribe?: (args: AfterSubscribeArgs) => void | Promise<void>\n    beforeUnsubscribe?: (args: BeforeUnsubscribeArgs) => void | Promise<void>\n    afterUnsubscribe?: (args: AfterUnsubscribeArgs) => void | Promise<void>\n  }\n\n  /**\n   * UI component overrides\n   */\n  components?: {\n    signupForm?: React.ComponentType<SignupFormProps>\n    preferencesForm?: React.ComponentType<PreferencesFormProps>\n  }\n\n  /**\n   * Feature flags\n   */\n  features?: {\n    /**\n     * Lead magnet configuration\n     */\n    leadMagnets?: {\n      enabled?: boolean\n      collection?: string\n    }\n    \n    /**\n     * Post-signup survey configuration\n     */\n    surveys?: {\n      enabled?: boolean\n      questions?: SurveyQuestion[]\n    }\n    \n    /**\n     * UTM tracking configuration\n     */\n    utmTracking?: {\n      enabled?: boolean\n      fields?: string[]\n    }\n    \n    /**\n     * Newsletter scheduling configuration\n     */\n    newsletterScheduling?: {\n      enabled?: boolean\n      /**\n       * Collections to add newsletter fields to\n       * Can be a string for single collection or array for multiple\n       * @example 'articles' or ['articles', 'posts', 'updates']\n       */\n      collections?: string | string[]\n      /**\n       * Field configuration\n       */\n      fields?: {\n        /**\n         * Group name for newsletter fields\n         * @default 'newsletterScheduling'\n         */\n        groupName?: string\n        /**\n         * Rich text field name to use for content\n         * @default 'content'\n         */\n        contentField?: string\n        /**\n         * Whether to create a markdown companion field\n         * @default true\n         */\n        createMarkdownField?: boolean\n      }\n    }\n    \n    \n    /**\n     * Newsletter management configuration\n     */\n    newsletterManagement?: {\n      /**\n       * Enable newsletter management features\n       * @default false\n       */\n      enabled?: boolean\n      /**\n       * Collection names for broadcast management\n       */\n      collections?: {\n        /**\n         * Broadcasts collection slug\n         * @default 'broadcasts'\n         */\n        broadcasts?: string\n      }\n      /**\n       * Optional: Custom broadcast provider implementation\n       * If not provided, will use the default email provider\n       */\n      provider?: BroadcastProvider\n    }\n  }\n\n  /**\n   * Internationalization configuration\n   */\n  i18n?: {\n    defaultLocale?: string\n    locales?: string[]\n  }\n\n  /**\n   * Custom email templates\n   */\n  customTemplates?: {\n    [key: string]: React.ComponentType<any>\n  }\n\n  /**\n   * Customization options for plugin collections\n   */\n  customizations?: {\n    broadcasts?: BroadcastCustomizations\n  }\n}\n\nexport interface ResendProviderConfig {\n  apiKey: string\n  fromEmail?: string\n  fromAddress?: string // Alias for fromEmail\n  fromName?: string\n  replyTo?: string\n  audienceIds?: {\n    [locale: string]: {\n      production?: string\n      development?: string\n    }\n  }\n}\n\nexport interface BroadcastProviderConfig {\n  apiUrl: string\n  token: string\n  fromEmail?: string\n  fromAddress?: string // Alias for fromEmail\n  fromName?: string\n  replyTo?: string\n}\n\nexport interface EmailProvider {\n  send(params: SendEmailParams): Promise<void>\n  addContact(contact: Subscriber): Promise<void>\n  updateContact(contact: Subscriber): Promise<void>\n  removeContact(email: string): Promise<void>\n}\n\nexport interface SendEmailParams {\n  to: string | string[]\n  subject: string\n  html?: string\n  text?: string\n  react?: React.ReactElement\n}\n\nexport interface Subscriber {\n  id: string\n  email: string\n  name?: string\n  locale?: string\n  subscriptionStatus: 'active' | 'unsubscribed' | 'pending'\n  emailPreferences?: {\n    newsletter?: boolean\n    announcements?: boolean\n    [key: string]: boolean | undefined\n  }\n  source?: string\n  importedFromProvider?: boolean\n  utmParameters?: {\n    source?: string\n    medium?: string\n    campaign?: string\n    content?: string\n    term?: string\n  }\n  // Additional fields that may exist in the database\n  signupMetadata?: {\n    ipAddress?: string\n    userAgent?: string\n    referrer?: string\n    signupPage?: string\n  }\n  leadMagnet?: string\n  unsubscribedAt?: string\n  magicLinkToken?: string\n  magicLinkTokenExpiry?: string\n  createdAt: string\n  updatedAt: string\n}\n\nexport interface WelcomeEmailProps {\n  subscriber: Subscriber\n  unsubscribeUrl: string\n  preferencesUrl: string\n}\n\nexport interface MagicLinkEmailProps {\n  magicLinkUrl: string\n  subscriber: Subscriber\n}\n\nexport interface SignupFormProps {\n  onSuccess?: (subscriber: Subscriber) => void\n  onError?: (error: Error) => void\n  showName?: boolean\n  showPreferences?: boolean\n  leadMagnet?: {\n    id: string\n    title: string\n    description?: string\n  }\n  className?: string\n  styles?: {\n    form?: React.CSSProperties\n    inputGroup?: React.CSSProperties\n    label?: React.CSSProperties\n    input?: React.CSSProperties\n    button?: React.CSSProperties\n    buttonDisabled?: React.CSSProperties\n    error?: React.CSSProperties\n    success?: React.CSSProperties\n    checkbox?: React.CSSProperties\n    checkboxInput?: React.CSSProperties\n    checkboxLabel?: React.CSSProperties\n  }\n  apiEndpoint?: string\n  buttonText?: string\n  loadingText?: string\n  successMessage?: string\n  placeholders?: {\n    email?: string\n    name?: string\n  }\n  labels?: {\n    email?: string\n    name?: string\n    newsletter?: string\n    announcements?: string\n  }\n}\n\nexport interface PreferencesFormProps {\n  subscriber?: Subscriber\n  onSuccess?: (subscriber: Subscriber) => void\n  onError?: (error: Error) => void\n  className?: string\n  styles?: {\n    container?: React.CSSProperties\n    heading?: React.CSSProperties\n    form?: React.CSSProperties\n    section?: React.CSSProperties\n    sectionTitle?: React.CSSProperties\n    inputGroup?: React.CSSProperties\n    label?: React.CSSProperties\n    input?: React.CSSProperties\n    select?: React.CSSProperties\n    checkbox?: React.CSSProperties\n    checkboxInput?: React.CSSProperties\n    checkboxLabel?: React.CSSProperties\n    buttonGroup?: React.CSSProperties\n    button?: React.CSSProperties\n    primaryButton?: React.CSSProperties\n    secondaryButton?: React.CSSProperties\n    dangerButton?: React.CSSProperties\n    error?: React.CSSProperties\n    success?: React.CSSProperties\n    info?: React.CSSProperties\n  }\n  sessionToken?: string\n  apiEndpoint?: string\n  showUnsubscribe?: boolean\n  locales?: string[]\n  labels?: {\n    title?: string\n    personalInfo?: string\n    emailPreferences?: string\n    name?: string\n    language?: string\n    newsletter?: string\n    announcements?: string\n    saveButton?: string\n    unsubscribeButton?: string\n    saving?: string\n    saved?: string\n    unsubscribeConfirm?: string\n  }\n}\n\nexport interface BeforeSubscribeArgs {\n  data: Partial<Subscriber>\n  req: any\n}\n\nexport interface AfterSubscribeArgs {\n  doc: Subscriber\n  req: any\n}\n\nexport interface BeforeUnsubscribeArgs {\n  email: string\n  req: any\n}\n\nexport interface AfterUnsubscribeArgs {\n  doc: Subscriber\n  req: any\n}\n\n\nexport interface SurveyQuestion {\n  id: string\n  question: string\n  type: 'text' | 'select' | 'multiselect' | 'radio'\n  options?: string[]\n  required?: boolean\n}\n\n// Request data interfaces for endpoints\nexport interface SubscribeRequestData {\n  email: string\n  name?: string\n  source?: string\n  preferences?: { [key: string]: boolean }\n  leadMagnet?: string\n  surveyResponses?: { [key: string]: string | string[] }\n  metadata?: {\n    locale?: string\n    signupPage?: string\n    [key: string]: unknown\n  }\n}\n\nexport interface UnsubscribeRequestData {\n  email?: string\n  token?: string\n}\n\nexport interface VerifyMagicLinkRequestData {\n  token: string\n}\n\nexport interface SigninRequestData {\n  email: string\n}\n\nexport interface UpdatePreferencesRequestData {\n  name?: string\n  locale?: string\n  emailPreferences?: { [key: string]: boolean }\n}\n\n// Extended request types with proper data typing\nexport interface ExtendedPayloadRequest extends Request {\n  payload: any // TODO: Add proper payload type\n  data?: unknown\n  ip?: string\n  connection?: {\n    remoteAddress?: string\n  }\n  cookies?: {\n    [key: string]: string\n  }\n  // Headers are inherited from Request, but we document common ones for reference\n  // Access via: req.headers.get('authorization'), req.headers.get('referer'), etc.\n}","import type { \n  Broadcast,\n  ListBroadcastOptions,\n  ListBroadcastResponse,\n  CreateBroadcastInput,\n  UpdateBroadcastInput,\n  SendBroadcastOptions,\n  BroadcastAnalytics,\n  BroadcastProviderCapabilities\n} from '../../types'\nimport { \n  BroadcastProviderError, \n  BroadcastErrorCode,\n  BroadcastStatus,\n  BaseBroadcastProvider\n} from '../../types'\nimport type { BroadcastProviderConfig } from '../../types'\n\ninterface BroadcastApiResponse {\n  id: number\n  name: string\n  subject: string\n  preheader?: string\n  body: string\n  status: string\n  track_opens: boolean\n  track_clicks: boolean\n  html_body: boolean\n  reply_to?: string\n  total_recipients: number\n  sent_at?: string\n  scheduled_send_at?: string\n  created_at: string\n  updated_at: string\n}\n\ninterface BroadcastListResponse {\n  data: BroadcastApiResponse[]\n  total: number\n}\n\n\nexport class BroadcastApiProvider extends BaseBroadcastProvider {\n  readonly name = 'broadcast'\n  private apiUrl: string\n  private token: string\n\n  constructor(config: BroadcastProviderConfig) {\n    super(config)\n    this.apiUrl = config.apiUrl.replace(/\\/$/, '') // Remove trailing slash\n    this.token = config.token\n    \n    if (!this.token) {\n      throw new BroadcastProviderError(\n        'Broadcast API token is required',\n        BroadcastErrorCode.CONFIGURATION_ERROR,\n        this.name\n      )\n    }\n  }\n\n  // Broadcast Management Methods\n  async list(options?: ListBroadcastOptions): Promise<ListBroadcastResponse<Broadcast>> {\n    try {\n      const params = new URLSearchParams()\n      if (options?.limit) params.append('limit', options.limit.toString())\n      if (options?.offset) params.append('offset', options.offset.toString())\n\n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts?${params}`, {\n        method: 'GET',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n      })\n\n      if (!response.ok) {\n        const error = await response.text()\n        throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n      }\n\n      const data: BroadcastListResponse = await response.json()\n      \n      const broadcasts = data.data.map(broadcast => this.transformBroadcastFromApi(broadcast))\n      \n      return this.buildListResponse(broadcasts, data.total, options)\n    } catch (error: unknown) {\n      throw new BroadcastProviderError(\n        `Failed to list broadcasts: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async get(id: string): Promise<Broadcast> {\n    try {\n      console.log('[BroadcastApiProvider] Getting broadcast with ID:', id)\n      \n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts/${id}`, {\n        method: 'GET',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n      })\n\n      if (!response.ok) {\n        if (response.status === 404) {\n          throw new BroadcastProviderError(\n            `Broadcast not found: ${id}`,\n            BroadcastErrorCode.NOT_FOUND,\n            this.name\n          )\n        }\n        const error = await response.text()\n        throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n      }\n\n      const broadcast: BroadcastApiResponse = await response.json()\n      console.log('[BroadcastApiProvider] GET response:', broadcast)\n      return this.transformBroadcastFromApi(broadcast)\n    } catch (error: unknown) {\n      if (error instanceof BroadcastProviderError) throw error\n      \n      throw new BroadcastProviderError(\n        `Failed to get broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async create(data: CreateBroadcastInput): Promise<Broadcast> {\n    try {\n      this.validateRequiredFields(data, ['name', 'subject', 'content'])\n\n      const requestBody = {\n        broadcast: {\n          name: data.name,\n          subject: data.subject,\n          preheader: data.preheader,\n          body: data.content,\n          html_body: true,\n          track_opens: data.trackOpens ?? true,\n          track_clicks: data.trackClicks ?? true,\n          reply_to: data.replyTo,\n          segment_ids: data.audienceIds,\n        }\n      }\n\n      // Log the request details (without exposing the token)\n      console.log('[BroadcastApiProvider] Creating broadcast:', {\n        url: `${this.apiUrl}/api/v1/broadcasts`,\n        method: 'POST',\n        hasToken: !!this.token,\n        tokenLength: this.token?.length,\n        body: JSON.stringify(requestBody, null, 2),\n      })\n\n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts`, {\n        method: 'POST',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify(requestBody),\n      })\n\n      console.log('[BroadcastApiProvider] Response status:', response.status)\n      console.log('[BroadcastApiProvider] Response headers:', Object.fromEntries(response.headers.entries()))\n\n      if (!response.ok) {\n        const errorText = await response.text()\n        console.error('[BroadcastApiProvider] Error response body:', errorText)\n        \n        // Try to parse as JSON if possible\n        let errorDetails\n        try {\n          errorDetails = JSON.parse(errorText)\n          console.error('[BroadcastApiProvider] Parsed error:', errorDetails)\n        } catch {\n          // Not JSON, use as is\n        }\n        \n        throw new Error(`Broadcast API error: ${response.status} - ${errorText}`)\n      }\n\n      const responseText = await response.text()\n      console.log('[BroadcastApiProvider] Success response body:', responseText)\n      \n      let result\n      try {\n        result = JSON.parse(responseText)\n      } catch {\n        throw new Error(`Failed to parse response as JSON: ${responseText}`)\n      }\n      \n      console.log('[BroadcastApiProvider] Parsed result:', result)\n      \n      if (!result.id) {\n        throw new Error(`Response missing expected 'id' field: ${JSON.stringify(result)}`)\n      }\n      \n      // Broadcast API returns just {id: 123}, so we need to fetch the full object\n      return this.get(result.id.toString())\n    } catch (error: unknown) {\n      if (error instanceof BroadcastProviderError) throw error\n      \n      throw new BroadcastProviderError(\n        `Failed to create broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async update(id: string, data: UpdateBroadcastInput): Promise<Broadcast> {\n    try {\n      // First check if the broadcast can be edited\n      const existing = await this.get(id)\n      if (!this.canEditInStatus(existing.sendStatus)) {\n        throw new BroadcastProviderError(\n          `Cannot update broadcast in status: ${existing.sendStatus}`,\n          BroadcastErrorCode.INVALID_STATUS,\n          this.name\n        )\n      }\n\n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts/${id}`, {\n        method: 'PATCH',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          broadcast: {\n            name: data.name,\n            subject: data.subject,\n            preheader: data.preheader,\n            body: data.content,\n            track_opens: data.trackOpens,\n            track_clicks: data.trackClicks,\n            reply_to: data.replyTo,\n            segment_ids: data.audienceIds,\n          }\n        }),\n      })\n\n      if (!response.ok) {\n        const error = await response.text()\n        throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n      }\n\n      const broadcast: BroadcastApiResponse = await response.json()\n      return this.transformBroadcastFromApi(broadcast)\n    } catch (error: unknown) {\n      if (error instanceof BroadcastProviderError) throw error\n      \n      throw new BroadcastProviderError(\n        `Failed to update broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async delete(id: string): Promise<void> {\n    try {\n      // First check if the broadcast can be deleted\n      const existing = await this.get(id)\n      if (!this.canEditInStatus(existing.sendStatus)) {\n        throw new BroadcastProviderError(\n          `Cannot delete broadcast in status: ${existing.sendStatus}`,\n          BroadcastErrorCode.INVALID_STATUS,\n          this.name\n        )\n      }\n\n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts/${id}`, {\n        method: 'DELETE',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n      })\n\n      if (!response.ok) {\n        const error = await response.text()\n        throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n      }\n    } catch (error: unknown) {\n      if (error instanceof BroadcastProviderError) throw error\n      \n      throw new BroadcastProviderError(\n        `Failed to delete broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async send(id: string, options?: SendBroadcastOptions): Promise<Broadcast> {\n    try {\n      // Check if we're in test mode\n      if (options?.testMode && options.testRecipients?.length) {\n        // TODO: Broadcast doesn't have a documented test send API\n        // For now, we'll throw an error\n        throw new BroadcastProviderError(\n          'Test send is not yet implemented for Broadcast provider',\n          BroadcastErrorCode.NOT_SUPPORTED,\n          this.name\n        )\n      }\n\n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts/${id}/send_broadcast`, {\n        method: 'POST',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          segment_ids: options?.audienceIds\n        }),\n      })\n\n      if (!response.ok) {\n        const error = await response.text()\n        throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n      }\n\n      // Response includes updated status\n      const result = await response.json()\n      return this.get(result.id.toString())\n    } catch (error: unknown) {\n      if (error instanceof BroadcastProviderError) throw error\n      \n      throw new BroadcastProviderError(\n        `Failed to send broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async schedule(id: string, scheduledAt: Date): Promise<Broadcast> {\n    try {\n      // Update the newsletter with scheduled time\n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts/${id}`, {\n        method: 'PATCH',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          broadcast: {\n            scheduled_send_at: scheduledAt.toISOString(),\n            // TODO: Handle timezone properly\n            scheduled_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone\n          }\n        }),\n      })\n\n      if (!response.ok) {\n        const error = await response.text()\n        throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n      }\n\n      const broadcast: BroadcastApiResponse = await response.json()\n      return this.transformBroadcastFromApi(broadcast)\n    } catch (error: unknown) {\n      throw new BroadcastProviderError(\n        `Failed to schedule broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async cancelSchedule(id: string): Promise<Broadcast> {\n    try {\n      // Clear the scheduled time\n      const response = await fetch(`${this.apiUrl}/api/v1/broadcasts/${id}`, {\n        method: 'PATCH',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          broadcast: {\n            scheduled_send_at: null,\n            scheduled_timezone: null\n          }\n        }),\n      })\n\n      if (!response.ok) {\n        const error = await response.text()\n        throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n      }\n\n      const broadcast: BroadcastApiResponse = await response.json()\n      return this.transformBroadcastFromApi(broadcast)\n    } catch (error: unknown) {\n      throw new BroadcastProviderError(\n        `Failed to cancel scheduled broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n        BroadcastErrorCode.PROVIDER_ERROR,\n        this.name,\n        error\n      )\n    }\n  }\n\n  async getAnalytics(_id: string): Promise<BroadcastAnalytics> {\n    // TODO: Broadcast analytics API is not documented in the CRUD API\n    // This would need additional API documentation\n    throw new BroadcastProviderError(\n      'Analytics API not yet implemented for Broadcast provider',\n      BroadcastErrorCode.NOT_SUPPORTED,\n      this.name\n    )\n  }\n\n  getCapabilities(): BroadcastProviderCapabilities {\n    return {\n      supportsScheduling: true,\n      supportsSegmentation: true,\n      supportsAnalytics: false, // Not documented yet\n      supportsABTesting: false,\n      supportsTemplates: false,\n      supportsPersonalization: true,\n      supportsMultipleChannels: false,\n      supportsChannelSegmentation: false,\n      editableStatuses: [BroadcastStatus.DRAFT, BroadcastStatus.SCHEDULED],\n      supportedContentTypes: ['html', 'text']\n    }\n  }\n\n  async validateConfiguration(): Promise<boolean> {\n    try {\n      // Try to list broadcasts with limit 1 to validate API access\n      await this.list({ limit: 1 })\n      return true\n    } catch {\n      return false\n    }\n  }\n\n  private transformBroadcastFromApi(broadcast: BroadcastApiResponse): Broadcast {\n    return {\n      id: broadcast.id.toString(),\n      name: broadcast.name,\n      subject: broadcast.subject,\n      preheader: broadcast.preheader,\n      content: broadcast.body,\n      sendStatus: this.mapBroadcastStatus(broadcast.status),\n      trackOpens: broadcast.track_opens,\n      trackClicks: broadcast.track_clicks,\n      replyTo: broadcast.reply_to,\n      recipientCount: broadcast.total_recipients,\n      sentAt: broadcast.sent_at ? new Date(broadcast.sent_at) : undefined,\n      scheduledAt: broadcast.scheduled_send_at ? new Date(broadcast.scheduled_send_at) : undefined,\n      createdAt: new Date(broadcast.created_at),\n      updatedAt: new Date(broadcast.updated_at),\n      providerData: { broadcast },\n      providerId: broadcast.id.toString(),\n      providerType: 'broadcast'\n    }\n  }\n\n  private mapBroadcastStatus(status: string): BroadcastStatus {\n    const statusMap: Record<string, BroadcastStatus> = {\n      'draft': BroadcastStatus.DRAFT,\n      'scheduled': BroadcastStatus.SCHEDULED,\n      'queueing': BroadcastStatus.SENDING,\n      'sending': BroadcastStatus.SENDING,\n      'sent': BroadcastStatus.SENT,\n      'failed': BroadcastStatus.FAILED,\n      'partial_failure': BroadcastStatus.FAILED,\n      'paused': BroadcastStatus.PAUSED,\n      'aborted': BroadcastStatus.CANCELED\n    }\n    return statusMap[status] || BroadcastStatus.DRAFT\n  }\n}","// Collection factories\nexport { createBroadcastsCollection } from '../collections/Broadcasts'\nexport { createSubscribersCollection } from '../collections/Subscribers'","import type { CollectionConfig } from 'payload'\nimport type { SerializedEditorState } from 'lexical'\nimport type { NewsletterPluginConfig } from '../types'\nimport type { BroadcastDocument, BroadcastHookContext } from '../types/scheduling'\nimport type { AudienceIdField } from '../types/broadcast'\nimport { BroadcastStatus } from '../types'\nimport { createEmailContentField, createEmailLexicalEditor } from '../fields/emailContent'\nimport { createBroadcastInlinePreviewField } from '../fields/broadcastInlinePreview'\nimport { createBroadcastScheduleField } from '../fields/broadcastSchedule'\nimport { convertToEmailSafeHtml } from '../utils/emailSafeHtml'\nimport { getBroadcastConfig } from '../utils/getBroadcastConfig'\nimport { getBroadcastProvider } from '../utils/getProvider'\nimport { shouldSyncToProvider, syncBroadcastToProvider } from '../utils/broadcast-sync'\nimport { detectStateTransition, areScheduledTimesEqual, parseScheduledDate, draftState, scheduledState, sendingState, failedState } from '../utils/scheduling-state'\nimport { getErrorMessage, getErrorDetails } from '../utils/getErrorMessage'\nimport { generateIdempotencyKey, getCompletedOperation, markOperationCompleted } from '../utils/idempotency'\nimport { createSendBroadcastEndpoint } from '../endpoints/broadcasts/send'\nimport { createScheduleBroadcastEndpoint, createCancelScheduleBroadcastEndpoint } from '../endpoints/broadcasts/schedule'\nimport { createRetrySyncEndpoint } from '../endpoints/broadcasts/retry-sync'\nimport { createTestBroadcastEndpoint } from '../endpoints/broadcasts/test'\nimport { createBroadcastPreviewEndpoint, populateMediaFields } from '../endpoints/broadcasts/preview'\n\nexport const createBroadcastsCollection = (pluginConfig: NewsletterPluginConfig): CollectionConfig => {\n  const hasProviders = !!(pluginConfig.providers?.broadcast || pluginConfig.providers?.resend)\n  const customizations = pluginConfig.customizations?.broadcasts\n\n  const collectionSlug = 'broadcasts'\n\n  return {\n    slug: collectionSlug,\n    access: {\n      read: () => true, // Public read access\n      create: ({ req: { user } }) => {\n        // Allow authenticated users to create\n        return Boolean(user)\n      },\n      update: ({ req: { user } }) => {\n        // Allow authenticated users to update\n        return Boolean(user)\n      },\n      delete: ({ req: { user } }) => {\n        // Allow authenticated users to delete\n        return Boolean(user)\n      },\n    },\n    versions: {\n      drafts: {\n        autosave: true,\n        schedulePublish: true,\n      }\n    },\n    labels: {\n      singular: 'Broadcast',\n      plural: 'Broadcasts',\n    },\n    admin: {\n      useAsTitle: 'subject',\n      description: 'Individual email campaigns sent to subscribers',\n      defaultColumns: ['subject', '_status', 'sendStatus', 'sentAt', 'recipientCount'],\n    },\n    endpoints: [\n      createSendBroadcastEndpoint(pluginConfig, collectionSlug),\n      createScheduleBroadcastEndpoint(pluginConfig, collectionSlug),\n      createCancelScheduleBroadcastEndpoint(pluginConfig, collectionSlug),\n      createRetrySyncEndpoint(pluginConfig, collectionSlug),\n      createTestBroadcastEndpoint(pluginConfig, collectionSlug),\n      createBroadcastPreviewEndpoint(pluginConfig, collectionSlug),\n    ],\n    fields: [\n      {\n        name: 'subject',\n        type: 'text',\n        required: true,\n        admin: {\n          description: 'Email subject line'\n        },\n      },\n      {\n        name: 'emailOnly',\n        type: 'checkbox',\n        label: 'Email Only',\n        defaultValue: false,\n        admin: {\n          description: 'Check this to send via email only (won\\'t be published on website). Use the plugin\\'s Schedule Send button instead of Payload\\'s Schedule Publish.',\n        },\n      },\n      // Add any additional fields from customizations after subject\n      ...(customizations?.additionalFields || []),\n      {\n        type: 'row',\n        fields: [\n          {\n            name: 'contentSection',\n            type: 'group',\n            label: false,\n            admin: {\n              width: '50%',\n              style: {\n                paddingRight: '1rem',\n              },\n            },\n            fields: [\n              {\n                name: 'preheader',\n                type: 'text',\n                admin: {\n                  description: 'Preview text shown in email clients'\n                },\n              },\n              // Apply content field customization if provided\n              // Process blocks server-side to avoid client serialization issues\n              (() => {\n                // Create email editor with custom blocks processed server-side\n                const emailEditor = createEmailLexicalEditor(customizations?.customBlocks)\n                \n                // Create base field with pre-processed editor\n                const baseField = createEmailContentField({\n                  admin: { description: 'Email content' },\n                  editor: emailEditor\n                })\n                \n                // Apply field overrides if provided\n                return customizations?.fieldOverrides?.content\n                  ? customizations.fieldOverrides.content(baseField)\n                  : baseField\n              })(),\n            ],\n          },\n          {\n            name: 'previewSection',\n            type: 'group',\n            label: false,\n            admin: {\n              width: '50%',\n            },\n            fields: [\n              createBroadcastInlinePreviewField(),\n            ],\n          },\n        ],\n      },\n      {\n        name: 'sendStatus',\n        type: 'select',\n        label: 'Send Status',\n        required: true,\n        defaultValue: BroadcastStatus.DRAFT,\n        options: [\n          { label: 'Draft', value: BroadcastStatus.DRAFT },\n          { label: 'Scheduled', value: BroadcastStatus.SCHEDULED },\n          { label: 'Sending', value: BroadcastStatus.SENDING },\n          { label: 'Sent', value: BroadcastStatus.SENT },\n          { label: 'Failed', value: BroadcastStatus.FAILED },\n          { label: 'Paused', value: BroadcastStatus.PAUSED },\n          { label: 'Canceled', value: BroadcastStatus.CANCELED },\n        ],\n        admin: {\n          readOnly: true,\n          description: 'The status of the email send operation',\n          components: {\n            Cell: 'payload-plugin-newsletter/components#StatusBadge',\n          },\n        },\n      },\n      // Scheduling controls - shows schedule/cancel buttons based on status\n      createBroadcastScheduleField(),\n      {\n        name: 'settings',\n        type: 'group',\n        fields: [\n          {\n            name: 'trackOpens',\n            type: 'checkbox',\n            defaultValue: true,\n            admin: {\n              description: 'Track when recipients open this email'\n            },\n          },\n          {\n            name: 'trackClicks',\n            type: 'checkbox',\n            defaultValue: true,\n            admin: {\n              description: 'Track when recipients click links'\n            },\n          },\n          {\n            name: 'replyTo',\n            type: 'email',\n            admin: {\n              description: 'Override the channel reply-to address for this broadcast'\n            },\n          },\n        ],\n      },\n      {\n        name: 'audienceIds',\n        type: 'array',\n        fields: [\n          {\n            name: 'audienceId',\n            type: 'text',\n            required: true,\n          },\n        ],\n        admin: {\n          description: 'Target specific audience segments',\n          condition: () => {\n            // Only show if the provider supports segmentation\n            return hasProviders\n          },\n        },\n      },\n      {\n        name: 'analytics',\n        type: 'group',\n        admin: {\n          readOnly: true,\n          condition: (data) => data?.sendStatus === BroadcastStatus.SENT,\n        },\n        fields: [\n          {\n            name: 'recipientCount',\n            type: 'number',\n            defaultValue: 0,\n          },\n          {\n            name: 'sent',\n            type: 'number',\n            defaultValue: 0,\n          },\n          {\n            name: 'delivered',\n            type: 'number',\n            defaultValue: 0,\n          },\n          {\n            name: 'opened',\n            type: 'number',\n            defaultValue: 0,\n          },\n          {\n            name: 'clicked',\n            type: 'number',\n            defaultValue: 0,\n          },\n          {\n            name: 'bounced',\n            type: 'number',\n            defaultValue: 0,\n          },\n          {\n            name: 'complained',\n            type: 'number',\n            defaultValue: 0,\n          },\n          {\n            name: 'unsubscribed',\n            type: 'number',\n            defaultValue: 0,\n          },\n        ],\n      },\n      {\n        name: 'sentAt',\n        type: 'date',\n        admin: {\n          readOnly: true,\n          date: {\n            displayFormat: 'MMM d, yyyy h:mm a',\n          },\n        },\n      },\n      {\n        name: 'scheduledAt',\n        type: 'date',\n        admin: {\n          condition: (data) => data?.sendStatus === BroadcastStatus.SCHEDULED,\n          date: {\n            displayFormat: 'MMM d, yyyy h:mm a',\n          },\n        },\n      },\n      {\n        name: 'providerId',\n        type: 'text',\n        admin: {\n          readOnly: true,\n          description: 'ID from the email provider',\n          condition: (data) => hasProviders && data?.providerId,\n        },\n      },\n      {\n        name: 'externalId',\n        type: 'text',\n        admin: {\n          readOnly: true,\n          description: 'External ID for webhook integration',\n        },\n      },\n      {\n        name: 'providerData',\n        type: 'json',\n        admin: {\n          readOnly: true,\n          condition: () => false, // Hidden by default\n        },\n      },\n      // Provider sync status tracking\n      {\n        name: 'providerSyncStatus',\n        type: 'select',\n        label: 'Provider Sync Status',\n        defaultValue: 'pending',\n        options: [\n          { label: 'Pending', value: 'pending' },\n          { label: 'Synced', value: 'synced' },\n          { label: 'Failed', value: 'failed' },\n        ],\n        admin: {\n          readOnly: true,\n          description: 'Status of sync with email provider',\n          condition: (data) => hasProviders && data?.providerId,\n          components: {\n            Field: 'payload-plugin-newsletter/components#SyncStatusField',\n          },\n        },\n      },\n      {\n        name: 'providerSyncError',\n        type: 'text',\n        admin: {\n          readOnly: true,\n          condition: (data) => data?.providerSyncStatus === 'failed',\n          description: 'Error message from last sync attempt',\n        },\n      },\n      {\n        name: 'lastSyncAttempt',\n        type: 'date',\n        admin: {\n          readOnly: true,\n          condition: () => false, // Hidden, used for tracking\n        },\n      },\n      // Webhook tracking fields\n      {\n        name: 'webhookData',\n        type: 'group',\n        label: 'Webhook Data',\n        admin: {\n          condition: () => false, // Hidden by default, used for webhook tracking\n        },\n        fields: [\n          {\n            name: 'lastWebhookEvent',\n            type: 'text',\n            admin: {\n              readOnly: true,\n            },\n          },\n          {\n            name: 'lastWebhookEventAt',\n            type: 'date',\n            admin: {\n              readOnly: true,\n            },\n          },\n          {\n            name: 'hasWarnings',\n            type: 'checkbox',\n            defaultValue: false,\n          },\n          {\n            name: 'failureReason',\n            type: 'text',\n          },\n          {\n            name: 'sentCount',\n            type: 'number',\n          },\n          {\n            name: 'totalCount',\n            type: 'number',\n          },\n          {\n            name: 'failedCount',\n            type: 'number',\n          },\n          {\n            name: 'remainingCount',\n            type: 'number',\n          },\n          {\n            name: 'sendingStartedAt',\n            type: 'date',\n          },\n          {\n            name: 'failedAt',\n            type: 'date',\n          },\n          {\n            name: 'abortedAt',\n            type: 'date',\n          },\n          {\n            name: 'abortReason',\n            type: 'text',\n          },\n          {\n            name: 'pausedAt',\n            type: 'date',\n          },\n          {\n            name: 'webhookEvents',\n            type: 'array',\n            label: 'Webhook Event Log',\n            maxRows: 10,\n            admin: {\n              readOnly: true,\n              description: 'Recent webhook events for debugging',\n            },\n            fields: [\n              {\n                name: 'eventType',\n                type: 'text',\n                admin: { readOnly: true },\n              },\n              {\n                name: 'receivedAt',\n                type: 'date',\n                admin: { readOnly: true },\n              },\n              {\n                name: 'eventPayload',\n                type: 'json',\n                admin: { readOnly: true },\n              },\n            ],\n          },\n        ],\n      },\n    ],\n    hooks: {\n      // Sync with provider on create and update\n      afterChange: [\n        async ({ doc, operation, req, previousDoc, context }) => {\n          if (!hasProviders) return doc\n\n          // CRITICAL: Check context flag FIRST to prevent infinite loops\n          // This must be at the TOP before any operation checks\n          const hookContext = context as BroadcastHookContext | undefined\n          if (hookContext?.isSchedulingUpdate) {\n            return doc\n          }\n\n          req.payload.logger.info({\n            operation,\n            hasProviderId: !!doc.providerId,\n            hasExternalId: !!doc.externalId,\n            sendStatus: doc.sendStatus,\n            publishStatus: doc._status,\n            hasSubject: !!doc.subject,\n            hasContent: !!doc.contentSection?.content\n          }, `Broadcast afterChange ${operation} hook triggered`)\n\n          // === CREATE OPERATION ===\n          if (operation === 'create') {\n            // Check if broadcast has sufficient content for sync\n            if (!shouldSyncToProvider(doc)) {\n              req.payload.logger.info(\n                { broadcastId: doc.id },\n                'Broadcast created without sufficient content - skipping provider sync'\n              )\n              return doc\n            }\n\n            // Sync to provider\n            try {\n              const provider = await getBroadcastProvider(req, pluginConfig)\n              const providerConfig = await getBroadcastConfig(req, pluginConfig)\n\n              const syncResult = await syncBroadcastToProvider(\n                doc,\n                req,\n                pluginConfig,\n                providerConfig,\n                provider\n              )\n\n              if (syncResult.success) {\n                req.payload.logger.info(\n                  { broadcastId: doc.id, providerId: syncResult.providerId },\n                  'Broadcast synced to provider on CREATE'\n                )\n\n                // Update document with provider IDs\n                // Using context flag to prevent this update from re-triggering the hook\n                await req.payload.update({\n                  collection: collectionSlug,\n                  id: doc.id,\n                  data: {\n                    providerId: syncResult.providerId,\n                    externalId: syncResult.externalId,\n                    providerData: syncResult.providerData,\n                    providerSyncStatus: 'synced',\n                    providerSyncError: null,\n                    lastSyncAttempt: new Date().toISOString(),\n                  },\n                  context: { isSchedulingUpdate: true } as BroadcastHookContext,\n                })\n\n                return {\n                  ...doc,\n                  providerId: syncResult.providerId,\n                  externalId: syncResult.externalId,\n                  providerData: syncResult.providerData,\n                  providerSyncStatus: 'synced',\n                  providerSyncError: null,\n                }\n              } else {\n                req.payload.logger.error(\n                  { broadcastId: doc.id, error: syncResult.error },\n                  'Failed to sync broadcast to provider on CREATE'\n                )\n\n                // Update document with failed status\n                await req.payload.update({\n                  collection: collectionSlug,\n                  id: doc.id,\n                  data: {\n                    providerSyncStatus: 'failed',\n                    providerSyncError: syncResult.error,\n                    lastSyncAttempt: new Date().toISOString(),\n                  },\n                  context: { isSchedulingUpdate: true } as BroadcastHookContext,\n                })\n\n                return {\n                  ...doc,\n                  providerSyncStatus: 'failed',\n                  providerSyncError: syncResult.error,\n                }\n              }\n            } catch (error: unknown) {\n              // Handle unexpected errors (e.g., provider initialization failure)\n              req.payload.logger.error(\n                { broadcastId: doc.id, error: getErrorDetails(error) },\n                'Unexpected error during CREATE sync'\n              )\n              return doc\n            }\n          }\n\n          // === UPDATE OPERATION ===\n          if (operation === 'update') {\n            try {\n              // Get provider (centralized initialization)\n              const provider = await getBroadcastProvider(req, pluginConfig)\n              const providerConfig = await getBroadcastConfig(req, pluginConfig)\n\n              // If no providerId/externalId and has enough content, create in provider\n              if (!doc.providerId && !doc.externalId && shouldSyncToProvider(doc)) {\n                req.payload.logger.info('Creating broadcast in provider on first update with content')\n\n                const syncResult = await syncBroadcastToProvider(\n                  doc,\n                  req,\n                  pluginConfig,\n                  providerConfig,\n                  provider\n                )\n\n                if (syncResult.success) {\n                  req.payload.logger.info(\n                    { broadcastId: doc.id, providerId: syncResult.providerId },\n                    'Broadcast synced to provider on UPDATE'\n                  )\n\n                  // Update document with provider IDs\n                  // Using context flag to prevent this update from re-triggering the hook\n                  await req.payload.update({\n                    collection: collectionSlug,\n                    id: doc.id,\n                    data: {\n                      providerId: syncResult.providerId,\n                      externalId: syncResult.externalId,\n                      providerData: syncResult.providerData,\n                      providerSyncStatus: 'synced',\n                      providerSyncError: null,\n                      lastSyncAttempt: new Date().toISOString(),\n                    },\n                    context: { isSchedulingUpdate: true } as BroadcastHookContext,\n                  })\n\n                  return {\n                    ...doc,\n                    providerId: syncResult.providerId,\n                    externalId: syncResult.externalId,\n                    providerData: syncResult.providerData,\n                    providerSyncStatus: 'synced',\n                    providerSyncError: null,\n                  }\n                } else {\n                  req.payload.logger.error(\n                    { broadcastId: doc.id, error: syncResult.error },\n                    'Failed to create broadcast in provider during UPDATE'\n                  )\n                  // Continue - don't block update, just log the error\n                }\n              }\n\n              // If no providerId, skip sync\n              if (!doc.providerId) {\n                req.payload.logger.info(`Broadcast ${doc.id} has no providerId and insufficient content for creation - skipping sync`)\n                return doc\n              }\n\n              // Handle normal updates to existing broadcasts (only if providerId exists)\n              if (doc.providerId) {\n                // Only sync if broadcast is still editable\n                const capabilities = provider.getCapabilities()\n                const sendStatus = doc.sendStatus || BroadcastStatus.DRAFT\n                if (!capabilities.editableStatuses.includes(sendStatus)) {\n                  req.payload.logger.info(`Skipping sync for broadcast in status: ${sendStatus}`)\n                  return doc\n                }\n\n                // Check what has changed\n                const contentChanged =\n                  doc.subject !== previousDoc?.subject ||\n                  doc.contentSection?.preheader !== previousDoc?.contentSection?.preheader ||\n                  JSON.stringify(doc.contentSection?.content) !== JSON.stringify(previousDoc?.contentSection?.content) ||\n                  doc.settings?.trackOpens !== previousDoc?.settings?.trackOpens ||\n                  doc.settings?.trackClicks !== previousDoc?.settings?.trackClicks ||\n                  doc.settings?.replyTo !== previousDoc?.settings?.replyTo ||\n                  JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds)\n\n                if (contentChanged) {\n                  // Build update data with proper types\n                  const updates: Partial<{\n                    name: string\n                    subject: string\n                    preheader: string\n                    content: string\n                    trackOpens: boolean\n                    trackClicks: boolean\n                    replyTo: string\n                    audienceIds: string[]\n                  }> = {}\n                  if (doc.subject !== previousDoc?.subject) {\n                    updates.name = doc.subject // Use subject as name in the provider\n                    updates.subject = doc.subject\n                  }\n                  if (doc.contentSection?.preheader !== previousDoc?.contentSection?.preheader) {\n                    updates.preheader = doc.contentSection?.preheader\n                  }\n                  if (JSON.stringify(doc.contentSection?.content) !== JSON.stringify(previousDoc?.contentSection?.content)) {\n                    const populatedContent = await populateMediaFields(doc.contentSection?.content, req.payload, pluginConfig) as SerializedEditorState | null\n\n                    // Get email preview customization options\n                    const emailPreviewConfig = pluginConfig.customizations?.broadcasts?.emailPreview\n\n                    updates.content = await convertToEmailSafeHtml(populatedContent, {\n                      wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,\n                      customWrapper: emailPreviewConfig?.customWrapper,\n                      preheader: doc.contentSection?.preheader,\n                      subject: doc.subject,\n                      documentData: doc, // Pass entire document\n                      customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter\n                    })\n                  }\n                  if (doc.settings?.trackOpens !== previousDoc?.settings?.trackOpens) {\n                    updates.trackOpens = doc.settings.trackOpens\n                  }\n                  if (doc.settings?.trackClicks !== previousDoc?.settings?.trackClicks) {\n                    updates.trackClicks = doc.settings.trackClicks\n                  }\n                  if (doc.settings?.replyTo !== previousDoc?.settings?.replyTo) {\n                    updates.replyTo = doc.settings.replyTo || providerConfig?.replyTo\n                  }\n                  if (JSON.stringify(doc.audienceIds) !== JSON.stringify(previousDoc?.audienceIds)) {\n                    updates.audienceIds = (doc.audienceIds as AudienceIdField[] | undefined)?.map((a) => a.audienceId)\n                  }\n\n                  req.payload.logger.info({\n                    providerId: doc.providerId,\n                    updates\n                  }, 'Syncing broadcast updates to provider')\n\n                  await provider.update(doc.providerId, updates)\n\n                  // Update sync status to synced\n                  await req.payload.update({\n                    collection: collectionSlug,\n                    id: doc.id,\n                    data: {\n                      providerSyncStatus: 'synced',\n                      providerSyncError: null,\n                      lastSyncAttempt: new Date().toISOString(),\n                    },\n                    context: { isSchedulingUpdate: true } as BroadcastHookContext,\n                  })\n\n                  req.payload.logger.info(`Broadcast ${doc.id} synced to provider successfully`)\n                } else {\n                  req.payload.logger.info('No content changes to sync to provider')\n                }\n              }\n            } catch (error: unknown) {\n              req.payload.logger.error(\n                {\n                  broadcastId: doc.id,\n                  subject: doc.subject,\n                  error: getErrorDetails(error),\n                },\n                'Failed to sync broadcast to provider'\n              )\n\n              // Update sync status to failed so user can see the issue\n              try {\n                await req.payload.update({\n                  collection: collectionSlug,\n                  id: doc.id,\n                  data: {\n                    providerSyncStatus: 'failed',\n                    providerSyncError: getErrorMessage(error),\n                    lastSyncAttempt: new Date().toISOString(),\n                  },\n                  context: { isSchedulingUpdate: true } as BroadcastHookContext,\n                })\n              } catch (updateError) {\n                req.payload.logger.error(\n                  { broadcastId: doc.id, error: getErrorDetails(updateError) },\n                  'Failed to update sync status after sync failure'\n                )\n              }\n              // Don't throw - allow Payload update to succeed even if provider sync fails\n            }\n          }\n\n          return doc\n        },\n        // Unified scheduling hook: syncs email scheduling with Payload publish scheduling\n        async ({ doc, operation, previousDoc, req, context }): Promise<typeof doc> => {\n          // Skip if this is an internal scheduling update (prevents recursion)\n          const hookContext = context as BroadcastHookContext | undefined\n          if (hookContext?.isSchedulingUpdate) {\n            return doc\n          }\n\n          // Only process updates\n          if (operation !== 'update') {\n            return doc\n          }\n\n          // Skip if no providers configured\n          if (!hasProviders) {\n            return doc\n          }\n\n          // Cast to typed document for better type safety\n          const broadcastDoc = doc as BroadcastDocument\n\n          // Skip if no providerId (not synced to provider yet)\n          if (!broadcastDoc.providerId) {\n            return doc\n          }\n\n          // Skip if email-only (handled by ScheduleModal, not Payload's Schedule Publish)\n          if (broadcastDoc.emailOnly === true) {\n            return doc\n          }\n\n          // Skip if already sent or sending\n          if (\n            broadcastDoc.sendStatus === BroadcastStatus.SENT ||\n            broadcastDoc.sendStatus === BroadcastStatus.SENDING\n          ) {\n            return doc\n          }\n\n          const transition = detectStateTransition(\n            previousDoc as BroadcastDocument | undefined,\n            broadcastDoc\n          )\n\n          const publishedAt = parseScheduledDate(broadcastDoc.publishedAt)\n          const now = new Date()\n\n          // --- IDEMPOTENCY CHECK ---\n          // Skip if already scheduled for this exact time\n          if (\n            broadcastDoc.sendStatus === BroadcastStatus.SCHEDULED &&\n            areScheduledTimesEqual(broadcastDoc.scheduledAt, publishedAt)\n          ) {\n            return doc\n          }\n\n          // --- PUBLISH TRANSITION ---\n          if (transition.wasUnpublished && transition.isNowPublished) {\n            try {\n              const provider = await getBroadcastProvider(req, pluginConfig)\n\n              // DECISION: Manual publish while scheduled = send immediately\n              // This matches user intent - clicking \"Publish\" means \"do it now\"\n              if (transition.isManualPublish) {\n                req.payload.logger.info(\n                  {\n                    broadcastId: broadcastDoc.id,\n                    action: 'manualPublishOverride',\n                    scheduledFor: broadcastDoc.publishedAt,\n                  },\n                  'Manual publish detected, sending immediately instead of waiting for scheduled time'\n                )\n              }\n\n              // Check if publishedAt is in the future AND not a manual publish\n              if (publishedAt && publishedAt.getTime() > now.getTime() && !transition.isManualPublish) {\n                // Future scheduled publish - schedule the email for that time\n                const scheduleKey = generateIdempotencyKey(broadcastDoc.id, 'schedule', {\n                  time: publishedAt.getTime(),\n                })\n\n                // Check if this exact schedule operation was recently completed\n                // (prevents duplicate if DB update failed after provider success)\n                const cached = getCompletedOperation(scheduleKey)\n                if (cached) {\n                  req.payload.logger.info(\n                    { broadcastId: broadcastDoc.id, idempotencyKey: scheduleKey },\n                    'Schedule operation already completed (idempotency check), updating local state only'\n                  )\n                } else {\n                  // NOTE: provider.schedule() expects Date object, not string\n                  await provider.schedule(broadcastDoc.providerId, publishedAt)\n                  markOperationCompleted(scheduleKey, { scheduledAt: publishedAt.toISOString() })\n                }\n\n                await req.payload.update({\n                  collection: 'broadcasts',\n                  id: broadcastDoc.id,\n                  data: scheduledState(publishedAt),\n                  context: { isSchedulingUpdate: true } as BroadcastHookContext,\n                })\n\n                req.payload.logger.info(\n                  {\n                    broadcastId: broadcastDoc.id,\n                    scheduledAt: publishedAt.toISOString(),\n                  },\n                  'Email scheduled to sync with website publish'\n                )\n              } else {\n                // Immediate publish OR manual publish - send email now\n                const sendKey = generateIdempotencyKey(broadcastDoc.id, 'send', {})\n\n                // Check if this send operation was recently completed\n                const cached = getCompletedOperation(sendKey)\n                if (cached) {\n                  req.payload.logger.info(\n                    { broadcastId: broadcastDoc.id, idempotencyKey: sendKey },\n                    'Send operation already completed (idempotency check), updating local state only'\n                  )\n                } else {\n                  await provider.send(broadcastDoc.providerId)\n                  markOperationCompleted(sendKey, { sentAt: new Date().toISOString() })\n                }\n\n                await req.payload.update({\n                  collection: 'broadcasts',\n                  id: broadcastDoc.id,\n                  data: {\n                    ...sendingState(),\n                    sentAt: new Date().toISOString(),\n                  },\n                  context: { isSchedulingUpdate: true } as BroadcastHookContext,\n                })\n\n                req.payload.logger.info(\n                  { broadcastId: broadcastDoc.id },\n                  'Broadcast sent successfully on publish'\n                )\n              }\n            } catch (error: unknown) {\n              req.payload.logger.error(\n                {\n                  broadcastId: broadcastDoc.id,\n                  error: getErrorDetails(error),\n                },\n                'Failed to schedule/send email for published broadcast'\n              )\n\n              await req.payload.update({\n                collection: 'broadcasts',\n                id: broadcastDoc.id,\n                data: {\n                  ...failedState(),\n                  // Store error in webhookData.failureReason since we don't have a sendError field\n                  webhookData: {\n                    ...((doc as any).webhookData || {}),\n                    failureReason: `Email operation failed: ${getErrorMessage(error)}`,\n                  },\n                },\n                context: { isSchedulingUpdate: true } as BroadcastHookContext,\n              })\n              // Don't throw - website is already published\n            }\n\n            return doc\n          }\n\n          // --- SCHEDULE CANCELLATION ---\n          if (\n            transition.wasScheduled &&\n            transition.isNoLongerScheduled &&\n            broadcastDoc.sendStatus === BroadcastStatus.SCHEDULED\n          ) {\n            try {\n              const provider = await getBroadcastProvider(req, pluginConfig)\n              const cancelKey = generateIdempotencyKey(broadcastDoc.id, 'cancel', {})\n\n              // Check if cancel was recently completed\n              const cached = getCompletedOperation(cancelKey)\n              if (cached) {\n                req.payload.logger.info(\n                  { broadcastId: broadcastDoc.id, idempotencyKey: cancelKey },\n                  'Cancel operation already completed (idempotency check), updating local state only'\n                )\n              } else {\n                await provider.cancelSchedule(broadcastDoc.providerId)\n                markOperationCompleted(cancelKey, { cancelledAt: new Date().toISOString() })\n              }\n\n              await req.payload.update({\n                collection: 'broadcasts',\n                id: broadcastDoc.id,\n                data: draftState(),\n                context: { isSchedulingUpdate: true } as BroadcastHookContext,\n              })\n\n              req.payload.logger.info(\n                { broadcastId: broadcastDoc.id },\n                'Email schedule cancelled (publish schedule removed)'\n              )\n            } catch (error: unknown) {\n              req.payload.logger.error(\n                {\n                  broadcastId: broadcastDoc.id,\n                  error: getErrorDetails(error),\n                },\n                'Failed to cancel scheduled email - email may still send at original time'\n              )\n              // Don't update status - let user know the cancel may have failed\n            }\n\n            return doc\n          }\n\n          // --- SCHEDULE TIME CHANGE ---\n          if (\n            transition.scheduleTimeChanged &&\n            publishedAt &&\n            broadcastDoc.sendStatus === BroadcastStatus.SCHEDULED\n          ) {\n            try {\n              const provider = await getBroadcastProvider(req, pluginConfig)\n              const previousScheduledAt = broadcastDoc.scheduledAt\n\n              // Use a compound idempotency key for reschedule (includes old and new time)\n              const rescheduleKey = generateIdempotencyKey(broadcastDoc.id, 'schedule', {\n                from: previousScheduledAt ? new Date(previousScheduledAt).getTime() : 0,\n                to: publishedAt.getTime(),\n              })\n\n              // Check if this exact reschedule was recently completed\n              const cached = getCompletedOperation(rescheduleKey)\n              if (cached) {\n                req.payload.logger.info(\n                  { broadcastId: broadcastDoc.id, idempotencyKey: rescheduleKey },\n                  'Reschedule operation already completed (idempotency check), updating local state only'\n                )\n              } else {\n                // Cancel existing schedule, then create new one\n                await provider.cancelSchedule(broadcastDoc.providerId)\n                await provider.schedule(broadcastDoc.providerId, publishedAt)\n                markOperationCompleted(rescheduleKey, {\n                  rescheduledAt: new Date().toISOString(),\n                  newTime: publishedAt.toISOString(),\n                })\n              }\n\n              await req.payload.update({\n                collection: 'broadcasts',\n                id: broadcastDoc.id,\n                data: {\n                  scheduledAt: publishedAt.toISOString(),\n                },\n                context: { isSchedulingUpdate: true } as BroadcastHookContext,\n              })\n\n              req.payload.logger.info(\n                {\n                  broadcastId: broadcastDoc.id,\n                  newScheduledAt: publishedAt.toISOString(),\n                },\n                'Email rescheduled to new publish time'\n              )\n            } catch (error: unknown) {\n              req.payload.logger.error(\n                {\n                  broadcastId: broadcastDoc.id,\n                  newScheduledAt: publishedAt.toISOString(),\n                  error: getErrorDetails(error),\n                },\n                'Failed to reschedule email - may send at original time or not at all'\n              )\n            }\n\n            return doc\n          }\n\n          return doc\n        },\n      ],\n      // beforeChange hooks can be added here if needed\n      beforeChange: [],\n      // Handle deletion\n      afterDelete: [\n        async ({ doc, req }) => {\n          if (!hasProviders || !doc?.providerId) return doc\n\n          try {\n            // Get provider (centralized initialization)\n            const provider = await getBroadcastProvider(req, pluginConfig)\n\n            // Only delete if broadcast is still editable\n            const capabilities = provider.getCapabilities()\n            if (capabilities.editableStatuses.includes(doc.sendStatus)) {\n              await provider.delete(doc.providerId)\n            }\n          } catch (error) {\n            // Log full error details for debugging\n            if (error instanceof Error) {\n              req.payload.logger.error('Failed to delete broadcast from provider:', {\n                message: error.message,\n                stack: error.stack,\n                name: error.name,\n                // If it's a BroadcastProviderError, it might have additional details\n                ...(error as any).details\n              })\n            } else {\n              req.payload.logger.error({ error: String(error) }, 'Failed to delete broadcast from provider')\n            }\n          }\n\n          return doc\n        },\n      ],\n    },\n  }\n}\n\n\n","import { \n  BoldFeature,\n  ItalicFeature,\n  UnderlineFeature,\n  StrikethroughFeature,\n  LinkFeature,\n  OrderedListFeature,\n  UnorderedListFeature,\n  HeadingFeature,\n  ParagraphFeature,\n  AlignFeature,\n  BlockquoteFeature,\n  BlocksFeature,\n  UploadFeature,\n  FixedToolbarFeature,\n  InlineToolbarFeature,\n  lexicalEditor,\n} from '@payloadcms/richtext-lexical'\nimport type { RichTextField, Block } from 'payload'\nimport { createEmailSafeBlocks } from '../utils/blockValidation'\n\n/**\n * Creates email-safe features for Lexical editor with optional additional blocks\n * Only includes features that render consistently across email clients\n */\n// Using any[] here because Payload's FeatureProviderServer type is complex\n// and varies between versions. The features are properly typed by Payload internally.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const createEmailSafeFeatures = (additionalBlocks?: Block[]): any[] => {\n  // Base email-safe blocks\n  const baseBlocks = [\n    {\n      slug: 'button',\n      fields: [\n        {\n          name: 'text',\n          type: 'text',\n          label: 'Button Text',\n          required: true,\n        },\n        {\n          name: 'url',\n          type: 'text',\n          label: 'Button URL',\n          required: true,\n          admin: {\n            description: 'Enter the full URL (including https://)',\n          },\n        },\n        {\n          name: 'style',\n          type: 'select',\n          label: 'Button Style',\n          defaultValue: 'primary',\n          options: [\n            { label: 'Primary', value: 'primary' },\n            { label: 'Secondary', value: 'secondary' },\n            { label: 'Outline', value: 'outline' },\n          ],\n        },\n      ],\n      interfaceName: 'EmailButton',\n      labels: {\n        singular: 'Button',\n        plural: 'Buttons',\n      },\n    },\n    {\n      slug: 'divider',\n      fields: [\n        {\n          name: 'style',\n          type: 'select',\n          label: 'Divider Style',\n          defaultValue: 'solid',\n          options: [\n            { label: 'Solid', value: 'solid' },\n            { label: 'Dashed', value: 'dashed' },\n            { label: 'Dotted', value: 'dotted' },\n          ],\n        },\n      ],\n      interfaceName: 'EmailDivider',\n      labels: {\n        singular: 'Divider',\n        plural: 'Dividers',\n      },\n    },\n  ] as Block[]\n\n  // Merge additional blocks if provided\n  const allBlocks = [\n    ...baseBlocks,\n    ...(additionalBlocks || [])\n  ]\n\n  return [\n    // Toolbars\n    FixedToolbarFeature(), // Fixed toolbar at the top\n    InlineToolbarFeature(), // Floating toolbar when text is selected\n    \n    // Basic text formatting\n    BoldFeature(),\n    ItalicFeature(),\n    UnderlineFeature(),\n    StrikethroughFeature(),\n    \n    // Links - use default fields to ensure drawer UI works correctly\n    LinkFeature(),\n    \n    // Lists\n    OrderedListFeature(),\n    UnorderedListFeature(),\n    \n    // Headings - limited to h1, h2, h3 for email compatibility\n    HeadingFeature({\n      enabledHeadingSizes: ['h1', 'h2', 'h3'],\n    }),\n    \n    // Basic paragraph and alignment\n    ParagraphFeature(),\n    AlignFeature(),\n    \n    // Blockquotes\n    BlockquoteFeature(),\n    \n    // Upload feature for images\n    UploadFeature({\n      collections: {\n        media: {\n          fields: [\n            {\n              name: 'caption',\n              type: 'text',\n              admin: {\n                description: 'Optional caption for the image',\n              },\n            },\n            {\n              name: 'altText',\n              type: 'text',\n              label: 'Alt Text',\n              required: true,\n              admin: {\n                description: 'Alternative text for accessibility and when image cannot be displayed',\n              },\n            },\n          ],\n        },\n      },\n    }),\n    \n    // Custom blocks for email-specific content\n    BlocksFeature({\n      blocks: allBlocks,\n    }),\n  ]\n}\n\n/**\n * Creates a Lexical editor configured specifically for email content\n * Processes blocks server-side to avoid client serialization issues\n */\nexport const createEmailLexicalEditor = (customBlocks: Block[] = []): any => {\n  const emailSafeBlocks = createEmailSafeBlocks(customBlocks)\n  \n  return lexicalEditor({\n    features: [\n      // Toolbars\n      FixedToolbarFeature(),\n      InlineToolbarFeature(),\n      \n      // Basic text formatting\n      BoldFeature(),\n      ItalicFeature(),\n      UnderlineFeature(),\n      StrikethroughFeature(),\n      \n      // Links - use default fields to ensure drawer UI works correctly\n      LinkFeature(),\n      \n      // Lists\n      OrderedListFeature(),\n      UnorderedListFeature(),\n      \n      // Headings - limited to h1, h2, h3 for email compatibility\n      HeadingFeature({\n        enabledHeadingSizes: ['h1', 'h2', 'h3'],\n      }),\n      \n      // Basic paragraph and alignment\n      ParagraphFeature(),\n      AlignFeature(),\n      \n      // Blockquotes\n      BlockquoteFeature(),\n      \n      // Upload feature for images\n      UploadFeature({\n        collections: {\n          media: {\n            fields: [\n              {\n                name: 'caption',\n                type: 'text',\n                admin: {\n                  description: 'Optional caption for the image',\n                },\n              },\n              {\n                name: 'altText',\n                type: 'text',\n                label: 'Alt Text',\n                required: true,\n                admin: {\n                  description: 'Alternative text for accessibility and when image cannot be displayed',\n                },\n              },\n            ],\n          },\n        },\n      }),\n      \n      // Email-safe blocks (processed server-side)\n      BlocksFeature({\n        blocks: emailSafeBlocks,\n      }),\n    ],\n  })\n}\n\n/**\n * Legacy export for backward compatibility\n */\nexport const emailSafeFeatures = createEmailSafeFeatures()\n\n/**\n * Creates an email-safe rich text field configuration\n */\nexport const createEmailContentField = (\n  overrides?: Partial<RichTextField> & {\n    additionalBlocks?: Block[]\n    editor?: any // Lexical editor instance\n  }\n): RichTextField => {\n  // Use provided editor or create one with blocks\n  const editor = overrides?.editor || createEmailLexicalEditor(overrides?.additionalBlocks)\n\n  return {\n    name: 'content',\n    type: 'richText',\n    required: true,\n    editor,\n    admin: {\n      description: 'Email content with limited formatting for compatibility',\n      ...overrides?.admin,\n    },\n    ...overrides,\n  }\n}","import type { Block } from 'payload'\n\n/**\n * Email-incompatible block types that should be warned about\n */\nconst EMAIL_INCOMPATIBLE_TYPES = [\n  'chart',\n  'dataTable', \n  'interactive',\n  'streamable',\n  'video',\n  'iframe',\n  'form',\n  'carousel',\n  'tabs',\n  'accordion',\n  'map'\n]\n\n/**\n * Validates that blocks are email-compatible and warns about potential issues\n */\nexport const validateEmailBlocks = (blocks: Block[]): void => {\n  blocks.forEach(block => {\n    if (EMAIL_INCOMPATIBLE_TYPES.includes(block.slug)) {\n      console.warn(`⚠️  Block \"${block.slug}\" may not be email-compatible. Consider creating an email-specific version.`)\n    }\n    \n    // Check for complex field types that might not work in emails\n    const hasComplexFields = block.fields?.some(field => {\n      const complexTypes = ['code', 'json', 'richText', 'blocks', 'array']\n      return complexTypes.includes(field.type)\n    })\n    \n    if (hasComplexFields) {\n      console.warn(`⚠️  Block \"${block.slug}\" contains complex field types that may not render consistently in email clients.`)\n    }\n  })\n}\n\n/**\n * Creates email-safe block configurations by filtering and validating blocks\n */\nexport const createEmailSafeBlocks = (customBlocks: Block[] = []): Block[] => {\n  // Validate blocks\n  validateEmailBlocks(customBlocks)\n  \n  // Base email-safe blocks that come with the plugin\n  const baseBlocks: Block[] = [\n    {\n      slug: 'button',\n      fields: [\n        {\n          name: 'text',\n          type: 'text',\n          label: 'Button Text',\n          required: true,\n        },\n        {\n          name: 'url',\n          type: 'text',\n          label: 'Button URL',\n          required: true,\n          admin: {\n            description: 'Enter the full URL (including https://)',\n          },\n        },\n        {\n          name: 'style',\n          type: 'select',\n          label: 'Button Style',\n          defaultValue: 'primary',\n          options: [\n            { label: 'Primary', value: 'primary' },\n            { label: 'Secondary', value: 'secondary' },\n            { label: 'Outline', value: 'outline' },\n          ],\n        },\n      ],\n      interfaceName: 'EmailButton',\n      labels: {\n        singular: 'Button',\n        plural: 'Buttons',\n      },\n    },\n    {\n      slug: 'divider',\n      fields: [\n        {\n          name: 'style',\n          type: 'select',\n          label: 'Divider Style',\n          defaultValue: 'solid',\n          options: [\n            { label: 'Solid', value: 'solid' },\n            { label: 'Dashed', value: 'dashed' },\n            { label: 'Dotted', value: 'dotted' },\n          ],\n        },\n      ],\n      interfaceName: 'EmailDivider',\n      labels: {\n        singular: 'Divider',\n        plural: 'Dividers',\n      },\n    },\n  ]\n  \n  // Combine base blocks with custom blocks\n  return [\n    ...baseBlocks,\n    ...customBlocks\n  ]\n}","import type { Field } from 'payload'\n\nexport const createBroadcastInlinePreviewField = (): Field => {\n  return {\n    name: 'broadcastInlinePreview',\n    type: 'ui',\n    admin: {\n      components: {\n        Field: 'payload-plugin-newsletter/components#BroadcastInlinePreview',\n      },\n    },\n  }\n}","import type { Field } from 'payload'\n\n/**\n * Creates a UI field that displays scheduling controls for broadcasts\n * Shows Schedule button for drafts, Cancel button for scheduled broadcasts\n */\nexport const createBroadcastScheduleField = (): Field => {\n  return {\n    name: 'scheduleControls',\n    type: 'ui',\n    label: 'Scheduling',\n    admin: {\n      components: {\n        Field: 'payload-plugin-newsletter/components#BroadcastScheduleField',\n      },\n    },\n  }\n}\n","import DOMPurify from 'isomorphic-dompurify'\nimport type { SerializedEditorState } from 'lexical'\n\n/**\n * DOMPurify configuration for email-safe HTML\n */\nexport const EMAIL_SAFE_CONFIG = {\n  ALLOWED_TAGS: [\n    'p', 'br', 'strong', 'b', 'em', 'i', 'u', 'strike', 's', 'span',\n    'a', 'h1', 'h2', 'h3', 'ul', 'ol', 'li', 'blockquote', 'hr',\n    'img', 'div', 'table', 'tr', 'td', 'th', 'tbody', 'thead'\n  ],\n  ALLOWED_ATTR: ['href', 'style', 'target', 'rel', 'align', 'src', 'alt', 'width', 'height', 'border', 'cellpadding', 'cellspacing'],\n  ALLOWED_STYLES: {\n    '*': [\n      'color', 'background-color', 'font-size', 'font-weight',\n      'font-style', 'text-decoration', 'text-align', 'margin',\n      'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n      'padding', 'padding-top', 'padding-right', 'padding-bottom', \n      'padding-left', 'line-height', 'border-left', 'border-left-width',\n      'border-left-style', 'border-left-color'\n    ],\n  },\n  FORBID_TAGS: ['script', 'style', 'iframe', 'object', 'embed', 'form', 'input'],\n  FORBID_ATTR: ['class', 'id', 'onclick', 'onload', 'onerror'],\n}\n\n/**\n * Converts Lexical editor state to email-safe HTML\n */\nexport async function convertToEmailSafeHtml(\n  editorState: SerializedEditorState | undefined | null,\n  options?: {\n    wrapInTemplate?: boolean\n    preheader?: string\n    mediaUrl?: string // Base URL for media files\n    customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n    payload?: any // Payload instance for populating relationships\n    populateFields?: string[] | ((blockType: string) => string[]) // Fields to populate\n    customWrapper?: (content: string, options?: { preheader?: string; subject?: string; documentData?: Record<string, any> }) => string | Promise<string>\n    subject?: string // Email subject for custom wrapper\n    documentData?: Record<string, any> // Generic document data for custom wrapper\n  }\n): Promise<string> {\n  // Handle empty content\n  if (!editorState) {\n    return ''\n  }\n  \n  // First, convert Lexical state to HTML using custom converters\n  const rawHtml = await lexicalToEmailHtml(editorState, options?.mediaUrl, options?.customBlockConverter)\n  \n  // Sanitize the HTML\n  const sanitizedHtml = DOMPurify.sanitize(rawHtml, EMAIL_SAFE_CONFIG)\n  \n  // Optionally wrap in email template\n  if (options?.wrapInTemplate) {\n    if (options.customWrapper) {\n      return await Promise.resolve(options.customWrapper(sanitizedHtml, { \n        preheader: options.preheader,\n        subject: options.subject,\n        documentData: options.documentData\n      }))\n    }\n    return wrapInEmailTemplate(sanitizedHtml, options.preheader)\n  }\n  \n  return sanitizedHtml\n}\n\n/**\n * Custom Lexical to HTML converter for email\n */\nasync function lexicalToEmailHtml(\n  editorState: SerializedEditorState, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const { root } = editorState\n  \n  if (!root || !root.children) {\n    return ''\n  }\n  \n  // Convert nodes asynchronously to support custom converters\n  const htmlParts = await Promise.all(\n    root.children.map((node: any) => convertNode(node, mediaUrl, customBlockConverter))\n  )\n  \n  return htmlParts.join('')\n}\n\n/**\n * Convert individual Lexical nodes to email-safe HTML\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertNode(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  switch (node.type) {\n    case 'paragraph':\n      return convertParagraph(node, mediaUrl, customBlockConverter)\n    case 'heading':\n      return convertHeading(node, mediaUrl, customBlockConverter)\n    case 'list':\n      return convertList(node, mediaUrl, customBlockConverter)\n    case 'listitem':\n      return convertListItem(node, mediaUrl, customBlockConverter)\n    case 'blockquote':\n      return convertBlockquote(node, mediaUrl, customBlockConverter)\n    case 'text':\n      return convertText(node)\n    case 'link':\n      return convertLink(node, mediaUrl, customBlockConverter)\n    case 'linebreak':\n      return '<br>'\n    case 'upload':\n      return convertUpload(node, mediaUrl)\n    case 'block':\n      return await convertBlock(node, mediaUrl, customBlockConverter)\n    default:\n      // Unknown node type - convert children if any\n      if (node.children) {\n        const childParts = await Promise.all(\n          node.children.map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n        )\n        return childParts.join('')\n      }\n      return ''\n  }\n}\n\n/**\n * Convert paragraph node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertParagraph(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const align = getAlignment(node.format)\n  const childParts = await Promise.all(\n    (node.children || []).map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n  )\n  const children = childParts.join('')\n  \n  if (!children.trim()) {\n    return '<p class=\"mobile-margin-bottom-16\" style=\"margin: 0 0 16px 0; min-height: 1em;\">&nbsp;</p>'\n  }\n  \n  return `<p class=\"mobile-margin-bottom-16\" style=\"margin: 0 0 16px 0; text-align: ${align}; font-size: 16px; line-height: 1.5;\">${children}</p>`\n}\n\n/**\n * Convert heading node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertHeading(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const tag = node.tag || 'h1'\n  const align = getAlignment(node.format)\n  const childParts = await Promise.all(\n    (node.children || []).map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n  )\n  const children = childParts.join('')\n  \n  const styles: Record<string, string> = {\n    h1: 'font-size: 32px; font-weight: 700; margin: 0 0 24px 0; line-height: 1.2;',\n    h2: 'font-size: 24px; font-weight: 600; margin: 0 0 16px 0; line-height: 1.3;',\n    h3: 'font-size: 20px; font-weight: 600; margin: 0 0 12px 0; line-height: 1.4;',\n  }\n  \n  const mobileClasses: Record<string, string> = {\n    h1: 'mobile-font-size-24',\n    h2: 'mobile-font-size-20',\n    h3: 'mobile-font-size-16',\n  }\n  \n  const style = `${styles[tag] || styles.h3} text-align: ${align};`\n  const mobileClass = mobileClasses[tag] || mobileClasses.h3\n  \n  return `<${tag} class=\"${mobileClass}\" style=\"${style}\">${children}</${tag}>`\n}\n\n/**\n * Convert list node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertList(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const tag = node.listType === 'number' ? 'ol' : 'ul'\n  const childParts = await Promise.all(\n    (node.children || []).map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n  )\n  const children = childParts.join('')\n  \n  const style = tag === 'ul' \n    ? 'margin: 0 0 16px 0; padding-left: 24px; list-style-type: disc; font-size: 16px; line-height: 1.5;'\n    : 'margin: 0 0 16px 0; padding-left: 24px; list-style-type: decimal; font-size: 16px; line-height: 1.5;'\n  \n  return `<${tag} class=\"mobile-margin-bottom-16\" style=\"${style}\">${children}</${tag}>`\n}\n\n/**\n * Convert list item node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertListItem(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const childParts = await Promise.all(\n    (node.children || []).map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n  )\n  const children = childParts.join('')\n  return `<li style=\"margin: 0 0 8px 0;\">${children}</li>`\n}\n\n/**\n * Convert blockquote node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertBlockquote(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const childParts = await Promise.all(\n    (node.children || []).map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n  )\n  const children = childParts.join('')\n  const style = 'margin: 0 0 16px 0; padding-left: 16px; border-left: 4px solid #e5e7eb; color: #6b7280;'\n  \n  return `<blockquote style=\"${style}\">${children}</blockquote>`\n}\n\n/**\n * Convert text node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction convertText(node: any): string {\n  let text = escapeHtml(node.text || '')\n  \n  // Apply formatting\n  if (node.format & 1) { // Bold\n    text = `<strong>${text}</strong>`\n  }\n  if (node.format & 2) { // Italic\n    text = `<em>${text}</em>`\n  }\n  if (node.format & 8) { // Underline\n    text = `<u>${text}</u>`\n  }\n  if (node.format & 4) { // Strikethrough\n    text = `<strike>${text}</strike>`\n  }\n  \n  return text\n}\n\n/**\n * Convert link node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertLink(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const childParts = await Promise.all(\n    (node.children || []).map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n  )\n  const children = childParts.join('')\n  const url = node.fields?.url || '#'\n  const newTab = node.fields?.newTab ?? false\n  \n  // Add target and rel attributes based on newTab setting\n  const targetAttr = newTab ? ' target=\"_blank\"' : ''\n  const relAttr = newTab ? ' rel=\"noopener noreferrer\"' : ''\n  \n  return `<a href=\"${escapeHtml(url)}\"${targetAttr}${relAttr} style=\"color: #2563eb; text-decoration: underline;\">${children}</a>`\n}\n\n/**\n * Convert upload (image) node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction convertUpload(node: any, mediaUrl?: string): string {\n  const upload = node.value\n  if (!upload) return ''\n  \n  // Get image URL - handle both direct URL and media object\n  let src = ''\n  if (typeof upload === 'string') {\n    src = upload\n  } else if (upload.url) {\n    src = upload.url\n  } else if (upload.filename && mediaUrl) {\n    // Construct URL from media URL and filename\n    src = `${mediaUrl}/${upload.filename}`\n  }\n  \n  const alt = node.fields?.altText || upload.alt || ''\n  const caption = node.fields?.caption || ''\n  \n  // Responsive email-safe image\n  const imgHtml = `<img src=\"${escapeHtml(src)}\" alt=\"${escapeHtml(alt)}\" class=\"mobile-width-100\" style=\"max-width: 100%; height: auto; display: block; margin: 0 auto; border-radius: 6px;\" />`\n  \n  if (caption) {\n    return `\n      <div style=\"margin: 0 0 16px 0; text-align: center;\" class=\"mobile-margin-bottom-16\">\n        ${imgHtml}\n        <p style=\"margin: 8px 0 0 0; font-size: 14px; color: #6b7280; font-style: italic; text-align: center;\" class=\"mobile-font-size-14\">${escapeHtml(caption)}</p>\n      </div>\n    `\n  }\n  \n  return `<div style=\"margin: 0 0 16px 0; text-align: center;\" class=\"mobile-margin-bottom-16\">${imgHtml}</div>`\n}\n\n/**\n * Convert custom block node\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function convertBlock(\n  node: any, \n  mediaUrl?: string,\n  customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>\n): Promise<string> {\n  const blockType = node.fields?.blockName || node.blockName\n  \n  // First, check if there's a custom converter for this block\n  if (customBlockConverter) {\n    try {\n      const customHtml = await customBlockConverter(node, mediaUrl)\n      if (customHtml) {\n        return customHtml\n      }\n    } catch (error) {\n      console.error(`Custom block converter error for ${blockType}:`, error)\n      // Fall through to default handling\n    }\n  }\n  \n  // Default handling for built-in blocks\n  switch (blockType) {\n    case 'button':\n      return convertButtonBlock(node.fields)\n    case 'divider':\n      return convertDividerBlock(node.fields)\n    default:\n      // Unknown block type - try to convert children\n      if (node.children) {\n        const childParts = await Promise.all(\n          node.children.map((child: any) => convertNode(child, mediaUrl, customBlockConverter))\n        )\n        return childParts.join('')\n      }\n      return ''\n  }\n}\n\n/**\n * Convert button block\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction convertButtonBlock(fields: any): string {\n  const text = fields?.text || 'Click here'\n  const url = fields?.url || '#'\n  const style = fields?.style || 'primary'\n  \n  const styles: Record<string, string> = {\n    primary: 'background-color: #2563eb; color: #ffffff; border: 2px solid #2563eb;',\n    secondary: 'background-color: #6b7280; color: #ffffff; border: 2px solid #6b7280;',\n    outline: 'background-color: transparent; color: #2563eb; border: 2px solid #2563eb;',\n  }\n  \n  const buttonStyle = `${styles[style] || styles.primary} display: inline-block; padding: 12px 24px; font-size: 16px; font-weight: 600; text-decoration: none; border-radius: 6px; text-align: center;`\n  \n  return `\n    <div style=\"margin: 0 0 16px 0; text-align: center;\">\n      <a href=\"${escapeHtml(url)}\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"${buttonStyle}\">${escapeHtml(text)}</a>\n    </div>\n  `\n}\n\n/**\n * Convert divider block\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction convertDividerBlock(fields: any): string {\n  const style = fields?.style || 'solid'\n  \n  const styles: Record<string, string> = {\n    solid: 'border-top: 1px solid #e5e7eb;',\n    dashed: 'border-top: 1px dashed #e5e7eb;',\n    dotted: 'border-top: 1px dotted #e5e7eb;',\n  }\n  \n  return `<hr style=\"${styles[style] || styles.solid} margin: 24px 0; border-bottom: none; border-left: none; border-right: none;\" />`\n}\n\n/**\n * Get text alignment from format number\n */\nfunction getAlignment(format?: number): string {\n  if (!format) return 'left'\n  \n  // Lexical alignment format values\n  if (format & 2) return 'center'\n  if (format & 3) return 'right'\n  if (format & 4) return 'justify'\n  \n  return 'left'\n}\n\n/**\n * Escape HTML special characters\n */\nfunction escapeHtml(text: string): string {\n  const map: Record<string, string> = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#039;'\n  }\n  \n  return text.replace(/[&<>\"']/g, m => map[m])\n}\n\n/**\n * Wrap content in a responsive email template\n */\nfunction wrapInEmailTemplate(content: string, preheader?: string): string {\n  return `<!DOCTYPE html>\n<html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"x-apple-disable-message-reformatting\">\n  <title>Newsletter</title>\n  \n  <!--[if mso]>\n  <noscript>\n    <xml>\n      <o:OfficeDocumentSettings>\n        <o:PixelsPerInch>96</o:PixelsPerInch>\n      </o:OfficeDocumentSettings>\n    </xml>\n  </noscript>\n  <![endif]-->\n  \n  <style>\n    /* Reset and base styles */\n    * {\n      -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n    }\n    \n    body {\n      margin: 0 !important;\n      padding: 0 !important;\n      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;\n      font-size: 16px;\n      line-height: 1.5;\n      color: #1A1A1A;\n      background-color: #f8f9fa;\n      -webkit-font-smoothing: antialiased;\n      -moz-osx-font-smoothing: grayscale;\n    }\n    \n    table {\n      border-spacing: 0 !important;\n      border-collapse: collapse !important;\n      table-layout: fixed !important;\n      margin: 0 auto !important;\n    }\n    \n    table table table {\n      table-layout: auto;\n    }\n    \n    img {\n      -ms-interpolation-mode: bicubic;\n      max-width: 100%;\n      height: auto;\n      border: 0;\n      outline: none;\n      text-decoration: none;\n    }\n    \n    /* Responsive styles */\n    @media only screen and (max-width: 640px) {\n      .mobile-hide {\n        display: none !important;\n      }\n      \n      .mobile-center {\n        text-align: center !important;\n      }\n      \n      .mobile-width-100 {\n        width: 100% !important;\n        max-width: 100% !important;\n      }\n      \n      .mobile-padding {\n        padding: 20px !important;\n      }\n      \n      .mobile-padding-sm {\n        padding: 16px !important;\n      }\n      \n      .mobile-font-size-14 {\n        font-size: 14px !important;\n      }\n      \n      .mobile-font-size-16 {\n        font-size: 16px !important;\n      }\n      \n      .mobile-font-size-20 {\n        font-size: 20px !important;\n        line-height: 1.3 !important;\n      }\n      \n      .mobile-font-size-24 {\n        font-size: 24px !important;\n        line-height: 1.2 !important;\n      }\n      \n      /* Stack sections on mobile */\n      .mobile-stack {\n        display: block !important;\n        width: 100% !important;\n      }\n      \n      /* Mobile-specific spacing */\n      .mobile-margin-bottom-16 {\n        margin-bottom: 16px !important;\n      }\n      \n      .mobile-margin-bottom-20 {\n        margin-bottom: 20px !important;\n      }\n    }\n    \n    /* Dark mode support */\n    @media (prefers-color-scheme: dark) {\n      .dark-mode-bg {\n        background-color: #1a1a1a !important;\n      }\n      \n      .dark-mode-text {\n        color: #ffffff !important;\n      }\n      \n      .dark-mode-border {\n        border-color: #333333 !important;\n      }\n    }\n    \n    /* Outlook-specific fixes */\n    <!--[if mso]>\n    <style>\n      table {\n        border-collapse: collapse;\n        border-spacing: 0;\n        border: none;\n        margin: 0;\n      }\n      \n      div, p {\n        margin: 0;\n      }\n    </style>\n    <![endif]-->\n  </style>\n</head>\n<body style=\"margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 16px; line-height: 1.5; color: #1A1A1A; background-color: #f8f9fa;\">\n  ${preheader ? `\n  <!-- Preheader text -->\n  <div style=\"display: none; max-height: 0; overflow: hidden; font-size: 1px; line-height: 1px; color: transparent;\">\n    ${escapeHtml(preheader)}\n  </div>\n  ` : ''}\n  \n  <!-- Main container -->\n  <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"margin: 0; padding: 0; background-color: #f8f9fa;\">\n    <tr>\n      <td align=\"center\" style=\"padding: 20px 10px;\">\n        <!-- Email wrapper -->\n        <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" width=\"600\" class=\"mobile-width-100\" style=\"margin: 0 auto; max-width: 600px;\">\n          <tr>\n            <td class=\"mobile-padding\" style=\"padding: 0;\">\n              <!-- Content area with light background -->\n              <div style=\"background-color: #ffffff; padding: 40px 30px; border-radius: 8px;\" class=\"mobile-padding\">\n                ${content}\n              </div>\n            </td>\n          </tr>\n        </table>\n      </td>\n    </tr>\n  </table>\n</body>\n</html>`\n}\n\n/**\n * Extract personalization tags from content\n */\nexport function extractPersonalizationTags(html: string): string[] {\n  const regex = /\\{\\{([^}]+)\\}\\}/g\n  const tags: string[] = []\n  let match\n  \n  while ((match = regex.exec(html)) !== null) {\n    tags.push(match[1].trim())\n  }\n  \n  return [...new Set(tags)]\n}\n\n/**\n * Replace personalization tags with sample data\n */\nexport function replacePersonalizationTags(\n  html: string, \n  sampleData: Record<string, string>\n): string {\n  return html.replace(/\\{\\{([^}]+)\\}\\}/g, (match, tag) => {\n    const trimmedTag = tag.trim()\n    return sampleData[trimmedTag] || match\n  })\n}","import type { PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig, BroadcastProviderConfig } from '../types'\n\nconst BROADCAST_CONFIG_CACHE_KEY = 'broadcastConfig'\n\nexport async function getBroadcastConfig(\n  req: PayloadRequest,\n  pluginConfig: NewsletterPluginConfig\n): Promise<BroadcastProviderConfig | null> {\n  // Check request context cache first to avoid duplicate database queries\n  const cached = req.context?.[BROADCAST_CONFIG_CACHE_KEY] as BroadcastProviderConfig | null | undefined\n  if (cached !== undefined) {\n    return cached\n  }\n\n  try {\n    // Get settings from Newsletter Settings collection\n    const settings = await req.payload.findGlobal({\n      slug: pluginConfig.settingsSlug || 'newsletter-settings',\n      req,\n    })\n\n    // Build provider config from settings, falling back to env vars\n    let result: BroadcastProviderConfig | null = null\n\n    if (settings?.provider === 'broadcast' && settings?.broadcastSettings) {\n      result = {\n        apiUrl: settings.broadcastSettings.apiUrl || pluginConfig.providers?.broadcast?.apiUrl || '',\n        token: settings.broadcastSettings.token || pluginConfig.providers?.broadcast?.token || '',\n        fromAddress: settings.fromAddress || pluginConfig.providers?.broadcast?.fromAddress || '',\n        fromName: settings.fromName || pluginConfig.providers?.broadcast?.fromName || '',\n        replyTo: settings.replyTo || pluginConfig.providers?.broadcast?.replyTo,\n      }\n    } else {\n      // Fall back to env var config\n      result = pluginConfig.providers?.broadcast || null\n    }\n\n    // Cache in request context for subsequent calls\n    if (req.context) {\n      req.context[BROADCAST_CONFIG_CACHE_KEY] = result\n    }\n\n    return result\n  } catch (error) {\n    req.payload.logger.error({ error: String(error) }, 'Failed to get broadcast config from settings')\n    // Fall back to env var config on error\n    const fallback = pluginConfig.providers?.broadcast || null\n\n    // Cache the fallback too\n    if (req.context) {\n      req.context[BROADCAST_CONFIG_CACHE_KEY] = fallback\n    }\n\n    return fallback\n  }\n}","import type { PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { getBroadcastConfig } from './getBroadcastConfig'\nimport { BroadcastProviderError, BroadcastErrorCode } from '../types/broadcast'\n\n/**\n * Get an initialized Broadcast API provider instance.\n * Centralizes provider initialization to reduce duplication across hooks and endpoints.\n *\n * @param req - Payload request object\n * @param pluginConfig - Newsletter plugin configuration\n * @returns Initialized BroadcastApiProvider instance\n * @throws BroadcastProviderError if provider is not configured\n */\nexport async function getBroadcastProvider(\n  req: PayloadRequest,\n  pluginConfig: NewsletterPluginConfig\n) {\n  const config = await getBroadcastConfig(req, pluginConfig)\n\n  if (!config?.token) {\n    throw new BroadcastProviderError(\n      'Broadcast provider not configured. Check Newsletter Settings or environment variables.',\n      BroadcastErrorCode.CONFIGURATION_ERROR,\n      'broadcast'\n    )\n  }\n\n  const { BroadcastApiProvider } = await import('../providers/broadcast/broadcast')\n  return new BroadcastApiProvider(config)\n}\n","import type { Payload } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\n/**\n * Recursively populates media fields in Lexical content.\n * Resolves Media IDs to full media objects with URLs.\n *\n * @param content - Lexical editor state content\n * @param payload - Payload instance for database queries\n * @param config - Newsletter plugin configuration\n * @returns Populated content with resolved media objects\n */\nexport async function populateMediaFields(\n  content: unknown,\n  payload: Payload,\n  config: NewsletterPluginConfig\n): Promise<unknown> {\n  if (!content || typeof content !== 'object') return content\n\n  const typedContent = content as { root?: { children?: unknown[] } }\n\n  // Handle Lexical editor state\n  if (typedContent.root?.children) {\n    for (const child of typedContent.root.children) {\n      await populateBlockMediaFields(child, payload, config)\n    }\n  }\n\n  return content\n}\n\n/**\n * Populates media fields in individual block nodes.\n * Handles upload fields, arrays of uploads, and rich text fields.\n */\nasync function populateBlockMediaFields(\n  node: unknown,\n  payload: Payload,\n  config: NewsletterPluginConfig\n): Promise<void> {\n  if (!node || typeof node !== 'object') return\n\n  const typedNode = node as {\n    type?: string\n    fields?: Record<string, unknown>\n    children?: unknown[]\n  }\n\n  // Check if this is a block node\n  if (typedNode.type === 'block' && typedNode.fields) {\n    const blockType = (typedNode.fields.blockType || typedNode.fields.blockName) as string | undefined\n\n    // Get custom blocks configuration\n    const customBlocks = config.customizations?.broadcasts?.customBlocks || []\n    const blockConfig = customBlocks.find((b: { slug: string }) => b.slug === blockType)\n\n    if (blockConfig && blockConfig.fields) {\n      // Find all upload fields in the block\n      for (const field of blockConfig.fields) {\n        if (field.type === 'upload' && field.relationTo && typedNode.fields[field.name]) {\n          const fieldValue = typedNode.fields[field.name]\n          const collectionName = Array.isArray(field.relationTo) ? field.relationTo[0] : field.relationTo\n\n          // If it's just an ID string, populate it\n          if (typeof fieldValue === 'string' && fieldValue.match(/^[a-f0-9]{24}$/i)) {\n            try {\n              const media = await payload.findByID({\n                collection: collectionName,\n                id: fieldValue,\n                depth: 0,\n              })\n\n              if (media) {\n                typedNode.fields[field.name] = media\n                payload.logger?.info(\n                  {\n                    mediaId: fieldValue,\n                    mediaUrl: (media as { url?: string }).url,\n                    filename: (media as { filename?: string }).filename,\n                  },\n                  `Populated ${field.name} for block ${blockType}`\n                )\n              }\n            } catch (error) {\n              payload.logger?.error(\n                { error: String(error) },\n                `Failed to populate ${field.name} for block ${blockType}`\n              )\n            }\n          }\n        }\n\n        // Also handle arrays of uploads\n        if (field.type === 'array' && field.fields) {\n          const arrayValue = typedNode.fields[field.name]\n          if (Array.isArray(arrayValue)) {\n            for (const arrayItem of arrayValue) {\n              if (arrayItem && typeof arrayItem === 'object') {\n                const typedArrayItem = arrayItem as Record<string, unknown>\n                // Recursively process array items for upload fields\n                for (const arrayField of field.fields) {\n                  if (\n                    arrayField.type === 'upload' &&\n                    arrayField.relationTo &&\n                    typedArrayItem[arrayField.name]\n                  ) {\n                    const arrayFieldValue = typedArrayItem[arrayField.name]\n                    const arrayCollectionName = Array.isArray(arrayField.relationTo)\n                      ? arrayField.relationTo[0]\n                      : arrayField.relationTo\n\n                    if (\n                      typeof arrayFieldValue === 'string' &&\n                      arrayFieldValue.match(/^[a-f0-9]{24}$/i)\n                    ) {\n                      try {\n                        const media = await payload.findByID({\n                          collection: arrayCollectionName,\n                          id: arrayFieldValue,\n                          depth: 0,\n                        })\n\n                        if (media) {\n                          typedArrayItem[arrayField.name] = media\n                          payload.logger?.info(\n                            {\n                              mediaId: arrayFieldValue,\n                              mediaUrl: (media as { url?: string }).url,\n                              filename: (media as { filename?: string }).filename,\n                            },\n                            `Populated array ${arrayField.name} for block ${blockType}`\n                          )\n                        }\n                      } catch (error) {\n                        payload.logger?.error(\n                          { error: String(error) },\n                          `Failed to populate array ${arrayField.name} for block ${blockType}`\n                        )\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          }\n        }\n\n        // Also handle rich text fields\n        if (field.type === 'richText' && typedNode.fields[field.name]) {\n          await populateRichTextUploads(typedNode.fields[field.name], payload)\n          payload.logger?.info(`Processed rich text field ${field.name} for upload nodes`)\n        }\n      }\n    }\n  }\n\n  // Recursively process children\n  if (typedNode.children) {\n    for (const child of typedNode.children) {\n      await populateBlockMediaFields(child, payload, config)\n    }\n  }\n}\n\n/**\n * Populates upload nodes within rich text content.\n * Resolves media IDs to full media objects.\n */\nasync function populateRichTextUploads(content: unknown, payload: Payload): Promise<void> {\n  if (!content || typeof content !== 'object') return\n\n  const typedContent = content as {\n    root?: { children?: unknown[] }\n  }\n\n  // Handle Lexical root structure\n  if (typedContent.root?.children) {\n    await processNodeArray(typedContent.root.children)\n  }\n\n  // Handle direct children array\n  if (Array.isArray(content)) {\n    await processNodeArray(content)\n  }\n\n  async function processNodeArray(nodes: unknown[]): Promise<void> {\n    await Promise.all(nodes.map(processNode))\n  }\n\n  async function processNode(node: unknown): Promise<void> {\n    if (!node || typeof node !== 'object') return\n\n    const typedNode = node as {\n      type?: string\n      relationTo?: string\n      value?: unknown\n      children?: unknown[]\n      root?: { children?: unknown[] }\n    }\n\n    // Check if this is an upload node with unpopulated value\n    if (\n      typedNode.type === 'upload' &&\n      typedNode.relationTo === 'media' &&\n      typeof typedNode.value === 'string' &&\n      typedNode.value.match(/^[a-f0-9]{24}$/i)\n    ) {\n      try {\n        const media = await payload.findByID({\n          collection: 'media',\n          id: typedNode.value,\n          depth: 0,\n        })\n\n        if (media) {\n          typedNode.value = media\n          payload.logger?.info(\n            {\n              mediaId: typedNode.value,\n              mediaUrl: (media as { url?: string }).url,\n              filename: (media as { filename?: string }).filename,\n            },\n            'Populated rich text upload node'\n          )\n        }\n      } catch (error) {\n        payload.logger?.error(\n          { error: String(error) },\n          `Failed to populate rich text upload ${typedNode.value}`\n        )\n      }\n    }\n\n    // Recursively process children\n    if (typedNode.children && Array.isArray(typedNode.children)) {\n      await processNodeArray(typedNode.children)\n    }\n\n    // Also check for root property (some Lexical structures)\n    if (typedNode.root?.children && Array.isArray(typedNode.root.children)) {\n      await processNodeArray(typedNode.root.children)\n    }\n  }\n}\n","import type { Endpoint, PayloadHandler, PayloadRequest } from 'payload'\nimport type { SerializedEditorState } from 'lexical'\nimport type { NewsletterPluginConfig } from '../../types'\nimport { convertToEmailSafeHtml } from '../../utils/emailSafeHtml'\nimport { populateMediaFields } from '../../utils/mediaPopulation'\n\n// Re-export for backwards compatibility\nexport { populateMediaFields } from '../../utils/mediaPopulation'\n\nexport const createBroadcastPreviewEndpoint = (\n  config: NewsletterPluginConfig,\n  _collectionSlug: string\n): Endpoint => {\n  return {\n    path: '/preview',\n    method: 'post',\n    handler: (async (req: PayloadRequest) => {\n      try {\n        // Parse request body\n        const data = await (req.json?.() || Promise.resolve({}))\n        const { content, preheader, subject, documentData } = data\n\n        if (!content) {\n          return Response.json({\n            success: false,\n            error: 'Content is required for preview',\n          }, { status: 400 })\n        }\n\n        // Get media URL from payload config or use default\n        const mediaUrl = req.payload.config.serverURL \n          ? `${req.payload.config.serverURL}/api/media`\n          : '/api/media'\n\n        // Populate media fields in custom blocks before conversion\n        req.payload.logger?.info('Populating media fields for email preview...')\n        const populatedContent = await populateMediaFields(content, req.payload, config)\n\n        // Get email preview customization options\n        const emailPreviewConfig = config.customizations?.broadcasts?.emailPreview\n        \n        // Convert content to email-safe HTML with customization options\n        const htmlContent = await convertToEmailSafeHtml(populatedContent as SerializedEditorState | null, {\n          wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,\n          preheader: preheader,\n          subject: subject,\n          mediaUrl: mediaUrl,\n          documentData, // Pass all document data\n          customBlockConverter: config.customizations?.broadcasts?.customBlockConverter,\n          customWrapper: emailPreviewConfig?.customWrapper,\n        })\n\n        return Response.json({\n          success: true,\n          html: htmlContent,\n          preview: {\n            subject: subject || 'Preview',\n            preheader: preheader || '',\n            html: htmlContent,\n          },\n        })\n      } catch (error) {\n        console.error('Failed to generate email preview:', error)\n        \n        return Response.json({\n          success: false,\n          error: 'Failed to generate email preview',\n        }, { status: 500 })\n      }\n    }) as PayloadHandler,\n  }\n}","import { BroadcastProviderError } from '../types/broadcast'\n\n/**\n * Extract error message from unknown error type.\n * Provides proper type narrowing for error handling.\n *\n * @param error - Unknown error value from catch block\n * @returns Human-readable error message string\n */\nexport function getErrorMessage(error: unknown): string {\n  if (error instanceof BroadcastProviderError) {\n    return `${error.code}: ${error.message}`\n  }\n  if (error instanceof Error) {\n    return error.message\n  }\n  return String(error)\n}\n\n/**\n * Extract structured error info for logging.\n * Provides consistent error object shape for pino logger.\n *\n * @param error - Unknown error value from catch block\n * @returns Structured error object for logging\n */\nexport function getErrorDetails(error: unknown): Record<string, unknown> {\n  if (error instanceof Error) {\n    return {\n      message: error.message,\n      name: error.name,\n      stack: error.stack,\n      ...(error instanceof BroadcastProviderError ? { code: error.code } : {}),\n    }\n  }\n  return { message: String(error) }\n}\n","import type { PayloadRequest } from 'payload'\nimport type { SerializedEditorState } from 'lexical'\nimport type { NewsletterPluginConfig, BroadcastProviderConfig } from '../types'\nimport type { ProviderCreateData, ProviderSyncResult, AudienceIdField } from '../types/broadcast'\nimport { convertToEmailSafeHtml } from './emailSafeHtml'\nimport { populateMediaFields } from '../endpoints/broadcasts/preview'\nimport { getErrorMessage } from './getErrorMessage'\n\n/**\n * Document shape for checking sync eligibility\n */\ninterface SyncEligibleDocument {\n  subject?: string | null\n  contentSection?: {\n    content?: unknown\n  } | null\n}\n\n/**\n * Document shape for building provider create data\n */\ninterface ProviderDocumentData {\n  subject: string\n  contentSection?: {\n    content?: unknown\n    preheader?: string\n  }\n  settings?: {\n    trackOpens?: boolean\n    trackClicks?: boolean\n    replyTo?: string\n  }\n  audienceIds?: AudienceIdField[]\n}\n\n/**\n * Provider interface for creating broadcasts\n */\ninterface BroadcastProvider {\n  create: (data: ProviderCreateData) => Promise<{ id: string; providerData?: unknown }>\n}\n\n/**\n * Check if a broadcast has sufficient content for provider sync.\n * Requires both subject and content to be present.\n */\nexport function shouldSyncToProvider(doc: SyncEligibleDocument): boolean {\n  return Boolean(doc.subject && doc.contentSection?.content)\n}\n\n/**\n * Build the data object required for creating a broadcast in the provider.\n * Handles HTML conversion and media population.\n */\nexport async function buildProviderCreateData(\n  doc: ProviderDocumentData,\n  req: PayloadRequest,\n  pluginConfig: NewsletterPluginConfig,\n  providerConfig: BroadcastProviderConfig | null\n): Promise<ProviderCreateData> {\n  const populatedContent = await populateMediaFields(\n    doc.contentSection?.content,\n    req.payload,\n    pluginConfig\n  ) as SerializedEditorState | null\n\n  const htmlContent = await convertToEmailSafeHtml(populatedContent, {\n    wrapInTemplate: pluginConfig.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,\n    customWrapper: pluginConfig.customizations?.broadcasts?.emailPreview?.customWrapper,\n    preheader: doc.contentSection?.preheader,\n    subject: doc.subject,\n    documentData: doc,\n    customBlockConverter: pluginConfig.customizations?.broadcasts?.customBlockConverter\n  })\n\n  return {\n    name: doc.subject,\n    subject: doc.subject,\n    preheader: doc.contentSection?.preheader || '',\n    content: htmlContent,\n    trackOpens: doc.settings?.trackOpens ?? true,\n    trackClicks: doc.settings?.trackClicks ?? true,\n    replyTo: doc.settings?.replyTo || providerConfig?.replyTo,\n    audienceIds: doc.audienceIds?.map((a) => a.audienceId) || [],\n  }\n}\n\n/**\n * Sync a broadcast to the provider (create operation).\n * Returns success with IDs or failure with error message.\n *\n * This function handles errors gracefully and returns a result object\n * rather than throwing, allowing callers to decide how to handle failures.\n */\nexport async function syncBroadcastToProvider(\n  doc: ProviderDocumentData,\n  req: PayloadRequest,\n  pluginConfig: NewsletterPluginConfig,\n  providerConfig: BroadcastProviderConfig | null,\n  provider: BroadcastProvider\n): Promise<ProviderSyncResult> {\n  try {\n    const createData = await buildProviderCreateData(doc, req, pluginConfig, providerConfig)\n    const providerBroadcast = await provider.create(createData)\n\n    return {\n      success: true,\n      providerId: providerBroadcast.id,\n      externalId: providerBroadcast.id,\n      providerData: providerBroadcast.providerData,\n    }\n  } catch (error: unknown) {\n    return {\n      success: false,\n      error: getErrorMessage(error),\n    }\n  }\n}\n","import type { BroadcastDocument, StateTransition } from '../types/scheduling'\nimport { BroadcastStatus } from '../types/broadcast'\n\n// =============================================================================\n// State Factory Functions\n// =============================================================================\n// These functions return guaranteed-valid state objects for database updates.\n// Using these instead of manually constructing objects prevents invalid states\n// like { sendStatus: 'draft', scheduledAt: '2024-01-01' }.\n\n/**\n * Create a valid draft state. Draft broadcasts cannot have a scheduledAt time.\n */\nexport function draftState(): { sendStatus: BroadcastStatus.DRAFT; scheduledAt: null } {\n  return { sendStatus: BroadcastStatus.DRAFT, scheduledAt: null }\n}\n\n/**\n * Create a valid scheduled state. Scheduled broadcasts must have a scheduledAt time.\n */\nexport function scheduledState(scheduledAt: Date): { sendStatus: BroadcastStatus.SCHEDULED; scheduledAt: string } {\n  return { sendStatus: BroadcastStatus.SCHEDULED, scheduledAt: scheduledAt.toISOString() }\n}\n\n/**\n * Create a valid sending state.\n */\nexport function sendingState(): { sendStatus: BroadcastStatus.SENDING } {\n  return { sendStatus: BroadcastStatus.SENDING }\n}\n\n/**\n * Create a valid sent state.\n */\nexport function sentState(): { sendStatus: BroadcastStatus.SENT } {\n  return { sendStatus: BroadcastStatus.SENT }\n}\n\n/**\n * Create a valid failed state.\n */\nexport function failedState(): { sendStatus: BroadcastStatus.FAILED } {\n  return { sendStatus: BroadcastStatus.FAILED }\n}\n\n// =============================================================================\n// State Transition Detection\n// =============================================================================\n\n/**\n * Detect all relevant state transitions for scheduling logic.\n * Pure function for easy testing.\n *\n * @param previousDoc - The document state before the change (may be undefined on create)\n * @param currentDoc - The current document state after the change\n * @returns StateTransition object describing what changed\n */\nexport function detectStateTransition(\n  previousDoc: BroadcastDocument | undefined,\n  currentDoc: BroadcastDocument\n): StateTransition {\n  const wasUnpublished = !previousDoc?._status || previousDoc._status === 'draft'\n  const isNowPublished = currentDoc._status === 'published'\n\n  // Scheduled = draft status with future publishedAt\n  const wasScheduled = previousDoc?._status === 'draft' && !!previousDoc?.publishedAt\n  const isNoLongerScheduled = currentDoc._status === 'draft' && !currentDoc.publishedAt\n\n  const scheduleTimeChanged = previousDoc?.publishedAt !== currentDoc.publishedAt\n\n  // Manual publish = was scheduled but now published without waiting for job\n  // Detected when: was draft+scheduled, now published, but publishedAt is still in the future\n  const publishedAtDate = currentDoc.publishedAt ? new Date(currentDoc.publishedAt) : null\n  const isManualPublish =\n    wasUnpublished &&\n    isNowPublished &&\n    publishedAtDate !== null &&\n    publishedAtDate.getTime() > Date.now()\n\n  return {\n    wasUnpublished,\n    isNowPublished,\n    wasScheduled,\n    isNoLongerScheduled,\n    scheduleTimeChanged,\n    isManualPublish,\n  }\n}\n\n/**\n * Check if two dates represent the same scheduled time.\n * Handles string/Date comparison safely.\n *\n * @param a - Scheduled time as ISO string (from document)\n * @param b - Scheduled time as Date object\n * @returns true if times are equal, false otherwise\n */\nexport function areScheduledTimesEqual(\n  a: string | null | undefined,\n  b: Date | null\n): boolean {\n  if (!a || !b) return false\n  return new Date(a).getTime() === b.getTime()\n}\n\n/**\n * Validate a date string and return a Date object or null.\n * Returns null for invalid or missing date strings.\n *\n * @param dateStr - ISO date string to parse\n * @returns Date object if valid, null otherwise\n */\nexport function parseScheduledDate(dateStr: string | null | undefined): Date | null {\n  if (!dateStr) return null\n  const date = new Date(dateStr)\n  if (Number.isNaN(date.getTime())) return null\n  return date\n}\n","/**\n * Simple in-memory idempotency tracking for provider operations.\n * Prevents duplicate API calls when database updates fail after successful provider calls.\n *\n * Keys expire after TTL to allow retries after reasonable time.\n */\n\ninterface IdempotencyEntry {\n  completedAt: number\n  result: unknown\n}\n\n// In-memory store for completed operations\nconst completedOperations = new Map<string, IdempotencyEntry>()\n\n// Default TTL: 5 minutes (operations older than this can be retried)\nconst DEFAULT_TTL_MS = 5 * 60 * 1000\n\n/**\n * Generate an idempotency key for a provider operation.\n *\n * @param broadcastId - The broadcast document ID\n * @param operation - The operation type (schedule, send, cancel)\n * @param params - Operation-specific parameters (e.g., scheduledAt timestamp)\n * @returns A unique key for this operation\n */\nexport function generateIdempotencyKey(\n  broadcastId: string,\n  operation: 'schedule' | 'send' | 'cancel',\n  params?: Record<string, string | number>\n): string {\n  const paramStr = params ? Object.entries(params).sort().map(([k, v]) => `${k}=${v}`).join('&') : ''\n  return `${broadcastId}:${operation}:${paramStr}`\n}\n\n/**\n * Check if an operation was recently completed successfully.\n * Used to prevent duplicate provider calls after DB update failures.\n *\n * @param key - Idempotency key from generateIdempotencyKey\n * @param ttlMs - Time-to-live in milliseconds (default: 5 minutes)\n * @returns The cached result if operation was recently completed, undefined otherwise\n */\nexport function getCompletedOperation<T = unknown>(\n  key: string,\n  ttlMs: number = DEFAULT_TTL_MS\n): T | undefined {\n  const entry = completedOperations.get(key)\n\n  if (!entry) {\n    return undefined\n  }\n\n  // Check if expired\n  if (Date.now() - entry.completedAt > ttlMs) {\n    completedOperations.delete(key)\n    return undefined\n  }\n\n  return entry.result as T\n}\n\n/**\n * Mark an operation as completed.\n * Call this after a successful provider operation.\n *\n * @param key - Idempotency key from generateIdempotencyKey\n * @param result - The result to cache\n */\nexport function markOperationCompleted(key: string, result: unknown): void {\n  completedOperations.set(key, {\n    completedAt: Date.now(),\n    result,\n  })\n\n  // Cleanup old entries periodically (every 100 operations)\n  if (completedOperations.size > 100) {\n    cleanupExpiredEntries()\n  }\n}\n\n/**\n * Clear a specific idempotency key.\n * Useful when you want to allow a retry.\n *\n * @param key - Idempotency key to clear\n */\nexport function clearIdempotencyKey(key: string): void {\n  completedOperations.delete(key)\n}\n\n/**\n * Remove expired entries from the cache.\n */\nfunction cleanupExpiredEntries(ttlMs: number = DEFAULT_TTL_MS): void {\n  const now = Date.now()\n  for (const [key, entry] of completedOperations.entries()) {\n    if (now - entry.completedAt > ttlMs) {\n      completedOperations.delete(key)\n    }\n  }\n}\n\n/**\n * Clear all idempotency tracking (useful for testing).\n */\nexport function clearAllIdempotencyKeys(): void {\n  completedOperations.clear()\n}\n","import type { Endpoint, PayloadHandler, PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig, SendBroadcastOptions } from '../../types'\nimport { NewsletterProviderError, NewsletterStatus } from '../../types'\nimport { requireAdmin } from '../../utils/auth'\nimport { getBroadcastProvider } from '../../utils/getProvider'\nimport { BroadcastProviderError } from '../../types/broadcast'\n\nexport const createSendBroadcastEndpoint = (\n  config: NewsletterPluginConfig,\n  collectionSlug: string\n): Endpoint => {\n  return {\n    path: '/:id/send',\n    method: 'post',\n    handler: (async (req: PayloadRequest) => {\n      try {\n        // Check authentication\n        const auth = await requireAdmin(req, config)\n        if (!auth.authorized) {\n          return Response.json({\n            success: false,\n            error: auth.error,\n          }, { status: 401 })\n        }\n\n        // Check if broadcast management is enabled\n        if (!config.features?.newsletterManagement?.enabled) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast management is not enabled',\n          }, { status: 400 })\n        }\n\n        // Get ID from URL\n        const url = new URL(req.url || '', `http://localhost`)\n        const pathParts = url.pathname.split('/')\n        const id = pathParts[pathParts.length - 2] // -2 because last part is 'send'\n\n        if (!id) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast ID is required',\n          }, { status: 400 })\n        }\n\n        // Parse request body\n        const data = await (req.json?.() || Promise.resolve({})) as SendBroadcastOptions\n\n        // Get the broadcast document\n        const broadcastDoc = await req.payload.findByID({\n          collection: collectionSlug,\n          id,\n          user: auth.user,\n        })\n\n        if (!broadcastDoc || !broadcastDoc.providerId) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast not found or not synced with provider',\n          }, { status: 404 })\n        }\n\n        // Get provider (centralized initialization)\n        const provider = await getBroadcastProvider(req, config)\n\n        // Send broadcast using provider ID\n        const broadcast = await provider.send(broadcastDoc.providerId, data)\n\n        // Update status in Payload collection\n        await req.payload.update({\n          collection: collectionSlug,\n          id,\n          data: {\n            sendStatus: NewsletterStatus.SENDING,\n            sentAt: new Date().toISOString(),\n          },\n          user: auth.user,\n        })\n\n        return Response.json({\n          success: true,\n          message: 'Broadcast sent successfully',\n          broadcast,\n        })\n      } catch (error) {\n        console.error('Failed to send broadcast:', error)\n\n        if (error instanceof BroadcastProviderError) {\n          return Response.json({\n            success: false,\n            error: error.message,\n            code: error.code,\n          }, { status: error.code === 'CONFIGURATION_ERROR' ? 500 : 500 })\n        }\n\n        if (error instanceof NewsletterProviderError) {\n          return Response.json({\n            success: false,\n            error: error.message,\n            code: error.code,\n          }, { status: error.code === 'NOT_SUPPORTED' ? 501 : 500 })\n        }\n\n        return Response.json({\n          success: false,\n          error: 'Failed to send broadcast',\n        }, { status: 500 })\n      }\n    }) as PayloadHandler,\n  }\n}","import type { Access, AccessArgs } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\n/**\n * Check if a user is an admin based on the plugin configuration\n */\nexport const isAdmin = (user: any, config?: NewsletterPluginConfig): boolean => {\n  if (!user || user.collection !== 'users') {\n    return false\n  }\n\n  // If custom admin check is provided, use it\n  if (config?.access?.isAdmin) {\n    return config.access.isAdmin(user)\n  }\n\n  // Default checks for common admin patterns\n  // 1. Check for admin role\n  if (user.roles?.includes('admin')) {\n    return true\n  }\n\n  // 2. Check for isAdmin boolean field\n  if (user.isAdmin === true) {\n    return true\n  }\n\n  // 3. Check for role field with admin value\n  if (user.role === 'admin') {\n    return true\n  }\n\n  // 4. Check for admin collection relationship\n  if (user.admin === true) {\n    return true\n  }\n\n  return false\n}\n\n/**\n * Create admin-only access control\n */\nexport const adminOnly = (config?: NewsletterPluginConfig): Access => \n  ({ req }: AccessArgs) => {\n    const user = req.user\n    return isAdmin(user, config)\n  }\n\n/**\n * Create admin or owner access control\n */\nexport const adminOrSelf = (config?: NewsletterPluginConfig): Access => \n  ({ req, id }: AccessArgs) => {\n    const user = req.user\n    \n    // No user = no access\n    if (!user) {\n      // For list operations without ID, return impossible condition\n      if (!id) {\n        return {\n          id: {\n            equals: 'unauthorized-no-access',\n          },\n        }\n      }\n      return false\n    }\n    \n    // Admins can access everything\n    if (isAdmin(user, config)) {\n      return true\n    }\n    \n    // Synthetic users (subscribers from magic link) can access their own data\n    if (user.collection === 'subscribers') {\n      // For list operations, scope to their own data\n      if (!id) {\n        return {\n          id: {\n            equals: user.id,\n          },\n        }\n      }\n      // For specific document access, check if it's their own\n      return id === user.id\n    }\n    \n    // Regular users cannot access subscriber data\n    if (!id) {\n      return {\n        id: {\n          equals: 'unauthorized-no-access',\n        },\n      }\n    }\n    return false\n  }","import type { PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { isAdmin } from './access'\n\n/**\n * Get authenticated user from request\n * In Payload v3, authentication is handled differently than v2\n */\nexport async function getAuthenticatedUser(req: PayloadRequest): Promise<any | null> {\n  try {\n    // Try to get the current user using Payload's auth\n    // This requires the request to have proper authentication headers/cookies\n    const me = await req.payload.find({\n      collection: 'users',\n      where: {\n        id: {\n          equals: 'me', // Special value in Payload to get current user\n        },\n      },\n      limit: 1,\n      depth: 0,\n    })\n    \n    return me.docs[0] || null\n  } catch {\n    return null\n  }\n}\n\n/**\n * Check if request has admin access\n */\nexport async function requireAdmin(\n  req: PayloadRequest,\n  config: NewsletterPluginConfig\n): Promise<{ authorized: true; user: any } | { authorized: false; error: string }> {\n  const user = await getAuthenticatedUser(req)\n  \n  if (!user) {\n    return {\n      authorized: false,\n      error: 'Authentication required',\n    }\n  }\n  \n  if (!isAdmin(user, config)) {\n    return {\n      authorized: false,\n      error: 'Admin access required',\n    }\n  }\n  \n  return {\n    authorized: true,\n    user,\n  }\n}","import type { Endpoint, PayloadHandler, PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig } from '../../types'\nimport { NewsletterProviderError, NewsletterStatus } from '../../types'\nimport { requireAdmin } from '../../utils/auth'\nimport { getBroadcastProvider } from '../../utils/getProvider'\nimport { BroadcastProviderError } from '../../types/broadcast'\nimport { scheduledState, draftState } from '../../utils/scheduling-state'\n\nexport const createScheduleBroadcastEndpoint = (\n  config: NewsletterPluginConfig,\n  collectionSlug: string\n): Endpoint => {\n  return {\n    path: '/:id/schedule',\n    method: 'post',\n    handler: (async (req: PayloadRequest) => {\n      try {\n        // Check authentication\n        const auth = await requireAdmin(req, config)\n        if (!auth.authorized) {\n          return Response.json({\n            success: false,\n            error: auth.error,\n          }, { status: 401 })\n        }\n\n        // Check if broadcast management is enabled\n        if (!config.features?.newsletterManagement?.enabled) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast management is not enabled',\n          }, { status: 400 })\n        }\n\n        // Get ID from URL\n        const url = new URL(req.url || '', `http://localhost`)\n        const pathParts = url.pathname.split('/')\n        const id = pathParts[pathParts.length - 2] // -2 because last part is 'schedule'\n\n        if (!id) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast ID is required',\n          }, { status: 400 })\n        }\n\n        // Parse request body\n        const data = await (req.json?.() || Promise.resolve({}))\n        const { scheduledAt } = data\n\n        if (!scheduledAt) {\n          return Response.json({\n            success: false,\n            error: 'scheduledAt is required',\n          }, { status: 400 })\n        }\n\n        // Parse and validate date\n        const scheduledDate = new Date(scheduledAt)\n        if (isNaN(scheduledDate.getTime())) {\n          return Response.json({\n            success: false,\n            error: 'Invalid scheduledAt date',\n          }, { status: 400 })\n        }\n\n        // Ensure scheduled date is in the future\n        if (scheduledDate <= new Date()) {\n          return Response.json({\n            success: false,\n            error: 'scheduledAt must be in the future',\n          }, { status: 400 })\n        }\n\n        // Get the broadcast document\n        const broadcastDoc = await req.payload.findByID({\n          collection: collectionSlug,\n          id,\n          user: auth.user,\n        })\n\n        if (!broadcastDoc || !broadcastDoc.providerId) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast not found or not synced with provider',\n          }, { status: 404 })\n        }\n\n        // Get provider (centralized initialization)\n        const provider = await getBroadcastProvider(req, config)\n\n        // Schedule broadcast using provider ID\n        const broadcast = await provider.schedule(broadcastDoc.providerId, scheduledDate)\n\n        // Update status in Payload collection\n        await req.payload.update({\n          collection: collectionSlug,\n          id,\n          data: scheduledState(scheduledDate),\n          user: auth.user,\n        })\n\n        return Response.json({\n          success: true,\n          message: `Broadcast scheduled for ${scheduledDate.toISOString()}`,\n          broadcast,\n        })\n      } catch (error) {\n        console.error('Failed to schedule broadcast:', error)\n\n        if (error instanceof BroadcastProviderError) {\n          return Response.json({\n            success: false,\n            error: error.message,\n            code: error.code,\n          }, { status: error.code === 'CONFIGURATION_ERROR' ? 500 : 500 })\n        }\n\n        if (error instanceof NewsletterProviderError) {\n          return Response.json({\n            success: false,\n            error: error.message,\n            code: error.code,\n          }, { status: error.code === 'NOT_SUPPORTED' ? 501 : 500 })\n        }\n\n        return Response.json({\n          success: false,\n          error: 'Failed to schedule broadcast',\n        }, { status: 500 })\n      }\n    }) as PayloadHandler,\n  }\n}\n\n/**\n * Create endpoint to cancel a scheduled broadcast.\n * DELETE /api/broadcasts/:id/schedule\n */\nexport const createCancelScheduleBroadcastEndpoint = (\n  config: NewsletterPluginConfig,\n  collectionSlug: string\n): Endpoint => {\n  return {\n    path: '/:id/schedule',\n    method: 'delete',\n    handler: (async (req: PayloadRequest) => {\n      try {\n        // Check authentication\n        const auth = await requireAdmin(req, config)\n        if (!auth.authorized) {\n          return Response.json({\n            success: false,\n            error: auth.error,\n          }, { status: 401 })\n        }\n\n        // Check if broadcast management is enabled\n        if (!config.features?.newsletterManagement?.enabled) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast management is not enabled',\n          }, { status: 400 })\n        }\n\n        // Get ID from URL\n        const url = new URL(req.url || '', `http://localhost`)\n        const pathParts = url.pathname.split('/')\n        const id = pathParts[pathParts.length - 2] // -2 because last part is 'schedule'\n\n        if (!id) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast ID is required',\n          }, { status: 400 })\n        }\n\n        // Get the broadcast document\n        const broadcastDoc = await req.payload.findByID({\n          collection: collectionSlug,\n          id,\n          user: auth.user,\n        })\n\n        if (!broadcastDoc || !broadcastDoc.providerId) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast not found or not synced with provider',\n          }, { status: 404 })\n        }\n\n        // Verify broadcast is currently scheduled\n        if (broadcastDoc.sendStatus !== NewsletterStatus.SCHEDULED) {\n          return Response.json({\n            success: false,\n            error: `Cannot cancel: broadcast is not scheduled (current status: ${broadcastDoc.sendStatus})`,\n          }, { status: 400 })\n        }\n\n        // Get provider and cancel schedule\n        const provider = await getBroadcastProvider(req, config)\n        await provider.cancelSchedule(broadcastDoc.providerId as string)\n\n        // Update status in Payload collection\n        await req.payload.update({\n          collection: collectionSlug,\n          id,\n          data: draftState(),\n          user: auth.user,\n        })\n\n        return Response.json({\n          success: true,\n          message: 'Broadcast schedule cancelled',\n        })\n      } catch (error) {\n        console.error('Failed to cancel scheduled broadcast:', error)\n\n        if (error instanceof NewsletterProviderError) {\n          return Response.json({\n            success: false,\n            error: error.message,\n            code: error.code,\n          }, { status: error.code === 'NOT_SUPPORTED' ? 501 : 500 })\n        }\n\n        return Response.json({\n          success: false,\n          error: 'Failed to cancel scheduled broadcast',\n        }, { status: 500 })\n      }\n    }) as PayloadHandler,\n  }\n}","import type { Endpoint, PayloadHandler, PayloadRequest } from 'payload'\nimport type { SerializedEditorState } from 'lexical'\nimport type { NewsletterPluginConfig } from '../../types'\nimport { requireAdmin } from '../../utils/auth'\nimport { getBroadcastProvider } from '../../utils/getProvider'\nimport { getBroadcastConfig } from '../../utils/getBroadcastConfig'\nimport { BroadcastProviderError } from '../../types/broadcast'\nimport { convertToEmailSafeHtml } from '../../utils/emailSafeHtml'\nimport { populateMediaFields } from './preview'\nimport { getErrorMessage } from '../../utils/getErrorMessage'\n\n/**\n * Create endpoint to retry syncing a broadcast with the provider.\n * POST /api/broadcasts/:id/retry-sync\n *\n * This endpoint allows users to manually retry syncing a broadcast\n * when the automatic sync has failed.\n */\nexport const createRetrySyncEndpoint = (\n  config: NewsletterPluginConfig,\n  collectionSlug: string\n): Endpoint => {\n  return {\n    path: '/:id/retry-sync',\n    method: 'post',\n    handler: (async (req: PayloadRequest) => {\n      try {\n        // Check authentication\n        const auth = await requireAdmin(req, config)\n        if (!auth.authorized) {\n          return Response.json({\n            success: false,\n            error: auth.error,\n          }, { status: 401 })\n        }\n\n        // Get ID from URL\n        const url = new URL(req.url || '', `http://localhost`)\n        const pathParts = url.pathname.split('/')\n        const id = pathParts[pathParts.length - 2] // -2 because last part is 'retry-sync'\n\n        if (!id) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast ID is required',\n          }, { status: 400 })\n        }\n\n        // Get the broadcast document\n        const broadcastDoc = await req.payload.findByID({\n          collection: collectionSlug,\n          id,\n          user: auth.user,\n        })\n\n        if (!broadcastDoc) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast not found',\n          }, { status: 404 })\n        }\n\n        // Get provider\n        const provider = await getBroadcastProvider(req, config)\n        const providerConfig = await getBroadcastConfig(req, config)\n\n        // If no providerId, create the broadcast in provider\n        if (!broadcastDoc.providerId) {\n          if (!broadcastDoc.subject || !broadcastDoc.contentSection?.content) {\n            return Response.json({\n              success: false,\n              error: 'Broadcast must have subject and content to sync',\n            }, { status: 400 })\n          }\n\n          // Convert content to HTML\n          const htmlContent = await convertToEmailSafeHtml(\n            await populateMediaFields(broadcastDoc.contentSection.content, req.payload, config) as SerializedEditorState | null,\n            {\n              wrapInTemplate: config.customizations?.broadcasts?.emailPreview?.wrapInTemplate ?? true,\n              customWrapper: config.customizations?.broadcasts?.emailPreview?.customWrapper,\n              preheader: broadcastDoc.contentSection?.preheader,\n              subject: broadcastDoc.subject,\n              documentData: broadcastDoc,\n              customBlockConverter: config.customizations?.broadcasts?.customBlockConverter\n            }\n          )\n\n          const createData = {\n            name: broadcastDoc.subject,\n            subject: broadcastDoc.subject,\n            preheader: broadcastDoc.contentSection?.preheader || '',\n            content: htmlContent,\n            trackOpens: broadcastDoc.settings?.trackOpens ?? true,\n            trackClicks: broadcastDoc.settings?.trackClicks ?? true,\n            replyTo: broadcastDoc.settings?.replyTo || providerConfig?.replyTo,\n            audienceIds: broadcastDoc.audienceIds?.map((a: any) => a.audienceId) || [],\n          }\n\n          const providerBroadcast = await provider.create(createData)\n\n          // Update document with provider ID and sync status\n          await req.payload.update({\n            collection: collectionSlug,\n            id,\n            data: {\n              providerId: providerBroadcast.id,\n              externalId: providerBroadcast.id,\n              providerData: providerBroadcast.providerData,\n              providerSyncStatus: 'synced',\n              providerSyncError: null,\n              lastSyncAttempt: new Date().toISOString(),\n            },\n            user: auth.user,\n          })\n\n          return Response.json({\n            success: true,\n            message: 'Broadcast created and synced with provider',\n          })\n        }\n\n        // If has providerId, update the broadcast in provider\n        const populatedContent = await populateMediaFields(\n          broadcastDoc.contentSection?.content,\n          req.payload,\n          config\n        ) as SerializedEditorState | null\n\n        const emailPreviewConfig = config.customizations?.broadcasts?.emailPreview\n\n        const htmlContent = await convertToEmailSafeHtml(populatedContent, {\n          wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,\n          customWrapper: emailPreviewConfig?.customWrapper,\n          preheader: broadcastDoc.contentSection?.preheader,\n          subject: broadcastDoc.subject,\n          documentData: broadcastDoc,\n          customBlockConverter: config.customizations?.broadcasts?.customBlockConverter\n        })\n\n        const updates = {\n          name: broadcastDoc.subject,\n          subject: broadcastDoc.subject,\n          preheader: broadcastDoc.contentSection?.preheader,\n          content: htmlContent,\n          trackOpens: broadcastDoc.settings?.trackOpens,\n          trackClicks: broadcastDoc.settings?.trackClicks,\n          replyTo: broadcastDoc.settings?.replyTo || providerConfig?.replyTo,\n          audienceIds: broadcastDoc.audienceIds?.map((a: any) => a.audienceId),\n        }\n\n        await provider.update(broadcastDoc.providerId as string, updates)\n\n        // Update sync status\n        await req.payload.update({\n          collection: collectionSlug,\n          id,\n          data: {\n            providerSyncStatus: 'synced',\n            providerSyncError: null,\n            lastSyncAttempt: new Date().toISOString(),\n          },\n          user: auth.user,\n        })\n\n        return Response.json({\n          success: true,\n          message: 'Broadcast synced with provider successfully',\n        })\n      } catch (error) {\n        console.error('Failed to retry sync:', error)\n\n        // Try to update sync status to failed\n        try {\n          const url = new URL(req.url || '', `http://localhost`)\n          const pathParts = url.pathname.split('/')\n          const id = pathParts[pathParts.length - 2]\n\n          if (id) {\n            await req.payload.update({\n              collection: collectionSlug,\n              id,\n              data: {\n                providerSyncStatus: 'failed',\n                providerSyncError: getErrorMessage(error),\n                lastSyncAttempt: new Date().toISOString(),\n              },\n            })\n          }\n        } catch {\n          // Ignore update error\n        }\n\n        if (error instanceof BroadcastProviderError) {\n          return Response.json({\n            success: false,\n            error: error.message,\n            code: error.code,\n          }, { status: 500 })\n        }\n\n        return Response.json({\n          success: false,\n          error: getErrorMessage(error),\n        }, { status: 500 })\n      }\n    }) as PayloadHandler,\n  }\n}\n","import type { Endpoint, PayloadHandler, PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig } from '../../types'\nimport { requireAdmin } from '../../utils/auth'\nimport { convertToEmailSafeHtml } from '../../utils/emailSafeHtml'\n\nexport const createTestBroadcastEndpoint = (\n  config: NewsletterPluginConfig,\n  collectionSlug: string\n): Endpoint => {\n  return {\n    path: '/:id/test',\n    method: 'post',\n    handler: (async (req: PayloadRequest) => {\n      try {\n        // Check authentication\n        const auth = await requireAdmin(req, config)\n        if (!auth.authorized) {\n          return Response.json({\n            success: false,\n            error: auth.error,\n          }, { status: 401 })\n        }\n\n        // Get ID from URL\n        const url = new URL(req.url || '', `http://localhost`)\n        const pathParts = url.pathname.split('/')\n        const id = pathParts[pathParts.length - 2] // -2 because last part is 'test'\n\n        if (!id) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast ID is required',\n          }, { status: 400 })\n        }\n\n        // Parse request body for optional test email\n        const data = await (req.json?.() || Promise.resolve({}))\n        const testEmail = data.email || auth.user.email\n\n        if (!testEmail) {\n          return Response.json({\n            success: false,\n            error: 'No email address available for test send',\n          }, { status: 400 })\n        }\n\n        // Get the broadcast document\n        const broadcast = await req.payload.findByID({\n          collection: collectionSlug,\n          id,\n          user: auth.user,\n        })\n\n        if (!broadcast) {\n          return Response.json({\n            success: false,\n            error: 'Broadcast not found',\n          }, { status: 404 })\n        }\n\n        // Convert content to email-safe HTML\n        const htmlContent = await convertToEmailSafeHtml(broadcast.content, {\n          wrapInTemplate: true,\n          preheader: broadcast.preheader,\n          customBlockConverter: config.customizations?.broadcasts?.customBlockConverter,\n        })\n\n        // Get email service\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        const emailService = (req.payload as any).newsletterEmailService\n        if (!emailService) {\n          return Response.json({\n            success: false,\n            error: 'Email service is not configured',\n          }, { status: 500 })\n        }\n\n        // Get sender info from provider config\n        const providerConfig = config.providers.default === 'resend' \n          ? config.providers.resend \n          : config.providers.broadcast\n        const fromEmail = providerConfig?.fromAddress || providerConfig?.fromEmail || 'noreply@example.com'\n        const fromName = providerConfig?.fromName || 'Newsletter'\n        const replyTo = broadcast.settings?.replyTo || providerConfig?.replyTo\n\n        // Send test email\n        await emailService.send({\n          to: testEmail,\n          from: fromEmail,\n          fromName: fromName,\n          replyTo: replyTo,\n          subject: `[TEST] ${broadcast.subject}`,\n          html: htmlContent,\n          trackOpens: false,\n          trackClicks: false,\n        })\n\n        return Response.json({\n          success: true,\n          message: `Test email sent to ${testEmail}`,\n        })\n      } catch (error) {\n        console.error('Failed to send test broadcast:', error)\n        \n        return Response.json({\n          success: false,\n          error: 'Failed to send test email',\n        }, { status: 500 })\n      }\n    }) as PayloadHandler,\n  }\n}","import { render } from '@react-email/render'\nimport { MagicLinkEmail } from './MagicLink'\nimport { WelcomeEmail } from './Welcome'\nimport { SignInEmail } from './SignIn'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport type EmailTemplate = 'magic-link' | 'welcome' | 'signin'\n\nexport interface BaseEmailData {\n  email?: string\n  siteName?: string\n  [key: string]: any\n}\n\nexport interface MagicLinkData extends BaseEmailData {\n  magicLink?: string\n  verificationUrl?: string\n  magicLinkUrl?: string\n  expiresIn?: string\n}\n\nexport interface WelcomeData extends BaseEmailData {\n  preferencesUrl?: string\n}\n\nexport async function renderEmail(\n  template: EmailTemplate, \n  data: MagicLinkData | WelcomeData,\n  config?: NewsletterPluginConfig\n): Promise<string> {\n  try {\n    // Check for custom templates if config provided\n    if (config?.customTemplates) {\n      const customTemplate = config.customTemplates[template]\n      if (customTemplate) {\n        const CustomComponent = customTemplate\n        return render(<CustomComponent {...data} />)\n      }\n    }\n    \n    // Fall back to built-in templates\n    switch (template) {\n      case 'magic-link': {\n        const magicLinkData = data as MagicLinkData\n        return render(\n          <MagicLinkEmail\n            magicLink={\n              magicLinkData.magicLink || \n              magicLinkData.verificationUrl || \n              magicLinkData.magicLinkUrl || \n              ''\n            }\n            email={magicLinkData.email || ''}\n            siteName={magicLinkData.siteName}\n            expiresIn={magicLinkData.expiresIn}\n          />\n        )\n      }\n      \n      case 'signin': {\n        const signinData = data as MagicLinkData\n        return render(\n          <SignInEmail\n            magicLink={\n              signinData.magicLink || \n              signinData.verificationUrl || \n              signinData.magicLinkUrl || \n              ''\n            }\n            email={signinData.email || ''}\n            siteName={signinData.siteName}\n            expiresIn={signinData.expiresIn}\n          />\n        )\n      }\n      \n      case 'welcome': {\n        const welcomeData = data as WelcomeData\n        return render(\n          <WelcomeEmail\n            email={welcomeData.email || ''}\n            siteName={welcomeData.siteName}\n            preferencesUrl={welcomeData.preferencesUrl}\n          />\n        )\n      }\n      \n      default:\n        throw new Error(`Unknown email template: ${template}`)\n    }\n  } catch (error) {\n    console.error(`Failed to render email template ${template}:`, error)\n    throw error\n  }\n}\n\n// Export for custom template rendering\nexport { MagicLinkEmail, WelcomeEmail, SignInEmail }","import React from 'react'\nimport {\n  Body,\n  Button,\n  Container,\n  Head,\n  Hr,\n  Html,\n  Preview,\n  Text,\n} from '@react-email/components'\nimport { styles } from './styles'\n\nexport interface MagicLinkEmailProps {\n  magicLink: string\n  email: string\n  siteName?: string\n  expiresIn?: string\n}\n\nexport const MagicLinkEmail: React.FC<MagicLinkEmailProps> = ({\n  magicLink,\n  email,\n  siteName = 'Newsletter',\n  expiresIn = '24 hours',\n}) => {\n  const previewText = `Sign in to ${siteName}`\n  \n  return (\n    <Html>\n      <Head />\n      <Preview>{previewText}</Preview>\n      <Body style={styles.main}>\n        <Container style={styles.container}>\n          <Text style={styles.heading}>Sign in to {siteName}</Text>\n          \n          <Text style={styles.text}>\n            Hi {email.split('@')[0]},\n          </Text>\n          \n          <Text style={styles.text}>\n            We received a request to sign in to your {siteName} account. \n            Click the button below to complete your sign in:\n          </Text>\n          \n          <Button href={magicLink} style={styles.button}>\n            Sign in to {siteName}\n          </Button>\n          \n          <Text style={styles.text}>\n            Or copy and paste this URL into your browser:\n          </Text>\n          \n          <code style={styles.code}>{magicLink}</code>\n          \n          <Hr style={styles.hr} />\n          \n          <Text style={styles.footer}>\n            This link will expire in {expiresIn}. If you didn't request this email, \n            you can safely ignore it.\n          </Text>\n        </Container>\n      </Body>\n    </Html>\n  )\n}\n\nexport default MagicLinkEmail","export const styles = {\n  main: {\n    backgroundColor: '#f6f9fc',\n    fontFamily:\n      '-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Ubuntu,sans-serif',\n  },\n  container: {\n    backgroundColor: '#ffffff',\n    border: '1px solid #f0f0f0',\n    borderRadius: '5px',\n    margin: '0 auto',\n    padding: '45px',\n    marginBottom: '64px',\n    maxWidth: '500px',\n  },\n  heading: {\n    fontSize: '24px',\n    letterSpacing: '-0.5px',\n    lineHeight: '1.3',\n    fontWeight: '600',\n    color: '#484848',\n    margin: '0 0 20px',\n    padding: '0',\n  },\n  text: {\n    fontSize: '16px',\n    lineHeight: '26px',\n    fontWeight: '400',\n    color: '#484848',\n    margin: '16px 0',\n  },\n  button: {\n    backgroundColor: '#000000',\n    borderRadius: '5px',\n    color: '#fff',\n    fontSize: '16px',\n    fontWeight: 'bold',\n    textDecoration: 'none',\n    textAlign: 'center' as const,\n    display: 'block',\n    width: '100%',\n    padding: '14px 20px',\n    margin: '30px 0',\n  },\n  link: {\n    color: '#2754C5',\n    fontSize: '14px',\n    textDecoration: 'underline',\n    wordBreak: 'break-all' as const,\n  },\n  hr: {\n    borderColor: '#e6ebf1',\n    margin: '30px 0',\n  },\n  footer: {\n    fontSize: '14px',\n    lineHeight: '24px',\n    color: '#9ca2ac',\n    textAlign: 'center' as const,\n    margin: '0',\n  },\n  code: {\n    display: 'inline-block',\n    padding: '16px',\n    width: '100%',\n    backgroundColor: '#f4f4f4',\n    borderRadius: '5px',\n    border: '1px solid #eee',\n    fontSize: '14px',\n    fontFamily: 'monospace',\n    textAlign: 'center' as const,\n    margin: '24px 0',\n  },\n}","import React from 'react'\nimport {\n  Body,\n  Button,\n  Container,\n  Head,\n  Hr,\n  Html,\n  Preview,\n  Text,\n} from '@react-email/components'\nimport { styles } from './styles'\n\nexport interface WelcomeEmailProps {\n  email: string\n  siteName?: string\n  preferencesUrl?: string\n}\n\nexport const WelcomeEmail: React.FC<WelcomeEmailProps> = ({\n  email,\n  siteName = 'Newsletter',\n  preferencesUrl,\n}) => {\n  const previewText = `Welcome to ${siteName}!`\n  const firstName = email.split('@')[0]\n  \n  return (\n    <Html>\n      <Head />\n      <Preview>{previewText}</Preview>\n      <Body style={styles.main}>\n        <Container style={styles.container}>\n          <Text style={styles.heading}>Welcome to {siteName}! 🎉</Text>\n          \n          <Text style={styles.text}>\n            Hi {firstName},\n          </Text>\n          \n          <Text style={styles.text}>\n            Thanks for subscribing to {siteName}! We're excited to have you as part \n            of our community.\n          </Text>\n          \n          <Text style={styles.text}>\n            You'll receive our newsletter based on your preferences. Speaking of which, \n            you can update your preferences anytime:\n          </Text>\n          \n          {preferencesUrl && (\n            <Button href={preferencesUrl} style={styles.button}>\n              Manage Preferences\n            </Button>\n          )}\n          \n          <Text style={styles.text}>\n            Here's what you can expect from us:\n          </Text>\n          \n          <Text style={styles.text}>\n            • Regular updates based on your chosen frequency<br />\n            • Content tailored to your interests<br />\n            • Easy unsubscribe options in every email<br />\n            • Your privacy respected always\n          </Text>\n          \n          <Hr style={styles.hr} />\n          \n          <Text style={styles.footer}>\n            If you have any questions, feel free to reply to this email. \n            We're here to help!\n          </Text>\n        </Container>\n      </Body>\n    </Html>\n  )\n}\n\nexport default WelcomeEmail","// SignIn is just an alias for MagicLink with slightly different defaults\nimport React from 'react'\nimport { MagicLinkEmail, MagicLinkEmailProps } from './MagicLink'\n\nexport const SignInEmail: React.FC<MagicLinkEmailProps> = (props) => {\n  return <MagicLinkEmail {...props} />\n}\n\nexport default SignInEmail","import type { CollectionConfig, Field, CollectionAfterChangeHook, CollectionBeforeDeleteHook } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { adminOnly, adminOrSelf } from '../utils/access'\nimport { renderEmail } from '../emails/render'\n\nexport const createSubscribersCollection = (\n  pluginConfig: NewsletterPluginConfig\n): CollectionConfig => {\n  const slug = pluginConfig.subscribersSlug || 'subscribers'\n  \n  // Default fields for the subscribers collection\n  const defaultFields: Field[] = [\n    // Core fields\n    {\n      name: 'email',\n      type: 'email',\n      required: true,\n      unique: true,\n      admin: {\n        description: 'Subscriber email address',\n      },\n    },\n    {\n      name: 'name',\n      type: 'text',\n      admin: {\n        description: 'Subscriber full name',\n      },\n    },\n    {\n      name: 'locale',\n      type: 'select',\n      options: pluginConfig.i18n?.locales?.map(locale => ({\n        label: locale.toUpperCase(),\n        value: locale,\n      })) || [\n        { label: 'EN', value: 'en' },\n      ],\n      defaultValue: pluginConfig.i18n?.defaultLocale || 'en',\n      admin: {\n        description: 'Preferred language for communications',\n      },\n    },\n    \n    // Authentication fields (hidden from admin UI)\n    {\n      name: 'magicLinkToken',\n      type: 'text',\n      hidden: true,\n    },\n    {\n      name: 'magicLinkTokenExpiry',\n      type: 'date',\n      hidden: true,\n    },\n    \n    // External ID for webhook integration\n    {\n      name: 'externalId',\n      type: 'text',\n      admin: {\n        description: 'ID from email service provider',\n        readOnly: true,\n      },\n    },\n    \n    // Subscription status\n    {\n      name: 'subscriptionStatus',\n      type: 'select',\n      options: [\n        { label: 'Active', value: 'active' },\n        { label: 'Unsubscribed', value: 'unsubscribed' },\n        { label: 'Pending', value: 'pending' },\n      ],\n      defaultValue: 'pending',\n      required: true,\n      admin: {\n        description: 'Current subscription status',\n      },\n    },\n    {\n      name: 'subscribedAt',\n      type: 'date',\n      admin: {\n        description: 'When the user subscribed',\n        readOnly: true,\n      },\n    },\n    {\n      name: 'unsubscribedAt',\n      type: 'date',\n      admin: {\n        condition: (data) => data?.subscriptionStatus === 'unsubscribed',\n        description: 'When the user unsubscribed',\n        readOnly: true,\n      },\n    },\n    {\n      name: 'unsubscribeReason',\n      type: 'text',\n      admin: {\n        condition: (data) => data?.subscriptionStatus === 'unsubscribed',\n        description: 'Reason for unsubscribing',\n        readOnly: true,\n      },\n    },\n    \n    // Email preferences\n    {\n      name: 'emailPreferences',\n      type: 'group',\n      fields: [\n        {\n          name: 'newsletter',\n          type: 'checkbox',\n          defaultValue: true,\n          label: 'Newsletter',\n          admin: {\n            description: 'Receive regular newsletter updates',\n          },\n        },\n        {\n          name: 'announcements',\n          type: 'checkbox',\n          defaultValue: true,\n          label: 'Announcements',\n          admin: {\n            description: 'Receive important announcements',\n          },\n        },\n      ],\n      admin: {\n        description: 'Email communication preferences',\n      },\n    },\n    \n    // Source tracking\n    {\n      name: 'source',\n      type: 'text',\n      admin: {\n        description: 'Where the subscriber signed up from',\n      },\n    },\n    \n    // Import tracking\n    {\n      name: 'importedFromProvider',\n      type: 'checkbox',\n      defaultValue: false,\n      admin: {\n        description: 'Indicates this subscriber was imported from an external provider via webhook',\n        position: 'sidebar',\n        readOnly: true,\n      },\n    },\n  ]\n\n  // Add UTM tracking fields if enabled\n  if (pluginConfig.features?.utmTracking?.enabled) {\n    const utmFields = pluginConfig.features.utmTracking.fields || [\n      'source',\n      'medium',\n      'campaign',\n      'content',\n      'term',\n    ]\n    \n    defaultFields.push({\n      name: 'utmParameters',\n      type: 'group',\n      fields: utmFields.map(field => ({\n        name: field,\n        type: 'text',\n        admin: {\n          description: `UTM ${field} parameter`,\n        },\n      })),\n      admin: {\n        description: 'UTM tracking parameters',\n      },\n    })\n  }\n\n  // Add signup metadata\n  defaultFields.push({\n    name: 'signupMetadata',\n    type: 'group',\n    fields: [\n      {\n        name: 'ipAddress',\n        type: 'text',\n        admin: {\n          readOnly: true,\n        },\n      },\n      {\n        name: 'userAgent',\n        type: 'text',\n        admin: {\n          readOnly: true,\n        },\n      },\n      {\n        name: 'referrer',\n        type: 'text',\n        admin: {\n          readOnly: true,\n        },\n      },\n      {\n        name: 'signupPage',\n        type: 'text',\n        admin: {\n          readOnly: true,\n        },\n      },\n    ],\n    admin: {\n      description: 'Technical information about signup',\n    },\n  })\n\n  // Add lead magnet field if enabled\n  if (pluginConfig.features?.leadMagnets?.enabled) {\n    defaultFields.push({\n      name: 'leadMagnet',\n      type: 'relationship',\n      relationTo: pluginConfig.features.leadMagnets.collection || 'media',\n      admin: {\n        description: 'Lead magnet downloaded at signup',\n      },\n    })\n  }\n\n  // Allow field customization\n  let fields = defaultFields\n  if (pluginConfig.fields?.overrides) {\n    fields = pluginConfig.fields.overrides({ defaultFields })\n  }\n  if (pluginConfig.fields?.additional) {\n    fields = [...fields, ...pluginConfig.fields.additional]\n  }\n\n  const subscribersCollection: CollectionConfig = {\n    slug,\n    labels: {\n      singular: 'Subscriber',\n      plural: 'Subscribers',\n    },\n    admin: {\n      useAsTitle: 'email',\n      defaultColumns: ['email', 'name', 'subscriptionStatus', 'createdAt'],\n      group: 'Newsletter',\n    },\n    fields,\n    hooks: {\n      afterChange: [\n        async ({ doc, req, operation, previousDoc }) => {\n          // After create logic\n          if (operation === 'create') {\n            // Add to email service\n            const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n            console.log('[Newsletter Plugin] Creating subscriber:', {\n              email: doc.email,\n              hasEmailService: !!emailService\n            })\n            \n            if (emailService) {\n              try {\n                await emailService.addContact(doc)\n                console.log('[Newsletter Plugin] Successfully added contact to email service')\n              } catch (error) {\n                console.error('[Newsletter Plugin] Failed to add contact to email service:', error)\n              }\n            } else {\n              console.warn('[Newsletter Plugin] No email service configured for subscriber creation')\n            }\n\n            // Send welcome email if active and not imported from provider\n            if (doc.subscriptionStatus === 'active' && emailService && !doc.importedFromProvider) {\n              try {\n                // Get settings for site name\n                const settings = await req.payload.findGlobal({\n                  slug: pluginConfig.settingsSlug || 'newsletter-settings',\n                })\n                \n                // Render welcome email\n                const serverURL = req.payload.config.serverURL || process.env.PAYLOAD_PUBLIC_SERVER_URL || ''\n                const html = await renderEmail('welcome', {\n                  email: doc.email,\n                  siteName: settings?.brandSettings?.siteName || 'Newsletter',\n                  preferencesUrl: `${serverURL}/account/preferences`, // This could be customized\n                }, pluginConfig)\n                \n                // Send email\n                await emailService.send({\n                  to: doc.email,\n                  subject: settings?.brandSettings?.siteName ? `Welcome to ${settings.brandSettings.siteName}!` : 'Welcome!',\n                  html,\n                })\n                \n                console.warn(`Welcome email sent to: ${doc.email}`)\n              } catch (error) {\n                console.error('Failed to send welcome email:', error)\n                // Don't fail the subscription if welcome email fails\n              }\n            }\n\n            // Custom after subscribe hook\n            if (pluginConfig.hooks?.afterSubscribe) {\n              await pluginConfig.hooks.afterSubscribe({ doc, req })\n            }\n          }\n          \n          // After update logic\n          if (operation === 'update' && previousDoc) {\n            // Update email service if status changed\n            const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n            \n            if (doc.subscriptionStatus !== previousDoc.subscriptionStatus) {\n              console.log('[Newsletter Plugin] Subscription status changed:', {\n                email: doc.email,\n                from: previousDoc.subscriptionStatus,\n                to: doc.subscriptionStatus,\n                hasEmailService: !!emailService\n              })\n              \n              if (emailService) {\n                try {\n                  await emailService.updateContact(doc)\n                  console.log('[Newsletter Plugin] Successfully updated contact in email service')\n                } catch (error) {\n                  console.error('[Newsletter Plugin] Failed to update contact in email service:', error)\n                }\n              } else {\n                console.warn('[Newsletter Plugin] No email service configured')\n              }\n            }\n\n            // Handle resubscribe - send welcome email for user-initiated resubscriptions\n            if (\n              doc.subscriptionStatus === 'active' &&\n              previousDoc.subscriptionStatus === 'unsubscribed' &&\n              !doc.importedFromProvider &&\n              emailService\n            ) {\n              try {\n                // Get settings for site name\n                const settings = await req.payload.findGlobal({\n                  slug: pluginConfig.settingsSlug || 'newsletter-settings',\n                })\n                \n                // Render welcome email\n                const serverURL = req.payload.config.serverURL || process.env.PAYLOAD_PUBLIC_SERVER_URL || ''\n                const html = await renderEmail('welcome', {\n                  email: doc.email,\n                  siteName: settings?.brandSettings?.siteName || 'Newsletter',\n                  preferencesUrl: `${serverURL}/account/preferences`,\n                }, pluginConfig)\n                \n                // Send email\n                await emailService.send({\n                  to: doc.email,\n                  subject: settings?.brandSettings?.siteName ? `Welcome back to ${settings.brandSettings.siteName}!` : 'Welcome back!',\n                  html,\n                })\n                \n                console.warn(`Welcome email sent to resubscribed user: ${doc.email}`)\n              } catch (error) {\n                console.error('Failed to send resubscription welcome email:', error)\n                // Don't fail the resubscription if welcome email fails\n              }\n              \n              // Call custom after subscribe hook for resubscriptions\n              if (pluginConfig.hooks?.afterSubscribe) {\n                await pluginConfig.hooks.afterSubscribe({ doc, req })\n              }\n            }\n\n            // Handle unsubscribe\n            if (\n              doc.subscriptionStatus === 'unsubscribed' &&\n              previousDoc.subscriptionStatus !== 'unsubscribed'\n            ) {\n              // Set unsubscribed timestamp\n              doc.unsubscribedAt = new Date().toISOString()\n              \n              // Custom after unsubscribe hook\n              if (pluginConfig.hooks?.afterUnsubscribe) {\n                await pluginConfig.hooks.afterUnsubscribe({ doc, req })\n              }\n            }\n          }\n        },\n      ] as CollectionAfterChangeHook[],\n      beforeDelete: [\n        async ({ id, req }) => {\n          // Remove from email service\n          const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n          if (emailService) {\n            try {\n              const doc = await req.payload.findByID({\n                collection: slug,\n                id,\n              })\n              await emailService.removeContact(doc.email)\n            } catch {\n              // Failed to remove contact from email service\n            }\n          }\n        },\n      ] as CollectionBeforeDeleteHook[],\n    },\n    access: {\n      create: () => true, // Public can subscribe\n      read: adminOrSelf(pluginConfig),\n      update: adminOrSelf(pluginConfig),\n      delete: adminOnly(pluginConfig),\n    },\n    timestamps: true,\n  }\n\n  return subscribersCollection\n}"],"mappings":"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","names":["init_broadcast","DOMPurify","styles","BroadcastApiProvider","htmlContent","import_components","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}