I would like to log a GraphQL-Request and its GraphQL-Response to database for some use cases. So far I have written a GraphQLExtension to access all data I need:
export class LoggingExtension extends GraphQLExtension {
willSendResponse(data: any): any {
/*
* data.graphqlResponse.data -> equal to { data: {} } of response
* data.graphqlResponse.errors -> equal to { errors: [] } of response
* data.context.user -> Authenticated user (added to context by AuthGuard)
* data.context.body.query -> equal to GraphQL-Request
*/
// Process data and (if necessary) write to database..
return data;
}
}
This Extension is integrated by GraphQLModule.forRoot({extensions: ...} inside my AppModule-Definition:
@Module({
imports: [
TypeOrmModule.forRoot({/*...*/}),
GraphQLModule.forRoot({
autoSchemaFile: 'schema.gql',
typePaths: ['./**/*.graphql'],
extensions: [() => new LoggingExtension()],
context: ({ req }) => ({
headers: req.headers,
user: req.user,
body: req.body
})
}),
/*...*/,
LogModule // provides and exports injectable LogService
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
]
})
export class AppModule {}
It seems to be that I am not able to to use the @Inject-Decorator in my LoggingExtension-Class because I would have to inject the LogService through its constructor. And unfortunately I am not able to pass the LogService to it during the initialisation of extensions from the GraphQLModule.
Therefore I have implemented alternatively an LoggingInterceptor which should do the same like the extension before. On contrast to extensions interceptors are injectable. So I am able to access my LogService I need to write to database. The only problem is that I can't access the final GraphQL-Response with its data- and error properties. (EDIT: Furthermore I cannot access neither the request-body nor the authenticated user. Solved by @jay-mcdoniel, accessible through GqlExecutionContext.create(context).getContext())
Instead the Interceptor provides the hole data of the processed query with all its resolved properties and the exceptions (in case of errors).
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(tap(
allData => console.log(allData),
exception => console.log(exception)));
}
}
But I want to access the data of the GraphQLResponse. I figured out that the interceptor is called before the extension. So the GraphQLResponse-Object does not seem to exist yet. Its generated after the interceptor gets called.
Any ideas?
from How to log final GraphQL-Reponse in Nest.js with injected Service to database
No comments:
Post a Comment