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.
87 lines (53 loc) • 2.34 kB
Markdown
# Architecture Overview - waitlist-mailer v2.0
## Design Principles
This library follows **clean architecture** principles with focus on:
1. **Modularity**: Each component has a single responsibility.
2. **Dependency Injection**: Components receive their dependencies.
3. **Adapter Pattern**: Storage and mail are pluggable interfaces.
4. **Event-Driven**: Rich event system for integrations.
5. **Type Safety**: Full TypeScript support with generics.
## Project Structure
```
lib/
├── index.ts # Main export point
├── types.ts # Core interfaces and types
├── core/
│ └── WaitlistManager.ts # Main orchestrator class
├── adapters/
│ ├── storage/
│ │ ├── MemoryStorage.ts # In-memory adapter
│ │ ├── MongooseStorage.ts # MongoDB adapter
│ │ └── SequelizeStorage.ts # SQL adapter
│ └── mail/
│ ├── NodemailerProvider.ts # SMTP mail provider
│ └── ConsoleMailProvider.ts # Console logger
└── index.test.ts # Comprehensive test suite
```
## Core Components
### 1. `types.ts` - The Contract
Defines all interfaces that adapters must implement. This ensures that any new storage or mail provider adheres to a strict contract, making the system easily extensible.
### 2. `core/WaitlistManager.ts` - The Orchestrator
The main business logic class that:
- Orchestrates storage and mail providers.
- Handles email validation.
- Emits events for each operation.
- Provides a clean async API.
- Defaults to `MemoryStorage` for ease of use.
### 3. Adapters
**Storage Adapters:**
- `MemoryStorage`: In-memory map (default).
- `MongooseStorage`: MongoDB integration.
- `SequelizeStorage`: SQL (Postgres, MySQL, SQLite) integration.
**Mail Adapters:**
- `NodemailerProvider`: SMTP sending.
- `ConsoleMailProvider`: Debugging output.
## Dependency Flow
```
User Code
↓
WaitlistManager
├── depends on → StorageProvider (interface)
├── depends on → MailProvider (interface)
└── emits → Events
```
**Key Takeaway**: WaitlistManager only knows about interfaces, not concrete classes. This allows users to swap implementations without modifying the core library code.