diff --git a/api/src/setting/repositories/setting.repository.ts b/api/src/setting/repositories/setting.repository.ts index 81d74ca8..e0523662 100644 --- a/api/src/setting/repositories/setting.repository.ts +++ b/api/src/setting/repositories/setting.repository.ts @@ -7,24 +7,19 @@ */ import { Injectable } from '@nestjs/common'; -import { - EventEmitter2, - IHookSettingsGroupLabelOperationMap, -} from '@nestjs/event-emitter'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { InjectModel } from '@nestjs/mongoose'; import { Document, FilterQuery, Model, - Query, Types, UpdateQuery, UpdateWithAggregationPipeline, } from 'mongoose'; import { I18nService } from '@/i18n/services/i18n.service'; -import { BaseRepository, EHook } from '@/utils/generics/base-repository'; -import { TFilterQuery } from '@/utils/types/filter.types'; +import { BaseRepository } from '@/utils/generics/base-repository'; import { Setting } from '../schemas/setting.schema'; import { SettingType } from '../schemas/types'; @@ -42,64 +37,24 @@ export class SettingRepository extends BaseRepository { async preCreateValidate( doc: Document & Setting & { _id: Types.ObjectId }, - filterCriteria: FilterQuery, - updates: UpdateWithAggregationPipeline | UpdateQuery, ) { this.validateSettingValue(doc.type, doc.value); - if (filterCriteria && updates) { - this.eventEmitter.emit( - `hook:setting:${EHook.preUpdateValidate}`, - filterCriteria, - updates, - ); - } } async preUpdateValidate( - criteria: string | TFilterQuery, - dto: UpdateQuery, - filterCriteria: FilterQuery, + criteria: FilterQuery, updates: UpdateWithAggregationPipeline | UpdateQuery, ): Promise { - const payload = dto.$set ? dto.$set : dto; - if (typeof payload.value !== 'undefined') { - const { type } = - 'type' in payload ? payload : await this.findOne(criteria); - this.validateSettingValue(type, payload.value); - this.eventEmitter.emit( - `hook:setting:${EHook.preUpdateValidate}`, - filterCriteria, - updates, - ); + if (!Array.isArray(updates)) { + const payload = updates.$set; + if (typeof payload.value !== 'undefined') { + const { type } = + 'type' in payload ? payload : await this.findOne(criteria); + this.validateSettingValue(type, payload.value); + } } } - /** - * Emits an event after a `Setting` has been updated. - * - * This method is used to synchronize global settings by emitting an event - * based on the `group` and `label` of the `Setting`. - * - * @param _query The Mongoose query object used to find and update the document. - * @param setting The updated `Setting` object. - */ - async postUpdate( - _query: Query< - Document, - Document, - unknown, - Setting, - 'findOneAndUpdate' - >, - setting: Setting, - ) { - const group = setting.group as keyof IHookSettingsGroupLabelOperationMap; - const label = setting.label as '*'; - - // Sync global settings var - this.eventEmitter.emit(`hook:${group}:${label}`, setting); - } - /** * Validates the `Setting` document after it has been retrieved. * diff --git a/api/src/utils/generics/base-repository.spec.ts b/api/src/utils/generics/base-repository.spec.ts index ef051aba..06241861 100644 --- a/api/src/utils/generics/base-repository.spec.ts +++ b/api/src/utils/generics/base-repository.spec.ts @@ -209,14 +209,10 @@ describe('BaseRepository', () => { await dummyRepository.updateOne(created.id, mockUpdate); expect(spyPreUpdateValidate).toHaveBeenCalledWith( - created.id, - mockUpdate, mockGetFilterValue, mockGetUpdateValue, ); expect(spyPostUpdateValidate).toHaveBeenCalledWith( - created.id, - mockUpdate, mockGetFilterValue, mockGetUpdateValue, ); @@ -261,8 +257,6 @@ describe('BaseRepository', () => { ).rejects.toThrow('Mocked error while validating dummy'); expect(spyPreUpdateValidate).toHaveBeenCalledWith( - created.id, - mockUpdate, mockGetFilterValue, mockGetUpdateValue, ); diff --git a/api/src/utils/generics/base-repository.ts b/api/src/utils/generics/base-repository.ts index 0fc1d270..c286dae0 100644 --- a/api/src/utils/generics/base-repository.ts +++ b/api/src/utils/generics/base-repository.ts @@ -39,19 +39,20 @@ export type DeleteResult = { }; export enum EHook { + preCreateValidate = 'preCreateValidate', preCreate = 'preCreate', + preUpdateValidate = 'preUpdateValidate', preUpdate = 'preUpdate', preUpdateMany = 'preUpdateMany', preDelete = 'preDelete', - preCreateValidate = 'preCreateValidate', + postCreateValidate = 'postCreateValidate', postCreate = 'postCreate', + postUpdateValidate = 'postUpdateValidate', postUpdate = 'postUpdate', postUpdateMany = 'postUpdateMany', postDelete = 'postDelete', - postCreateValidate = 'postCreateValidate', - preUpdateValidate = 'preUpdateValidate', - postUpdateValidate = 'postUpdateValidate', } + // ! ------------------------------------ Note -------------------------------------------- // Methods like `update()`, `updateOne()`, `updateMany()`, `findOneAndUpdate()`, // `findByIdAndUpdate()`, `findOneAndReplace()`, `findOneAndDelete()`, and `findByIdAndDelete()` @@ -476,8 +477,21 @@ export abstract class BaseRepository< ); const filterCriteria = query.getFilter(); const queryUpdates = query.getUpdate(); - await this.preUpdateValidate(criteria, dto, filterCriteria, queryUpdates); - await this.postUpdateValidate(criteria, dto, filterCriteria, queryUpdates); + + await this.preUpdateValidate(filterCriteria, queryUpdates); + this.emitter.emit( + this.getEventName(EHook.preUpdateValidate), + filterCriteria, + queryUpdates, + ); + + await this.postUpdateValidate(filterCriteria, queryUpdates); + this.emitter.emit( + this.getEventName(EHook.postUpdateValidate), + filterCriteria, + queryUpdates, + ); + return await this.executeOne(query, this.cls); } @@ -512,18 +526,14 @@ export abstract class BaseRepository< // Nothing ... } - async preUpdateValidate>( - _criteria: string | TFilterQuery, - _dto: UpdateQuery, + async preUpdateValidate( _filterCriteria: FilterQuery, _updates: UpdateWithAggregationPipeline | UpdateQuery, ): Promise { // Nothing ... } - async postUpdateValidate>( - _criteria: string | TFilterQuery, - _dto: UpdateQuery, + async postUpdateValidate( _filterCriteria: FilterQuery, _updates: UpdateWithAggregationPipeline | UpdateQuery, ): Promise { diff --git a/api/types/event-emitter.d.ts b/api/types/event-emitter.d.ts index a0245507..5f5972c5 100644 --- a/api/types/event-emitter.d.ts +++ b/api/types/event-emitter.d.ts @@ -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). */ -import type { Document, FilterQuery, Query } from 'mongoose'; +import type { Document, Query } from 'mongoose'; import { type Socket } from 'socket.io'; import { type BotStats } from '@/analytics/schemas/bot-stats.schema'; @@ -179,11 +179,13 @@ declare module '@nestjs/event-emitter' { type EventNamespaces = keyof IHookEntityOperationMap; /* pre hooks */ - type TPreValidate = THydratedDocument; + type TPreCreateValidate = THydratedDocument; type TPreCreate = THydratedDocument; - type TPreUpdate = TFilterQuery & object; + type TPreUpdateValidate = FilterQuery; + + type TPreUpdate = TFilterQuery; type TPreDelete = Query< DeleteResult, @@ -195,27 +197,27 @@ declare module '@nestjs/event-emitter' { >; type TPreUnion = - | TPreValidate + | TPreCreateValidate | TPreCreate + | TPreUpdateValidate | TPreUpdate | TPreDelete; /* post hooks */ - type TPostValidate = THydratedDocument; + type TPostCreateValidate = THydratedDocument; type TPostCreate = THydratedDocument; + type TPostUpdateValidate = FilterQuery; + type TPostUpdate = THydratedDocument; - type TPreUpdateValidate = FilterQuery; - - type TPostUpdateValidate = THydratedDocument; - type TPostDelete = DeleteResult; type TPostUnion = - | TPostValidate + | TPostCreateValidate | TPostCreate + | TPostUpdateValidate | TPostUpdate | TPostDelete; @@ -251,11 +253,14 @@ declare module '@nestjs/event-emitter' { T = IHookEntityOperationMap[E]['schema'], > = | { - [EHook.preCreateValidate]: TPreValidate; + [EHook.preCreateValidate]: TPreCreateValidate; } | { [EHook.preCreate]: TPreCreate; } + | { + [EHook.preUpdateValidate]: TPreUpdateValidate; + } | { [EHook.preUpdate]: TPreUpdate; } @@ -263,22 +268,19 @@ declare module '@nestjs/event-emitter' { [EHook.preDelete]: TPreDelete; } | { - [EHook.postCreateValidate]: TPostValidate; + [EHook.postCreateValidate]: TPostCreateValidate; } | { [EHook.postCreate]: TPostCreate; } + | { + [EHook.postUpdateValidate]: TPostUpdateValidate; + } | { [EHook.postUpdate]: TPostUpdate; } | { [EHook.postDelete]: TPostDelete; - } - | { - [EHook.preUpdateValidate]: TPreUpdateValidate; - } - | { - [EHook.postUpdateValidate]: TPostUpdateValidate; }; type TNormalizedHook = Extract<