eslint-plugin-nextfriday 1.4.0 → 1.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#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.
8
+
3
9
  ## 1.4.0
4
10
 
5
11
  ### 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.0",
44
44
  description: "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
45
45
  keywords: [
46
46
  "eslint",
@@ -90,8 +90,8 @@ 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",
93
+ eslint: "eslint src --ext .js,.ts --fix",
94
+ "eslint:check": "eslint src --ext .js,.ts",
95
95
  preinstall: "npx only-allow pnpm",
96
96
  prepare: "husky",
97
97
  prepublishOnly: "pnpm run build",
@@ -465,12 +465,65 @@ var noEmoji = createRule6({
465
465
  });
466
466
  var no_emoji_default = noEmoji;
467
467
 
468
- // src/rules/no-explicit-return-type.ts
468
+ // src/rules/no-env-fallback.ts
469
469
  var import_utils7 = require("@typescript-eslint/utils");
470
470
  var createRule7 = import_utils7.ESLintUtils.RuleCreator(
471
471
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
472
472
  );
473
- var noExplicitReturnType = createRule7({
473
+ var noEnvFallback = createRule7({
474
+ name: "no-env-fallback",
475
+ meta: {
476
+ type: "problem",
477
+ docs: {
478
+ description: "Disallow fallback values for environment variables as they can be dangerous in production"
479
+ },
480
+ messages: {
481
+ noEnvFallback: "Avoid using fallback values with process.env. Environment variables should fail explicitly when missing rather than silently using a default value."
482
+ },
483
+ schema: []
484
+ },
485
+ defaultOptions: [],
486
+ create(context) {
487
+ const isProcessEnvAccess = (node) => {
488
+ if (node.type !== import_utils7.AST_NODE_TYPES.MemberExpression) {
489
+ return false;
490
+ }
491
+ const { object } = node;
492
+ if (object.type !== import_utils7.AST_NODE_TYPES.MemberExpression) {
493
+ return false;
494
+ }
495
+ const processNode = object.object;
496
+ const envNode = object.property;
497
+ return processNode.type === import_utils7.AST_NODE_TYPES.Identifier && processNode.name === "process" && envNode.type === import_utils7.AST_NODE_TYPES.Identifier && envNode.name === "env";
498
+ };
499
+ return {
500
+ LogicalExpression(node) {
501
+ if ((node.operator === "||" || node.operator === "??") && isProcessEnvAccess(node.left)) {
502
+ context.report({
503
+ node,
504
+ messageId: "noEnvFallback"
505
+ });
506
+ }
507
+ },
508
+ ConditionalExpression(node) {
509
+ if (isProcessEnvAccess(node.test)) {
510
+ context.report({
511
+ node,
512
+ messageId: "noEnvFallback"
513
+ });
514
+ }
515
+ }
516
+ };
517
+ }
518
+ });
519
+ var no_env_fallback_default = noEnvFallback;
520
+
521
+ // src/rules/no-explicit-return-type.ts
522
+ var import_utils8 = require("@typescript-eslint/utils");
523
+ var createRule8 = import_utils8.ESLintUtils.RuleCreator(
524
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
525
+ );
526
+ var noExplicitReturnType = createRule8({
474
527
  name: "no-explicit-return-type",
475
528
  meta: {
476
529
  type: "suggestion",
@@ -510,11 +563,11 @@ var noExplicitReturnType = createRule7({
510
563
  var no_explicit_return_type_default = noExplicitReturnType;
511
564
 
512
565
  // src/rules/no-logic-in-params.ts
513
- var import_utils8 = require("@typescript-eslint/utils");
514
- var createRule8 = import_utils8.ESLintUtils.RuleCreator(
566
+ var import_utils9 = require("@typescript-eslint/utils");
567
+ var createRule9 = import_utils9.ESLintUtils.RuleCreator(
515
568
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
516
569
  );
517
- var noLogicInParams = createRule8({
570
+ var noLogicInParams = createRule9({
518
571
  name: "no-logic-in-params",
519
572
  meta: {
520
573
  type: "suggestion",
@@ -529,20 +582,20 @@ var noLogicInParams = createRule8({
529
582
  defaultOptions: [],
530
583
  create(context) {
531
584
  const isComplexExpression = (node) => {
532
- if (node.type === import_utils8.AST_NODE_TYPES.SpreadElement) {
585
+ if (node.type === import_utils9.AST_NODE_TYPES.SpreadElement) {
533
586
  return false;
534
587
  }
535
- if (node.type === import_utils8.AST_NODE_TYPES.ConditionalExpression) {
588
+ if (node.type === import_utils9.AST_NODE_TYPES.ConditionalExpression) {
536
589
  return true;
537
590
  }
538
- if (node.type === import_utils8.AST_NODE_TYPES.LogicalExpression) {
591
+ if (node.type === import_utils9.AST_NODE_TYPES.LogicalExpression) {
539
592
  return true;
540
593
  }
541
- if (node.type === import_utils8.AST_NODE_TYPES.BinaryExpression) {
594
+ if (node.type === import_utils9.AST_NODE_TYPES.BinaryExpression) {
542
595
  const logicalOperators = ["==", "===", "!=", "!==", "<", ">", "<=", ">=", "in", "instanceof"];
543
596
  return logicalOperators.includes(node.operator);
544
597
  }
545
- if (node.type === import_utils8.AST_NODE_TYPES.UnaryExpression) {
598
+ if (node.type === import_utils9.AST_NODE_TYPES.UnaryExpression) {
546
599
  return node.operator === "!";
547
600
  }
548
601
  return false;
@@ -574,11 +627,11 @@ var noLogicInParams = createRule8({
574
627
  var no_logic_in_params_default = noLogicInParams;
575
628
 
576
629
  // src/rules/prefer-destructuring-params.ts
577
- var import_utils9 = require("@typescript-eslint/utils");
578
- var createRule9 = import_utils9.ESLintUtils.RuleCreator(
630
+ var import_utils10 = require("@typescript-eslint/utils");
631
+ var createRule10 = import_utils10.ESLintUtils.RuleCreator(
579
632
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
580
633
  );
581
- var preferDestructuringParams = createRule9({
634
+ var preferDestructuringParams = createRule10({
582
635
  name: "prefer-destructuring-params",
583
636
  meta: {
584
637
  type: "suggestion",
@@ -594,18 +647,18 @@ var preferDestructuringParams = createRule9({
594
647
  create(context) {
595
648
  const isCallbackFunction = (node) => {
596
649
  const { parent } = node;
597
- return parent?.type === import_utils9.AST_NODE_TYPES.CallExpression;
650
+ return parent?.type === import_utils10.AST_NODE_TYPES.CallExpression;
598
651
  };
599
652
  const isDeveloperFunction = (node) => {
600
- if (node.type === import_utils9.AST_NODE_TYPES.FunctionDeclaration) {
653
+ if (node.type === import_utils10.AST_NODE_TYPES.FunctionDeclaration) {
601
654
  return true;
602
655
  }
603
- if (node.type === import_utils9.AST_NODE_TYPES.FunctionExpression || node.type === import_utils9.AST_NODE_TYPES.ArrowFunctionExpression) {
656
+ if (node.type === import_utils10.AST_NODE_TYPES.FunctionExpression || node.type === import_utils10.AST_NODE_TYPES.ArrowFunctionExpression) {
604
657
  if (isCallbackFunction(node)) {
605
658
  return false;
606
659
  }
607
660
  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;
661
+ 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
662
  }
610
663
  return false;
611
664
  };
@@ -617,7 +670,7 @@ var preferDestructuringParams = createRule9({
617
670
  if (!isDeveloperFunction(node)) {
618
671
  return;
619
672
  }
620
- if (node.type === import_utils9.AST_NODE_TYPES.FunctionDeclaration && node.id) {
673
+ if (node.type === import_utils10.AST_NODE_TYPES.FunctionDeclaration && node.id) {
621
674
  const functionName = node.id.name;
622
675
  if (functionName.startsWith("_") || functionName.includes("$") || /^[A-Z][a-zA-Z]*$/.test(functionName)) {
623
676
  return;
@@ -627,7 +680,7 @@ var preferDestructuringParams = createRule9({
627
680
  return;
628
681
  }
629
682
  const hasNonDestructuredParams = node.params.some(
630
- (param) => param.type !== import_utils9.AST_NODE_TYPES.ObjectPattern && param.type !== import_utils9.AST_NODE_TYPES.RestElement
683
+ (param) => param.type !== import_utils10.AST_NODE_TYPES.ObjectPattern && param.type !== import_utils10.AST_NODE_TYPES.RestElement
631
684
  );
632
685
  if (hasNonDestructuredParams) {
633
686
  context.report({
@@ -646,11 +699,11 @@ var preferDestructuringParams = createRule9({
646
699
  var prefer_destructuring_params_default = preferDestructuringParams;
647
700
 
648
701
  // src/rules/prefer-import-type.ts
649
- var import_utils10 = require("@typescript-eslint/utils");
650
- var createRule10 = import_utils10.ESLintUtils.RuleCreator(
702
+ var import_utils11 = require("@typescript-eslint/utils");
703
+ var createRule11 = import_utils11.ESLintUtils.RuleCreator(
651
704
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
652
705
  );
653
- var preferImportType = createRule10({
706
+ var preferImportType = createRule11({
654
707
  name: "prefer-import-type",
655
708
  meta: {
656
709
  type: "suggestion",
@@ -681,14 +734,14 @@ var preferImportType = createRule10({
681
734
  return;
682
735
  }
683
736
  const isTypeOnlyImport = node.specifiers.every((specifier) => {
684
- if (specifier.type === import_utils10.AST_NODE_TYPES.ImportDefaultSpecifier) {
737
+ if (specifier.type === import_utils11.AST_NODE_TYPES.ImportDefaultSpecifier) {
685
738
  return false;
686
739
  }
687
- if (specifier.type === import_utils10.AST_NODE_TYPES.ImportNamespaceSpecifier) {
740
+ if (specifier.type === import_utils11.AST_NODE_TYPES.ImportNamespaceSpecifier) {
688
741
  return false;
689
742
  }
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;
743
+ if (specifier.type === import_utils11.AST_NODE_TYPES.ImportSpecifier) {
744
+ const importedName = specifier.imported.type === import_utils11.AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value;
692
745
  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
746
  importedName
694
747
  ) || importedName.endsWith("Type") || importedName.endsWith("Interface") || importedName.endsWith("Props");
@@ -716,11 +769,11 @@ var preferImportType = createRule10({
716
769
  var prefer_import_type_default = preferImportType;
717
770
 
718
771
  // src/rules/prefer-interface-over-inline-types.ts
719
- var import_utils11 = require("@typescript-eslint/utils");
720
- var createRule11 = import_utils11.ESLintUtils.RuleCreator(
772
+ var import_utils12 = require("@typescript-eslint/utils");
773
+ var createRule12 = import_utils12.ESLintUtils.RuleCreator(
721
774
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
722
775
  );
723
- var preferInterfaceOverInlineTypes = createRule11({
776
+ var preferInterfaceOverInlineTypes = createRule12({
724
777
  name: "prefer-interface-over-inline-types",
725
778
  meta: {
726
779
  type: "suggestion",
@@ -736,54 +789,54 @@ var preferInterfaceOverInlineTypes = createRule11({
736
789
  defaultOptions: [],
737
790
  create(context) {
738
791
  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;
792
+ 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
793
  }
741
794
  function hasJSXInLogical(node) {
742
- return node.right.type === import_utils11.AST_NODE_TYPES.JSXElement || node.right.type === import_utils11.AST_NODE_TYPES.JSXFragment;
795
+ return node.right.type === import_utils12.AST_NODE_TYPES.JSXElement || node.right.type === import_utils12.AST_NODE_TYPES.JSXFragment;
743
796
  }
744
797
  function hasJSXReturn(block) {
745
798
  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);
799
+ if (stmt.type === import_utils12.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
800
+ 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
801
  }
749
802
  return false;
750
803
  });
751
804
  }
752
805
  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) {
806
+ if (node.type === import_utils12.AST_NODE_TYPES.ArrowFunctionExpression) {
807
+ if (node.body.type === import_utils12.AST_NODE_TYPES.JSXElement || node.body.type === import_utils12.AST_NODE_TYPES.JSXFragment) {
755
808
  return true;
756
809
  }
757
- if (node.body.type === import_utils11.AST_NODE_TYPES.BlockStatement) {
810
+ if (node.body.type === import_utils12.AST_NODE_TYPES.BlockStatement) {
758
811
  return hasJSXReturn(node.body);
759
812
  }
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) {
813
+ } else if (node.type === import_utils12.AST_NODE_TYPES.FunctionExpression || node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration) {
814
+ if (node.body && node.body.type === import_utils12.AST_NODE_TYPES.BlockStatement) {
762
815
  return hasJSXReturn(node.body);
763
816
  }
764
817
  }
765
818
  return false;
766
819
  }
767
820
  function isInlineTypeAnnotation(node) {
768
- if (node.type === import_utils11.AST_NODE_TYPES.TSTypeLiteral) {
821
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
769
822
  return true;
770
823
  }
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);
824
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
825
+ return node.typeArguments.params.some((param) => param.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral);
773
826
  }
774
- if (node.type === import_utils11.AST_NODE_TYPES.TSUnionType) {
827
+ if (node.type === import_utils12.AST_NODE_TYPES.TSUnionType) {
775
828
  return node.types.some((type) => isInlineTypeAnnotation(type));
776
829
  }
777
830
  return false;
778
831
  }
779
832
  function hasInlineObjectType(node) {
780
- if (node.type === import_utils11.AST_NODE_TYPES.TSTypeLiteral) {
833
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
781
834
  return true;
782
835
  }
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);
836
+ if (node.type === import_utils12.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
837
+ return node.typeArguments.params.some((param) => param.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral);
785
838
  }
786
- if (node.type === import_utils11.AST_NODE_TYPES.TSUnionType) {
839
+ if (node.type === import_utils12.AST_NODE_TYPES.TSUnionType) {
787
840
  return node.types.some((type) => hasInlineObjectType(type));
788
841
  }
789
842
  return false;
@@ -796,7 +849,7 @@ var preferInterfaceOverInlineTypes = createRule11({
796
849
  return;
797
850
  }
798
851
  const param = node.params[0];
799
- if (param.type === import_utils11.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
852
+ if (param.type === import_utils12.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
800
853
  const { typeAnnotation } = param.typeAnnotation;
801
854
  if (isInlineTypeAnnotation(typeAnnotation) && hasInlineObjectType(typeAnnotation)) {
802
855
  context.report({
@@ -816,11 +869,11 @@ var preferInterfaceOverInlineTypes = createRule11({
816
869
  var prefer_interface_over_inline_types_default = preferInterfaceOverInlineTypes;
817
870
 
818
871
  // src/rules/prefer-named-param-types.ts
819
- var import_utils12 = require("@typescript-eslint/utils");
820
- var createRule12 = import_utils12.ESLintUtils.RuleCreator(
872
+ var import_utils13 = require("@typescript-eslint/utils");
873
+ var createRule13 = import_utils13.ESLintUtils.RuleCreator(
821
874
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
822
875
  );
823
- var preferNamedParamTypes = createRule12({
876
+ var preferNamedParamTypes = createRule13({
824
877
  name: "prefer-named-param-types",
825
878
  meta: {
826
879
  type: "suggestion",
@@ -835,16 +888,16 @@ var preferNamedParamTypes = createRule12({
835
888
  defaultOptions: [],
836
889
  create(context) {
837
890
  function hasInlineObjectType(param) {
838
- if (param.type === import_utils12.AST_NODE_TYPES.AssignmentPattern) {
891
+ if (param.type === import_utils13.AST_NODE_TYPES.AssignmentPattern) {
839
892
  return hasInlineObjectType(param.left);
840
893
  }
841
- if (param.type === import_utils12.AST_NODE_TYPES.ObjectPattern) {
842
- if (param.typeAnnotation?.typeAnnotation.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
894
+ if (param.type === import_utils13.AST_NODE_TYPES.ObjectPattern) {
895
+ if (param.typeAnnotation?.typeAnnotation.type === import_utils13.AST_NODE_TYPES.TSTypeLiteral) {
843
896
  return true;
844
897
  }
845
898
  }
846
- if (param.type === import_utils12.AST_NODE_TYPES.Identifier) {
847
- if (param.typeAnnotation?.typeAnnotation.type === import_utils12.AST_NODE_TYPES.TSTypeLiteral) {
899
+ if (param.type === import_utils13.AST_NODE_TYPES.Identifier) {
900
+ if (param.typeAnnotation?.typeAnnotation.type === import_utils13.AST_NODE_TYPES.TSTypeLiteral) {
848
901
  return true;
849
902
  }
850
903
  }
@@ -878,11 +931,11 @@ var preferNamedParamTypes = createRule12({
878
931
  var prefer_named_param_types_default = preferNamedParamTypes;
879
932
 
880
933
  // src/rules/prefer-react-import-types.ts
881
- var import_utils13 = require("@typescript-eslint/utils");
882
- var createRule13 = import_utils13.ESLintUtils.RuleCreator(
934
+ var import_utils14 = require("@typescript-eslint/utils");
935
+ var createRule14 = import_utils14.ESLintUtils.RuleCreator(
883
936
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
884
937
  );
885
- var preferReactImportTypes = createRule13({
938
+ var preferReactImportTypes = createRule14({
886
939
  name: "prefer-react-import-types",
887
940
  meta: {
888
941
  type: "suggestion",
@@ -958,7 +1011,7 @@ var preferReactImportTypes = createRule13({
958
1011
  ]);
959
1012
  const allReactExports = /* @__PURE__ */ new Set([...reactTypes, ...reactRuntimeExports]);
960
1013
  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)) {
1014
+ 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
1015
  const typeName = node.property.name;
963
1016
  const isType = reactTypes.has(typeName);
964
1017
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -975,7 +1028,7 @@ var preferReactImportTypes = createRule13({
975
1028
  return {
976
1029
  MemberExpression: checkMemberExpression,
977
1030
  "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)) {
1031
+ 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
1032
  const typeName = node.right.name;
980
1033
  const isType = reactTypes.has(typeName);
981
1034
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -995,11 +1048,11 @@ var preferReactImportTypes = createRule13({
995
1048
  var prefer_react_import_types_default = preferReactImportTypes;
996
1049
 
997
1050
  // src/rules/react-props-destructure.ts
998
- var import_utils14 = require("@typescript-eslint/utils");
999
- var createRule14 = import_utils14.ESLintUtils.RuleCreator(
1051
+ var import_utils15 = require("@typescript-eslint/utils");
1052
+ var createRule15 = import_utils15.ESLintUtils.RuleCreator(
1000
1053
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replace(/-/g, "_").toUpperCase()}.md`
1001
1054
  );
1002
- var reactPropsDestructure = createRule14({
1055
+ var reactPropsDestructure = createRule15({
1003
1056
  name: "react-props-destructure",
1004
1057
  meta: {
1005
1058
  type: "suggestion",
@@ -1015,29 +1068,29 @@ var reactPropsDestructure = createRule14({
1015
1068
  defaultOptions: [],
1016
1069
  create(context) {
1017
1070
  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;
1071
+ 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
1072
  }
1020
1073
  function hasJSXInLogical(node) {
1021
- return node.right.type === import_utils14.AST_NODE_TYPES.JSXElement || node.right.type === import_utils14.AST_NODE_TYPES.JSXFragment;
1074
+ return node.right.type === import_utils15.AST_NODE_TYPES.JSXElement || node.right.type === import_utils15.AST_NODE_TYPES.JSXFragment;
1022
1075
  }
1023
1076
  function hasJSXReturn(block) {
1024
1077
  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);
1078
+ if (stmt.type === import_utils15.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
1079
+ 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
1080
  }
1028
1081
  return false;
1029
1082
  });
1030
1083
  }
1031
1084
  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) {
1085
+ if (node.type === import_utils15.AST_NODE_TYPES.ArrowFunctionExpression) {
1086
+ if (node.body.type === import_utils15.AST_NODE_TYPES.JSXElement || node.body.type === import_utils15.AST_NODE_TYPES.JSXFragment) {
1034
1087
  return true;
1035
1088
  }
1036
- if (node.body.type === import_utils14.AST_NODE_TYPES.BlockStatement) {
1089
+ if (node.body.type === import_utils15.AST_NODE_TYPES.BlockStatement) {
1037
1090
  return hasJSXReturn(node.body);
1038
1091
  }
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) {
1092
+ } else if (node.type === import_utils15.AST_NODE_TYPES.FunctionExpression || node.type === import_utils15.AST_NODE_TYPES.FunctionDeclaration) {
1093
+ if (node.body && node.body.type === import_utils15.AST_NODE_TYPES.BlockStatement) {
1041
1094
  return hasJSXReturn(node.body);
1042
1095
  }
1043
1096
  }
@@ -1051,9 +1104,9 @@ var reactPropsDestructure = createRule14({
1051
1104
  return;
1052
1105
  }
1053
1106
  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) {
1107
+ if (param.type === import_utils15.AST_NODE_TYPES.ObjectPattern) {
1108
+ const properties = param.properties.filter((prop) => prop.type === import_utils15.AST_NODE_TYPES.Property).map((prop) => {
1109
+ if (prop.key.type === import_utils15.AST_NODE_TYPES.Identifier) {
1057
1110
  return prop.key.name;
1058
1111
  }
1059
1112
  return null;
@@ -1091,6 +1144,7 @@ var rules = {
1091
1144
  "md-filename-case-restriction": md_filename_case_restriction_default,
1092
1145
  "no-complex-inline-return": no_complex_inline_return_default,
1093
1146
  "no-emoji": no_emoji_default,
1147
+ "no-env-fallback": no_env_fallback_default,
1094
1148
  "no-explicit-return-type": no_explicit_return_type_default,
1095
1149
  "no-logic-in-params": no_logic_in_params_default,
1096
1150
  "prefer-destructuring-params": prefer_destructuring_params_default,
@@ -1114,7 +1168,8 @@ var baseRules = {
1114
1168
  "nextfriday/prefer-named-param-types": "warn",
1115
1169
  "nextfriday/prefer-react-import-types": "warn",
1116
1170
  "nextfriday/no-complex-inline-return": "warn",
1117
- "nextfriday/no-logic-in-params": "warn"
1171
+ "nextfriday/no-logic-in-params": "warn",
1172
+ "nextfriday/no-env-fallback": "warn"
1118
1173
  };
1119
1174
  var baseRecommendedRules = {
1120
1175
  "nextfriday/no-emoji": "error",
@@ -1126,7 +1181,8 @@ var baseRecommendedRules = {
1126
1181
  "nextfriday/prefer-named-param-types": "error",
1127
1182
  "nextfriday/prefer-react-import-types": "error",
1128
1183
  "nextfriday/no-complex-inline-return": "error",
1129
- "nextfriday/no-logic-in-params": "error"
1184
+ "nextfriday/no-logic-in-params": "error",
1185
+ "nextfriday/no-env-fallback": "error"
1130
1186
  };
1131
1187
  var jsxRules = {
1132
1188
  "nextfriday/jsx-pascal-case": "warn",