@astralibx/email-rule-engine 14.0.0 → 14.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/README.md +1 -1
- package/dist/index.cjs +7 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +7 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ const engine = createEmailRuleEngine({
|
|
|
41
41
|
text: params.textBody,
|
|
42
42
|
});
|
|
43
43
|
},
|
|
44
|
-
selectAgent: async () => ({ accountId: 'default',
|
|
44
|
+
selectAgent: async () => ({ accountId: 'default', contactValue: 'noreply@myapp.com', metadata: {} }),
|
|
45
45
|
findIdentifier: async (email) => {
|
|
46
46
|
const contact = await Contact.findOne({ email });
|
|
47
47
|
return contact ? { id: contact._id.toString(), contactId: contact._id.toString() } : null;
|
package/dist/index.cjs
CHANGED
|
@@ -37,9 +37,8 @@ function renderMjml(body) {
|
|
|
37
37
|
minify: false
|
|
38
38
|
});
|
|
39
39
|
if (result.errors?.length) {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
throw new Error(`MJML compilation errors: ${critical.map((e) => e.message).join("; ")}`);
|
|
40
|
+
for (const err of result.errors) {
|
|
41
|
+
console.warn(`MJML warning: ${err.message || JSON.stringify(err)}`);
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
return result.html;
|
|
@@ -58,7 +57,10 @@ var DATE_FORMAT_OPTIONS = {
|
|
|
58
57
|
month: "short",
|
|
59
58
|
year: "numeric"
|
|
60
59
|
};
|
|
60
|
+
var registered = false;
|
|
61
61
|
function registerEmailHelpers() {
|
|
62
|
+
if (registered) return;
|
|
63
|
+
registered = true;
|
|
62
64
|
Handlebars__default.default.registerHelper("currency", (val) => {
|
|
63
65
|
const num = Number(val);
|
|
64
66
|
if (isNaN(num)) return String(val ?? "");
|
|
@@ -92,13 +94,13 @@ function createEmailRuleEngine(config) {
|
|
|
92
94
|
textBody: text,
|
|
93
95
|
ruleId: params.ruleId,
|
|
94
96
|
autoApprove: params.autoApprove,
|
|
95
|
-
attachments: params.metadata?.attachments
|
|
97
|
+
attachments: Array.isArray(params.metadata?.attachments) ? params.metadata.attachments : void 0
|
|
96
98
|
});
|
|
97
99
|
},
|
|
98
100
|
sendTest: config.adapters.sendTestEmail ? async (to, body, subject, metadata) => {
|
|
99
101
|
const html = renderMjml(body);
|
|
100
102
|
const text = htmlToPlainText(html);
|
|
101
|
-
await config.adapters.sendTestEmail(to, subject || "", html, text, metadata?.attachments
|
|
103
|
+
await config.adapters.sendTestEmail(to, subject || "", html, text, Array.isArray(metadata?.attachments) ? metadata.attachments : void 0);
|
|
102
104
|
} : void 0
|
|
103
105
|
}
|
|
104
106
|
};
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mjml-renderer.ts","../src/email-helpers.ts","../src/index.ts"],"names":["mjml2html","convert","Handlebars","createRuleEngine"],"mappings":";;;;;;;;;;;;;AAGA,IAAM,cAAA,GAAiB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAA,CAAA;AAYvB,IAAM,eAAA,GAAkB,CAAA;AAAA;AAAA;AAAA;AAAA,OAAA,CAAA;AAMjB,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,IAAK,CAAC,IAAA,CAAK,IAAA,EAAK,CAAE,UAAA,CAAW,OAAO,CAAA,EAAG;AAC9D,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,EAAK,CAAE,UAAA,CAAW,OAAO,CAAA,GAC3C,IAAA,GACA,CAAA,EAAG,cAAc,CAAA,EAAG,IAAI,GAAG,eAAe,CAAA,CAAA;AAE9C,EAAA,MAAM,MAAA,GAASA,2BAAU,QAAA,EAAU;AAAA,IACjC,eAAA,EAAiB,MAAA;AAAA,IACjB,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAQ;
|
|
1
|
+
{"version":3,"sources":["../src/mjml-renderer.ts","../src/email-helpers.ts","../src/index.ts"],"names":["mjml2html","convert","Handlebars","createRuleEngine"],"mappings":";;;;;;;;;;;;;AAGA,IAAM,cAAA,GAAiB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAA,CAAA;AAYvB,IAAM,eAAA,GAAkB,CAAA;AAAA;AAAA;AAAA;AAAA,OAAA,CAAA;AAMjB,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,IAAK,CAAC,IAAA,CAAK,IAAA,EAAK,CAAE,UAAA,CAAW,OAAO,CAAA,EAAG;AAC9D,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,EAAK,CAAE,UAAA,CAAW,OAAO,CAAA,GAC3C,IAAA,GACA,CAAA,EAAG,cAAc,CAAA,EAAG,IAAI,GAAG,eAAe,CAAA,CAAA;AAE9C,EAAA,MAAM,MAAA,GAASA,2BAAU,QAAA,EAAU;AAAA,IACjC,eAAA,EAAiB,MAAA;AAAA,IACjB,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAQ;AAEzB,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,MAAA,EAAQ;AAC/B,MAAA,OAAA,CAAQ,IAAA,CAAK,iBAAkB,GAAA,CAAY,OAAA,IAAW,KAAK,SAAA,CAAU,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,IAC7E;AAAA,EACF;AAEA,EAAA,OAAO,MAAA,CAAO,IAAA;AAChB;AAEO,SAAS,gBAAgB,IAAA,EAAsB;AACpD,EAAA,OAAOC,mBAAQ,IAAA,EAAM;AAAA,IACnB,QAAA,EAAU,EAAA;AAAA,IACV,SAAA,EAAW;AAAA,MACT,EAAE,QAAA,EAAU,GAAA,EAAK,SAAS,EAAE,wBAAA,EAA0B,MAAK,EAAE;AAAA,MAC7D,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,MAAA;AAAO;AACpC,GACD,CAAA;AACH;ACnDA,IAAM,mBAAA,GAAkD;AAAA,EACtD,GAAA,EAAK,SAAA;AAAA,EACL,KAAA,EAAO,OAAA;AAAA,EACP,IAAA,EAAM;AACR,CAAA;AAEA,IAAI,UAAA,GAAa,KAAA;AAEV,SAAS,oBAAA,GAA6B;AAC3C,EAAA,IAAI,UAAA,EAAY;AAChB,EAAA,UAAA,GAAa,IAAA;AACb,EAAAC,2BAAA,CAAW,cAAA,CAAe,UAAA,EAAY,CAAC,GAAA,KAAa;AAClD,IAAA,MAAM,GAAA,GAAM,OAAO,GAAG,CAAA;AACtB,IAAA,IAAI,MAAM,GAAG,CAAA,EAAG,OAAO,MAAA,CAAO,OAAO,EAAE,CAAA;AACvC,IAAA,OAAO,CAAA,MAAA,EAAI,GAAA,CAAI,cAAA,CAAe,OAAO,CAAC,CAAA,CAAA;AAAA,EACxC,CAAC,CAAA;AAED,EAAAA,2BAAA,CAAW,cAAA,CAAe,YAAA,EAAc,CAAC,IAAA,KAAc;AACrD,IAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,IAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAK,IAAI,CAAA;AACvB,IAAA,IAAI,MAAM,CAAA,CAAE,OAAA,EAAS,CAAA,EAAG,OAAO,OAAO,IAAI,CAAA;AAC1C,IAAA,OAAO,CAAA,CAAE,kBAAA,CAAmB,OAAA,EAAS,mBAAmB,CAAA;AAAA,EAC1D,CAAC,CAAA;AACH;ACGO,SAAS,sBAAsB,MAAA,EAA2C;AAE/E,EAAA,oBAAA,EAAqB;AAErB,EAAA,MAAM,UAAA,GAA+B;AAAA,IACnC,GAAG,MAAA;AAAA,IACH,QAAA,EAAU;AAAA,MACR,UAAA,EAAY,OAAO,QAAA,CAAS,UAAA;AAAA,MAC5B,WAAA,EAAa,OAAO,QAAA,CAAS,WAAA;AAAA,MAC7B,WAAA,EAAa,OAAO,QAAA,CAAS,WAAA;AAAA,MAC7B,cAAA,EAAgB,OAAO,QAAA,CAAS,cAAA;AAAA,MAChC,IAAA,EAAM,OAAO,MAAA,KAAuB;AAClC,QAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,CAAO,IAAI,CAAA;AACnC,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,QAAA,IAAY,eAAA,CAAgB,IAAI,CAAA;AACpD,QAAA,MAAM,MAAA,CAAO,SAAS,SAAA,CAAU;AAAA,UAC9B,cAAc,MAAA,CAAO,YAAA;AAAA,UACrB,WAAW,MAAA,CAAO,SAAA;AAAA,UAClB,WAAW,MAAA,CAAO,SAAA;AAAA,UAClB,OAAA,EAAS,OAAO,OAAA,IAAW,EAAA;AAAA,UAC3B,QAAA,EAAU,IAAA;AAAA,UACV,QAAA,EAAU,IAAA;AAAA,UACV,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf,aAAa,MAAA,CAAO,WAAA;AAAA,UACpB,WAAA,EAAa,MAAM,OAAA,CAAQ,MAAA,CAAO,UAAU,WAAW,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc;AAAA,SAC1F,CAAA;AAAA,MACH,CAAA;AAAA,MACA,QAAA,EAAU,OAAO,QAAA,CAAS,aAAA,GACtB,OAAO,EAAA,EAAY,IAAA,EAAc,SAAkB,QAAA,KAAuC;AACxF,QAAA,MAAM,IAAA,GAAO,WAAW,IAAI,CAAA;AAC5B,QAAA,MAAM,IAAA,GAAO,gBAAgB,IAAI,CAAA;AACjC,QAAA,MAAM,MAAA,CAAO,QAAA,CAAS,aAAA,CAAe,EAAA,EAAI,WAAW,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,KAAA,CAAM,QAAQ,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAAS,cAAc,MAAS,CAAA;AAAA,MAC7I,CAAA,GACA;AAAA;AACN,GACF;AAEA,EAAA,OAAOC,4BAAiB,UAAU,CAAA;AACpC","file":"index.cjs","sourcesContent":["import mjml2html from 'mjml';\nimport { convert } from 'html-to-text';\n\nconst MJML_BASE_OPEN = `<mjml>\n <mj-head>\n <mj-attributes>\n <mj-all font-family=\"Arial, sans-serif\" />\n <mj-text font-size=\"15px\" color=\"#333333\" line-height=\"1.6\" />\n </mj-attributes>\n </mj-head>\n <mj-body background-color=\"#ffffff\">\n <mj-section padding=\"20px\">\n <mj-column>\n <mj-text>`;\n\nconst MJML_BASE_CLOSE = ` </mj-text>\n </mj-column>\n </mj-section>\n </mj-body>\n</mjml>`;\n\nexport function renderMjml(body: string): string {\n if (!body.includes('<mj-') && !body.trim().startsWith('<mjml')) {\n return body;\n }\n\n const fullMjml = body.trim().startsWith('<mjml')\n ? body\n : `${MJML_BASE_OPEN}${body}${MJML_BASE_CLOSE}`;\n\n const result = mjml2html(fullMjml, {\n validationLevel: 'soft',\n minify: false,\n });\n\n if (result.errors?.length) {\n // Log all MJML warnings/errors for debugging\n for (const err of result.errors) {\n console.warn(`MJML warning: ${(err as any).message || JSON.stringify(err)}`);\n }\n }\n\n return result.html;\n}\n\nexport function htmlToPlainText(html: string): string {\n return convert(html, {\n wordwrap: 80,\n selectors: [\n { selector: 'a', options: { hideLinkHrefIfSameAsText: true } },\n { selector: 'img', format: 'skip' },\n ],\n });\n}\n","import Handlebars from 'handlebars';\n\nconst DATE_FORMAT_OPTIONS: Intl.DateTimeFormatOptions = {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n};\n\nlet registered = false;\n\nexport function registerEmailHelpers(): void {\n if (registered) return;\n registered = true;\n Handlebars.registerHelper('currency', (val: any) => {\n const num = Number(val);\n if (isNaN(num)) return String(val ?? '');\n return `₹${num.toLocaleString('en-IN')}`;\n });\n\n Handlebars.registerHelper('formatDate', (date: any) => {\n if (!date) return '';\n const d = new Date(date);\n if (isNaN(d.getTime())) return String(date);\n return d.toLocaleDateString('en-IN', DATE_FORMAT_OPTIONS);\n });\n}\n","import {\n createRuleEngine,\n type RuleEngine,\n type RuleEngineConfig,\n type SendParams,\n} from '@astralibx/rule-engine';\nimport { renderMjml, htmlToPlainText } from './mjml-renderer';\nimport { registerEmailHelpers } from './email-helpers';\n\nexport interface EmailSendParams {\n identifierId: string;\n contactId: string;\n accountId: string;\n subject: string;\n htmlBody: string;\n textBody: string;\n ruleId: string;\n autoApprove: boolean;\n attachments?: Array<{ filename: string; url: string; contentType: string }>;\n}\n\nexport interface EmailRuleEngineConfig extends Omit<RuleEngineConfig, 'adapters'> {\n adapters: Omit<RuleEngineConfig['adapters'], 'send' | 'sendTest'> & {\n sendEmail: (params: EmailSendParams) => Promise<void>;\n sendTestEmail?: (to: string, subject: string, html: string, text: string, attachments?: Array<{ filename: string; url: string; contentType: string }>) => Promise<void>;\n };\n}\n\nexport function createEmailRuleEngine(config: EmailRuleEngineConfig): RuleEngine {\n // Register email-specific helpers before engine creation\n registerEmailHelpers();\n\n const coreConfig: RuleEngineConfig = {\n ...config,\n adapters: {\n queryUsers: config.adapters.queryUsers,\n resolveData: config.adapters.resolveData,\n selectAgent: config.adapters.selectAgent,\n findIdentifier: config.adapters.findIdentifier,\n send: async (params: SendParams) => {\n const html = renderMjml(params.body);\n const text = params.textBody || htmlToPlainText(html);\n await config.adapters.sendEmail({\n identifierId: params.identifierId,\n contactId: params.contactId,\n accountId: params.accountId,\n subject: params.subject || '',\n htmlBody: html,\n textBody: text,\n ruleId: params.ruleId,\n autoApprove: params.autoApprove,\n attachments: Array.isArray(params.metadata?.attachments) ? params.metadata.attachments : undefined,\n });\n },\n sendTest: config.adapters.sendTestEmail\n ? async (to: string, body: string, subject?: string, metadata?: Record<string, unknown>) => {\n const html = renderMjml(body);\n const text = htmlToPlainText(html);\n await config.adapters.sendTestEmail!(to, subject || '', html, text, Array.isArray(metadata?.attachments) ? metadata.attachments : undefined);\n }\n : undefined,\n },\n };\n\n return createRuleEngine(coreConfig);\n}\n\n// Re-export everything from core\nexport * from '@astralibx/rule-engine';\n\n// Export email-specific utilities\nexport { renderMjml, htmlToPlainText } from './mjml-renderer';\nexport { registerEmailHelpers } from './email-helpers';\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -31,9 +31,8 @@ function renderMjml(body) {
|
|
|
31
31
|
minify: false
|
|
32
32
|
});
|
|
33
33
|
if (result.errors?.length) {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
throw new Error(`MJML compilation errors: ${critical.map((e) => e.message).join("; ")}`);
|
|
34
|
+
for (const err of result.errors) {
|
|
35
|
+
console.warn(`MJML warning: ${err.message || JSON.stringify(err)}`);
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
return result.html;
|
|
@@ -52,7 +51,10 @@ var DATE_FORMAT_OPTIONS = {
|
|
|
52
51
|
month: "short",
|
|
53
52
|
year: "numeric"
|
|
54
53
|
};
|
|
54
|
+
var registered = false;
|
|
55
55
|
function registerEmailHelpers() {
|
|
56
|
+
if (registered) return;
|
|
57
|
+
registered = true;
|
|
56
58
|
Handlebars.registerHelper("currency", (val) => {
|
|
57
59
|
const num = Number(val);
|
|
58
60
|
if (isNaN(num)) return String(val ?? "");
|
|
@@ -86,13 +88,13 @@ function createEmailRuleEngine(config) {
|
|
|
86
88
|
textBody: text,
|
|
87
89
|
ruleId: params.ruleId,
|
|
88
90
|
autoApprove: params.autoApprove,
|
|
89
|
-
attachments: params.metadata?.attachments
|
|
91
|
+
attachments: Array.isArray(params.metadata?.attachments) ? params.metadata.attachments : void 0
|
|
90
92
|
});
|
|
91
93
|
},
|
|
92
94
|
sendTest: config.adapters.sendTestEmail ? async (to, body, subject, metadata) => {
|
|
93
95
|
const html = renderMjml(body);
|
|
94
96
|
const text = htmlToPlainText(html);
|
|
95
|
-
await config.adapters.sendTestEmail(to, subject || "", html, text, metadata?.attachments
|
|
97
|
+
await config.adapters.sendTestEmail(to, subject || "", html, text, Array.isArray(metadata?.attachments) ? metadata.attachments : void 0);
|
|
96
98
|
} : void 0
|
|
97
99
|
}
|
|
98
100
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mjml-renderer.ts","../src/email-helpers.ts","../src/index.ts"],"names":[],"mappings":";;;;;;;AAGA,IAAM,cAAA,GAAiB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAA,CAAA;AAYvB,IAAM,eAAA,GAAkB,CAAA;AAAA;AAAA;AAAA;AAAA,OAAA,CAAA;AAMjB,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,IAAK,CAAC,IAAA,CAAK,IAAA,EAAK,CAAE,UAAA,CAAW,OAAO,CAAA,EAAG;AAC9D,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,EAAK,CAAE,UAAA,CAAW,OAAO,CAAA,GAC3C,IAAA,GACA,CAAA,EAAG,cAAc,CAAA,EAAG,IAAI,GAAG,eAAe,CAAA,CAAA;AAE9C,EAAA,MAAM,MAAA,GAAS,UAAU,QAAA,EAAU;AAAA,IACjC,eAAA,EAAiB,MAAA;AAAA,IACjB,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAQ;
|
|
1
|
+
{"version":3,"sources":["../src/mjml-renderer.ts","../src/email-helpers.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import mjml2html from 'mjml';\nimport { convert } from 'html-to-text';\n\nconst MJML_BASE_OPEN = `<mjml>\n <mj-head>\n <mj-attributes>\n <mj-all font-family=\"Arial, sans-serif\" />\n <mj-text font-size=\"15px\" color=\"#333333\" line-height=\"1.6\" />\n </mj-attributes>\n </mj-head>\n <mj-body background-color=\"#ffffff\">\n <mj-section padding=\"20px\">\n <mj-column>\n <mj-text>`;\n\nconst MJML_BASE_CLOSE = ` </mj-text>\n </mj-column>\n </mj-section>\n </mj-body>\n</mjml>`;\n\nexport function renderMjml(body: string): string {\n if (!body.includes('<mj-') && !body.trim().startsWith('<mjml')) {\n return body;\n }\n\n const fullMjml = body.trim().startsWith('<mjml')\n ? body\n : `${MJML_BASE_OPEN}${body}${MJML_BASE_CLOSE}`;\n\n const result = mjml2html(fullMjml, {\n validationLevel: 'soft',\n minify: false,\n });\n\n if (result.errors?.length) {\n // Log all MJML warnings/errors for debugging\n for (const err of result.errors) {\n console.warn(`MJML warning: ${(err as any).message || JSON.stringify(err)}`);\n }\n }\n\n return result.html;\n}\n\nexport function htmlToPlainText(html: string): string {\n return convert(html, {\n wordwrap: 80,\n selectors: [\n { selector: 'a', options: { hideLinkHrefIfSameAsText: true } },\n { selector: 'img', format: 'skip' },\n ],\n });\n}\n","import Handlebars from 'handlebars';\n\nconst DATE_FORMAT_OPTIONS: Intl.DateTimeFormatOptions = {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n};\n\nlet registered = false;\n\nexport function registerEmailHelpers(): void {\n if (registered) return;\n registered = true;\n Handlebars.registerHelper('currency', (val: any) => {\n const num = Number(val);\n if (isNaN(num)) return String(val ?? '');\n return `₹${num.toLocaleString('en-IN')}`;\n });\n\n Handlebars.registerHelper('formatDate', (date: any) => {\n if (!date) return '';\n const d = new Date(date);\n if (isNaN(d.getTime())) return String(date);\n return d.toLocaleDateString('en-IN', DATE_FORMAT_OPTIONS);\n });\n}\n","import {\n createRuleEngine,\n type RuleEngine,\n type RuleEngineConfig,\n type SendParams,\n} from '@astralibx/rule-engine';\nimport { renderMjml, htmlToPlainText } from './mjml-renderer';\nimport { registerEmailHelpers } from './email-helpers';\n\nexport interface EmailSendParams {\n identifierId: string;\n contactId: string;\n accountId: string;\n subject: string;\n htmlBody: string;\n textBody: string;\n ruleId: string;\n autoApprove: boolean;\n attachments?: Array<{ filename: string; url: string; contentType: string }>;\n}\n\nexport interface EmailRuleEngineConfig extends Omit<RuleEngineConfig, 'adapters'> {\n adapters: Omit<RuleEngineConfig['adapters'], 'send' | 'sendTest'> & {\n sendEmail: (params: EmailSendParams) => Promise<void>;\n sendTestEmail?: (to: string, subject: string, html: string, text: string, attachments?: Array<{ filename: string; url: string; contentType: string }>) => Promise<void>;\n };\n}\n\nexport function createEmailRuleEngine(config: EmailRuleEngineConfig): RuleEngine {\n // Register email-specific helpers before engine creation\n registerEmailHelpers();\n\n const coreConfig: RuleEngineConfig = {\n ...config,\n adapters: {\n queryUsers: config.adapters.queryUsers,\n resolveData: config.adapters.resolveData,\n selectAgent: config.adapters.selectAgent,\n findIdentifier: config.adapters.findIdentifier,\n send: async (params: SendParams) => {\n const html = renderMjml(params.body);\n const text = params.textBody || htmlToPlainText(html);\n await config.adapters.sendEmail({\n identifierId: params.identifierId,\n contactId: params.contactId,\n accountId: params.accountId,\n subject: params.subject || '',\n htmlBody: html,\n textBody: text,\n ruleId: params.ruleId,\n autoApprove: params.autoApprove,\n attachments: Array.isArray(params.metadata?.attachments) ? params.metadata.attachments : undefined,\n });\n },\n sendTest: config.adapters.sendTestEmail\n ? async (to: string, body: string, subject?: string, metadata?: Record<string, unknown>) => {\n const html = renderMjml(body);\n const text = htmlToPlainText(html);\n await config.adapters.sendTestEmail!(to, subject || '', html, text, Array.isArray(metadata?.attachments) ? metadata.attachments : undefined);\n }\n : undefined,\n },\n };\n\n return createRuleEngine(coreConfig);\n}\n\n// Re-export everything from core\nexport * from '@astralibx/rule-engine';\n\n// Export email-specific utilities\nexport { renderMjml, htmlToPlainText } from './mjml-renderer';\nexport { registerEmailHelpers } from './email-helpers';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astralibx/email-rule-engine",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.1",
|
|
4
4
|
"description": "Email automation engine — thin wrapper over @astralibx/rule-engine with MJML rendering",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"mjml": "^4.0.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@astralibx/rule-engine": "^1.0.0",
|
|
53
52
|
"express": "^4.18.0 || ^5.0.0",
|
|
53
|
+
"handlebars": "^4.7.0",
|
|
54
54
|
"ioredis": "^5.0.0",
|
|
55
55
|
"mongoose": "^7.0.0 || ^8.0.0"
|
|
56
56
|
},
|
|
@@ -60,9 +60,7 @@
|
|
|
60
60
|
"@types/node": "^22.0.0",
|
|
61
61
|
"@vitest/coverage-v8": "^3.0.0",
|
|
62
62
|
"express": "^5.0.0",
|
|
63
|
-
"html-to-text": "^9.0.5",
|
|
64
63
|
"ioredis": "^5.4.2",
|
|
65
|
-
"mjml": "^4.15.3",
|
|
66
64
|
"mongodb-memory-server": "^10.0.0",
|
|
67
65
|
"mongoose": "^8.12.1",
|
|
68
66
|
"typescript": "^5.8.2",
|