Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor GraphQLResponse type; drop formatResponse #6502

Merged
merged 1 commit into from
Jun 2, 2022

Conversation

glasser
Copy link
Member

@glasser glasser commented May 31, 2022

Previously, the GraphQLResponse type contains the fields that are
returned in the body of a GraphQL response, plus an http field with
statusCode and headers.

Now, we put the body fields (the "result") inside a result field next
to http. This lets us just use the graphql-js ExecutionResult and
FormattedExecutionResult types in a bunch of places as well. Among other
things, this set us up for an incremental delivery world where sometimes
there's an async iterator of these results instead of a single result.

Changes vs v3 include:

  • The GraphQLResponse type as seen on plugin
    GraphQLRequestContext.response has most of its fields move to a
    result sub-object. Also, the types of values in the objects under
    data and extensions become unknown instead of any (so
    consumers may need to do some casts).
  • Remove formatResponse hook. The newer plugin API willSendResponse
    can do anything that it can do.
  • GraphQLRequestContext.response is always set, as is
    GraphQLResponse.http.
  • GraphQLExecutionResult is replaced with the nearly identical
    ExecutionResult. This is the type returned by the gateway execute
    command. The same slight typing difference about any vs unknown
    applies here but should be pretty irrelevant as the executor is
    producing these values.
  • If a resolveOperation hook throws or if the main execute call throws,
    return 500 status code instead of 400.

Internal changes include:

  • Various functions in requestPipeline no longer return the
    GraphQLResponse (which can just be read off of
    requestContext.response).
  • New HTTPGraphQLHead type and newHTTPGraphQLHead() function
    (previously we used a Pick<HTTPGraphQLResponse> thing for this).
  • Instead of turning sendErrorResponse calls into 400s in runHttpQuery
    as a weird special case, just do it directly in sendErrorResponse.
    These errors will now also contain a content-length header.

@codesandbox-ci
Copy link

codesandbox-ci bot commented May 31, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit aafdb67:

Sandbox Source
Apollo Server Typescript Configuration
Apollo Server Configuration


return {
hints: cacheHints,
policyIfCacheable: response.extensions!.__policyIfCacheable__,
policyIfCacheable: response.result.extensions!.__policyIfCacheable__ as any,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a type argument to FormattedExecutionResult that might be the solution to the as any here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, not really sure where that would work. we would want to add generics to GraphQLResponse too then? which would have to be different for different operations? or are you just saying add a slightly different cast here?

note that the reason for this change is just that the old typings had extensions have any as its record value type and now it's unknown.

Comment on lines 431 to 432
function parse(query: string, parseOptions?: ParseOptions): DocumentNode {
return graphqlParse(query, parseOptions);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to your changes but why does this exist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before Jesse removed the old extension stack API this function called it. (05f0d2f) Sure, let's inline, why not.

updateResponseHTTP(http);

if (!requestContext.response.http.statusCode) {
// TODO(AS4): This is a bit weird because it can
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dangling comment

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I made it less weird... was going to say that a few of the things that set it seemed more 500y, but as noted in the PR desc I made those into 500s.

Previously, the GraphQLResponse type contains the fields that are
returned in the body of a GraphQL response, plus an `http` field with
statusCode and headers.

Now, we put the body fields (the "result") inside a `result` field next
to `http`. This lets us just use the graphql-js ExecutionResult and
FormattedExecutionResult types in a bunch of places as well. Among other
things, this set us up for an incremental delivery world where sometimes
there's an async iterator of these results instead of a single result.

Changes vs v3 include:
- The `GraphQLResponse` type as seen on plugin
  `GraphQLRequestContext.response` has most of its fields move to a
  `result` sub-object. Also, the types of values in the objects under
  `data` and `extensions` become `unknown` instead of `any` (so
  consumers may need to do some casts).
- Remove `formatResponse` hook. The newer plugin API `willSendResponse`
  can do anything that it can do.
- `GraphQLRequestContext.response` is always set, as is
  `GraphQLResponse.http`.
- `GraphQLExecutionResult` is replaced with the nearly identical
  `ExecutionResult`. This is the type returned by the gateway execute
  command. The same slight typing difference about any vs unknown
  applies here but should be pretty irrelevant as the executor is
  producing these values.
- If a resolveOperation hook throws or if the main execute call throws,
  return 500 status code instead of 400.

Internal changes include:
- Various functions in requestPipeline no longer return the
  GraphQLResponse (which can just be read off of
  requestContext.response).
- New HTTPGraphQLHead type and newHTTPGraphQLHead() function
  (previously we used a `Pick<HTTPGraphQLResponse>` thing for this).
- Instead of turning sendErrorResponse calls into 400s in runHttpQuery
  as a weird special case, just do it directly in sendErrorResponse.
  These errors will now also contain a `content-length` header.
@glasser glasser force-pushed the glasser/v4-response-refactor branch from f6be96a to aafdb67 Compare June 2, 2022 05:15
@glasser glasser enabled auto-merge (squash) June 2, 2022 05:15
@glasser glasser merged commit 4ecb828 into version-4 Jun 2, 2022
@glasser glasser deleted the glasser/v4-response-refactor branch June 2, 2022 05:16
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants