@tanstack/eslint-plugin-query 5.17.7 → 5.17.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/dist/cjs/configs.cjs +23 -0
  2. package/dist/cjs/configs.cjs.map +1 -0
  3. package/dist/cjs/configs.d.cts +6 -0
  4. package/dist/cjs/index.cjs +7 -0
  5. package/dist/cjs/index.cjs.map +1 -0
  6. package/dist/cjs/index.d.cts +2 -0
  7. package/dist/cjs/rules/exhaustive-deps.rule.cjs +114 -0
  8. package/dist/cjs/rules/exhaustive-deps.rule.cjs.map +1 -0
  9. package/dist/cjs/rules/exhaustive-deps.rule.d.cts +3 -0
  10. package/dist/cjs/rules/exhaustive-deps.utils.cjs +26 -0
  11. package/dist/cjs/rules/exhaustive-deps.utils.cjs.map +1 -0
  12. package/{build/legacy → dist/cjs}/rules/exhaustive-deps.utils.d.cts +2 -5
  13. package/dist/cjs/rules/no-rest-desctructuring/no-rest-destructuring.rule.cjs +60 -0
  14. package/dist/cjs/rules/no-rest-desctructuring/no-rest-destructuring.rule.cjs.map +1 -0
  15. package/dist/cjs/rules/no-rest-desctructuring/no-rest-destructuring.rule.d.cts +2 -0
  16. package/dist/cjs/rules/no-rest-desctructuring/no-rest-destructuring.test.d.cts +1 -0
  17. package/dist/cjs/rules/no-rest-desctructuring/no-rest-destructuring.utils.cjs +13 -0
  18. package/dist/cjs/rules/no-rest-desctructuring/no-rest-destructuring.utils.cjs.map +1 -0
  19. package/dist/cjs/rules/no-rest-desctructuring/no-rest-destructuring.utils.d.cts +4 -0
  20. package/dist/cjs/rules/stable-query-client/stable-query-client.rule.cjs +66 -0
  21. package/dist/cjs/rules/stable-query-client/stable-query-client.rule.cjs.map +1 -0
  22. package/dist/cjs/rules/stable-query-client/stable-query-client.rule.d.cts +3 -0
  23. package/dist/cjs/rules/stable-query-client/stable-query-client.test.d.cts +1 -0
  24. package/dist/cjs/rules.cjs +12 -0
  25. package/dist/cjs/rules.cjs.map +1 -0
  26. package/dist/cjs/rules.d.cts +5 -0
  27. package/{build/legacy → dist/cjs}/utils/ast-utils.cjs +31 -57
  28. package/dist/cjs/utils/ast-utils.cjs.map +1 -0
  29. package/{build/legacy → dist/cjs}/utils/ast-utils.d.cts +4 -6
  30. package/dist/cjs/utils/create-rule.cjs +13 -0
  31. package/dist/cjs/utils/create-rule.cjs.map +1 -0
  32. package/dist/cjs/utils/create-rule.d.cts +7 -0
  33. package/{build/legacy → dist/cjs}/utils/detect-react-query-imports.cjs +6 -32
  34. package/dist/cjs/utils/detect-react-query-imports.cjs.map +1 -0
  35. package/{build/legacy → dist/cjs}/utils/detect-react-query-imports.d.cts +5 -6
  36. package/dist/cjs/utils/test-utils.d.cts +1 -0
  37. package/dist/cjs/utils/unique-by.cjs +7 -0
  38. package/dist/cjs/utils/unique-by.cjs.map +1 -0
  39. package/dist/cjs/utils/unique-by.d.cts +1 -0
  40. package/dist/esm/configs.d.ts +6 -0
  41. package/{build/legacy → dist/esm}/configs.js +2 -3
  42. package/dist/esm/configs.js.map +1 -0
  43. package/dist/esm/index.d.ts +2 -0
  44. package/{build/legacy → dist/esm}/index.js +1 -2
  45. package/dist/esm/index.js.map +1 -0
  46. package/dist/esm/rules/exhaustive-deps.rule.d.ts +3 -0
  47. package/{build/legacy → dist/esm}/rules/exhaustive-deps.rule.js +5 -6
  48. package/dist/esm/rules/exhaustive-deps.rule.js.map +1 -0
  49. package/{build/legacy → dist/esm}/rules/exhaustive-deps.utils.d.ts +2 -5
  50. package/{build/legacy → dist/esm}/rules/exhaustive-deps.utils.js +2 -3
  51. package/dist/esm/rules/exhaustive-deps.utils.js.map +1 -0
  52. package/dist/esm/rules/no-rest-desctructuring/no-rest-destructuring.rule.d.ts +2 -0
  53. package/{build/legacy → dist/esm}/rules/no-rest-desctructuring/no-rest-destructuring.rule.js +4 -5
  54. package/dist/esm/rules/no-rest-desctructuring/no-rest-destructuring.rule.js.map +1 -0
  55. package/dist/esm/rules/no-rest-desctructuring/no-rest-destructuring.test.d.ts +1 -0
  56. package/dist/esm/rules/no-rest-desctructuring/no-rest-destructuring.utils.d.ts +4 -0
  57. package/{build/legacy → dist/esm}/rules/no-rest-desctructuring/no-rest-destructuring.utils.js +2 -3
  58. package/dist/esm/rules/no-rest-desctructuring/no-rest-destructuring.utils.js.map +1 -0
  59. package/dist/esm/rules/stable-query-client/stable-query-client.rule.d.ts +3 -0
  60. package/{build/legacy → dist/esm}/rules/stable-query-client/stable-query-client.rule.js +3 -4
  61. package/dist/esm/rules/stable-query-client/stable-query-client.rule.js.map +1 -0
  62. package/dist/esm/rules/stable-query-client/stable-query-client.test.d.ts +1 -0
  63. package/dist/esm/rules.d.ts +5 -0
  64. package/dist/esm/rules.js +12 -0
  65. package/dist/esm/rules.js.map +1 -0
  66. package/{build/legacy → dist/esm}/utils/ast-utils.d.ts +4 -6
  67. package/{build/legacy → dist/esm}/utils/ast-utils.js +2 -3
  68. package/dist/esm/utils/ast-utils.js.map +1 -0
  69. package/dist/esm/utils/create-rule.d.ts +7 -0
  70. package/{build/legacy → dist/esm}/utils/create-rule.js +2 -3
  71. package/dist/esm/utils/create-rule.js.map +1 -0
  72. package/{build/legacy → dist/esm}/utils/detect-react-query-imports.d.ts +5 -6
  73. package/{build/legacy → dist/esm}/utils/detect-react-query-imports.js +1 -2
  74. package/dist/esm/utils/detect-react-query-imports.js.map +1 -0
  75. package/dist/esm/utils/test-utils.d.ts +1 -0
  76. package/dist/esm/utils/unique-by.d.ts +1 -0
  77. package/{build/legacy → dist/esm}/utils/unique-by.js +1 -2
  78. package/dist/esm/utils/unique-by.js.map +1 -0
  79. package/package.json +11 -12
  80. package/build/legacy/__tests__/configs.test.cjs +0 -24
  81. package/build/legacy/__tests__/configs.test.cjs.map +0 -1
  82. package/build/legacy/__tests__/configs.test.d.cts +0 -2
  83. package/build/legacy/__tests__/configs.test.d.ts +0 -2
  84. package/build/legacy/__tests__/configs.test.js +0 -22
  85. package/build/legacy/__tests__/configs.test.js.map +0 -1
  86. package/build/legacy/__tests__/exhaustive-deps.test.cjs +0 -722
  87. package/build/legacy/__tests__/exhaustive-deps.test.cjs.map +0 -1
  88. package/build/legacy/__tests__/exhaustive-deps.test.d.cts +0 -2
  89. package/build/legacy/__tests__/exhaustive-deps.test.d.ts +0 -2
  90. package/build/legacy/__tests__/exhaustive-deps.test.js +0 -720
  91. package/build/legacy/__tests__/exhaustive-deps.test.js.map +0 -1
  92. package/build/legacy/configs.cjs +0 -49
  93. package/build/legacy/configs.cjs.map +0 -1
  94. package/build/legacy/configs.d.cts +0 -8
  95. package/build/legacy/configs.d.ts +0 -8
  96. package/build/legacy/configs.js.map +0 -1
  97. package/build/legacy/index.cjs +0 -34
  98. package/build/legacy/index.cjs.map +0 -1
  99. package/build/legacy/index.d.cts +0 -3
  100. package/build/legacy/index.d.ts +0 -3
  101. package/build/legacy/index.js.map +0 -1
  102. package/build/legacy/rules/exhaustive-deps.rule.cjs +0 -141
  103. package/build/legacy/rules/exhaustive-deps.rule.cjs.map +0 -1
  104. package/build/legacy/rules/exhaustive-deps.rule.d.cts +0 -6
  105. package/build/legacy/rules/exhaustive-deps.rule.d.ts +0 -6
  106. package/build/legacy/rules/exhaustive-deps.rule.js.map +0 -1
  107. package/build/legacy/rules/exhaustive-deps.utils.cjs +0 -52
  108. package/build/legacy/rules/exhaustive-deps.utils.cjs.map +0 -1
  109. package/build/legacy/rules/exhaustive-deps.utils.js.map +0 -1
  110. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.rule.cjs +0 -87
  111. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.rule.cjs.map +0 -1
  112. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.rule.d.cts +0 -6
  113. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.rule.d.ts +0 -6
  114. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.rule.js.map +0 -1
  115. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.test.cjs +0 -197
  116. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.test.cjs.map +0 -1
  117. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.test.d.cts +0 -2
  118. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.test.d.ts +0 -2
  119. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.test.js +0 -195
  120. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.test.js.map +0 -1
  121. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.utils.cjs +0 -39
  122. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.utils.cjs.map +0 -1
  123. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.utils.d.cts +0 -7
  124. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.utils.d.ts +0 -7
  125. package/build/legacy/rules/no-rest-desctructuring/no-rest-destructuring.utils.js.map +0 -1
  126. package/build/legacy/rules/stable-query-client/stable-query-client.rule.cjs +0 -93
  127. package/build/legacy/rules/stable-query-client/stable-query-client.rule.cjs.map +0 -1
  128. package/build/legacy/rules/stable-query-client/stable-query-client.rule.d.cts +0 -6
  129. package/build/legacy/rules/stable-query-client/stable-query-client.rule.d.ts +0 -6
  130. package/build/legacy/rules/stable-query-client/stable-query-client.rule.js.map +0 -1
  131. package/build/legacy/rules/stable-query-client/stable-query-client.test.cjs +0 -197
  132. package/build/legacy/rules/stable-query-client/stable-query-client.test.cjs.map +0 -1
  133. package/build/legacy/rules/stable-query-client/stable-query-client.test.d.cts +0 -2
  134. package/build/legacy/rules/stable-query-client/stable-query-client.test.d.ts +0 -2
  135. package/build/legacy/rules/stable-query-client/stable-query-client.test.js +0 -195
  136. package/build/legacy/rules/stable-query-client/stable-query-client.test.js.map +0 -1
  137. package/build/legacy/rules.cjs +0 -48
  138. package/build/legacy/rules.cjs.map +0 -1
  139. package/build/legacy/rules.d.cts +0 -9
  140. package/build/legacy/rules.d.ts +0 -9
  141. package/build/legacy/rules.js +0 -13
  142. package/build/legacy/rules.js.map +0 -1
  143. package/build/legacy/utils/ast-utils.cjs.map +0 -1
  144. package/build/legacy/utils/ast-utils.js.map +0 -1
  145. package/build/legacy/utils/create-rule.cjs +0 -39
  146. package/build/legacy/utils/create-rule.cjs.map +0 -1
  147. package/build/legacy/utils/create-rule.d.cts +0 -10
  148. package/build/legacy/utils/create-rule.d.ts +0 -10
  149. package/build/legacy/utils/create-rule.js.map +0 -1
  150. package/build/legacy/utils/detect-react-query-imports.cjs.map +0 -1
  151. package/build/legacy/utils/detect-react-query-imports.js.map +0 -1
  152. package/build/legacy/utils/object-utils.cjs +0 -33
  153. package/build/legacy/utils/object-utils.cjs.map +0 -1
  154. package/build/legacy/utils/object-utils.d.cts +0 -3
  155. package/build/legacy/utils/object-utils.d.ts +0 -3
  156. package/build/legacy/utils/object-utils.js +0 -8
  157. package/build/legacy/utils/object-utils.js.map +0 -1
  158. package/build/legacy/utils/test-utils.cjs +0 -36
  159. package/build/legacy/utils/test-utils.cjs.map +0 -1
  160. package/build/legacy/utils/test-utils.d.cts +0 -3
  161. package/build/legacy/utils/test-utils.d.ts +0 -3
  162. package/build/legacy/utils/test-utils.js +0 -11
  163. package/build/legacy/utils/test-utils.js.map +0 -1
  164. package/build/legacy/utils/unique-by.cjs +0 -33
  165. package/build/legacy/utils/unique-by.cjs.map +0 -1
  166. package/build/legacy/utils/unique-by.d.cts +0 -3
  167. package/build/legacy/utils/unique-by.d.ts +0 -3
  168. package/build/legacy/utils/unique-by.js.map +0 -1
  169. package/src/utils/object-utils.ts +0 -5
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const rules = require("./rules.cjs");
4
+ function generateRecommendedConfig(allRules) {
5
+ return Object.entries(allRules).reduce(
6
+ (memo, [name, rule]) => {
7
+ const { recommended } = rule.meta.docs || {};
8
+ return {
9
+ ...memo,
10
+ ...recommended ? { [`@tanstack/query/${name}`]: recommended } : {}
11
+ };
12
+ },
13
+ {}
14
+ );
15
+ }
16
+ const configs = {
17
+ recommended: {
18
+ plugins: ["@tanstack/eslint-plugin-query"],
19
+ rules: generateRecommendedConfig(rules.rules)
20
+ }
21
+ };
22
+ exports.configs = configs;
23
+ //# sourceMappingURL=configs.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configs.cjs","sources":["../../src/configs.ts"],"sourcesContent":["import { rules } from './rules'\nimport type { TSESLint } from '@typescript-eslint/utils'\n\nfunction generateRecommendedConfig(\n allRules: Record<string, TSESLint.RuleModule<any, any>>,\n) {\n return Object.entries(allRules).reduce(\n (memo, [name, rule]) => {\n const { recommended } = rule.meta.docs || {}\n\n return {\n ...memo,\n ...(recommended ? { [`@tanstack/query/${name}`]: recommended } : {}),\n }\n },\n {} as Record<string, 'strict' | 'error' | 'warn'>,\n )\n}\n\nexport const configs = {\n recommended: {\n plugins: ['@tanstack/eslint-plugin-query'],\n rules: generateRecommendedConfig(rules),\n },\n}\n"],"names":["rules"],"mappings":";;;AAGA,SAAS,0BACP,UACA;AACO,SAAA,OAAO,QAAQ,QAAQ,EAAE;AAAA,IAC9B,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM;AACtB,YAAM,EAAE,YAAY,IAAI,KAAK,KAAK,QAAQ,CAAA;AAEnC,aAAA;AAAA,QACL,GAAG;AAAA,QACH,GAAI,cAAc,EAAE,CAAC,mBAAmB,IAAI,EAAE,GAAG,YAAY,IAAI,CAAC;AAAA,MAAA;AAAA,IAEtE;AAAA,IACA,CAAC;AAAA,EAAA;AAEL;AAEO,MAAM,UAAU;AAAA,EACrB,aAAa;AAAA,IACX,SAAS,CAAC,+BAA+B;AAAA,IACzC,OAAO,0BAA0BA,WAAK;AAAA,EACxC;AACF;;"}
@@ -0,0 +1,6 @@
1
+ export declare const configs: {
2
+ recommended: {
3
+ plugins: string[];
4
+ rules: Record<string, "error" | "strict" | "warn">;
5
+ };
6
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const configs = require("./configs.cjs");
4
+ const rules = require("./rules.cjs");
5
+ exports.configs = configs.configs;
6
+ exports.rules = rules.rules;
7
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,2 @@
1
+ export { configs } from './configs';
2
+ export { rules } from './rules';
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("@typescript-eslint/utils");
4
+ const astUtils = require("../utils/ast-utils.cjs");
5
+ const createRule = require("../utils/create-rule.cjs");
6
+ const uniqueBy = require("../utils/unique-by.cjs");
7
+ const exhaustiveDeps_utils = require("./exhaustive-deps.utils.cjs");
8
+ const QUERY_KEY = "queryKey";
9
+ const QUERY_FN = "queryFn";
10
+ const name = "exhaustive-deps";
11
+ const rule = createRule.createRule({
12
+ name,
13
+ meta: {
14
+ type: "problem",
15
+ docs: {
16
+ description: "Exhaustive deps rule for useQuery",
17
+ recommended: "error"
18
+ },
19
+ messages: {
20
+ missingDeps: `The following dependencies are missing in your queryKey: {{deps}}`,
21
+ fixTo: "Fix to {{result}}"
22
+ },
23
+ hasSuggestions: true,
24
+ fixable: "code",
25
+ schema: []
26
+ },
27
+ defaultOptions: [],
28
+ create(context) {
29
+ return {
30
+ Property(node) {
31
+ if (node.parent === void 0 || !astUtils.ASTUtils.isObjectExpression(node.parent) || !astUtils.ASTUtils.isIdentifierWithName(node.key, QUERY_KEY)) {
32
+ return;
33
+ }
34
+ const scopeManager = context.getSourceCode().scopeManager;
35
+ const queryKey = astUtils.ASTUtils.findPropertyWithIdentifierKey(
36
+ node.parent.properties,
37
+ QUERY_KEY
38
+ );
39
+ const queryFn = astUtils.ASTUtils.findPropertyWithIdentifierKey(
40
+ node.parent.properties,
41
+ QUERY_FN
42
+ );
43
+ if (scopeManager === null || queryKey === void 0 || queryFn === void 0 || queryFn.value.type !== utils.AST_NODE_TYPES.ArrowFunctionExpression) {
44
+ return;
45
+ }
46
+ let queryKeyNode = queryKey.value;
47
+ if (queryKeyNode.type === utils.AST_NODE_TYPES.TSAsExpression && queryKeyNode.expression.type === utils.AST_NODE_TYPES.ArrayExpression) {
48
+ queryKeyNode = queryKeyNode.expression;
49
+ }
50
+ if (queryKeyNode.type === utils.AST_NODE_TYPES.Identifier) {
51
+ const expression = astUtils.ASTUtils.getReferencedExpressionByIdentifier({
52
+ context,
53
+ node: queryKeyNode
54
+ });
55
+ if ((expression == null ? void 0 : expression.type) === utils.AST_NODE_TYPES.ArrayExpression) {
56
+ queryKeyNode = expression;
57
+ }
58
+ }
59
+ const sourceCode = context.getSourceCode();
60
+ const queryKeyValue = queryKeyNode;
61
+ const externalRefs = astUtils.ASTUtils.getExternalRefs({
62
+ scopeManager,
63
+ sourceCode,
64
+ node: queryFn.value
65
+ });
66
+ const relevantRefs = externalRefs.filter(
67
+ (reference) => exhaustiveDeps_utils.ExhaustiveDepsUtils.isRelevantReference({
68
+ context,
69
+ reference,
70
+ scopeManager
71
+ })
72
+ );
73
+ const existingKeys = astUtils.ASTUtils.getNestedIdentifiers(queryKeyValue).map(
74
+ (identifier) => astUtils.ASTUtils.mapKeyNodeToText(identifier, sourceCode)
75
+ );
76
+ const missingRefs = relevantRefs.map((ref) => ({
77
+ ref,
78
+ text: astUtils.ASTUtils.mapKeyNodeToText(ref.identifier, sourceCode)
79
+ })).filter(({ ref, text }) => {
80
+ return !ref.isTypeReference && !astUtils.ASTUtils.isAncestorIsCallee(ref.identifier) && !existingKeys.some((existingKey) => existingKey === text) && !existingKeys.includes(text.split(".")[0] ?? "");
81
+ }).map(({ ref, text }) => ({
82
+ identifier: ref.identifier,
83
+ text
84
+ }));
85
+ const uniqueMissingRefs = uniqueBy.uniqueBy(missingRefs, (x) => x.text);
86
+ if (uniqueMissingRefs.length > 0) {
87
+ const missingAsText = uniqueMissingRefs.map((ref) => astUtils.ASTUtils.mapKeyNodeToText(ref.identifier, sourceCode)).join(", ");
88
+ const existingWithMissing = sourceCode.getText(queryKeyValue).replace(/\]$/, `, ${missingAsText}]`);
89
+ const suggestions = [];
90
+ if (queryKeyNode.type === utils.AST_NODE_TYPES.ArrayExpression) {
91
+ suggestions.push({
92
+ messageId: "fixTo",
93
+ data: { result: existingWithMissing },
94
+ fix(fixer) {
95
+ return fixer.replaceText(queryKeyValue, existingWithMissing);
96
+ }
97
+ });
98
+ }
99
+ context.report({
100
+ node,
101
+ messageId: "missingDeps",
102
+ data: {
103
+ deps: uniqueMissingRefs.map((ref) => ref.text).join(", ")
104
+ },
105
+ suggest: suggestions
106
+ });
107
+ }
108
+ }
109
+ };
110
+ }
111
+ });
112
+ exports.name = name;
113
+ exports.rule = rule;
114
+ //# sourceMappingURL=exhaustive-deps.rule.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exhaustive-deps.rule.cjs","sources":["../../../src/rules/exhaustive-deps.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../utils/ast-utils'\nimport { createRule } from '../utils/create-rule'\nimport { uniqueBy } from '../utils/unique-by'\nimport { ExhaustiveDepsUtils } from './exhaustive-deps.utils'\nimport type { TSESLint } from '@typescript-eslint/utils'\n\nconst QUERY_KEY = 'queryKey'\nconst QUERY_FN = 'queryFn'\n\nexport const name = 'exhaustive-deps'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description: 'Exhaustive deps rule for useQuery',\n recommended: 'error',\n },\n messages: {\n missingDeps: `The following dependencies are missing in your queryKey: {{deps}}`,\n fixTo: 'Fix to {{result}}',\n },\n hasSuggestions: true,\n fixable: 'code',\n schema: [],\n },\n defaultOptions: [],\n\n create(context) {\n return {\n Property(node) {\n if (\n node.parent === undefined ||\n !ASTUtils.isObjectExpression(node.parent) ||\n !ASTUtils.isIdentifierWithName(node.key, QUERY_KEY)\n ) {\n return\n }\n\n const scopeManager = context.getSourceCode().scopeManager\n const queryKey = ASTUtils.findPropertyWithIdentifierKey(\n node.parent.properties,\n QUERY_KEY,\n )\n const queryFn = ASTUtils.findPropertyWithIdentifierKey(\n node.parent.properties,\n QUERY_FN,\n )\n\n if (\n scopeManager === null ||\n queryKey === undefined ||\n queryFn === undefined ||\n queryFn.value.type !== AST_NODE_TYPES.ArrowFunctionExpression\n ) {\n return\n }\n\n let queryKeyNode = queryKey.value\n\n if (\n queryKeyNode.type === AST_NODE_TYPES.TSAsExpression &&\n queryKeyNode.expression.type === AST_NODE_TYPES.ArrayExpression\n ) {\n queryKeyNode = queryKeyNode.expression\n }\n\n if (queryKeyNode.type === AST_NODE_TYPES.Identifier) {\n const expression = ASTUtils.getReferencedExpressionByIdentifier({\n context,\n node: queryKeyNode,\n })\n\n if (expression?.type === AST_NODE_TYPES.ArrayExpression) {\n queryKeyNode = expression\n }\n }\n\n const sourceCode = context.getSourceCode()\n const queryKeyValue = queryKeyNode\n const externalRefs = ASTUtils.getExternalRefs({\n scopeManager,\n sourceCode,\n node: queryFn.value,\n })\n\n const relevantRefs = externalRefs.filter((reference) =>\n ExhaustiveDepsUtils.isRelevantReference({\n context,\n reference,\n scopeManager,\n }),\n )\n\n const existingKeys = ASTUtils.getNestedIdentifiers(queryKeyValue).map(\n (identifier) => ASTUtils.mapKeyNodeToText(identifier, sourceCode),\n )\n\n const missingRefs = relevantRefs\n .map((ref) => ({\n ref: ref,\n text: ASTUtils.mapKeyNodeToText(ref.identifier, sourceCode),\n }))\n .filter(({ ref, text }) => {\n return (\n !ref.isTypeReference &&\n !ASTUtils.isAncestorIsCallee(ref.identifier) &&\n !existingKeys.some((existingKey) => existingKey === text) &&\n !existingKeys.includes(text.split('.')[0] ?? '')\n )\n })\n .map(({ ref, text }) => ({\n identifier: ref.identifier,\n text: text,\n }))\n\n const uniqueMissingRefs = uniqueBy(missingRefs, (x) => x.text)\n\n if (uniqueMissingRefs.length > 0) {\n const missingAsText = uniqueMissingRefs\n .map((ref) => ASTUtils.mapKeyNodeToText(ref.identifier, sourceCode))\n .join(', ')\n\n const existingWithMissing = sourceCode\n .getText(queryKeyValue)\n .replace(/\\]$/, `, ${missingAsText}]`)\n\n const suggestions: TSESLint.ReportSuggestionArray<string> = []\n\n if (queryKeyNode.type === AST_NODE_TYPES.ArrayExpression) {\n suggestions.push({\n messageId: 'fixTo',\n data: { result: existingWithMissing },\n fix(fixer) {\n return fixer.replaceText(queryKeyValue, existingWithMissing)\n },\n })\n }\n\n context.report({\n node: node,\n messageId: 'missingDeps',\n data: {\n deps: uniqueMissingRefs.map((ref) => ref.text).join(', '),\n },\n suggest: suggestions,\n })\n }\n },\n }\n },\n})\n"],"names":["createRule","ASTUtils","AST_NODE_TYPES","ExhaustiveDepsUtils","uniqueBy"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ export declare const name = "exhaustive-deps";
3
+ export declare const rule: TSESLint.RuleModule<string, readonly unknown[], TSESLint.RuleListener>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("@typescript-eslint/utils");
4
+ const astUtils = require("../utils/ast-utils.cjs");
5
+ const ExhaustiveDepsUtils = {
6
+ isRelevantReference(params) {
7
+ var _a;
8
+ const { reference, scopeManager, context } = params;
9
+ const component = astUtils.ASTUtils.getFunctionAncestor(context);
10
+ if (component !== void 0 && !astUtils.ASTUtils.isDeclaredInNode({
11
+ scopeManager,
12
+ reference,
13
+ functionNode: component
14
+ })) {
15
+ return false;
16
+ }
17
+ return reference.identifier.name !== "undefined" && ((_a = reference.identifier.parent) == null ? void 0 : _a.type) !== utils.AST_NODE_TYPES.NewExpression && !ExhaustiveDepsUtils.isQueryClientReference(reference);
18
+ },
19
+ isQueryClientReference(reference) {
20
+ var _a, _b, _c;
21
+ const declarator = (_b = (_a = reference.resolved) == null ? void 0 : _a.defs[0]) == null ? void 0 : _b.node;
22
+ return (declarator == null ? void 0 : declarator.type) === utils.AST_NODE_TYPES.VariableDeclarator && ((_c = declarator.init) == null ? void 0 : _c.type) === utils.AST_NODE_TYPES.CallExpression && declarator.init.callee.type === utils.AST_NODE_TYPES.Identifier && declarator.init.callee.name === "useQueryClient";
23
+ }
24
+ };
25
+ exports.ExhaustiveDepsUtils = ExhaustiveDepsUtils;
26
+ //# sourceMappingURL=exhaustive-deps.utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exhaustive-deps.utils.cjs","sources":["../../../src/rules/exhaustive-deps.utils.ts"],"sourcesContent":["import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../utils/ast-utils'\nimport type { TSESLint } from '@typescript-eslint/utils'\n\nexport const ExhaustiveDepsUtils = {\n isRelevantReference(params: {\n context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>\n reference: TSESLint.Scope.Reference\n scopeManager: TSESLint.Scope.ScopeManager\n }) {\n const { reference, scopeManager, context } = params\n const component = ASTUtils.getFunctionAncestor(context)\n\n if (\n component !== undefined &&\n !ASTUtils.isDeclaredInNode({\n scopeManager,\n reference,\n functionNode: component,\n })\n ) {\n return false\n }\n\n return (\n reference.identifier.name !== 'undefined' &&\n reference.identifier.parent?.type !== AST_NODE_TYPES.NewExpression &&\n !ExhaustiveDepsUtils.isQueryClientReference(reference)\n )\n },\n isQueryClientReference(reference: TSESLint.Scope.Reference) {\n const declarator = reference.resolved?.defs[0]?.node\n\n return (\n declarator?.type === AST_NODE_TYPES.VariableDeclarator &&\n declarator.init?.type === AST_NODE_TYPES.CallExpression &&\n declarator.init.callee.type === AST_NODE_TYPES.Identifier &&\n declarator.init.callee.name === 'useQueryClient'\n )\n },\n}\n"],"names":["ASTUtils","AST_NODE_TYPES"],"mappings":";;;;AAIO,MAAM,sBAAsB;AAAA,EACjC,oBAAoB,QAIjB;;AACD,UAAM,EAAE,WAAW,cAAc,QAAA,IAAY;AACvC,UAAA,YAAYA,SAAAA,SAAS,oBAAoB,OAAO;AAEtD,QACE,cAAc,UACd,CAACA,SAAAA,SAAS,iBAAiB;AAAA,MACzB;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAAA,CACf,GACD;AACO,aAAA;AAAA,IACT;AAEA,WACE,UAAU,WAAW,SAAS,iBAC9B,eAAU,WAAW,WAArB,mBAA6B,UAASC,MAAAA,eAAe,iBACrD,CAAC,oBAAoB,uBAAuB,SAAS;AAAA,EAEzD;AAAA,EACA,uBAAuB,WAAqC;;AAC1D,UAAM,cAAa,qBAAU,aAAV,mBAAoB,KAAK,OAAzB,mBAA6B;AAEhD,YACE,yCAAY,UAASA,MAAAA,eAAe,wBACpC,gBAAW,SAAX,mBAAiB,UAASA,MAAe,eAAA,kBACzC,WAAW,KAAK,OAAO,SAASA,MAAAA,eAAe,cAC/C,WAAW,KAAK,OAAO,SAAS;AAAA,EAEpC;AACF;;"}
@@ -1,6 +1,5 @@
1
- import { TSESLint } from '@typescript-eslint/utils';
2
-
3
- declare const ExhaustiveDepsUtils: {
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ export declare const ExhaustiveDepsUtils: {
4
3
  isRelevantReference(params: {
5
4
  context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>;
6
5
  reference: TSESLint.Scope.Reference;
@@ -8,5 +7,3 @@ declare const ExhaustiveDepsUtils: {
8
7
  }): boolean;
9
8
  isQueryClientReference(reference: TSESLint.Scope.Reference): boolean;
10
9
  };
11
-
12
- export { ExhaustiveDepsUtils };
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("@typescript-eslint/utils");
4
+ const createRule = require("../../utils/create-rule.cjs");
5
+ const astUtils = require("../../utils/ast-utils.cjs");
6
+ const noRestDestructuring_utils = require("./no-rest-destructuring.utils.cjs");
7
+ const name = "no-rest-destructuring";
8
+ const queryHooks = ["useQuery", "useQueries", "useInfiniteQuery"];
9
+ const rule = createRule.createRule({
10
+ name,
11
+ meta: {
12
+ type: "problem",
13
+ docs: {
14
+ description: "Disallows rest destructuring in queries",
15
+ recommended: "warn"
16
+ },
17
+ messages: {
18
+ objectRestDestructure: `Object rest destructuring on a query will observe all changes to the query, leading to excessive re-renders.`
19
+ },
20
+ schema: []
21
+ },
22
+ defaultOptions: [],
23
+ create(context, _, helpers) {
24
+ return {
25
+ CallExpression(node) {
26
+ var _a;
27
+ if (!astUtils.ASTUtils.isIdentifierWithOneOfNames(node.callee, queryHooks) || !helpers.isTanstackQueryImport(node.callee) || ((_a = node.parent) == null ? void 0 : _a.type) !== utils.AST_NODE_TYPES.VariableDeclarator) {
28
+ return;
29
+ }
30
+ const returnValue = node.parent.id;
31
+ if (node.callee.name !== "useQueries") {
32
+ if (noRestDestructuring_utils.NoRestDestructuringUtils.isObjectRestDestructuring(returnValue)) {
33
+ context.report({
34
+ node: node.parent,
35
+ messageId: "objectRestDestructure"
36
+ });
37
+ }
38
+ return;
39
+ }
40
+ if (returnValue.type !== utils.AST_NODE_TYPES.ArrayPattern) {
41
+ return;
42
+ }
43
+ returnValue.elements.forEach((queryResult) => {
44
+ if (queryResult === null) {
45
+ return;
46
+ }
47
+ if (noRestDestructuring_utils.NoRestDestructuringUtils.isObjectRestDestructuring(queryResult)) {
48
+ context.report({
49
+ node: queryResult,
50
+ messageId: "objectRestDestructure"
51
+ });
52
+ }
53
+ });
54
+ }
55
+ };
56
+ }
57
+ });
58
+ exports.name = name;
59
+ exports.rule = rule;
60
+ //# sourceMappingURL=no-rest-destructuring.rule.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-rest-destructuring.rule.cjs","sources":["../../../../src/rules/no-rest-desctructuring/no-rest-destructuring.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport { createRule } from '../../utils/create-rule'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { NoRestDestructuringUtils } from './no-rest-destructuring.utils'\n\nexport const name = 'no-rest-destructuring'\n\nconst queryHooks = ['useQuery', 'useQueries', 'useInfiniteQuery']\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallows rest destructuring in queries',\n recommended: 'warn',\n },\n messages: {\n objectRestDestructure: `Object rest destructuring on a query will observe all changes to the query, leading to excessive re-renders.`,\n },\n schema: [],\n },\n defaultOptions: [],\n\n create(context, _, helpers) {\n return {\n CallExpression(node) {\n if (\n !ASTUtils.isIdentifierWithOneOfNames(node.callee, queryHooks) ||\n !helpers.isTanstackQueryImport(node.callee) ||\n node.parent?.type !== AST_NODE_TYPES.VariableDeclarator\n ) {\n return\n }\n\n const returnValue = node.parent.id\n if (node.callee.name !== 'useQueries') {\n if (NoRestDestructuringUtils.isObjectRestDestructuring(returnValue)) {\n context.report({\n node: node.parent,\n messageId: 'objectRestDestructure',\n })\n }\n return\n }\n\n if (returnValue.type !== AST_NODE_TYPES.ArrayPattern) {\n return\n }\n returnValue.elements.forEach((queryResult) => {\n if (queryResult === null) {\n return\n }\n if (NoRestDestructuringUtils.isObjectRestDestructuring(queryResult)) {\n context.report({\n node: queryResult,\n messageId: 'objectRestDestructure',\n })\n }\n })\n },\n }\n },\n})\n"],"names":["createRule","ASTUtils","AST_NODE_TYPES","NoRestDestructuringUtils"],"mappings":";;;;;;AAKO,MAAM,OAAO;AAEpB,MAAM,aAAa,CAAC,YAAY,cAAc,kBAAkB;AAEzD,MAAM,OAAOA,WAAAA,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,uBAAuB;AAAA,IACzB;AAAA,IACA,QAAQ,CAAC;AAAA,EACX;AAAA,EACA,gBAAgB,CAAC;AAAA,EAEjB,OAAO,SAAS,GAAG,SAAS;AACnB,WAAA;AAAA,MACL,eAAe,MAAM;;AACnB,YACE,CAACC,SAAS,SAAA,2BAA2B,KAAK,QAAQ,UAAU,KAC5D,CAAC,QAAQ,sBAAsB,KAAK,MAAM,OAC1C,UAAK,WAAL,mBAAa,UAASC,qBAAe,oBACrC;AACA;AAAA,QACF;AAEM,cAAA,cAAc,KAAK,OAAO;AAC5B,YAAA,KAAK,OAAO,SAAS,cAAc;AACjC,cAAAC,0BAAA,yBAAyB,0BAA0B,WAAW,GAAG;AACnE,oBAAQ,OAAO;AAAA,cACb,MAAM,KAAK;AAAA,cACX,WAAW;AAAA,YAAA,CACZ;AAAA,UACH;AACA;AAAA,QACF;AAEI,YAAA,YAAY,SAASD,MAAA,eAAe,cAAc;AACpD;AAAA,QACF;AACY,oBAAA,SAAS,QAAQ,CAAC,gBAAgB;AAC5C,cAAI,gBAAgB,MAAM;AACxB;AAAA,UACF;AACI,cAAAC,0BAAA,yBAAyB,0BAA0B,WAAW,GAAG;AACnE,oBAAQ,OAAO;AAAA,cACb,MAAM;AAAA,cACN,WAAW;AAAA,YAAA,CACZ;AAAA,UACH;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IAAA;AAAA,EAEJ;AACF,CAAC;;;"}
@@ -0,0 +1,2 @@
1
+ export declare const name = "no-rest-destructuring";
2
+ export declare const rule: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<string, readonly unknown[], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("@typescript-eslint/utils");
4
+ const NoRestDestructuringUtils = {
5
+ isObjectRestDestructuring(node) {
6
+ if (node.type !== utils.AST_NODE_TYPES.ObjectPattern) {
7
+ return false;
8
+ }
9
+ return node.properties.some((p) => p.type === utils.AST_NODE_TYPES.RestElement);
10
+ }
11
+ };
12
+ exports.NoRestDestructuringUtils = NoRestDestructuringUtils;
13
+ //# sourceMappingURL=no-rest-destructuring.utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-rest-destructuring.utils.cjs","sources":["../../../../src/rules/no-rest-desctructuring/no-rest-destructuring.utils.ts"],"sourcesContent":["import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nexport const NoRestDestructuringUtils = {\n isObjectRestDestructuring(node: TSESTree.Node): boolean {\n if (node.type !== AST_NODE_TYPES.ObjectPattern) {\n return false\n }\n return node.properties.some((p) => p.type === AST_NODE_TYPES.RestElement)\n },\n}\n"],"names":["AST_NODE_TYPES"],"mappings":";;;AAGO,MAAM,2BAA2B;AAAA,EACtC,0BAA0B,MAA8B;AAClD,QAAA,KAAK,SAASA,MAAA,eAAe,eAAe;AACvC,aAAA;AAAA,IACT;AACO,WAAA,KAAK,WAAW,KAAK,CAAC,MAAM,EAAE,SAASA,qBAAe,WAAW;AAAA,EAC1E;AACF;;"}
@@ -0,0 +1,4 @@
1
+ import type { TSESTree } from '@typescript-eslint/utils';
2
+ export declare const NoRestDestructuringUtils: {
3
+ isObjectRestDestructuring(node: TSESTree.Node): boolean;
4
+ };
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("@typescript-eslint/utils");
4
+ const astUtils = require("../../utils/ast-utils.cjs");
5
+ const createRule = require("../../utils/create-rule.cjs");
6
+ const name = "stable-query-client";
7
+ const rule = createRule.createRule({
8
+ name,
9
+ meta: {
10
+ type: "problem",
11
+ docs: {
12
+ description: "Makes sure that QueryClient is stable",
13
+ recommended: "error"
14
+ },
15
+ messages: {
16
+ unstable: [
17
+ "QueryClient is not stable. It should be either extracted from the component or wrapped in React.useState.",
18
+ "See https://tkdodo.eu/blog/react-query-fa-qs#2-the-queryclient-is-not-stable"
19
+ ].join("\n"),
20
+ fixTo: "Fix to {{result}}"
21
+ },
22
+ hasSuggestions: true,
23
+ fixable: "code",
24
+ schema: []
25
+ },
26
+ defaultOptions: [],
27
+ create(context, _, helpers) {
28
+ return {
29
+ NewExpression(node) {
30
+ var _a;
31
+ if (node.callee.type !== utils.AST_NODE_TYPES.Identifier || node.callee.name !== "QueryClient" || ((_a = node.parent) == null ? void 0 : _a.type) !== utils.AST_NODE_TYPES.VariableDeclarator || !helpers.isSpecificTanstackQueryImport(
32
+ node.callee,
33
+ "@tanstack/react-query"
34
+ )) {
35
+ return;
36
+ }
37
+ const fnAncestor = astUtils.ASTUtils.getFunctionAncestor(context);
38
+ const isReactServerComponent = (fnAncestor == null ? void 0 : fnAncestor.async) === true;
39
+ if (!astUtils.ASTUtils.isValidReactComponentOrHookName(fnAncestor == null ? void 0 : fnAncestor.id) || isReactServerComponent) {
40
+ return;
41
+ }
42
+ context.report({
43
+ node: node.parent,
44
+ messageId: "unstable",
45
+ fix: (() => {
46
+ const { parent } = node;
47
+ if (parent.id.type !== utils.AST_NODE_TYPES.Identifier) {
48
+ return;
49
+ }
50
+ const nodeText = context.getSourceCode().getText(node);
51
+ const variableName = parent.id.name;
52
+ return (fixer) => {
53
+ return fixer.replaceTextRange(
54
+ [parent.range[0], parent.range[1]],
55
+ `[${variableName}] = React.useState(() => ${nodeText})`
56
+ );
57
+ };
58
+ })()
59
+ });
60
+ }
61
+ };
62
+ }
63
+ });
64
+ exports.name = name;
65
+ exports.rule = rule;
66
+ //# sourceMappingURL=stable-query-client.rule.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stable-query-client.rule.cjs","sources":["../../../../src/rules/stable-query-client/stable-query-client.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { createRule } from '../../utils/create-rule'\nimport type { TSESLint } from '@typescript-eslint/utils'\n\nexport const name = 'stable-query-client'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description: 'Makes sure that QueryClient is stable',\n recommended: 'error',\n },\n messages: {\n unstable: [\n 'QueryClient is not stable. It should be either extracted from the component or wrapped in React.useState.',\n 'See https://tkdodo.eu/blog/react-query-fa-qs#2-the-queryclient-is-not-stable',\n ].join('\\n'),\n fixTo: 'Fix to {{result}}',\n },\n hasSuggestions: true,\n fixable: 'code',\n schema: [],\n },\n defaultOptions: [],\n\n create(context, _, helpers) {\n return {\n NewExpression(node) {\n if (\n node.callee.type !== AST_NODE_TYPES.Identifier ||\n node.callee.name !== 'QueryClient' ||\n node.parent?.type !== AST_NODE_TYPES.VariableDeclarator ||\n !helpers.isSpecificTanstackQueryImport(\n node.callee,\n '@tanstack/react-query',\n )\n ) {\n return\n }\n\n const fnAncestor = ASTUtils.getFunctionAncestor(context)\n const isReactServerComponent = fnAncestor?.async === true\n\n if (\n !ASTUtils.isValidReactComponentOrHookName(fnAncestor?.id) ||\n isReactServerComponent\n ) {\n return\n }\n\n context.report({\n node: node.parent,\n messageId: 'unstable',\n fix: (() => {\n const { parent } = node\n\n if (parent.id.type !== AST_NODE_TYPES.Identifier) {\n return\n }\n\n const nodeText = context.getSourceCode().getText(node)\n const variableName = parent.id.name\n\n return (fixer: TSESLint.RuleFixer) => {\n return fixer.replaceTextRange(\n [parent.range[0], parent.range[1]],\n `[${variableName}] = React.useState(() => ${nodeText})`,\n )\n }\n })(),\n })\n },\n }\n },\n})\n"],"names":["createRule","AST_NODE_TYPES","ASTUtils"],"mappings":";;;;;AAKO,MAAM,OAAO;AAEb,MAAM,OAAOA,WAAAA,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,UAAU;AAAA,QACR;AAAA,QACA;AAAA,MAAA,EACA,KAAK,IAAI;AAAA,MACX,OAAO;AAAA,IACT;AAAA,IACA,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,QAAQ,CAAC;AAAA,EACX;AAAA,EACA,gBAAgB,CAAC;AAAA,EAEjB,OAAO,SAAS,GAAG,SAAS;AACnB,WAAA;AAAA,MACL,cAAc,MAAM;;AAClB,YACE,KAAK,OAAO,SAASC,MAAA,eAAe,cACpC,KAAK,OAAO,SAAS,mBACrB,UAAK,WAAL,mBAAa,UAASA,MAAe,eAAA,sBACrC,CAAC,QAAQ;AAAA,UACP,KAAK;AAAA,UACL;AAAA,QAAA,GAEF;AACA;AAAA,QACF;AAEM,cAAA,aAAaC,SAAAA,SAAS,oBAAoB,OAAO;AACjD,cAAA,0BAAyB,yCAAY,WAAU;AAErD,YACE,CAACA,SAAS,SAAA,gCAAgC,yCAAY,EAAE,KACxD,wBACA;AACA;AAAA,QACF;AAEA,gBAAQ,OAAO;AAAA,UACb,MAAM,KAAK;AAAA,UACX,WAAW;AAAA,UACX,MAAM,MAAM;AACJ,kBAAA,EAAE,OAAW,IAAA;AAEnB,gBAAI,OAAO,GAAG,SAASD,MAAAA,eAAe,YAAY;AAChD;AAAA,YACF;AAEA,kBAAM,WAAW,QAAQ,cAAc,EAAE,QAAQ,IAAI;AAC/C,kBAAA,eAAe,OAAO,GAAG;AAE/B,mBAAO,CAAC,UAA8B;AACpC,qBAAO,MAAM;AAAA,gBACX,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC;AAAA,gBACjC,IAAI,YAAY,4BAA4B,QAAQ;AAAA,cAAA;AAAA,YACtD;AAAA,UACF,GACC;AAAA,QAAA,CACJ;AAAA,MACH;AAAA,IAAA;AAAA,EAEJ;AACF,CAAC;;;"}
@@ -0,0 +1,3 @@
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ export declare const name = "stable-query-client";
3
+ export declare const rule: TSESLint.RuleModule<string, readonly unknown[], TSESLint.RuleListener>;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const exhaustiveDeps_rule = require("./rules/exhaustive-deps.rule.cjs");
4
+ const stableQueryClient_rule = require("./rules/stable-query-client/stable-query-client.rule.cjs");
5
+ const noRestDestructuring_rule = require("./rules/no-rest-desctructuring/no-rest-destructuring.rule.cjs");
6
+ const rules = {
7
+ [exhaustiveDeps_rule.name]: exhaustiveDeps_rule.rule,
8
+ [stableQueryClient_rule.name]: stableQueryClient_rule.rule,
9
+ [noRestDestructuring_rule.name]: noRestDestructuring_rule.rule
10
+ };
11
+ exports.rules = rules;
12
+ //# sourceMappingURL=rules.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.cjs","sources":["../../src/rules.ts"],"sourcesContent":["import * as exhaustiveDeps from './rules/exhaustive-deps.rule'\nimport * as stableQueryClient from './rules/stable-query-client/stable-query-client.rule'\nimport * as noRestDestructuring from './rules/no-rest-desctructuring/no-rest-destructuring.rule'\n\nexport const rules = {\n [exhaustiveDeps.name]: exhaustiveDeps.rule,\n [stableQueryClient.name]: stableQueryClient.rule,\n [noRestDestructuring.name]: noRestDestructuring.rule,\n}\n"],"names":["exhaustiveDeps.name","exhaustiveDeps.rule","stableQueryClient.name","stableQueryClient.rule","noRestDestructuring.name","noRestDestructuring.rule"],"mappings":";;;;;AAIO,MAAM,QAAQ;AAAA,EACnB,CAACA,oBAAmB,IAAA,GAAGC,oBAAe;AAAA,EACtC,CAACC,uBAAsB,IAAA,GAAGC,uBAAkB;AAAA,EAC5C,CAACC,yBAAwB,IAAA,GAAGC,yBAAoB;AAClD;;"}
@@ -0,0 +1,5 @@
1
+ export declare const rules: {
2
+ "exhaustive-deps": import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<string, readonly unknown[], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
3
+ "stable-query-client": import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<string, readonly unknown[], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
4
+ "no-rest-destructuring": import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<string, readonly unknown[], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
5
+ };
@@ -1,36 +1,13 @@
1
1
  "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/utils/ast-utils.ts
21
- var ast_utils_exports = {};
22
- __export(ast_utils_exports, {
23
- ASTUtils: () => ASTUtils
24
- });
25
- module.exports = __toCommonJS(ast_utils_exports);
26
- var import_utils = require("@typescript-eslint/utils");
27
- var import_unique_by = require("./unique-by.cjs");
28
- var ASTUtils = {
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("@typescript-eslint/utils");
4
+ const uniqueBy = require("./unique-by.cjs");
5
+ const ASTUtils = {
29
6
  isNodeOfOneOf(node, types) {
30
7
  return types.includes(node.type);
31
8
  },
32
9
  isIdentifier(node) {
33
- return node.type === import_utils.AST_NODE_TYPES.Identifier;
10
+ return node.type === utils.AST_NODE_TYPES.Identifier;
34
11
  },
35
12
  isIdentifierWithName(node, name) {
36
13
  return ASTUtils.isIdentifier(node) && node.name === name;
@@ -39,10 +16,10 @@ var ASTUtils = {
39
16
  return ASTUtils.isIdentifier(node) && name.includes(node.name);
40
17
  },
41
18
  isProperty(node) {
42
- return node.type === import_utils.AST_NODE_TYPES.Property;
19
+ return node.type === utils.AST_NODE_TYPES.Property;
43
20
  },
44
21
  isObjectExpression(node) {
45
- return node.type === import_utils.AST_NODE_TYPES.ObjectExpression;
22
+ return node.type === utils.AST_NODE_TYPES.ObjectExpression;
46
23
  },
47
24
  isPropertyWithIdentifierKey(node, key) {
48
25
  return ASTUtils.isProperty(node) && ASTUtils.isIdentifierWithName(node.key, key);
@@ -79,22 +56,22 @@ var ASTUtils = {
79
56
  identifiers.push(...ASTUtils.getNestedIdentifiers(x));
80
57
  });
81
58
  }
82
- if (node.type === import_utils.AST_NODE_TYPES.Property) {
59
+ if (node.type === utils.AST_NODE_TYPES.Property) {
83
60
  identifiers.push(...ASTUtils.getNestedIdentifiers(node.value));
84
61
  }
85
- if (node.type === import_utils.AST_NODE_TYPES.SpreadElement) {
62
+ if (node.type === utils.AST_NODE_TYPES.SpreadElement) {
86
63
  identifiers.push(...ASTUtils.getNestedIdentifiers(node.argument));
87
64
  }
88
- if (node.type === import_utils.AST_NODE_TYPES.MemberExpression) {
65
+ if (node.type === utils.AST_NODE_TYPES.MemberExpression) {
89
66
  identifiers.push(...ASTUtils.getNestedIdentifiers(node.object));
90
67
  }
91
- if (node.type === import_utils.AST_NODE_TYPES.UnaryExpression) {
68
+ if (node.type === utils.AST_NODE_TYPES.UnaryExpression) {
92
69
  identifiers.push(...ASTUtils.getNestedIdentifiers(node.argument));
93
70
  }
94
- if (node.type === import_utils.AST_NODE_TYPES.ChainExpression) {
71
+ if (node.type === utils.AST_NODE_TYPES.ChainExpression) {
95
72
  identifiers.push(...ASTUtils.getNestedIdentifiers(node.expression));
96
73
  }
97
- if (node.type === import_utils.AST_NODE_TYPES.TSNonNullExpression) {
74
+ if (node.type === utils.AST_NODE_TYPES.TSNonNullExpression) {
98
75
  identifiers.push(...ASTUtils.getNestedIdentifiers(node.expression));
99
76
  }
100
77
  return identifiers;
@@ -103,10 +80,10 @@ var ASTUtils = {
103
80
  let previousNode = identifier;
104
81
  let currentNode = identifier.parent;
105
82
  while (currentNode !== void 0) {
106
- if (currentNode.type === import_utils.AST_NODE_TYPES.CallExpression && currentNode.callee === previousNode) {
83
+ if (currentNode.type === utils.AST_NODE_TYPES.CallExpression && currentNode.callee === previousNode) {
107
84
  return true;
108
85
  }
109
- if (currentNode.type !== import_utils.AST_NODE_TYPES.MemberExpression) {
86
+ if (currentNode.type !== utils.AST_NODE_TYPES.MemberExpression) {
110
87
  return false;
111
88
  }
112
89
  previousNode = currentNode;
@@ -137,8 +114,8 @@ var ASTUtils = {
137
114
  }
138
115
  const references = scope.references.filter((x) => x.isRead() && !scope.set.has(x.identifier.name)).map((x) => {
139
116
  const referenceNode = ASTUtils.traverseUpOnly(x.identifier, [
140
- import_utils.AST_NODE_TYPES.MemberExpression,
141
- import_utils.AST_NODE_TYPES.Identifier
117
+ utils.AST_NODE_TYPES.MemberExpression,
118
+ utils.AST_NODE_TYPES.Identifier
142
119
  ]);
143
120
  return {
144
121
  variable: x,
@@ -152,13 +129,13 @@ var ASTUtils = {
152
129
  const externalRefs = references.filter(
153
130
  (x) => x.variable.resolved === null || !localRefIds.has(x.text)
154
131
  );
155
- return (0, import_unique_by.uniqueBy)(externalRefs, (x) => x.text).map((x) => x.variable);
132
+ return uniqueBy.uniqueBy(externalRefs, (x) => x.text).map((x) => x.variable);
156
133
  },
157
134
  mapKeyNodeToText(node, sourceCode) {
158
135
  return sourceCode.getText(
159
136
  ASTUtils.traverseUpOnly(node, [
160
- import_utils.AST_NODE_TYPES.MemberExpression,
161
- import_utils.AST_NODE_TYPES.Identifier
137
+ utils.AST_NODE_TYPES.MemberExpression,
138
+ utils.AST_NODE_TYPES.Identifier
162
139
  ])
163
140
  );
164
141
  },
@@ -168,13 +145,13 @@ var ASTUtils = {
168
145
  getFunctionAncestor(context) {
169
146
  var _a;
170
147
  for (const ancestor of context.getAncestors()) {
171
- if (ancestor.type === import_utils.AST_NODE_TYPES.FunctionDeclaration) {
148
+ if (ancestor.type === utils.AST_NODE_TYPES.FunctionDeclaration) {
172
149
  return ancestor;
173
150
  }
174
- if (((_a = ancestor.parent) == null ? void 0 : _a.type) === import_utils.AST_NODE_TYPES.VariableDeclarator && ancestor.parent.id.type === import_utils.AST_NODE_TYPES.Identifier && ASTUtils.isNodeOfOneOf(ancestor, [
175
- import_utils.AST_NODE_TYPES.FunctionDeclaration,
176
- import_utils.AST_NODE_TYPES.FunctionExpression,
177
- import_utils.AST_NODE_TYPES.ArrowFunctionExpression
151
+ if (((_a = ancestor.parent) == null ? void 0 : _a.type) === utils.AST_NODE_TYPES.VariableDeclarator && ancestor.parent.id.type === utils.AST_NODE_TYPES.Identifier && ASTUtils.isNodeOfOneOf(ancestor, [
152
+ utils.AST_NODE_TYPES.FunctionDeclaration,
153
+ utils.AST_NODE_TYPES.FunctionExpression,
154
+ utils.AST_NODE_TYPES.ArrowFunctionExpression
178
155
  ])) {
179
156
  return ancestor;
180
157
  }
@@ -185,15 +162,15 @@ var ASTUtils = {
185
162
  var _a, _b, _c;
186
163
  const { node, context } = params;
187
164
  const resolvedNode = (_c = (_b = (_a = context.getScope().references.find((ref) => ref.identifier === node)) == null ? void 0 : _a.resolved) == null ? void 0 : _b.defs[0]) == null ? void 0 : _c.node;
188
- if ((resolvedNode == null ? void 0 : resolvedNode.type) !== import_utils.AST_NODE_TYPES.VariableDeclarator) {
165
+ if ((resolvedNode == null ? void 0 : resolvedNode.type) !== utils.AST_NODE_TYPES.VariableDeclarator) {
189
166
  return null;
190
167
  }
191
168
  return resolvedNode.init;
192
169
  },
193
170
  getClosestVariableDeclarator(node) {
194
171
  let currentNode = node;
195
- while (currentNode !== void 0 && currentNode.type !== import_utils.AST_NODE_TYPES.Program) {
196
- if (currentNode.type === import_utils.AST_NODE_TYPES.VariableDeclarator) {
172
+ while (currentNode !== void 0 && currentNode.type !== utils.AST_NODE_TYPES.Program) {
173
+ if (currentNode.type === utils.AST_NODE_TYPES.VariableDeclarator) {
197
174
  return currentNode;
198
175
  }
199
176
  currentNode = currentNode.parent;
@@ -202,7 +179,7 @@ var ASTUtils = {
202
179
  },
203
180
  getNestedReturnStatements(node) {
204
181
  const returnStatements = [];
205
- if (node.type === import_utils.AST_NODE_TYPES.ReturnStatement) {
182
+ if (node.type === utils.AST_NODE_TYPES.ReturnStatement) {
206
183
  returnStatements.push(node);
207
184
  }
208
185
  if ("body" in node && node.body !== void 0 && node.body !== null) {
@@ -253,8 +230,5 @@ var ASTUtils = {
253
230
  return returnStatements;
254
231
  }
255
232
  };
256
- // Annotate the CommonJS export names for ESM import in node:
257
- 0 && (module.exports = {
258
- ASTUtils
259
- });
260
- //# sourceMappingURL=ast-utils.cjs.map
233
+ exports.ASTUtils = ASTUtils;
234
+ //# sourceMappingURL=ast-utils.cjs.map