@bernierllc/email-sender-manager 1.0.1
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/LICENSE +5 -0
- package/README.md +466 -0
- package/dist/__tests__/manager.test.d.ts +2 -0
- package/dist/__tests__/manager.test.d.ts.map +1 -0
- package/dist/__tests__/manager.test.js +344 -0
- package/dist/__tests__/manager.test.js.map +1 -0
- package/dist/__tests__/mocks/mock-database.d.ts +15 -0
- package/dist/__tests__/mocks/mock-database.d.ts.map +1 -0
- package/dist/__tests__/mocks/mock-database.js +219 -0
- package/dist/__tests__/mocks/mock-database.js.map +1 -0
- package/dist/__tests__/selection/selector.test.d.ts +2 -0
- package/dist/__tests__/selection/selector.test.d.ts.map +1 -0
- package/dist/__tests__/selection/selector.test.js +351 -0
- package/dist/__tests__/selection/selector.test.js.map +1 -0
- package/dist/__tests__/utils/domain-utils.test.d.ts +2 -0
- package/dist/__tests__/utils/domain-utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/domain-utils.test.js +91 -0
- package/dist/__tests__/utils/domain-utils.test.js.map +1 -0
- package/dist/__tests__/utils/validation-utils.test.d.ts +2 -0
- package/dist/__tests__/utils/validation-utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/validation-utils.test.js +117 -0
- package/dist/__tests__/utils/validation-utils.test.js.map +1 -0
- package/dist/database/bootstrap.d.ts +35 -0
- package/dist/database/bootstrap.d.ts.map +1 -0
- package/dist/database/bootstrap.js +183 -0
- package/dist/database/bootstrap.js.map +1 -0
- package/dist/database/schema.d.ts +13 -0
- package/dist/database/schema.d.ts.map +1 -0
- package/dist/database/schema.js +72 -0
- package/dist/database/schema.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +85 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +469 -0
- package/dist/manager.js.map +1 -0
- package/dist/selection/selector.d.ts +27 -0
- package/dist/selection/selector.d.ts.map +1 -0
- package/dist/selection/selector.js +107 -0
- package/dist/selection/selector.js.map +1 -0
- package/dist/types.d.ts +257 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/domain-utils.d.ts +21 -0
- package/dist/utils/domain-utils.d.ts.map +1 -0
- package/dist/utils/domain-utils.js +65 -0
- package/dist/utils/domain-utils.js.map +1 -0
- package/dist/utils/validation-utils.d.ts +23 -0
- package/dist/utils/validation-utils.d.ts.map +1 -0
- package/dist/utils/validation-utils.js +148 -0
- package/dist/utils/validation-utils.js.map +1 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright (c) 2025 Bernier LLC
|
|
2
|
+
|
|
3
|
+
This file is licensed to the client under a limited-use license.
|
|
4
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
5
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
package/README.md
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
# @bernierllc/email-sender-manager
|
|
2
|
+
|
|
3
|
+
Database-backed email sender configuration management with provider verification integration. Manage, verify, and intelligently select email sender configurations for your applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bernierllc/email-sender-manager
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Database-Backed Storage**: Persistent sender configurations with transaction support
|
|
14
|
+
- **Provider Integration**: Verify sender configurations with email providers (SendGrid, Mailgun, etc.)
|
|
15
|
+
- **Smart Sender Selection**: Intelligent sender selection based on domain matching, priority, or round-robin strategies
|
|
16
|
+
- **Bootstrap System**: Automatic database schema creation and default sender seeding
|
|
17
|
+
- **Full TypeScript Support**: Complete type definitions with strict mode compliance
|
|
18
|
+
- **Comprehensive Validation**: Email format validation, domain restrictions, and configuration checks
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { EmailSenderManager } from '@bernierllc/email-sender-manager';
|
|
24
|
+
import type { DatabaseAdapter } from '@bernierllc/email-sender-manager';
|
|
25
|
+
|
|
26
|
+
// Implement your database adapter
|
|
27
|
+
const databaseAdapter: DatabaseAdapter = {
|
|
28
|
+
async execute(query: string, params?: unknown[]): Promise<void> {
|
|
29
|
+
// Your database execute logic
|
|
30
|
+
},
|
|
31
|
+
async query<T = unknown>(query: string, params?: unknown[]): Promise<T[]> {
|
|
32
|
+
// Your database query logic
|
|
33
|
+
},
|
|
34
|
+
async queryOne<T = unknown>(query: string, params?: unknown[]): Promise<T | null> {
|
|
35
|
+
// Your database queryOne logic
|
|
36
|
+
},
|
|
37
|
+
async transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T> {
|
|
38
|
+
// Your transaction logic
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Initialize manager
|
|
43
|
+
const manager = new EmailSenderManager({
|
|
44
|
+
database: databaseAdapter,
|
|
45
|
+
bootstrap: {
|
|
46
|
+
enabled: true,
|
|
47
|
+
createTables: true,
|
|
48
|
+
seedDefaultSenders: true,
|
|
49
|
+
defaultSenders: [
|
|
50
|
+
{
|
|
51
|
+
name: 'Default Sender',
|
|
52
|
+
fromEmail: 'noreply@example.com',
|
|
53
|
+
fromName: 'My App',
|
|
54
|
+
provider: 'sendgrid',
|
|
55
|
+
priority: 1,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
environment: 'production',
|
|
59
|
+
},
|
|
60
|
+
selection: {
|
|
61
|
+
strategy: 'domain_match',
|
|
62
|
+
fallbackToDefault: true,
|
|
63
|
+
domainMatchingRules: [],
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Bootstrap database
|
|
68
|
+
await manager.bootstrapDatabase();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Core Concepts
|
|
72
|
+
|
|
73
|
+
### Sender Configuration
|
|
74
|
+
|
|
75
|
+
A sender configuration represents an email address that can send emails through your application:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
interface SenderConfiguration {
|
|
79
|
+
id: string;
|
|
80
|
+
name: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
fromEmail: string;
|
|
83
|
+
fromName: string;
|
|
84
|
+
replyToEmail?: string;
|
|
85
|
+
replyToName?: string;
|
|
86
|
+
provider: string;
|
|
87
|
+
providerSenderId?: string;
|
|
88
|
+
providerMetadata?: Record<string, unknown>;
|
|
89
|
+
isVerified: boolean;
|
|
90
|
+
verificationStatus: 'pending' | 'verified' | 'failed' | 'expired';
|
|
91
|
+
lastVerifiedAt?: Date;
|
|
92
|
+
isDefault: boolean;
|
|
93
|
+
isActive: boolean;
|
|
94
|
+
priority: number; // Lower = higher priority
|
|
95
|
+
allowedDomains?: string[];
|
|
96
|
+
domain: string;
|
|
97
|
+
createdAt: Date;
|
|
98
|
+
updatedAt: Date;
|
|
99
|
+
createdBy: string;
|
|
100
|
+
lastModifiedBy: string;
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Provider Integration
|
|
105
|
+
|
|
106
|
+
Providers verify sender configurations with email service providers:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
interface SenderProviderPlugin {
|
|
110
|
+
readonly providerId: string;
|
|
111
|
+
readonly name: string;
|
|
112
|
+
validateSender(email: string): Promise<ProviderValidationResult>;
|
|
113
|
+
getVerifiedSenders(): Promise<ProviderSender[]>;
|
|
114
|
+
syncSender(sender: SenderConfiguration): Promise<SyncResult>;
|
|
115
|
+
getCapabilities(): string[];
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Usage Examples
|
|
120
|
+
|
|
121
|
+
### Creating Senders
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Create a new sender
|
|
125
|
+
const sender = await manager.createSender({
|
|
126
|
+
name: 'Marketing Team',
|
|
127
|
+
fromEmail: 'marketing@example.com',
|
|
128
|
+
fromName: 'Marketing Department',
|
|
129
|
+
replyToEmail: 'support@example.com',
|
|
130
|
+
provider: 'sendgrid',
|
|
131
|
+
priority: 10,
|
|
132
|
+
allowedDomains: ['example.com', '*.example.com'],
|
|
133
|
+
createdBy: 'admin-user',
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
console.log(`Created sender: ${sender.id}`);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Updating Senders
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Update sender configuration
|
|
143
|
+
const updated = await manager.updateSender(sender.id, {
|
|
144
|
+
name: 'Updated Name',
|
|
145
|
+
priority: 5,
|
|
146
|
+
isActive: true,
|
|
147
|
+
lastModifiedBy: 'admin-user',
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Listing Senders
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// List all active senders
|
|
155
|
+
const activeSenders = await manager.listSenders({
|
|
156
|
+
isActive: true,
|
|
157
|
+
orderBy: 'priority',
|
|
158
|
+
orderDirection: 'asc',
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// List verified senders for a specific provider
|
|
162
|
+
const verifiedSenders = await manager.listSenders({
|
|
163
|
+
provider: 'sendgrid',
|
|
164
|
+
isVerified: true,
|
|
165
|
+
limit: 10,
|
|
166
|
+
offset: 0,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Paginate through results
|
|
170
|
+
console.log(`Total: ${activeSenders.total}, Showing: ${activeSenders.items.length}`);
|
|
171
|
+
console.log(`Has more: ${activeSenders.hasMore}`);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Sender Selection
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// Select best sender for an email
|
|
178
|
+
const bestSender = await manager.selectBestSender('user@example.com', {
|
|
179
|
+
strategy: 'domain_match', // or 'priority' or 'round_robin'
|
|
180
|
+
allowUnverified: false,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
if (bestSender) {
|
|
184
|
+
console.log(`Using sender: ${bestSender.fromEmail} (priority: ${bestSender.priority})`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Select sender for specific provider
|
|
188
|
+
const sendgridSender = await manager.selectBestSender('user@example.com', {
|
|
189
|
+
provider: 'sendgrid',
|
|
190
|
+
strategy: 'priority',
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Provider Verification
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import type { SenderProviderPlugin } from '@bernierllc/email-sender-manager';
|
|
198
|
+
|
|
199
|
+
// Implement a provider plugin
|
|
200
|
+
class SendGridProvider implements SenderProviderPlugin {
|
|
201
|
+
readonly providerId = 'sendgrid';
|
|
202
|
+
readonly name = 'SendGrid';
|
|
203
|
+
|
|
204
|
+
constructor(private apiKey: string) {}
|
|
205
|
+
|
|
206
|
+
async validateSender(email: string): Promise<ProviderValidationResult> {
|
|
207
|
+
// Call SendGrid API to verify sender
|
|
208
|
+
const verifiedSenders = await this.getVerifiedSenders();
|
|
209
|
+
const match = verifiedSenders.find((s) => s.email === email);
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
isVerified: Boolean(match?.isVerified),
|
|
213
|
+
verificationStatus: match?.verificationStatus || 'not_found',
|
|
214
|
+
lastChecked: new Date(),
|
|
215
|
+
metadata: { providerId: match?.id },
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async getVerifiedSenders(): Promise<ProviderSender[]> {
|
|
220
|
+
// Fetch from SendGrid API
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async syncSender(sender: SenderConfiguration): Promise<SyncResult> {
|
|
225
|
+
// Sync with SendGrid
|
|
226
|
+
return { success: true, senderId: sender.id, synced: true };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
getCapabilities(): string[] {
|
|
230
|
+
return ['verification', 'sync'];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Register provider
|
|
235
|
+
const provider = new SendGridProvider(process.env.SENDGRID_API_KEY!);
|
|
236
|
+
await manager.registerProvider(provider);
|
|
237
|
+
|
|
238
|
+
// Verify a sender
|
|
239
|
+
const verification = await manager.verifySender(sender.id);
|
|
240
|
+
console.log(`Verified: ${verification.isVerified}`);
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Bootstrap Configuration
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const manager = new EmailSenderManager({
|
|
247
|
+
database: databaseAdapter,
|
|
248
|
+
bootstrap: {
|
|
249
|
+
enabled: true,
|
|
250
|
+
createTables: true,
|
|
251
|
+
seedDefaultSenders: true,
|
|
252
|
+
defaultSenders: [
|
|
253
|
+
{
|
|
254
|
+
name: 'Default Sender',
|
|
255
|
+
fromEmail: 'noreply@example.com',
|
|
256
|
+
fromName: 'My Application',
|
|
257
|
+
provider: 'sendgrid',
|
|
258
|
+
priority: 1,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: 'Marketing Sender',
|
|
262
|
+
fromEmail: 'marketing@example.com',
|
|
263
|
+
fromName: 'Marketing Team',
|
|
264
|
+
provider: 'sendgrid',
|
|
265
|
+
priority: 10,
|
|
266
|
+
allowedDomains: ['example.com'],
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
environment: 'production',
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Run bootstrap
|
|
274
|
+
const result = await manager.bootstrapDatabase();
|
|
275
|
+
console.log(result.message);
|
|
276
|
+
// Output: "Bootstrap completed successfully. Tables created: true, Senders seeded: 2"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Selection Strategies
|
|
280
|
+
|
|
281
|
+
### Domain Matching
|
|
282
|
+
|
|
283
|
+
Selects senders based on domain relationships:
|
|
284
|
+
|
|
285
|
+
1. **Exact domain match**: `example.com` sender for `user@example.com`
|
|
286
|
+
2. **Subdomain match**: `example.com` sender for `user@app.example.com`
|
|
287
|
+
3. **Allowed domains**: Senders with `allowedDomains` configuration
|
|
288
|
+
4. **Fallback to priority**: If no domain match found
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
const sender = await manager.selectBestSender('user@app.example.com', {
|
|
292
|
+
strategy: 'domain_match',
|
|
293
|
+
});
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Priority-Based
|
|
297
|
+
|
|
298
|
+
Selects sender with lowest priority number (higher priority):
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
const sender = await manager.selectBestSender('user@example.com', {
|
|
302
|
+
strategy: 'priority',
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Round-Robin
|
|
307
|
+
|
|
308
|
+
Distributes selections evenly across available senders:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const sender = await manager.selectBestSender('user@example.com', {
|
|
312
|
+
strategy: 'round_robin',
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Domain Utilities
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import {
|
|
320
|
+
extractDomain,
|
|
321
|
+
isDomainMatch,
|
|
322
|
+
isValidEmail,
|
|
323
|
+
getParentDomain,
|
|
324
|
+
isSubdomainOf,
|
|
325
|
+
} from '@bernierllc/email-sender-manager';
|
|
326
|
+
|
|
327
|
+
// Extract domain from email
|
|
328
|
+
const domain = extractDomain('user@example.com'); // "example.com"
|
|
329
|
+
|
|
330
|
+
// Check domain matching with wildcards
|
|
331
|
+
const matches = isDomainMatch('app.example.com', '*.example.com'); // true
|
|
332
|
+
|
|
333
|
+
// Validate email format
|
|
334
|
+
const valid = isValidEmail('user@example.com'); // true
|
|
335
|
+
|
|
336
|
+
// Get parent domain
|
|
337
|
+
const parent = getParentDomain('app.example.com'); // "example.com"
|
|
338
|
+
|
|
339
|
+
// Check subdomain relationship
|
|
340
|
+
const isSub = isSubdomainOf('app.example.com', 'example.com'); // true
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Validation
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
import { validateCreateSenderRequest } from '@bernierllc/email-sender-manager';
|
|
347
|
+
|
|
348
|
+
// Validate sender creation request
|
|
349
|
+
const validation = validateCreateSenderRequest({
|
|
350
|
+
name: 'Test Sender',
|
|
351
|
+
fromEmail: 'test@example.com',
|
|
352
|
+
fromName: 'Test',
|
|
353
|
+
provider: 'sendgrid',
|
|
354
|
+
createdBy: 'admin',
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
if (validation.errors.length > 0) {
|
|
358
|
+
console.error('Validation errors:', validation.errors);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (validation.warnings.length > 0) {
|
|
362
|
+
console.warn('Validation warnings:', validation.warnings);
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Database Schema
|
|
367
|
+
|
|
368
|
+
The package automatically creates the following database schema:
|
|
369
|
+
|
|
370
|
+
```sql
|
|
371
|
+
CREATE TABLE IF NOT EXISTS email_senders (
|
|
372
|
+
id VARCHAR(255) PRIMARY KEY,
|
|
373
|
+
name VARCHAR(255) NOT NULL,
|
|
374
|
+
description TEXT,
|
|
375
|
+
from_email VARCHAR(255) NOT NULL UNIQUE,
|
|
376
|
+
from_name VARCHAR(255) NOT NULL,
|
|
377
|
+
reply_to_email VARCHAR(255),
|
|
378
|
+
reply_to_name VARCHAR(255),
|
|
379
|
+
provider VARCHAR(100) NOT NULL,
|
|
380
|
+
provider_sender_id VARCHAR(255),
|
|
381
|
+
provider_metadata JSON,
|
|
382
|
+
is_verified BOOLEAN DEFAULT FALSE,
|
|
383
|
+
verification_status VARCHAR(50) DEFAULT 'pending',
|
|
384
|
+
last_verified_at TIMESTAMP NULL,
|
|
385
|
+
verification_error TEXT,
|
|
386
|
+
is_default BOOLEAN DEFAULT FALSE,
|
|
387
|
+
is_active BOOLEAN DEFAULT TRUE,
|
|
388
|
+
priority INTEGER DEFAULT 100,
|
|
389
|
+
allowed_domains JSON,
|
|
390
|
+
domain VARCHAR(255) NOT NULL,
|
|
391
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
392
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
393
|
+
created_by VARCHAR(255),
|
|
394
|
+
last_modified_by VARCHAR(255),
|
|
395
|
+
INDEX idx_email_senders_from_email (from_email),
|
|
396
|
+
INDEX idx_email_senders_domain (domain),
|
|
397
|
+
INDEX idx_email_senders_provider (provider),
|
|
398
|
+
INDEX idx_email_senders_active (is_active),
|
|
399
|
+
INDEX idx_email_senders_default (is_default),
|
|
400
|
+
INDEX idx_email_senders_priority (priority)
|
|
401
|
+
);
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## API Reference
|
|
405
|
+
|
|
406
|
+
### EmailSenderManager
|
|
407
|
+
|
|
408
|
+
Main class for managing sender configurations.
|
|
409
|
+
|
|
410
|
+
#### Constructor
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
constructor(config: SenderManagerConfig)
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
#### Methods
|
|
417
|
+
|
|
418
|
+
- `bootstrapDatabase(): Promise<BootstrapResult>` - Initialize database and seed default senders
|
|
419
|
+
- `createSender(request: CreateSenderRequest): Promise<SenderConfiguration>` - Create new sender
|
|
420
|
+
- `updateSender(id: string, updates: UpdateSenderRequest): Promise<SenderConfiguration>` - Update existing sender
|
|
421
|
+
- `deleteSender(id: string): Promise<void>` - Delete sender
|
|
422
|
+
- `getSender(id: string): Promise<SenderConfiguration | null>` - Get sender by ID
|
|
423
|
+
- `listSenders(options?: ListSendersOptions): Promise<PaginatedResult<SenderConfiguration>>` - List senders with filters
|
|
424
|
+
- `validateSender(id: string): Promise<SenderValidationResult>` - Validate sender configuration
|
|
425
|
+
- `verifySender(id: string, provider?: string): Promise<VerificationResult>` - Verify sender with provider
|
|
426
|
+
- `selectBestSender(fromEmail: string, options?: SelectionOptions): Promise<SenderConfiguration | null>` - Select optimal sender
|
|
427
|
+
- `getDefaultSender(provider?: string): Promise<SenderConfiguration | null>` - Get default sender
|
|
428
|
+
- `getSendersByDomain(domain: string): Promise<SenderConfiguration[]>` - Get senders for domain
|
|
429
|
+
- `registerProvider(provider: SenderProviderPlugin): Promise<void>` - Register provider plugin
|
|
430
|
+
- `syncWithProviders(): Promise<SyncResult[]>` - Sync all senders with providers
|
|
431
|
+
- `cleanupInactiveSenders(): Promise<CleanupResult>` - Remove inactive senders
|
|
432
|
+
|
|
433
|
+
## Integration Status
|
|
434
|
+
|
|
435
|
+
- **Logger**: Not applicable - Core utility package with database-backed state (logging handled at service layer)
|
|
436
|
+
- **Docs-Suite**: Ready - Comprehensive API documentation with TypeDoc comments exported
|
|
437
|
+
- **NeverHub**: Not applicable - Core utility package focused on email sender configuration management. NeverHub integration is appropriate at the service layer where sender selection events and metrics would be published to the event bus. This package provides the foundational primitives for sender management without environment-dependent behavior.
|
|
438
|
+
|
|
439
|
+
## Testing
|
|
440
|
+
|
|
441
|
+
The package includes comprehensive tests with 90%+ coverage:
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
# Run tests
|
|
445
|
+
npm test
|
|
446
|
+
|
|
447
|
+
# Run tests with coverage
|
|
448
|
+
npm run test:coverage
|
|
449
|
+
|
|
450
|
+
# Run tests once
|
|
451
|
+
npm run test:run
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## License
|
|
455
|
+
|
|
456
|
+
Copyright (c) 2025 Bernier LLC
|
|
457
|
+
|
|
458
|
+
This file is licensed to the client under a limited-use license.
|
|
459
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
460
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
461
|
+
|
|
462
|
+
## See Also
|
|
463
|
+
|
|
464
|
+
- [@bernierllc/email-sender](https://www.npmjs.com/package/@bernierllc/email-sender) - Email sending abstraction
|
|
465
|
+
- [@bernierllc/logger](https://www.npmjs.com/package/@bernierllc/logger) - Logging utilities
|
|
466
|
+
- [@bernierllc/retry-policy](https://www.npmjs.com/package/@bernierllc/retry-policy) - Retry logic utilities
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/manager.test.ts"],"names":[],"mappings":""}
|