@twin.org/messaging-service 0.0.1-next.2
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/LICENSE +201 -0
- package/README.md +21 -0
- package/dist/cjs/index.cjs +238 -0
- package/dist/esm/index.mjs +236 -0
- package/dist/types/entities/templateEntry.d.ts +21 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/messagingService.d.ts +74 -0
- package/docs/changelog.md +5 -0
- package/docs/examples.md +1 -0
- package/docs/open-api/spec.json +403 -0
- package/docs/reference/classes/MessagingService.md +225 -0
- package/docs/reference/index.md +5 -0
- package/locales/en.json +13 -0
- package/package.json +42 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { Is, GeneralError, Guards } from '@twin.org/core';
|
|
2
|
+
import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
|
|
3
|
+
import { MessagingEmailConnectorFactory, MessagingPushNotificationsConnectorFactory, MessagingSmsConnectorFactory } from '@twin.org/messaging-models';
|
|
4
|
+
import { property, entity } from '@twin.org/entity';
|
|
5
|
+
|
|
6
|
+
// Copyright 2024 IOTA Stiftung.
|
|
7
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
8
|
+
/**
|
|
9
|
+
* Call defining a template message entry.
|
|
10
|
+
*/
|
|
11
|
+
let TemplateEntry = class TemplateEntry {
|
|
12
|
+
/**
|
|
13
|
+
* The id.
|
|
14
|
+
*/
|
|
15
|
+
id;
|
|
16
|
+
/**
|
|
17
|
+
* The title.
|
|
18
|
+
*/
|
|
19
|
+
title;
|
|
20
|
+
/**
|
|
21
|
+
* The content.
|
|
22
|
+
*/
|
|
23
|
+
content;
|
|
24
|
+
/**
|
|
25
|
+
* The timestamp of the template entry.
|
|
26
|
+
*/
|
|
27
|
+
ts;
|
|
28
|
+
};
|
|
29
|
+
__decorate([
|
|
30
|
+
property({ type: "string", isPrimary: true }),
|
|
31
|
+
__metadata("design:type", String)
|
|
32
|
+
], TemplateEntry.prototype, "id", void 0);
|
|
33
|
+
__decorate([
|
|
34
|
+
property({ type: "string" }),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], TemplateEntry.prototype, "title", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
property({ type: "string" }),
|
|
39
|
+
__metadata("design:type", String)
|
|
40
|
+
], TemplateEntry.prototype, "content", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
property({ type: "integer" }),
|
|
43
|
+
__metadata("design:type", Number)
|
|
44
|
+
], TemplateEntry.prototype, "ts", void 0);
|
|
45
|
+
TemplateEntry = __decorate([
|
|
46
|
+
entity()
|
|
47
|
+
], TemplateEntry);
|
|
48
|
+
|
|
49
|
+
// Copyright 2024 IOTA Stiftung.
|
|
50
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
51
|
+
/**
|
|
52
|
+
* Service for performing email messaging operations to a connector.
|
|
53
|
+
*/
|
|
54
|
+
class MessagingService {
|
|
55
|
+
/**
|
|
56
|
+
* Runtime name for the class.
|
|
57
|
+
*/
|
|
58
|
+
CLASS_NAME = "MessagingService";
|
|
59
|
+
/**
|
|
60
|
+
* Emails messaging connector used by the service.
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
_emailMessagingConnector;
|
|
64
|
+
/**
|
|
65
|
+
* Push notifications messaging connector used by the service.
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
_pushNotificationMessagingConnector;
|
|
69
|
+
/**
|
|
70
|
+
* SMS messaging connector used by the service.
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
_smsMessagingConnector;
|
|
74
|
+
/**
|
|
75
|
+
* Entity storage connector used by the service.
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
_entityStorageConnector;
|
|
79
|
+
/**
|
|
80
|
+
* Create a new instance of MessagingService.
|
|
81
|
+
* @param options The options for the connector.
|
|
82
|
+
* @param options.messagingEmailConnectorType The type of the email messaging connector to use, defaults to not configured.
|
|
83
|
+
* @param options.messagingPushNotificationConnectorType The type of the push notifications messaging connector to use, defaults to not configured.
|
|
84
|
+
* @param options.messagingSmsConnectorType The type of the sms messaging connector to use, defaults to not configured.
|
|
85
|
+
* @param options.templateEntryStorageConnectorType The type of the entity connector to use, defaults to "messaging-templates".
|
|
86
|
+
*/
|
|
87
|
+
constructor(options) {
|
|
88
|
+
if (Is.stringValue(options?.messagingEmailConnectorType)) {
|
|
89
|
+
this._emailMessagingConnector = MessagingEmailConnectorFactory.get(options.messagingEmailConnectorType);
|
|
90
|
+
}
|
|
91
|
+
if (Is.stringValue(options?.messagingPushNotificationConnectorType)) {
|
|
92
|
+
this._pushNotificationMessagingConnector = MessagingPushNotificationsConnectorFactory.get(options.messagingPushNotificationConnectorType);
|
|
93
|
+
}
|
|
94
|
+
if (Is.stringValue(options?.messagingSmsConnectorType)) {
|
|
95
|
+
this._smsMessagingConnector = MessagingSmsConnectorFactory.get(options.messagingSmsConnectorType);
|
|
96
|
+
}
|
|
97
|
+
this._entityStorageConnector = EntityStorageConnectorFactory.get(options?.templateEntryStorageConnectorType ?? "template-entry");
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Send a custom email.
|
|
101
|
+
* @param sender The sender email address.
|
|
102
|
+
* @param recipients An array of recipients email addresses.
|
|
103
|
+
* @param templateId The id of the email template.
|
|
104
|
+
* @param data The data to populate the email template.
|
|
105
|
+
* @param locale The locale of the email template.
|
|
106
|
+
* @returns If the email was sent successfully.
|
|
107
|
+
*/
|
|
108
|
+
async sendCustomEmail(sender, recipients, templateId, data, locale) {
|
|
109
|
+
if (Is.empty(this._emailMessagingConnector)) {
|
|
110
|
+
throw new GeneralError(this.CLASS_NAME, "notConfiguredEmailMessagingConnector");
|
|
111
|
+
}
|
|
112
|
+
Guards.stringValue(this.CLASS_NAME, "sender", sender);
|
|
113
|
+
Guards.arrayValue(this.CLASS_NAME, "recipients", recipients);
|
|
114
|
+
Guards.stringValue(this.CLASS_NAME, "templateId", templateId);
|
|
115
|
+
Guards.object(this.CLASS_NAME, "data", data);
|
|
116
|
+
Guards.stringValue(this.CLASS_NAME, "locale", locale);
|
|
117
|
+
const template = await this.getTemplate(templateId, locale);
|
|
118
|
+
const populatedTemplate = this.populateTemplate(template, data);
|
|
119
|
+
return this._emailMessagingConnector.sendCustomEmail(sender, recipients, populatedTemplate.title, populatedTemplate.content);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Registers a device to an specific app in order to send notifications to it.
|
|
123
|
+
* @param applicationId The application address.
|
|
124
|
+
* @param deviceToken The device token.
|
|
125
|
+
* @returns If the device was registered successfully.
|
|
126
|
+
*/
|
|
127
|
+
async registerDevice(applicationId, deviceToken) {
|
|
128
|
+
if (Is.empty(this._pushNotificationMessagingConnector)) {
|
|
129
|
+
throw new GeneralError(this.CLASS_NAME, "notConfiguredPushNotificationMessagingConnector");
|
|
130
|
+
}
|
|
131
|
+
Guards.stringValue(this.CLASS_NAME, "applicationId", applicationId);
|
|
132
|
+
Guards.stringValue(this.CLASS_NAME, "deviceToken", deviceToken);
|
|
133
|
+
return this._pushNotificationMessagingConnector.registerDevice(applicationId, deviceToken);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Send a push notification to a device.
|
|
137
|
+
* @param deviceAddress The address of the device.
|
|
138
|
+
* @param templateId The id of the push notification template.
|
|
139
|
+
* @param data The data to populate the push notification template.
|
|
140
|
+
* @param locale The locale of the push notification template.
|
|
141
|
+
* @returns If the notification was sent successfully.
|
|
142
|
+
*/
|
|
143
|
+
async sendSinglePushNotification(deviceAddress, templateId, data, locale) {
|
|
144
|
+
if (Is.empty(this._pushNotificationMessagingConnector)) {
|
|
145
|
+
throw new GeneralError(this.CLASS_NAME, "notConfiguredPushNotificationMessagingConnector");
|
|
146
|
+
}
|
|
147
|
+
Guards.stringValue(this.CLASS_NAME, "deviceAddress", deviceAddress);
|
|
148
|
+
Guards.stringValue(this.CLASS_NAME, "templateId", templateId);
|
|
149
|
+
Guards.object(this.CLASS_NAME, "data", data);
|
|
150
|
+
Guards.stringValue(this.CLASS_NAME, "locale", locale);
|
|
151
|
+
const template = await this.getTemplate(templateId, locale);
|
|
152
|
+
const populatedTemplate = this.populateTemplate(template, data);
|
|
153
|
+
return this._pushNotificationMessagingConnector.sendSinglePushNotification(deviceAddress, populatedTemplate.title, populatedTemplate.content);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Send a SMS message to a phone number.
|
|
157
|
+
* @param phoneNumber The recipient phone number.
|
|
158
|
+
* @param templateId The id of the SMS template.
|
|
159
|
+
* @param data The data to populate the SMS template.
|
|
160
|
+
* @param locale The locale of the SMS template.
|
|
161
|
+
* @returns If the SMS was sent successfully.
|
|
162
|
+
*/
|
|
163
|
+
async sendSMS(phoneNumber, templateId, data, locale) {
|
|
164
|
+
if (Is.empty(this._smsMessagingConnector)) {
|
|
165
|
+
throw new GeneralError(this.CLASS_NAME, "notConfiguredSmsMessagingConnector");
|
|
166
|
+
}
|
|
167
|
+
Guards.stringValue(this.CLASS_NAME, "phoneNumber", phoneNumber);
|
|
168
|
+
Guards.stringValue(this.CLASS_NAME, "templateId", templateId);
|
|
169
|
+
Guards.object(this.CLASS_NAME, "data", data);
|
|
170
|
+
Guards.stringValue(this.CLASS_NAME, "locale", locale);
|
|
171
|
+
const template = await this.getTemplate(templateId, locale);
|
|
172
|
+
const populatedTemplate = this.populateTemplate(template, data);
|
|
173
|
+
return this._smsMessagingConnector.sendSMS(phoneNumber, populatedTemplate.content);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Create or update a template.
|
|
177
|
+
* @param templateId The id of the template.
|
|
178
|
+
* @param locale The locale of the template.
|
|
179
|
+
* @param title The title of the template.
|
|
180
|
+
* @param content The content of the template.
|
|
181
|
+
* @returns If the template was created or updated successfully.
|
|
182
|
+
*/
|
|
183
|
+
async createOrUpdateTemplate(templateId, locale, title, content) {
|
|
184
|
+
Guards.stringValue(this.CLASS_NAME, "templateId", templateId);
|
|
185
|
+
Guards.stringValue(this.CLASS_NAME, "locale", locale);
|
|
186
|
+
Guards.stringValue(this.CLASS_NAME, "title", title);
|
|
187
|
+
Guards.stringValue(this.CLASS_NAME, "content", content);
|
|
188
|
+
const templateEntry = new TemplateEntry();
|
|
189
|
+
templateEntry.id = `${templateId}:${locale}`;
|
|
190
|
+
templateEntry.ts = Date.now();
|
|
191
|
+
templateEntry.title = title;
|
|
192
|
+
templateEntry.content = content;
|
|
193
|
+
await this._entityStorageConnector.set(templateEntry);
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get the email template by id and locale.
|
|
198
|
+
* @param templateId The id of the email template.
|
|
199
|
+
* @param locale The locale of the email template.
|
|
200
|
+
* @returns The email template.
|
|
201
|
+
* @internal
|
|
202
|
+
*/
|
|
203
|
+
async getTemplate(templateId, locale) {
|
|
204
|
+
const entityId = `${templateId}:${locale}`;
|
|
205
|
+
const templateInfo = await this._entityStorageConnector.get(entityId);
|
|
206
|
+
if (!templateInfo) {
|
|
207
|
+
throw new GeneralError(this.CLASS_NAME, "getTemplateFailed", { templateId, locale });
|
|
208
|
+
}
|
|
209
|
+
return templateInfo;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Populate the template with data.
|
|
213
|
+
* @param template The template.
|
|
214
|
+
* @param template.title The title of the template.
|
|
215
|
+
* @param template.content The content of the template.
|
|
216
|
+
* @param data The data to populate the template.
|
|
217
|
+
* @internal
|
|
218
|
+
* @returns The populated template.
|
|
219
|
+
*/
|
|
220
|
+
populateTemplate(template, data) {
|
|
221
|
+
let populatedTitle = template.title;
|
|
222
|
+
let populatedContent = template.content;
|
|
223
|
+
for (const key in data) {
|
|
224
|
+
const value = data[key];
|
|
225
|
+
const placeholder = `{{${key}}}`;
|
|
226
|
+
populatedTitle = populatedTitle.replace(new RegExp(placeholder, "g"), value);
|
|
227
|
+
populatedContent = populatedContent.replace(new RegExp(placeholder, "g"), value);
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
title: populatedTitle,
|
|
231
|
+
content: populatedContent
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export { MessagingService };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Call defining a template message entry.
|
|
3
|
+
*/
|
|
4
|
+
export declare class TemplateEntry {
|
|
5
|
+
/**
|
|
6
|
+
* The id.
|
|
7
|
+
*/
|
|
8
|
+
id: string;
|
|
9
|
+
/**
|
|
10
|
+
* The title.
|
|
11
|
+
*/
|
|
12
|
+
title: string;
|
|
13
|
+
/**
|
|
14
|
+
* The content.
|
|
15
|
+
*/
|
|
16
|
+
content: string;
|
|
17
|
+
/**
|
|
18
|
+
* The timestamp of the template entry.
|
|
19
|
+
*/
|
|
20
|
+
ts: number;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./messagingService";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type IMessagingComponent } from "@twin.org/messaging-models";
|
|
2
|
+
/**
|
|
3
|
+
* Service for performing email messaging operations to a connector.
|
|
4
|
+
*/
|
|
5
|
+
export declare class MessagingService implements IMessagingComponent {
|
|
6
|
+
/**
|
|
7
|
+
* Runtime name for the class.
|
|
8
|
+
*/
|
|
9
|
+
readonly CLASS_NAME: string;
|
|
10
|
+
/**
|
|
11
|
+
* Create a new instance of MessagingService.
|
|
12
|
+
* @param options The options for the connector.
|
|
13
|
+
* @param options.messagingEmailConnectorType The type of the email messaging connector to use, defaults to not configured.
|
|
14
|
+
* @param options.messagingPushNotificationConnectorType The type of the push notifications messaging connector to use, defaults to not configured.
|
|
15
|
+
* @param options.messagingSmsConnectorType The type of the sms messaging connector to use, defaults to not configured.
|
|
16
|
+
* @param options.templateEntryStorageConnectorType The type of the entity connector to use, defaults to "messaging-templates".
|
|
17
|
+
*/
|
|
18
|
+
constructor(options?: {
|
|
19
|
+
messagingEmailConnectorType?: string;
|
|
20
|
+
messagingPushNotificationConnectorType?: string;
|
|
21
|
+
messagingSmsConnectorType?: string;
|
|
22
|
+
templateEntryStorageConnectorType?: string;
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Send a custom email.
|
|
26
|
+
* @param sender The sender email address.
|
|
27
|
+
* @param recipients An array of recipients email addresses.
|
|
28
|
+
* @param templateId The id of the email template.
|
|
29
|
+
* @param data The data to populate the email template.
|
|
30
|
+
* @param locale The locale of the email template.
|
|
31
|
+
* @returns If the email was sent successfully.
|
|
32
|
+
*/
|
|
33
|
+
sendCustomEmail(sender: string, recipients: string[], templateId: string, data: {
|
|
34
|
+
[key: string]: string;
|
|
35
|
+
}, locale: string): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Registers a device to an specific app in order to send notifications to it.
|
|
38
|
+
* @param applicationId The application address.
|
|
39
|
+
* @param deviceToken The device token.
|
|
40
|
+
* @returns If the device was registered successfully.
|
|
41
|
+
*/
|
|
42
|
+
registerDevice(applicationId: string, deviceToken: string): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Send a push notification to a device.
|
|
45
|
+
* @param deviceAddress The address of the device.
|
|
46
|
+
* @param templateId The id of the push notification template.
|
|
47
|
+
* @param data The data to populate the push notification template.
|
|
48
|
+
* @param locale The locale of the push notification template.
|
|
49
|
+
* @returns If the notification was sent successfully.
|
|
50
|
+
*/
|
|
51
|
+
sendSinglePushNotification(deviceAddress: string, templateId: string, data: {
|
|
52
|
+
[key: string]: string;
|
|
53
|
+
}, locale: string): Promise<boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* Send a SMS message to a phone number.
|
|
56
|
+
* @param phoneNumber The recipient phone number.
|
|
57
|
+
* @param templateId The id of the SMS template.
|
|
58
|
+
* @param data The data to populate the SMS template.
|
|
59
|
+
* @param locale The locale of the SMS template.
|
|
60
|
+
* @returns If the SMS was sent successfully.
|
|
61
|
+
*/
|
|
62
|
+
sendSMS(phoneNumber: string, templateId: string, data: {
|
|
63
|
+
[key: string]: string;
|
|
64
|
+
}, locale: string): Promise<boolean>;
|
|
65
|
+
/**
|
|
66
|
+
* Create or update a template.
|
|
67
|
+
* @param templateId The id of the template.
|
|
68
|
+
* @param locale The locale of the template.
|
|
69
|
+
* @param title The title of the template.
|
|
70
|
+
* @param content The content of the template.
|
|
71
|
+
* @returns If the template was created or updated successfully.
|
|
72
|
+
*/
|
|
73
|
+
createOrUpdateTemplate(templateId: string, locale: string, title: string, content: string): Promise<boolean>;
|
|
74
|
+
}
|
package/docs/examples.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @twin.org/messaging-service - Examples
|