@memberjunction/communication-engine 4.0.0 → 4.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 +198 -0
- package/package.json +6 -6
- package/readme.md +129 -270
package/README.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# @memberjunction/communication-engine
|
|
2
|
+
|
|
3
|
+
Server-side communication engine for MemberJunction. This package extends `CommunicationEngineBase` from `@memberjunction/communication-types` to provide the concrete implementation for sending messages, creating drafts, and managing communication runs through registered providers.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TD
|
|
9
|
+
subgraph engine["@memberjunction/communication-engine"]
|
|
10
|
+
CE["CommunicationEngine\n(Singleton)"]
|
|
11
|
+
PMS["ProcessedMessageServer"]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
subgraph base["@memberjunction/communication-types"]
|
|
15
|
+
CEB["CommunicationEngineBase"]
|
|
16
|
+
BCP["BaseCommunicationProvider"]
|
|
17
|
+
MSG["Message"]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
subgraph providers["Registered Providers"]
|
|
21
|
+
SG["SendGrid"]
|
|
22
|
+
GM["Gmail"]
|
|
23
|
+
TW["Twilio"]
|
|
24
|
+
MSP["MS Graph"]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
subgraph templates["@memberjunction/templates"]
|
|
28
|
+
TE["TemplateEngineServer"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
CEB --> CE
|
|
32
|
+
CE -->|GetProvider| BCP
|
|
33
|
+
CE -->|processes| MSG
|
|
34
|
+
MSG --> PMS
|
|
35
|
+
PMS -->|renders via| TE
|
|
36
|
+
BCP --> SG
|
|
37
|
+
BCP --> GM
|
|
38
|
+
BCP --> TW
|
|
39
|
+
BCP --> MSP
|
|
40
|
+
|
|
41
|
+
style engine fill:#7c5295,stroke:#563a6b,color:#fff
|
|
42
|
+
style base fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
43
|
+
style providers fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
44
|
+
style templates fill:#b8762f,stroke:#8a5722,color:#fff
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install @memberjunction/communication-engine
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Key Classes
|
|
54
|
+
|
|
55
|
+
### CommunicationEngine
|
|
56
|
+
|
|
57
|
+
Singleton engine that orchestrates message sending across all registered providers. Handles provider lookup via the MJGlobal class factory, message processing (template rendering), communication run lifecycle, and logging.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { CommunicationEngine } from '@memberjunction/communication-engine';
|
|
61
|
+
import { Message, MessageRecipient } from '@memberjunction/communication-types';
|
|
62
|
+
|
|
63
|
+
const engine = CommunicationEngine.Instance;
|
|
64
|
+
await engine.Config(false, contextUser);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Sending a Single Message
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const message = new Message();
|
|
71
|
+
message.From = 'sender@example.com';
|
|
72
|
+
message.To = 'recipient@example.com';
|
|
73
|
+
message.Subject = 'Welcome';
|
|
74
|
+
message.HTMLBody = '<h1>Hello</h1>';
|
|
75
|
+
|
|
76
|
+
const result = await engine.SendSingleMessage(
|
|
77
|
+
'SendGrid', // provider name
|
|
78
|
+
'Email', // provider message type name
|
|
79
|
+
message,
|
|
80
|
+
undefined, // optional CommunicationRunEntity
|
|
81
|
+
false // previewOnly
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (result.Success) {
|
|
85
|
+
console.log('Message sent');
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Sending to Multiple Recipients
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const recipients: MessageRecipient[] = [
|
|
93
|
+
{ To: 'alice@example.com', FullName: 'Alice', ContextData: { role: 'admin' } },
|
|
94
|
+
{ To: 'bob@example.com', FullName: 'Bob', ContextData: { role: 'user' } }
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
const message = new Message();
|
|
98
|
+
message.From = 'noreply@example.com';
|
|
99
|
+
message.BodyTemplate = templateEntity; // uses template for personalization
|
|
100
|
+
message.Subject = 'Update';
|
|
101
|
+
|
|
102
|
+
const results = await engine.SendMessages(
|
|
103
|
+
'SendGrid',
|
|
104
|
+
'Email',
|
|
105
|
+
message,
|
|
106
|
+
recipients,
|
|
107
|
+
false // previewOnly
|
|
108
|
+
);
|
|
109
|
+
// results is MessageResult[] - one per recipient
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Creating a Draft
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const message = new Message();
|
|
116
|
+
message.From = 'user@example.com';
|
|
117
|
+
message.To = 'recipient@example.com';
|
|
118
|
+
message.Subject = 'Draft Email';
|
|
119
|
+
message.HTMLBody = '<p>Content here</p>';
|
|
120
|
+
|
|
121
|
+
const result = await engine.CreateDraft(
|
|
122
|
+
message,
|
|
123
|
+
'Microsoft Graph', // only providers with SupportsDrafts
|
|
124
|
+
contextUser
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
if (result.Success) {
|
|
128
|
+
console.log(`Draft ID: ${result.DraftID}`);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Per-Request Credentials
|
|
133
|
+
|
|
134
|
+
All send methods accept an optional `credentials` parameter for per-request credential overrides:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { SendGridCredentials } from '@memberjunction/communication-sendgrid';
|
|
138
|
+
|
|
139
|
+
const result = await engine.SendSingleMessage(
|
|
140
|
+
'SendGrid',
|
|
141
|
+
'Email',
|
|
142
|
+
message,
|
|
143
|
+
undefined,
|
|
144
|
+
false,
|
|
145
|
+
{ apiKey: 'SG.customer-specific-key' } // per-request credentials
|
|
146
|
+
);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### ProcessedMessageServer
|
|
150
|
+
|
|
151
|
+
Server-side implementation of `ProcessedMessage` that renders templates using `TemplateEngineServer`. Automatically processes body, HTML body, and subject templates with the provided context data.
|
|
152
|
+
|
|
153
|
+
```mermaid
|
|
154
|
+
sequenceDiagram
|
|
155
|
+
participant App as Application
|
|
156
|
+
participant CE as CommunicationEngine
|
|
157
|
+
participant PMS as ProcessedMessageServer
|
|
158
|
+
participant TE as TemplateEngineServer
|
|
159
|
+
participant P as Provider
|
|
160
|
+
|
|
161
|
+
App->>CE: SendSingleMessage(providerName, messageType, message)
|
|
162
|
+
CE->>CE: GetProvider(providerName)
|
|
163
|
+
CE->>PMS: new ProcessedMessageServer(message)
|
|
164
|
+
CE->>PMS: Process()
|
|
165
|
+
PMS->>TE: RenderTemplate(bodyTemplate, contextData)
|
|
166
|
+
TE-->>PMS: rendered content
|
|
167
|
+
PMS-->>CE: ProcessResult
|
|
168
|
+
CE->>P: SendSingleMessage(processedMessage, credentials)
|
|
169
|
+
P-->>CE: MessageResult
|
|
170
|
+
CE-->>App: MessageResult
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## API Reference
|
|
174
|
+
|
|
175
|
+
| Method | Description |
|
|
176
|
+
|--------|-------------|
|
|
177
|
+
| `Config(forceRefresh, contextUser, provider)` | Initialize the engine and load metadata |
|
|
178
|
+
| `GetProvider(providerName)` | Retrieve a provider instance from the class factory |
|
|
179
|
+
| `SendSingleMessage(provider, type, message, run?, preview?, credentials?)` | Send one message |
|
|
180
|
+
| `SendMessages(provider, type, message, recipients, preview?, credentials?)` | Send to multiple recipients |
|
|
181
|
+
| `CreateDraft(message, providerName, contextUser?, credentials?)` | Create a draft message |
|
|
182
|
+
|
|
183
|
+
## Dependencies
|
|
184
|
+
|
|
185
|
+
| Package | Purpose |
|
|
186
|
+
|---------|---------|
|
|
187
|
+
| `@memberjunction/communication-types` | Base engine, provider, and message types |
|
|
188
|
+
| `@memberjunction/core` | UserInfo, logging, metadata access |
|
|
189
|
+
| `@memberjunction/core-entities` | CommunicationRunEntity and related entities |
|
|
190
|
+
| `@memberjunction/global` | MJGlobal class factory for provider instantiation |
|
|
191
|
+
| `@memberjunction/templates` | Server-side template rendering engine |
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
npm run build # Compile TypeScript
|
|
197
|
+
npm start # Watch mode
|
|
198
|
+
```
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/communication-engine",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.1.0",
|
|
5
5
|
"description": "MemberJunction: Core Communication Framework Library",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"typescript": "^5.9.3"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@memberjunction/global": "4.
|
|
24
|
-
"@memberjunction/core": "4.
|
|
25
|
-
"@memberjunction/templates": "4.
|
|
26
|
-
"@memberjunction/core-entities": "4.
|
|
27
|
-
"@memberjunction/communication-types": "4.
|
|
23
|
+
"@memberjunction/global": "4.1.0",
|
|
24
|
+
"@memberjunction/core": "4.1.0",
|
|
25
|
+
"@memberjunction/templates": "4.1.0",
|
|
26
|
+
"@memberjunction/core-entities": "4.1.0",
|
|
27
|
+
"@memberjunction/communication-types": "4.1.0",
|
|
28
28
|
"rxjs": "^7.8.2"
|
|
29
29
|
},
|
|
30
30
|
"repository": {
|
package/readme.md
CHANGED
|
@@ -1,16 +1,48 @@
|
|
|
1
1
|
# @memberjunction/communication-engine
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
Server-side communication engine for MemberJunction. This package extends `CommunicationEngineBase` from `@memberjunction/communication-types` to provide the concrete implementation for sending messages, creating drafts, and managing communication runs through registered providers.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TD
|
|
9
|
+
subgraph engine["@memberjunction/communication-engine"]
|
|
10
|
+
CE["CommunicationEngine\n(Singleton)"]
|
|
11
|
+
PMS["ProcessedMessageServer"]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
subgraph base["@memberjunction/communication-types"]
|
|
15
|
+
CEB["CommunicationEngineBase"]
|
|
16
|
+
BCP["BaseCommunicationProvider"]
|
|
17
|
+
MSG["Message"]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
subgraph providers["Registered Providers"]
|
|
21
|
+
SG["SendGrid"]
|
|
22
|
+
GM["Gmail"]
|
|
23
|
+
TW["Twilio"]
|
|
24
|
+
MSP["MS Graph"]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
subgraph templates["@memberjunction/templates"]
|
|
28
|
+
TE["TemplateEngineServer"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
CEB --> CE
|
|
32
|
+
CE -->|GetProvider| BCP
|
|
33
|
+
CE -->|processes| MSG
|
|
34
|
+
MSG --> PMS
|
|
35
|
+
PMS -->|renders via| TE
|
|
36
|
+
BCP --> SG
|
|
37
|
+
BCP --> GM
|
|
38
|
+
BCP --> TW
|
|
39
|
+
BCP --> MSP
|
|
40
|
+
|
|
41
|
+
style engine fill:#7c5295,stroke:#563a6b,color:#fff
|
|
42
|
+
style base fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
43
|
+
style providers fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
44
|
+
style templates fill:#b8762f,stroke:#8a5722,color:#fff
|
|
45
|
+
```
|
|
14
46
|
|
|
15
47
|
## Installation
|
|
16
48
|
|
|
@@ -18,322 +50,149 @@ This package serves as the core engine for the MemberJunction communication syst
|
|
|
18
50
|
npm install @memberjunction/communication-engine
|
|
19
51
|
```
|
|
20
52
|
|
|
21
|
-
##
|
|
53
|
+
## Key Classes
|
|
22
54
|
|
|
23
55
|
### CommunicationEngine
|
|
24
56
|
|
|
25
|
-
|
|
57
|
+
Singleton engine that orchestrates message sending across all registered providers. Handles provider lookup via the MJGlobal class factory, message processing (template rendering), communication run lifecycle, and logging.
|
|
26
58
|
|
|
27
59
|
```typescript
|
|
28
60
|
import { CommunicationEngine } from '@memberjunction/communication-engine';
|
|
61
|
+
import { Message, MessageRecipient } from '@memberjunction/communication-types';
|
|
29
62
|
|
|
30
|
-
// Get the singleton instance
|
|
31
63
|
const engine = CommunicationEngine.Instance;
|
|
32
|
-
|
|
33
|
-
// Configuration must be called before use
|
|
34
|
-
await engine.Config();
|
|
64
|
+
await engine.Config(false, contextUser);
|
|
35
65
|
```
|
|
36
66
|
|
|
37
|
-
### ProcessedMessageServer
|
|
38
|
-
|
|
39
|
-
Server-side message processor that handles template rendering for message bodies, HTML bodies, and subjects.
|
|
40
|
-
|
|
41
|
-
## Usage Examples
|
|
42
|
-
|
|
43
67
|
### Sending a Single Message
|
|
44
68
|
|
|
45
69
|
```typescript
|
|
46
|
-
import { CommunicationEngine } from '@memberjunction/communication-engine';
|
|
47
|
-
import { Message } from '@memberjunction/communication-types';
|
|
48
|
-
|
|
49
|
-
// Create a message
|
|
50
70
|
const message = new Message();
|
|
51
|
-
message.
|
|
52
|
-
message.
|
|
53
|
-
message.
|
|
54
|
-
message.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
'
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
message.From = 'sender@example.com';
|
|
72
|
+
message.To = 'recipient@example.com';
|
|
73
|
+
message.Subject = 'Welcome';
|
|
74
|
+
message.HTMLBody = '<h1>Hello</h1>';
|
|
75
|
+
|
|
76
|
+
const result = await engine.SendSingleMessage(
|
|
77
|
+
'SendGrid', // provider name
|
|
78
|
+
'Email', // provider message type name
|
|
79
|
+
message,
|
|
80
|
+
undefined, // optional CommunicationRunEntity
|
|
81
|
+
false // previewOnly
|
|
61
82
|
);
|
|
62
83
|
|
|
63
84
|
if (result.Success) {
|
|
64
|
-
console.log('Message sent
|
|
65
|
-
} else {
|
|
66
|
-
console.error('Failed to send:', result.Error);
|
|
85
|
+
console.log('Message sent');
|
|
67
86
|
}
|
|
68
87
|
```
|
|
69
88
|
|
|
70
|
-
### Sending
|
|
89
|
+
### Sending to Multiple Recipients
|
|
71
90
|
|
|
72
91
|
```typescript
|
|
73
|
-
import { CommunicationEngine } from '@memberjunction/communication-engine';
|
|
74
|
-
import { Message } from '@memberjunction/communication-types';
|
|
75
|
-
import { Metadata } from '@memberjunction/core';
|
|
76
|
-
|
|
77
|
-
// Get template from metadata
|
|
78
|
-
const md = new Metadata();
|
|
79
|
-
const template = await md.GetEntityObject('Templates');
|
|
80
|
-
await template.LoadByName('Welcome Email');
|
|
81
|
-
|
|
82
|
-
// Create message with template
|
|
83
|
-
const message = new Message();
|
|
84
|
-
message.BodyTemplate = template;
|
|
85
|
-
message.To = 'user@example.com';
|
|
86
|
-
message.From = 'noreply@memberjunction.com';
|
|
87
|
-
message.ContextData = {
|
|
88
|
-
firstName: 'John',
|
|
89
|
-
accountType: 'Premium',
|
|
90
|
-
activationDate: new Date()
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
// Send the message - templates will be automatically processed
|
|
94
|
-
const result = await CommunicationEngine.Instance.SendSingleMessage(
|
|
95
|
-
'SendGrid',
|
|
96
|
-
'Email',
|
|
97
|
-
message
|
|
98
|
-
);
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Batch Message Sending
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
import { CommunicationEngine } from '@memberjunction/communication-engine';
|
|
105
|
-
import { Message, MessageRecipient } from '@memberjunction/communication-types';
|
|
106
|
-
|
|
107
|
-
// Create base message
|
|
108
|
-
const baseMessage = new Message();
|
|
109
|
-
baseMessage.Subject = 'Monthly Newsletter';
|
|
110
|
-
baseMessage.BodyTemplate = newsletterTemplate;
|
|
111
|
-
baseMessage.From = 'newsletter@memberjunction.com';
|
|
112
|
-
|
|
113
|
-
// Create recipient list with individual context data
|
|
114
92
|
const recipients: MessageRecipient[] = [
|
|
115
|
-
{
|
|
116
|
-
|
|
117
|
-
ContextData: { name: 'Alice', memberSince: '2023' }
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
To: 'user2@example.com',
|
|
121
|
-
ContextData: { name: 'Bob', memberSince: '2022' }
|
|
122
|
-
}
|
|
93
|
+
{ To: 'alice@example.com', FullName: 'Alice', ContextData: { role: 'admin' } },
|
|
94
|
+
{ To: 'bob@example.com', FullName: 'Bob', ContextData: { role: 'user' } }
|
|
123
95
|
];
|
|
124
96
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
baseMessage,
|
|
130
|
-
recipients
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
// Check results
|
|
134
|
-
results.forEach((result, index) => {
|
|
135
|
-
if (result.Success) {
|
|
136
|
-
console.log(`Sent to ${recipients[index].To}`);
|
|
137
|
-
} else {
|
|
138
|
-
console.error(`Failed for ${recipients[index].To}: ${result.Error}`);
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Preview Mode
|
|
144
|
-
|
|
145
|
-
You can preview processed messages without actually sending them:
|
|
97
|
+
const message = new Message();
|
|
98
|
+
message.From = 'noreply@example.com';
|
|
99
|
+
message.BodyTemplate = templateEntity; // uses template for personalization
|
|
100
|
+
message.Subject = 'Update';
|
|
146
101
|
|
|
147
|
-
|
|
148
|
-
const result = await CommunicationEngine.Instance.SendSingleMessage(
|
|
102
|
+
const results = await engine.SendMessages(
|
|
149
103
|
'SendGrid',
|
|
150
104
|
'Email',
|
|
151
105
|
message,
|
|
152
|
-
|
|
153
|
-
|
|
106
|
+
recipients,
|
|
107
|
+
false // previewOnly
|
|
154
108
|
);
|
|
155
|
-
|
|
156
|
-
if (result.Success) {
|
|
157
|
-
const processedMessage = result.Message;
|
|
158
|
-
console.log('Subject:', processedMessage.ProcessedSubject);
|
|
159
|
-
console.log('Body:', processedMessage.ProcessedBody);
|
|
160
|
-
console.log('HTML Body:', processedMessage.ProcessedHTMLBody);
|
|
161
|
-
}
|
|
109
|
+
// results is MessageResult[] - one per recipient
|
|
162
110
|
```
|
|
163
111
|
|
|
164
|
-
### Creating Draft
|
|
165
|
-
|
|
166
|
-
Create draft messages that can be edited and sent later (only supported by providers with mailbox access):
|
|
112
|
+
### Creating a Draft
|
|
167
113
|
|
|
168
114
|
```typescript
|
|
169
|
-
import { CommunicationEngine } from '@memberjunction/communication-engine';
|
|
170
|
-
import { Message } from '@memberjunction/communication-types';
|
|
171
|
-
|
|
172
|
-
// Get the engine instance
|
|
173
|
-
const engine = CommunicationEngine.Instance;
|
|
174
|
-
await engine.Config();
|
|
175
|
-
|
|
176
|
-
// Create a message
|
|
177
115
|
const message = new Message();
|
|
116
|
+
message.From = 'user@example.com';
|
|
178
117
|
message.To = 'recipient@example.com';
|
|
179
|
-
message.
|
|
180
|
-
message.
|
|
181
|
-
message.Body = 'This is a draft message that can be edited later';
|
|
118
|
+
message.Subject = 'Draft Email';
|
|
119
|
+
message.HTMLBody = '<p>Content here</p>';
|
|
182
120
|
|
|
183
|
-
// Create draft using Gmail (or 'Microsoft Graph')
|
|
184
121
|
const result = await engine.CreateDraft(
|
|
185
122
|
message,
|
|
186
|
-
'
|
|
123
|
+
'Microsoft Graph', // only providers with SupportsDrafts
|
|
187
124
|
contextUser
|
|
188
125
|
);
|
|
189
126
|
|
|
190
127
|
if (result.Success) {
|
|
191
|
-
console.log(`Draft
|
|
192
|
-
// Draft can now be edited or sent through the provider's native interface
|
|
193
|
-
} else {
|
|
194
|
-
console.error(`Failed to create draft: ${result.ErrorMessage}`);
|
|
128
|
+
console.log(`Draft ID: ${result.DraftID}`);
|
|
195
129
|
}
|
|
196
130
|
```
|
|
197
131
|
|
|
198
|
-
|
|
199
|
-
- **Gmail**: Drafts created in Gmail drafts folder
|
|
200
|
-
- **Microsoft Graph**: Drafts created in Outlook/Exchange drafts folder
|
|
201
|
-
|
|
202
|
-
**Providers NOT Supporting Drafts**:
|
|
203
|
-
- **SendGrid**: Service-based email, no mailbox
|
|
204
|
-
- **Twilio**: SMS/messaging service, no draft concept
|
|
132
|
+
### Per-Request Credentials
|
|
205
133
|
|
|
206
|
-
|
|
134
|
+
All send methods accept an optional `credentials` parameter for per-request credential overrides:
|
|
207
135
|
|
|
208
136
|
```typescript
|
|
209
|
-
|
|
210
|
-
const provider = CommunicationEngine.Instance.GetProvider('SendGrid');
|
|
211
|
-
|
|
212
|
-
// List all available providers
|
|
213
|
-
const providers = CommunicationEngine.Instance.Providers;
|
|
214
|
-
providers.forEach(p => {
|
|
215
|
-
console.log(`Provider: ${p.Name}`);
|
|
216
|
-
p.MessageTypes.forEach(mt => {
|
|
217
|
-
console.log(` - ${mt.Name}`);
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## API Reference
|
|
223
|
-
|
|
224
|
-
### CommunicationEngine
|
|
225
|
-
|
|
226
|
-
#### Properties
|
|
227
|
-
|
|
228
|
-
- `Instance: CommunicationEngine` - Static singleton instance
|
|
229
|
-
- `Providers: CommunicationProviderEntity[]` - List of configured providers
|
|
230
|
-
- `Loaded: boolean` - Whether metadata has been loaded
|
|
231
|
-
|
|
232
|
-
#### Methods
|
|
233
|
-
|
|
234
|
-
##### `Config(contextUser?: UserInfo): Promise<void>`
|
|
235
|
-
Initializes the engine with metadata. Must be called before using other methods.
|
|
137
|
+
import { SendGridCredentials } from '@memberjunction/communication-sendgrid';
|
|
236
138
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
- `message`: The message to send
|
|
247
|
-
- `run`: Optional communication run for grouping messages
|
|
248
|
-
- `previewOnly`: If true, processes templates but doesn't send
|
|
249
|
-
|
|
250
|
-
##### `SendMessages(providerName: string, providerMessageTypeName: string, message: Message, recipients: MessageRecipient[], previewOnly?: boolean): Promise<MessageResult[]>`
|
|
251
|
-
Sends messages to multiple recipients in a single run.
|
|
252
|
-
|
|
253
|
-
##### `CreateDraft(message: Message, providerName: string, contextUser?: UserInfo): Promise<CreateDraftResult>`
|
|
254
|
-
Creates a draft message using the specified provider.
|
|
255
|
-
|
|
256
|
-
Parameters:
|
|
257
|
-
- `message`: The message to save as a draft
|
|
258
|
-
- `providerName`: Name of the provider (must support drafts, e.g., 'Gmail', 'Microsoft Graph')
|
|
259
|
-
- `contextUser`: Optional user context for server-side operations
|
|
260
|
-
|
|
261
|
-
Returns a `CreateDraftResult` with:
|
|
262
|
-
- `Success`: Whether the draft was created successfully
|
|
263
|
-
- `DraftID`: The provider-specific draft identifier (if successful)
|
|
264
|
-
- `ErrorMessage`: Error details (if failed)
|
|
265
|
-
|
|
266
|
-
**Note**: Only providers with mailbox access support drafts (Gmail, MS Graph). Service-based providers (SendGrid, Twilio) will return an error.
|
|
139
|
+
const result = await engine.SendSingleMessage(
|
|
140
|
+
'SendGrid',
|
|
141
|
+
'Email',
|
|
142
|
+
message,
|
|
143
|
+
undefined,
|
|
144
|
+
false,
|
|
145
|
+
{ apiKey: 'SG.customer-specific-key' } // per-request credentials
|
|
146
|
+
);
|
|
147
|
+
```
|
|
267
148
|
|
|
268
149
|
### ProcessedMessageServer
|
|
269
150
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
## Error Handling
|
|
292
|
-
|
|
293
|
-
The engine provides detailed error messages for common scenarios:
|
|
294
|
-
|
|
295
|
-
- Provider not found
|
|
296
|
-
- Provider message type not found
|
|
297
|
-
- Template rendering failures
|
|
298
|
-
- Communication run failures
|
|
299
|
-
- Missing required template content types
|
|
300
|
-
|
|
301
|
-
Always wrap communication calls in try-catch blocks:
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
try {
|
|
305
|
-
const result = await CommunicationEngine.Instance.SendSingleMessage(...);
|
|
306
|
-
if (!result.Success) {
|
|
307
|
-
// Handle send failure
|
|
308
|
-
console.error(result.Error);
|
|
309
|
-
}
|
|
310
|
-
} catch (error) {
|
|
311
|
-
// Handle engine errors
|
|
312
|
-
console.error('Engine error:', error.message);
|
|
313
|
-
}
|
|
151
|
+
Server-side implementation of `ProcessedMessage` that renders templates using `TemplateEngineServer`. Automatically processes body, HTML body, and subject templates with the provided context data.
|
|
152
|
+
|
|
153
|
+
```mermaid
|
|
154
|
+
sequenceDiagram
|
|
155
|
+
participant App as Application
|
|
156
|
+
participant CE as CommunicationEngine
|
|
157
|
+
participant PMS as ProcessedMessageServer
|
|
158
|
+
participant TE as TemplateEngineServer
|
|
159
|
+
participant P as Provider
|
|
160
|
+
|
|
161
|
+
App->>CE: SendSingleMessage(providerName, messageType, message)
|
|
162
|
+
CE->>CE: GetProvider(providerName)
|
|
163
|
+
CE->>PMS: new ProcessedMessageServer(message)
|
|
164
|
+
CE->>PMS: Process()
|
|
165
|
+
PMS->>TE: RenderTemplate(bodyTemplate, contextData)
|
|
166
|
+
TE-->>PMS: rendered content
|
|
167
|
+
PMS-->>CE: ProcessResult
|
|
168
|
+
CE->>P: SendSingleMessage(processedMessage, credentials)
|
|
169
|
+
P-->>CE: MessageResult
|
|
170
|
+
CE-->>App: MessageResult
|
|
314
171
|
```
|
|
315
172
|
|
|
316
|
-
##
|
|
317
|
-
|
|
318
|
-
- `@memberjunction/global`: Core MemberJunction utilities
|
|
319
|
-
- `@memberjunction/core`: Core MemberJunction functionality
|
|
320
|
-
- `@memberjunction/templates`: Template engine integration
|
|
321
|
-
- `@memberjunction/core-entities`: Entity definitions
|
|
322
|
-
- `@memberjunction/communication-types`: Type definitions
|
|
323
|
-
- `rxjs`: Reactive Extensions for JavaScript
|
|
324
|
-
|
|
325
|
-
## Integration with Other MJ Packages
|
|
326
|
-
|
|
327
|
-
This package integrates seamlessly with:
|
|
173
|
+
## API Reference
|
|
328
174
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
175
|
+
| Method | Description |
|
|
176
|
+
|--------|-------------|
|
|
177
|
+
| `Config(forceRefresh, contextUser, provider)` | Initialize the engine and load metadata |
|
|
178
|
+
| `GetProvider(providerName)` | Retrieve a provider instance from the class factory |
|
|
179
|
+
| `SendSingleMessage(provider, type, message, run?, preview?, credentials?)` | Send one message |
|
|
180
|
+
| `SendMessages(provider, type, message, recipients, preview?, credentials?)` | Send to multiple recipients |
|
|
181
|
+
| `CreateDraft(message, providerName, contextUser?, credentials?)` | Create a draft message |
|
|
332
182
|
|
|
333
|
-
##
|
|
183
|
+
## Dependencies
|
|
334
184
|
|
|
335
|
-
|
|
185
|
+
| Package | Purpose |
|
|
186
|
+
|---------|---------|
|
|
187
|
+
| `@memberjunction/communication-types` | Base engine, provider, and message types |
|
|
188
|
+
| `@memberjunction/core` | UserInfo, logging, metadata access |
|
|
189
|
+
| `@memberjunction/core-entities` | CommunicationRunEntity and related entities |
|
|
190
|
+
| `@memberjunction/global` | MJGlobal class factory for provider instantiation |
|
|
191
|
+
| `@memberjunction/templates` | Server-side template rendering engine |
|
|
336
192
|
|
|
337
|
-
##
|
|
193
|
+
## Development
|
|
338
194
|
|
|
339
|
-
|
|
195
|
+
```bash
|
|
196
|
+
npm run build # Compile TypeScript
|
|
197
|
+
npm start # Watch mode
|
|
198
|
+
```
|