@astralibx/email-rule-engine 14.0.1 → 14.0.3

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 CHANGED
@@ -77,6 +77,7 @@ For templates, rules, conditions, collections, joins, throttling, hooks, and the
77
77
  - [Templates & Rules](https://github.com/Hariprakash1997/astralib/blob/main/packages/rule-engine/core/docs/templates-and-rules.md)
78
78
  - [Throttling & Hooks](https://github.com/Hariprakash1997/astralib/blob/main/packages/rule-engine/core/docs/throttling-and-hooks.md)
79
79
  - [Glossary](https://github.com/Hariprakash1997/astralib/blob/main/packages/rule-engine/core/docs/glossary.md)
80
+ - [Changelog](https://github.com/Hariprakash1997/astralib/blob/main/packages/email/rule-engine/CHANGELOG.md)
80
81
 
81
82
  ## License
82
83
 
package/dist/index.cjs CHANGED
@@ -73,6 +73,8 @@ function registerEmailHelpers() {
73
73
  return d.toLocaleDateString("en-IN", DATE_FORMAT_OPTIONS);
74
74
  });
75
75
  }
76
+
77
+ // src/index.ts
76
78
  function createEmailRuleEngine(config) {
77
79
  registerEmailHelpers();
78
80
  const coreConfig = {
@@ -111,11 +113,5 @@ exports.createEmailRuleEngine = createEmailRuleEngine;
111
113
  exports.htmlToPlainText = htmlToPlainText;
112
114
  exports.registerEmailHelpers = registerEmailHelpers;
113
115
  exports.renderMjml = renderMjml;
114
- Object.keys(ruleEngine).forEach(function (k) {
115
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
116
- enumerable: true,
117
- get: function () { return ruleEngine[k]; }
118
- });
119
- });
120
116
  //# sourceMappingURL=index.cjs.map
121
117
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mjml-renderer.ts","../src/email-helpers.ts","../src/index.ts"],"names":["mjml2html","convert","Handlebars","createRuleEngine"],"mappings":"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","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"]}
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// Export email-specific utilities\nexport { renderMjml, htmlToPlainText } from './mjml-renderer';\nexport { registerEmailHelpers } from './email-helpers';\nexport type { RuleEngine } from '@astralibx/rule-engine';\n"]}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RuleEngineConfig, RuleEngine } from '@astralibx/rule-engine';
2
- export * from '@astralibx/rule-engine';
2
+ export { RuleEngine } from '@astralibx/rule-engine';
3
3
 
4
4
  declare function renderMjml(body: string): string;
5
5
  declare function htmlToPlainText(html: string): string;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RuleEngineConfig, RuleEngine } from '@astralibx/rule-engine';
2
- export * from '@astralibx/rule-engine';
2
+ export { RuleEngine } from '@astralibx/rule-engine';
3
3
 
4
4
  declare function renderMjml(body: string): string;
5
5
  declare function htmlToPlainText(html: string): string;
package/dist/index.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  import { createRuleEngine } from '@astralibx/rule-engine';
2
- export * from '@astralibx/rule-engine';
3
2
  import mjml2html from 'mjml';
4
3
  import { convert } from 'html-to-text';
5
4
  import Handlebars from 'handlebars';
@@ -67,6 +66,8 @@ function registerEmailHelpers() {
67
66
  return d.toLocaleDateString("en-IN", DATE_FORMAT_OPTIONS);
68
67
  });
69
68
  }
69
+
70
+ // src/index.ts
70
71
  function createEmailRuleEngine(config) {
71
72
  registerEmailHelpers();
72
73
  const coreConfig = {
@@ -1 +1 @@
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"]}
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// Export email-specific utilities\nexport { renderMjml, htmlToPlainText } from './mjml-renderer';\nexport { registerEmailHelpers } from './email-helpers';\nexport type { RuleEngine } from '@astralibx/rule-engine';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astralibx/email-rule-engine",
3
- "version": "14.0.1",
3
+ "version": "14.0.3",
4
4
  "description": "Email automation engine — thin wrapper over @astralibx/rule-engine with MJML rendering",
5
5
  "repository": {
6
6
  "type": "git",