eslint-plugin-nextfriday 1.4.0 → 1.5.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 1.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#30](https://github.com/next-friday/eslint-plugin-nextfriday/pull/30) [`cc054bc`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/cc054bc46b902af77e747b72b09eb56854ea9630) Thanks [@nextfridaydeveloper](https://github.com/nextfridaydeveloper)! - Fix package installation warnings by removing preinstall script and making prepare script fail-safe
8
+
9
+ ## 1.5.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#28](https://github.com/next-friday/eslint-plugin-nextfriday/pull/28) [`387c2b8`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/387c2b8a6d0e4668daa035ab3bc3ad2f41e5d8f3) Thanks [@nextfridaydeveloper](https://github.com/nextfridaydeveloper)! - Add new `no-env-fallback` rule to prevent dangerous fallback values for environment variables. This rule disallows using `||`, `??`, or ternary operators with `process.env` to ensure applications fail explicitly when required environment variables are missing rather than silently using default values.
14
+
3
15
  ## 1.4.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -69,6 +69,7 @@ export default [
69
69
  "nextfriday/prefer-react-import-types": "error",
70
70
  "nextfriday/no-complex-inline-return": "error",
71
71
  "nextfriday/no-logic-in-params": "error",
72
+ "nextfriday/no-env-fallback": "error",
72
73
  "nextfriday/jsx-pascal-case": "error",
73
74
  "nextfriday/prefer-interface-over-inline-types": "error",
74
75
  "nextfriday/react-props-destructure": "error",
