fix: implement dynamic create DTO for Block

This commit is contained in:
yassinedorbozgithub 2025-01-10 11:30:23 +01:00
parent 66ba5bff64
commit ffc260bba2
7 changed files with 62 additions and 40 deletions

View File

@ -21,6 +21,7 @@ import {
IsString, IsString,
} from 'class-validator'; } from 'class-validator';
import { DtoConfig } from '@/utils/types/dto.types';
import { IsObjectId } from '@/utils/validation-rules/is-object-id'; import { IsObjectId } from '@/utils/validation-rules/is-object-id';
import { CaptureVar } from '../schemas/types/capture-var'; import { CaptureVar } from '../schemas/types/capture-var';
@ -146,3 +147,7 @@ export class BlockUpdateDto extends PartialType(
@IsOptional() @IsOptional()
trigger_channels?: string[]; trigger_channels?: string[];
} }
export type BlockDTOMap = DtoConfig<{
create: BlockCreateDto;
}>;

View File

@ -22,7 +22,7 @@ import { LoggerService } from '@/logger/logger.service';
import { BaseRepository, DeleteResult } from '@/utils/generics/base-repository'; import { BaseRepository, DeleteResult } from '@/utils/generics/base-repository';
import { TFilterQuery } from '@/utils/types/filter.types'; import { TFilterQuery } from '@/utils/types/filter.types';
import { BlockCreateDto, BlockUpdateDto } from '../dto/block.dto'; import { BlockCreateDto, BlockDTOMap, BlockUpdateDto } from '../dto/block.dto';
import { import {
Block, Block,
BLOCK_POPULATE, BLOCK_POPULATE,
@ -34,7 +34,8 @@ import {
export class BlockRepository extends BaseRepository< export class BlockRepository extends BaseRepository<
Block, Block,
BlockPopulate, BlockPopulate,
BlockFull BlockFull,
BlockDTOMap
> { > {
constructor( constructor(
readonly eventEmitter: EventEmitter2, readonly eventEmitter: EventEmitter2,

View File

@ -43,7 +43,7 @@ export class BlockStub extends BaseSchema {
validate: isPatternList, validate: isPatternList,
default: [], default: [],
}) })
patterns?: Pattern[]; patterns: Pattern[];
@Prop([ @Prop([
{ {
@ -52,7 +52,7 @@ export class BlockStub extends BaseSchema {
default: [], default: [],
}, },
]) ])
trigger_labels?: unknown; trigger_labels: unknown;
@Prop([ @Prop([
{ {
@ -61,19 +61,19 @@ export class BlockStub extends BaseSchema {
default: [], default: [],
}, },
]) ])
assign_labels?: unknown; assign_labels: unknown;
@Prop({ @Prop({
type: Object, type: Object,
default: [], default: [],
}) })
trigger_channels?: string[]; trigger_channels: string[];
@Prop({ @Prop({
type: Object, type: Object,
default: {}, default: {},
}) })
options?: BlockOptions; options: BlockOptions;
@Prop({ @Prop({
type: Object, type: Object,
@ -88,13 +88,13 @@ export class BlockStub extends BaseSchema {
default: [], default: [],
}, },
]) ])
nextBlocks?: unknown; nextBlocks: unknown;
@Prop({ @Prop({
type: MongooseSchema.Types.ObjectId, type: MongooseSchema.Types.ObjectId,
ref: 'Block', ref: 'Block',
}) })
attachedBlock?: unknown; attachedBlock: unknown;
@Prop({ @Prop({
type: MongooseSchema.Types.ObjectId, type: MongooseSchema.Types.ObjectId,
@ -106,14 +106,14 @@ export class BlockStub extends BaseSchema {
type: Boolean, type: Boolean,
default: false, default: false,
}) })
starts_conversation?: boolean; starts_conversation: boolean;
@Prop({ @Prop({
type: Object, type: Object,
validate: isValidVarCapture, validate: isValidVarCapture,
default: [], default: [],
}) })
capture_vars?: CaptureVar[]; capture_vars: CaptureVar[];
@Prop({ @Prop({
type: Object, type: Object,
@ -125,22 +125,22 @@ export class BlockStub extends BaseSchema {
type: Boolean, type: Boolean,
default: false, default: false,
}) })
builtin?: boolean; builtin: boolean;
} }
@Schema({ timestamps: true }) @Schema({ timestamps: true })
export class Block extends BlockStub { export class Block extends BlockStub {
@Transform(({ obj }) => obj.trigger_labels?.map((elem) => elem.toString())) @Transform(({ obj }) => obj.trigger_labels.map((elem) => elem.toString()))
trigger_labels?: string[]; trigger_labels: string[];
@Transform(({ obj }) => obj.assign_labels?.map((elem) => elem.toString())) @Transform(({ obj }) => obj.assign_labels.map((elem) => elem.toString()))
assign_labels?: string[]; assign_labels: string[];
@Transform(({ obj }) => obj.nextBlocks?.map((elem) => elem.toString())) @Transform(({ obj }) => obj.nextBlocks.map((elem) => elem.toString()))
nextBlocks?: string[]; nextBlocks: string[];
@Transform(({ obj }) => obj.attachedBlock?.toString() || null) @Transform(({ obj }) => obj.attachedBlock?.toString() || null)
attachedBlock?: string; attachedBlock: string;
@Transform(({ obj }) => obj.category.toString()) @Transform(({ obj }) => obj.category.toString())
category: string; category: string;
@ -161,16 +161,16 @@ export class BlockFull extends BlockStub {
assign_labels: Label[]; assign_labels: Label[];
@Type(() => Block) @Type(() => Block)
nextBlocks?: Block[]; nextBlocks: Block[];
@Type(() => Block) @Type(() => Block)
attachedBlock?: Block; attachedBlock: Block;
@Type(() => Category) @Type(() => Category)
category: Category; category: Category;
@Type(() => Block) @Type(() => Block)
previousBlocks: Block[]; previousBlocks?: Block[];
@Type(() => Block) @Type(() => Block)
attachedToBlock?: Block; attachedToBlock?: Block;

View File

@ -22,6 +22,7 @@ import { SettingService } from '@/setting/services/setting.service';
import { BaseService } from '@/utils/generics/base-service'; import { BaseService } from '@/utils/generics/base-service';
import { getRandom } from '@/utils/helpers/safeRandom'; import { getRandom } from '@/utils/helpers/safeRandom';
import { BlockDTOMap } from '../dto/block.dto';
import { BlockRepository } from '../repositories/block.repository'; import { BlockRepository } from '../repositories/block.repository';
import { Block, BlockFull, BlockPopulate } from '../schemas/block.schema'; import { Block, BlockFull, BlockPopulate } from '../schemas/block.schema';
import { Context } from '../schemas/types/context'; import { Context } from '../schemas/types/context';
@ -35,7 +36,12 @@ import { Payload, StdQuickReply } from '../schemas/types/quick-reply';
import { SubscriberContext } from '../schemas/types/subscriberContext'; import { SubscriberContext } from '../schemas/types/subscriberContext';
@Injectable() @Injectable()
export class BlockService extends BaseService<Block, BlockPopulate, BlockFull> { export class BlockService extends BaseService<
Block,
BlockPopulate,
BlockFull,
BlockDTOMap
> {
constructor( constructor(
readonly repository: BlockRepository, readonly repository: BlockRepository,
private readonly contentService: ContentService, private readonly contentService: ContentService,

View File

@ -154,6 +154,7 @@ describe('TranslationService', () => {
}, },
}, },
options: {}, options: {},
attachedBlock: null,
}; };
const mockedPlugin: any = { const mockedPlugin: any = {

View File

@ -8,17 +8,35 @@
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import { BlockCreateDto } from '@/chat/dto/block.dto'; import { Block, BlockModel } from '@/chat/schemas/block.schema';
import { BlockModel, Block } from '@/chat/schemas/block.schema';
import { CategoryModel } from '@/chat/schemas/category.schema'; import { CategoryModel } from '@/chat/schemas/category.schema';
import { FileType } from '@/chat/schemas/types/attachment'; import { FileType } from '@/chat/schemas/types/attachment';
import { ButtonType } from '@/chat/schemas/types/button'; import { ButtonType } from '@/chat/schemas/types/button';
import { QuickReplyType } from '@/chat/schemas/types/quick-reply'; import { QuickReplyType } from '@/chat/schemas/types/quick-reply';
import { BaseSchema } from '@/utils/generics/base-schema';
import { getFixturesWithDefaultValues } from '../defaultValues'; import { getFixturesWithDefaultValues } from '../defaultValues';
import { TFixturesDefaultValues } from '../types';
export const blocks: BlockCreateDto[] = [ export const fieldsWithDefaultValues = {
options: {},
nextBlocks: [],
capture_vars: [],
assign_labels: [],
trigger_labels: [],
builtin: false,
starts_conversation: false,
attachedBlock: null,
attachedToBlock: null,
} satisfies Partial<Block>;
type TFieldWithDefaultValues =
| keyof typeof fieldsWithDefaultValues
| keyof BaseSchema;
type TTransformedField<T> = Omit<T, TFieldWithDefaultValues> &
Partial<Pick<Block, TFieldWithDefaultValues>>;
type TBlock = TTransformedField<Block>;
export const blocks: TBlock[] = [
{ {
name: 'hasNextBlocks', name: 'hasNextBlocks',
patterns: ['Hi'], patterns: ['Hi'],
@ -163,20 +181,9 @@ export const blocks: BlockCreateDto[] = [
}, },
]; ];
export const blockDefaultValues: TFixturesDefaultValues<Block> = { export const blockFixtures = getFixturesWithDefaultValues<TBlock>({
options: {},
builtin: false,
nextBlocks: [],
capture_vars: [],
assign_labels: [],
trigger_labels: [],
starts_conversation: false,
attachedToBlock: null,
};
export const blockFixtures = getFixturesWithDefaultValues<Block>({
fixtures: blocks, fixtures: blocks,
defaultValues: blockDefaultValues, defaultValues: fieldsWithDefaultValues,
}); });
export const installBlockFixtures = async () => { export const installBlockFixtures = async () => {

View File

@ -95,6 +95,7 @@ export const baseBlockInstance = {
category: undefined, category: undefined,
previousBlocks: [], previousBlocks: [],
trigger_channels: [], trigger_channels: [],
nextBlocks: [],
...modelInstance, ...modelInstance,
}; };
@ -103,6 +104,7 @@ export const blockEmpty: BlockFull = {
name: 'Empty', name: 'Empty',
patterns: [], patterns: [],
message: [''], message: [''],
nextBlocks: [],
}; };
// Translation Data // Translation Data