feat: Dynamic hook registration for WorkspaceQueryHooks (#6008)

#### Overview

This PR introduces a new API for dynamically registering and executing
pre and post query hooks in the Workspace Query Hook system using the
`@WorkspaceQueryHook` decorator. This approach eliminates the need for
manual provider registration, and fix the issue of `undefined` or `null`
repository using `@InjectWorkspaceRepository`.

#### New API

**Define a Hook**

Use the `@WorkspaceQueryHook` decorator to define pre or post hooks:

```typescript
@WorkspaceQueryHook({
  key: `calendarEvent.findMany`,
  scope: Scope.REQUEST,
})
export class CalendarEventFindManyPreQueryHook implements WorkspaceQueryHookInstance {
  async execute(userId: string, workspaceId: string, payload: FindManyResolverArgs): Promise<void> {
    if (!payload?.filter?.id?.eq) {
      throw new BadRequestException('id filter is required');
    }

    // Implement hook logic here
  }
}
```

This API simplifies the registration and execution of query hooks,
providing a more flexible and maintainable approach.

---------

Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
Jérémy M
2024-06-25 12:41:46 +02:00
committed by GitHub
parent 4dfca45fd3
commit 7c2e745b45
32 changed files with 472 additions and 235 deletions

View File

@ -141,8 +141,10 @@ export class GraphQLConfigService
// Create a new contextId for each request // Create a new contextId for each request
const contextId = ContextIdFactory.create(); const contextId = ContextIdFactory.create();
// Register the request in the contextId if (this.moduleRef.registerRequestByContextId) {
this.moduleRef.registerRequestByContextId(context.req, contextId); // Register the request in the contextId
this.moduleRef.registerRequestByContextId(context.req, contextId);
}
// Resolve the WorkspaceSchemaFactory for the contextId // Resolve the WorkspaceSchemaFactory for the contextId
const workspaceFactory = await this.moduleRef.resolve( const workspaceFactory = await this.moduleRef.resolve(

View File

@ -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],
},
};

View File

@ -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 {}

View File

@ -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<T extends ExecutePreHookMethod>(
userId: string | undefined,
workspaceId: string,
objectName: string,
method: T,
payload: WorkspacePreQueryHookPayload<T>,
): Promise<void> {
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);
}
}
}

View File

@ -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);
};
}

View File

@ -1,6 +1,6 @@
import { ResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { ResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
export interface WorkspacePreQueryHook { export interface WorkspaceQueryHookInstance {
execute( execute(
userId: string | undefined, userId: string | undefined,
workspaceId: string, workspaceId: string,

View File

@ -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<T> {
instance: T;
host: Module;
isRequestScoped: boolean;
}
@Injectable()
export class WorkspaceQueryHookStorage {
private preHookInstances = new Map<
WorkspaceQueryHookKey,
WorkspaceQueryHookData<WorkspaceQueryHookInstance>[]
>();
private postHookInstances = new Map<
WorkspaceQueryHookKey,
WorkspaceQueryHookData<WorkspaceQueryHookInstance>[]
>();
registerWorkspaceQueryPreHookInstance(
key: WorkspaceQueryHookKey,
data: WorkspaceQueryHookData<WorkspaceQueryHookInstance>,
) {
if (!this.preHookInstances.has(key)) {
this.preHookInstances.set(key, []);
}
this.preHookInstances.get(key)?.push(data);
}
getWorkspaceQueryPreHookInstances(
key: WorkspaceQueryHookKey,
): WorkspaceQueryHookData<WorkspaceQueryHookInstance>[] | undefined {
return this.preHookInstances.get(key);
}
registerWorkspaceQueryPostHookInstance(
key: WorkspaceQueryHookKey,
data: WorkspaceQueryHookData<WorkspaceQueryHookInstance>,
) {
if (!this.postHookInstances.has(key)) {
this.postHookInstances.set(key, []);
}
this.postHookInstances.get(key)?.push(data);
}
getWorkspaceQueryPostHookInstances(
key: WorkspaceQueryHookKey,
): WorkspaceQueryHookData<WorkspaceQueryHookInstance>[] | undefined {
return this.postHookInstances.get(key);
}
}

View File

@ -10,26 +10,10 @@ import {
UpdateOneResolverArgs, UpdateOneResolverArgs,
} from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
export type ExecutePreHookMethod = export enum WorkspaceQueryHookType {
| 'createMany' PreHook = 'PreHook',
| 'createOne' PostHook = 'PostHook',
| '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 type WorkspacePreQueryHookPayload<T> = T extends 'createMany' export type WorkspacePreQueryHookPayload<T> = T extends 'createMany'
? CreateManyResolverArgs ? CreateManyResolverArgs

View File

@ -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<any> | Function): boolean {
if (!target) {
return false;
}
return !!this.reflector.get(WORKSPACE_QUERY_HOOK_METADATA, target);
}
getWorkspaceQueryHookMetadata(
target: Type<any> | Function,
): WorkspaceQueryHookOptions | undefined {
return this.reflector.get(WORKSPACE_QUERY_HOOK_METADATA, target);
}
}

View File

@ -0,0 +1,3 @@
export const WORKSPACE_QUERY_HOOK_METADATA = Symbol(
'workspace-query-hook:query-hook-metadata',
);

View File

@ -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<WorkspaceQueryHookInstance['execute']>,
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;
}
}
}

View File

@ -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 {}

View File

@ -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<T>,
): Promise<void> {
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,
);
}
}
}

