payload-plugin-newsletter
Version:
Complete newsletter management plugin for Payload CMS with subscriber management, magic link authentication, and email service integration
1,026 lines (1,019 loc) • 29.4 kB
TypeScript
import { Field, Block, RichTextField } from 'payload';
/**
* Core types for newsletter management functionality
*/
/**
* Represents a newsletter/broadcast in the system
*/
interface Newsletter {
id: string;
name: string;
subject: string;
preheader?: string;
content: string;
status: NewsletterStatus;
trackOpens: boolean;
trackClicks: boolean;
replyTo?: string;
recipientCount?: number;
sentAt?: Date;
scheduledAt?: Date;
createdAt: Date;
updatedAt: Date;
providerData?: Record<string, any>;
providerId?: string;
providerType?: 'broadcast' | 'resend';
}
/**
* Possible statuses for a newsletter
*/
declare enum NewsletterStatus {
DRAFT = "draft",
SCHEDULED = "scheduled",
SENDING = "sending",
SENT = "sent",
FAILED = "failed",
PAUSED = "paused",
CANCELED = "canceled"
}
/**
* Options for listing newsletters
*/
interface ListNewsletterOptions {
limit?: number;
offset?: number;
status?: NewsletterStatus;
sortBy?: 'createdAt' | 'updatedAt' | 'sentAt' | 'name';
sortOrder?: 'asc' | 'desc';
}
/**
* Response from listing newsletters
*/
interface ListNewsletterResponse<T = Newsletter> {
items: T[];
total: number;
limit: number;
offset: number;
hasMore: boolean;
}
/**
* Input for creating a new newsletter
*/
interface CreateNewsletterInput {
name: string;
subject: string;
preheader?: string;
content: string;
trackOpens?: boolean;
trackClicks?: boolean;
replyTo?: string;
audienceIds?: string[];
}
/**
* Input for updating an existing newsletter
*/
interface UpdateNewsletterInput {
name?: string;
subject?: string;
preheader?: string;
content?: string;
trackOpens?: boolean;
trackClicks?: boolean;
replyTo?: string;
audienceIds?: string[];
}
/**
* Options for sending a newsletter
*/
interface SendNewsletterOptions {
audienceIds?: string[];
testMode?: boolean;
testRecipients?: string[];
}
/**
* Analytics data for a newsletter
*/
interface NewsletterAnalytics {
sent: number;
delivered: number;
opened: number;
clicked: number;
bounced: number;
complained: number;
unsubscribed: number;
deliveryRate?: number;
openRate?: number;
clickRate?: number;
bounceRate?: number;
}
/**
* Capabilities that a newsletter provider supports
*/
interface NewsletterProviderCapabilities {
supportsScheduling: boolean;
supportsSegmentation: boolean;
supportsAnalytics: boolean;
supportsABTesting: boolean;
supportsTemplates: boolean;
supportsPersonalization: boolean;
maxRecipientsPerSend?: number;
editableStatuses: NewsletterStatus[];
supportedContentTypes: ('html' | 'text' | 'react')[];
}
/**
* Error types specific to newsletter operations
*/
declare class NewsletterProviderError extends Error {
code: NewsletterErrorCode;
provider: string;
details?: any | undefined;
constructor(message: string, code: NewsletterErrorCode, provider: string, details?: any | undefined);
}
declare enum NewsletterErrorCode {
NOT_SUPPORTED = "NOT_SUPPORTED",
INVALID_STATUS = "INVALID_STATUS",
PROVIDER_ERROR = "PROVIDER_ERROR",
VALIDATION_ERROR = "VALIDATION_ERROR",
NOT_FOUND = "NOT_FOUND",
PERMISSION_DENIED = "PERMISSION_DENIED",
RATE_LIMITED = "RATE_LIMITED",
CONFIGURATION_ERROR = "CONFIGURATION_ERROR"
}
/**
* Newsletter template for reusable content
*/
interface NewsletterTemplate {
id: string;
name: string;
description?: string;
content: string;
variables?: NewsletterTemplateVariable[];
createdAt: Date;
updatedAt: Date;
}
interface NewsletterTemplateVariable {
name: string;
type: 'text' | 'html' | 'image' | 'url';
defaultValue?: string;
required?: boolean;
}
/**
* Core types for broadcast management functionality
*/
/**
* Represents a broadcast (individual email campaign) in the system
*/
interface Broadcast {
id: string;
name: string;
subject: string;
preheader?: string;
content: string;
sendStatus: BroadcastStatus;
trackOpens: boolean;
trackClicks: boolean;
replyTo?: string;
recipientCount?: number;
sentAt?: Date;
scheduledAt?: Date;
createdAt: Date;
updatedAt: Date;
providerData?: Record<string, any>;
providerId?: string;
providerType?: 'broadcast' | 'resend';
}
/**
* Possible statuses for a broadcast
*/
declare enum BroadcastStatus {
DRAFT = "draft",
SCHEDULED = "scheduled",
SENDING = "sending",
SENT = "sent",
FAILED = "failed",
PAUSED = "paused",
CANCELED = "canceled"
}
/**
* Options for listing broadcasts
*/
interface ListBroadcastOptions {
limit?: number;
offset?: number;
status?: BroadcastStatus;
sortBy?: 'createdAt' | 'updatedAt' | 'sentAt' | 'name';
sortOrder?: 'asc' | 'desc';
}
/**
* Response from listing broadcasts
*/
interface ListBroadcastResponse<T = Broadcast> {
items: T[];
total: number;
limit: number;
offset: number;
hasMore: boolean;
}
/**
* Input for creating a new broadcast
*/
interface CreateBroadcastInput {
name: string;
subject: string;
preheader?: string;
content: string;
trackOpens?: boolean;
trackClicks?: boolean;
replyTo?: string;
audienceIds?: string[];
}
/**
* Input for updating an existing broadcast
*/
interface UpdateBroadcastInput {
name?: string;
subject?: string;
preheader?: string;
content?: string;
trackOpens?: boolean;
trackClicks?: boolean;
replyTo?: string;
audienceIds?: string[];
}
/**
* Options for sending a broadcast
*/
interface SendBroadcastOptions {
audienceIds?: string[];
testMode?: boolean;
testRecipients?: string[];
}
/**
* Analytics data for a broadcast
*/
interface BroadcastAnalytics {
sent: number;
delivered: number;
opened: number;
clicked: number;
bounced: number;
complained: number;
unsubscribed: number;
deliveryRate?: number;
openRate?: number;
clickRate?: number;
bounceRate?: number;
}
/**
* Capabilities that a broadcast provider supports
*/
interface BroadcastProviderCapabilities {
supportsScheduling: boolean;
supportsSegmentation: boolean;
supportsAnalytics: boolean;
supportsABTesting: boolean;
supportsTemplates: boolean;
supportsPersonalization: boolean;
maxRecipientsPerSend?: number;
editableStatuses: BroadcastStatus[];
supportedContentTypes: ('html' | 'text' | 'react')[];
supportsMultipleChannels: boolean;
supportsChannelSegmentation: boolean;
}
/**
* Error types specific to broadcast operations
*/
declare class BroadcastProviderError extends Error {
code: BroadcastErrorCode;
provider: string;
details?: any | undefined;
constructor(message: string, code: BroadcastErrorCode, provider: string, details?: any | undefined);
}
declare enum BroadcastErrorCode {
NOT_SUPPORTED = "NOT_SUPPORTED",
INVALID_STATUS = "INVALID_STATUS",
PROVIDER_ERROR = "PROVIDER_ERROR",
VALIDATION_ERROR = "VALIDATION_ERROR",
NOT_FOUND = "NOT_FOUND",
PERMISSION_DENIED = "PERMISSION_DENIED",
RATE_LIMITED = "RATE_LIMITED",
CONFIGURATION_ERROR = "CONFIGURATION_ERROR"
}
/**
* Broadcast template for reusable content
*/
interface BroadcastTemplate {
id: string;
name: string;
description?: string;
content: string;
variables?: BroadcastTemplateVariable[];
createdAt: Date;
updatedAt: Date;
}
interface BroadcastTemplateVariable {
name: string;
type: 'text' | 'html' | 'image' | 'url';
defaultValue?: string;
required?: boolean;
}
/**
* Provider interfaces for broadcast management
*/
/**
* Main interface for broadcast providers
*/
interface BroadcastProvider {
/**
* Get the provider name
*/
readonly name: string;
/**
* List broadcasts with pagination
*/
list(options?: ListBroadcastOptions): Promise<ListBroadcastResponse<Broadcast>>;
/**
* Get a specific broadcast by ID
*/
get(id: string): Promise<Broadcast>;
/**
* Create a new broadcast
*/
create(data: CreateBroadcastInput): Promise<Broadcast>;
/**
* Update an existing broadcast
*/
update(id: string, data: UpdateBroadcastInput): Promise<Broadcast>;
/**
* Delete a broadcast
*/
delete(id: string): Promise<void>;
/**
* Send a broadcast immediately or to test recipients
*/
send(id: string, options?: SendBroadcastOptions): Promise<Broadcast>;
/**
* Schedule a broadcast for future sending
*/
schedule(id: string, scheduledAt: Date): Promise<Broadcast>;
/**
* Cancel a scheduled broadcast
*/
cancelSchedule(id: string): Promise<Broadcast>;
/**
* Get analytics for a broadcast
*/
getAnalytics(id: string): Promise<BroadcastAnalytics>;
/**
* Get provider capabilities
*/
getCapabilities(): BroadcastProviderCapabilities;
/**
* Validate that the provider is properly configured
*/
validateConfiguration(): Promise<boolean>;
}
/**
* Legacy newsletter provider interface for backwards compatibility
* @deprecated Use BroadcastProvider instead
*/
interface NewsletterProvider {
/**
* Get the provider name
*/
readonly name: string;
/**
* List newsletters with pagination
*/
list(options?: ListNewsletterOptions): Promise<ListNewsletterResponse<Newsletter>>;
/**
* Get a specific newsletter by ID
*/
get(id: string): Promise<Newsletter>;
/**
* Create a new newsletter
*/
create(data: CreateNewsletterInput): Promise<Newsletter>;
/**
* Update an existing newsletter
*/
update(id: string, data: UpdateNewsletterInput): Promise<Newsletter>;
/**
* Delete a newsletter
*/
delete(id: string): Promise<void>;
/**
* Send a newsletter immediately or to test recipients
*/
send(id: string, options?: SendNewsletterOptions): Promise<Newsletter>;
/**
* Schedule a newsletter for future sending
*/
schedule(id: string, scheduledAt: Date): Promise<Newsletter>;
/**
* Cancel a scheduled newsletter
*/
cancelSchedule(id: string): Promise<Newsletter>;
/**
* Get analytics for a newsletter
*/
getAnalytics(id: string): Promise<NewsletterAnalytics>;
/**
* Get provider capabilities
*/
getCapabilities(): NewsletterProviderCapabilities;
/**
* Validate that the provider is properly configured
*/
validateConfiguration(): Promise<boolean>;
}
/**
* Base abstract class for broadcast providers
*/
declare abstract class BaseBroadcastProvider implements BroadcastProvider {
protected config: any;
abstract readonly name: string;
constructor(config: any);
abstract list(options?: ListBroadcastOptions): Promise<ListBroadcastResponse<Broadcast>>;
abstract get(id: string): Promise<Broadcast>;
abstract create(data: CreateBroadcastInput): Promise<Broadcast>;
abstract update(id: string, data: UpdateBroadcastInput): Promise<Broadcast>;
abstract delete(id: string): Promise<void>;
abstract send(id: string, options?: SendBroadcastOptions): Promise<Broadcast>;
abstract getCapabilities(): BroadcastProviderCapabilities;
abstract validateConfiguration(): Promise<boolean>;
/**
* Schedule a broadcast - default implementation throws not supported
*/
schedule(_id: string, _scheduledAt: Date): Promise<Broadcast>;
/**
* Cancel scheduled broadcast - default implementation throws not supported
*/
cancelSchedule(_id: string): Promise<Broadcast>;
/**
* Get analytics - default implementation returns zeros
*/
getAnalytics(_id: string): Promise<BroadcastAnalytics>;
/**
* Helper method to validate required fields
*/
protected validateRequiredFields(data: any, fields: string[]): void;
/**
* Helper method to check if a status transition is allowed
*/
protected canEditInStatus(status: BroadcastStatus): boolean;
/**
* Helper to build pagination response
*/
protected buildListResponse<T>(items: T[], total: number, options?: ListBroadcastOptions): ListBroadcastResponse<T>;
}
/**
* Base abstract class for newsletter providers
* @deprecated Use BaseBroadcastProvider instead
*/
declare abstract class BaseNewsletterProvider implements NewsletterProvider {
protected config: any;
abstract readonly name: string;
constructor(config: any);
abstract list(options?: ListNewsletterOptions): Promise<ListNewsletterResponse<Newsletter>>;
abstract get(id: string): Promise<Newsletter>;
abstract create(data: CreateNewsletterInput): Promise<Newsletter>;
abstract update(id: string, data: UpdateNewsletterInput): Promise<Newsletter>;
abstract delete(id: string): Promise<void>;
abstract send(id: string, options?: SendNewsletterOptions): Promise<Newsletter>;
abstract getCapabilities(): NewsletterProviderCapabilities;
abstract validateConfiguration(): Promise<boolean>;
/**
* Schedule a newsletter - default implementation throws not supported
*/
schedule(_id: string, _scheduledAt: Date): Promise<Newsletter>;
/**
* Cancel scheduled newsletter - default implementation throws not supported
*/
cancelSchedule(_id: string): Promise<Newsletter>;
/**
* Get analytics - default implementation returns zeros
*/
getAnalytics(_id: string): Promise<NewsletterAnalytics>;
/**
* Helper method to validate required fields
*/
protected validateRequiredFields(data: any, fields: string[]): void;
/**
* Helper method to check if a status transition is allowed
*/
protected canEditInStatus(status: NewsletterStatus): boolean;
/**
* Helper to build pagination response
*/
protected buildListResponse<T>(items: T[], total: number, options?: ListNewsletterOptions): ListNewsletterResponse<T>;
}
interface EmailWrapperOptions {
preheader?: string;
subject?: string;
documentData?: Record<string, any>;
}
type CustomEmailWrapper = (content: string, options?: EmailWrapperOptions) => string | Promise<string>;
interface BroadcastCustomizations {
additionalFields?: Field[];
customBlocks?: Block[];
fieldOverrides?: {
content?: (defaultField: RichTextField) => RichTextField;
};
/**
* Custom block email converter
* @param node - The block node from Lexical editor state
* @param mediaUrl - Base URL for media files
* @returns Promise<string> - The email-safe HTML for the block
*/
customBlockConverter?: (node: any, mediaUrl?: string) => Promise<string>;
/**
* Fields to populate in custom blocks before email conversion
* Can be an array of field names or a function that returns field names based on block type
* This is useful for upload fields that need to be populated with full media objects
*
* @example
* // Array of field names to always populate
* populateFields: ['bannerImage', 'sponsorLogo']
*
* @example
* // Function to return fields based on block type
* populateFields: (blockType) => {
* if (blockType === 'newsletter-hero') return ['bannerImage', 'sponsorLogo']
* if (blockType === 'content-section') return ['featuredImage']
* return []
* }
*/
populateFields?: string[] | ((blockType: string) => string[]);
/**
* Email preview customization options
*/
emailPreview?: {
/**
* Whether to wrap preview content in default email template
* @default true
*/
wrapInTemplate?: boolean;
/**
* Custom wrapper function for preview content
* Receives the converted HTML and should return wrapped HTML
*/
customWrapper?: (content: string, options?: EmailWrapperOptions) => string | Promise<string>;
/**
* Custom preview component to replace the default one entirely
* If provided, this component will be used instead of the default EmailPreview
*/
customPreviewComponent?: string;
};
}
interface NewsletterPluginConfig {
/**
* Enable or disable the plugin
* @default true
*/
enabled?: boolean;
/**
* Slug for the subscribers collection
* @default 'subscribers'
*/
subscribersSlug?: string;
/**
* Slug for the newsletter settings global
* @default 'newsletter-settings'
*/
settingsSlug?: string;
/**
* Authentication configuration for magic links
*/
auth?: {
/**
* Enable magic link authentication
* @default true
*/
enabled?: boolean;
/**
* Token expiration time
* @default '7d'
*/
tokenExpiration?: string;
/**
* Path where magic link redirects
* @default '/newsletter/verify'
*/
magicLinkPath?: string;
/**
* Allow unsubscribed users to sign in
* @default false
*/
allowUnsubscribedSignin?: boolean;
/**
* Allow unsubscribed users to resubscribe
* @default false
*/
allowResubscribe?: boolean;
};
/**
* Access control configuration
*/
access?: {
/**
* Custom function to determine if a user is an admin
* @param user - The authenticated user object
* @returns true if the user should have admin access
*/
isAdmin?: (user: any) => boolean;
};
/**
* Email provider configuration
*/
providers: {
/**
* Default provider to use
*/
default: 'resend' | 'broadcast' | string;
/**
* Resend provider configuration
*/
resend?: ResendProviderConfig;
/**
* Broadcast provider configuration
*/
broadcast?: BroadcastProviderConfig;
};
/**
* Field customization options
*/
fields?: {
/**
* Override default fields
*/
overrides?: (args: {
defaultFields: Field[];
}) => Field[];
/**
* Additional custom fields
*/
additional?: Field[];
};
/**
* Email template components
*/
templates?: {
/**
* Welcome email template
*/
welcome?: React.ComponentType<WelcomeEmailProps>;
/**
* Magic link email template
*/
magicLink?: React.ComponentType<MagicLinkEmailProps>;
};
/**
* Plugin hooks
*/
hooks?: {
beforeSubscribe?: (args: BeforeSubscribeArgs) => void | Promise<void>;
afterSubscribe?: (args: AfterSubscribeArgs) => void | Promise<void>;
beforeUnsubscribe?: (args: BeforeUnsubscribeArgs) => void | Promise<void>;
afterUnsubscribe?: (args: AfterUnsubscribeArgs) => void | Promise<void>;
};
/**
* UI component overrides
*/
components?: {
signupForm?: React.ComponentType<SignupFormProps>;
preferencesForm?: React.ComponentType<PreferencesFormProps>;
};
/**
* Feature flags
*/
features?: {
/**
* Lead magnet configuration
*/
leadMagnets?: {
enabled?: boolean;
collection?: string;
};
/**
* Post-signup survey configuration
*/
surveys?: {
enabled?: boolean;
questions?: SurveyQuestion[];
};
/**
* UTM tracking configuration
*/
utmTracking?: {
enabled?: boolean;
fields?: string[];
};
/**
* Newsletter scheduling configuration
*/
newsletterScheduling?: {
enabled?: boolean;
/**
* Collections to add newsletter fields to
* Can be a string for single collection or array for multiple
* @example 'articles' or ['articles', 'posts', 'updates']
*/
collections?: string | string[];
/**
* Field configuration
*/
fields?: {
/**
* Group name for newsletter fields
* @default 'newsletterScheduling'
*/
groupName?: string;
/**
* Rich text field name to use for content
* @default 'content'
*/
contentField?: string;
/**
* Whether to create a markdown companion field
* @default true
*/
createMarkdownField?: boolean;
};
};
/**
* Newsletter management configuration
*/
newsletterManagement?: {
/**
* Enable newsletter management features
* @default false
*/
enabled?: boolean;
/**
* Collection names for broadcast management
*/
collections?: {
/**
* Broadcasts collection slug
* @default 'broadcasts'
*/
broadcasts?: string;
};
/**
* Optional: Custom broadcast provider implementation
* If not provided, will use the default email provider
*/
provider?: BroadcastProvider;
};
};
/**
* Internationalization configuration
*/
i18n?: {
defaultLocale?: string;
locales?: string[];
};
/**
* Custom email templates
*/
customTemplates?: {
[key: string]: React.ComponentType<any>;
};
/**
* Customization options for plugin collections
*/
customizations?: {
broadcasts?: BroadcastCustomizations;
};
}
interface ResendProviderConfig {
apiKey: string;
fromEmail?: string;
fromAddress?: string;
fromName?: string;
replyTo?: string;
audienceIds?: {
[locale: string]: {
production?: string;
development?: string;
};
};
}
interface BroadcastProviderConfig {
apiUrl: string;
token: string;
fromEmail?: string;
fromAddress?: string;
fromName?: string;
replyTo?: string;
}
interface EmailProvider {
send(params: SendEmailParams): Promise<void>;
addContact(contact: Subscriber): Promise<void>;
updateContact(contact: Subscriber): Promise<void>;
removeContact(email: string): Promise<void>;
}
interface SendEmailParams {
to: string | string[];
subject: string;
html?: string;
text?: string;
react?: React.ReactElement;
}
interface Subscriber {
id: string;
email: string;
name?: string;
locale?: string;
subscriptionStatus: 'active' | 'unsubscribed' | 'pending';
emailPreferences?: {
newsletter?: boolean;
announcements?: boolean;
[key: string]: boolean | undefined;
};
source?: string;
importedFromProvider?: boolean;
utmParameters?: {
source?: string;
medium?: string;
campaign?: string;
content?: string;
term?: string;
};
signupMetadata?: {
ipAddress?: string;
userAgent?: string;
referrer?: string;
signupPage?: string;
};
leadMagnet?: string;
unsubscribedAt?: string;
magicLinkToken?: string;
magicLinkTokenExpiry?: string;
createdAt: string;
updatedAt: string;
}
interface WelcomeEmailProps {
subscriber: Subscriber;
unsubscribeUrl: string;
preferencesUrl: string;
}
interface MagicLinkEmailProps {
magicLinkUrl: string;
subscriber: Subscriber;
}
interface SignupFormProps {
onSuccess?: (subscriber: Subscriber) => void;
onError?: (error: Error) => void;
showName?: boolean;
showPreferences?: boolean;
leadMagnet?: {
id: string;
title: string;
description?: string;
};
className?: string;
styles?: {
form?: React.CSSProperties;
inputGroup?: React.CSSProperties;
label?: React.CSSProperties;
input?: React.CSSProperties;
button?: React.CSSProperties;
buttonDisabled?: React.CSSProperties;
error?: React.CSSProperties;
success?: React.CSSProperties;
checkbox?: React.CSSProperties;
checkboxInput?: React.CSSProperties;
checkboxLabel?: React.CSSProperties;
};
apiEndpoint?: string;
buttonText?: string;
loadingText?: string;
successMessage?: string;
placeholders?: {
email?: string;
name?: string;
};
labels?: {
email?: string;
name?: string;
newsletter?: string;
announcements?: string;
};
}
interface PreferencesFormProps {
subscriber?: Subscriber;
onSuccess?: (subscriber: Subscriber) => void;
onError?: (error: Error) => void;
className?: string;
styles?: {
container?: React.CSSProperties;
heading?: React.CSSProperties;
form?: React.CSSProperties;
section?: React.CSSProperties;
sectionTitle?: React.CSSProperties;
inputGroup?: React.CSSProperties;
label?: React.CSSProperties;
input?: React.CSSProperties;
select?: React.CSSProperties;
checkbox?: React.CSSProperties;
checkboxInput?: React.CSSProperties;
checkboxLabel?: React.CSSProperties;
buttonGroup?: React.CSSProperties;
button?: React.CSSProperties;
primaryButton?: React.CSSProperties;
secondaryButton?: React.CSSProperties;
dangerButton?: React.CSSProperties;
error?: React.CSSProperties;
success?: React.CSSProperties;
info?: React.CSSProperties;
};
sessionToken?: string;
apiEndpoint?: string;
showUnsubscribe?: boolean;
locales?: string[];
labels?: {
title?: string;
personalInfo?: string;
emailPreferences?: string;
name?: string;
language?: string;
newsletter?: string;
announcements?: string;
saveButton?: string;
unsubscribeButton?: string;
saving?: string;
saved?: string;
unsubscribeConfirm?: string;
};
}
interface BeforeSubscribeArgs {
data: Partial<Subscriber>;
req: any;
}
interface AfterSubscribeArgs {
doc: Subscriber;
req: any;
}
interface BeforeUnsubscribeArgs {
email: string;
req: any;
}
interface AfterUnsubscribeArgs {
doc: Subscriber;
req: any;
}
interface SurveyQuestion {
id: string;
question: string;
type: 'text' | 'select' | 'multiselect' | 'radio';
options?: string[];
required?: boolean;
}
interface SubscribeRequestData {
email: string;
name?: string;
source?: string;
preferences?: {
[key: string]: boolean;
};
leadMagnet?: string;
surveyResponses?: {
[key: string]: string | string[];
};
metadata?: {
locale?: string;
signupPage?: string;
[key: string]: unknown;
};
}
interface UnsubscribeRequestData {
email?: string;
token?: string;
}
interface VerifyMagicLinkRequestData {
token: string;
}
interface SigninRequestData {
email: string;
}
interface UpdatePreferencesRequestData {
name?: string;
locale?: string;
emailPreferences?: {
[key: string]: boolean;
};
}
interface ExtendedPayloadRequest extends Request {
payload: any;
data?: unknown;
ip?: string;
connection?: {
remoteAddress?: string;
};
cookies?: {
[key: string]: string;
};
}
export { type AfterSubscribeArgs, type AfterUnsubscribeArgs, BaseBroadcastProvider, BaseNewsletterProvider, type BeforeSubscribeArgs, type BeforeUnsubscribeArgs, type Broadcast, type BroadcastAnalytics, type BroadcastCustomizations, BroadcastErrorCode, type BroadcastProvider, type BroadcastProviderCapabilities, type BroadcastProviderConfig, BroadcastProviderError, BroadcastStatus, type BroadcastTemplate, type BroadcastTemplateVariable, type CreateBroadcastInput, type CreateNewsletterInput, type CustomEmailWrapper, type EmailProvider, type EmailWrapperOptions, type ExtendedPayloadRequest, type ListBroadcastOptions, type ListBroadcastResponse, type ListNewsletterOptions, type ListNewsletterResponse, type MagicLinkEmailProps, type Newsletter, type NewsletterAnalytics, NewsletterErrorCode, type NewsletterPluginConfig, type NewsletterProvider, type NewsletterProviderCapabilities, NewsletterProviderError, NewsletterStatus, type NewsletterTemplate, type NewsletterTemplateVariable, type PreferencesFormProps, type ResendProviderConfig, type SendBroadcastOptions, type SendEmailParams, type SendNewsletterOptions, type SigninRequestData, type SignupFormProps, type SubscribeRequestData, type Subscriber, type SurveyQuestion, type UnsubscribeRequestData, type UpdateBroadcastInput, type UpdateNewsletterInput, type UpdatePreferencesRequestData, type VerifyMagicLinkRequestData, type WelcomeEmailProps };