File tree Expand file tree Collapse file tree 8 files changed +161
-38
lines changed Expand file tree Collapse file tree 8 files changed +161
-38
lines changed Original file line number Diff line number Diff line change @@ -21,9 +21,10 @@ export default [
2121💼 Configurations enabled in.\
2222✅ Set in the ` recommended ` configuration.
2323
24- | Name | Description | 💼 |
25- | :------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | :- |
26- | [ use-query-no-inline-query] ( docs/rules/use-query-no-inline-query.md ) | Enforces useQuery (and family) hooks use some form of query constructor pattern. Will error if queryKey or queryFn properties are passed to the hook | ✅ |
24+ | Name | Description | 💼 |
25+ | :------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | :- |
26+ | [ invalidate-queries-no-inline-query] ( docs/rules/invalidate-queries-no-inline-query.md ) | Enforces queryClient.invalidateQueries don't have inline queries. Will error if queryKey or queryFn properties are passed to the function | ✅ |
27+ | [ use-query-no-inline-query] ( docs/rules/use-query-no-inline-query.md ) | Enforces useQuery (and family) hooks use some form of query constructor pattern. Will error if queryKey or queryFn properties are passed to the hook | ✅ |
2728
2829<!-- end auto-generated rules list -->
2930<!-- prettier-ignore-end -->
Original file line number Diff line number Diff line change 1+ # Enforces queryClient.invalidateQueries don't have inline queries. Will error if queryKey or queryFn properties are passed to the function (` react-query-options/invalidate-queries-no-inline-query ` )
2+
3+ 💼 This rule is enabled in the ✅ ` recommended ` config.
4+
5+ <!-- end auto-generated rule header -->
6+
7+ ## Fail
8+
9+ ``` js
10+ queryClient .invalidateQueries ({
11+ queryKey: [/* */ ],
12+ /* additional properties */
13+ })
14+
15+ queryClient .invalidateQueries ({
16+ queryFn : () => { /* */ }
17+ /* additional properties */
18+ })
19+ ```
20+
21+ ## Pass
22+
23+ ``` js
24+ const query = {
25+ queryKey: [/* */ ],
26+ queryFn : () => { /* */ }
27+ }
28+
29+ const queryBuilder = () => ({
30+ queryKey: [/* */ ],
31+ queryFn : () => { /* */ }
32+ })
33+
34+ queryClient .invalidateQueries (query)
35+ queryClient .invalidateQueries (queryBuilder ())
36+ queryClient .invalidateQueries ({
37+ ... queryBuilder (),
38+ /* additional properties */
39+ select : (data ) => data
40+ })
41+ ```
Original file line number Diff line number Diff line change 44
55<!-- end auto-generated rule header -->
66
7- Enforces useQuery (and family) hooks use some form of query constructor pattern. Will error if queryKey or queryFn properties are passed to the hook
8-
97## Fail
108
119``` js
Original file line number Diff line number Diff line change 11import useQueryNoInlineQuery from "./rules/use-query-no-inline-query.js" ;
2+ import invalidateQueriesNoInlineQuery from "./rules/invalidate-queries-no-inline-query.js" ;
23
34import pkg from "../package.json" with { type : "json" } ;
45
6+ const rules = [ useQueryNoInlineQuery , invalidateQueriesNoInlineQuery ] ;
7+
58const reactQueryOptions = {
69 meta : {
710 name : pkg . name ,
@@ -11,9 +14,7 @@ const reactQueryOptions = {
1114 get configs ( ) {
1215 return configs ;
1316 } ,
14- rules : {
15- [ useQueryNoInlineQuery . name ] : useQueryNoInlineQuery . rule ,
16- } ,
17+ rules : Object . fromEntries ( rules . map ( ( rule ) => [ rule . name , rule . rule ] ) ) ,
1718} ;
1819
1920const configs = {
@@ -22,10 +23,12 @@ const configs = {
2223 plugins : {
2324 [ reactQueryOptions . meta . namespace ] : reactQueryOptions ,
2425 } ,
25- rules : {
26- [ `${ reactQueryOptions . meta . namespace } /${ useQueryNoInlineQuery . name } ` ] :
26+ rules : Object . fromEntries (
27+ rules . map ( ( rule ) => [
28+ [ `${ reactQueryOptions . meta . namespace } /${ rule . name } ` ] ,
2729 "error" ,
28- } ,
30+ ] ) ,
31+ ) ,
2932 } ,
3033 ] ,
3134} ;
Original file line number Diff line number Diff line change 1+ import "../_test/setup.js" ;
2+
3+ import { RuleTester } from "@typescript-eslint/rule-tester" ;
4+
5+ import requireQueryOptions from "./invalidate-queries-no-inline-query.js" ;
6+
7+ const ruleTester = new RuleTester ( { } ) ;
8+
9+ ruleTester . run ( requireQueryOptions . name , requireQueryOptions . rule , {
10+ valid : [
11+ { code : `queryClient.invalidateQueries(usersQuery)` } ,
12+ { code : `queryClient.invalidateQueries({ ...usersQuery })` } ,
13+ { code : `queryClient.invalidateQueries({ ...usersQuery() })` } ,
14+ ] ,
15+ invalid : [
16+ {
17+ code : `queryClient.invalidateQueries({ queryKey: [] })` ,
18+ errors : [ { messageId : "no-inline-query" } ] ,
19+ } ,
20+ {
21+ code : `queryClient.invalidateQueries({ ...queryOptions, queryKey: [] })` ,
22+ errors : [ { messageId : "no-inline-query" } ] ,
23+ } ,
24+ {
25+ code : `queryClient.invalidateQueries({ queryFn: () => {} })` ,
26+ errors : [ { messageId : "no-inline-query" } ] ,
27+ } ,
28+ {
29+ code : `queryClient.invalidateQueries({ ...queryOptions, queryFn: () => {} })` ,
30+ errors : [ { messageId : "no-inline-query" } ] ,
31+ } ,
32+ ] ,
33+ } ) ;
Original file line number Diff line number Diff line change 1+ import { AST_NODE_TYPES } from "@typescript-eslint/utils" ;
2+ import { createRule , isValidQueryNode } from "../utils.js" ;
3+
4+ const name = "invalidate-queries-no-inline-query" ;
5+
6+ export default {
7+ name,
8+ rule : createRule ( {
9+ name,
10+ defaultOptions : [ ] ,
11+ meta : {
12+ type : "suggestion" ,
13+ messages : {
14+ "no-inline-query" : "Expected query hook to use queryOptions pattern" ,
15+ } ,
16+ docs : {
17+ description :
18+ "Enforces queryClient.invalidateQueries don't have inline queries. Will error if queryKey or queryFn properties are passed to the function" ,
19+ } ,
20+ schema : [ ] ,
21+ } ,
22+ create ( context ) {
23+ return {
24+ CallExpression ( node ) {
25+ if (
26+ // check queryClient.invalidateQueries
27+ node . callee . type === AST_NODE_TYPES . MemberExpression &&
28+ node . callee . object . type === AST_NODE_TYPES . Identifier &&
29+ node . callee . object . name === "queryClient" &&
30+ node . callee . property . type === AST_NODE_TYPES . Identifier &&
31+ node . callee . property . name === "invalidateQueries"
32+ ) {
33+ if ( ! node . arguments [ 0 ] ) return ;
34+
35+ if ( ! isValidQueryNode ( node . arguments [ 0 ] ) )
36+ context . report ( {
37+ messageId : "no-inline-query" ,
38+ node,
39+ } ) ;
40+ }
41+ } ,
42+ } ;
43+ } ,
44+ } ) ,
45+ } ;
Original file line number Diff line number Diff line change 1- import {
2- AST_NODE_TYPES ,
3- ESLintUtils ,
4- TSESTree ,
5- } from "@typescript-eslint/utils" ;
6-
7- const createRule = ESLintUtils . RuleCreator (
8- ( name ) =>
9- `https://github.com/danielpza/eslint-plugin-react-query/docs/rules/${ name } .md` ,
10- ) ;
1+ import { AST_NODE_TYPES } from "@typescript-eslint/utils" ;
2+ import { createRule , isValidQueryNode } from "../utils.js" ;
113
124const useQueryHooks = [
135 // see https://tanstack.com/query/latest/docs/framework/react/reference/useQuery
@@ -19,23 +11,6 @@ const useQueryHooks = [
1911 "useSuspenseInfiniteQuery" ,
2012] ;
2113
22- const invalidProperties = [ "queryKey" , "queryFn" ] ;
23-
24- function isValidQueryNode ( queryNode : TSESTree . Node ) {
25- // we only care about object expressions
26- if ( queryNode . type !== AST_NODE_TYPES . ObjectExpression ) return true ;
27-
28- // check if any of the properties is queryKey or queryFn
29- const hasInvalidProperties = queryNode . properties . find (
30- ( property ) =>
31- property . type === AST_NODE_TYPES . Property &&
32- property . key . type === AST_NODE_TYPES . Identifier &&
33- invalidProperties . includes ( property . key . name ) ,
34- ) ;
35-
36- return ! hasInvalidProperties ;
37- }
38-
3914const name = "use-query-no-inline-query" ;
4015
4116export default {
Original file line number Diff line number Diff line change 1+ import {
2+ AST_NODE_TYPES ,
3+ ESLintUtils ,
4+ TSESTree ,
5+ } from "@typescript-eslint/utils" ;
6+
7+ export const INVALID_QUERY_PROPERTIES = [ "queryKey" , "queryFn" ] ;
8+
9+ export const createRule = ESLintUtils . RuleCreator (
10+ ( name ) =>
11+ `https://github.com/danielpza/eslint-plugin-react-query/docs/rules/${ name } .md` ,
12+ ) ;
13+
14+ export function isValidQueryNode ( queryNode : TSESTree . Node ) {
15+ // we only care about object expressions
16+ if ( queryNode . type !== AST_NODE_TYPES . ObjectExpression ) return true ;
17+
18+ // check if any of the properties is queryKey or queryFn
19+ const hasInvalidProperties = queryNode . properties . find (
20+ ( property ) =>
21+ property . type === AST_NODE_TYPES . Property &&
22+ property . key . type === AST_NODE_TYPES . Identifier &&
23+ INVALID_QUERY_PROPERTIES . includes ( property . key . name ) ,
24+ ) ;
25+
26+ return ! hasInvalidProperties ;
27+ }
You can’t perform that action at this time.
0 commit comments