payload-plugin-newsletter 0.8.7 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/access.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","../src/globals/NewsletterSettings.ts","../src/providers/resend.ts","../src/providers/types.ts","../src/providers/broadcast.ts","../src/providers/index.ts","../src/utils/validation.ts","../src/utils/jwt.ts","../src/endpoints/subscribe.ts","../src/endpoints/verify-magic-link.ts","../src/endpoints/preferences.ts","../src/endpoints/unsubscribe.ts","../src/utils/rate-limiter.ts","../src/endpoints/signin.ts","../src/endpoints/me.ts","../src/endpoints/signout.ts","../src/endpoints/index.ts","../src/fields/newsletterScheduling.ts","../src/jobs/sync-unsubscribes.ts","../src/utilities/session.ts","../src/index.ts"],"sourcesContent":["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 { render } from '@react-email/render'\nimport { MagicLinkEmail } from './MagicLink'\nimport { WelcomeEmail } from './Welcome'\nimport { SignInEmail } from './SignIn'\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): Promise<string> {\n try {\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 // 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: '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 // 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\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 if (emailService) {\n try {\n await emailService.addContact(doc)\n } catch {\n // Failed to add contact to email service\n }\n }\n\n // Send welcome email if active\n if (doc.subscriptionStatus === 'active' && emailService) {\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 })\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 if (\n doc.subscriptionStatus !== previousDoc.subscriptionStatus &&\n emailService\n ) {\n try {\n await emailService.updateContact(doc)\n } catch {\n // Failed to update contact in email service\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}","import type { GlobalConfig } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { adminOnly } from '../utils/access'\n\nexport const createNewsletterSettingsGlobal = (\n pluginConfig: NewsletterPluginConfig\n): GlobalConfig => {\n const slug = pluginConfig.settingsSlug || 'newsletter-settings'\n \n return {\n slug,\n label: 'Newsletter Settings',\n admin: {\n group: 'Newsletter',\n description: 'Configure email provider settings and templates',\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n label: 'Provider Settings',\n fields: [\n {\n name: 'provider',\n type: 'select',\n label: 'Email Provider',\n required: true,\n options: [\n { label: 'Resend', value: 'resend' },\n { label: 'Broadcast (Self-Hosted)', value: 'broadcast' },\n ],\n defaultValue: pluginConfig.providers.default,\n admin: {\n description: 'Choose which email service to use',\n },\n },\n {\n name: 'resendSettings',\n type: 'group',\n label: 'Resend Settings',\n admin: {\n condition: (data) => data?.provider === 'resend',\n },\n fields: [\n {\n name: 'apiKey',\n type: 'text',\n label: 'API Key',\n required: true,\n admin: {\n description: 'Your Resend API key',\n },\n },\n {\n name: 'audienceIds',\n type: 'array',\n label: 'Audience IDs by Locale',\n fields: [\n {\n name: 'locale',\n type: 'select',\n label: 'Locale',\n required: true,\n options: pluginConfig.i18n?.locales?.map(locale => ({\n label: locale.toUpperCase(),\n value: locale,\n })) || [\n { label: 'EN', value: 'en' },\n ],\n },\n {\n name: 'production',\n type: 'text',\n label: 'Production Audience ID',\n },\n {\n name: 'development',\n type: 'text',\n label: 'Development Audience ID',\n },\n ],\n },\n ],\n },\n {\n name: 'broadcastSettings',\n type: 'group',\n label: 'Broadcast Settings',\n admin: {\n condition: (data) => data?.provider === 'broadcast',\n },\n fields: [\n {\n name: 'apiUrl',\n type: 'text',\n label: 'API URL',\n required: true,\n admin: {\n description: 'Your Broadcast instance URL',\n },\n },\n {\n name: 'productionToken',\n type: 'text',\n label: 'Production Token',\n admin: {\n description: 'Token for production environment',\n },\n },\n {\n name: 'developmentToken',\n type: 'text',\n label: 'Development Token',\n admin: {\n description: 'Token for development environment',\n },\n },\n ],\n },\n {\n name: 'fromAddress',\n type: 'email',\n label: 'From Address',\n required: true,\n admin: {\n description: 'Default sender email address',\n },\n },\n {\n name: 'fromName',\n type: 'text',\n label: 'From Name',\n required: true,\n admin: {\n description: 'Default sender name',\n },\n },\n {\n name: 'replyTo',\n type: 'email',\n label: 'Reply-To Address',\n admin: {\n description: 'Optional reply-to email address',\n },\n },\n ],\n },\n {\n label: 'Email Templates',\n fields: [\n {\n name: 'emailTemplates',\n type: 'group',\n label: 'Email Templates',\n fields: [\n {\n name: 'welcome',\n type: 'group',\n label: 'Welcome Email',\n fields: [\n {\n name: 'enabled',\n type: 'checkbox',\n label: 'Send Welcome Email',\n defaultValue: true,\n },\n {\n name: 'subject',\n type: 'text',\n label: 'Subject Line',\n defaultValue: 'Welcome to {{fromName}}!',\n admin: {\n condition: (data) => data?.emailTemplates?.welcome?.enabled,\n },\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Preheader Text',\n admin: {\n condition: (data) => data?.emailTemplates?.welcome?.enabled,\n },\n },\n ],\n },\n {\n name: 'magicLink',\n type: 'group',\n label: 'Magic Link Email',\n fields: [\n {\n name: 'subject',\n type: 'text',\n label: 'Subject Line',\n defaultValue: 'Sign in to {{fromName}}',\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Preheader Text',\n defaultValue: 'Click the link to access your preferences',\n },\n {\n name: 'expirationTime',\n type: 'select',\n label: 'Link Expiration',\n defaultValue: '7d',\n options: [\n { label: '1 hour', value: '1h' },\n { label: '24 hours', value: '24h' },\n { label: '7 days', value: '7d' },\n { label: '30 days', value: '30d' },\n ],\n },\n ],\n },\n ],\n },\n ],\n },\n {\n label: 'Subscription Settings',\n fields: [\n {\n name: 'subscriptionSettings',\n type: 'group',\n label: 'Subscription Settings',\n fields: [\n {\n name: 'requireDoubleOptIn',\n type: 'checkbox',\n label: 'Require Double Opt-In',\n defaultValue: false,\n admin: {\n description: 'Require email confirmation before activating subscriptions',\n },\n },\n {\n name: 'allowedDomains',\n type: 'array',\n label: 'Allowed Email Domains',\n admin: {\n description: 'Leave empty to allow all domains',\n },\n fields: [\n {\n name: 'domain',\n type: 'text',\n label: 'Domain',\n required: true,\n admin: {\n placeholder: 'example.com',\n },\n },\n ],\n },\n {\n name: 'maxSubscribersPerIP',\n type: 'number',\n label: 'Max Subscribers per IP',\n defaultValue: 10,\n min: 1,\n admin: {\n description: 'Maximum number of subscriptions allowed from a single IP address',\n },\n },\n ],\n },\n ],\n },\n ],\n },\n ],\n hooks: {\n beforeChange: [\n async ({ data, req }) => {\n // Verify admin access for settings changes\n if (!req.user || req.user.collection !== 'users') {\n throw new Error('Only administrators can modify newsletter settings')\n }\n \n return data\n },\n ],\n afterChange: [\n async ({ doc, req }) => {\n // Reinitialize email service when settings change\n if ((req.payload as any).newsletterEmailService) {\n try {\n // TODO: Implement email service reinitialization\n console.warn('Newsletter settings updated, reinitializing service...')\n } catch {\n // Failed to reinitialize email service\n }\n }\n \n return doc\n },\n ],\n },\n access: {\n read: () => true, // Settings can be read publicly for validation\n update: adminOnly(pluginConfig),\n },\n }\n}","import { Resend } from 'resend'\nimport type { EmailProvider, SendEmailParams } from './types'\nimport { EmailProviderError } from './types'\nimport type { Subscriber, ResendProviderConfig } from '../types'\n\nexport class ResendProvider implements EmailProvider {\n private client: Resend\n private audienceIds: ResendProviderConfig['audienceIds']\n private fromAddress: string\n private fromName: string\n private isDevelopment: boolean\n\n constructor(config: ResendProviderConfig & { \n fromAddress: string\n fromName: string \n }) {\n this.client = new Resend(config.apiKey)\n this.audienceIds = config.audienceIds || {}\n this.fromAddress = config.fromAddress\n this.fromName = config.fromName\n this.isDevelopment = process.env.NODE_ENV !== 'production'\n }\n\n getProvider(): string {\n return 'resend'\n }\n\n async send(params: SendEmailParams): Promise<void> {\n try {\n const from = params.from || {\n email: this.fromAddress,\n name: this.fromName,\n }\n\n if (!params.html && !params.text) {\n throw new Error('Either html or text content is required')\n }\n\n await this.client.emails.send({\n from: `${from.name} <${from.email}>`,\n to: Array.isArray(params.to) ? params.to : [params.to],\n subject: params.subject,\n html: params.html || '',\n text: params.text,\n replyTo: params.replyTo,\n })\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to send email via Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n async addContact(contact: Subscriber): Promise<void> {\n try {\n const audienceId = this.getAudienceId(contact.locale)\n if (!audienceId) {\n console.warn(`No audience ID configured for locale: ${contact.locale}`)\n return\n }\n\n await this.client.contacts.create({\n email: contact.email,\n firstName: contact.name?.split(' ')[0],\n lastName: contact.name?.split(' ').slice(1).join(' '),\n unsubscribed: contact.subscriptionStatus === 'unsubscribed',\n audienceId,\n })\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to add contact to Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n async updateContact(contact: Subscriber): Promise<void> {\n try {\n const audienceId = this.getAudienceId(contact.locale)\n if (!audienceId) {\n console.warn(`No audience ID configured for locale: ${contact.locale}`)\n return\n }\n\n // Resend requires finding the contact first\n const contacts = await this.client.contacts.list({ audienceId })\n const existingContact = contacts.data?.data?.find(c => c.email === contact.email)\n\n if (existingContact) {\n await this.client.contacts.update({\n id: existingContact.id,\n audienceId,\n firstName: contact.name?.split(' ')[0],\n lastName: contact.name?.split(' ').slice(1).join(' '),\n unsubscribed: contact.subscriptionStatus === 'unsubscribed',\n })\n } else {\n // If contact doesn't exist, add them\n await this.addContact(contact)\n }\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to update contact in Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n async removeContact(email: string): Promise<void> {\n try {\n // Resend doesn't have a direct remove method, so we unsubscribe instead\n // First, we need to find the contact across all audiences\n for (const locale in this.audienceIds) {\n const audienceId = this.getAudienceId(locale)\n if (!audienceId) continue\n\n const contacts = await this.client.contacts.list({ audienceId })\n const contact = contacts.data?.data?.find(c => c.email === email)\n\n if (contact) {\n await this.client.contacts.update({\n id: contact.id,\n audienceId,\n unsubscribed: true,\n })\n break\n }\n }\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to remove contact from Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n private getAudienceId(locale?: string): string | undefined {\n const localeKey = locale || 'en'\n if (!this.audienceIds) return undefined\n \n const localeConfig = this.audienceIds[localeKey]\n if (!localeConfig) return undefined\n\n const audienceId = this.isDevelopment \n ? (localeConfig.development || localeConfig.production)\n : (localeConfig.production || localeConfig.development)\n \n return audienceId\n }\n}","import type { Subscriber } from '../types'\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 getProvider(): string\n}\n\nexport interface SendEmailParams {\n to: string | string[]\n subject: string\n html?: string\n text?: string\n react?: React.ReactElement\n from?: {\n email: string\n name?: string\n }\n replyTo?: string\n}\n\nexport interface EmailServiceConfig {\n provider: 'resend' | 'broadcast' | string\n fromAddress: string\n fromName: string\n replyTo?: string\n resend?: {\n apiKey: string\n audienceIds?: Record<string, { production?: string; development?: string }>\n }\n broadcast?: {\n apiUrl: string\n tokens: {\n production?: string\n development?: string\n }\n }\n}\n\nexport class EmailProviderError extends Error {\n provider: string\n originalError?: any\n\n constructor(message: string, provider: string, originalError?: any) {\n super(message)\n this.name = 'EmailProviderError'\n this.provider = provider\n this.originalError = originalError\n }\n}","import type { EmailProvider, SendEmailParams } from './types'\nimport { EmailProviderError } from './types'\nimport type { Subscriber, BroadcastProviderConfig } from '../types'\n\nexport class BroadcastProvider implements EmailProvider {\n private apiUrl: string\n private token: string\n private fromAddress: string\n private fromName: string\n private isDevelopment: boolean\n\n constructor(config: BroadcastProviderConfig & { \n fromAddress: string\n fromName: string \n }) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '') // Remove trailing slash\n this.isDevelopment = process.env.NODE_ENV !== 'production'\n this.token = this.isDevelopment \n ? config.tokens.development || config.tokens.production || ''\n : config.tokens.production || config.tokens.development || ''\n this.fromAddress = config.fromAddress\n this.fromName = config.fromName\n }\n\n getProvider(): string {\n return 'broadcast'\n }\n\n async send(params: SendEmailParams): Promise<void> {\n try {\n const from = params.from || {\n email: this.fromAddress,\n name: this.fromName,\n }\n\n const recipients = Array.isArray(params.to) ? params.to : [params.to]\n \n // Broadcast expects a specific format\n const response = await fetch(`${this.apiUrl}/api/v1/emails`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n from_email: from.email,\n from_name: from.name,\n to: recipients,\n subject: params.subject,\n html_body: params.html,\n text_body: params.text,\n reply_to: params.replyTo,\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 throw new EmailProviderError(\n `Failed to send email via Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n\n async addContact(contact: Subscriber): Promise<void> {\n try {\n const [firstName, ...lastNameParts] = (contact.name || '').split(' ')\n const lastName = lastNameParts.join(' ')\n\n const response = await fetch(`${this.apiUrl}/api/v1/subscribers.json`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n subscriber: {\n email: contact.email,\n first_name: firstName || undefined,\n last_name: lastName || undefined,\n tags: [`lang:${contact.locale || 'en'}`],\n is_active: contact.subscriptionStatus === 'active',\n source: contact.source,\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 } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to add contact to Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n\n async updateContact(contact: Subscriber): Promise<void> {\n try {\n // First, try to find the contact\n const searchResponse = await fetch(\n `${this.apiUrl}/api/v1/subscribers/find.json?email=${encodeURIComponent(contact.email)}`,\n {\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n },\n }\n )\n\n if (!searchResponse.ok) {\n // If contact doesn't exist, create it\n await this.addContact(contact)\n return\n }\n\n const existingContact = await searchResponse.json()\n\n if (!existingContact || !existingContact.id) {\n await this.addContact(contact)\n return\n }\n\n const [firstName, ...lastNameParts] = (contact.name || '').split(' ')\n const lastName = lastNameParts.join(' ')\n\n // Update existing contact\n const response = await fetch(`${this.apiUrl}/api/v1/subscribers.json`, {\n method: 'PATCH',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n email: contact.email,\n subscriber: {\n first_name: firstName || undefined,\n last_name: lastName || undefined,\n tags: [`lang:${contact.locale || 'en'}`],\n is_active: contact.subscriptionStatus === 'active',\n source: contact.source,\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 } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to update contact in Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n\n async removeContact(email: string): Promise<void> {\n try {\n // First, find the contact\n const searchResponse = await fetch(\n `${this.apiUrl}/api/v1/subscribers/find.json?email=${encodeURIComponent(email)}`,\n {\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n },\n }\n )\n\n if (!searchResponse.ok) {\n // Contact doesn't exist, nothing to remove\n return\n }\n\n const contact = await searchResponse.json()\n\n if (!contact || !contact.id) {\n return\n }\n\n // Deactivate the contact\n const response = await fetch(`${this.apiUrl}/api/v1/subscribers/deactivate.json`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email }),\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 throw new EmailProviderError(\n `Failed to remove contact from Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n}","import type { EmailProvider, EmailServiceConfig, SendEmailParams } from './types'\nimport type { Subscriber } from '../types'\nimport { ResendProvider } from './resend'\nimport { BroadcastProvider } from './broadcast'\n\nexport * from './types'\n\nexport class EmailService {\n private provider: EmailProvider\n\n constructor(config: EmailServiceConfig) {\n this.provider = this.createProvider(config)\n }\n\n private createProvider(config: EmailServiceConfig): EmailProvider {\n const baseConfig = {\n fromAddress: config.fromAddress,\n fromName: config.fromName,\n }\n\n switch (config.provider) {\n case 'resend':\n if (!config.resend) {\n throw new Error('Resend configuration is required when using Resend provider')\n }\n return new ResendProvider({\n ...config.resend,\n ...baseConfig,\n })\n\n case 'broadcast':\n if (!config.broadcast) {\n throw new Error('Broadcast configuration is required when using Broadcast provider')\n }\n return new BroadcastProvider({\n ...config.broadcast,\n ...baseConfig,\n })\n\n default:\n throw new Error(`Unknown email provider: ${config.provider}`)\n }\n }\n\n async send(params: SendEmailParams): Promise<void> {\n return this.provider.send(params)\n }\n\n async addContact(contact: Subscriber): Promise<void> {\n return this.provider.addContact(contact)\n }\n\n async updateContact(contact: Subscriber): Promise<void> {\n return this.provider.updateContact(contact)\n }\n\n async removeContact(email: string): Promise<void> {\n return this.provider.removeContact(email)\n }\n\n getProvider(): string {\n return this.provider.getProvider()\n }\n\n /**\n * Update the provider configuration\n * Useful when settings are changed in the admin UI\n */\n updateConfig(config: EmailServiceConfig): void {\n this.provider = this.createProvider(config)\n }\n}\n\n/**\n * Create email service from plugin configuration\n */\nexport function createEmailService(config: EmailServiceConfig): EmailService {\n return new EmailService(config)\n}","import DOMPurify from 'isomorphic-dompurify'\n\n/**\n * Validate email address format\n */\nexport function isValidEmail(email: string): boolean {\n if (!email || typeof email !== 'string') return false\n \n // Trim whitespace\n const trimmed = email.trim()\n \n // Length limits\n if (trimmed.length > 255) return false\n \n // Check for dangerous patterns\n if (trimmed.includes('<') || trimmed.includes('>')) return false\n if (trimmed.includes('javascript:')) return false\n if (trimmed.includes('data:')) return false\n \n // Basic format validation with stricter regex\n const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/\n if (!emailRegex.test(trimmed)) return false\n \n // Additional validation rules\n const parts = trimmed.split('@')\n if (parts.length !== 2) return false\n \n const [localPart, domain] = parts\n \n // Check local part length\n if (localPart.length > 64 || localPart.length === 0) return false\n \n // Check for invalid patterns\n if (localPart.startsWith('.') || localPart.endsWith('.')) return false\n if (domain.startsWith('.') || domain.endsWith('.')) return false\n if (domain.includes('..')) return false\n if (localPart.includes('..')) return false\n \n return true\n}\n\n/**\n * Normalize email for rate limiting and deduplication\n */\nexport function normalizeEmail(email: string): string {\n if (!email || typeof email !== 'string') return ''\n \n const parts = email.toLowerCase().trim().split('@')\n if (parts.length !== 2) return email.toLowerCase().trim()\n \n let [localPart] = parts\n const [, domain] = parts\n \n // Remove dots from local part (Gmail-style)\n localPart = localPart.replace(/\\./g, '')\n \n // Remove everything after + (Gmail-style aliases)\n const plusIndex = localPart.indexOf('+')\n if (plusIndex > -1) {\n localPart = localPart.substring(0, plusIndex)\n }\n \n return `${localPart}@${domain}`\n}\n\n/**\n * Check if email domain is allowed\n */\nexport function isDomainAllowed(\n email: string,\n allowedDomains?: string[]\n): boolean {\n // Validate email format first\n if (!isValidEmail(email)) {\n return false\n }\n \n // If no domains specified, allow all valid emails\n if (!allowedDomains || allowedDomains.length === 0) {\n return true\n }\n\n const domain = email.split('@')[1]?.toLowerCase()\n if (!domain) return false\n\n return allowedDomains.some(\n allowedDomain => domain === allowedDomain.toLowerCase()\n )\n}\n\n/**\n * Sanitize user input to prevent XSS\n */\nexport function sanitizeInput(input: string): string {\n if (!input) return ''\n \n // First, remove all HTML tags and scripts\n let cleaned = DOMPurify.sanitize(input, { \n ALLOWED_TAGS: [],\n ALLOWED_ATTR: [],\n KEEP_CONTENT: true\n })\n \n // Additional security: remove dangerous patterns\n cleaned = cleaned\n .replace(/javascript:/gi, '')\n .replace(/data:/gi, '')\n .replace(/vbscript:/gi, '')\n .replace(/file:\\/\\//gi, '')\n .replace(/onload/gi, '')\n .replace(/onerror/gi, '')\n .replace(/onclick/gi, '')\n .replace(/onmouseover/gi, '')\n .replace(/alert\\(/gi, '')\n .replace(/prompt\\(/gi, '')\n .replace(/confirm\\(/gi, '')\n .replace(/\\|/g, '') // Remove pipe character (command injection)\n .replace(/;/g, '') // Remove semicolon (command chaining)\n .replace(/`/g, '') // Remove backticks (command substitution)\n .replace(/&&/g, '') // Remove command chaining\n .replace(/\\$\\(/g, '') // Remove command substitution pattern $()\n .replace(/\\.\\./g, '') // Remove directory traversal\n .replace(/\\/..\\//g, '') // Remove path traversal\n .replace(/\\0/g, '') // Remove null bytes\n \n return cleaned.trim()\n}\n\n/**\n * Extract UTM parameters from URL search params\n */\nexport function extractUTMParams(searchParams: URLSearchParams): Record<string, string> {\n const utmParams: Record<string, string> = {}\n const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']\n\n utmKeys.forEach(key => {\n const value = searchParams.get(key)\n if (value) {\n // Remove 'utm_' prefix for storage\n const shortKey = key.replace('utm_', '')\n utmParams[shortKey] = value\n }\n })\n\n return utmParams\n}\n\n/**\n * Validate source field - only allow predefined values\n */\nexport function isValidSource(source: string): boolean {\n if (!source || typeof source !== 'string') return false\n \n const allowedSources = [\n 'website',\n 'api',\n 'import',\n 'admin',\n 'signup-form',\n 'magic-link',\n 'preferences',\n 'external'\n ]\n \n return allowedSources.includes(source)\n}\n\n/**\n * Validate subscriber data before creation\n */\nexport interface ValidateSubscriberResult {\n valid: boolean\n errors: string[]\n}\n\nexport function validateSubscriberData(data: any): ValidateSubscriberResult {\n const errors: string[] = []\n\n // Email validation\n if (!data.email) {\n errors.push('Email is required')\n } else if (!isValidEmail(data.email)) {\n errors.push('Invalid email format')\n }\n\n // Name validation (optional but if provided, should be reasonable)\n if (data.name && data.name.length > 100) {\n errors.push('Name is too long (max 100 characters)')\n }\n\n // Source validation\n if (data.source !== undefined) {\n if (!data.source || data.source.length === 0) {\n errors.push('Source cannot be empty')\n } else if (data.source.length > 50) {\n errors.push('Source is too long (max 50 characters)')\n } else if (!isValidSource(data.source)) {\n errors.push('Invalid source value')\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}","import jwt from 'jsonwebtoken'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport interface MagicLinkTokenPayload {\n subscriberId: string\n email: string\n type: 'magic-link'\n}\n\nexport interface SessionTokenPayload {\n subscriberId: string\n email: string\n type: 'session'\n}\n\n/**\n * Get JWT secret from environment or generate a warning\n */\nfunction getJWTSecret(): string {\n const secret = process.env.JWT_SECRET || process.env.PAYLOAD_SECRET\n\n if (!secret) {\n console.warn(\n 'WARNING: No JWT_SECRET or PAYLOAD_SECRET found in environment variables. ' +\n 'Magic link authentication will not work properly. ' +\n 'Please set JWT_SECRET in your environment.'\n )\n // Return a placeholder to prevent crashes during development\n return 'INSECURE_DEVELOPMENT_SECRET_PLEASE_SET_JWT_SECRET'\n }\n\n return secret\n}\n\n/**\n * Generate a magic link token for email authentication\n */\nexport function generateMagicLinkToken(\n subscriberId: string,\n email: string,\n config: NewsletterPluginConfig\n): string {\n const payload: MagicLinkTokenPayload = {\n subscriberId,\n email,\n type: 'magic-link',\n }\n\n const expiresIn = config.auth?.tokenExpiration || '7d'\n\n return jwt.sign(payload, getJWTSecret(), {\n expiresIn: expiresIn,\n issuer: 'payload-newsletter-plugin',\n } as jwt.SignOptions)\n}\n\n/**\n * Verify a magic link token\n */\nexport function verifyMagicLinkToken(token: string): MagicLinkTokenPayload {\n try {\n const payload = jwt.verify(token, getJWTSecret(), {\n issuer: 'payload-newsletter-plugin',\n }) as any\n\n if (payload.type !== 'magic-link') {\n throw new Error('Invalid token type')\n }\n\n return payload as MagicLinkTokenPayload\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'TokenExpiredError') {\n throw new Error('Magic link has expired. Please request a new one.')\n }\n if (error instanceof Error && error.name === 'JsonWebTokenError') {\n throw new Error('Invalid magic link token')\n }\n throw error\n }\n}\n\n/**\n * Generate a session token after successful magic link verification\n */\nexport function generateSessionToken(\n subscriberId: string,\n email: string\n): string {\n const payload: SessionTokenPayload = {\n subscriberId,\n email,\n type: 'session',\n }\n\n return jwt.sign(payload, getJWTSecret(), {\n expiresIn: '30d',\n issuer: 'payload-newsletter-plugin',\n })\n}\n\n/**\n * Verify a session token\n */\nexport function verifySessionToken(token: string): SessionTokenPayload {\n try {\n const payload = jwt.verify(token, getJWTSecret(), {\n issuer: 'payload-newsletter-plugin',\n }) as any\n\n if (payload.type !== 'session') {\n throw new Error('Invalid token type')\n }\n\n return payload as SessionTokenPayload\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'TokenExpiredError') {\n throw new Error('Session has expired. Please sign in again.')\n }\n if (error instanceof Error && error.name === 'JsonWebTokenError') {\n throw new Error('Invalid session token')\n }\n throw error\n }\n}\n\n/**\n * Generate a magic link URL\n */\nexport function generateMagicLinkURL(\n token: string,\n baseURL: string,\n config: NewsletterPluginConfig\n): string {\n const path = config.auth?.magicLinkPath || '/newsletter/verify'\n const url = new URL(path, baseURL)\n url.searchParams.set('token', token)\n return url.toString()\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, Subscriber, SubscribeRequestData, ExtendedPayloadRequest } from '../types'\nimport { \n isDomainAllowed, \n sanitizeInput, \n validateSubscriberData,\n extractUTMParams \n} from '../utils/validation'\nimport { generateMagicLinkToken, generateMagicLinkURL } from '../utils/jwt'\nimport { renderEmail } from '../emails/render'\n\nexport const createSubscribeEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/subscribe',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { \n email, \n name, \n source,\n preferences,\n leadMagnet,\n surveyResponses,\n metadata = {}\n } = data as SubscribeRequestData\n\n // Trim email before validation\n const trimmedEmail = email?.trim()\n\n // Validate input\n const validation = validateSubscriberData({ email: trimmedEmail, name, source })\n if (!validation.valid) {\n return Response.json({\n success: false,\n errors: validation.errors,\n }, { status: 400 })\n }\n\n // Check domain restrictions from global settings\n // Settings are public info needed for validation, but we can still respect access control\n const settings = await req.payload.findGlobal({\n slug: config.settingsSlug || 'newsletter-settings',\n overrideAccess: false,\n // No user context for public endpoint\n })\n\n const allowedDomains = settings?.subscriptionSettings?.allowedDomains?.map((d: { domain: string }) => d.domain) || []\n if (!isDomainAllowed(trimmedEmail, allowedDomains)) {\n return Response.json({\n success: false,\n error: 'Email domain not allowed',\n }, { status: 400 })\n }\n\n // Check if already subscribed\n // This needs admin access to check for existing email\n const existing = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n email: {\n equals: trimmedEmail.toLowerCase(),\n },\n },\n overrideAccess: true, // Need to check for duplicates in public endpoint\n })\n\n if (existing.docs.length > 0) {\n const subscriber = existing.docs[0]\n \n // If unsubscribed, don't allow resubscription via API\n if (subscriber.subscriptionStatus === 'unsubscribed') {\n return Response.json({\n success: false,\n error: 'This email has been unsubscribed. Please contact support to resubscribe.',\n }, { status: 400 })\n }\n\n return Response.json({\n success: false,\n error: 'Already subscribed',\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n }, { status: 400 })\n }\n\n // Check IP rate limiting\n const ipAddress = req.ip || req.connection?.remoteAddress\n const maxPerIP = settings?.subscriptionSettings?.maxSubscribersPerIP || 10\n\n const ipSubscribers = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n 'signupMetadata.ipAddress': {\n equals: ipAddress,\n },\n },\n overrideAccess: true, // Need to check IP limits in public endpoint\n })\n\n if (ipSubscribers.docs.length >= maxPerIP) {\n return Response.json({\n success: false,\n error: 'Too many subscriptions from this IP address',\n }, { status: 429 })\n }\n\n // Extract UTM parameters\n const referer = req.headers.get('referer') || req.headers.get('referrer') || ''\n let utmParams = {}\n if (referer) {\n try {\n utmParams = extractUTMParams(new URL(referer).searchParams)\n } catch {\n // Invalid URL, ignore UTM params\n }\n }\n\n // Prepare subscriber data\n const subscriberData: Partial<Subscriber> = {\n email: trimmedEmail.toLowerCase(),\n name: name ? sanitizeInput(name) : undefined,\n locale: metadata.locale || config.i18n?.defaultLocale || 'en',\n subscriptionStatus: settings?.subscriptionSettings?.requireDoubleOptIn ? 'pending' : 'active',\n source: source || 'api',\n emailPreferences: {\n newsletter: true,\n announcements: true,\n ...(preferences || {}),\n },\n signupMetadata: {\n ipAddress,\n userAgent: req.headers.get('user-agent') || undefined,\n referrer: referer,\n signupPage: metadata.signupPage || referer,\n },\n }\n\n // Add UTM parameters if tracking is enabled\n if (config.features?.utmTracking?.enabled && Object.keys(utmParams).length > 0) {\n subscriberData.utmParameters = utmParams\n }\n\n // Add lead magnet if provided\n if (config.features?.leadMagnets?.enabled && leadMagnet) {\n subscriberData.leadMagnet = leadMagnet\n }\n\n // Create subscriber\n // Public endpoint needs to create subscribers\n const subscriber = await req.payload.create({\n collection: config.subscribersSlug || 'subscribers',\n data: subscriberData,\n overrideAccess: true, // Public endpoint needs to create subscribers\n })\n\n // Handle survey responses if provided\n if (config.features?.surveys?.enabled && surveyResponses) {\n // TODO: Store survey responses\n }\n\n // Send confirmation email if double opt-in\n if (settings?.subscriptionSettings?.requireDoubleOptIn) {\n try {\n // Generate magic link token\n const token = generateMagicLinkToken(\n String(subscriber.id),\n subscriber.email,\n config\n )\n \n // Generate magic link URL\n const serverURL = req.payload.config.serverURL || process.env.PAYLOAD_PUBLIC_SERVER_URL || ''\n const magicLinkURL = generateMagicLinkURL(token, serverURL, config)\n \n // Get email service\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n \n if (emailService) {\n // Render email\n const html = await renderEmail('magic-link', {\n magicLink: magicLinkURL,\n email: subscriber.email,\n siteName: settings?.brandSettings?.siteName || 'Newsletter',\n expiresIn: config.auth?.tokenExpiration || '7d',\n })\n \n // Send email\n await emailService.send({\n to: subscriber.email,\n subject: settings?.brandSettings?.siteName ? `Verify your email for ${settings.brandSettings.siteName}` : 'Verify your email',\n html,\n })\n \n // Magic link email sent successfully\n } else {\n console.warn('Email service not initialized, cannot send magic link')\n }\n } catch (error) {\n console.error('Failed to send magic link email:', error)\n // Don't fail the subscription if email fails\n }\n }\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n message: settings?.subscriptionSettings?.requireDoubleOptIn \n ? 'Please check your email to confirm your subscription'\n : 'Successfully subscribed',\n })\n } catch {\n return Response.json({\n success: false,\n error: 'Failed to subscribe. Please try again.',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, VerifyMagicLinkRequestData, ExtendedPayloadRequest } from '../types'\nimport { \n verifyMagicLinkToken, \n generateSessionToken \n} from '../utils/jwt'\nimport { renderEmail } from '../emails/render'\n\nexport const createVerifyMagicLinkEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/verify-magic-link',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { token } = data as VerifyMagicLinkRequestData\n\n if (!token) {\n return Response.json({\n success: false,\n error: 'Token is required',\n }, { status: 400 })\n }\n\n // Verify the magic link token\n let payload\n try {\n payload = verifyMagicLinkToken(token)\n } catch (error: unknown) {\n return Response.json({\n success: false,\n error: error instanceof Error ? error.message : 'Invalid token',\n }, { status: 401 })\n }\n\n // Find the subscriber - token verified so we can use admin access for initial lookup\n const subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n // Keep overrideAccess: true for token verification\n })\n\n if (!subscriber) {\n return Response.json({\n success: false,\n error: 'Subscriber not found',\n }, { status: 404 })\n }\n\n // Check if email matches\n if (subscriber.email !== payload.email) {\n return Response.json({\n success: false,\n error: 'Invalid token',\n }, { status: 401 })\n }\n\n // Check if subscriber is active\n if (subscriber.subscriptionStatus === 'unsubscribed') {\n return Response.json({\n success: false,\n error: 'This email has been unsubscribed',\n }, { status: 403 })\n }\n\n // Create synthetic user for subscriber operations\n const syntheticUser = {\n collection: 'subscribers',\n id: subscriber.id,\n email: subscriber.email,\n }\n\n // Update subscription status if pending\n let isNewlyActivated = false\n if (subscriber.subscriptionStatus === 'pending') {\n await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: subscriber.id,\n data: {\n subscriptionStatus: 'active',\n },\n overrideAccess: false,\n user: syntheticUser,\n })\n isNewlyActivated = true\n }\n\n // Clear the magic link token\n await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: subscriber.id,\n data: {\n magicLinkToken: null,\n magicLinkTokenExpiry: null,\n },\n overrideAccess: false,\n user: syntheticUser,\n })\n\n // Generate session token\n const sessionToken = generateSessionToken(\n String(subscriber.id),\n subscriber.email\n )\n\n // Send welcome email if newly activated\n if (isNewlyActivated) {\n try {\n // Get email service\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n \n if (emailService) {\n // Get settings for site name\n const settings = await req.payload.findGlobal({\n slug: config.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: subscriber.email,\n siteName: settings?.brandSettings?.siteName || 'Newsletter',\n preferencesUrl: `${serverURL}/account/preferences`, // This could be customized\n })\n \n // Send email\n await emailService.send({\n to: subscriber.email,\n subject: settings?.brandSettings?.siteName ? `Welcome to ${settings.brandSettings.siteName}!` : 'Welcome!',\n html,\n })\n \n // Welcome email sent successfully\n } else {\n console.warn('Email service not initialized, cannot send welcome email')\n }\n } catch (error) {\n console.error('Failed to send welcome email:', error)\n // Don't fail the verification if welcome email fails\n }\n }\n\n // Set the session cookie\n const headers = new Headers()\n headers.append('Set-Cookie', `newsletter-auth=${sessionToken}; HttpOnly; Secure=${process.env.NODE_ENV === 'production'}; SameSite=Lax; Path=/; Max-Age=${30 * 24 * 60 * 60}`)\n\n return Response.json({\n success: true,\n sessionToken,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n locale: subscriber.locale,\n emailPreferences: subscriber.emailPreferences,\n },\n }, { headers })\n } catch (error: unknown) {\n console.error('Verify magic link error:', error)\n return Response.json({\n success: false,\n error: 'Failed to verify magic link',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, Subscriber, UpdatePreferencesRequestData, ExtendedPayloadRequest } from '../types'\nimport { verifySessionToken } from '../utils/jwt'\n\nexport const createPreferencesEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/preferences',\n method: 'get',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n // Get token from Authorization header\n const authHeader = req.headers.get('authorization')\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n return Response.json({\n success: false,\n error: 'Authorization required',\n }, { status: 401 })\n }\n\n const token = authHeader.substring(7)\n\n // Verify session token\n let payload\n try {\n payload = verifySessionToken(token)\n } catch (error: unknown) {\n return Response.json({\n success: false,\n error: error instanceof Error ? error.message : 'Invalid token',\n }, { status: 401 })\n }\n\n // Get subscriber - use synthetic user to ensure access control\n const subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n overrideAccess: false,\n user: {\n collection: 'subscribers',\n id: payload.subscriberId,\n email: payload.email,\n },\n })\n\n if (!subscriber) {\n return Response.json({\n success: false,\n error: 'Subscriber not found',\n }, { status: 404 })\n }\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n locale: subscriber.locale,\n emailPreferences: subscriber.emailPreferences,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n })\n } catch (error: unknown) {\n console.error('Get preferences error:', error)\n return Response.json({\n success: false,\n error: 'Failed to get preferences',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}\n\nexport const createUpdatePreferencesEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/preferences',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n // Get token from Authorization header\n const authHeader = req.headers.get('authorization')\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n return Response.json({\n success: false,\n error: 'Authorization required',\n }, { status: 401 })\n }\n\n const token = authHeader.substring(7)\n\n // Verify session token\n let payload\n try {\n payload = verifySessionToken(token)\n } catch (error: unknown) {\n return Response.json({\n success: false,\n error: error instanceof Error ? error.message : 'Invalid token',\n }, { status: 401 })\n }\n\n const data = await req.json()\n const { name, locale, emailPreferences } = data as UpdatePreferencesRequestData\n\n // Prepare update data\n const updateData: Partial<Subscriber> = {}\n \n if (name !== undefined) {\n updateData.name = name\n }\n \n if (locale !== undefined) {\n updateData.locale = locale\n }\n \n if (emailPreferences !== undefined) {\n updateData.emailPreferences = emailPreferences\n }\n\n // Update subscriber - use synthetic user to ensure only updating own data\n const subscriber = await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n data: updateData,\n overrideAccess: false,\n user: {\n collection: 'subscribers',\n id: payload.subscriberId,\n email: payload.email,\n },\n })\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n locale: subscriber.locale,\n emailPreferences: subscriber.emailPreferences,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n })\n } catch (error: unknown) {\n console.error('Update preferences error:', error)\n return Response.json({\n success: false,\n error: 'Failed to update preferences',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, UnsubscribeRequestData, ExtendedPayloadRequest } from '../types'\nimport { isValidEmail } from '../utils/validation'\n\nexport const createUnsubscribeEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/unsubscribe',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { email, token } = data as UnsubscribeRequestData\n\n // Two methods: email or token\n if (!email && !token) {\n return Response.json({\n success: false,\n error: 'Email or token is required',\n }, { status: 400 })\n }\n\n let subscriber\n\n if (token) {\n // Token-based unsubscribe (from email link)\n try {\n const jwt = await import('jsonwebtoken')\n const payload = jwt.verify(\n token,\n process.env.JWT_SECRET || process.env.PAYLOAD_SECRET || ''\n ) as { type: string; subscriberId: string; email: string }\n\n if (payload.type !== 'unsubscribe') {\n throw new Error('Invalid token type')\n }\n\n // Token verified, so we can look up the subscriber\n // Using overrideAccess: true here is OK since we verified the token\n subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n })\n } catch {\n return Response.json({\n success: false,\n error: 'Invalid or expired unsubscribe link',\n }, { status: 401 })\n }\n } else {\n // Email-based unsubscribe\n if (!email || !isValidEmail(email)) {\n return Response.json({\n success: false,\n error: 'Invalid email format',\n }, { status: 400 })\n }\n\n const result = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n email: {\n equals: email!.toLowerCase(),\n },\n },\n })\n\n if (result.docs.length === 0) {\n // Don't reveal if email exists or not\n return Response.json({\n success: true,\n message: 'If this email was subscribed, it has been unsubscribed.',\n })\n }\n\n subscriber = result.docs[0]\n }\n\n if (!subscriber) {\n return Response.json({\n success: true,\n message: 'If this email was subscribed, it has been unsubscribed.',\n })\n }\n\n // Check if already unsubscribed\n if (subscriber.subscriptionStatus === 'unsubscribed') {\n return Response.json({\n success: true,\n message: 'Already unsubscribed',\n })\n }\n\n // Update subscription status - use synthetic user to ensure proper access\n await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: subscriber.id,\n data: {\n subscriptionStatus: 'unsubscribed',\n unsubscribedAt: new Date().toISOString(),\n },\n overrideAccess: false,\n user: {\n collection: 'subscribers',\n id: subscriber.id,\n email: subscriber.email,\n },\n })\n\n return Response.json({\n success: true,\n message: 'Successfully unsubscribed',\n })\n } catch (error: unknown) {\n console.error('Unsubscribe error:', error)\n return Response.json({\n success: false,\n error: 'Failed to unsubscribe. Please try again.',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","export interface RateLimiterOptions {\n maxAttempts: number\n windowMs: number\n prefix?: string\n}\n\nexport class RateLimiter {\n private attempts: Map<string, { count: number; resetTime: number }> = new Map()\n private options: RateLimiterOptions\n\n constructor(options: RateLimiterOptions) {\n this.options = options\n }\n\n async checkLimit(key: string): Promise<boolean> {\n const now = Date.now()\n const record = this.attempts.get(key)\n\n if (!record || record.resetTime < now) {\n this.attempts.set(key, {\n count: 1,\n resetTime: now + this.options.windowMs\n })\n return true\n }\n\n if (record.count >= this.options.maxAttempts) {\n return false\n }\n\n record.count++\n return true\n }\n\n async incrementAttempt(key: string): Promise<void> {\n const now = Date.now()\n const record = this.attempts.get(key)\n\n if (!record || record.resetTime < now) {\n this.attempts.set(key, {\n count: 1,\n resetTime: now + this.options.windowMs\n })\n } else {\n record.count++\n }\n }\n\n async reset(key: string): Promise<void> {\n this.attempts.delete(key)\n }\n\n async resetAll(): Promise<void> {\n this.attempts.clear()\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, SigninRequestData, ExtendedPayloadRequest } from '../types'\nimport { validateSubscriberData } from '../utils/validation'\nimport { generateMagicLinkToken, generateMagicLinkURL } from '../utils/jwt'\nimport { renderEmail } from '../emails/render'\nimport { RateLimiter } from '../utils/rate-limiter'\n\n// Create rate limiter: 5 attempts per 15 minutes\nconst signinRateLimiter = new RateLimiter({\n maxAttempts: 5,\n windowMs: 15 * 60 * 1000, // 15 minutes\n prefix: 'signin',\n})\n\nexport const createSigninEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/signin',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { email } = data as SigninRequestData\n\n // Validate email\n const validation = validateSubscriberData({ email })\n if (!validation.valid) {\n return Response.json({\n success: false,\n errors: validation.errors,\n }, { status: 400 })\n }\n\n // Check rate limit (per email to prevent abuse)\n const rateLimitKey = `signin:${email.toLowerCase()}`\n const allowed = await signinRateLimiter.checkLimit(rateLimitKey)\n \n if (!allowed) {\n return Response.json({\n success: false,\n error: 'Too many sign-in attempts. Please try again later.',\n }, { status: 429 })\n }\n\n // Find existing active subscriber\n const result = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n email: { equals: email.toLowerCase() },\n subscriptionStatus: { equals: 'active' },\n },\n limit: 1,\n overrideAccess: true, // Need to check subscriber exists\n })\n\n if (result.docs.length === 0) {\n return Response.json({\n success: false,\n error: 'Email not found. Please subscribe first.',\n }, { status: 404 })\n }\n\n const subscriber = result.docs[0]\n\n // Generate magic link token\n const token = generateMagicLinkToken(\n String(subscriber.id),\n subscriber.email,\n config\n )\n\n // Generate magic link URL\n const serverURL = req.payload.config.serverURL || process.env.PAYLOAD_PUBLIC_SERVER_URL || ''\n const magicLinkURL = generateMagicLinkURL(token, serverURL, config)\n\n // Get email service\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n\n if (emailService) {\n // Get settings for customization\n const settings = await req.payload.findGlobal({\n slug: config.settingsSlug || 'newsletter-settings',\n })\n\n // Render email\n const html = await renderEmail('signin', {\n magicLink: magicLinkURL,\n email: subscriber.email,\n siteName: settings?.brandSettings?.siteName || 'Newsletter',\n expiresIn: config.auth?.tokenExpiration || '7d',\n })\n\n // Send email\n await emailService.send({\n to: subscriber.email,\n subject: settings?.brandSettings?.siteName \n ? `Sign in to ${settings.brandSettings.siteName}` \n : 'Sign in to your account',\n html,\n })\n\n // Sign-in email sent successfully\n } else {\n console.warn('Email service not initialized, cannot send sign-in link')\n }\n\n return Response.json({\n success: true,\n message: 'Check your email for the sign-in link',\n })\n } catch (error) {\n console.error('Sign-in error:', error)\n return Response.json({\n success: false,\n error: 'Failed to process sign-in request',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, ExtendedPayloadRequest } from '../types'\nimport { verifySessionToken } from '../utils/jwt'\n\nexport const createMeEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/me',\n method: 'get',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n // Get token from cookie header\n const cookieHeader = req.headers.get('cookie') || ''\n const cookies = Object.fromEntries(\n cookieHeader.split('; ').map(c => {\n const [key, ...value] = c.split('=')\n return [key, value.join('=')]\n })\n )\n const token = cookies['newsletter-auth']\n \n if (!token) {\n return Response.json({\n success: false,\n error: 'Not authenticated',\n }, { status: 401 })\n }\n\n // Verify the session token\n let payload\n try {\n payload = verifySessionToken(token)\n } catch {\n return Response.json({\n success: false,\n error: 'Invalid or expired session',\n }, { status: 401 })\n }\n\n // Get fresh subscriber data\n const subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n overrideAccess: true, // Need to get subscriber data\n })\n\n if (!subscriber || subscriber.subscriptionStatus !== 'active') {\n return Response.json({\n success: false,\n error: 'Not authenticated',\n }, { status: 401 })\n }\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n status: subscriber.subscriptionStatus,\n preferences: {\n frequency: subscriber.emailPreferences?.frequency,\n categories: subscriber.emailPreferences?.categories,\n },\n createdAt: subscriber.createdAt,\n updatedAt: subscriber.updatedAt,\n },\n })\n } catch (error) {\n console.error('Me endpoint error:', error)\n return Response.json({\n success: false,\n error: 'Internal server error',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, ExtendedPayloadRequest } from '../types'\n\nexport const createSignoutEndpoint = (\n _config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/signout',\n method: 'post',\n handler: ((_req: ExtendedPayloadRequest) => {\n try {\n // In Payload v3, cookies are handled differently\n // The Response object doesn't have a clearCookie method\n // We'll need to set the cookie with an expired date\n const headers = new Headers()\n headers.append('Set-Cookie', `newsletter-auth=; HttpOnly; Secure=${process.env.NODE_ENV === 'production'}; SameSite=Lax; Path=/; Max-Age=0`)\n \n return Response.json({ \n success: true, \n message: 'Signed out successfully' \n }, { headers })\n } catch (error) {\n console.error('Signout error:', error)\n return Response.json({\n success: false,\n error: 'Failed to sign out',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { createSubscribeEndpoint } from './subscribe'\nimport { createVerifyMagicLinkEndpoint } from './verify-magic-link'\nimport { createPreferencesEndpoint, createUpdatePreferencesEndpoint } from './preferences'\nimport { createUnsubscribeEndpoint } from './unsubscribe'\nimport { createSigninEndpoint } from './signin'\nimport { createMeEndpoint } from './me'\nimport { createSignoutEndpoint } from './signout'\n\nexport function createNewsletterEndpoints(\n config: NewsletterPluginConfig\n): Endpoint[] {\n const endpoints: Endpoint[] = [\n createSubscribeEndpoint(config),\n createUnsubscribeEndpoint(config),\n ]\n\n // Add auth endpoints if enabled\n if (config.auth?.enabled !== false) {\n endpoints.push(\n createVerifyMagicLinkEndpoint(config),\n createPreferencesEndpoint(config),\n createUpdatePreferencesEndpoint(config),\n createSigninEndpoint(config),\n createMeEndpoint(config),\n createSignoutEndpoint(config)\n )\n }\n\n return endpoints\n}","import type { Field } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport function createNewsletterSchedulingFields(\n config: NewsletterPluginConfig\n): Field[] {\n const groupName = config.features?.newsletterScheduling?.fields?.groupName || 'newsletterScheduling'\n const contentField = config.features?.newsletterScheduling?.fields?.contentField || 'content'\n const createMarkdownField = config.features?.newsletterScheduling?.fields?.createMarkdownField !== false\n\n const fields: Field[] = [\n {\n name: groupName,\n type: 'group',\n label: 'Newsletter Scheduling',\n admin: {\n condition: (data, { user }) => user?.collection === 'users', // Only show for admin users\n },\n fields: [\n {\n name: 'scheduled',\n type: 'checkbox',\n label: 'Schedule for Newsletter',\n defaultValue: false,\n admin: {\n description: 'Schedule this content to be sent as a newsletter',\n },\n },\n {\n name: 'scheduledDate',\n type: 'date',\n label: 'Send Date',\n required: true,\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'When to send this newsletter',\n },\n },\n {\n name: 'sentDate',\n type: 'date',\n label: 'Sent Date',\n admin: {\n readOnly: true,\n condition: (data) => data?.[groupName]?.sendStatus === 'sent',\n description: 'When this newsletter was sent',\n },\n },\n {\n name: 'sendStatus',\n type: 'select',\n label: 'Status',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Scheduled', value: 'scheduled' },\n { label: 'Sending', value: 'sending' },\n { label: 'Sent', value: 'sent' },\n { label: 'Failed', value: 'failed' },\n ],\n defaultValue: 'draft',\n admin: {\n readOnly: true,\n description: 'Current send status',\n },\n },\n {\n name: 'emailSubject',\n type: 'text',\n label: 'Email Subject',\n required: true,\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Subject line for the newsletter email',\n },\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Email Preheader',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Preview text that appears after the subject line',\n },\n },\n {\n name: 'segments',\n type: 'select',\n label: 'Target Segments',\n hasMany: true,\n options: [\n { label: 'All Subscribers', value: 'all' },\n ...(config.i18n?.locales?.map(locale => ({\n label: `${locale.toUpperCase()} Subscribers`,\n value: locale,\n })) || []),\n ],\n defaultValue: ['all'],\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Which subscriber segments to send to',\n },\n },\n {\n name: 'testEmails',\n type: 'array',\n label: 'Test Email Recipients',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled && data?.[groupName]?.sendStatus === 'draft',\n description: 'Send test emails before scheduling',\n },\n fields: [\n {\n name: 'email',\n type: 'email',\n required: true,\n },\n ],\n },\n ],\n },\n ]\n\n // Add markdown companion field if requested\n if (createMarkdownField) {\n fields.push(createMarkdownFieldInternal({\n name: `${contentField}Markdown`,\n richTextField: contentField,\n label: 'Email Content (Markdown)',\n admin: {\n position: 'sidebar',\n condition: (data: any) => Boolean(data?.[contentField] && data?.[groupName]?.scheduled),\n description: 'Markdown version for email rendering',\n readOnly: true,\n },\n }))\n }\n\n return fields\n}\n\n/**\n * Create a markdown companion field for rich text\n * This creates a virtual field that converts rich text to markdown\n */\nfunction createMarkdownFieldInternal(config: {\n name: string\n richTextField: string\n label?: string\n admin?: any\n}): Field {\n return {\n name: config.name,\n type: 'textarea',\n label: config.label || 'Markdown',\n admin: {\n ...config.admin,\n description: config.admin?.description || 'Auto-generated from rich text content',\n },\n hooks: {\n afterRead: [\n async ({ data }) => {\n // Convert rich text to markdown on read\n if (data?.[config.richTextField]) {\n try {\n const { convertLexicalToMarkdown } = await import('@payloadcms/richtext-lexical')\n return convertLexicalToMarkdown({\n data: data[config.richTextField],\n } as any)\n } catch {\n return ''\n }\n }\n return ''\n },\n ],\n beforeChange: [\n () => {\n // Don't save markdown to database\n return null\n },\n ],\n },\n }\n}","import type { TaskConfig, PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig } from '../types/index'\n\nexport const createUnsubscribeSyncJob = (\n pluginConfig: NewsletterPluginConfig\n): TaskConfig => {\n return {\n slug: 'sync-unsubscribes',\n label: 'Sync Unsubscribes from Email Service',\n handler: async ({ req }: { req: PayloadRequest }) => {\n const subscribersSlug = pluginConfig.subscribersSlug || 'subscribers'\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n \n if (!emailService) {\n console.error('Email service not configured')\n return {\n output: {\n syncedCount: 0\n }\n }\n }\n\n let syncedCount = 0\n \n try {\n // For Broadcast: Poll all subscribers\n if (emailService.getProvider() === 'broadcast') {\n console.warn('Starting Broadcast unsubscribe sync...')\n \n // Get Broadcast configuration\n const broadcastConfig = pluginConfig.providers?.broadcast\n if (!broadcastConfig) {\n throw new Error('Broadcast configuration not found')\n }\n\n const apiUrl = broadcastConfig.apiUrl.replace(/\\/$/, '')\n const token = process.env.NODE_ENV === 'production' \n ? broadcastConfig.tokens.production \n : broadcastConfig.tokens.development\n\n let page = 1\n let hasMore = true\n\n while (hasMore) {\n // Fetch subscribers from Broadcast\n const response = await fetch(\n `${apiUrl}/api/v1/subscribers.json?page=${page}`,\n {\n headers: {\n 'Authorization': `Bearer ${token}`,\n },\n }\n )\n\n if (!response.ok) {\n throw new Error(`Broadcast API error: ${response.status}`)\n }\n\n const data = await response.json()\n const broadcastSubscribers = data.subscribers || []\n \n // Process each subscriber\n for (const broadcastSub of broadcastSubscribers) {\n // Find corresponding subscriber in Payload\n const payloadSubscribers = await req.payload.find({\n collection: subscribersSlug,\n where: {\n email: {\n equals: broadcastSub.email,\n },\n },\n limit: 1,\n })\n\n if (payloadSubscribers.docs.length > 0) {\n const payloadSub = payloadSubscribers.docs[0]\n \n // Check if unsubscribe status differs\n const broadcastUnsubscribed = !broadcastSub.is_active || broadcastSub.unsubscribed_at\n const payloadUnsubscribed = payloadSub.subscriptionStatus === 'unsubscribed'\n \n if (broadcastUnsubscribed && !payloadUnsubscribed) {\n // Update Payload subscriber to unsubscribed\n await req.payload.update({\n collection: subscribersSlug,\n id: payloadSub.id,\n data: {\n subscriptionStatus: 'unsubscribed',\n unsubscribedAt: broadcastSub.unsubscribed_at || new Date().toISOString(),\n },\n })\n syncedCount++\n console.warn(`Unsubscribed: ${broadcastSub.email}`)\n }\n }\n }\n\n // Check pagination\n if (data.pagination && data.pagination.current < data.pagination.total_pages) {\n page++\n } else {\n hasMore = false\n }\n }\n\n console.warn(`Broadcast sync complete. Unsubscribed ${syncedCount} contacts.`)\n }\n\n // For Resend: Use Audiences API\n if (emailService.getProvider() === 'resend') {\n console.warn('Starting Resend unsubscribe sync...')\n \n // Note: Resend webhooks are preferred over polling\n // This is a fallback polling implementation\n \n // First, get all audiences\n const resendConfig = pluginConfig.providers?.resend\n if (!resendConfig) {\n throw new Error('Resend configuration not found')\n }\n\n // You would need to implement audience/contact polling here\n // Resend's API structure would require:\n // 1. List audiences\n // 2. For each audience, list contacts\n // 3. Check unsubscribed status\n \n console.warn('Resend polling implementation needed - webhooks recommended')\n }\n\n // Custom after sync hook\n if (pluginConfig.hooks?.afterUnsubscribeSync) {\n await pluginConfig.hooks.afterUnsubscribeSync({ \n req, \n syncedCount: syncedCount\n })\n }\n\n } catch (error) {\n console.error('Unsubscribe sync error:', error)\n throw error\n }\n \n return {\n output: {\n syncedCount\n }\n }\n },\n }\n}","import type { PayloadRequest } from 'payload'\nimport jwt from 'jsonwebtoken'\n\n// Next.js types - these are optional and only used when Next.js is available\ninterface NextApiRequest {\n cookies?: { [key: string]: string }\n headers?: { [key: string]: string | string[] | undefined }\n [key: string]: any\n}\n\ninterface GetServerSidePropsContext {\n req: {\n cookies?: { [key: string]: string }\n headers?: { [key: string]: string | string[] | undefined }\n [key: string]: any\n }\n [key: string]: any\n}\n\ninterface TokenPayload {\n id: string\n email: string\n type?: string\n iat?: number\n exp?: number\n}\n\n/**\n * Extract token from request cookies\n */\nexport const getTokenFromRequest = (\n req: NextApiRequest | GetServerSidePropsContext['req'] | PayloadRequest\n): string | null => {\n // Handle different request types\n const cookies = (req as any).cookies || (req as any).headers?.cookie\n \n if (!cookies) return null\n \n // Parse cookies if it's a string\n if (typeof cookies === 'string') {\n const parsed = cookies.split(';').reduce((acc, cookie) => {\n const [key, value] = cookie.trim().split('=')\n acc[key] = value\n return acc\n }, {} as Record<string, string>)\n return parsed['newsletter-auth'] || null\n }\n \n // Direct cookie object\n return cookies['newsletter-auth'] || null\n}\n\n/**\n * Verify JWT token\n */\nexport const verifyToken = (\n token: string, \n secret: string\n): TokenPayload | null => {\n try {\n const decoded = jwt.verify(token, secret) as TokenPayload\n return decoded\n } catch {\n return null\n }\n}\n\n/**\n * Get authentication state for server-side rendering\n */\nexport const getServerSideAuth = async (\n context: GetServerSidePropsContext,\n secret?: string\n): Promise<{ subscriber: TokenPayload | null; isAuthenticated: boolean }> => {\n const token = getTokenFromRequest(context.req)\n \n if (!token) {\n return { subscriber: null, isAuthenticated: false }\n }\n \n const payloadSecret = secret || process.env.PAYLOAD_SECRET\n if (!payloadSecret) {\n console.error('No secret provided for token verification')\n return { subscriber: null, isAuthenticated: false }\n }\n \n const decoded = verifyToken(token, payloadSecret)\n \n if (!decoded) {\n return { subscriber: null, isAuthenticated: false }\n }\n \n return {\n subscriber: decoded,\n isAuthenticated: true,\n }\n}\n\n/**\n * Higher-order function for protecting pages\n */\nexport const requireAuth = <P extends { [key: string]: any }>(\n gssp?: (context: GetServerSidePropsContext) => Promise<{ props: P }>\n) => {\n return async (context: GetServerSidePropsContext) => {\n const { isAuthenticated, subscriber } = await getServerSideAuth(context)\n \n if (!isAuthenticated) {\n return {\n redirect: {\n destination: '/auth/signin',\n permanent: false,\n },\n }\n }\n \n // If there's a custom getServerSideProps, run it\n if (gssp) {\n const result = await gssp(context)\n return {\n ...result,\n props: {\n ...result.props,\n subscriber,\n },\n }\n }\n \n // Otherwise just return the subscriber\n return {\n props: {\n subscriber,\n } as any as P,\n }\n }\n}\n\n/**\n * Check if request has valid authentication\n */\nexport const isAuthenticated = (\n req: PayloadRequest | NextApiRequest,\n secret: string\n): boolean => {\n const token = getTokenFromRequest(req)\n if (!token) return false\n \n const decoded = verifyToken(token, secret)\n return !!decoded\n}","import type { Config } from 'payload'\nimport type { NewsletterPluginConfig } from './types'\nimport { createSubscribersCollection } from './collections/Subscribers'\nimport { createNewsletterSettingsGlobal } from './globals/NewsletterSettings'\nimport { createEmailService } from './providers'\nimport { createNewsletterEndpoints } from './endpoints'\nimport { createNewsletterSchedulingFields } from './fields/newsletterScheduling'\nimport { createUnsubscribeSyncJob } from './jobs/sync-unsubscribes'\n\n// Extend Payload type to include our email service\ndeclare module 'payload' {\n interface BasePayload {\n newsletterEmailService?: any\n }\n}\n\nexport const newsletterPlugin = (pluginConfig: NewsletterPluginConfig) => (incomingConfig: Config): Config => {\n // Validate and set defaults\n const config: NewsletterPluginConfig = {\n enabled: true,\n subscribersSlug: 'subscribers',\n settingsSlug: 'newsletter-settings',\n auth: {\n enabled: true,\n tokenExpiration: '7d',\n magicLinkPath: '/newsletter/verify',\n ...pluginConfig.auth,\n },\n ...pluginConfig,\n }\n\n // If plugin is disabled, return config unchanged\n if (!config.enabled) {\n return incomingConfig\n }\n\n // Create plugin collections and globals\n const subscribersCollection = createSubscribersCollection(config)\n const settingsGlobal = createNewsletterSettingsGlobal(config)\n\n // Build collections array\n let collections = [...(incomingConfig.collections || []), subscribersCollection]\n\n // Extend collections with newsletter scheduling fields if enabled\n if (config.features?.newsletterScheduling?.enabled) {\n const targetCollections = config.features.newsletterScheduling.collections || 'articles'\n const collectionsToExtend = Array.isArray(targetCollections) ? targetCollections : [targetCollections]\n const schedulingFields = createNewsletterSchedulingFields(config)\n \n collections = collections.map(collection => {\n if (collectionsToExtend.includes(collection.slug)) {\n return {\n ...collection,\n fields: [\n ...collection.fields,\n ...schedulingFields,\n ],\n }\n }\n return collection\n })\n }\n\n // Create API endpoints\n const endpoints = createNewsletterEndpoints(config)\n\n // Create sync job if enabled\n const syncJob = config.features?.unsubscribeSync?.enabled ? createUnsubscribeSyncJob(config) : null\n\n // Build the modified config\n const modifiedConfig: Config = {\n ...incomingConfig,\n collections,\n globals: [\n ...(incomingConfig.globals || []),\n settingsGlobal,\n ],\n endpoints: [\n ...(incomingConfig.endpoints || []),\n ...endpoints,\n ],\n jobs: syncJob ? {\n ...(incomingConfig.jobs || {}),\n tasks: [\n ...(incomingConfig.jobs?.tasks || []),\n syncJob,\n ],\n // Add cron schedule if specified\n autoRun: config.features?.unsubscribeSync?.schedule ? (\n Array.isArray(incomingConfig.jobs?.autoRun) \n ? [...incomingConfig.jobs.autoRun, {\n cron: config.features.unsubscribeSync.schedule,\n queue: 'newsletter-sync',\n limit: 100,\n }]\n : typeof incomingConfig.jobs?.autoRun === 'function'\n ? async (payload: any) => {\n const autoRunFn = incomingConfig.jobs!.autoRun as (payload: any) => any[] | Promise<any[]>\n const existingConfigs = await autoRunFn(payload)\n return [...existingConfigs, {\n cron: config.features!.unsubscribeSync!.schedule,\n queue: 'newsletter-sync',\n limit: 100,\n }]\n }\n : [{\n cron: config.features!.unsubscribeSync!.schedule,\n queue: 'newsletter-sync',\n limit: 100,\n }]\n ) : incomingConfig.jobs?.autoRun,\n } : incomingConfig.jobs,\n onInit: async (payload) => {\n // Initialize email service\n try {\n // Get settings from global\n const settings = await payload.findGlobal({\n slug: config.settingsSlug || 'newsletter-settings',\n })\n\n let emailServiceConfig: any\n \n if (settings) {\n emailServiceConfig = {\n provider: settings.provider || config.providers.default,\n fromAddress: settings.fromAddress || config.providers.resend?.fromAddress || config.providers.broadcast?.fromAddress || 'noreply@example.com',\n fromName: settings.fromName || config.providers.resend?.fromName || config.providers.broadcast?.fromName || 'Newsletter',\n replyTo: settings.replyTo,\n resend: settings.provider === 'resend' ? {\n apiKey: settings.resendSettings?.apiKey || config.providers.resend?.apiKey || '',\n audienceIds: settings.resendSettings?.audienceIds?.reduce((acc: any, item: any) => {\n acc[item.locale] = {\n production: item.production,\n development: item.development,\n }\n return acc\n }, {}) || config.providers.resend?.audienceIds,\n } : config.providers.resend,\n broadcast: settings.provider === 'broadcast' ? {\n apiUrl: settings.broadcastSettings?.apiUrl || config.providers.broadcast?.apiUrl || '',\n tokens: {\n production: settings.broadcastSettings?.productionToken || config.providers.broadcast?.tokens.production,\n development: settings.broadcastSettings?.developmentToken || config.providers.broadcast?.tokens.development,\n },\n } : config.providers.broadcast,\n }\n } else {\n // Use config defaults\n emailServiceConfig = {\n provider: config.providers.default,\n fromAddress: config.providers.resend?.fromAddress || config.providers.broadcast?.fromAddress || 'noreply@example.com',\n fromName: config.providers.resend?.fromName || config.providers.broadcast?.fromName || 'Newsletter',\n resend: config.providers.resend,\n broadcast: config.providers.broadcast,\n }\n }\n\n (payload as any).newsletterEmailService = createEmailService(emailServiceConfig)\n\n console.warn('Newsletter plugin initialized with', (payload as any).newsletterEmailService.getProvider(), 'provider')\n } catch (error) {\n console.error('Failed to initialize newsletter email service:', error)\n }\n\n // Call original onInit if it exists\n if (incomingConfig.onInit) {\n await incomingConfig.onInit(payload)\n }\n },\n }\n\n return modifiedConfig\n}\n\nexport { newsletterPlugin as default }\n\n// Export session utilities\nexport * from './utilities/session'"],"mappings":"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","names":["Body","Button","Container","Head","Hr","Html","Preview","Text","jsx","jsxs","Html","Head","Preview","Body","Container","Text","Button","Hr","jsx","jsx","subscriber","jwt","jwt","isAuthenticated"]}
1
+ {"version":3,"sources":["../src/types/newsletter.ts","../src/types/broadcast.ts","../src/types/channel.ts","../src/types/providers.ts","../src/types/index.ts","../src/providers/broadcast/broadcast.ts","../src/providers/resend/broadcast.ts","../src/utils/access.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","../src/globals/NewsletterSettings.ts","../src/providers/resend.ts","../src/providers/types.ts","../src/providers/broadcast.ts","../src/providers/index.ts","../src/utils/validation.ts","../src/utils/jwt.ts","../src/endpoints/subscribe.ts","../src/endpoints/verify-magic-link.ts","../src/endpoints/preferences.ts","../src/endpoints/unsubscribe.ts","../src/utils/rate-limiter.ts","../src/endpoints/signin.ts","../src/endpoints/me.ts","../src/endpoints/signout.ts","../src/endpoints/broadcasts/send.ts","../src/utils/auth.ts","../src/endpoints/broadcasts/schedule.ts","../src/utils/emailSafeHtml.ts","../src/endpoints/broadcasts/test.ts","../src/endpoints/broadcasts/index.ts","../src/endpoints/index.ts","../src/fields/newsletterScheduling.ts","../src/jobs/sync-unsubscribes.ts","../src/collections/Channels.ts","../src/collections/Broadcasts.ts","../src/fields/emailContent.ts","../src/index.ts","../src/utilities/session.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 channelId: string; // Reference to the channel this broadcast belongs to\n name: string;\n subject: string;\n preheader?: string;\n content: string; // HTML content\n status: 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 channelId?: string; // Filter by channel\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 channelId: string; // Which channel to send to\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 within the channel\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 within the channel\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 // Channel-specific capabilities\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 CHANNEL_NOT_FOUND = 'CHANNEL_NOT_FOUND',\n INVALID_CHANNEL = 'INVALID_CHANNEL'\n}\n\n/**\n * Broadcast template for reusable content\n */\nexport interface BroadcastTemplate {\n id: string;\n channelId?: string; // Optional channel-specific template\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// 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';","export interface Channel {\n id: string;\n name: string;\n description?: string;\n fromName: string;\n fromEmail: string;\n replyTo?: string;\n providerId: string;\n providerType: 'broadcast' | 'resend';\n subscriberCount?: number;\n active: boolean;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface CreateChannelInput {\n name: string;\n description?: string;\n fromName: string;\n fromEmail: string;\n replyTo?: string;\n}\n\nexport interface UpdateChannelInput {\n name?: string;\n description?: string;\n fromName?: string;\n fromEmail?: string;\n replyTo?: string;\n active?: boolean;\n}\n\nexport interface ListChannelsOptions {\n limit?: number;\n offset?: number;\n active?: boolean;\n}\n\nexport interface ListChannelsResponse {\n channels: Channel[];\n total: number;\n limit: number;\n offset: number;\n}","/**\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// Import channel types\nimport type {\n Channel,\n CreateChannelInput,\n UpdateChannelInput,\n ListChannelsOptions,\n ListChannelsResponse\n} from './channel'\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 // Channel management methods\n /**\n * List channels (newsletter types/publications)\n */\n listChannels(options?: ListChannelsOptions): Promise<ListChannelsResponse>;\n \n /**\n * Get a specific channel by ID\n */\n getChannel(id: string): Promise<Channel>;\n \n /**\n * Create a new channel\n */\n createChannel(data: CreateChannelInput): Promise<Channel>;\n \n /**\n * Update an existing channel\n */\n updateChannel(id: string, data: UpdateChannelInput): Promise<Channel>;\n \n /**\n * Delete a channel\n */\n deleteChannel(id: string): Promise<void>;\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 // Channel management - abstract methods\n abstract listChannels(options?: ListChannelsOptions): Promise<ListChannelsResponse>;\n abstract getChannel(id: string): Promise<Channel>;\n abstract createChannel(data: CreateChannelInput): Promise<Channel>;\n abstract updateChannel(id: string, data: UpdateChannelInput): Promise<Channel>;\n abstract deleteChannel(id: string): Promise<void>;\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 } from 'payload'\nimport type { BroadcastProvider } from './providers'\n\n// Export broadcast and channel types\nexport * from './broadcast'\nexport * from './channel'\nexport * from './providers'\n// Export legacy newsletter types for backwards compatibility\nexport * from './newsletter'\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 /**\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 afterUnsubscribeSync?: (args: AfterUnsubscribeSyncArgs) => 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 * Unsubscribe sync configuration\n */\n unsubscribeSync?: {\n /**\n * Enable sync of unsubscribes from email service to Payload\n * @default false\n */\n enabled?: boolean\n /**\n * Cron schedule for sync job (e.g., '0 * * * *' for hourly)\n * If not provided, job must be triggered manually\n */\n schedule?: string\n /**\n * Queue name for the sync job\n * @default 'newsletter-sync'\n */\n queue?: string\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 * Channels collection slug\n * @default 'channels'\n */\n channels?: string\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\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 tokens: {\n production?: string\n development?: string\n }\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 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\nexport interface AfterUnsubscribeSyncArgs {\n req: any\n syncedCount: number\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 Channel,\n CreateChannelInput,\n UpdateChannelInput,\n ListChannelsOptions,\n ListChannelsResponse\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// Channel API interfaces\ninterface BroadcastChannelApiResponse {\n id: number\n name: string\n description?: string\n address: string\n from: string\n reply_to?: string\n total_active_subscribers: number\n created_at: string\n updated_at: string\n}\n\nexport class BroadcastApiProvider extends BaseBroadcastProvider {\n readonly name = 'broadcast'\n private apiUrl: string\n private token: string\n private isDevelopment: boolean\n\n constructor(config: BroadcastProviderConfig) {\n super(config)\n this.apiUrl = config.apiUrl.replace(/\\/$/, '') // Remove trailing slash\n this.isDevelopment = process.env.NODE_ENV !== 'production'\n this.token = this.isDevelopment \n ? config.tokens.development || config.tokens.production || ''\n : config.tokens.production || config.tokens.development || ''\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 // Channel Management Methods\n async listChannels(options?: ListChannelsOptions): Promise<ListChannelsResponse> {\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/channels?${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 = await response.json()\n const channels = data.data.map((channel: BroadcastChannelApiResponse) => this.transformChannelFromApi(channel))\n \n return {\n channels,\n total: data.total || channels.length,\n limit: options?.limit || 20,\n offset: options?.offset || 0\n }\n } catch (error: unknown) {\n throw new BroadcastProviderError(\n `Failed to list channels: ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n async getChannel(id: string): Promise<Channel> {\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/channels/${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 `Channel not found: ${id}`,\n BroadcastErrorCode.CHANNEL_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 channel: BroadcastChannelApiResponse = await response.json()\n return this.transformChannelFromApi(channel)\n } catch (error: unknown) {\n if (error instanceof BroadcastProviderError) throw error\n \n throw new BroadcastProviderError(\n `Failed to get channel: ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n async createChannel(data: CreateChannelInput): Promise<Channel> {\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/channels`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n channel: {\n name: data.name,\n description: data.description,\n from: data.fromName,\n address: data.fromEmail,\n reply_to: data.replyTo\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 channel: BroadcastChannelApiResponse = await response.json()\n return this.transformChannelFromApi(channel)\n } catch (error: unknown) {\n throw new BroadcastProviderError(\n `Failed to create channel: ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n async updateChannel(id: string, data: UpdateChannelInput): Promise<Channel> {\n try {\n const updateData: any = { channel: {} }\n if (data.name !== undefined) updateData.channel.name = data.name\n if (data.description !== undefined) updateData.channel.description = data.description\n if (data.fromName !== undefined) updateData.channel.from = data.fromName\n if (data.fromEmail !== undefined) updateData.channel.address = data.fromEmail\n if (data.replyTo !== undefined) updateData.channel.reply_to = data.replyTo\n\n const response = await fetch(`${this.apiUrl}/api/v1/channels/${id}`, {\n method: 'PATCH',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(updateData)\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 channel: BroadcastChannelApiResponse = await response.json()\n return this.transformChannelFromApi(channel)\n } catch (error: unknown) {\n throw new BroadcastProviderError(\n `Failed to update channel: ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n async deleteChannel(id: string): Promise<void> {\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/channels/${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 throw new BroadcastProviderError(\n `Failed to delete channel: ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\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 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 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, ['channelId', 'name', 'subject', 'content'])\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({\n broadcast: {\n channel_id: parseInt(data.channelId), // Broadcast API uses numeric IDs\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\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Broadcast API error: ${response.status} - ${error}`)\n }\n\n const result = await response.json()\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.status)) {\n throw new BroadcastProviderError(\n `Cannot update broadcast in status: ${existing.status}`,\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.status)) {\n throw new BroadcastProviderError(\n `Cannot delete broadcast in status: ${existing.status}`,\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: true,\n supportsChannelSegmentation: true,\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 (error) {\n return false\n }\n }\n\n private transformBroadcastFromApi(broadcast: BroadcastApiResponse): Broadcast {\n // TODO: We need to get the channel_id from the broadcast API response\n // For now, we'll use a placeholder\n return {\n id: broadcast.id.toString(),\n channelId: '1', // TODO: Get from API response when available\n name: broadcast.name,\n subject: broadcast.subject,\n preheader: broadcast.preheader,\n content: broadcast.body,\n status: 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 transformChannelFromApi(channel: BroadcastChannelApiResponse): Channel {\n return {\n id: channel.id.toString(),\n name: channel.name,\n description: channel.description,\n fromName: channel.from,\n fromEmail: channel.address,\n replyTo: channel.reply_to,\n providerId: channel.id.toString(),\n providerType: 'broadcast',\n subscriberCount: channel.total_active_subscribers,\n active: true, // Broadcast API doesn't have an active field\n createdAt: new Date(channel.created_at),\n updatedAt: new Date(channel.updated_at)\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}","import { Resend } from 'resend'\nimport type { \n Broadcast,\n ListBroadcastOptions,\n ListBroadcastResponse,\n CreateBroadcastInput,\n UpdateBroadcastInput,\n SendBroadcastOptions,\n BroadcastAnalytics,\n BroadcastProviderCapabilities,\n Channel,\n CreateChannelInput,\n UpdateChannelInput,\n ListChannelsOptions,\n ListChannelsResponse\n} from '../../types'\nimport { \n BroadcastProviderError, \n BroadcastErrorCode,\n BroadcastStatus,\n BaseBroadcastProvider\n} from '../../types'\nimport type { ResendProviderConfig } from '../../types'\n\n/**\n * Resend Broadcast Provider\n * \n * IMPORTANT LIMITATIONS:\n * - Resend's Broadcast API is not fully documented publicly\n * - Many operations may not be available via API\n * - Broadcasts created via API can only be edited via API (not in dashboard)\n * - Channel management maps to Resend's Audience API\n * - Some methods below are marked as TODO pending official API documentation\n */\nexport class ResendBroadcastProvider extends BaseBroadcastProvider {\n readonly name = 'resend'\n private client: Resend\n private audienceIds: ResendProviderConfig['audienceIds']\n private isDevelopment: boolean\n\n constructor(config: ResendProviderConfig) {\n super(config)\n this.client = new Resend(config.apiKey)\n this.audienceIds = config.audienceIds || {}\n this.isDevelopment = process.env.NODE_ENV !== 'production'\n \n if (!config.apiKey) {\n throw new BroadcastProviderError(\n 'Resend API key is required',\n BroadcastErrorCode.CONFIGURATION_ERROR,\n this.name\n )\n }\n }\n\n // Channel Management Methods (map to Resend Audiences)\n async listChannels(options?: ListChannelsOptions): Promise<ListChannelsResponse> {\n try {\n // Resend audiences API\n const response = await this.client.audiences.list()\n \n const channels: Channel[] = response.data?.data?.map(audience => ({\n id: audience.id,\n name: audience.name,\n description: undefined, // Resend doesn't have description\n fromName: (this.config as ResendProviderConfig).fromName || '',\n fromEmail: (this.config as ResendProviderConfig).fromEmail || '',\n replyTo: (this.config as ResendProviderConfig).replyTo,\n providerId: audience.id,\n providerType: 'resend' as const,\n subscriberCount: undefined, // Not available in list API\n active: true,\n createdAt: new Date(audience.created_at),\n updatedAt: new Date(audience.created_at) // No updated_at in Resend\n })) || []\n \n return {\n channels,\n total: channels.length,\n limit: options?.limit || 100,\n offset: options?.offset || 0\n }\n } catch (error: unknown) {\n throw new BroadcastProviderError(\n `Failed to list channels (audiences): ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n async getChannel(id: string): Promise<Channel> {\n try {\n const response = await this.client.audiences.get(id)\n \n if (!response.data) {\n throw new BroadcastProviderError(\n `Channel (audience) not found: ${id}`,\n BroadcastErrorCode.CHANNEL_NOT_FOUND,\n this.name\n )\n }\n \n return {\n id: response.data.id,\n name: response.data.name,\n description: undefined,\n fromName: (this.config as ResendProviderConfig).fromName || '',\n fromEmail: (this.config as ResendProviderConfig).fromEmail || '',\n replyTo: (this.config as ResendProviderConfig).replyTo,\n providerId: response.data.id,\n providerType: 'resend',\n subscriberCount: undefined, // Not available\n active: true,\n createdAt: new Date(response.data.created_at),\n updatedAt: new Date(response.data.created_at)\n }\n } catch (error: unknown) {\n if (error instanceof BroadcastProviderError) throw error\n \n throw new BroadcastProviderError(\n `Failed to get channel (audience): ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n async createChannel(data: CreateChannelInput): Promise<Channel> {\n try {\n const response = await this.client.audiences.create({\n name: data.name\n })\n \n if (!response.data) {\n throw new Error('Failed to create audience')\n }\n \n return {\n id: response.data.id,\n name: response.data.name,\n description: data.description,\n fromName: data.fromName,\n fromEmail: data.fromEmail,\n replyTo: data.replyTo,\n providerId: response.data.id,\n providerType: 'resend',\n subscriberCount: 0,\n active: true,\n createdAt: new Date(),\n updatedAt: new Date()\n }\n } catch (error: unknown) {\n throw new BroadcastProviderError(\n `Failed to create channel (audience): ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n async updateChannel(id: string, data: UpdateChannelInput): Promise<Channel> {\n // Resend doesn't support updating audiences via API\n throw new BroadcastProviderError(\n 'Updating channels (audiences) is not supported by Resend API',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\n }\n\n async deleteChannel(id: string): Promise<void> {\n try {\n await this.client.audiences.remove(id)\n } catch (error: unknown) {\n throw new BroadcastProviderError(\n `Failed to delete channel (audience): ${error instanceof Error ? error.message : 'Unknown error'}`,\n BroadcastErrorCode.PROVIDER_ERROR,\n this.name,\n error\n )\n }\n }\n\n // Broadcast Management Methods\n async list(options?: ListBroadcastOptions): Promise<ListBroadcastResponse<Broadcast>> {\n // TODO: Resend broadcast list API is not documented\n // The SDK may have undocumented methods we could explore\n // For now, we throw a not supported error\n throw new BroadcastProviderError(\n 'Listing broadcasts is not currently supported by Resend API. ' +\n 'This feature may be available in the dashboard only.',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\n }\n\n async get(id: string): Promise<Broadcast> {\n // TODO: Resend broadcast get API is not documented\n // We would need to explore if the SDK has undocumented methods\n throw new BroadcastProviderError(\n 'Getting individual broadcasts is not currently supported by Resend API. ' +\n 'This feature may be available in the dashboard only.',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\n }\n\n async create(data: CreateBroadcastInput): Promise<Broadcast> {\n try {\n this.validateRequiredFields(data, ['channelId', 'name', 'subject', 'content'])\n\n // Get the appropriate audience ID\n const locale = 'en' // TODO: Make this configurable\n const audienceConfig = this.audienceIds?.[locale]\n const audienceId = this.isDevelopment \n ? audienceConfig?.development || audienceConfig?.production\n : audienceConfig?.production || audienceConfig?.development\n\n if (!audienceId && data.audienceIds?.length) {\n // Use provided audience ID if no default configured\n // Note: Resend might only support one audience per broadcast\n }\n\n // TODO: The exact Resend broadcast creation API is not documented\n // Based on their blog posts, it seems broadcasts can be created via API\n // but the exact endpoint/method is unclear\n \n // Attempt to use broadcasts if available in SDK\n const resendClient = this.client as any\n if (resendClient.broadcasts?.create) {\n const broadcast = await resendClient.broadcasts.create({\n name: data.name,\n subject: data.subject,\n from: `${(this.config as ResendProviderConfig).fromName || 'Newsletter'} <${(this.config as ResendProviderConfig).fromEmail || 'noreply@example.com'}>`,\n reply_to: data.replyTo,\n audience_id: audienceId || data.audienceIds?.[0],\n content: {\n html: data.content,\n // TODO: Handle plain text version\n }\n })\n\n // Transform to our Broadcast type\n return this.transformResendToBroadcast(broadcast)\n }\n\n // If broadcasts API not available, throw error\n throw new BroadcastProviderError(\n 'Creating broadcasts via API is not currently supported. ' +\n 'Please check if Resend has released their Broadcasts API.',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\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 // TODO: Resend broadcast update API is not documented\n // Important: Resend has restrictions where broadcasts created via API\n // can only be edited via API (not in dashboard)\n throw new BroadcastProviderError(\n 'Updating broadcasts is not currently supported by Resend API. ' +\n 'Note: Resend broadcasts can only be edited where they were created.',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\n }\n\n async delete(id: string): Promise<void> {\n // TODO: Resend broadcast delete API is not documented\n throw new BroadcastProviderError(\n 'Deleting broadcasts is not currently supported by Resend API.',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\n }\n\n async send(id: string, options?: SendBroadcastOptions): Promise<Broadcast> {\n try {\n // TODO: The exact Resend broadcast send API is not documented\n // Based on their features, sending broadcasts is supported\n \n const resendClient = this.client as any\n if (resendClient.broadcasts?.send) {\n await resendClient.broadcasts.send(id, {\n audience_id: options?.audienceIds?.[0],\n // TODO: Handle test mode if supported\n })\n\n // We can't get the updated broadcast, so return a mock\n return {\n id,\n channelId: options?.audienceIds?.[0] || '1',\n name: 'Unknown',\n subject: 'Unknown',\n content: '',\n status: BroadcastStatus.SENDING,\n trackOpens: true,\n trackClicks: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n providerType: 'resend'\n } as Broadcast\n }\n\n throw new BroadcastProviderError(\n 'Sending broadcasts via API is not currently supported. ' +\n 'Please check if Resend has released their Broadcasts API.',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\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 // Scheduling is not supported according to our research\n throw new BroadcastProviderError(\n 'Scheduling broadcasts is not supported by Resend',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\n }\n\n async getAnalytics(id: string): Promise<BroadcastAnalytics> {\n // TODO: Resend does support analytics, but the API is not documented\n // They have dashboard analytics for broadcasts\n throw new BroadcastProviderError(\n 'Getting broadcast analytics via API is not currently supported. ' +\n 'Analytics may be available in the Resend dashboard.',\n BroadcastErrorCode.NOT_SUPPORTED,\n this.name\n )\n }\n\n getCapabilities(): BroadcastProviderCapabilities {\n return {\n supportsScheduling: false, // Not documented\n supportsSegmentation: true, // Via Audiences\n supportsAnalytics: true, // Available in dashboard, API unclear\n supportsABTesting: false,\n supportsTemplates: false, // Not clear from docs\n supportsPersonalization: true, // Via merge tags\n supportsMultipleChannels: true, // Via multiple audiences\n supportsChannelSegmentation: false, // Not within a single audience\n editableStatuses: [], // Unclear which statuses can be edited\n supportedContentTypes: ['html'] // React components via SDK\n }\n }\n\n async validateConfiguration(): Promise<boolean> {\n try {\n // Try to use the API key to validate it works\n // We can try to list audiences as a validation check\n const resendClient = this.client as any\n if (resendClient.audiences?.list) {\n await resendClient.audiences.list({ limit: 1 })\n return true\n }\n \n // Fallback: try to send a test email to validate API key\n await this.client.emails.send({\n from: 'onboarding@resend.dev',\n to: 'delivered@resend.dev',\n subject: 'Configuration Test',\n html: '<p>Testing configuration</p>'\n })\n return true\n } catch (error) {\n return false\n }\n }\n\n /**\n * Transform Resend broadcast to our Broadcast type\n * NOTE: This is speculative based on what the API might return\n */\n private transformResendToBroadcast(broadcast: any): Broadcast {\n return {\n id: broadcast.id,\n channelId: broadcast.audience_id || '1', // Map audience_id to channelId\n name: broadcast.name || 'Untitled',\n subject: broadcast.subject,\n preheader: broadcast.preheader,\n content: broadcast.content?.html || broadcast.html || '',\n status: this.mapResendStatus(broadcast.status),\n trackOpens: true, // Resend tracks by default\n trackClicks: true, // Resend tracks by default\n replyTo: broadcast.reply_to,\n recipientCount: broadcast.recipient_count,\n sentAt: broadcast.sent_at ? new Date(broadcast.sent_at) : undefined,\n scheduledAt: broadcast.scheduled_at ? new Date(broadcast.scheduled_at) : undefined,\n createdAt: new Date(broadcast.created_at || Date.now()),\n updatedAt: new Date(broadcast.updated_at || Date.now()),\n providerData: { broadcast },\n providerId: broadcast.id,\n providerType: 'resend'\n }\n }\n\n private mapResendStatus(status?: string): BroadcastStatus {\n if (!status) return BroadcastStatus.DRAFT\n \n // NOTE: Resend statuses are not documented, these are guesses\n const statusMap: Record<string, BroadcastStatus> = {\n 'draft': BroadcastStatus.DRAFT,\n 'scheduled': BroadcastStatus.SCHEDULED,\n 'sending': BroadcastStatus.SENDING,\n 'sent': BroadcastStatus.SENT,\n 'failed': BroadcastStatus.FAILED\n }\n return statusMap[status.toLowerCase()] || BroadcastStatus.DRAFT\n }\n}\n\n/**\n * IMPLEMENTATION NOTES:\n * \n * 1. Most methods throw NOT_SUPPORTED errors because Resend's Broadcast API\n * is not publicly documented\n * \n * 2. The SDK might have undocumented methods (broadcasts.create, broadcasts.send, etc.)\n * that we attempt to use, but we can't guarantee they exist\n * \n * 3. Important limitation: Broadcasts created via API can only be edited via API,\n * not in the Resend dashboard\n * \n * 4. Resend uses \"Audiences\" instead of \"Segments\" for targeting\n * \n * 5. Analytics are available in the dashboard but API access is unclear\n * \n * FUTURE IMPROVEMENTS:\n * - Monitor Resend's documentation for Broadcast API updates\n * - Explore SDK source code for undocumented methods\n * - Consider using Resend's email API to simulate broadcasts\n * - Add webhook support for delivery/open/click tracking\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 { render } from '@react-email/render'\nimport { MagicLinkEmail } from './MagicLink'\nimport { WelcomeEmail } from './Welcome'\nimport { SignInEmail } from './SignIn'\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): Promise<string> {\n try {\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 // 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: '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 // 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\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 if (emailService) {\n try {\n await emailService.addContact(doc)\n } catch {\n // Failed to add contact to email service\n }\n }\n\n // Send welcome email if active\n if (doc.subscriptionStatus === 'active' && emailService) {\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 })\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 if (\n doc.subscriptionStatus !== previousDoc.subscriptionStatus &&\n emailService\n ) {\n try {\n await emailService.updateContact(doc)\n } catch {\n // Failed to update contact in email service\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}","import type { GlobalConfig } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { adminOnly } from '../utils/access'\n\nexport const createNewsletterSettingsGlobal = (\n pluginConfig: NewsletterPluginConfig\n): GlobalConfig => {\n const slug = pluginConfig.settingsSlug || 'newsletter-settings'\n \n return {\n slug,\n label: 'Newsletter Settings',\n admin: {\n group: 'Newsletter',\n description: 'Configure email provider settings and templates',\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n label: 'Provider Settings',\n fields: [\n {\n name: 'provider',\n type: 'select',\n label: 'Email Provider',\n required: true,\n options: [\n { label: 'Resend', value: 'resend' },\n { label: 'Broadcast (Self-Hosted)', value: 'broadcast' },\n ],\n defaultValue: pluginConfig.providers.default,\n admin: {\n description: 'Choose which email service to use',\n },\n },\n {\n name: 'resendSettings',\n type: 'group',\n label: 'Resend Settings',\n admin: {\n condition: (data) => data?.provider === 'resend',\n },\n fields: [\n {\n name: 'apiKey',\n type: 'text',\n label: 'API Key',\n required: true,\n admin: {\n description: 'Your Resend API key',\n },\n },\n {\n name: 'audienceIds',\n type: 'array',\n label: 'Audience IDs by Locale',\n fields: [\n {\n name: 'locale',\n type: 'select',\n label: 'Locale',\n required: true,\n options: pluginConfig.i18n?.locales?.map(locale => ({\n label: locale.toUpperCase(),\n value: locale,\n })) || [\n { label: 'EN', value: 'en' },\n ],\n },\n {\n name: 'production',\n type: 'text',\n label: 'Production Audience ID',\n },\n {\n name: 'development',\n type: 'text',\n label: 'Development Audience ID',\n },\n ],\n },\n ],\n },\n {\n name: 'broadcastSettings',\n type: 'group',\n label: 'Broadcast Settings',\n admin: {\n condition: (data) => data?.provider === 'broadcast',\n },\n fields: [\n {\n name: 'apiUrl',\n type: 'text',\n label: 'API URL',\n required: true,\n admin: {\n description: 'Your Broadcast instance URL',\n },\n },\n {\n name: 'productionToken',\n type: 'text',\n label: 'Production Token',\n admin: {\n description: 'Token for production environment',\n },\n },\n {\n name: 'developmentToken',\n type: 'text',\n label: 'Development Token',\n admin: {\n description: 'Token for development environment',\n },\n },\n ],\n },\n {\n name: 'fromAddress',\n type: 'email',\n label: 'From Address',\n required: true,\n admin: {\n description: 'Default sender email address',\n },\n },\n {\n name: 'fromName',\n type: 'text',\n label: 'From Name',\n required: true,\n admin: {\n description: 'Default sender name',\n },\n },\n {\n name: 'replyTo',\n type: 'email',\n label: 'Reply-To Address',\n admin: {\n description: 'Optional reply-to email address',\n },\n },\n ],\n },\n {\n label: 'Email Templates',\n fields: [\n {\n name: 'emailTemplates',\n type: 'group',\n label: 'Email Templates',\n fields: [\n {\n name: 'welcome',\n type: 'group',\n label: 'Welcome Email',\n fields: [\n {\n name: 'enabled',\n type: 'checkbox',\n label: 'Send Welcome Email',\n defaultValue: true,\n },\n {\n name: 'subject',\n type: 'text',\n label: 'Subject Line',\n defaultValue: 'Welcome to {{fromName}}!',\n admin: {\n condition: (data) => data?.emailTemplates?.welcome?.enabled,\n },\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Preheader Text',\n admin: {\n condition: (data) => data?.emailTemplates?.welcome?.enabled,\n },\n },\n ],\n },\n {\n name: 'magicLink',\n type: 'group',\n label: 'Magic Link Email',\n fields: [\n {\n name: 'subject',\n type: 'text',\n label: 'Subject Line',\n defaultValue: 'Sign in to {{fromName}}',\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Preheader Text',\n defaultValue: 'Click the link to access your preferences',\n },\n {\n name: 'expirationTime',\n type: 'select',\n label: 'Link Expiration',\n defaultValue: '7d',\n options: [\n { label: '1 hour', value: '1h' },\n { label: '24 hours', value: '24h' },\n { label: '7 days', value: '7d' },\n { label: '30 days', value: '30d' },\n ],\n },\n ],\n },\n ],\n },\n ],\n },\n {\n label: 'Subscription Settings',\n fields: [\n {\n name: 'subscriptionSettings',\n type: 'group',\n label: 'Subscription Settings',\n fields: [\n {\n name: 'requireDoubleOptIn',\n type: 'checkbox',\n label: 'Require Double Opt-In',\n defaultValue: false,\n admin: {\n description: 'Require email confirmation before activating subscriptions',\n },\n },\n {\n name: 'allowedDomains',\n type: 'array',\n label: 'Allowed Email Domains',\n admin: {\n description: 'Leave empty to allow all domains',\n },\n fields: [\n {\n name: 'domain',\n type: 'text',\n label: 'Domain',\n required: true,\n admin: {\n placeholder: 'example.com',\n },\n },\n ],\n },\n {\n name: 'maxSubscribersPerIP',\n type: 'number',\n label: 'Max Subscribers per IP',\n defaultValue: 10,\n min: 1,\n admin: {\n description: 'Maximum number of subscriptions allowed from a single IP address',\n },\n },\n ],\n },\n ],\n },\n ],\n },\n ],\n hooks: {\n beforeChange: [\n async ({ data, req }) => {\n // Verify admin access for settings changes\n if (!req.user || req.user.collection !== 'users') {\n throw new Error('Only administrators can modify newsletter settings')\n }\n \n return data\n },\n ],\n afterChange: [\n async ({ doc, req }) => {\n // Reinitialize email service when settings change\n if ((req.payload as any).newsletterEmailService) {\n try {\n // TODO: Implement email service reinitialization\n console.warn('Newsletter settings updated, reinitializing service...')\n } catch {\n // Failed to reinitialize email service\n }\n }\n \n return doc\n },\n ],\n },\n access: {\n read: () => true, // Settings can be read publicly for validation\n update: adminOnly(pluginConfig),\n },\n }\n}","import { Resend } from 'resend'\nimport type { EmailProvider, SendEmailParams } from './types'\nimport { EmailProviderError } from './types'\nimport type { Subscriber, ResendProviderConfig } from '../types'\n\nexport class ResendProvider implements EmailProvider {\n private client: Resend\n private audienceIds: ResendProviderConfig['audienceIds']\n private fromAddress: string\n private fromName: string\n private isDevelopment: boolean\n\n constructor(config: ResendProviderConfig & { \n fromAddress: string\n fromName: string \n }) {\n this.client = new Resend(config.apiKey)\n this.audienceIds = config.audienceIds || {}\n this.fromAddress = config.fromAddress\n this.fromName = config.fromName\n this.isDevelopment = process.env.NODE_ENV !== 'production'\n }\n\n getProvider(): string {\n return 'resend'\n }\n\n async send(params: SendEmailParams): Promise<void> {\n try {\n const from = params.from || {\n email: this.fromAddress,\n name: this.fromName,\n }\n\n if (!params.html && !params.text) {\n throw new Error('Either html or text content is required')\n }\n\n await this.client.emails.send({\n from: `${from.name} <${from.email}>`,\n to: Array.isArray(params.to) ? params.to : [params.to],\n subject: params.subject,\n html: params.html || '',\n text: params.text,\n replyTo: params.replyTo,\n })\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to send email via Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n async addContact(contact: Subscriber): Promise<void> {\n try {\n const audienceId = this.getAudienceId(contact.locale)\n if (!audienceId) {\n console.warn(`No audience ID configured for locale: ${contact.locale}`)\n return\n }\n\n await this.client.contacts.create({\n email: contact.email,\n firstName: contact.name?.split(' ')[0],\n lastName: contact.name?.split(' ').slice(1).join(' '),\n unsubscribed: contact.subscriptionStatus === 'unsubscribed',\n audienceId,\n })\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to add contact to Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n async updateContact(contact: Subscriber): Promise<void> {\n try {\n const audienceId = this.getAudienceId(contact.locale)\n if (!audienceId) {\n console.warn(`No audience ID configured for locale: ${contact.locale}`)\n return\n }\n\n // Resend requires finding the contact first\n const contacts = await this.client.contacts.list({ audienceId })\n const existingContact = contacts.data?.data?.find(c => c.email === contact.email)\n\n if (existingContact) {\n await this.client.contacts.update({\n id: existingContact.id,\n audienceId,\n firstName: contact.name?.split(' ')[0],\n lastName: contact.name?.split(' ').slice(1).join(' '),\n unsubscribed: contact.subscriptionStatus === 'unsubscribed',\n })\n } else {\n // If contact doesn't exist, add them\n await this.addContact(contact)\n }\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to update contact in Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n async removeContact(email: string): Promise<void> {\n try {\n // Resend doesn't have a direct remove method, so we unsubscribe instead\n // First, we need to find the contact across all audiences\n for (const locale in this.audienceIds) {\n const audienceId = this.getAudienceId(locale)\n if (!audienceId) continue\n\n const contacts = await this.client.contacts.list({ audienceId })\n const contact = contacts.data?.data?.find(c => c.email === email)\n\n if (contact) {\n await this.client.contacts.update({\n id: contact.id,\n audienceId,\n unsubscribed: true,\n })\n break\n }\n }\n } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to remove contact from Resend: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'resend',\n error\n )\n }\n }\n\n private getAudienceId(locale?: string): string | undefined {\n const localeKey = locale || 'en'\n if (!this.audienceIds) return undefined\n \n const localeConfig = this.audienceIds[localeKey]\n if (!localeConfig) return undefined\n\n const audienceId = this.isDevelopment \n ? (localeConfig.development || localeConfig.production)\n : (localeConfig.production || localeConfig.development)\n \n return audienceId\n }\n}","import type { Subscriber } from '../types'\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 getProvider(): string\n}\n\nexport interface SendEmailParams {\n to: string | string[]\n subject: string\n html?: string\n text?: string\n react?: React.ReactElement\n from?: {\n email: string\n name?: string\n }\n replyTo?: string\n}\n\nexport interface EmailServiceConfig {\n provider: 'resend' | 'broadcast' | string\n fromAddress: string\n fromName: string\n replyTo?: string\n resend?: {\n apiKey: string\n audienceIds?: Record<string, { production?: string; development?: string }>\n }\n broadcast?: {\n apiUrl: string\n tokens: {\n production?: string\n development?: string\n }\n }\n}\n\nexport class EmailProviderError extends Error {\n provider: string\n originalError?: any\n\n constructor(message: string, provider: string, originalError?: any) {\n super(message)\n this.name = 'EmailProviderError'\n this.provider = provider\n this.originalError = originalError\n }\n}","import type { EmailProvider, SendEmailParams } from './types'\nimport { EmailProviderError } from './types'\nimport type { Subscriber, BroadcastProviderConfig } from '../types'\n\nexport class BroadcastProvider implements EmailProvider {\n private apiUrl: string\n private token: string\n private fromAddress: string\n private fromName: string\n private isDevelopment: boolean\n\n constructor(config: BroadcastProviderConfig & { \n fromAddress: string\n fromName: string \n }) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '') // Remove trailing slash\n this.isDevelopment = process.env.NODE_ENV !== 'production'\n this.token = this.isDevelopment \n ? config.tokens.development || config.tokens.production || ''\n : config.tokens.production || config.tokens.development || ''\n this.fromAddress = config.fromAddress\n this.fromName = config.fromName\n }\n\n getProvider(): string {\n return 'broadcast'\n }\n\n async send(params: SendEmailParams): Promise<void> {\n try {\n const from = params.from || {\n email: this.fromAddress,\n name: this.fromName,\n }\n\n const recipients = Array.isArray(params.to) ? params.to : [params.to]\n \n // Broadcast expects a specific format\n const response = await fetch(`${this.apiUrl}/api/v1/emails`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n from_email: from.email,\n from_name: from.name,\n to: recipients,\n subject: params.subject,\n html_body: params.html,\n text_body: params.text,\n reply_to: params.replyTo,\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 throw new EmailProviderError(\n `Failed to send email via Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n\n async addContact(contact: Subscriber): Promise<void> {\n try {\n const [firstName, ...lastNameParts] = (contact.name || '').split(' ')\n const lastName = lastNameParts.join(' ')\n\n const response = await fetch(`${this.apiUrl}/api/v1/subscribers.json`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n subscriber: {\n email: contact.email,\n first_name: firstName || undefined,\n last_name: lastName || undefined,\n tags: [`lang:${contact.locale || 'en'}`],\n is_active: contact.subscriptionStatus === 'active',\n source: contact.source,\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 } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to add contact to Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n\n async updateContact(contact: Subscriber): Promise<void> {\n try {\n // First, try to find the contact\n const searchResponse = await fetch(\n `${this.apiUrl}/api/v1/subscribers/find.json?email=${encodeURIComponent(contact.email)}`,\n {\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n },\n }\n )\n\n if (!searchResponse.ok) {\n // If contact doesn't exist, create it\n await this.addContact(contact)\n return\n }\n\n const existingContact = await searchResponse.json()\n\n if (!existingContact || !existingContact.id) {\n await this.addContact(contact)\n return\n }\n\n const [firstName, ...lastNameParts] = (contact.name || '').split(' ')\n const lastName = lastNameParts.join(' ')\n\n // Update existing contact\n const response = await fetch(`${this.apiUrl}/api/v1/subscribers.json`, {\n method: 'PATCH',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n email: contact.email,\n subscriber: {\n first_name: firstName || undefined,\n last_name: lastName || undefined,\n tags: [`lang:${contact.locale || 'en'}`],\n is_active: contact.subscriptionStatus === 'active',\n source: contact.source,\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 } catch (error: unknown) {\n throw new EmailProviderError(\n `Failed to update contact in Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n\n async removeContact(email: string): Promise<void> {\n try {\n // First, find the contact\n const searchResponse = await fetch(\n `${this.apiUrl}/api/v1/subscribers/find.json?email=${encodeURIComponent(email)}`,\n {\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n },\n }\n )\n\n if (!searchResponse.ok) {\n // Contact doesn't exist, nothing to remove\n return\n }\n\n const contact = await searchResponse.json()\n\n if (!contact || !contact.id) {\n return\n }\n\n // Deactivate the contact\n const response = await fetch(`${this.apiUrl}/api/v1/subscribers/deactivate.json`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email }),\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 throw new EmailProviderError(\n `Failed to remove contact from Broadcast: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'broadcast',\n error\n )\n }\n }\n}","import type { EmailProvider, EmailServiceConfig, SendEmailParams } from './types'\nimport type { Subscriber } from '../types'\nimport { ResendProvider } from './resend'\nimport { BroadcastProvider } from './broadcast'\n\nexport * from './types'\n\nexport class EmailService {\n private provider: EmailProvider\n\n constructor(config: EmailServiceConfig) {\n this.provider = this.createProvider(config)\n }\n\n private createProvider(config: EmailServiceConfig): EmailProvider {\n const baseConfig = {\n fromAddress: config.fromAddress,\n fromName: config.fromName,\n }\n\n switch (config.provider) {\n case 'resend':\n if (!config.resend) {\n throw new Error('Resend configuration is required when using Resend provider')\n }\n return new ResendProvider({\n ...config.resend,\n ...baseConfig,\n })\n\n case 'broadcast':\n if (!config.broadcast) {\n throw new Error('Broadcast configuration is required when using Broadcast provider')\n }\n return new BroadcastProvider({\n ...config.broadcast,\n ...baseConfig,\n })\n\n default:\n throw new Error(`Unknown email provider: ${config.provider}`)\n }\n }\n\n async send(params: SendEmailParams): Promise<void> {\n return this.provider.send(params)\n }\n\n async addContact(contact: Subscriber): Promise<void> {\n return this.provider.addContact(contact)\n }\n\n async updateContact(contact: Subscriber): Promise<void> {\n return this.provider.updateContact(contact)\n }\n\n async removeContact(email: string): Promise<void> {\n return this.provider.removeContact(email)\n }\n\n getProvider(): string {\n return this.provider.getProvider()\n }\n\n /**\n * Update the provider configuration\n * Useful when settings are changed in the admin UI\n */\n updateConfig(config: EmailServiceConfig): void {\n this.provider = this.createProvider(config)\n }\n}\n\n/**\n * Create email service from plugin configuration\n */\nexport function createEmailService(config: EmailServiceConfig): EmailService {\n return new EmailService(config)\n}","import DOMPurify from 'isomorphic-dompurify'\n\n/**\n * Validate email address format\n */\nexport function isValidEmail(email: string): boolean {\n if (!email || typeof email !== 'string') return false\n \n // Trim whitespace\n const trimmed = email.trim()\n \n // Length limits\n if (trimmed.length > 255) return false\n \n // Check for dangerous patterns\n if (trimmed.includes('<') || trimmed.includes('>')) return false\n if (trimmed.includes('javascript:')) return false\n if (trimmed.includes('data:')) return false\n \n // Basic format validation with stricter regex\n const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/\n if (!emailRegex.test(trimmed)) return false\n \n // Additional validation rules\n const parts = trimmed.split('@')\n if (parts.length !== 2) return false\n \n const [localPart, domain] = parts\n \n // Check local part length\n if (localPart.length > 64 || localPart.length === 0) return false\n \n // Check for invalid patterns\n if (localPart.startsWith('.') || localPart.endsWith('.')) return false\n if (domain.startsWith('.') || domain.endsWith('.')) return false\n if (domain.includes('..')) return false\n if (localPart.includes('..')) return false\n \n return true\n}\n\n/**\n * Normalize email for rate limiting and deduplication\n */\nexport function normalizeEmail(email: string): string {\n if (!email || typeof email !== 'string') return ''\n \n const parts = email.toLowerCase().trim().split('@')\n if (parts.length !== 2) return email.toLowerCase().trim()\n \n let [localPart] = parts\n const [, domain] = parts\n \n // Remove dots from local part (Gmail-style)\n localPart = localPart.replace(/\\./g, '')\n \n // Remove everything after + (Gmail-style aliases)\n const plusIndex = localPart.indexOf('+')\n if (plusIndex > -1) {\n localPart = localPart.substring(0, plusIndex)\n }\n \n return `${localPart}@${domain}`\n}\n\n/**\n * Check if email domain is allowed\n */\nexport function isDomainAllowed(\n email: string,\n allowedDomains?: string[]\n): boolean {\n // Validate email format first\n if (!isValidEmail(email)) {\n return false\n }\n \n // If no domains specified, allow all valid emails\n if (!allowedDomains || allowedDomains.length === 0) {\n return true\n }\n\n const domain = email.split('@')[1]?.toLowerCase()\n if (!domain) return false\n\n return allowedDomains.some(\n allowedDomain => domain === allowedDomain.toLowerCase()\n )\n}\n\n/**\n * Sanitize user input to prevent XSS\n */\nexport function sanitizeInput(input: string): string {\n if (!input) return ''\n \n // First, remove all HTML tags and scripts\n let cleaned = DOMPurify.sanitize(input, { \n ALLOWED_TAGS: [],\n ALLOWED_ATTR: [],\n KEEP_CONTENT: true\n })\n \n // Additional security: remove dangerous patterns\n cleaned = cleaned\n .replace(/javascript:/gi, '')\n .replace(/data:/gi, '')\n .replace(/vbscript:/gi, '')\n .replace(/file:\\/\\//gi, '')\n .replace(/onload/gi, '')\n .replace(/onerror/gi, '')\n .replace(/onclick/gi, '')\n .replace(/onmouseover/gi, '')\n .replace(/alert\\(/gi, '')\n .replace(/prompt\\(/gi, '')\n .replace(/confirm\\(/gi, '')\n .replace(/\\|/g, '') // Remove pipe character (command injection)\n .replace(/;/g, '') // Remove semicolon (command chaining)\n .replace(/`/g, '') // Remove backticks (command substitution)\n .replace(/&&/g, '') // Remove command chaining\n .replace(/\\$\\(/g, '') // Remove command substitution pattern $()\n .replace(/\\.\\./g, '') // Remove directory traversal\n .replace(/\\/..\\//g, '') // Remove path traversal\n .replace(/\\0/g, '') // Remove null bytes\n \n return cleaned.trim()\n}\n\n/**\n * Extract UTM parameters from URL search params\n */\nexport function extractUTMParams(searchParams: URLSearchParams): Record<string, string> {\n const utmParams: Record<string, string> = {}\n const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']\n\n utmKeys.forEach(key => {\n const value = searchParams.get(key)\n if (value) {\n // Remove 'utm_' prefix for storage\n const shortKey = key.replace('utm_', '')\n utmParams[shortKey] = value\n }\n })\n\n return utmParams\n}\n\n/**\n * Validate source field - only allow predefined values\n */\nexport function isValidSource(source: string): boolean {\n if (!source || typeof source !== 'string') return false\n \n const allowedSources = [\n 'website',\n 'api',\n 'import',\n 'admin',\n 'signup-form',\n 'magic-link',\n 'preferences',\n 'external'\n ]\n \n return allowedSources.includes(source)\n}\n\n/**\n * Validate subscriber data before creation\n */\nexport interface ValidateSubscriberResult {\n valid: boolean\n errors: string[]\n}\n\nexport function validateSubscriberData(data: any): ValidateSubscriberResult {\n const errors: string[] = []\n\n // Email validation\n if (!data.email) {\n errors.push('Email is required')\n } else if (!isValidEmail(data.email)) {\n errors.push('Invalid email format')\n }\n\n // Name validation (optional but if provided, should be reasonable)\n if (data.name && data.name.length > 100) {\n errors.push('Name is too long (max 100 characters)')\n }\n\n // Source validation\n if (data.source !== undefined) {\n if (!data.source || data.source.length === 0) {\n errors.push('Source cannot be empty')\n } else if (data.source.length > 50) {\n errors.push('Source is too long (max 50 characters)')\n } else if (!isValidSource(data.source)) {\n errors.push('Invalid source value')\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n }\n}","import jwt from 'jsonwebtoken'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport interface MagicLinkTokenPayload {\n subscriberId: string\n email: string\n type: 'magic-link'\n}\n\nexport interface SessionTokenPayload {\n subscriberId: string\n email: string\n type: 'session'\n}\n\n/**\n * Get JWT secret from environment or generate a warning\n */\nfunction getJWTSecret(): string {\n const secret = process.env.JWT_SECRET || process.env.PAYLOAD_SECRET\n\n if (!secret) {\n console.warn(\n 'WARNING: No JWT_SECRET or PAYLOAD_SECRET found in environment variables. ' +\n 'Magic link authentication will not work properly. ' +\n 'Please set JWT_SECRET in your environment.'\n )\n // Return a placeholder to prevent crashes during development\n return 'INSECURE_DEVELOPMENT_SECRET_PLEASE_SET_JWT_SECRET'\n }\n\n return secret\n}\n\n/**\n * Generate a magic link token for email authentication\n */\nexport function generateMagicLinkToken(\n subscriberId: string,\n email: string,\n config: NewsletterPluginConfig\n): string {\n const payload: MagicLinkTokenPayload = {\n subscriberId,\n email,\n type: 'magic-link',\n }\n\n const expiresIn = config.auth?.tokenExpiration || '7d'\n\n return jwt.sign(payload, getJWTSecret(), {\n expiresIn: expiresIn,\n issuer: 'payload-newsletter-plugin',\n } as jwt.SignOptions)\n}\n\n/**\n * Verify a magic link token\n */\nexport function verifyMagicLinkToken(token: string): MagicLinkTokenPayload {\n try {\n const payload = jwt.verify(token, getJWTSecret(), {\n issuer: 'payload-newsletter-plugin',\n }) as any\n\n if (payload.type !== 'magic-link') {\n throw new Error('Invalid token type')\n }\n\n return payload as MagicLinkTokenPayload\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'TokenExpiredError') {\n throw new Error('Magic link has expired. Please request a new one.')\n }\n if (error instanceof Error && error.name === 'JsonWebTokenError') {\n throw new Error('Invalid magic link token')\n }\n throw error\n }\n}\n\n/**\n * Generate a session token after successful magic link verification\n */\nexport function generateSessionToken(\n subscriberId: string,\n email: string\n): string {\n const payload: SessionTokenPayload = {\n subscriberId,\n email,\n type: 'session',\n }\n\n return jwt.sign(payload, getJWTSecret(), {\n expiresIn: '30d',\n issuer: 'payload-newsletter-plugin',\n })\n}\n\n/**\n * Verify a session token\n */\nexport function verifySessionToken(token: string): SessionTokenPayload {\n try {\n const payload = jwt.verify(token, getJWTSecret(), {\n issuer: 'payload-newsletter-plugin',\n }) as any\n\n if (payload.type !== 'session') {\n throw new Error('Invalid token type')\n }\n\n return payload as SessionTokenPayload\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'TokenExpiredError') {\n throw new Error('Session has expired. Please sign in again.')\n }\n if (error instanceof Error && error.name === 'JsonWebTokenError') {\n throw new Error('Invalid session token')\n }\n throw error\n }\n}\n\n/**\n * Generate a magic link URL\n */\nexport function generateMagicLinkURL(\n token: string,\n baseURL: string,\n config: NewsletterPluginConfig\n): string {\n const path = config.auth?.magicLinkPath || '/newsletter/verify'\n const url = new URL(path, baseURL)\n url.searchParams.set('token', token)\n return url.toString()\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, Subscriber, SubscribeRequestData, ExtendedPayloadRequest } from '../types'\nimport { \n isDomainAllowed, \n sanitizeInput, \n validateSubscriberData,\n extractUTMParams \n} from '../utils/validation'\nimport { generateMagicLinkToken, generateMagicLinkURL } from '../utils/jwt'\nimport { renderEmail } from '../emails/render'\n\nexport const createSubscribeEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/subscribe',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { \n email, \n name, \n source,\n preferences,\n leadMagnet,\n surveyResponses,\n metadata = {}\n } = data as SubscribeRequestData\n\n // Trim email before validation\n const trimmedEmail = email?.trim()\n\n // Validate input\n const validation = validateSubscriberData({ email: trimmedEmail, name, source })\n if (!validation.valid) {\n return Response.json({\n success: false,\n errors: validation.errors,\n }, { status: 400 })\n }\n\n // Check domain restrictions from global settings\n // Settings are public info needed for validation, but we can still respect access control\n const settings = await req.payload.findGlobal({\n slug: config.settingsSlug || 'newsletter-settings',\n overrideAccess: false,\n // No user context for public endpoint\n })\n\n const allowedDomains = settings?.subscriptionSettings?.allowedDomains?.map((d: { domain: string }) => d.domain) || []\n if (!isDomainAllowed(trimmedEmail, allowedDomains)) {\n return Response.json({\n success: false,\n error: 'Email domain not allowed',\n }, { status: 400 })\n }\n\n // Check if already subscribed\n // This needs admin access to check for existing email\n const existing = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n email: {\n equals: trimmedEmail.toLowerCase(),\n },\n },\n overrideAccess: true, // Need to check for duplicates in public endpoint\n })\n\n if (existing.docs.length > 0) {\n const subscriber = existing.docs[0]\n \n // If unsubscribed, don't allow resubscription via API\n if (subscriber.subscriptionStatus === 'unsubscribed') {\n return Response.json({\n success: false,\n error: 'This email has been unsubscribed. Please contact support to resubscribe.',\n }, { status: 400 })\n }\n\n return Response.json({\n success: false,\n error: 'Already subscribed',\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n }, { status: 400 })\n }\n\n // Check IP rate limiting\n const ipAddress = req.ip || req.connection?.remoteAddress\n const maxPerIP = settings?.subscriptionSettings?.maxSubscribersPerIP || 10\n\n const ipSubscribers = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n 'signupMetadata.ipAddress': {\n equals: ipAddress,\n },\n },\n overrideAccess: true, // Need to check IP limits in public endpoint\n })\n\n if (ipSubscribers.docs.length >= maxPerIP) {\n return Response.json({\n success: false,\n error: 'Too many subscriptions from this IP address',\n }, { status: 429 })\n }\n\n // Extract UTM parameters\n const referer = req.headers.get('referer') || req.headers.get('referrer') || ''\n let utmParams = {}\n if (referer) {\n try {\n utmParams = extractUTMParams(new URL(referer).searchParams)\n } catch {\n // Invalid URL, ignore UTM params\n }\n }\n\n // Prepare subscriber data\n const subscriberData: Partial<Subscriber> = {\n email: trimmedEmail.toLowerCase(),\n name: name ? sanitizeInput(name) : undefined,\n locale: metadata.locale || config.i18n?.defaultLocale || 'en',\n subscriptionStatus: settings?.subscriptionSettings?.requireDoubleOptIn ? 'pending' : 'active',\n source: source || 'api',\n emailPreferences: {\n newsletter: true,\n announcements: true,\n ...(preferences || {}),\n },\n signupMetadata: {\n ipAddress,\n userAgent: req.headers.get('user-agent') || undefined,\n referrer: referer,\n signupPage: metadata.signupPage || referer,\n },\n }\n\n // Add UTM parameters if tracking is enabled\n if (config.features?.utmTracking?.enabled && Object.keys(utmParams).length > 0) {\n subscriberData.utmParameters = utmParams\n }\n\n // Add lead magnet if provided\n if (config.features?.leadMagnets?.enabled && leadMagnet) {\n subscriberData.leadMagnet = leadMagnet\n }\n\n // Create subscriber\n // Public endpoint needs to create subscribers\n const subscriber = await req.payload.create({\n collection: config.subscribersSlug || 'subscribers',\n data: subscriberData,\n overrideAccess: true, // Public endpoint needs to create subscribers\n })\n\n // Handle survey responses if provided\n if (config.features?.surveys?.enabled && surveyResponses) {\n // TODO: Store survey responses\n }\n\n // Send confirmation email if double opt-in\n if (settings?.subscriptionSettings?.requireDoubleOptIn) {\n try {\n // Generate magic link token\n const token = generateMagicLinkToken(\n String(subscriber.id),\n subscriber.email,\n config\n )\n \n // Generate magic link URL\n const serverURL = req.payload.config.serverURL || process.env.PAYLOAD_PUBLIC_SERVER_URL || ''\n const magicLinkURL = generateMagicLinkURL(token, serverURL, config)\n \n // Get email service\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n \n if (emailService) {\n // Render email\n const html = await renderEmail('magic-link', {\n magicLink: magicLinkURL,\n email: subscriber.email,\n siteName: settings?.brandSettings?.siteName || 'Newsletter',\n expiresIn: config.auth?.tokenExpiration || '7d',\n })\n \n // Send email\n await emailService.send({\n to: subscriber.email,\n subject: settings?.brandSettings?.siteName ? `Verify your email for ${settings.brandSettings.siteName}` : 'Verify your email',\n html,\n })\n \n // Magic link email sent successfully\n } else {\n console.warn('Email service not initialized, cannot send magic link')\n }\n } catch (error) {\n console.error('Failed to send magic link email:', error)\n // Don't fail the subscription if email fails\n }\n }\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n message: settings?.subscriptionSettings?.requireDoubleOptIn \n ? 'Please check your email to confirm your subscription'\n : 'Successfully subscribed',\n })\n } catch {\n return Response.json({\n success: false,\n error: 'Failed to subscribe. Please try again.',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, VerifyMagicLinkRequestData, ExtendedPayloadRequest } from '../types'\nimport { \n verifyMagicLinkToken, \n generateSessionToken \n} from '../utils/jwt'\nimport { renderEmail } from '../emails/render'\n\nexport const createVerifyMagicLinkEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/verify-magic-link',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { token } = data as VerifyMagicLinkRequestData\n\n if (!token) {\n return Response.json({\n success: false,\n error: 'Token is required',\n }, { status: 400 })\n }\n\n // Verify the magic link token\n let payload\n try {\n payload = verifyMagicLinkToken(token)\n } catch (error: unknown) {\n return Response.json({\n success: false,\n error: error instanceof Error ? error.message : 'Invalid token',\n }, { status: 401 })\n }\n\n // Find the subscriber - token verified so we can use admin access for initial lookup\n const subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n // Keep overrideAccess: true for token verification\n })\n\n if (!subscriber) {\n return Response.json({\n success: false,\n error: 'Subscriber not found',\n }, { status: 404 })\n }\n\n // Check if email matches\n if (subscriber.email !== payload.email) {\n return Response.json({\n success: false,\n error: 'Invalid token',\n }, { status: 401 })\n }\n\n // Check if subscriber is active\n if (subscriber.subscriptionStatus === 'unsubscribed') {\n return Response.json({\n success: false,\n error: 'This email has been unsubscribed',\n }, { status: 403 })\n }\n\n // Create synthetic user for subscriber operations\n const syntheticUser = {\n collection: 'subscribers',\n id: subscriber.id,\n email: subscriber.email,\n }\n\n // Update subscription status if pending\n let isNewlyActivated = false\n if (subscriber.subscriptionStatus === 'pending') {\n await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: subscriber.id,\n data: {\n subscriptionStatus: 'active',\n },\n overrideAccess: false,\n user: syntheticUser,\n })\n isNewlyActivated = true\n }\n\n // Clear the magic link token\n await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: subscriber.id,\n data: {\n magicLinkToken: null,\n magicLinkTokenExpiry: null,\n },\n overrideAccess: false,\n user: syntheticUser,\n })\n\n // Generate session token\n const sessionToken = generateSessionToken(\n String(subscriber.id),\n subscriber.email\n )\n\n // Send welcome email if newly activated\n if (isNewlyActivated) {\n try {\n // Get email service\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n \n if (emailService) {\n // Get settings for site name\n const settings = await req.payload.findGlobal({\n slug: config.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: subscriber.email,\n siteName: settings?.brandSettings?.siteName || 'Newsletter',\n preferencesUrl: `${serverURL}/account/preferences`, // This could be customized\n })\n \n // Send email\n await emailService.send({\n to: subscriber.email,\n subject: settings?.brandSettings?.siteName ? `Welcome to ${settings.brandSettings.siteName}!` : 'Welcome!',\n html,\n })\n \n // Welcome email sent successfully\n } else {\n console.warn('Email service not initialized, cannot send welcome email')\n }\n } catch (error) {\n console.error('Failed to send welcome email:', error)\n // Don't fail the verification if welcome email fails\n }\n }\n\n // Set the session cookie\n const headers = new Headers()\n headers.append('Set-Cookie', `newsletter-auth=${sessionToken}; HttpOnly; Secure=${process.env.NODE_ENV === 'production'}; SameSite=Lax; Path=/; Max-Age=${30 * 24 * 60 * 60}`)\n\n return Response.json({\n success: true,\n sessionToken,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n locale: subscriber.locale,\n emailPreferences: subscriber.emailPreferences,\n },\n }, { headers })\n } catch (error: unknown) {\n console.error('Verify magic link error:', error)\n return Response.json({\n success: false,\n error: 'Failed to verify magic link',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, Subscriber, UpdatePreferencesRequestData, ExtendedPayloadRequest } from '../types'\nimport { verifySessionToken } from '../utils/jwt'\n\nexport const createPreferencesEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/preferences',\n method: 'get',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n // Get token from Authorization header\n const authHeader = req.headers.get('authorization')\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n return Response.json({\n success: false,\n error: 'Authorization required',\n }, { status: 401 })\n }\n\n const token = authHeader.substring(7)\n\n // Verify session token\n let payload\n try {\n payload = verifySessionToken(token)\n } catch (error: unknown) {\n return Response.json({\n success: false,\n error: error instanceof Error ? error.message : 'Invalid token',\n }, { status: 401 })\n }\n\n // Get subscriber - use synthetic user to ensure access control\n const subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n overrideAccess: false,\n user: {\n collection: 'subscribers',\n id: payload.subscriberId,\n email: payload.email,\n },\n })\n\n if (!subscriber) {\n return Response.json({\n success: false,\n error: 'Subscriber not found',\n }, { status: 404 })\n }\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n locale: subscriber.locale,\n emailPreferences: subscriber.emailPreferences,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n })\n } catch (error: unknown) {\n console.error('Get preferences error:', error)\n return Response.json({\n success: false,\n error: 'Failed to get preferences',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}\n\nexport const createUpdatePreferencesEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/preferences',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n // Get token from Authorization header\n const authHeader = req.headers.get('authorization')\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n return Response.json({\n success: false,\n error: 'Authorization required',\n }, { status: 401 })\n }\n\n const token = authHeader.substring(7)\n\n // Verify session token\n let payload\n try {\n payload = verifySessionToken(token)\n } catch (error: unknown) {\n return Response.json({\n success: false,\n error: error instanceof Error ? error.message : 'Invalid token',\n }, { status: 401 })\n }\n\n const data = await req.json()\n const { name, locale, emailPreferences } = data as UpdatePreferencesRequestData\n\n // Prepare update data\n const updateData: Partial<Subscriber> = {}\n \n if (name !== undefined) {\n updateData.name = name\n }\n \n if (locale !== undefined) {\n updateData.locale = locale\n }\n \n if (emailPreferences !== undefined) {\n updateData.emailPreferences = emailPreferences\n }\n\n // Update subscriber - use synthetic user to ensure only updating own data\n const subscriber = await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n data: updateData,\n overrideAccess: false,\n user: {\n collection: 'subscribers',\n id: payload.subscriberId,\n email: payload.email,\n },\n })\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n locale: subscriber.locale,\n emailPreferences: subscriber.emailPreferences,\n subscriptionStatus: subscriber.subscriptionStatus,\n },\n })\n } catch (error: unknown) {\n console.error('Update preferences error:', error)\n return Response.json({\n success: false,\n error: 'Failed to update preferences',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, UnsubscribeRequestData, ExtendedPayloadRequest } from '../types'\nimport { isValidEmail } from '../utils/validation'\n\nexport const createUnsubscribeEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/unsubscribe',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { email, token } = data as UnsubscribeRequestData\n\n // Two methods: email or token\n if (!email && !token) {\n return Response.json({\n success: false,\n error: 'Email or token is required',\n }, { status: 400 })\n }\n\n let subscriber\n\n if (token) {\n // Token-based unsubscribe (from email link)\n try {\n const jwt = await import('jsonwebtoken')\n const payload = jwt.verify(\n token,\n process.env.JWT_SECRET || process.env.PAYLOAD_SECRET || ''\n ) as { type: string; subscriberId: string; email: string }\n\n if (payload.type !== 'unsubscribe') {\n throw new Error('Invalid token type')\n }\n\n // Token verified, so we can look up the subscriber\n // Using overrideAccess: true here is OK since we verified the token\n subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n })\n } catch {\n return Response.json({\n success: false,\n error: 'Invalid or expired unsubscribe link',\n }, { status: 401 })\n }\n } else {\n // Email-based unsubscribe\n if (!email || !isValidEmail(email)) {\n return Response.json({\n success: false,\n error: 'Invalid email format',\n }, { status: 400 })\n }\n\n const result = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n email: {\n equals: email!.toLowerCase(),\n },\n },\n })\n\n if (result.docs.length === 0) {\n // Don't reveal if email exists or not\n return Response.json({\n success: true,\n message: 'If this email was subscribed, it has been unsubscribed.',\n })\n }\n\n subscriber = result.docs[0]\n }\n\n if (!subscriber) {\n return Response.json({\n success: true,\n message: 'If this email was subscribed, it has been unsubscribed.',\n })\n }\n\n // Check if already unsubscribed\n if (subscriber.subscriptionStatus === 'unsubscribed') {\n return Response.json({\n success: true,\n message: 'Already unsubscribed',\n })\n }\n\n // Update subscription status - use synthetic user to ensure proper access\n await req.payload.update({\n collection: config.subscribersSlug || 'subscribers',\n id: subscriber.id,\n data: {\n subscriptionStatus: 'unsubscribed',\n unsubscribedAt: new Date().toISOString(),\n },\n overrideAccess: false,\n user: {\n collection: 'subscribers',\n id: subscriber.id,\n email: subscriber.email,\n },\n })\n\n return Response.json({\n success: true,\n message: 'Successfully unsubscribed',\n })\n } catch (error: unknown) {\n console.error('Unsubscribe error:', error)\n return Response.json({\n success: false,\n error: 'Failed to unsubscribe. Please try again.',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","export interface RateLimiterOptions {\n maxAttempts: number\n windowMs: number\n prefix?: string\n}\n\nexport class RateLimiter {\n private attempts: Map<string, { count: number; resetTime: number }> = new Map()\n private options: RateLimiterOptions\n\n constructor(options: RateLimiterOptions) {\n this.options = options\n }\n\n async checkLimit(key: string): Promise<boolean> {\n const now = Date.now()\n const record = this.attempts.get(key)\n\n if (!record || record.resetTime < now) {\n this.attempts.set(key, {\n count: 1,\n resetTime: now + this.options.windowMs\n })\n return true\n }\n\n if (record.count >= this.options.maxAttempts) {\n return false\n }\n\n record.count++\n return true\n }\n\n async incrementAttempt(key: string): Promise<void> {\n const now = Date.now()\n const record = this.attempts.get(key)\n\n if (!record || record.resetTime < now) {\n this.attempts.set(key, {\n count: 1,\n resetTime: now + this.options.windowMs\n })\n } else {\n record.count++\n }\n }\n\n async reset(key: string): Promise<void> {\n this.attempts.delete(key)\n }\n\n async resetAll(): Promise<void> {\n this.attempts.clear()\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, SigninRequestData, ExtendedPayloadRequest } from '../types'\nimport { validateSubscriberData } from '../utils/validation'\nimport { generateMagicLinkToken, generateMagicLinkURL } from '../utils/jwt'\nimport { renderEmail } from '../emails/render'\nimport { RateLimiter } from '../utils/rate-limiter'\n\n// Create rate limiter: 5 attempts per 15 minutes\nconst signinRateLimiter = new RateLimiter({\n maxAttempts: 5,\n windowMs: 15 * 60 * 1000, // 15 minutes\n prefix: 'signin',\n})\n\nexport const createSigninEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/signin',\n method: 'post',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n const data = await req.json()\n const { email } = data as SigninRequestData\n\n // Validate email\n const validation = validateSubscriberData({ email })\n if (!validation.valid) {\n return Response.json({\n success: false,\n errors: validation.errors,\n }, { status: 400 })\n }\n\n // Check rate limit (per email to prevent abuse)\n const rateLimitKey = `signin:${email.toLowerCase()}`\n const allowed = await signinRateLimiter.checkLimit(rateLimitKey)\n \n if (!allowed) {\n return Response.json({\n success: false,\n error: 'Too many sign-in attempts. Please try again later.',\n }, { status: 429 })\n }\n\n // Find existing active subscriber\n const result = await req.payload.find({\n collection: config.subscribersSlug || 'subscribers',\n where: {\n email: { equals: email.toLowerCase() },\n subscriptionStatus: { equals: 'active' },\n },\n limit: 1,\n overrideAccess: true, // Need to check subscriber exists\n })\n\n if (result.docs.length === 0) {\n return Response.json({\n success: false,\n error: 'Email not found. Please subscribe first.',\n }, { status: 404 })\n }\n\n const subscriber = result.docs[0]\n\n // Generate magic link token\n const token = generateMagicLinkToken(\n String(subscriber.id),\n subscriber.email,\n config\n )\n\n // Generate magic link URL\n const serverURL = req.payload.config.serverURL || process.env.PAYLOAD_PUBLIC_SERVER_URL || ''\n const magicLinkURL = generateMagicLinkURL(token, serverURL, config)\n\n // Get email service\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n\n if (emailService) {\n // Get settings for customization\n const settings = await req.payload.findGlobal({\n slug: config.settingsSlug || 'newsletter-settings',\n })\n\n // Render email\n const html = await renderEmail('signin', {\n magicLink: magicLinkURL,\n email: subscriber.email,\n siteName: settings?.brandSettings?.siteName || 'Newsletter',\n expiresIn: config.auth?.tokenExpiration || '7d',\n })\n\n // Send email\n await emailService.send({\n to: subscriber.email,\n subject: settings?.brandSettings?.siteName \n ? `Sign in to ${settings.brandSettings.siteName}` \n : 'Sign in to your account',\n html,\n })\n\n // Sign-in email sent successfully\n } else {\n console.warn('Email service not initialized, cannot send sign-in link')\n }\n\n return Response.json({\n success: true,\n message: 'Check your email for the sign-in link',\n })\n } catch (error) {\n console.error('Sign-in error:', error)\n return Response.json({\n success: false,\n error: 'Failed to process sign-in request',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, ExtendedPayloadRequest } from '../types'\nimport { verifySessionToken } from '../utils/jwt'\n\nexport const createMeEndpoint = (\n config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/me',\n method: 'get',\n handler: (async (req: ExtendedPayloadRequest) => {\n try {\n // Get token from cookie header\n const cookieHeader = req.headers.get('cookie') || ''\n const cookies = Object.fromEntries(\n cookieHeader.split('; ').map(c => {\n const [key, ...value] = c.split('=')\n return [key, value.join('=')]\n })\n )\n const token = cookies['newsletter-auth']\n \n if (!token) {\n return Response.json({\n success: false,\n error: 'Not authenticated',\n }, { status: 401 })\n }\n\n // Verify the session token\n let payload\n try {\n payload = verifySessionToken(token)\n } catch {\n return Response.json({\n success: false,\n error: 'Invalid or expired session',\n }, { status: 401 })\n }\n\n // Get fresh subscriber data\n const subscriber = await req.payload.findByID({\n collection: config.subscribersSlug || 'subscribers',\n id: payload.subscriberId,\n overrideAccess: true, // Need to get subscriber data\n })\n\n if (!subscriber || subscriber.subscriptionStatus !== 'active') {\n return Response.json({\n success: false,\n error: 'Not authenticated',\n }, { status: 401 })\n }\n\n return Response.json({\n success: true,\n subscriber: {\n id: subscriber.id,\n email: subscriber.email,\n name: subscriber.name,\n status: subscriber.subscriptionStatus,\n preferences: {\n frequency: subscriber.emailPreferences?.frequency,\n categories: subscriber.emailPreferences?.categories,\n },\n createdAt: subscriber.createdAt,\n updatedAt: subscriber.updatedAt,\n },\n })\n } catch (error) {\n console.error('Me endpoint error:', error)\n return Response.json({\n success: false,\n error: 'Internal server error',\n }, { status: 500 })\n }\n }) as PayloadHandler,\n }\n}","import type { Endpoint, PayloadHandler } from 'payload'\nimport type { NewsletterPluginConfig, ExtendedPayloadRequest } from '../types'\n\nexport const createSignoutEndpoint = (\n _config: NewsletterPluginConfig\n): Endpoint => {\n return {\n path: '/newsletter/signout',\n method: 'post',\n handler: ((_req: ExtendedPayloadRequest) => {\n try {\n // In Payload v3, cookies are handled differently\n // The Response object doesn't have a clearCookie method\n // We'll need to set the cookie with an expired date\n const headers = new Headers()\n headers.append('Set-Cookie', `newsletter-auth=; HttpOnly; Secure=${process.env.NODE_ENV === 'production'}; SameSite=Lax; Path=/; Max-Age=0`)\n \n return Response.json({ \n success: true, \n message: 'Signed out successfully' \n }, { headers })\n } catch (error) {\n console.error('Signout error:', error)\n return Response.json({\n success: false,\n error: 'Failed to sign out',\n }, { status: 500 })\n }\n }) as PayloadHandler,\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'\n\nexport const createSendBroadcastEndpoint = (\n config: NewsletterPluginConfig,\n collectionSlug: string\n): Endpoint => {\n return {\n path: `/${collectionSlug}/: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 // Get broadcast provider\n const broadcastProvider = (req.payload as any).newsletterProvider\n if (!broadcastProvider) {\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 to get the provider ID\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 // Send broadcast using provider ID\n const broadcast = await broadcastProvider.send(broadcastDoc.providerId, data)\n\n // Update status in Payload collection\n await req.payload.update({\n collection: collectionSlug,\n id,\n data: {\n status: 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 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 { 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'\n\nexport const createScheduleBroadcastEndpoint = (\n config: NewsletterPluginConfig,\n collectionSlug: string\n): Endpoint => {\n return {\n path: `/${collectionSlug}/: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 // Get broadcast provider\n const broadcastProvider = (req.payload as any).newsletterProvider\n if (!broadcastProvider) {\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 to get the provider ID\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 // Schedule broadcast using provider ID\n const broadcast = await broadcastProvider.schedule(broadcastDoc.providerId, scheduledDate)\n\n // Update status in Payload collection\n await req.payload.update({\n collection: collectionSlug,\n id,\n data: {\n status: NewsletterStatus.SCHEDULED,\n scheduledAt: scheduledDate.toISOString(),\n },\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 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}","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 ],\n ALLOWED_ATTR: ['href', 'style', 'target', 'rel', 'align'],\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,\n options?: {\n wrapInTemplate?: boolean\n preheader?: string\n }\n): Promise<string> {\n // First, convert Lexical state to HTML using custom converters\n const rawHtml = await lexicalToEmailHtml(editorState)\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 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(editorState: SerializedEditorState): Promise<string> {\n const { root } = editorState\n \n if (!root || !root.children) {\n return ''\n }\n \n const html = root.children.map((node: any) => convertNode(node)).join('')\n return html\n}\n\n/**\n * Convert individual Lexical nodes to email-safe HTML\n */\nfunction convertNode(node: any): string {\n switch (node.type) {\n case 'paragraph':\n return convertParagraph(node)\n case 'heading':\n return convertHeading(node)\n case 'list':\n return convertList(node)\n case 'listitem':\n return convertListItem(node)\n case 'blockquote':\n return convertBlockquote(node)\n case 'text':\n return convertText(node)\n case 'link':\n return convertLink(node)\n case 'linebreak':\n return '<br>'\n default:\n // Unknown node type - convert children if any\n if (node.children) {\n return node.children.map(convertNode).join('')\n }\n return ''\n }\n}\n\n/**\n * Convert paragraph node\n */\nfunction convertParagraph(node: any): string {\n const align = getAlignment(node.format)\n const children = node.children?.map(convertNode).join('') || ''\n \n if (!children.trim()) {\n return '<p style=\"margin: 0 0 16px 0; min-height: 1em;\">&nbsp;</p>'\n }\n \n return `<p style=\"margin: 0 0 16px 0; text-align: ${align};\">${children}</p>`\n}\n\n/**\n * Convert heading node\n */\nfunction convertHeading(node: any): string {\n const tag = node.tag || 'h1'\n const align = getAlignment(node.format)\n const children = node.children?.map(convertNode).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 style = `${styles[tag] || styles.h3} text-align: ${align};`\n \n return `<${tag} style=\"${style}\">${children}</${tag}>`\n}\n\n/**\n * Convert list node\n */\nfunction convertList(node: any): string {\n const tag = node.listType === 'number' ? 'ol' : 'ul'\n const children = node.children?.map(convertNode).join('') || ''\n \n const style = tag === 'ul' \n ? 'margin: 0 0 16px 0; padding-left: 24px; list-style-type: disc;'\n : 'margin: 0 0 16px 0; padding-left: 24px; list-style-type: decimal;'\n \n return `<${tag} style=\"${style}\">${children}</${tag}>`\n}\n\n/**\n * Convert list item node\n */\nfunction convertListItem(node: any): string {\n const children = node.children?.map(convertNode).join('') || ''\n return `<li style=\"margin: 0 0 8px 0;\">${children}</li>`\n}\n\n/**\n * Convert blockquote node\n */\nfunction convertBlockquote(node: any): string {\n const children = node.children?.map(convertNode).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 */\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 */\nfunction convertLink(node: any): string {\n const children = node.children?.map(convertNode).join('') || ''\n const url = node.fields?.url || '#'\n \n // Ensure links open in new tab and have security attributes\n return `<a href=\"${escapeHtml(url)}\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color: #2563eb; text-decoration: underline;\">${children}</a>`\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 basic email template\n */\nfunction wrapInEmailTemplate(content: string, preheader?: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Email</title>\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</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: #333333; background-color: #f3f4f6;\">\n ${preheader ? `<div style=\"display: none; max-height: 0; overflow: hidden;\">${escapeHtml(preheader)}</div>` : ''}\n <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"margin: 0; padding: 0;\">\n <tr>\n <td align=\"center\" style=\"padding: 20px 0;\">\n <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" width=\"600\" style=\"margin: 0 auto; background-color: #ffffff; border-radius: 8px; overflow: hidden;\">\n <tr>\n <td style=\"padding: 40px 30px;\">\n ${content}\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 { 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: `/${collectionSlug}/: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 // Get the channel for sender info\n const channel = await req.payload.findByID({\n collection: 'channels',\n id: typeof broadcast.channel === 'string' ? broadcast.channel : broadcast.channel.id,\n user: auth.user,\n })\n\n // Convert content to email-safe HTML\n const htmlContent = await convertToEmailSafeHtml(broadcast.content, {\n wrapInTemplate: true,\n preheader: broadcast.preheader,\n })\n\n // Get email service\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 // Send test email\n await emailService.send({\n to: testEmail,\n from: channel?.fromEmail || config.providers.resend?.fromAddress || 'noreply@example.com',\n fromName: channel?.fromName || config.providers.resend?.fromName || 'Newsletter',\n replyTo: broadcast.settings?.replyTo || channel?.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 type { Endpoint } from 'payload'\nimport type { NewsletterPluginConfig } from '../../types'\nimport { createSendBroadcastEndpoint } from './send'\nimport { createScheduleBroadcastEndpoint } from './schedule'\nimport { createTestBroadcastEndpoint } from './test'\n\nexport const createBroadcastManagementEndpoints = (\n config: NewsletterPluginConfig\n): Endpoint[] => {\n // Only create endpoints if broadcast management is enabled\n if (!config.features?.newsletterManagement?.enabled) {\n return []\n }\n\n // Only create custom action endpoints\n // CRUD operations are handled by Payload's automatic REST API\n const collectionSlug = config.features.newsletterManagement.collections?.broadcasts || 'broadcasts'\n \n return [\n createSendBroadcastEndpoint(config, collectionSlug),\n createScheduleBroadcastEndpoint(config, collectionSlug),\n createTestBroadcastEndpoint(config, collectionSlug),\n ]\n}","import type { Endpoint } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { createSubscribeEndpoint } from './subscribe'\nimport { createVerifyMagicLinkEndpoint } from './verify-magic-link'\nimport { createPreferencesEndpoint, createUpdatePreferencesEndpoint } from './preferences'\nimport { createUnsubscribeEndpoint } from './unsubscribe'\nimport { createSigninEndpoint } from './signin'\nimport { createMeEndpoint } from './me'\nimport { createSignoutEndpoint } from './signout'\nimport { createBroadcastManagementEndpoints } from './broadcasts'\n\nexport function createNewsletterEndpoints(\n config: NewsletterPluginConfig\n): Endpoint[] {\n const endpoints: Endpoint[] = [\n createSubscribeEndpoint(config),\n createUnsubscribeEndpoint(config),\n ]\n\n // Add auth endpoints if enabled\n if (config.auth?.enabled !== false) {\n endpoints.push(\n createVerifyMagicLinkEndpoint(config),\n createPreferencesEndpoint(config),\n createUpdatePreferencesEndpoint(config),\n createSigninEndpoint(config),\n createMeEndpoint(config),\n createSignoutEndpoint(config)\n )\n }\n\n // Add broadcast management endpoints if enabled\n endpoints.push(...createBroadcastManagementEndpoints(config))\n\n return endpoints\n}","import type { Field } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport function createNewsletterSchedulingFields(\n config: NewsletterPluginConfig\n): Field[] {\n const groupName = config.features?.newsletterScheduling?.fields?.groupName || 'newsletterScheduling'\n const contentField = config.features?.newsletterScheduling?.fields?.contentField || 'content'\n const createMarkdownField = config.features?.newsletterScheduling?.fields?.createMarkdownField !== false\n\n const fields: Field[] = [\n {\n name: groupName,\n type: 'group',\n label: 'Newsletter Scheduling',\n admin: {\n condition: (data, { user }) => user?.collection === 'users', // Only show for admin users\n },\n fields: [\n {\n name: 'scheduled',\n type: 'checkbox',\n label: 'Schedule for Newsletter',\n defaultValue: false,\n admin: {\n description: 'Schedule this content to be sent as a newsletter',\n },\n },\n {\n name: 'scheduledDate',\n type: 'date',\n label: 'Send Date',\n required: true,\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'When to send this newsletter',\n },\n },\n {\n name: 'sentDate',\n type: 'date',\n label: 'Sent Date',\n admin: {\n readOnly: true,\n condition: (data) => data?.[groupName]?.sendStatus === 'sent',\n description: 'When this newsletter was sent',\n },\n },\n {\n name: 'sendStatus',\n type: 'select',\n label: 'Status',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Scheduled', value: 'scheduled' },\n { label: 'Sending', value: 'sending' },\n { label: 'Sent', value: 'sent' },\n { label: 'Failed', value: 'failed' },\n ],\n defaultValue: 'draft',\n admin: {\n readOnly: true,\n description: 'Current send status',\n },\n },\n {\n name: 'emailSubject',\n type: 'text',\n label: 'Email Subject',\n required: true,\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Subject line for the newsletter email',\n },\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Email Preheader',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Preview text that appears after the subject line',\n },\n },\n {\n name: 'segments',\n type: 'select',\n label: 'Target Segments',\n hasMany: true,\n options: [\n { label: 'All Subscribers', value: 'all' },\n ...(config.i18n?.locales?.map(locale => ({\n label: `${locale.toUpperCase()} Subscribers`,\n value: locale,\n })) || []),\n ],\n defaultValue: ['all'],\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Which subscriber segments to send to',\n },\n },\n {\n name: 'testEmails',\n type: 'array',\n label: 'Test Email Recipients',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled && data?.[groupName]?.sendStatus === 'draft',\n description: 'Send test emails before scheduling',\n },\n fields: [\n {\n name: 'email',\n type: 'email',\n required: true,\n },\n ],\n },\n ],\n },\n ]\n\n // Add markdown companion field if requested\n if (createMarkdownField) {\n fields.push(createMarkdownFieldInternal({\n name: `${contentField}Markdown`,\n richTextField: contentField,\n label: 'Email Content (Markdown)',\n admin: {\n position: 'sidebar',\n condition: (data: any) => Boolean(data?.[contentField] && data?.[groupName]?.scheduled),\n description: 'Markdown version for email rendering',\n readOnly: true,\n },\n }))\n }\n\n return fields\n}\n\n/**\n * Create a markdown companion field for rich text\n * This creates a virtual field that converts rich text to markdown\n */\nfunction createMarkdownFieldInternal(config: {\n name: string\n richTextField: string\n label?: string\n admin?: any\n}): Field {\n return {\n name: config.name,\n type: 'textarea',\n label: config.label || 'Markdown',\n admin: {\n ...config.admin,\n description: config.admin?.description || 'Auto-generated from rich text content',\n },\n hooks: {\n afterRead: [\n async ({ data }) => {\n // Convert rich text to markdown on read\n if (data?.[config.richTextField]) {\n try {\n const { convertLexicalToMarkdown } = await import('@payloadcms/richtext-lexical')\n return convertLexicalToMarkdown({\n data: data[config.richTextField],\n } as any)\n } catch {\n return ''\n }\n }\n return ''\n },\n ],\n beforeChange: [\n () => {\n // Don't save markdown to database\n return null\n },\n ],\n },\n }\n}","import type { TaskConfig, PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig } from '../types/index'\n\nexport const createUnsubscribeSyncJob = (\n pluginConfig: NewsletterPluginConfig\n): TaskConfig => {\n return {\n slug: 'sync-unsubscribes',\n label: 'Sync Unsubscribes from Email Service',\n handler: async ({ req }: { req: PayloadRequest }) => {\n const subscribersSlug = pluginConfig.subscribersSlug || 'subscribers'\n const emailService = (req.payload as any).newsletterEmailService // TODO: Add proper type for newsletter email service\n \n if (!emailService) {\n console.error('Email service not configured')\n return {\n output: {\n syncedCount: 0\n }\n }\n }\n\n let syncedCount = 0\n \n try {\n // For Broadcast: Poll all subscribers\n if (emailService.getProvider() === 'broadcast') {\n console.warn('Starting Broadcast unsubscribe sync...')\n \n // Get Broadcast configuration\n const broadcastConfig = pluginConfig.providers?.broadcast\n if (!broadcastConfig) {\n throw new Error('Broadcast configuration not found')\n }\n\n const apiUrl = broadcastConfig.apiUrl.replace(/\\/$/, '')\n const token = process.env.NODE_ENV === 'production' \n ? broadcastConfig.tokens.production \n : broadcastConfig.tokens.development\n\n let page = 1\n let hasMore = true\n\n while (hasMore) {\n // Fetch subscribers from Broadcast\n const response = await fetch(\n `${apiUrl}/api/v1/subscribers.json?page=${page}`,\n {\n headers: {\n 'Authorization': `Bearer ${token}`,\n },\n }\n )\n\n if (!response.ok) {\n throw new Error(`Broadcast API error: ${response.status}`)\n }\n\n const data = await response.json()\n const broadcastSubscribers = data.subscribers || []\n \n // Process each subscriber\n for (const broadcastSub of broadcastSubscribers) {\n // Find corresponding subscriber in Payload\n const payloadSubscribers = await req.payload.find({\n collection: subscribersSlug,\n where: {\n email: {\n equals: broadcastSub.email,\n },\n },\n limit: 1,\n })\n\n if (payloadSubscribers.docs.length > 0) {\n const payloadSub = payloadSubscribers.docs[0]\n \n // Check if unsubscribe status differs\n const broadcastUnsubscribed = !broadcastSub.is_active || broadcastSub.unsubscribed_at\n const payloadUnsubscribed = payloadSub.subscriptionStatus === 'unsubscribed'\n \n if (broadcastUnsubscribed && !payloadUnsubscribed) {\n // Update Payload subscriber to unsubscribed\n await req.payload.update({\n collection: subscribersSlug,\n id: payloadSub.id,\n data: {\n subscriptionStatus: 'unsubscribed',\n unsubscribedAt: broadcastSub.unsubscribed_at || new Date().toISOString(),\n },\n })\n syncedCount++\n console.warn(`Unsubscribed: ${broadcastSub.email}`)\n }\n }\n }\n\n // Check pagination\n if (data.pagination && data.pagination.current < data.pagination.total_pages) {\n page++\n } else {\n hasMore = false\n }\n }\n\n console.warn(`Broadcast sync complete. Unsubscribed ${syncedCount} contacts.`)\n }\n\n // For Resend: Use Audiences API\n if (emailService.getProvider() === 'resend') {\n console.warn('Starting Resend unsubscribe sync...')\n \n // Note: Resend webhooks are preferred over polling\n // This is a fallback polling implementation\n \n // First, get all audiences\n const resendConfig = pluginConfig.providers?.resend\n if (!resendConfig) {\n throw new Error('Resend configuration not found')\n }\n\n // You would need to implement audience/contact polling here\n // Resend's API structure would require:\n // 1. List audiences\n // 2. For each audience, list contacts\n // 3. Check unsubscribed status\n \n console.warn('Resend polling implementation needed - webhooks recommended')\n }\n\n // Custom after sync hook\n if (pluginConfig.hooks?.afterUnsubscribeSync) {\n await pluginConfig.hooks.afterUnsubscribeSync({ \n req, \n syncedCount: syncedCount\n })\n }\n\n } catch (error) {\n console.error('Unsubscribe sync error:', error)\n throw error\n }\n \n return {\n output: {\n syncedCount\n }\n }\n },\n }\n}","import type { CollectionConfig } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport const createChannelsCollection = (pluginConfig: NewsletterPluginConfig): CollectionConfig => {\n const hasProviders = !!(pluginConfig.providers?.broadcast || pluginConfig.providers?.resend)\n\n return {\n slug: 'channels',\n labels: {\n singular: 'Channel',\n plural: 'Channels',\n },\n admin: {\n useAsTitle: 'name',\n description: 'Newsletter channels/publications that can send broadcasts',\n defaultColumns: ['name', 'fromEmail', 'subscriberCount', 'active'],\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n required: true,\n admin: {\n description: 'The name of this newsletter channel'\n },\n },\n {\n name: 'description',\n type: 'textarea',\n admin: {\n description: 'A brief description of what this channel is about'\n },\n },\n {\n name: 'fromName',\n type: 'text',\n required: true,\n admin: {\n description: 'The sender name that appears in emails'\n },\n },\n {\n name: 'fromEmail',\n type: 'email',\n required: true,\n admin: {\n description: 'The sender email address'\n },\n },\n {\n name: 'replyTo',\n type: 'email',\n admin: {\n description: 'Reply-to email address (optional)'\n },\n },\n {\n name: 'providerType',\n type: 'select',\n required: true,\n options: [\n ...(pluginConfig.providers?.broadcast ? [{ label: 'Broadcast', value: 'broadcast' }] : []),\n ...(pluginConfig.providers?.resend ? [{ label: 'Resend', value: 'resend' }] : []),\n ],\n admin: {\n description: 'Which email provider manages this channel'\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: 'subscriberCount',\n type: 'number',\n admin: {\n readOnly: true,\n description: 'Number of active subscribers',\n },\n defaultValue: 0,\n },\n {\n name: 'active',\n type: 'checkbox',\n defaultValue: true,\n admin: {\n description: 'Whether this channel is currently active'\n },\n },\n {\n name: 'settings',\n type: 'group',\n fields: [\n {\n name: 'defaultTrackOpens',\n type: 'checkbox',\n defaultValue: true,\n admin: {\n description: 'Track email opens by default for broadcasts in this channel'\n },\n },\n {\n name: 'defaultTrackClicks',\n type: 'checkbox',\n defaultValue: true,\n admin: {\n description: 'Track link clicks by default for broadcasts in this channel'\n },\n },\n {\n name: 'requireDoubleOptIn',\n type: 'checkbox',\n defaultValue: false,\n admin: {\n description: 'Require double opt-in for new subscribers'\n },\n },\n ],\n },\n ],\n hooks: {\n // Sync with provider on create\n afterChange: [\n async ({ doc, operation, req }) => {\n if (!hasProviders || operation !== 'create') return doc\n\n try {\n const provider = await getProvider(doc.providerType, pluginConfig)\n if (!provider) return doc\n\n // Create channel in provider\n const providerChannel = await provider.createChannel({\n name: doc.name,\n description: doc.description,\n fromName: doc.fromName,\n fromEmail: doc.fromEmail,\n replyTo: doc.replyTo,\n })\n\n // Update with provider ID\n await req.payload.update({\n collection: 'channels',\n id: doc.id,\n data: {\n providerId: providerChannel.id,\n subscriberCount: providerChannel.subscriberCount || 0,\n },\n req,\n })\n\n return {\n ...doc,\n providerId: providerChannel.id,\n subscriberCount: providerChannel.subscriberCount || 0,\n }\n } catch (error) {\n req.payload.logger.error('Failed to create channel in provider:', error)\n return doc\n }\n },\n ],\n // Sync updates with provider\n beforeChange: [\n async ({ data, originalDoc, operation, req }) => {\n if (!hasProviders || !originalDoc?.providerId || operation !== 'update') return data\n\n try {\n const provider = await getProvider(originalDoc.providerType, pluginConfig)\n if (!provider) return data\n\n // Check what fields changed\n const updates: any = {}\n if (data.name !== originalDoc.name) updates.name = data.name\n if (data.description !== originalDoc.description) updates.description = data.description\n if (data.fromName !== originalDoc.fromName) updates.fromName = data.fromName\n if (data.fromEmail !== originalDoc.fromEmail) updates.fromEmail = data.fromEmail\n if (data.replyTo !== originalDoc.replyTo) updates.replyTo = data.replyTo\n\n if (Object.keys(updates).length > 0) {\n await provider.updateChannel(originalDoc.providerId, updates)\n }\n } catch (error) {\n req.payload.logger.error('Failed to update channel in provider:', error)\n // Continue with local update even if provider fails\n }\n\n return data\n },\n ],\n // Handle deletion\n afterDelete: [\n async ({ doc, req }) => {\n if (!hasProviders || !doc?.providerId) return doc\n\n try {\n const provider = await getProvider(doc.providerType, pluginConfig)\n if (!provider) return doc\n\n await provider.deleteChannel(doc.providerId)\n } catch (error) {\n req.payload.logger.error('Failed to delete channel from provider:', error)\n }\n\n return doc\n },\n ],\n },\n }\n}\n\n// Helper to get provider instance\nasync function getProvider(providerType: string, config: NewsletterPluginConfig): Promise<any> {\n if (providerType === 'broadcast') {\n const { BroadcastApiProvider } = await import('../providers/broadcast/broadcast')\n const providerConfig = config.providers?.broadcast\n return providerConfig ? new BroadcastApiProvider(providerConfig) : null\n }\n \n if (providerType === 'resend') {\n const { ResendBroadcastProvider } = await import('../providers/resend/broadcast')\n const providerConfig = config.providers?.resend\n return providerConfig ? new ResendBroadcastProvider(providerConfig) : null\n }\n\n return null\n}","import type { CollectionConfig } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { BroadcastStatus } from '../types'\nimport { createEmailContentField } from '../fields/emailContent'\nimport { convertToEmailSafeHtml } from '../utils/emailSafeHtml'\n\nexport const createBroadcastsCollection = (pluginConfig: NewsletterPluginConfig): CollectionConfig => {\n const hasProviders = !!(pluginConfig.providers?.broadcast || pluginConfig.providers?.resend)\n\n return {\n slug: 'broadcasts',\n labels: {\n singular: 'Broadcast',\n plural: 'Broadcasts',\n },\n admin: {\n useAsTitle: 'name',\n description: 'Individual email campaigns sent to subscribers',\n defaultColumns: ['name', 'subject', 'status', 'channel', 'sentAt', 'actions'],\n },\n fields: [\n {\n name: 'channel',\n type: 'relationship',\n relationTo: 'channels',\n required: true,\n admin: {\n description: 'The channel this broadcast belongs to'\n },\n },\n {\n name: 'name',\n type: 'text',\n required: true,\n admin: {\n description: 'Internal name for this broadcast'\n },\n },\n {\n name: 'subject',\n type: 'text',\n required: true,\n admin: {\n description: 'Email subject line'\n },\n },\n {\n name: 'preheader',\n type: 'text',\n admin: {\n description: 'Preview text shown in email clients'\n },\n },\n createEmailContentField({\n admin: {\n description: 'Email content',\n },\n }),\n {\n name: 'emailPreview',\n type: 'ui',\n admin: {\n components: {\n Field: '/src/components/Broadcasts/EmailPreviewField',\n },\n },\n },\n {\n name: 'status',\n type: 'select',\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 components: {\n Cell: '/src/components/Broadcasts/StatusBadge',\n },\n },\n },\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?.status === 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?.status === 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: 'providerData',\n type: 'json',\n admin: {\n readOnly: true,\n condition: () => false, // Hidden by default\n },\n },\n // UI Field for custom actions in list view\n {\n name: 'actions',\n type: 'ui',\n admin: {\n components: {\n Cell: '/src/components/Broadcasts/ActionsCell',\n Field: '/src/components/Broadcasts/EmptyField',\n },\n disableListColumn: false,\n },\n },\n ],\n hooks: {\n // Sync with provider on create\n afterChange: [\n async ({ doc, operation, req }) => {\n if (!hasProviders || operation !== 'create') return doc\n\n try {\n // Get the channel to determine provider\n const channel = await req.payload.findByID({\n collection: 'channels',\n id: typeof doc.channel === 'string' ? doc.channel : doc.channel.id,\n req,\n })\n\n const provider = await getProvider(channel.providerType, pluginConfig)\n if (!provider) return doc\n\n // Convert rich text to HTML\n const htmlContent = await convertToEmailSafeHtml(doc.content)\n\n // Create broadcast in provider\n const providerBroadcast = await provider.create({\n channelId: channel.providerId || channel.id,\n name: doc.name,\n subject: doc.subject,\n preheader: doc.preheader,\n content: htmlContent,\n trackOpens: doc.settings?.trackOpens,\n trackClicks: doc.settings?.trackClicks,\n replyTo: doc.settings?.replyTo,\n audienceIds: doc.audienceIds?.map((a: any) => a.audienceId),\n })\n\n // Update with provider ID\n await req.payload.update({\n collection: 'broadcasts',\n id: doc.id,\n data: {\n providerId: providerBroadcast.id,\n providerData: providerBroadcast.providerData,\n },\n req,\n })\n\n return {\n ...doc,\n providerId: providerBroadcast.id,\n providerData: providerBroadcast.providerData,\n }\n } catch (error) {\n req.payload.logger.error('Failed to create broadcast in provider:', error)\n return doc\n }\n },\n ],\n // Sync updates with provider\n beforeChange: [\n async ({ data, originalDoc, operation, req }) => {\n if (!hasProviders || !originalDoc?.providerId || operation !== 'update') return data\n\n try {\n // Get the channel to determine provider\n const channelId = data.channel || originalDoc.channel\n const channel = await req.payload.findByID({\n collection: 'channels',\n id: typeof channelId === 'string' ? channelId : channelId.id,\n req,\n })\n\n const provider = await getProvider(channel.providerType, pluginConfig)\n if (!provider) return data\n\n // Only sync if broadcast is still editable\n const capabilities = provider.getCapabilities()\n if (!capabilities.editableStatuses.includes(originalDoc.status)) {\n return data\n }\n\n // Build update data\n const updates: any = {}\n if (data.name !== originalDoc.name) updates.name = data.name\n if (data.subject !== originalDoc.subject) updates.subject = data.subject\n if (data.preheader !== originalDoc.preheader) updates.preheader = data.preheader\n if (data.content !== originalDoc.content) {\n updates.content = await convertToEmailSafeHtml(data.content)\n }\n if (data.settings?.trackOpens !== originalDoc.settings?.trackOpens) {\n updates.trackOpens = data.settings.trackOpens\n }\n if (data.settings?.trackClicks !== originalDoc.settings?.trackClicks) {\n updates.trackClicks = data.settings.trackClicks\n }\n if (data.settings?.replyTo !== originalDoc.settings?.replyTo) {\n updates.replyTo = data.settings.replyTo\n }\n if (JSON.stringify(data.audienceIds) !== JSON.stringify(originalDoc.audienceIds)) {\n updates.audienceIds = data.audienceIds?.map((a: any) => a.audienceId)\n }\n\n if (Object.keys(updates).length > 0) {\n await provider.update(originalDoc.providerId, updates)\n }\n } catch (error) {\n req.payload.logger.error('Failed to update broadcast in provider:', error)\n // Continue with local update even if provider fails\n }\n\n return data\n },\n ],\n // Handle deletion\n afterDelete: [\n async ({ doc, req }) => {\n if (!hasProviders || !doc?.providerId) return doc\n\n try {\n // Get the channel to determine provider\n const channel = await req.payload.findByID({\n collection: 'channels',\n id: typeof doc.channel === 'string' ? doc.channel : doc.channel.id,\n req,\n })\n\n const provider = await getProvider(channel.providerType, pluginConfig)\n if (!provider) return doc\n\n // Only delete if broadcast is still editable\n const capabilities = provider.getCapabilities()\n if (capabilities.editableStatuses.includes(doc.status)) {\n await provider.delete(doc.providerId)\n }\n } catch (error) {\n req.payload.logger.error('Failed to delete broadcast from provider:', error)\n }\n\n return doc\n },\n ],\n },\n }\n}\n\n// Helper to get provider instance\nasync function getProvider(providerType: string, config: NewsletterPluginConfig): Promise<any> {\n if (providerType === 'broadcast') {\n const { BroadcastApiProvider } = await import('../providers/broadcast/broadcast')\n const providerConfig = config.providers?.broadcast\n return providerConfig ? new BroadcastApiProvider(providerConfig) : null\n }\n \n if (providerType === 'resend') {\n const { ResendBroadcastProvider } = await import('../providers/resend/broadcast')\n const providerConfig = config.providers?.resend\n return providerConfig ? new ResendBroadcastProvider(providerConfig) : null\n }\n\n return null\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 lexicalEditor,\n} from '@payloadcms/richtext-lexical'\nimport type { RichTextField } from 'payload'\n\n/**\n * Email-safe features for Lexical editor\n * Only includes features that render consistently across email clients\n */\nexport const emailSafeFeatures: any[] = [\n // Basic text formatting\n BoldFeature(),\n ItalicFeature(),\n UnderlineFeature(),\n StrikethroughFeature(),\n \n // Links with simple configuration\n LinkFeature({\n fields: [{\n name: 'url',\n type: 'text',\n required: true,\n admin: {\n description: 'Enter the full URL (including https://)',\n },\n }],\n }),\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\n/**\n * Creates an email-safe rich text field configuration\n */\nexport const createEmailContentField = (overrides?: Partial<RichTextField>): RichTextField => {\n return {\n name: 'content',\n type: 'richText',\n required: true,\n editor: lexicalEditor({\n features: emailSafeFeatures,\n }),\n admin: {\n description: 'Email content with limited formatting for compatibility',\n ...overrides?.admin,\n },\n ...overrides,\n }\n}","import type { Config } from 'payload'\nimport type { NewsletterPluginConfig, BroadcastProvider } from './types'\nimport { createSubscribersCollection } from './collections/Subscribers'\nimport { createNewsletterSettingsGlobal } from './globals/NewsletterSettings'\nimport { createEmailService } from './providers'\nimport { createNewsletterEndpoints } from './endpoints'\nimport { createNewsletterSchedulingFields } from './fields/newsletterScheduling'\nimport { createUnsubscribeSyncJob } from './jobs/sync-unsubscribes'\nimport { createChannelsCollection } from './collections/Channels'\nimport { createBroadcastsCollection } from './collections/Broadcasts'\nimport { BroadcastApiProvider } from './providers/broadcast/broadcast'\nimport { ResendBroadcastProvider } from './providers/resend/broadcast'\n\n// Extend Payload type to include our email service and broadcast provider\ndeclare module 'payload' {\n interface BasePayload {\n newsletterEmailService?: any\n broadcastProvider?: BroadcastProvider\n // Legacy support\n newsletterProvider?: BroadcastProvider\n }\n}\n\nexport const newsletterPlugin = (pluginConfig: NewsletterPluginConfig) => (incomingConfig: Config): Config => {\n // Validate and set defaults\n const config: NewsletterPluginConfig = {\n enabled: true,\n subscribersSlug: 'subscribers',\n settingsSlug: 'newsletter-settings',\n auth: {\n enabled: true,\n tokenExpiration: '7d',\n magicLinkPath: '/newsletter/verify',\n ...pluginConfig.auth,\n },\n ...pluginConfig,\n }\n\n // If plugin is disabled, return config unchanged\n if (!config.enabled) {\n return incomingConfig\n }\n\n // Create plugin collections and globals\n const subscribersCollection = createSubscribersCollection(config)\n const settingsGlobal = createNewsletterSettingsGlobal(config)\n\n // Build collections array\n let collections = [...(incomingConfig.collections || []), subscribersCollection]\n\n // Add broadcast management collections if enabled\n if (config.features?.newsletterManagement?.enabled) {\n const channelsCollection = createChannelsCollection(config)\n const broadcastsCollection = createBroadcastsCollection(config)\n collections.push(channelsCollection, broadcastsCollection)\n }\n\n // Extend collections with newsletter scheduling fields if enabled\n if (config.features?.newsletterScheduling?.enabled) {\n const targetCollections = config.features.newsletterScheduling.collections || 'articles'\n const collectionsToExtend = Array.isArray(targetCollections) ? targetCollections : [targetCollections]\n const schedulingFields = createNewsletterSchedulingFields(config)\n \n collections = collections.map(collection => {\n if (collectionsToExtend.includes(collection.slug)) {\n return {\n ...collection,\n fields: [\n ...collection.fields,\n ...schedulingFields,\n ],\n }\n }\n return collection\n })\n }\n\n // Create API endpoints\n const endpoints = createNewsletterEndpoints(config)\n\n // Create sync job if enabled\n const syncJob = config.features?.unsubscribeSync?.enabled ? createUnsubscribeSyncJob(config) : null\n\n // Build the modified config\n const modifiedConfig: Config = {\n ...incomingConfig,\n collections,\n globals: [\n ...(incomingConfig.globals || []),\n settingsGlobal,\n ],\n endpoints: [\n ...(incomingConfig.endpoints || []),\n ...endpoints,\n ],\n jobs: syncJob ? {\n ...(incomingConfig.jobs || {}),\n tasks: [\n ...(incomingConfig.jobs?.tasks || []),\n syncJob,\n ],\n // Add cron schedule if specified\n autoRun: config.features?.unsubscribeSync?.schedule ? (\n Array.isArray(incomingConfig.jobs?.autoRun) \n ? [...incomingConfig.jobs.autoRun, {\n cron: config.features.unsubscribeSync.schedule,\n queue: 'newsletter-sync',\n limit: 100,\n }]\n : typeof incomingConfig.jobs?.autoRun === 'function'\n ? async (payload: any) => {\n const autoRunFn = incomingConfig.jobs!.autoRun as (payload: any) => any[] | Promise<any[]>\n const existingConfigs = await autoRunFn(payload)\n return [...existingConfigs, {\n cron: config.features!.unsubscribeSync!.schedule,\n queue: 'newsletter-sync',\n limit: 100,\n }]\n }\n : [{\n cron: config.features!.unsubscribeSync!.schedule,\n queue: 'newsletter-sync',\n limit: 100,\n }]\n ) : incomingConfig.jobs?.autoRun,\n } : incomingConfig.jobs,\n onInit: async (payload) => {\n // Initialize email service\n try {\n // Get settings from global\n const settings = await payload.findGlobal({\n slug: config.settingsSlug || 'newsletter-settings',\n })\n\n let emailServiceConfig: any\n \n if (settings) {\n emailServiceConfig = {\n provider: settings.provider || config.providers.default,\n fromAddress: settings.fromAddress || config.providers.resend?.fromAddress || config.providers.broadcast?.fromAddress || 'noreply@example.com',\n fromName: settings.fromName || config.providers.resend?.fromName || config.providers.broadcast?.fromName || 'Newsletter',\n replyTo: settings.replyTo,\n resend: settings.provider === 'resend' ? {\n apiKey: settings.resendSettings?.apiKey || config.providers.resend?.apiKey || '',\n audienceIds: settings.resendSettings?.audienceIds?.reduce((acc: any, item: any) => {\n acc[item.locale] = {\n production: item.production,\n development: item.development,\n }\n return acc\n }, {}) || config.providers.resend?.audienceIds,\n } : config.providers.resend,\n broadcast: settings.provider === 'broadcast' ? {\n apiUrl: settings.broadcastSettings?.apiUrl || config.providers.broadcast?.apiUrl || '',\n tokens: {\n production: settings.broadcastSettings?.productionToken || config.providers.broadcast?.tokens.production,\n development: settings.broadcastSettings?.developmentToken || config.providers.broadcast?.tokens.development,\n },\n } : config.providers.broadcast,\n }\n } else {\n // Use config defaults\n emailServiceConfig = {\n provider: config.providers.default,\n fromAddress: config.providers.resend?.fromAddress || config.providers.broadcast?.fromAddress || 'noreply@example.com',\n fromName: config.providers.resend?.fromName || config.providers.broadcast?.fromName || 'Newsletter',\n resend: config.providers.resend,\n broadcast: config.providers.broadcast,\n }\n }\n\n (payload as any).newsletterEmailService = createEmailService(emailServiceConfig)\n\n console.warn('Newsletter plugin initialized with', (payload as any).newsletterEmailService.getProvider(), 'provider')\n \n // Initialize broadcast management provider if enabled\n if (config.features?.newsletterManagement?.enabled) {\n try {\n // Use custom provider if provided\n let broadcastProvider: BroadcastProvider\n \n if (config.features.newsletterManagement.provider) {\n broadcastProvider = config.features.newsletterManagement.provider\n } else {\n // Create provider based on email service config\n const providerType = emailServiceConfig.provider || config.providers.default\n \n if (providerType === 'broadcast' && emailServiceConfig.broadcast) {\n broadcastProvider = new BroadcastApiProvider(emailServiceConfig.broadcast)\n } else if (providerType === 'resend' && emailServiceConfig.resend) {\n broadcastProvider = new ResendBroadcastProvider(emailServiceConfig.resend)\n } else {\n throw new Error(`Unsupported broadcast provider: ${providerType}`)\n }\n }\n \n // Attach broadcast provider to payload instance\n const payloadWithProvider = payload as any\n payloadWithProvider.broadcastProvider = broadcastProvider\n // Legacy support\n payloadWithProvider.newsletterProvider = broadcastProvider\n \n console.warn('Broadcast management initialized with', broadcastProvider.name, 'provider')\n } catch (error) {\n console.error('Failed to initialize broadcast management provider:', error)\n }\n }\n } catch (error) {\n console.error('Failed to initialize newsletter email service:', error)\n }\n\n // Call original onInit if it exists\n if (incomingConfig.onInit) {\n await incomingConfig.onInit(payload)\n }\n },\n }\n\n return modifiedConfig\n}\n\nexport { newsletterPlugin as default }\n\n// Export session utilities\nexport * from './utilities/session'","import type { PayloadRequest } from 'payload'\nimport jwt from 'jsonwebtoken'\n\n// Next.js types - these are optional and only used when Next.js is available\ninterface NextApiRequest {\n cookies?: { [key: string]: string }\n headers?: { [key: string]: string | string[] | undefined }\n [key: string]: any\n}\n\ninterface GetServerSidePropsContext {\n req: {\n cookies?: { [key: string]: string }\n headers?: { [key: string]: string | string[] | undefined }\n [key: string]: any\n }\n [key: string]: any\n}\n\ninterface TokenPayload {\n id: string\n email: string\n type?: string\n iat?: number\n exp?: number\n}\n\n/**\n * Extract token from request cookies\n */\nexport const getTokenFromRequest = (\n req: NextApiRequest | GetServerSidePropsContext['req'] | PayloadRequest\n): string | null => {\n // Handle different request types\n const cookies = (req as any).cookies || (req as any).headers?.cookie\n \n if (!cookies) return null\n \n // Parse cookies if it's a string\n if (typeof cookies === 'string') {\n const parsed = cookies.split(';').reduce((acc, cookie) => {\n const [key, value] = cookie.trim().split('=')\n acc[key] = value\n return acc\n }, {} as Record<string, string>)\n return parsed['newsletter-auth'] || null\n }\n \n // Direct cookie object\n return cookies['newsletter-auth'] || null\n}\n\n/**\n * Verify JWT token\n */\nexport const verifyToken = (\n token: string, \n secret: string\n): TokenPayload | null => {\n try {\n const decoded = jwt.verify(token, secret) as TokenPayload\n return decoded\n } catch {\n return null\n }\n}\n\n/**\n * Get authentication state for server-side rendering\n */\nexport const getServerSideAuth = async (\n context: GetServerSidePropsContext,\n secret?: string\n): Promise<{ subscriber: TokenPayload | null; isAuthenticated: boolean }> => {\n const token = getTokenFromRequest(context.req)\n \n if (!token) {\n return { subscriber: null, isAuthenticated: false }\n }\n \n const payloadSecret = secret || process.env.PAYLOAD_SECRET\n if (!payloadSecret) {\n console.error('No secret provided for token verification')\n return { subscriber: null, isAuthenticated: false }\n }\n \n const decoded = verifyToken(token, payloadSecret)\n \n if (!decoded) {\n return { subscriber: null, isAuthenticated: false }\n }\n \n return {\n subscriber: decoded,\n isAuthenticated: true,\n }\n}\n\n/**\n * Higher-order function for protecting pages\n */\nexport const requireAuth = <P extends { [key: string]: any }>(\n gssp?: (context: GetServerSidePropsContext) => Promise<{ props: P }>\n) => {\n return async (context: GetServerSidePropsContext) => {\n const { isAuthenticated, subscriber } = await getServerSideAuth(context)\n \n if (!isAuthenticated) {\n return {\n redirect: {\n destination: '/auth/signin',\n permanent: false,\n },\n }\n }\n \n // If there's a custom getServerSideProps, run it\n if (gssp) {\n const result = await gssp(context)\n return {\n ...result,\n props: {\n ...result.props,\n subscriber,\n },\n }\n }\n \n // Otherwise just return the subscriber\n return {\n props: {\n subscriber,\n } as any as P,\n }\n }\n}\n\n/**\n * Check if request has valid authentication\n */\nexport const isAuthenticated = (\n req: PayloadRequest | NextApiRequest,\n secret: string\n): boolean => {\n const token = getTokenFromRequest(req)\n if (!token) return false\n \n const decoded = verifyToken(token, secret)\n return !!decoded\n}"],"mappings":"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","names":["init_broadcast","broadcast_exports","Resend","init_broadcast","Body","Button","Container","Head","Hr","Html","Preview","Text","jsx","jsxs","Html","Head","Preview","Body","Container","Text","Button","Hr","jsx","jsx","subscriber","jwt","DOMPurify","styles","BroadcastApiProvider","ResendBroadcastProvider","getProvider","BroadcastApiProvider","ResendBroadcastProvider","init_broadcast","jwt","isAuthenticated"]}