@blumintinc/eslint-plugin-blumint 1.20.77 → 1.20.78
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
|
@@ -34,6 +34,24 @@ exports.enforceFirestorePathUtils = (0, createRule_1.createRule)({
|
|
|
34
34
|
typeof node.value === 'string') ||
|
|
35
35
|
node.type === utils_1.AST_NODE_TYPES.TemplateLiteral);
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* A `+` chain qualifies as an inline path only when a string literal or
|
|
39
|
+
* template literal appears somewhere in it: that literal is the hard-coded
|
|
40
|
+
* path fragment the rule exists to push behind a helper. The walk recurses
|
|
41
|
+
* because `'teams/' + teamId + '/members'` parses as a left-nested
|
|
42
|
+
* BinaryExpression, which leaves the literals below the outermost operands.
|
|
43
|
+
* A chain of opaque operands (`a + b`) constructs no path fragment inline,
|
|
44
|
+
* so it keeps the same indirection allowance as a bare variable.
|
|
45
|
+
*/
|
|
46
|
+
function isInlinePathExpression(node) {
|
|
47
|
+
if (isStringLiteralOrTemplate(node)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return (node.type === utils_1.AST_NODE_TYPES.BinaryExpression &&
|
|
51
|
+
node.operator === '+' &&
|
|
52
|
+
(isInlinePathExpression(node.left) ||
|
|
53
|
+
isInlinePathExpression(node.right)));
|
|
54
|
+
}
|
|
37
55
|
function isUtilityFunction(node) {
|
|
38
56
|
if (node.type !== utils_1.AST_NODE_TYPES.CallExpression) {
|
|
39
57
|
return false;
|
|
@@ -59,8 +77,9 @@ exports.enforceFirestorePathUtils = (0, createRule_1.createRule)({
|
|
|
59
77
|
if (isUtilityFunction(pathArg)) {
|
|
60
78
|
return;
|
|
61
79
|
}
|
|
62
|
-
// Skip if it's a variable or other
|
|
63
|
-
|
|
80
|
+
// Skip if it's a variable or other expression that hides construction
|
|
81
|
+
// behind a name rather than assembling the path inline
|
|
82
|
+
if (!isInlinePathExpression(pathArg)) {
|
|
64
83
|
return;
|
|
65
84
|
}
|
|
66
85
|
// Skip test files
|
|
@@ -14,7 +14,7 @@ exports.enforceRealtimedbPathUtils = (0, createRule_1.createRule)({
|
|
|
14
14
|
},
|
|
15
15
|
schema: [],
|
|
16
16
|
messages: {
|
|
17
|
-
requirePathUtil: 'Use a utility function for Realtime Database paths to ensure type safety and maintainability. Instead of `ref(
|
|
17
|
+
requirePathUtil: 'Use a utility function for Realtime Database paths to ensure type safety and maintainability. Instead of `admin.database().ref(`users/${userId}`)`, create and use a utility function: `const toUserPath = (id: string) => `users/${id}`; admin.database().ref(toUserPath(userId))`.',
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
defaultOptions: [],
|
|
@@ -59,6 +59,24 @@ exports.enforceRealtimedbPathUtils = (0, createRule_1.createRule)({
|
|
|
59
59
|
typeof node.value === 'string') ||
|
|
60
60
|
node.type === utils_1.AST_NODE_TYPES.TemplateLiteral);
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* A `+` chain qualifies as an inline path only when a string literal or
|
|
64
|
+
* template literal appears somewhere in it: that literal is the hard-coded
|
|
65
|
+
* path fragment the rule exists to push behind a helper. The walk recurses
|
|
66
|
+
* because `'users/' + userId + '/posts'` parses as a left-nested
|
|
67
|
+
* BinaryExpression, which leaves the literals below the outermost operands.
|
|
68
|
+
* A chain of opaque operands (`a + b`) constructs no path fragment inline,
|
|
69
|
+
* so it keeps the same indirection allowance as a bare variable.
|
|
70
|
+
*/
|
|
71
|
+
function isInlinePathExpression(node) {
|
|
72
|
+
if (isStringLiteralOrTemplate(node)) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return (node.type === utils_1.AST_NODE_TYPES.BinaryExpression &&
|
|
76
|
+
node.operator === '+' &&
|
|
77
|
+
(isInlinePathExpression(node.left) ||
|
|
78
|
+
isInlinePathExpression(node.right)));
|
|
79
|
+
}
|
|
62
80
|
function isUtilityFunction(node) {
|
|
63
81
|
if (node.type !== utils_1.AST_NODE_TYPES.CallExpression) {
|
|
64
82
|
return false;
|
|
@@ -84,8 +102,9 @@ exports.enforceRealtimedbPathUtils = (0, createRule_1.createRule)({
|
|
|
84
102
|
if (isUtilityFunction(pathArg)) {
|
|
85
103
|
return;
|
|
86
104
|
}
|
|
87
|
-
// Skip if it's a variable or other
|
|
88
|
-
|
|
105
|
+
// Skip if it's a variable or other expression that hides construction
|
|
106
|
+
// behind a name rather than assembling the path inline
|
|
107
|
+
if (!isInlinePathExpression(pathArg)) {
|
|
89
108
|
return;
|
|
90
109
|
}
|
|
91
110
|
// Skip test files
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.78",
|
|
4
|
+
"date": "2026-08-02T08:45:25.049Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "enforce-firestore-path-utils",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
1611
|
|
11
|
+
],
|
|
12
|
+
"summary": "report concatenated inline paths (closes #1611)"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "enforce-realtimedb-path-utils",
|
|
16
|
+
"changeType": "fix",
|
|
17
|
+
"issues": [
|
|
18
|
+
1612
|
|
19
|
+
],
|
|
20
|
+
"summary": "report concatenated inline paths (closes #1612)"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
2
24
|
{
|
|
3
25
|
"version": "1.20.77",
|
|
4
26
|
"date": "2026-08-02T08:02:01.009Z",
|