hexabot/api/types/event-emitter.d.ts

399 lines
12 KiB
TypeScript
Raw Normal View History

/*
* Copyright © 2024 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).
*/
2024-10-09 07:26:39 +00:00
import { type OnEventOptions } from '@nestjs/event-emitter/dist/interfaces';
2024-10-19 06:10:59 +00:00
import type { Listener, OnOptions } from 'eventemitter2';
2024-10-29 13:36:46 +00:00
import type { Document, Query } from 'mongoose';
2024-10-09 07:26:39 +00:00
import { type Socket } from 'socket.io';
import { type BotStats } from '@/analytics/schemas/bot-stats.schema';
import { type Attachment } from '@/attachment/schemas/attachment.schema';
import type EventWrapper from '@/channel/lib/EventWrapper';
2024-10-26 09:36:47 +00:00
import { type SubscriberUpdateDto } from '@/chat/dto/subscriber.dto';
2024-10-19 06:10:59 +00:00
import type { Block, BlockFull } from '@/chat/schemas/block.schema';
2024-10-09 07:26:39 +00:00
import { type Category } from '@/chat/schemas/category.schema';
import { type ContextVar } from '@/chat/schemas/context-var.schema';
import { type Conversation } from '@/chat/schemas/conversation.schema';
2024-10-17 05:55:51 +00:00
import type { Label, LabelDocument } from '@/chat/schemas/label.schema';
2024-10-09 07:26:39 +00:00
import { type Message } from '@/chat/schemas/message.schema';
import { type Subscriber } from '@/chat/schemas/subscriber.schema';
import { type ContentType } from '@/cms/schemas/content-type.schema';
import { type Content } from '@/cms/schemas/content.schema';
import { type Menu } from '@/cms/schemas/menu.schema';
import { type Language } from '@/i18n/schemas/language.schema';
import { type Translation } from '@/i18n/schemas/translation.schema';
import type {
NlpEntity,
NlpEntityDocument,
} from '@/nlp/schemas/nlp-entity.schema';
import { type NlpSampleEntity } from '@/nlp/schemas/nlp-sample-entity.schema';
import { type NlpSample } from '@/nlp/schemas/nlp-sample.schema';
2024-10-19 06:10:59 +00:00
import {
2024-10-09 07:26:39 +00:00
NlpValueDocument,
2024-10-19 06:10:59 +00:00
type NlpValue,
2024-10-09 07:26:39 +00:00
} from '@/nlp/schemas/nlp-value.schema';
import { type Setting } from '@/setting/schemas/setting.schema';
import { type Invitation } from '@/user/schemas/invitation.schema';
import { type Model } from '@/user/schemas/model.schema';
import { type Permission } from '@/user/schemas/permission.schema';
import { type Role } from '@/user/schemas/role.schema';
import { type User } from '@/user/schemas/user.schema';
import { EHook, type DeleteResult } from '@/utils/generics/base-repository';
2024-10-29 13:36:46 +00:00
import { TFilterQuery, THydratedDocument } from '@/utils/types/filter.types';
2024-10-09 07:26:39 +00:00
import '@nestjs/event-emitter';
/**
* @description Module declaration that extends the NestJS EventEmitter with custom event types and methods.
*/
declare module '@nestjs/event-emitter' {
2024-10-26 14:13:48 +00:00
interface TDefinition<S, O = object> {
schema: S;
operations: O;
}
2024-10-09 07:26:39 +00:00
2024-10-26 14:13:48 +00:00
interface IHookExtensionsOperationMap {}
2024-10-09 07:26:39 +00:00
2024-10-26 14:13:48 +00:00
interface IHookSettingsGroupLabelOperationMap {
2024-10-09 07:26:39 +00:00
chatbot_settings: TDefinition<
object,
{
2024-10-16 17:50:13 +00:00
global_fallback: Setting;
fallback_block: Setting;
fallback_message: Setting;
2024-10-09 07:26:39 +00:00
}
>;
contact: TDefinition<
object,
{
2024-10-16 17:50:13 +00:00
contact_email_recipient: Setting;
company_name: Setting;
company_phone: Setting;
company_email: Setting;
company_address1: Setting;
company_address2: Setting;
company_city: Setting;
company_zipcode: Setting;
company_state: Setting;
company_country: Setting;
2024-10-09 07:26:39 +00:00
}
>;
}
/* custom hooks */
2024-10-26 14:13:48 +00:00
interface IHookOperationMap
2024-10-09 07:26:39 +00:00
extends IHookSettingsGroupLabelOperationMap,
IHookExtensionsOperationMap {
analytics: TDefinition<
object,
{
block: BlockFull;
passation: Subscriber;
'fallback-local': BlockFull;
2024-10-09 07:26:39 +00:00
'fallback-global': EventWrapper<any, any>;
}
>;
chatbot: TDefinition<
object,
{
2024-10-09 07:29:05 +00:00
sent: unknown;
received: unknown;
message: unknown;
delivery: unknown;
read: unknown;
typing: unknown;
follow: unknown;
echo: unknown;
}
>;
websocket: TDefinition<
object,
{
connection: Socket;
}
>;
}
2024-10-09 07:26:39 +00:00
/* hooks */
2024-10-26 14:13:48 +00:00
interface IHookEntityOperationMap extends IHookOperationMap {
stats: TDefinition<BotStats, { entry: string }>;
attachment: TDefinition<Attachment>;
block: TDefinition<Block>;
category: TDefinition<Category>;
contextVar: TDefinition<ContextVar>;
conversation: TDefinition<Conversation, { end: unknown; close: unknown }>;
label: TDefinition<
Label,
2024-10-09 07:26:39 +00:00
{ create: LabelDocument; delete: Label | Label[] }
>;
message: TDefinition<Message>;
subscriber: TDefinition<Subscriber, { assign: SubscriberUpdateDto }>;
contentType: TDefinition<ContentType>;
content: TDefinition<Content>;
menu: TDefinition<Menu>;
2024-10-09 07:26:39 +00:00
language: TDefinition<Language, { delete: Language | Language[] }>;
translation: TDefinition<Translation>;
nlpEntity: TDefinition<
NlpEntity,
{
2024-10-09 07:26:39 +00:00
create: NlpEntityDocument;
update: NlpEntity;
2024-10-09 07:26:39 +00:00
delete: NlpEntity | NlpEntity[];
}
>;
nlpSampleEntity: TDefinition<NlpSampleEntity>;
nlpSample: TDefinition<NlpSample>;
nlpValue: TDefinition<
NlpValue,
2024-10-09 07:26:39 +00:00
{
create: NlpValueDocument;
update: NlpValue;
delete: NlpValue | NlpValue[];
}
>;
setting: TDefinition<Setting>;
invitation: TDefinition<Invitation>;
model: TDefinition<Model>;
permission: TDefinition<Permission>;
role: TDefinition<Role>;
user: TDefinition<User, { lastvisit: Subscriber }>;
}
2024-10-25 11:27:55 +00:00
/* entities hooks having schemas */
2024-10-26 14:13:48 +00:00
type IHookEntities = keyof Omit<
IHookEntityOperationMap,
keyof IHookOperationMap
>;
/**
* @description A constrained string type that allows specific string values while preserving type safety.
*/
2024-10-26 14:13:48 +00:00
type ConstrainedString = string & Record<never, never>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type EventNamespaces = keyof IHookEntityOperationMap;
2024-10-09 07:26:39 +00:00
/* pre hooks */
2024-10-26 14:13:48 +00:00
type TPreValidate<T> = THydratedDocument<T>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPreCreate<T> = THydratedDocument<T>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPreUpdate<T> = TFilterQuery<T> & object;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPreDelete<T> = Query<
2024-10-09 07:26:39 +00:00
DeleteResult,
Document<T>,
unknown,
T,
'deleteOne',
Record<string, never>
>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPreUnion<T> =
2024-10-09 07:26:39 +00:00
| TPreValidate<T>
| TPreCreate<T>
| TPreUpdate<T>
2024-10-19 06:10:59 +00:00
| TPreDelete<T>;
2024-10-09 07:26:39 +00:00
/* post hooks */
2024-10-26 14:13:48 +00:00
type TPostValidate<T> = THydratedDocument<T>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPostCreate<T> = THydratedDocument<T>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPostUpdate<T> = THydratedDocument<T>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPostDelete = DeleteResult;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPostUnion<T> =
2024-10-09 07:26:39 +00:00
| TPostValidate<T>
| TPostCreate<T>
| TPostUpdate<T>
| TPostDelete;
2024-10-26 14:13:48 +00:00
type TCustomOperations<E extends keyof IHookEntityOperationMap> =
2024-10-19 06:10:59 +00:00
IHookEntityOperationMap[E]['operations'][keyof IHookEntityOperationMap[E]['operations']];
2024-10-09 07:26:39 +00:00
2024-10-19 06:10:59 +00:00
/* union hooks */
2024-10-26 14:13:48 +00:00
type TUnion<G, E> = E extends keyof IHookEntityOperationMap
2024-10-19 06:10:59 +00:00
? E extends keyof IHookOperationMap
? TCustomOperations<E>
: TPreUnion<G> | TPostUnion<G> | TCustomOperations<E>
2024-10-09 07:26:39 +00:00
: never;
/* Normalized hook */
2024-10-26 14:13:48 +00:00
enum EHookPrefix {
2024-10-09 07:26:39 +00:00
pre = 'pre',
post = 'post',
}
2024-10-26 14:13:48 +00:00
type TCompatibleHook<
2024-10-09 07:26:39 +00:00
P extends `${EHookPrefix}`,
T = `${EHook}`,
> = T extends `${P}${infer I}` ? `${P}${I}` : never;
2024-10-26 14:13:48 +00:00
type TPreHook = TCompatibleHook<EHookPrefix.pre>;
2024-10-26 09:36:47 +00:00
2024-10-26 14:13:48 +00:00
type TPostHook = TCompatibleHook<EHookPrefix.post>;
2024-10-26 14:13:48 +00:00
type TNormalizedEvents = '*' | TPreHook | TPostHook;
2024-10-26 14:13:48 +00:00
type TNormalizedHooks<
2024-10-19 06:10:59 +00:00
E extends keyof IHookEntityOperationMap,
T = IHookEntityOperationMap[E]['schema'],
> =
| {
[EHook.preValidate]: TPreValidate<T>;
}
| {
[EHook.preCreate]: TPreCreate<T>;
}
| {
2024-10-30 13:32:42 +00:00
[EHook.preUpdate]: TPreUpdate<T>;
2024-10-19 06:10:59 +00:00
}
| {
[EHook.preDelete]: TPreDelete<T>;
}
| {
[EHook.postValidate]: TPostValidate<T>;
}
| {
[EHook.postCreate]: TPostCreate<T>;
}
| {
[EHook.postUpdate]: TPostUpdate<T>;
}
| {
[EHook.postDelete]: TPostDelete;
};
2024-10-26 14:13:48 +00:00
type TNormalizedHook<E extends keyof IHookEntityOperationMap, O> = Extract<
TNormalizedHooks<E>,
{ [key in O]: unknown }
>[O];
2024-10-09 07:26:39 +00:00
/* Extended hook */
2024-10-26 14:13:48 +00:00
type TExtendedHook<
2024-10-19 06:10:59 +00:00
E extends keyof IHookEntityOperationMap,
O extends keyof IHookEntityOperationMap[E]['operations'],
> = IHookEntityOperationMap[E]['operations'][O];
2024-10-26 14:13:48 +00:00
type EventValueOf<G> = G extends `hook:${infer E}:${infer O}`
2024-10-19 06:10:59 +00:00
? O extends '*'
? TUnion<G, E>
: E extends keyof IHookEntityOperationMap
? O extends keyof IHookEntityOperationMap[E]['operations']
? TExtendedHook<E, O>
: TNormalizedHook<E, O>
: never
: never;
2024-10-26 14:13:48 +00:00
type IsHookEvent<G extends EventNamespaces | ConstrainedString> =
2024-10-19 06:10:59 +00:00
G extends EventNamespaces
? true
: G extends `hook:${infer N}:${string}`
? N extends keyof IHookEntityOperationMap
? true
: false
: false;
2024-10-26 14:13:48 +00:00
type TCustomEvents<G extends keyof IHookEntityOperationMap> =
2024-10-19 06:10:59 +00:00
keyof IHookEntityOperationMap[G]['operations'] & string;
2024-10-26 14:13:48 +00:00
type customEvent<G extends EventNamespaces | ConstrainedString> =
2024-10-19 06:10:59 +00:00
G extends EventNamespaces
? G extends `hook:${string}`
? G
: `hook:${G}:${TNormalizedEvents | TCustomEvents<G>}`
: never;
2024-10-26 14:13:48 +00:00
interface ListenerFn<G extends EventNamespaces | ConstrainedString> {
(value: EventValueOf<G>, ...values: any[]): void;
}
2024-10-26 14:13:48 +00:00
class EventEmitter2 {
2024-10-09 07:26:39 +00:00
emit<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
value: EventValueOf<H>,
...values: any[]
): boolean;
2024-10-09 07:26:39 +00:00
emitAsync<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
value: EventValueOf<H>,
...values: any[]
): Promise<any[]>;
2024-10-09 07:26:39 +00:00
addListener<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
): this | Listener;
2024-10-09 07:26:39 +00:00
on<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
options?: boolean | OnOptions,
): this | Listener;
2024-10-09 07:26:39 +00:00
once<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
options?: true | OnOptions,
): this | Listener;
2024-10-09 07:26:39 +00:00
prependOnceListener<
G extends EventNamespaces | ConstrainedString,
H extends G,
>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
options?: boolean | OnOptions,
): this | Listener;
2024-10-09 07:26:39 +00:00
many<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
timesToListen: number,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
options?: boolean | OnOptions,
): this | Listener;
2024-10-09 07:26:39 +00:00
prependMany<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
timesToListen: number,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
options?: boolean | OnOptions,
): this | Listener;
2024-10-09 07:26:39 +00:00
removeListener<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
): this;
2024-10-09 07:26:39 +00:00
off<G extends EventNamespaces | ConstrainedString, H extends G>(
customEvent: customEvent<G>,
2024-10-09 07:26:39 +00:00
listener: ListenerFn<H>,
): this;
}
declare type OnEventMethodDecorator<
G extends EventNamespaces | ConstrainedString,
> = <T, K extends keyof T>(
target: IsHookEvent<G> extends true
? [T[K]] extends [(params: EventValueOf<G>, ...rest: any[]) => any]
? T
: never
: T,
propertyKey: K,
) => void;
2024-10-26 14:13:48 +00:00
declare function OnEvent<
G extends EventNamespaces | ConstrainedString,
2024-10-09 07:26:39 +00:00
H extends G,
>(
event: customEvent<G>,
options?: OnEventOptions | undefined,
2024-10-09 07:26:39 +00:00
): OnEventMethodDecorator<H>;
}