waitlist-mailer
Version:
Modern, modular TypeScript library for managing waitlists with pluggable storage and mail providers. Supports MongoDB, SQL databases, and custom adapters with zero required dependencies for basic usage.
187 lines (183 loc) • 6.43 kB
TypeScript
import { EventEmitter } from 'events';
import { WaitlistManagerConfig, JoinResult, WaitlistEntry, EmailContext, SearchOptions } from '../types.js';
/**
* @fileoverview WaitlistManager - The core orchestrator for the waitlist-mailer library.
* * This class implements clean architecture principles:
* - Dependency Injection: Storage and mail providers are injected
* - Single Responsibility: Only orchestrates business logic
* - Open/Closed: Extensible through adapters without modification
* - Interface Segregation: Depends on interfaces, not concrete implementations
*/
/**
* Main WaitlistManager class.
* Orchestrates storage and mail providers to manage a waitlist.
* * @template T - Metadata type for custom fields
* * @example
* ```typescript
* // Default memory storage
* const manager = new WaitlistManager({ companyName: 'My App' });
* * // Custom storage and mailer
* const manager = new WaitlistManager({
* storage: new MongooseStorage(...),
* mailer: new NodemailerProvider(...)
* });
* ```
*/
declare class WaitlistManager<T = any> extends EventEmitter {
private storage;
private mailer?;
private companyName;
private initialized;
/**
* Create a new WaitlistManager instance.
* @param config - Configuration object with storage, optional mailer, etc.
*/
constructor(config: WaitlistManagerConfig<T>);
/**
* Initialize connections to storage and mail providers.
* @returns Promise that resolves when initialization is complete
*/
connect(): Promise<void>;
/**
* Wait for the manager to be fully initialized.
* @returns Promise that resolves when initialized
*/
waitForInitialization(): Promise<void>;
/**
* Check if the manager is initialized.
* @returns true if initialized
*/
isInitialized(): boolean;
/**
* Add an email to the waitlist.
* * Validates the email and checks for duplicates before adding.
* Optionally sends a confirmation email.
* * @param email - The email address to add
* @param metadata - Optional custom metadata
* @returns Result object with success status and message
* * @example
* ```typescript
* const result = await manager.join('user@example.com', {
* name: 'Alice',
* referralSource: 'ProductHunt'
* });
* * if (result.success) {
* console.log('User added:', result.email);
* }
* ```
*/
join(email: string, metadata?: T): Promise<JoinResult>;
/**
* Remove an email from the waitlist.
* @param email - The email address to remove
* @returns true if the email was found and removed
*/
leave(email: string): Promise<boolean>;
/**
* Check if an email is in the waitlist.
* @param email - The email to check
* @returns true if the email exists
*/
has(email: string): Promise<boolean>;
/**
* Get all waitlist entries.
* @returns Array of WaitlistEntry objects
*/
getAll(): Promise<WaitlistEntry<T>[]>;
/**
* Get count of waitlist entries.
* @returns Number of entries
*/
count(): Promise<number>;
/**
* Clear all entries from the waitlist.
* @returns true if successful
*/
clear(): Promise<boolean>;
/**
* Send a custom email to an address.
* Useful for sending emails to users who aren't on the waitlist.
* * @param email - Recipient email
* @param context - Email context with template variables
* @returns true if sent successfully
*/
sendEmail(email: string, context: EmailContext): Promise<boolean>;
/**
* Send emails to all waitlist members.
* Processes emails concurrently with configurable concurrency limit.
* Uses streaming when available to avoid loading all entries into memory.
*
* @param contextBuilder - Function to build context for each email
* @param concurrency - Maximum concurrent emails to send (1 = sequential, Infinity = all at once)
* Default: 5 for balance between speed and resource usage
* @returns Object with statistics
*
* @example
* ```typescript
* // Send with default concurrency (5 at a time)
* const result = await manager.sendBulkEmails((email) => ({
* subject: 'Welcome!'
* }));
*
* // Send slowly (1 at a time)
* const result = await manager.sendBulkEmails(
* (email) => ({ subject: 'Welcome!' }),
* 1
* );
*
* // Send fast (all at once - use with caution)
* const result = await manager.sendBulkEmails(
* (email) => ({ subject: 'Welcome!' }),
* Infinity
* );
* ```
*/
sendBulkEmails(contextBuilder: (email: string, metadata?: T) => EmailContext, concurrency?: number): Promise<{
sent: number;
failed: number;
total: number;
}>;
/**
* Send bulk emails using streaming to avoid memory issues.
* Processes entries in batches using the storage iterator.
* @private
*/
private sendBulkEmailsWithStreaming;
/**
* Legacy bulk email method that loads all entries into memory.
* Used as fallback when storage doesn't support streaming.
* @private
*/
private sendBulkEmailsLegacy;
/**
* Internal method to send a single bulk email.
* @private
*/
private sendSingleBulkEmail;
/**
* Get entries matching a search pattern.
* Delegates to storage provider for efficient database-level filtering when available.
* Falls back to in-memory filtering if storage doesn't support search.
*
* @param pattern - Pattern to search for (partial email match)
* @param options - Optional search options (limit, offset, caseInsensitive)
* @returns Matching entries
*
* @example
* ```typescript
* // Simple search
* const gmailUsers = await manager.search('gmail.com');
*
* // Paginated search
* const page1 = await manager.search('example', { limit: 10, offset: 0 });
* const page2 = await manager.search('example', { limit: 10, offset: 10 });
* ```
*/
search(pattern: string, options?: SearchOptions): Promise<WaitlistEntry<T>[]>;
/**
* Disconnect from storage and mail providers.
* Should be called before shutting down the application.
*/
disconnect(): Promise<void>;
}
export { WaitlistManager };