@memberjunction/communication-twilio 4.0.0 → 4.2.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 CHANGED
@@ -1,18 +1,42 @@
1
1
  # @memberjunction/communication-twilio
2
2
 
3
- A Twilio provider implementation for the MemberJunction Communication framework, enabling SMS, WhatsApp, and Facebook Messenger messaging capabilities.
4
-
5
- ## Overview
6
-
7
- This package provides a Twilio-based implementation of the MemberJunction Communication Provider interface. It supports sending and receiving messages through multiple channels:
8
-
9
- - **SMS** - Traditional text messaging
10
- - **WhatsApp** - WhatsApp Business messaging
11
- - **Facebook Messenger** - Facebook page messaging
12
-
13
- The provider automatically detects the appropriate channel based on the recipient format and handles all necessary formatting and API interactions with Twilio's services.
14
-
15
- **Note**: Twilio does not support draft messages. The `CreateDraft()` method returns an error indicating this limitation, as SMS/messaging services don't have a draft concept.
3
+ Twilio provider for the MemberJunction Communication Framework. This provider enables messaging across multiple channels -- SMS, WhatsApp Business, and Facebook Messenger -- through the Twilio API. The channel is automatically detected based on recipient format.
4
+
5
+ ## Architecture
6
+
7
+ ```mermaid
8
+ graph TD
9
+ subgraph twilio["@memberjunction/communication-twilio"]
10
+ TP["TwilioProvider"]
11
+ CFG["Config Module\n(Environment Variables)"]
12
+ CRED["TwilioCredentials"]
13
+ DETECT["Channel Detection\n(SMS / WhatsApp / Messenger)"]
14
+ end
15
+
16
+ subgraph tw["Twilio Service"]
17
+ API["Twilio REST API"]
18
+ SMS["SMS / MMS"]
19
+ WA["WhatsApp Business"]
20
+ FB["Facebook Messenger"]
21
+ end
22
+
23
+ subgraph base["@memberjunction/communication-types"]
24
+ BCP["BaseCommunicationProvider"]
25
+ end
26
+
27
+ BCP --> TP
28
+ TP --> CFG
29
+ TP --> CRED
30
+ TP --> DETECT
31
+ TP --> API
32
+ API --> SMS
33
+ API --> WA
34
+ API --> FB
35
+
36
+ style twilio fill:#2d6a9f,stroke:#1a4971,color:#fff
37
+ style tw fill:#7c5295,stroke:#563a6b,color:#fff
38
+ style base fill:#2d8659,stroke:#1a5c3a,color:#fff
39
+ ```
16
40
 
17
41
  ## Installation
18
42
 
@@ -22,260 +46,193 @@ npm install @memberjunction/communication-twilio
22
46
 
23
47
  ## Configuration
24
48
 
25
- The provider requires environment variables to be set for Twilio credentials. Create a `.env` file in your project root:
49
+ Set the following environment variables:
26
50
 
27
51
  ```env
28
- # Required - Twilio Account Credentials
29
- TWILIO_ACCOUNT_SID=your_account_sid
30
- TWILIO_AUTH_TOKEN=your_auth_token
52
+ # Required
53
+ TWILIO_ACCOUNT_SID=your-account-sid
54
+ TWILIO_AUTH_TOKEN=your-auth-token
31
55
  TWILIO_PHONE_NUMBER=+1234567890
32
56
 
33
- # Optional - For WhatsApp messaging
57
+ # Optional (for additional channels)
34
58
  TWILIO_WHATSAPP_NUMBER=+1234567890
35
-
36
- # Optional - For Facebook Messenger
37
- TWILIO_FACEBOOK_PAGE_ID=your_page_id
59
+ TWILIO_FACEBOOK_PAGE_ID=your-page-id
38
60
  ```
39
61
 
40
- ### Environment Variables
62
+ ## Channel Detection
63
+
64
+ The provider automatically selects the messaging channel based on the recipient format:
41
65
 
