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

RFC: Mark certain queries as used even no attributes are accessed #269

Open
wolflu05 opened this issue Mar 19, 2024 · 5 comments
Open

RFC: Mark certain queries as used even no attributes are accessed #269

wolflu05 opened this issue Mar 19, 2024 · 5 comments

Comments

@wolflu05
Copy link

Summary

Checking for unused fields is a really powerful feature which definitely makes sense, but sometimes we don't want that, but instead want to pass the complete return type to an other function which e.g. stores this in local storage, but then we end up with an error that not all properties are accessed. E.g.:

const meQuery = graphql(`
  # we have an error here: Field(s) me.username are not used.
  query me {
    me {
      id
      username
      # ...
    }
  }
`);

const res = await client.query(meQuery, {});
localStorage.setItem("user", res.data!.me);

Proposed Solution

Add some type of @gql-tada-mark-used comment, which could be used like this:

const res = await client.query(meQuery, {});
localStorage.setItem("user", res.data!.me);  // @gql-tada-mark-used

This should then mark everything from the me query as used and there shouldn't be an error

Alternatively a simple @gql-tada-ignore-unused comment to the query definition may be sufficient too.

// @gql-tada-ignore-unused
const meQuery = graphql(`
  # we have an error here: Field(s) me.username are not used.
  query me {

Requirements

Have the ability to mark certain queries as fully used and ignore checking if all fields are actually accessed, because that will fail if the complete object is passed to any function.

@kitten kitten transferred this issue from 0no-co/gql.tada Mar 19, 2024
@kitten
Copy link
Member

kitten commented Mar 19, 2024

Transferred to GraphQLSP, since this is where this is implemented.
This definitely makes sense, especially once we start adding the CLI.

However, I think we may want to first consider expanding bail-out patterns, e.g. when a given field is passed into a function, we should, under some circumstances mark it as used automatically.

@wolflu05
Copy link
Author

Thanks for you quick answer and transferring it to this repo, I was not aware that there is a different repo for the LSP.

I'm not sure how much forward through the call tree one could track the usage of the attributes. But in some circumstances one need to save all the attributes, where I think it makes sense to intentionally say that from now on a query should be marked as "all fields used". If following through the call tree to identify used/unused attributes would work, this would conflict with always marking as used if passed to a function, that's why I suggested to intentionally mark it.

@gterras
Copy link

gterras commented Apr 30, 2024

I'm trying gql.tada for e2e testing a graphQL API along with supertest, Field(s) 'login.token' are not used. doesn't look like there is an easy way to tell the field is used here:

const query = graphql(`
	query login($email: String!, $password: String!) {
		login(email: $email, password: $password) { 
			token 
		}
	}
`)

const variables: VariablesOf<typeof query> = { email, password }

const { body } = await request(app.getHttpServer())
	.post(GQL_ENDPOINT)
	.send({
		query: print(query),
		variables,
	})
	.expect(200)

return body.data.login.token

@kitten
Copy link
Member

kitten commented May 1, 2024

@gterras For a field to be marked as used the result type has to flow through to a type in your code. The type checker here can't infer the type of body and it's untyped.

An easy way to fix that is to wrap this request(...).post call in your own helper.

You can adapt this example though from the docs to type your body type: https://gql-tada.0no.co/guides/typed-documents#typeddocumentnode-types

@gterras
Copy link

gterras commented May 1, 2024

An easy way to fix that is to wrap this request(...).post call in your own helper.

Indeed although I posted this e2e example as a somewhat legitimate use case for needing an escape hatch to that warning, in the sense that adding a wrapper to an 2e2 suite makes it instantly harder to understand, use and maintain.

Like this wrapper would also need a way to inject a token or return errors when needed, and would then need to be tested on its own. I like my tests (especially e2e) to be self-contained and to have zero abstraction (like in the posted example) so that a modified test cannot in any way impact another test.

Also this wrapper requires quite some typing work, and while I don't doubt this is very useful in front-end code, in a testing context it feels like it could be advantageously replaced with a type assertion (since the result will be used only once).

For the record I solved the warning issue by moving the query and its variables to a dedicated file, which makes me think people doing this in the first place would not ever see the warning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants