mailpit-api 1.5.3 → 1.6.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
@@ -61,6 +61,7 @@ export const test = base.extend<MyFixtures>({
61
61
  const mailpit = new MailpitClient("http://localhost:8025");
62
62
  await mailpit.deleteMessages();
63
63
  await use(mailpit);
64
+ mailpit.disconnect();
64
65
  },
65
66
  });
66
67
 
@@ -75,7 +76,10 @@ test("should receive welcome email after registration", async ({
75
76
  page,
76
77
  mailpit,
77
78
  }) => {
78
- // Register
79
+ // Start waiting for the new email event before triggering the action
80
+ const emailPromise = mailpit.waitForEvent("new");
81
+
82
+ // Register a new user
79
83
  await page.goto("/register");
80
84
  await page.getByTestId("email").fill("test@example.test");
81
85
  await page.getByTestId("password").fill("password123");
@@ -84,12 +88,12 @@ test("should receive welcome email after registration", async ({
84
88
  // Wait for success message on page
85
89
  await expect(page.getByTestId("success-message")).toBeVisible();
86
90
 
87
- // Get the welcome email
88
- const message = await mailpit.getMessageSummary();
91
+ // Wait for the new email event (up to 5 seconds by default)
92
+ const event = await emailPromise;
89
93
 
90
- expect(message.To[0].Address).toBe("test@example.test");
91
- expect(message.From.Address).toBe("no-reply@your-app.test");
92
- expect(message.Subject).toBe("Welcome to Our App");
93
- expect(message.Text).toContain("Thank you for registering with our app!");
94
+ // Verify the email from the event data
95
+ expect(event.Data.To[0].Address).toBe("test@example.test");
96
+ expect(event.Data.From.Address).toBe("no-reply@your-app.test");
97
+ expect(event.Data.Subject).toBe("Welcome to Our App");
94
98
  });
95
99
  ```
package/dist/index.d.mts CHANGED
@@ -177,38 +177,7 @@ interface MailpitMessageSummaryResponse {
177
177
  /** Response for the {@link MailpitClient.listMessages| listMessages()} API containing the summary of multiple messages. */
178
178
  interface MailpitMessagesSummaryResponse {
179
179
  /** Messages */
180
- messages: {
181
- /** The number of attachments */
182
- Attachments: number;
183
- /** BCC addresses */
184
- Bcc: MailpitEmailAddressResponse[];
185
- /** CC addresses */
186
- Cc: MailpitEmailAddressResponse[];
187
- /** Created time in ISO format: 1970-01-01T00:00:00.000Z */
188
- Created: string;
189
- /** Sender address */
190
- From: MailpitEmailAddressResponse;
191
- /** Database ID */
192
- ID: string;
193
- /** Message ID */
194
- MessageID: string;
195
- /** Read status */
196
- Read: boolean;
197
- /** Reply-To addresses */
198
- ReplyTo: MailpitEmailAddressResponse[];
199
- /** Message size in bytes (total) */
200
- Size: number;
201
- /** Message snippet includes up to 250 characters */
202
- Snippet: string;
203
- /** Email subject */
204
- Subject: string;
205
- /** Message tags */
206
- Tags: string[];
207
- /** To addresses */
208
- To: MailpitEmailAddressResponse[];
209
- /** Username used for authentication (if provided) with the SMTP or {@link MailpitClient.sendMessage| sendMessage} */
210
- Username?: string;
211
- }[];
180
+ messages: MailpitMessageListItem[];
212
181
  /** Total number of messages matching the current query */
213
182
  messages_count: number;
214
183
  /** Total number of unread messages matching current query */
@@ -224,6 +193,39 @@ interface MailpitMessagesSummaryResponse {
224
193
  /** @deprecated No longer documented upstream */
225
194
  count: number;
226
195
  }
196
+ /** Represents a message item in a list or WebSocket event */
197
+ interface MailpitMessageListItem {
198
+ /** The number of attachments */
199
+ Attachments: number;
200
+ /** BCC addresses */
201
+ Bcc: MailpitEmailAddressResponse[];
202
+ /** CC addresses */
203
+ Cc: MailpitEmailAddressResponse[];
204
+ /** Created time in ISO format: 1970-01-01T00:00:00.000Z */
205
+ Created: string;
206
+ /** Sender address */
207
+ From: MailpitEmailAddressResponse;
208
+ /** Database ID */
209
+ ID: string;
210
+ /** Message ID */
211
+ MessageID: string;
212
+ /** Read status */
213
+ Read: boolean;
214
+ /** Reply-To addresses */
215
+ ReplyTo: MailpitEmailAddressResponse[];
216
+ /** Message size in bytes (total) */
217
+ Size: number;
218
+ /** Message snippet includes up to 250 characters */
219
+ Snippet: string;
220
+ /** Email subject */
221
+ Subject: string;
222
+ /** Message tags */
223
+ Tags: string[];
224
+ /** To addresses */
225
+ To: MailpitEmailAddressResponse[];
226
+ /** Username used for authentication (if provided) with the SMTP or {@link MailpitClient.sendMessage| sendMessage} */
227
+ Username?: string;
228
+ }
227
229
  /** Response for the {@link MailpitClient.getMessageHeaders | getMessageHeaders()} API containing message headers */
228
230
  interface MailpitMessageHeadersResponse {
229
231
  /** Message headers */
@@ -411,6 +413,91 @@ interface MailpitAttachmentDataResponse {
411
413
  /** The attachment MIME type */
412
414
  contentType: string;
413
415
  }
416
+ /** Message summary data structure returned in "new" events */
417
+ type MailpitMessageSummary = MailpitMessageListItem;
418
+ /** Statistics data structure returned in "stats" events */
419
+ interface MailpitStatsData {
420
+ /** Total number of messages in the database */
421
+ Total: number;
422
+ /** Total number of unread messages */
423
+ Unread: number;
424
+ /** Mailpit version */
425
+ Version: string;
426
+ }
427
+ /** Update data structure returned in "update" events */
428
+ interface MailpitUpdateData {
429
+ /** Message database ID */
430
+ ID: string;
431
+ /** Read status (if changed) */
432
+ Read?: boolean;
433
+ /** Tags (if changed) */
434
+ Tags?: string[];
435
+ }
436
+ /** Delete data structure returned in "delete" events */
437
+ interface MailpitDeleteData {
438
+ /** Message database ID */
439
+ ID: string;
440
+ }
441
+ /** Error data structure returned in "error" events */
442
+ interface MailpitErrorData {
443
+ /** Error severity level */
444
+ Level: string;
445
+ /** Error type */
446
+ Type: string;
447
+ /** Client IP address */
448
+ IP: string;
449
+ /** Error message */
450
+ Message: string;
451
+ }
452
+ /** Event message containing a type and data payload */
453
+ interface MailpitEvent<T = MailpitMessageSummary | MailpitStatsData | MailpitUpdateData | MailpitDeleteData | MailpitErrorData | null> {
454
+ /** Type of event being broadcast */
455
+ Type: string;
456
+ /** Event data payload */
457
+ Data: T;
458
+ }
459
+ /** Event for new messages */
460
+ interface MailpitNewMessageEvent extends MailpitEvent<MailpitMessageSummary> {
461
+ Type: "new";
462
+ }
463
+ /** Event for statistics updates */
464
+ interface MailpitStatsEvent extends MailpitEvent<MailpitStatsData> {
465
+ Type: "stats";
466
+ }
467
+ /** Event for message updates */
468
+ interface MailpitUpdateEvent extends MailpitEvent<MailpitUpdateData> {
469
+ Type: "update";
470
+ }
471
+ /** Event for message deletion */
472
+ interface MailpitDeleteEvent extends MailpitEvent<MailpitDeleteData> {
473
+ Type: "delete";
474
+ }
475
+ /** Event for database pruning (Data is null) */
476
+ interface MailpitPruneEvent extends MailpitEvent<null> {
477
+ Type: "prune";
478
+ }
479
+ /** Event for truncating all messages (Data is null) */
480
+ interface MailpitTruncateEvent extends MailpitEvent<null> {
481
+ Type: "truncate";
482
+ }
483
+ /** Event for client errors (SMTP/POP3 errors) */
484
+ interface MailpitErrorEvent extends MailpitEvent<MailpitErrorData> {
485
+ Type: "error";
486
+ }
487
+ /** Maps event type strings to their corresponding event interfaces */
488
+ interface MailpitEventMap {
489
+ new: MailpitNewMessageEvent;
490
+ stats: MailpitStatsEvent;
491
+ update: MailpitUpdateEvent;
492
+ delete: MailpitDeleteEvent;
493
+ prune: MailpitPruneEvent;
494
+ truncate: MailpitTruncateEvent;
495
+ error: MailpitErrorEvent;
496
+ /** Wildcard event type that matches all events */
497
+ "*": MailpitEvent;
498
+ }
499
+ /** Valid event types including specific event names and the wildcard "*" */
500
+ type MailpitEventType = keyof MailpitEventMap;
414
501
  /**
415
502
  * Client for interacting with the {@link https://mailpit.axllent.org/docs/api-v1/ | Mailpit API}.
416
503
  * @example
@@ -422,6 +509,10 @@ interface MailpitAttachmentDataResponse {
422
509
  */
423
510
  declare class MailpitClient {
424
511
  private readonly axiosInstance;
512
+ private readonly baseURL;
513
+ private readonly wsURL;
514
+ private webSocket;
515
+ private eventListeners;
425
516
  /**
426
517
  * Creates an instance of {@link MailpitClient}.
427
518
  * @param baseURL - The base URL of the Mailpit API.
@@ -435,8 +526,8 @@ declare class MailpitClient {
435
526
  * @example Basic Auth
436
527
  * ```typescript
437
528
  * const mailpit = new MailpitClient("http://localhost:8025", {
438
- * username: "admin",
439
- * password: "supersecret",
529
+ * username: "admin",
530
+ * password: "supersecret"
440
531
  * });
441
532
  * ```
442
533
  */
@@ -781,6 +872,110 @@ declare class MailpitClient {
781
872
  * ```
782
873
  */
783
874
  renderMessageText(id?: string): Promise<string>;
875
+ /**
876
+ * @internal
877
+ * Connects to the WebSocket endpoint for receiving real-time events.
878
+ */
879
+ private connectWebSocket;
880
+ /**
881
+ * @internal
882
+ * Adds a listener to the event listeners map.
883
+ * @param eventType - The type of event to listen for
884
+ * @param listener - The listener function to add
885
+ */
886
+ private addListener;
887
+ /**
888
+ * @internal
889
+ * Removes a listener from the event listeners map.
890
+ * @param eventType - The type of event to remove the listener from
891
+ * @param listener - The listener function to remove
892
+ */
893
+ private removeListener;
894
+ /**
895
+ * @internal
896
+ * Dispatches a message to listeners of a specific event type.
897
+ * @param eventType - The event type to dispatch to
898
+ * @param message - The event message
899
+ */
900
+ private dispatchToListeners;
901
+ /**
902
+ * @internal
903
+ * Handles incoming WebSocket messages and dispatches them to registered listeners.
904
+ * @param message - The event message
905
+ */
906
+ private handleWebSocketMessage;
907
+ /**
908
+ * Disconnects from the real-time event stream.
909
+ * @example
910
+ * ```typescript
911
+ * mailpit.disconnect();
912
+ * ```
913
+ */
914
+ disconnect(): void;
915
+ /**
916
+ * Registers a listener for real-time events of a specific type.
917
+ * @remarks
918
+ * Automatically connects to the event stream if not already connected.
919
+ * @param eventType - The type of event to listen for.
920
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
921
+ * Use "*" to listen for all event types (Useful if processing all events uniformly (e.g., logging, debugging, metrics)).
922
+ * @param listener - The callback function to invoke when an event is received
923
+ * @returns A function to unregister the listener
924
+ * @example Listen for event type "new" messages (recommended)
925
+ * ```typescript
926
+ * const unsubscribe = mailpit.onEvent("new", (event) => {
927
+ * // event.Data is typed as MailpitMessageSummary with full type safety
928
+ * console.log("New message:", event.Data.Subject);
929
+ * });
930
+ *
931
+ * // Other code...
932
+ *
933
+ * // Unsubscribe listener when no longer needed
934
+ * unsubscribe();
935
+ * ```
936
+ * @example Listen for all events uniformly (for logging/debugging)
937
+ * ```typescript
938
+ * const unsubscribe = mailpit.onEvent("*", (event) => {
939
+ * // Generic processing for all event types
940
+ * console.log(`Event ${event.Type} received`);
941
+ * });
942
+ *
943
+ * // Other code...
944
+ *
945
+ * // Unsubscribe listener when no longer needed
946
+ * unsubscribe();
947
+ * ```
948
+ */
949
+ onEvent<T extends keyof MailpitEventMap>(eventType: T, listener: (event: MailpitEventMap[T]) => void): () => void;
950
+ /**
951
+ * Waits for the next event of a specific type.
952
+ * @remarks
953
+ * Automatically connects to the event stream if not already connected.
954
+ * Primarily intended for testing scenarios where you need to wait for a single specific event.
955
+ * The promise will reject if the timeout is reached before an event is received.
956
+ * @param eventType - The type of event to wait for.
957
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
958
+ * @param timeout - Timeout in milliseconds (default: 5000ms). Pass `Infinity` to disable timeout.
959
+ * @returns A promise that resolves with the event when received, or rejects on timeout
960
+ * @example Basic usage
961
+ * ```typescript
962
+ * // Create the promise before triggering the event
963
+ * const eventPromise = mailpit.waitForEvent("new");
964
+ *
965
+ * // Do something that triggers an email to send
966
+ * await mailpit.sendMessage({
967
+ * From: { Email: "test@example.com" },
968
+ * To: [{ Email: "recipient@example.com" }],
969
+ * Subject: "Test",
970
+ * });
971
+ *
972
+ * // Wait for the event confirming the message was received
973
+ * const event = await eventPromise;
974
+ * // event.Data is fully typed as MailpitMessageSummary
975
+ * console.log("Message received:", event.Data.Subject);
976
+ * ```
977
+ */
978
+ waitForEvent<T extends Exclude<keyof MailpitEventMap, "*">>(eventType: T, timeout?: number): Promise<MailpitEventMap[T]>;
784
979
  }
785
980
 
786
- export { type MailpitAttachmentDataResponse, type MailpitAttachmentRequest, type MailpitAttachmentResponse, type MailpitChaosTrigger, type MailpitChaosTriggersRequest, type MailpitChaosTriggersResponse, MailpitClient, type MailpitConfigurationResponse, type MailpitDatabaseIDsRequest, type MailpitEmailAddressRequest, type MailpitEmailAddressResponse, type MailpitHTMLCheckResponse, type MailpitInfoResponse, type MailpitLinkCheckResponse, type MailpitMessageHeadersResponse, type MailpitMessageSummaryResponse, type MailpitMessagesSummaryResponse, type MailpitReadStatusRequest, type MailpitSearchMessagesRequest, type MailpitSearchRequest, type MailpitSendMessageConfirmationResponse, type MailpitSendRequest, type MailpitSetTagsRequest, type MailpitSpamAssassinResponse, type MailpitTimeZoneRequest };
981
+ export { type MailpitAttachmentDataResponse, type MailpitAttachmentRequest, type MailpitAttachmentResponse, type MailpitChaosTrigger, type MailpitChaosTriggersRequest, type MailpitChaosTriggersResponse, MailpitClient, type MailpitConfigurationResponse, type MailpitDatabaseIDsRequest, type MailpitDeleteData, type MailpitDeleteEvent, type MailpitEmailAddressRequest, type MailpitEmailAddressResponse, type MailpitErrorData, type MailpitErrorEvent, type MailpitEvent, type MailpitEventMap, type MailpitEventType, type MailpitHTMLCheckResponse, type MailpitInfoResponse, type MailpitLinkCheckResponse, type MailpitMessageHeadersResponse, type MailpitMessageListItem, type MailpitMessageSummary, type MailpitMessageSummaryResponse, type MailpitMessagesSummaryResponse, type MailpitNewMessageEvent, type MailpitPruneEvent, type MailpitReadStatusRequest, type MailpitSearchMessagesRequest, type MailpitSearchRequest, type MailpitSendMessageConfirmationResponse, type MailpitSendRequest, type MailpitSetTagsRequest, type MailpitSpamAssassinResponse, type MailpitStatsData, type MailpitStatsEvent, type MailpitTimeZoneRequest, type MailpitTruncateEvent, type MailpitUpdateData, type MailpitUpdateEvent };
package/dist/index.d.ts CHANGED
@@ -177,38 +177,7 @@ interface MailpitMessageSummaryResponse {
177
177
  /** Response for the {@link MailpitClient.listMessages| listMessages()} API containing the summary of multiple messages. */
178
178
  interface MailpitMessagesSummaryResponse {
179
179
  /** Messages */
180
- messages: {
181
- /** The number of attachments */
182
- Attachments: number;
183
- /** BCC addresses */
184
- Bcc: MailpitEmailAddressResponse[];
185
- /** CC addresses */
186
- Cc: MailpitEmailAddressResponse[];
187
- /** Created time in ISO format: 1970-01-01T00:00:00.000Z */
188
- Created: string;
189
- /** Sender address */
190
- From: MailpitEmailAddressResponse;
191
- /** Database ID */
192
- ID: string;
193
- /** Message ID */
194
- MessageID: string;
195
- /** Read status */
196
- Read: boolean;
197
- /** Reply-To addresses */
198
- ReplyTo: MailpitEmailAddressResponse[];
199
- /** Message size in bytes (total) */
200
- Size: number;
201
- /** Message snippet includes up to 250 characters */
202
- Snippet: string;
203
- /** Email subject */
204
- Subject: string;
205
- /** Message tags */
206
- Tags: string[];
207
- /** To addresses */
208
- To: MailpitEmailAddressResponse[];
209
- /** Username used for authentication (if provided) with the SMTP or {@link MailpitClient.sendMessage| sendMessage} */
210
- Username?: string;
211
- }[];
180
+ messages: MailpitMessageListItem[];
212
181
  /** Total number of messages matching the current query */
213
182
  messages_count: number;
214
183
  /** Total number of unread messages matching current query */
@@ -224,6 +193,39 @@ interface MailpitMessagesSummaryResponse {
224
193
  /** @deprecated No longer documented upstream */
225
194
  count: number;
226
195
  }
196
+ /** Represents a message item in a list or WebSocket event */
197
+ interface MailpitMessageListItem {
198
+ /** The number of attachments */
199
+ Attachments: number;
200
+ /** BCC addresses */
201
+ Bcc: MailpitEmailAddressResponse[];
202
+ /** CC addresses */
203
+ Cc: MailpitEmailAddressResponse[];
204
+ /** Created time in ISO format: 1970-01-01T00:00:00.000Z */
205
+ Created: string;
206
+ /** Sender address */
207
+ From: MailpitEmailAddressResponse;
208
+ /** Database ID */
209
+ ID: string;
210
+ /** Message ID */
211
+ MessageID: string;
212
+ /** Read status */
213
+ Read: boolean;
214
+ /** Reply-To addresses */
215
+ ReplyTo: MailpitEmailAddressResponse[];
216
+ /** Message size in bytes (total) */
217
+ Size: number;
218
+ /** Message snippet includes up to 250 characters */
219
+ Snippet: string;
220
+ /** Email subject */
221
+ Subject: string;
222
+ /** Message tags */
223
+ Tags: string[];
224
+ /** To addresses */
225
+ To: MailpitEmailAddressResponse[];
226
+ /** Username used for authentication (if provided) with the SMTP or {@link MailpitClient.sendMessage| sendMessage} */
227
+ Username?: string;
228
+ }
227
229
  /** Response for the {@link MailpitClient.getMessageHeaders | getMessageHeaders()} API containing message headers */
228
230
  interface MailpitMessageHeadersResponse {
229
231
  /** Message headers */
@@ -411,6 +413,91 @@ interface MailpitAttachmentDataResponse {
411
413
  /** The attachment MIME type */
412
414
  contentType: string;
413
415
  }
416
+ /** Message summary data structure returned in "new" events */
417
+ type MailpitMessageSummary = MailpitMessageListItem;
418
+ /** Statistics data structure returned in "stats" events */
419
+ interface MailpitStatsData {
420
+ /** Total number of messages in the database */
421
+ Total: number;
422
+ /** Total number of unread messages */
423
+ Unread: number;
424
+ /** Mailpit version */
425
+ Version: string;
426
+ }
427
+ /** Update data structure returned in "update" events */
428
+ interface MailpitUpdateData {
429
+ /** Message database ID */
430
+ ID: string;
431
+ /** Read status (if changed) */
432
+ Read?: boolean;
433
+ /** Tags (if changed) */
434
+ Tags?: string[];
435
+ }
436
+ /** Delete data structure returned in "delete" events */
437
+ interface MailpitDeleteData {
438
+ /** Message database ID */
439
+ ID: string;
440
+ }
441
+ /** Error data structure returned in "error" events */
442
+ interface MailpitErrorData {
443
+ /** Error severity level */
444
+ Level: string;
445
+ /** Error type */
446
+ Type: string;
447
+ /** Client IP address */
448
+ IP: string;
449
+ /** Error message */
450
+ Message: string;
451
+ }
452
+ /** Event message containing a type and data payload */
453
+ interface MailpitEvent<T = MailpitMessageSummary | MailpitStatsData | MailpitUpdateData | MailpitDeleteData | MailpitErrorData | null> {
454
+ /** Type of event being broadcast */
455
+ Type: string;
456
+ /** Event data payload */
457
+ Data: T;
458
+ }
459
+ /** Event for new messages */
460
+ interface MailpitNewMessageEvent extends MailpitEvent<MailpitMessageSummary> {
461
+ Type: "new";
462
+ }
463
+ /** Event for statistics updates */
464
+ interface MailpitStatsEvent extends MailpitEvent<MailpitStatsData> {
465
+ Type: "stats";
466
+ }
467
+ /** Event for message updates */
468
+ interface MailpitUpdateEvent extends MailpitEvent<MailpitUpdateData> {
469
+ Type: "update";
470
+ }
471
+ /** Event for message deletion */
472
+ interface MailpitDeleteEvent extends MailpitEvent<MailpitDeleteData> {
473
+ Type: "delete";
474
+ }
475
+ /** Event for database pruning (Data is null) */
476
+ interface MailpitPruneEvent extends MailpitEvent<null> {
477
+ Type: "prune";
478
+ }
479
+ /** Event for truncating all messages (Data is null) */
480
+ interface MailpitTruncateEvent extends MailpitEvent<null> {
481
+ Type: "truncate";
482
+ }
483
+ /** Event for client errors (SMTP/POP3 errors) */
484
+ interface MailpitErrorEvent extends MailpitEvent<MailpitErrorData> {
485
+ Type: "error";
486
+ }
487
+ /** Maps event type strings to their corresponding event interfaces */
488
+ interface MailpitEventMap {
489
+ new: MailpitNewMessageEvent;
490
+ stats: MailpitStatsEvent;
491
+ update: MailpitUpdateEvent;
492
+ delete: MailpitDeleteEvent;
493
+ prune: MailpitPruneEvent;
494
+ truncate: MailpitTruncateEvent;
495
+ error: MailpitErrorEvent;
496
+ /** Wildcard event type that matches all events */
497
+ "*": MailpitEvent;
498
+ }
499
+ /** Valid event types including specific event names and the wildcard "*" */
500
+ type MailpitEventType = keyof MailpitEventMap;
414
501
  /**
415
502
  * Client for interacting with the {@link https://mailpit.axllent.org/docs/api-v1/ | Mailpit API}.
416
503
  * @example
@@ -422,6 +509,10 @@ interface MailpitAttachmentDataResponse {
422
509
  */
423
510
  declare class MailpitClient {
424
511
  private readonly axiosInstance;
512
+ private readonly baseURL;
513
+ private readonly wsURL;
514
+ private webSocket;
515
+ private eventListeners;
425
516
  /**
426
517
  * Creates an instance of {@link MailpitClient}.
427
518
  * @param baseURL - The base URL of the Mailpit API.
@@ -435,8 +526,8 @@ declare class MailpitClient {
435
526
  * @example Basic Auth
436
527
  * ```typescript
437
528
  * const mailpit = new MailpitClient("http://localhost:8025", {
438
- * username: "admin",
439
- * password: "supersecret",
529
+ * username: "admin",
530
+ * password: "supersecret"
440
531
  * });
441
532
  * ```
442
533
  */
@@ -781,6 +872,110 @@ declare class MailpitClient {
781
872
  * ```
782
873
  */
783
874
  renderMessageText(id?: string): Promise<string>;
875
+ /**
876
+ * @internal
877
+ * Connects to the WebSocket endpoint for receiving real-time events.
878
+ */
879
+ private connectWebSocket;
880
+ /**
881
+ * @internal
882
+ * Adds a listener to the event listeners map.
883
+ * @param eventType - The type of event to listen for
884
+ * @param listener - The listener function to add
885
+ */
886
+ private addListener;
887
+ /**
888
+ * @internal
889
+ * Removes a listener from the event listeners map.
890
+ * @param eventType - The type of event to remove the listener from
891
+ * @param listener - The listener function to remove
892
+ */
893
+ private removeListener;
894
+ /**
895
+ * @internal
896
+ * Dispatches a message to listeners of a specific event type.
897
+ * @param eventType - The event type to dispatch to
898
+ * @param message - The event message
899
+ */
900
+ private dispatchToListeners;
901
+ /**
902
+ * @internal
903
+ * Handles incoming WebSocket messages and dispatches them to registered listeners.
904
+ * @param message - The event message
905
+ */
906
+ private handleWebSocketMessage;
907
+ /**
908
+ * Disconnects from the real-time event stream.
909
+ * @example
910
+ * ```typescript
911
+ * mailpit.disconnect();
912
+ * ```
913
+ */
914
+ disconnect(): void;
915
+ /**
916
+ * Registers a listener for real-time events of a specific type.
917
+ * @remarks
918
+ * Automatically connects to the event stream if not already connected.
919
+ * @param eventType - The type of event to listen for.
920
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
921
+ * Use "*" to listen for all event types (Useful if processing all events uniformly (e.g., logging, debugging, metrics)).
922
+ * @param listener - The callback function to invoke when an event is received
923
+ * @returns A function to unregister the listener
924
+ * @example Listen for event type "new" messages (recommended)
925
+ * ```typescript
926
+ * const unsubscribe = mailpit.onEvent("new", (event) => {
927
+ * // event.Data is typed as MailpitMessageSummary with full type safety
928
+ * console.log("New message:", event.Data.Subject);
929
+ * });
930
+ *
931
+ * // Other code...
932
+ *
933
+ * // Unsubscribe listener when no longer needed
934
+ * unsubscribe();
935
+ * ```
936
+ * @example Listen for all events uniformly (for logging/debugging)
937
+ * ```typescript
938
+ * const unsubscribe = mailpit.onEvent("*", (event) => {
939
+ * // Generic processing for all event types
940
+ * console.log(`Event ${event.Type} received`);
941
+ * });
942
+ *
943
+ * // Other code...
944
+ *
945
+ * // Unsubscribe listener when no longer needed
946
+ * unsubscribe();
947
+ * ```
948
+ */
949
+ onEvent<T extends keyof MailpitEventMap>(eventType: T, listener: (event: MailpitEventMap[T]) => void): () => void;
950
+ /**
951
+ * Waits for the next event of a specific type.
952
+ * @remarks
953
+ * Automatically connects to the event stream if not already connected.
954
+ * Primarily intended for testing scenarios where you need to wait for a single specific event.
955
+ * The promise will reject if the timeout is reached before an event is received.
956
+ * @param eventType - The type of event to wait for.
957
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
958
+ * @param timeout - Timeout in milliseconds (default: 5000ms). Pass `Infinity` to disable timeout.
959
+ * @returns A promise that resolves with the event when received, or rejects on timeout
960
+ * @example Basic usage
961
+ * ```typescript
962
+ * // Create the promise before triggering the event
963
+ * const eventPromise = mailpit.waitForEvent("new");
964
+ *
965
+ * // Do something that triggers an email to send
966
+ * await mailpit.sendMessage({
967
+ * From: { Email: "test@example.com" },
968
+ * To: [{ Email: "recipient@example.com" }],
969
+ * Subject: "Test",
970
+ * });
971
+ *
972
+ * // Wait for the event confirming the message was received
973
+ * const event = await eventPromise;
974
+ * // event.Data is fully typed as MailpitMessageSummary
975
+ * console.log("Message received:", event.Data.Subject);
976
+ * ```
977
+ */
978
+ waitForEvent<T extends Exclude<keyof MailpitEventMap, "*">>(eventType: T, timeout?: number): Promise<MailpitEventMap[T]>;
784
979
  }
785
980
 
786
- export { type MailpitAttachmentDataResponse, type MailpitAttachmentRequest, type MailpitAttachmentResponse, type MailpitChaosTrigger, type MailpitChaosTriggersRequest, type MailpitChaosTriggersResponse, MailpitClient, type MailpitConfigurationResponse, type MailpitDatabaseIDsRequest, type MailpitEmailAddressRequest, type MailpitEmailAddressResponse, type MailpitHTMLCheckResponse, type MailpitInfoResponse, type MailpitLinkCheckResponse, type MailpitMessageHeadersResponse, type MailpitMessageSummaryResponse, type MailpitMessagesSummaryResponse, type MailpitReadStatusRequest, type MailpitSearchMessagesRequest, type MailpitSearchRequest, type MailpitSendMessageConfirmationResponse, type MailpitSendRequest, type MailpitSetTagsRequest, type MailpitSpamAssassinResponse, type MailpitTimeZoneRequest };
981
+ export { type MailpitAttachmentDataResponse, type MailpitAttachmentRequest, type MailpitAttachmentResponse, type MailpitChaosTrigger, type MailpitChaosTriggersRequest, type MailpitChaosTriggersResponse, MailpitClient, type MailpitConfigurationResponse, type MailpitDatabaseIDsRequest, type MailpitDeleteData, type MailpitDeleteEvent, type MailpitEmailAddressRequest, type MailpitEmailAddressResponse, type MailpitErrorData, type MailpitErrorEvent, type MailpitEvent, type MailpitEventMap, type MailpitEventType, type MailpitHTMLCheckResponse, type MailpitInfoResponse, type MailpitLinkCheckResponse, type MailpitMessageHeadersResponse, type MailpitMessageListItem, type MailpitMessageSummary, type MailpitMessageSummaryResponse, type MailpitMessagesSummaryResponse, type MailpitNewMessageEvent, type MailpitPruneEvent, type MailpitReadStatusRequest, type MailpitSearchMessagesRequest, type MailpitSearchRequest, type MailpitSendMessageConfirmationResponse, type MailpitSendRequest, type MailpitSetTagsRequest, type MailpitSpamAssassinResponse, type MailpitStatsData, type MailpitStatsEvent, type MailpitTimeZoneRequest, type MailpitTruncateEvent, type MailpitUpdateData, type MailpitUpdateEvent };
package/dist/index.js CHANGED
@@ -34,8 +34,14 @@ __export(index_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(index_exports);
36
36
  var import_axios = __toESM(require("axios"));
37
+ var import_partysocket = require("partysocket");
38
+ var import_ws = __toESM(require("ws"));
37
39
  var MailpitClient = class {
38
40
  axiosInstance;
41
+ baseURL;
42
+ wsURL;
43
+ webSocket = null;
44
+ eventListeners = /* @__PURE__ */ new Map();
39
45
  /**
40
46
  * Creates an instance of {@link MailpitClient}.
41
47
  * @param baseURL - The base URL of the Mailpit API.
@@ -49,12 +55,19 @@ var MailpitClient = class {
49
55
  * @example Basic Auth
50
56
  * ```typescript
51
57
  * const mailpit = new MailpitClient("http://localhost:8025", {
52
- * username: "admin",
53
- * password: "supersecret",
58
+ * username: "admin",
59
+ * password: "supersecret"
54
60
  * });
55
61
  * ```
56
62
  */
57
63
  constructor(baseURL, auth) {
64
+ if (!baseURL || !/^https?:\/\//.test(baseURL)) {
65
+ throw new Error(
66
+ "The value of the 'baseURL' parameter must start with http:// or https://"
67
+ );
68
+ }
69
+ this.baseURL = baseURL;
70
+ this.wsURL = `${baseURL.replace(/^http/, "ws")}/api/events`;
58
71
  this.axiosInstance = import_axios.default.create({
59
72
  baseURL,
60
73
  auth,
@@ -564,6 +577,198 @@ var MailpitClient = class {
564
577
  () => this.axiosInstance.get(`/view/${id}.txt`)
565
578
  );
566
579
  }
580
+ /**
581
+ * @internal
582
+ * Connects to the WebSocket endpoint for receiving real-time events.
583
+ */
584
+ connectWebSocket() {
585
+ if (this.webSocket && (this.webSocket.readyState === import_partysocket.WebSocket.OPEN || this.webSocket.readyState === import_partysocket.WebSocket.CONNECTING)) {
586
+ return;
587
+ }
588
+ const wsOptions = {};
589
+ if (this.axiosInstance.defaults.auth) {
590
+ wsOptions.headers = {
591
+ Authorization: `Basic ${Buffer.from(`${this.axiosInstance.defaults.auth.username}:${this.axiosInstance.defaults.auth.password}`).toString("base64")}`
592
+ };
593
+ }
594
+ class AuthenticatedWebSocket extends import_ws.default {
595
+ constructor(address, options) {
596
+ super(address, { ...wsOptions, ...options });
597
+ }
598
+ }
599
+ this.webSocket = new import_partysocket.WebSocket(this.wsURL, void 0, {
600
+ WebSocket: AuthenticatedWebSocket
601
+ });
602
+ this.webSocket.addEventListener("message", (event) => {
603
+ let message;
604
+ try {
605
+ message = JSON.parse(event.data);
606
+ } catch {
607
+ return;
608
+ }
609
+ this.handleWebSocketMessage(message);
610
+ });
611
+ }
612
+ /**
613
+ * @internal
614
+ * Adds a listener to the event listeners map.
615
+ * @param eventType - The type of event to listen for
616
+ * @param listener - The listener function to add
617
+ */
618
+ addListener(eventType, listener) {
619
+ if (!this.eventListeners.has(eventType)) {
620
+ this.eventListeners.set(eventType, /* @__PURE__ */ new Set());
621
+ }
622
+ this.eventListeners.get(eventType)?.add(listener);
623
+ }
624
+ /**
625
+ * @internal
626
+ * Removes a listener from the event listeners map.
627
+ * @param eventType - The type of event to remove the listener from
628
+ * @param listener - The listener function to remove
629
+ */
630
+ removeListener(eventType, listener) {
631
+ const listeners = this.eventListeners.get(eventType);
632
+ if (listeners) {
633
+ listeners.delete(listener);
634
+ if (listeners.size === 0) {
635
+ this.eventListeners.delete(eventType);
636
+ }
637
+ }
638
+ }
639
+ /**
640
+ * @internal
641
+ * Dispatches a message to listeners of a specific event type.
642
+ * @param eventType - The event type to dispatch to
643
+ * @param message - The event message
644
+ */
645
+ dispatchToListeners(eventType, message) {
646
+ const listeners = this.eventListeners.get(eventType);
647
+ if (listeners) {
648
+ listeners.forEach((listener) => {
649
+ listener(message);
650
+ });
651
+ }
652
+ }
653
+ /**
654
+ * @internal
655
+ * Handles incoming WebSocket messages and dispatches them to registered listeners.
656
+ * @param message - The event message
657
+ */
658
+ handleWebSocketMessage(message) {
659
+ this.dispatchToListeners(message.Type, message);
660
+ this.dispatchToListeners("*", message);
661
+ }
662
+ /**
663
+ * Disconnects from the real-time event stream.
664
+ * @example
665
+ * ```typescript
666
+ * mailpit.disconnect();
667
+ * ```
668
+ */
669
+ disconnect() {
670
+ if (this.webSocket) {
671
+ const ws = this.webSocket;
672
+ this.webSocket = null;
673
+ ws.close(1e3, "Client disconnect");
674
+ }
675
+ }
676
+ /**
677
+ * Registers a listener for real-time events of a specific type.
678
+ * @remarks
679
+ * Automatically connects to the event stream if not already connected.
680
+ * @param eventType - The type of event to listen for.
681
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
682
+ * Use "*" to listen for all event types (Useful if processing all events uniformly (e.g., logging, debugging, metrics)).
683
+ * @param listener - The callback function to invoke when an event is received
684
+ * @returns A function to unregister the listener
685
+ * @example Listen for event type "new" messages (recommended)
686
+ * ```typescript
687
+ * const unsubscribe = mailpit.onEvent("new", (event) => {
688
+ * // event.Data is typed as MailpitMessageSummary with full type safety
689
+ * console.log("New message:", event.Data.Subject);
690
+ * });
691
+ *
692
+ * // Other code...
693
+ *
694
+ * // Unsubscribe listener when no longer needed
695
+ * unsubscribe();
696
+ * ```
697
+ * @example Listen for all events uniformly (for logging/debugging)
698
+ * ```typescript
699
+ * const unsubscribe = mailpit.onEvent("*", (event) => {
700
+ * // Generic processing for all event types
701
+ * console.log(`Event ${event.Type} received`);
702
+ * });
703
+ *
704
+ * // Other code...
705
+ *
706
+ * // Unsubscribe listener when no longer needed
707
+ * unsubscribe();
708
+ * ```
709
+ */
710
+ onEvent(eventType, listener) {
711
+ if (!this.webSocket || this.webSocket.readyState === import_partysocket.WebSocket.CLOSED) {
712
+ this.connectWebSocket();
713
+ }
714
+ this.addListener(eventType, listener);
715
+ return () => {
716
+ this.removeListener(eventType, listener);
717
+ };
718
+ }
719
+ /**
720
+ * Waits for the next event of a specific type.
721
+ * @remarks
722
+ * Automatically connects to the event stream if not already connected.
723
+ * Primarily intended for testing scenarios where you need to wait for a single specific event.
724
+ * The promise will reject if the timeout is reached before an event is received.
725
+ * @param eventType - The type of event to wait for.
726
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
727
+ * @param timeout - Timeout in milliseconds (default: 5000ms). Pass `Infinity` to disable timeout.
728
+ * @returns A promise that resolves with the event when received, or rejects on timeout
729
+ * @example Basic usage
730
+ * ```typescript
731
+ * // Create the promise before triggering the event
732
+ * const eventPromise = mailpit.waitForEvent("new");
733
+ *
734
+ * // Do something that triggers an email to send
735
+ * await mailpit.sendMessage({
736
+ * From: { Email: "test@example.com" },
737
+ * To: [{ Email: "recipient@example.com" }],
738
+ * Subject: "Test",
739
+ * });
740
+ *
741
+ * // Wait for the event confirming the message was received
742
+ * const event = await eventPromise;
743
+ * // event.Data is fully typed as MailpitMessageSummary
744
+ * console.log("Message received:", event.Data.Subject);
745
+ * ```
746
+ */
747
+ waitForEvent(eventType, timeout = 5e3) {
748
+ if (!this.webSocket || this.webSocket.readyState === import_partysocket.WebSocket.CLOSED) {
749
+ this.connectWebSocket();
750
+ }
751
+ return new Promise((resolve, reject) => {
752
+ let timer = null;
753
+ const cleanup = () => {
754
+ if (timer) {
755
+ clearTimeout(timer);
756
+ }
757
+ this.removeListener(eventType, listener);
758
+ };
759
+ const listener = (event) => {
760
+ cleanup();
761
+ resolve(event);
762
+ };
763
+ this.addListener(eventType, listener);
764
+ if (isFinite(timeout)) {
765
+ timer = setTimeout(() => {
766
+ cleanup();
767
+ reject(new Error(`Timeout waiting for event of type "${eventType}"`));
768
+ }, timeout);
769
+ }
770
+ });
771
+ }
567
772
  };
568
773
  // Annotate the CommonJS export names for ESM import in node:
569
774
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -2,8 +2,14 @@
2
2
  import axios, {
3
3
  isAxiosError
4
4
  } from "axios";
5
+ import { WebSocket as ReconnectingWebSocket } from "partysocket";
6
+ import WS from "ws";
5
7
  var MailpitClient = class {
6
8
  axiosInstance;
9
+ baseURL;
10
+ wsURL;
11
+ webSocket = null;
12
+ eventListeners = /* @__PURE__ */ new Map();
7
13
  /**
8
14
  * Creates an instance of {@link MailpitClient}.
9
15
  * @param baseURL - The base URL of the Mailpit API.
@@ -17,12 +23,19 @@ var MailpitClient = class {
17
23
  * @example Basic Auth
18
24
  * ```typescript
19
25
  * const mailpit = new MailpitClient("http://localhost:8025", {
20
- * username: "admin",
21
- * password: "supersecret",
26
+ * username: "admin",
27
+ * password: "supersecret"
22
28
  * });
23
29
  * ```
24
30
  */
25
31
  constructor(baseURL, auth) {
32
+ if (!baseURL || !/^https?:\/\//.test(baseURL)) {
33
+ throw new Error(
34
+ "The value of the 'baseURL' parameter must start with http:// or https://"
35
+ );
36
+ }
37
+ this.baseURL = baseURL;
38
+ this.wsURL = `${baseURL.replace(/^http/, "ws")}/api/events`;
26
39
  this.axiosInstance = axios.create({
27
40
  baseURL,
28
41
  auth,
@@ -532,6 +545,198 @@ var MailpitClient = class {
532
545
  () => this.axiosInstance.get(`/view/${id}.txt`)
533
546
  );
534
547
  }
548
+ /**
549
+ * @internal
550
+ * Connects to the WebSocket endpoint for receiving real-time events.
551
+ */
552
+ connectWebSocket() {
553
+ if (this.webSocket && (this.webSocket.readyState === ReconnectingWebSocket.OPEN || this.webSocket.readyState === ReconnectingWebSocket.CONNECTING)) {
554
+ return;
555
+ }
556
+ const wsOptions = {};
557
+ if (this.axiosInstance.defaults.auth) {
558
+ wsOptions.headers = {
559
+ Authorization: `Basic ${Buffer.from(`${this.axiosInstance.defaults.auth.username}:${this.axiosInstance.defaults.auth.password}`).toString("base64")}`
560
+ };
561
+ }
562
+ class AuthenticatedWebSocket extends WS {
563
+ constructor(address, options) {
564
+ super(address, { ...wsOptions, ...options });
565
+ }
566
+ }
567
+ this.webSocket = new ReconnectingWebSocket(this.wsURL, void 0, {
568
+ WebSocket: AuthenticatedWebSocket
569
+ });
570
+ this.webSocket.addEventListener("message", (event) => {
571
+ let message;
572
+ try {
573
+ message = JSON.parse(event.data);
574
+ } catch {
575
+ return;
576
+ }
577
+ this.handleWebSocketMessage(message);
578
+ });
579
+ }
580
+ /**
581
+ * @internal
582
+ * Adds a listener to the event listeners map.
583
+ * @param eventType - The type of event to listen for
584
+ * @param listener - The listener function to add
585
+ */
586
+ addListener(eventType, listener) {
587
+ if (!this.eventListeners.has(eventType)) {
588
+ this.eventListeners.set(eventType, /* @__PURE__ */ new Set());
589
+ }
590
+ this.eventListeners.get(eventType)?.add(listener);
591
+ }
592
+ /**
593
+ * @internal
594
+ * Removes a listener from the event listeners map.
595
+ * @param eventType - The type of event to remove the listener from
596
+ * @param listener - The listener function to remove
597
+ */
598
+ removeListener(eventType, listener) {
599
+ const listeners = this.eventListeners.get(eventType);
600
+ if (listeners) {
601
+ listeners.delete(listener);
602
+ if (listeners.size === 0) {
603
+ this.eventListeners.delete(eventType);
604
+ }
605
+ }
606
+ }
607
+ /**
608
+ * @internal
609
+ * Dispatches a message to listeners of a specific event type.
610
+ * @param eventType - The event type to dispatch to
611
+ * @param message - The event message
612
+ */
613
+ dispatchToListeners(eventType, message) {
614
+ const listeners = this.eventListeners.get(eventType);
615
+ if (listeners) {
616
+ listeners.forEach((listener) => {
617
+ listener(message);
618
+ });
619
+ }
620
+ }
621
+ /**
622
+ * @internal
623
+ * Handles incoming WebSocket messages and dispatches them to registered listeners.
624
+ * @param message - The event message
625
+ */
626
+ handleWebSocketMessage(message) {
627
+ this.dispatchToListeners(message.Type, message);
628
+ this.dispatchToListeners("*", message);
629
+ }
630
+ /**
631
+ * Disconnects from the real-time event stream.
632
+ * @example
633
+ * ```typescript
634
+ * mailpit.disconnect();
635
+ * ```
636
+ */
637
+ disconnect() {
638
+ if (this.webSocket) {
639
+ const ws = this.webSocket;
640
+ this.webSocket = null;
641
+ ws.close(1e3, "Client disconnect");
642
+ }
643
+ }
644
+ /**
645
+ * Registers a listener for real-time events of a specific type.
646
+ * @remarks
647
+ * Automatically connects to the event stream if not already connected.
648
+ * @param eventType - The type of event to listen for.
649
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
650
+ * Use "*" to listen for all event types (Useful if processing all events uniformly (e.g., logging, debugging, metrics)).
651
+ * @param listener - The callback function to invoke when an event is received
652
+ * @returns A function to unregister the listener
653
+ * @example Listen for event type "new" messages (recommended)
654
+ * ```typescript
655
+ * const unsubscribe = mailpit.onEvent("new", (event) => {
656
+ * // event.Data is typed as MailpitMessageSummary with full type safety
657
+ * console.log("New message:", event.Data.Subject);
658
+ * });
659
+ *
660
+ * // Other code...
661
+ *
662
+ * // Unsubscribe listener when no longer needed
663
+ * unsubscribe();
664
+ * ```
665
+ * @example Listen for all events uniformly (for logging/debugging)
666
+ * ```typescript
667
+ * const unsubscribe = mailpit.onEvent("*", (event) => {
668
+ * // Generic processing for all event types
669
+ * console.log(`Event ${event.Type} received`);
670
+ * });
671
+ *
672
+ * // Other code...
673
+ *
674
+ * // Unsubscribe listener when no longer needed
675
+ * unsubscribe();
676
+ * ```
677
+ */
678
+ onEvent(eventType, listener) {
679
+ if (!this.webSocket || this.webSocket.readyState === ReconnectingWebSocket.CLOSED) {
680
+ this.connectWebSocket();
681
+ }
682
+ this.addListener(eventType, listener);
683
+ return () => {
684
+ this.removeListener(eventType, listener);
685
+ };
686
+ }
687
+ /**
688
+ * Waits for the next event of a specific type.
689
+ * @remarks
690
+ * Automatically connects to the event stream if not already connected.
691
+ * Primarily intended for testing scenarios where you need to wait for a single specific event.
692
+ * The promise will reject if the timeout is reached before an event is received.
693
+ * @param eventType - The type of event to wait for.
694
+ * Specific event types include: "new" (new messages), "stats", "update", "delete", "prune", "truncate", and "error".
695
+ * @param timeout - Timeout in milliseconds (default: 5000ms). Pass `Infinity` to disable timeout.
696
+ * @returns A promise that resolves with the event when received, or rejects on timeout
697
+ * @example Basic usage
698
+ * ```typescript
699
+ * // Create the promise before triggering the event
700
+ * const eventPromise = mailpit.waitForEvent("new");
701
+ *
702
+ * // Do something that triggers an email to send
703
+ * await mailpit.sendMessage({
704
+ * From: { Email: "test@example.com" },
705
+ * To: [{ Email: "recipient@example.com" }],
706
+ * Subject: "Test",
707
+ * });
708
+ *
709
+ * // Wait for the event confirming the message was received
710
+ * const event = await eventPromise;
711
+ * // event.Data is fully typed as MailpitMessageSummary
712
+ * console.log("Message received:", event.Data.Subject);
713
+ * ```
714
+ */
715
+ waitForEvent(eventType, timeout = 5e3) {
716
+ if (!this.webSocket || this.webSocket.readyState === ReconnectingWebSocket.CLOSED) {
717
+ this.connectWebSocket();
718
+ }
719
+ return new Promise((resolve, reject) => {
720
+ let timer = null;
721
+ const cleanup = () => {
722
+ if (timer) {
723
+ clearTimeout(timer);
724
+ }
725
+ this.removeListener(eventType, listener);
726
+ };
727
+ const listener = (event) => {
728
+ cleanup();
729
+ resolve(event);
730
+ };
731
+ this.addListener(eventType, listener);
732
+ if (isFinite(timeout)) {
733
+ timer = setTimeout(() => {
734
+ cleanup();
735
+ reject(new Error(`Timeout waiting for event of type "${eventType}"`));
736
+ }, timeout);
737
+ }
738
+ });
739
+ }
535
740
  };
536
741
  export {
537
742
  MailpitClient
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailpit-api",
3
- "version": "1.5.3",
3
+ "version": "1.6.0",
4
4
  "description": "A TypeScript client for interacting with Mailpit's REST API.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -59,23 +59,26 @@
59
59
  "author": "Matthew Spahr",
60
60
  "license": "MIT",
61
61
  "dependencies": {
62
- "axios": "^1.8.4"
62
+ "axios": "^1.12.1",
63
+ "partysocket": "^1.1.10",
64
+ "ws": "^8.18.3"
63
65
  },
64
66
  "devDependencies": {
65
- "@eslint/js": "^9.30.0",
66
- "@jest/globals": "^30.0.3",
67
- "@types/node": "^22.15.34",
68
- "dotenv": "^16.6.1",
69
- "eslint": "^9.30.0",
70
- "eslint-plugin-jest": "^29.0.1",
71
- "jest": "^30.0.3",
72
- "prettier": "^3.6.2",
73
- "ts-jest": "^29.4.0",
74
- "tsup": "^8.5.0",
75
- "tsx": "^4.20.3",
76
- "typedoc": "^0.28.7",
77
- "typedoc-github-theme": "^0.3.0",
78
- "typescript": "^5.8.3",
79
- "typescript-eslint": "^8.35.1"
67
+ "@eslint/js": "^9.39.2",
68
+ "@jest/globals": "^30.2.0",
69
+ "@types/node": "^22.19.5",
70
+ "@types/ws": "^8.18.1",
71
+ "dotenv": "^17.2.3",
72
+ "eslint": "^9.39.2",
73
+ "eslint-plugin-jest": "^29.12.1",
74
+ "jest": "^30.2.0",
75
+ "prettier": "^3.7.4",
76
+ "ts-jest": "^29.4.6",
77
+ "tsup": "^8.5.1",
78
+ "tsx": "^4.21.0",
79
+ "typedoc": "^0.28.15",
80
+ "typedoc-github-theme": "^0.3.1",
81
+ "typescript": "^5.9.3",
82
+ "typescript-eslint": "^8.52.0"
80
83
  }
81
84
  }