feat: Implement dual email sending for contact form submissions, including a customer confirmation and internal notification, by refactoring email rendering to accept pre-rendered HTML.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import client, { ensureAuthenticated } from '@/lib/directus';
|
||||
import { createItem } from '@directus/sdk';
|
||||
import { sendEmail } from '@/lib/mail/mailer';
|
||||
import ContactEmail from '@/components/emails/ContactEmail';
|
||||
import { render, ContactFormNotification, ConfirmationMessage } from '@mintel/mail';
|
||||
import React from 'react';
|
||||
import { getServerAppServices } from '@/lib/services/create-services.server';
|
||||
|
||||
@@ -51,38 +51,73 @@ export async function sendContactFormAction(formData: FormData) {
|
||||
services.errors.captureException(error, { action: 'directus_store_submission' });
|
||||
}
|
||||
|
||||
// 2. Send Email
|
||||
logger.info('Sending contact form email', { email, productName });
|
||||
// 2. Send Emails
|
||||
logger.info('Sending branded emails', { email, productName });
|
||||
|
||||
const subject = productName ? `Product Inquiry: ${productName}` : 'New Contact Form Submission';
|
||||
const notificationSubject = productName
|
||||
? `Product Inquiry: ${productName}`
|
||||
: 'New Contact Form Submission';
|
||||
const confirmationSubject = 'Thank you for your inquiry';
|
||||
|
||||
const result = await sendEmail({
|
||||
subject,
|
||||
template: React.createElement(ContactEmail, {
|
||||
name,
|
||||
email,
|
||||
message,
|
||||
productName: productName || undefined,
|
||||
subject,
|
||||
}),
|
||||
});
|
||||
try {
|
||||
// 2a. Send notification to Mintel/Client
|
||||
const notificationHtml = await render(
|
||||
React.createElement(ContactFormNotification, {
|
||||
name,
|
||||
email,
|
||||
message,
|
||||
productName: productName || undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
logger.info('Contact form email sent successfully', { messageId: result.messageId });
|
||||
const notificationResult = await sendEmail({
|
||||
subject: notificationSubject,
|
||||
html: notificationHtml,
|
||||
});
|
||||
|
||||
if (notificationResult.success) {
|
||||
logger.info('Notification email sent successfully', {
|
||||
messageId: notificationResult.messageId,
|
||||
});
|
||||
}
|
||||
|
||||
// 2b. Send confirmation to Customer (branded as KLZ Cables)
|
||||
const confirmationHtml = await render(
|
||||
React.createElement(ConfirmationMessage, {
|
||||
name,
|
||||
clientName: 'KLZ Cables',
|
||||
// brandColor: '#82ed20', // Optional: could be KLZ specific
|
||||
}),
|
||||
);
|
||||
|
||||
const confirmationResult = await sendEmail({
|
||||
to: email,
|
||||
subject: confirmationSubject,
|
||||
html: confirmationHtml,
|
||||
});
|
||||
|
||||
if (confirmationResult.success) {
|
||||
logger.info('Confirmation email sent successfully', {
|
||||
messageId: confirmationResult.messageId,
|
||||
});
|
||||
}
|
||||
|
||||
// Notify via Gotify (Internal)
|
||||
await services.notifications.notify({
|
||||
title: `📩 ${subject}`,
|
||||
title: `📩 ${notificationSubject}`,
|
||||
message: `New message from ${name} (${email}):\n\n${message}`,
|
||||
priority: 5,
|
||||
});
|
||||
} else {
|
||||
logger.error('Failed to send contact form email', { error: result.error });
|
||||
services.errors.captureException(result.error, { action: 'sendContactFormAction', email });
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
logger.error('Failed to send branded emails', { error });
|
||||
services.errors.captureException(error, { action: 'sendContactFormAction', email });
|
||||
await services.notifications.notify({
|
||||
title: '🚨 Contact Form Error',
|
||||
message: `Failed to send email for ${name} (${email}). Error: ${JSON.stringify(result.error)}`,
|
||||
message: `Failed to send emails for ${name} (${email}). Error: ${JSON.stringify(error)}`,
|
||||
priority: 8,
|
||||
});
|
||||
return { success: false, error };
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import nodemailer from "nodemailer";
|
||||
import { render } from "@react-email/components";
|
||||
import { ReactElement } from "react";
|
||||
import { getServerAppServices } from "@/lib/services/create-services.server";
|
||||
import { config } from "../config";
|
||||
import nodemailer from 'nodemailer';
|
||||
import { getServerAppServices } from '@/lib/services/create-services.server';
|
||||
import { config } from '../config';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: config.mail.host,
|
||||
@@ -17,12 +16,10 @@ const transporter = nodemailer.createTransport({
|
||||
interface SendEmailOptions {
|
||||
to?: string | string[];
|
||||
subject: string;
|
||||
template: ReactElement;
|
||||
html: string;
|
||||
}
|
||||
|
||||
export async function sendEmail({ to, subject, template }: SendEmailOptions) {
|
||||
const html = await render(template);
|
||||
|
||||
export async function sendEmail({ to, subject, html }: SendEmailOptions) {
|
||||
const recipients = to || config.mail.recipients;
|
||||
|
||||
const mailOptions = {
|
||||
@@ -36,10 +33,10 @@ export async function sendEmail({ to, subject, template }: SendEmailOptions) {
|
||||
|
||||
try {
|
||||
const info = await transporter.sendMail(mailOptions);
|
||||
logger.info("Email sent successfully", { messageId: info.messageId, subject, recipients });
|
||||
logger.info('Email sent successfully', { messageId: info.messageId, subject, recipients });
|
||||
return { success: true, messageId: info.messageId };
|
||||
} catch (error) {
|
||||
logger.error("Error sending email", { error, subject, recipients });
|
||||
logger.error('Error sending email', { error, subject, recipients });
|
||||
return { success: false, error };
|
||||
}
|
||||
}
|
||||
|
||||
366
package-lock.json
generated
366
package-lock.json
generated
@@ -9,6 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@directus/sdk": "^18.0.3",
|
||||
"@mintel/mail": "^1.2.0",
|
||||
"@react-email/components": "^1.0.6",
|
||||
"@react-pdf/renderer": "^4.3.2",
|
||||
"@sentry/nextjs": "^8.55.0",
|
||||
@@ -3137,6 +3138,347 @@
|
||||
"react": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://npm.infra.mintel.me/@mintel/mail/-/mail-1.2.2.tgz",
|
||||
"integrity": "sha512-lusy3VKpuI7XfZLUkEuW5VHPKjsGTX7FWFGXvFgs/80eUTTL14HyqsiV778lIKX16Yi6yBH5g64EBvcvXZfbpQ==",
|
||||
"dependencies": {
|
||||
"@react-email/components": "^0.0.33",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/body": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.11.tgz",
|
||||
"integrity": "sha512-ZSD2SxVSgUjHGrB0Wi+4tu3MEpB4fYSbezsFNEJk2xCWDBkFiOeEsjTmR5dvi+CxTK691hQTQlHv0XWuP7ENTg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/button": {
|
||||
"version": "0.0.19",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.19.tgz",
|
||||
"integrity": "sha512-HYHrhyVGt7rdM/ls6FuuD6XE7fa7bjZTJqB2byn6/oGsfiEZaogY77OtoLL/mrQHjHjZiJadtAMSik9XLcm7+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/code-block": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.11.tgz",
|
||||
"integrity": "sha512-4D43p+LIMjDzm66gTDrZch0Flkip5je91mAT7iGs6+SbPyalHgIA+lFQoQwhz/VzHHLxuD0LV6gwmU/WUQ2WEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prismjs": "1.29.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/code-inline": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/code-inline/-/code-inline-0.0.5.tgz",
|
||||
"integrity": "sha512-MmAsOzdJpzsnY2cZoPHFPk6uDO/Ncpb4Kh1hAt9UZc1xOW3fIzpe1Pi9y9p6wwUmpaeeDalJxAxH6/fnTquinA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/column": {
|
||||
"version": "0.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.13.tgz",
|
||||
"integrity": "sha512-Lqq17l7ShzJG/d3b1w/+lVO+gp2FM05ZUo/nW0rjxB8xBICXOVv6PqjDnn3FXKssvhO5qAV20lHM6S+spRhEwQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/components": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.33.tgz",
|
||||
"integrity": "sha512-/GKdT3YijT1iEWPAXF644jr12w5xVgzUr0zlbZGt2KOkGeFHNZUCL5UtRopmnjrH/Fayf8Gjv6q/4E2cZgDtdQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@react-email/body": "0.0.11",
|
||||
"@react-email/button": "0.0.19",
|
||||
"@react-email/code-block": "0.0.11",
|
||||
"@react-email/code-inline": "0.0.5",
|
||||
"@react-email/column": "0.0.13",
|
||||
"@react-email/container": "0.0.15",
|
||||
"@react-email/font": "0.0.9",
|
||||
"@react-email/head": "0.0.12",
|
||||
"@react-email/heading": "0.0.15",
|
||||
"@react-email/hr": "0.0.11",
|
||||
"@react-email/html": "0.0.11",
|
||||
"@react-email/img": "0.0.11",
|
||||
"@react-email/link": "0.0.12",
|
||||
"@react-email/markdown": "0.0.14",
|
||||
"@react-email/preview": "0.0.12",
|
||||
"@react-email/render": "1.0.5",
|
||||
"@react-email/row": "0.0.12",
|
||||
"@react-email/section": "0.0.16",
|
||||
"@react-email/tailwind": "1.0.4",
|
||||
"@react-email/text": "0.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/container": {
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.15.tgz",
|
||||
"integrity": "sha512-Qo2IQo0ru2kZq47REmHW3iXjAQaKu4tpeq/M8m1zHIVwKduL2vYOBQWbC2oDnMtWPmkBjej6XxgtZByxM6cCFg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/font": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.9.tgz",
|
||||
"integrity": "sha512-4zjq23oT9APXkerqeslPH3OZWuh5X4crHK6nx82mVHV2SrLba8+8dPEnWbaACWTNjOCbcLIzaC9unk7Wq2MIXw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/head": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.12.tgz",
|
||||
"integrity": "sha512-X2Ii6dDFMF+D4niNwMAHbTkeCjlYYnMsd7edXOsi0JByxt9wNyZ9EnhFiBoQdqkE+SMDcu8TlNNttMrf5sJeMA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/heading": {
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.15.tgz",
|
||||
"integrity": "sha512-xF2GqsvBrp/HbRHWEfOgSfRFX+Q8I5KBEIG5+Lv3Vb2R/NYr0s8A5JhHHGf2pWBMJdbP4B2WHgj/VUrhy8dkIg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/hr": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.11.tgz",
|
||||
"integrity": "sha512-S1gZHVhwOsd1Iad5IFhpfICwNPMGPJidG/Uysy1AwmspyoAP5a4Iw3OWEpINFdgh9MHladbxcLKO2AJO+cA9Lw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/html": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.11.tgz",
|
||||
"integrity": "sha512-qJhbOQy5VW5qzU74AimjAR9FRFQfrMa7dn4gkEXKMB/S9xZN8e1yC1uA9C15jkXI/PzmJ0muDIWmFwatm5/+VA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/img": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.11.tgz",
|
||||
"integrity": "sha512-aGc8Y6U5C3igoMaqAJKsCpkbm1XjguQ09Acd+YcTKwjnC2+0w3yGUJkjWB2vTx4tN8dCqQCXO8FmdJpMfOA9EQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/link": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.12.tgz",
|
||||
"integrity": "sha512-vF+xxQk2fGS1CN7UPQDbzvcBGfffr+GjTPNiWM38fhBfsLv6A/YUfaqxWlmL7zLzVmo0K2cvvV9wxlSyNba1aQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/markdown": {
|
||||
"version": "0.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.14.tgz",
|
||||
"integrity": "sha512-5IsobCyPkb4XwnQO8uFfGcNOxnsg3311GRXhJ3uKv51P7Jxme4ycC/MITnwIZ10w2zx7HIyTiqVzTj4XbuIHbg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"md-to-react-email": "5.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/preview": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.12.tgz",
|
||||
"integrity": "sha512-g/H5fa9PQPDK6WUEG7iTlC19sAktI23qyoiJtMLqQiXFCfWeQMhqjLGKeLSKkfzszqmfJCjZtpSiKtBoOdxp3Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/render": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/render/-/render-1.0.5.tgz",
|
||||
"integrity": "sha512-CA69HYXPk21HhtAXATIr+9JJwpDNmAFCvdMUjWmeoD1+KhJ9NAxusMRxKNeibdZdslmq3edaeOKGbdQ9qjK8LQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"html-to-text": "9.0.5",
|
||||
"prettier": "3.4.2",
|
||||
"react-promise-suspense": "0.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/row": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.12.tgz",
|
||||
"integrity": "sha512-HkCdnEjvK3o+n0y0tZKXYhIXUNPDx+2vq1dJTmqappVHXS5tXS6W5JOPZr5j+eoZ8gY3PShI2LWj5rWF7ZEtIQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/section": {
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.16.tgz",
|
||||
"integrity": "sha512-FjqF9xQ8FoeUZYKSdt8sMIKvoT9XF8BrzhT3xiFKdEMwYNbsDflcjfErJe3jb7Wj/es/lKTbV5QR1dnLzGpL3w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/tailwind": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-1.0.4.tgz",
|
||||
"integrity": "sha512-tJdcusncdqgvTUYZIuhNC6LYTfL9vNTSQpwWdTCQhQ1lsrNCEE4OKCSdzSV3S9F32pi0i0xQ+YPJHKIzGjdTSA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/@react-email/text": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.11.tgz",
|
||||
"integrity": "sha512-a7nl/2KLpRHOYx75YbYZpWspUbX1DFY7JIZbOv5x0QU8SvwDbJt+Hm01vG34PffFyYvHEXrc6Qnip2RTjljNjg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/prettier": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
|
||||
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/prismjs": {
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
|
||||
"integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/react": {
|
||||
"version": "19.2.4",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
||||
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/react-dom": {
|
||||
"version": "19.2.4",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
|
||||
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@mintel/mail/node_modules/scheduler": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
|
||||
@@ -15823,6 +16165,30 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/md-to-react-email": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/md-to-react-email/-/md-to-react-email-5.0.5.tgz",
|
||||
"integrity": "sha512-OvAXqwq57uOk+WZqFFNCMZz8yDp8BD3WazW1wAKHUrPbbdr89K9DWS6JXY09vd9xNdPNeurI8DU/X4flcfaD8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"marked": "7.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0 || ^19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/md-to-react-email/node_modules/marked": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-7.0.4.tgz",
|
||||
"integrity": "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-from-markdown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@directus/sdk": "^18.0.3",
|
||||
"@mintel/mail": "^1.2.0",
|
||||
"@react-email/components": "^1.0.6",
|
||||
"@react-pdf/renderer": "^4.3.2",
|
||||
"@sentry/nextjs": "^8.55.0",
|
||||
|
||||
Reference in New Issue
Block a user