View File

@ -2,7 +2,7 @@ import { Module } from '@nestjs/common';
import { WorkspaceQueryBuilderModule } from 'src/engine/api/graphql/workspace-query-builder/workspace-query-builder.module'; 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 { 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 { workspaceQueryRunnerFactories } from 'src/engine/api/graphql/workspace-query-runner/factories';
import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; 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, AuthModule,
WorkspaceQueryBuilderModule, WorkspaceQueryBuilderModule,
WorkspaceDataSourceModule, WorkspaceDataSourceModule,
WorkspacePreQueryHookModule, WorkspaceQueryHookModule,
ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]), ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]),
AnalyticsModule, AnalyticsModule,
], ],

View File

@ -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 { 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 { 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 { 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 { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { NotFoundError } from 'src/engine/utils/graphql-errors.util'; import { NotFoundError } from 'src/engine/utils/graphql-errors.util';
import { QueryRunnerArgsFactory } from 'src/engine/api/graphql/workspace-query-runner/factories/query-runner-args.factory'; 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) @InjectMessageQueue(MessageQueue.webhookQueue)
private readonly messageQueueService: MessageQueueService, private readonly messageQueueService: MessageQueueService,
private readonly eventEmitter: EventEmitter2, private readonly eventEmitter: EventEmitter2,
private readonly workspacePreQueryHookService: WorkspacePreQueryHookService, private readonly workspaceQueryHookService: WorkspaceQueryHookService,
private readonly environmentService: EnvironmentService, private readonly environmentService: EnvironmentService,
) {} ) {}
@ -101,7 +101,7 @@ export class WorkspaceQueryRunnerService {
options, options,
); );
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,
@ -148,7 +148,7 @@ export class WorkspaceQueryRunnerService {
options, options,
); );
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,
@ -223,7 +223,7 @@ export class WorkspaceQueryRunnerService {
existingRecord, existingRecord,
); );
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,
@ -260,7 +260,7 @@ export class WorkspaceQueryRunnerService {
ResolverArgsType.CreateMany, ResolverArgsType.CreateMany,
)) as CreateManyResolverArgs<Record>; )) as CreateManyResolverArgs<Record>;
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,
@ -333,7 +333,7 @@ export class WorkspaceQueryRunnerService {
options, options,
); );
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,
@ -389,7 +389,7 @@ export class WorkspaceQueryRunnerService {
atMost: maximumRecordAffected, atMost: maximumRecordAffected,
}); });
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,
@ -441,7 +441,7 @@ export class WorkspaceQueryRunnerService {
atMost: maximumRecordAffected, atMost: maximumRecordAffected,
}); });
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,
@ -509,7 +509,7 @@ export class WorkspaceQueryRunnerService {
); );
// TODO END // TODO END
await this.workspacePreQueryHookService.executePreHooks( await this.workspaceQueryHookService.executePreQueryHooks(
userId, userId,
workspaceId, workspaceId,
objectMetadataItem.nameSingular, objectMetadataItem.nameSingular,

View File

@ -47,10 +47,17 @@ export class PgBossDriver
} }
: {}, : {},
async (job) => { 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({ await handler({
data: job.data, data: job.data,
id: job.id, id: job.id,
name: job.name.split('.')[1], name: jobName,
}); });
}, },
); );