42
- | Variable | Required | Description |
43
- |----------|----------|-------------|
44
- | `TWILIO_ACCOUNT_SID` | Yes | Your Twilio Account SID |
45
- | `TWILIO_AUTH_TOKEN` | Yes | Your Twilio Auth Token |
46
- | `TWILIO_PHONE_NUMBER` | Yes | Your Twilio phone number for SMS |
47
- | `TWILIO_WHATSAPP_NUMBER` | No | Your Twilio WhatsApp-enabled number |
48
- | `TWILIO_FACEBOOK_PAGE_ID` | No | Your Facebook Page ID for Messenger |
66
+ ```mermaid
67
+ flowchart LR
68
+ TO["Recipient Address"] --> CHECK{"Prefix?"}
69
+ CHECK -->|"whatsapp:+1..."| WA["WhatsApp Channel"]
70
+ CHECK -->|"messenger:psid"| FB["Messenger Channel"]
71
+ CHECK -->|"+1234567890"| SMS["SMS Channel"]
49
72
 
50
- ## Usage
73
+ style TO fill:#2d6a9f,stroke:#1a4971,color:#fff
74
+ style WA fill:#2d8659,stroke:#1a5c3a,color:#fff
75
+ style FB fill:#7c5295,stroke:#563a6b,color:#fff
76
+ style SMS fill:#b8762f,stroke:#8a5722,color:#fff
77
+ ```
51
78
 
52
- ### Basic Setup
79
+ | Recipient Format | Channel | From Number Config |
80
+ |-----------------|---------|-------------------|
81
+ | `+1234567890` | SMS | `TWILIO_PHONE_NUMBER` |
82
+ | `whatsapp:+1234567890` | WhatsApp | `TWILIO_WHATSAPP_NUMBER` |
83
+ | `messenger:user_psid` | Facebook Messenger | `TWILIO_FACEBOOK_PAGE_ID` |
53
84
 
54
- ```typescript
55
- import { TwilioProvider } from '@memberjunction/communication-twilio';
85
+ ## Supported Operations
56
86
 
57
- // The provider will be automatically registered with the MemberJunction framework
58
- // via the @RegisterClass decorator when imported
59
- const provider = new TwilioProvider();
60
- ```
87
+ | Operation | Supported | Notes |
88
+ |-----------|-----------|-------|
89
+ | `SendSingleMessage` | Yes | Auto-detects channel, supports media URLs |
90
+ | `GetMessages` | Yes | Filter by from, to, dateSent |
91
+ | `ForwardMessage` | Yes | Reconstructs message body with forward prefix |
92
+ | `ReplyToMessage` | Yes | Fetches original, sends to original sender |
93
+ | `CreateDraft` | No | Messaging services have no draft concept |
94
+ | Extended operations | No | No folder, search, or attachment operations |
95
+
96
+ ## Usage
61
97
 
62
- ### Sending Messages
98
+ ### Sending SMS
63
99
 
64
- #### SMS Message
65
100
  ```typescript
66
- import { ProcessedMessage } from '@memberjunction/communication-types';
101
+ import { CommunicationEngine } from '@memberjunction/communication-engine';
102
+ import { Message } from '@memberjunction/communication-types';
67
103
 
68
- const message: ProcessedMessage = {
69
- To: '+1234567890',
70
- ProcessedBody: 'Hello from MemberJunction!',
71
- // Other required fields...
72
- };
104
+ const engine = CommunicationEngine.Instance;
105
+ await engine.Config(false, contextUser);
73
106
 
74
- const result = await provider.SendSingleMessage(message);
75
- if (result.Success) {
76
- console.log('SMS sent successfully');
77
- } else {
78
- console.error('Failed to send SMS:', result.Error);
79
- }
107
+ const message = new Message();
108
+ message.To = '+1234567890';
109
+ message.Body = 'Hello from MemberJunction!';
110
+
111
+ const result = await engine.SendSingleMessage('Twilio', 'Standard SMS', message);
80
112
  ```
81
113
 
82
- #### WhatsApp Message
114
+ ### Sending WhatsApp Message
115
+
83
116
  ```typescript
84
- const whatsappMessage: ProcessedMessage = {
85
- To: 'whatsapp:+1234567890', // Prefix with 'whatsapp:'
86
- ProcessedBody: 'Hello from WhatsApp!',
87
- // Other required fields...
88
- };
117
+ const message = new Message();
118
+ message.To = 'whatsapp:+1234567890';
119
+ message.Body = 'Hello via WhatsApp!';
89
120
 
90
- const result = await provider.SendSingleMessage(whatsappMessage);
121
+ const result = await engine.SendSingleMessage('Twilio', 'Standard SMS', message);
91
122
  ```
