Add more typescript types (#867)
This commit is contained in:
parent
effbd44f48
commit
c62e1a0eeb
3 changed files with 51 additions and 18 deletions
|
@ -2,20 +2,31 @@ import nodemailer from "nodemailer";
|
||||||
|
|
||||||
import { serverConfig } from "../serverConfig";
|
import { serverConfig } from "../serverConfig";
|
||||||
|
|
||||||
export default function createInvitationEmail(data: any, options: any = {}) {
|
export type Invitation = {
|
||||||
return sendEmail(data, {
|
from?: string;
|
||||||
provider: {
|
toEmail: string;
|
||||||
|
teamName: string;
|
||||||
|
token?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type EmailProvider = {
|
||||||
|
from: string;
|
||||||
|
transport: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function createInvitationEmail(data: Invitation) {
|
||||||
|
const provider = {
|
||||||
transport: serverConfig.transport,
|
transport: serverConfig.transport,
|
||||||
from: serverConfig.from,
|
from: serverConfig.from,
|
||||||
},
|
} as EmailProvider;
|
||||||
...options,
|
return sendEmail(data, provider);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendEmail = (invitation: any, { provider }) =>
|
const sendEmail = (invitation: Invitation, provider: EmailProvider): Promise<void> =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const { transport, from } = provider;
|
const { transport, from } = provider;
|
||||||
|
|
||||||
|
const invitationHtml = html(invitation);
|
||||||
nodemailer.createTransport(transport).sendMail(
|
nodemailer.createTransport(transport).sendMail(
|
||||||
{
|
{
|
||||||
from: `Cal.com <${from}>`,
|
from: `Cal.com <${from}>`,
|
||||||
|
@ -23,8 +34,8 @@ const sendEmail = (invitation: any, { provider }) =>
|
||||||
subject:
|
subject:
|
||||||
(invitation.from ? invitation.from + " invited you" : "You have been invited") +
|
(invitation.from ? invitation.from + " invited you" : "You have been invited") +
|
||||||
` to join ${invitation.teamName}`,
|
` to join ${invitation.teamName}`,
|
||||||
html: html(invitation),
|
html: invitationHtml,
|
||||||
text: text(invitation),
|
text: text(invitationHtml),
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -36,7 +47,7 @@ const sendEmail = (invitation: any, { provider }) =>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const html = (invitation: any) => {
|
export function html(invitation: Invitation): string {
|
||||||
let url: string = process.env.BASE_URL + "/settings/teams";
|
let url: string = process.env.BASE_URL + "/settings/teams";
|
||||||
if (invitation.token) {
|
if (invitation.token) {
|
||||||
url = `${process.env.BASE_URL}/auth/signup?token=${invitation.token}&callbackUrl=${url}`;
|
url = `${process.env.BASE_URL}/auth/signup?token=${invitation.token}&callbackUrl=${url}`;
|
||||||
|
@ -82,10 +93,9 @@ const html = (invitation: any) => {
|
||||||
</table>
|
</table>
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
// just strip all HTML and convert <br /> to \n
|
// just strip all HTML and convert <br /> to \n
|
||||||
const text = (evt: any) =>
|
export function text(htmlStr: string): string {
|
||||||
html(evt)
|
return htmlStr.replace("<br />", "\n").replace(/<[^>]+>/g, "");
|
||||||
.replace("<br />", "\n")
|
}
|
||||||
.replace(/<[^>]+>/g, "");
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
|
|
||||||
import createInvitationEmail from "../../../../lib/emails/invitation";
|
import { createInvitationEmail } from "../../../../lib/emails/invitation";
|
||||||
import prisma from "../../../../lib/prisma";
|
import prisma from "../../../../lib/prisma";
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
|
23
test/lib/emails/invitation.test.ts
Normal file
23
test/lib/emails/invitation.test.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { expect, it } from "@jest/globals";
|
||||||
|
|
||||||
|
import { html, text, Invitation } from "@lib/emails/invitation";
|
||||||
|
|
||||||
|
it("email text rendering should strip tags and add new lines", () => {
|
||||||
|
const result = text("<p>hello world</p><br /><div>welcome to the brave <span>new</span> world");
|
||||||
|
expect(result).toEqual("hello world\nwelcome to the brave new world");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("email html should render invite email", () => {
|
||||||
|
const invitation = {
|
||||||
|
from: "Huxley",
|
||||||
|
toEmail: "hello@example.com",
|
||||||
|
teamName: "Calendar Lovers",
|
||||||
|
token: "invite-token",
|
||||||
|
} as Invitation;
|
||||||
|
const result = html(invitation);
|
||||||
|
expect(result).toContain('<br />Huxley invited you to join the team "Calendar Lovers" in Cal.com.<br />');
|
||||||
|
expect(result).toContain("/auth/signup?token=invite-token&");
|
||||||
|
expect(result).toContain(
|
||||||
|
'If you prefer not to use "hello@example.com" as your Cal.com email or already have a Cal.com account, please request another invitation to that email.'
|
||||||
|
);
|
||||||
|
});
|
Loading…
Reference in a new issue