Add workspacePreQueryHook module (#3879)

* rebase

* reorganise messaging folders

* fix

* fix after review

* fix yarn lock
This commit is contained in:
Weiko
2024-02-13 18:23:29 +01:00
committed by GitHub
parent 36b69a8625
commit 458e8c839f
63 changed files with 494 additions and 70 deletions

View File

@ -5,6 +5,7 @@ import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/
export interface WorkspaceQueryRunnerOptions {
workspaceId: string;
userId: string | undefined;
info: GraphQLResolveInfo;
objectMetadataItem: ObjectMetadataInterface;
fieldMetadataCollection: FieldMetadataInterface[];

View File

@ -0,0 +1,9 @@
import { ResolverArgs } from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
export interface WorkspacePreQueryHook {
execute(
userId: string | undefined,
workspaceId: string,
payload: ResolverArgs,
): Promise<void>;
}

View File

@ -0,0 +1,48 @@
import {
CreateManyResolverArgs,
CreateOneResolverArgs,
DeleteManyResolverArgs,
DeleteOneResolverArgs,
FindManyResolverArgs,
FindOneResolverArgs,
UpdateManyResolverArgs,
UpdateOneResolverArgs,
} from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
export type ExecutePreHookMethod =
| 'createMany'
| 'createOne'
| 'deleteMany'
| 'deleteOne'
| 'findMany'
| 'findOne'
| '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'
? CreateManyResolverArgs
: T extends 'createOne'
? CreateOneResolverArgs
: T extends 'deleteMany'
? DeleteManyResolverArgs
: T extends 'deleteOne'
? DeleteOneResolverArgs
: T extends 'findMany'
? FindManyResolverArgs
: T extends 'findOne'
? FindOneResolverArgs
: T extends 'updateMany'
? UpdateManyResolverArgs
: T extends 'updateOne'
? UpdateOneResolverArgs
: never;

View File

@ -0,0 +1,11 @@
import { MessageFindManyPreQueryHook } from 'src/workspace/messaging/query-hooks/message/message-find-many.pre-query.hook';
import { MessageFindOnePreQueryHook } from 'src/workspace/messaging/query-hooks/message/message-find-one.pre-query-hook';
import { WorkspaceQueryHook } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type';
// TODO: move to a decorator
export const workspacePreQueryHooks: WorkspaceQueryHook = {
message: {
findOne: [MessageFindOnePreQueryHook.name],
findMany: [MessageFindManyPreQueryHook.name],
},
};

View File

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { MessagingQueryHookModule } from 'src/workspace/messaging/query-hooks/messaging-query-hook.module';
import { WorkspacePreQueryHookService } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service';
@Module({
imports: [MessagingQueryHookModule],
providers: [WorkspacePreQueryHookService],
exports: [WorkspacePreQueryHookService],
})
export class WorkspacePreQueryHookModule {}

View File

@ -0,0 +1,34 @@
import { Injectable } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { WorkspacePreQueryHook } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
import {
ExecutePreHookMethod,
WorkspacePreQueryHookPayload,
} from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type';
import { workspacePreQueryHooks } from 'src/workspace/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

@ -2,11 +2,16 @@ import { Module } from '@nestjs/common';
import { WorkspaceQueryBuilderModule } from 'src/workspace/workspace-query-builder/workspace-query-builder.module';
import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module';
import { WorkspacePreQueryHookModule } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module';
import { WorkspaceQueryRunnerService } from './workspace-query-runner.service';
@Module({
imports: [WorkspaceQueryBuilderModule, WorkspaceDataSourceModule],
imports: [
WorkspaceQueryBuilderModule,
WorkspaceDataSourceModule,
WorkspacePreQueryHookModule,
],
providers: [WorkspaceQueryRunnerService],
exports: [WorkspaceQueryRunnerService],
})

View File

@ -38,6 +38,7 @@ import { computeObjectTargetTable } from 'src/workspace/utils/compute-object-tar
import { ObjectRecordDeleteEvent } from 'src/integrations/event-emitter/types/object-record-delete.event';
import { ObjectRecordCreateEvent } from 'src/integrations/event-emitter/types/object-record-create.event';
import { ObjectRecordUpdateEvent } from 'src/integrations/event-emitter/types/object-record-update.event';
import { WorkspacePreQueryHookService } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service';
import { WorkspaceQueryRunnerOptions } from './interfaces/query-runner-option.interface';
import {
@ -53,6 +54,7 @@ export class WorkspaceQueryRunnerService {
@Inject(MessageQueue.webhookQueue)
private readonly messageQueueService: MessageQueueService,
private readonly eventEmitter: EventEmitter2,
private readonly workspacePreQueryHookService: WorkspacePreQueryHookService,
) {}
async findMany<
@ -63,7 +65,7 @@ export class WorkspaceQueryRunnerService {
args: FindManyResolverArgs<Filter, OrderBy>,
options: WorkspaceQueryRunnerOptions,
): Promise<IConnection<Record> | undefined> {
const { workspaceId, objectMetadataItem } = options;
const { workspaceId, userId, objectMetadataItem } = options;
const start = performance.now();
const query = await this.workspaceQueryBuilderFactory.findMany(
@ -71,6 +73,14 @@ export class WorkspaceQueryRunnerService {
options,
);
await this.workspacePreQueryHookService.executePreHooks(
userId,
workspaceId,
objectMetadataItem.nameSingular,
'findMany',
args,
);
const result = await this.execute(query, workspaceId);
const end = performance.now();
@ -97,11 +107,20 @@ export class WorkspaceQueryRunnerService {
if (!args.filter || Object.keys(args.filter).length === 0) {
throw new BadRequestException('Missing filter argument');
}
const { workspaceId, objectMetadataItem } = options;
const { workspaceId, userId, objectMetadataItem } = options;
const query = await this.workspaceQueryBuilderFactory.findOne(
args,
options,
);
await this.workspacePreQueryHookService.executePreHooks(
userId,
workspaceId,
objectMetadataItem.nameSingular,
'findOne',
args,
);
const result = await this.execute(query, workspaceId);
const parsedResult = this.parseResult<IConnection<Record>>(
result,
@ -170,6 +189,7 @@ export class WorkspaceQueryRunnerService {
args,
options,
);
const result = await this.execute(query, workspaceId);
const parsedResults = this.parseResult<PGGraphQLMutation<Record>>(
@ -232,6 +252,7 @@ export class WorkspaceQueryRunnerService {
args,
options,
);
const result = await this.execute(query, workspaceId);
const parsedResults = this.parseResult<PGGraphQLMutation<Record>>(
@ -338,7 +359,7 @@ export class WorkspaceQueryRunnerService {
const result = graphqlResult?.[0]?.resolve?.data?.[entityKey];
const errors = graphqlResult?.[0]?.resolve?.errors;
if (!result) {
if (errors && errors.length > 0) {
throw new InternalServerErrorException(
`GraphQL errors on ${command}${
objectMetadataItem.nameSingular