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

Export ErrorCode and ErrorName enums and types from apollo-server-errors #6316

Closed
wants to merge 2 commits into from

Conversation

brycefranzen
Copy link

@brycefranzen brycefranzen commented Apr 13, 2022

Functionality is the same.

This PR updates apollo-server-errors to have strict types rather than magic strings and then exports those types for use in other applications.

We need these types exported for correctly handling errors on apollo-client (react)

@apollo-cla
Copy link

@brycefranzen: 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/

@netlify
Copy link

netlify bot commented Apr 13, 2022

👷 Deploy request for apollo-server-docs pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit bfbaae1

@codesandbox-ci
Copy link

codesandbox-ci bot commented Apr 13, 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 bfbaae1:

Sandbox Source
Apollo Server Typescript Configuration
Apollo Server Configuration

@JVMartin
Copy link

Much better.. these shouldn't need to be "magic strings" anywhere. Thanks!

@glasser
Copy link
Member

glasser commented Apr 13, 2022

@brycefranzen It's basically impossible to review this PR since GitHub isn't recognizing the file rename. Is it possible to split into multiple commits, some of which do the rename and some of which make the changes? Or perhaps just don't do the file separation at all; we've moved the contents of this file around a bunch on version-4 already so keeping the original file will make merging easier.

Also there's a good chance we won't merge this directly into main (though it'll be easier to decide that once we can tell what the actual diff is), since we're currently focused on Apollo Server 4 which simplifies a lot of things about AS. Figuring out a better future for ApolloError is one of those things. We (probably @IvanGoncharov) are working on this relatively soon (#6053) and we should definitely take the needs addressed in this PR into consideration as part of that.

@brycefranzen
Copy link
Author

brycefranzen commented Apr 13, 2022

updated below

@brycefranzen brycefranzen reopened this Apr 13, 2022
@brycefranzen
Copy link
Author

brycefranzen commented Apr 13, 2022

@brycefranzen It's basically impossible to review this PR since GitHub isn't recognizing the file rename. Is it possible to split into multiple commits, some of which do the rename and some of which make the changes? Or perhaps just don't do the file separation at all; we've moved the contents of this file around a bunch on version-4 already so keeping the original file will make merging easier.

Also there's a good chance we won't merge this directly into main (though it'll be easier to decide that once we can tell what the actual diff is), since we're currently focused on Apollo Server 4 which simplifies a lot of things about AS. Figuring out a better future for ApolloError is one of those things. We (probably @IvanGoncharov) are working on this relatively soon (#6053) and we should definitely take the needs addressed in this PR into consideration as part of that.

I have split the changes into separate commits. Looks like the diff is still not displaying the rename correctly :/ However, now you can view the changes in commit diffs: bfbaae1

If the preference is that I don't rename the file, I can do that instead. However, this matches the structure of the rest of the project to have the "index" file export everything and have separate files aside from the "index" file for the logic.

@glasser
Copy link
Member

glasser commented Apr 20, 2022

Thanks, this is now reviewable!

@IvanGoncharov what do you think of this change?

@glasser
Copy link
Member

glasser commented Apr 27, 2022

I wonder if a better model would be for each error type to have a static code property so that it's UserInputError.code rather than ErrorCode.USER_INPUT_ERROR. Is it important to be able to declare things to have an ErrorCode type?

@brycefranzen
Copy link
Author

I wonder if a better model would be for each error type to have a static code property so that it's UserInputError.code rather than ErrorCode.USER_INPUT_ERROR. Is it important to be able to declare things to have an ErrorCode type?

Yes, we need to be able to declare an error response from the server on apollo-client as being an "ErrorCode" type. We would like to be able to use this new exported "ErrorCode" type in react apollo-client to handle server errors correctly rather than checking for "magic strings" returned from the server.

For consistency, these changes follow the same structure/logic for handling types as is used in the rest of the apollographql repo. The code works, is reviewable, and all checks have passed. What's the hold-up/hesitation on merging this MR?

@glasser
Copy link
Member

glasser commented Jun 21, 2022

Well the main reason is that we've completely rewritten error handling to simplify it a lot on the version-4 branch, so I'd like to get input from @IvanGoncharov who did that work. We also have been cautious about the use of TypeScript enums; we only have one in AS3 (CacheScope) and we've changed it to export type CacheScope = 'PUBLIC' | 'PRIVATE' in AS4, because we've found that keeping our interfaces as "type-only" as possible seems superior. So the static approach would only add runtime code to classes which already require runtime code.

Is the idea that you actually want to use ErrorCode at runtime? So you would have some sort of "is this an ErrorCode" function too?

@brycefranzen
Copy link
Author

brycefranzen commented Jul 15, 2022

Well the main reason is that we've completely rewritten error handling to simplify it a lot on the version-4 branch, so I'd like to get input from @IvanGoncharov who did that work. We also have been cautious about the use of TypeScript enums; we only have one in AS3 (CacheScope) and we've changed it to export type CacheScope = 'PUBLIC' | 'PRIVATE' in AS4, because we've found that keeping our interfaces as "type-only" as possible seems superior. So the static approach would only add runtime code to classes which already require runtime code.

Is the idea that you actually want to use ErrorCode at runtime? So you would have some sort of "is this an ErrorCode" function too?

Correct. We want to be able to do something like this on the apollo-client at runtime:

import { ErrorCode } from 'apollo-server-errors';

const isUnAuthenticatedError = err.extensions?.code === ErrorCode.UNAUTHENTICATED;

However, currently on the UI we have to do this, or make our own types locally:

const isUnAuthenticatedError = err.extensions?.code === 'UNAUTHENTICATED';

@glasser
Copy link
Member

glasser commented Jul 20, 2022

@brycefranzen It looks like #6705 ends up resolving this problem by adding

export enum ApolloServerErrorCode {
  GRAPHQL_PARSE_FAILED = 'GRAPHQL_PARSE_FAILED',
  GRAPHQL_VALIDATION_FAILED = 'GRAPHQL_VALIDATION_FAILED',
  PERSISTED_QUERY_NOT_FOUND = 'PERSISTED_QUERY_NOT_FOUND',
  PERSISTED_QUERY_NOT_SUPPORTED = 'PERSISTED_QUERY_NOT_SUPPORTED',
  BAD_USER_INPUT = 'BAD_USER_INPUT',
  OPERATION_RESOLUTION_FAILURE = 'OPERATION_RESOLUTION_FAILURE',
  BAD_REQUEST = 'BAD_REQUEST',
}

Note that we actually stop exporting the error classes in this change, just the enums.

It seems like you probably want to use this enum in a client, not in the server, so it might be awkward that this is now part of @apollo/server rather than a standalone class. We can consider making a tiny package just for this, but also I think I will adapt @IvanGoncharov 's PR to put this enum in its own @apollo/server/errors export, so that while you will need to take the full set of dependencies of @apollo/server locally when you build your client, your bundler should be smart enough to skip everything else when bundling.

@glasser
Copy link
Member

glasser commented Jul 20, 2022

(Note that this doesn't include ErrorName, just error code, but I think the whole point of error code is it's the thing you should be matching against, so that seems reasonable?)

@brycefranzen
Copy link
Author

@brycefranzen It looks like #6705 ends up resolving this problem by adding

export enum ApolloServerErrorCode {
  GRAPHQL_PARSE_FAILED = 'GRAPHQL_PARSE_FAILED',
  GRAPHQL_VALIDATION_FAILED = 'GRAPHQL_VALIDATION_FAILED',
  PERSISTED_QUERY_NOT_FOUND = 'PERSISTED_QUERY_NOT_FOUND',
  PERSISTED_QUERY_NOT_SUPPORTED = 'PERSISTED_QUERY_NOT_SUPPORTED',
  BAD_USER_INPUT = 'BAD_USER_INPUT',
  OPERATION_RESOLUTION_FAILURE = 'OPERATION_RESOLUTION_FAILURE',
  BAD_REQUEST = 'BAD_REQUEST',
}

Note that we actually stop exporting the error classes in this change, just the enums.

It seems like you probably want to use this enum in a client, not in the server, so it might be awkward that this is now part of @apollo/server rather than a standalone class. We can consider making a tiny package just for this, but also I think I will adapt @IvanGoncharov 's PR to put this enum in its own @apollo/server/errors export, so that while you will need to take the full set of dependencies of @apollo/server locally when you build your client, your bundler should be smart enough to skip everything else when bundling.

In theory, yeah, this would solve the problem. However, it doesn't contain all the available codes (at least not in the currently version).

Missing types:
FORBIDDEN, UNAUTHENTICATED, INTERNAL_SERVER_ERROR

@glasser
Copy link
Member

glasser commented Jul 20, 2022

We are removing FORBIDDEN and UNAUTHENTICATED since they have never been produced or treated specially by Apollo Server itself. (They are used by apollo-datasource-rest, but that's not really part of Apollo Server and will be moved to its own repository and release cycle in AS4.) If you want to use those codes in your app, great, but you can define it yourself just like any other error code you find valuable. Good point re INTERNAL_SERVER_ERROR; fixed!

@glasser
Copy link
Member

glasser commented Oct 19, 2022

AS4 does have an error code enum, inspired by this PR.

As suggested above, the point of error codes is that it's the only thing you should rely on, so an enum for error name doesn't really make sense.

Thanks for inspiring this improvement!

@glasser glasser closed this Oct 19, 2022
@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.

4 participants