UNPKG

@coursebuilder/core

Version:

Core package for Course Builder

257 lines (254 loc) 9.69 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/lib/send-server-email.ts var send_server_email_exports = {}; __export(send_server_email_exports, { createVerificationUrl: () => createVerificationUrl, sendServerEmail: () => sendServerEmail }); module.exports = __toCommonJS(send_server_email_exports); var import_crypto = require("crypto"); var import_uuid = require("uuid"); // src/lib/send-verification-request.ts var import_components = require("@react-email/components"); var import_new_member = require("@coursebuilder/email-templates/emails/new-member"); var import_post_purchase_login = require("@coursebuilder/email-templates/emails/post-purchase-login"); var sendVerificationRequest = /* @__PURE__ */ __name(async (params, adapter) => { const { identifier: email, name, url, provider, theme, expires, merchantChargeId, type = "login" } = params; const { host } = new URL(url); console.log(`[sendVerificationRequest] Initiated. Type: ${type}, Email: ${email}, Host: ${host}${merchantChargeId ? `, MerchantChargeId: ${merchantChargeId}` : ""}`); let text = params.text || defaultText; let html = params.html || defaultHtml; const { server, from } = provider.options ? provider.options : provider; const { getUserByEmail, findOrCreateUser } = adapter; let subject; switch (type) { case "purchase": subject = `Thank you for Purchasing ${process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE} (${host})`; break; case "transfer": subject = `Accept Your Seat for ${process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE} (${host})`; break; case "signup": subject = `Welcome to ${process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE} (${host})`; html = signUpHtml; text = signUpText; break; default: subject = `Log in to ${process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE} (${host})`; } console.log(`[sendVerificationRequest] Determined email subject: "${subject}"`); let user; try { user = process.env.CREATE_USER_ON_LOGIN !== "false" ? await findOrCreateUser(email, name) : await getUserByEmail?.(email); if (!user) { console.warn(`[sendVerificationRequest] User not found and creation disabled/failed for email: ${email}. Aborting.`); return; } console.log(`[sendVerificationRequest] User found or created for email: ${email}, ID: ${user.id || user?.user?.id || "unknown"}`); } catch (error) { console.error(`[sendVerificationRequest] Error during user lookup/creation for email: ${email}`, error); throw error; } if (process.env.LOG_VERIFICATION_URL) { console.log(` \u{1F44B} MAGIC LINK URL ****************** `); console.log(url); console.log(` ************************************ `); } if (process.env.SKIP_EMAIL === "true") { console.warn(`[sendVerificationRequest] \u{1F6AB} Email sending is disabled via SKIP_EMAIL.`); return; } if (!process.env.POSTMARK_API_TOKEN && !process.env.POSTMARK_KEY) { console.error("[sendVerificationRequest] \u{1F6AB} Missing Postmark API Key (POSTMARK_API_TOKEN or POSTMARK_KEY). Cannot send email."); throw new Error("Missing Postmark API Key"); } try { const textBody = await text({ url, host, email, expires, merchantChargeId }, theme); const htmlBody = await html({ url, host, email, expires, merchantChargeId }, theme); console.log(`[sendVerificationRequest] Attempting to send email via Postmark to ${email} from ${from}`); const res = await fetch("https://api.postmarkapp.com/email", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", "X-Postmark-Server-Token": process.env.POSTMARK_API_TOKEN || process.env.POSTMARK_KEY }, body: JSON.stringify({ From: from, To: email, Subject: subject, TextBody: textBody, HtmlBody: htmlBody, MessageStream: "outbound" }) }); if (!res.ok) { const errorBody = await res.json(); console.error(`[sendVerificationRequest] Postmark error sending email to ${email}. Status: ${res.status}`, errorBody); throw new Error(`Postmark error: ${res.status} ${JSON.stringify(errorBody)}`); } console.log(`[sendVerificationRequest] \u2705 Email successfully sent to ${email} via Postmark. Status: ${res.status}`); } catch (error) { console.error(`[sendVerificationRequest] \u{1F4A5} Failed to send email to ${email}. Error:`, error); throw error; } }, "sendVerificationRequest"); function defaultHtml({ url, host, email, merchantChargeId }, theme) { return (0, import_components.render)((0, import_post_purchase_login.PostPurchaseLoginEmail)({ url, host, email, siteName: process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE || "", ...merchantChargeId && { invoiceUrl: `${process.env.COURSEBUILDER_URL}/invoices/${merchantChargeId}` }, previewText: process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE || "login link" }, theme)); } __name(defaultHtml, "defaultHtml"); async function defaultText({ url, host, email, merchantChargeId }, theme) { return await (0, import_components.render)((0, import_post_purchase_login.PostPurchaseLoginEmail)({ url, host, email, siteName: process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE || "", ...merchantChargeId && { invoiceUrl: `${process.env.COURSEBUILDER_URL}/invoices/${merchantChargeId}` }, previewText: process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE || "login link" }, theme), { plainText: true }); } __name(defaultText, "defaultText"); async function signUpHtml({ url, host, email }, theme) { return await (0, import_components.render)((0, import_new_member.NewMemberEmail)({ url, host, email, siteName: process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE || "" })); } __name(signUpHtml, "signUpHtml"); async function signUpText({ url, host, email }, theme) { return await (0, import_components.render)((0, import_new_member.NewMemberEmail)({ url, host, email, siteName: process.env.NEXT_PUBLIC_PRODUCT_NAME || process.env.NEXT_PUBLIC_SITE_TITLE || "" }), { plainText: true }); } __name(signUpText, "signUpText"); // src/lib/send-server-email.ts function hashToken(token, options) { const { provider, secret } = options; return (0, import_crypto.createHash)("sha256").update(`${token}${provider.secret ?? secret}`).digest("hex"); } __name(hashToken, "hashToken"); async function createVerificationUrl({ email, emailProvider, adapter, callbackUrl, expiresAt, authOptions, baseUrl }) { if (!emailProvider) return; callbackUrl = callbackUrl || baseUrl; const token = await emailProvider.generateVerificationToken?.() ?? (0, import_uuid.v4)(); const ONE_DAY_IN_SECONDS = 86400; const durationInMilliseconds = (emailProvider.maxAge ?? ONE_DAY_IN_SECONDS) * 1e3; const expires = expiresAt || new Date(Date.now() + durationInMilliseconds); await adapter.createVerificationToken?.({ identifier: email, token: hashToken(token, { provider: emailProvider, secret: authOptions.secret }), expires }); const params = new URLSearchParams({ callbackUrl, token, email }); const verificationUrl = `${baseUrl}/api/auth/callback/${emailProvider.id}?${params}`; return { url: verificationUrl, token, expires }; } __name(createVerificationUrl, "createVerificationUrl"); async function sendServerEmail({ email, callbackUrl, emailProvider, type = "login", html, text, expiresAt, authOptions, adapter, baseUrl, merchantChargeId }) { if (!emailProvider) return; try { const verificationDetails = await createVerificationUrl({ email, authOptions, callbackUrl, emailProvider, expiresAt: expiresAt || void 0, adapter, baseUrl }); if (!verificationDetails) return; const { url, token, expires } = verificationDetails; await sendVerificationRequest({ identifier: email, url, theme: { colorScheme: "auto" }, provider: emailProvider, token, expires, type, html, text, merchantChargeId }, adapter); } catch (error) { console.error(error); throw new Error("Unable to sendVerificationRequest"); } } __name(sendServerEmail, "sendServerEmail"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createVerificationUrl, sendServerEmail }); //# sourceMappingURL=send-server-email.cjs.map