atalay
atalay4d ago

Using Resend with Convex getting error

"use node";

import { v } from "convex/values";
import { mutation } from "./_generated/server";
import { nanoid } from "nanoid";
import { Resend } from "resend";
import { VerificationEmail } from "../emails/verification-email";
import { ConfirmationEmail } from "../emails/confirmation-email";
import { TeamNotificationEmail } from "../emails/team-notification-email";

const TOKEN_EXPIRY = 5 * 60 * 1000; // 5 dakika

export const submitApplication = mutation({
args: {
email: v.string(),
name: v.string(),
experience: v.string(),
whyYou: v.string(),
resendApiKey: v.string(),
websiteUrl: v.string(),
},
handler: async (ctx, args) => {
const now = Date.now();
const verificationToken = nanoid(32);
const tokenExpiry = now + TOKEN_EXPIRY;

// Başvuruyu kaydet
const applicationId = await ctx.db.insert("testerApplications", {
email: args.email,
name: args.name,
experience: args.experience,
whyYou: args.whyYou,
status: "pending",
verificationToken,
tokenExpiry,
createdAt: now,
lastAttempt: now,
});

// Resend client'ı oluştur
const resend = new Resend(args.resendApiKey);
const verificationUrl = `${args.websiteUrl}/verify?token=${verificationToken}`;

// Doğrulama emaili gönder
await resend.emails.send({
from: "Lamron Studio <support@lamronstudio.com>",
to: [args.email],
subject: "Email Adresinizi Doğrulayın",
react: VerificationEmail({ name: args.name, verificationUrl }),
});

return { success: true, applicationId };
},
});

export const verifyApplication = mutation({
args: {
token: v.string(),
resendApiKey: v.string(),
},
handler: async (ctx, args) => {
const now = Date.now();

const application = await ctx.db
.query("testerApplications")
.filter((q) => q.eq(q.field("verificationToken"), args.token))
.first();

if (!application) {
throw new Error("Geçersiz doğrulama kodu");
}

if (application.tokenExpiry < now) {
await ctx.db.patch(application._id, { status: "expired" });
throw new Error("Doğrulama kodunun süresi dolmuş");
}

if (application.status !== "pending") {
throw new Error("Başvuru doğrulama beklemede değil");
}

// Başvuruyu onayla
await ctx.db.patch(application._id, { status: "verified" });

// Resend client'ı oluştur
const resend = new Resend(args.resendApiKey);

// Onay emaili gönder
await resend.emails.send({
from: "Lamron Studio <support@lamronstudio.com>",
to: application.email,
subject: "Lamron Studio Test Ekibine Hoş Geldiniz!",
react: ConfirmationEmail({ name: application.name, email: application.email }),
});

// Yöneticiye bildirim emaili gönder
await resend.emails.send({
from: "Lamron Studio <support@lamronstudio.com>",
to: "atalay.gov@gmail.com",
subject: `Yeni Test Ekibi Başvurusu: ${application.name}`,
react: TeamNotificationEmail({
name: application.name,
email: application.email,
experience: application.experience,
whyYou: application.whyYou
}),
});

return { success: true };
},
});
"use node";

import { v } from "convex/values";
import { mutation } from "./_generated/server";
import { nanoid } from "nanoid";
import { Resend } from "resend";
import { VerificationEmail } from "../emails/verification-email";
import { ConfirmationEmail } from "../emails/confirmation-email";
import { TeamNotificationEmail } from "../emails/team-notification-email";

const TOKEN_EXPIRY = 5 * 60 * 1000; // 5 dakika

export const submitApplication = mutation({
args: {
email: v.string(),
name: v.string(),
experience: v.string(),
whyYou: v.string(),
resendApiKey: v.string(),
websiteUrl: v.string(),
},
handler: async (ctx, args) => {
const now = Date.now();
const verificationToken = nanoid(32);
const tokenExpiry = now + TOKEN_EXPIRY;

// Başvuruyu kaydet
const applicationId = await ctx.db.insert("testerApplications", {
email: args.email,
name: args.name,
experience: args.experience,
whyYou: args.whyYou,
status: "pending",
verificationToken,
tokenExpiry,
createdAt: now,
lastAttempt: now,
});

// Resend client'ı oluştur
const resend = new Resend(args.resendApiKey);
const verificationUrl = `${args.websiteUrl}/verify?token=${verificationToken}`;

// Doğrulama emaili gönder
await resend.emails.send({
from: "Lamron Studio <support@lamronstudio.com>",
to: [args.email],
subject: "Email Adresinizi Doğrulayın",
react: VerificationEmail({ name: args.name, verificationUrl }),
});

return { success: true, applicationId };
},
});

export const verifyApplication = mutation({
args: {
token: v.string(),
resendApiKey: v.string(),
},
handler: async (ctx, args) => {
const now = Date.now();

const application = await ctx.db
.query("testerApplications")
.filter((q) => q.eq(q.field("verificationToken"), args.token))
.first();

if (!application) {
throw new Error("Geçersiz doğrulama kodu");
}

if (application.tokenExpiry < now) {
await ctx.db.patch(application._id, { status: "expired" });
throw new Error("Doğrulama kodunun süresi dolmuş");
}

if (application.status !== "pending") {
throw new Error("Başvuru doğrulama beklemede değil");
}

// Başvuruyu onayla
await ctx.db.patch(application._id, { status: "verified" });

// Resend client'ı oluştur
const resend = new Resend(args.resendApiKey);

// Onay emaili gönder
await resend.emails.send({
from: "Lamron Studio <support@lamronstudio.com>",
to: application.email,
subject: "Lamron Studio Test Ekibine Hoş Geldiniz!",
react: ConfirmationEmail({ name: application.name, email: application.email }),
});

// Yöneticiye bildirim emaili gönder
await resend.emails.send({
from: "Lamron Studio <support@lamronstudio.com>",
to: "atalay.gov@gmail.com",
subject: `Yeni Test Ekibi Başvurusu: ${application.name}`,
react: TeamNotificationEmail({
name: application.name,
email: application.email,
experience: application.experience,
whyYou: application.whyYou
}),
});

return { success: true };
},
});
I'm getting this error: [CONVEX M(testerApplications:submitApplication)] [Request ID: 9839abbfc75c3f95] Server Error Uncaught Error: Failed to render React component. Make sure to install @react-email/render at throw [as throw] (<anonymous>) I'm adding to my next.config.ts this: serverExternalPackages: [ '@react-email/components', '@react-email/render', '@react-email/tailwind', ], but not helped me... Can you help me guys? Does convex structure allow tsx components?
1 Reply
Convex Bot
Convex Bot4d ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!

Did you find this page helpful?