@blumintinc/eslint-plugin-blumint 1.20.65 → 1.20.66
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/lib/index.js
CHANGED
|
@@ -655,10 +655,50 @@ exports.enforceFirestoreDocRefGeneric = (0, createRule_1.createRule)({
|
|
|
655
655
|
return tracesToRulesUnitTesting(node.expression, visited);
|
|
656
656
|
case utils_1.AST_NODE_TYPES.Identifier:
|
|
657
657
|
return identifierTracesToRulesUnitTesting(node, visited);
|
|
658
|
+
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
|
|
659
|
+
case utils_1.AST_NODE_TYPES.FunctionExpression:
|
|
660
|
+
case utils_1.AST_NODE_TYPES.FunctionDeclaration:
|
|
661
|
+
return functionReturnTracesToRulesUnitTesting(node, visited);
|
|
658
662
|
default:
|
|
659
663
|
return false;
|
|
660
664
|
}
|
|
661
665
|
}
|
|
666
|
+
/**
|
|
667
|
+
* Reached when a receiver is the result of calling a local helper, so what
|
|
668
|
+
* the helper hands back decides the surface. Only top-level returns are
|
|
669
|
+
* read; a return nested inside another function belongs to that one.
|
|
670
|
+
*/
|
|
671
|
+
function functionReturnTracesToRulesUnitTesting(node, visited) {
|
|
672
|
+
if (node.body.type !== utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
673
|
+
return tracesToRulesUnitTesting(node.body, visited);
|
|
674
|
+
}
|
|
675
|
+
return node.body.body.some((statement) => statement.type === utils_1.AST_NODE_TYPES.ReturnStatement &&
|
|
676
|
+
tracesToRulesUnitTesting(statement.argument, visited));
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* `withSecurityRulesDisabled` is the one API here that delivers a context
|
|
680
|
+
* through a callback rather than a return value, and the documented spelling
|
|
681
|
+
* leaves the parameter unannotated, so the call it belongs to is the only
|
|
682
|
+
* evidence of the surface.
|
|
683
|
+
*/
|
|
684
|
+
const CONTEXT_CALLBACK_METHOD = 'withSecurityRulesDisabled';
|
|
685
|
+
function parameterTracesToRulesUnitTesting(name, owner, visited) {
|
|
686
|
+
if (name.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
687
|
+
name.typeAnnotation &&
|
|
688
|
+
isRulesUnitTestingType(name.typeAnnotation.typeAnnotation)) {
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
691
|
+
const call = owner.parent;
|
|
692
|
+
if (!call ||
|
|
693
|
+
call.type !== utils_1.AST_NODE_TYPES.CallExpression ||
|
|
694
|
+
!call.arguments.includes(owner) ||
|
|
695
|
+
call.callee.type !== utils_1.AST_NODE_TYPES.MemberExpression ||
|
|
696
|
+
call.callee.property.type !== utils_1.AST_NODE_TYPES.Identifier ||
|
|
697
|
+
call.callee.property.name !== CONTEXT_CALLBACK_METHOD) {
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
return tracesToRulesUnitTesting(call.callee.object, visited);
|
|
701
|
+
}
|
|
662
702
|
function identifierTracesToRulesUnitTesting(node, visited) {
|
|
663
703
|
const scope = ASTHelpers_1.ASTHelpers.getScope(context, node);
|
|
664
704
|
const variable = ASTHelpers_1.ASTHelpers.findVariableInScope(scope, node.name);
|
|
@@ -670,24 +710,36 @@ exports.enforceFirestoreDocRefGeneric = (0, createRule_1.createRule)({
|
|
|
670
710
|
return (def.parent?.type === utils_1.AST_NODE_TYPES.ImportDeclaration &&
|
|
671
711
|
def.parent.source.value === RULES_UNIT_TESTING_MODULE);
|
|
672
712
|
}
|
|
673
|
-
// Covers the `withSecurityRulesDisabled(async (ctx: RulesTestContext) =>
|
|
674
|
-
// ...)` callback, where the compat handle never appears as an initializer.
|
|
675
713
|
if (def.type === 'Parameter') {
|
|
676
|
-
|
|
677
|
-
|
|
714
|
+
return parameterTracesToRulesUnitTesting(def.name, def.node, visited);
|
|
715
|
+
}
|
|
716
|
+
// A hoisted declaration binds the helper the same way a `const` arrow
|
|
717
|
+
// does; an ambient `declare function` has no body and falls through.
|
|
718
|
+
if (def.type === 'FunctionName') {
|
|
719
|
+
return tracesToRulesUnitTesting(def.node, visited);
|
|
678
720
|
}
|
|
679
721
|
if (def.type !== 'Variable' ||
|
|
680
|
-
def.node.type !== utils_1.AST_NODE_TYPES.VariableDeclarator
|
|
681
|
-
def.parent?.type !== utils_1.AST_NODE_TYPES.VariableDeclaration ||
|
|
682
|
-
def.parent.kind !== 'const') {
|
|
722
|
+
def.node.type !== utils_1.AST_NODE_TYPES.VariableDeclarator) {
|
|
683
723
|
return false;
|
|
684
724
|
}
|
|
685
725
|
const declarator = def.node;
|
|
726
|
+
// An annotation constrains every assignment rather than just the
|
|
727
|
+
// initializer, so unlike an initializer it survives a `let`. The
|
|
728
|
+
// environment handle is created in `beforeAll` and so cannot be `const`;
|
|
729
|
+
// `let testEnv: RulesTestEnvironment` is the documented spelling, and
|
|
730
|
+
// TypeScript refuses to put another surface in it.
|
|
686
731
|
if (declarator.id.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
687
732
|
declarator.id.typeAnnotation &&
|
|
688
733
|
isRulesUnitTestingType(declarator.id.typeAnnotation.typeAnnotation)) {
|
|
689
734
|
return true;
|
|
690
735
|
}
|
|
736
|
+
// Without that guarantee only a `const` initializer is followed, mirroring
|
|
737
|
+
// `isTypedCollectionBinding`: an unannotated reassignable binding can hold
|
|
738
|
+
// an Admin SDK handle by the time it reaches `.doc()`.
|
|
739
|
+
if (def.parent?.type !== utils_1.AST_NODE_TYPES.VariableDeclaration ||
|
|
740
|
+
def.parent.kind !== 'const') {
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
691
743
|
return tracesToRulesUnitTesting(declarator.init, visited);
|
|
692
744
|
}
|
|
693
745
|
return {
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.66",
|
|
4
|
+
"date": "2026-08-01T13:53:31.680Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "enforce-firestore-doc-ref-generic",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
1564
|
|
11
|
+
],
|
|
12
|
+
"summary": "trace compat receivers through annotated lets and seeding callbacks (closes #1564)"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
2
16
|
{
|
|
3
17
|
"version": "1.20.65",
|
|
4
18
|
"date": "2026-08-01T13:35:40.762Z",
|