import { type OnEventOptions } from '@nestjs/event-emitter/dist/interfaces'; import type { Document, HydratedDocument, Query, TFilterQuery } from 'mongoose'; 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'; import { BlockFull, type Block } from '@/chat/schemas/block.schema'; 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'; import type { Label, LabelDocument } from '@/chat/schemas/label.schema'; 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'; import type { NlpValue, NlpValueDocument, } from '@/nlp/schemas/nlp-value.schema'; import { type Setting } from '@/setting/schemas/setting.schema'; import type { CheckboxSetting, TextSetting } from '@/setting/schemas/types'; 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'; import { type SubscriberUpdateDto } from './chat/dto/subscriber.dto'; import '@nestjs/event-emitter'; /** * @description Module declaration that extends the NestJS EventEmitter with custom event types and methods. */ declare module '@nestjs/event-emitter' { interface TDefinition { schema: S; operations: O; } interface IHookExtensionsOperationMap { messenger: TDefinition< object, { get_started_button: Setting; access_token: Setting; composer_input_disabled: CheckboxSetting; greeting_text: TextSetting; } >; } interface IHookSettingsGroupLabelOperationMap { chatbot_settings: TDefinition< object, { global_fallback: Setting; fallback_block: Setting; fallback_message: Setting; } >; contact: TDefinition< object, { 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; } >; nlp_settings: TDefinition< object, { provider: Setting; endpoint: Setting; token: Setting; threshold: Setting; } >; } /* custom hooks */ interface IHookOperationMap extends IHookSettingsGroupLabelOperationMap, IHookExtensionsOperationMap { analytics: TDefinition< object, { block: BlockFull; passation: Subscriber; 'fallback-local': BlockFull; 'fallback-global': EventWrapper; } >; chatbot: TDefinition< object, { sent: unknown; received: unknown; message: unknown; delivery: unknown; read: unknown; typing: unknown; follow: unknown; echo: unknown; } >; websocket: TDefinition< object, { connection: Socket; } >; } /* entities hooks */ interface IHookEntityOperationMap extends IHookOperationMap { stats: TDefinition; attachment: TDefinition; block: TDefinition; category: TDefinition; contextVar: TDefinition; conversation: TDefinition; label: TDefinition< Label, { create: LabelDocument; delete: Label | Label[] } >; message: TDefinition; subscriber: TDefinition; contentType: TDefinition; content: TDefinition; menu: TDefinition; language: TDefinition; translation: TDefinition; nlpEntity: TDefinition< NlpEntity, { create: NlpEntityDocument; update: NlpEntity; delete: NlpEntity | NlpEntity[]; } >; nlpSampleEntity: TDefinition; nlpSample: TDefinition; nlpValue: TDefinition< NlpValue, { create: NlpValueDocument; update: NlpValue; delete: NlpValue | NlpValue[]; } >; setting: TDefinition; invitation: TDefinition; model: TDefinition; permission: TDefinition; role: TDefinition; user: TDefinition; } /** * @description A constrained string type that allows specific string values while preserving type safety. */ type ConstrainedString = string & Record; type EventNamespaces = keyof IHookEntityOperationMap; /* pre hooks */ type TPreValidate = HydratedDocument; type TPreCreate = HydratedDocument; type TPreUpdate = TFilterQuery & object; type TPreDelete = Query< DeleteResult, Document, unknown, T, 'deleteOne', Record >; type TPreUnion = | TPreValidate | TPreCreate | TPreUpdate | TPreDelete; /* post hooks */ type TPostValidate = HydratedDocument; type TPostCreate = HydratedDocument; type TPostUpdate = HydratedDocument; type TPostDelete = DeleteResult; type TPostUnion = | TPostValidate | TPostCreate | TPostUpdate | TPostDelete; /* union hooks */ type TUnion = E extends keyof IHookOperationMap ? IHookEntityOperationMap[E]['operations'][keyof IHookEntityOperationMap[E]['operations']] : | TPreUnion | TPostUnion | IHookEntityOperationMap[E]['operations'][keyof IHookEntityOperationMap[E]['operations']]; type THookSplitter = H extends `hook:${infer E}:${infer O}` ? [E, O] : never; /* Normalized hook */ enum EHookPrefix { pre = 'pre', post = 'post', } type TCompatibleHook< P extends `${EHookPrefix}`, T = `${EHook}`, > = T extends `${P}${infer I}` ? `${P}${I}` : never; type TPreHook = TCompatibleHook; type TPostHook = TCompatibleHook; type hookTypes = O extends keyof IHookOperationMap ? '*' : '*' | TPreHook | TPostHook; type TNormalizedPreHook = O extends `${EHook.preValidate}` ? TPreValidate : O extends `${EHook.preCreate}` ? TPreCreate : O extends `${EHook.preUpdate}` ? TPreUpdate : O extends `${EHook.preDelete}` ? TPreDelete : never; type TNormalizedPostHook = O extends `${EHook.postValidate}` ? TPostValidate : O extends `${EHook.postCreate}` ? TPostCreate : O extends `${EHook.postUpdate}` ? TPostUpdate : O extends `${EHook.postDelete}` ? TPostDelete : never; type TNormalizedHook = TNormalizedPreHook & TNormalizedPostHook; /* Extended hook */ type TExtendedHook = IHookEntityOperationMap[E]['operations'][O]; type EventValueOf< G, E = THookSplitter[0], O = THookSplitter[1], > = O extends '*' ? TUnion : O extends hookTypes ? TNormalizedHook : TExtendedHook; type IsHookEvent = G extends EventNamespaces ? true : G extends `hook:${infer N}:${string}` ? N extends keyof IHookEntityOperationMap ? true : false : false; type customEvent = G extends EventNamespaces ? G extends `hook:${string}` ? G : `hook:${G}:${hookTypes | keyof IHookEntityOperationMap[G]['operations']}` : never; export interface ListenerFn { (value: EventValueOf, ...values: any[]): void; } export class EventEmitter2 { emit( customEvent: customEvent, value: EventValueOf, ...values: any[] ): boolean; emitAsync( customEvent: customEvent, value: EventValueOf, ...values: any[] ): Promise; addListener( customEvent: customEvent, listener: ListenerFn, ): this | Listener; on( customEvent: customEvent, listener: ListenerFn, options?: boolean | OnOptions, ): this | Listener; once( customEvent: customEvent, listener: ListenerFn, options?: true | OnOptions, ): this | Listener; prependOnceListener< G extends EventNamespaces | ConstrainedString, H extends G, >( customEvent: customEvent, listener: ListenerFn, options?: boolean | OnOptions, ): this | Listener; many( customEvent: customEvent, timesToListen: number, listener: ListenerFn, options?: boolean | OnOptions, ): this | Listener; prependMany( customEvent: customEvent, timesToListen: number, listener: ListenerFn, options?: boolean | OnOptions, ): this | Listener; removeListener( customEvent: customEvent, listener: ListenerFn, ): this; off( customEvent: customEvent, listener: ListenerFn, ): this; } declare type OnEventMethodDecorator< G extends EventNamespaces | ConstrainedString, > = ( target: IsHookEvent extends true ? [T[K]] extends [(params: EventValueOf, ...rest: any[]) => any] ? T : never : T, propertyKey: K, ) => void; export declare function OnEvent< G extends EventNamespaces | ConstrainedString, H extends G, >( event: customEvent, options?: OnEventOptions | undefined, ): OnEventMethodDecorator; }