Refactor backend folder structure (#4505)

* Refactor backend folder structure

Co-authored-by: Charles Bochet <charles@twenty.com>

* fix tests

* fix

* move yoga hooks

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Weiko
2024-03-15 18:37:09 +01:00
committed by GitHub
parent afb9b3e375
commit 2c09096edd
523 changed files with 1386 additions and 1856 deletions

View File

@ -0,0 +1,5 @@
import { SendMailOptions } from 'nodemailer';
export interface EmailDriver {
send(sendMailOptions: SendMailOptions): Promise<void>;
}

View File

@ -0,0 +1,20 @@
import { Logger } from '@nestjs/common';
import { SendMailOptions } from 'nodemailer';
import { EmailDriver } from 'src/engine/integrations/email/drivers/interfaces/email-driver.interface';
export class LoggerDriver implements EmailDriver {
private readonly logger = new Logger(LoggerDriver.name);
async send(sendMailOptions: SendMailOptions): Promise<void> {
const info =
`Sent email to: ${sendMailOptions.to}\n` +
`From: ${sendMailOptions.from}\n` +
`Subject: ${sendMailOptions.subject}\n` +
`Content Text: ${sendMailOptions.text}\n` +
`Content HTML: ${sendMailOptions.html}`;
this.logger.log(info);
}
}

View File

@ -0,0 +1,26 @@
import { Logger } from '@nestjs/common';
import { createTransport, Transporter, SendMailOptions } from 'nodemailer';
import SMTPConnection from 'nodemailer/lib/smtp-connection';
import { EmailDriver } from 'src/engine/integrations/email/drivers/interfaces/email-driver.interface';
export class SmtpDriver implements EmailDriver {
private readonly logger = new Logger(SmtpDriver.name);
private transport: Transporter;
constructor(options: SMTPConnection.Options) {
this.transport = createTransport(options);
}
async send(sendMailOptions: SendMailOptions): Promise<void> {
this.transport
.sendMail(sendMailOptions)
.then(() =>
this.logger.log(`Email to '${sendMailOptions.to}' successfully sent`),
)
.catch((err) =>
this.logger.error(`sending email to '${sendMailOptions.to}': ${err}`),
);
}
}

View File

@ -0,0 +1,16 @@
import { Injectable } from '@nestjs/common';
import { SendMailOptions } from 'nodemailer';
import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface';
import { EmailSenderService } from 'src/engine/integrations/email/email-sender.service';
@Injectable()
export class EmailSenderJob implements MessageQueueJob<SendMailOptions> {
constructor(private readonly emailSenderService: EmailSenderService) {}
async handle(data: SendMailOptions): Promise<void> {
await this.emailSenderService.send(data);
}
}

View File

@ -0,0 +1,16 @@
import { Inject, Injectable } from '@nestjs/common';
import { SendMailOptions } from 'nodemailer';
import { EmailDriver } from 'src/engine/integrations/email/drivers/interfaces/email-driver.interface';
import { EMAIL_DRIVER } from 'src/engine/integrations/email/email.constants';
@Injectable()
export class EmailSenderService implements EmailDriver {
constructor(@Inject(EMAIL_DRIVER) private driver: EmailDriver) {}
async send(sendMailOptions: SendMailOptions): Promise<void> {
await this.driver.send(sendMailOptions);
}
}

View File

@ -0,0 +1 @@
export const EMAIL_DRIVER = Symbol('EMAIL_DRIVER');

View File

@ -0,0 +1,40 @@
import {
EmailDriver,
EmailModuleOptions,
} from 'src/engine/integrations/email/interfaces/email.interface';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
export const emailModuleFactory = (
environmentService: EnvironmentService,
): EmailModuleOptions => {
const driver = environmentService.get('EMAIL_DRIVER');
switch (driver) {
case EmailDriver.Logger: {
return;
}
case EmailDriver.Smtp: {
const host = environmentService.get('EMAIL_SMTP_HOST');
const port = environmentService.get('EMAIL_SMTP_PORT');
const user = environmentService.get('EMAIL_SMTP_USER');
const pass = environmentService.get('EMAIL_SMTP_PASSWORD');
if (!(host && port)) {
throw new Error(
`${driver} email driver requires host: ${host} and port: ${port} to be defined, check your .env file`,
);
}
const auth = user && pass ? { user, pass } : undefined;
if (auth) {
return { host, port, auth };
}
return { host, port };
}
default:
throw new Error(`Invalid email driver (${driver}), check your .env file`);
}
};

View File

@ -0,0 +1,30 @@
import { DynamicModule, Global } from '@nestjs/common';
import { EmailModuleAsyncOptions } from 'src/engine/integrations/email/interfaces/email.interface';
import { EMAIL_DRIVER } from 'src/engine/integrations/email/email.constants';
import { LoggerDriver } from 'src/engine/integrations/email/drivers/logger.driver';
import { SmtpDriver } from 'src/engine/integrations/email/drivers/smtp.driver';
import { EmailService } from 'src/engine/integrations/email/email.service';
import { EmailSenderService } from 'src/engine/integrations/email/email-sender.service';
@Global()
export class EmailModule {
static forRoot(options: EmailModuleAsyncOptions): DynamicModule {
const provider = {
provide: EMAIL_DRIVER,
useFactory: (...args: any[]) => {
const config = options.useFactory(...args);
return config ? new SmtpDriver(config) : new LoggerDriver();
},
inject: options.inject || [],
};
return {
module: EmailModule,
providers: [EmailSenderService, EmailService, provider],
exports: [EmailSenderService, EmailService],
};
}
}

View File

@ -0,0 +1,23 @@
import { Inject, Injectable } from '@nestjs/common';
import { SendMailOptions } from 'nodemailer';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
import { EmailSenderJob } from 'src/engine/integrations/email/email-sender.job';
@Injectable()
export class EmailService {
constructor(
@Inject(MessageQueue.emailQueue)
private readonly messageQueueService: MessageQueueService,
) {}
async send(sendMailOptions: SendMailOptions): Promise<void> {
await this.messageQueueService.add<SendMailOptions>(
EmailSenderJob.name,
sendMailOptions,
{ retryLimit: 3 },
);
}
}

View File

@ -0,0 +1,15 @@
import { FactoryProvider, ModuleMetadata } from '@nestjs/common';
import SMTPConnection from 'nodemailer/lib/smtp-connection';
export enum EmailDriver {
Logger = 'logger',
Smtp = 'smtp',
}
export type EmailModuleOptions = SMTPConnection.Options | undefined;
export type EmailModuleAsyncOptions = {
useFactory: (...args: any[]) => EmailModuleOptions;
} & Pick<ModuleMetadata, 'imports'> &
Pick<FactoryProvider, 'inject'>;