@mailhooks/sdk 2.2.0 → 2.4.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/dist/index.d.ts +174 -1
- package/dist/index.js +148 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,14 @@ interface Attachment {
|
|
|
5
5
|
filename: string;
|
|
6
6
|
contentType: string;
|
|
7
7
|
size: number;
|
|
8
|
+
/** Storage path for the attachment (only present for custom storage) */
|
|
9
|
+
storagePath?: string;
|
|
10
|
+
}
|
|
11
|
+
interface StorageConfigSummary {
|
|
12
|
+
/** Storage provider type */
|
|
13
|
+
provider: 'S3' | 'AZURE_BLOB' | 'GCS';
|
|
14
|
+
/** Storage bucket or container name */
|
|
15
|
+
bucket: string;
|
|
8
16
|
}
|
|
9
17
|
interface Email {
|
|
10
18
|
id: string;
|
|
@@ -14,6 +22,12 @@ interface Email {
|
|
|
14
22
|
read: boolean;
|
|
15
23
|
createdAt: Date;
|
|
16
24
|
attachments: Attachment[];
|
|
25
|
+
/** Whether this email is stored in custom (BYOB) storage */
|
|
26
|
+
usesCustomStorage?: boolean;
|
|
27
|
+
/** Storage configuration details (only present for custom storage) */
|
|
28
|
+
storageConfig?: StorageConfigSummary;
|
|
29
|
+
/** Storage path for the email EML file (only present for custom storage) */
|
|
30
|
+
storagePath?: string;
|
|
17
31
|
}
|
|
18
32
|
interface EmailContent {
|
|
19
33
|
html?: string;
|
|
@@ -138,8 +152,160 @@ declare class EmailsResource extends MailhooksClient {
|
|
|
138
152
|
waitFor(options?: WaitForOptions): Promise<Email>;
|
|
139
153
|
}
|
|
140
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Event types for real-time notifications
|
|
157
|
+
*/
|
|
158
|
+
declare enum RealtimeEventType {
|
|
159
|
+
EMAIL_RECEIVED = "email.received",
|
|
160
|
+
EMAIL_UPDATED = "email.updated",
|
|
161
|
+
HEARTBEAT = "heartbeat",
|
|
162
|
+
CONNECTED = "connected"
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Email received event payload
|
|
166
|
+
*/
|
|
167
|
+
interface EmailReceivedPayload {
|
|
168
|
+
id: string;
|
|
169
|
+
from: string;
|
|
170
|
+
to: string[];
|
|
171
|
+
subject: string;
|
|
172
|
+
domainId?: string;
|
|
173
|
+
domain?: string;
|
|
174
|
+
createdAt: string;
|
|
175
|
+
hasAttachments: boolean;
|
|
176
|
+
attachmentCount: number;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Email updated event payload
|
|
180
|
+
*/
|
|
181
|
+
interface EmailUpdatedPayload {
|
|
182
|
+
id: string;
|
|
183
|
+
changes: {
|
|
184
|
+
read?: boolean;
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Connected event payload
|
|
189
|
+
*/
|
|
190
|
+
interface ConnectedPayload {
|
|
191
|
+
tenantId: string;
|
|
192
|
+
connectedAt: string;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Heartbeat event payload
|
|
196
|
+
*/
|
|
197
|
+
interface HeartbeatPayload {
|
|
198
|
+
timestamp: string;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Base realtime event structure
|
|
202
|
+
*/
|
|
203
|
+
interface RealtimeEvent<T = unknown> {
|
|
204
|
+
type: RealtimeEventType;
|
|
205
|
+
timestamp: string;
|
|
206
|
+
data: T;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Callback handlers for realtime events
|
|
210
|
+
*/
|
|
211
|
+
interface RealtimeCallbacks {
|
|
212
|
+
onEmailReceived?: (payload: EmailReceivedPayload) => void;
|
|
213
|
+
onEmailUpdated?: (payload: EmailUpdatedPayload) => void;
|
|
214
|
+
onConnected?: (payload: ConnectedPayload) => void;
|
|
215
|
+
onHeartbeat?: (payload: HeartbeatPayload) => void;
|
|
216
|
+
onError?: (error: Error) => void;
|
|
217
|
+
onDisconnect?: () => void;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Subscription options
|
|
221
|
+
*/
|
|
222
|
+
interface SubscribeOptions extends RealtimeCallbacks {
|
|
223
|
+
/** Auto-reconnect on disconnect (default: true) */
|
|
224
|
+
autoReconnect?: boolean;
|
|
225
|
+
/** Reconnect delay in milliseconds (default: 5000) */
|
|
226
|
+
reconnectDelay?: number;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Subscription handle returned from subscribe()
|
|
230
|
+
*/
|
|
231
|
+
interface RealtimeSubscription {
|
|
232
|
+
/** Disconnect from the SSE stream */
|
|
233
|
+
disconnect: () => void;
|
|
234
|
+
/** Whether currently connected */
|
|
235
|
+
isConnected: () => boolean;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Realtime resource for subscribing to email notifications via SSE
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* const mailhooks = new Mailhooks({ apiKey: 'your-api-key' });
|
|
243
|
+
*
|
|
244
|
+
* // Subscribe to real-time notifications
|
|
245
|
+
* const subscription = mailhooks.realtime.subscribe({
|
|
246
|
+
* onEmailReceived: (email) => {
|
|
247
|
+
* console.log('New email:', email.subject);
|
|
248
|
+
* },
|
|
249
|
+
* onError: (error) => {
|
|
250
|
+
* console.error('Connection error:', error);
|
|
251
|
+
* },
|
|
252
|
+
* });
|
|
253
|
+
*
|
|
254
|
+
* // Later, disconnect
|
|
255
|
+
* subscription.disconnect();
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare class RealtimeResource {
|
|
259
|
+
private config;
|
|
260
|
+
private eventSource;
|
|
261
|
+
private reconnectTimeout;
|
|
262
|
+
constructor(config: MailhooksConfig);
|
|
263
|
+
/**
|
|
264
|
+
* Check if the plan allows real-time notifications and get connection quota
|
|
265
|
+
*
|
|
266
|
+
* @returns Promise resolving to access status and connection limits
|
|
267
|
+
*/
|
|
268
|
+
checkAccess(): Promise<{
|
|
269
|
+
hasAccess: boolean;
|
|
270
|
+
maxConnections: number;
|
|
271
|
+
currentConnections: number;
|
|
272
|
+
}>;
|
|
273
|
+
/**
|
|
274
|
+
* Subscribe to real-time email notifications via Server-Sent Events (SSE)
|
|
275
|
+
*
|
|
276
|
+
* Note: This method requires the EventSource API, which is available in browsers
|
|
277
|
+
* and can be polyfilled in Node.js using packages like 'eventsource'.
|
|
278
|
+
*
|
|
279
|
+
* @param options Subscription options and callbacks
|
|
280
|
+
* @returns Subscription handle with disconnect method
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```typescript
|
|
284
|
+
* const subscription = mailhooks.realtime.subscribe({
|
|
285
|
+
* onEmailReceived: (email) => {
|
|
286
|
+
* console.log('New email from:', email.from);
|
|
287
|
+
* console.log('Subject:', email.subject);
|
|
288
|
+
* },
|
|
289
|
+
* onConnected: () => {
|
|
290
|
+
* console.log('Connected to real-time notifications');
|
|
291
|
+
* },
|
|
292
|
+
* onError: (error) => {
|
|
293
|
+
* console.error('Error:', error);
|
|
294
|
+
* },
|
|
295
|
+
* autoReconnect: true,
|
|
296
|
+
* reconnectDelay: 5000,
|
|
297
|
+
* });
|
|
298
|
+
*
|
|
299
|
+
* // Disconnect when done
|
|
300
|
+
* subscription.disconnect();
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
subscribe(options?: SubscribeOptions): RealtimeSubscription;
|
|
304
|
+
}
|
|
305
|
+
|
|
141
306
|
declare class Mailhooks {
|
|
142
307
|
emails: EmailsResource;
|
|
308
|
+
realtime: RealtimeResource;
|
|
143
309
|
constructor(config: MailhooksConfig);
|
|
144
310
|
/**
|
|
145
311
|
* Create a new Mailhooks SDK instance
|
|
@@ -218,6 +384,13 @@ interface WebhookPayload {
|
|
|
218
384
|
usesCustomStorage: boolean;
|
|
219
385
|
/** Storage path for the email (only present when usesCustomStorage is true) */
|
|
220
386
|
storagePath?: string;
|
|
387
|
+
/** Storage configuration details (only present when usesCustomStorage is true) */
|
|
388
|
+
storageConfig?: {
|
|
389
|
+
/** Storage provider type (S3, AZURE_BLOB, GCS) */
|
|
390
|
+
provider: string;
|
|
391
|
+
/** Storage bucket or container name */
|
|
392
|
+
bucket: string;
|
|
393
|
+
};
|
|
221
394
|
}
|
|
222
395
|
/**
|
|
223
396
|
* Verifies a webhook signature using HMAC-SHA256.
|
|
@@ -333,4 +506,4 @@ interface ParsedEmail {
|
|
|
333
506
|
*/
|
|
334
507
|
declare function parseEml(eml: Buffer | string): Promise<ParsedEmail>;
|
|
335
508
|
|
|
336
|
-
export { type Attachment, type DownloadResponse, type Email, type EmailContent, type EmailFilter, type EmailListParams, type EmailSort, EmailsResource, type EmailsResponse, Mailhooks, type MailhooksConfig, type PaginationResponse, type ParsedEmail, type WaitForOptions, type WebhookPayload, constructSignature, Mailhooks as default, parseEml, parseWebhookPayload, verifyWebhookSignature };
|
|
509
|
+
export { type Attachment, type ConnectedPayload, type DownloadResponse, type Email, type EmailContent, type EmailFilter, type EmailListParams, type EmailReceivedPayload, type EmailSort, type EmailUpdatedPayload, EmailsResource, type EmailsResponse, type HeartbeatPayload, Mailhooks, type MailhooksConfig, type PaginationResponse, type ParsedEmail, type RealtimeCallbacks, type RealtimeEvent, RealtimeEventType, RealtimeResource, type RealtimeSubscription, type StorageConfigSummary, type SubscribeOptions, type WaitForOptions, type WebhookPayload, constructSignature, Mailhooks as default, parseEml, parseWebhookPayload, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -242,10 +242,157 @@ var EmailsResource = class extends MailhooksClient {
|
|
|
242
242
|
}
|
|
243
243
|
};
|
|
244
244
|
|
|
245
|
+
// src/realtime.ts
|
|
246
|
+
var RealtimeEventType = /* @__PURE__ */ ((RealtimeEventType2) => {
|
|
247
|
+
RealtimeEventType2["EMAIL_RECEIVED"] = "email.received";
|
|
248
|
+
RealtimeEventType2["EMAIL_UPDATED"] = "email.updated";
|
|
249
|
+
RealtimeEventType2["HEARTBEAT"] = "heartbeat";
|
|
250
|
+
RealtimeEventType2["CONNECTED"] = "connected";
|
|
251
|
+
return RealtimeEventType2;
|
|
252
|
+
})(RealtimeEventType || {});
|
|
253
|
+
var RealtimeResource = class {
|
|
254
|
+
constructor(config) {
|
|
255
|
+
this.eventSource = null;
|
|
256
|
+
this.reconnectTimeout = null;
|
|
257
|
+
this.config = config;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Check if the plan allows real-time notifications and get connection quota
|
|
261
|
+
*
|
|
262
|
+
* @returns Promise resolving to access status and connection limits
|
|
263
|
+
*/
|
|
264
|
+
async checkAccess() {
|
|
265
|
+
const baseUrl = this.config.baseUrl ?? "https://mailhooks.dev/api";
|
|
266
|
+
const response = await fetch(`${baseUrl}/v1/realtime/plan-access`, {
|
|
267
|
+
headers: {
|
|
268
|
+
"x-api-key": this.config.apiKey
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
if (!response.ok) {
|
|
272
|
+
throw new Error(`Failed to check plan access: ${response.statusText}`);
|
|
273
|
+
}
|
|
274
|
+
return response.json();
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Subscribe to real-time email notifications via Server-Sent Events (SSE)
|
|
278
|
+
*
|
|
279
|
+
* Note: This method requires the EventSource API, which is available in browsers
|
|
280
|
+
* and can be polyfilled in Node.js using packages like 'eventsource'.
|
|
281
|
+
*
|
|
282
|
+
* @param options Subscription options and callbacks
|
|
283
|
+
* @returns Subscription handle with disconnect method
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```typescript
|
|
287
|
+
* const subscription = mailhooks.realtime.subscribe({
|
|
288
|
+
* onEmailReceived: (email) => {
|
|
289
|
+
* console.log('New email from:', email.from);
|
|
290
|
+
* console.log('Subject:', email.subject);
|
|
291
|
+
* },
|
|
292
|
+
* onConnected: () => {
|
|
293
|
+
* console.log('Connected to real-time notifications');
|
|
294
|
+
* },
|
|
295
|
+
* onError: (error) => {
|
|
296
|
+
* console.error('Error:', error);
|
|
297
|
+
* },
|
|
298
|
+
* autoReconnect: true,
|
|
299
|
+
* reconnectDelay: 5000,
|
|
300
|
+
* });
|
|
301
|
+
*
|
|
302
|
+
* // Disconnect when done
|
|
303
|
+
* subscription.disconnect();
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
subscribe(options = {}) {
|
|
307
|
+
const {
|
|
308
|
+
onEmailReceived,
|
|
309
|
+
onEmailUpdated,
|
|
310
|
+
onConnected,
|
|
311
|
+
onHeartbeat,
|
|
312
|
+
onError,
|
|
313
|
+
onDisconnect,
|
|
314
|
+
autoReconnect = true,
|
|
315
|
+
reconnectDelay = 5e3
|
|
316
|
+
} = options;
|
|
317
|
+
if (this.reconnectTimeout) {
|
|
318
|
+
clearTimeout(this.reconnectTimeout);
|
|
319
|
+
this.reconnectTimeout = null;
|
|
320
|
+
}
|
|
321
|
+
if (this.eventSource) {
|
|
322
|
+
this.eventSource.close();
|
|
323
|
+
this.eventSource = null;
|
|
324
|
+
}
|
|
325
|
+
if (typeof EventSource === "undefined") {
|
|
326
|
+
throw new Error(
|
|
327
|
+
'EventSource is not available. In Node.js, install and import the "eventsource" package.'
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
const baseUrl = this.config.baseUrl ?? "https://mailhooks.dev/api";
|
|
331
|
+
const url = `${baseUrl}/v1/realtime/events?token=${encodeURIComponent(this.config.apiKey)}`;
|
|
332
|
+
const connect = () => {
|
|
333
|
+
this.eventSource = new EventSource(url);
|
|
334
|
+
this.eventSource.onmessage = (event) => {
|
|
335
|
+
try {
|
|
336
|
+
const data = JSON.parse(event.data);
|
|
337
|
+
switch (data.type) {
|
|
338
|
+
case "connected" /* CONNECTED */:
|
|
339
|
+
onConnected?.(data.data);
|
|
340
|
+
break;
|
|
341
|
+
case "email.received" /* EMAIL_RECEIVED */:
|
|
342
|
+
onEmailReceived?.(data.data);
|
|
343
|
+
break;
|
|
344
|
+
case "email.updated" /* EMAIL_UPDATED */:
|
|
345
|
+
onEmailUpdated?.(data.data);
|
|
346
|
+
break;
|
|
347
|
+
case "heartbeat" /* HEARTBEAT */:
|
|
348
|
+
onHeartbeat?.(data.data);
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
} catch (error) {
|
|
352
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
353
|
+
onError?.(new Error(`Failed to parse event: ${message}`));
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
this.eventSource.onerror = (event) => {
|
|
357
|
+
onError?.(new Error("SSE connection error"));
|
|
358
|
+
this.eventSource?.close();
|
|
359
|
+
this.eventSource = null;
|
|
360
|
+
onDisconnect?.();
|
|
361
|
+
if (autoReconnect) {
|
|
362
|
+
if (this.reconnectTimeout) {
|
|
363
|
+
clearTimeout(this.reconnectTimeout);
|
|
364
|
+
}
|
|
365
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
366
|
+
connect();
|
|
367
|
+
}, reconnectDelay);
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
connect();
|
|
372
|
+
return {
|
|
373
|
+
disconnect: () => {
|
|
374
|
+
if (this.reconnectTimeout) {
|
|
375
|
+
clearTimeout(this.reconnectTimeout);
|
|
376
|
+
this.reconnectTimeout = null;
|
|
377
|
+
}
|
|
378
|
+
if (this.eventSource) {
|
|
379
|
+
this.eventSource.close();
|
|
380
|
+
this.eventSource = null;
|
|
381
|
+
onDisconnect?.();
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
isConnected: () => {
|
|
385
|
+
return this.eventSource?.readyState === EventSource.OPEN;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
|
|
245
391
|
// src/mailhooks.ts
|
|
246
392
|
var Mailhooks = class _Mailhooks {
|
|
247
393
|
constructor(config) {
|
|
248
394
|
this.emails = new EmailsResource(config);
|
|
395
|
+
this.realtime = new RealtimeResource(config);
|
|
249
396
|
}
|
|
250
397
|
/**
|
|
251
398
|
* Create a new Mailhooks SDK instance
|
|
@@ -312,4 +459,4 @@ async function parseEml(eml) {
|
|
|
312
459
|
// src/index.ts
|
|
313
460
|
var index_default = Mailhooks;
|
|
314
461
|
|
|
315
|
-
export { EmailsResource, Mailhooks, constructSignature, index_default as default, parseEml, parseWebhookPayload, verifyWebhookSignature };
|
|
462
|
+
export { EmailsResource, Mailhooks, RealtimeEventType, RealtimeResource, constructSignature, index_default as default, parseEml, parseWebhookPayload, verifyWebhookSignature };
|