mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
fix: implement dynamic create DTO for Block
This commit is contained in:
parent
66ba5bff64
commit
ffc260bba2
@ -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;
|
||||||
|
}>;
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -154,6 +154,7 @@ describe('TranslationService', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
options: {},
|
options: {},
|
||||||
|
attachedBlock: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockedPlugin: any = {
|
const mockedPlugin: any = {
|
||||||
|
41
api/src/utils/test/fixtures/block.ts
vendored
41
api/src/utils/test/fixtures/block.ts
vendored
@ -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 () => {
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user