@gravito/signal 3.0.4 → 3.1.2
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 +26 -15
- package/dist/Mailable.d.ts +453 -0
- package/dist/OrbitSignal.d.ts +267 -0
- package/{src/Queueable.ts → dist/Queueable.d.ts} +1 -1
- package/{src/TypedMailable.ts → dist/TypedMailable.d.ts} +12 -13
- package/dist/dev/DevMailbox.d.ts +79 -0
- package/dist/dev/DevServer.d.ts +39 -0
- package/dist/dev/storage/FileMailboxStorage.d.ts +16 -0
- package/dist/dev/storage/MailboxStorage.d.ts +14 -0
- package/dist/dev/storage/MemoryMailboxStorage.d.ts +13 -0
- package/dist/dev/ui/mailbox.d.ts +11 -0
- package/dist/dev/ui/preview.d.ts +11 -0
- package/dist/dev/ui/shared.d.ts +15 -0
- package/dist/errors.d.ts +58 -0
- package/{src/events.ts → dist/events.d.ts} +20 -29
- package/dist/{lib-HJTRWKU5.mjs → index.cjs} +4687 -10983
- package/dist/index.d.ts +303 -1874
- package/dist/index.js +317 -45939
- package/dist/index.mjs +59748 -27
- package/dist/renderers/HtmlRenderer.d.ts +34 -0
- package/dist/renderers/MjmlRenderer.d.ts +41 -0
- package/dist/renderers/ReactMjmlRenderer.d.ts +38 -0
- package/dist/renderers/ReactRenderer.d.ts +46 -0
- package/{src/renderers/Renderer.ts → dist/renderers/Renderer.d.ts} +23 -24
- package/dist/renderers/TemplateRenderer.d.ts +55 -0
- package/dist/renderers/VueMjmlRenderer.d.ts +39 -0
- package/dist/renderers/VueRenderer.d.ts +47 -0
- package/dist/renderers/mjml-templates.d.ts +11 -0
- package/dist/transports/BaseTransport.d.ts +111 -0
- package/dist/transports/LogTransport.d.ts +42 -0
- package/dist/transports/MemoryTransport.d.ts +51 -0
- package/dist/transports/SesTransport.d.ts +79 -0
- package/dist/transports/SmtpTransport.d.ts +124 -0
- package/dist/transports/Transport.d.ts +44 -0
- package/dist/types.d.ts +294 -0
- package/{src/utils/html.ts → dist/utils/html.d.ts} +1 -15
- package/dist/webhooks/SendGridWebhookDriver.d.ts +45 -0
- package/dist/webhooks/SesWebhookDriver.d.ts +23 -0
- package/package.json +20 -8
- package/CHANGELOG.md +0 -74
- package/dist/MjmlRenderer-IUH663FT.mjs +0 -8
- package/dist/ReactMjmlRenderer-C3P5YO5L.mjs +0 -8
- package/dist/ReactRenderer-24SQ4KRU.mjs +0 -27
- package/dist/ReactRenderer-2JFLRVST.mjs +0 -45
- package/dist/ReactRenderer-CMCAOEPH.mjs +0 -28
- package/dist/ReactRenderer-KYNA4WKE.mjs +0 -28
- package/dist/ReactRenderer-LYEOSYFS.mjs +0 -28
- package/dist/ReactRenderer-V54CUUEI.mjs +0 -45
- package/dist/VueMjmlRenderer-4F4CXHDB.mjs +0 -8
- package/dist/VueMjmlRenderer-5WZR4CQG.mjs +0 -8
- package/dist/VueMjmlRenderer-U5YMWI44.mjs +0 -8
- package/dist/VueRenderer-3YBRQXME.mjs +0 -48
- package/dist/VueRenderer-46JGXTJ2.mjs +0 -48
- package/dist/VueRenderer-5KWD4R3C.mjs +0 -48
- package/dist/VueRenderer-C23U4O5E.mjs +0 -48
- package/dist/VueRenderer-DWTCD2RF.mjs +0 -31
- package/dist/VueRenderer-IIR5SYTM.mjs +0 -31
- package/dist/VueRenderer-LEVDFLHP.mjs +0 -31
- package/dist/VueRenderer-RNHSCCRI.mjs +0 -48
- package/dist/VueRenderer-SUP66ISX.mjs +0 -29
- package/dist/chunk-3WOR3XSL.mjs +0 -82
- package/dist/chunk-DBFIVHHG.mjs +0 -79
- package/dist/chunk-EBO3CZXG.mjs +0 -15
- package/dist/chunk-HEBXNMVQ.mjs +0 -48
- package/dist/chunk-KB7IDDBT.mjs +0 -82
- package/dist/chunk-LZL5UUPC.mjs +0 -82
- package/dist/chunk-W6LXIJKK.mjs +0 -57
- package/dist/chunk-XBIVBJS2.mjs +0 -8
- package/dist/index.d.mts +0 -2115
- package/dist/server-renderer-4IM3P5XZ.mjs +0 -37183
- package/dist/server-renderer-4W4FI7YG.mjs +0 -37269
- package/dist/server-renderer-7KWFSTPV.mjs +0 -37193
- package/dist/server-renderer-S5FPSTJ2.mjs +0 -37183
- package/dist/server-renderer-X5LUFVWT.mjs +0 -37193
- package/doc/OPTIMIZATION_PLAN.md +0 -496
- package/scripts/check-coverage.ts +0 -64
- package/src/Mailable.ts +0 -674
- package/src/OrbitSignal.ts +0 -451
- package/src/dev/DevMailbox.ts +0 -146
- package/src/dev/DevServer.ts +0 -192
- package/src/dev/storage/FileMailboxStorage.ts +0 -66
- package/src/dev/storage/MailboxStorage.ts +0 -15
- package/src/dev/storage/MemoryMailboxStorage.ts +0 -36
- package/src/dev/ui/mailbox.ts +0 -77
- package/src/dev/ui/preview.ts +0 -103
- package/src/dev/ui/shared.ts +0 -60
- package/src/errors.ts +0 -69
- package/src/index.ts +0 -41
- package/src/renderers/HtmlRenderer.ts +0 -41
- package/src/renderers/MjmlRenderer.ts +0 -73
- package/src/renderers/ReactMjmlRenderer.ts +0 -94
- package/src/renderers/ReactRenderer.ts +0 -66
- package/src/renderers/TemplateRenderer.ts +0 -84
- package/src/renderers/VueMjmlRenderer.ts +0 -99
- package/src/renderers/VueRenderer.ts +0 -71
- package/src/renderers/mjml-templates.ts +0 -50
- package/src/transports/BaseTransport.ts +0 -148
- package/src/transports/LogTransport.ts +0 -55
- package/src/transports/MemoryTransport.ts +0 -55
- package/src/transports/SesTransport.ts +0 -129
- package/src/transports/SmtpTransport.ts +0 -184
- package/src/transports/Transport.ts +0 -45
- package/src/types.ts +0 -309
- package/src/webhooks/SendGridWebhookDriver.ts +0 -80
- package/src/webhooks/SesWebhookDriver.ts +0 -44
- package/tests/DevMailbox.test.ts +0 -54
- package/tests/FileMailboxStorage.test.ts +0 -56
- package/tests/MjmlLayout.test.ts +0 -28
- package/tests/MjmlRenderer.test.ts +0 -53
- package/tests/OrbitSignalWebhook.test.ts +0 -56
- package/tests/ReactMjmlRenderer.test.ts +0 -33
- package/tests/SendGridWebhookDriver.test.ts +0 -69
- package/tests/SesWebhookDriver.test.ts +0 -46
- package/tests/VueMjmlRenderer.test.ts +0 -35
- package/tests/dev-server.test.ts +0 -66
- package/tests/log-transport.test.ts +0 -21
- package/tests/mailable-extra.test.ts +0 -68
- package/tests/mailable.test.ts +0 -77
- package/tests/orbit-signal.test.ts +0 -43
- package/tests/renderers.test.ts +0 -58
- package/tests/template-renderer.test.ts +0 -24
- package/tests/transports.test.ts +0 -52
- package/tests/ui.test.ts +0 -37
- package/tsconfig.json +0 -14
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Message } from '../types';
|
|
2
|
+
import { BaseTransport, type TransportOptions } from './BaseTransport';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for SMTP email transport.
|
|
5
|
+
*
|
|
6
|
+
* Defines the connection parameters, authentication, and pooling settings for
|
|
7
|
+
* communicating with an SMTP server.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const config: SmtpConfig = {
|
|
12
|
+
* host: 'smtp.mailtrap.io',
|
|
13
|
+
* port: 2525,
|
|
14
|
+
* auth: { user: 'username', pass: 'password' },
|
|
15
|
+
* poolSize: 10
|
|
16
|
+
* };
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export interface SmtpConfig extends TransportOptions {
|
|
22
|
+
/** SMTP server hostname or IP address. */
|
|
23
|
+
host: string;
|
|
24
|
+
/** SMTP server port (typically 25, 465, or 587). */
|
|
25
|
+
port: number;
|
|
26
|
+
/** Whether to use a secure TLS/SSL connection. Should be true for port 465. */
|
|
27
|
+
secure?: boolean;
|
|
28
|
+
/** Authentication credentials for the SMTP server. */
|
|
29
|
+
auth?: {
|
|
30
|
+
/** SMTP username. */
|
|
31
|
+
user: string;
|
|
32
|
+
/** SMTP password. */
|
|
33
|
+
pass: string;
|
|
34
|
+
};
|
|
35
|
+
/** TLS specific options for the connection. */
|
|
36
|
+
tls?: {
|
|
37
|
+
/** Whether to reject unauthorized certificates (useful for self-signed certs). */
|
|
38
|
+
rejectUnauthorized?: boolean;
|
|
39
|
+
/** Specific cipher suite to use for the connection. */
|
|
40
|
+
ciphers?: string;
|
|
41
|
+
};
|
|
42
|
+
/** Number of concurrent connections to maintain in the pool. */
|
|
43
|
+
poolSize?: number;
|
|
44
|
+
/** Maximum time in milliseconds a connection can remain idle before being closed. */
|
|
45
|
+
maxIdleTime?: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* SMTP email transport with connection pooling and automatic retry.
|
|
49
|
+
*
|
|
50
|
+
* This transport uses the standard SMTP protocol to deliver emails. It leverages
|
|
51
|
+
* `nodemailer` for robust protocol implementation and includes built-in support
|
|
52
|
+
* for connection pooling to improve performance when sending multiple emails.
|
|
53
|
+
* It inherits automatic retry logic from `BaseTransport`.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { SmtpTransport } from '@gravito/signal';
|
|
58
|
+
*
|
|
59
|
+
* const transport = new SmtpTransport({
|
|
60
|
+
* host: 'smtp.example.com',
|
|
61
|
+
* port: 587,
|
|
62
|
+
* auth: { user: 'user', pass: 'pass' }
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* await transport.send(message);
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
export declare class SmtpTransport extends BaseTransport {
|
|
71
|
+
private transporter;
|
|
72
|
+
/**
|
|
73
|
+
* Initializes the SMTP transport with the provided configuration.
|
|
74
|
+
*
|
|
75
|
+
* Sets up the underlying nodemailer transporter with connection pooling enabled.
|
|
76
|
+
*
|
|
77
|
+
* @param config - SMTP connection and retry configuration.
|
|
78
|
+
*/
|
|
79
|
+
constructor(config: SmtpConfig);
|
|
80
|
+
/**
|
|
81
|
+
* Internal method to perform the actual SMTP delivery.
|
|
82
|
+
*
|
|
83
|
+
* Maps the generic `Message` object to the format expected by nodemailer.
|
|
84
|
+
*
|
|
85
|
+
* @param message - The message to deliver.
|
|
86
|
+
* @returns A promise that resolves when the SMTP server accepts the message.
|
|
87
|
+
* @throws {Error} If the SMTP server rejects the message or connection fails.
|
|
88
|
+
*/
|
|
89
|
+
protected doSend(message: Message): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Gracefully shuts down the transport and closes all pooled connections.
|
|
92
|
+
*
|
|
93
|
+
* This should be called during application shutdown to ensure no resources are leaked.
|
|
94
|
+
*
|
|
95
|
+
* @returns A promise that resolves when all connections are closed.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* await transport.close();
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
close(): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Verifies the SMTP connection and authentication.
|
|
105
|
+
*
|
|
106
|
+
* Useful for health checks or validating configuration during startup.
|
|
107
|
+
*
|
|
108
|
+
* @returns A promise that resolves to true if the connection is valid, false otherwise.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const isValid = await transport.verify();
|
|
113
|
+
* if (!isValid) throw new Error('SMTP configuration is invalid');
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
verify(): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* Formats an Address object into a standard RFC 822 string.
|
|
119
|
+
*
|
|
120
|
+
* @param addr - The address object to format.
|
|
121
|
+
* @returns A string in the format "Name <email@example.com>" or just "email@example.com".
|
|
122
|
+
*/
|
|
123
|
+
private formatAddress;
|
|
124
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Message } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for email transport mechanisms.
|
|
4
|
+
*
|
|
5
|
+
* Transports are responsible for the final delivery of an email message to its destination,
|
|
6
|
+
* whether it's a real SMTP server, a cloud service like AWS SES, or a local log for development.
|
|
7
|
+
* This abstraction allows the core mail service to remain agnostic of the delivery method.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* class CustomTransport implements Transport {
|
|
12
|
+
* async send(message: Message): Promise<void> {
|
|
13
|
+
* // Implementation logic to deliver the message
|
|
14
|
+
* console.log(`Sending email to ${message.to[0].address}`);
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export interface Transport {
|
|
22
|
+
/**
|
|
23
|
+
* Send the given message using the underlying transport mechanism.
|
|
24
|
+
*
|
|
25
|
+
* This method handles the actual communication with the delivery service.
|
|
26
|
+
* Implementations should handle connection management and protocol-specific logic.
|
|
27
|
+
*
|
|
28
|
+
* @param message - The finalized message object containing recipients, subject, and content.
|
|
29
|
+
* @returns A promise that resolves when the message has been successfully handed off to the transport.
|
|
30
|
+
* @throws {MailTransportError} If the delivery fails after all internal retry attempts.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const transport: Transport = new LogTransport();
|
|
35
|
+
* await transport.send({
|
|
36
|
+
* from: { address: 'sender@example.com' },
|
|
37
|
+
* to: [{ address: 'receiver@example.com' }],
|
|
38
|
+
* subject: 'Hello',
|
|
39
|
+
* html: '<p>World</p>'
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
send(message: Message): Promise<void>;
|
|
44
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import type { GravitoContext } from '@gravito/core';
|
|
2
|
+
import type { Transport } from './transports/Transport';
|
|
3
|
+
/**
|
|
4
|
+
* Interface for Webhook Drivers.
|
|
5
|
+
*/
|
|
6
|
+
export interface WebhookDriver {
|
|
7
|
+
handle(c: GravitoContext): Promise<{
|
|
8
|
+
event: string;
|
|
9
|
+
payload: any;
|
|
10
|
+
}[] | null>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Transport interface for sending email messages.
|
|
14
|
+
*
|
|
15
|
+
* Defines the contract for different delivery mechanisms (SMTP, SES, etc.).
|
|
16
|
+
*/
|
|
17
|
+
export type { Transport };
|
|
18
|
+
/**
|
|
19
|
+
* Representation of an email address with optional display name.
|
|
20
|
+
*
|
|
21
|
+
* Defines the structure for email addresses used throughout the mail system.
|
|
22
|
+
* Supports both simple string addresses and formatted addresses with display names.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Simple address
|
|
27
|
+
* const addr1: Address = { address: 'user@example.com' }
|
|
28
|
+
*
|
|
29
|
+
* // Address with display name
|
|
30
|
+
* const addr2: Address = {
|
|
31
|
+
* name: 'John Doe',
|
|
32
|
+
* address: 'john@example.com'
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @see {@link Envelope} For the email envelope structure
|
|
37
|
+
* @see {@link Message} For the complete message structure
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
* @since 3.0.0
|
|
41
|
+
*/
|
|
42
|
+
export interface Address {
|
|
43
|
+
/** The display name of the recipient/sender, e.g., "John Doe". */
|
|
44
|
+
name?: string;
|
|
45
|
+
/** The actual email address string. */
|
|
46
|
+
address: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Configuration for an email attachment.
|
|
50
|
+
*
|
|
51
|
+
* Defines file attachments for email messages. Supports both regular attachments
|
|
52
|
+
* and inline attachments (e.g., embedded images referenced via Content-ID).
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // Regular file attachment
|
|
57
|
+
* const attachment: Attachment = {
|
|
58
|
+
* filename: 'document.pdf',
|
|
59
|
+
* content: Buffer.from('...'),
|
|
60
|
+
* contentType: 'application/pdf'
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* // Inline image attachment
|
|
64
|
+
* const inlineImage: Attachment = {
|
|
65
|
+
* filename: 'logo.png',
|
|
66
|
+
* content: Buffer.from('...'),
|
|
67
|
+
* contentType: 'image/png',
|
|
68
|
+
* cid: 'logo@example.com' // Reference in HTML: <img src="cid:logo@example.com">
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @see {@link Envelope} For adding attachments to emails
|
|
73
|
+
*
|
|
74
|
+
* @public
|
|
75
|
+
* @since 3.0.0
|
|
76
|
+
*/
|
|
77
|
+
export interface Attachment {
|
|
78
|
+
/** The filename of the attachment. */
|
|
79
|
+
filename: string;
|
|
80
|
+
/** The content of the attachment as a string or Buffer. */
|
|
81
|
+
content: string | Buffer;
|
|
82
|
+
/** Optional MIME type of the content. */
|
|
83
|
+
contentType?: string;
|
|
84
|
+
/** Optional Content-ID for referencing within HTML content (inline images). */
|
|
85
|
+
cid?: string;
|
|
86
|
+
/** Optional content encoding. */
|
|
87
|
+
encoding?: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The envelope containing metadata for an email message.
|
|
91
|
+
*
|
|
92
|
+
* Used during the construction phase of a Mailable. All fields are optional
|
|
93
|
+
* at this stage and will be validated when converting to a Message.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const envelope: Envelope = {
|
|
98
|
+
* from: { name: 'App', address: 'noreply@app.com' },
|
|
99
|
+
* to: [{ address: 'user@example.com' }],
|
|
100
|
+
* subject: 'Welcome!',
|
|
101
|
+
* priority: 'high',
|
|
102
|
+
* replyTo: { address: 'support@app.com' }
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @see {@link Mailable} For building envelopes fluently
|
|
107
|
+
* @see {@link Message} For the validated, finalized message structure
|
|
108
|
+
*
|
|
109
|
+
* @public
|
|
110
|
+
* @since 3.0.0
|
|
111
|
+
*/
|
|
112
|
+
export interface Envelope {
|
|
113
|
+
/** The sender's address. */
|
|
114
|
+
from?: Address | undefined;
|
|
115
|
+
/** Primary recipients. */
|
|
116
|
+
to?: Address[] | undefined;
|
|
117
|
+
/** Carbon copy recipients. */
|
|
118
|
+
cc?: Address[] | undefined;
|
|
119
|
+
/** Blind carbon copy recipients. */
|
|
120
|
+
bcc?: Address[] | undefined;
|
|
121
|
+
/** Reply-to address. */
|
|
122
|
+
replyTo?: Address | undefined;
|
|
123
|
+
/** Email subject line. */
|
|
124
|
+
subject?: string | undefined;
|
|
125
|
+
/** Importance level of the email. */
|
|
126
|
+
priority?: 'high' | 'normal' | 'low' | undefined;
|
|
127
|
+
/** List of file attachments. */
|
|
128
|
+
attachments?: Attachment[] | undefined;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* A fully finalized email message ready to be sent by a transport.
|
|
132
|
+
*
|
|
133
|
+
* Requires mandatory fields that were optional in the Envelope.
|
|
134
|
+
* This structure is passed to Transport implementations for actual delivery.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const message: Message = {
|
|
139
|
+
* from: { name: 'App', address: 'noreply@app.com' },
|
|
140
|
+
* to: [{ address: 'user@example.com' }],
|
|
141
|
+
* subject: 'Welcome to our service',
|
|
142
|
+
* html: '<h1>Welcome!</h1><p>Thanks for joining.</p>',
|
|
143
|
+
* text: 'Welcome! Thanks for joining.',
|
|
144
|
+
* priority: 'normal',
|
|
145
|
+
* headers: { 'X-Custom-Header': 'value' }
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @see {@link Envelope} For the construction phase structure
|
|
150
|
+
* @see {@link Transport} For implementations that send messages
|
|
151
|
+
*
|
|
152
|
+
* @public
|
|
153
|
+
* @since 3.0.0
|
|
154
|
+
*/
|
|
155
|
+
export interface Message extends Envelope {
|
|
156
|
+
/** The mandatory sender's address. */
|
|
157
|
+
from: Address;
|
|
158
|
+
/** At least one recipient is required. */
|
|
159
|
+
to: Address[];
|
|
160
|
+
/** Mandatory subject. */
|
|
161
|
+
subject: string;
|
|
162
|
+
/** The rendered HTML body content. */
|
|
163
|
+
html: string;
|
|
164
|
+
/** Optional rendered plain text body content. */
|
|
165
|
+
text?: string;
|
|
166
|
+
/** Custom SMTP headers. */
|
|
167
|
+
headers?: Record<string, string>;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Global configuration options for OrbitSignal and Mailable instances.
|
|
171
|
+
*
|
|
172
|
+
* Configures the mail service behavior, transport mechanism, development tools,
|
|
173
|
+
* and internationalization support.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* import { OrbitSignal, SmtpTransport } from '@gravito/signal'
|
|
178
|
+
*
|
|
179
|
+
* const config: MailConfig = {
|
|
180
|
+
* from: { name: 'My App', address: 'noreply@myapp.com' },
|
|
181
|
+
* transport: new SmtpTransport({
|
|
182
|
+
* host: 'smtp.mailtrap.io',
|
|
183
|
+
* port: 2525,
|
|
184
|
+
* auth: { user: 'user', pass: 'pass' }
|
|
185
|
+
* }),
|
|
186
|
+
* devMode: process.env.NODE_ENV === 'development',
|
|
187
|
+
* viewsDir: './src/emails',
|
|
188
|
+
* devUiPrefix: '/__mail',
|
|
189
|
+
* translator: (key, replace, locale) => i18n.t(key, { ...replace, locale })
|
|
190
|
+
* }
|
|
191
|
+
*
|
|
192
|
+
* const mail = new OrbitSignal(config)
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @see {@link OrbitSignal} For the mail service implementation
|
|
196
|
+
* @see {@link Transport} For available transport options
|
|
197
|
+
*
|
|
198
|
+
* @public
|
|
199
|
+
* @since 3.0.0
|
|
200
|
+
*/
|
|
201
|
+
export interface MailConfig {
|
|
202
|
+
/**
|
|
203
|
+
* Default sender address used if not specified in the Mailable.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* from: { name: 'My App', address: 'noreply@myapp.com' }
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
from?: Address;
|
|
211
|
+
/**
|
|
212
|
+
* The transport mechanism used to send emails (e.g., SMTP, SES, Log).
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```typescript
|
|
216
|
+
* import { SmtpTransport } from '@gravito/signal'
|
|
217
|
+
* transport: new SmtpTransport({ host: 'smtp.example.com', port: 587 })
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
transport?: Transport;
|
|
221
|
+
/**
|
|
222
|
+
* Enable development mode.
|
|
223
|
+
* When true, emails are intercepted by the DevMailbox instead of being sent.
|
|
224
|
+
*
|
|
225
|
+
* @default false
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* devMode: process.env.NODE_ENV === 'development'
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
devMode?: boolean | undefined;
|
|
232
|
+
/**
|
|
233
|
+
* Directory where email templates are located for use with OrbitPrism.
|
|
234
|
+
*
|
|
235
|
+
* @default "src/emails"
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* viewsDir: './resources/views/emails'
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
viewsDir?: string | undefined;
|
|
242
|
+
/**
|
|
243
|
+
* URL prefix for the Mail Dev UI.
|
|
244
|
+
*
|
|
245
|
+
* @default "/__mail"
|
|
246
|
+
* @example
|
|
247
|
+
* ```typescript
|
|
248
|
+
* devUiPrefix: '/dev/mailbox'
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
devUiPrefix?: string | undefined;
|
|
252
|
+
/**
|
|
253
|
+
* Whether to allow access to the Mail Dev UI in production environments.
|
|
254
|
+
*
|
|
255
|
+
* @default false
|
|
256
|
+
* @example
|
|
257
|
+
* ```typescript
|
|
258
|
+
* devUiAllowInProduction: process.env.ALLOW_MAIL_UI === 'true'
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
devUiAllowInProduction?: boolean | undefined;
|
|
262
|
+
/**
|
|
263
|
+
* Authorization gate for the Mail Dev UI.
|
|
264
|
+
* Should return true to allow access to the UI.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```typescript
|
|
268
|
+
* devUiGate: async (ctx) => {
|
|
269
|
+
* const user = await ctx.get('auth').user()
|
|
270
|
+
* return user?.role === 'admin'
|
|
271
|
+
* }
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
devUiGate?: ((ctx: GravitoContext) => boolean | Promise<boolean>) | undefined;
|
|
275
|
+
/**
|
|
276
|
+
* Translation function for internationalization within emails.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```typescript
|
|
280
|
+
* translator: (key, replace, locale) => {
|
|
281
|
+
* return i18n.t(key, { ...replace, locale: locale || 'en' })
|
|
282
|
+
* }
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
translator?: ((key: string, replace?: Record<string, unknown>, locale?: string) => string) | undefined;
|
|
286
|
+
/**
|
|
287
|
+
* URL prefix for Webhook endpoints.
|
|
288
|
+
*/
|
|
289
|
+
webhookPrefix?: string | undefined;
|
|
290
|
+
/**
|
|
291
|
+
* Dictionary of registered webhook drivers.
|
|
292
|
+
*/
|
|
293
|
+
webhookDrivers?: Record<string, WebhookDriver> | undefined;
|
|
294
|
+
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* @module utils/html
|
|
8
8
|
* @since 3.1.0
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
10
|
/**
|
|
12
11
|
* Convert HTML content to plain text.
|
|
13
12
|
*
|
|
@@ -27,17 +26,4 @@
|
|
|
27
26
|
* @public
|
|
28
27
|
* @since 3.1.0
|
|
29
28
|
*/
|
|
30
|
-
export function stripHtml(html: string): string
|
|
31
|
-
return html
|
|
32
|
-
.replace(/<style(?:\s[^>]*)?>[\s\S]*?<\/style>/gi, '')
|
|
33
|
-
.replace(/<script(?:\s[^>]*)?>[\s\S]*?<\/script>/gi, '')
|
|
34
|
-
.replace(/<[^>]+>/g, '')
|
|
35
|
-
.replace(/ /g, ' ')
|
|
36
|
-
.replace(/&/g, '&')
|
|
37
|
-
.replace(/</g, '<')
|
|
38
|
-
.replace(/>/g, '>')
|
|
39
|
-
.replace(/"/g, '"')
|
|
40
|
-
.replace(/'/g, "'")
|
|
41
|
-
.replace(/\s+/g, ' ')
|
|
42
|
-
.trim()
|
|
43
|
-
}
|
|
29
|
+
export declare function stripHtml(html: string): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { GravitoContext } from '@gravito/core';
|
|
2
|
+
import type { WebhookDriver } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for SendGrid Webhook Driver.
|
|
5
|
+
*/
|
|
6
|
+
export interface SendGridWebhookConfig {
|
|
7
|
+
/**
|
|
8
|
+
* Public key or Verification Secret for signature validation.
|
|
9
|
+
* If provided, all requests will be validated.
|
|
10
|
+
*/
|
|
11
|
+
publicKey?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* SendGrid Webhook Driver.
|
|
15
|
+
*
|
|
16
|
+
* Handles Event Webhooks from SendGrid (delivered, bounced, opened, clicked, etc.).
|
|
17
|
+
*
|
|
18
|
+
* @see https://docs.sendgrid.com/for-developers/tracking-events/event-webhook
|
|
19
|
+
* @public
|
|
20
|
+
* @since 1.1.0
|
|
21
|
+
*/
|
|
22
|
+
export declare class SendGridWebhookDriver implements WebhookDriver {
|
|
23
|
+
private config;
|
|
24
|
+
constructor(config?: SendGridWebhookConfig);
|
|
25
|
+
/**
|
|
26
|
+
* Handles the SendGrid webhook request.
|
|
27
|
+
*/
|
|
28
|
+
handle(c: GravitoContext): Promise<{
|
|
29
|
+
event: string;
|
|
30
|
+
payload: any;
|
|
31
|
+
}[] | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Verifies the SendGrid webhook signature.
|
|
34
|
+
*
|
|
35
|
+
* @param payload - Raw request body string.
|
|
36
|
+
* @param signature - Signature from X-Twilio-Email-Event-Webhook-Signature header.
|
|
37
|
+
* @param timestamp - Timestamp from X-Twilio-Email-Event-Webhook-Timestamp header.
|
|
38
|
+
* @returns True if signature is valid.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* Real SendGrid validation uses Elliptic Curve (ECDSA).
|
|
42
|
+
* This is a placeholder for the logic structure.
|
|
43
|
+
*/
|
|
44
|
+
private verifySignature;
|
|
45
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { GravitoContext } from '@gravito/core';
|
|
2
|
+
import type { WebhookDriver } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* AWS SES Webhook Driver.
|
|
5
|
+
*
|
|
6
|
+
* Handles SES Notifications via Amazon SNS (Complaints, Bounces, Deliveries).
|
|
7
|
+
*
|
|
8
|
+
* @see https://docs.aws.amazon.com/ses/latest/dg/monitor-sending-activity-using-notifications.html
|
|
9
|
+
* @public
|
|
10
|
+
* @since 1.1.0
|
|
11
|
+
*/
|
|
12
|
+
export declare class SesWebhookDriver implements WebhookDriver {
|
|
13
|
+
/**
|
|
14
|
+
* Handles the AWS SES/SNS webhook request.
|
|
15
|
+
*
|
|
16
|
+
* @param c - The Gravito request context.
|
|
17
|
+
* @returns Array of processed events or null if ignored.
|
|
18
|
+
*/
|
|
19
|
+
handle(c: GravitoContext): Promise<{
|
|
20
|
+
event: string;
|
|
21
|
+
payload: any;
|
|
22
|
+
}[] | null>;
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravito/signal",
|
|
3
|
-
"
|
|
3
|
+
"sideEffects": false,
|
|
4
|
+
"version": "3.1.2",
|
|
4
5
|
"description": "Powerful email framework for Gravito applications with Dev UI and multi-renderer support.",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"module": "dist/index.mjs",
|
|
7
8
|
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
8
16
|
"scripts": {
|
|
9
|
-
"build": "
|
|
17
|
+
"build": "bun run build.ts",
|
|
18
|
+
"build:dts": "bun run build.ts --dts-only",
|
|
10
19
|
"test": "bun test --timeout=10000",
|
|
11
20
|
"test:coverage": "bun test --timeout=10000 --coverage --coverage-reporter=lcov --coverage-dir coverage && bun run --bun scripts/check-coverage.ts",
|
|
12
21
|
"test:ci": "bun test --timeout=10000 --coverage --coverage-reporter=lcov --coverage-dir coverage && bun run --bun scripts/check-coverage.ts",
|
|
@@ -14,6 +23,10 @@
|
|
|
14
23
|
"test:unit": "bun test tests/ --timeout=10000",
|
|
15
24
|
"test:integration": "test $(find tests -name '*.integration.test.ts' 2>/dev/null | wc -l) -gt 0 && find tests -name '*.integration.test.ts' -print0 | xargs -0 bun test --timeout=10000 || echo 'No integration tests found'"
|
|
16
25
|
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
17
30
|
"keywords": [
|
|
18
31
|
"gravito",
|
|
19
32
|
"mail",
|
|
@@ -29,8 +42,8 @@
|
|
|
29
42
|
"nodemailer": "^7.0.11"
|
|
30
43
|
},
|
|
31
44
|
"peerDependencies": {
|
|
32
|
-
"@gravito/core": "^
|
|
33
|
-
"@gravito/stream": "^2.0
|
|
45
|
+
"@gravito/core": "^2.0.0",
|
|
46
|
+
"@gravito/stream": "^2.1.0",
|
|
34
47
|
"@gravito/prism": "^3.1.1",
|
|
35
48
|
"react": "^19.0.0",
|
|
36
49
|
"react-dom": "^19.0.0",
|
|
@@ -51,14 +64,13 @@
|
|
|
51
64
|
}
|
|
52
65
|
},
|
|
53
66
|
"devDependencies": {
|
|
54
|
-
"@gravito/prism": "
|
|
55
|
-
"@gravito/stream": "
|
|
67
|
+
"@gravito/prism": "workspace:*",
|
|
68
|
+
"@gravito/stream": "workspace:*",
|
|
56
69
|
"@types/nodemailer": "^6.4.14",
|
|
57
70
|
"@types/react": "^19.0.0",
|
|
58
71
|
"@types/react-dom": "^19.0.0",
|
|
59
72
|
"@vue/server-renderer": "^3.0.0",
|
|
60
|
-
"@gravito/core": "
|
|
61
|
-
"tsup": "8.5.1",
|
|
73
|
+
"@gravito/core": "workspace:*",
|
|
62
74
|
"typescript": "^5.9.3",
|
|
63
75
|
"vue": "^3.0.0",
|
|
64
76
|
"bun-types": "latest"
|
package/CHANGELOG.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# @gravito/signal
|
|
2
|
-
|
|
3
|
-
## 3.0.4
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Convert all workspace:\* dependencies to version numbers for npm publishing
|
|
8
|
-
|
|
9
|
-
- Fixed 144 workspace:\* dependencies across 58 packages
|
|
10
|
-
- Ensures all packages work properly when installed from npm
|
|
11
|
-
- Resolves issues with bunx and npm installation of CLI tools
|
|
12
|
-
- All internal dependencies now use explicit version constraints
|
|
13
|
-
|
|
14
|
-
- Updated dependencies
|
|
15
|
-
- @gravito/core@1.6.1
|
|
16
|
-
- @gravito/prism@3.1.1
|
|
17
|
-
- @gravito/stream@2.0.2
|
|
18
|
-
|
|
19
|
-
## 3.0.3
|
|
20
|
-
|
|
21
|
-
### Patch Changes
|
|
22
|
-
|
|
23
|
-
- Updated dependencies [6234dab]
|
|
24
|
-
- @gravito/prism@3.0.2
|
|
25
|
-
|
|
26
|
-
## 3.0.2
|
|
27
|
-
|
|
28
|
-
### Patch Changes
|
|
29
|
-
|
|
30
|
-
- Updated dependencies [905588f]
|
|
31
|
-
- @gravito/stream@2.0.1
|
|
32
|
-
|
|
33
|
-
## 3.0.1
|
|
34
|
-
|
|
35
|
-
### Patch Changes
|
|
36
|
-
|
|
37
|
-
- Updated dependencies
|
|
38
|
-
- @gravito/core@1.2.1
|
|
39
|
-
- @gravito/stream@1.0.3
|
|
40
|
-
- @gravito/prism@3.0.1
|
|
41
|
-
|
|
42
|
-
## 3.0.0
|
|
43
|
-
|
|
44
|
-
### Patch Changes
|
|
45
|
-
|
|
46
|
-
- Updated dependencies
|
|
47
|
-
- @gravito/core@1.2.0
|
|
48
|
-
- @gravito/prism@3.0.0
|
|
49
|
-
- @gravito/stream@1.0.2
|
|
50
|
-
|
|
51
|
-
## 2.0.0
|
|
52
|
-
|
|
53
|
-
### Patch Changes
|
|
54
|
-
|
|
55
|
-
- Updated dependencies
|
|
56
|
-
- Updated dependencies
|
|
57
|
-
- @gravito/core@1.1.0
|
|
58
|
-
- @gravito/prism@2.0.0
|
|
59
|
-
- @gravito/stream@1.0.1
|
|
60
|
-
|
|
61
|
-
## 1.0.1
|
|
62
|
-
|
|
63
|
-
### Patch Changes
|
|
64
|
-
|
|
65
|
-
- Refactored all scaffold generators (Enterprise MVC, Clean Architecture, Action Domain, DDD) to adopt the Service Provider pattern and a modern 4-step bootstrap lifecycle. Fixed a missing mock in @gravito/signal tests.
|
|
66
|
-
|
|
67
|
-
## 1.0.0
|
|
68
|
-
|
|
69
|
-
### Patch Changes
|
|
70
|
-
|
|
71
|
-
- Updated dependencies
|
|
72
|
-
- @gravito/core@1.0.0
|
|
73
|
-
- @gravito/stream@1.0.0
|
|
74
|
-
- @gravito/prism@1.0.0
|