mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
Merge pull request #1135 from Hexastack/1134-issue---api-make-sure-hookentityprepostupdate-is-used-across-the-board
fix(api): resolve predefined update hooks bug
This commit is contained in:
commit
c5abe12971
@ -228,4 +228,33 @@ describe('NlpEntityRepository', () => {
|
||||
expect(nlpEntity).toEqualPayload(result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postUpdate', () => {
|
||||
it('should update an NlpEntity and trigger a postUpdate event', async () => {
|
||||
jest.spyOn(nlpService, 'handleEntityPostUpdate');
|
||||
jest.spyOn(llmNluHelper, 'updateEntity');
|
||||
|
||||
nlpEntityRepository.eventEmitter.once(
|
||||
'hook:nlpEntity:postUpdate',
|
||||
async (...[query, updated]) => {
|
||||
await nlpService.handleEntityPostUpdate(query, updated);
|
||||
expect(llmNluHelper.updateEntity).toHaveBeenCalledWith(updated);
|
||||
},
|
||||
);
|
||||
|
||||
const updatedNlpEntity = await nlpEntityRepository.updateOne(
|
||||
{
|
||||
name: 'test2',
|
||||
},
|
||||
{ value: 'test3' },
|
||||
);
|
||||
|
||||
expect(nlpService.handleEntityPostUpdate).toHaveBeenCalledTimes(1);
|
||||
expect(llmNluHelper.updateEntity).toHaveBeenCalledTimes(1);
|
||||
|
||||
const result = await nlpEntityRepository.findOne(updatedNlpEntity.id);
|
||||
|
||||
expect(result).toEqualPayload(updatedNlpEntity);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { Document, Model, Query } from 'mongoose';
|
||||
import { Model } from 'mongoose';
|
||||
|
||||
import { BaseRepository } from '@/utils/generics/base-repository';
|
||||
|
||||
@ -30,28 +30,4 @@ export class NlpEntityRepository extends BaseRepository<
|
||||
constructor(@InjectModel(NlpEntity.name) readonly model: Model<NlpEntity>) {
|
||||
super(model, NlpEntity, NLP_ENTITY_POPULATE, NlpEntityFull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-update hook that triggers after an NLP entity is updated.
|
||||
* Emits an event to notify other parts of the system about the update.
|
||||
* Bypasses built-in entities.
|
||||
*
|
||||
* @param query - The query used to find and update the entity.
|
||||
* @param updated - The updated NLP entity document.
|
||||
*/
|
||||
async postUpdate(
|
||||
_query: Query<
|
||||
Document<NlpEntity, any, any>,
|
||||
Document<NlpEntity, any, any>,
|
||||
unknown,
|
||||
NlpEntity,
|
||||
'findOneAndUpdate'
|
||||
>,
|
||||
updated: NlpEntity,
|
||||
): Promise<void> {
|
||||
if (!updated?.builtin) {
|
||||
// Bypass builtin entities (probably fixtures)
|
||||
this.eventEmitter.emit('hook:nlpEntity:update', updated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,4 +250,34 @@ describe('NlpValueRepository', () => {
|
||||
expect(nlpValue).toEqualPayload(result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postUpdate', () => {
|
||||
it('should update an NlpValue and trigger a postUpdate event', async () => {
|
||||
jest.spyOn(nlpService, 'handleValuePostUpdate');
|
||||
jest.spyOn(llmNluHelper, 'updateValue');
|
||||
|
||||
nlpValueRepository.eventEmitter.once(
|
||||
'hook:nlpValue:postUpdate',
|
||||
async (...[query, updated]) => {
|
||||
await nlpService.handleValuePostUpdate(query, updated);
|
||||
|
||||
expect(llmNluHelper.updateValue).toHaveBeenCalledWith(updated);
|
||||
},
|
||||
);
|
||||
|
||||
const updatedNlpValue = await nlpValueRepository.updateOne(
|
||||
{
|
||||
value: 'test',
|
||||
},
|
||||
{ value: 'test2' },
|
||||
);
|
||||
|
||||
expect(nlpService.handleValuePostUpdate).toHaveBeenCalledTimes(1);
|
||||
expect(llmNluHelper.updateValue).toHaveBeenCalledTimes(1);
|
||||
|
||||
const result = await nlpValueRepository.findOne(updatedNlpValue.id);
|
||||
|
||||
expect(result).toEqualPayload(updatedNlpValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -9,14 +9,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import {
|
||||
Document,
|
||||
Model,
|
||||
PipelineStage,
|
||||
Query,
|
||||
SortOrder,
|
||||
Types,
|
||||
} from 'mongoose';
|
||||
import { Model, PipelineStage, SortOrder, Types } from 'mongoose';
|
||||
|
||||
import { BaseRepository } from '@/utils/generics/base-repository';
|
||||
import { PageQueryDto } from '@/utils/pagination/pagination-query.dto';
|
||||
@ -45,28 +38,6 @@ export class NlpValueRepository extends BaseRepository<
|
||||
super(model, NlpValue, NLP_VALUE_POPULATE, NlpValueFull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an event after an NLP value is updated, bypassing built-in values.
|
||||
*
|
||||
* @param query - The query that was used to update the NLP value.
|
||||
* @param updated - The updated NLP value document.
|
||||
*/
|
||||
async postUpdate(
|
||||
_query: Query<
|
||||
Document<NlpValue, any, any>,
|
||||
Document<NlpValue, any, any>,
|
||||
unknown,
|
||||
NlpValue,
|
||||
'findOneAndUpdate'
|
||||
>,
|
||||
updated: NlpValue,
|
||||
): Promise<void> {
|
||||
if (!updated?.builtin) {
|
||||
// Bypass builtin entities (probably fixtures)
|
||||
this.eventEmitter.emit('hook:nlpValue:update', updated);
|
||||
}
|
||||
}
|
||||
|
||||
private getSortDirection(sortOrder: SortOrder) {
|
||||
return typeof sortOrder === 'number'
|
||||
? sortOrder
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Document, Query } from 'mongoose';
|
||||
|
||||
import { HelperService } from '@/helper/helper.service';
|
||||
import { HelperType, NLU } from '@/helper/types';
|
||||
@ -96,17 +97,30 @@ export class NlpService {
|
||||
*
|
||||
* @param entity - The NLP entity to be updated.
|
||||
*/
|
||||
@OnEvent('hook:nlpEntity:update')
|
||||
async handleEntityUpdate(entity: NlpEntity) {
|
||||
@OnEvent('hook:nlpEntity:postUpdate')
|
||||
async handleEntityPostUpdate(
|
||||
_query: Query<
|
||||
Document<NlpEntity>,
|
||||
Document<NlpEntity>,
|
||||
unknown,
|
||||
NlpEntity,
|
||||
'findOneAndUpdate'
|
||||
>,
|
||||
updated: NlpEntity,
|
||||
) {
|
||||
if (!updated?.builtin) {
|
||||
// Synchonize new entity with NLP provider
|
||||
try {
|
||||
const helper = await this.helperService.getDefaultNluHelper();
|
||||
await helper.updateEntity(entity);
|
||||
this.logger.debug('Updated entity successfully synced!', entity);
|
||||
const helper = await this.helperService.getDefaultHelper(
|
||||
HelperType.NLU,
|
||||
);
|
||||
await helper.updateEntity(updated);
|
||||
this.logger.debug('Updated entity successfully synced!', updated);
|
||||
} catch (err) {
|
||||
this.logger.error('Unable to sync updated entity', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Before deleting a `nlpEntity`, this method deletes the related `nlpValue` and `nlpSampleEntity`. Synchronizes the deletion with the external NLP provider
|
||||
@ -180,17 +194,30 @@ export class NlpService {
|
||||
*
|
||||
* @param value - The NLP value to be updated.
|
||||
*/
|
||||
@OnEvent('hook:nlpValue:update')
|
||||
async handleValueUpdate(value: NlpValue) {
|
||||
@OnEvent('hook:nlpValue:postUpdate')
|
||||
async handleValuePostUpdate(
|
||||
_query: Query<
|
||||
Document<NlpValue, any, any>,
|
||||
Document<NlpValue, any, any>,
|
||||
unknown,
|
||||
NlpValue,
|
||||
'findOneAndUpdate'
|
||||
>,
|
||||
updated: NlpValue,
|
||||
) {
|
||||
if (!updated?.builtin) {
|
||||
// Synchonize new value with NLP provider
|
||||
try {
|
||||
const helper = await this.helperService.getDefaultNluHelper();
|
||||
await helper.updateValue(value);
|
||||
this.logger.debug('Updated value successfully synced!', value);
|
||||
const helper = await this.helperService.getDefaultHelper(
|
||||
HelperType.NLU,
|
||||
);
|
||||
await helper.updateValue(updated);
|
||||
this.logger.debug('Updated value successfully synced!', updated);
|
||||
} catch (err) {
|
||||
this.logger.error('Unable to sync updated value', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Before deleting a `nlpValue`, this method deletes the related `nlpSampleEntity`. Synchronizes the deletion with the external NLP provider
|
||||
|
7
api/types/event-emitter.d.ts
vendored
7
api/types/event-emitter.d.ts
vendored
@ -132,10 +132,10 @@ declare module '@nestjs/event-emitter' {
|
||||
menu: TDefinition<Menu>;
|
||||
language: TDefinition<Language>;
|
||||
translation: TDefinition<Translation>;
|
||||
nlpEntity: TDefinition<NlpEntity, { update: NlpEntity }>;
|
||||
nlpEntity: TDefinition<NlpEntity>;
|
||||
nlpSampleEntity: TDefinition<NlpSampleEntity>;
|
||||
nlpSample: TDefinition<NlpSample>;
|
||||
nlpValue: TDefinition<NlpValue, { update: NlpValue }>;
|
||||
nlpValue: TDefinition<NlpValue>;
|
||||
setting: TDefinition<Setting>;
|
||||
invitation: TDefinition<Invitation>;
|
||||
model: TDefinition<Model>;
|
||||
@ -189,7 +189,8 @@ declare module '@nestjs/event-emitter' {
|
||||
|
||||
type TPostUpdateValidate<T> = FilterQuery<T>;
|
||||
|
||||
type TPostUpdate<T> = THydratedDocument<T>;
|
||||
// TODO this type will be optimized soon in a separated PR
|
||||
type TPostUpdate<T> = T & any;
|
||||
|
||||
type TPostDelete = DeleteResult;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user