diff --git a/package.json b/package.json
index e1c6a4e05..201c00ad2 100644
--- a/package.json
+++ b/package.json
@@ -39,6 +39,8 @@
"@octokit/graphql": "^7.0.2",
"@ptc-org/nestjs-query-core": "^4.2.0",
"@ptc-org/nestjs-query-typeorm": "4.2.1-alpha.2",
+ "@react-email/components": "0.0.12",
+ "@react-email/render": "0.0.10",
"@sentry/node": "^7.66.0",
"@sentry/profiling-node": "^1.2.6",
"@sentry/react": "^7.88.0",
diff --git a/packages/twenty-server/src/emails/common-style.ts b/packages/twenty-server/src/emails/common-style.ts
new file mode 100644
index 000000000..6a80ebedd
--- /dev/null
+++ b/packages/twenty-server/src/emails/common-style.ts
@@ -0,0 +1,48 @@
+const grayScale = {
+ gray100: '#000000',
+ gray90: '#141414',
+ gray85: '#171717',
+ gray80: '#1b1b1b',
+ gray75: '#1d1d1d',
+ gray70: '#222222',
+ gray65: '#292929',
+ gray60: '#333333',
+ gray55: '#4c4c4c',
+ gray50: '#666666',
+ gray45: '#818181',
+ gray40: '#999999',
+ gray35: '#b3b3b3',
+ gray30: '#cccccc',
+ gray25: '#d6d6d6',
+ gray20: '#ebebeb',
+ gray15: '#f1f1f1',
+ gray10: '#fcfcfc',
+ gray0: '#ffffff',
+};
+
+export const emailTheme = {
+ font: {
+ colors: {
+ highlighted: grayScale.gray60,
+ primary: grayScale.gray50,
+ inverted: grayScale.gray0,
+ },
+ weight: {
+ regular: 400,
+ bold: 600,
+ },
+ size: {
+ md: '13px',
+ lg: '16px',
+ },
+ },
+ background: {
+ colors: { highlight: grayScale.gray15 },
+ radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${grayScale.gray60} 100%)`,
+ radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${grayScale.gray60} 100%)`,
+ transparent: {
+ medium: 'rgba(0, 0, 0, 0.08)',
+ light: 'rgba(0, 0, 0, 0.04)',
+ },
+ },
+};
diff --git a/packages/twenty-server/src/emails/components/BaseEmail.tsx b/packages/twenty-server/src/emails/components/BaseEmail.tsx
new file mode 100644
index 000000000..6717f0e57
--- /dev/null
+++ b/packages/twenty-server/src/emails/components/BaseEmail.tsx
@@ -0,0 +1,17 @@
+import * as React from 'react';
+import { Container, Html } from '@react-email/components';
+
+import { BaseHead } from 'src/emails/components/BaseHead';
+import { Logo } from 'src/emails/components/Logo';
+
+export const BaseEmail = ({ children }) => {
+ return (
+
+
+
+
+ {children}
+
+
+ );
+};
diff --git a/packages/twenty-server/src/emails/components/BaseHead.tsx b/packages/twenty-server/src/emails/components/BaseHead.tsx
new file mode 100644
index 000000000..6d3c92be1
--- /dev/null
+++ b/packages/twenty-server/src/emails/components/BaseHead.tsx
@@ -0,0 +1,22 @@
+import { Font, Head } from '@react-email/components';
+import * as React from 'react';
+
+import { emailTheme } from 'src/emails/common-style';
+
+export const BaseHead = () => {
+ return (
+
+ Twenty email
+
+
+ );
+};
diff --git a/packages/twenty-server/src/emails/components/CallToAction.tsx b/packages/twenty-server/src/emails/components/CallToAction.tsx
new file mode 100644
index 000000000..774899923
--- /dev/null
+++ b/packages/twenty-server/src/emails/components/CallToAction.tsx
@@ -0,0 +1,23 @@
+import { Button } from '@react-email/button';
+import * as React from 'react';
+
+import { emailTheme } from 'src/emails/common-style';
+const callToActionStyle = {
+ display: 'flex',
+ padding: '8px 32px',
+ borderRadius: '8px',
+ border: `1px solid ${emailTheme.background.transparent.light}`,
+ background: emailTheme.background.radialGradient,
+ boxShadow: `0px 2px 4px 0px ${emailTheme.background.transparent.light}, 0px 0px 4px 0px ${emailTheme.background.transparent.medium}`,
+ color: emailTheme.font.colors.inverted,
+ fontSize: emailTheme.font.size.md,
+ fontWeight: emailTheme.font.weight.bold,
+};
+
+export const CallToAction = ({ value, href }) => {
+ return (
+
+ );
+};
diff --git a/packages/twenty-server/src/emails/components/HighlightedText.tsx b/packages/twenty-server/src/emails/components/HighlightedText.tsx
new file mode 100644
index 000000000..75010e017
--- /dev/null
+++ b/packages/twenty-server/src/emails/components/HighlightedText.tsx
@@ -0,0 +1,30 @@
+import * as React from 'react';
+import { Row } from '@react-email/row';
+import { Text } from '@react-email/text';
+import { Column } from '@react-email/components';
+
+import { emailTheme } from 'src/emails/common-style';
+
+const rowStyle = {
+ display: 'flex',
+};
+
+const highlightedStyle = {
+ borderRadius: '4px',
+ background: emailTheme.background.colors.highlight,
+ padding: '4px 8px',
+ margin: 0,
+ fontSize: emailTheme.font.size.lg,
+ fontWeight: emailTheme.font.weight.bold,
+ color: emailTheme.font.colors.highlighted,
+};
+
+export const HighlightedText = ({ value }) => {
+ return (
+
+
+ {value}
+
+
+ );
+};
diff --git a/packages/twenty-server/src/emails/components/Logo.tsx b/packages/twenty-server/src/emails/components/Logo.tsx
new file mode 100644
index 000000000..7b0638426
--- /dev/null
+++ b/packages/twenty-server/src/emails/components/Logo.tsx
@@ -0,0 +1,17 @@
+import { Img } from '@react-email/components';
+
+const logoStyle = {
+ marginBottom: '40px',
+};
+
+export const Logo = () => {
+ return (
+
+ );
+};
diff --git a/packages/twenty-server/src/emails/components/MainText.tsx b/packages/twenty-server/src/emails/components/MainText.tsx
new file mode 100644
index 000000000..8412c2bd9
--- /dev/null
+++ b/packages/twenty-server/src/emails/components/MainText.tsx
@@ -0,0 +1,14 @@
+import { Text } from '@react-email/text';
+import * as React from 'react';
+
+import { emailTheme } from 'src/emails/common-style';
+
+const mainTextStyle = {
+ fontSize: emailTheme.font.size.md,
+ fontWeight: emailTheme.font.weight.regular,
+ color: emailTheme.font.colors.primary,
+};
+
+export const MainText = ({ children }) => {
+ return {children};
+};
diff --git a/packages/twenty-server/src/emails/components/Title.tsx b/packages/twenty-server/src/emails/components/Title.tsx
new file mode 100644
index 000000000..1b5aed29a
--- /dev/null
+++ b/packages/twenty-server/src/emails/components/Title.tsx
@@ -0,0 +1,6 @@
+import { Heading } from '@react-email/components';
+import * as React from 'react';
+
+export const Title = ({ value }) => {
+ return {value};
+};
diff --git a/packages/twenty-server/src/integrations/email/email-sender.job.ts b/packages/twenty-server/src/integrations/email/email-sender.job.ts
new file mode 100644
index 000000000..d6ad62c37
--- /dev/null
+++ b/packages/twenty-server/src/integrations/email/email-sender.job.ts
@@ -0,0 +1,18 @@
+import { Injectable } from '@nestjs/common';
+
+import { SendMailOptions } from 'nodemailer';
+
+import { MessageQueueJob } from 'src/integrations/message-queue/interfaces/message-queue-job.interface';
+
+import { EmailSenderService } from 'src/integrations/email/email-sender.service';
+
+@Injectable()
+export class EmailSenderJob implements MessageQueueJob {
+ constructor(private readonly emailSenderService: EmailSenderService) {}
+
+ async handle(data: SendMailOptions): Promise {
+ process.stdout.write(`Sending email to ${data.to} ...`);
+ await this.emailSenderService.send(data);
+ console.log(' done!');
+ }
+}
diff --git a/packages/twenty-server/src/integrations/email/email-sender.service.ts b/packages/twenty-server/src/integrations/email/email-sender.service.ts
new file mode 100644
index 000000000..58b6c4a9c
--- /dev/null
+++ b/packages/twenty-server/src/integrations/email/email-sender.service.ts
@@ -0,0 +1,16 @@
+import { Inject, Injectable } from '@nestjs/common';
+
+import { SendMailOptions } from 'nodemailer';
+
+import { EmailDriver } from 'src/integrations/email/drivers/interfaces/email-driver.interface';
+
+import { EMAIL_DRIVER } from 'src/integrations/email/email.constants';
+
+@Injectable()
+export class EmailSenderService implements EmailDriver {
+ constructor(@Inject(EMAIL_DRIVER) private driver: EmailDriver) {}
+
+ async send(sendMailOptions: SendMailOptions): Promise {
+ await this.driver.send(sendMailOptions);
+ }
+}
diff --git a/packages/twenty-server/src/integrations/email/email.module.ts b/packages/twenty-server/src/integrations/email/email.module.ts
index 2e4c8d9a1..d18fa71fd 100644
--- a/packages/twenty-server/src/integrations/email/email.module.ts
+++ b/packages/twenty-server/src/integrations/email/email.module.ts
@@ -6,6 +6,7 @@ import { EMAIL_DRIVER } from 'src/integrations/email/email.constants';
import { LoggerDriver } from 'src/integrations/email/drivers/logger.driver';
import { SmtpDriver } from 'src/integrations/email/drivers/smtp.driver';
import { EmailService } from 'src/integrations/email/email.service';
+import { EmailSenderService } from 'src/integrations/email/email-sender.service';
@Global()
export class EmailModule {
@@ -22,8 +23,8 @@ export class EmailModule {
return {
module: EmailModule,
- providers: [EmailService, provider],
- exports: [EmailService],
+ providers: [EmailSenderService, EmailService, provider],
+ exports: [EmailSenderService, EmailService],
};
}
}
diff --git a/packages/twenty-server/src/integrations/email/email.service.ts b/packages/twenty-server/src/integrations/email/email.service.ts
index 1c94c33b1..8963ce74d 100644
--- a/packages/twenty-server/src/integrations/email/email.service.ts
+++ b/packages/twenty-server/src/integrations/email/email.service.ts
@@ -2,15 +2,22 @@ import { Inject, Injectable } from '@nestjs/common';
import { SendMailOptions } from 'nodemailer';
-import { EmailDriver } from 'src/integrations/email/drivers/interfaces/email-driver.interface';
-
-import { EMAIL_DRIVER } from 'src/integrations/email/email.constants';
+import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
+import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
+import { EmailSenderJob } from 'src/integrations/email/email-sender.job';
@Injectable()
-export class EmailService implements EmailDriver {
- constructor(@Inject(EMAIL_DRIVER) private driver: EmailDriver) {}
+export class EmailService {
+ constructor(
+ @Inject(MessageQueue.emailQueue)
+ private readonly messageQueueService: MessageQueueService,
+ ) {}
async send(sendMailOptions: SendMailOptions): Promise {
- await this.driver.send(sendMailOptions);
+ await this.messageQueueService.add(
+ EmailSenderJob.name,
+ sendMailOptions,
+ { retryLimit: 3 },
+ );
}
}
diff --git a/packages/twenty-server/src/integrations/integrations.module.ts b/packages/twenty-server/src/integrations/integrations.module.ts
index 51ac6f089..7c63cfe56 100644
--- a/packages/twenty-server/src/integrations/integrations.module.ts
+++ b/packages/twenty-server/src/integrations/integrations.module.ts
@@ -6,8 +6,8 @@ import { exceptionHandlerModuleFactory } from 'src/integrations/exception-handle
import { fileStorageModuleFactory } from 'src/integrations/file-storage/file-storage.module-factory';
import { loggerModuleFactory } from 'src/integrations/logger/logger.module-factory';
import { messageQueueModuleFactory } from 'src/integrations/message-queue/message-queue.module-factory';
-import { emailModuleFactory } from 'src/integrations/email/email.module-factory';
import { EmailModule } from 'src/integrations/email/email.module';
+import { emailModuleFactory } from 'src/integrations/email/email.module-factory';
import { EnvironmentModule } from './environment/environment.module';
import { EnvironmentService } from './environment/environment.service';
diff --git a/packages/twenty-server/src/integrations/message-queue/jobs.module.ts b/packages/twenty-server/src/integrations/message-queue/jobs.module.ts
index 345c4a418..110471846 100644
--- a/packages/twenty-server/src/integrations/message-queue/jobs.module.ts
+++ b/packages/twenty-server/src/integrations/message-queue/jobs.module.ts
@@ -10,6 +10,7 @@ import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metada
import { DataSourceModule } from 'src/metadata/data-source/data-source.module';
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { FetchWorkspaceMessagesModule } from 'src/workspace/messaging/services/fetch-workspace-messages.module';
+import { EmailSenderJob } from 'src/integrations/email/email-sender.job';
@Module({
imports: [
@@ -33,6 +34,10 @@ import { FetchWorkspaceMessagesModule } from 'src/workspace/messaging/services/f
provide: CallWebhookJob.name,
useClass: CallWebhookJob,
},
+ {
+ provide: EmailSenderJob.name,
+ useClass: EmailSenderJob,
+ },
],
})
export class JobsModule {
diff --git a/packages/twenty-server/src/integrations/message-queue/message-queue.constants.ts b/packages/twenty-server/src/integrations/message-queue/message-queue.constants.ts
index 925407e98..228311c50 100644
--- a/packages/twenty-server/src/integrations/message-queue/message-queue.constants.ts
+++ b/packages/twenty-server/src/integrations/message-queue/message-queue.constants.ts
@@ -5,4 +5,5 @@ export enum MessageQueue {
messagingQueue = 'messaging-queue',
webhookQueue = 'webhook-queue',
cronQueue = 'cron-queue',
+ emailQueue = 'email-queue',
}
diff --git a/packages/twenty-server/src/queue-worker.module.ts b/packages/twenty-server/src/queue-worker.module.ts
index fbf96e590..06fa839eb 100644
--- a/packages/twenty-server/src/queue-worker.module.ts
+++ b/packages/twenty-server/src/queue-worker.module.ts
@@ -7,6 +7,7 @@ import { loggerModuleFactory } from 'src/integrations/logger/logger.module-facto
import { JobsModule } from 'src/integrations/message-queue/jobs.module';
import { MessageQueueModule } from 'src/integrations/message-queue/message-queue.module';
import { messageQueueModuleFactory } from 'src/integrations/message-queue/message-queue.module-factory';
+import { IntegrationsModule } from 'src/integrations/integrations.module';
@Module({
imports: [
@@ -20,6 +21,7 @@ import { messageQueueModuleFactory } from 'src/integrations/message-queue/messag
inject: [EnvironmentService],
}),
JobsModule,
+ IntegrationsModule,
],
})
export class QueueWorkerModule {}
diff --git a/packages/twenty-server/tsconfig.json b/packages/twenty-server/tsconfig.json
index f5993c216..6acfb191b 100644
--- a/packages/twenty-server/tsconfig.json
+++ b/packages/twenty-server/tsconfig.json
@@ -22,6 +22,7 @@
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"resolveJsonModule": true,
- "types": ["jest", "node"]
+ "types": ["jest", "node"],
+ "jsx": "react-jsx"
}
}
diff --git a/yarn.lock b/yarn.lock
index b353f28c2..ceb4e2666 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8416,6 +8416,13 @@ __metadata:
languageName: node
linkType: hard
+"@one-ini/wasm@npm:0.1.1":
+ version: 0.1.1
+ resolution: "@one-ini/wasm@npm:0.1.1"
+ checksum: 54700e055037f1a63bfcc86d24822203b25759598c2c3e295d1435130a449108aebc119c9c2e467744767dbe0b6ab47a182c61aa1071ba7368f5e20ab197ba65
+ languageName: node
+ linkType: hard
+
"@open-draft/deferred-promise@npm:^2.1.0, @open-draft/deferred-promise@npm:^2.2.0":
version: 2.2.0
resolution: "@open-draft/deferred-promise@npm:2.2.0"
@@ -9795,6 +9802,205 @@ __metadata:
languageName: node
linkType: hard
+"@react-email/body@npm:0.0.4":
+ version: 0.0.4
+ resolution: "@react-email/body@npm:0.0.4"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 756a184bc1284e8ce1828cd3abc0ea3aa24262e6c677b4e4de48fd6c298717fbc0164e7af7ac4c72262bc3138222ab7fc30c63b0520178315fece2bd78d12f98
+ languageName: node
+ linkType: hard
+
+"@react-email/button@npm:0.0.11":
+ version: 0.0.11
+ resolution: "@react-email/button@npm:0.0.11"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 91de881f33adec7f5ff311dc8259771fff638cbb736a851a6d4a7e634378555177eb112bc38abb18af7e4bc8ccc899f5bce5b20d409e377d289904d37a20c0ce
+ languageName: node
+ linkType: hard
+
+"@react-email/column@npm:0.0.8":
+ version: 0.0.8
+ resolution: "@react-email/column@npm:0.0.8"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 5a937dbe7a69c1db8078f84cf70b66224be187dafa78e683103ccbbdb5d3ad2267f7b92c4fbd73922e8c8dda2a4372f37c1a7efac38501cb356d20c028a87574
+ languageName: node
+ linkType: hard
+
+"@react-email/components@npm:0.0.12":
+ version: 0.0.12
+ resolution: "@react-email/components@npm:0.0.12"
+ dependencies:
+ "@react-email/body": "npm:0.0.4"
+ "@react-email/button": "npm:0.0.11"
+ "@react-email/column": "npm:0.0.8"
+ "@react-email/container": "npm:0.0.10"
+ "@react-email/font": "npm:0.0.4"
+ "@react-email/head": "npm:0.0.6"
+ "@react-email/heading": "npm:0.0.9"
+ "@react-email/hr": "npm:0.0.6"
+ "@react-email/html": "npm:0.0.6"
+ "@react-email/img": "npm:0.0.6"
+ "@react-email/link": "npm:0.0.6"
+ "@react-email/preview": "npm:0.0.7"
+ "@react-email/render": "npm:0.0.9"
+ "@react-email/row": "npm:0.0.6"
+ "@react-email/section": "npm:0.0.10"
+ "@react-email/tailwind": "npm:0.0.13"
+ "@react-email/text": "npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 1cc01198e5eeb42aac79b11e1a0ceaddd75d3164425899d6fc676ddbcd84cb869cebb0c6feb1f4383ba92d150c32e94d1fe5eec2ee74711b9309569e3d9bc6ac
+ languageName: node
+ linkType: hard
+
+"@react-email/container@npm:0.0.10":
+ version: 0.0.10
+ resolution: "@react-email/container@npm:0.0.10"
+ peerDependencies:
+ react: 18.2.0
+ checksum: d074fad448f6033d232b890b9d1a9914d0f92908ba494feaa627828718f4fa6e639636f239eb8eeb8b597c220da9019e90cb72ee2b0328c2ec908fd73e48fc13
+ languageName: node
+ linkType: hard
+
+"@react-email/font@npm:0.0.4":
+ version: 0.0.4
+ resolution: "@react-email/font@npm:0.0.4"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 066a0016fa78267c83665d5e3846421f7d787361b11f4e712bd32353d0de947a72a42036fdfd35b75eff479ca77deba0f5c220bee43ace8594f7c6345c30a0bc
+ languageName: node
+ linkType: hard
+
+"@react-email/head@npm:0.0.6":
+ version: 0.0.6
+ resolution: "@react-email/head@npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: aa2362c965c6f1fa2bcd41be04c1ce8695864153768b4ba4f4b102dd1e1adb28ba067c54f71ded592799aacfa348813cae0f442797b3448bb87feb4588443546
+ languageName: node
+ linkType: hard
+
+"@react-email/heading@npm:0.0.9":
+ version: 0.0.9
+ resolution: "@react-email/heading@npm:0.0.9"
+ dependencies:
+ "@radix-ui/react-slot": "npm:1.0.2"
+ react: "npm:18.2.0"
+ checksum: d082d2a4d3db312cbaa0d62419cc1b29c6b6c3ee1467a220c97c9cb009be1af5f6409370b9caac054d8aee8d326fb6e894a72073ff429f05ed097ba471e12a43
+ languageName: node
+ linkType: hard
+
+"@react-email/hr@npm:0.0.6":
+ version: 0.0.6
+ resolution: "@react-email/hr@npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: b965c176192a06b39d2c696a8b747cdf4060ba7229a7d45eaf1d5729c59920fefe90f43fbc5f8d203a8e5d77645ee62745d06ec5ec5c9b030815f0642a8ac4ab
+ languageName: node
+ linkType: hard
+
+"@react-email/html@npm:0.0.6":
+ version: 0.0.6
+ resolution: "@react-email/html@npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 9046476ccb20e405a64e33ca3a80f1ed7645bacec0601001fd36efd95497a5999daebf0ad141f0c08387190582e23ff2b2f7fc536461ec9b27d0b397a311fe4f
+ languageName: node
+ linkType: hard
+
+"@react-email/img@npm:0.0.6":
+ version: 0.0.6
+ resolution: "@react-email/img@npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 046f0b60bdf9c7c04a2033b39967de96e31ffedae8922f9f187ce39f6040deee33f02e5695f56c26cf1691cce7de937bcbd303c3804b9a824d0aabc71427a462
+ languageName: node
+ linkType: hard
+
+"@react-email/link@npm:0.0.6":
+ version: 0.0.6
+ resolution: "@react-email/link@npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 3e5eb2e222abe99bdcec6127a20d4ac8ed584189527a2bced119b09d08625b74f0ffa8a1de009974b4cd47249ade4081e108ca4fd65daa0ca811a7c6058cf838
+ languageName: node
+ linkType: hard
+
+"@react-email/preview@npm:0.0.7":
+ version: 0.0.7
+ resolution: "@react-email/preview@npm:0.0.7"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 9125597760e69d36b9caf1a94595913f52364642351728a5ff91b7d97fce26fad74bae5f1c9baade8831f4154d4c88c773adcbc1f9f1d602b4113c50bf21eb30
+ languageName: node
+ linkType: hard
+
+"@react-email/render@npm:0.0.10":
+ version: 0.0.10
+ resolution: "@react-email/render@npm:0.0.10"
+ dependencies:
+ html-to-text: "npm:9.0.5"
+ pretty: "npm:2.0.0"
+ react: "npm:18.2.0"
+ react-dom: "npm:18.2.0"
+ checksum: ea0db578ef58734160ac512d04de5b09f558d192fbb74c0b9bdb3006e91d0d73ee7d77007f4740bef0d587f8b231f8dba5ef01e16e18d2deb37859ddd2e7d09a
+ languageName: node
+ linkType: hard
+
+"@react-email/render@npm:0.0.9":
+ version: 0.0.9
+ resolution: "@react-email/render@npm:0.0.9"
+ dependencies:
+ html-to-text: "npm:9.0.5"
+ pretty: "npm:2.0.0"
+ react: "npm:18.2.0"
+ react-dom: "npm:18.2.0"
+ checksum: 128b3a7c65e77a14600e48fb24183e182de82b4ddc8ff11bb239c421fa68bd6eb8b063822b5abe9f8599e34ece315cdb961b4133c59285cebcc517d2ec0ae8da
+ languageName: node
+ linkType: hard
+
+"@react-email/row@npm:0.0.6":
+ version: 0.0.6
+ resolution: "@react-email/row@npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: ca1d92094a5ccc35c93560538311c38989162e9f0235a71897296bc43f2c0ba31d53df9c7db1688f7be0d77ccc03a0094cc227c4d095787f3b3ea0c3d262e520
+ languageName: node
+ linkType: hard
+
+"@react-email/section@npm:0.0.10":
+ version: 0.0.10
+ resolution: "@react-email/section@npm:0.0.10"
+ peerDependencies:
+ react: 18.2.0
+ checksum: d1af5dc3ff9a5bd2675a82f976df79ab5acded5ca305536df36ad84440b3828b021f8026d721e34fe92853bc3dfe8b9aa4603c25bf2f901b22049748ed6a7fbc
+ languageName: node
+ linkType: hard
+
+"@react-email/tailwind@npm:0.0.13":
+ version: 0.0.13
+ resolution: "@react-email/tailwind@npm:0.0.13"
+ dependencies:
+ react: "npm:18.2.0"
+ react-dom: "npm:18.2.0"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 5980a8593b699e9a0e0a8178120d206e74ccb525ba5fedb02e7048f8efff7ca41f82308584624a9701dc021d2ccfd8fa224f11a191d78e567a77f8d35bd47bb4
+ languageName: node
+ linkType: hard
+
+"@react-email/text@npm:0.0.6":
+ version: 0.0.6
+ resolution: "@react-email/text@npm:0.0.6"
+ peerDependencies:
+ react: 18.2.0
+ checksum: 1e960838bfe81bf33b42db1aa1d84446fc36911b4d9e9a79570d9a43fe9cc29d9271f7e1b25448383d8fe950a73130f8bed5c65cd8dbc786a2e6fe02e0c16202
+ languageName: node
+ linkType: hard
+
"@react-hook/debounce@npm:^3.0.0":
version: 3.0.0
resolution: "@react-hook/debounce@npm:3.0.0"
@@ -19889,7 +20095,18 @@ __metadata:
languageName: node
linkType: hard
-"config-chain@npm:^1.1.11":
+"condense-newlines@npm:^0.2.1":
+ version: 0.2.1
+ resolution: "condense-newlines@npm:0.2.1"
+ dependencies:
+ extend-shallow: "npm:^2.0.1"
+ is-whitespace: "npm:^0.3.0"
+ kind-of: "npm:^3.0.2"
+ checksum: 19485db92a5d4658b50ab250626ece0cebe57f73af126b348604309894ed9a2b05f88f1802a090fd1897156eda0af69d8f14446bc62f978e0d048b5135e91694
+ languageName: node
+ linkType: hard
+
+"config-chain@npm:^1.1.11, config-chain@npm:^1.1.13":
version: 1.1.13
resolution: "config-chain@npm:1.1.13"
dependencies:
@@ -21842,6 +22059,20 @@ __metadata:
languageName: node
linkType: hard
+"editorconfig@npm:^1.0.3":
+ version: 1.0.4
+ resolution: "editorconfig@npm:1.0.4"
+ dependencies:
+ "@one-ini/wasm": "npm:0.1.1"
+ commander: "npm:^10.0.0"
+ minimatch: "npm:9.0.1"
+ semver: "npm:^7.5.3"
+ bin:
+ editorconfig: bin/editorconfig
+ checksum: ed6985959d7b34a56e1c09bef118758c81c969489b768d152c93689fce8403b0452462e934f665febaba3478eebc0fd41c0a36100783eaadf6d926c4abc87a3d
+ languageName: node
+ linkType: hard
+
"ee-first@npm:1.1.1":
version: 1.1.1
resolution: "ee-first@npm:1.1.1"
@@ -24670,7 +24901,7 @@ __metadata:
languageName: node
linkType: hard
-"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7":
+"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.3, glob@npm:^10.3.7":
version: 10.3.10
resolution: "glob@npm:10.3.10"
dependencies:
@@ -27074,7 +27305,7 @@ __metadata:
languageName: node
linkType: hard
-"is-buffer@npm:^1.1.0":
+"is-buffer@npm:^1.1.0, is-buffer@npm:^1.1.5":
version: 1.1.6
resolution: "is-buffer@npm:1.1.6"
checksum: ae18aa0b6e113d6c490ad1db5e8df9bdb57758382b313f5a22c9c61084875c6396d50bbf49315f5b1926d142d74dfb8d31b40d993a383e0a158b15fea7a82234
@@ -27635,6 +27866,13 @@ __metadata:
languageName: node
linkType: hard
+"is-whitespace@npm:^0.3.0":
+ version: 0.3.0
+ resolution: "is-whitespace@npm:0.3.0"
+ checksum: 2f4ef13e0195170bbb587437133ef81ed9d6aec1c5e88f4c2b9055a18a1e70f75d9a9376f0cdae64f3c519e05e5f734d6b8f9682e5cb50384843480bade785ae
+ languageName: node
+ linkType: hard
+
"is-windows@npm:^0.2.0":
version: 0.2.0
resolution: "is-windows@npm:0.2.0"
@@ -28608,6 +28846,22 @@ __metadata:
languageName: node
linkType: hard
+"js-beautify@npm:^1.6.12":
+ version: 1.14.11
+ resolution: "js-beautify@npm:1.14.11"
+ dependencies:
+ config-chain: "npm:^1.1.13"
+ editorconfig: "npm:^1.0.3"
+ glob: "npm:^10.3.3"
+ nopt: "npm:^7.2.0"
+ bin:
+ css-beautify: js/bin/css-beautify.js
+ html-beautify: js/bin/html-beautify.js
+ js-beautify: js/bin/js-beautify.js
+ checksum: 23267f8e68a4cf190274906fbec98c4fa44025e1b7e1fa701480867c9ab6b2b90a1bb2b358cd487c34d735a1039c16bcb51f82d390bcc6384172cc540aa11c9b
+ languageName: node
+ linkType: hard
+
"js-cookie@npm:^2.2.1":
version: 2.2.1
resolution: "js-cookie@npm:2.2.1"
@@ -29167,6 +29421,15 @@ __metadata:
languageName: node
linkType: hard
+"kind-of@npm:^3.0.2":
+ version: 3.2.2
+ resolution: "kind-of@npm:3.2.2"
+ dependencies:
+ is-buffer: "npm:^1.1.5"
+ checksum: 7e34bc29d4b02c997f92f080de34ebb92033a96736bbb0bb2410e033a7e5ae6571f1fa37b2d7710018f95361473b816c604234197f4f203f9cf149d8ef1574d9
+ languageName: node
+ linkType: hard
+
"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2":
version: 6.0.3
resolution: "kind-of@npm:6.0.3"
@@ -32285,6 +32548,15 @@ __metadata:
languageName: node
linkType: hard
+"minimatch@npm:9.0.1":
+ version: 9.0.1
+ resolution: "minimatch@npm:9.0.1"
+ dependencies:
+ brace-expansion: "npm:^2.0.1"
+ checksum: aa043eb8822210b39888a5d0d28df0017b365af5add9bd522f180d2a6962de1cbbf1bdeacdb1b17f410dc3336bc8d76fb1d3e814cdc65d00c2f68e01f0010096
+ languageName: node
+ linkType: hard
+
"minimatch@npm:9.0.3, minimatch@npm:^9.0.0, minimatch@npm:^9.0.1":
version: 9.0.3
resolution: "minimatch@npm:9.0.3"
@@ -33222,7 +33494,7 @@ __metadata:
languageName: node
linkType: hard
-"nopt@npm:^7.0.0":
+"nopt@npm:^7.0.0, nopt@npm:^7.2.0":
version: 7.2.0
resolution: "nopt@npm:7.2.0"
dependencies:
@@ -35916,6 +36188,17 @@ __metadata:
languageName: node
linkType: hard
+"pretty@npm:2.0.0":
+ version: 2.0.0
+ resolution: "pretty@npm:2.0.0"
+ dependencies:
+ condense-newlines: "npm:^0.2.1"
+ extend-shallow: "npm:^2.0.1"
+ js-beautify: "npm:^1.6.12"
+ checksum: 2fcd72f331d0afae3893ba88a5c05f6fdd62b059cb309028aa3309fc8a90410d81dfe66ae95677bc6d6d4a68f3cc1a247c13e5872bd35686f99acb33acc51164
+ languageName: node
+ linkType: hard
+
"prettyjson@npm:^1.2.1":
version: 1.2.5
resolution: "prettyjson@npm:1.2.5"
@@ -36728,7 +37011,7 @@ __metadata:
languageName: node
linkType: hard
-"react-dom@npm:^18.2.0":
+"react-dom@npm:18.2.0, react-dom@npm:^18.2.0":
version: 18.2.0
resolution: "react-dom@npm:18.2.0"
dependencies:
@@ -37263,7 +37546,7 @@ __metadata:
languageName: node
linkType: hard
-"react@npm:^18, react@npm:^18.2.0":
+"react@npm:18.2.0, react@npm:^18, react@npm:^18.2.0":
version: 18.2.0
resolution: "react@npm:18.2.0"
dependencies:
@@ -41529,6 +41812,8 @@ __metadata:
"@octokit/graphql": "npm:^7.0.2"
"@ptc-org/nestjs-query-core": "npm:^4.2.0"
"@ptc-org/nestjs-query-typeorm": "npm:4.2.1-alpha.2"
+ "@react-email/components": "npm:0.0.12"
+ "@react-email/render": "npm:0.0.10"
"@sentry/node": "npm:^7.66.0"
"@sentry/profiling-node": "npm:^1.2.6"
"@sentry/react": "npm:^7.88.0"