@onivoro/server-aws-sns 24.39.0 → 25.0.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/README.md +31 -128
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ AWS SNS integration for NestJS applications.
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @onivoro/server-aws-sns
|
|
8
|
+
npm install @onivoro/server-aws-sns @aws-sdk/client-sns
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Overview
|
|
@@ -20,23 +20,30 @@ import { ServerAwsSnsModule } from '@onivoro/server-aws-sns';
|
|
|
20
20
|
|
|
21
21
|
@Module({
|
|
22
22
|
imports: [
|
|
23
|
-
ServerAwsSnsModule.configure(
|
|
24
|
-
|
|
23
|
+
ServerAwsSnsModule.configure({
|
|
24
|
+
AWS_REGION: process.env.AWS_REGION!,
|
|
25
|
+
AWS_PROFILE: process.env.AWS_PROFILE, // optional
|
|
26
|
+
}),
|
|
27
|
+
],
|
|
25
28
|
})
|
|
26
29
|
export class AppModule {}
|
|
27
30
|
```
|
|
28
31
|
|
|
29
32
|
## Configuration
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
`configure()` takes the config object directly; the module does not read environment variables itself.
|
|
32
35
|
|
|
33
36
|
```typescript
|
|
34
37
|
export class ServerAwsSnsConfig {
|
|
38
|
+
AWS_PROFILE?: string;
|
|
35
39
|
AWS_REGION: string;
|
|
36
|
-
AWS_PROFILE?: string; // Optional AWS profile
|
|
37
40
|
}
|
|
38
41
|
```
|
|
39
42
|
|
|
43
|
+
Credentials come from [`@onivoro/server-aws-credential-providers`](../aws-credential-providers/): when `AWS_PROFILE` is set the named profile is used, otherwise the AWS SDK default credential chain applies.
|
|
44
|
+
|
|
45
|
+
The module provides and exports an `SNSClient` (configured with `AWS_REGION`) and `ServerAwsSnsConfig`.
|
|
46
|
+
|
|
40
47
|
## Usage
|
|
41
48
|
|
|
42
49
|
This module provides only the SNS client injection. There is no custom service implementation. You need to inject the SNS client directly and use AWS SDK methods:
|
|
@@ -54,9 +61,9 @@ export class NotificationService {
|
|
|
54
61
|
const command = new PublishCommand({
|
|
55
62
|
TopicArn: topicArn,
|
|
56
63
|
Message: message,
|
|
57
|
-
Subject: subject
|
|
64
|
+
Subject: subject,
|
|
58
65
|
});
|
|
59
|
-
|
|
66
|
+
|
|
60
67
|
return await this.snsClient.send(command);
|
|
61
68
|
}
|
|
62
69
|
|
|
@@ -64,18 +71,18 @@ export class NotificationService {
|
|
|
64
71
|
async sendSMS(phoneNumber: string, message: string) {
|
|
65
72
|
const command = new PublishCommand({
|
|
66
73
|
PhoneNumber: phoneNumber,
|
|
67
|
-
Message: message
|
|
74
|
+
Message: message,
|
|
68
75
|
});
|
|
69
|
-
|
|
76
|
+
|
|
70
77
|
return await this.snsClient.send(command);
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
// Create topic
|
|
74
81
|
async createTopic(topicName: string) {
|
|
75
82
|
const command = new CreateTopicCommand({
|
|
76
|
-
Name: topicName
|
|
83
|
+
Name: topicName,
|
|
77
84
|
});
|
|
78
|
-
|
|
85
|
+
|
|
79
86
|
const response = await this.snsClient.send(command);
|
|
80
87
|
return response.TopicArn;
|
|
81
88
|
}
|
|
@@ -85,109 +92,10 @@ export class NotificationService {
|
|
|
85
92
|
const command = new SubscribeCommand({
|
|
86
93
|
TopicArn: topicArn,
|
|
87
94
|
Protocol: 'email',
|
|
88
|
-
Endpoint: email
|
|
95
|
+
Endpoint: email,
|
|
89
96
|
});
|
|
90
|
-
|
|
91
|
-
return await this.snsClient.send(command);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Complete Example
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
import { Module, Injectable, Controller, Post, Body } from '@nestjs/common';
|
|
100
|
-
import { ServerAwsSnsModule } from '@onivoro/server-aws-sns';
|
|
101
|
-
import {
|
|
102
|
-
SNSClient,
|
|
103
|
-
PublishCommand,
|
|
104
|
-
CreateTopicCommand,
|
|
105
|
-
ListTopicsCommand,
|
|
106
|
-
DeleteTopicCommand
|
|
107
|
-
} from '@aws-sdk/client-sns';
|
|
108
|
-
|
|
109
|
-
@Module({
|
|
110
|
-
imports: [ServerAwsSnsModule.configure()],
|
|
111
|
-
controllers: [NotificationController],
|
|
112
|
-
providers: [NotificationService]
|
|
113
|
-
})
|
|
114
|
-
export class NotificationModule {}
|
|
115
|
-
|
|
116
|
-
@Injectable()
|
|
117
|
-
export class NotificationService {
|
|
118
|
-
constructor(private readonly snsClient: SNSClient) {}
|
|
119
|
-
|
|
120
|
-
async sendNotification(type: string, message: string, recipients: string[]) {
|
|
121
|
-
const topicName = `notifications-${type}`;
|
|
122
|
-
|
|
123
|
-
// Create or get topic
|
|
124
|
-
const createCommand = new CreateTopicCommand({ Name: topicName });
|
|
125
|
-
const { TopicArn } = await this.snsClient.send(createCommand);
|
|
126
|
-
|
|
127
|
-
// Publish message
|
|
128
|
-
const publishCommand = new PublishCommand({
|
|
129
|
-
TopicArn,
|
|
130
|
-
Message: JSON.stringify({
|
|
131
|
-
default: message,
|
|
132
|
-
email: message,
|
|
133
|
-
sms: message.substring(0, 140) // SMS has character limit
|
|
134
|
-
}),
|
|
135
|
-
MessageStructure: 'json',
|
|
136
|
-
Subject: `${type} Notification`
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
return await this.snsClient.send(publishCommand);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async sendBulkSMS(phoneNumbers: string[], message: string) {
|
|
143
|
-
const results = await Promise.allSettled(
|
|
144
|
-
phoneNumbers.map(phone =>
|
|
145
|
-
this.snsClient.send(new PublishCommand({
|
|
146
|
-
PhoneNumber: phone,
|
|
147
|
-
Message: message
|
|
148
|
-
}))
|
|
149
|
-
)
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
successful: results.filter(r => r.status === 'fulfilled').length,
|
|
154
|
-
failed: results.filter(r => r.status === 'rejected').length
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async listTopics() {
|
|
159
|
-
const command = new ListTopicsCommand({});
|
|
160
|
-
const response = await this.snsClient.send(command);
|
|
161
|
-
return response.Topics;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
@Controller('notifications')
|
|
166
|
-
export class NotificationController {
|
|
167
|
-
constructor(private readonly notificationService: NotificationService) {}
|
|
168
|
-
|
|
169
|
-
@Post('send')
|
|
170
|
-
async sendNotification(@Body() body: {
|
|
171
|
-
type: string;
|
|
172
|
-
message: string;
|
|
173
|
-
recipients: string[];
|
|
174
|
-
}) {
|
|
175
|
-
return await this.notificationService.sendNotification(
|
|
176
|
-
body.type,
|
|
177
|
-
body.message,
|
|
178
|
-
body.recipients
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
@Post('sms/bulk')
|
|
183
|
-
async sendBulkSMS(@Body() body: {
|
|
184
|
-
phoneNumbers: string[];
|
|
185
|
-
message: string;
|
|
186
|
-
}) {
|
|
187
|
-
return await this.notificationService.sendBulkSMS(
|
|
188
|
-
body.phoneNumbers,
|
|
189
|
-
body.message
|
|
190
|
-
);
|
|
98
|
+
return await this.snsClient.send(command);
|
|
191
99
|
}
|
|
192
100
|
}
|
|
193
101
|
```
|
|
@@ -197,7 +105,10 @@ export class NotificationController {
|
|
|
197
105
|
Since this module only provides the client, here are examples of common operations:
|
|
198
106
|
|
|
199
107
|
### Topic Management
|
|
108
|
+
|
|
200
109
|
```typescript
|
|
110
|
+
import { CreateTopicCommand, DeleteTopicCommand, ListTopicsCommand, PublishCommand, SubscribeCommand } from '@aws-sdk/client-sns';
|
|
111
|
+
|
|
201
112
|
// Create topic
|
|
202
113
|
const createCommand = new CreateTopicCommand({ Name: 'my-topic' });
|
|
203
114
|
const { TopicArn } = await snsClient.send(createCommand);
|
|
@@ -212,12 +123,13 @@ await snsClient.send(deleteCommand);
|
|
|
212
123
|
```
|
|
213
124
|
|
|
214
125
|
### Subscriptions
|
|
126
|
+
|
|
215
127
|
```typescript
|
|
216
128
|
// Email subscription
|
|
217
129
|
const subscribeCommand = new SubscribeCommand({
|
|
218
130
|
TopicArn: 'arn:aws:sns:...',
|
|
219
131
|
Protocol: 'email',
|
|
220
|
-
Endpoint: 'user@example.com'
|
|
132
|
+
Endpoint: 'user@example.com',
|
|
221
133
|
});
|
|
222
134
|
await snsClient.send(subscribeCommand);
|
|
223
135
|
|
|
@@ -225,17 +137,18 @@ await snsClient.send(subscribeCommand);
|
|
|
225
137
|
const smsSubscribeCommand = new SubscribeCommand({
|
|
226
138
|
TopicArn: 'arn:aws:sns:...',
|
|
227
139
|
Protocol: 'sms',
|
|
228
|
-
Endpoint: '+1234567890'
|
|
140
|
+
Endpoint: '+1234567890',
|
|
229
141
|
});
|
|
230
142
|
await snsClient.send(smsSubscribeCommand);
|
|
231
143
|
```
|
|
232
144
|
|
|
233
145
|
### Publishing
|
|
146
|
+
|
|
234
147
|
```typescript
|
|
235
148
|
// Simple message
|
|
236
149
|
const publishCommand = new PublishCommand({
|
|
237
150
|
TopicArn: 'arn:aws:sns:...',
|
|
238
|
-
Message: 'Hello World'
|
|
151
|
+
Message: 'Hello World',
|
|
239
152
|
});
|
|
240
153
|
await snsClient.send(publishCommand);
|
|
241
154
|
|
|
@@ -245,23 +158,13 @@ const structuredCommand = new PublishCommand({
|
|
|
245
158
|
Message: JSON.stringify({
|
|
246
159
|
default: 'Default message',
|
|
247
160
|
email: 'Detailed email message',
|
|
248
|
-
sms: 'Short SMS'
|
|
161
|
+
sms: 'Short SMS',
|
|
249
162
|
}),
|
|
250
|
-
MessageStructure: 'json'
|
|
163
|
+
MessageStructure: 'json',
|
|
251
164
|
});
|
|
252
165
|
await snsClient.send(structuredCommand);
|
|
253
166
|
```
|
|
254
167
|
|
|
255
|
-
## Environment Variables
|
|
256
|
-
|
|
257
|
-
```bash
|
|
258
|
-
# Required
|
|
259
|
-
AWS_REGION=us-east-1
|
|
260
|
-
|
|
261
|
-
# Optional
|
|
262
|
-
AWS_PROFILE=my-profile
|
|
263
|
-
```
|
|
264
|
-
|
|
265
168
|
## Limitations
|
|
266
169
|
|
|
267
170
|
- No custom service implementation - only provides SNS client
|
|
@@ -280,4 +183,4 @@ AWS_PROFILE=my-profile
|
|
|
280
183
|
|
|
281
184
|
## License
|
|
282
185
|
|
|
283
|
-
MIT
|
|
186
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onivoro/server-aws-sns",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "25.0.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"url": "https://github.com/onivoro/monorepo.git"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@onivoro/server-aws-credential-providers": "
|
|
14
|
-
"@onivoro/server-common": "
|
|
13
|
+
"@onivoro/server-aws-credential-providers": "25.0.2",
|
|
14
|
+
"@onivoro/server-common": "25.0.2",
|
|
15
15
|
"tslib": "^2.3.0"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|