Feat/async formatters [formatError, formatResponse]
Context
I want to use internationalization inside the formatError, because I don't want to pass the context to translate the message for all the resolvers when I could just pass once. But unfortunately the library I'm using to do that is based on promises and the formatError didn't support that. Also, the request context wasn't being passed to it, and information about the request can be really relevant when comes to format errors, for example I could use the request headers to get the accept language to translate the message according to the user browser.
Changes
- Enabled promises to format error
- Enabled promises to format response
- Add request context to format error
@greguintow: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/
We agree that it's reasonable to get a full GraphQLRequestContext for all request-based hooks and to be able to use async functions. In fact, that's how the plugin API works; GraphQLRequestContext was literally introduced as "the thing that all plugins receive" and as of AS3, almost all plugin APIs are async.
formatError is an older hook and so it's inconsistent with the newer plugin system. My main thought is it might make sense to fully deprecate formatError and provide this functionality via the plugin system — either by extending the existing didEncounterErrors to be able to optionally return a replacement error list (or mutate requestContext.errors), or by adding a new formatError equivalent to it, or something. (We'd have to think about what it means if multiple plugins try to do this, though!)
I think it wouldn't be possible to do formatError with didEncounterErrors, also it's not a responsibility of a plugin, as the website says:
Plugins extend Apollo Server's functionality by performing custom operations in response to certain events. These events correspond to individual phases of the GraphQL request lifecycle, and to the lifecycle of Apollo Server itself.
I think my solution could provide a simplicity to format the error in the end of the request without adding so much complexity of thinking in all the possible behaviors could have by having it inside didEncounterErrors
We have significantly rewritten how error handling works in AS4 so this PR does not apply directly and I'm going to close it.
We made some improvements to formatError but we did not make it async or provide the full GraphQLRequestContext to it. You can use didEncounterErrors/didEncounterSubsequentErrors or willSendResponse/willSendSubsequentPayload to rewrite errors with access to GraphQLRequestContext and as an async function, though this doesn't handle errors that occur early in processing an operation (before the GraphQLRequestContext has been constructed). Those errors now do consistently use formatError and also invoke invalidRequestWasReceived or contextCreationDidFail hooks; I'm not sure if those hooks can successfully rewrite the error but it would be nice to improve them so that they can.
While I'm not a huge fan of optionally-async functions, it might be appropriate to change formatError in this way because we (oops) didn't make it async in AS4.