We were using a global ValidationPipe in main.ts. This is an issue as @Controllers should return HttpExecption and @Resolvers should return GraphqlErrors Removing the global pipe and creating a ResolverValidationPipe able to generate GraphqlError. We also need to handle the exception in a filter to avoid nest to think it's unhandled and make it flow to logs Next step: - it would be nice to have both @UsePipes(ResolverValidationPipe) + @UseFilters(GraphqlValidationExceptionFilter) come together. This should be possible if we create a @GraphQLResolver annotation
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
import { Inject, UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
|
import { Args, Resolver, Subscription } from '@nestjs/graphql';
|
|
|
|
import { RedisPubSub } from 'graphql-redis-subscriptions';
|
|
import { isDefined } from 'twenty-shared/utils';
|
|
|
|
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
|
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
|
import { UserAuthGuard } from 'src/engine/guards/user-auth.guard';
|
|
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
|
import { OnDbEventDTO } from 'src/engine/subscriptions/dtos/on-db-event.dto';
|
|
import { OnDbEventInput } from 'src/engine/subscriptions/dtos/on-db-event.input';
|
|
|
|
@Resolver()
|
|
@UseGuards(WorkspaceAuthGuard, UserAuthGuard)
|
|
@UsePipes(ResolverValidationPipe)
|
|
@UseFilters(PreventNestToAutoLogGraphqlErrorsFilter)
|
|
export class SubscriptionsResolver {
|
|
constructor(@Inject('PUB_SUB') private readonly pubSub: RedisPubSub) {}
|
|
|
|
@Subscription(() => OnDbEventDTO, {
|
|
filter: (
|
|
payload: { onDbEvent: OnDbEventDTO },
|
|
variables: { input: OnDbEventInput },
|
|
) => {
|
|
const isActionMatching =
|
|
!isDefined(variables.input.action) ||
|
|
payload.onDbEvent.action === variables.input.action;
|
|
|
|
const isObjectNameSingularMatching =
|
|
!isDefined(variables.input.objectNameSingular) ||
|
|
payload.onDbEvent.objectNameSingular ===
|
|
variables.input.objectNameSingular;
|
|
|
|
const isRecordIdMatching =
|
|
!isDefined(variables.input.recordId) ||
|
|
payload.onDbEvent.record.id === variables.input.recordId;
|
|
|
|
return (
|
|
isActionMatching && isObjectNameSingularMatching && isRecordIdMatching
|
|
);
|
|
},
|
|
})
|
|
onDbEvent(@Args('input') _: OnDbEventInput) {
|
|
return this.pubSub.asyncIterator('onDbEvent');
|
|
}
|
|
}
|