@parsrun/email 0.1.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.
@@ -0,0 +1,47 @@
1
+ import { EmailProvider, EmailProviderConfig, EmailOptions, EmailResult, BatchEmailOptions, BatchEmailResult } from '../types.js';
2
+ import '@parsrun/types';
3
+
4
+ /**
5
+ * @parsrun/email - SendGrid Provider
6
+ * Edge-compatible SendGrid email provider
7
+ */
8
+
9
+ /**
10
+ * SendGrid Email Provider
11
+ * Uses fetch API for edge compatibility
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const sendgrid = new SendGridProvider({
16
+ * apiKey: process.env.SENDGRID_API_KEY,
17
+ * fromEmail: 'hello@example.com',
18
+ * fromName: 'My App',
19
+ * });
20
+ *
21
+ * await sendgrid.send({
22
+ * to: 'user@example.com',
23
+ * subject: 'Hello',
24
+ * html: '<p>Hello World!</p>',
25
+ * });
26
+ * ```
27
+ */
28
+ declare class SendGridProvider implements EmailProvider {
29
+ readonly type: "sendgrid";
30
+ private apiKey;
31
+ private fromEmail;
32
+ private fromName;
33
+ private baseUrl;
34
+ constructor(config: EmailProviderConfig);
35
+ private formatAddress;
36
+ private formatAddresses;
37
+ send(options: EmailOptions): Promise<EmailResult>;
38
+ sendBatch(options: BatchEmailOptions): Promise<BatchEmailResult>;
39
+ verify(): Promise<boolean>;
40
+ private uint8ArrayToBase64;
41
+ }
42
+ /**
43
+ * Create a SendGrid provider
44
+ */
45
+ declare function createSendGridProvider(config: EmailProviderConfig): SendGridProvider;
46
+
47
+ export { SendGridProvider, createSendGridProvider };
@@ -0,0 +1,193 @@
1
+ // src/types.ts
2
+ import {
3
+ type,
4
+ emailAddress,
5
+ emailAttachment,
6
+ sendEmailOptions,
7
+ sendTemplateEmailOptions,
8
+ emailSendResult,
9
+ smtpConfig,
10
+ resendConfig,
11
+ sendgridConfig,
12
+ sesConfig,
13
+ postmarkConfig,
14
+ emailConfig
15
+ } from "@parsrun/types";
16
+ var EmailError = class extends Error {
17
+ constructor(message, code, cause) {
18
+ super(message);
19
+ this.code = code;
20
+ this.cause = cause;
21
+ this.name = "EmailError";
22
+ }
23
+ };
24
+ var EmailErrorCodes = {
25
+ INVALID_CONFIG: "INVALID_CONFIG",
26
+ INVALID_RECIPIENT: "INVALID_RECIPIENT",
27
+ INVALID_CONTENT: "INVALID_CONTENT",
28
+ SEND_FAILED: "SEND_FAILED",
29
+ RATE_LIMITED: "RATE_LIMITED",
30
+ PROVIDER_ERROR: "PROVIDER_ERROR",
31
+ TEMPLATE_ERROR: "TEMPLATE_ERROR",
32
+ ATTACHMENT_ERROR: "ATTACHMENT_ERROR"
33
+ };
34
+
35
+ // src/providers/sendgrid.ts
36
+ var SendGridProvider = class {
37
+ type = "sendgrid";
38
+ apiKey;
39
+ fromEmail;
40
+ fromName;
41
+ baseUrl = "https://api.sendgrid.com/v3";
42
+ constructor(config) {
43
+ this.apiKey = config.apiKey;
44
+ this.fromEmail = config.fromEmail;
45
+ this.fromName = config.fromName;
46
+ }
47
+ formatAddress(address) {
48
+ if (typeof address === "string") {
49
+ return { email: address };
50
+ }
51
+ return address.name ? { email: address.email, name: address.name } : { email: address.email };
52
+ }
53
+ formatAddresses(addresses) {
54
+ if (Array.isArray(addresses)) {
55
+ return addresses.map((a) => this.formatAddress(a));
56
+ }
57
+ return [this.formatAddress(addresses)];
58
+ }
59
+ async send(options) {
60
+ const from = options.from ? this.formatAddress(options.from) : this.fromName ? { email: this.fromEmail, name: this.fromName } : { email: this.fromEmail };
61
+ const personalization = {
62
+ to: this.formatAddresses(options.to)
63
+ };
64
+ if (options.cc) {
65
+ personalization.cc = this.formatAddresses(options.cc);
66
+ }
67
+ if (options.bcc) {
68
+ personalization.bcc = this.formatAddresses(options.bcc);
69
+ }
70
+ if (options.headers) {
71
+ personalization.headers = options.headers;
72
+ }
73
+ const payload = {
74
+ personalizations: [personalization],
75
+ from,
76
+ subject: options.subject,
77
+ content: []
78
+ };
79
+ const content = [];
80
+ if (options.text) {
81
+ content.push({ type: "text/plain", value: options.text });
82
+ }
83
+ if (options.html) {
84
+ content.push({ type: "text/html", value: options.html });
85
+ }
86
+ payload["content"] = content;
87
+ if (options.replyTo) {
88
+ payload["reply_to"] = this.formatAddress(options.replyTo);
89
+ }
90
+ if (options.attachments && options.attachments.length > 0) {
91
+ payload["attachments"] = options.attachments.map((att) => ({
92
+ filename: att.filename,
93
+ content: typeof att.content === "string" ? att.content : this.uint8ArrayToBase64(att.content),
94
+ type: att.contentType,
95
+ content_id: att.contentId,
96
+ disposition: att.contentId ? "inline" : "attachment"
97
+ }));
98
+ }
99
+ if (options.scheduledAt) {
100
+ payload["send_at"] = Math.floor(options.scheduledAt.getTime() / 1e3);
101
+ }
102
+ try {
103
+ const response = await fetch(`${this.baseUrl}/mail/send`, {
104
+ method: "POST",
105
+ headers: {
106
+ "Authorization": `Bearer ${this.apiKey}`,
107
+ "Content-Type": "application/json"
108
+ },
109
+ body: JSON.stringify(payload)
110
+ });
111
+ if (response.status === 202) {
112
+ const messageId = response.headers.get("x-message-id");
113
+ return {
114
+ success: true,
115
+ messageId: messageId ?? void 0
116
+ };
117
+ }
118
+ const data = await response.json().catch(() => ({}));
119
+ const errorMessage = data.errors?.[0]?.message || `HTTP ${response.status}`;
120
+ return {
121
+ success: false,
122
+ error: errorMessage,
123
+ data
124
+ };
125
+ } catch (err) {
126
+ throw new EmailError(
127
+ `SendGrid send failed: ${err instanceof Error ? err.message : "Unknown error"}`,
128
+ EmailErrorCodes.SEND_FAILED,
129
+ err
130
+ );
131
+ }
132
+ }
133
+ async sendBatch(options) {
134
+ const results = [];
135
+ let successful = 0;
136
+ let failed = 0;
137
+ for (const email of options.emails) {
138
+ try {
139
+ const result = await this.send(email);
140
+ results.push(result);
141
+ if (result.success) {
142
+ successful++;
143
+ } else {
144
+ failed++;
145
+ if (options.stopOnError) break;
146
+ }
147
+ } catch (err) {
148
+ failed++;
149
+ results.push({
150
+ success: false,
151
+ error: err instanceof Error ? err.message : "Unknown error"
152
+ });
153
+ if (options.stopOnError) break;
154
+ }
155
+ }
156
+ return {
157
+ total: options.emails.length,
158
+ successful,
159
+ failed,
160
+ results
161
+ };
162
+ }
163
+ async verify() {
164
+ try {
165
+ const response = await fetch(`${this.baseUrl}/scopes`, {
166
+ headers: {
167
+ "Authorization": `Bearer ${this.apiKey}`
168
+ }
169
+ });
170
+ return response.ok;
171
+ } catch {
172
+ return false;
173
+ }
174
+ }
175
+ uint8ArrayToBase64(data) {
176
+ let binary = "";
177
+ for (let i = 0; i < data.length; i++) {
178
+ const byte = data[i];
179
+ if (byte !== void 0) {
180
+ binary += String.fromCharCode(byte);
181
+ }
182
+ }
183
+ return btoa(binary);
184
+ }
185
+ };
186
+ function createSendGridProvider(config) {
187
+ return new SendGridProvider(config);
188
+ }
189
+ export {
190
+ SendGridProvider,
191
+ createSendGridProvider
192
+ };
193
+ //# sourceMappingURL=sendgrid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types.ts","../../src/providers/sendgrid.ts"],"sourcesContent":["/**\n * @parsrun/email - Type Definitions\n * Email types and interfaces\n */\n\n// Re-export types from @parsrun/types for convenience\nexport {\n type,\n emailAddress,\n emailAttachment,\n sendEmailOptions,\n sendTemplateEmailOptions,\n emailSendResult,\n smtpConfig,\n resendConfig,\n sendgridConfig,\n sesConfig,\n postmarkConfig,\n emailConfig,\n type EmailAddress as ParsEmailAddress,\n type EmailAttachment as ParsEmailAttachment,\n type SendEmailOptions,\n type SendTemplateEmailOptions,\n type EmailSendResult,\n type SmtpConfig,\n type ResendConfig,\n type SendgridConfig,\n type SesConfig,\n type PostmarkConfig,\n type EmailConfig,\n} from \"@parsrun/types\";\n\n/**\n * Email provider type\n */\nexport type EmailProviderType = \"resend\" | \"sendgrid\" | \"postmark\" | \"ses\" | \"console\" | \"mailgun\";\n\n/**\n * Email address with optional name\n */\nexport interface EmailAddress {\n email: string;\n name?: string | undefined;\n}\n\n/**\n * Email attachment\n */\nexport interface EmailAttachment {\n /** File name */\n filename: string;\n /** File content (base64 encoded or Buffer) */\n content: string | Uint8Array;\n /** Content type (MIME type) */\n contentType?: string | undefined;\n /** Content ID for inline attachments */\n contentId?: string | undefined;\n}\n\n/**\n * Email options\n */\nexport interface EmailOptions {\n /** Recipient email address(es) */\n to: string | string[] | EmailAddress | EmailAddress[];\n /** Email subject */\n subject: string;\n /** HTML content */\n html?: string | undefined;\n /** Plain text content */\n text?: string | undefined;\n /** From address (overrides default) */\n from?: string | EmailAddress | undefined;\n /** Reply-to address */\n replyTo?: string | EmailAddress | undefined;\n /** CC recipients */\n cc?: string | string[] | EmailAddress | EmailAddress[] | undefined;\n /** BCC recipients */\n bcc?: string | string[] | EmailAddress | EmailAddress[] | undefined;\n /** Attachments */\n attachments?: EmailAttachment[] | undefined;\n /** Custom headers */\n headers?: Record<string, string> | undefined;\n /** Tags for tracking */\n tags?: Record<string, string> | undefined;\n /** Schedule send time */\n scheduledAt?: Date | undefined;\n}\n\n/**\n * Email send result\n */\nexport interface EmailResult {\n /** Whether send was successful */\n success: boolean;\n /** Message ID from provider */\n messageId?: string | undefined;\n /** Error message if failed */\n error?: string | undefined;\n /** Provider-specific response data */\n data?: unknown;\n}\n\n/**\n * Batch email options\n */\nexport interface BatchEmailOptions {\n /** List of emails to send */\n emails: EmailOptions[];\n /** Whether to stop on first error */\n stopOnError?: boolean | undefined;\n}\n\n/**\n * Batch email result\n */\nexport interface BatchEmailResult {\n /** Total emails attempted */\n total: number;\n /** Successful sends */\n successful: number;\n /** Failed sends */\n failed: number;\n /** Individual results */\n results: EmailResult[];\n}\n\n/**\n * Email provider configuration\n */\nexport interface EmailProviderConfig {\n /** API key for the provider */\n apiKey: string;\n /** Default from email */\n fromEmail: string;\n /** Default from name */\n fromName?: string | undefined;\n /** Provider-specific options */\n options?: Record<string, unknown> | undefined;\n}\n\n/**\n * Email provider interface\n */\nexport interface EmailProvider {\n /** Provider type */\n readonly type: EmailProviderType;\n\n /**\n * Send a single email\n */\n send(options: EmailOptions): Promise<EmailResult>;\n\n /**\n * Send multiple emails\n */\n sendBatch?(options: BatchEmailOptions): Promise<BatchEmailResult>;\n\n /**\n * Verify provider configuration\n */\n verify?(): Promise<boolean>;\n}\n\n/**\n * Email service configuration\n */\nexport interface EmailServiceConfig {\n /** Provider type */\n provider: EmailProviderType;\n /** API key */\n apiKey: string;\n /** Default from email */\n fromEmail: string;\n /** Default from name */\n fromName?: string | undefined;\n /** Enable debug logging */\n debug?: boolean | undefined;\n /** Provider-specific options */\n providerOptions?: Record<string, unknown> | undefined;\n}\n\n/**\n * Template data for email templates\n */\nexport interface TemplateData {\n [key: string]: string | number | boolean | undefined | null | TemplateData | TemplateData[];\n}\n\n/**\n * Email template\n */\nexport interface EmailTemplate {\n /** Template name */\n name: string;\n /** Subject template */\n subject: string;\n /** HTML template */\n html: string;\n /** Plain text template */\n text?: string | undefined;\n}\n\n/**\n * Email error\n */\nexport class EmailError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly cause?: unknown\n ) {\n super(message);\n this.name = \"EmailError\";\n }\n}\n\n/**\n * Common email error codes\n */\nexport const EmailErrorCodes = {\n INVALID_CONFIG: \"INVALID_CONFIG\",\n INVALID_RECIPIENT: \"INVALID_RECIPIENT\",\n INVALID_CONTENT: \"INVALID_CONTENT\",\n SEND_FAILED: \"SEND_FAILED\",\n RATE_LIMITED: \"RATE_LIMITED\",\n PROVIDER_ERROR: \"PROVIDER_ERROR\",\n TEMPLATE_ERROR: \"TEMPLATE_ERROR\",\n ATTACHMENT_ERROR: \"ATTACHMENT_ERROR\",\n} as const;\n","/**\n * @parsrun/email - SendGrid Provider\n * Edge-compatible SendGrid email provider\n */\n\nimport type {\n BatchEmailOptions,\n BatchEmailResult,\n EmailAddress,\n EmailOptions,\n EmailProvider,\n EmailProviderConfig,\n EmailResult,\n} from \"../types.js\";\nimport { EmailError, EmailErrorCodes } from \"../types.js\";\n\n/**\n * SendGrid Email Provider\n * Uses fetch API for edge compatibility\n *\n * @example\n * ```typescript\n * const sendgrid = new SendGridProvider({\n * apiKey: process.env.SENDGRID_API_KEY,\n * fromEmail: 'hello@example.com',\n * fromName: 'My App',\n * });\n *\n * await sendgrid.send({\n * to: 'user@example.com',\n * subject: 'Hello',\n * html: '<p>Hello World!</p>',\n * });\n * ```\n */\nexport class SendGridProvider implements EmailProvider {\n readonly type = \"sendgrid\" as const;\n\n private apiKey: string;\n private fromEmail: string;\n private fromName: string | undefined;\n private baseUrl = \"https://api.sendgrid.com/v3\";\n\n constructor(config: EmailProviderConfig) {\n this.apiKey = config.apiKey;\n this.fromEmail = config.fromEmail;\n this.fromName = config.fromName;\n }\n\n private formatAddress(address: string | EmailAddress): { email: string; name?: string | undefined } {\n if (typeof address === \"string\") {\n return { email: address };\n }\n return address.name ? { email: address.email, name: address.name } : { email: address.email };\n }\n\n private formatAddresses(\n addresses: string | string[] | EmailAddress | EmailAddress[]\n ): Array<{ email: string; name?: string | undefined }> {\n if (Array.isArray(addresses)) {\n return addresses.map((a) => this.formatAddress(a));\n }\n return [this.formatAddress(addresses)];\n }\n\n async send(options: EmailOptions): Promise<EmailResult> {\n const from = options.from\n ? this.formatAddress(options.from)\n : this.fromName\n ? { email: this.fromEmail, name: this.fromName }\n : { email: this.fromEmail };\n\n const personalization: {\n to: Array<{ email: string; name?: string | undefined }>;\n cc?: Array<{ email: string; name?: string | undefined }> | undefined;\n bcc?: Array<{ email: string; name?: string | undefined }> | undefined;\n headers?: Record<string, string> | undefined;\n } = {\n to: this.formatAddresses(options.to),\n };\n\n if (options.cc) {\n personalization.cc = this.formatAddresses(options.cc);\n }\n if (options.bcc) {\n personalization.bcc = this.formatAddresses(options.bcc);\n }\n if (options.headers) {\n personalization.headers = options.headers;\n }\n\n const payload: Record<string, unknown> = {\n personalizations: [personalization],\n from,\n subject: options.subject,\n content: [],\n };\n\n const content: Array<{ type: string; value: string }> = [];\n if (options.text) {\n content.push({ type: \"text/plain\", value: options.text });\n }\n if (options.html) {\n content.push({ type: \"text/html\", value: options.html });\n }\n payload[\"content\"] = content;\n\n if (options.replyTo) {\n payload[\"reply_to\"] = this.formatAddress(options.replyTo);\n }\n\n if (options.attachments && options.attachments.length > 0) {\n payload[\"attachments\"] = options.attachments.map((att) => ({\n filename: att.filename,\n content: typeof att.content === \"string\"\n ? att.content\n : this.uint8ArrayToBase64(att.content),\n type: att.contentType,\n content_id: att.contentId,\n disposition: att.contentId ? \"inline\" : \"attachment\",\n }));\n }\n\n if (options.scheduledAt) {\n payload[\"send_at\"] = Math.floor(options.scheduledAt.getTime() / 1000);\n }\n\n try {\n const response = await fetch(`${this.baseUrl}/mail/send`, {\n method: \"POST\",\n headers: {\n \"Authorization\": `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n });\n\n // SendGrid returns 202 for success with no body\n if (response.status === 202) {\n const messageId = response.headers.get(\"x-message-id\");\n return {\n success: true,\n messageId: messageId ?? undefined,\n };\n }\n\n const data = await response.json().catch(() => ({})) as { errors?: Array<{ message: string }> };\n const errorMessage = data.errors?.[0]?.message || `HTTP ${response.status}`;\n\n return {\n success: false,\n error: errorMessage,\n data,\n };\n } catch (err) {\n throw new EmailError(\n `SendGrid send failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n EmailErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n async sendBatch(options: BatchEmailOptions): Promise<BatchEmailResult> {\n const results: EmailResult[] = [];\n let successful = 0;\n let failed = 0;\n\n for (const email of options.emails) {\n try {\n const result = await this.send(email);\n results.push(result);\n\n if (result.success) {\n successful++;\n } else {\n failed++;\n if (options.stopOnError) break;\n }\n } catch (err) {\n failed++;\n results.push({\n success: false,\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n\n if (options.stopOnError) break;\n }\n }\n\n return {\n total: options.emails.length,\n successful,\n failed,\n results,\n };\n }\n\n async verify(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/scopes`, {\n headers: {\n \"Authorization\": `Bearer ${this.apiKey}`,\n },\n });\n\n return response.ok;\n } catch {\n return false;\n }\n }\n\n private uint8ArrayToBase64(data: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < data.length; i++) {\n const byte = data[i];\n if (byte !== undefined) {\n binary += String.fromCharCode(byte);\n }\n }\n return btoa(binary);\n }\n}\n\n/**\n * Create a SendGrid provider\n */\nexport function createSendGridProvider(config: EmailProviderConfig): SendGridProvider {\n return new SendGridProvider(config);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,114 @@
1
+ import { TemplateData, EmailTemplate } from '../types.js';
2
+ import '@parsrun/types';
3
+
4
+ /**
5
+ * @parsrun/email - Email Templates
6
+ * Pre-built templates for common email use cases
7
+ */
8
+
9
+ /**
10
+ * Simple template engine - replaces {{key}} with values
11
+ */
12
+ declare function renderTemplate(template: string, data: TemplateData): string;
13
+ /**
14
+ * Base email wrapper with consistent styling
15
+ */
16
+ declare function wrapEmailHtml(content: string, options?: {
17
+ brandName?: string | undefined;
18
+ brandColor?: string | undefined;
19
+ footerText?: string | undefined;
20
+ }): string;
21
+ interface OTPTemplateData extends TemplateData {
22
+ code: string;
23
+ expiresInMinutes?: number;
24
+ brandName?: string;
25
+ brandColor?: string;
26
+ }
27
+ declare const otpTemplate: EmailTemplate;
28
+ declare function renderOTPEmail(data: OTPTemplateData): {
29
+ subject: string;
30
+ html: string;
31
+ text: string;
32
+ };
33
+ interface MagicLinkTemplateData extends TemplateData {
34
+ url: string;
35
+ expiresInMinutes?: number;
36
+ brandName?: string;
37
+ brandColor?: string;
38
+ }
39
+ declare const magicLinkTemplate: EmailTemplate;
40
+ declare function renderMagicLinkEmail(data: MagicLinkTemplateData): {
41
+ subject: string;
42
+ html: string;
43
+ text: string;
44
+ };
45
+ interface VerificationTemplateData extends TemplateData {
46
+ url: string;
47
+ name?: string;
48
+ expiresInHours?: number;
49
+ brandName?: string;
50
+ brandColor?: string;
51
+ }
52
+ declare const verificationTemplate: EmailTemplate;
53
+ declare function renderVerificationEmail(data: VerificationTemplateData): {
54
+ subject: string;
55
+ html: string;
56
+ text: string;
57
+ };
58
+ interface WelcomeTemplateData extends TemplateData {
59
+ name?: string;
60
+ loginUrl?: string;
61
+ brandName?: string;
62
+ brandColor?: string;
63
+ }
64
+ declare const welcomeTemplate: EmailTemplate;
65
+ declare function renderWelcomeEmail(data: WelcomeTemplateData): {
66
+ subject: string;
67
+ html: string;
68
+ text: string;
69
+ };
70
+ interface PasswordResetTemplateData extends TemplateData {
71
+ url: string;
72
+ expiresInMinutes?: number;
73
+ brandName?: string;
74
+ brandColor?: string;
75
+ }
76
+ declare const passwordResetTemplate: EmailTemplate;
77
+ declare function renderPasswordResetEmail(data: PasswordResetTemplateData): {
78
+ subject: string;
79
+ html: string;
80
+ text: string;
81
+ };
82
+ interface InvitationTemplateData extends TemplateData {
83
+ url: string;
84
+ inviterName?: string;
85
+ organizationName?: string;
86
+ role?: string;
87
+ expiresInDays?: number;
88
+ brandName?: string;
89
+ brandColor?: string;
90
+ }
91
+ declare const invitationTemplate: EmailTemplate;
92
+ declare function renderInvitationEmail(data: InvitationTemplateData): {
93
+ subject: string;
94
+ html: string;
95
+ text: string;
96
+ };
97
+ declare const templates: {
98
+ readonly otp: EmailTemplate;
99
+ readonly magicLink: EmailTemplate;
100
+ readonly verification: EmailTemplate;
101
+ readonly welcome: EmailTemplate;
102
+ readonly passwordReset: EmailTemplate;
103
+ readonly invitation: EmailTemplate;
104
+ };
105
+ declare const renderFunctions: {
106
+ readonly otp: typeof renderOTPEmail;
107
+ readonly magicLink: typeof renderMagicLinkEmail;
108
+ readonly verification: typeof renderVerificationEmail;
109
+ readonly welcome: typeof renderWelcomeEmail;
110
+ readonly passwordReset: typeof renderPasswordResetEmail;
111
+ readonly invitation: typeof renderInvitationEmail;
112
+ };
113
+
114
+ export { type InvitationTemplateData, type MagicLinkTemplateData, type OTPTemplateData, type PasswordResetTemplateData, type VerificationTemplateData, type WelcomeTemplateData, invitationTemplate, magicLinkTemplate, otpTemplate, passwordResetTemplate, renderFunctions, renderInvitationEmail, renderMagicLinkEmail, renderOTPEmail, renderPasswordResetEmail, renderTemplate, renderVerificationEmail, renderWelcomeEmail, templates, verificationTemplate, welcomeTemplate, wrapEmailHtml };