@simplens/resend 1.0.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 ADDED
@@ -0,0 +1,87 @@
1
+ # @simplens/resend
2
+
3
+ Resend email provider plugin for [SimpleNS](https://github.com/SimpleNotificationSystem/SimpleNotificationSystem).
4
+
5
+ ## Features
6
+
7
+ - 📧 Send HTML emails via [Resend](https://resend.com)
8
+ - 🖼️ Automatic base64 image extraction to CID attachments
9
+ - 🔄 Template variable replacement (`{{var}}`, `${var}`, `{var}`, `$var`)
10
+ - ⚡ Built-in rate limiting (configurable)
11
+ - ✅ Full TypeScript support
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @simplens/resend
17
+ ```
18
+
19
+ ## Configuration
20
+
21
+ Add to your `simplens.config.yaml` or generate using `npx @simplens/config-gen gen @simplens/resend`:
22
+
23
+ ```yaml
24
+ providers:
25
+ - package: '@simplens/resend'
26
+ id: email-resend
27
+ credentials:
28
+ RESEND_API_KEY: ${RESEND_API_KEY}
29
+ FROM_EMAIL: ${FROM_EMAIL}
30
+ options:
31
+ rateLimit:
32
+ maxTokens: 100 # Max emails in bucket
33
+ refillRate: 100 # Tokens refilled per interval
34
+ refillInterval: day # second | minute | hour | day
35
+ ```
36
+
37
+ ### Required Credentials
38
+
39
+ | Credential | Description |
40
+ |------------|-------------|
41
+ | `RESEND_API_KEY` | Your Resend API key ([get one here](https://resend.com/api-keys)) |
42
+ | `FROM_EMAIL` | Verified sender email address ([verify domain](https://resend.com/domains)) |
43
+
44
+
45
+ ## Notification Schema
46
+
47
+ | Field | Type | Required | Description |
48
+ |-------|------|----------|-------------|
49
+ | `channel` | `'email'` | ✅ | Must be `'email'` |
50
+ | `recipient.user_id` | `string` | ✅ | User identifier |
51
+ | `recipient.email` | `string` | ✅ | Valid email address |
52
+ | `content.subject` | `string` | ✅ | Email subject line |
53
+ | `content.html` | `string` | ✅ | HTML content (must contain at least one HTML tag) |
54
+ | `variables` | `Record<string, unknown>` | ❌ | Template variables |
55
+
56
+ ## Rate Limiting
57
+
58
+ Resend free tier allows 100 emails/day. Configure based on your plan:
59
+
60
+ | Plan | Suggested Config |
61
+ |------|------------------|
62
+ | Free | `maxTokens: 100, refillRate: 100, refillInterval: day` |
63
+ | Pro | `maxTokens: 5000, refillRate: 5000, refillInterval: day` |
64
+
65
+ ## Development
66
+
67
+ ```bash
68
+ # Install dependencies
69
+ npm install
70
+
71
+ # Build
72
+ npm run build
73
+
74
+ # Run tests
75
+ npm test
76
+
77
+ # Manual test (requires .env with RESEND_API_KEY, FROM_EMAIL, TO_EMAIL)
78
+ npm run test:send
79
+ ```
80
+
81
+ ## License
82
+
83
+ MIT
84
+
85
+ ## Author
86
+
87
+ SimpleNS Team
@@ -0,0 +1,179 @@
1
+ /**
2
+ * @simplens/resend
3
+ *
4
+ * Resend email provider plugin for SimpleNS.
5
+ * Uses Resend API for email delivery.
6
+ */
7
+ import { z, type SimpleNSProvider, type ProviderManifest, type ProviderConfig, type DeliveryResult, type RateLimitConfig } from '@simplens/sdk';
8
+ declare const notificationSchema: z.ZodObject<{
9
+ notification_id: z.ZodString;
10
+ request_id: z.ZodString;
11
+ client_id: z.ZodString;
12
+ provider: z.ZodOptional<z.ZodString>;
13
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
14
+ webhook_url: z.ZodString;
15
+ retry_count: z.ZodNumber;
16
+ } & {
17
+ channel: z.ZodLiteral<"email">;
18
+ recipient: z.ZodObject<{
19
+ user_id: z.ZodString;
20
+ email: z.ZodString;
21
+ }, "strip", z.ZodTypeAny, {
22
+ user_id: string;
23
+ email: string;
24
+ }, {
25
+ user_id: string;
26
+ email: string;
27
+ }>;
28
+ content: z.ZodObject<{
29
+ subject: z.ZodString;
30
+ html: z.ZodEffects<z.ZodString, string, string>;
31
+ }, "strip", z.ZodTypeAny, {
32
+ subject: string;
33
+ html: string;
34
+ }, {
35
+ subject: string;
36
+ html: string;
37
+ }>;
38
+ created_at: z.ZodDate;
39
+ }, "strip", z.ZodTypeAny, {
40
+ channel: "email";
41
+ recipient: {
42
+ user_id: string;
43
+ email: string;
44
+ };
45
+ content: {
46
+ subject: string;
47
+ html: string;
48
+ };
49
+ created_at: Date;
50
+ notification_id: string;
51
+ request_id: string;
52
+ client_id: string;
53
+ webhook_url: string;
54
+ retry_count: number;
55
+ provider?: string | undefined;
56
+ variables?: Record<string, string> | undefined;
57
+ }, {
58
+ channel: "email";
59
+ recipient: {
60
+ user_id: string;
61
+ email: string;
62
+ };
63
+ content: {
64
+ subject: string;
65
+ html: string;
66
+ };
67
+ created_at: Date;
68
+ notification_id: string;
69
+ request_id: string;
70
+ client_id: string;
71
+ webhook_url: string;
72
+ retry_count: number;
73
+ provider?: string | undefined;
74
+ variables?: Record<string, string> | undefined;
75
+ }>;
76
+ type Notification = z.infer<typeof notificationSchema>;
77
+ declare class ResendProvider implements SimpleNSProvider<Notification> {
78
+ private config;
79
+ private from_email;
80
+ private resend;
81
+ readonly manifest: ProviderManifest;
82
+ getNotificationSchema(): z.ZodObject<{
83
+ notification_id: z.ZodString;
84
+ request_id: z.ZodString;
85
+ client_id: z.ZodString;
86
+ provider: z.ZodOptional<z.ZodString>;
87
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
88
+ webhook_url: z.ZodString;
89
+ retry_count: z.ZodNumber;
90
+ } & {
91
+ channel: z.ZodLiteral<"email">;
92
+ recipient: z.ZodObject<{
93
+ user_id: z.ZodString;
94
+ email: z.ZodString;
95
+ }, "strip", z.ZodTypeAny, {
96
+ user_id: string;
97
+ email: string;
98
+ }, {
99
+ user_id: string;
100
+ email: string;
101
+ }>;
102
+ content: z.ZodObject<{
103
+ subject: z.ZodString;
104
+ html: z.ZodEffects<z.ZodString, string, string>;
105
+ }, "strip", z.ZodTypeAny, {
106
+ subject: string;
107
+ html: string;
108
+ }, {
109
+ subject: string;
110
+ html: string;
111
+ }>;
112
+ created_at: z.ZodDate;
113
+ }, "strip", z.ZodTypeAny, {
114
+ channel: "email";
115
+ recipient: {
116
+ user_id: string;
117
+ email: string;
118
+ };
119
+ content: {
120
+ subject: string;
121
+ html: string;
122
+ };
123
+ created_at: Date;
124
+ notification_id: string;
125
+ request_id: string;
126
+ client_id: string;
127
+ webhook_url: string;
128
+ retry_count: number;
129
+ provider?: string | undefined;
130
+ variables?: Record<string, string> | undefined;
131
+ }, {
132
+ channel: "email";
133
+ recipient: {
134
+ user_id: string;
135
+ email: string;
136
+ };
137
+ content: {
138
+ subject: string;
139
+ html: string;
140
+ };
141
+ created_at: Date;
142
+ notification_id: string;
143
+ request_id: string;
144
+ client_id: string;
145
+ webhook_url: string;
146
+ retry_count: number;
147
+ provider?: string | undefined;
148
+ variables?: Record<string, string> | undefined;
149
+ }>;
150
+ getRecipientSchema(): z.ZodObject<{
151
+ user_id: z.ZodString;
152
+ email: z.ZodString;
153
+ }, "strip", z.ZodTypeAny, {
154
+ user_id: string;
155
+ email: string;
156
+ }, {
157
+ user_id: string;
158
+ email: string;
159
+ }>;
160
+ getContentSchema(): z.ZodObject<{
161
+ subject: z.ZodString;
162
+ html: z.ZodEffects<z.ZodString, string, string>;
163
+ }, "strip", z.ZodTypeAny, {
164
+ subject: string;
165
+ html: string;
166
+ }, {
167
+ subject: string;
168
+ html: string;
169
+ }>;
170
+ getRateLimitConfig(): RateLimitConfig;
171
+ initialize(config: ProviderConfig): Promise<void>;
172
+ healthCheck(): Promise<boolean>;
173
+ send(notification: Notification): Promise<DeliveryResult>;
174
+ shutdown(): Promise<void>;
175
+ }
176
+ export default ResendProvider;
177
+ export type { Notification as ResendNotification };
178
+ export declare function createProvider(): ResendProvider;
179
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACH,CAAC,EACD,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EAEvB,MAAM,eAAe,CAAC;AAoHvB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKtB,CAAC;AAEH,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEvD,cAAM,cAAe,YAAW,gBAAgB,CAAC,YAAY,CAAC;IAC1D,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,MAAM,CAAuB;IAErC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CASjC;IAEF,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAIrB,kBAAkB;;;;;;;;;;IAIlB,gBAAgB;;;;;;;;;;IAIhB,kBAAkB,IAAI,eAAe;IAW/B,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjD,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAsGzD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKlC;AAGD,eAAe,cAAc,CAAC;AAG9B,YAAY,EAAE,YAAY,IAAI,kBAAkB,EAAE,CAAC;AAGnD,wBAAgB,cAAc,IAAI,cAAc,CAE/C"}
package/dist/index.js ADDED
@@ -0,0 +1,230 @@
1
+ /**
2
+ * @simplens/resend
3
+ *
4
+ * Resend email provider plugin for SimpleNS.
5
+ * Uses Resend API for email delivery.
6
+ */
7
+ import { z, baseNotificationSchema, } from '@simplens/sdk';
8
+ import { Resend } from 'resend';
9
+ /**
10
+ * Extracts base64 encoded images from HTML and converts them to CID attachments.
11
+ * This is necessary because most email clients block inline base64 images.
12
+ *
13
+ * @param html - The HTML content containing base64 images
14
+ * @returns Object with processed HTML (cid: references) and attachments array
15
+ */
16
+ function extractBase64Images(html) {
17
+ const attachments = [];
18
+ // Regex to match base64 image data URIs in img src attributes
19
+ // Matches: <img ... src="data:image/TYPE;base64,DATA" ...>
20
+ const base64ImageRegex = /<img([^>]*)\ssrc=["']data:(image\/(\w+));base64,([^"']+)["']([^>]*)>/gi;
21
+ let imageIndex = 0;
22
+ const timestamp = Date.now();
23
+ const processedHtml = html.replace(base64ImageRegex, (match, before, mimeType, extension, base64Data, after) => {
24
+ const contentId = `embedded-image-${imageIndex}-${timestamp}`;
25
+ const filename = `image-${imageIndex}.${extension}`;
26
+ attachments.push({
27
+ filename,
28
+ content: base64Data, // Keep as base64 string for Resend
29
+ contentId,
30
+ contentType: mimeType,
31
+ });
32
+ imageIndex++;
33
+ return `<img${before} src="cid:${contentId}"${after}>`;
34
+ });
35
+ return { html: processedHtml, attachments };
36
+ }
37
+ /**
38
+ * Replaces template variables in a string using multiple common patterns.
39
+ *
40
+ * Supported patterns:
41
+ * - {{variable}} - Handlebars/Mustache style
42
+ * - ${variable} - ES6 template literal style
43
+ * - {variable} - Simple brace style
44
+ * - $variable - Shell/PHP style (word characters only)
45
+ *
46
+ * @param template - The template string containing variables
47
+ * @param variables - Record of variable names to values
48
+ * @returns The template with all variables replaced
49
+ */
50
+ function replaceTemplateVariables(template, variables) {
51
+ let result = template;
52
+ // Define all supported patterns with their regex
53
+ // Order matters: more specific patterns first to avoid partial matches
54
+ const patterns = [
55
+ /\{\{(\w+)\}\}/g, // {{variable}}
56
+ /\$\{(\w+)\}/g, // ${variable}
57
+ /\{(\w+)\}/g, // {variable}
58
+ /\$(\w+)/g, // $variable
59
+ ];
60
+ for (const pattern of patterns) {
61
+ result = result.replace(pattern, (match, varName) => {
62
+ if (varName in variables) {
63
+ return String(variables[varName]);
64
+ }
65
+ return match; // Leave unmatched patterns as-is
66
+ });
67
+ }
68
+ return result;
69
+ }
70
+ // Define your schemas
71
+ const recipientSchema = z.object({
72
+ user_id: z.string(),
73
+ email: z.string().email()
74
+ });
75
+ const htmlSchema = z.string().refine((value) => {
76
+ // Check if string contains at least one HTML tag
77
+ const htmlTagPattern = /<[a-z][\s\S]*>/i;
78
+ return htmlTagPattern.test(value);
79
+ }, { message: 'Invalid HTML: must contain at least one HTML tag' });
80
+ const contentSchema = z.object({
81
+ subject: z.string(),
82
+ html: htmlSchema,
83
+ });
84
+ const notificationSchema = baseNotificationSchema.extend({
85
+ channel: z.literal('email'),
86
+ recipient: recipientSchema,
87
+ content: contentSchema,
88
+ created_at: z.coerce.date(),
89
+ });
90
+ class ResendProvider {
91
+ config = null;
92
+ from_email = '';
93
+ resend = null;
94
+ manifest = {
95
+ name: '@simplens/resend',
96
+ version: '1.0.0',
97
+ channel: 'email',
98
+ displayName: 'Resend',
99
+ description: 'Send notifications via Resend',
100
+ author: 'Adhish Krishna S',
101
+ homepage: '',
102
+ requiredCredentials: ["RESEND_API_KEY", "FROM_EMAIL"],
103
+ };
104
+ getNotificationSchema() {
105
+ return notificationSchema;
106
+ }
107
+ getRecipientSchema() {
108
+ return recipientSchema;
109
+ }
110
+ getContentSchema() {
111
+ return contentSchema;
112
+ }
113
+ getRateLimitConfig() {
114
+ const options = this.config?.options;
115
+ const rateLimit = options?.rateLimit;
116
+ return {
117
+ maxTokens: rateLimit?.maxTokens || 100, //default set to 100 emails / day for free tier
118
+ refillRate: rateLimit?.refillRate || 100,
119
+ refillInterval: rateLimit?.refillInterval || 'day'
120
+ };
121
+ }
122
+ async initialize(config) {
123
+ this.config = config;
124
+ const api_key = config.credentials['RESEND_API_KEY'];
125
+ const from_email = config.credentials['FROM_EMAIL'];
126
+ if (!api_key || !from_email) {
127
+ throw new Error('RESEND_API_KEY and FROM_EMAIL are required');
128
+ }
129
+ this.from_email = from_email;
130
+ this.resend = new Resend(api_key);
131
+ console.log(`[ResendProvider] Initialized with from_email: ${from_email}`);
132
+ }
133
+ async healthCheck() {
134
+ return this.config !== null && this.resend !== null;
135
+ }
136
+ async send(notification) {
137
+ if (!this.resend) {
138
+ return {
139
+ success: false,
140
+ error: { code: 'NOT_INITIALIZED', message: 'Resend client not initialized', retryable: false },
141
+ };
142
+ }
143
+ try {
144
+ let htmlContent = notification.content.html;
145
+ let subject = notification.content.subject;
146
+ // Replace template variables if provided
147
+ if (notification.variables) {
148
+ htmlContent = replaceTemplateVariables(htmlContent, notification.variables);
149
+ subject = replaceTemplateVariables(subject, notification.variables);
150
+ }
151
+ // Extract base64 images and convert to attachments
152
+ const { html, attachments } = extractBase64Images(htmlContent);
153
+ // Build the email payload
154
+ const emailPayload = {
155
+ from: this.from_email,
156
+ to: notification.recipient.email,
157
+ subject: subject,
158
+ html: html,
159
+ };
160
+ // Add attachments if any base64 images were found
161
+ if (attachments.length > 0) {
162
+ emailPayload.attachments = attachments.map(att => ({
163
+ filename: att.filename,
164
+ content: att.content,
165
+ contentId: att.contentId, // Required for CID embedding
166
+ }));
167
+ }
168
+ const response = await this.resend.emails.send(emailPayload);
169
+ if (response.error) {
170
+ console.error(`[ResendProvider] Send failed:`, response.error);
171
+ // Determine if retryable based on error type
172
+ const nonRetryablePatterns = [
173
+ 'validation',
174
+ 'invalid',
175
+ 'unauthorized',
176
+ 'forbidden',
177
+ ];
178
+ const errorMessage = response.error.message || 'Unknown error';
179
+ const retryable = !nonRetryablePatterns.some(p => errorMessage.toLowerCase().includes(p.toLowerCase()));
180
+ return {
181
+ success: false,
182
+ error: {
183
+ code: response.error.name || 'SEND_FAILED',
184
+ message: errorMessage,
185
+ retryable,
186
+ },
187
+ };
188
+ }
189
+ console.log(`[ResendProvider] Email sent: ${response.data?.id} to ${notification.recipient.email}`);
190
+ return {
191
+ success: true,
192
+ messageId: response.data?.id,
193
+ providerResponse: response.data,
194
+ };
195
+ }
196
+ catch (err) {
197
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
198
+ // Determine if retryable
199
+ const nonRetryablePatterns = [
200
+ 'validation',
201
+ 'invalid',
202
+ 'unauthorized',
203
+ 'forbidden',
204
+ 'api key',
205
+ ];
206
+ const retryable = !nonRetryablePatterns.some(p => errorMessage.toLowerCase().includes(p.toLowerCase()));
207
+ console.error(`[ResendProvider] Send failed:`, err);
208
+ return {
209
+ success: false,
210
+ error: {
211
+ code: 'SEND_FAILED',
212
+ message: errorMessage,
213
+ retryable,
214
+ },
215
+ };
216
+ }
217
+ }
218
+ async shutdown() {
219
+ this.config = null;
220
+ this.resend = null;
221
+ console.log('[ResendProvider] Shutdown complete');
222
+ }
223
+ }
224
+ // Export the provider class as default
225
+ export default ResendProvider;
226
+ // Export a factory function for convenience
227
+ export function createProvider() {
228
+ return new ResendProvider();
229
+ }
230
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@simplens/resend",
3
+ "version": "1.0.0",
4
+ "description": "Send notifications via Resend",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "type": "module",
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "test": "vitest run",
18
+ "test:watch": "vitest",
19
+ "test:send": "npx tsx scripts/test-send.ts",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "simplens",
24
+ "plugin",
25
+ "email",
26
+ "notification"
27
+ ],
28
+ "author": "Adhish Krishna S <adhishthesak@gmail.com>",
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "@simplens/sdk": "^1.0.3",
32
+ "resend": "^6.7.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.0.0",
36
+ "dotenv": "^17.2.3",
37
+ "typescript": "^5.0.0",
38
+ "vitest": "^2.0.0"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/SimpleNotificationSystem/plugin-resend"
47
+ }
48
+ }