@@ -125,6 +126,7 @@ module.exports = {
125
126
  | [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
126
127
  | [no-complex-inline-return](docs/rules/NO_COMPLEX_INLINE_RETURN.md) | Disallow complex inline expressions in return statements - prefer const first | ❌ |
127
128
  | [no-logic-in-params](docs/rules/NO_LOGIC_IN_PARAMS.md) | Disallow logic or conditions in function parameters - extract to const first | ❌ |
129
+ | [no-env-fallback](docs/rules/NO_ENV_FALLBACK.md) | Disallow fallback values for environment variables as they can be dangerous | ❌ |
128
130
 
129
131
  ## Configurations
130
132
 
@@ -144,6 +146,7 @@ Basic configuration without JSX-specific rules:
144
146
  - `nextfriday/prefer-react-import-types`: `"error"`
145
147
  - `nextfriday/no-complex-inline-return`: `"error"`
146
148
  - `nextfriday/no-logic-in-params`: `"error"`
149
+ - `nextfriday/no-env-fallback`: `"error"`
147
150
 
148
151
  #### `base/recommended`
149
152
 
@@ -0,0 +1,53 @@
1
+ # no-env-fallback
2
+
3
+ Disallow fallback values for environment variables as they can be dangerous in production.
4
+
5
+ ## Rule Details
6
+
7
+ This rule prevents using fallback values with `process.env` environment variables. When environment variables have fallback values (using `||`, `??`, or ternary operators), applications can silently run with default values instead of failing when required configuration is missing. This can lead to security issues, incorrect behavior in production, or hard-to-debug problems.
8
+
9
+ It's safer to let the application fail explicitly when required environment variables are missing, rather than continuing with potentially incorrect default values.
10
+
11
+ ## Examples
12
+
13
+ **Incorrect** code for this rule:
14
+
15
+ ```js
16
+ const apiKey = process.env.API_KEY || "default-key";
17
+ const dbUrl = process.env.DATABASE_URL ?? "localhost";
18
+ const port = process.env.PORT ? "8080" : "3000";
19
+
20
+ const config = {
21
+ secret: process.env.SECRET_KEY || "unsafe-default",
22
+ region: process.env.AWS_REGION ?? "us-east-1",
23
+ };
24
+
25
+ function getToken() {
26
+ return process.env.AUTH_TOKEN || "abc123";
27
+ }
28
+ ```
29
+
30
+ **Correct** code for this rule:
31
+
32
+ ```js
33
+ const apiKey = process.env.API_KEY;
34
+ const dbUrl = process.env.DATABASE_URL;
35
+ const port = process.env.PORT;
36
+
37
+ const config = {
38
+ secret: process.env.SECRET_KEY,
39
+ region: process.env.AWS_REGION,
40
+ };
41
+
42
+ function getToken() {
43
+ return process.env.AUTH_TOKEN;
44
+ }
45
+
46
+ if (!process.env.API_KEY) {
47
+ throw new Error("API_KEY environment variable is required");
48
+ }
49
+ ```
50
+
51
+ ## When Not To Use It
52
+
53
+ If your application intentionally uses default values for optional configuration and you have explicit handling for required vs optional environment variables, you may want to disable this rule. However, it's generally safer to validate required environment variables at application startup rather than using fallback values.
package/lib/index.cjs CHANGED
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(index_exports);
40
40
  // package.json
41
41
  var package_default = {
42
42
  name: "eslint-plugin-nextfriday",
43
- version: "1.4.0",
43
+ version: "1.5.1",
44
44
  description: "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
45
45
  keywords: [
46
46
  "eslint",
@@ -90,10 +90,9 @@ var package_default = {
90
90
  "changeset:publish": "npm publish --provenance --access public",
91
91
  "changeset:version": "changeset version",
92
92
  clear: "rm -rf lib node_modules/.cache .eslintcache",
93
- eslint: "eslint src --ext .js,.ts,.mjs --fix",
94
- "eslint:check": "eslint src --ext .js,.ts,.mjs",
95
- preinstall: "npx only-allow pnpm",
96
- prepare: "husky",
93
+ eslint: "eslint src --ext .js,.ts --fix",
94
+ "eslint:check": "eslint src --ext .js,.ts",
95
+ prepare: "husky || true",
97
96
  prepublishOnly: "pnpm run build",
98
97
  prettier: "prettier --write .",
99
98
  "prettier:check": "prettier --check .",
@@ -465,12 +464,65 @@ var noEmoji = createRule6({
465
464
  });
466
465
  var no_emoji_default = noEmoji;
467
466
 
468
- // src/rules/no-explicit-return-type.ts
467
+ // src/rules/no-env-fallback.ts
469
468
  var import_utils7 = require("@typescript-eslint/utils");
470
469
  var createRule7 = import_utils7.ESLintUtils.RuleCreator(
471
470
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
472
471
  );
473
- var noExplicitReturnType = createRule7({
472
+ var noEnvFallback = createRule7({
473
+ name: "no-env-fallback",
474
+ meta: {
475
+ type: "problem",
476
+ docs: {
477
+ description: "Disallow fallback values for environment variables as they can be dangerous in production"
478
+ },
479
+ messages: {
480
+ noEnvFallback: "Avoid using fallback values with process.env. Environment variables should fail explicitly when missing rather than silently using a default value."
481
+ },
482
+ schema: []
483
+ },
484
+ defaultOptions: [],
485
+ create(context) {
486
+ const isProcessEnvAccess = (node) => {
487
+ if (node.type !== import_utils7.AST_NODE_TYPES.MemberExpression) {
488
+ return false;
489
+ }
490
+ const { object } = node;
491
+ if (object.type !== import_utils7.AST_NODE_TYPES.MemberExpression) {
492
+ return false;
493
+ }
494
+ const processNode = object.object;
495
+ const envNode = object.property;
496
+ return processNode.type === import_utils7.AST_NODE_TYPES.Identifier && processNode.name === "process" && envNode.type === import_utils7.AST_NODE_TYPES.Identifier && envNode.name === "env";
497
+ };
498
+ return {
499
+ LogicalExpression(node) {
500
+ if ((node.operator === "||" || node.operator === "??") && isProcessEnvAccess(node.left)) {
501
+ context.report({
502
+ node,
503
+ messageId: "noEnvFallback"
504
+ });
505
+ }
506
+ },
507
+ ConditionalExpression(node) {
508
+ if (isProcessEnvAccess(node.test)) {
509
+ context.report({
510
+ node,
511
+ messageId: "noEnvFallback"
512
+ });
513
+ }
514
+ }
515
+ };
516
+ }
517
+ });
518
+ var no_env_fallback_default = noEnvFallback;
519
+
520
+ // src/rules/no-explicit-return-type.ts
521
+ var import_utils8 = require("@typescript-eslint/utils");
522
+ var createRule8 = import_utils8.ESLintUtils.RuleCreator(
523
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
524
+ );
525
+ var noExplicitReturnType = createRule8({
474
526
  name: "no-explicit-return-type",
475
527
  meta: {
476
528
  type: "suggestion",
@@ -510,11 +562,11 @@ var noExplicitReturnType = createRule7({
510
562
  var no_explicit_return_type_default = noExplicitReturnType;
511
563
 
512
564
  // src/rules/no-logic-in-params.ts
513
- var import_utils8 = require("@typescript-eslint/utils");
514
- var createRule8 = import_utils8.ESLintUtils.RuleCreator(
565
+ var import_utils9 = require("@typescript-eslint/utils");
566
+ var createRule9 = import_utils9.ESLintUtils.RuleCreator(
515
567
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
516
568
  );
517
- var noLogicInParams = createRule8({
569
+ var noLogicInParams = createRule9({
518
570
  name: "no-logic-in-params",
519
571
  meta: {
520
572
  type: "suggestion",
@@ -529,20 +581,20 @@ var noLogicInParams = createRule8({
529
581
  defaultOptions: [],
530
582
  create(context) {
531
583
  const isComplexExpression = (node) => {
532
- if (node.type === import_utils8.AST_NODE_TYPES.SpreadElement) {
584
+ if (node.type === import_utils9.AST_NODE_TYPES.SpreadElement) {
533
585
  return false;
534
586
  }
535
- if (node.type === import_utils8.AST_NODE_TYPES.ConditionalExpression) {
587
+ if (node.type === import_utils9.AST_NODE_TYPES.ConditionalExpression) {
536
588
  return true;
537
589
  }
538
- if (node.type === import_utils8.AST_NODE_TYPES.LogicalExpression) {
590
+ if (node.type === import_utils9.AST_NODE_TYPES.LogicalExpression) {
539
591
  return true;
540
592
  }
541
- if (node.type === import_utils8.AST_NODE_TYPES.BinaryExpression) {
593
+ if (node.type === import_utils9.AST_NODE_TYPES.BinaryExpression) {
542
594
  const logicalOperators = ["==", "===", "!=", "!==", "<", ">", "<=", ">=", "in", "instanceof"];
543
595
  return logicalOperators.includes(node.operator);
544
596
  }
545
- if (node.type === import_utils8.AST_NODE_TYPES.UnaryExpression) {
597
+ if (node.type === import_utils9.AST_NODE_TYPES.UnaryExpression) {
546
598
  return node.operator === "!";
547
599
  }
548
600
  return false;
@@ -574,11 +626,11 @@ var noLogicInParams = createRule8({
574
626
  var no_logic_in_params_default = noLogicInParams;
575
627
 
576
628
  // src/rules/prefer-destructuring-params.ts
577
- var import_utils9 = require("@typescript-eslint/utils");
578
- var createRule9 = import_utils9.ESLintUtils.RuleCreator(
629
+ var import_utils10 = require("@typescript-eslint/utils");
630
+ var createRule10 = import_utils10.ESLintUtils.RuleCreator(
579
631
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
580
632
  );
581
- var preferDestructuringParams = createRule9({
633
+ var preferDestructuringParams = createRule10({
582
634
  name: "prefer-destructuring-params",
583
635
  meta: {
584
636
  type: "suggestion",
@@ -594,18 +646,18 @@ var preferDestructuringParams = createRule9({
594
646
  create(context) {
595
647
  const isCallbackFunction = (node) => {
596
648
  const { parent } = node;
597
- return parent?.type === import_utils9.AST_NODE_TYPES.CallExpression;
649
+ return parent?.type === import_utils10.AST_NODE_TYPES.CallExpression;
598
650
  };
599
651
  const isDeveloperFunction = (node) => {
600
- if (node.type === import_utils9.AST_NODE_TYPES.FunctionDeclaration) {
652
+ if (node.type === import_utils10.AST_NODE_TYPES.FunctionDeclaration) {
601
653
  return true;
602
654
  }
603
- if (node.type === import_utils9.AST_NODE_TYPES.FunctionExpression || node.type === import_utils9.AST_NODE_TYPES.ArrowFunctionExpression) {
655
+ if (node.type === import_utils10.AST_NODE_TYPES.FunctionExpression || node.type === import_utils10.AST_NODE_TYPES.ArrowFunctionExpression) {
604
656
  if (isCallbackFunction(node)) {
605
657
  return false;
606
658
  }
607
659
  const { parent } = node;
608
- return parent?.type === import_utils9.AST_NODE_TYPES.VariableDeclarator || parent?.type === import_utils9.AST_NODE_TYPES.AssignmentExpression || parent?.type === import_utils9.AST_NODE_TYPES.Property || parent?.type === import_utils9.AST_NODE_TYPES.MethodDefinition;
660
+ return parent?.type === import_utils10.AST_NODE_TYPES.VariableDeclarator || parent?.type === import_utils10.AST_NODE_TYPES.AssignmentExpression || parent?.type === import_utils10.AST_NODE_TYPES.Property || parent?.type === import_utils10.AST_NODE_TYPES.MethodDefinition;
609
661
  }
610
662
  return false;
611
663
  };
@@ -617,7 +669,7 @@ var preferDestructuringParams = createRule9({
617
669
  if (!isDeveloperFunction(node)) {
618
670
  return;
619
671
  }
620
- if (node.type === import_utils9.AST_NODE_TYPES.FunctionDeclaration && node.id) {
672
+ if (node.type === import_utils10.AST_NODE_TYPES.FunctionDeclaration && node.id) {
621
673
  const functionName = node.id.name;
622
674
  if (functionName.startsWith("_") || functionName.includes("$") || /^[A-Z][a-zA-Z]*$/.test(functionName)) {
623
675
  return;
@@ -627,7 +679,7 @@ var preferDestructuringParams = createRule9({
627
679
  return;
628
680
  }
629
681
  const hasNonDestructuredParams = node.params.some(
630
- (param) => param.type !== import_utils9.AST_NODE_TYPES.ObjectPattern && param.type !== import_utils9.AST_NODE_TYPES.RestElement
682
+ (param) => param.type !== import_utils10.AST_NODE_TYPES.ObjectPattern && param.type !== import_utils10.AST_NODE_TYPES.RestElement
631
683
  );
632
684
  if (hasNonDestructuredParams) {
633
685
  context.report({
@@ -646,11 +698,11 @@ var preferDestructuringParams = createRule9({
646
698
  var prefer_destructuring_params_default = preferDestructuringParams;
647
699
 
648
700
  // src/rules/prefer-import-type.ts
649
- var import_utils10 = require("@typescript-eslint/utils");
650
- var createRule10 = import_utils10.ESLintUtils.RuleCreator(
701
+ var import_utils11 = require("@typescript-eslint/utils");
702
+ var createRule11 = import_utils11.ESLintUtils.RuleCreator(
651
703
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
652
704
  );
653
- var preferImportType = createRule10({
705
+ var preferImportType = createRule11({
654
706
  name: "prefer-import-type",
655
707
  meta: {
656
708
  type: "suggestion",
@@ -681,14 +733,14 @@ var preferImportType = createRule10({
681
733
  return;
682
734
  }
683
735
  const isTypeOnlyImport = node.specifiers.every((specifier) => {
684
- if (specifier.type === import_utils10.AST_NODE_TYPES.ImportDefaultSpecifier) {
736
+ if (specifier.type === import_utils11.AST_NODE_TYPES.ImportDefaultSpecifier) {
685
737
  return false;
686
738
  }
687
- if (specifier.type === import_utils10.AST_NODE_TYPES.ImportNamespaceSpecifier) {
739
+ if (specifier.type === import_utils11.AST_NODE_TYPES.ImportNamespaceSpecifier) {
688
740
  return false;
689
741
  }
690
- if (specifier.type === import_utils10.AST_NODE_TYPES.ImportSpecifier) {
691
- const importedName = specifier.imported.type === import_utils10.AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value;
742
+ if (specifier.type === import_utils11.AST_NODE_TYPES.ImportSpecifier) {
743
+ const importedName = specifier.imported.type === import_utils11.AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value;
692
744
  const isKnownTypeOnly = node.source.value === "@typescript-eslint/utils" && ["TSESTree", "RuleContext"].includes(importedName) || node.source.value === "react" && ["Component", "ComponentProps", "ReactNode", "FC", "JSX", "ReactElement", "PropsWithChildren"].includes(
693
745
  importedName
694
746
  ) || importedName.endsWith("Type") || importedName.endsWith("Interface") || importedName.endsWith("Props");
@@ -716,11 +768,11 @@ var preferImportType = createRule10({
716
768
  var prefer_import_type_default = preferImportType;
717
769
 
718
770
  // src/rules/prefer-interface-over-inline-types.ts
719
- var import_utils11 = require("@typescript-eslint/utils");
720
- var createRule11 = import_utils11.ESLintUtils.RuleCreator(
771
+ var import_utils12 = require("@typescript-eslint/utils");
772
+ var createRule12 = import_utils12.ESLintUtils.RuleCreator(
721
773
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
722
774
  );
723
- var preferInterfaceOverInlineTypes = createRule11({
775
+ var preferInterfaceOverInlineTypes = createRule12({
724
776
  name: "prefer-interface-over-inline-types",
725
777
  meta: {
726
778
  type: "suggestion",
@@ -736,54 +788,54 @@ var preferInterfaceOverInlineTypes = createRule11({
736
788
  defaultOptions: [],
737
789
  create(context) {
738
790
  function hasJSXInConditional(node) {
739
- return node.consequent.type === import_utils11.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils11.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils11.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils11.AST_NODE_TYPES.JSXFragment;
791
+ return node.consequent.type === import_utils12.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils12.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils12.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils12.AST_NODE_TYPES.JSXFragment;
740
792
  }
741
793
  function hasJSXInLogical(node) {
742
- return node.right.type === import_utils11.AST_NODE_TYPES.JSXElement || node.right.type === import_utils11.AST_NODE_TYPES.JSXFragment;
794
+ return node.right.type === import_utils12.AST_NODE_TYPES.JSXElement || node.right.type === import_utils12.AST_NODE_TYPES.JSXFragment;
743
795
  }
744
796
  function hasJSXReturn(block) {
745
797
  return block.body.some((stmt) => {
746
- if (stmt.type === import_utils11.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
747
- return stmt.argument.type === import_utils11.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils11.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils11.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils11.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
798
+ if (stmt.type === import_utils12.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
799
+ return stmt.argument.type === import_utils12.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils12.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils12.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils12.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
748
800
  }
749
801
  return false;
750
802
  });
751
803
  }
752
804
  function isReactComponent(node) {
753
- if (node.type === import_utils11.AST_NODE_TYPES.ArrowFunctionExpression) {
754
- if (node.body.type === import_utils11.AST_NODE_TYPES.JSXElement || node.body.type === import_utils11.AST_NODE_TYPES.JSXFragment) {
805
+ if (node.type === import_utils12.AST_NODE_TYPES.ArrowFunctionExpression) {
806
+ if (node.body.type === import_utils12.AST_NODE_TYPES.JSXElement || node.body.type === import_utils12.AST_NODE_TYPES.JSXFragment) {
755
807
  return true;
756
808
  }
757
- if (node.body.type === import_utils11.AST_NODE_TYPES.BlockStatement) {
809
+ if (node.body.type === import_utils12.AST_NODE_TYPES.BlockStatement) {
758
810
  return hasJSXReturn(node.body);
759
811
  }
760
- } else if (node.type === import_utils11.AST_NODE_TYPES.FunctionExpression || node.type === import_utils11.AST_NODE_TYPES.FunctionDeclaration) {
761
- if (node.body && node.body.type === import_utils11.AST_NODE_TYPES.BlockStatement) {
812
+ } else if (node.type === import_utils12.AST_NODE_TYPES.FunctionExpression || node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration) {
813
+ if (node.body && node.body.type === import_utils12.AST_NODE_TYPES.BlockStatement) {
762
814
  return hasJSXReturn(node.body);
763
815
  }
764
816
  }
765
817
  return false;
766
818
  }
767
819
  function isInlineTypeAnnotation(node) {
768
- if (node.type === import_utils11.AST_NODE_TYPES.TSTypeLiteral) {
820
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
769
821
  return true;
770
822
  }
771
- if (node.type === import_utils11.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
772
- return node.typeArguments.params.some((param) => param.type === import_utils11.AST_NODE_TYPES.TSTypeLiteral);
823
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
824
+ return node.typeArguments.params.some((param) => param.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral);
773
825
  }
774
- if (node.type === import_utils11.AST_NODE_TYPES.TSUnionType) {
826
+ if (node.type === import_utils12.AST_NODE_TYPES.TSUnionType) {
775
827
  return node.types.some((type) => isInlineTypeAnnotation(type));
776
828
  }
777
829
  return false;
778
830
  }
779
831
  function hasInlineObjectType(node) {
780
- if (node.type === import_utils11.AST_NODE_TYPES.TSTypeLiteral) {
832
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
781
833
  return true;
782
834
  }
783
- if (node.type === import_utils11.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
784
- return node.typeArguments.params.some((param) => param.type === import_utils11.AST_NODE_TYPES.TSTypeLiteral);
835
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
836
+ return node.typeArguments.params.some((param) => param.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral);
785
837
  }
786
- if (node.type === import_utils11.AST_NODE_TYPES.TSUnionType) {
838
+ if (node.type === import_utils12.AST_NODE_TYPES.TSUnionType) {
787
839
  return node.types.some((type) => hasInlineObjectType(type));
788
840
  }
789
841
  return false;
@@ -796,7 +848,7 @@ var preferInterfaceOverInlineTypes = createRule11({
796
848
  return;
797
849
  }
798
850
  const param = node.params[0];
799
- if (param.type === import_utils11.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
851
+ if (param.type === import_utils12.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
800
852
  const { typeAnnotation } = param.typeAnnotation;
801
853
  if (isInlineTypeAnnotation(typeAnnotation) && hasInlineObjectType(typeAnnotation)) {
802
854
  context.report({
@@ -816,11 +868,11 @@ var preferInterfaceOverInlineTypes = createRule11({
816
868
  var prefer_interface_over_inline_types_default = preferInterfaceOverInlineTypes;
817
869
 
818
870
  // src/rules/prefer-named-param-types.ts
819
- var import_utils12 = require("@typescript-eslint/utils");
820
- var createRule12 = import_utils12.ESLintUtils.RuleCreator(
871
+ var import_utils13 = require("@typescript-eslint/utils");
872
+ var createRule13 = import_utils13.ESLintUtils.RuleCreator(
821
873
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
822
874
  );
823
- var preferNamedParamTypes = createRule12({
875
+ var preferNamedParamTypes = createRule13({
824
876
  name: "prefer-named-param-types",
825
877
  meta: {
826
878
  type: "suggestion",
@@ -835,16 +887,16 @@ var preferNamedParamTypes = createRule12({
835
887
  defaultOptions: [],
836
888
  create(context) {
837
889
  function hasInlineObjectType(param) {
838
- if (param.type === import_utils12.AST_NODE_TYPES.AssignmentPattern) {
890
+ if (param.type === import_utils13.AST_NODE_TYPES.AssignmentPattern) {
839
891
  return hasInlineObjectType(param.left);
840
892
  }
841
- if (param.type === import_utils12.AST_NODE_TYPES.ObjectPattern) {
842
- if (param.typeAnnotation?.typeAnnotation.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
893
+ if (param.type === import_utils13.AST_NODE_TYPES.ObjectPattern) {
894
+ if (param.typeAnnotation?.typeAnnotation.type === import_utils13.AST_NODE_TYPES.TSTypeLiteral) {
843
895
  return true;
844
896
  }
845
897
  }
846
- if (param.type === import_utils12.AST_NODE_TYPES.Identifier) {
847
- if (param.typeAnnotation?.typeAnnotation.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
898
+ if (param.type === import_utils13.AST_NODE_TYPES.Identifier) {
899
+ if (param.typeAnnotation?.typeAnnotation.type === import_utils13.AST_NODE_TYPES.TSTypeLiteral) {
848
900
  return true;
849
901
  }
850
902
  }
@@ -878,11 +930,11 @@ var preferNamedParamTypes = createRule12({
878
930
  var prefer_named_param_types_default = preferNamedParamTypes;
879
931
 
880
932
  // src/rules/prefer-react-import-types.ts
881
- var import_utils13 = require("@typescript-eslint/utils");
882
- var createRule13 = import_utils13.ESLintUtils.RuleCreator(
933
+ var import_utils14 = require("@typescript-eslint/utils");
934
+ var createRule14 = import_utils14.ESLintUtils.RuleCreator(
883
935
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
884
936
  );
885
- var preferReactImportTypes = createRule13({
937
+ var preferReactImportTypes = createRule14({
886
938
  name: "prefer-react-import-types",
887
939
  meta: {
888
940
  type: "suggestion",
@@ -958,7 +1010,7 @@ var preferReactImportTypes = createRule13({
958
1010
  ]);
959
1011
  const allReactExports = /* @__PURE__ */ new Set([...reactTypes, ...reactRuntimeExports]);
960
1012
  function checkMemberExpression(node) {
961
- if (node.object.type === import_utils13.AST_NODE_TYPES.Identifier && node.object.name === "React" && node.property.type === import_utils13.AST_NODE_TYPES.Identifier && allReactExports.has(node.property.name)) {
1013
+ if (node.object.type === import_utils14.AST_NODE_TYPES.Identifier && node.object.name === "React" && node.property.type === import_utils14.AST_NODE_TYPES.Identifier && allReactExports.has(node.property.name)) {
962
1014
  const typeName = node.property.name;
963
1015
  const isType = reactTypes.has(typeName);
964
1016
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -975,7 +1027,7 @@ var preferReactImportTypes = createRule13({
975
1027
  return {
976
1028
  MemberExpression: checkMemberExpression,
977
1029
  "TSTypeReference > TSQualifiedName": (node) => {
978
- if (node.left.type === import_utils13.AST_NODE_TYPES.Identifier && node.left.name === "React" && node.right.type === import_utils13.AST_NODE_TYPES.Identifier && allReactExports.has(node.right.name)) {
1030
+ if (node.left.type === import_utils14.AST_NODE_TYPES.Identifier && node.left.name === "React" && node.right.type === import_utils14.AST_NODE_TYPES.Identifier && allReactExports.has(node.right.name)) {
979
1031
  const typeName = node.right.name;
980
1032
  const isType = reactTypes.has(typeName);
981
1033
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -995,11 +1047,11 @@ var preferReactImportTypes = createRule13({
995
1047
  var prefer_react_import_types_default = preferReactImportTypes;
996
1048
 
997
1049
  // src/rules/react-props-destructure.ts
998
- var import_utils14 = require("@typescript-eslint/utils");
999
- var createRule14 = import_utils14.ESLintUtils.RuleCreator(
1050
+ var import_utils15 = require("@typescript-eslint/utils");
1051
+ var createRule15 = import_utils15.ESLintUtils.RuleCreator(
1000
1052
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
1001
1053
  );
1002
- var reactPropsDestructure = createRule14({
1054
+ var reactPropsDestructure = createRule15({
1003
1055
  name: "react-props-destructure",
1004
1056
  meta: {
1005
1057
  type: "suggestion",
@@ -1015,29 +1067,29 @@ var reactPropsDestructure = createRule14({
1015
1067
  defaultOptions: [],
1016
1068
  create(context) {
1017
1069
  function hasJSXInConditional(node) {
1018
- return node.consequent.type === import_utils14.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils14.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils14.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils14.AST_NODE_TYPES.JSXFragment;
1070
+ return node.consequent.type === import_utils15.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils15.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils15.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils15.AST_NODE_TYPES.JSXFragment;
1019
1071
  }
1020
1072
  function hasJSXInLogical(node) {
1021
- return node.right.type === import_utils14.AST_NODE_TYPES.JSXElement || node.right.type === import_utils14.AST_NODE_TYPES.JSXFragment;
1073
+ return node.right.type === import_utils15.AST_NODE_TYPES.JSXElement || node.right.type === import_utils15.AST_NODE_TYPES.JSXFragment;
1022
1074
  }
1023
1075
  function hasJSXReturn(block) {
1024
1076
  return block.body.some((stmt) => {
1025
- if (stmt.type === import_utils14.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
1026
- return stmt.argument.type === import_utils14.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils14.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils14.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils14.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
1077
+ if (stmt.type === import_utils15.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
1078
+ return stmt.argument.type === import_utils15.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils15.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils15.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils15.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
1027
1079
  }
1028
1080
  return false;
1029
1081
  });
1030
1082
  }
1031
1083
  function isReactComponent(node) {
1032
- if (node.type === import_utils14.AST_NODE_TYPES.ArrowFunctionExpression) {
1033
- if (node.body.type === import_utils14.AST_NODE_TYPES.JSXElement || node.body.type === import_utils14.AST_NODE_TYPES.JSXFragment) {
1084
+ if (node.type === import_utils15.AST_NODE_TYPES.ArrowFunctionExpression) {
1085
+ if (node.body.type === import_utils15.AST_NODE_TYPES.JSXElement || node.body.type === import_utils15.AST_NODE_TYPES.JSXFragment) {
1034
1086
  return true;
1035
1087
  }
1036
- if (node.body.type === import_utils14.AST_NODE_TYPES.BlockStatement) {
1088
+ if (node.body.type === import_utils15.AST_NODE_TYPES.BlockStatement) {
1037
1089
  return hasJSXReturn(node.body);
1038
1090
  }
1039
- } else if (node.type === import_utils14.AST_NODE_TYPES.FunctionExpression || node.type === import_utils14.AST_NODE_TYPES.FunctionDeclaration) {
1040
- if (node.body && node.body.type === import_utils14.AST_NODE_TYPES.BlockStatement) {
1091
+ } else if (node.type === import_utils15.AST_NODE_TYPES.FunctionExpression || node.type === import_utils15.AST_NODE_TYPES.FunctionDeclaration) {
1092
+ if (node.body && node.body.type === import_utils15.AST_NODE_TYPES.BlockStatement) {
1041
1093
  return hasJSXReturn(node.body);
1042
1094
  }
1043
1095
  }
@@ -1051,9 +1103,9 @@ var reactPropsDestructure = createRule14({
1051
1103
  return;
1052
1104
  }
1053
1105
  const param = node.params[0];
1054
- if (param.type === import_utils14.AST_NODE_TYPES.ObjectPattern) {
1055
- const properties = param.properties.filter((prop) => prop.type === import_utils14.AST_NODE_TYPES.Property).map((prop) => {
1056
- if (prop.key.type === import_utils14.AST_NODE_TYPES.Identifier) {
1106
+ if (param.type === import_utils15.AST_NODE_TYPES.ObjectPattern) {
1107
+ const properties = param.properties.filter((prop) => prop.type === import_utils15.AST_NODE_TYPES.Property).map((prop) => {
1108
+ if (prop.key.type === import_utils15.AST_NODE_TYPES.Identifier) {
1057
1109
  return prop.key.name;
1058
1110
  }
1059
1111
  return null;
@@ -1091,6 +1143,7 @@ var rules = {
1091
1143
  "md-filename-case-restriction": md_filename_case_restriction_default,
1092
1144
  "no-complex-inline-return": no_complex_inline_return_default,
1093
1145
  "no-emoji": no_emoji_default,
1146
+ "no-env-fallback": no_env_fallback_default,
1094
1147
  "no-explicit-return-type": no_explicit_return_type_default,
1095
1148
  "no-logic-in-params": no_logic_in_params_default,
1096
1149
  "prefer-destructuring-params": prefer_destructuring_params_default,
@@ -1114,7 +1167,8 @@ var baseRules = {
1114
1167
  "nextfriday/prefer-named-param-types": "warn",
1115
1168
  "nextfriday/prefer-react-import-types": "warn",
1116
1169
  "nextfriday/no-complex-inline-return": "warn",
1117
- "nextfriday/no-logic-in-params": "warn"
1170
+ "nextfriday/no-logic-in-params": "warn",
1171
+ "nextfriday/no-env-fallback": "warn"
1118
1172
  };
1119
1173
  var baseRecommendedRules = {
1120
1174
  "nextfriday/no-emoji": "error",
@@ -1126,7 +1180,8 @@ var baseRecommendedRules = {
1126
1180
  "nextfriday/prefer-named-param-types": "error",
1127
1181
  "nextfriday/prefer-react-import-types": "error",
1128
1182
  "nextfriday/no-complex-inline-return": "error",
1129
- "nextfriday/no-logic-in-params": "error"
1183
+ "nextfriday/no-logic-in-params": "error",
1184
+ "nextfriday/no-env-fallback": "error"
1130
1185
  };
1131
1186
  var jsxRules = {
1132
1187
  "nextfriday/jsx-pascal-case": "warn",