@agilebot/eslint-plugin 0.5.1 → 0.5.3

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.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/dist/index.js +75 -13
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @agilebot/eslint-plugin
2
2
 
3
- Agilebot extended ESLint rules. For @agilebot/eslint-config.
3
+ [![npm](https://img.shields.io/npm/v/@agilebot/eslint-plugin?color=444&label=)](https://npmjs.com/package/@agilebot/eslint-plugin)
4
+
5
+ Agilebot extended ESLint rules. Designed for @agilebot/eslint-config.
4
6
 
5
7
  ### Usage
6
8
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license @agilebot/eslint-plugin v0.5.1
2
+ * @license @agilebot/eslint-plugin v0.5.3
3
3
  *
4
4
  * Copyright (c) Agilebot, Inc. and its affiliates.
5
5
  *
@@ -792,6 +792,14 @@ var reactBetterExhaustiveDeps = {
792
792
  enableDangerousAutofixThisMayCauseInfiniteLoops: {
793
793
  type: 'boolean'
794
794
  },
795
+ customHooks: {
796
+ type: 'object',
797
+ additionalProperties: {
798
+ callbackIndex: {
799
+ type: 'number'
800
+ }
801
+ }
802
+ },
795
803
  staticHooks: {
796
804
  type: 'object',
797
805
  additionalProperties: {
@@ -819,11 +827,13 @@ var reactBetterExhaustiveDeps = {
819
827
  create(context) {
820
828
  const additionalHooks = context.options && context.options[0] && context.options[0].additionalHooks ? new RegExp(context.options[0].additionalHooks) : undefined;
821
829
  const enableDangerousAutofixThisMayCauseInfiniteLoops = context.options && context.options[0] && context.options[0].enableDangerousAutofixThisMayCauseInfiniteLoops || false;
830
+ const customHooks = context.options && context.options[0] && context.options[0].customHooks || {};
822
831
  const staticHooks = context.options && context.options[0] && context.options[0].staticHooks || {};
823
832
  const checkMemoizedVariableIsStatic = context.options && context.options[0] && context.options[0].checkMemoizedVariableIsStatic || false;
824
833
  const options = {
825
834
  additionalHooks,
826
835
  enableDangerousAutofixThisMayCauseInfiniteLoops,
836
+ customHooks,
827
837
  staticHooks,
828
838
  checkMemoizedVariableIsStatic
829
839
  };
@@ -861,10 +871,20 @@ var reactBetterExhaustiveDeps = {
861
871
  }
862
872
  function visitFunctionWithDependencies(node, declaredDependenciesNode, reactiveHook, reactiveHookName, isEffect) {
863
873
  if (isEffect && node.async) {
864
- reportProblem({
865
- node: node,
866
- message: "Effect callbacks are synchronous to prevent race conditions. " + "Put the async function inside:\n\n" + 'useEffect(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + ' // ...\n' + ' }\n' + ' fetchData();\n' + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + 'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching'
867
- });
874
+ let isCustomHook = false;
875
+ if (options.customHooks) {
876
+ Object.entries(options.customHooks).forEach(([key, customParts]) => {
877
+ if (typeof customParts === 'object' && new RegExp(key).test(reactiveHookName)) {
878
+ isCustomHook = true;
879
+ }
880
+ });
881
+ }
882
+ if (!isCustomHook) {
883
+ reportProblem({
884
+ node: node,
885
+ message: "Effect callbacks are synchronous to prevent race conditions. " + "Put the async function inside:\n\n" + 'useEffect(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + ' // ...\n' + ' }\n' + ' fetchData();\n' + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + 'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching'
886
+ });
887
+ }
868
888
  }
869
889
  const scope = scopeManager.acquire(node);
870
890
  const pureScopes = new Set();
@@ -1904,6 +1924,22 @@ function getReactiveHookCallbackIndex(calleeNode, options) {
1904
1924
  case 'useImperativeHandle':
1905
1925
  return 1;
1906
1926
  default:
1927
+ if (node === calleeNode && options && options.customHooks) {
1928
+ let name;
1929
+ try {
1930
+ name = analyzePropertyChain(node, null);
1931
+ } catch (err) {
1932
+ if (/Unsupported node type/.test(err.message)) {
1933
+ return 0;
1934
+ }
1935
+ throw err;
1936
+ }
1937
+ for (const [key, customParts] of Object.entries(options.customHooks)) {
1938
+ if (typeof customParts === 'object' && typeof customParts.callbackIndex === 'number' && new RegExp(key).test(name)) {
1939
+ return customParts.callbackIndex;
1940
+ }
1941
+ }
1942
+ }
1907
1943
  if (node === calleeNode && options && options.additionalHooks) {
1908
1944
  let name;
1909
1945
  try {
@@ -2627,8 +2663,8 @@ var tssUnusedClasses = createRule({
2627
2663
  const RULE_NAME = 'var-naming';
2628
2664
  const reactGlobalFuncs = new Set(['createContext', 'forwardRef', 'lazy', 'memo', 'combineProviders']);
2629
2665
  const reactFCTypes = new Set(['FC', 'FunctionComponent', 'VFC', 'VoidFunctionComponent']);
2630
- const otherTypes = new Set(['StoryObj', 'StoryFn']);
2631
- const defaultExcludes = ['^(__dirname|__filename)$', '(.*)Event$'];
2666
+ const defaultExcludeTypes = ['StoryObj', 'StoryFn'];
2667
+ const defaultExcludeNames = ['^(__dirname|__filename)$', '(.*)Event$'];
2632
2668
  var varNaming = createRule({
2633
2669
  name: RULE_NAME,
2634
2670
  meta: {
@@ -2652,7 +2688,19 @@ var varNaming = createRule({
2652
2688
  "enum": ['camelCase', 'PascalCase', 'UPPER_CASE']
2653
2689
  }
2654
2690
  },
2655
- exclude: {
2691
+ excludeNames: {
2692
+ type: 'array',
2693
+ items: {
2694
+ type: 'string'
2695
+ }
2696
+ },
2697
+ excludeFuncs: {
2698
+ type: 'array',
2699
+ items: {
2700
+ type: 'string'
2701
+ }
2702
+ },
2703
+ excludeTypes: {
2656
2704
  type: 'array',
2657
2705
  items: {
2658
2706
  type: 'string'
@@ -2673,8 +2721,11 @@ var varNaming = createRule({
2673
2721
  }
2674
2722
  const funcFormat = context.options[0].funcFormat || ['camelCase'];
2675
2723
  const varFormat = context.options[0].varFormat || ['camelCase', 'UPPER_CASE'];
2676
- let exclude = context.options[0].exclude || [];
2677
- exclude = [...defaultExcludes, ...exclude];
2724
+ let excludeNames = context.options[0].excludeNames || [];
2725
+ excludeNames = [...defaultExcludeNames, ...excludeNames];
2726
+ const excludeFuncs = context.options[0].excludeFuncs || [];
2727
+ let excludeTypes = context.options[0].excludeTypes || [];
2728
+ excludeTypes = [...defaultExcludeTypes, ...excludeTypes];
2678
2729
  function validate(type, {
2679
2730
  node,
2680
2731
  name
@@ -2801,14 +2852,18 @@ var varNaming = createRule({
2801
2852
  }
2802
2853
  } else if (node.id) {
2803
2854
  const varName = node.id.name;
2804
- for (const excludeRegex of exclude) {
2855
+ for (const excludeRegex of excludeNames) {
2805
2856
  if (new RegExp(excludeRegex).test(varName)) {
2806
2857
  return;
2807
2858
  }
2808
2859
  }
2809
2860
  const typeName = getTypeReference(node);
2810
- if (typeName && otherTypes.has(typeName)) {
2811
- return;
2861
+ if (typeName) {
2862
+ for (const excludeRegex of excludeTypes) {
2863
+ if (new RegExp(excludeRegex).test(typeName)) {
2864
+ return;
2865
+ }
2866
+ }
2812
2867
  }
2813
2868
  if (node.id.parent && node.id.parent.init) {
2814
2869
  let calleeName;
@@ -2820,6 +2875,13 @@ var varNaming = createRule({
2820
2875
  shouldCheckReact = true;
2821
2876
  calleeName = node.id.parent.init.expression.callee.name;
2822
2877
  }
2878
+ if (calleeName) {
2879
+ for (const excludeRegex of excludeFuncs) {
2880
+ if (new RegExp(excludeRegex).test(calleeName)) {
2881
+ return;
2882
+ }
2883
+ }
2884
+ }
2823
2885
  if (shouldCheckReact) {
2824
2886
  if (!calleeName) {
2825
2887
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agilebot/eslint-plugin",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Agilebot's ESLint plugin",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,11 +19,11 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@eslint/compat": "^1.1.1",
22
- "@typescript-eslint/utils": "~8.5.0",
22
+ "@typescript-eslint/utils": "~8.7.0",
23
23
  "eslint-plugin-deprecation": "^3.0.0",
24
24
  "eslint-plugin-react": "^7.35.0",
25
25
  "eslint-plugin-react-hooks": "^4.6.2",
26
- "@agilebot/eslint-utils": "0.5.1"
26
+ "@agilebot/eslint-utils": "0.5.3"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
@@ -36,7 +36,7 @@
36
36
  "@types/estree": "^1.0.5",
37
37
  "color-name": "^2.0.0",
38
38
  "eslint-vitest-rule-tester": "^0.6.1",
39
- "typescript-eslint": "~8.5.0"
39
+ "typescript-eslint": "~8.7.0"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "rollup -c rollup.config.mjs",