mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
Merge branch '548-issue-generic-support-of-multiple-dto-per-service' into 540-issue-nlp-module-strictnullchecks-issues
This commit is contained in:
@@ -10,6 +10,7 @@ import { NotFoundException } from '@nestjs/common';
|
||||
|
||||
import { TFilterQuery } from '@/utils/types/filter.types';
|
||||
|
||||
import { DtoConfig } from '../types/dto.types';
|
||||
import { TValidateProps } from '../types/filter.types';
|
||||
|
||||
import { BaseSchema } from './base-schema';
|
||||
@@ -20,8 +21,9 @@ export abstract class BaseController<
|
||||
TStub = never,
|
||||
P extends string = never,
|
||||
TFull extends Omit<T, P> = never,
|
||||
Dto extends DtoConfig = object,
|
||||
> {
|
||||
constructor(protected readonly service: BaseService<T, P, TFull>) {}
|
||||
constructor(protected readonly service: BaseService<T, P, TFull, Dto>) {}
|
||||
|
||||
/**
|
||||
* Checks if the given populate fields are allowed based on the allowed fields list.
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
import { TFilterQuery } from '@/utils/types/filter.types';
|
||||
|
||||
import { PageQueryDto, QuerySortDto } from '../pagination/pagination-query.dto';
|
||||
import { DtoAction, DtoConfig, DtoInfer } from '../types/dto.types';
|
||||
|
||||
import { BaseSchema } from './base-schema';
|
||||
import { LifecycleHookManager } from './lifecycle-hook-manager';
|
||||
@@ -70,7 +71,8 @@ export abstract class BaseRepository<
|
||||
T extends FlattenMaps<unknown>,
|
||||
P extends string = never,
|
||||
TFull extends Omit<T, P> = never,
|
||||
U = Omit<T, keyof BaseSchema>,
|
||||
Dto extends DtoConfig = object,
|
||||
U extends Omit<T, keyof BaseSchema> = Omit<T, keyof BaseSchema>,
|
||||
D = Document<T>,
|
||||
> {
|
||||
private readonly transformOpts = { excludePrefixes: ['_', 'password'] };
|
||||
@@ -454,7 +456,7 @@ export abstract class BaseRepository<
|
||||
return await this.model.countDocuments(criteria).exec();
|
||||
}
|
||||
|
||||
async create(dto: U): Promise<T> {
|
||||
async create(dto: DtoInfer<DtoAction.Create, Dto, U>): Promise<T> {
|
||||
const doc = await this.model.create(dto);
|
||||
|
||||
return plainToClass(
|
||||
@@ -464,7 +466,9 @@ export abstract class BaseRepository<
|
||||
);
|
||||
}
|
||||
|
||||
async createMany(dtoArray: U[]): Promise<T[]> {
|
||||
async createMany(
|
||||
dtoArray: DtoInfer<DtoAction.Create, Dto, U>[],
|
||||
): Promise<T[]> {
|
||||
const docs = await this.model.create(dtoArray);
|
||||
|
||||
return docs.map((doc) =>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
import { FlattenMaps } from 'mongoose';
|
||||
|
||||
import { DtoAction, DtoConfig, DtoInfer } from '../types/dto.types';
|
||||
|
||||
import { BaseRepository } from './base-repository';
|
||||
import { BaseSchema } from './base-schema';
|
||||
|
||||
@@ -15,8 +17,12 @@ export abstract class BaseSeeder<
|
||||
T extends FlattenMaps<unknown>,
|
||||
P extends string = never,
|
||||
TFull extends Omit<T, P> = never,
|
||||
Dto extends DtoConfig = object,
|
||||
U extends Omit<T, keyof BaseSchema> = Omit<T, keyof BaseSchema>,
|
||||
> {
|
||||
constructor(protected readonly repository: BaseRepository<T, P, TFull>) {}
|
||||
constructor(
|
||||
protected readonly repository: BaseRepository<T, P, TFull, Dto>,
|
||||
) {}
|
||||
|
||||
async findAll(): Promise<T[]> {
|
||||
return await this.repository.findAll();
|
||||
@@ -27,7 +33,7 @@ export abstract class BaseSeeder<
|
||||
return count === 0;
|
||||
}
|
||||
|
||||
async seed(models: Omit<T, keyof BaseSchema>[]): Promise<boolean> {
|
||||
async seed(models: DtoInfer<DtoAction.Create, Dto, U>[]): Promise<boolean> {
|
||||
if (await this.isEmpty()) {
|
||||
await this.repository.createMany(models);
|
||||
return true;
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ProjectionType, QueryOptions } from 'mongoose';
|
||||
import { TFilterQuery } from '@/utils/types/filter.types';
|
||||
|
||||
import { PageQueryDto, QuerySortDto } from '../pagination/pagination-query.dto';
|
||||
import { DtoAction, DtoConfig, DtoInfer } from '../types/dto.types';
|
||||
|
||||
import { BaseRepository } from './base-repository';
|
||||
import { BaseSchema } from './base-schema';
|
||||
@@ -22,8 +23,12 @@ export abstract class BaseService<
|
||||
T extends BaseSchema,
|
||||
P extends string = never,
|
||||
TFull extends Omit<T, P> = never,
|
||||
Dto extends DtoConfig = object,
|
||||
U extends Omit<T, keyof BaseSchema> = Omit<T, keyof BaseSchema>,
|
||||
> {
|
||||
constructor(protected readonly repository: BaseRepository<T, P, TFull>) {}
|
||||
constructor(
|
||||
protected readonly repository: BaseRepository<T, P, TFull, Dto>,
|
||||
) {}
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
@@ -140,7 +145,7 @@ export abstract class BaseService<
|
||||
return await this.repository.count(criteria);
|
||||
}
|
||||
|
||||
async create<D extends Omit<T, keyof BaseSchema>>(dto: D): Promise<T> {
|
||||
async create(dto: DtoInfer<DtoAction.Create, Dto, U>): Promise<T> {
|
||||
try {
|
||||
return await this.repository.create(dto);
|
||||
} catch (error) {
|
||||
@@ -153,9 +158,9 @@ export abstract class BaseService<
|
||||
}
|
||||
}
|
||||
|
||||
async findOneOrCreate<D extends Omit<T, keyof BaseSchema>>(
|
||||
async findOneOrCreate(
|
||||
criteria: string | TFilterQuery<T>,
|
||||
dto: D,
|
||||
dto: DtoInfer<DtoAction.Create, Dto, U>,
|
||||
): Promise<T> {
|
||||
const result = await this.findOne(criteria);
|
||||
if (!result) {
|
||||
@@ -164,24 +169,21 @@ export abstract class BaseService<
|
||||
return result;
|
||||
}
|
||||
|
||||
async createMany<D extends Omit<T, keyof BaseSchema>>(
|
||||
dtoArray: D[],
|
||||
async createMany(
|
||||
dtoArray: DtoInfer<DtoAction.Create, Dto, U>[],
|
||||
): Promise<T[]> {
|
||||
return await this.repository.createMany(dtoArray);
|
||||
}
|
||||
|
||||
async updateOne<D extends Partial<Omit<T, keyof BaseSchema>>>(
|
||||
async updateOne(
|
||||
criteria: string | TFilterQuery<T>,
|
||||
dto: D,
|
||||
options?: QueryOptions<D> | null,
|
||||
dto: Partial<U>,
|
||||
options?: QueryOptions<Partial<U>> | null,
|
||||
): Promise<T | null> {
|
||||
return await this.repository.updateOne(criteria, dto, options);
|
||||
}
|
||||
|
||||
async updateMany<D extends Partial<Omit<T, keyof BaseSchema>>>(
|
||||
filter: TFilterQuery<T>,
|
||||
dto: D,
|
||||
) {
|
||||
async updateMany(filter: TFilterQuery<T>, dto: Partial<U>) {
|
||||
return await this.repository.updateMany(filter, dto);
|
||||
}
|
||||
|
||||
|
||||
41
api/src/utils/test/fixtures/block.ts
vendored
41
api/src/utils/test/fixtures/block.ts
vendored
@@ -9,20 +9,34 @@
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
import { BlockCreateDto } from '@/chat/dto/block.dto';
|
||||
import { BlockModel, Block } from '@/chat/schemas/block.schema';
|
||||
import { Block, BlockModel } from '@/chat/schemas/block.schema';
|
||||
import { CategoryModel } from '@/chat/schemas/category.schema';
|
||||
import { FileType } from '@/chat/schemas/types/attachment';
|
||||
import { ButtonType } from '@/chat/schemas/types/button';
|
||||
import { QuickReplyType } from '@/chat/schemas/types/quick-reply';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
export const blocks: BlockCreateDto[] = [
|
||||
type TBlockFixtures = FixturesTypeBuilder<Block, BlockCreateDto>;
|
||||
|
||||
export const blockDefaultValues: TBlockFixtures['defaultValues'] = {
|
||||
options: {},
|
||||
nextBlocks: [],
|
||||
capture_vars: [],
|
||||
assign_labels: [],
|
||||
trigger_labels: [],
|
||||
trigger_channels: [],
|
||||
builtin: false,
|
||||
starts_conversation: false,
|
||||
attachedBlock: null,
|
||||
attachedToBlock: null,
|
||||
};
|
||||
|
||||
export const blocks: TBlockFixtures['values'][] = [
|
||||
{
|
||||
name: 'hasNextBlocks',
|
||||
patterns: ['Hi'],
|
||||
trigger_channels: [],
|
||||
category: null,
|
||||
options: {
|
||||
typing: 0,
|
||||
@@ -41,7 +55,6 @@ export const blocks: BlockCreateDto[] = [
|
||||
{
|
||||
name: 'hasPreviousBlocks',
|
||||
patterns: ['colors'],
|
||||
trigger_channels: [],
|
||||
category: null,
|
||||
options: {
|
||||
typing: 0,
|
||||
@@ -79,7 +92,6 @@ export const blocks: BlockCreateDto[] = [
|
||||
{
|
||||
name: 'buttons',
|
||||
patterns: ['about'],
|
||||
trigger_channels: [],
|
||||
category: null,
|
||||
options: {
|
||||
typing: 0,
|
||||
@@ -117,7 +129,6 @@ export const blocks: BlockCreateDto[] = [
|
||||
{
|
||||
name: 'attachment',
|
||||
patterns: ['image'],
|
||||
trigger_channels: [],
|
||||
category: null,
|
||||
options: {
|
||||
typing: 0,
|
||||
@@ -144,7 +155,6 @@ export const blocks: BlockCreateDto[] = [
|
||||
{
|
||||
name: 'test',
|
||||
patterns: ['yes'],
|
||||
trigger_channels: [],
|
||||
category: null,
|
||||
//to be verified
|
||||
options: {
|
||||
@@ -163,18 +173,9 @@ export const blocks: BlockCreateDto[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const blockDefaultValues: TFixturesDefaultValues<Block> = {
|
||||
options: {},
|
||||
builtin: false,
|
||||
nextBlocks: [],
|
||||
capture_vars: [],
|
||||
assign_labels: [],
|
||||
trigger_labels: [],
|
||||
starts_conversation: false,
|
||||
attachedToBlock: null,
|
||||
};
|
||||
|
||||
export const blockFixtures = getFixturesWithDefaultValues<Block>({
|
||||
export const blockFixtures = getFixturesWithDefaultValues<
|
||||
TBlockFixtures['values']
|
||||
>({
|
||||
fixtures: blocks,
|
||||
defaultValues: blockDefaultValues,
|
||||
});
|
||||
|
||||
29
api/src/utils/test/fixtures/category.ts
vendored
29
api/src/utils/test/fixtures/category.ts
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
@@ -9,12 +9,23 @@
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
import { CategoryCreateDto } from '@/chat/dto/category.dto';
|
||||
import { CategoryModel, Category } from '@/chat/schemas/category.schema';
|
||||
import { Category, CategoryModel } from '@/chat/schemas/category.schema';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
export const categories: CategoryCreateDto[] = [
|
||||
export type TCategoryFixtures = FixturesTypeBuilder<
|
||||
Category,
|
||||
CategoryCreateDto
|
||||
>;
|
||||
|
||||
export const categoryDefaultValues: TCategoryFixtures['defaultValues'] = {
|
||||
builtin: false,
|
||||
zoom: 100,
|
||||
offset: [0, 0],
|
||||
};
|
||||
|
||||
export const categories: TCategoryFixtures['values'][] = [
|
||||
{
|
||||
label: 'test category 1',
|
||||
},
|
||||
@@ -23,13 +34,9 @@ export const categories: CategoryCreateDto[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const categoryDefaultValues: TFixturesDefaultValues<Category> = {
|
||||
builtin: false,
|
||||
zoom: 100,
|
||||
offset: [0, 0],
|
||||
};
|
||||
|
||||
export const categoryFixtures = getFixturesWithDefaultValues<Category>({
|
||||
export const categoryFixtures = getFixturesWithDefaultValues<
|
||||
TCategoryFixtures['values']
|
||||
>({
|
||||
fixtures: categories,
|
||||
defaultValues: categoryDefaultValues,
|
||||
});
|
||||
|
||||
23
api/src/utils/test/fixtures/content.ts
vendored
23
api/src/utils/test/fixtures/content.ts
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
@@ -12,12 +12,18 @@ import { ContentCreateDto } from '@/cms/dto/content.dto';
|
||||
import { Content, ContentModel } from '@/cms/schemas/content.schema';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
import { installAttachmentFixtures } from './attachment';
|
||||
import { installContentTypeFixtures } from './contenttype';
|
||||
|
||||
const contents: ContentCreateDto[] = [
|
||||
type TContentFixtures = FixturesTypeBuilder<Content, ContentCreateDto>;
|
||||
|
||||
export const contentDefaultValues: TContentFixtures['defaultValues'] = {
|
||||
status: true,
|
||||
};
|
||||
|
||||
const contents: TContentFixtures['values'][] = [
|
||||
{
|
||||
title: 'Jean',
|
||||
dynamicFields: {
|
||||
@@ -131,14 +137,11 @@ const contents: ContentCreateDto[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const categoryDefaultValues: TFixturesDefaultValues<Content> = {
|
||||
status: true,
|
||||
createdAt: undefined,
|
||||
};
|
||||
|
||||
export const contentFixtures = getFixturesWithDefaultValues<Content>({
|
||||
export const contentFixtures = getFixturesWithDefaultValues<
|
||||
TContentFixtures['values']
|
||||
>({
|
||||
fixtures: contents,
|
||||
defaultValues: categoryDefaultValues,
|
||||
defaultValues: contentDefaultValues,
|
||||
});
|
||||
|
||||
export const installContentFixtures = async () => {
|
||||
|
||||
45
api/src/utils/test/fixtures/contenttype.ts
vendored
45
api/src/utils/test/fixtures/contenttype.ts
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
@@ -15,9 +15,29 @@ import {
|
||||
} from '@/cms/schemas/content-type.schema';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
const contentTypes: ContentTypeCreateDto[] = [
|
||||
type TContentTypeFixtures = FixturesTypeBuilder<
|
||||
ContentType,
|
||||
ContentTypeCreateDto
|
||||
>;
|
||||
|
||||
export const contentTypeDefaultValues: TContentTypeFixtures['defaultValues'] = {
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
label: 'Title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
label: 'Status',
|
||||
type: 'checkbox',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const contentTypes: TContentTypeFixtures['values'][] = [
|
||||
{
|
||||
name: 'Product',
|
||||
fields: [
|
||||
@@ -100,22 +120,9 @@ const contentTypes: ContentTypeCreateDto[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const contentTypeDefaultValues: TFixturesDefaultValues<ContentType> = {
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
label: 'Title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
label: 'Status',
|
||||
type: 'checkbox',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const contentTypeFixtures = getFixturesWithDefaultValues<ContentType>({
|
||||
export const contentTypeFixtures = getFixturesWithDefaultValues<
|
||||
TContentTypeFixtures['values']
|
||||
>({
|
||||
fixtures: contentTypes,
|
||||
defaultValues: contentTypeDefaultValues,
|
||||
});
|
||||
|
||||
20
api/src/utils/test/fixtures/contextvar.ts
vendored
20
api/src/utils/test/fixtures/contextvar.ts
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
@@ -9,25 +9,33 @@
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
import { ContextVarCreateDto } from '@/chat/dto/context-var.dto';
|
||||
import { ContextVarModel, ContextVar } from '@/chat/schemas/context-var.schema';
|
||||
import { ContextVar, ContextVarModel } from '@/chat/schemas/context-var.schema';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
const contextVars: ContextVarCreateDto[] = [
|
||||
type TContentVarFixtures = FixturesTypeBuilder<ContextVar, ContextVarCreateDto>;
|
||||
|
||||
export const contentVarDefaultValues: TContentVarFixtures['defaultValues'] = {
|
||||
permanent: false,
|
||||
};
|
||||
|
||||
const contextVars: TContentVarFixtures['values'][] = [
|
||||
{
|
||||
label: 'test context var 1',
|
||||
name: 'test1',
|
||||
permanent: false,
|
||||
},
|
||||
{
|
||||
label: 'test context var 2',
|
||||
name: 'test2',
|
||||
permanent: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const contextVarFixtures = getFixturesWithDefaultValues<ContextVar>({
|
||||
export const contextVarFixtures = getFixturesWithDefaultValues<
|
||||
TContentVarFixtures['values']
|
||||
>({
|
||||
fixtures: contextVars,
|
||||
defaultValues: contentVarDefaultValues,
|
||||
});
|
||||
|
||||
export const installContextVarFixtures = async () => {
|
||||
|
||||
21
api/src/utils/test/fixtures/conversation.ts
vendored
21
api/src/utils/test/fixtures/conversation.ts
vendored
@@ -9,10 +9,7 @@
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
import { ConversationCreateDto } from '@/chat/dto/conversation.dto';
|
||||
import {
|
||||
Conversation,
|
||||
ConversationModel,
|
||||
} from '@/chat/schemas/conversation.schema';
|
||||
import { ConversationModel } from '@/chat/schemas/conversation.schema';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
@@ -116,14 +113,16 @@ const conversations: ConversationCreateDto[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const conversationDefaultValues: TFixturesDefaultValues<Conversation> = {
|
||||
active: false,
|
||||
};
|
||||
export const conversationDefaultValues: TFixturesDefaultValues<ConversationCreateDto> =
|
||||
{
|
||||
active: false,
|
||||
};
|
||||
|
||||
export const conversationFixtures = getFixturesWithDefaultValues<Conversation>({
|
||||
fixtures: conversations,
|
||||
defaultValues: conversationDefaultValues,
|
||||
});
|
||||
export const conversationFixtures =
|
||||
getFixturesWithDefaultValues<ConversationCreateDto>({
|
||||
fixtures: conversations,
|
||||
defaultValues: conversationDefaultValues,
|
||||
});
|
||||
|
||||
export const installConversationTypeFixtures = async () => {
|
||||
const subscribers = await installSubscriberFixtures();
|
||||
|
||||
22
api/src/utils/test/fixtures/label.ts
vendored
22
api/src/utils/test/fixtures/label.ts
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
@@ -12,9 +12,15 @@ import { LabelCreateDto } from '@/chat/dto/label.dto';
|
||||
import { Label, LabelModel } from '@/chat/schemas/label.schema';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
export const labels: LabelCreateDto[] = [
|
||||
type TLabelFixtures = FixturesTypeBuilder<Label, LabelCreateDto>;
|
||||
|
||||
export const contentLabelDefaultValues: TLabelFixtures['defaultValues'] = {
|
||||
builtin: false,
|
||||
};
|
||||
|
||||
export const labels: TLabelFixtures['values'][] = [
|
||||
{
|
||||
description: 'test description 1',
|
||||
label_id: {
|
||||
@@ -39,13 +45,11 @@ export const labels: LabelCreateDto[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const labelDefaultValues: TFixturesDefaultValues<Label> = {
|
||||
builtin: false,
|
||||
};
|
||||
|
||||
export const labelFixtures = getFixturesWithDefaultValues<Label>({
|
||||
export const labelFixtures = getFixturesWithDefaultValues<
|
||||
TLabelFixtures['values']
|
||||
>({
|
||||
fixtures: labels,
|
||||
defaultValues: labelDefaultValues,
|
||||
defaultValues: contentLabelDefaultValues,
|
||||
});
|
||||
|
||||
export const installLabelFixtures = async () => {
|
||||
|
||||
22
api/src/utils/test/fixtures/nlpsample.ts
vendored
22
api/src/utils/test/fixtures/nlpsample.ts
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
@@ -13,11 +13,18 @@ import { NlpSample, NlpSampleModel } from '@/nlp/schemas/nlp-sample.schema';
|
||||
import { NlpSampleState } from '@/nlp/schemas/types';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
import { installLanguageFixtures } from './language';
|
||||
|
||||
const nlpSamples: NlpSampleCreateDto[] = [
|
||||
type TNlpSampleFixtures = FixturesTypeBuilder<NlpSample, NlpSampleCreateDto>;
|
||||
|
||||
export const nlpSampleDefaultValues: TNlpSampleFixtures['defaultValues'] = {
|
||||
type: NlpSampleState.train,
|
||||
trained: false,
|
||||
};
|
||||
|
||||
const nlpSamples: TNlpSampleFixtures['values'][] = [
|
||||
{
|
||||
text: 'yess',
|
||||
language: '0',
|
||||
@@ -38,12 +45,9 @@ const nlpSamples: NlpSampleCreateDto[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const nlpSampleDefaultValues: TFixturesDefaultValues<NlpSample> = {
|
||||
type: NlpSampleState.train,
|
||||
trained: false,
|
||||
};
|
||||
|
||||
export const nlpSampleFixtures = getFixturesWithDefaultValues<NlpSample>({
|
||||
export const nlpSampleFixtures = getFixturesWithDefaultValues<
|
||||
TNlpSampleFixtures['values']
|
||||
>({
|
||||
fixtures: nlpSamples,
|
||||
defaultValues: nlpSampleDefaultValues,
|
||||
});
|
||||
|
||||
34
api/src/utils/test/fixtures/subscriber.ts
vendored
34
api/src/utils/test/fixtures/subscriber.ts
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Hexastack. All rights reserved.
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
@@ -12,12 +12,23 @@ import { SubscriberCreateDto } from '@/chat/dto/subscriber.dto';
|
||||
import { Subscriber, SubscriberModel } from '@/chat/schemas/subscriber.schema';
|
||||
|
||||
import { getFixturesWithDefaultValues } from '../defaultValues';
|
||||
import { TFixturesDefaultValues } from '../types';
|
||||
import { FixturesTypeBuilder } from '../types';
|
||||
|
||||
import { installLabelFixtures } from './label';
|
||||
import { installUserFixtures } from './user';
|
||||
|
||||
const subscribers: SubscriberCreateDto[] = [
|
||||
type TSubscriberFixtures = FixturesTypeBuilder<Subscriber, SubscriberCreateDto>;
|
||||
|
||||
export const subscriberDefaultValues: TSubscriberFixtures['defaultValues'] = {
|
||||
timezone: 0,
|
||||
assignedTo: null,
|
||||
assignedAt: null,
|
||||
lastvisit: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||
retainedFrom: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||
avatar: null,
|
||||
};
|
||||
|
||||
const subscribers: TSubscriberFixtures['values'][] = [
|
||||
{
|
||||
foreign_id: 'foreign-id-messenger',
|
||||
first_name: 'Jhon',
|
||||
@@ -30,7 +41,6 @@ const subscribers: SubscriberCreateDto[] = [
|
||||
name: 'messenger-channel',
|
||||
},
|
||||
labels: [],
|
||||
assignedAt: null,
|
||||
lastvisit: new Date('2020-01-01T20:40:03.249Z'),
|
||||
retainedFrom: new Date('2020-01-01T20:40:03.249Z'),
|
||||
},
|
||||
@@ -46,7 +56,6 @@ const subscribers: SubscriberCreateDto[] = [
|
||||
name: 'web-channel',
|
||||
},
|
||||
labels: [],
|
||||
assignedAt: null,
|
||||
lastvisit: new Date('2021-01-01T20:40:03.249Z'),
|
||||
retainedFrom: new Date('2021-01-02T20:40:03.249Z'),
|
||||
},
|
||||
@@ -62,7 +71,6 @@ const subscribers: SubscriberCreateDto[] = [
|
||||
name: 'web-channel',
|
||||
},
|
||||
labels: [],
|
||||
assignedAt: null,
|
||||
lastvisit: new Date('2022-01-01T20:40:03.249Z'),
|
||||
retainedFrom: new Date('2022-01-02T20:40:03.249Z'),
|
||||
},
|
||||
@@ -78,22 +86,14 @@ const subscribers: SubscriberCreateDto[] = [
|
||||
name: 'web-channel',
|
||||
},
|
||||
labels: [],
|
||||
assignedAt: null,
|
||||
lastvisit: new Date('2024-01-01T20:40:03.249Z'),
|
||||
retainedFrom: new Date('2024-01-02T20:40:03.249Z'),
|
||||
},
|
||||
];
|
||||
|
||||
export const subscriberDefaultValues: TFixturesDefaultValues<Subscriber> = {
|
||||
timezone: 0,
|
||||
assignedTo: null,
|
||||
assignedAt: null,
|
||||
lastvisit: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||
retainedFrom: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||
avatar: null,
|
||||
};
|
||||
|
||||
export const subscriberFixtures = getFixturesWithDefaultValues<Subscriber>({
|
||||
export const subscriberFixtures = getFixturesWithDefaultValues<
|
||||
TSubscriberFixtures['values']
|
||||
>({
|
||||
fixtures: subscribers,
|
||||
defaultValues: subscriberDefaultValues,
|
||||
});
|
||||
|
||||
@@ -95,6 +95,7 @@ export const baseBlockInstance = {
|
||||
category: undefined,
|
||||
previousBlocks: [],
|
||||
trigger_channels: [],
|
||||
nextBlocks: [],
|
||||
...modelInstance,
|
||||
};
|
||||
|
||||
@@ -103,6 +104,7 @@ export const blockEmpty: BlockFull = {
|
||||
name: 'Empty',
|
||||
patterns: [],
|
||||
message: [''],
|
||||
nextBlocks: [],
|
||||
};
|
||||
|
||||
// Translation Data
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import { BaseSchema } from '../generics/base-schema';
|
||||
|
||||
type TOptionalPropertyOf<T> = Exclude<
|
||||
export type TOptionalPropertyOf<T> = Exclude<
|
||||
{
|
||||
[K in keyof T]: T extends Record<K, T[K]> ? never : K;
|
||||
}[keyof T],
|
||||
@@ -23,3 +23,25 @@ export type TFixtures<T> = Omit<T, keyof BaseSchema> & {
|
||||
export type TFixturesDefaultValues<T, S = TFixtures<T>> = {
|
||||
[key in TOptionalPropertyOf<S>]?: S[key];
|
||||
} & { createdAt?: BaseSchema['createdAt'] };
|
||||
|
||||
export type TOptionalPropertyFrom<O extends object, O1 extends object> = Pick<
|
||||
O1,
|
||||
Exclude<keyof O1, keyof O>
|
||||
> &
|
||||
Pick<O, Exclude<keyof O, keyof O1>>;
|
||||
|
||||
export type OptionalProperties<T, K extends keyof T> = Omit<
|
||||
T,
|
||||
K | keyof BaseSchema
|
||||
> &
|
||||
Partial<Pick<T, K>>;
|
||||
|
||||
export type FixturesTypeBuilder<
|
||||
S extends object,
|
||||
D extends object,
|
||||
DO = TFixturesDefaultValues<D>,
|
||||
U = Partial<TFixtures<TOptionalPropertyFrom<D, S>>>,
|
||||
> = {
|
||||
defaultValues: DO & U;
|
||||
values: OptionalProperties<S, keyof S & keyof (DO & U)>;
|
||||
};
|
||||
|
||||
24
api/src/utils/types/dto.types.ts
Normal file
24
api/src/utils/types/dto.types.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright © 2025 Hexastack. All rights reserved.
|
||||
*
|
||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||
* 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).
|
||||
*/
|
||||
|
||||
export enum DtoAction {
|
||||
Create = 'create',
|
||||
Read = 'read',
|
||||
Update = 'update',
|
||||
Delete = 'delete',
|
||||
}
|
||||
|
||||
export type DtoConfig<
|
||||
C extends Partial<Record<DtoAction, object>> = Partial<
|
||||
Record<DtoAction, object>
|
||||
>,
|
||||
> = C;
|
||||
|
||||
export type DtoInfer<K extends keyof Dto, Dto, I> = Dto[K] extends object
|
||||
? Dto[K]
|
||||
: I;
|
||||
Reference in New Issue
Block a user