Skip to content

Instantly share code, notes, and snippets.

@EndyKaufman
Last active January 22, 2024 20:47
Show Gist options
  • Save EndyKaufman/aa8a7ebb750540217a08fac72292a9c2 to your computer and use it in GitHub Desktop.
Save EndyKaufman/aa8a7ebb750540217a08fac72292a9c2 to your computer and use it in GitHub Desktop.
CoreClassSerializerInterceptor.ts
import { CallHandler, ClassSerializerInterceptor, ExecutionContext, Injectable, Logger, Module, PlainLiteralObject, SetMetadata, Type } from '@nestjs/common';
import { APP_INTERCEPTOR, Reflector } from '@nestjs/core';
import { ClassTransformOptions, plainToClass } from 'class-transformer';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export const GQL_RETURN_TYPE = 'GQL_RETURN_TYPE';
export const GqlReturn = (type: Type<any>) => SetMetadata('GQL_RETURN_TYPE', type);
@Resolver()
export class PaymentBalanceResolver {
@GqlReturn(BalanceDto)
@Query(() => BalanceDto, {
nullable: false,
})
getUserBalance(@CurrentUser() currentUser: CurrentUserType): Observable<BalanceDto> {
return this.paymentBalanceService.getUserBalance(currentUser.id);
}
}
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useFactory: (reflector: any): ClassSerializerInterceptor => new ClassSerializerInterceptor(reflector),
inject: [Reflector],
},
PaymentBalanceResolver,
],
})
export class AppModule {}
@Injectable()
export class CoreClassSerializerInterceptor extends ClassSerializerInterceptor {
private readonly logger = new Logger(CoreClassSerializerInterceptor.name);
constructor(protected readonly reflector: any, defaultOptions?: ClassTransformOptions) {
super(reflector, defaultOptions);
this.logger.log('create');
}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
if ((context.getType() as string) === 'graphql') {
const op = context.getArgByIndex(3).operation.operation;
if (op === 'subscription') {
return next.handle();
}
const contextOptions = this.getContextOptions(context);
const options = {
...this.defaultOptions,
...contextOptions,
};
return next
.handle()
.pipe(
map((res: PlainLiteralObject | Array<PlainLiteralObject>) =>
this.serialize(res, { ...options, returnClass: Reflect.getMetadata(GQL_RETURN_TYPE, context.getHandler()) })
)
);
}
return next.handle();
}
serialize(
response: PlainLiteralObject | Array<PlainLiteralObject>,
options: ClassTransformOptions & { returnClass: any }
): PlainLiteralObject | Array<PlainLiteralObject> {
try {
const result = super.serialize(options.returnClass ? plainToClass(options.returnClass, response) : response, options);
return result;
} catch (err) {
this.logger.debug(response);
this.logger.error(err);
throw err;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment