@astralibx/email-rule-engine 1.0.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 +192 -0
- package/dist/controllers/index.d.ts +5 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/index.js +12 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/controllers/rule.controller.d.ts +13 -0
- package/dist/controllers/rule.controller.d.ts.map +1 -0
- package/dist/controllers/rule.controller.js +142 -0
- package/dist/controllers/rule.controller.js.map +1 -0
- package/dist/controllers/runner.controller.d.ts +8 -0
- package/dist/controllers/runner.controller.d.ts.map +1 -0
- package/dist/controllers/runner.controller.js +22 -0
- package/dist/controllers/runner.controller.js.map +1 -0
- package/dist/controllers/settings.controller.d.ts +7 -0
- package/dist/controllers/settings.controller.d.ts.map +1 -0
- package/dist/controllers/settings.controller.js +56 -0
- package/dist/controllers/settings.controller.js.map +1 -0
- package/dist/controllers/template.controller.d.ts +15 -0
- package/dist/controllers/template.controller.d.ts.map +1 -0
- package/dist/controllers/template.controller.js +169 -0
- package/dist/controllers/template.controller.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/index.d.ts +16 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +47 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/schemas/index.d.ts +6 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +14 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/rule-send.schema.d.ts +25 -0
- package/dist/schemas/rule-send.schema.d.ts.map +1 -0
- package/dist/schemas/rule-send.schema.js +41 -0
- package/dist/schemas/rule-send.schema.js.map +1 -0
- package/dist/schemas/rule.schema.d.ts +22 -0
- package/dist/schemas/rule.schema.d.ts.map +1 -0
- package/dist/schemas/rule.schema.js +81 -0
- package/dist/schemas/rule.schema.js.map +1 -0
- package/dist/schemas/run-log.schema.d.ts +39 -0
- package/dist/schemas/run-log.schema.d.ts.map +1 -0
- package/dist/schemas/run-log.schema.js +47 -0
- package/dist/schemas/run-log.schema.js.map +1 -0
- package/dist/schemas/template.schema.d.ts +24 -0
- package/dist/schemas/template.schema.d.ts.map +1 -0
- package/dist/schemas/template.schema.js +65 -0
- package/dist/schemas/template.schema.js.map +1 -0
- package/dist/schemas/throttle-config.schema.d.ts +19 -0
- package/dist/schemas/throttle-config.schema.d.ts.map +1 -0
- package/dist/schemas/throttle-config.schema.js +32 -0
- package/dist/schemas/throttle-config.schema.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +12 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/rule-runner.service.d.ts +31 -0
- package/dist/services/rule-runner.service.d.ts.map +1 -0
- package/dist/services/rule-runner.service.js +253 -0
- package/dist/services/rule-runner.service.js.map +1 -0
- package/dist/services/rule.service.d.ts +27 -0
- package/dist/services/rule.service.d.ts.map +1 -0
- package/dist/services/rule.service.js +127 -0
- package/dist/services/rule.service.js.map +1 -0
- package/dist/services/template-render.service.d.ts +23 -0
- package/dist/services/template-render.service.d.ts.map +1 -0
- package/dist/services/template-render.service.js +178 -0
- package/dist/services/template-render.service.js.map +1 -0
- package/dist/services/template.service.d.ts +42 -0
- package/dist/services/template.service.d.ts.map +1 -0
- package/dist/services/template.service.js +128 -0
- package/dist/services/template.service.js.map +1 -0
- package/dist/types/config.types.d.ts +50 -0
- package/dist/types/config.types.d.ts.map +1 -0
- package/dist/types/config.types.js +3 -0
- package/dist/types/config.types.js.map +1 -0
- package/dist/types/enums.d.ts +43 -0
- package/dist/types/enums.d.ts.map +1 -0
- package/dist/types/enums.js +40 -0
- package/dist/types/enums.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/rule.types.d.ts +91 -0
- package/dist/types/rule.types.d.ts.map +1 -0
- package/dist/types/rule.types.js +3 -0
- package/dist/types/rule.types.js.map +1 -0
- package/dist/types/template.types.d.ts +43 -0
- package/dist/types/template.types.d.ts.map +1 -0
- package/dist/types/template.types.js +3 -0
- package/dist/types/template.types.js.map +1 -0
- package/dist/types/throttle.types.d.ts +15 -0
- package/dist/types/throttle.types.d.ts.map +1 -0
- package/dist/types/throttle.types.js +3 -0
- package/dist/types/throttle.types.js.map +1 -0
- package/dist/utils/express-helpers.d.ts +4 -0
- package/dist/utils/express-helpers.d.ts.map +1 -0
- package/dist/utils/express-helpers.js +15 -0
- package/dist/utils/express-helpers.js.map +1 -0
- package/dist/utils/redis-lock.d.ts +13 -0
- package/dist/utils/redis-lock.d.ts.map +1 -0
- package/dist/utils/redis-lock.js +36 -0
- package/dist/utils/redis-lock.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,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
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @astralibx/email-rule-engine
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { createEmailRuleEngine } from '@astralibx/email-rule-engine';
|
|
22
|
+
import mongoose from 'mongoose';
|
|
23
|
+
import Redis from 'ioredis';
|
|
24
|
+
|
|
25
|
+
const dbConnection = mongoose.createConnection('mongodb://localhost/myapp');
|
|
26
|
+
const redis = new Redis();
|
|
27
|
+
|
|
28
|
+
const engine = createEmailRuleEngine({
|
|
29
|
+
db: { connection: dbConnection },
|
|
30
|
+
redis: { connection: redis, keyPrefix: 'myapp:' },
|
|
31
|
+
|
|
32
|
+
// Your platform values (used for enum validation in schemas)
|
|
33
|
+
platforms: ['web', 'mobile', 'both'],
|
|
34
|
+
|
|
35
|
+
adapters: {
|
|
36
|
+
// Find users matching rule conditions — YOUR query logic
|
|
37
|
+
queryUsers: async (target, limit) => {
|
|
38
|
+
return db.collection('users')
|
|
39
|
+
.find({ role: target.role })
|
|
40
|
+
.limit(limit)
|
|
41
|
+
.toArray();
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
// Transform user record into template variables
|
|
45
|
+
resolveData: (user) => ({
|
|
46
|
+
recipient: { name: user.name, email: user.email },
|
|
47
|
+
platform: { name: 'My App', domain: 'myapp.com' }
|
|
48
|
+
}),
|
|
49
|
+
|
|
50
|
+
// Deliver the email (save as draft, send directly, queue — your choice)
|
|
51
|
+
sendEmail: async (params) => {
|
|
52
|
+
await myEmailService.send({
|
|
53
|
+
to: params.identifierId,
|
|
54
|
+
subject: params.subject,
|
|
55
|
+
html: params.htmlBody,
|
|
56
|
+
text: params.textBody
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// Select a sending account (return null to skip recipient)
|
|
61
|
+
selectAgent: async (identifierId) => {
|
|
62
|
+
const account = await myAccounts.findBest();
|
|
63
|
+
return account ? { accountId: account.id } : null;
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// Map email address to your identifier system
|
|
67
|
+
findIdentifier: async (email) => {
|
|
68
|
+
const id = await myIdentifiers.findByEmail(email);
|
|
69
|
+
return id ? { id: id._id, contactId: id.contactId } : null;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
// Optional: send test emails
|
|
73
|
+
sendTestEmail: async (to, subject, html, text) => {
|
|
74
|
+
await mySmtp.send({ to, subject, html, text });
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
logger: console,
|
|
79
|
+
|
|
80
|
+
options: {
|
|
81
|
+
lockTTLMs: 30 * 60 * 1000, // 30 min lock timeout
|
|
82
|
+
defaultMaxPerRun: 500 // max users per rule execution
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Mount Express routes
|
|
87
|
+
app.use('/api/email-rules', engine.routes);
|
|
88
|
+
|
|
89
|
+
// Run rules via cron
|
|
90
|
+
cron.schedule('0 9 * * *', () => engine.runner.runAllRules());
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## API Routes
|
|
94
|
+
|
|
95
|
+
Once mounted, the engine exposes these endpoints:
|
|
96
|
+
|
|
97
|
+
### Templates
|
|
98
|
+
| Method | Path | Description |
|
|
99
|
+
|--------|------|-------------|
|
|
100
|
+
| GET | `/templates` | List all templates (filterable by category, audience, platform) |
|
|
101
|
+
| POST | `/templates` | Create new template |
|
|
102
|
+
| GET | `/templates/:id` | Get template by ID |
|
|
103
|
+
| PUT | `/templates/:id` | Update template |
|
|
104
|
+
| DELETE | `/templates/:id` | Delete template |
|
|
105
|
+
| PATCH | `/templates/:id/toggle` | Toggle active/inactive |
|
|
106
|
+
| POST | `/templates/:id/preview` | Render preview with sample data |
|
|
107
|
+
| POST | `/templates/:id/test-email` | Send test email |
|
|
108
|
+
| POST | `/templates/validate` | Validate MJML + Handlebars syntax |
|
|
109
|
+
| POST | `/templates/preview` | Preview raw template (without saving) |
|
|
110
|
+
|
|
111
|
+
### Rules
|
|
112
|
+
| Method | Path | Description |
|
|
113
|
+
|--------|------|-------------|
|
|
114
|
+
| GET | `/rules` | List all rules (with populated template info) |
|
|
115
|
+
| POST | `/rules` | Create new rule |
|
|
116
|
+
| GET | `/rules/:id` | Get rule by ID |
|
|
117
|
+
| PATCH | `/rules/:id` | Update rule |
|
|
118
|
+
| DELETE | `/rules/:id` | Delete (or disable if has send history) |
|
|
119
|
+
| PATCH | `/rules/:id/toggle` | Toggle active/inactive |
|
|
120
|
+
| POST | `/rules/:id/dry-run` | Count matching users without sending |
|
|
121
|
+
| GET | `/rules/run-history` | Get execution history |
|
|
122
|
+
|
|
123
|
+
### Runner
|
|
124
|
+
| Method | Path | Description |
|
|
125
|
+
|--------|------|-------------|
|
|
126
|
+
| POST | `/runner` | Trigger manual rule run (fire-and-forget) |
|
|
127
|
+
| GET | `/runner/status` | Get latest run result |
|
|
128
|
+
|
|
129
|
+
### Settings
|
|
130
|
+
| Method | Path | Description |
|
|
131
|
+
|--------|------|-------------|
|
|
132
|
+
| GET | `/settings/throttle` | Get throttle configuration |
|
|
133
|
+
| PATCH | `/settings/throttle` | Update throttle limits |
|
|
134
|
+
|
|
135
|
+
## Config Reference
|
|
136
|
+
|
|
137
|
+
### `EmailRuleEngineConfig`
|
|
138
|
+
|
|
139
|
+
| Field | Type | Required | Description |
|
|
140
|
+
|-------|------|----------|-------------|
|
|
141
|
+
| `db.connection` | `mongoose.Connection` | Yes | Mongoose connection for rule engine collections |
|
|
142
|
+
| `db.collectionPrefix` | `string` | No | Prefix for collection names (e.g., `'myapp_'`) |
|
|
143
|
+
| `redis.connection` | `Redis` | Yes | ioredis instance for distributed locking |
|
|
144
|
+
| `redis.keyPrefix` | `string` | No | Prefix for Redis keys (e.g., `'myapp:'`) |
|
|
145
|
+
| `platforms` | `string[]` | No | Valid platform values for schema validation |
|
|
146
|
+
| `adapters` | object | Yes | Project-specific callbacks (see below) |
|
|
147
|
+
| `logger` | `LogAdapter` | No | Logger with info/warn/error methods |
|
|
148
|
+
| `options.lockTTLMs` | `number` | No | Lock timeout in ms (default: 30 min) |
|
|
149
|
+
| `options.defaultMaxPerRun` | `number` | No | Default user limit per rule (default: 500) |
|
|
150
|
+
|
|
151
|
+
### Adapters
|
|
152
|
+
|
|
153
|
+
| Adapter | Signature | Description |
|
|
154
|
+
|---------|-----------|-------------|
|
|
155
|
+
| `queryUsers` | `(target, limit) => Promise<Record[]>` | Find users matching rule conditions |
|
|
156
|
+
| `resolveData` | `(user) => Record` | Map user to template variables |
|
|
157
|
+
| `sendEmail` | `(params) => Promise<void>` | Deliver or draft the email |
|
|
158
|
+
| `selectAgent` | `(identifierId) => Promise<{accountId} \| null>` | Pick sending account |
|
|
159
|
+
| `findIdentifier` | `(email) => Promise<{id, contactId} \| null>` | Map email to identifier |
|
|
160
|
+
| `sendTestEmail` | `(to, subject, html, text) => Promise<void>` | Optional: send test emails |
|
|
161
|
+
|
|
162
|
+
## Handlebars Helpers
|
|
163
|
+
|
|
164
|
+
Built-in template helpers available in all templates:
|
|
165
|
+
|
|
166
|
+
| Helper | Usage | Output |
|
|
167
|
+
|--------|-------|--------|
|
|
168
|
+
| `currency` | `{{currency 1500}}` | `₹1,500` |
|
|
169
|
+
| `formatDate` | `{{formatDate date}}` | `13 Mar 2026` |
|
|
170
|
+
| `capitalize` | `{{capitalize "hello"}}` | `Hello` |
|
|
171
|
+
| `lowercase` | `{{lowercase "HELLO"}}` | `hello` |
|
|
172
|
+
| `uppercase` | `{{uppercase "hello"}}` | `HELLO` |
|
|
173
|
+
| `join` | `{{join items ", "}}` | `a, b, c` |
|
|
174
|
+
| `pluralize` | `{{pluralize count "item" "items"}}` | `items` |
|
|
175
|
+
| `eq/neq/gt/lt/gte/lte` | `{{#if (eq a b)}}` | Comparison |
|
|
176
|
+
| `not` | `{{#if (not val)}}` | Negation |
|
|
177
|
+
|
|
178
|
+
## Collections Created
|
|
179
|
+
|
|
180
|
+
The engine creates these MongoDB collections (prefixed if configured):
|
|
181
|
+
|
|
182
|
+
| Collection | Purpose | TTL |
|
|
183
|
+
|------------|---------|-----|
|
|
184
|
+
| `email_templates` | MJML + Handlebars templates | - |
|
|
185
|
+
| `email_rules` | Automation rules with conditions | - |
|
|
186
|
+
| `email_rule_sends` | Per-user send tracking (dedup) | - |
|
|
187
|
+
| `email_rule_run_logs` | Execution history | 90 days |
|
|
188
|
+
| `email_throttle_config` | Throttle settings (singleton) | - |
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createTemplateController } from './template.controller';
|
|
2
|
+
export { createRuleController } from './rule.controller';
|
|
3
|
+
export { createRunnerController } from './runner.controller';
|
|
4
|
+
export { createSettingsController } from './settings.controller';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/controllers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSettingsController = exports.createRunnerController = exports.createRuleController = exports.createTemplateController = void 0;
|
|
4
|
+
var template_controller_1 = require("./template.controller");
|
|
5
|
+
Object.defineProperty(exports, "createTemplateController", { enumerable: true, get: function () { return template_controller_1.createTemplateController; } });
|
|
6
|
+
var rule_controller_1 = require("./rule.controller");
|
|
7
|
+
Object.defineProperty(exports, "createRuleController", { enumerable: true, get: function () { return rule_controller_1.createRuleController; } });
|
|
8
|
+
var runner_controller_1 = require("./runner.controller");
|
|
9
|
+
Object.defineProperty(exports, "createRunnerController", { enumerable: true, get: function () { return runner_controller_1.createRunnerController; } });
|
|
10
|
+
var settings_controller_1 = require("./settings.controller");
|
|
11
|
+
Object.defineProperty(exports, "createSettingsController", { enumerable: true, get: function () { return settings_controller_1.createSettingsController; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/controllers/index.ts"],"names":[],"mappings":";;;AAAA,6DAAiE;AAAxD,+HAAA,wBAAwB,OAAA;AACjC,qDAAyD;AAAhD,uHAAA,oBAAoB,OAAA;AAC7B,yDAA6D;AAApD,2HAAA,sBAAsB,OAAA;AAC/B,6DAAiE;AAAxD,+HAAA,wBAAwB,OAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import type { RuleService } from '../services/rule.service';
|
|
3
|
+
export declare function createRuleController(ruleService: RuleService, platformValues?: string[]): {
|
|
4
|
+
list: (_req: Request, res: Response) => Promise<void>;
|
|
5
|
+
getById: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
6
|
+
create: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
7
|
+
update: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
8
|
+
remove: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
9
|
+
toggleActive: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
10
|
+
dryRun: (req: Request, res: Response) => Promise<void>;
|
|
11
|
+
runHistory: (req: Request, res: Response) => Promise<void>;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=rule.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/rule.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAa5D,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;iBAE5D,OAAO,OAAO,QAAQ;mBAUpB,OAAO,OAAO,QAAQ;kBAavB,OAAO,OAAO,QAAQ;kBA4BtB,OAAO,OAAO,QAAQ;kBA4BtB,OAAO,OAAO,QAAQ;wBAahB,OAAO,OAAO,QAAQ;kBAa5B,OAAO,OAAO,QAAQ;sBAUlB,OAAO,OAAO,QAAQ;EAatD"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRuleController = createRuleController;
|
|
4
|
+
const enums_1 = require("../types/enums");
|
|
5
|
+
const express_helpers_1 = require("../utils/express-helpers");
|
|
6
|
+
function isValidEnum(enumObj, value) {
|
|
7
|
+
return typeof value === 'string' && Object.values(enumObj).includes(value);
|
|
8
|
+
}
|
|
9
|
+
function getErrorStatus(message) {
|
|
10
|
+
if (message.includes('not found'))
|
|
11
|
+
return 404;
|
|
12
|
+
if (message.includes('mismatch') || message.includes('validation failed') || message.includes('Cannot activate'))
|
|
13
|
+
return 400;
|
|
14
|
+
return 500;
|
|
15
|
+
}
|
|
16
|
+
function createRuleController(ruleService, platformValues) {
|
|
17
|
+
async function list(_req, res) {
|
|
18
|
+
try {
|
|
19
|
+
const rules = await ruleService.list();
|
|
20
|
+
res.json({ success: true, data: { rules } });
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
24
|
+
res.status(500).json({ success: false, error: message });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function getById(req, res) {
|
|
28
|
+
try {
|
|
29
|
+
const rule = await ruleService.getById((0, express_helpers_1.getParam)(req, 'id'));
|
|
30
|
+
if (!rule) {
|
|
31
|
+
return res.status(404).json({ success: false, error: 'Rule not found' });
|
|
32
|
+
}
|
|
33
|
+
res.json({ success: true, data: { rule } });
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
37
|
+
res.status(500).json({ success: false, error: message });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function create(req, res) {
|
|
41
|
+
try {
|
|
42
|
+
const { name, target, templateId } = req.body;
|
|
43
|
+
if (!name || !target || !templateId) {
|
|
44
|
+
return res.status(400).json({ success: false, error: 'name, target, and templateId are required' });
|
|
45
|
+
}
|
|
46
|
+
if (!target.role || !isValidEnum(enums_1.TemplateAudience, target.role)) {
|
|
47
|
+
return res.status(400).json({ success: false, error: `Invalid target.role. Must be one of: ${Object.values(enums_1.TemplateAudience).join(', ')}` });
|
|
48
|
+
}
|
|
49
|
+
if (platformValues && !platformValues.includes(target.platform)) {
|
|
50
|
+
return res.status(400).json({ success: false, error: `Invalid target.platform. Must be one of: ${platformValues.join(', ')}` });
|
|
51
|
+
}
|
|
52
|
+
if (!Array.isArray(target.conditions)) {
|
|
53
|
+
return res.status(400).json({ success: false, error: 'target.conditions must be an array' });
|
|
54
|
+
}
|
|
55
|
+
if (req.body.emailType && !isValidEnum(enums_1.EmailType, req.body.emailType)) {
|
|
56
|
+
return res.status(400).json({ success: false, error: `Invalid emailType. Must be one of: ${Object.values(enums_1.EmailType).join(', ')}` });
|
|
57
|
+
}
|
|
58
|
+
const rule = await ruleService.create(req.body);
|
|
59
|
+
res.status(201).json({ success: true, data: { rule } });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
63
|
+
res.status(getErrorStatus(message)).json({ success: false, error: message });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function update(req, res) {
|
|
67
|
+
try {
|
|
68
|
+
const { target, emailType } = req.body;
|
|
69
|
+
if (target?.role && !isValidEnum(enums_1.TemplateAudience, target.role)) {
|
|
70
|
+
return res.status(400).json({ success: false, error: `Invalid target.role. Must be one of: ${Object.values(enums_1.TemplateAudience).join(', ')}` });
|
|
71
|
+
}
|
|
72
|
+
if (target?.platform && platformValues && !platformValues.includes(target.platform)) {
|
|
73
|
+
return res.status(400).json({ success: false, error: `Invalid target.platform. Must be one of: ${platformValues.join(', ')}` });
|
|
74
|
+
}
|
|
75
|
+
if (target?.conditions && !Array.isArray(target.conditions)) {
|
|
76
|
+
return res.status(400).json({ success: false, error: 'target.conditions must be an array' });
|
|
77
|
+
}
|
|
78
|
+
if (emailType && !isValidEnum(enums_1.EmailType, emailType)) {
|
|
79
|
+
return res.status(400).json({ success: false, error: `Invalid emailType. Must be one of: ${Object.values(enums_1.EmailType).join(', ')}` });
|
|
80
|
+
}
|
|
81
|
+
const rule = await ruleService.update((0, express_helpers_1.getParam)(req, 'id'), req.body);
|
|
82
|
+
if (!rule) {
|
|
83
|
+
return res.status(404).json({ success: false, error: 'Rule not found' });
|
|
84
|
+
}
|
|
85
|
+
res.json({ success: true, data: { rule } });
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
89
|
+
res.status(getErrorStatus(message)).json({ success: false, error: message });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function remove(req, res) {
|
|
93
|
+
try {
|
|
94
|
+
const result = await ruleService.delete((0, express_helpers_1.getParam)(req, 'id'));
|
|
95
|
+
if (!result.deleted && !result.disabled) {
|
|
96
|
+
return res.status(404).json({ success: false, error: 'Rule not found' });
|
|
97
|
+
}
|
|
98
|
+
res.json({ success: true, data: result });
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
102
|
+
res.status(500).json({ success: false, error: message });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function toggleActive(req, res) {
|
|
106
|
+
try {
|
|
107
|
+
const rule = await ruleService.toggleActive((0, express_helpers_1.getParam)(req, 'id'));
|
|
108
|
+
if (!rule) {
|
|
109
|
+
return res.status(404).json({ success: false, error: 'Rule not found' });
|
|
110
|
+
}
|
|
111
|
+
res.json({ success: true, data: { rule } });
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
115
|
+
res.status(getErrorStatus(message)).json({ success: false, error: message });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function dryRun(req, res) {
|
|
119
|
+
try {
|
|
120
|
+
const result = await ruleService.dryRun((0, express_helpers_1.getParam)(req, 'id'));
|
|
121
|
+
res.json({ success: true, data: result });
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
125
|
+
res.status(getErrorStatus(message)).json({ success: false, error: message });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function runHistory(req, res) {
|
|
129
|
+
try {
|
|
130
|
+
const limitParam = req.query.limit;
|
|
131
|
+
const limit = parseInt(String(Array.isArray(limitParam) ? limitParam[0] : limitParam), 10) || 20;
|
|
132
|
+
const logs = await ruleService.getRunHistory(limit);
|
|
133
|
+
res.json({ success: true, data: { logs } });
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
137
|
+
res.status(500).json({ success: false, error: message });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return { list, getById, create, update, remove, toggleActive, dryRun, runHistory };
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=rule.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule.controller.js","sourceRoot":"","sources":["../../src/controllers/rule.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import type { RuleRunnerService } from '../services/rule-runner.service';
|
|
3
|
+
import type { EmailRuleRunLogModel } from '../schemas/run-log.schema';
|
|
4
|
+
export declare function createRunnerController(runnerService: RuleRunnerService, EmailRuleRunLog: EmailRuleRunLogModel): {
|
|
5
|
+
triggerManualRun: (_req: Request, res: Response) => Promise<void>;
|
|
6
|
+
getLatestRun: (_req: Request, res: Response) => Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=runner.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/runner.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,oBAAoB;6BAEtE,OAAO,OAAO,QAAQ;yBAK1B,OAAO,OAAO,QAAQ;EAWzD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRunnerController = createRunnerController;
|
|
4
|
+
const enums_1 = require("../types/enums");
|
|
5
|
+
function createRunnerController(runnerService, EmailRuleRunLog) {
|
|
6
|
+
async function triggerManualRun(_req, res) {
|
|
7
|
+
runnerService.runAllRules(enums_1.RunTrigger.Manual).catch(() => { });
|
|
8
|
+
res.json({ success: true, data: { message: 'Rule run triggered' } });
|
|
9
|
+
}
|
|
10
|
+
async function getLatestRun(_req, res) {
|
|
11
|
+
try {
|
|
12
|
+
const latestRun = await EmailRuleRunLog.findOne().sort({ runAt: -1 });
|
|
13
|
+
res.json({ success: true, data: { latestRun } });
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
17
|
+
res.status(500).json({ success: false, error: message });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return { triggerManualRun, getLatestRun };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=runner.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.controller.js","sourceRoot":"","sources":["../../src/controllers/runner.controller.ts"],"names":[],"mappings":";;AAKA,wDAkBC;AAtBD,0CAA4C;AAI5C,SAAgB,sBAAsB,CAAC,aAAgC,EAAE,eAAqC;IAE5G,KAAK,UAAU,gBAAgB,CAAC,IAAa,EAAE,GAAa;QAC1D,aAAa,CAAC,WAAW,CAAC,kBAAU,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC7D,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,UAAU,YAAY,CAAC,IAAa,EAAE,GAAa;QACtD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACtE,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import type { EmailThrottleConfigModel } from '../schemas/throttle-config.schema';
|
|
3
|
+
export declare function createSettingsController(EmailThrottleConfig: EmailThrottleConfigModel): {
|
|
4
|
+
getThrottleConfig: (_req: Request, res: Response) => Promise<void>;
|
|
5
|
+
updateThrottleConfig: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=settings.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/settings.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAElF,wBAAgB,wBAAwB,CAAC,mBAAmB,EAAE,wBAAwB;8BAE7C,OAAO,OAAO,QAAQ;gCAUpB,OAAO,OAAO,QAAQ;EAiDhE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSettingsController = createSettingsController;
|
|
4
|
+
function createSettingsController(EmailThrottleConfig) {
|
|
5
|
+
async function getThrottleConfig(_req, res) {
|
|
6
|
+
try {
|
|
7
|
+
const config = await EmailThrottleConfig.getConfig();
|
|
8
|
+
res.json({ success: true, data: { config } });
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
12
|
+
res.status(500).json({ success: false, error: message });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function updateThrottleConfig(req, res) {
|
|
16
|
+
try {
|
|
17
|
+
const { maxPerUserPerDay, maxPerUserPerWeek, minGapDays } = req.body;
|
|
18
|
+
const updates = {};
|
|
19
|
+
if (maxPerUserPerDay !== undefined) {
|
|
20
|
+
if (!Number.isInteger(maxPerUserPerDay) || maxPerUserPerDay < 1) {
|
|
21
|
+
return res.status(400).json({ success: false, error: 'maxPerUserPerDay must be a positive integer' });
|
|
22
|
+
}
|
|
23
|
+
updates.maxPerUserPerDay = maxPerUserPerDay;
|
|
24
|
+
}
|
|
25
|
+
if (maxPerUserPerWeek !== undefined) {
|
|
26
|
+
if (!Number.isInteger(maxPerUserPerWeek) || maxPerUserPerWeek < 1) {
|
|
27
|
+
return res.status(400).json({ success: false, error: 'maxPerUserPerWeek must be a positive integer' });
|
|
28
|
+
}
|
|
29
|
+
updates.maxPerUserPerWeek = maxPerUserPerWeek;
|
|
30
|
+
}
|
|
31
|
+
if (minGapDays !== undefined) {
|
|
32
|
+
if (!Number.isInteger(minGapDays) || minGapDays < 0) {
|
|
33
|
+
return res.status(400).json({ success: false, error: 'minGapDays must be a non-negative integer' });
|
|
34
|
+
}
|
|
35
|
+
updates.minGapDays = minGapDays;
|
|
36
|
+
}
|
|
37
|
+
if (Object.keys(updates).length === 0) {
|
|
38
|
+
return res.status(400).json({ success: false, error: 'No valid fields to update' });
|
|
39
|
+
}
|
|
40
|
+
const config = await EmailThrottleConfig.getConfig();
|
|
41
|
+
const finalDaily = updates.maxPerUserPerDay ?? config.maxPerUserPerDay;
|
|
42
|
+
const finalWeekly = updates.maxPerUserPerWeek ?? config.maxPerUserPerWeek;
|
|
43
|
+
if (finalWeekly < finalDaily) {
|
|
44
|
+
return res.status(400).json({ success: false, error: 'maxPerUserPerWeek must be >= maxPerUserPerDay' });
|
|
45
|
+
}
|
|
46
|
+
const updated = await EmailThrottleConfig.findByIdAndUpdate(config._id, { $set: updates }, { new: true });
|
|
47
|
+
res.json({ success: true, data: { config: updated } });
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
51
|
+
res.status(500).json({ success: false, error: message });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { getThrottleConfig, updateThrottleConfig };
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=settings.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.controller.js","sourceRoot":"","sources":["../../src/controllers/settings.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import type { TemplateService } from '../services/template.service';
|
|
3
|
+
export declare function createTemplateController(templateService: TemplateService, platformValues?: string[]): {
|
|
4
|
+
list: (req: Request, res: Response) => Promise<void>;
|
|
5
|
+
getById: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
6
|
+
create: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
7
|
+
update: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
8
|
+
remove: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
9
|
+
toggleActive: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
10
|
+
preview: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
11
|
+
previewRaw: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
12
|
+
validate: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
13
|
+
sendTestEmail: (req: Request, res: Response) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=template.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/template.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAapE,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,eAAe,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;gBAEzE,OAAO,OAAO,QAAQ;mBAgBnB,OAAO,OAAO,QAAQ;kBAavB,OAAO,OAAO,QAAQ;kBAyBtB,OAAO,OAAO,QAAQ;kBAatB,OAAO,OAAO,QAAQ;wBAahB,OAAO,OAAO,QAAQ;mBAa3B,OAAO,OAAO,QAAQ;sBAcnB,OAAO,OAAO,QAAQ;oBAcxB,OAAO,OAAO,QAAQ;yBAcjB,OAAO,OAAO,QAAQ;EAkBzD"}
|