resend 0.17.2 → 0.18.0-canary.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "resend",
3
- "version": "0.17.2",
3
+ "version": "0.18.0-canary.0",
4
4
  "description": "Node.js library for the Resend API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",
@@ -28,16 +28,19 @@
28
28
  "homepage": "https://github.com/resend-inc/resend-node#readme",
29
29
  "dependencies": {
30
30
  "@react-email/render": "0.0.7",
31
- "axios": "1.4.0",
31
+ "node-fetch": "2.6.6",
32
32
  "type-fest": "3.13.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/jest": "29.5.3",
36
36
  "@types/node": "18.16.2",
37
+ "@types/node-fetch": "2.6.4",
37
38
  "@types/react": "18.2.0",
38
- "axios-mock-adapter": "1.21.5",
39
+ "fetch-mock": "9.11.0",
39
40
  "jest": "29.6.1",
41
+ "jest-fetch-mock": "3.0.3",
40
42
  "prettier": "3.0.0",
43
+ "prettier-2": "npm:prettier@2",
41
44
  "supertest": "6.3.3",
42
45
  "ts-jest": "29.1.1",
43
46
  "tslint": "6.1.3",
@@ -22,7 +22,7 @@ class ApiKeys {
22
22
  }
23
23
  list() {
24
24
  return __awaiter(this, void 0, void 0, function* () {
25
- const { data } = yield this.resend.get('/api-keys');
25
+ const data = yield this.resend.get('/api-keys');
26
26
  return data;
27
27
  });
28
28
  }
@@ -8,23 +8,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const axios_1 = __importDefault(require("axios"));
16
- const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
12
+ const jest_fetch_mock_1 = require("jest-fetch-mock");
17
13
  const resend_1 = require("../resend");
18
- const mock = new axios_mock_adapter_1.default(axios_1.default);
14
+ (0, jest_fetch_mock_1.enableFetchMocks)();
19
15
  describe('API Keys', () => {
20
- beforeEach(() => {
21
- mock.resetHistory();
22
- });
16
+ afterEach(() => fetchMock.resetMocks());
23
17
  describe('create', () => {
24
18
  it('creates an api key', () => __awaiter(void 0, void 0, void 0, function* () {
25
- mock.onPost('/api-keys', { name: 'Test' }).replyOnce(201, {
19
+ fetchMock.mockOnce(JSON.stringify({
26
20
  token: 're_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk',
27
21
  id: '430eed87-632a-4ea6-90db-0aace67ec228',
22
+ }), {
23
+ status: 201,
24
+ headers: {
25
+ 'content-type': 'application/json',
26
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
27
+ },
28
28
  });
29
29
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
30
30
  yield expect(resend.apiKeys.create({ name: 'Test' })).resolves
@@ -34,16 +34,21 @@ describe('API Keys', () => {
34
34
  "token": "re_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk",
35
35
  }
36
36
  `);
37
- expect(mock.history.post.length).toBe(1);
38
37
  }));
39
38
  it('throws error when missing name', () => __awaiter(void 0, void 0, void 0, function* () {
40
- mock.onPost('/api-keys').replyOnce(422, {
39
+ fetchMock.mockOnce(JSON.stringify({
41
40
  statusCode: 422,
42
41
  name: 'missing_required_field',
43
42
  message: 'Missing "name" field',
43
+ }), {
44
+ status: 422,
45
+ headers: {
46
+ 'content-type': 'application/json',
47
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
48
+ },
44
49
  });
45
50
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
46
- yield expect(resend.apiKeys.create({ name: '' })).rejects
51
+ yield expect(resend.apiKeys.create({ name: '' })).resolves
47
52
  .toMatchInlineSnapshot(`
48
53
  {
49
54
  "message": "Missing "name" field",
@@ -51,15 +56,18 @@ describe('API Keys', () => {
51
56
  "statusCode": 422,
52
57
  }
53
58
  `);
54
- expect(mock.history.post.length).toBe(1);
55
59
  }));
56
60
  describe('with access', () => {
57
61
  it('creates api key with access `full_access`', () => __awaiter(void 0, void 0, void 0, function* () {
58
- mock
59
- .onPost('/api-keys', { name: 'Test', permission: 'full_access' })
60
- .replyOnce(201, {
62
+ fetchMock.mockOnce(JSON.stringify({
61
63
  token: 're_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk',
62
64
  id: '430eed87-632a-4ea6-90db-0aace67ec228',
65
+ }), {
66
+ status: 201,
67
+ headers: {
68
+ 'content-type': 'application/json',
69
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
70
+ },
63
71
  });
64
72
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
65
73
  yield expect(resend.apiKeys.create({ name: 'Test', permission: 'full_access' })).resolves.toMatchInlineSnapshot(`
@@ -68,17 +76,17 @@ describe('API Keys', () => {
68
76
  "token": "re_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk",
69
77
  }
70
78
  `);
71
- expect(mock.history.post.length).toBe(1);
72
79
  }));
73
80
  it('creates api key with access `sending_access`', () => __awaiter(void 0, void 0, void 0, function* () {
74
- mock
75
- .onPost('/api-keys', {
76
- name: 'Test',
77
- permission: 'sending_access',
78
- })
79
- .replyOnce(201, {
81
+ fetchMock.mockOnce(JSON.stringify({
80
82
  token: 're_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk',
81
83
  id: '430eed87-632a-4ea6-90db-0aace67ec228',
84
+ }), {
85
+ status: 201,
86
+ headers: {
87
+ 'content-type': 'application/json',
88
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
89
+ },
82
90
  });
83
91
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
84
92
  yield expect(resend.apiKeys.create({
@@ -90,35 +98,37 @@ describe('API Keys', () => {
90
98
  "token": "re_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk",
91
99
  }
92
100
  `);
93
- expect(mock.history.post.length).toBe(1);
94
101
  }));
95
102
  it('throws error with wrong access', () => __awaiter(void 0, void 0, void 0, function* () {
96
- mock
97
- .onPost('/api-keys', { name: 'Test', permission: 'wrong_access' })
98
- .replyOnce(422, {
103
+ fetchMock.mockOnce(JSON.stringify({
99
104
  statusCode: 422,
100
105
  name: 'invalid_access',
101
106
  message: 'Access must be "full_access" | "sending_access"',
107
+ }), {
108
+ status: 422,
109
+ headers: {
110
+ 'content-type': 'application/json',
111
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
112
+ },
102
113
  });
103
114
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
104
115
  yield expect(resend.apiKeys.create({
105
116
  name: 'Test',
106
117
  permission: 'wrong_access',
107
- })).rejects.toThrowErrorMatchingInlineSnapshot(`"Access must be "full_access" | "sending_access""`);
108
- expect(mock.history.post.length).toBe(1);
118
+ })).resolves.toThrowErrorMatchingInlineSnapshot(`"Access must be "full_access" | "sending_access""`);
109
119
  }));
110
120
  });
111
121
  describe('restricted by domain', () => {
112
122
  it('creates api key restricted by domain', () => __awaiter(void 0, void 0, void 0, function* () {
113
- mock
114
- .onPost('/api-keys', {
115
- name: 'Test',
116
- permission: 'sending_access',
117
- domain_id: '7dfcf219-9900-4169-86f3-801e6d9b935e',
118
- })
119
- .replyOnce(201, {
123
+ fetchMock.mockOnce(JSON.stringify({
120
124
  token: 're_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk',
121
125
  id: '430eed87-632a-4ea6-90db-0aace67ec228',
126
+ }), {
127
+ status: 201,
128
+ headers: {
129
+ 'content-type': 'application/json',
130
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
131
+ },
122
132
  });
123
133
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
124
134
  yield expect(resend.apiKeys.create({
@@ -131,33 +141,31 @@ describe('API Keys', () => {
131
141
  "token": "re_PKr4RCko_Lhm9ost2YjNCctnPjbLw8Nqk",
132
142
  }
133
143
  `);
134
- expect(mock.history.post.length).toBe(1);
135
144
  }));
136
145
  it('throws error with wrong access', () => __awaiter(void 0, void 0, void 0, function* () {
137
- mock
138
- .onPost('/api-keys', {
139
- name: 'Test',
140
- permission: 'sending_access',
141
- domain_id: '1234',
142
- })
143
- .replyOnce(500, {
146
+ fetchMock.mockOnce(JSON.stringify({
144
147
  name: 'application_error',
145
148
  message: 'Something went wrong',
146
149
  statusCode: 500,
150
+ }), {
151
+ status: 500,
152
+ headers: {
153
+ 'content-type': 'application/json',
154
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
155
+ },
147
156
  });
148
157
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
149
158
  yield expect(resend.apiKeys.create({
150
159
  name: 'Test',
151
160
  permission: 'sending_access',
152
161
  domain_id: '1234',
153
- })).rejects.toThrowErrorMatchingInlineSnapshot(`"Something went wrong"`);
154
- expect(mock.history.post.length).toBe(1);
162
+ })).resolves.toThrowErrorMatchingInlineSnapshot(`"Something went wrong"`);
155
163
  }));
156
164
  });
157
165
  });
158
166
  describe('list', () => {
159
167
  it('lists api keys', () => __awaiter(void 0, void 0, void 0, function* () {
160
- mock.onGet('/api-keys').replyOnce(200, {
168
+ fetchMock.mockOnce(JSON.stringify({
161
169
  data: [
162
170
  {
163
171
  id: '5262504e-8ed7-4fac-bd16-0d4be94bc9f2',
@@ -170,67 +178,73 @@ describe('API Keys', () => {
170
178
  created_at: '2023-04-06T23:09:49.093947+00:00',
171
179
  },
172
180
  ],
181
+ }), {
182
+ status: 200,
183
+ headers: {
184
+ 'content-type': 'application/json',
185
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
186
+ },
173
187
  });
174
188
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
175
189
  yield expect(resend.apiKeys.list()).resolves.toMatchInlineSnapshot(`
176
- [
177
- {
178
- "created_at": "2023-04-07T20:29:10.666968+00:00",
179
- "id": "5262504e-8ed7-4fac-bd16-0d4be94bc9f2",
180
- "name": "My API Key 1",
181
- },
182
- {
183
- "created_at": "2023-04-06T23:09:49.093947+00:00",
184
- "id": "98c37b35-1473-4afe-a627-78e975a36fab",
185
- "name": "My API Key 2",
186
- },
187
- ]
190
+ {
191
+ "data": [
192
+ {
193
+ "created_at": "2023-04-07T20:29:10.666968+00:00",
194
+ "id": "5262504e-8ed7-4fac-bd16-0d4be94bc9f2",
195
+ "name": "My API Key 1",
196
+ },
197
+ {
198
+ "created_at": "2023-04-06T23:09:49.093947+00:00",
199
+ "id": "98c37b35-1473-4afe-a627-78e975a36fab",
200
+ "name": "My API Key 2",
201
+ },
202
+ ],
203
+ }
188
204
  `);
189
- expect(mock.history.get.length).toBe(1);
190
205
  }));
191
206
  });
192
207
  describe('remove', () => {
193
208
  it('removes an api key', () => __awaiter(void 0, void 0, void 0, function* () {
194
- mock
195
- .onDelete('/api-keys/5262504e-8ed7-4fac-bd16-0d4be94bc9f2')
196
- .replyOnce(200);
209
+ fetchMock.mockOnce(JSON.stringify({}), {
210
+ status: 200,
211
+ headers: {
212
+ 'content-type': 'application/json',
213
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
214
+ },
215
+ });
197
216
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
198
217
  yield expect(resend.apiKeys.remove('5262504e-8ed7-4fac-bd16-0d4be94bc9f2')).resolves.toMatchInlineSnapshot(`undefined`);
199
- expect(mock.history.delete.length).toBe(1);
200
218
  }));
201
219
  it('throws error when missing id', () => __awaiter(void 0, void 0, void 0, function* () {
202
- mock.onDelete('/api-keys/').replyOnce(500, {
220
+ fetchMock.mockOnce(JSON.stringify({
203
221
  name: 'application_error',
204
222
  message: 'Something went wrong',
205
223
  statusCode: 500,
224
+ }), {
225
+ status: 500,
226
+ headers: {
227
+ 'content-type': 'application/json',
228
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
229
+ },
206
230
  });
207
231
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
208
- yield expect(resend.apiKeys.remove('')).rejects.toMatchInlineSnapshot(`
209
- {
210
- "message": "Something went wrong",
211
- "name": "application_error",
212
- "statusCode": 500,
213
- }
214
- `);
215
- expect(mock.history.delete.length).toBe(1);
232
+ yield expect(resend.apiKeys.remove('')).resolves.toMatchInlineSnapshot(`undefined`);
216
233
  }));
217
234
  it('throws error when wrong id', () => __awaiter(void 0, void 0, void 0, function* () {
218
- mock
219
- .onDelete('/api-keys/34bd250e-615a-400c-be11-5912572ee15b')
220
- .replyOnce(500, {
235
+ fetchMock.mockOnce(JSON.stringify({
221
236
  name: 'not_found',
222
237
  message: 'API key not found',
223
238
  statusCode: 404,
239
+ }), {
240
+ status: 404,
241
+ headers: {
242
+ 'content-type': 'application/json',
243
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
244
+ },
224
245
  });
225
246
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
226
- yield expect(resend.apiKeys.remove('34bd250e-615a-400c-be11-5912572ee15b')).rejects.toMatchInlineSnapshot(`
227
- {
228
- "message": "API key not found",
229
- "name": "not_found",
230
- "statusCode": 404,
231
- }
232
- `);
233
- expect(mock.history.delete.length).toBe(1);
247
+ yield expect(resend.apiKeys.remove('34bd250e-615a-400c-be11-5912572ee15b')).resolves.toMatchInlineSnapshot(`undefined`);
234
248
  }));
235
249
  });
236
250
  });
@@ -22,7 +22,7 @@ class Domains {
22
22
  }
23
23
  list() {
24
24
  return __awaiter(this, void 0, void 0, function* () {
25
- const { data } = yield this.resend.get('/domains');
25
+ const data = yield this.resend.get('/domains');
26
26
  return data;
27
27
  });
28
28
  }
@@ -8,21 +8,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const axios_1 = __importDefault(require("axios"));
16
- const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
12
+ const jest_fetch_mock_1 = require("jest-fetch-mock");
17
13
  const resend_1 = require("../resend");
18
- const mock = new axios_mock_adapter_1.default(axios_1.default);
14
+ (0, jest_fetch_mock_1.enableFetchMocks)();
19
15
  describe('Domains', () => {
20
- beforeEach(() => {
21
- mock.resetHistory();
22
- });
16
+ afterEach(() => fetchMock.resetMocks());
23
17
  describe('create', () => {
24
18
  it('creates a domain', () => __awaiter(void 0, void 0, void 0, function* () {
25
- mock.onPost('/domains', { name: 'resend.com' }).replyOnce(201, {
19
+ fetchMock.mockOnce(JSON.stringify({
26
20
  id: '3d4a472d-bc6d-4dd2-aa9d-d3d50ce87222',
27
21
  name: 'resend.com',
28
22
  created_at: '2023-04-07T22:48:33.420498+00:00',
@@ -71,6 +65,12 @@ describe('Domains', () => {
71
65
  },
72
66
  ],
73
67
  region: 'us-east-1',
68
+ }), {
69
+ status: 200,
70
+ headers: {
71
+ 'content-type': 'application/json',
72
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
73
+ },
74
74
  });
75
75
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
76
76
  yield expect(resend.domains.create({ name: 'resend.com' })).resolves
@@ -126,16 +126,21 @@ describe('Domains', () => {
126
126
  "status": "not_started",
127
127
  }
128
128
  `);
129
- expect(mock.history.post.length).toBe(1);
130
129
  }));
131
130
  it('throws error when missing name', () => __awaiter(void 0, void 0, void 0, function* () {
132
- mock.onPost('/domains').replyOnce(422, {
131
+ fetchMock.mockOnce(JSON.stringify({
133
132
  statusCode: 422,
134
133
  name: 'missing_required_field',
135
134
  message: 'Missing "name" field',
135
+ }), {
136
+ status: 422,
137
+ headers: {
138
+ 'content-type': 'application/json',
139
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
140
+ },
136
141
  });
137
142
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
138
- yield expect(resend.domains.create({ name: '' })).rejects
143
+ yield expect(resend.domains.create({ name: '' })).resolves
139
144
  .toMatchInlineSnapshot(`
140
145
  {
141
146
  "message": "Missing "name" field",
@@ -143,13 +148,10 @@ describe('Domains', () => {
143
148
  "statusCode": 422,
144
149
  }
145
150
  `);
146
- expect(mock.history.post.length).toBe(1);
147
151
  }));
148
152
  describe('with region', () => {
149
153
  it('creates a domain with region', () => __awaiter(void 0, void 0, void 0, function* () {
150
- mock
151
- .onPost('/domains', { name: 'resend.com', region: 'eu-west-1' })
152
- .replyOnce(201, {
154
+ fetchMock.mockOnce(JSON.stringify({
153
155
  id: '3d4a472d-bc6d-4dd2-aa9d-d3d50ce87222',
154
156
  name: 'resend.com',
155
157
  created_at: '2023-04-07T22:48:33.420498+00:00',
@@ -198,7 +200,7 @@ describe('Domains', () => {
198
200
  },
199
201
  ],
200
202
  region: 'eu-west-1',
201
- });
203
+ }));
202
204
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
203
205
  yield expect(resend.domains.create({ name: 'resend.com', region: 'eu-west-1' })).resolves.toMatchInlineSnapshot(`
204
206
  {
@@ -252,32 +254,36 @@ describe('Domains', () => {
252
254
  "status": "not_started",
253
255
  }
254
256
  `);
255
- expect(mock.history.post.length).toBe(1);
256
257
  }));
257
258
  it('throws error with wrong region', () => __awaiter(void 0, void 0, void 0, function* () {
258
- mock.onPost('/domains').replyOnce(422, {
259
+ fetchMock.mockOnce(JSON.stringify({
259
260
  statusCode: 422,
260
261
  name: 'invalid_region',
261
262
  message: 'Region must be "us-east-1" | "eu-west-1" | "sa-east-1"',
263
+ }), {
264
+ status: 422,
265
+ headers: {
266
+ 'content-type': 'application/json',
267
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
268
+ },
262
269
  });
263
270
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
264
271
  yield expect(resend.domains.create({
265
272
  name: 'resend.com',
266
273
  region: 'remote',
267
- })).rejects.toMatchInlineSnapshot(`
274
+ })).resolves.toMatchInlineSnapshot(`
268
275
  {
269
276
  "message": "Region must be "us-east-1" | "eu-west-1" | "sa-east-1"",
270
277
  "name": "invalid_region",
271
278
  "statusCode": 422,
272
279
  }
273
280
  `);
274
- expect(mock.history.post.length).toBe(1);
275
281
  }));
276
282
  });
277
283
  });
278
284
  describe('list', () => {
279
285
  it('lists domains', () => __awaiter(void 0, void 0, void 0, function* () {
280
- mock.onGet('/domains').replyOnce(200, {
286
+ fetchMock.mockOnce(JSON.stringify({
281
287
  data: [
282
288
  {
283
289
  id: 'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
@@ -294,36 +300,49 @@ describe('Domains', () => {
294
300
  region: 'us-east-1',
295
301
  },
296
302
  ],
303
+ }), {
304
+ status: 200,
305
+ headers: {
306
+ 'content-type': 'application/json',
307
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
308
+ },
297
309
  });
298
310
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
299
311
  yield expect(resend.domains.list()).resolves.toMatchInlineSnapshot(`
300
- [
301
- {
302
- "created_at": "2023-04-07T23:13:52.669661+00:00",
303
- "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
304
- "name": "resend.com",
305
- "region": "eu-west-1",
306
- "status": "not_started",
307
- },
308
- {
309
- "created_at": "2023-04-07T23:13:20.417116+00:00",
310
- "id": "ac7503ac-e027-4aea-94b3-b0acd46f65f9",
311
- "name": "react.email",
312
- "region": "us-east-1",
313
- "status": "not_started",
314
- },
315
- ]
312
+ {
313
+ "data": [
314
+ {
315
+ "created_at": "2023-04-07T23:13:52.669661+00:00",
316
+ "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
317
+ "name": "resend.com",
318
+ "region": "eu-west-1",
319
+ "status": "not_started",
320
+ },
321
+ {
322
+ "created_at": "2023-04-07T23:13:20.417116+00:00",
323
+ "id": "ac7503ac-e027-4aea-94b3-b0acd46f65f9",
324
+ "name": "react.email",
325
+ "region": "us-east-1",
326
+ "status": "not_started",
327
+ },
328
+ ],
329
+ }
316
330
  `);
317
- expect(mock.history.get.length).toBe(1);
318
331
  }));
319
332
  });
320
333
  describe('get', () => {
321
334
  describe('when domain not found', () => {
322
335
  it('returns error', () => __awaiter(void 0, void 0, void 0, function* () {
323
- mock.onGet('/domains/1234').replyOnce(200, {
336
+ fetchMock.mockOnce(JSON.stringify({
324
337
  name: 'not_found',
325
338
  message: 'Domain not found',
326
339
  statusCode: 404,
340
+ }), {
341
+ status: 404,
342
+ headers: {
343
+ 'content-type': 'application/json',
344
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
345
+ },
327
346
  });
328
347
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
329
348
  yield expect(resend.domains.get('1234')).resolves
@@ -372,7 +391,13 @@ describe('Domains', () => {
372
391
  },
373
392
  ],
374
393
  };
375
- mock.onGet('/domains/1234').replyOnce(200, domain);
394
+ fetchMock.mockOnce(JSON.stringify(domain), {
395
+ status: 200,
396
+ headers: {
397
+ 'content-type': 'application/json',
398
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
399
+ },
400
+ });
376
401
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
377
402
  yield expect(resend.domains.get('1234')).resolves.toMatchInlineSnapshot(`
378
403
  {
@@ -415,22 +440,28 @@ describe('Domains', () => {
415
440
  });
416
441
  describe('verify', () => {
417
442
  it('verifies a domain', () => __awaiter(void 0, void 0, void 0, function* () {
418
- mock
419
- .onPost('/domains/5262504e-8ed7-4fac-bd16-0d4be94bc9f2/verify')
420
- .replyOnce(200);
443
+ fetchMock.mockOnce(JSON.stringify({}), {
444
+ status: 200,
445
+ headers: {
446
+ 'content-type': 'application/json',
447
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
448
+ },
449
+ });
421
450
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
422
451
  yield expect(resend.domains.verify('5262504e-8ed7-4fac-bd16-0d4be94bc9f2')).resolves.toMatchInlineSnapshot(`undefined`);
423
- expect(mock.history.post.length).toBe(1);
424
452
  }));
425
453
  });
426
454
  describe('remove', () => {
427
455
  it('removes a domain', () => __awaiter(void 0, void 0, void 0, function* () {
428
- mock
429
- .onDelete('/domains/5262504e-8ed7-4fac-bd16-0d4be94bc9f2')
430
- .replyOnce(200);
456
+ fetchMock.mockOnce(JSON.stringify({}), {
457
+ status: 200,
458
+ headers: {
459
+ 'content-type': 'application/json',
460
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
461
+ },
462
+ });
431
463
  const resend = new resend_1.Resend('re_zKa4RCko_Lhm9ost2YjNCctnPjbLw8Nop');
432
464
  yield expect(resend.domains.remove('5262504e-8ed7-4fac-bd16-0d4be94bc9f2')).resolves.toMatchInlineSnapshot(`undefined`);
433
- expect(mock.history.delete.length).toBe(1);
434
465
  }));
435
466
  });
436
467
  });
@@ -24,3 +24,10 @@ export interface DomainDkimRecord {
24
24
  priority?: number;
25
25
  proxy_status?: 'enable' | 'disable';
26
26
  }
27
+ export interface Domain {
28
+ id: string;
29
+ name: string;
30
+ status: DomainStatus;
31
+ created_at: string;
32
+ region: DomainRegion;
33
+ }
@@ -1,8 +1,4 @@
1
- import { DomainRegion, DomainStatus } from './domain';
1
+ import { Domain } from './domain';
2
2
  export type ListDomainsResponse = {
3
- name: string;
4
- id: string;
5
- created_at: string;
6
- region: DomainRegion;
7
- status: DomainStatus;
8
- }[];
3
+ data: Domain[];
4
+ };
@@ -1,4 +1,3 @@
1
- import { AxiosResponse } from 'axios';
2
1
  import { GetOptions, PostOptions, PutOptions } from './common/interfaces';
3
2
  import { ApiKeys } from './api-keys/api-keys';
4
3
  import { Domains } from './domains/domains';
@@ -7,14 +6,14 @@ import { CreateEmailOptions, CreateEmailResponse } from './emails/interfaces';
7
6
  export declare class Resend {
8
7
  readonly key?: string | undefined;
9
8
  private readonly headers;
10
- private readonly request;
11
9
  readonly apiKeys: ApiKeys;
12
10
  readonly domains: Domains;
13
11
  readonly emails: Emails;
14
12
  constructor(key?: string | undefined);
13
+ fetchRequest(path: string, options?: {}): Promise<any>;
15
14
  post<T>(path: string, entity?: any, options?: PostOptions): Promise<T>;
16
15
  get<T>(path: string, options?: GetOptions): Promise<T>;
17
- put(path: string, entity: any, options?: PutOptions): Promise<AxiosResponse>;
18
- delete(path: string, query?: any): Promise<AxiosResponse>;
16
+ put<T>(path: string, entity: any, options?: PutOptions): Promise<T>;
17
+ delete<T>(path: string, query?: any): Promise<T>;
19
18
  sendEmail(data: CreateEmailOptions): Promise<CreateEmailResponse>;
20
19
  }
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,12 +31,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
31
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
32
  });
10
33
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
34
  Object.defineProperty(exports, "__esModule", { value: true });
15
35
  exports.Resend = void 0;
16
- const axios_1 = __importDefault(require("axios"));
36
+ const node_fetch_1 = __importStar(require("node-fetch"));
17
37
  const render_1 = require("@react-email/render");
18
38
  const package_json_1 = require("../package.json");
19
39
  const api_keys_1 = require("./api-keys/api-keys");
@@ -33,110 +53,70 @@ class Resend {
33
53
  throw new Error('Missing API key. Pass it to the constructor `new Resend("re_123")`');
34
54
  }
35
55
  }
36
- this.headers = {
56
+ this.headers = new node_fetch_1.Headers({
37
57
  Authorization: `Bearer ${this.key}`,
38
58
  'User-Agent': userAgent,
39
59
  'Content-Type': 'application/json',
40
- };
41
- this.request = axios_1.default.create({
42
- baseURL: baseUrl,
43
- headers: this.headers,
44
- maxContentLength: Infinity,
45
- maxBodyLength: Infinity,
46
60
  });
47
- this.request.interceptors.response.use((response) => {
48
- if (response.data) {
49
- return response.data;
50
- }
51
- return response;
52
- }, (error) => {
53
- var _a, _b, _c;
54
- if ((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) {
55
- return Promise.reject(error.response.data.error);
56
- }
57
- if ((_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.data) {
58
- return Promise.reject(error.response.data);
61
+ }
62
+ fetchRequest(path, options = {}) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ const response = yield (0, node_fetch_1.default)(`${baseUrl}${path}`, options);
65
+ if (!response.ok) {
66
+ const error = yield response.json();
67
+ return error;
59
68
  }
60
- return Promise.reject(error);
69
+ return yield response.json();
61
70
  });
62
71
  }
63
72
  post(path, entity, options) {
64
73
  return __awaiter(this, void 0, void 0, function* () {
65
- const requestHeaders = {};
66
- try {
67
- return yield this.request.post(path, entity, {
68
- params: options === null || options === void 0 ? void 0 : options.query,
69
- headers: requestHeaders,
70
- });
71
- }
72
- catch (error) {
73
- throw error;
74
- }
74
+ const requestOptions = Object.assign({ method: 'POST', headers: this.headers, body: JSON.stringify(entity) }, options);
75
+ return yield this.fetchRequest(path, requestOptions);
75
76
  });
76
77
  }
77
78
  get(path, options = {}) {
78
79
  return __awaiter(this, void 0, void 0, function* () {
79
- try {
80
- return yield this.request.get(path, {
81
- params: options.query,
82
- });
83
- }
84
- catch (error) {
85
- throw error;
86
- }
80
+ const requestOptions = Object.assign({ method: 'GET', headers: this.headers }, options);
81
+ return yield this.fetchRequest(path, requestOptions);
87
82
  });
88
83
  }
89
84
  put(path, entity, options = {}) {
90
85
  return __awaiter(this, void 0, void 0, function* () {
91
- const requestHeaders = {};
92
- try {
93
- return yield this.request.put(path, entity, {
94
- params: options.query,
95
- headers: requestHeaders,
96
- });
97
- }
98
- catch (error) {
99
- throw error;
100
- }
86
+ const requestOptions = Object.assign({ method: 'PUT', headers: this.headers, body: JSON.stringify(entity) }, options);
87
+ return yield this.fetchRequest(path, requestOptions);
101
88
  });
102
89
  }
103
90
  delete(path, query) {
104
91
  return __awaiter(this, void 0, void 0, function* () {
105
- try {
106
- return yield this.request.delete(path, {
107
- params: query,
108
- });
109
- }
110
- catch (error) {
111
- throw error;
112
- }
92
+ const requestOptions = {
93
+ method: 'DELETE',
94
+ headers: this.headers,
95
+ body: JSON.stringify(query),
96
+ };
97
+ return yield this.fetchRequest(path, requestOptions);
113
98
  });
114
99
  }
115
100
  sendEmail(data) {
116
101
  return __awaiter(this, void 0, void 0, function* () {
117
- try {
118
- const path = `${baseUrl}/email`;
119
- if (data.react) {
120
- data.html = (0, render_1.render)(data.react);
121
- delete data.react;
122
- }
123
- const response = yield this.post(path, {
124
- from: data.from,
125
- to: data.to,
126
- bcc: data.bcc,
127
- cc: data.cc,
128
- reply_to: data.reply_to,
129
- subject: data.subject,
130
- text: data.text,
131
- html: data.html,
132
- attachments: data.attachments,
133
- tags: data.tags,
134
- });
135
- return response;
136
- }
137
- catch (error) {
138
- throw error;
102
+ const path = '/email';
103
+ if (data.react) {
104
+ data.html = (0, render_1.render)(data.react);
105
+ delete data.react;
139
106
  }
107
+ const response = yield this.post(path, {
108
+ from: data.from,
109
+ to: data.to,
110
+ bcc: data.bcc,
111
+ cc: data.cc,
112
+ reply_to: data.reply_to,
113
+ subject: data.subject,
114
+ text: data.text,
115
+ html: data.html,
116
+ attachments: data.attachments,
117
+ tags: data.tags,
118
+ });
119
+ return response;
140
120
  });
141
121
  }
142
122
  }
@@ -8,17 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
12
  const resend_1 = require("./resend");
16
- const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
17
- const axios_1 = __importDefault(require("axios"));
18
- const mock = new axios_mock_adapter_1.default(axios_1.default);
13
+ const jest_fetch_mock_1 = require("jest-fetch-mock");
14
+ (0, jest_fetch_mock_1.enableFetchMocks)();
19
15
  const resend = new resend_1.Resend('re_924b3rjh2387fbewf823');
20
16
  describe('Resend', () => {
21
- afterEach(() => mock.resetHistory());
17
+ afterEach(() => fetchMock.resetMocks());
22
18
  it('throws API key error', () => {
23
19
  expect(() => new resend_1.Resend()).toThrowErrorMatchingSnapshot();
24
20
  });
@@ -29,13 +25,20 @@ describe('Resend', () => {
29
25
  subject: 'Hello World',
30
26
  html: '<h1>Hello world</h1>',
31
27
  };
32
- mock.onPost('/emails', payload).replyOnce(200, {
28
+ fetchMock.mockOnce(JSON.stringify({
33
29
  id: '1234',
34
30
  from: 'bu@resend.com',
35
31
  to: 'zeno@resend.com',
36
32
  created_at: '123',
33
+ }), {
34
+ status: 200,
35
+ headers: {
36
+ 'content-type': 'application/json',
37
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
38
+ },
37
39
  });
38
- const data = yield resend.emails.send(payload);
40
+ const response = yield resend.emails.send(payload);
41
+ const data = yield response;
39
42
  expect(data).toMatchInlineSnapshot(`
40
43
  {
41
44
  "created_at": "123",
@@ -52,13 +55,20 @@ describe('Resend', () => {
52
55
  subject: 'Hello World',
53
56
  text: 'Hello world',
54
57
  };
55
- mock.onPost('/emails', payload).replyOnce(200, {
58
+ fetchMock.mockOnce(JSON.stringify({
56
59
  id: '1234',
57
60
  from: 'admin@resend.com',
58
61
  to: ['bu@resend.com', 'zeno@resend.com'],
59
62
  created_at: '123',
63
+ }), {
64
+ status: 200,
65
+ headers: {
66
+ 'content-type': 'application/json',
67
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
68
+ },
60
69
  });
61
- const data = yield resend.emails.send(payload);
70
+ const response = yield resend.emails.send(payload);
71
+ const data = yield response;
62
72
  expect(data).toMatchInlineSnapshot(`
63
73
  {
64
74
  "created_at": "123",
@@ -79,14 +89,21 @@ describe('Resend', () => {
79
89
  subject: 'Hello World',
80
90
  text: 'Hello world',
81
91
  };
82
- mock.onPost('/emails', payload).replyOnce(200, {
92
+ fetchMock.mockOnce(JSON.stringify({
83
93
  id: '1234',
84
94
  from: 'admin@resend.com',
85
95
  to: 'bu@resend.com',
86
96
  bcc: ['foo@resend.com', 'bar@resend.com'],
87
97
  created_at: '123',
98
+ }), {
99
+ status: 200,
100
+ headers: {
101
+ 'content-type': 'application/json',
102
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
103
+ },
88
104
  });
89
- const data = yield resend.emails.send(payload);
105
+ const response = yield resend.emails.send(payload);
106
+ const data = yield response;
90
107
  expect(data).toMatchInlineSnapshot(`
91
108
  {
92
109
  "bcc": [
@@ -108,14 +125,21 @@ describe('Resend', () => {
108
125
  subject: 'Hello World',
109
126
  text: 'Hello world',
110
127
  };
111
- mock.onPost('/emails', payload).replyOnce(200, {
128
+ fetchMock.mockOnce(JSON.stringify({
112
129
  id: '1234',
113
130
  from: 'admin@resend.com',
114
131
  to: 'bu@resend.com',
115
132
  cc: ['foo@resend.com', 'bar@resend.com'],
116
133
  created_at: '123',
134
+ }), {
135
+ status: 200,
136
+ headers: {
137
+ 'content-type': 'application/json',
138
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
139
+ },
117
140
  });
118
- const data = yield resend.emails.send(payload);
141
+ const response = yield resend.emails.send(payload);
142
+ const data = yield response;
119
143
  expect(data).toMatchInlineSnapshot(`
120
144
  {
121
145
  "cc": [
@@ -130,28 +154,28 @@ describe('Resend', () => {
130
154
  `);
131
155
  }));
132
156
  it('sends email with multiple replyTo emails', () => __awaiter(void 0, void 0, void 0, function* () {
133
- const apiPayload = {
157
+ const payload = {
134
158
  from: 'admin@resend.com',
135
159
  to: 'bu@resend.com',
136
160
  reply_to: ['foo@resend.com', 'bar@resend.com'],
137
161
  subject: 'Hello World',
138
162
  text: 'Hello world',
139
163
  };
140
- mock.onPost('/emails', apiPayload).replyOnce(200, {
164
+ fetchMock.mockOnce(JSON.stringify({
141
165
  id: '1234',
142
166
  from: 'admin@resend.com',
143
167
  to: 'bu@resend.com',
144
168
  reply_to: ['foo@resend.com', 'bar@resend.com'],
145
169
  created_at: '123',
170
+ }), {
171
+ status: 200,
172
+ headers: {
173
+ 'content-type': 'application/json',
174
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
175
+ },
146
176
  });
147
- const payload = {
148
- from: 'admin@resend.com',
149
- to: 'bu@resend.com',
150
- reply_to: ['foo@resend.com', 'bar@resend.com'],
151
- subject: 'Hello World',
152
- text: 'Hello world',
153
- };
154
- const data = yield resend.emails.send(payload);
177
+ const response = yield resend.emails.send(payload);
178
+ const data = yield response;
155
179
  expect(data).toMatchInlineSnapshot(`
156
180
  {
157
181
  "created_at": "123",
@@ -175,10 +199,17 @@ describe('Resend', () => {
175
199
  text: 'Hello world',
176
200
  to: 'bu@resend.com',
177
201
  };
178
- mock.onPost('/emails', payload).replyOnce(200, {
202
+ fetchMock.mockOnce(JSON.stringify({
179
203
  id: '1234',
204
+ }), {
205
+ status: 200,
206
+ headers: {
207
+ 'content-type': 'application/json',
208
+ Authorization: 'Bearer re_924b3rjh2387fbewf823',
209
+ },
180
210
  });
181
- const data = yield resend.emails.send(payload);
211
+ const response = yield resend.emails.send(payload);
212
+ const data = yield response;
182
213
  expect(data).toMatchInlineSnapshot(`
183
214
  {
184
215
  "id": "1234",
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const _1 = require(".");
4
+ const resend = new _1.Resend('re_RL6QTnHU_Jhn8WoXG3a6qXz9ZpQ9s56fq');
5
+ // const p: any = {
6
+ // from: 'bu@resend.com',
7
+ // to: 'develired@resend.dev',
8
+ // text: 'Nice',
9
+ // }
10
+ resend.domains.list().then(console.log).catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "resend",
3
- "version": "0.17.2",
3
+ "version": "0.18.0-canary.0",
4
4
  "description": "Node.js library for the Resend API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/src/index.d.ts",
@@ -28,16 +28,19 @@
28
28
  "homepage": "https://github.com/resend-inc/resend-node#readme",
29
29
  "dependencies": {
30
30
  "@react-email/render": "0.0.7",
31
- "axios": "1.4.0",
31
+ "node-fetch": "2.6.6",
32
32
  "type-fest": "3.13.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/jest": "29.5.3",
36
36
  "@types/node": "18.16.2",
37
+ "@types/node-fetch": "2.6.4",
37
38
  "@types/react": "18.2.0",
38
- "axios-mock-adapter": "1.21.5",
39
+ "fetch-mock": "9.11.0",
39
40
  "jest": "29.6.1",
41
+ "jest-fetch-mock": "3.0.3",
40
42
  "prettier": "3.0.0",
43
+ "prettier-2": "npm:prettier@2",
41
44
  "supertest": "6.3.3",
42
45
  "ts-jest": "29.1.1",
43
46
  "tslint": "6.1.3",