Merge pull request #1145 from Hexastack/1144-issue---remove-optional-di

fix(api): make optional DI required
This commit is contained in:
Med Marrouchi 2025-06-19 10:08:45 +01:00 committed by GitHub
commit 078e70d95a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 83 additions and 113 deletions

View File

@ -8,7 +8,7 @@
import { Readable, Stream } from 'stream'; import { Readable, Stream } from 'stream';
import { Injectable, Optional, StreamableFile } from '@nestjs/common'; import { Injectable, StreamableFile } from '@nestjs/common';
import { HelperService } from '@/helper/helper.service'; import { HelperService } from '@/helper/helper.service';
import { HelperType } from '@/helper/types'; import { HelperType } from '@/helper/types';
@ -22,7 +22,7 @@ import { Attachment } from '../schemas/attachment.schema';
export class AttachmentService extends BaseService<Attachment> { export class AttachmentService extends BaseService<Attachment> {
constructor( constructor(
readonly repository: AttachmentRepository, readonly repository: AttachmentRepository,
@Optional() private readonly helperService: HelperService, private readonly helperService: HelperService,
) { ) {
super(repository); super(repository);
} }

View File

@ -6,7 +6,7 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/ */
import { ForbiddenException, Injectable, Optional } from '@nestjs/common'; import { ForbiddenException, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose'; import { InjectModel } from '@nestjs/mongoose';
import { Document, Model, Query } from 'mongoose'; import { Document, Model, Query } from 'mongoose';
@ -26,7 +26,7 @@ export class CategoryRepository extends BaseRepository<
> { > {
constructor( constructor(
@InjectModel(Category.name) readonly model: Model<Category>, @InjectModel(Category.name) readonly model: Model<Category>,
@Optional() private readonly blockService?: BlockService, private readonly blockService: BlockService,
) { ) {
super(model, Category); super(model, Category);
} }
@ -49,7 +49,7 @@ export class CategoryRepository extends BaseRepository<
criteria: TFilterQuery<Category>, criteria: TFilterQuery<Category>,
) { ) {
if (criteria._id) { if (criteria._id) {
const block = await this.blockService?.findOneAndPopulate({ const block = await this.blockService.findOneAndPopulate({
category: criteria._id, category: criteria._id,
}); });

View File

@ -10,7 +10,6 @@ import {
ForbiddenException, ForbiddenException,
Injectable, Injectable,
NotFoundException, NotFoundException,
Optional,
} from '@nestjs/common'; } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose'; import { InjectModel } from '@nestjs/mongoose';
import { Document, Model, Query } from 'mongoose'; import { Document, Model, Query } from 'mongoose';
@ -29,14 +28,11 @@ export class ContextVarRepository extends BaseRepository<
never, never,
ContextVarDto ContextVarDto
> { > {
private readonly blockService: BlockService;
constructor( constructor(
@InjectModel(ContextVar.name) readonly model: Model<ContextVar>, @InjectModel(ContextVar.name) readonly model: Model<ContextVar>,
@Optional() blockService?: BlockService, private readonly blockService: BlockService,
) { ) {
super(model, ContextVar); super(model, ContextVar);
if (blockService) this.blockService = blockService;
} }
/** /**
@ -65,7 +61,7 @@ export class ContextVarRepository extends BaseRepository<
throw new NotFoundException(`Context var with ID ${id} not found.`); throw new NotFoundException(`Context var with ID ${id} not found.`);
} }
const associatedBlocks = await this.blockService?.find({ const associatedBlocks = await this.blockService.find({
capture_vars: { $elemMatch: { context_var: contextVar.name } }, capture_vars: { $elemMatch: { context_var: contextVar.name } },
}); });

View File

@ -6,11 +6,7 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/ */
import { import { Injectable, InternalServerErrorException } from '@nestjs/common';
Injectable,
InternalServerErrorException,
Optional,
} from '@nestjs/common';
import { BaseService } from '@/utils/generics/base-service'; import { BaseService } from '@/utils/generics/base-service';
import { import {
@ -36,14 +32,11 @@ export class MessageService extends BaseService<
MessagePopulate, MessagePopulate,
MessageFull MessageFull
> { > {
private readonly gateway: WebsocketGateway;
constructor( constructor(
private readonly messageRepository: MessageRepository, private readonly messageRepository: MessageRepository,
@Optional() gateway?: WebsocketGateway, private readonly gateway: WebsocketGateway,
) { ) {
super(messageRepository); super(messageRepository);
if (gateway) this.gateway = gateway;
} }
/** /**

View File

@ -6,11 +6,7 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/ */
import { import { Injectable, InternalServerErrorException } from '@nestjs/common';
Injectable,
InternalServerErrorException,
Optional,
} from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter'; import { OnEvent } from '@nestjs/event-emitter';
import mime from 'mime'; import mime from 'mime';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
@ -53,15 +49,12 @@ export class SubscriberService extends BaseService<
SubscriberFull, SubscriberFull,
SubscriberDto SubscriberDto
> { > {
private readonly gateway: WebsocketGateway;
constructor( constructor(
readonly repository: SubscriberRepository, readonly repository: SubscriberRepository,
protected readonly attachmentService: AttachmentService, protected readonly attachmentService: AttachmentService,
@Optional() gateway?: WebsocketGateway, private readonly gateway: WebsocketGateway,
) { ) {
super(repository); super(repository);
if (gateway) this.gateway = gateway;
} }
/** /**

View File

@ -6,7 +6,7 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/ */
import { ForbiddenException, Injectable, Optional } from '@nestjs/common'; import { ForbiddenException, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose'; import { InjectModel } from '@nestjs/mongoose';
import { Document, Model, Query } from 'mongoose'; import { Document, Model, Query } from 'mongoose';
@ -28,7 +28,7 @@ export class ContentTypeRepository extends BaseRepository<
constructor( constructor(
@InjectModel(ContentType.name) readonly model: Model<ContentType>, @InjectModel(ContentType.name) readonly model: Model<ContentType>,
@InjectModel(Content.name) private readonly contentModel: Model<Content>, @InjectModel(Content.name) private readonly contentModel: Model<Content>,
@Optional() private readonly blockService?: BlockService, private readonly blockService: BlockService,
) { ) {
super(model, ContentType); super(model, ContentType);
} }
@ -53,7 +53,7 @@ export class ContentTypeRepository extends BaseRepository<
criteria: TFilterQuery<ContentType>, criteria: TFilterQuery<ContentType>,
) { ) {
if (criteria._id) { if (criteria._id) {
const associatedBlock = await this.blockService?.findOne({ const associatedBlock = await this.blockService.findOne({
'options.content.entity': criteria._id, 'options.content.entity': criteria._id,
}); });
if (associatedBlock) { if (associatedBlock) {

View File

@ -12,7 +12,6 @@ import {
Inject, Inject,
Injectable, Injectable,
InternalServerErrorException, InternalServerErrorException,
Optional,
} from '@nestjs/common'; } from '@nestjs/common';
import { JwtService, JwtSignOptions } from '@nestjs/jwt'; import { JwtService, JwtSignOptions } from '@nestjs/jwt';
@ -41,7 +40,7 @@ export class InvitationService extends BaseService<
@Inject(JwtService) private readonly jwtService: JwtService, @Inject(JwtService) private readonly jwtService: JwtService,
protected readonly i18n: I18nService, protected readonly i18n: I18nService,
public readonly languageService: LanguageService, public readonly languageService: LanguageService,
@Optional() private readonly mailerService?: MailerService, private readonly mailerService: MailerService,
) { ) {
super(repository); super(repository);
} }
@ -61,31 +60,28 @@ export class InvitationService extends BaseService<
*/ */
async create(dto: InvitationCreateDto): Promise<Invitation> { async create(dto: InvitationCreateDto): Promise<Invitation> {
const jwt = await this.sign({ ...dto }); const jwt = await this.sign({ ...dto });
if (this.mailerService) { try {
try { const defaultLanguage = await this.languageService.getDefaultLanguage();
const defaultLanguage = await this.languageService.getDefaultLanguage(); await this.mailerService.sendMail({
await this.mailerService.sendMail({ to: dto.email,
to: dto.email, template: 'invitation.mjml',
template: 'invitation.mjml', context: {
context: { appName: config.parameters.appName,
appName: config.parameters.appName, appUrl: config.uiBaseUrl,
appUrl: config.uiBaseUrl, token: jwt,
token: jwt, // TODO: Which language should we use?
// TODO: Which language should we use? t: (key: string) => this.i18n.t(key, { lang: defaultLanguage.code }),
t: (key: string) => },
this.i18n.t(key, { lang: defaultLanguage.code }), subject: this.i18n.t('invitation_subject'),
}, });
subject: this.i18n.t('invitation_subject'), } catch (e) {
}); this.logger.error(
} catch (e) { 'Could not send email',
this.logger.error( e.message,
'Could not send email', e.stack,
e.message, 'InvitationService',
e.stack, );
'InvitationService', throw new InternalServerErrorException('Could not send email');
);
throw new InternalServerErrorException('Could not send email');
}
} }
const newInvitation = await super.create({ ...dto, token: jwt }); const newInvitation = await super.create({ ...dto, token: jwt });
return { ...newInvitation, token: jwt }; return { ...newInvitation, token: jwt };

View File

@ -14,7 +14,6 @@ import {
Injectable, Injectable,
InternalServerErrorException, InternalServerErrorException,
NotFoundException, NotFoundException,
Optional,
UnauthorizedException, UnauthorizedException,
} from '@nestjs/common'; } from '@nestjs/common';
import { JwtService, JwtSignOptions } from '@nestjs/jwt'; import { JwtService, JwtSignOptions } from '@nestjs/jwt';
@ -37,7 +36,7 @@ export class PasswordResetService {
private readonly userService: UserService, private readonly userService: UserService,
public readonly i18n: I18nService, public readonly i18n: I18nService,
public readonly languageService: LanguageService, public readonly languageService: LanguageService,
@Optional() private readonly mailerService?: MailerService, private readonly mailerService: MailerService,
) {} ) {}
public readonly jwtSignOptions: JwtSignOptions = { public readonly jwtSignOptions: JwtSignOptions = {
@ -60,31 +59,28 @@ export class PasswordResetService {
} }
const jwt = await this.sign({ ...dto }); const jwt = await this.sign({ ...dto });
if (this.mailerService) { try {
try { const defaultLanguage = await this.languageService.getDefaultLanguage();
const defaultLanguage = await this.languageService.getDefaultLanguage(); await this.mailerService.sendMail({
await this.mailerService.sendMail({ to: dto.email,
to: dto.email, template: 'password_reset.mjml',
template: 'password_reset.mjml', context: {
context: { appName: config.parameters.appName,
appName: config.parameters.appName, appUrl: config.uiBaseUrl,
appUrl: config.uiBaseUrl, token: jwt,
token: jwt, first_name: user.first_name,
first_name: user.first_name, t: (key: string) => this.i18n.t(key, { lang: defaultLanguage.code }),
t: (key: string) => },
this.i18n.t(key, { lang: defaultLanguage.code }), subject: this.i18n.t('password_reset_subject'),
}, });
subject: this.i18n.t('password_reset_subject'), } catch (e) {
}); this.logger.error(
} catch (e) { 'Could not send email',
this.logger.error( e.message,
'Could not send email', e.stack,
e.message, 'InvitationService',
e.stack, );
'InvitationService', throw new InternalServerErrorException('Could not send email');
);
throw new InternalServerErrorException('Could not send email');
}
} }
// TODO: hash the token before saving it // TODO: hash the token before saving it

View File

@ -12,7 +12,6 @@ import {
Inject, Inject,
Injectable, Injectable,
InternalServerErrorException, InternalServerErrorException,
Optional,
UnauthorizedException, UnauthorizedException,
} from '@nestjs/common'; } from '@nestjs/common';
import { JwtService, JwtSignOptions } from '@nestjs/jwt'; import { JwtService, JwtSignOptions } from '@nestjs/jwt';
@ -40,7 +39,7 @@ export class ValidateAccountService {
private logger: LoggerService, private logger: LoggerService,
private readonly i18n: I18nService, private readonly i18n: I18nService,
private readonly languageService: LanguageService, private readonly languageService: LanguageService,
@Optional() private readonly mailerService?: MailerService, private readonly mailerService: MailerService,
) {} ) {}
/** /**
@ -77,31 +76,28 @@ export class ValidateAccountService {
) { ) {
const confirmationToken = await this.sign({ email: dto.email }); const confirmationToken = await this.sign({ email: dto.email });
if (this.mailerService) { try {
try { const defaultLanguage = await this.languageService.getDefaultLanguage();
const defaultLanguage = await this.languageService.getDefaultLanguage(); await this.mailerService.sendMail({
await this.mailerService.sendMail({ to: dto.email,
to: dto.email, template: 'account_confirmation.mjml',
template: 'account_confirmation.mjml', context: {
context: { appName: config.parameters.appName,
appName: config.parameters.appName, appUrl: config.uiBaseUrl,
appUrl: config.uiBaseUrl, token: confirmationToken,
token: confirmationToken, first_name: dto.first_name,
first_name: dto.first_name, t: (key: string) => this.i18n.t(key, { lang: defaultLanguage.code }),
t: (key: string) => },
this.i18n.t(key, { lang: defaultLanguage.code }), subject: this.i18n.t('account_confirmation_subject'),
}, });
subject: this.i18n.t('account_confirmation_subject'), } catch (e) {
}); this.logger.error(
} catch (e) { 'Could not send email',
this.logger.error( e.message,
'Could not send email', e.stack,
e.message, 'ValidateAccount',
e.stack, );
'ValidateAccount', throw new InternalServerErrorException('Could not send email');
);
throw new InternalServerErrorException('Could not send email');
}
} }
} }