View File

@ -14,7 +14,7 @@ export class ScopedWorkspaceDatasourceFactory {
public async create(entities: EntitySchema[]) { public async create(entities: EntitySchema[]) {
const workspaceId: string | undefined = const workspaceId: string | undefined =
this.request['req']?.['workspaceId']; this.request?.['req']?.['workspaceId'];
if (!workspaceId) { if (!workspaceId) {
return null; return null;

View File

@ -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 { 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 { 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 { 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 { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; 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 export class CalendarEventFindManyPreQueryHook
implements WorkspacePreQueryHook implements WorkspaceQueryHookInstance
{ {
constructor( constructor(
@InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity)
@ -27,25 +31,24 @@ export class CalendarEventFindManyPreQueryHook
throw new BadRequestException('id filter is required'); throw new BadRequestException('id filter is required');
} }
// TODO: Re-implement this using twenty ORM const calendarChannelCalendarEventAssociations =
// const calendarChannelCalendarEventAssociations = await this.calendarChannelEventAssociationRepository.find({
// await this.calendarChannelEventAssociationRepository.find({ where: {
// where: { calendarEvent: {
// calendarEvent: { id: payload?.filter?.id?.eq,
// id: payload?.filter?.id?.eq, },
// }, },
// }, relations: ['calendarChannel.connectedAccount'],
// relations: ['calendarChannel.connectedAccount'], });
// });
// if (calendarChannelCalendarEventAssociations.length === 0) { if (calendarChannelCalendarEventAssociations.length === 0) {
// throw new NotFoundException(); throw new NotFoundException();
// } }
// await this.canAccessCalendarEventService.canAccessCalendarEvent( await this.canAccessCalendarEventService.canAccessCalendarEvent(
// userId, userId,
// workspaceId, workspaceId,
// calendarChannelCalendarEventAssociations, calendarChannelCalendarEventAssociations,
// ); );
} }
} }

View File

@ -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 { 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 { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; 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 { 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'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.workspace-entity';
@Injectable() @WorkspaceQueryHook({
export class CalendarEventFindOnePreQueryHook implements WorkspacePreQueryHook { key: `calendarEvent.findOne`,
scope: Scope.REQUEST,
})
export class CalendarEventFindOnePreQueryHook
implements WorkspaceQueryHookInstance
{
constructor( constructor(
@InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity)
private readonly calendarChannelEventAssociationRepository: WorkspaceRepository<CalendarChannelEventAssociationWorkspaceEntity>, private readonly calendarChannelEventAssociationRepository: WorkspaceRepository<CalendarChannelEventAssociationWorkspaceEntity>,
@ -26,23 +32,24 @@ export class CalendarEventFindOnePreQueryHook implements WorkspacePreQueryHook {
} }
// TODO: Re-implement this using twenty ORM // TODO: Re-implement this using twenty ORM
// const calendarChannelCalendarEventAssociations = const calendarChannelCalendarEventAssociations =
// await this.calendarChannelEventAssociationRepository.find({ await this.calendarChannelEventAssociationRepository.find({
// where: { where: {
// calendarEvent: { calendarEvent: {
// id: payload?.filter?.id?.eq, id: payload?.filter?.id?.eq,
// }, },
// }, },
// }); relations: ['calendarChannel.connectedAccount'],
});
// if (calendarChannelCalendarEventAssociations.length === 0) { if (calendarChannelCalendarEventAssociations.length === 0) {
// throw new NotFoundException(); throw new NotFoundException();
// } }
// await this.canAccessCalendarEventService.canAccessCalendarEvent( await this.canAccessCalendarEventService.canAccessCalendarEvent(
// userId, userId,
// workspaceId, workspaceId,
// calendarChannelCalendarEventAssociations, calendarChannelCalendarEventAssociations,
// ); );
} }
} }

View File

@ -60,7 +60,7 @@ export class CanAccessCalendarEventService {
const calendarChannelsConnectedAccounts = const calendarChannelsConnectedAccounts =
await this.connectedAccountRepository.getByIds( await this.connectedAccountRepository.getByIds(
calendarChannels.map((channel) => channel.connectedAccount.id), calendarChannels.map((channel) => channel.connectedAccountId),
workspaceId, workspaceId,
); );

View File

@ -23,14 +23,8 @@ import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
], ],
providers: [ providers: [
CanAccessCalendarEventService, CanAccessCalendarEventService,
{ CalendarEventFindOnePreQueryHook,
provide: CalendarEventFindOnePreQueryHook.name, CalendarEventFindManyPreQueryHook,
useClass: CalendarEventFindOnePreQueryHook,
},
{
provide: CalendarEventFindManyPreQueryHook.name,
useClass: CalendarEventFindManyPreQueryHook,
},
], ],
}) })
export class CalendarQueryHookModule {} export class CalendarQueryHookModule {}

