@astralibx/email-rule-engine 1.0.0 → 1.1.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/README.md +488 -192
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas/rule.schema.d.ts +1 -1
- package/dist/schemas/rule.schema.d.ts.map +1 -1
- package/dist/schemas/rule.schema.js +2 -2
- package/dist/schemas/rule.schema.js.map +1 -1
- package/dist/schemas/template.schema.d.ts +1 -1
- package/dist/schemas/template.schema.d.ts.map +1 -1
- package/dist/schemas/template.schema.js +2 -2
- package/dist/schemas/template.schema.js.map +1 -1
- package/dist/services/template-render.service.js +14 -14
- package/dist/types/config.types.d.ts +1 -0
- package/dist/types/config.types.d.ts.map +1 -1
- package/package.json +49 -49
package/README.md
CHANGED
|
@@ -1,192 +1,488 @@
|
|
|
1
|
-
# @astralibx/email-rule-engine
|
|
2
|
-
|
|
3
|
-
Rule-based email automation engine with MJML + Handlebars templates, per-user throttling, and Redis distributed locking.
|
|
4
|
-
|
|
5
|
-
## What It Does
|
|
6
|
-
|
|
7
|
-
- **Templates**: MJML + Handlebars email templates with CRUD, validation, preview, and variable extraction
|
|
8
|
-
- **Rules**: Condition-based rules that target users and send templated emails
|
|
9
|
-
- **Throttling**: Per-user daily/weekly limits with configurable minimum gap between emails
|
|
10
|
-
- **Distributed Locking**: Redis-based locks prevent concurrent rule runs
|
|
11
|
-
- **Run History**: Detailed logging of every rule execution with per-rule stats
|
|
12
|
-
- **Draft Workflow**: Supports draft → approve → send pipeline via adapter
|
|
13
|
-
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
1
|
+
# @astralibx/email-rule-engine
|
|
2
|
+
|
|
3
|
+
Rule-based email automation engine with MJML + Handlebars templates, per-user throttling, and Redis distributed locking.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
- **Templates**: MJML + Handlebars email templates with CRUD, validation, preview, and variable extraction
|
|
8
|
+
- **Rules**: Condition-based rules that target users and send templated emails
|
|
9
|
+
- **Throttling**: Per-user daily/weekly limits with configurable minimum gap between emails
|
|
10
|
+
- **Distributed Locking**: Redis-based locks prevent concurrent rule runs
|
|
11
|
+
- **Run History**: Detailed logging of every rule execution with per-rule stats
|
|
12
|
+
- **Draft Workflow**: Supports draft → approve → send pipeline via adapter
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
| Dependency | Version | Why |
|
|
17
|
+
|------------|---------|-----|
|
|
18
|
+
| Node.js | >= 18 | Runtime |
|
|
19
|
+
| MongoDB | >= 5.0 | Data storage |
|
|
20
|
+
| Redis | >= 6.0 | Distributed locking |
|
|
21
|
+
|
|
22
|
+
### Peer Dependencies
|
|
23
|
+
|
|
24
|
+
These must be installed in your project:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install express mongoose ioredis handlebars mjml html-to-text
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Package | Version | Purpose |
|
|
31
|
+
|---------|---------|---------|
|
|
32
|
+
| `express` | ^4.18 or ^5.0 | HTTP routes |
|
|
33
|
+
| `mongoose` | ^7.0 or ^8.0 | MongoDB ODM |
|
|
34
|
+
| `ioredis` | ^5.0 | Redis client |
|
|
35
|
+
| `handlebars` | ^4.7 | Template variables |
|
|
36
|
+
| `mjml` | ^4.0 | Responsive email HTML |
|
|
37
|
+
| `html-to-text` | ^9.0 | Plain text fallback |
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @astralibx/email-rule-engine
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## How It Works
|
|
46
|
+
|
|
47
|
+
The engine handles the **generic plumbing** — templates, rules, throttling, locking, REST API routes, and run history. Your project provides the **specific logic** through 5 adapter functions.
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
┌─────────────────────────────────────────────────────────┐
|
|
51
|
+
│ YOUR APPLICATION │
|
|
52
|
+
│ │
|
|
53
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
54
|
+
│ │ queryUsers │ │ resolveData │ │ sendEmail │ │
|
|
55
|
+
│ │ (find who │ │ (map user to │ │ (deliver or │ │
|
|
56
|
+
│ │ to email) │ │ template │ │ save draft) │ │
|
|
57
|
+
│ │ │ │ variables) │ │ │ │
|
|
58
|
+
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
|
59
|
+
│ │ │ │ │
|
|
60
|
+
│ ┌──────┴───────┐ ┌──────┴───────┐ │
|
|
61
|
+
│ │ selectAgent │ │findIdentifier│ │
|
|
62
|
+
│ │ (pick sender) │ │ (map email │ │
|
|
63
|
+
│ │ │ │ to contact) │ │
|
|
64
|
+
│ └──────┬───────┘ └──────┬───────┘ │
|
|
65
|
+
└─────────┼─────────────────┼────────────────────────────┘
|
|
66
|
+
│ │
|
|
67
|
+
┌─────────▼─────────────────▼────────────────────────────┐
|
|
68
|
+
│ @astralibx/email-rule-engine │
|
|
69
|
+
│ │
|
|
70
|
+
│ Templates ─► Rules ─► Runner ─► Throttle ─► Lock │
|
|
71
|
+
│ MJML/HBS CRUD Execute Per-user Redis │
|
|
72
|
+
│ Render Match Adapters Limits Prevent │
|
|
73
|
+
│ Duplicates │
|
|
74
|
+
│ │
|
|
75
|
+
│ REST API: /templates, /rules, /runner, /settings │
|
|
76
|
+
│ MongoDB: 5 collections auto-created │
|
|
77
|
+
└──────────────────────────────────────────────────────────┘
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
### Step 1: Create Adapters
|
|
83
|
+
|
|
84
|
+
These are the 5 functions that connect the engine to YOUR data and infrastructure.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// adapters.ts
|
|
88
|
+
import { SendEmailParams } from '@astralibx/email-rule-engine';
|
|
89
|
+
|
|
90
|
+
// 1. Find users matching rule conditions — YOUR query logic
|
|
91
|
+
async function queryUsers(target: any, limit: number) {
|
|
92
|
+
// `target` contains: { role, platform, conditions[] }
|
|
93
|
+
// Build your own query based on these conditions
|
|
94
|
+
return db.collection('users')
|
|
95
|
+
.find({ role: target.role, platform: target.platform })
|
|
96
|
+
.limit(limit)
|
|
97
|
+
.toArray();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 2. Transform a user record into template variables
|
|
101
|
+
// These variables become available in your Handlebars templates
|
|
102
|
+
function resolveData(user: Record<string, unknown>) {
|
|
103
|
+
return {
|
|
104
|
+
user: {
|
|
105
|
+
name: user.name,
|
|
106
|
+
email: user.email,
|
|
107
|
+
},
|
|
108
|
+
platform: {
|
|
109
|
+
name: 'My App',
|
|
110
|
+
domain: 'myapp.com',
|
|
111
|
+
supportEmail: 'help@myapp.com',
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 3. Deliver the email — save as draft, send directly, or queue
|
|
117
|
+
async function sendEmail(params: SendEmailParams) {
|
|
118
|
+
// params contains:
|
|
119
|
+
// identifierId - your internal email contact ID
|
|
120
|
+
// contactId - your internal contact ID
|
|
121
|
+
// accountId - selected sender account ID
|
|
122
|
+
// subject - rendered subject line
|
|
123
|
+
// htmlBody - rendered HTML (from MJML)
|
|
124
|
+
// textBody - rendered plain text
|
|
125
|
+
// ruleId - which rule triggered this
|
|
126
|
+
// autoApprove - whether to send immediately or queue for review
|
|
127
|
+
await myEmailService.send({
|
|
128
|
+
to: params.identifierId,
|
|
129
|
+
subject: params.subject,
|
|
130
|
+
html: params.htmlBody,
|
|
131
|
+
text: params.textBody,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 4. Select a sending account — return null to skip this recipient
|
|
136
|
+
async function selectAgent(identifierId: string) {
|
|
137
|
+
const account = await myAccounts.findBestAvailable();
|
|
138
|
+
return account ? { accountId: account.id } : null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 5. Map an email address to your contact/identifier system
|
|
142
|
+
async function findIdentifier(email: string) {
|
|
143
|
+
const contact = await myContacts.findByEmail(email);
|
|
144
|
+
return contact
|
|
145
|
+
? { id: contact._id.toString(), contactId: contact.contactId.toString() }
|
|
146
|
+
: null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const adapters = {
|
|
150
|
+
queryUsers,
|
|
151
|
+
resolveData,
|
|
152
|
+
sendEmail,
|
|
153
|
+
selectAgent,
|
|
154
|
+
findIdentifier,
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Step 2: Initialize the Engine
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// email-engine-setup.ts
|
|
162
|
+
import { createEmailRuleEngine } from '@astralibx/email-rule-engine';
|
|
163
|
+
import mongoose from 'mongoose';
|
|
164
|
+
import Redis from 'ioredis';
|
|
165
|
+
import { adapters } from './adapters';
|
|
166
|
+
|
|
167
|
+
const dbConnection = mongoose.createConnection('mongodb://localhost/myapp');
|
|
168
|
+
const redis = new Redis();
|
|
169
|
+
|
|
170
|
+
const engine = createEmailRuleEngine({
|
|
171
|
+
// MongoDB connection — engine creates 5 collections on this connection
|
|
172
|
+
db: {
|
|
173
|
+
connection: dbConnection,
|
|
174
|
+
collectionPrefix: '', // optional: prefix collection names (e.g., 'myapp_')
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
// Redis — used for distributed locking only
|
|
178
|
+
redis: {
|
|
179
|
+
connection: redis,
|
|
180
|
+
keyPrefix: 'myapp:', // optional: prefix Redis keys
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
// Custom enum values for your domain
|
|
184
|
+
// These control what values are allowed in template/rule schemas
|
|
185
|
+
platforms: ['web', 'mobile', 'both'], // your platform identifiers
|
|
186
|
+
audiences: ['customer', 'provider', 'all'], // your user role identifiers
|
|
187
|
+
|
|
188
|
+
// Your 5 adapter functions
|
|
189
|
+
adapters,
|
|
190
|
+
|
|
191
|
+
// Optional: logger (must have info/warn/error methods)
|
|
192
|
+
logger: console,
|
|
193
|
+
|
|
194
|
+
// Optional: tuning
|
|
195
|
+
options: {
|
|
196
|
+
lockTTLMs: 30 * 60 * 1000, // lock timeout (default: 30 min)
|
|
197
|
+
defaultMaxPerRun: 500, // max users per rule execution (default: 500)
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
export { engine };
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Step 3: Mount Routes
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// app.ts
|
|
208
|
+
import express from 'express';
|
|
209
|
+
import { engine } from './email-engine-setup';
|
|
210
|
+
|
|
211
|
+
const app = express();
|
|
212
|
+
app.use(express.json());
|
|
213
|
+
|
|
214
|
+
// Mount all email rule engine routes under a prefix
|
|
215
|
+
app.use('/api/email-rules', engine.routes);
|
|
216
|
+
|
|
217
|
+
app.listen(3000);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Step 4: Schedule Rule Execution
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import cron from 'node-cron';
|
|
224
|
+
import { engine } from './email-engine-setup';
|
|
225
|
+
|
|
226
|
+
// Run all active rules every day at 9 AM
|
|
227
|
+
cron.schedule('0 9 * * *', () => {
|
|
228
|
+
engine.runner.runAllRules();
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## What You Get Back
|
|
233
|
+
|
|
234
|
+
`createEmailRuleEngine()` returns:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
{
|
|
238
|
+
routes: Router; // Express router — mount with app.use()
|
|
239
|
+
runner: RuleRunnerService; // Call runner.runAllRules() from cron
|
|
240
|
+
templateService: TemplateService; // Direct access if needed
|
|
241
|
+
ruleService: RuleService; // Direct access if needed
|
|
242
|
+
models: {
|
|
243
|
+
EmailTemplate, // Mongoose models if you need direct DB access
|
|
244
|
+
EmailRule,
|
|
245
|
+
EmailRuleSend,
|
|
246
|
+
EmailRuleRunLog,
|
|
247
|
+
EmailThrottleConfig,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## API Routes
|
|
253
|
+
|
|
254
|
+
Once mounted, these endpoints are available:
|
|
255
|
+
|
|
256
|
+
### Templates
|
|
257
|
+
|
|
258
|
+
| Method | Path | Description |
|
|
259
|
+
|--------|------|-------------|
|
|
260
|
+
| GET | `/templates` | List all templates (filterable by `category`, `audience`, `platform`) |
|
|
261
|
+
| POST | `/templates` | Create new template |
|
|
262
|
+
| GET | `/templates/:id` | Get template by ID |
|
|
263
|
+
| PUT | `/templates/:id` | Update template |
|
|
264
|
+
| DELETE | `/templates/:id` | Delete template |
|
|
265
|
+
| PATCH | `/templates/:id/toggle` | Toggle active/inactive |
|
|
266
|
+
| POST | `/templates/:id/preview` | Render preview with sample data |
|
|
267
|
+
| POST | `/templates/:id/test-email` | Send test email (requires `sendTestEmail` adapter) |
|
|
268
|
+
| POST | `/templates/validate` | Validate MJML + Handlebars syntax |
|
|
269
|
+
| POST | `/templates/preview` | Preview raw template without saving |
|
|
270
|
+
|
|
271
|
+
### Rules
|
|
272
|
+
|
|
273
|
+
| Method | Path | Description |
|
|
274
|
+
|--------|------|-------------|
|
|
275
|
+
| GET | `/rules` | List all rules (with populated template info) |
|
|
276
|
+
| POST | `/rules` | Create new rule |
|
|
277
|
+
| GET | `/rules/:id` | Get rule by ID |
|
|
278
|
+
| PATCH | `/rules/:id` | Update rule |
|
|
279
|
+
| DELETE | `/rules/:id` | Delete (or disable if has send history) |
|
|
280
|
+
| PATCH | `/rules/:id/toggle` | Toggle active/inactive |
|
|
281
|
+
| POST | `/rules/:id/dry-run` | Count matching users without sending |
|
|
282
|
+
| GET | `/rules/run-history` | Get execution history |
|
|
283
|
+
|
|
284
|
+
### Runner
|
|
285
|
+
|
|
286
|
+
| Method | Path | Description |
|
|
287
|
+
|--------|------|-------------|
|
|
288
|
+
| POST | `/runner` | Trigger manual rule run (fire-and-forget) |
|
|
289
|
+
| GET | `/runner/status` | Get latest run result |
|
|
290
|
+
|
|
291
|
+
### Settings
|
|
292
|
+
|
|
293
|
+
| Method | Path | Description |
|
|
294
|
+
|--------|------|-------------|
|
|
295
|
+
| GET | `/settings/throttle` | Get throttle configuration |
|
|
296
|
+
| PATCH | `/settings/throttle` | Update throttle limits |
|
|
297
|
+
|
|
298
|
+
## Config Reference
|
|
299
|
+
|
|
300
|
+
### `EmailRuleEngineConfig`
|
|
301
|
+
|
|
302
|
+
| Field | Type | Required | Default | Description |
|
|
303
|
+
|-------|------|----------|---------|-------------|
|
|
304
|
+
| `db.connection` | `mongoose.Connection` | Yes | — | Mongoose connection for engine collections |
|
|
305
|
+
| `db.collectionPrefix` | `string` | No | `''` | Prefix for collection names (e.g., `'myapp_'`) |
|
|
306
|
+
| `redis.connection` | `Redis` | Yes | — | ioredis instance for distributed locking |
|
|
307
|
+
| `redis.keyPrefix` | `string` | No | `''` | Prefix for Redis keys (e.g., `'myapp:'`) |
|
|
308
|
+
| `platforms` | `string[]` | No | `['web', 'mobile', 'both']` | Valid platform values for schema enum validation |
|
|
309
|
+
| `audiences` | `string[]` | No | `['customer', 'provider', 'all']` | Valid audience/role values for schema enum validation |
|
|
310
|
+
| `adapters` | `object` | Yes | — | Your 5 project-specific callbacks (see below) |
|
|
311
|
+
| `logger` | `LogAdapter` | No | silent | Object with `info`, `warn`, `error` methods |
|
|
312
|
+
| `options.lockTTLMs` | `number` | No | `1800000` | Lock timeout in ms (30 min) |
|
|
313
|
+
| `options.defaultMaxPerRun` | `number` | No | `500` | Max users processed per rule execution |
|
|
314
|
+
|
|
315
|
+
### Adapters
|
|
316
|
+
|
|
317
|
+
| Adapter | Signature | Required | Description |
|
|
318
|
+
|---------|-----------|----------|-------------|
|
|
319
|
+
| `queryUsers` | `(target, limit) => Promise<Record[]>` | Yes | Find users matching rule target conditions. `target` has `role`, `platform`, `conditions[]` |
|
|
320
|
+
| `resolveData` | `(user) => Record` | Yes | Transform a user record into Handlebars template variables |
|
|
321
|
+
| `sendEmail` | `(params: SendEmailParams) => Promise<void>` | Yes | Deliver the email (send, queue, or save as draft) |
|
|
322
|
+
| `selectAgent` | `(identifierId) => Promise<{accountId} \| null>` | Yes | Pick a sending account. Return `null` to skip this recipient |
|
|
323
|
+
| `findIdentifier` | `(email) => Promise<{id, contactId} \| null>` | Yes | Map email address to your contact system. Return `null` to skip |
|
|
324
|
+
| `sendTestEmail` | `(to, subject, html, text) => Promise<void>` | No | Send test email for template preview |
|
|
325
|
+
|
|
326
|
+
### `SendEmailParams`
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
{
|
|
330
|
+
identifierId: string; // Your internal email contact ID
|
|
331
|
+
contactId: string; // Your internal contact ID
|
|
332
|
+
accountId: string; // Selected sender account ID
|
|
333
|
+
subject: string; // Rendered subject line
|
|
334
|
+
htmlBody: string; // Rendered HTML from MJML template
|
|
335
|
+
textBody: string; // Rendered plain text
|
|
336
|
+
ruleId: string; // Rule that triggered this send
|
|
337
|
+
autoApprove: boolean; // true = send now, false = save as draft for review
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Template System
|
|
342
|
+
|
|
343
|
+
Templates use [MJML](https://mjml.io/) for responsive email HTML and [Handlebars](https://handlebarsjs.com/) for dynamic variables.
|
|
344
|
+
|
|
345
|
+
### Writing a Template
|
|
346
|
+
|
|
347
|
+
**Subject** (Handlebars only):
|
|
348
|
+
```
|
|
349
|
+
Welcome to {{platform.name}}, {{user.name}}!
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Body** (MJML + Handlebars):
|
|
353
|
+
```html
|
|
354
|
+
<mjml>
|
|
355
|
+
<mj-body>
|
|
356
|
+
<mj-section>
|
|
357
|
+
<mj-column>
|
|
358
|
+
<mj-text>
|
|
359
|
+
Hi {{user.name}},
|
|
360
|
+
Welcome to {{platform.name}}!
|
|
361
|
+
{{#if subscription}}
|
|
362
|
+
Your {{subscription.planName}} plan includes {{subscription.sessions}} sessions.
|
|
363
|
+
{{/if}}
|
|
364
|
+
</mj-text>
|
|
365
|
+
<mj-button href="{{platform.bookingLink}}">Book Now</mj-button>
|
|
366
|
+
</mj-column>
|
|
367
|
+
</mj-section>
|
|
368
|
+
</mj-body>
|
|
369
|
+
</mjml>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The variables available in templates depend on what your `resolveData` adapter returns.
|
|
373
|
+
|
|
374
|
+
### Built-in Handlebars Helpers
|
|
375
|
+
|
|
376
|
+
| Helper | Usage | Output |
|
|
377
|
+
|--------|-------|--------|
|
|
378
|
+
| `currency` | `{{currency 1500}}` | `₹1,500` |
|
|
379
|
+
| `formatDate` | `{{formatDate date}}` | `13 Mar 2026` |
|
|
380
|
+
| `capitalize` | `{{capitalize "hello"}}` | `Hello` |
|
|
381
|
+
| `lowercase` | `{{lowercase "HELLO"}}` | `hello` |
|
|
382
|
+
| `uppercase` | `{{uppercase "hello"}}` | `HELLO` |
|
|
383
|
+
| `join` | `{{join items ", "}}` | `a, b, c` |
|
|
384
|
+
| `pluralize` | `{{pluralize count "item" "items"}}` | `items` |
|
|
385
|
+
| `eq/neq/gt/lt/gte/lte` | `{{#if (eq a b)}}` | Comparison |
|
|
386
|
+
| `not` | `{{#if (not val)}}` | Negation |
|
|
387
|
+
|
|
388
|
+
## Rule Execution Flow
|
|
389
|
+
|
|
390
|
+
When `engine.runner.runAllRules()` is called:
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
1. Acquire Redis lock (prevents concurrent runs)
|
|
394
|
+
2. Load throttle config (daily/weekly limits, min gap)
|
|
395
|
+
3. Load all active rules (sorted by priority)
|
|
396
|
+
4. For each rule:
|
|
397
|
+
a. Load linked template
|
|
398
|
+
b. Call YOUR queryUsers(target, limit) adapter
|
|
399
|
+
c. For each matched user:
|
|
400
|
+
- Check send history (sendOnce, resendAfterDays)
|
|
401
|
+
- Call YOUR findIdentifier(email) adapter
|
|
402
|
+
- Check throttle limits (daily, weekly, min gap)
|
|
403
|
+
- Call YOUR selectAgent(identifierId) adapter
|
|
404
|
+
- Call YOUR resolveData(user) adapter
|
|
405
|
+
- Render template (MJML → HTML, Handlebars → variables)
|
|
406
|
+
- Call YOUR sendEmail(params) adapter
|
|
407
|
+
- Log send for deduplication
|
|
408
|
+
d. Update rule stats (totalSent, lastRunAt)
|
|
409
|
+
5. Save run log with per-rule statistics
|
|
410
|
+
6. Release Redis lock
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Collections Created
|
|
414
|
+
|
|
415
|
+
The engine creates these MongoDB collections (prefixed if `db.collectionPrefix` is set):
|
|
416
|
+
|
|
417
|
+
| Collection | Purpose | Auto-cleanup |
|
|
418
|
+
|------------|---------|--------------|
|
|
419
|
+
| `email_templates` | MJML + Handlebars templates | — |
|
|
420
|
+
| `email_rules` | Automation rules with conditions and targeting | — |
|
|
421
|
+
| `email_rule_sends` | Per-user send tracking for deduplication | — |
|
|
422
|
+
| `email_rule_run_logs` | Execution history with per-rule stats | 90 days TTL |
|
|
423
|
+
| `email_throttle_config` | Throttle settings (singleton document) | — |
|
|
424
|
+
|
|
425
|
+
## Throttle Configuration
|
|
426
|
+
|
|
427
|
+
Default throttle settings (configurable via `PATCH /settings/throttle`):
|
|
428
|
+
|
|
429
|
+
```json
|
|
430
|
+
{
|
|
431
|
+
"maxPerUserPerDay": 2,
|
|
432
|
+
"maxPerUserPerWeek": 5,
|
|
433
|
+
"minGapDays": 1,
|
|
434
|
+
"window": "rolling"
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Rules with `bypassThrottle: true` or `emailType: 'transactional'` skip throttle checks.
|
|
439
|
+
|
|
440
|
+
## TypeScript Exports
|
|
441
|
+
|
|
442
|
+
The package exports everything you might need:
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
// Factory
|
|
446
|
+
import { createEmailRuleEngine } from '@astralibx/email-rule-engine';
|
|
447
|
+
|
|
448
|
+
// Types
|
|
449
|
+
import type {
|
|
450
|
+
EmailRuleEngineConfig,
|
|
451
|
+
SendEmailParams,
|
|
452
|
+
AgentSelection,
|
|
453
|
+
RecipientIdentifier,
|
|
454
|
+
LogAdapter,
|
|
455
|
+
EmailRule,
|
|
456
|
+
EmailTemplate,
|
|
457
|
+
RuleTarget,
|
|
458
|
+
RuleCondition,
|
|
459
|
+
RuleRunStats,
|
|
460
|
+
PerRuleStats,
|
|
461
|
+
CreateEmailRuleInput,
|
|
462
|
+
UpdateEmailRuleInput,
|
|
463
|
+
CreateEmailTemplateInput,
|
|
464
|
+
UpdateEmailTemplateInput,
|
|
465
|
+
} from '@astralibx/email-rule-engine';
|
|
466
|
+
|
|
467
|
+
// Enums
|
|
468
|
+
import {
|
|
469
|
+
TemplateAudience,
|
|
470
|
+
TemplateCategory,
|
|
471
|
+
RuleOperator,
|
|
472
|
+
EmailType,
|
|
473
|
+
RunTrigger,
|
|
474
|
+
} from '@astralibx/email-rule-engine';
|
|
475
|
+
|
|
476
|
+
// Services (for advanced usage)
|
|
477
|
+
import {
|
|
478
|
+
TemplateRenderService,
|
|
479
|
+
TemplateService,
|
|
480
|
+
RuleService,
|
|
481
|
+
RuleRunnerService,
|
|
482
|
+
RedisLock,
|
|
483
|
+
} from '@astralibx/email-rule-engine';
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
## License
|
|
487
|
+
|
|
488
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -28,8 +28,8 @@ const routes_1 = require("./routes");
|
|
|
28
28
|
function createEmailRuleEngine(config) {
|
|
29
29
|
const conn = config.db.connection;
|
|
30
30
|
const prefix = config.db.collectionPrefix || '';
|
|
31
|
-
const EmailTemplate = conn.model(`${prefix}EmailTemplate`, (0, template_schema_1.createEmailTemplateSchema)(config.platforms));
|
|
32
|
-
const EmailRule = conn.model(`${prefix}EmailRule`, (0, rule_schema_1.createEmailRuleSchema)(config.platforms));
|
|
31
|
+
const EmailTemplate = conn.model(`${prefix}EmailTemplate`, (0, template_schema_1.createEmailTemplateSchema)(config.platforms, config.audiences));
|
|
32
|
+
const EmailRule = conn.model(`${prefix}EmailRule`, (0, rule_schema_1.createEmailRuleSchema)(config.platforms, config.audiences));
|
|
33
33
|
const EmailRuleSend = conn.model(`${prefix}EmailRuleSend`, (0, rule_send_schema_1.createEmailRuleSendSchema)());
|
|
34
34
|
const EmailRuleRunLog = conn.model(`${prefix}EmailRuleRunLog`, (0, run_log_schema_1.createEmailRuleRunLogSchema)());
|
|
35
35
|
const EmailThrottleConfig = conn.model(`${prefix}EmailThrottleConfig`, (0, throttle_config_schema_1.createEmailThrottleConfigSchema)());
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA0BA,sDAmDC;AA5ED,+DAA+F;AAC/F,uDAAmF;AACnF,iEAAgG;AAChG,6DAAkG;AAClG,6EAAkH;AAClH,kEAA8D;AAC9D,0DAAsD;AACtD,wEAAmE;AACnE,qCAAwC;AAiBxC,SAAgB,qBAAqB,CAAC,MAA6B;IACjE,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,IAAI,EAAE,CAAC;IAEhD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAC9B,GAAG,MAAM,eAAe,EACxB,IAAA,2CAAyB,EAAC,MAAM,CAAC,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA0BA,sDAmDC;AA5ED,+DAA+F;AAC/F,uDAAmF;AACnF,iEAAgG;AAChG,6DAAkG;AAClG,6EAAkH;AAClH,kEAA8D;AAC9D,0DAAsD;AACtD,wEAAmE;AACnE,qCAAwC;AAiBxC,SAAgB,qBAAqB,CAAC,MAA6B;IACjE,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,IAAI,EAAE,CAAC;IAEhD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAC9B,GAAG,MAAM,eAAe,EACxB,IAAA,2CAAyB,EAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CACxC,CAAC;IAExB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAC1B,GAAG,MAAM,WAAW,EACpB,IAAA,mCAAqB,EAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CACxC,CAAC;IAEpB,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAC9B,GAAG,MAAM,eAAe,EACxB,IAAA,4CAAyB,GAAE,CACN,CAAC;IAExB,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAChC,GAAG,MAAM,iBAAiB,EAC1B,IAAA,4CAA2B,GAAE,CACN,CAAC;IAE1B,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CACpC,GAAG,MAAM,qBAAqB,EAC9B,IAAA,wDAA+B,GAAE,CACN,CAAC;IAE9B,MAAM,eAAe,GAAG,IAAI,kCAAe,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,IAAI,0BAAW,CAAC,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;IACvF,MAAM,aAAa,GAAG,IAAI,uCAAiB,CACzC,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,CACtF,CAAC;IAEF,MAAM,MAAM,GAAG,IAAA,qBAAY,EAAC;QAC1B,eAAe;QACf,WAAW;QACX,aAAa;QACb,eAAe;QACf,mBAAmB;QACnB,cAAc,EAAE,MAAM,CAAC,SAAS;KACjC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,MAAM,EAAE,aAAa;QACrB,eAAe;QACf,WAAW;QACX,MAAM,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE;KAC1F,CAAC;AACJ,CAAC;AAED,0CAAwB;AACxB,4CAA0B;AAC1B,8EAAqH;AAA5G,gIAAA,qBAAqB,OAAA;AAC9B,gEAA8D;AAArD,mHAAA,eAAe,OAAA;AACxB,wDAAsD;AAA7C,2GAAA,WAAW,OAAA;AACpB,sEAAmE;AAA1D,wHAAA,iBAAiB,OAAA;AAC1B,iDAA+C;AAAtC,uGAAA,SAAS,OAAA"}
|
|
@@ -10,7 +10,7 @@ export interface EmailRuleStatics {
|
|
|
10
10
|
createRule(input: CreateEmailRuleInput): Promise<EmailRuleDocument>;
|
|
11
11
|
}
|
|
12
12
|
export type EmailRuleModel = Model<IEmailRule> & EmailRuleStatics;
|
|
13
|
-
export declare function createEmailRuleSchema(platformValues?: string[]): Schema<IEmailRule, Model<IEmailRule, any, any, any, import("mongoose").Document<unknown, any, IEmailRule, any, {}> & IEmailRule & {
|
|
13
|
+
export declare function createEmailRuleSchema(platformValues?: string[], audienceValues?: string[]): Schema<IEmailRule, Model<IEmailRule, any, any, any, import("mongoose").Document<unknown, any, IEmailRule, any, {}> & IEmailRule & {
|
|
14
14
|
_id: Types.ObjectId;
|
|
15
15
|
} & {
|
|
16
16
|
__v: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/rule.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3E,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,SAAS,EAAE,KAAK,GAAG,YAAY,CAAC;IACvE,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC;CAC5B;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,UAAU,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC3C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACpF,UAAU,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACrE;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,gBAAgB,CAAC;AAElE,wBAAgB,qBAAqB,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE;;;;;;;;
|
|
1
|
+
{"version":3,"file":"rule.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/rule.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3E,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,SAAS,EAAE,KAAK,GAAG,YAAY,CAAC;IACvE,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC;CAC5B;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,UAAU,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC3C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACpF,UAAU,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACrE;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,gBAAgB,CAAC;AAElE,wBAAgB,qBAAqB,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;;;;;;;;GA0FzF"}
|
|
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createEmailRuleSchema = createEmailRuleSchema;
|
|
4
4
|
const mongoose_1 = require("mongoose");
|
|
5
5
|
const enums_1 = require("../types/enums");
|
|
6
|
-
function createEmailRuleSchema(platformValues) {
|
|
6
|
+
function createEmailRuleSchema(platformValues, audienceValues) {
|
|
7
7
|
const RuleConditionSchema = new mongoose_1.Schema({
|
|
8
8
|
field: { type: String, required: true },
|
|
9
9
|
operator: { type: String, enum: Object.values(enums_1.RuleOperator), required: true },
|
|
10
10
|
value: { type: mongoose_1.Schema.Types.Mixed }
|
|
11
11
|
}, { _id: false });
|
|
12
12
|
const RuleTargetSchema = new mongoose_1.Schema({
|
|
13
|
-
role: { type: String, enum: Object.values(enums_1.TemplateAudience), required: true },
|
|
13
|
+
role: { type: String, enum: audienceValues || Object.values(enums_1.TemplateAudience), required: true },
|
|
14
14
|
platform: {
|
|
15
15
|
type: String,
|
|
16
16
|
required: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule.schema.js","sourceRoot":"","sources":["../../src/schemas/rule.schema.ts"],"names":[],"mappings":";;AAkBA,sDA0FC;AA5GD,uCAAkE;AAClE,0CAA2E;AAiB3E,SAAgB,qBAAqB,CAAC,cAAyB;
|
|
1
|
+
{"version":3,"file":"rule.schema.js","sourceRoot":"","sources":["../../src/schemas/rule.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ export interface EmailTemplateStatics {
|
|
|
12
12
|
createTemplate(input: CreateEmailTemplateInput): Promise<EmailTemplateDocument>;
|
|
13
13
|
}
|
|
14
14
|
export type EmailTemplateModel = Model<IEmailTemplate> & EmailTemplateStatics;
|
|
15
|
-
export declare function createEmailTemplateSchema(platformValues?: string[]): Schema<IEmailTemplate, Model<IEmailTemplate, any, any, any, import("mongoose").Document<unknown, any, IEmailTemplate, any, {}> & IEmailTemplate & {
|
|
15
|
+
export declare function createEmailTemplateSchema(platformValues?: string[], audienceValues?: string[]): Schema<IEmailTemplate, Model<IEmailTemplate, any, any, any, import("mongoose").Document<unknown, any, IEmailTemplate, any, {}> & IEmailTemplate & {
|
|
16
16
|
_id: import("mongoose").Types.ObjectId;
|
|
17
17
|
} & {
|
|
18
18
|
__v: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/template.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEvF,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC;CAAG;AAErE,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IAChE,UAAU,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC/C,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC7E,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC7E,cAAc,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACjF;AAED,MAAM,MAAM,kBAAkB,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,oBAAoB,CAAC;AAE9E,wBAAgB,yBAAyB,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE;;;;;;;;
|
|
1
|
+
{"version":3,"file":"template.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/template.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEvF,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC;CAAG;AAErE,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IAChE,UAAU,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC/C,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC7E,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC7E,cAAc,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACjF;AAED,MAAM,MAAM,kBAAkB,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,oBAAoB,CAAC;AAE9E,wBAAgB,yBAAyB,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;;;;;;;;GAsE7F"}
|
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createEmailTemplateSchema = createEmailTemplateSchema;
|
|
4
4
|
const mongoose_1 = require("mongoose");
|
|
5
5
|
const enums_1 = require("../types/enums");
|
|
6
|
-
function createEmailTemplateSchema(platformValues) {
|
|
6
|
+
function createEmailTemplateSchema(platformValues, audienceValues) {
|
|
7
7
|
const schema = new mongoose_1.Schema({
|
|
8
8
|
name: { type: String, required: true },
|
|
9
9
|
slug: { type: String, required: true, unique: true },
|
|
10
10
|
description: String,
|
|
11
11
|
category: { type: String, enum: Object.values(enums_1.TemplateCategory), required: true },
|
|
12
|
-
audience: { type: String, enum: Object.values(enums_1.TemplateAudience), required: true },
|
|
12
|
+
audience: { type: String, enum: audienceValues || Object.values(enums_1.TemplateAudience), required: true },
|
|
13
13
|
platform: {
|
|
14
14
|
type: String,
|
|
15
15
|
required: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.schema.js","sourceRoot":"","sources":["../../src/schemas/template.schema.ts"],"names":[],"mappings":";;AAkBA,8DAsEC;AAxFD,uCAA2D;AAC3D,0CAAoE;AAiBpE,SAAgB,yBAAyB,CAAC,cAAyB;
|
|
1
|
+
{"version":3,"file":"template.schema.js","sourceRoot":"","sources":["../../src/schemas/template.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,21 +7,21 @@ exports.TemplateRenderService = void 0;
|
|
|
7
7
|
const handlebars_1 = __importDefault(require("handlebars"));
|
|
8
8
|
const mjml_1 = __importDefault(require("mjml"));
|
|
9
9
|
const html_to_text_1 = require("html-to-text");
|
|
10
|
-
const MJML_BASE_OPEN = `<mjml>
|
|
11
|
-
<mj-head>
|
|
12
|
-
<mj-attributes>
|
|
13
|
-
<mj-all font-family="Arial, sans-serif" />
|
|
14
|
-
<mj-text font-size="15px" color="#333333" line-height="1.6" />
|
|
15
|
-
</mj-attributes>
|
|
16
|
-
</mj-head>
|
|
17
|
-
<mj-body background-color="#ffffff">
|
|
18
|
-
<mj-section padding="20px">
|
|
19
|
-
<mj-column>
|
|
10
|
+
const MJML_BASE_OPEN = `<mjml>
|
|
11
|
+
<mj-head>
|
|
12
|
+
<mj-attributes>
|
|
13
|
+
<mj-all font-family="Arial, sans-serif" />
|
|
14
|
+
<mj-text font-size="15px" color="#333333" line-height="1.6" />
|
|
15
|
+
</mj-attributes>
|
|
16
|
+
</mj-head>
|
|
17
|
+
<mj-body background-color="#ffffff">
|
|
18
|
+
<mj-section padding="20px">
|
|
19
|
+
<mj-column>
|
|
20
20
|
<mj-text>`;
|
|
21
|
-
const MJML_BASE_CLOSE = ` </mj-text>
|
|
22
|
-
</mj-column>
|
|
23
|
-
</mj-section>
|
|
24
|
-
</mj-body>
|
|
21
|
+
const MJML_BASE_CLOSE = ` </mj-text>
|
|
22
|
+
</mj-column>
|
|
23
|
+
</mj-section>
|
|
24
|
+
</mj-body>
|
|
25
25
|
</mjml>`;
|
|
26
26
|
const DATE_FORMAT_OPTIONS = {
|
|
27
27
|
day: 'numeric',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.types.d.ts","sourceRoot":"","sources":["../../src/types/config.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE;QACF,UAAU,EAAE,UAAU,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IAEF,KAAK,EAAE;QACL,UAAU,EAAE,KAAK,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAEF,QAAQ,EAAE;QACR,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACtF,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACxE,SAAS,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACtD,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;QACtE,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;QACvE,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC5F,CAAC;IAEF,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH"}
|
|
1
|
+
{"version":3,"file":"config.types.d.ts","sourceRoot":"","sources":["../../src/types/config.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE;QACF,UAAU,EAAE,UAAU,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IAEF,KAAK,EAAE;QACL,UAAU,EAAE,KAAK,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAEF,QAAQ,EAAE;QACR,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACtF,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACxE,SAAS,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACtD,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;QACtE,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;QACvE,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC5F,CAAC;IAEF,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH"}
|
package/package.json
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@astralibx/email-rule-engine",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Rule-based email automation engine with MJML + Handlebars templates, throttling, and distributed locking",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist"
|
|
9
|
-
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"test": "jest",
|
|
13
|
-
"prepublishOnly": "npm run build",
|
|
14
|
-
"clean": "rm -rf dist"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"email",
|
|
18
|
-
"automation",
|
|
19
|
-
"rule-engine",
|
|
20
|
-
"mjml",
|
|
21
|
-
"handlebars",
|
|
22
|
-
"throttle"
|
|
23
|
-
],
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"peerDependencies": {
|
|
26
|
-
"express": "^4.18.0 || ^5.0.0",
|
|
27
|
-
"handlebars": "^4.7.0",
|
|
28
|
-
"html-to-text": "^9.0.0",
|
|
29
|
-
"ioredis": "^5.0.0",
|
|
30
|
-
"mjml": "^4.0.0",
|
|
31
|
-
"mongoose": "^7.0.0 || ^8.0.0"
|
|
32
|
-
},
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"@types/jest": "^29.5.0",
|
|
35
|
-
"@types/express": "^5.0.0",
|
|
36
|
-
"@types/html-to-text": "^9.0.4",
|
|
37
|
-
"@types/mjml": "^4.7.4",
|
|
38
|
-
"@types/node": "^22.0.0",
|
|
39
|
-
"express": "^5.0.0",
|
|
40
|
-
"handlebars": "^4.7.8",
|
|
41
|
-
"html-to-text": "^9.0.5",
|
|
42
|
-
"ioredis": "^5.4.2",
|
|
43
|
-
"mjml": "^4.15.3",
|
|
44
|
-
"mongoose": "^8.12.1",
|
|
45
|
-
"jest": "^29.7.0",
|
|
46
|
-
"ts-jest": "^29.2.0",
|
|
47
|
-
"typescript": "^5.8.2"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@astralibx/email-rule-engine",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Rule-based email automation engine with MJML + Handlebars templates, throttling, and distributed locking",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "jest",
|
|
13
|
+
"prepublishOnly": "npm run build",
|
|
14
|
+
"clean": "rm -rf dist"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"email",
|
|
18
|
+
"automation",
|
|
19
|
+
"rule-engine",
|
|
20
|
+
"mjml",
|
|
21
|
+
"handlebars",
|
|
22
|
+
"throttle"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"express": "^4.18.0 || ^5.0.0",
|
|
27
|
+
"handlebars": "^4.7.0",
|
|
28
|
+
"html-to-text": "^9.0.0",
|
|
29
|
+
"ioredis": "^5.0.0",
|
|
30
|
+
"mjml": "^4.0.0",
|
|
31
|
+
"mongoose": "^7.0.0 || ^8.0.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/jest": "^29.5.0",
|
|
35
|
+
"@types/express": "^5.0.0",
|
|
36
|
+
"@types/html-to-text": "^9.0.4",
|
|
37
|
+
"@types/mjml": "^4.7.4",
|
|
38
|
+
"@types/node": "^22.0.0",
|
|
39
|
+
"express": "^5.0.0",
|
|
40
|
+
"handlebars": "^4.7.8",
|
|
41
|
+
"html-to-text": "^9.0.5",
|
|
42
|
+
"ioredis": "^5.4.2",
|
|
43
|
+
"mjml": "^4.15.3",
|
|
44
|
+
"mongoose": "^8.12.1",
|
|
45
|
+
"jest": "^29.7.0",
|
|
46
|
+
"ts-jest": "^29.2.0",
|
|
47
|
+
"typescript": "^5.8.2"
|
|
48
|
+
}
|
|
49
|
+
}
|