92
123
 
93
- #### Facebook Messenger Message
124
+ ### Sending Facebook Messenger Message
125
+
94
126
  ```typescript
95
- const messengerMessage: ProcessedMessage = {
96
- To: 'messenger:user_psid', // Prefix with 'messenger:' and use Page-Scoped ID
97
- ProcessedBody: 'Hello from Messenger!',
98
- // Other required fields...
99
- };
127
+ const message = new Message();
128
+ message.To = 'messenger:user_psid';
129
+ message.Body = 'Hello via Messenger!';
100
130
 
101
- const result = await provider.SendSingleMessage(messengerMessage);
131
+ const result = await engine.SendSingleMessage('Twilio', 'Standard SMS', message);
102
132
  ```
103
133
 
104
- #### Sending Media (MMS/WhatsApp Media)
134
+ ### Sending Media (MMS / WhatsApp)
135
+
105
136
  ```typescript
106
- const mediaMessage: ProcessedMessage = {
107
- To: '+1234567890',
108
- ProcessedBody: 'Check out this image!',
109
- ContextData: {
137
+ const message = new Message();
138
+ message.To = '+1234567890';
139
+ message.Body = 'Check out this image!';
140
+ message.ContextData = {
110
141
  mediaUrls: ['https://example.com/image.jpg']
111
- },
112
- // Other required fields...
113
142
  };
114
143
 
115
- const result = await provider.SendSingleMessage(mediaMessage);
144
+ const result = await engine.SendSingleMessage('Twilio', 'Standard SMS', message);
116
145
  ```
117
146
 
118
147
  ### Retrieving Messages
119
148
 
120
149
  ```typescript
121
- import { GetMessagesParams } from '@memberjunction/communication-types';
122
-
123
- const params: GetMessagesParams = {
124
- NumMessages: 50,
125
- ContextData: {
126
- // Optional filters
127
- from: '+1234567890',
128
- to: '+0987654321',
129
- dateSent: new Date('2024-01-01')
130
- }
131
- };
132
-
133
- const result = await provider.GetMessages(params);
134
- if (result.Success) {
135
- console.log(`Retrieved ${result.Messages.length} messages`);
136
- result.Messages.forEach(msg => {
137
- console.log(`From: ${msg.From}, Body: ${msg.Body}`);
138
- });
139
- }
150
+ const provider = engine.GetProvider('Twilio');
151
+
152
+ const result = await provider.GetMessages({
153
+ NumMessages: 50,
154
+ ContextData: {
155
+ from: '+1234567890',
156
+ to: '+0987654321',
157
+ dateSent: new Date('2025-01-01')
158
+ }
159
+ });
160
+
161
+ result.Messages.forEach(msg => {
162
+ console.log(`${msg.From} -> ${msg.To}: ${msg.Body}`);
163
+ });
140
164
  ```
141
165
 
142
- ### Replying to Messages
166
+ ### Per-Request Credentials
143
167
 
144
168
  ```typescript
145
- import { ReplyToMessageParams } from '@memberjunction/communication-types';
146
-
147
- const replyParams: ReplyToMessageParams = {
148
- MessageID: 'original_message_sid', // The Twilio Message SID
149
- Message: {
150
- ProcessedBody: 'Thanks for your message!',
151
- // Other message fields...
152
- }
153
- };
169
+ import { TwilioCredentials } from '@memberjunction/communication-twilio';
154
170
 
155
- const result = await provider.ReplyToMessage(replyParams);
156
- if (result.Success) {
157
- console.log('Reply sent successfully');
158
- }
171
+ const result = await provider.SendSingleMessage(processedMessage, {
172
+ accountSid: 'customer-sid',
173
+ authToken: 'customer-token',
174
+ phoneNumber: '+1987654321'
175
+ } as TwilioCredentials);
159
176
  ```
160
177
 
161
- ### Forwarding Messages
178
+ ### Replying to a Message
162
179
 