View File

@ -237,6 +237,8 @@ export class CalendarChannelWorkspaceEntity extends BaseWorkspaceEntity {
}) })
connectedAccount: Relation<ConnectedAccountWorkspaceEntity>; connectedAccount: Relation<ConnectedAccountWorkspaceEntity>;
connectedAccountId: string;
@WorkspaceRelation({ @WorkspaceRelation({
standardId: standardId:
CALENDAR_CHANNEL_STANDARD_FIELD_IDS.calendarChannelEventAssociations, CALENDAR_CHANNEL_STANDARD_FIELD_IDS.calendarChannelEventAssociations,

View File

@ -1,15 +1,16 @@
import { Injectable } from '@nestjs/common'; import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.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 { import {
BlocklistItem, BlocklistItem,
BlocklistValidationService, BlocklistValidationService,
} from 'src/modules/connected-account/services/blocklist/blocklist-validation.service'; } from 'src/modules/connected-account/services/blocklist/blocklist-validation.service';
@Injectable() @WorkspaceQueryHook(`blocklist.createMany`)
export class BlocklistCreateManyPreQueryHook implements WorkspacePreQueryHook { export class BlocklistCreateManyPreQueryHook
implements WorkspaceQueryHookInstance
{
constructor( constructor(
private readonly blocklistValidationService: BlocklistValidationService, private readonly blocklistValidationService: BlocklistValidationService,
) {} ) {}

View File

@ -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() import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
export class BlocklistUpdateManyPreQueryHook implements WorkspacePreQueryHook {
@WorkspaceQueryHook(`blocklist.updateMany`)
export class BlocklistUpdateManyPreQueryHook
implements WorkspaceQueryHookInstance
{
constructor() {} constructor() {}
async execute(): Promise<void> { async execute(): Promise<void> {

View File

@ -1,15 +1,16 @@
import { Injectable } from '@nestjs/common'; import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.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 { import {
BlocklistItem, BlocklistItem,
BlocklistValidationService, BlocklistValidationService,
} from 'src/modules/connected-account/services/blocklist/blocklist-validation.service'; } from 'src/modules/connected-account/services/blocklist/blocklist-validation.service';
@Injectable() @WorkspaceQueryHook(`blocklist.updateOne`)
export class BlocklistUpdateOnePreQueryHook implements WorkspacePreQueryHook { export class BlocklistUpdateOnePreQueryHook
implements WorkspaceQueryHookInstance
{
constructor( constructor(
private readonly blocklistValidationService: BlocklistValidationService, private readonly blocklistValidationService: BlocklistValidationService,
) {} ) {}

View File

@ -8,18 +8,9 @@ import { BlocklistValidationModule } from 'src/modules/connected-account/service
@Module({ @Module({
imports: [BlocklistValidationModule], imports: [BlocklistValidationModule],
providers: [ providers: [
{ BlocklistCreateManyPreQueryHook,
provide: BlocklistCreateManyPreQueryHook.name, BlocklistUpdateManyPreQueryHook,
useClass: BlocklistCreateManyPreQueryHook, BlocklistUpdateOnePreQueryHook,
},
{
provide: BlocklistUpdateManyPreQueryHook.name,
useClass: BlocklistUpdateManyPreQueryHook,
},
{
provide: BlocklistUpdateOnePreQueryHook.name,
useClass: BlocklistUpdateOnePreQueryHook,
},
], ],
}) })
export class ConnectedAccountQueryHookModule {} export class ConnectedAccountQueryHookModule {}

View File

@ -1,19 +1,16 @@
import { import { BadRequestException, NotFoundException } from '@nestjs/common';
BadRequestException,
Injectable,
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 { 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 { 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 { 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 { 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'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
@Injectable() @WorkspaceQueryHook(`message.findMany`)
export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook { export class MessageFindManyPreQueryHook implements WorkspaceQueryHookInstance {
constructor( constructor(
@InjectObjectMetadataRepository( @InjectObjectMetadataRepository(
MessageChannelMessageAssociationWorkspaceEntity, MessageChannelMessageAssociationWorkspaceEntity,

View File

@ -1,16 +1,17 @@
/* eslint-disable @typescript-eslint/no-unused-vars */ /* 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 { 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 { 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 { 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 { 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'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
@Injectable() @WorkspaceQueryHook(`message.findOne`)
export class MessageFindOnePreQueryHook implements WorkspacePreQueryHook { export class MessageFindOnePreQueryHook implements WorkspaceQueryHookInstance {
constructor( constructor(
@InjectObjectMetadataRepository( @InjectObjectMetadataRepository(
MessageChannelMessageAssociationWorkspaceEntity, MessageChannelMessageAssociationWorkspaceEntity,

View File

@ -20,14 +20,8 @@ import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/stan
], ],
providers: [ providers: [
CanAccessMessageThreadService, CanAccessMessageThreadService,
{ MessageFindOnePreQueryHook,
provide: MessageFindOnePreQueryHook.name, MessageFindManyPreQueryHook,
useClass: MessageFindOnePreQueryHook,
},
{
provide: MessageFindManyPreQueryHook.name,
useClass: MessageFindManyPreQueryHook,
},
], ],
}) })
export class MessagingQueryHookModule {} export class MessagingQueryHookModule {}

View File

@ -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 export class WorkspaceMemberDeleteManyPreQueryHook
implements WorkspacePreQueryHook implements WorkspaceQueryHookInstance
{ {
constructor() {} constructor() {}

View File

@ -1,16 +1,15 @@
import { Injectable } from '@nestjs/common'; import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.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 { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/comment.workspace-entity'; import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/comment.workspace-entity';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity'; import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
@Injectable() @WorkspaceQueryHook(`workspaceMember.deleteOne`)
export class WorkspaceMemberDeleteOnePreQueryHook export class WorkspaceMemberDeleteOnePreQueryHook
implements WorkspacePreQueryHook implements WorkspaceQueryHookInstance
{ {
constructor( constructor(
@InjectWorkspaceRepository(AttachmentWorkspaceEntity) @InjectWorkspaceRepository(AttachmentWorkspaceEntity)

View File

@ -14,14 +14,8 @@ import { WorkspaceMemberDeleteOnePreQueryHook } from 'src/modules/workspace-memb
]), ]),
], ],
providers: [ providers: [
{ WorkspaceMemberDeleteOnePreQueryHook,
provide: WorkspaceMemberDeleteOnePreQueryHook.name, WorkspaceMemberDeleteManyPreQueryHook,
useClass: WorkspaceMemberDeleteOnePreQueryHook,
},
{
provide: WorkspaceMemberDeleteManyPreQueryHook.name,
useClass: WorkspaceMemberDeleteManyPreQueryHook,
},
], ],
}) })
export class WorkspaceMemberQueryHookModule {} export class WorkspaceMemberQueryHookModule {}