From 2c3cd6da6ac56fed0e8c51995edca3fa931262a0 Mon Sep 17 00:00:00 2001 From: Jean du Plessis Date: Wed, 25 Mar 2026 23:02:10 +0200 Subject: [PATCH] refactor(email): add explicit return types to email send functions tsgo 7.0 enforces TS2883 which requires explicit return type annotations when the inferred type references non-portable vendor types. Add explicit return types to email send functions using the existing SendResult type, and change sendViaMailgun to return Promise instead of leaking the mailgun client type through declarations. --- src/lib/email-mailgun.ts | 11 ++++++++--- src/lib/email.ts | 33 +++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/lib/email-mailgun.ts b/src/lib/email-mailgun.ts index 6df9d5ef55..7718682d33 100644 --- a/src/lib/email-mailgun.ts +++ b/src/lib/email-mailgun.ts @@ -11,19 +11,24 @@ type SendViaMailgunParams = { html: string; }; -export async function sendViaMailgun({ to, subject, html }: SendViaMailgunParams) { +export async function sendViaMailgun({ + to, + subject, + html, +}: SendViaMailgunParams): Promise { if (!MAILGUN_API_KEY || !MAILGUN_DOMAIN) { const message = 'MAILGUN_API_KEY/MAILGUN_DOMAIN not set — cannot send email via Mailgun'; console.warn(message); captureMessage(message, { level: 'warning', tags: { source: 'email_service' } }); - return; + return false; } const client = mailgun.client({ username: 'api', key: MAILGUN_API_KEY }); - return client.messages.create(MAILGUN_DOMAIN, { + await client.messages.create(MAILGUN_DOMAIN, { from: 'Kilo Code ', 'h:Reply-To': 'hi@kilocode.ai', to, subject, html, }); + return true; } diff --git a/src/lib/email.ts b/src/lib/email.ts index 57ccd38914..4b92a423a5 100644 --- a/src/lib/email.ts +++ b/src/lib/email.ts @@ -115,7 +115,7 @@ type Props = { organizationId: string; }; -export async function sendOrgSubscriptionEmail(to: string, props: Props) { +export async function sendOrgSubscriptionEmail(to: string, props: Props): Promise { const seats = `${props.seatCount} seat${props.seatCount === 1 ? '' : 's'}`; const organization_url = `${NEXTAUTH_URL}/organizations/${props.organizationId}`; const invoices_url = `${NEXTAUTH_URL}/organizations/${props.organizationId}/payment-details`; @@ -126,7 +126,7 @@ export async function sendOrgSubscriptionEmail(to: string, props: Props) { }); } -export async function sendOrgRenewedEmail(to: string, props: Props) { +export async function sendOrgRenewedEmail(to: string, props: Props): Promise { const seats = `${props.seatCount} seat${props.seatCount === 1 ? '' : 's'}`; const invoices_url = `${NEXTAUTH_URL}/organizations/${props.organizationId}/payment-details`; return send({ @@ -136,7 +136,10 @@ export async function sendOrgRenewedEmail(to: string, props: Props) { }); } -export async function sendOrgCancelledEmail(to: string, props: Omit) { +export async function sendOrgCancelledEmail( + to: string, + props: Omit +): Promise { const invoices_url = `${NEXTAUTH_URL}/organizations/${props.organizationId}/payment-details`; return send({ to, @@ -148,7 +151,7 @@ export async function sendOrgCancelledEmail(to: string, props: Omit & { new_user_email: string } -) { +): Promise { const organization_url = `${NEXTAUTH_URL}/organizations/${props.organizationId}`; return send({ to, @@ -157,7 +160,9 @@ export async function sendOrgSSOUserJoinedEmail( }); } -export async function sendOrganizationInviteEmail(data: OrganizationInviteEmailData) { +export async function sendOrganizationInviteEmail( + data: OrganizationInviteEmailData +): Promise { return send({ to: data.to, templateName: 'orgInvitation', @@ -172,7 +177,7 @@ export async function sendOrganizationInviteEmail(data: OrganizationInviteEmailD export async function sendMagicLinkEmail( magicLink: MagicLinkTokenWithPlaintext, callbackUrl?: string -) { +): Promise { return send({ to: magicLink.email, templateName: 'magicLink', @@ -189,7 +194,7 @@ export async function sendMagicLinkEmail( export async function sendAutoTopUpFailedEmail( to: string, props: { reason: string; organizationId?: string } -) { +): Promise { const credits_url = props.organizationId ? `${NEXTAUTH_URL}/organizations/${props.organizationId}/payment-details` : `${NEXTAUTH_URL}/credits?show-auto-top-up`; @@ -207,7 +212,9 @@ type SendDeploymentFailedEmailProps = { repository: string; }; -export async function sendDeploymentFailedEmail(props: SendDeploymentFailedEmailProps) { +export async function sendDeploymentFailedEmail( + props: SendDeploymentFailedEmailProps +): Promise { return send({ to: props.to, templateName: 'deployFailed', @@ -225,7 +232,7 @@ type SendBalanceAlertEmailProps = { to: string[]; }; -export async function sendBalanceAlertEmail(props: SendBalanceAlertEmailProps) { +export async function sendBalanceAlertEmail(props: SendBalanceAlertEmailProps): Promise { const { organizationId, minimum_balance, to } = props; if (!to || to.length === 0) { @@ -270,7 +277,7 @@ type OssInviteEmailData = { monthlyCreditsUsd: number; }; -export async function sendOssInviteNewUserEmail(data: OssInviteEmailData) { +export async function sendOssInviteNewUserEmail(data: OssInviteEmailData): Promise { const integrations_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}/integrations`; const code_reviews_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}/code-reviews`; const tierConfig = ossTierConfig[data.tier]; @@ -292,7 +299,7 @@ export async function sendOssInviteNewUserEmail(data: OssInviteEmailData) { export async function sendOssInviteExistingUserEmail( data: Omit -) { +): Promise { const organization_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}`; const integrations_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}/integrations`; const code_reviews_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}/code-reviews`; @@ -321,7 +328,9 @@ type OssProvisionEmailData = { monthlyCreditsUsd: number; }; -export async function sendOssExistingOrgProvisionedEmail(data: OssProvisionEmailData) { +export async function sendOssExistingOrgProvisionedEmail( + data: OssProvisionEmailData +): Promise { const organization_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}`; const integrations_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}/integrations`; const code_reviews_url = `${NEXTAUTH_URL}/organizations/${data.organizationId}/code-reviews`;