163
180
  ```typescript
164
- import { ForwardMessageParams } from '@memberjunction/communication-types';
165
-
166
- const forwardParams: ForwardMessageParams = {
167
- MessageID: 'message_to_forward_sid',
168
- ToRecipients: ['+1234567890', 'whatsapp:+0987654321'],
169
- Message: 'FYI - forwarding this message' // Optional comment
170
- };
171
-
172
- const result = await provider.ForwardMessage(forwardParams);
173
- if (result.Success) {
174
- console.log('Message forwarded successfully');
175
- }
181
+ const result = await provider.ReplyToMessage({
182
+ MessageID: 'original-twilio-message-sid',
183
+ Message: processedReply
184
+ });
176
185
  ```
177
186
 
178
- ## Channel Detection
179
-
180
- The provider automatically detects the communication channel based on the recipient format:
181
-
182
- - **SMS**: Standard phone number format (e.g., `+1234567890`)
183
- - **WhatsApp**: Prefixed with `whatsapp:` (e.g., `whatsapp:+1234567890`)
184
- - **Facebook Messenger**: Prefixed with `messenger:` (e.g., `messenger:user_psid`)
185
-
186
- ## API Reference
187
-
188
- ### TwilioProvider
189
-
190
- The main provider class that implements the `BaseCommunicationProvider` interface.
191
-
192
- #### Methods
193
-
194
- ##### `SendSingleMessage(message: ProcessedMessage): Promise<MessageResult>`
195
- Sends a single message through the appropriate Twilio channel.
187
+ ### Forwarding a Message
196
188
 
197
- **Parameters:**
198
- - `message`: The processed message to send
199
- - `To`: Recipient (phone number or channel-prefixed ID)
200
- - `From`: (Optional) Sender ID, defaults to configured numbers
201
- - `ProcessedBody`: The message content
202
- - `ContextData.mediaUrls`: (Optional) Array of media URLs for MMS/WhatsApp media
203
-
204
- **Returns:** `MessageResult` with success status and any error information
205
-
206
- ##### `GetMessages(params: GetMessagesParams): Promise<GetMessagesResult>`
207
- Retrieves messages from Twilio based on filter criteria.
208
-
209
- **Parameters:**
210
- - `params`: Message retrieval parameters
211
- - `NumMessages`: Maximum number of messages to retrieve
212
- - `ContextData`: Optional filters (from, to, dateSent)
213
-
214
- **Returns:** `GetMessagesResult` with retrieved messages and status
189
+ ```typescript
190
+ const result = await provider.ForwardMessage({
191
+ MessageID: 'message-sid-to-forward',
192
+ ToRecipients: ['+1234567890', 'whatsapp:+0987654321'],
193
+ Message: 'FYI - forwarding this message'
194
+ });
195
+ ```
215
196
 
216
- ##### `ReplyToMessage(params: ReplyToMessageParams): Promise<ReplyToMessageResult>`
217
- Sends a reply to a specific message.
197
+ ## TwilioCredentials
218
198
 
219
- **Parameters:**
220
- - `params`: Reply parameters
221
- - `MessageID`: The Twilio SID of the message to reply to
222
- - `Message`: The reply message content
199
+ ```typescript
200
+ interface TwilioCredentials extends ProviderCredentialsBase {
201
+ accountSid?: string;
202
+ authToken?: string;
203
+ phoneNumber?: string;
204
+ whatsappNumber?: string;
205
+ facebookPageId?: string;
206
+ disableEnvironmentFallback?: boolean;
207
+ }
208
+ ```
223
209
 
224
- **Returns:** `ReplyToMessageResult` with success status
210
+ ## Client Caching
225
211
 
226
- ##### `ForwardMessage(params: ForwardMessageParams): Promise<ForwardMessageResult>`
227
- Forwards a message to one or more recipients.
212
+ The provider caches Twilio client instances for performance. Environment credential clients are shared across all calls; per-request credential clients are cached by `accountSid`.
228
213
 
229
- **Parameters:**
230
- - `params`: Forward parameters
231
- - `MessageID`: The Twilio SID of the message to forward
232
- - `ToRecipients`: Array of recipient addresses
233
- - `Message`: (Optional) Additional comment to include
214
+ ## Important Notes
234
215
 
