Skip to content

Commit b16a475

Browse files
authored
feat(no-process-env): Allow users to exclude specific variables (#345)
* fix(no-process-env): Include computed Literals * feat(no-process-env): Allow users to exclude specific variables * docs(no-process-env): Add allowedVariables documentation * Remove comments from test cases
1 parent 148e47e commit b16a475

File tree

3 files changed

+126
-1
lines changed

3 files changed

+126
-1
lines changed

docs/rules/no-process-env.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ if(config.env === "development") {
3030
}
3131
```
3232

33+
### Options
34+
35+
```json
36+
{
37+
"rules": {
38+
"n/no-process-env": ["error", {
39+
"allowedVariables": ["NODE_ENV"]
40+
}]
41+
}
42+
}
43+
```
44+
45+
#### allowedVariables
46+
47+
Sometimes you need to allow specific environment variables, this option allows you to exclude specific variables from triggering a linting error.
48+
3349
## 🔎 Implementation
3450

3551
- [Rule source](../../lib/rules/no-process-env.js)

lib/rules/no-process-env.js

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,26 @@ const querySelector = [
1313
`[computed!=true]`,
1414
`[object.name="process"]`,
1515
`[property.name="env"]`,
16+
`,`,
17+
`MemberExpression`,
18+
`[computed=true]`,
19+
`[object.name="process"]`,
20+
`[property.value="env"]`,
1621
]
1722

23+
/**
24+
* @param {unknown} node [description]
25+
* @returns {node is import('estree').MemberExpression}
26+
*/
27+
function isMemberExpresion(node) {
28+
return (
29+
node != null &&
30+
typeof node === "object" &&
31+
"type" in node &&
32+
node.type === "MemberExpression"
33+
)
34+
}
35+
1836
/** @type {import('eslint').Rule.RuleModule} */
1937
module.exports = {
2038
meta: {
@@ -25,16 +43,48 @@ module.exports = {
2543
url: "https://github.com/eslint-community/eslint-plugin-n/blob/HEAD/docs/rules/no-process-env.md",
2644
},
2745
fixable: null,
28-
schema: [],
46+
schema: [
47+
{
48+
type: "object",
49+
properties: {
50+
allowedVariables: {
51+
type: "array",
52+
items: { type: "string" },
53+
},
54+
},
55+
additionalProperties: false,
56+
},
57+
],
2958
messages: {
3059
unexpectedProcessEnv: "Unexpected use of process.env.",
3160
},
3261
},
3362

3463
create(context) {
64+
const options = context.options[0] ?? {}
65+
/** @type {string[]} */
66+
const allowedVariables = options.allowedVariables ?? []
3567
return {
3668
/** @param {import('estree').MemberExpression} node */
3769
[querySelector.join("")](node) {
70+
if (
71+
"parent" in node &&
72+
isMemberExpresion(node.parent) &&
73+
node.parent.property != null
74+
) {
75+
const child = node.parent.property
76+
if (
77+
(child.type === "Identifier" &&
78+
node.parent.computed === false &&
79+
allowedVariables.includes(child.name)) ||
80+
(child.type === "Literal" &&
81+
typeof child.value === "string" &&
82+
node.parent.computed === true &&
83+
allowedVariables.includes(child.value))
84+
) {
85+
return
86+
}
87+
}
3888
context.report({ node, messageId: "unexpectedProcessEnv" })
3989
},
4090
}

tests/lib/rules/no-process-env.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,24 @@ new RuleTester().run("no-process-env", rule, {
1313
"process[env]",
1414
"process.nextTick",
1515
"process.execArgv",
16+
17+
// allowedVariables
18+
{
19+
code: "process.env.NODE_ENV",
20+
options: [{ allowedVariables: ["NODE_ENV"] }],
21+
},
22+
{
23+
code: "process.env['NODE_ENV']",
24+
options: [{ allowedVariables: ["NODE_ENV"] }],
25+
},
26+
{
27+
code: "process['env'].NODE_ENV",
28+
options: [{ allowedVariables: ["NODE_ENV"] }],
29+
},
30+
{
31+
code: "process['env']['NODE_ENV']",
32+
options: [{ allowedVariables: ["NODE_ENV"] }],
33+
},
1634
],
1735

1836
invalid: [
@@ -25,6 +43,15 @@ new RuleTester().run("no-process-env", rule, {
2543
},
2644
],
2745
},
46+
{
47+
code: "process['env']",
48+
errors: [
49+
{
50+
messageId: "unexpectedProcessEnv",
51+
type: "MemberExpression",
52+
},
53+
],
54+
},
2855
{
2956
code: "process.env.ENV",
3057
errors: [
@@ -43,5 +70,37 @@ new RuleTester().run("no-process-env", rule, {
4370
},
4471
],
4572
},
73+
74+
// allowedVariables
75+
{
76+
code: "process.env['OTHER_VARIABLE']",
77+
options: [{ allowedVariables: ["NODE_ENV"] }],
78+
errors: [{ messageId: "unexpectedProcessEnv" }],
79+
},
80+
{
81+
code: "process.env.OTHER_VARIABLE",
82+
options: [{ allowedVariables: ["NODE_ENV"] }],
83+
errors: [{ messageId: "unexpectedProcessEnv" }],
84+
},
85+
{
86+
code: "process['env']['OTHER_VARIABLE']",
87+
options: [{ allowedVariables: ["NODE_ENV"] }],
88+
errors: [{ messageId: "unexpectedProcessEnv" }],
89+
},
90+
{
91+
code: "process['env'].OTHER_VARIABLE",
92+
options: [{ allowedVariables: ["NODE_ENV"] }],
93+
errors: [{ messageId: "unexpectedProcessEnv" }],
94+
},
95+
{
96+
code: "process.env[NODE_ENV]",
97+
options: [{ allowedVariables: ["NODE_ENV"] }],
98+
errors: [{ messageId: "unexpectedProcessEnv" }],
99+
},
100+
{
101+
code: "process['env'][NODE_ENV]",
102+
options: [{ allowedVariables: ["NODE_ENV"] }],
103+
errors: [{ messageId: "unexpectedProcessEnv" }],
104+
},
46105
],
47106
})

0 commit comments

Comments
 (0)