@ewyn/client 0.1.0 → 0.2.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 CHANGED
@@ -22,9 +22,9 @@ yarn add @ewyn/client
22
22
  ### Basic Usage
23
23
 
24
24
  ```typescript
25
- import { Mailer } from '@ewyn/client';
25
+ import { Ewyn } from '@ewyn/client';
26
26
 
27
- const client = new Mailer({
27
+ const client = new Ewyn({
28
28
  workspaceId: 'your-workspace-id',
29
29
  apiKey: 'your-api-key',
30
30
  baseUrl: 'https://www.ewyn.ai/api/v1', // optional; omit to use production default
@@ -46,7 +46,7 @@ await client.send({
46
46
  Get full TypeScript autocomplete and validation by copying your template config from the dashboard:
47
47
 
48
48
  ```typescript
49
- import { Mailer } from '@ewyn/client';
49
+ import { Ewyn } from '@ewyn/client';
50
50
 
51
51
  // 1. Copy template config from dashboard (API Keys page)
52
52
  const config = {
@@ -71,7 +71,7 @@ const config = {
71
71
  } as const; // ← Important: use 'as const'
72
72
 
73
73
  // 2. Initialize with config
74
- const client = new Mailer({
74
+ const client = new Ewyn({
75
75
  workspaceId: 'your-workspace-id',
76
76
  apiKey: 'your-api-key',
77
77
  templates: config,
@@ -103,7 +103,7 @@ const config = {
103
103
  // ... paste here
104
104
  } as const;
105
105
 
106
- const client = new Mailer({
106
+ const client = new Ewyn({
107
107
  workspaceId: 'your-workspace-id',
108
108
  apiKey: 'your-api-key',
109
109
  templates: config, // Now fully type-safe!
@@ -123,12 +123,12 @@ curl -X GET https://www.ewyn.ai/api/v1/workspaces/YOUR_WORKSPACE_ID/templates/co
123
123
 
124
124
  ## API Reference
125
125
 
126
- ### `Mailer` Class
126
+ ### `Ewyn` Class
127
127
 
128
128
  #### Constructor
129
129
 
130
130
  ```typescript
131
- new Mailer(options: MailerOptions)
131
+ new Ewyn(options: EwynOptions)
132
132
  ```
133
133
 
134
134
  **Options:**
@@ -168,20 +168,20 @@ Send an email using a template.
168
168
 
169
169
  **Throws:**
170
170
 
171
- - `MailerApiError`: If the API request fails
171
+ - `EwynApiError`: If the API request fails
172
172
  - `Error`: If validation fails (missing template, missing variables, etc.)
173
173
 
174
174
  ### Error Handling
175
175
 
176
- The SDK throws `MailerApiError` for API errors:
176
+ The SDK throws `EwynApiError` for API errors:
177
177
 
178
178
  ```typescript
179
- import { Mailer, MailerApiError } from '@ewyn/client';
179
+ import { Ewyn, EwynApiError } from '@ewyn/client';
180
180
 
181
181
  try {
182
182
  await client.send({ /* ... */ });
183
183
  } catch (error) {
184
- if (error instanceof MailerApiError) {
184
+ if (error instanceof EwynApiError) {
185
185
  console.error('API Error:', error.status, error.message);
186
186
  console.error('Details:', error.details);
187
187
 
@@ -7,7 +7,7 @@
7
7
  * variables at compile time.
8
8
  */
9
9
  import { expectTypeOf, test } from 'vitest';
10
- import { Mailer } from '../index.js';
10
+ import { Ewyn } from '../index.js';
11
11
  // Dashboard-shaped config: same structure as getConfig response (id, name, version, vars)
12
12
  const dashboardConfig = {
13
13
  welcome: {
@@ -29,7 +29,7 @@ const dashboardConfig = {
29
29
  },
30
30
  };
31
31
  test('client with dashboard config has typed send', () => {
32
- const client = new Mailer({
32
+ const client = new Ewyn({
33
33
  workspaceId: 'ws',
34
34
  apiKey: 'key',
35
35
  templates: dashboardConfig,
@@ -38,7 +38,7 @@ test('client with dashboard config has typed send', () => {
38
38
  expectTypeOf(client.send).toBeFunction();
39
39
  });
40
40
  test('valid send: required var present, optional omitted', () => {
41
- const client = new Mailer({
41
+ const client = new Ewyn({
42
42
  workspaceId: 'ws',
43
43
  apiKey: 'key',
44
44
  templates: dashboardConfig,
@@ -50,7 +50,7 @@ test('valid send: required var present, optional omitted', () => {
50
50
  }).toMatchTypeOf();
51
51
  });
52
52
  test('valid send: required and optional vars', () => {
53
- const client = new Mailer({
53
+ const client = new Ewyn({
54
54
  workspaceId: 'ws',
55
55
  apiKey: 'key',
56
56
  templates: dashboardConfig,
@@ -62,7 +62,7 @@ test('valid send: required and optional vars', () => {
62
62
  }).toMatchTypeOf();
63
63
  });
64
64
  test('valid send: hyphenated template name', () => {
65
- const client = new Mailer({
65
+ const client = new Ewyn({
66
66
  workspaceId: 'ws',
67
67
  apiKey: 'key',
68
68
  templates: dashboardConfig,
@@ -74,7 +74,7 @@ test('valid send: hyphenated template name', () => {
74
74
  }).toMatchTypeOf();
75
75
  });
76
76
  test('send return type is Promise<SendEmailResponse>', () => {
77
- const client = new Mailer({
77
+ const client = new Ewyn({
78
78
  workspaceId: 'ws',
79
79
  apiKey: 'key',
80
80
  templates: dashboardConfig,
@@ -86,7 +86,7 @@ test('template name is constrained to config keys at type level', () => {
86
86
  expectTypeOf().toMatchTypeOf();
87
87
  });
88
88
  test('missing required variable is rejected by types', () => {
89
- const client = new Mailer({
89
+ const client = new Ewyn({
90
90
  workspaceId: 'ws',
91
91
  apiKey: 'key',
92
92
  templates: dashboardConfig,
@@ -7,7 +7,7 @@
7
7
  * the dashboard" work with the SDK and that runtime validation behaves correctly.
8
8
  */
9
9
  import { beforeEach, describe, expect, it, vi } from 'vitest';
10
- import { Mailer } from '../index.js';
10
+ import { Ewyn } from '../index.js';
11
11
  global.fetch = vi.fn();
12
12
  describe('Dashboard config (runtime)', () => {
13
13
  beforeEach(() => {
@@ -45,7 +45,7 @@ describe('Dashboard config (runtime)', () => {
45
45
  },
46
46
  };
47
47
  it('sends with dashboard-shaped config (only required vars)', async () => {
48
- const client = new Mailer({
48
+ const client = new Ewyn({
49
49
  workspaceId: 'ws-1',
50
50
  apiKey: 'key-1',
51
51
  baseUrl: 'https://api.test.com/api/v1',
@@ -81,7 +81,7 @@ describe('Dashboard config (runtime)', () => {
81
81
  expect(body.variables).toEqual({ firstName: 'Jane', lastName: 'Doe' });
82
82
  });
83
83
  it('sends with dashboard-shaped config (mixed required/optional, hyphenated key)', async () => {
84
- const client = new Mailer({
84
+ const client = new Ewyn({
85
85
  workspaceId: 'ws-2',
86
86
  apiKey: 'key-2',
87
87
  baseUrl: 'https://api.test.com/api/v1',
@@ -117,7 +117,7 @@ describe('Dashboard config (runtime)', () => {
117
117
  });
118
118
  });
119
119
  it('sends with template that has empty vars (dashboard shape)', async () => {
120
- const client = new Mailer({
120
+ const client = new Ewyn({
121
121
  workspaceId: 'ws-3',
122
122
  apiKey: 'key-3',
123
123
  baseUrl: 'https://api.test.com/api/v1',
@@ -147,7 +147,7 @@ describe('Dashboard config (runtime)', () => {
147
147
  expect(body.variables).toEqual({});
148
148
  });
149
149
  it('throws when required variable is missing (dashboard config)', async () => {
150
- const client = new Mailer({
150
+ const client = new Ewyn({
151
151
  workspaceId: 'ws-1',
152
152
  apiKey: 'key-1',
153
153
  baseUrl: 'https://api.test.com/api/v1',
@@ -165,7 +165,7 @@ describe('Dashboard config (runtime)', () => {
165
165
  })).rejects.toThrow('Missing required variables for template "welcome": lastName');
166
166
  });
167
167
  it('throws when template name is not in config (dashboard config)', async () => {
168
- const client = new Mailer({
168
+ const client = new Ewyn({
169
169
  workspaceId: 'ws-1',
170
170
  apiKey: 'key-1',
171
171
  baseUrl: 'https://api.test.com/api/v1',
@@ -1,24 +1,24 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { MailerApiError } from '../errors.js';
3
- describe('MailerApiError', () => {
2
+ import { EwynApiError } from '../errors.js';
3
+ describe('EwynApiError', () => {
4
4
  describe('constructor', () => {
5
5
  it('should create error with status code', () => {
6
- const error = new MailerApiError(400);
6
+ const error = new EwynApiError(400);
7
7
  expect(error).toBeInstanceOf(Error);
8
- expect(error).toBeInstanceOf(MailerApiError);
8
+ expect(error).toBeInstanceOf(EwynApiError);
9
9
  expect(error.status).toBe(400);
10
10
  expect(error.message).toBe('API request failed with status 400');
11
- expect(error.name).toBe('MailerApiError');
11
+ expect(error.name).toBe('EwynApiError');
12
12
  });
13
13
  it('should create error with custom message', () => {
14
- const error = new MailerApiError(400, 'INVALID_REQUEST', undefined, 'Invalid email address');
14
+ const error = new EwynApiError(400, 'INVALID_REQUEST', undefined, 'Invalid email address');
15
15
  expect(error.status).toBe(400);
16
16
  expect(error.code).toBe('INVALID_REQUEST');
17
17
  expect(error.message).toBe('Invalid email address');
18
18
  });
19
19
  it('should create error with details', () => {
20
20
  const details = { field: 'to', reason: 'Invalid email format' };
21
- const error = new MailerApiError(400, 'VALIDATION_ERROR', details);
21
+ const error = new EwynApiError(400, 'VALIDATION_ERROR', details);
22
22
  expect(error.status).toBe(400);
23
23
  expect(error.code).toBe('VALIDATION_ERROR');
24
24
  expect(error.details).toEqual(details);
@@ -26,62 +26,62 @@ describe('MailerApiError', () => {
26
26
  });
27
27
  describe('isClientError', () => {
28
28
  it('should return true for 4xx errors', () => {
29
- expect(new MailerApiError(400).isClientError()).toBe(true);
30
- expect(new MailerApiError(401).isClientError()).toBe(true);
31
- expect(new MailerApiError(404).isClientError()).toBe(true);
32
- expect(new MailerApiError(429).isClientError()).toBe(true);
33
- expect(new MailerApiError(499).isClientError()).toBe(true);
29
+ expect(new EwynApiError(400).isClientError()).toBe(true);
30
+ expect(new EwynApiError(401).isClientError()).toBe(true);
31
+ expect(new EwynApiError(404).isClientError()).toBe(true);
32
+ expect(new EwynApiError(429).isClientError()).toBe(true);
33
+ expect(new EwynApiError(499).isClientError()).toBe(true);
34
34
  });
35
35
  it('should return false for non-4xx errors', () => {
36
- expect(new MailerApiError(200).isClientError()).toBe(false);
37
- expect(new MailerApiError(399).isClientError()).toBe(false);
38
- expect(new MailerApiError(500).isClientError()).toBe(false);
36
+ expect(new EwynApiError(200).isClientError()).toBe(false);
37
+ expect(new EwynApiError(399).isClientError()).toBe(false);
38
+ expect(new EwynApiError(500).isClientError()).toBe(false);
39
39
  });
40
40
  });
41
41
  describe('isServerError', () => {
42
42
  it('should return true for 5xx errors', () => {
43
- expect(new MailerApiError(500).isServerError()).toBe(true);
44
- expect(new MailerApiError(502).isServerError()).toBe(true);
45
- expect(new MailerApiError(503).isServerError()).toBe(true);
46
- expect(new MailerApiError(599).isServerError()).toBe(true);
43
+ expect(new EwynApiError(500).isServerError()).toBe(true);
44
+ expect(new EwynApiError(502).isServerError()).toBe(true);
45
+ expect(new EwynApiError(503).isServerError()).toBe(true);
46
+ expect(new EwynApiError(599).isServerError()).toBe(true);
47
47
  });
48
48
  it('should return false for non-5xx errors', () => {
49
- expect(new MailerApiError(200).isServerError()).toBe(false);
50
- expect(new MailerApiError(400).isServerError()).toBe(false);
51
- expect(new MailerApiError(499).isServerError()).toBe(false);
49
+ expect(new EwynApiError(200).isServerError()).toBe(false);
50
+ expect(new EwynApiError(400).isServerError()).toBe(false);
51
+ expect(new EwynApiError(499).isServerError()).toBe(false);
52
52
  });
53
53
  });
54
54
  describe('isRetryable', () => {
55
55
  it('should return true for 429 rate limit', () => {
56
- expect(new MailerApiError(429).isRetryable()).toBe(true);
56
+ expect(new EwynApiError(429).isRetryable()).toBe(true);
57
57
  });
58
58
  it('should return true for 5xx errors', () => {
59
- expect(new MailerApiError(500).isRetryable()).toBe(true);
60
- expect(new MailerApiError(502).isRetryable()).toBe(true);
61
- expect(new MailerApiError(503).isRetryable()).toBe(true);
59
+ expect(new EwynApiError(500).isRetryable()).toBe(true);
60
+ expect(new EwynApiError(502).isRetryable()).toBe(true);
61
+ expect(new EwynApiError(503).isRetryable()).toBe(true);
62
62
  });
63
63
  it('should return false for other errors', () => {
64
- expect(new MailerApiError(200).isRetryable()).toBe(false);
65
- expect(new MailerApiError(400).isRetryable()).toBe(false);
66
- expect(new MailerApiError(401).isRetryable()).toBe(false);
67
- expect(new MailerApiError(404).isRetryable()).toBe(false);
64
+ expect(new EwynApiError(200).isRetryable()).toBe(false);
65
+ expect(new EwynApiError(400).isRetryable()).toBe(false);
66
+ expect(new EwynApiError(401).isRetryable()).toBe(false);
67
+ expect(new EwynApiError(404).isRetryable()).toBe(false);
68
68
  });
69
69
  });
70
70
  describe('error prototype chain', () => {
71
71
  it('should maintain correct prototype chain', () => {
72
- const error = new MailerApiError(400);
72
+ const error = new EwynApiError(400);
73
73
  expect(error instanceof Error).toBe(true);
74
- expect(error instanceof MailerApiError).toBe(true);
75
- expect(Object.getPrototypeOf(error)).toBe(MailerApiError.prototype);
74
+ expect(error instanceof EwynApiError).toBe(true);
75
+ expect(Object.getPrototypeOf(error)).toBe(EwynApiError.prototype);
76
76
  });
77
77
  it('should work with try-catch instanceof checks', () => {
78
78
  try {
79
- throw new MailerApiError(400, 'TEST_ERROR');
79
+ throw new EwynApiError(400, 'TEST_ERROR');
80
80
  }
81
81
  catch (error) {
82
- expect(error instanceof MailerApiError).toBe(true);
82
+ expect(error instanceof EwynApiError).toBe(true);
83
83
  expect(error instanceof Error).toBe(true);
84
- if (error instanceof MailerApiError) {
84
+ if (error instanceof EwynApiError) {
85
85
  expect(error.code).toBe('TEST_ERROR');
86
86
  }
87
87
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ewyn.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ewyn.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ewyn.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,429 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { Ewyn, EwynApiError } from '../index.js';
3
+ // Mock fetch globally
4
+ global.fetch = vi.fn();
5
+ describe('Ewyn SDK', () => {
6
+ let client;
7
+ beforeEach(() => {
8
+ vi.clearAllMocks();
9
+ global.fetch.mockReset();
10
+ client = new Ewyn({
11
+ workspaceId: 'test-workspace-id',
12
+ apiKey: 'test-api-key',
13
+ baseUrl: 'https://api.test.com/api/v1',
14
+ maxRetries: 2, // Allow 1 retry (attempt < maxRetries)
15
+ timeout: 5000,
16
+ });
17
+ });
18
+ describe('constructor', () => {
19
+ it('should create client with required options', () => {
20
+ expect(client).toBeInstanceOf(Ewyn);
21
+ });
22
+ it('should use default base URL if not provided', () => {
23
+ const defaultClient = new Ewyn({
24
+ workspaceId: 'test-workspace-id',
25
+ apiKey: 'test-api-key',
26
+ });
27
+ expect(defaultClient).toBeInstanceOf(Ewyn);
28
+ });
29
+ it('should accept template config', () => {
30
+ const config = {
31
+ welcome: {
32
+ id: 'version-uuid',
33
+ name: 'Welcome',
34
+ version: 1,
35
+ vars: {
36
+ firstName: { required: true },
37
+ },
38
+ },
39
+ };
40
+ const configClient = new Ewyn({
41
+ workspaceId: 'test-workspace-id',
42
+ apiKey: 'test-api-key',
43
+ templates: config,
44
+ });
45
+ expect(configClient).toBeInstanceOf(Ewyn);
46
+ });
47
+ });
48
+ describe('send', () => {
49
+ it('should send email with template ID', async () => {
50
+ const mockResponse = {
51
+ messageId: 'msg-123',
52
+ status: 'queued',
53
+ queuedAt: '2024-01-01T00:00:00Z',
54
+ };
55
+ global.fetch.mockResolvedValueOnce({
56
+ ok: true,
57
+ status: 200,
58
+ json: async () => mockResponse,
59
+ });
60
+ const result = await client.send({
61
+ to: 'test@example.com',
62
+ templateId: 'template-uuid',
63
+ variables: {
64
+ firstName: 'John',
65
+ },
66
+ });
67
+ expect(result).toEqual(mockResponse);
68
+ expect(global.fetch).toHaveBeenCalledWith('https://api.test.com/api/v1/workspaces/test-workspace-id/send', expect.objectContaining({
69
+ method: 'POST',
70
+ headers: expect.objectContaining({
71
+ 'Content-Type': 'application/json',
72
+ 'Authorization': 'Bearer test-api-key',
73
+ }),
74
+ body: JSON.stringify({
75
+ to: 'test@example.com',
76
+ templateId: 'template-uuid',
77
+ variables: {
78
+ firstName: 'John',
79
+ },
80
+ }),
81
+ }));
82
+ });
83
+ it('should send email with template name when config provided', async () => {
84
+ const config = {
85
+ welcome: {
86
+ id: 'version-uuid',
87
+ name: 'Welcome',
88
+ version: 1,
89
+ vars: {
90
+ firstName: { required: true },
91
+ },
92
+ },
93
+ };
94
+ const configClient = new Ewyn({
95
+ workspaceId: 'test-workspace-id',
96
+ apiKey: 'test-api-key',
97
+ templates: config,
98
+ });
99
+ const mockResponse = {
100
+ messageId: 'msg-123',
101
+ status: 'queued',
102
+ queuedAt: '2024-01-01T00:00:00Z',
103
+ };
104
+ global.fetch.mockResolvedValueOnce({
105
+ ok: true,
106
+ status: 200,
107
+ json: async () => mockResponse,
108
+ });
109
+ const result = await configClient.send({
110
+ to: 'test@example.com',
111
+ template: 'welcome',
112
+ variables: {
113
+ firstName: 'John',
114
+ },
115
+ });
116
+ expect(result).toEqual(mockResponse);
117
+ });
118
+ it('should include version parameter if specified', async () => {
119
+ const mockResponse = {
120
+ messageId: 'msg-123',
121
+ status: 'queued',
122
+ queuedAt: '2024-01-01T00:00:00Z',
123
+ };
124
+ global.fetch.mockResolvedValueOnce({
125
+ ok: true,
126
+ status: 200,
127
+ json: async () => mockResponse,
128
+ });
129
+ await client.send({
130
+ to: 'test@example.com',
131
+ templateId: 'template-uuid',
132
+ version: 2,
133
+ variables: {
134
+ firstName: 'John',
135
+ },
136
+ });
137
+ expect(global.fetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
138
+ body: expect.stringContaining('"version":2'),
139
+ }));
140
+ });
141
+ it('should include metadata if provided', async () => {
142
+ const mockResponse = {
143
+ messageId: 'msg-123',
144
+ status: 'queued',
145
+ queuedAt: '2024-01-01T00:00:00Z',
146
+ };
147
+ global.fetch.mockResolvedValueOnce({
148
+ ok: true,
149
+ status: 200,
150
+ json: async () => mockResponse,
151
+ });
152
+ await client.send({
153
+ to: 'test@example.com',
154
+ templateId: 'template-uuid',
155
+ metadata: {
156
+ userId: 'user-123',
157
+ },
158
+ });
159
+ expect(global.fetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
160
+ body: expect.stringContaining('"metadata"'),
161
+ }));
162
+ });
163
+ it('should include idempotency key if provided', async () => {
164
+ const mockResponse = {
165
+ messageId: 'msg-123',
166
+ status: 'queued',
167
+ queuedAt: '2024-01-01T00:00:00Z',
168
+ };
169
+ global.fetch.mockResolvedValueOnce({
170
+ ok: true,
171
+ status: 200,
172
+ json: async () => mockResponse,
173
+ });
174
+ await client.send({
175
+ to: 'test@example.com',
176
+ templateId: 'template-uuid',
177
+ idempotencyKey: 'idempotency-key-123',
178
+ });
179
+ expect(global.fetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
180
+ body: expect.stringContaining('"idempotencyKey":"idempotency-key-123"'),
181
+ }));
182
+ });
183
+ it('should throw error if neither templateId nor template provided', async () => {
184
+ await expect(client.send({
185
+ to: 'test@example.com',
186
+ variables: {},
187
+ })).rejects.toThrow('Either templateId or template must be provided');
188
+ });
189
+ it('should throw error if template name provided without config', async () => {
190
+ await expect(client.send({
191
+ to: 'test@example.com',
192
+ template: 'welcome',
193
+ variables: {},
194
+ })).rejects.toThrow('Template name provided but no template config was provided');
195
+ });
196
+ it('should throw error if template not found in config', async () => {
197
+ const config = {
198
+ welcome: {
199
+ id: 'version-uuid',
200
+ name: 'Welcome',
201
+ version: 1,
202
+ vars: {},
203
+ },
204
+ };
205
+ const configClient = new Ewyn({
206
+ workspaceId: 'test-workspace-id',
207
+ apiKey: 'test-api-key',
208
+ templates: config,
209
+ });
210
+ await expect(configClient.send({
211
+ to: 'test@example.com',
212
+ template: 'nonexistent',
213
+ variables: {},
214
+ })).rejects.toThrow('Template "nonexistent" not found in template config');
215
+ });
216
+ });
217
+ describe('variable validation', () => {
218
+ it('should validate required variables', async () => {
219
+ const config = {
220
+ welcome: {
221
+ id: 'version-uuid',
222
+ name: 'Welcome',
223
+ version: 1,
224
+ vars: {
225
+ firstName: { required: true },
226
+ lastName: { required: true },
227
+ },
228
+ },
229
+ };
230
+ const configClient = new Ewyn({
231
+ workspaceId: 'test-workspace-id',
232
+ apiKey: 'test-api-key',
233
+ templates: config,
234
+ });
235
+ await expect(configClient.send({
236
+ to: 'test@example.com',
237
+ template: 'welcome',
238
+ variables: {
239
+ firstName: 'John',
240
+ // lastName missing
241
+ },
242
+ })).rejects.toThrow('Missing required variables for template "welcome": lastName');
243
+ });
244
+ it('should allow optional variables to be omitted', async () => {
245
+ const config = {
246
+ welcome: {
247
+ id: 'version-uuid',
248
+ name: 'Welcome',
249
+ version: 1,
250
+ vars: {
251
+ firstName: { required: true },
252
+ lastName: { required: false },
253
+ },
254
+ },
255
+ };
256
+ const configClient = new Ewyn({
257
+ workspaceId: 'test-workspace-id',
258
+ apiKey: 'test-api-key',
259
+ templates: config,
260
+ });
261
+ const mockResponse = {
262
+ messageId: 'msg-123',
263
+ status: 'queued',
264
+ queuedAt: '2024-01-01T00:00:00Z',
265
+ };
266
+ global.fetch.mockResolvedValueOnce({
267
+ ok: true,
268
+ status: 200,
269
+ json: async () => mockResponse,
270
+ });
271
+ const result = await configClient.send({
272
+ to: 'test@example.com',
273
+ template: 'welcome',
274
+ variables: {
275
+ firstName: 'John',
276
+ // lastName omitted (optional)
277
+ },
278
+ });
279
+ expect(result).toEqual(mockResponse);
280
+ });
281
+ });
282
+ describe('error handling', () => {
283
+ it('should throw EwynApiError on 400 error', async () => {
284
+ const mock400Response = {
285
+ ok: false,
286
+ status: 400,
287
+ json: async () => ({
288
+ error: 'Bad request',
289
+ code: 'INVALID_REQUEST',
290
+ details: { field: 'to' },
291
+ }),
292
+ };
293
+ global.fetch
294
+ .mockResolvedValueOnce(mock400Response)
295
+ .mockResolvedValueOnce(mock400Response);
296
+ await expect(client.send({
297
+ to: 'test@example.com',
298
+ templateId: 'template-uuid',
299
+ })).rejects.toThrow(EwynApiError);
300
+ try {
301
+ await client.send({
302
+ to: 'test@example.com',
303
+ templateId: 'template-uuid',
304
+ });
305
+ }
306
+ catch (error) {
307
+ expect(error).toBeInstanceOf(EwynApiError);
308
+ expect(error.status).toBe(400);
309
+ expect(error.code).toBe('INVALID_REQUEST');
310
+ expect(error.isClientError()).toBe(true);
311
+ expect(error.isServerError()).toBe(false);
312
+ expect(error.isRetryable()).toBe(false);
313
+ }
314
+ });
315
+ it('should throw EwynApiError on 429 rate limit', async () => {
316
+ global.fetch.mockResolvedValue({
317
+ ok: false,
318
+ status: 429,
319
+ json: async () => ({
320
+ error: 'Too many requests',
321
+ code: 'RATE_LIMITED',
322
+ }),
323
+ });
324
+ try {
325
+ await client.send({
326
+ to: 'test@example.com',
327
+ templateId: 'template-uuid',
328
+ });
329
+ }
330
+ catch (error) {
331
+ expect(error).toBeInstanceOf(EwynApiError);
332
+ expect(error.status).toBe(429);
333
+ expect(error.isRetryable()).toBe(true);
334
+ }
335
+ // Should have retried once (maxRetries: 1)
336
+ expect(global.fetch).toHaveBeenCalledTimes(2);
337
+ });
338
+ it('should throw EwynApiError on 500 server error', async () => {
339
+ global.fetch.mockResolvedValue({
340
+ ok: false,
341
+ status: 500,
342
+ json: async () => ({
343
+ error: 'Internal server error',
344
+ }),
345
+ });
346
+ try {
347
+ await client.send({
348
+ to: 'test@example.com',
349
+ templateId: 'template-uuid',
350
+ });
351
+ }
352
+ catch (error) {
353
+ expect(error).toBeInstanceOf(EwynApiError);
354
+ expect(error.status).toBe(500);
355
+ expect(error.isServerError()).toBe(true);
356
+ expect(error.isRetryable()).toBe(true);
357
+ }
358
+ // Should have retried once
359
+ expect(global.fetch).toHaveBeenCalledTimes(2);
360
+ });
361
+ it('should handle network errors', async () => {
362
+ global.fetch.mockRejectedValue(new Error('Network error'));
363
+ await expect(client.send({
364
+ to: 'test@example.com',
365
+ templateId: 'template-uuid',
366
+ })).rejects.toThrow('Network error');
367
+ // Should have retried once
368
+ expect(global.fetch).toHaveBeenCalledTimes(2);
369
+ });
370
+ it('should handle timeout errors', async () => {
371
+ const abortError = new Error('The operation was aborted');
372
+ abortError.name = 'AbortError';
373
+ global.fetch.mockRejectedValueOnce(abortError);
374
+ try {
375
+ await client.send({
376
+ to: 'test@example.com',
377
+ templateId: 'template-uuid',
378
+ });
379
+ }
380
+ catch (error) {
381
+ expect(error).toBeInstanceOf(EwynApiError);
382
+ expect(error.status).toBe(408);
383
+ expect(error.code).toBe('TIMEOUT');
384
+ }
385
+ });
386
+ });
387
+ describe('retry logic', () => {
388
+ it('should retry on 5xx errors with exponential backoff', async () => {
389
+ const startTime = Date.now();
390
+ global.fetch
391
+ .mockResolvedValueOnce({
392
+ ok: false,
393
+ status: 500,
394
+ json: async () => ({ error: 'Server error' }),
395
+ })
396
+ .mockResolvedValueOnce({
397
+ ok: true,
398
+ status: 200,
399
+ json: async () => ({
400
+ messageId: 'msg-123',
401
+ status: 'queued',
402
+ queuedAt: '2024-01-01T00:00:00Z',
403
+ }),
404
+ });
405
+ const result = await client.send({
406
+ to: 'test@example.com',
407
+ templateId: 'template-uuid',
408
+ });
409
+ const duration = Date.now() - startTime;
410
+ expect(result.messageId).toBe('msg-123');
411
+ expect(global.fetch).toHaveBeenCalledTimes(2);
412
+ // Should have waited ~1 second between attempts
413
+ expect(duration).toBeGreaterThanOrEqual(950);
414
+ });
415
+ it('should not retry on 4xx client errors', async () => {
416
+ global.fetch.mockResolvedValueOnce({
417
+ ok: false,
418
+ status: 404,
419
+ json: async () => ({ error: 'Not found' }),
420
+ });
421
+ await expect(client.send({
422
+ to: 'test@example.com',
423
+ templateId: 'template-uuid',
424
+ })).rejects.toThrow(EwynApiError);
425
+ // Should not retry
426
+ expect(global.fetch).toHaveBeenCalledTimes(1);
427
+ });
428
+ });
429
+ });
package/dist/errors.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * API Error class for handling HTTP errors from the Mailer API
2
+ * API Error class for handling HTTP errors from the Ewyn API
3
3
  */
4
- export declare class MailerApiError extends Error {
4
+ export declare class EwynApiError extends Error {
5
5
  status: number;
6
6
  code?: string | undefined;
7
7
  details?: unknown | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;IAE9B,MAAM,EAAE,MAAM;IACd,IAAI,CAAC,EAAE,MAAM;IACb,OAAO,CAAC,EAAE,OAAO;gBAFjB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,OAAO,CAAC,EAAE,OAAO,YAAA,EACxB,OAAO,CAAC,EAAE,MAAM;IAOlB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,WAAW,IAAI,OAAO;CAGvB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;IAE5B,MAAM,EAAE,MAAM;IACd,IAAI,CAAC,EAAE,MAAM;IACb,OAAO,CAAC,EAAE,OAAO;gBAFjB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,OAAO,CAAC,EAAE,OAAO,YAAA,EACxB,OAAO,CAAC,EAAE,MAAM;IAOlB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,WAAW,IAAI,OAAO;CAGvB"}
package/dist/errors.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * API Error class for handling HTTP errors from the Mailer API
2
+ * API Error class for handling HTTP errors from the Ewyn API
3
3
  */
4
- export class MailerApiError extends Error {
4
+ export class EwynApiError extends Error {
5
5
  status;
6
6
  code;
7
7
  details;
@@ -10,8 +10,8 @@ export class MailerApiError extends Error {
10
10
  this.status = status;
11
11
  this.code = code;
12
12
  this.details = details;
13
- this.name = 'MailerApiError';
14
- Object.setPrototypeOf(this, MailerApiError.prototype);
13
+ this.name = 'EwynApiError';
14
+ Object.setPrototypeOf(this, EwynApiError.prototype);
15
15
  }
16
16
  /**
17
17
  * Check if the error is a client error (4xx)
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import type { MailerOptions, MailerOptionsTyped, SendEmailOptions, SendEmailOptionsTyped, SendEmailResponse, TemplateConfig } from './types.js';
1
+ import type { EwynOptions, EwynOptionsTyped, SendEmailOptions, SendEmailOptionsTyped, SendEmailResponse, TemplateConfig } from './types.js';
2
2
  /**
3
- * Mailer SDK Client
3
+ * Ewyn SDK Client
4
4
  *
5
5
  * @example Basic usage without template config
6
6
  * ```ts
7
- * const client = new Mailer({
7
+ * const client = new Ewyn({
8
8
  * workspaceId: 'your-workspace-id',
9
9
  * apiKey: 'your-api-key',
10
10
  * });
@@ -30,7 +30,7 @@ import type { MailerOptions, MailerOptionsTyped, SendEmailOptions, SendEmailOpti
30
30
  * }
31
31
  * } as const;
32
32
  *
33
- * const client = new Mailer({
33
+ * const client = new Ewyn({
34
34
  * workspaceId: 'your-workspace-id',
35
35
  * apiKey: 'your-api-key',
36
36
  * templates: config
@@ -46,20 +46,20 @@ import type { MailerOptions, MailerOptionsTyped, SendEmailOptions, SendEmailOpti
46
46
  * });
47
47
  * ```
48
48
  */
49
- export declare class Mailer<TConfig extends TemplateConfig = TemplateConfig> {
49
+ export declare class Ewyn<TConfig extends TemplateConfig = TemplateConfig> {
50
50
  private readonly workspaceId;
51
51
  private readonly apiKey;
52
52
  private readonly baseUrl;
53
53
  private readonly templates?;
54
54
  private readonly maxRetries;
55
55
  private readonly timeout;
56
- constructor(options: MailerOptions | MailerOptionsTyped<TConfig>);
56
+ constructor(options: EwynOptions | EwynOptionsTyped<TConfig>);
57
57
  /**
58
58
  * Send an email using a template
59
59
  *
60
60
  * @param options - Email sending options
61
61
  * @returns Promise resolving to the send response
62
- * @throws {MailerApiError} If the API request fails
62
+ * @throws {EwynApiError} If the API request fails
63
63
  *
64
64
  * @example With template ID
65
65
  * ```ts
@@ -94,6 +94,6 @@ export declare class Mailer<TConfig extends TemplateConfig = TemplateConfig> {
94
94
  */
95
95
  private requestWithRetry;
96
96
  }
97
- export { MailerApiError } from './errors.js';
98
- export type { MailerOptions, MailerOptionsTyped, SendEmailOptions, SendEmailOptionsBase, SendEmailOptionsTyped, SendEmailResponse, TemplateConfig, TemplateConfigEntry, TemplateVariable } from './types.js';
97
+ export { EwynApiError } from './errors.js';
98
+ export type { EwynOptions, EwynOptionsTyped, SendEmailOptions, SendEmailOptionsBase, SendEmailOptionsTyped, SendEmailResponse, TemplateConfig, TemplateConfigEntry, TemplateVariable, } from './types.js';
99
99
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,MAAM,CAAC,OAAO,SAAS,cAAc,GAAG,cAAc;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,aAAa,GAAG,kBAAkB,CAAC,OAAO,CAAC;IAShE;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,IAAI,CACR,OAAO,EAAE,OAAO,SAAS,cAAc,GACnC,qBAAqB,CAAC,OAAO,CAAC,GAAG,gBAAgB,GACjD,gBAAgB,GACnB,OAAO,CAAC,iBAAiB,CAAC;IA8C7B;;OAEG;YACW,iBAAiB;IAyB/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;YACW,gBAAgB;CAuE/B;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,IAAI,CAAC,OAAO,SAAS,cAAc,GAAG,cAAc;IAC/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,WAAW,GAAG,gBAAgB,CAAC,OAAO,CAAC;IAS5D;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,IAAI,CACR,OAAO,EAAE,OAAO,SAAS,cAAc,GACnC,qBAAqB,CAAC,OAAO,CAAC,GAAG,gBAAgB,GACjD,gBAAgB,GACnB,OAAO,CAAC,iBAAiB,CAAC;IA8C7B;;OAEG;YACW,iBAAiB;IAyB/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;YACW,gBAAgB;CAuE/B;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { MailerApiError } from './errors.js';
1
+ import { EwynApiError } from './errors.js';
2
2
  /**
3
- * Mailer SDK Client
3
+ * Ewyn SDK Client
4
4
  *
5
5
  * @example Basic usage without template config
6
6
  * ```ts
7
- * const client = new Mailer({
7
+ * const client = new Ewyn({
8
8
  * workspaceId: 'your-workspace-id',
9
9
  * apiKey: 'your-api-key',
10
10
  * });
@@ -30,7 +30,7 @@ import { MailerApiError } from './errors.js';
30
30
  * }
31
31
  * } as const;
32
32
  *
33
- * const client = new Mailer({
33
+ * const client = new Ewyn({
34
34
  * workspaceId: 'your-workspace-id',
35
35
  * apiKey: 'your-api-key',
36
36
  * templates: config
@@ -46,7 +46,7 @@ import { MailerApiError } from './errors.js';
46
46
  * });
47
47
  * ```
48
48
  */
49
- export class Mailer {
49
+ export class Ewyn {
50
50
  workspaceId;
51
51
  apiKey;
52
52
  baseUrl;
@@ -66,7 +66,7 @@ export class Mailer {
66
66
  *
67
67
  * @param options - Email sending options
68
68
  * @returns Promise resolving to the send response
69
- * @throws {MailerApiError} If the API request fails
69
+ * @throws {EwynApiError} If the API request fails
70
70
  *
71
71
  * @example With template ID
72
72
  * ```ts
@@ -177,7 +177,7 @@ export class Mailer {
177
177
  clearTimeout(timeoutId);
178
178
  const data = await response.json().catch(() => ({}));
179
179
  if (!response.ok) {
180
- const error = new MailerApiError(response.status, data.code, data.details || data, data.error || data.message);
180
+ const error = new EwynApiError(response.status, data.code, data.details || data, data.error || data.message);
181
181
  // Retry on retryable errors
182
182
  if (error.isRetryable() && attempt < this.maxRetries) {
183
183
  // Exponential backoff: 1s, 2s, 4s
@@ -191,12 +191,12 @@ export class Mailer {
191
191
  }
192
192
  catch (error) {
193
193
  clearTimeout(timeoutId);
194
- if (error instanceof MailerApiError) {
194
+ if (error instanceof EwynApiError) {
195
195
  throw error;
196
196
  }
197
197
  // Handle network errors or timeouts
198
198
  if (error instanceof Error && error.name === 'AbortError') {
199
- throw new MailerApiError(408, 'TIMEOUT', undefined, `Request timed out after ${this.timeout}ms`);
199
+ throw new EwynApiError(408, 'TIMEOUT', undefined, `Request timed out after ${this.timeout}ms`);
200
200
  }
201
201
  // Retry on network errors if we have attempts left
202
202
  if (attempt < this.maxRetries) {
@@ -204,8 +204,8 @@ export class Mailer {
204
204
  await new Promise((resolve) => setTimeout(resolve, delay));
205
205
  return this.requestWithRetry(path, init, attempt + 1);
206
206
  }
207
- throw new MailerApiError(500, 'NETWORK_ERROR', undefined, error instanceof Error ? error.message : 'Unknown network error');
207
+ throw new EwynApiError(500, 'NETWORK_ERROR', undefined, error instanceof Error ? error.message : 'Unknown network error');
208
208
  }
209
209
  }
210
210
  }
211
- export { MailerApiError } from './errors.js';
211
+ export { EwynApiError } from './errors.js';
package/dist/types.d.ts CHANGED
@@ -97,9 +97,9 @@ export interface SendEmailResponse {
97
97
  queuedAt: string;
98
98
  }
99
99
  /**
100
- * Configuration options for the Mailer client (base)
100
+ * Configuration options for the Ewyn client (base)
101
101
  */
102
- export interface MailerOptionsBase {
102
+ export interface EwynOptionsBase {
103
103
  /** Workspace ID (UUID) */
104
104
  workspaceId: string;
105
105
  /** API key secret */
@@ -114,14 +114,14 @@ export interface MailerOptionsBase {
114
114
  /**
115
115
  * Configuration options with typed template config
116
116
  */
117
- export type MailerOptionsTyped<TConfig extends TemplateConfig> = MailerOptionsBase & {
117
+ export type EwynOptionsTyped<TConfig extends TemplateConfig> = EwynOptionsBase & {
118
118
  /** Template configuration for type-safe sending */
119
119
  templates: TConfig;
120
120
  };
121
121
  /**
122
- * Configuration options for the Mailer client (generic version)
122
+ * Configuration options for the Ewyn client (generic version)
123
123
  */
124
- export type MailerOptions = MailerOptionsBase & {
124
+ export type EwynOptions = EwynOptionsBase & {
125
125
  /** Template configuration for name-based sending and validation */
126
126
  templates?: TemplateConfig;
127
127
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ewyn/client",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Official TypeScript SDK for Ewyn email service with full type safety",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",