235
- **Returns:** `ForwardMessageResult` with success status
216
+ - SMS/messaging channels use **plain text only** -- HTML content is not supported
217
+ - Message threading is simulated using Twilio Message SIDs (Twilio has no native thread concept)
218
+ - Forwarding reconstructs the message content with a "Forwarded message" prefix
219
+ - Media attachments are supported through the `mediaUrls` context data property
220
+ - All operations are asynchronous via the Twilio REST API
236
221
 
237
222
  ## Dependencies
238
223
 
239
- This package depends on:
240
- - `@memberjunction/communication-types` - Communication provider interfaces
241
- - `@memberjunction/core` - Core MemberJunction utilities
242
- - `@memberjunction/global` - Global registration utilities
243
- - `twilio` - Official Twilio SDK
244
- - `dotenv` - Environment variable management
245
- - `env-var` - Environment variable validation
246
-
247
- ## Integration with MemberJunction
248
-
249
- This provider is automatically registered with the MemberJunction framework using the `@RegisterClass` decorator. Once imported, it becomes available for use through the MemberJunction communication system.
224
+ | Package | Purpose |
225
+ |---------|---------|
226
+ | `@memberjunction/communication-types` | Base provider class and type definitions |
227
+ | `@memberjunction/core` | Logging utilities (LogError, LogStatus) |
228
+ | `@memberjunction/global` | RegisterClass decorator |
229
+ | `twilio` | Official Twilio SDK |
230
+ | `dotenv` | Environment variable loading |
231
+ | `env-var` | Environment variable validation |
250
232
 
251
- The provider name registered is: **"Twilio"**
252
-
253
- ## Build and Development
254
-
255
- ### Building the Package
256
- ```bash
257
- npm run build
258
- ```
233
+ ## Development
259
234
 
260
- ### Cleaning Build Artifacts
261
235
  ```bash
262
- npm run clean
236
+ npm run build # Compile TypeScript
237
+ npm run clean # Remove dist directory
263
238
  ```
264
-
265
- ### TypeScript Configuration
266
- The package uses TypeScript and compiles to ES2020 with CommonJS modules. Type definitions are included in the distribution.
267
-
268
- ## Notes
269
-
270
- - The provider uses plain text for message bodies as HTML is not supported by SMS/messaging channels
271
- - Message threading is simulated using Message SIDs as Twilio doesn't have a native thread concept
272
- - Media attachments are supported through the `mediaUrls` context data property
273
- - All messages are sent asynchronously using the Twilio REST API
274
-
275
- ## Error Handling
276
-
277
- The provider includes comprehensive error handling with detailed logging through the MemberJunction logging system. All errors are caught and returned in the result objects with descriptive error messages.
278
-
279
- ## License
280
-
281
- This package is part of the MemberJunction framework. See the main repository for license information.
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
- import * as env from 'env-var';
2
- import * as dotenv from 'dotenv';
1
+ import env from 'env-var';
2
+ import dotenv from 'dotenv';
3
3
  // Load environment variables from .env file
4
4
  dotenv.config({ quiet: true });
5
5
  // Twilio credentials - now optional to support per-request credential override
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,SAAS,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,4CAA4C;AAC5C,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAE/B,+EAA+E;AAC/E,qDAAqD;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AACrF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AAEzF,yDAAyD;AACzD,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AAE/F,0DAA0D;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,SAAS,CAAC;AAC1B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAE/B,+EAA+E;AAC/E,qDAAqD;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AACrF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AAEzF,yDAAyD;AACzD,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;AAE/F,0DAA0D;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/communication-twilio",
3
3
  "type": "module",
4
- "version": "4.0.0",
4
+ "version": "4.2.0",
5
5
  "description": "Twilio provider for MemberJunction Communication framework",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -13,9 +13,9 @@
13
13
  "clean": "rimraf dist"
14
14
  },
15
15
  "dependencies": {
16
- "@memberjunction/communication-types": "4.0.0",
17
- "@memberjunction/core": "4.0.0",
18
- "@memberjunction/global": "4.0.0",
16
+ "@memberjunction/communication-types": "4.2.0",
17
+ "@memberjunction/core": "4.2.0",
18
+ "@memberjunction/global": "4.2.0",
19
19
  "dotenv": "^17.2.4",
20
20
  "env-var": "^7.4.1",
21
21
  "twilio": "^5.12.1"