@tanstack/eslint-plugin-query 5.94.5 → 5.95.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/build/legacy/_tsup-dts-rollup.d.cts +57 -3
- package/build/legacy/_tsup-dts-rollup.d.ts +57 -3
- package/build/legacy/{chunk-HD2KSEKJ.js → chunk-T44AUBX4.js} +289 -90
- package/build/legacy/chunk-T44AUBX4.js.map +1 -0
- package/build/legacy/index.cjs +288 -89
- package/build/legacy/index.cjs.map +1 -1
- package/build/legacy/index.js +1 -1
- package/build/legacy/rules.cjs +288 -89
- package/build/legacy/rules.cjs.map +1 -1
- package/build/legacy/rules.js +1 -1
- package/build/modern/_tsup-dts-rollup.d.cts +57 -3
- package/build/modern/_tsup-dts-rollup.d.ts +57 -3
- package/build/modern/{chunk-XO2SGL7P.js → chunk-XH4ABCYA.js} +288 -90
- package/build/modern/chunk-XH4ABCYA.js.map +1 -0
- package/build/modern/index.cjs +287 -89
- package/build/modern/index.cjs.map +1 -1
- package/build/modern/index.js +1 -1
- package/build/modern/rules.cjs +287 -89
- package/build/modern/rules.cjs.map +1 -1
- package/build/modern/rules.js +1 -1
- package/package.json +1 -1
- package/src/rules/exhaustive-deps/exhaustive-deps.rule.ts +136 -90
- package/src/rules/exhaustive-deps/exhaustive-deps.utils.ts +248 -22
- package/src/utils/ast-utils.ts +2 -25
- package/build/legacy/chunk-HD2KSEKJ.js.map +0 -1
- package/build/modern/chunk-XO2SGL7P.js.map +0 -1
|
@@ -104,21 +104,6 @@ var ASTUtils = {
|
|
|
104
104
|
}
|
|
105
105
|
return identifiers;
|
|
106
106
|
},
|
|
107
|
-
isAncestorIsCallee(identifier) {
|
|
108
|
-
let previousNode = identifier;
|
|
109
|
-
let currentNode = identifier.parent;
|
|
110
|
-
while (currentNode !== void 0) {
|
|
111
|
-
if (currentNode.type === AST_NODE_TYPES.CallExpression && currentNode.callee === previousNode) {
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
if (currentNode.type !== AST_NODE_TYPES.MemberExpression) {
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
previousNode = currentNode;
|
|
118
|
-
currentNode = currentNode.parent;
|
|
119
|
-
}
|
|
120
|
-
return false;
|
|
121
|
-
},
|
|
122
107
|
traverseUpOnly(identifier, allowedNodeTypes) {
|
|
123
108
|
const parent = identifier.parent;
|
|
124
109
|
if (parent !== void 0 && allowedNodeTypes.includes(parent.type)) {
|
|
@@ -339,7 +324,7 @@ var ExhaustiveDepsUtils = {
|
|
|
339
324
|
const { sourceCode, reference, scopeManager, node, filename } = params;
|
|
340
325
|
const component = ASTUtils.getFunctionAncestor(sourceCode, node);
|
|
341
326
|
const queryFnScope = scopeManager.acquire(node);
|
|
342
|
-
if (queryFnScope === null) {
|
|
327
|
+
if (queryFnScope === null || reference.isValueReference === false) {
|
|
343
328
|
return false;
|
|
344
329
|
}
|
|
345
330
|
let currentScope = reference.resolved?.scope ?? null;
|
|
@@ -371,15 +356,57 @@ var ExhaustiveDepsUtils = {
|
|
|
371
356
|
}
|
|
372
357
|
return reference.identifier.name !== "undefined" && reference.identifier.parent.type !== AST_NODE_TYPES2.NewExpression && !ExhaustiveDepsUtils.isInstanceOfKind(reference.identifier.parent);
|
|
373
358
|
},
|
|
374
|
-
|
|
375
|
-
|
|
359
|
+
/**
|
|
360
|
+
* Given required refs and existing queryKey entries, compute missing dependency paths
|
|
361
|
+
* respecting allowlisted variables and types.
|
|
362
|
+
*/
|
|
363
|
+
computeFilteredMissingPaths(params) {
|
|
364
|
+
const {
|
|
365
|
+
requiredRefs,
|
|
366
|
+
allowlistedVariables,
|
|
367
|
+
existingRootIdentifiers,
|
|
368
|
+
existingFullPaths
|
|
369
|
+
} = params;
|
|
370
|
+
const missingPaths = /* @__PURE__ */ new Set();
|
|
371
|
+
for (const { root, path, allowlistedByType } of requiredRefs) {
|
|
372
|
+
if (existingRootIdentifiers.has(root)) continue;
|
|
373
|
+
if (allowlistedVariables.has(root)) continue;
|
|
374
|
+
if (existingFullPaths.has(path)) continue;
|
|
375
|
+
if (allowlistedByType) continue;
|
|
376
|
+
missingPaths.add(path);
|
|
377
|
+
}
|
|
378
|
+
for (const path of missingPaths) {
|
|
379
|
+
const root = path.split(".")[0];
|
|
380
|
+
if (root !== path && root !== void 0 && missingPaths.has(root)) {
|
|
381
|
+
missingPaths.delete(path);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return Array.from(missingPaths);
|
|
376
385
|
},
|
|
386
|
+
/**
|
|
387
|
+
* Extract existing queryKey deps as root identifiers and full member paths.
|
|
388
|
+
*/
|
|
377
389
|
collectQueryKeyDeps(params) {
|
|
378
390
|
const { sourceCode, scopeManager, queryKeyNode } = params;
|
|
379
|
-
const
|
|
391
|
+
const roots = /* @__PURE__ */ new Set();
|
|
392
|
+
const paths = /* @__PURE__ */ new Set();
|
|
380
393
|
const visitorKeys = sourceCode.visitorKeys;
|
|
381
|
-
function
|
|
382
|
-
|
|
394
|
+
function addRoot(name8) {
|
|
395
|
+
const cleaned = ExhaustiveDepsUtils.normalizeChain(name8);
|
|
396
|
+
roots.add(cleaned);
|
|
397
|
+
paths.add(cleaned);
|
|
398
|
+
}
|
|
399
|
+
function addFull(text) {
|
|
400
|
+
const cleaned = ExhaustiveDepsUtils.normalizeChain(text);
|
|
401
|
+
paths.add(cleaned);
|
|
402
|
+
}
|
|
403
|
+
function addRefPath(refPath) {
|
|
404
|
+
if (!refPath) return;
|
|
405
|
+
if (refPath.coversRootMembers) {
|
|
406
|
+
addRoot(refPath.root);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
addFull(refPath.path);
|
|
383
410
|
}
|
|
384
411
|
function visitChildren(node) {
|
|
385
412
|
const keys = visitorKeys[node.type] ?? [];
|
|
@@ -401,9 +428,15 @@ var ExhaustiveDepsUtils = {
|
|
|
401
428
|
function visit(node) {
|
|
402
429
|
if (!node) return;
|
|
403
430
|
switch (node.type) {
|
|
404
|
-
case AST_NODE_TYPES2.Identifier:
|
|
405
|
-
|
|
431
|
+
case AST_NODE_TYPES2.Identifier: {
|
|
432
|
+
addRefPath(
|
|
433
|
+
ExhaustiveDepsUtils.computeRefPath({
|
|
434
|
+
identifier: node,
|
|
435
|
+
sourceCode
|
|
436
|
+
})
|
|
437
|
+
);
|
|
406
438
|
return;
|
|
439
|
+
}
|
|
407
440
|
case AST_NODE_TYPES2.ArrowFunctionExpression:
|
|
408
441
|
case AST_NODE_TYPES2.FunctionExpression:
|
|
409
442
|
for (const reference of ExhaustiveDepsUtils.collectExternalRefsInFunction(
|
|
@@ -412,9 +445,15 @@ var ExhaustiveDepsUtils = {
|
|
|
412
445
|
scopeManager
|
|
413
446
|
}
|
|
414
447
|
)) {
|
|
415
|
-
if (reference.identifier.type
|
|
416
|
-
|
|
448
|
+
if (reference.identifier.type !== AST_NODE_TYPES2.Identifier) {
|
|
449
|
+
continue;
|
|
417
450
|
}
|
|
451
|
+
addRefPath(
|
|
452
|
+
ExhaustiveDepsUtils.computeRefPath({
|
|
453
|
+
identifier: reference.identifier,
|
|
454
|
+
sourceCode
|
|
455
|
+
})
|
|
456
|
+
);
|
|
418
457
|
}
|
|
419
458
|
return;
|
|
420
459
|
case AST_NODE_TYPES2.Property:
|
|
@@ -422,26 +461,96 @@ var ExhaustiveDepsUtils = {
|
|
|
422
461
|
return;
|
|
423
462
|
case AST_NODE_TYPES2.MemberExpression:
|
|
424
463
|
if (node.parent.type === AST_NODE_TYPES2.CallExpression && node.parent.callee === node && node.object.type === AST_NODE_TYPES2.Identifier) {
|
|
425
|
-
|
|
464
|
+
addRoot(node.object.name);
|
|
426
465
|
} else {
|
|
427
466
|
visit(node.object);
|
|
428
467
|
}
|
|
429
468
|
return;
|
|
430
469
|
case AST_NODE_TYPES2.CallExpression:
|
|
431
470
|
node.arguments.forEach((argument) => visit(argument));
|
|
432
|
-
|
|
433
|
-
|
|
471
|
+
switch (node.callee.type) {
|
|
472
|
+
case AST_NODE_TYPES2.Identifier:
|
|
473
|
+
case AST_NODE_TYPES2.MemberExpression:
|
|
474
|
+
case AST_NODE_TYPES2.ChainExpression:
|
|
475
|
+
case AST_NODE_TYPES2.TSNonNullExpression:
|
|
476
|
+
visit(node.callee);
|
|
477
|
+
break;
|
|
434
478
|
}
|
|
435
479
|
return;
|
|
436
480
|
}
|
|
437
481
|
visitChildren(node);
|
|
438
482
|
}
|
|
439
483
|
visit(queryKeyNode);
|
|
440
|
-
return
|
|
484
|
+
return { roots, paths };
|
|
441
485
|
},
|
|
442
486
|
isNode(value) {
|
|
443
487
|
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
|
|
444
488
|
},
|
|
489
|
+
/**
|
|
490
|
+
* Checks whether the resolved variable is allowlisted by its type annotation
|
|
491
|
+
*/
|
|
492
|
+
variableIsAllowlistedByType(params) {
|
|
493
|
+
const { allowlistedTypes, variable } = params;
|
|
494
|
+
if (allowlistedTypes.size === 0) return false;
|
|
495
|
+
if (!variable) return false;
|
|
496
|
+
for (const id of variable.identifiers) {
|
|
497
|
+
if (id.typeAnnotation) {
|
|
498
|
+
const typeIdentifiers = /* @__PURE__ */ new Set();
|
|
499
|
+
ExhaustiveDepsUtils.collectTypeIdentifiers(
|
|
500
|
+
id.typeAnnotation.typeAnnotation,
|
|
501
|
+
typeIdentifiers
|
|
502
|
+
);
|
|
503
|
+
for (const typeIdentifier of typeIdentifiers) {
|
|
504
|
+
if (allowlistedTypes.has(typeIdentifier)) return true;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return false;
|
|
509
|
+
},
|
|
510
|
+
isInstanceOfKind(node) {
|
|
511
|
+
return node.type === AST_NODE_TYPES2.BinaryExpression && node.operator === "instanceof";
|
|
512
|
+
},
|
|
513
|
+
/**
|
|
514
|
+
* Normalizes a chain by removing optional chaining operators
|
|
515
|
+
*
|
|
516
|
+
* Example: `a?.b.c!` -> `a.b.c`
|
|
517
|
+
*/
|
|
518
|
+
normalizeChain(text) {
|
|
519
|
+
return text.replace(/(?:\?(\.)|!)/g, "$1");
|
|
520
|
+
},
|
|
521
|
+
/**
|
|
522
|
+
* Computes the reference path for an identifier
|
|
523
|
+
*
|
|
524
|
+
* Example: `a.b.c!` -> `{ path: 'a.b.c', root: 'a' }`
|
|
525
|
+
*/
|
|
526
|
+
computeRefPath(params) {
|
|
527
|
+
const { identifier, sourceCode } = params;
|
|
528
|
+
const fullChainNode = ASTUtils.traverseUpOnly(identifier, [
|
|
529
|
+
AST_NODE_TYPES2.MemberExpression,
|
|
530
|
+
AST_NODE_TYPES2.TSNonNullExpression,
|
|
531
|
+
AST_NODE_TYPES2.Identifier
|
|
532
|
+
]);
|
|
533
|
+
const fullText = ExhaustiveDepsUtils.normalizeChain(
|
|
534
|
+
sourceCode.getText(fullChainNode)
|
|
535
|
+
);
|
|
536
|
+
const parent = fullChainNode.parent;
|
|
537
|
+
let dependencyPath = fullText;
|
|
538
|
+
let coversRootMembers = fullText === identifier.name;
|
|
539
|
+
if (parent && parent.type === AST_NODE_TYPES2.CallExpression && parent.callee === fullChainNode) {
|
|
540
|
+
const segments = fullText.split(".");
|
|
541
|
+
if (segments.length > 1) {
|
|
542
|
+
dependencyPath = segments.slice(0, -1).join(".");
|
|
543
|
+
}
|
|
544
|
+
coversRootMembers = false;
|
|
545
|
+
}
|
|
546
|
+
dependencyPath = dependencyPath.split(".")[0] === "" ? identifier.name : dependencyPath;
|
|
547
|
+
const root = dependencyPath.split(".")[0];
|
|
548
|
+
return {
|
|
549
|
+
path: dependencyPath,
|
|
550
|
+
root: root ?? identifier.name,
|
|
551
|
+
coversRootMembers: coversRootMembers && dependencyPath === root
|
|
552
|
+
};
|
|
553
|
+
},
|
|
445
554
|
collectExternalRefsInFunction(params) {
|
|
446
555
|
const { functionNode, scopeManager } = params;
|
|
447
556
|
const functionScope = scopeManager.acquire(functionNode);
|
|
@@ -473,6 +582,52 @@ var ExhaustiveDepsUtils = {
|
|
|
473
582
|
}
|
|
474
583
|
collect(functionScope);
|
|
475
584
|
return externalRefs;
|
|
585
|
+
},
|
|
586
|
+
/**
|
|
587
|
+
* Recursively collects type identifiers from a type annotation
|
|
588
|
+
*/
|
|
589
|
+
collectTypeIdentifiers(typeNode, out) {
|
|
590
|
+
switch (typeNode.type) {
|
|
591
|
+
case AST_NODE_TYPES2.TSTypeReference: {
|
|
592
|
+
if (typeNode.typeName.type === AST_NODE_TYPES2.Identifier) {
|
|
593
|
+
out.add(typeNode.typeName.name);
|
|
594
|
+
}
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
case AST_NODE_TYPES2.TSUnionType:
|
|
598
|
+
case AST_NODE_TYPES2.TSIntersectionType: {
|
|
599
|
+
typeNode.types.forEach(
|
|
600
|
+
(t) => ExhaustiveDepsUtils.collectTypeIdentifiers(t, out)
|
|
601
|
+
);
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
case AST_NODE_TYPES2.TSArrayType: {
|
|
605
|
+
ExhaustiveDepsUtils.collectTypeIdentifiers(typeNode.elementType, out);
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
case AST_NODE_TYPES2.TSTupleType: {
|
|
609
|
+
typeNode.elementTypes.forEach(
|
|
610
|
+
(et) => ExhaustiveDepsUtils.collectTypeIdentifiers(et, out)
|
|
611
|
+
);
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
/**
|
|
617
|
+
* Gets the function expression nodes from a queryFn property, handling conditional expressions.
|
|
618
|
+
* When neither branch is skipToken, returns both branches so all deps are scanned.
|
|
619
|
+
*/
|
|
620
|
+
getQueryFnNodes(queryFn) {
|
|
621
|
+
if (queryFn.value.type !== AST_NODE_TYPES2.ConditionalExpression) {
|
|
622
|
+
return [queryFn.value];
|
|
623
|
+
}
|
|
624
|
+
if (queryFn.value.consequent.type === AST_NODE_TYPES2.Identifier && queryFn.value.consequent.name === "skipToken") {
|
|
625
|
+
return [queryFn.value.alternate];
|
|
626
|
+
}
|
|
627
|
+
if (queryFn.value.alternate.type === AST_NODE_TYPES2.Identifier && queryFn.value.alternate.name === "skipToken") {
|
|
628
|
+
return [queryFn.value.consequent];
|
|
629
|
+
}
|
|
630
|
+
return [queryFn.value.consequent, queryFn.value.alternate];
|
|
476
631
|
}
|
|
477
632
|
};
|
|
478
633
|
|
|
@@ -495,22 +650,34 @@ var rule = createRule({
|
|
|
495
650
|
},
|
|
496
651
|
hasSuggestions: true,
|
|
497
652
|
fixable: "code",
|
|
498
|
-
schema: [
|
|
653
|
+
schema: [
|
|
654
|
+
{
|
|
655
|
+
type: "object",
|
|
656
|
+
properties: {
|
|
657
|
+
allowlist: {
|
|
658
|
+
type: "object",
|
|
659
|
+
properties: {
|
|
660
|
+
variables: { type: "array", items: { type: "string" } },
|
|
661
|
+
types: { type: "array", items: { type: "string" } }
|
|
662
|
+
},
|
|
663
|
+
additionalProperties: false
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
additionalProperties: false
|
|
667
|
+
}
|
|
668
|
+
]
|
|
499
669
|
},
|
|
500
670
|
defaultOptions: [],
|
|
501
671
|
create: detectTanstackQueryImports((context) => {
|
|
502
672
|
return {
|
|
503
|
-
|
|
504
|
-
if (!ASTUtils.isObjectExpression(node.parent) || !ASTUtils.isIdentifierWithName(node.key, QUERY_KEY)) {
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
673
|
+
ObjectExpression: (node) => {
|
|
507
674
|
const scopeManager = context.sourceCode.scopeManager;
|
|
508
675
|
const queryKey = ASTUtils.findPropertyWithIdentifierKey(
|
|
509
|
-
node.
|
|
676
|
+
node.properties,
|
|
510
677
|
QUERY_KEY
|
|
511
678
|
);
|
|
512
679
|
const queryFn = ASTUtils.findPropertyWithIdentifierKey(
|
|
513
|
-
node.
|
|
680
|
+
node.properties,
|
|
514
681
|
QUERY_FN
|
|
515
682
|
);
|
|
516
683
|
if (scopeManager === null || queryKey === void 0 || queryFn === void 0 || !ASTUtils.isNodeOfOneOf(queryFn.value, [
|
|
@@ -524,73 +691,104 @@ var rule = createRule({
|
|
|
524
691
|
queryKey.value,
|
|
525
692
|
context
|
|
526
693
|
);
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
node: getQueryFnRelevantNode(queryFn)
|
|
531
|
-
});
|
|
532
|
-
const relevantRefs = externalRefs.filter(
|
|
533
|
-
(reference) => ExhaustiveDepsUtils.isRelevantReference({
|
|
534
|
-
sourceCode: context.sourceCode,
|
|
535
|
-
reference,
|
|
694
|
+
const queryFnNodes = ExhaustiveDepsUtils.getQueryFnNodes(queryFn);
|
|
695
|
+
const externalRefs = queryFnNodes.flatMap(
|
|
696
|
+
(fnNode) => ASTUtils.getExternalRefs({
|
|
536
697
|
scopeManager,
|
|
537
|
-
|
|
538
|
-
|
|
698
|
+
sourceCode: context.sourceCode,
|
|
699
|
+
node: fnNode
|
|
539
700
|
})
|
|
540
701
|
);
|
|
702
|
+
const relevantRefs = externalRefs.filter(
|
|
703
|
+
(reference) => queryFnNodes.some(
|
|
704
|
+
(fnNode) => ExhaustiveDepsUtils.isRelevantReference({
|
|
705
|
+
sourceCode: context.sourceCode,
|
|
706
|
+
reference,
|
|
707
|
+
scopeManager,
|
|
708
|
+
node: fnNode,
|
|
709
|
+
filename: context.filename
|
|
710
|
+
})
|
|
711
|
+
)
|
|
712
|
+
);
|
|
713
|
+
const ruleOptions = context.options.at(0);
|
|
714
|
+
const allowlistedVariables = new Set(
|
|
715
|
+
ruleOptions?.allowlist?.variables ?? []
|
|
716
|
+
);
|
|
717
|
+
const allowlistedTypes = new Set(ruleOptions?.allowlist?.types ?? []);
|
|
718
|
+
const requiredRefs = relevantRefs.flatMap((ref) => {
|
|
719
|
+
if (ref.identifier.type !== AST_NODE_TYPES3.Identifier) return [];
|
|
720
|
+
const refPath = ExhaustiveDepsUtils.computeRefPath({
|
|
721
|
+
identifier: ref.identifier,
|
|
722
|
+
sourceCode: context.sourceCode
|
|
723
|
+
});
|
|
724
|
+
if (refPath === null) return [];
|
|
725
|
+
return [
|
|
726
|
+
{
|
|
727
|
+
...refPath,
|
|
728
|
+
allowlistedByType: ExhaustiveDepsUtils.variableIsAllowlistedByType({
|
|
729
|
+
allowlistedTypes,
|
|
730
|
+
variable: ref.resolved ?? null
|
|
731
|
+
})
|
|
732
|
+
}
|
|
733
|
+
];
|
|
734
|
+
});
|
|
735
|
+
if (requiredRefs.length === 0) return;
|
|
541
736
|
const queryKeyDeps = ExhaustiveDepsUtils.collectQueryKeyDeps({
|
|
542
737
|
sourceCode: context.sourceCode,
|
|
543
738
|
scopeManager,
|
|
544
739
|
queryKeyNode
|
|
545
740
|
});
|
|
546
|
-
const
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
messageId: "fixTo",
|
|
567
|
-
data: { result: existingWithMissing },
|
|
568
|
-
fix(fixer) {
|
|
569
|
-
return fixer.replaceText(queryKeyNode, existingWithMissing);
|
|
570
|
-
}
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
context.report({
|
|
574
|
-
node,
|
|
575
|
-
messageId: "missingDeps",
|
|
576
|
-
data: {
|
|
577
|
-
deps: uniqueMissingRefs.map((ref) => ref.text).join(", ")
|
|
578
|
-
},
|
|
579
|
-
suggest: suggestions
|
|
580
|
-
});
|
|
581
|
-
}
|
|
741
|
+
const missingPaths = ExhaustiveDepsUtils.computeFilteredMissingPaths({
|
|
742
|
+
requiredRefs,
|
|
743
|
+
allowlistedVariables,
|
|
744
|
+
existingRootIdentifiers: queryKeyDeps.roots,
|
|
745
|
+
existingFullPaths: queryKeyDeps.paths
|
|
746
|
+
});
|
|
747
|
+
if (missingPaths.length === 0) return;
|
|
748
|
+
const missingAsText = missingPaths.join(", ");
|
|
749
|
+
const suggestions = buildSuggestions({
|
|
750
|
+
queryKeyNode,
|
|
751
|
+
missingPaths,
|
|
752
|
+
missingAsText,
|
|
753
|
+
sourceCode: context.sourceCode
|
|
754
|
+
});
|
|
755
|
+
context.report({
|
|
756
|
+
node,
|
|
757
|
+
messageId: "missingDeps",
|
|
758
|
+
data: { deps: missingAsText },
|
|
759
|
+
suggest: suggestions
|
|
760
|
+
});
|
|
582
761
|
}
|
|
583
762
|
};
|
|
584
763
|
})
|
|
585
764
|
});
|
|
586
|
-
function
|
|
587
|
-
|
|
588
|
-
|
|
765
|
+
function buildSuggestions(params) {
|
|
766
|
+
const { queryKeyNode, missingPaths, missingAsText, sourceCode } = params;
|
|
767
|
+
if (queryKeyNode.type !== AST_NODE_TYPES3.ArrayExpression) {
|
|
768
|
+
return [];
|
|
589
769
|
}
|
|
590
|
-
|
|
591
|
-
|
|
770
|
+
const closingBracket = sourceCode.getLastToken(queryKeyNode);
|
|
771
|
+
if (!closingBracket) return [];
|
|
772
|
+
const existingElements = queryKeyNode.elements.filter((el) => el !== null).map((el) => sourceCode.getText(el));
|
|
773
|
+
const resultText = `[${[...existingElements, ...missingPaths].join(", ")}]`;
|
|
774
|
+
if (queryKeyNode.elements.length === 0) {
|
|
775
|
+
return [
|
|
776
|
+
{
|
|
777
|
+
messageId: "fixTo",
|
|
778
|
+
data: { result: resultText },
|
|
779
|
+
fix: (fixer) => fixer.replaceText(queryKeyNode, resultText)
|
|
780
|
+
}
|
|
781
|
+
];
|
|
592
782
|
}
|
|
593
|
-
|
|
783
|
+
const tokenBefore = sourceCode.getTokenBefore(closingBracket);
|
|
784
|
+
const separator = tokenBefore?.value === "," ? " " : ", ";
|
|
785
|
+
return [
|
|
786
|
+
{
|
|
787
|
+
messageId: "fixTo",
|
|
788
|
+
data: { result: resultText },
|
|
789
|
+
fix: (fixer) => fixer.insertTextBefore(closingBracket, `${separator}${missingAsText}`)
|
|
790
|
+
}
|
|
791
|
+
];
|
|
594
792
|
}
|
|
595
793
|
function dereferenceVariablesAndTypeAssertions(queryKeyNode, context) {
|
|
596
794
|
const visitedNodes = /* @__PURE__ */ new Set();
|
|
@@ -1134,4 +1332,4 @@ var rules = {
|
|
|
1134
1332
|
export {
|
|
1135
1333
|
rules
|
|
1136
1334
|
};
|
|
1137
|
-
//# sourceMappingURL=chunk-
|
|
1335
|
+
//# sourceMappingURL=chunk-XH4ABCYA.js.map
|