diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts index b71ff69d4dd8..266dbf2ce48c 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts @@ -141,8 +141,10 @@ export class GraphQLConfigService // Create a new contextId for each request const contextId = ContextIdFactory.create(); - // Register the request in the contextId - this.moduleRef.registerRequestByContextId(context.req, contextId); + if (this.moduleRef.registerRequestByContextId) { + // Register the request in the contextId + this.moduleRef.registerRequestByContextId(context.req, contextId); + } // Resolve the WorkspaceSchemaFactory for the contextId const workspaceFactory = await this.moduleRef.resolve( diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts deleted file mode 100644 index 518e147241a1..000000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type'; -import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook'; -import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook'; -import { BlocklistCreateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook'; -import { BlocklistUpdateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-many.pre-query.hook'; -import { BlocklistUpdateOnePreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook'; -import { WorkspaceMemberDeleteOnePreQueryHook } from 'src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook'; -import { WorkspaceMemberDeleteManyPreQueryHook } from 'src/modules/workspace-member/query-hooks/workspace-member-delete-many.pre-query.hook'; -import { MessageFindManyPreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook'; -import { MessageFindOnePreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook'; - -// TODO: move to a decorator -export const workspacePreQueryHooks: WorkspaceQueryHook = { - message: { - findOne: [MessageFindOnePreQueryHook.name], - findMany: [MessageFindManyPreQueryHook.name], - }, - calendarEvent: { - findOne: [CalendarEventFindOnePreQueryHook.name], - findMany: [CalendarEventFindManyPreQueryHook.name], - }, - blocklist: { - createMany: [BlocklistCreateManyPreQueryHook.name], - updateMany: [BlocklistUpdateManyPreQueryHook.name], - updateOne: [BlocklistUpdateOnePreQueryHook.name], - }, - workspaceMember: { - deleteOne: [WorkspaceMemberDeleteOnePreQueryHook.name], - deleteMany: [WorkspaceMemberDeleteManyPreQueryHook.name], - }, -}; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts deleted file mode 100644 index 8ea6b6a6e11b..000000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { WorkspacePreQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service'; -import { CalendarQueryHookModule } from 'src/modules/calendar/query-hooks/calendar-query-hook.module'; -import { ConnectedAccountQueryHookModule } from 'src/modules/connected-account/query-hooks/connected-account-query-hook.module'; -import { MessagingQueryHookModule } from 'src/modules/messaging/common/query-hooks/messaging-query-hook.module'; -import { WorkspaceMemberQueryHookModule } from 'src/modules/workspace-member/query-hooks/workspace-member-query-hook.module'; - -@Module({ - imports: [ - MessagingQueryHookModule, - CalendarQueryHookModule, - ConnectedAccountQueryHookModule, - WorkspaceMemberQueryHookModule, - ], - providers: [WorkspacePreQueryHookService], - exports: [WorkspacePreQueryHookService], -}) -export class WorkspacePreQueryHookModule {} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service.ts deleted file mode 100644 index 28681e0b965b..000000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { ModuleRef } from '@nestjs/core'; - -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; - -import { - ExecutePreHookMethod, - WorkspacePreQueryHookPayload, -} from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type'; -import { workspacePreQueryHooks } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config'; - -@Injectable() -export class WorkspacePreQueryHookService { - constructor(private readonly workspaceQueryHookModuleRef: ModuleRef) {} - - public async executePreHooks( - userId: string | undefined, - workspaceId: string, - objectName: string, - method: T, - payload: WorkspacePreQueryHookPayload, - ): Promise { - const hooks = workspacePreQueryHooks[objectName] || []; - - for (const hookName of Object.values(hooks[method] ?? [])) { - const hook: WorkspacePreQueryHook = - await this.workspaceQueryHookModuleRef.get(hookName, { - strict: false, - }); - - await hook.execute(userId, workspaceId, payload); - } - } -} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator.ts new file mode 100644 index 000000000000..d87979418638 --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator.ts @@ -0,0 +1,40 @@ +import { Scope, SetMetadata } from '@nestjs/common'; +import { SCOPE_OPTIONS_METADATA } from '@nestjs/common/constants'; + +import { WorkspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WORKSPACE_QUERY_HOOK_METADATA } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.constants'; +import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type'; + +export type WorkspaceQueryHookKey = + `${string}.${WorkspaceResolverBuilderMethodNames}`; + +export interface WorkspaceQueryHookOptions { + key: WorkspaceQueryHookKey; + type?: WorkspaceQueryHookType; + scope?: Scope; +} + +export function WorkspaceQueryHook(key: WorkspaceQueryHookKey): ClassDecorator; +export function WorkspaceQueryHook( + options: WorkspaceQueryHookOptions, +): ClassDecorator; +export function WorkspaceQueryHook( + keyOrOptions: WorkspaceQueryHookKey | WorkspaceQueryHookOptions, +): ClassDecorator { + const options: WorkspaceQueryHookOptions = + keyOrOptions && typeof keyOrOptions === 'object' + ? keyOrOptions + : { key: keyOrOptions }; + + // Default to PreHook + if (!options.type) { + options.type = WorkspaceQueryHookType.PreHook; + } + + // eslint-disable-next-line @typescript-eslint/ban-types + return (target: Function) => { + SetMetadata(SCOPE_OPTIONS_METADATA, options)(target); + SetMetadata(WORKSPACE_QUERY_HOOK_METADATA, options)(target); + }; +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface.ts similarity index 84% rename from packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface.ts rename to packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface.ts index 60a782e8c443..93c3964c83b5 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface.ts @@ -1,6 +1,6 @@ import { ResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; -export interface WorkspacePreQueryHook { +export interface WorkspaceQueryHookInstance { execute( userId: string | undefined, workspaceId: string, diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage.ts new file mode 100644 index 000000000000..18b25d1d964d --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage.ts @@ -0,0 +1,59 @@ +// hook-registry.service.ts +import { Injectable } from '@nestjs/common'; +import { Module } from '@nestjs/core/injector/module'; + +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; + +import { WorkspaceQueryHookKey } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; + +interface WorkspaceQueryHookData { + instance: T; + host: Module; + isRequestScoped: boolean; +} + +@Injectable() +export class WorkspaceQueryHookStorage { + private preHookInstances = new Map< + WorkspaceQueryHookKey, + WorkspaceQueryHookData[] + >(); + private postHookInstances = new Map< + WorkspaceQueryHookKey, + WorkspaceQueryHookData[] + >(); + + registerWorkspaceQueryPreHookInstance( + key: WorkspaceQueryHookKey, + data: WorkspaceQueryHookData, + ) { + if (!this.preHookInstances.has(key)) { + this.preHookInstances.set(key, []); + } + + this.preHookInstances.get(key)?.push(data); + } + + getWorkspaceQueryPreHookInstances( + key: WorkspaceQueryHookKey, + ): WorkspaceQueryHookData[] | undefined { + return this.preHookInstances.get(key); + } + + registerWorkspaceQueryPostHookInstance( + key: WorkspaceQueryHookKey, + data: WorkspaceQueryHookData, + ) { + if (!this.postHookInstances.has(key)) { + this.postHookInstances.set(key, []); + } + + this.postHookInstances.get(key)?.push(data); + } + + getWorkspaceQueryPostHookInstances( + key: WorkspaceQueryHookKey, + ): WorkspaceQueryHookData[] | undefined { + return this.postHookInstances.get(key); + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type.ts similarity index 73% rename from packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type.ts rename to packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type.ts index 84d75b1358b9..40ec1df6b4d4 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type.ts @@ -10,26 +10,10 @@ import { UpdateOneResolverArgs, } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; -export type ExecutePreHookMethod = - | 'createMany' - | 'createOne' - | 'deleteMany' - | 'deleteOne' - | 'findMany' - | 'findOne' - | 'findDuplicates' - | 'updateMany' - | 'updateOne'; - -export type ObjectName = string; - -export type HookName = string; - -export type WorkspaceQueryHook = { - [key in ObjectName]: { - [key in ExecutePreHookMethod]?: HookName[]; - }; -}; +export enum WorkspaceQueryHookType { + PreHook = 'PreHook', + PostHook = 'PostHook', +} export type WorkspacePreQueryHookPayload = T extends 'createMany' ? CreateManyResolverArgs diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook-metadata.accessor.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook-metadata.accessor.ts new file mode 100644 index 000000000000..229e0b0bf3db --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook-metadata.accessor.ts @@ -0,0 +1,25 @@ +/* eslint-disable @typescript-eslint/ban-types */ +import { Injectable, Type } from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; + +import { WORKSPACE_QUERY_HOOK_METADATA } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.constants'; +import { WorkspaceQueryHookOptions } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; + +@Injectable() +export class WorkspaceQueryHookMetadataAccessor { + constructor(private readonly reflector: Reflector) {} + + isWorkspaceQueryHook(target: Type | Function): boolean { + if (!target) { + return false; + } + + return !!this.reflector.get(WORKSPACE_QUERY_HOOK_METADATA, target); + } + + getWorkspaceQueryHookMetadata( + target: Type | Function, + ): WorkspaceQueryHookOptions | undefined { + return this.reflector.get(WORKSPACE_QUERY_HOOK_METADATA, target); + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.constants.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.constants.ts new file mode 100644 index 000000000000..ea1aadc49006 --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.constants.ts @@ -0,0 +1,3 @@ +export const WORKSPACE_QUERY_HOOK_METADATA = Symbol( + 'workspace-query-hook:query-hook-metadata', +); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer.ts new file mode 100644 index 000000000000..87bce8248bd1 --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer.ts @@ -0,0 +1,139 @@ +import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; +import { DiscoveryService, ModuleRef, createContextId } from '@nestjs/core'; +import { Module } from '@nestjs/core/injector/module'; +import { Injector } from '@nestjs/core/injector/injector'; + +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; + +import { WorkspaceQueryHookMetadataAccessor } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook-metadata.accessor'; +import { WorkspaceQueryHookStorage } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage'; +import { WorkspaceQueryHookKey } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type'; + +@Injectable() +export class WorkspaceQueryHookExplorer implements OnModuleInit { + private readonly logger = new Logger('WorkspaceQueryHookModule'); + private readonly injector = new Injector(); + + constructor( + private readonly moduleRef: ModuleRef, + private readonly discoveryService: DiscoveryService, + private readonly metadataAccessor: WorkspaceQueryHookMetadataAccessor, + private readonly workspaceQueryHookStorage: WorkspaceQueryHookStorage, + ) {} + + onModuleInit() { + this.explore(); + } + + async explore() { + const hooks = this.discoveryService + .getProviders() + .filter((wrapper) => + this.metadataAccessor.isWorkspaceQueryHook( + !wrapper.metatype || wrapper.inject + ? wrapper.instance?.constructor + : wrapper.metatype, + ), + ); + + for (const hook of hooks) { + const { instance, metatype } = hook; + + const { key, type } = + this.metadataAccessor.getWorkspaceQueryHookMetadata( + instance.constructor || metatype, + ) ?? {}; + + if (!key || !type) { + this.logger.error( + `PreHook ${hook.name} is missing key or type metadata`, + ); + continue; + } + + if (!hook.host) { + this.logger.error(`PreHook ${hook.name} is missing host metadata`); + + continue; + } + + this.registerWorkspaceQueryHook( + key, + type, + instance, + hook.host, + !hook.isDependencyTreeStatic(), + ); + } + } + + async handleHook( + payload: Parameters, + instance: object, + host: Module, + isRequestScoped: boolean, + ) { + const methodName = 'execute'; + + if (isRequestScoped) { + const contextId = createContextId(); + + if (this.moduleRef.registerRequestByContextId) { + this.moduleRef.registerRequestByContextId( + { + req: { + workspaceId: payload?.[1], + }, + }, + contextId, + ); + } + + const contextInstance = await this.injector.loadPerContext( + instance, + host, + host.providers, + contextId, + ); + + await contextInstance[methodName].call(contextInstance, ...payload); + } else { + await instance[methodName].call(instance, ...payload); + } + } + + private registerWorkspaceQueryHook( + key: WorkspaceQueryHookKey, + type: WorkspaceQueryHookType, + instance: object, + host: Module, + isRequestScoped: boolean, + ) { + switch (type) { + case WorkspaceQueryHookType.PreHook: + this.workspaceQueryHookStorage.registerWorkspaceQueryPreHookInstance( + key, + { + instance: instance as WorkspaceQueryHookInstance, + host, + isRequestScoped, + }, + ); + break; + case WorkspaceQueryHookType.PostHook: + this.workspaceQueryHookStorage.registerWorkspaceQueryPostHookInstance( + key, + { + instance: instance as WorkspaceQueryHookInstance, + host, + isRequestScoped, + }, + ); + break; + default: + this.logger.error(`Unknown WorkspaceQueryHookType: ${type}`); + break; + } + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.module.ts new file mode 100644 index 000000000000..f018238835a2 --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.module.ts @@ -0,0 +1,29 @@ +import { Module } from '@nestjs/common'; +import { DiscoveryModule } from '@nestjs/core'; + +import { WorkspaceQueryHookStorage } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage'; +import { WorkspaceQueryHookMetadataAccessor } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook-metadata.accessor'; +import { WorkspaceQueryHookExplorer } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer'; +import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service'; +import { CalendarQueryHookModule } from 'src/modules/calendar/query-hooks/calendar-query-hook.module'; +import { ConnectedAccountQueryHookModule } from 'src/modules/connected-account/query-hooks/connected-account-query-hook.module'; +import { MessagingQueryHookModule } from 'src/modules/messaging/common/query-hooks/messaging-query-hook.module'; +import { WorkspaceMemberQueryHookModule } from 'src/modules/workspace-member/query-hooks/workspace-member-query-hook.module'; + +@Module({ + imports: [ + MessagingQueryHookModule, + CalendarQueryHookModule, + ConnectedAccountQueryHookModule, + WorkspaceMemberQueryHookModule, + DiscoveryModule, + ], + providers: [ + WorkspaceQueryHookService, + WorkspaceQueryHookExplorer, + WorkspaceQueryHookMetadataAccessor, + WorkspaceQueryHookStorage, + ], + exports: [WorkspaceQueryHookService], +}) +export class WorkspaceQueryHookModule {} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service.ts new file mode 100644 index 000000000000..adfd90f4261d --- /dev/null +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service.ts @@ -0,0 +1,43 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { WorkspaceQueryHookStorage } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage'; +import { WorkspaceQueryHookKey } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { WorkspaceQueryHookExplorer } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.explorer'; +import { WorkspacePreQueryHookPayload } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type'; + +@Injectable() +export class WorkspaceQueryHookService { + constructor( + private readonly workspaceQueryHookStorage: WorkspaceQueryHookStorage, + private readonly workspaceQueryHookExplorer: WorkspaceQueryHookExplorer, + ) {} + + public async executePreQueryHooks< + T extends WorkspaceResolverBuilderMethodNames, + >( + userId: string | undefined, + workspaceId: string, + objectName: string, + methodName: T, + payload: WorkspacePreQueryHookPayload, + ): Promise { + const key: WorkspaceQueryHookKey = `${objectName}.${methodName}`; + const preHookInstances = + this.workspaceQueryHookStorage.getWorkspaceQueryPreHookInstances(key); + + if (!preHookInstances) { + return; + } + + for (const preHookInstance of preHookInstances) { + await this.workspaceQueryHookExplorer.handleHook( + [userId, workspaceId, payload], + preHookInstance.instance, + preHookInstance.host, + preHookInstance.isRequestScoped, + ); + } + } +} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts index f7358021b849..d81f5b7e2441 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { WorkspaceQueryBuilderModule } from 'src/engine/api/graphql/workspace-query-builder/workspace-query-builder.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; -import { WorkspacePreQueryHookModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module'; +import { WorkspaceQueryHookModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.module'; import { workspaceQueryRunnerFactories } from 'src/engine/api/graphql/workspace-query-runner/factories'; import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -20,7 +20,7 @@ import { EntityEventsToDbListener } from './listeners/entity-events-to-db.listen AuthModule, WorkspaceQueryBuilderModule, WorkspaceDataSourceModule, - WorkspacePreQueryHookModule, + WorkspaceQueryHookModule, ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]), AnalyticsModule, ], diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts index d5ea042a1606..6c4bb35e9805 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service.ts @@ -42,7 +42,7 @@ import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; -import { WorkspacePreQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service'; +import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { NotFoundError } from 'src/engine/utils/graphql-errors.util'; import { QueryRunnerArgsFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-runner-args.factory'; @@ -75,7 +75,7 @@ export class WorkspaceQueryRunnerService { @InjectMessageQueue(MessageQueue.webhookQueue) private readonly messageQueueService: MessageQueueService, private readonly eventEmitter: EventEmitter2, - private readonly workspacePreQueryHookService: WorkspacePreQueryHookService, + private readonly workspaceQueryHookService: WorkspaceQueryHookService, private readonly environmentService: EnvironmentService, ) {} @@ -101,7 +101,7 @@ export class WorkspaceQueryRunnerService { options, ); - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, @@ -148,7 +148,7 @@ export class WorkspaceQueryRunnerService { options, ); - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, @@ -223,7 +223,7 @@ export class WorkspaceQueryRunnerService { existingRecord, ); - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, @@ -260,7 +260,7 @@ export class WorkspaceQueryRunnerService { ResolverArgsType.CreateMany, )) as CreateManyResolverArgs; - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, @@ -333,7 +333,7 @@ export class WorkspaceQueryRunnerService { options, ); - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, @@ -389,7 +389,7 @@ export class WorkspaceQueryRunnerService { atMost: maximumRecordAffected, }); - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, @@ -441,7 +441,7 @@ export class WorkspaceQueryRunnerService { atMost: maximumRecordAffected, }); - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, @@ -509,7 +509,7 @@ export class WorkspaceQueryRunnerService { ); // TODO END - await this.workspacePreQueryHookService.executePreHooks( + await this.workspaceQueryHookService.executePreQueryHooks( userId, workspaceId, objectMetadataItem.nameSingular, diff --git a/packages/twenty-server/src/engine/integrations/message-queue/drivers/pg-boss.driver.ts b/packages/twenty-server/src/engine/integrations/message-queue/drivers/pg-boss.driver.ts index ca3a0cd5f945..98631bc88121 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/drivers/pg-boss.driver.ts +++ b/packages/twenty-server/src/engine/integrations/message-queue/drivers/pg-boss.driver.ts @@ -47,10 +47,17 @@ export class PgBossDriver } : {}, async (job) => { + // PGBoss work with wildcard job name + const jobName = job.name.split('.')?.[1]; + + if (!jobName) { + throw new Error('Job name could not be splited from the job.'); + } + await handler({ data: job.data, id: job.id, - name: job.name.split('.')[1], + name: jobName, }); }, ); diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-datasource.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-datasource.factory.ts index 62166e536c51..e040f6ddc46a 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-datasource.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/scoped-workspace-datasource.factory.ts @@ -14,7 +14,7 @@ export class ScopedWorkspaceDatasourceFactory { public async create(entities: EntitySchema[]) { const workspaceId: string | undefined = - this.request['req']?.['workspaceId']; + this.request?.['req']?.['workspaceId']; if (!workspaceId) { return null; diff --git a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts index ee20809427d3..d7c67d409efc 100644 --- a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts @@ -1,16 +1,20 @@ -import { BadRequestException, Injectable } from '@nestjs/common'; +import { BadRequestException, NotFoundException, Scope } from '@nestjs/common'; -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.workspace-entity'; import { CanAccessCalendarEventService } from 'src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service'; import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; -@Injectable() +@WorkspaceQueryHook({ + key: `calendarEvent.findMany`, + scope: Scope.REQUEST, +}) export class CalendarEventFindManyPreQueryHook - implements WorkspacePreQueryHook + implements WorkspaceQueryHookInstance { constructor( @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) @@ -27,25 +31,24 @@ export class CalendarEventFindManyPreQueryHook throw new BadRequestException('id filter is required'); } - // TODO: Re-implement this using twenty ORM - // const calendarChannelCalendarEventAssociations = - // await this.calendarChannelEventAssociationRepository.find({ - // where: { - // calendarEvent: { - // id: payload?.filter?.id?.eq, - // }, - // }, - // relations: ['calendarChannel.connectedAccount'], - // }); + const calendarChannelCalendarEventAssociations = + await this.calendarChannelEventAssociationRepository.find({ + where: { + calendarEvent: { + id: payload?.filter?.id?.eq, + }, + }, + relations: ['calendarChannel.connectedAccount'], + }); - // if (calendarChannelCalendarEventAssociations.length === 0) { - // throw new NotFoundException(); - // } + if (calendarChannelCalendarEventAssociations.length === 0) { + throw new NotFoundException(); + } - // await this.canAccessCalendarEventService.canAccessCalendarEvent( - // userId, - // workspaceId, - // calendarChannelCalendarEventAssociations, - // ); + await this.canAccessCalendarEventService.canAccessCalendarEvent( + userId, + workspaceId, + calendarChannelCalendarEventAssociations, + ); } } diff --git a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts index 34642b128e48..4deb02b2c97f 100644 --- a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts +++ b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts @@ -1,15 +1,21 @@ -import { BadRequestException, Injectable } from '@nestjs/common'; +import { BadRequestException, NotFoundException, Scope } from '@nestjs/common'; -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; import { CanAccessCalendarEventService } from 'src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.workspace-entity'; -@Injectable() -export class CalendarEventFindOnePreQueryHook implements WorkspacePreQueryHook { +@WorkspaceQueryHook({ + key: `calendarEvent.findOne`, + scope: Scope.REQUEST, +}) +export class CalendarEventFindOnePreQueryHook + implements WorkspaceQueryHookInstance +{ constructor( @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) private readonly calendarChannelEventAssociationRepository: WorkspaceRepository, @@ -26,23 +32,24 @@ export class CalendarEventFindOnePreQueryHook implements WorkspacePreQueryHook { } // TODO: Re-implement this using twenty ORM - // const calendarChannelCalendarEventAssociations = - // await this.calendarChannelEventAssociationRepository.find({ - // where: { - // calendarEvent: { - // id: payload?.filter?.id?.eq, - // }, - // }, - // }); + const calendarChannelCalendarEventAssociations = + await this.calendarChannelEventAssociationRepository.find({ + where: { + calendarEvent: { + id: payload?.filter?.id?.eq, + }, + }, + relations: ['calendarChannel.connectedAccount'], + }); - // if (calendarChannelCalendarEventAssociations.length === 0) { - // throw new NotFoundException(); - // } + if (calendarChannelCalendarEventAssociations.length === 0) { + throw new NotFoundException(); + } - // await this.canAccessCalendarEventService.canAccessCalendarEvent( - // userId, - // workspaceId, - // calendarChannelCalendarEventAssociations, - // ); + await this.canAccessCalendarEventService.canAccessCalendarEvent( + userId, + workspaceId, + calendarChannelCalendarEventAssociations, + ); } } diff --git a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service.ts b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service.ts index b86a3ca1cda6..80528e04004f 100644 --- a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service.ts +++ b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service.ts @@ -60,7 +60,7 @@ export class CanAccessCalendarEventService { const calendarChannelsConnectedAccounts = await this.connectedAccountRepository.getByIds( - calendarChannels.map((channel) => channel.connectedAccount.id), + calendarChannels.map((channel) => channel.connectedAccountId), workspaceId, ); diff --git a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-query-hook.module.ts b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-query-hook.module.ts index 555b10719f7f..c85bf53c7391 100644 --- a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-query-hook.module.ts +++ b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-query-hook.module.ts @@ -23,14 +23,8 @@ import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module'; ], providers: [ CanAccessCalendarEventService, - { - provide: CalendarEventFindOnePreQueryHook.name, - useClass: CalendarEventFindOnePreQueryHook, - }, - { - provide: CalendarEventFindManyPreQueryHook.name, - useClass: CalendarEventFindManyPreQueryHook, - }, + CalendarEventFindOnePreQueryHook, + CalendarEventFindManyPreQueryHook, ], }) export class CalendarQueryHookModule {} diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts index c72af80f87fb..3e63dcbe26da 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts @@ -237,6 +237,8 @@ export class CalendarChannelWorkspaceEntity extends BaseWorkspaceEntity { }) connectedAccount: Relation; + connectedAccountId: string; + @WorkspaceRelation({ standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.calendarChannelEventAssociations, diff --git a/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook.ts b/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook.ts index 30e025de1079..9acb2b4bfa1c 100644 --- a/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook.ts @@ -1,15 +1,16 @@ -import { Injectable } from '@nestjs/common'; - -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { BlocklistItem, BlocklistValidationService, } from 'src/modules/connected-account/services/blocklist/blocklist-validation.service'; -@Injectable() -export class BlocklistCreateManyPreQueryHook implements WorkspacePreQueryHook { +@WorkspaceQueryHook(`blocklist.createMany`) +export class BlocklistCreateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ constructor( private readonly blocklistValidationService: BlocklistValidationService, ) {} diff --git a/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-many.pre-query.hook.ts b/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-many.pre-query.hook.ts index 1ce12a5350df..28be74cfc6dc 100644 --- a/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-many.pre-query.hook.ts @@ -1,9 +1,13 @@ -import { Injectable, MethodNotAllowedException } from '@nestjs/common'; +import { MethodNotAllowedException } from '@nestjs/common'; -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; -@Injectable() -export class BlocklistUpdateManyPreQueryHook implements WorkspacePreQueryHook { +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; + +@WorkspaceQueryHook(`blocklist.updateMany`) +export class BlocklistUpdateManyPreQueryHook + implements WorkspaceQueryHookInstance +{ constructor() {} async execute(): Promise { diff --git a/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook.ts b/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook.ts index 28c39a43b2e9..cbb3f0fae562 100644 --- a/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook.ts @@ -1,15 +1,16 @@ -import { Injectable } from '@nestjs/common'; - -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { BlocklistItem, BlocklistValidationService, } from 'src/modules/connected-account/services/blocklist/blocklist-validation.service'; -@Injectable() -export class BlocklistUpdateOnePreQueryHook implements WorkspacePreQueryHook { +@WorkspaceQueryHook(`blocklist.updateOne`) +export class BlocklistUpdateOnePreQueryHook + implements WorkspaceQueryHookInstance +{ constructor( private readonly blocklistValidationService: BlocklistValidationService, ) {} diff --git a/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-query-hook.module.ts b/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-query-hook.module.ts index c711b4b567c8..d6fb5b434735 100644 --- a/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-query-hook.module.ts +++ b/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-query-hook.module.ts @@ -8,18 +8,9 @@ import { BlocklistValidationModule } from 'src/modules/connected-account/service @Module({ imports: [BlocklistValidationModule], providers: [ - { - provide: BlocklistCreateManyPreQueryHook.name, - useClass: BlocklistCreateManyPreQueryHook, - }, - { - provide: BlocklistUpdateManyPreQueryHook.name, - useClass: BlocklistUpdateManyPreQueryHook, - }, - { - provide: BlocklistUpdateOnePreQueryHook.name, - useClass: BlocklistUpdateOnePreQueryHook, - }, + BlocklistCreateManyPreQueryHook, + BlocklistUpdateManyPreQueryHook, + BlocklistUpdateOnePreQueryHook, ], }) export class ConnectedAccountQueryHookModule {} diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts index 8e82c578afe2..0e2f2a5d79a7 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts @@ -1,19 +1,16 @@ -import { - BadRequestException, - Injectable, - NotFoundException, -} from '@nestjs/common'; +import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service'; import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; -@Injectable() -export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook { +@WorkspaceQueryHook(`message.findMany`) +export class MessageFindManyPreQueryHook implements WorkspaceQueryHookInstance { constructor( @InjectObjectMetadataRepository( MessageChannelMessageAssociationWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts index 2140ac01081a..713e024894f6 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts @@ -1,16 +1,17 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { NotFoundException } from '@nestjs/common'; -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service'; import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; -@Injectable() -export class MessageFindOnePreQueryHook implements WorkspacePreQueryHook { +@WorkspaceQueryHook(`message.findOne`) +export class MessageFindOnePreQueryHook implements WorkspaceQueryHookInstance { constructor( @InjectObjectMetadataRepository( MessageChannelMessageAssociationWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts index f27adf462af7..4268de828017 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts @@ -20,14 +20,8 @@ import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/stan ], providers: [ CanAccessMessageThreadService, - { - provide: MessageFindOnePreQueryHook.name, - useClass: MessageFindOnePreQueryHook, - }, - { - provide: MessageFindManyPreQueryHook.name, - useClass: MessageFindManyPreQueryHook, - }, + MessageFindOnePreQueryHook, + MessageFindManyPreQueryHook, ], }) export class MessagingQueryHookModule {} diff --git a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-many.pre-query.hook.ts b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-many.pre-query.hook.ts index e0650b7e2548..9effd33285b7 100644 --- a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-many.pre-query.hook.ts @@ -1,10 +1,12 @@ -import { Injectable, MethodNotAllowedException } from '@nestjs/common'; +import { MethodNotAllowedException } from '@nestjs/common'; -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; -@Injectable() +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; + +@WorkspaceQueryHook(`workspaceMember.deleteMany`) export class WorkspaceMemberDeleteManyPreQueryHook - implements WorkspacePreQueryHook + implements WorkspaceQueryHookInstance { constructor() {} diff --git a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts index 67f7d3f9e64f..d5edd6ff5b32 100644 --- a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts @@ -1,16 +1,15 @@ -import { Injectable } from '@nestjs/common'; - -import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; +import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/comment.workspace-entity'; import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity'; -@Injectable() +@WorkspaceQueryHook(`workspaceMember.deleteOne`) export class WorkspaceMemberDeleteOnePreQueryHook - implements WorkspacePreQueryHook + implements WorkspaceQueryHookInstance { constructor( @InjectWorkspaceRepository(AttachmentWorkspaceEntity) diff --git a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-query-hook.module.ts b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-query-hook.module.ts index 44f2362c839c..051354c6becb 100644 --- a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-query-hook.module.ts +++ b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-query-hook.module.ts @@ -14,14 +14,8 @@ import { WorkspaceMemberDeleteOnePreQueryHook } from 'src/modules/workspace-memb ]), ], providers: [ - { - provide: WorkspaceMemberDeleteOnePreQueryHook.name, - useClass: WorkspaceMemberDeleteOnePreQueryHook, - }, - { - provide: WorkspaceMemberDeleteManyPreQueryHook.name, - useClass: WorkspaceMemberDeleteManyPreQueryHook, - }, + WorkspaceMemberDeleteOnePreQueryHook, + WorkspaceMemberDeleteManyPreQueryHook, ], }) export class WorkspaceMemberQueryHookModule {}