@tanstack/eslint-plugin-query 5.71.5 → 5.72.0
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.
- package/dist/index.cjs +1001 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +968 -0
- package/dist/index.js.map +1 -0
- package/dist/rules.cjs +966 -0
- package/dist/rules.cjs.map +1 -0
- package/dist/rules.js +929 -0
- package/dist/rules.js.map +1 -0
- package/package.json +12 -12
- package/dist/cjs/index.cjs +0 -38
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/index.d.cts +0 -13
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.rule.cjs +0 -134
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.rule.cjs.map +0 -1
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.rule.d.cts +0 -4
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.utils.cjs +0 -26
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.utils.cjs.map +0 -1
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.utils.d.cts +0 -10
- package/dist/cjs/rules/infinite-query-property-order/constants.cjs +0 -13
- package/dist/cjs/rules/infinite-query-property-order/constants.cjs.map +0 -1
- package/dist/cjs/rules/infinite-query-property-order/constants.d.cts +0 -4
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.rule.cjs +0 -88
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.rule.cjs.map +0 -1
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.rule.d.cts +0 -4
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.utils.cjs +0 -47
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.utils.cjs.map +0 -1
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.utils.d.cts +0 -1
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.rule.cjs +0 -92
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.rule.cjs.map +0 -1
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.rule.d.cts +0 -4
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.utils.cjs +0 -13
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.utils.cjs.map +0 -1
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.utils.d.cts +0 -4
- package/dist/cjs/rules/no-unstable-deps/no-unstable-deps.rule.cjs +0 -93
- package/dist/cjs/rules/no-unstable-deps/no-unstable-deps.rule.cjs.map +0 -1
- package/dist/cjs/rules/no-unstable-deps/no-unstable-deps.rule.d.cts +0 -6
- package/dist/cjs/rules/stable-query-client/stable-query-client.rule.cjs +0 -71
- package/dist/cjs/rules/stable-query-client/stable-query-client.rule.cjs.map +0 -1
- package/dist/cjs/rules/stable-query-client/stable-query-client.rule.d.cts +0 -4
- package/dist/cjs/rules.cjs +0 -16
- package/dist/cjs/rules.cjs.map +0 -1
- package/dist/cjs/rules.d.cts +0 -3
- package/dist/cjs/types.d.cts +0 -3
- package/dist/cjs/utils/ast-utils.cjs +0 -267
- package/dist/cjs/utils/ast-utils.cjs.map +0 -1
- package/dist/cjs/utils/ast-utils.d.cts +0 -38
- package/dist/cjs/utils/detect-react-query-imports.cjs +0 -55
- package/dist/cjs/utils/detect-react-query-imports.cjs.map +0 -1
- package/dist/cjs/utils/detect-react-query-imports.d.cts +0 -11
- package/dist/cjs/utils/get-docs-url.cjs +0 -5
- package/dist/cjs/utils/get-docs-url.cjs.map +0 -1
- package/dist/cjs/utils/get-docs-url.d.cts +0 -1
- package/dist/cjs/utils/unique-by.cjs +0 -7
- package/dist/cjs/utils/unique-by.cjs.map +0 -1
- package/dist/cjs/utils/unique-by.d.cts +0 -1
- package/dist/esm/index.d.ts +0 -13
- package/dist/esm/index.js +0 -39
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.rule.d.ts +0 -4
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.rule.js +0 -134
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.rule.js.map +0 -1
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.utils.d.ts +0 -10
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.utils.js +0 -26
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.utils.js.map +0 -1
- package/dist/esm/rules/infinite-query-property-order/constants.d.ts +0 -4
- package/dist/esm/rules/infinite-query-property-order/constants.js +0 -13
- package/dist/esm/rules/infinite-query-property-order/constants.js.map +0 -1
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.d.ts +0 -4
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.js +0 -88
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.js.map +0 -1
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.d.ts +0 -1
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.js +0 -47
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.js.map +0 -1
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.rule.d.ts +0 -4
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.rule.js +0 -92
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.rule.js.map +0 -1
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.utils.d.ts +0 -4
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.utils.js +0 -13
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.utils.js.map +0 -1
- package/dist/esm/rules/no-unstable-deps/no-unstable-deps.rule.d.ts +0 -6
- package/dist/esm/rules/no-unstable-deps/no-unstable-deps.rule.js +0 -93
- package/dist/esm/rules/no-unstable-deps/no-unstable-deps.rule.js.map +0 -1
- package/dist/esm/rules/stable-query-client/stable-query-client.rule.d.ts +0 -4
- package/dist/esm/rules/stable-query-client/stable-query-client.rule.js +0 -71
- package/dist/esm/rules/stable-query-client/stable-query-client.rule.js.map +0 -1
- package/dist/esm/rules.d.ts +0 -3
- package/dist/esm/rules.js +0 -16
- package/dist/esm/rules.js.map +0 -1
- package/dist/esm/types.d.ts +0 -3
- package/dist/esm/utils/ast-utils.d.ts +0 -38
- package/dist/esm/utils/ast-utils.js +0 -267
- package/dist/esm/utils/ast-utils.js.map +0 -1
- package/dist/esm/utils/detect-react-query-imports.d.ts +0 -11
- package/dist/esm/utils/detect-react-query-imports.js +0 -55
- package/dist/esm/utils/detect-react-query-imports.js.map +0 -1
- package/dist/esm/utils/get-docs-url.d.ts +0 -1
- package/dist/esm/utils/get-docs-url.js +0 -5
- package/dist/esm/utils/get-docs-url.js.map +0 -1
- package/dist/esm/utils/unique-by.d.ts +0 -1
- package/dist/esm/utils/unique-by.js +0 -7
- package/dist/esm/utils/unique-by.js.map +0 -1
- package/src/index.ts +0 -52
- package/src/rules/exhaustive-deps/exhaustive-deps.rule.ts +0 -184
- package/src/rules/exhaustive-deps/exhaustive-deps.utils.ts +0 -41
- package/src/rules/infinite-query-property-order/constants.ts +0 -17
- package/src/rules/infinite-query-property-order/infinite-query-property-order.rule.ts +0 -107
- package/src/rules/infinite-query-property-order/infinite-query-property-order.utils.ts +0 -67
- package/src/rules/no-rest-destructuring/no-rest-destructuring.rule.ts +0 -115
- package/src/rules/no-rest-destructuring/no-rest-destructuring.utils.ts +0 -11
- package/src/rules/no-unstable-deps/no-unstable-deps.rule.ts +0 -129
- package/src/rules/stable-query-client/stable-query-client.rule.ts +0 -88
- package/src/rules.ts +0 -23
- package/src/types.ts +0 -3
- package/src/utils/ast-utils.ts +0 -391
- package/src/utils/detect-react-query-imports.ts +0 -97
- package/src/utils/get-docs-url.ts +0 -2
- package/src/utils/unique-by.ts +0 -3
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exhaustive-deps.rule.js","sources":["../../../../src/rules/exhaustive-deps/exhaustive-deps.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { uniqueBy } from '../../utils/unique-by'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport { ExhaustiveDepsUtils } from './exhaustive-deps.utils'\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst QUERY_KEY = 'queryKey'\nconst QUERY_FN = 'queryFn'\n\nexport const name = 'exhaustive-deps'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\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: detectTanstackQueryImports((context) => {\n return {\n Property: (node) => {\n if (\n !ASTUtils.isObjectExpression(node.parent) ||\n !ASTUtils.isIdentifierWithName(node.key, QUERY_KEY)\n ) {\n return\n }\n\n const scopeManager = context.sourceCode.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 !ASTUtils.isNodeOfOneOf(queryFn.value, [\n AST_NODE_TYPES.ArrowFunctionExpression,\n AST_NODE_TYPES.FunctionExpression,\n AST_NODE_TYPES.ConditionalExpression,\n ])\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 externalRefs = ASTUtils.getExternalRefs({\n scopeManager,\n sourceCode: context.sourceCode,\n node: getQueryFnRelevantNode(queryFn),\n })\n\n const relevantRefs = externalRefs.filter((reference) =>\n ExhaustiveDepsUtils.isRelevantReference({\n sourceCode: context.sourceCode,\n reference,\n scopeManager,\n node: getQueryFnRelevantNode(queryFn),\n }),\n )\n\n const existingKeys = ASTUtils.getNestedIdentifiers(queryKeyNode).map(\n (identifier) =>\n ASTUtils.mapKeyNodeToBaseText(identifier, context.sourceCode),\n )\n\n const missingRefs = relevantRefs\n .map((ref) => ({\n ref: ref,\n text: ASTUtils.mapKeyNodeToBaseText(\n ref.identifier,\n context.sourceCode,\n ),\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) =>\n ASTUtils.mapKeyNodeToText(ref.identifier, context.sourceCode),\n )\n .join(', ')\n\n const queryKeyValue = context.sourceCode.getText(queryKeyNode)\n\n const existingWithMissing =\n queryKeyValue === '[]'\n ? `[${missingAsText}]`\n : queryKeyValue.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(queryKeyNode, 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\nfunction getQueryFnRelevantNode(queryFn: TSESTree.Property) {\n if (queryFn.value.type !== AST_NODE_TYPES.ConditionalExpression) {\n return queryFn.value\n }\n\n if (\n queryFn.value.consequent.type === AST_NODE_TYPES.Identifier &&\n queryFn.value.consequent.name === 'skipToken'\n ) {\n return queryFn.value.alternate\n }\n\n return queryFn.value.consequent\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
export declare const ExhaustiveDepsUtils: {
|
|
3
|
-
isRelevantReference(params: {
|
|
4
|
-
sourceCode: Readonly<TSESLint.SourceCode>;
|
|
5
|
-
reference: TSESLint.Scope.Reference;
|
|
6
|
-
scopeManager: TSESLint.Scope.ScopeManager;
|
|
7
|
-
node: TSESTree.Node;
|
|
8
|
-
}): boolean;
|
|
9
|
-
isInstanceOfKind(node: TSESTree.Node): boolean;
|
|
10
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
-
import { ASTUtils } from "../../utils/ast-utils.js";
|
|
3
|
-
const ExhaustiveDepsUtils = {
|
|
4
|
-
isRelevantReference(params) {
|
|
5
|
-
const { sourceCode, reference, scopeManager, node } = params;
|
|
6
|
-
const component = ASTUtils.getFunctionAncestor(sourceCode, node);
|
|
7
|
-
if (component === void 0) {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
if (!ASTUtils.isDeclaredInNode({
|
|
11
|
-
scopeManager,
|
|
12
|
-
reference,
|
|
13
|
-
functionNode: component
|
|
14
|
-
})) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
return reference.identifier.name !== "undefined" && reference.identifier.parent.type !== AST_NODE_TYPES.NewExpression && !ExhaustiveDepsUtils.isInstanceOfKind(reference.identifier.parent);
|
|
18
|
-
},
|
|
19
|
-
isInstanceOfKind(node) {
|
|
20
|
-
return node.type === AST_NODE_TYPES.BinaryExpression && node.operator === "instanceof";
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
export {
|
|
24
|
-
ExhaustiveDepsUtils
|
|
25
|
-
};
|
|
26
|
-
//# sourceMappingURL=exhaustive-deps.utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exhaustive-deps.utils.js","sources":["../../../../src/rules/exhaustive-deps/exhaustive-deps.utils.ts"],"sourcesContent":["import { AST_NODE_TYPES } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils'\n\nexport const ExhaustiveDepsUtils = {\n isRelevantReference(params: {\n sourceCode: Readonly<TSESLint.SourceCode>\n reference: TSESLint.Scope.Reference\n scopeManager: TSESLint.Scope.ScopeManager\n node: TSESTree.Node\n }) {\n const { sourceCode, reference, scopeManager, node } = params\n const component = ASTUtils.getFunctionAncestor(sourceCode, node)\n\n if (component === undefined) {\n return false\n }\n\n if (\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.isInstanceOfKind(reference.identifier.parent)\n )\n },\n isInstanceOfKind(node: TSESTree.Node) {\n return (\n node.type === AST_NODE_TYPES.BinaryExpression &&\n node.operator === 'instanceof'\n )\n },\n}\n"],"names":[],"mappings":";;AAIO,MAAM,sBAAsB;AAAA,EACjC,oBAAoB,QAKjB;AACD,UAAM,EAAE,YAAY,WAAW,cAAc,KAAS,IAAA;AACtD,UAAM,YAAY,SAAS,oBAAoB,YAAY,IAAI;AAE/D,QAAI,cAAc,QAAW;AACpB,aAAA;AAAA,IAAA;AAIP,QAAA,CAAC,SAAS,iBAAiB;AAAA,MACzB;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAAA,CACf,GACD;AACO,aAAA;AAAA,IAAA;AAGT,WACE,UAAU,WAAW,SAAS,eAC9B,UAAU,WAAW,OAAO,SAAS,eAAe,iBACpD,CAAC,oBAAoB,iBAAiB,UAAU,WAAW,MAAM;AAAA,EAErE;AAAA,EACA,iBAAiB,MAAqB;AACpC,WACE,KAAK,SAAS,eAAe,oBAC7B,KAAK,aAAa;AAAA,EAAA;AAGxB;"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export declare const infiniteQueryFunctions: readonly ["infiniteQueryOptions", "useInfiniteQuery", "useSuspenseInfiniteQuery"];
|
|
2
|
-
export type InfiniteQueryFunctions = (typeof infiniteQueryFunctions)[number];
|
|
3
|
-
export declare const checkedProperties: readonly ["queryFn", "getPreviousPageParam", "getNextPageParam"];
|
|
4
|
-
export declare const sortRules: readonly [readonly [readonly ["queryFn"], readonly ["getPreviousPageParam", "getNextPageParam"]]];
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const infiniteQueryFunctions = [
|
|
2
|
-
"infiniteQueryOptions",
|
|
3
|
-
"useInfiniteQuery",
|
|
4
|
-
"useSuspenseInfiniteQuery"
|
|
5
|
-
];
|
|
6
|
-
const sortRules = [
|
|
7
|
-
[["queryFn"], ["getPreviousPageParam", "getNextPageParam"]]
|
|
8
|
-
];
|
|
9
|
-
export {
|
|
10
|
-
infiniteQueryFunctions,
|
|
11
|
-
sortRules
|
|
12
|
-
};
|
|
13
|
-
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":["../../../../src/rules/infinite-query-property-order/constants.ts"],"sourcesContent":["export const infiniteQueryFunctions = [\n 'infiniteQueryOptions',\n 'useInfiniteQuery',\n 'useSuspenseInfiniteQuery',\n] as const\n\nexport type InfiniteQueryFunctions = (typeof infiniteQueryFunctions)[number]\n\nexport const checkedProperties = [\n 'queryFn',\n 'getPreviousPageParam',\n 'getNextPageParam',\n] as const\n\nexport const sortRules = [\n [['queryFn'], ['getPreviousPageParam', 'getNextPageParam']],\n] as const\n"],"names":[],"mappings":"AAAO,MAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AACF;AAUO,MAAM,YAAY;AAAA,EACvB,CAAC,CAAC,SAAS,GAAG,CAAC,wBAAwB,kBAAkB,CAAC;AAC5D;"}
|
package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
import { ExtraRuleDocs } from '../../types';
|
|
3
|
-
export declare const name = "infinite-query-property-order";
|
|
4
|
-
export declare const rule: ESLintUtils.RuleModule<string, readonly unknown[], ExtraRuleDocs, ESLintUtils.RuleListener>;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
-
import { getDocsUrl } from "../../utils/get-docs-url.js";
|
|
3
|
-
import { detectTanstackQueryImports } from "../../utils/detect-react-query-imports.js";
|
|
4
|
-
import { sortDataByOrder } from "./infinite-query-property-order.utils.js";
|
|
5
|
-
import { infiniteQueryFunctions, sortRules } from "./constants.js";
|
|
6
|
-
const createRule = ESLintUtils.RuleCreator(getDocsUrl);
|
|
7
|
-
const infiniteQueryFunctionsSet = new Set(infiniteQueryFunctions);
|
|
8
|
-
function isInfiniteQueryFunction(node) {
|
|
9
|
-
return infiniteQueryFunctionsSet.has(node);
|
|
10
|
-
}
|
|
11
|
-
const name = "infinite-query-property-order";
|
|
12
|
-
const rule = createRule({
|
|
13
|
-
name,
|
|
14
|
-
meta: {
|
|
15
|
-
type: "problem",
|
|
16
|
-
docs: {
|
|
17
|
-
description: "Ensure correct order of inference sensitive properties for infinite queries",
|
|
18
|
-
recommended: "error"
|
|
19
|
-
},
|
|
20
|
-
messages: {
|
|
21
|
-
invalidOrder: "Invalid order of properties for `{{function}}`."
|
|
22
|
-
},
|
|
23
|
-
schema: [],
|
|
24
|
-
hasSuggestions: true,
|
|
25
|
-
fixable: "code"
|
|
26
|
-
},
|
|
27
|
-
defaultOptions: [],
|
|
28
|
-
create: detectTanstackQueryImports((context) => {
|
|
29
|
-
return {
|
|
30
|
-
CallExpression(node) {
|
|
31
|
-
if (node.callee.type !== AST_NODE_TYPES.Identifier) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const infiniteQueryFunction = node.callee.name;
|
|
35
|
-
if (!isInfiniteQueryFunction(infiniteQueryFunction)) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const argument = node.arguments[0];
|
|
39
|
-
if (argument === void 0 || argument.type !== "ObjectExpression") {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const allProperties = argument.properties;
|
|
43
|
-
if (allProperties.length < 2) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const properties = allProperties.flatMap((p, index) => {
|
|
47
|
-
if (p.type === AST_NODE_TYPES.Property && p.key.type === AST_NODE_TYPES.Identifier) {
|
|
48
|
-
return { name: p.key.name, property: p };
|
|
49
|
-
} else return { name: `_property_${index}`, property: p };
|
|
50
|
-
});
|
|
51
|
-
const sortedProperties = sortDataByOrder(properties, sortRules, "name");
|
|
52
|
-
if (sortedProperties === null) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
context.report({
|
|
56
|
-
node: argument,
|
|
57
|
-
data: { function: node.callee.name },
|
|
58
|
-
messageId: "invalidOrder",
|
|
59
|
-
fix(fixer) {
|
|
60
|
-
const sourceCode = context.sourceCode;
|
|
61
|
-
const reorderedText = sortedProperties.reduce(
|
|
62
|
-
(sourceText, specifier, index) => {
|
|
63
|
-
let textBetweenProperties = "";
|
|
64
|
-
if (index < allProperties.length - 1) {
|
|
65
|
-
textBetweenProperties = sourceCode.getText().slice(
|
|
66
|
-
allProperties[index].range[1],
|
|
67
|
-
allProperties[index + 1].range[0]
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
return sourceText + sourceCode.getText(specifier.property) + textBetweenProperties;
|
|
71
|
-
},
|
|
72
|
-
""
|
|
73
|
-
);
|
|
74
|
-
return fixer.replaceTextRange(
|
|
75
|
-
[allProperties[0].range[0], allProperties.at(-1).range[1]],
|
|
76
|
-
reorderedText
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
})
|
|
83
|
-
});
|
|
84
|
-
export {
|
|
85
|
-
name,
|
|
86
|
-
rule
|
|
87
|
-
};
|
|
88
|
-
//# sourceMappingURL=infinite-query-property-order.rule.js.map
|
package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"infinite-query-property-order.rule.js","sources":["../../../../src/rules/infinite-query-property-order/infinite-query-property-order.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport { sortDataByOrder } from './infinite-query-property-order.utils'\nimport { infiniteQueryFunctions, sortRules } from './constants'\nimport type { InfiniteQueryFunctions } from './constants'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst infiniteQueryFunctionsSet = new Set(infiniteQueryFunctions)\nfunction isInfiniteQueryFunction(node: any): node is InfiniteQueryFunctions {\n return infiniteQueryFunctionsSet.has(node)\n}\n\nexport const name = 'infinite-query-property-order'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Ensure correct order of inference sensitive properties for infinite queries',\n recommended: 'error',\n },\n messages: {\n invalidOrder: 'Invalid order of properties for `{{function}}`.',\n },\n schema: [],\n hasSuggestions: true,\n fixable: 'code',\n },\n defaultOptions: [],\n\n create: detectTanstackQueryImports((context) => {\n return {\n CallExpression(node) {\n if (node.callee.type !== AST_NODE_TYPES.Identifier) {\n return\n }\n const infiniteQueryFunction = node.callee.name\n if (!isInfiniteQueryFunction(infiniteQueryFunction)) {\n return\n }\n const argument = node.arguments[0]\n if (argument === undefined || argument.type !== 'ObjectExpression') {\n return\n }\n\n const allProperties = argument.properties\n\n // no need to sort if there is at max 1 property\n if (allProperties.length < 2) {\n return\n }\n\n const properties = allProperties.flatMap((p, index) => {\n if (\n p.type === AST_NODE_TYPES.Property &&\n p.key.type === AST_NODE_TYPES.Identifier\n ) {\n return { name: p.key.name, property: p }\n } else return { name: `_property_${index}`, property: p }\n })\n\n const sortedProperties = sortDataByOrder(properties, sortRules, 'name')\n if (sortedProperties === null) {\n return\n }\n context.report({\n node: argument,\n data: { function: node.callee.name },\n messageId: 'invalidOrder',\n fix(fixer) {\n const sourceCode = context.sourceCode\n\n const reorderedText = sortedProperties.reduce(\n (sourceText, specifier, index) => {\n let textBetweenProperties = ''\n if (index < allProperties.length - 1) {\n textBetweenProperties = sourceCode\n .getText()\n .slice(\n allProperties[index]!.range[1],\n allProperties[index + 1]!.range[0],\n )\n }\n return (\n sourceText +\n sourceCode.getText(specifier.property) +\n textBetweenProperties\n )\n },\n '',\n )\n return fixer.replaceTextRange(\n [allProperties[0]!.range[0], allProperties.at(-1)!.range[1]],\n reorderedText,\n )\n },\n })\n },\n }\n }),\n})\n"],"names":[],"mappings":";;;;;AASA,MAAM,aAAa,YAAY,YAA2B,UAAU;AAEpE,MAAM,4BAA4B,IAAI,IAAI,sBAAsB;AAChE,SAAS,wBAAwB,MAA2C;AACnE,SAAA,0BAA0B,IAAI,IAAI;AAC3C;AAEO,MAAM,OAAO;AAEb,MAAM,OAAO,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aACE;AAAA,MACF,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,cAAc;AAAA,IAChB;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,gBAAgB;AAAA,IAChB,SAAS;AAAA,EACX;AAAA,EACA,gBAAgB,CAAC;AAAA,EAEjB,QAAQ,2BAA2B,CAAC,YAAY;AACvC,WAAA;AAAA,MACL,eAAe,MAAM;AACnB,YAAI,KAAK,OAAO,SAAS,eAAe,YAAY;AAClD;AAAA,QAAA;AAEI,cAAA,wBAAwB,KAAK,OAAO;AACtC,YAAA,CAAC,wBAAwB,qBAAqB,GAAG;AACnD;AAAA,QAAA;AAEI,cAAA,WAAW,KAAK,UAAU,CAAC;AACjC,YAAI,aAAa,UAAa,SAAS,SAAS,oBAAoB;AAClE;AAAA,QAAA;AAGF,cAAM,gBAAgB,SAAS;AAG3B,YAAA,cAAc,SAAS,GAAG;AAC5B;AAAA,QAAA;AAGF,cAAM,aAAa,cAAc,QAAQ,CAAC,GAAG,UAAU;AAEnD,cAAA,EAAE,SAAS,eAAe,YAC1B,EAAE,IAAI,SAAS,eAAe,YAC9B;AACA,mBAAO,EAAE,MAAM,EAAE,IAAI,MAAM,UAAU,EAAE;AAAA,UAAA,cAC3B,EAAE,MAAM,aAAa,KAAK,IAAI,UAAU,EAAE;AAAA,QAAA,CACzD;AAED,cAAM,mBAAmB,gBAAgB,YAAY,WAAW,MAAM;AACtE,YAAI,qBAAqB,MAAM;AAC7B;AAAA,QAAA;AAEF,gBAAQ,OAAO;AAAA,UACb,MAAM;AAAA,UACN,MAAM,EAAE,UAAU,KAAK,OAAO,KAAK;AAAA,UACnC,WAAW;AAAA,UACX,IAAI,OAAO;AACT,kBAAM,aAAa,QAAQ;AAE3B,kBAAM,gBAAgB,iBAAiB;AAAA,cACrC,CAAC,YAAY,WAAW,UAAU;AAChC,oBAAI,wBAAwB;AACxB,oBAAA,QAAQ,cAAc,SAAS,GAAG;AACZ,0CAAA,WACrB,UACA;AAAA,oBACC,cAAc,KAAK,EAAG,MAAM,CAAC;AAAA,oBAC7B,cAAc,QAAQ,CAAC,EAAG,MAAM,CAAC;AAAA,kBACnC;AAAA,gBAAA;AAEJ,uBACE,aACA,WAAW,QAAQ,UAAU,QAAQ,IACrC;AAAA,cAEJ;AAAA,cACA;AAAA,YACF;AACA,mBAAO,MAAM;AAAA,cACX,CAAC,cAAc,CAAC,EAAG,MAAM,CAAC,GAAG,cAAc,GAAG,EAAE,EAAG,MAAM,CAAC,CAAC;AAAA,cAC3D;AAAA,YACF;AAAA,UAAA;AAAA,QACF,CACD;AAAA,MAAA;AAAA,IAEL;AAAA,EACD,CAAA;AACH,CAAC;"}
|
package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function sortDataByOrder<T, TKey extends keyof T>(data: Array<T> | ReadonlyArray<T>, orderRules: ReadonlyArray<Readonly<[ReadonlyArray<T[TKey]>, ReadonlyArray<T[TKey]>]>>, key: TKey): Array<T> | null;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
function sortDataByOrder(data, orderRules, key) {
|
|
2
|
-
const getSubsetIndex = (item, subsets) => {
|
|
3
|
-
var _a;
|
|
4
|
-
for (let i = 0; i < subsets.length; i++) {
|
|
5
|
-
if ((_a = subsets[i]) == null ? void 0 : _a.includes(item)) {
|
|
6
|
-
return i;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
return null;
|
|
10
|
-
};
|
|
11
|
-
const orderSets = orderRules.reduce(
|
|
12
|
-
(sets, [A, B]) => [...sets, A, B],
|
|
13
|
-
[]
|
|
14
|
-
);
|
|
15
|
-
const inOrderArray = data.filter(
|
|
16
|
-
(item) => getSubsetIndex(item[key], orderSets) !== null
|
|
17
|
-
);
|
|
18
|
-
let wasResorted = false;
|
|
19
|
-
const sortedArray = inOrderArray.sort((a, b) => {
|
|
20
|
-
const aKey = a[key], bKey = b[key];
|
|
21
|
-
const aSubsetIndex = getSubsetIndex(aKey, orderSets);
|
|
22
|
-
const bSubsetIndex = getSubsetIndex(bKey, orderSets);
|
|
23
|
-
if (aSubsetIndex !== null && bSubsetIndex !== null && aSubsetIndex !== bSubsetIndex) {
|
|
24
|
-
return aSubsetIndex - bSubsetIndex;
|
|
25
|
-
}
|
|
26
|
-
return 0;
|
|
27
|
-
});
|
|
28
|
-
const inOrderIterator = sortedArray.values();
|
|
29
|
-
const result = data.map((item) => {
|
|
30
|
-
if (getSubsetIndex(item[key], orderSets) !== null) {
|
|
31
|
-
const sortedItem = inOrderIterator.next().value;
|
|
32
|
-
if (sortedItem[key] !== item[key]) {
|
|
33
|
-
wasResorted = true;
|
|
34
|
-
}
|
|
35
|
-
return sortedItem;
|
|
36
|
-
}
|
|
37
|
-
return item;
|
|
38
|
-
});
|
|
39
|
-
if (!wasResorted) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
|
-
}
|
|
44
|
-
export {
|
|
45
|
-
sortDataByOrder
|
|
46
|
-
};
|
|
47
|
-
//# sourceMappingURL=infinite-query-property-order.utils.js.map
|
package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"infinite-query-property-order.utils.js","sources":["../../../../src/rules/infinite-query-property-order/infinite-query-property-order.utils.ts"],"sourcesContent":["export function sortDataByOrder<T, TKey extends keyof T>(\n data: Array<T> | ReadonlyArray<T>,\n orderRules: ReadonlyArray<\n Readonly<[ReadonlyArray<T[TKey]>, ReadonlyArray<T[TKey]>]>\n >,\n key: TKey,\n): Array<T> | null {\n const getSubsetIndex = (\n item: T[TKey],\n subsets: ReadonlyArray<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n ): number | null => {\n for (let i = 0; i < subsets.length; i++) {\n if (subsets[i]?.includes(item)) {\n return i\n }\n }\n return null\n }\n\n const orderSets = orderRules.reduce(\n (sets, [A, B]) => [...sets, A, B],\n [] as Array<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n )\n\n const inOrderArray = data.filter(\n (item) => getSubsetIndex(item[key], orderSets) !== null,\n )\n\n let wasResorted = false as boolean\n\n // Sort by the relative order defined by the rules\n const sortedArray = inOrderArray.sort((a, b) => {\n const aKey = a[key],\n bKey = b[key]\n const aSubsetIndex = getSubsetIndex(aKey, orderSets)\n const bSubsetIndex = getSubsetIndex(bKey, orderSets)\n\n // If both items belong to different subsets, sort by their subset order\n if (\n aSubsetIndex !== null &&\n bSubsetIndex !== null &&\n aSubsetIndex !== bSubsetIndex\n ) {\n return aSubsetIndex - bSubsetIndex\n }\n\n // If both items belong to the same subset or neither is in the subset, keep their relative order\n return 0\n })\n\n const inOrderIterator = sortedArray.values()\n const result = data.map((item) => {\n if (getSubsetIndex(item[key], orderSets) !== null) {\n const sortedItem = inOrderIterator.next().value!\n if (sortedItem[key] !== item[key]) {\n wasResorted = true\n }\n return sortedItem\n }\n return item\n })\n\n if (!wasResorted) {\n return null\n }\n return result\n}\n"],"names":[],"mappings":"AAAgB,SAAA,gBACd,MACA,YAGA,KACiB;AACX,QAAA,iBAAiB,CACrB,MACA,YACkB;AAVN;AAWZ,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,WAAI,aAAQ,CAAC,MAAT,mBAAY,SAAS,OAAO;AACvB,eAAA;AAAA,MAAA;AAAA,IACT;AAEK,WAAA;AAAA,EACT;AAEA,QAAM,YAAY,WAAW;AAAA,IAC3B,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC;AAAA,IAChC,CAAA;AAAA,EACF;AAEA,QAAM,eAAe,KAAK;AAAA,IACxB,CAAC,SAAS,eAAe,KAAK,GAAG,GAAG,SAAS,MAAM;AAAA,EACrD;AAEA,MAAI,cAAc;AAGlB,QAAM,cAAc,aAAa,KAAK,CAAC,GAAG,MAAM;AAC9C,UAAM,OAAO,EAAE,GAAG,GAChB,OAAO,EAAE,GAAG;AACR,UAAA,eAAe,eAAe,MAAM,SAAS;AAC7C,UAAA,eAAe,eAAe,MAAM,SAAS;AAGnD,QACE,iBAAiB,QACjB,iBAAiB,QACjB,iBAAiB,cACjB;AACA,aAAO,eAAe;AAAA,IAAA;AAIjB,WAAA;AAAA,EAAA,CACR;AAEK,QAAA,kBAAkB,YAAY,OAAO;AAC3C,QAAM,SAAS,KAAK,IAAI,CAAC,SAAS;AAChC,QAAI,eAAe,KAAK,GAAG,GAAG,SAAS,MAAM,MAAM;AAC3C,YAAA,aAAa,gBAAgB,KAAA,EAAO;AAC1C,UAAI,WAAW,GAAG,MAAM,KAAK,GAAG,GAAG;AACnB,sBAAA;AAAA,MAAA;AAET,aAAA;AAAA,IAAA;AAEF,WAAA;AAAA,EAAA,CACR;AAED,MAAI,CAAC,aAAa;AACT,WAAA;AAAA,EAAA;AAEF,SAAA;AACT;"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
import { ExtraRuleDocs } from '../../types';
|
|
3
|
-
export declare const name = "no-rest-destructuring";
|
|
4
|
-
export declare const rule: ESLintUtils.RuleModule<string, readonly unknown[], ExtraRuleDocs, ESLintUtils.RuleListener>;
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
-
import { getDocsUrl } from "../../utils/get-docs-url.js";
|
|
3
|
-
import { ASTUtils } from "../../utils/ast-utils.js";
|
|
4
|
-
import { detectTanstackQueryImports } from "../../utils/detect-react-query-imports.js";
|
|
5
|
-
import { NoRestDestructuringUtils } from "./no-rest-destructuring.utils.js";
|
|
6
|
-
const name = "no-rest-destructuring";
|
|
7
|
-
const queryHooks = [
|
|
8
|
-
"useQuery",
|
|
9
|
-
"useQueries",
|
|
10
|
-
"useInfiniteQuery",
|
|
11
|
-
"useSuspenseQuery",
|
|
12
|
-
"useSuspenseQueries",
|
|
13
|
-
"useSuspenseInfiniteQuery"
|
|
14
|
-
];
|
|
15
|
-
const createRule = ESLintUtils.RuleCreator(getDocsUrl);
|
|
16
|
-
const rule = createRule({
|
|
17
|
-
name,
|
|
18
|
-
meta: {
|
|
19
|
-
type: "problem",
|
|
20
|
-
docs: {
|
|
21
|
-
description: "Disallows rest destructuring in queries",
|
|
22
|
-
recommended: "warn"
|
|
23
|
-
},
|
|
24
|
-
messages: {
|
|
25
|
-
objectRestDestructure: `Object rest destructuring on a query will observe all changes to the query, leading to excessive re-renders.`
|
|
26
|
-
},
|
|
27
|
-
schema: []
|
|
28
|
-
},
|
|
29
|
-
defaultOptions: [],
|
|
30
|
-
create: detectTanstackQueryImports((context, _, helpers) => {
|
|
31
|
-
const queryResultVariables = /* @__PURE__ */ new Set();
|
|
32
|
-
return {
|
|
33
|
-
CallExpression: (node) => {
|
|
34
|
-
if (!ASTUtils.isIdentifierWithOneOfNames(node.callee, queryHooks) || node.parent.type !== AST_NODE_TYPES.VariableDeclarator || !helpers.isTanstackQueryImport(node.callee)) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const returnValue = node.parent.id;
|
|
38
|
-
if (node.callee.name !== "useQueries" && node.callee.name !== "useSuspenseQueries") {
|
|
39
|
-
if (NoRestDestructuringUtils.isObjectRestDestructuring(returnValue)) {
|
|
40
|
-
return context.report({
|
|
41
|
-
node: node.parent,
|
|
42
|
-
messageId: "objectRestDestructure"
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
if (returnValue.type === AST_NODE_TYPES.Identifier) {
|
|
46
|
-
queryResultVariables.add(returnValue.name);
|
|
47
|
-
}
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (returnValue.type !== AST_NODE_TYPES.ArrayPattern) {
|
|
51
|
-
if (returnValue.type === AST_NODE_TYPES.Identifier) {
|
|
52
|
-
queryResultVariables.add(returnValue.name);
|
|
53
|
-
}
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
returnValue.elements.forEach((queryResult) => {
|
|
57
|
-
if (queryResult === null) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (NoRestDestructuringUtils.isObjectRestDestructuring(queryResult)) {
|
|
61
|
-
context.report({
|
|
62
|
-
node: queryResult,
|
|
63
|
-
messageId: "objectRestDestructure"
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
},
|
|
68
|
-
VariableDeclarator: (node) => {
|
|
69
|
-
var _a;
|
|
70
|
-
if (((_a = node.init) == null ? void 0 : _a.type) === AST_NODE_TYPES.Identifier && queryResultVariables.has(node.init.name) && NoRestDestructuringUtils.isObjectRestDestructuring(node.id)) {
|
|
71
|
-
context.report({
|
|
72
|
-
node,
|
|
73
|
-
messageId: "objectRestDestructure"
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
SpreadElement: (node) => {
|
|
78
|
-
if (node.argument.type === AST_NODE_TYPES.Identifier && queryResultVariables.has(node.argument.name)) {
|
|
79
|
-
context.report({
|
|
80
|
-
node,
|
|
81
|
-
messageId: "objectRestDestructure"
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
})
|
|
87
|
-
});
|
|
88
|
-
export {
|
|
89
|
-
name,
|
|
90
|
-
rule
|
|
91
|
-
};
|
|
92
|
-
//# sourceMappingURL=no-rest-destructuring.rule.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"no-rest-destructuring.rule.js","sources":["../../../../src/rules/no-rest-destructuring/no-rest-destructuring.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport { NoRestDestructuringUtils } from './no-rest-destructuring.utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nexport const name = 'no-rest-destructuring'\n\nconst queryHooks = [\n 'useQuery',\n 'useQueries',\n 'useInfiniteQuery',\n 'useSuspenseQuery',\n 'useSuspenseQueries',\n 'useSuspenseInfiniteQuery',\n]\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\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: detectTanstackQueryImports((context, _, helpers) => {\n const queryResultVariables = new Set<string>()\n\n return {\n CallExpression: (node) => {\n if (\n !ASTUtils.isIdentifierWithOneOfNames(node.callee, queryHooks) ||\n node.parent.type !== AST_NODE_TYPES.VariableDeclarator ||\n !helpers.isTanstackQueryImport(node.callee)\n ) {\n return\n }\n\n const returnValue = node.parent.id\n\n if (\n node.callee.name !== 'useQueries' &&\n node.callee.name !== 'useSuspenseQueries'\n ) {\n if (NoRestDestructuringUtils.isObjectRestDestructuring(returnValue)) {\n return context.report({\n node: node.parent,\n messageId: 'objectRestDestructure',\n })\n }\n\n if (returnValue.type === AST_NODE_TYPES.Identifier) {\n queryResultVariables.add(returnValue.name)\n }\n\n return\n }\n\n if (returnValue.type !== AST_NODE_TYPES.ArrayPattern) {\n if (returnValue.type === AST_NODE_TYPES.Identifier) {\n queryResultVariables.add(returnValue.name)\n }\n return\n }\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 VariableDeclarator: (node) => {\n if (\n node.init?.type === AST_NODE_TYPES.Identifier &&\n queryResultVariables.has(node.init.name) &&\n NoRestDestructuringUtils.isObjectRestDestructuring(node.id)\n ) {\n context.report({\n node,\n messageId: 'objectRestDestructure',\n })\n }\n },\n\n SpreadElement: (node) => {\n if (\n node.argument.type === AST_NODE_TYPES.Identifier &&\n queryResultVariables.has(node.argument.name)\n ) {\n context.report({\n node,\n messageId: 'objectRestDestructure',\n })\n }\n },\n }\n }),\n})\n"],"names":[],"mappings":";;;;;AAOO,MAAM,OAAO;AAEpB,MAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,aAAa,YAAY,YAA2B,UAAU;AAE7D,MAAM,OAAO,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,CAAA;AAAA,EACV;AAAA,EACA,gBAAgB,CAAC;AAAA,EAEjB,QAAQ,2BAA2B,CAAC,SAAS,GAAG,YAAY;AACpD,UAAA,2CAA2B,IAAY;AAEtC,WAAA;AAAA,MACL,gBAAgB,CAAC,SAAS;AACxB,YACE,CAAC,SAAS,2BAA2B,KAAK,QAAQ,UAAU,KAC5D,KAAK,OAAO,SAAS,eAAe,sBACpC,CAAC,QAAQ,sBAAsB,KAAK,MAAM,GAC1C;AACA;AAAA,QAAA;AAGI,cAAA,cAAc,KAAK,OAAO;AAEhC,YACE,KAAK,OAAO,SAAS,gBACrB,KAAK,OAAO,SAAS,sBACrB;AACI,cAAA,yBAAyB,0BAA0B,WAAW,GAAG;AACnE,mBAAO,QAAQ,OAAO;AAAA,cACpB,MAAM,KAAK;AAAA,cACX,WAAW;AAAA,YAAA,CACZ;AAAA,UAAA;AAGC,cAAA,YAAY,SAAS,eAAe,YAAY;AAC7B,iCAAA,IAAI,YAAY,IAAI;AAAA,UAAA;AAG3C;AAAA,QAAA;AAGE,YAAA,YAAY,SAAS,eAAe,cAAc;AAChD,cAAA,YAAY,SAAS,eAAe,YAAY;AAC7B,iCAAA,IAAI,YAAY,IAAI;AAAA,UAAA;AAE3C;AAAA,QAAA;AAGU,oBAAA,SAAS,QAAQ,CAAC,gBAAgB;AAC5C,cAAI,gBAAgB,MAAM;AACxB;AAAA,UAAA;AAEE,cAAA,yBAAyB,0BAA0B,WAAW,GAAG;AACnE,oBAAQ,OAAO;AAAA,cACb,MAAM;AAAA,cACN,WAAW;AAAA,YAAA,CACZ;AAAA,UAAA;AAAA,QACH,CACD;AAAA,MACH;AAAA,MAEA,oBAAoB,CAAC,SAAS;;AAC5B,cACE,UAAK,SAAL,mBAAW,UAAS,eAAe,cACnC,qBAAqB,IAAI,KAAK,KAAK,IAAI,KACvC,yBAAyB,0BAA0B,KAAK,EAAE,GAC1D;AACA,kBAAQ,OAAO;AAAA,YACb;AAAA,YACA,WAAW;AAAA,UAAA,CACZ;AAAA,QAAA;AAAA,MAEL;AAAA,MAEA,eAAe,CAAC,SAAS;AAErB,YAAA,KAAK,SAAS,SAAS,eAAe,cACtC,qBAAqB,IAAI,KAAK,SAAS,IAAI,GAC3C;AACA,kBAAQ,OAAO;AAAA,YACb;AAAA,YACA,WAAW;AAAA,UAAA,CACZ;AAAA,QAAA;AAAA,MACH;AAAA,IAEJ;AAAA,EACD,CAAA;AACH,CAAC;"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
-
const NoRestDestructuringUtils = {
|
|
3
|
-
isObjectRestDestructuring(node) {
|
|
4
|
-
if (node.type !== AST_NODE_TYPES.ObjectPattern) {
|
|
5
|
-
return false;
|
|
6
|
-
}
|
|
7
|
-
return node.properties.some((p) => p.type === AST_NODE_TYPES.RestElement);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
export {
|
|
11
|
-
NoRestDestructuringUtils
|
|
12
|
-
};
|
|
13
|
-
//# sourceMappingURL=no-rest-destructuring.utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"no-rest-destructuring.utils.js","sources":["../../../../src/rules/no-rest-destructuring/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":[],"mappings":";AAGO,MAAM,2BAA2B;AAAA,EACtC,0BAA0B,MAA8B;AAClD,QAAA,KAAK,SAAS,eAAe,eAAe;AACvC,aAAA;AAAA,IAAA;AAEF,WAAA,KAAK,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,eAAe,WAAW;AAAA,EAAA;AAE5E;"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
import { ExtraRuleDocs } from '../../types';
|
|
3
|
-
export declare const name = "no-unstable-deps";
|
|
4
|
-
export declare const reactHookNames: string[];
|
|
5
|
-
export declare const useQueryHookNames: string[];
|
|
6
|
-
export declare const rule: ESLintUtils.RuleModule<string, readonly unknown[], ExtraRuleDocs, ESLintUtils.RuleListener>;
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
-
import { getDocsUrl } from "../../utils/get-docs-url.js";
|
|
3
|
-
import { detectTanstackQueryImports } from "../../utils/detect-react-query-imports.js";
|
|
4
|
-
const name = "no-unstable-deps";
|
|
5
|
-
const reactHookNames = ["useEffect", "useCallback", "useMemo"];
|
|
6
|
-
const useQueryHookNames = [
|
|
7
|
-
"useQuery",
|
|
8
|
-
"useSuspenseQuery",
|
|
9
|
-
"useQueries",
|
|
10
|
-
"useSuspenseQueries",
|
|
11
|
-
"useInfiniteQuery",
|
|
12
|
-
"useSuspenseInfiniteQuery"
|
|
13
|
-
];
|
|
14
|
-
const allHookNames = ["useMutation", ...useQueryHookNames];
|
|
15
|
-
const createRule = ESLintUtils.RuleCreator(getDocsUrl);
|
|
16
|
-
const rule = createRule({
|
|
17
|
-
name,
|
|
18
|
-
meta: {
|
|
19
|
-
type: "problem",
|
|
20
|
-
docs: {
|
|
21
|
-
description: "Disallow putting the result of query hooks directly in a React hook dependency array",
|
|
22
|
-
recommended: "error"
|
|
23
|
-
},
|
|
24
|
-
messages: {
|
|
25
|
-
noUnstableDeps: `The result of {{queryHook}} is not referentially stable, so don't pass it directly into the dependencies array of {{reactHook}}. Instead, destructure the return value of {{queryHook}} and pass the destructured values into the dependency array of {{reactHook}}.`
|
|
26
|
-
},
|
|
27
|
-
schema: []
|
|
28
|
-
},
|
|
29
|
-
defaultOptions: [],
|
|
30
|
-
create: detectTanstackQueryImports((context) => {
|
|
31
|
-
const trackedVariables = {};
|
|
32
|
-
const hookAliasMap = {};
|
|
33
|
-
function getReactHook(node) {
|
|
34
|
-
if (node.callee.type === "Identifier") {
|
|
35
|
-
const calleeName = node.callee.name;
|
|
36
|
-
if (reactHookNames.includes(calleeName) || calleeName in hookAliasMap) {
|
|
37
|
-
return calleeName;
|
|
38
|
-
}
|
|
39
|
-
} else if (node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.object.name === "React" && node.callee.property.type === "Identifier" && reactHookNames.includes(node.callee.property.name)) {
|
|
40
|
-
return node.callee.property.name;
|
|
41
|
-
}
|
|
42
|
-
return void 0;
|
|
43
|
-
}
|
|
44
|
-
function collectVariableNames(pattern, queryHook) {
|
|
45
|
-
if (pattern.type === AST_NODE_TYPES.Identifier) {
|
|
46
|
-
trackedVariables[pattern.name] = queryHook;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
ImportDeclaration(node) {
|
|
51
|
-
if (node.specifiers.length > 0 && node.importKind === "value" && node.source.value === "React") {
|
|
52
|
-
node.specifiers.forEach((specifier) => {
|
|
53
|
-
if (specifier.type === AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES.Identifier && reactHookNames.includes(specifier.imported.name)) {
|
|
54
|
-
hookAliasMap[specifier.local.name] = specifier.imported.name;
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
VariableDeclarator(node) {
|
|
60
|
-
if (node.init !== null && node.init.type === AST_NODE_TYPES.CallExpression && node.init.callee.type === AST_NODE_TYPES.Identifier && allHookNames.includes(node.init.callee.name)) {
|
|
61
|
-
collectVariableNames(node.id, node.init.callee.name);
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
CallExpression: (node) => {
|
|
65
|
-
var _a;
|
|
66
|
-
const reactHook = getReactHook(node);
|
|
67
|
-
if (reactHook !== void 0 && node.arguments.length > 1 && ((_a = node.arguments[1]) == null ? void 0 : _a.type) === AST_NODE_TYPES.ArrayExpression) {
|
|
68
|
-
const depsArray = node.arguments[1].elements;
|
|
69
|
-
depsArray.forEach((dep) => {
|
|
70
|
-
if (dep !== null && dep.type === AST_NODE_TYPES.Identifier && trackedVariables[dep.name] !== void 0) {
|
|
71
|
-
const queryHook = trackedVariables[dep.name];
|
|
72
|
-
context.report({
|
|
73
|
-
node: dep,
|
|
74
|
-
messageId: "noUnstableDeps",
|
|
75
|
-
data: {
|
|
76
|
-
queryHook,
|
|
77
|
-
reactHook
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
})
|
|
86
|
-
});
|
|
87
|
-
export {
|
|
88
|
-
name,
|
|
89
|
-
reactHookNames,
|
|
90
|
-
rule,
|
|
91
|
-
useQueryHookNames
|
|
92
|
-
};
|
|
93
|
-
//# sourceMappingURL=no-unstable-deps.rule.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"no-unstable-deps.rule.js","sources":["../../../../src/rules/no-unstable-deps/no-unstable-deps.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport type { TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nexport const name = 'no-unstable-deps'\n\nexport const reactHookNames = ['useEffect', 'useCallback', 'useMemo']\nexport const useQueryHookNames = [\n 'useQuery',\n 'useSuspenseQuery',\n 'useQueries',\n 'useSuspenseQueries',\n 'useInfiniteQuery',\n 'useSuspenseInfiniteQuery',\n]\nconst allHookNames = ['useMutation', ...useQueryHookNames]\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Disallow putting the result of query hooks directly in a React hook dependency array',\n recommended: 'error',\n },\n messages: {\n noUnstableDeps: `The result of {{queryHook}} is not referentially stable, so don't pass it directly into the dependencies array of {{reactHook}}. Instead, destructure the return value of {{queryHook}} and pass the destructured values into the dependency array of {{reactHook}}.`,\n },\n schema: [],\n },\n defaultOptions: [],\n\n create: detectTanstackQueryImports((context) => {\n const trackedVariables: Record<string, string> = {}\n const hookAliasMap: Record<string, string> = {}\n\n function getReactHook(node: TSESTree.CallExpression): string | undefined {\n if (node.callee.type === 'Identifier') {\n const calleeName = node.callee.name\n // Check if the identifier is a known React hook or an alias\n if (reactHookNames.includes(calleeName) || calleeName in hookAliasMap) {\n return calleeName\n }\n } else if (\n node.callee.type === 'MemberExpression' &&\n node.callee.object.type === 'Identifier' &&\n node.callee.object.name === 'React' &&\n node.callee.property.type === 'Identifier' &&\n reactHookNames.includes(node.callee.property.name)\n ) {\n // Member expression case: `React.useCallback`\n return node.callee.property.name\n }\n return undefined\n }\n\n function collectVariableNames(\n pattern: TSESTree.BindingName,\n queryHook: string,\n ) {\n if (pattern.type === AST_NODE_TYPES.Identifier) {\n trackedVariables[pattern.name] = queryHook\n }\n }\n\n return {\n ImportDeclaration(node: TSESTree.ImportDeclaration) {\n if (\n node.specifiers.length > 0 &&\n node.importKind === 'value' &&\n node.source.value === 'React'\n ) {\n node.specifiers.forEach((specifier) => {\n if (\n specifier.type === AST_NODE_TYPES.ImportSpecifier &&\n specifier.imported.type === AST_NODE_TYPES.Identifier &&\n reactHookNames.includes(specifier.imported.name)\n ) {\n // Track alias or direct import\n hookAliasMap[specifier.local.name] = specifier.imported.name\n }\n })\n }\n },\n\n VariableDeclarator(node) {\n if (\n node.init !== null &&\n node.init.type === AST_NODE_TYPES.CallExpression &&\n node.init.callee.type === AST_NODE_TYPES.Identifier &&\n allHookNames.includes(node.init.callee.name)\n ) {\n collectVariableNames(node.id, node.init.callee.name)\n }\n },\n CallExpression: (node) => {\n const reactHook = getReactHook(node)\n if (\n reactHook !== undefined &&\n node.arguments.length > 1 &&\n node.arguments[1]?.type === AST_NODE_TYPES.ArrayExpression\n ) {\n const depsArray = node.arguments[1].elements\n depsArray.forEach((dep) => {\n if (\n dep !== null &&\n dep.type === AST_NODE_TYPES.Identifier &&\n trackedVariables[dep.name] !== undefined\n ) {\n const queryHook = trackedVariables[dep.name]\n context.report({\n node: dep,\n messageId: 'noUnstableDeps',\n data: {\n queryHook,\n reactHook,\n },\n })\n }\n })\n }\n },\n }\n }),\n})\n"],"names":[],"mappings":";;;AAMO,MAAM,OAAO;AAEb,MAAM,iBAAiB,CAAC,aAAa,eAAe,SAAS;AAC7D,MAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,MAAM,eAAe,CAAC,eAAe,GAAG,iBAAiB;AACzD,MAAM,aAAa,YAAY,YAA2B,UAAU;AAE7D,MAAM,OAAO,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aACE;AAAA,MACF,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,gBAAgB;AAAA,IAClB;AAAA,IACA,QAAQ,CAAA;AAAA,EACV;AAAA,EACA,gBAAgB,CAAC;AAAA,EAEjB,QAAQ,2BAA2B,CAAC,YAAY;AAC9C,UAAM,mBAA2C,CAAC;AAClD,UAAM,eAAuC,CAAC;AAE9C,aAAS,aAAa,MAAmD;AACnE,UAAA,KAAK,OAAO,SAAS,cAAc;AAC/B,cAAA,aAAa,KAAK,OAAO;AAE/B,YAAI,eAAe,SAAS,UAAU,KAAK,cAAc,cAAc;AAC9D,iBAAA;AAAA,QAAA;AAAA,MAEX,WACE,KAAK,OAAO,SAAS,sBACrB,KAAK,OAAO,OAAO,SAAS,gBAC5B,KAAK,OAAO,OAAO,SAAS,WAC5B,KAAK,OAAO,SAAS,SAAS,gBAC9B,eAAe,SAAS,KAAK,OAAO,SAAS,IAAI,GACjD;AAEO,eAAA,KAAK,OAAO,SAAS;AAAA,MAAA;AAEvB,aAAA;AAAA,IAAA;AAGA,aAAA,qBACP,SACA,WACA;AACI,UAAA,QAAQ,SAAS,eAAe,YAAY;AAC7B,yBAAA,QAAQ,IAAI,IAAI;AAAA,MAAA;AAAA,IACnC;AAGK,WAAA;AAAA,MACL,kBAAkB,MAAkC;AAEhD,YAAA,KAAK,WAAW,SAAS,KACzB,KAAK,eAAe,WACpB,KAAK,OAAO,UAAU,SACtB;AACK,eAAA,WAAW,QAAQ,CAAC,cAAc;AACrC,gBACE,UAAU,SAAS,eAAe,mBAClC,UAAU,SAAS,SAAS,eAAe,cAC3C,eAAe,SAAS,UAAU,SAAS,IAAI,GAC/C;AAEA,2BAAa,UAAU,MAAM,IAAI,IAAI,UAAU,SAAS;AAAA,YAAA;AAAA,UAC1D,CACD;AAAA,QAAA;AAAA,MAEL;AAAA,MAEA,mBAAmB,MAAM;AAErB,YAAA,KAAK,SAAS,QACd,KAAK,KAAK,SAAS,eAAe,kBAClC,KAAK,KAAK,OAAO,SAAS,eAAe,cACzC,aAAa,SAAS,KAAK,KAAK,OAAO,IAAI,GAC3C;AACA,+BAAqB,KAAK,IAAI,KAAK,KAAK,OAAO,IAAI;AAAA,QAAA;AAAA,MAEvD;AAAA,MACA,gBAAgB,CAAC,SAAS;;AAClB,cAAA,YAAY,aAAa,IAAI;AACnC,YACE,cAAc,UACd,KAAK,UAAU,SAAS,OACxB,UAAK,UAAU,CAAC,MAAhB,mBAAmB,UAAS,eAAe,iBAC3C;AACA,gBAAM,YAAY,KAAK,UAAU,CAAC,EAAE;AAC1B,oBAAA,QAAQ,CAAC,QAAQ;AAEvB,gBAAA,QAAQ,QACR,IAAI,SAAS,eAAe,cAC5B,iBAAiB,IAAI,IAAI,MAAM,QAC/B;AACM,oBAAA,YAAY,iBAAiB,IAAI,IAAI;AAC3C,sBAAQ,OAAO;AAAA,gBACb,MAAM;AAAA,gBACN,WAAW;AAAA,gBACX,MAAM;AAAA,kBACJ;AAAA,kBACA;AAAA,gBAAA;AAAA,cACF,CACD;AAAA,YAAA;AAAA,UACH,CACD;AAAA,QAAA;AAAA,MACH;AAAA,IAEJ;AAAA,EACD,CAAA;AACH,CAAC;"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
import { ExtraRuleDocs } from '../../types';
|
|
3
|
-
export declare const name = "stable-query-client";
|
|
4
|
-
export declare const rule: ESLintUtils.RuleModule<string, readonly unknown[], ExtraRuleDocs, ESLintUtils.RuleListener>;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
-
import { ASTUtils } from "../../utils/ast-utils.js";
|
|
3
|
-
import { getDocsUrl } from "../../utils/get-docs-url.js";
|
|
4
|
-
import { detectTanstackQueryImports } from "../../utils/detect-react-query-imports.js";
|
|
5
|
-
const name = "stable-query-client";
|
|
6
|
-
const createRule = ESLintUtils.RuleCreator(getDocsUrl);
|
|
7
|
-
const rule = 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: detectTanstackQueryImports((context, _, helpers) => {
|
|
28
|
-
return {
|
|
29
|
-
NewExpression: (node) => {
|
|
30
|
-
if (node.callee.type !== AST_NODE_TYPES.Identifier || node.callee.name !== "QueryClient" || node.parent.type !== AST_NODE_TYPES.VariableDeclarator || !helpers.isSpecificTanstackQueryImport(
|
|
31
|
-
node.callee,
|
|
32
|
-
"@tanstack/react-query"
|
|
33
|
-
)) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const fnAncestor = ASTUtils.getFunctionAncestor(
|
|
37
|
-
context.sourceCode,
|
|
38
|
-
node
|
|
39
|
-
);
|
|
40
|
-
const isReactServerComponent = (fnAncestor == null ? void 0 : fnAncestor.async) === true;
|
|
41
|
-
if (!ASTUtils.isValidReactComponentOrHookName(fnAncestor == null ? void 0 : fnAncestor.id) || isReactServerComponent) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
context.report({
|
|
45
|
-
node: node.parent,
|
|
46
|
-
messageId: "unstable",
|
|
47
|
-
fix: (() => {
|
|
48
|
-
const { parent } = node;
|
|
49
|
-
if (parent.id.type !== AST_NODE_TYPES.Identifier) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
53
|
-
const nodeText = sourceCode.getText(node);
|
|
54
|
-
const variableName = parent.id.name;
|
|
55
|
-
return (fixer) => {
|
|
56
|
-
return fixer.replaceTextRange(
|
|
57
|
-
[parent.range[0], parent.range[1]],
|
|
58
|
-
`[${variableName}] = React.useState(() => ${nodeText})`
|
|
59
|
-
);
|
|
60
|
-
};
|
|
61
|
-
})()
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
})
|
|
66
|
-
});
|
|
67
|
-
export {
|
|
68
|
-
name,
|
|
69
|
-
rule
|
|
70
|
-
};
|
|
71
|
-
//# sourceMappingURL=stable-query-client.rule.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stable-query-client.rule.js","sources":["../../../../src/rules/stable-query-client/stable-query-client.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\nimport { ASTUtils } from '../../utils/ast-utils'\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'\nimport type { TSESLint } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nexport const name = 'stable-query-client'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\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: detectTanstackQueryImports((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(\n context.sourceCode,\n node,\n )\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 // we need the fallbacks for backwards compat with eslint < 8.37.0\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const sourceCode = context.sourceCode ?? context.getSourceCode()\n const nodeText = sourceCode.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":[],"mappings":";;;;AAOO,MAAM,OAAO;AAEpB,MAAM,aAAa,YAAY,YAA2B,UAAU;AAE7D,MAAM,OAAO,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,CAAA;AAAA,EACV;AAAA,EACA,gBAAgB,CAAC;AAAA,EAEjB,QAAQ,2BAA2B,CAAC,SAAS,GAAG,YAAY;AACnD,WAAA;AAAA,MACL,eAAe,CAAC,SAAS;AACvB,YACE,KAAK,OAAO,SAAS,eAAe,cACpC,KAAK,OAAO,SAAS,iBACrB,KAAK,OAAO,SAAS,eAAe,sBACpC,CAAC,QAAQ;AAAA,UACP,KAAK;AAAA,UACL;AAAA,QAAA,GAEF;AACA;AAAA,QAAA;AAGF,cAAM,aAAa,SAAS;AAAA,UAC1B,QAAQ;AAAA,UACR;AAAA,QACF;AACM,cAAA,0BAAyB,yCAAY,WAAU;AAErD,YACE,CAAC,SAAS,gCAAgC,yCAAY,EAAE,KACxD,wBACA;AACA;AAAA,QAAA;AAGF,gBAAQ,OAAO;AAAA,UACb,MAAM,KAAK;AAAA,UACX,WAAW;AAAA,UACX,MAAM,MAAM;AACJ,kBAAA,EAAE,WAAW;AAEnB,gBAAI,OAAO,GAAG,SAAS,eAAe,YAAY;AAChD;AAAA,YAAA;AAKF,kBAAM,aAAa,QAAQ,cAAc,QAAQ,cAAc;AACzD,kBAAA,WAAW,WAAW,QAAQ,IAAI;AAClC,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,cACtD;AAAA,YACF;AAAA,UACC,GAAA;AAAA,QAAA,CACJ;AAAA,MAAA;AAAA,IAEL;AAAA,EACD,CAAA;AACH,CAAC;"}
|
package/dist/esm/rules.d.ts
DELETED
package/dist/esm/rules.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { rule as rule$4, name as name$4 } from "./rules/exhaustive-deps/exhaustive-deps.rule.js";
|
|
2
|
-
import { rule as rule$3, name as name$3 } from "./rules/stable-query-client/stable-query-client.rule.js";
|
|
3
|
-
import { rule as rule$2, name as name$2 } from "./rules/no-rest-destructuring/no-rest-destructuring.rule.js";
|
|
4
|
-
import { rule as rule$1, name as name$1 } from "./rules/no-unstable-deps/no-unstable-deps.rule.js";
|
|
5
|
-
import { rule, name } from "./rules/infinite-query-property-order/infinite-query-property-order.rule.js";
|
|
6
|
-
const rules = {
|
|
7
|
-
[name$4]: rule$4,
|
|
8
|
-
[name$3]: rule$3,
|
|
9
|
-
[name$2]: rule$2,
|
|
10
|
-
[name$1]: rule$1,
|
|
11
|
-
[name]: rule
|
|
12
|
-
};
|
|
13
|
-
export {
|
|
14
|
-
rules
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=rules.js.map
|
package/dist/esm/rules.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sources":["../../src/rules.ts"],"sourcesContent":["import * as exhaustiveDeps from './rules/exhaustive-deps/exhaustive-deps.rule'\nimport * as stableQueryClient from './rules/stable-query-client/stable-query-client.rule'\nimport * as noRestDestructuring from './rules/no-rest-destructuring/no-rest-destructuring.rule'\nimport * as noUnstableDeps from './rules/no-unstable-deps/no-unstable-deps.rule'\nimport * as infiniteQueryPropertyOrder from './rules/infinite-query-property-order/infinite-query-property-order.rule'\nimport type { ESLintUtils } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from './types'\n\nexport const rules: Record<\n string,\n ESLintUtils.RuleModule<\n string,\n ReadonlyArray<unknown>,\n ExtraRuleDocs,\n ESLintUtils.RuleListener\n >\n> = {\n [exhaustiveDeps.name]: exhaustiveDeps.rule,\n [stableQueryClient.name]: stableQueryClient.rule,\n [noRestDestructuring.name]: noRestDestructuring.rule,\n [noUnstableDeps.name]: noUnstableDeps.rule,\n [infiniteQueryPropertyOrder.name]: infiniteQueryPropertyOrder.rule,\n}\n"],"names":["exhaustiveDeps.name","exhaustiveDeps.rule","stableQueryClient.name","stableQueryClient.rule","noRestDestructuring.name","noRestDestructuring.rule","noUnstableDeps.name","noUnstableDeps.rule","infiniteQueryPropertyOrder.name","infiniteQueryPropertyOrder.rule"],"mappings":";;;;;AAQO,MAAM,QAQT;AAAA,EACF,CAACA,MAAmB,GAAGC;AAAAA,EACvB,CAACC,MAAsB,GAAGC;AAAAA,EAC1B,CAACC,MAAwB,GAAGC;AAAAA,EAC5B,CAACC,MAAmB,GAAGC;AAAAA,EACvB,CAACC,IAA+B,GAAGC;AACrC;"}
|