diff --git a/.github/workflows/ci-backend-email.yml b/.github/workflows/ci-backend-email.yml new file mode 100644 index 0000000..180210b --- /dev/null +++ b/.github/workflows/ci-backend-email.yml @@ -0,0 +1,50 @@ +name: CI checks for backend/email workspace + +on: + pull_request: + branches: ['main'] + paths: ['backend/email/**/*', '!**/*.{txt,md,png}'] + push: + branches: ['main'] + paths: ['backend/email/**/*', '!**/*.{txt,md,png}'] + +defaults: + run: + working-directory: backend/email + +jobs: + eslint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - name: Install yarn + run: npm install -g yarn + - name: Install dependencies + run: yarn + - name: Run ESLint + run: yarn eslint . + prettier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - name: Install yarn + run: npm install -g yarn + - name: Install dependencies + run: yarn + - name: Run prettier + run: yarn prettier . --check --ignore-unknown + typecheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - name: Install yarn + run: npm install -g yarn + - name: Install dependencies + run: yarn + - name: Use tsc to build + run: yarn tsc -b + - name: Use tsc to typecheck + run: yarn tsc --noEmit --strict diff --git a/backend/email/.prettierignore b/backend/email/.prettierignore new file mode 100644 index 0000000..f62d700 --- /dev/null +++ b/backend/email/.prettierignore @@ -0,0 +1 @@ +lib/**/* diff --git a/backend/email/emails/functions/helpers.tsx b/backend/email/emails/functions/helpers.tsx index 534e363..286b2f1 100644 --- a/backend/email/emails/functions/helpers.tsx +++ b/backend/email/emails/functions/helpers.tsx @@ -13,10 +13,8 @@ export const sendNewMatchEmail = async ( privateUser: PrivateUser, matchedWithUser: User ) => { - const { sendToEmail, unsubscribeUrl } = getNotificationDestinationsForUser( - privateUser, - 'new_match' - ) + const { sendToEmail /*, unsubscribeUrl*/ } = + getNotificationDestinationsForUser(privateUser, 'new_match') if (!privateUser.email || !sendToEmail) return const lover = await getLover(privateUser.id) if (!lover) return @@ -30,7 +28,7 @@ export const sendNewMatchEmail = async ( onUser={lover.user} matchedWithUser={matchedWithUser} matchedLover={lover} - unsubscribeUrl={unsubscribeUrl} + /*unsubscribeUrl={unsubscribeUrl}*/ /> ), }) @@ -42,10 +40,8 @@ export const sendNewMessageEmail = async ( toUser: User, channelId: number ) => { - const { sendToEmail, unsubscribeUrl } = getNotificationDestinationsForUser( - privateUser, - 'new_message' - ) + const { sendToEmail /*, unsubscribeUrl*/ } = + getNotificationDestinationsForUser(privateUser, 'new_message') if (!privateUser.email || !sendToEmail) return const lover = await getLover(fromUser.id) @@ -65,7 +61,7 @@ export const sendNewMessageEmail = async ( fromUserLover={lover} toUser={toUser} channelId={channelId} - unsubscribeUrl={unsubscribeUrl} + /*unsubscribeUrl={unsubscribeUrl}*/ /> ), }) @@ -77,10 +73,8 @@ export const sendNewEndorsementEmail = async ( onUser: User, text: string ) => { - const { sendToEmail, unsubscribeUrl } = getNotificationDestinationsForUser( - privateUser, - 'new_endorsement' - ) + const { sendToEmail /*, unsubscribeUrl*/ } = + getNotificationDestinationsForUser(privateUser, 'new_endorsement') if (!privateUser.email || !sendToEmail) return return await sendEmail({ @@ -92,7 +86,7 @@ export const sendNewEndorsementEmail = async ( fromUser={fromUser} onUser={onUser} endorsementText={text} - unsubscribeUrl={unsubscribeUrl} + /*unsubscribeUrl={unsubscribeUrl}*/ /> ), }) diff --git a/backend/email/emails/functions/send-test-email.ts b/backend/email/emails/functions/send-test-email.ts index c4e8188..b330083 100755 --- a/backend/email/emails/functions/send-test-email.ts +++ b/backend/email/emails/functions/send-test-email.ts @@ -11,4 +11,4 @@ if (require.main === module) { sendTestEmail(email) .then(() => console.log('Email sent successfully!')) .catch((error) => console.error('Failed to send email:', error)) -} \ No newline at end of file +} diff --git a/backend/email/emails/new-endorsement.tsx b/backend/email/emails/new-endorsement.tsx index 9ab5879..0989be0 100644 --- a/backend/email/emails/new-endorsement.tsx +++ b/backend/email/emails/new-endorsement.tsx @@ -6,7 +6,7 @@ import { Head, Html, Img, - Link, + //Link, Preview, Row, Section, @@ -20,18 +20,17 @@ interface NewEndorsementEmailProps { fromUser: User onUser: User endorsementText: string - unsubscribeUrl: string + //unsubscribeUrl: string } -export const NewEndorsementEmail = ({ - fromUser, - onUser, - endorsementText, - unsubscribeUrl, -}: NewEndorsementEmailProps) => { - const name = onUser.name.split(' ')[0] +export const NewEndorsementEmail = ( + newEndorsementEmailProps: NewEndorsementEmailProps +) => { + const onUser: User = newEndorsementEmailProps.onUser + const fromUser: User = newEndorsementEmailProps.fromUser + const name: string = onUser.name.split(' ')[0] - const endorsementUrl = `https://${DOMAIN}/${onUser.username}` + const endorsementUrl: string = `https://${DOMAIN}/${newEndorsementEmailProps.onUser.username}` return ( @@ -65,7 +64,9 @@ export const NewEndorsementEmail = ({ /> - "{endorsementText}" + + "{newEndorsementEmailProps.endorsementText}" + @@ -172,9 +173,9 @@ const footerText = { fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif', } -const footerLink = { +/*const footerLink = { color: 'inherit', textDecoration: 'none', -} +}*/ export default NewEndorsementEmail diff --git a/backend/email/emails/new-match.tsx b/backend/email/emails/new-match.tsx index d385a76..ea6fdc2 100644 --- a/backend/email/emails/new-match.tsx +++ b/backend/email/emails/new-match.tsx @@ -20,18 +20,15 @@ interface NewMatchEmailProps { onUser: User matchedWithUser: User matchedLover: LoverRow - unsubscribeUrl: string + //unsubscribeUrl: string } -export const NewMatchEmail = ({ - onUser, - matchedWithUser, - matchedLover, - unsubscribeUrl, -}: NewMatchEmailProps) => { - const name = onUser.name.split(' ')[0] - const userImgSrc = getLoveOgImageUrl(matchedWithUser, matchedLover) - const userUrl = `https://${DOMAIN}/${matchedWithUser.username}` +export const NewMatchEmail = (newMatchEmailProps: NewMatchEmailProps) => { + const name: string = newMatchEmailProps.onUser.name.split(' ')[0] + const matchedWithUser: User = newMatchEmailProps.matchedWithUser + const matchedLover: LoverRow = newMatchEmailProps.matchedLover + const userImgSrc: string = getLoveOgImageUrl(matchedWithUser, matchedLover) + const userUrl: string = `https://${DOMAIN}/${matchedWithUser.username}` return ( @@ -159,9 +156,9 @@ const footerText = { fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif', } -const footerLink = { +/*const footerLink = { color: 'inherit', textDecoration: 'none', -} +}*/ export default NewMatchEmail diff --git a/backend/email/emails/new-message.tsx b/backend/email/emails/new-message.tsx index 3ec643f..7be3a95 100644 --- a/backend/email/emails/new-message.tsx +++ b/backend/email/emails/new-message.tsx @@ -15,7 +15,7 @@ import { type LoverRow } from 'common/love/lover' import { jamesLover, jamesUser, - sinclairLover, + //sinclairLover, sinclairUser, } from './functions/mock' import { DOMAIN } from 'common/envs/constants' @@ -26,20 +26,18 @@ interface NewMessageEmailProps { fromUserLover: LoverRow toUser: User channelId: number - unsubscribeUrl: string + //unsubscribeUrl: string } -export const NewMessageEmail = ({ - fromUser, - fromUserLover, - toUser, - channelId, - unsubscribeUrl, -}: NewMessageEmailProps) => { - const name = toUser.name.split(' ')[0] - const creatorName = fromUser.name - const messagesUrl = `https://${DOMAIN}/messages/${channelId}` - const userImgSrc = getLoveOgImageUrl(fromUser, fromUserLover) +export const NewMessageEmail = (newMessageEmailProps: NewMessageEmailProps) => { + const name: string = newMessageEmailProps.toUser.name.split(' ')[0] + const creatorName: string = newMessageEmailProps.fromUser.name + const channelId: number = newMessageEmailProps.channelId + const messagesUrl: string = `https://${DOMAIN}/messages/${channelId}` + const userImgSrc: string = getLoveOgImageUrl( + newMessageEmailProps.fromUser, + newMessageEmailProps.fromUserLover + ) return ( @@ -98,7 +96,7 @@ NewMessageEmail.PreviewProps = { fromUserLover: jamesLover, toUser: sinclairUser, channelId: 1, - unsubscribeUrl: 'https://manifold.love/unsubscribe', + //unsubscribeUrl: 'https://manifold.love/unsubscribe', } as NewMessageEmailProps const main = { diff --git a/backend/email/eslint.config.mjs b/backend/email/eslint.config.mjs new file mode 100644 index 0000000..9548caf --- /dev/null +++ b/backend/email/eslint.config.mjs @@ -0,0 +1,13 @@ +import globals from 'globals' +import pluginJs from '@eslint/js' +import tseslint from 'typescript-eslint' + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { ignores: ['lib/'] }, // generated by `tsc -b` so irrelevant (and all imports turn into requires there anyways) + { files: ['**/*.{js,mjs,cjs,ts}'] }, + { languageOptions: { globals: globals.node } }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { rules: { '@typescript-eslint/no-unused-expressions': 'off' } }, +] diff --git a/backend/email/package.json b/backend/email/package.json index 94a6e81..7198946 100644 --- a/backend/email/package.json +++ b/backend/email/package.json @@ -7,11 +7,15 @@ "build": "tsc -b" }, "dependencies": { + "@eslint/js": "9.32.0", "@react-email/components": "0.0.33", + "eslint": "9.32.0", + "globals": "16.3.0", "react": "19.0.0", "react-dom": "19.0.0", "react-email": "3.0.7", - "resend": "4.1.2" + "resend": "4.1.2", + "typescript-eslint": "8.39.0" }, "devDependencies": { "@types/html-to-text": "9.0.4",