relayjs / eslint-plugin-relay Goto Github PK
View Code? Open in Web Editor NEWA plugin for the code linter ESLint to lint specific details about Relay.
License: MIT License
A plugin for the code linter ESLint to lint specific details about Relay.
License: MIT License
Hi, we have a monorepo setup with yarn workspaces, where we have 2 apps, and a workspace of shared fragments between these apps.
Importing import { MyComponent } from '@org/fragments
triggers error from this rule, even if its fragment is correctly used in the importing component.
I tried having a look at the code and see if I could come up with a fix, but it seems like this rule is based on matching the ImportDeclaration value against the name of the fragment.
I am not sure how eslint can extract this from the workspace name.
If a component queries for some fields, we should try to detect if some of those fields are not used in the component and might indicate overfetching.
Thanks so much for creating this awesome project and improving workflows when working with Relay.
To make the configuration a bit easier, we've created graphql-config. It would be great if this tool would support this standard as well!
Apparently code like below triggers the rules because the type alias isn't followed:
import type {
HiringProfileRecruitingEmail_email as Email
} from 'HiringProfileRecruitingEmail_email.graphql';
Nothing explaining in the Readme.md about how to get this to work or any examples.
Hi ๐
We are having a little issue with upgrading to the latest version.
Running lint locally fails with
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Node'
| property 'expressions' -> object with constructor 'Array'
| index 0 -> object with constructor 'Node'
--- property 'parent' closes the circle
at stringify (<anonymous>)
But on the CI it gives a different error. You can see the CI run here.
The error on the CI says The "path" argument must be of type string. Received undefined
.
This is the line that causes the error. Changing it from import(..)
to require(..)
solves it locally, but I expect it should work for import as well
We encounter the following pattern:
UserList
, that defines a callback onSelectUser
, which accepts an @inline
fragment named UserList_onSelectUser_user
.UserDetail
component as props.onSelectUser
, to which a user
is passed where ...UserList_onSelectUser_user
is spread.UserList
from the child component, which is just silly!)We anticipate that this pattern will occur somewhat frequently for us.
ignore: RegExp
parameter to the rule be an accepted addition? Namely, we would like to opt out of this lint rule by having certain inline fragments contain _inline_
in their name. (We would pair this with an additional rule, probably Pinterest-only, that enforced that only @inline
fragments can contain _inline_
in their name.)We should setup travis especially to ensure node 4.x compatibility.
Thanks for creating this ๐๐ป
I am trying to add the rules to my CRA v4 project. And while the rules do work I get no line numbers for unused-fields.
Not sure if this is a problem on my end or a limitation of the rule?
Do you get line numbers along with the warnings from unused-fields?
Hello, i'm trying to add a linter for deprecrated fields on my project,
our schema is quite large, and i struggle to find a linter that could do it well...
i was wondering if you would consider adding one in the project?
i might try my hand at it
In the case somebody is using Intersection types (https://flow.org/en/docs/types/intersections/#toc-impossible-intersection-types)
We should follow the intersected type, and if it's and object, check its props. If not an object, and is instead an imported type, we can:
Currently, you can switch between imports being auto fixed either:
haste: true
=> "<type>.graphql"
haste: false
=> "./__generated__/<type>.graphql"
.
But with artifactDirectory
set it would probably need to be:
baseUrl
setting in tsconfig (which is not always possible, because either not set, or not a ts repository at all)With the following code I'm getting issues on fragment spreads. I've tried shifting things about a bit but can't work out what the issue is. The code executes fine at runtime.
export const MessageSenderAvatar: FC<MessageSenderAvatarProps> = ({
messageSenderAvatarRef = null,
}) => {
const fragmentRef = useFragment(
graphql`
fragment MessageSenderAvatarFragment on Message {
sender {
__typename
... on User {
...UserAvatarFragment <--- ISSUE
}
... on Bot {
...BotAvatarFragment <--- ISSUE
}
}
}
`,
messageSenderAvatarRef
);
if (fragmentRef == null) {
return null;
}
if (fragmentRef.sender.__typename === 'User') {
return <UserAvatar userAvatarRef={fragmentRef.sender} />;
}
if (fragmentRef.sender.__typename === 'Bot') {
return <BotAvatar botAvatarRef={fragmentRef.sender} />;
}
return <AnonymousUserAvatar />;
};
and UserAvatar such as
export const UserAvatar: FC<UserAvatarProps> = ({ userAvatarRef, size = AvatarSize.Size40 }) => {
const { avatarUrlTemplate, displayName } = useFragment(
graphql`
fragment UserAvatarFragment on User {
avatarUrlTemplate
displayName
}
`,
userAvatarRef
);
return (
<AvatarView
name={displayName}
imageUrl={getScaledUrlTemplate(avatarUrlTemplate, size)}
size={size}
/>
);
};
I apologize for the indecision on whether this issue is a bug report or a support question. At the heart of it, my ESLint config consists of extends from several different plugins (e.g., eslint-plugin-react
), none of which need an explicit reference in the plugins
section. Based on that, I'd expect that if I use extends: ['plugin:relay/recommended']
that that would imply plugins: ['relay']
, but it currently does not.
Before opening this issue, I tried to see if ESLint was specially handling these other plugins or if the plugins were violating some spec, but still working incidentally. Unfortunately, I couldn't find anything conclusive. The ESLint docs give examples where the plugins
section is populated, but don't really say if that's a requirement. Interestingly, the eslint-plugin-react
example config is different than the one in eslint-plugin-react's docs and says you don't need to populate plugins
if using an extends
ruleset.
If this functionality can't be added, then I think the docs could be enhanced. While I realize adding 'relay'
to the plugins section is step 1 of "How to Use", it's paired with a step 2 that discusses activating individual rules. I misread the part about using "plugin:relay/recommended"
as an alternative to both steps that preceded it, rather than just the most recent step. I was likely primed to misread that based on my experience with other ESLint plugins.
There have been no releases despite there having been active contributions.
We at @contra heavily rely on Relay and would want to have a functioning ESLint plugin.
Do you need help maintaining this package?
If you are not planning on maintaining this package, would you be open to handing over the namespace?
We are leaning towards publishing eslint-plugin-relay fork, but I wanted to discuss with the existing maintainers before taking any initiative here.
Passing fields into components by spreading shows them as unused by the relay/unused-fields
, while passing them one by one does not cause any issues.
type Props = {
data: ParentComponent_data;
};
const ParentComponent: FC<Props> = ({ data }) => {
const { title, ...rest } = data;
return <SharedComponent title={title} {...rest} />;
}
export default createFragmentContainer(ParentComponent, {
data: graphql`
fragment ParentComponent_data on Data {
name # <- Triggers a warning about not being used!
title
}
`,
});
v0.0.28 release has involved to update graphql
dep from v0.13.0 to v14.0.0. The problem with the latter version it doesn't support node 9.x:
error [email protected]: The engine "node" is incompatible with this module. Expected version "6.x || 8.x || >= 10.x".
So, I think this evolution would have deserved at least a minor version.
There is still some enforcement. For example, the module name still has to be included. But the property name is no longer required in the fragment name which makes this line a bit obsolete:
Thanks for having a look! ๐
Fields with __clientField directive should not be marked as unused.
Imagine I'm using draftText field only, but eslint-plugin-relay warn about text is not used. It isn't, because I am using only draftText.
text @__clientField(handle: "draftText")
For example, before Relay 13, it was required to annotate useLazyLoadQuery
like so:
const data = useLazyLoadQuery<NavigationHeaderBadgeQuery>(graphql` โฆ `);
However, this is no longer required when used together with relay_integration=true
Flow option, see: facebook/relay@3c45f95
This issue proposes to remove or change relay/generated-flow-types
rule to support this new way of using Relay 13.
I'm not entirely sure because the naming linting does apply to query names, but not fragment names (on relay v14.0.0)
In the code for the graphql-naming rule I see this:
const CREATE_CONTAINER_FUNCTIONS = new Set([
'createFragmentContainer',
'createPaginationContainer',
'createRefetchContainer'
]);
It seems like it's just checking these container functions which aren't in the latest relay which uses hooks like useFragment
.
Hey, I faced an issue recently with readInlineData
function call. I forgot to pass fragment reference (second argument) to readInlineData and had some challenges to figure out why my feature wasn't working properly.
Flow also haven't covered this case, so I thought that it would be nice to have a rule check similar to rule-hook-required-argument
.
For context here is a link for the doc https://relay.dev/docs/en/graphql-in-relay#inline
Hello, my colleague discovered that incorrect Relay imports are not reported as expected. Failing test (well, should be failing but it's not):
{
code: `
import type {invalid as MyComponent_user} from './__generated__/MyComponent_user.graphql'
class MyComponent extends React.Component<{user: MyComponent_user}> {
render() {
return <div />;
}
}
createFragmentContainer(MyComponent, {
user: graphql\`fragment MyComponent_user on User {id}\`,
});
`,
errors: [
{
message: 'TODO: invalid type imported'
}
]
},
Notice that the imported type invalid as MyComponent_user
doesn't exist. In fact, this rule doesn't require the import at all and it is happy even if you delete the import type
line completely. Seems like it takes into account only the property name used in props definition but not the imports. I believe this is not intended and it's a bug because seems like there are tests to cover this but they don't work as I would expect - the import is irrelevant for them:
eslint-plugin-relay/test/test.js
Lines 232 to 233 in 267d5e6
cc @kassens, thanks for checking it and confirming/rejecting it
Scenario:
@relay(mask: false)
Eslint flags the relay/generated-flow-types
error.
I'm working on an overdue migration from TSLint to ESLint due to the former's deprecation in favor of the latter. I had been using a plugin called tslint-plugin-relay, which ported rules from this project over to TypeScript. Is there any interest in supporting TypeScript rules to parallel the Flow rules? If so, I'd be happy to work on upstreaming work from tslint-plugin-relay. If not, I can work on separate plugin instead.
We currently have the ability to auto-fix code with this plugin, but the test cases for this have been switched off with this flag:
https://github.com/relayjs/eslint-plugin-relay/blob/master/test/test.js#L18
We should get rid of the flag at some point. I'm just making this issue to track this for now :)
I've got the error below when I forgot to have on User
on my fragment for instance:
user: graphql`
fragment MyComponent_user {
}
TypeError: Cannot read property 'kind' of null
at walkAST (/Users/sibelius/Dev/app-test/node_modules/eslint-plugin-relay/src/rule-unused-fields.js:21:14)
at getGraphQLFieldNames (/Users/sibelius/Dev/app-test/node_modules/eslint-plugin-relay/src/rule-unused-fields.js:51:3)
at Program:exit.templateLiterals.forEach.templateLiteral (/Users/sibelius/Dev/app-test/node_modules/eslint-plugin-relay/src/rule-unused-fields.js:132:31)
at Array.forEach (<anonymous>)
at Program:exit (/Users/sibelius/Dev/app-test/node_modules/eslint-plugin-relay/src/rule-unused-fields.js:129:24)
Should we handle this case?
Hi! I am not sure whether this is a bug report or rather a feature request. I noticed that it's possible to spread a fragment even though it's never actually being used. I believe this rule should also catch this case since it leads to overfetching.
...LabelsList_data
...LabelsListSelect_data
labels {
- ...Label_label # not needed but not reported
id
name
}
STDERR
../eslint-plugin-relay/eslint-plugin-relay.js:330
propTypeProperty.value.typeAnnotation.id.name === type
TypeError: Cannot read property 'name' of undefined
at validateObjectTypeAnnotation (../eslint-plugin-relay/eslint-plugin-relay.js:330:45)
at Program:exit.expectedTypes.forEach.type (../eslint-plugin-relay/eslint-plugin-relay.js:741:23)
at Array.forEach (native)
at EventEmitter.Program:exit (../eslint-plugin-relay/eslint-plugin-relay.js:687:25)
at emitOne (events.js:120:20)
at EventEmitter.emit (events.js:210:7)
at NodeEventGenerator.leaveNode (../eslint/lib/util/node-event-generator.js:49:22)
Concerning this bit of code here:
if (
propTypeProperty.value.type === 'NullableTypeAnnotation' &&
propTypeProperty.value.typeAnnotation.id.name === type
) {
return true;
}
Hello,
I have the following typescript code:
export const supportedCurrenciesEnum = ['usd', 'eur', 'czk'] as const;
export type supportedCurrencyType = (typeof supportedCurrenciesEnum)[number];
// then in the fragment query i'm using this code:
fragment {
salePercentage {
czk
usd
eur
}
}
// then deep in the react code i'm trying to access the salePercentage value like this:
const currencyCode: supportedCurrencyType = 'czk';
salePercentage[currencyCode]
But the rule still complaining on the fields in the fragment:
This queries for the field `czk` but this file does not seem to use it directly. If a different file needs this information that file should export a fragment and colocate the query for the data with the usage.
If only interested in the existence of a record, __typename can be used without this warning.eslint(relay/unused-fields)
But when i access the salePercentage like this:
const value = currencyCode === 'czk' ? salePercentage.czk : currencyCode === 'eur' ? salePercentage.eur : salePercentage.usd;
It works.
Do you have please any idea how to keep the easy access and don't use the second approach without the eslint warning?
Thank you
Can we add docs for these rules? Ideally ones that follow the template suggested by ESLint's internal rules? Could be split into per-rule PRs.
We have an internal version of docs for must-colocate-fragment which I'd dropped here. Someone could use that as a starting place for OSS docs: https://gist.github.com/captbaritone/42c183b03df984e0db4dcfd0fc24bfdf
I'm looking to use this plugin but it's unclear from the README what each rule does. Can you add an explanation of what each rule's purpose is and examples of what passing & failing code looks like? Thanks!
I've described it in some detail in the PR that fixes this issue here #104, but I'm opening an issue to track it. If that's not the right way to do this, then feel free to close this issue.
The problem code:
import MyComponent from './';
graphql`fragment foo on Page {
...MyComponent_foo
}`
Currently throws the error:
This spreads the fragment
MyComponent_foo
but this module does not use it directly. If a different module needs this information, that module should directly define a fragment querying for that data, colocated next to where the data is used.
Which is highly confusing, as it is imported.
I believe this is an edge-case surfaced by our pattern of importing relative components in the same directory, so I've tried to tweak the module parser to handle this by checking the name of the parent directory in my PR.
Another option would be to operate on the variable name but that seems far worse and too much like the strict horrors of Relay compat.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.