@bigbinary/eslint-plugin-neeto 1.1.24 → 1.1.26

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 +2 -1
  2. package/dist/index.js +174 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -46,7 +46,8 @@ module.exports = {
46
46
 
47
47
  ## Exported rules
48
48
 
49
-
49
+ - [use-use-query-client-hook](./docs/src/rules/use-use-query-client-hook.md)
50
+ - [use-early-return](./docs/src/rules/use-early-return.md)
50
51
  - [use-classnames-for-dynamic-classes](./docs/src/rules/use-classnames-for-dynamic-classes.md)
51
52
  - [use-use-mutation-with-invalidation-hook](./docs/src/rules/use-use-mutation-with-invalidation-hook.md)
52
53
  - [no-withT-for-smart-components](./docs/src/rules/no-withT-for-smart-components.md)
package/dist/index.js CHANGED
@@ -42,6 +42,8 @@
42
42
  var commonResolve$2 = loadJS$2("node_modules/@bigbinary/neeto-commons-frontend/configs/webpack/resolve.js");
43
43
  var resolve$2 = ramda.mergeDeepLeft(projectResolve$2, commonResolve$2);
44
44
  var rules = {
45
+ "@bigbinary/neeto/use-use-query-client-hook": "error",
46
+ "@bigbinary/neeto/use-early-return": "warn",
45
47
  "@bigbinary/neeto/use-classnames-for-dynamic-classes": "error",
46
48
  "@bigbinary/neeto/use-use-mutation-with-invalidation-hook": "error",
47
49
  "@bigbinary/neeto/no-withT-for-smart-components": "error",
@@ -553,6 +555,8 @@
553
555
  var MOVE_SPREAD_ATTRIBUTES_TO_TOP = "Move spread attribute to top";
554
556
  var USE_USE_MUTATION_WITH_INVALIDATION = "Use useMutationWithInvalidation from 'neetocommons/react-utils'";
555
557
  var USE_CLASSNAMES_PACKAGE = "Use classnames package for dynamic classes";
558
+ var USE_USE_QUERY_CLIENT_HOOK = "Use 'useQueryClient' hook from 'react-query'";
559
+ var USE_EARLY_RETURN = "Use early return to avoid nested statement";
556
560
 
557
561
  var PACKAGES_TO_CHECK = ["@bigbinary/neeto-molecules", "@bigbinary/neetoui", "@bigbinary/neeto-commons-frontend"];
558
562
 
@@ -6001,7 +6005,7 @@
6001
6005
  var BREAK_STATEMENT_PATTERN = {
6002
6006
  type: TYPES.BREAK_STATEMENT
6003
6007
  };
6004
- var RETURN_STATEMENT_PATTERN = {
6008
+ var RETURN_STATEMENT_PATTERN$1 = {
6005
6009
  type: TYPES.RETURN_STATEMENT
6006
6010
  };
6007
6011
  var ARRAY_LENGTH_TEST_PATTERN = {
@@ -6044,7 +6048,7 @@
6044
6048
  var _blockStatement$body = _slicedToArray(blockStatement.body, 2),
6045
6049
  firstStatement = _blockStatement$body[0],
6046
6050
  secondStatement = _blockStatement$body[1];
6047
- if (!(pure.matches(USE_TRANSLATION_HOOK_PATTERN, firstStatement) && pure.matches(RETURN_STATEMENT_PATTERN, secondStatement))) {
6051
+ if (!(pure.matches(USE_TRANSLATION_HOOK_PATTERN, firstStatement) && pure.matches(RETURN_STATEMENT_PATTERN$1, secondStatement))) {
6048
6052
  return;
6049
6053
  }
6050
6054
  context.report({
@@ -8133,7 +8137,7 @@
8133
8137
  };
8134
8138
 
8135
8139
  var isForLoopReplacable = function isForLoopReplacable(node) {
8136
- return ramda.not(patternExistsDeep(BREAK_STATEMENT_PATTERN, node.body) || patternExistsDeep(RETURN_STATEMENT_PATTERN, node.body) || patternExistsDeep(CHAR_AT_PATTERN, node.body));
8140
+ return ramda.not(patternExistsDeep(BREAK_STATEMENT_PATTERN, node.body) || patternExistsDeep(RETURN_STATEMENT_PATTERN$1, node.body) || patternExistsDeep(CHAR_AT_PATTERN, node.body));
8137
8141
  };
8138
8142
  var useArrayMethods = {
8139
8143
  meta: {
@@ -8811,6 +8815,69 @@
8811
8815
  }
8812
8816
  };
8813
8817
 
8818
+ var RETURN_STATEMENT_PATTERN = {
8819
+ type: TYPES.RETURN_STATEMENT
8820
+ };
8821
+ var RETURN_BLOCK_PATTERN = {
8822
+ type: TYPES.BLOCK_STATEMENT,
8823
+ body: function body(_body) {
8824
+ return _body.length === 1 && pure.matches(RETURN_STATEMENT_PATTERN, _body[0]);
8825
+ }
8826
+ };
8827
+
8828
+ var useEarlyReturn = {
8829
+ meta: {
8830
+ type: "suggestion",
8831
+ docs: {
8832
+ url: "https://github.com/bigbinary/eslint-plugin-neeto/blob/main/docs/src/rules/use-early-return.md",
8833
+ description: "Use early return to avoid nested statements in a function"
8834
+ },
8835
+ fixable: "code"
8836
+ },
8837
+ create: function create(context) {
8838
+ return {
8839
+ ":matches(FunctionDeclaration, ArrowFunctionExpression) > BlockStatement > IfStatement:first-child": function matchesFunctionDeclarationArrowFunctionExpressionBlockStatementIfStatementFirstChild(node) {
8840
+ // checks if a node is `return` type or `block` with only a `return` type
8841
+ var isReturnBlock = ramda.either(pure.matches(RETURN_STATEMENT_PATTERN), pure.matches(RETURN_BLOCK_PATTERN));
8842
+ var ensurePunctuation = function ensurePunctuation(text) {
8843
+ return text.endsWith(";") ? text : "".concat(text, ";");
8844
+ };
8845
+ if (
8846
+ // ignore if:
8847
+ node.parent.body.length > 1 ||
8848
+ // function includes other statements.
8849
+ node.consequent.type !== TYPES.BLOCK_STATEMENT ||
8850
+ // avoid inline `if` statement.
8851
+ isReturnBlock(node.consequent) ||
8852
+ // `if` block only has return statement.
8853
+ node.alternate && !isReturnBlock(node.alternate) ||
8854
+ // `else` block has statements other than return.
8855
+ node.alternate && node.alternate.type === TYPES.IF_STATEMENT // nested if-else ladder
8856
+ ) {
8857
+ return;
8858
+ }
8859
+ var fix = function fix(fixer) {
8860
+ var condition = context.getSourceCode().getText(node.test);
8861
+ var consequent = context.getSourceCode().getText(node.consequent).replace(/^\{|\}$/g, "");
8862
+ var alternate = "return;";
8863
+ if (node.alternate && isReturnBlock(node.alternate)) {
8864
+ alternate = context.getSourceCode().getText(node.alternate);
8865
+ if (node.alternate.type === TYPES.RETURN_STATEMENT) {
8866
+ alternate = ensurePunctuation(alternate);
8867
+ }
8868
+ }
8869
+ return [fixer.insertTextBefore(node, "if(!(".concat(condition, ")) ").concat(alternate)), fixer.replaceText(node, consequent)];
8870
+ };
8871
+ context.report({
8872
+ node: node,
8873
+ message: USE_EARLY_RETURN,
8874
+ fix: fix
8875
+ });
8876
+ }
8877
+ };
8878
+ }
8879
+ };
8880
+
8814
8881
  const defaultOpts$2 = {
8815
8882
  xml: false,
8816
8883
  decodeEntities: true,
@@ -26665,6 +26732,108 @@
26665
26732
  }
26666
26733
  };
26667
26734
 
26735
+ // import queryClient from "..";
26736
+ var QUERY_CLIENT_IMPORT_PATTERN = {
26737
+ type: TYPES.IMPORT_DECLARATION,
26738
+ specifiers: [{
26739
+ type: TYPES.IMPORT_DEFAULT_SPECIFIER,
26740
+ local: {
26741
+ type: TYPES.IDENTIFIER,
26742
+ name: "queryClient"
26743
+ }
26744
+ }]
26745
+ };
26746
+
26747
+ // import { useQueryClient } from "react-query";
26748
+ var USE_QUERY_CLIENT_IMPORT_PATTERN = {
26749
+ type: TYPES.IMPORT_DECLARATION,
26750
+ source: {
26751
+ type: TYPES.LITERAL,
26752
+ value: "react-query"
26753
+ },
26754
+ specifiers: pure.existsBy({
26755
+ type: TYPES.IMPORT_SPECIFIER,
26756
+ local: {
26757
+ type: TYPES.IDENTIFIER,
26758
+ name: "useQueryClient"
26759
+ }
26760
+ })
26761
+ };
26762
+
26763
+ // import {...} from "react-query";
26764
+ var REACT_QUERY_IMPORT_PATTERN = {
26765
+ type: TYPES.IMPORT_DECLARATION,
26766
+ source: {
26767
+ type: TYPES.LITERAL,
26768
+ value: "react-query"
26769
+ },
26770
+ specifiers: [{
26771
+ type: TYPES.IMPORT_SPECIFIER
26772
+ }]
26773
+ };
26774
+
26775
+ var getQueryClientInitializationFix = function getQueryClientInitializationFix(context, fixer, body) {
26776
+ if (body.type === TYPES.BLOCK_STATEMENT) {
26777
+ var indentLevel = context.getSourceCode().getFirstToken(body.body[0]).loc.start.column;
26778
+ return fixer.insertTextBefore(body.body[0], "const queryClient = useQueryClient();\n".concat(" ".repeat(indentLevel)));
26779
+ }
26780
+ return fixer.replaceText(body, "{ const queryClient = useQueryClient(); return (".concat(context.getSourceCode().getText(body), ") }"));
26781
+ };
26782
+
26783
+ var useUseQueryClientHook = {
26784
+ meta: {
26785
+ type: "problem",
26786
+ docs: {
26787
+ url: "https://github.com/bigbinary/eslint-plugin-neeto/blob/main/docs/src/rules/use-use-query-client-hook.md",
26788
+ description: "Enforce use of useQueryClient hook instead of direct queryClient import"
26789
+ },
26790
+ fixable: "code"
26791
+ },
26792
+ create: function create(context) {
26793
+ return {
26794
+ VariableDeclarator: function VariableDeclarator(node) {
26795
+ var _node$parent, _findBy2;
26796
+ if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.parent.type) !== TYPES.PROGRAM) return;
26797
+ var text = context.getSourceCode().getText(node);
26798
+ if (!text.includes("queryClient.") || text.includes("const queryClient = useQueryClient();")) {
26799
+ return;
26800
+ }
26801
+ var body = node.init.body || ((_findBy2 = pure._findBy({
26802
+ type: TYPES.ARROW_FUNCTION_EXPRESSION
26803
+ }, node.init.arguments)) === null || _findBy2 === void 0 ? void 0 : _findBy2.body);
26804
+ var allImports = getAllImports(node);
26805
+ var queryClientImport = pure.findBy(QUERY_CLIENT_IMPORT_PATTERN, allImports);
26806
+ if (!queryClientImport || !body) return;
26807
+ if (!(/^[A-Z]/.test(node.id.name) || node.id.name.startsWith("use"))) {
26808
+ context.report({
26809
+ node: queryClientImport,
26810
+ message: USE_USE_QUERY_CLIENT_HOOK
26811
+ });
26812
+ return;
26813
+ }
26814
+ context.report({
26815
+ node: queryClientImport,
26816
+ message: USE_USE_QUERY_CLIENT_HOOK,
26817
+ fix: function fix(fixer) {
26818
+ var initializeQueryClient = getQueryClientInitializationFix(context, fixer, body);
26819
+ var importExists = pure.existsBy(USE_QUERY_CLIENT_IMPORT_PATTERN, allImports);
26820
+ if (!importExists) {
26821
+ var addImport = addFunctionImport({
26822
+ context: context,
26823
+ fixer: fixer,
26824
+ functions: ["useQueryClient"],
26825
+ importPattern: REACT_QUERY_IMPORT_PATTERN
26826
+ });
26827
+ return [initializeQueryClient, addImport];
26828
+ }
26829
+ return initializeQueryClient;
26830
+ }
26831
+ });
26832
+ }
26833
+ };
26834
+ }
26835
+ };
26836
+
26668
26837
  var useWebpackAlias = {
26669
26838
  meta: {
26670
26839
  type: "suggestion",
@@ -27248,6 +27417,8 @@
27248
27417
 
27249
27418
  var index = {
27250
27419
  rules: {
27420
+ "use-use-query-client-hook": useUseQueryClientHook,
27421
+ "use-early-return": useEarlyReturn,
27251
27422
  "use-classnames-for-dynamic-classes": useClassnamesForDynamicClasses,
27252
27423
  "use-use-mutation-with-invalidation-hook": useUseMutationWithInvalidationHook,
27253
27424
  "no-withT-for-smart-components": noWithTForSmartComponents,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigbinary/eslint-plugin-neeto",
3
- "version": "1.1.24",
3
+ "version": "1.1.26",
4
4
  "main": "dist/index.js",
5
5
  "license": "UNLICENSED",
6
6
  "scripts": {