@aphexcms/resend-adapter 0.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 +141 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# @aphex/resend-adapter
|
|
2
|
+
|
|
3
|
+
Resend email adapter for Aphex CMS.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @aphex/resend-adapter resend
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Basic Setup
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// src/lib/server/email/index.ts
|
|
17
|
+
import { createResendAdapter } from '@aphex/resend-adapter';
|
|
18
|
+
import { RESEND_API_KEY } from '$env/static/private';
|
|
19
|
+
|
|
20
|
+
export const emailAdapter = createResendAdapter({
|
|
21
|
+
apiKey: RESEND_API_KEY
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Environment Variables
|
|
26
|
+
|
|
27
|
+
Add to your `.env` file:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
RESEND_API_KEY=re_your_api_key_here
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Sending Emails
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { emailAdapter } from '$lib/server/email';
|
|
37
|
+
|
|
38
|
+
// Send a single email
|
|
39
|
+
const result = await emailAdapter.send({
|
|
40
|
+
from: 'Acme <onboarding@resend.dev>',
|
|
41
|
+
to: 'user@example.com',
|
|
42
|
+
subject: 'Hello World',
|
|
43
|
+
html: '<p>Hello from Aphex CMS!</p>'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (result.error) {
|
|
47
|
+
console.error('Failed to send email:', result.error);
|
|
48
|
+
} else {
|
|
49
|
+
console.log('Email sent successfully:', result.id);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Batch Sending
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
const results = await emailAdapter.sendBatch([
|
|
57
|
+
{
|
|
58
|
+
from: 'Acme <onboarding@resend.dev>',
|
|
59
|
+
to: 'user1@example.com',
|
|
60
|
+
subject: 'Welcome',
|
|
61
|
+
html: '<p>Welcome user 1!</p>'
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
from: 'Acme <onboarding@resend.dev>',
|
|
65
|
+
to: 'user2@example.com',
|
|
66
|
+
subject: 'Welcome',
|
|
67
|
+
html: '<p>Welcome user 2!</p>'
|
|
68
|
+
}
|
|
69
|
+
]);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Advanced Options
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
await emailAdapter.send({
|
|
76
|
+
from: 'Acme <onboarding@resend.dev>',
|
|
77
|
+
to: ['user1@example.com', 'user2@example.com'],
|
|
78
|
+
cc: 'manager@example.com',
|
|
79
|
+
bcc: 'archive@example.com',
|
|
80
|
+
replyTo: 'support@example.com',
|
|
81
|
+
subject: 'Newsletter',
|
|
82
|
+
html: '<h1>Monthly Update</h1>',
|
|
83
|
+
text: 'Monthly Update',
|
|
84
|
+
tags: [
|
|
85
|
+
{ name: 'category', value: 'newsletter' },
|
|
86
|
+
{ name: 'month', value: 'january' }
|
|
87
|
+
],
|
|
88
|
+
attachments: [
|
|
89
|
+
{
|
|
90
|
+
filename: 'invoice.pdf',
|
|
91
|
+
content: pdfBuffer
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## API Reference
|
|
98
|
+
|
|
99
|
+
### `createResendAdapter(config)`
|
|
100
|
+
|
|
101
|
+
Creates a new Resend email adapter instance.
|
|
102
|
+
|
|
103
|
+
**Config:**
|
|
104
|
+
|
|
105
|
+
- `apiKey` (required): Your Resend API key
|
|
106
|
+
|
|
107
|
+
**Returns:** `EmailAdapter`
|
|
108
|
+
|
|
109
|
+
### `EmailAdapter.send(options)`
|
|
110
|
+
|
|
111
|
+
Sends a single email.
|
|
112
|
+
|
|
113
|
+
**Options:**
|
|
114
|
+
|
|
115
|
+
- `from` (required): Sender email address
|
|
116
|
+
- `to` (required): Recipient email(s)
|
|
117
|
+
- `subject` (required): Email subject
|
|
118
|
+
- `html`: HTML content
|
|
119
|
+
- `text`: Plain text content
|
|
120
|
+
- `cc`: CC recipients
|
|
121
|
+
- `bcc`: BCC recipients
|
|
122
|
+
- `replyTo`: Reply-to address
|
|
123
|
+
- `tags`: Array of tags for tracking
|
|
124
|
+
- `attachments`: Array of file attachments
|
|
125
|
+
|
|
126
|
+
**Returns:** `Promise<SendEmailResult>`
|
|
127
|
+
|
|
128
|
+
### `EmailAdapter.sendBatch(emails)`
|
|
129
|
+
|
|
130
|
+
Sends multiple emails in a batch.
|
|
131
|
+
|
|
132
|
+
**Parameters:**
|
|
133
|
+
|
|
134
|
+
- `emails`: Array of `SendEmailOptions`
|
|
135
|
+
|
|
136
|
+
**Returns:** `Promise<SendEmailResult[]>`
|
|
137
|
+
|
|
138
|
+
## Learn More
|
|
139
|
+
|
|
140
|
+
- [Resend Documentation](https://resend.com/docs)
|
|
141
|
+
- [Aphex CMS Documentation](../../README.md)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EmailAdapter, SendEmailOptions, SendEmailResult, EmailConfig } from '@aphexcms/cms-core/server';
|
|
2
|
+
export interface ResendConfig extends EmailConfig {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class ResendAdapter implements EmailAdapter {
|
|
6
|
+
readonly name = "resend";
|
|
7
|
+
private resend;
|
|
8
|
+
constructor(config: ResendConfig);
|
|
9
|
+
send(options: SendEmailOptions): Promise<SendEmailResult>;
|
|
10
|
+
sendBatch(emails: SendEmailOptions[]): Promise<SendEmailResult[]>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createResendAdapter(config: ResendConfig): EmailAdapter;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,YAAa,SAAQ,WAAW;IAChD,MAAM,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,aAAc,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,YAAY;IAO1B,IAAI,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAoCzD,SAAS,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAyCvE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAEtE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Resend } from 'resend';
|
|
2
|
+
export class ResendAdapter {
|
|
3
|
+
name = 'resend';
|
|
4
|
+
resend;
|
|
5
|
+
constructor(config) {
|
|
6
|
+
if (!config.apiKey) {
|
|
7
|
+
throw new Error('Resend API key is required');
|
|
8
|
+
}
|
|
9
|
+
this.resend = new Resend(config.apiKey);
|
|
10
|
+
}
|
|
11
|
+
async send(options) {
|
|
12
|
+
try {
|
|
13
|
+
const emailOptions = {
|
|
14
|
+
from: options.from,
|
|
15
|
+
to: Array.isArray(options.to) ? options.to : [options.to],
|
|
16
|
+
subject: options.subject,
|
|
17
|
+
html: options.html || '',
|
|
18
|
+
...(options.text && { text: options.text }),
|
|
19
|
+
...(options.cc && { cc: Array.isArray(options.cc) ? options.cc : [options.cc] }),
|
|
20
|
+
...(options.bcc && { bcc: Array.isArray(options.bcc) ? options.bcc : [options.bcc] }),
|
|
21
|
+
...(options.replyTo && { replyTo: options.replyTo }),
|
|
22
|
+
...(options.tags && { tags: options.tags }),
|
|
23
|
+
...(options.attachments && { attachments: options.attachments })
|
|
24
|
+
};
|
|
25
|
+
const { data, error } = await this.resend.emails.send(emailOptions);
|
|
26
|
+
if (error) {
|
|
27
|
+
return {
|
|
28
|
+
id: '',
|
|
29
|
+
error: error.message
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
id: data?.id || '',
|
|
34
|
+
error: undefined
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return {
|
|
39
|
+
id: '',
|
|
40
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async sendBatch(emails) {
|
|
45
|
+
try {
|
|
46
|
+
const { data, error } = await this.resend.batch.send(emails.map((email) => {
|
|
47
|
+
const batchEmail = {
|
|
48
|
+
from: email.from,
|
|
49
|
+
to: Array.isArray(email.to) ? email.to : [email.to],
|
|
50
|
+
subject: email.subject,
|
|
51
|
+
html: email.html || '',
|
|
52
|
+
...(email.text && { text: email.text }),
|
|
53
|
+
...(email.cc && { cc: Array.isArray(email.cc) ? email.cc : [email.cc] }),
|
|
54
|
+
...(email.bcc && { bcc: Array.isArray(email.bcc) ? email.bcc : [email.bcc] }),
|
|
55
|
+
...(email.replyTo && { replyTo: email.replyTo }),
|
|
56
|
+
...(email.tags && { tags: email.tags }),
|
|
57
|
+
...(email.attachments && { attachments: email.attachments })
|
|
58
|
+
};
|
|
59
|
+
return batchEmail;
|
|
60
|
+
}));
|
|
61
|
+
if (error) {
|
|
62
|
+
return emails.map(() => ({
|
|
63
|
+
id: '',
|
|
64
|
+
error: error.message
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
return (data?.data?.map((result) => ({
|
|
68
|
+
id: result.id || '',
|
|
69
|
+
error: undefined
|
|
70
|
+
})) || []);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
74
|
+
return emails.map(() => ({
|
|
75
|
+
id: '',
|
|
76
|
+
error: errorMessage
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export function createResendAdapter(config) {
|
|
82
|
+
return new ResendAdapter(config);
|
|
83
|
+
}
|
|
84
|
+
//# 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,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aphexcms/resend-adapter",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
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
|
+
"./schema": {
|
|
14
|
+
"types": "./dist/schema.d.ts",
|
|
15
|
+
"import": "./dist/schema.js",
|
|
16
|
+
"default": "./dist/schema.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"prepublishOnly": "pnpm build"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@aphexcms/cms-core": "workspace:*",
|
|
28
|
+
"resend": "^4.0.1"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@aphexcms/cms-core": "workspace:*"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@aphexcms/cms-core": "workspace:*",
|
|
35
|
+
"tsup": "^8.0.0",
|
|
36
|
+
"typescript": "^5.3.3"
|
|
37
|
+
}
|
|
38
|
+
}
|