eslint-plugin-remeda 1.7.0 → 1.8.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/dist/index.cjs CHANGED
@@ -41,12 +41,13 @@ var main = "dist/index.js";
41
41
  var scripts = {
42
42
  "build": "tsdown",
43
43
  "typecheck": "tsc",
44
- "lint": "eslint",
44
+ "lint": "eslint --max-warnings=0",
45
45
  "knip": "knip",
46
46
  "test:watch": "vitest --ui",
47
47
  "test": "vitest run",
48
- "attw": "attw --pack .",
49
- "qa": "pnpm typecheck && pnpm test && pnpm knip && attw",
48
+ "check-sheriff-inconsistencies": "sheriff",
49
+ "attw": "attw --ignore-rules=false-export-default --pack .",
50
+ "qa": "pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm knip && pnpm attw && pnpm check-sheriff-inconsistencies",
50
51
  "nuke": "rm -rf node_modules pnpm-lock.yaml",
51
52
  "update:eslint-docs": "eslint-doc-generator",
52
53
  "lint:eslint-docs": "pnpm update:eslint-docs -- --check",
@@ -80,7 +81,7 @@ var bugs = "https://github.com/AndreaPontrandolfo/eslint-plugin-remeda/issues";
80
81
  var peerDependencies = { "eslint": ">=9.0.0" };
81
82
  var devDependencies = {
82
83
  "@arethetypeswrong/cli": "^0.17.4",
83
- "@sherifforg/cli": "^8.2.0",
84
+ "@sherifforg/cli": "^8.3.0",
84
85
  "@types/lodash-es": "^4.17.12",
85
86
  "@types/node": "^22.14.0",
86
87
  "@typescript-eslint/utils": "^8.29.0",
@@ -202,8 +203,8 @@ function isMemberExpOf$1(node, objectName, { maxLength = Number.MAX_VALUE, allow
202
203
  let currentNode = node;
203
204
  let depth = maxLength;
204
205
  while (currentNode && depth) if (allowComputed || isPropAccess(currentNode)) {
205
- if (currentNode.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && "name" in currentNode.object && currentNode.object.name === objectName) return true;
206
- currentNode = "object" in currentNode ? currentNode.object : void 0;
206
+ if (currentNode.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && currentNode.object.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && currentNode.object.name === objectName) return true;
207
+ currentNode = currentNode.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression ? currentNode.object : void 0;
207
208
  depth = depth - 1;
208
209
  } else return false;
209
210
  return false;
@@ -239,7 +240,7 @@ function hasOnlyOneStatement$2(func) {
239
240
  * @param node - The node to check.
240
241
  */
241
242
  function isObjectOfMethodCall(node) {
242
- return (0, lodash_es.get)(node, "parent.object") === node && (0, lodash_es.get)(node, "parent.parent.type") === "CallExpression";
243
+ return (0, lodash_es.get)(node, "parent.object") === node && (0, lodash_es.get)(node, "parent.parent.type") === __typescript_eslint_utils.AST_NODE_TYPES.CallExpression;
243
244
  }
244
245
  /**
245
246
  * Returns whether the node is a literal.
@@ -405,7 +406,9 @@ function getExpressionComparedToInt$1(node, value$1, checkOver) {
405
406
  *
406
407
  * @param node - The node to check.
407
408
  */
408
- const isIndexOfCall = (node) => isMethodCall$1(node) && getMethodName$2(node) === "indexOf";
409
+ const isIndexOfCall = (node) => {
410
+ return isMethodCall$1(node) && getMethodName$2(node) === "indexOf";
411
+ };
409
412
  /**
410
413
  * Returns whether the node is a call to findIndex.
411
414
  *
@@ -549,7 +552,7 @@ __export(methodData_exports, {
549
552
  fromPairs: () => fromPairs,
550
553
  functions: () => functions,
551
554
  functionsIn: () => functionsIn,
552
- get: () => get$5,
555
+ get: () => get$4,
553
556
  groupBy: () => groupBy,
554
557
  gt: () => gt,
555
558
  gte: () => gte,
@@ -593,14 +596,14 @@ __export(methodData_exports, {
593
596
  isNative: () => isNative,
594
597
  isNull: () => isNull,
595
598
  isNullish: () => isNullish,
596
- isNumber: () => isNumber$1,
599
+ isNumber: () => isNumber$2,
597
600
  isObject: () => isObject$1,
598
601
  isObjectLike: () => isObjectLike,
599
602
  isPlainObject: () => isPlainObject,
600
603
  isRegExp: () => isRegExp,
601
604
  isSafeInteger: () => isSafeInteger,
602
605
  isSet: () => isSet,
603
- isString: () => isString,
606
+ isString: () => isString$1,
604
607
  isSymbol: () => isSymbol,
605
608
  isTypedArray: () => isTypedArray,
606
609
  isUndefined: () => isUndefined,
@@ -1324,7 +1327,7 @@ const functionsIn = {
1324
1327
  iteratee: false,
1325
1328
  args: 1
1326
1329
  };
1327
- const get$5 = {
1330
+ const get$4 = {
1328
1331
  wrapper: false,
1329
1332
  shorthand: false,
1330
1333
  chainable: false,
@@ -1633,7 +1636,7 @@ const isNull = {
1633
1636
  iteratee: false,
1634
1637
  args: 1
1635
1638
  };
1636
- const isNumber$1 = {
1639
+ const isNumber$2 = {
1637
1640
  wrapper: false,
1638
1641
  shorthand: false,
1639
1642
  chainable: false,
@@ -1682,7 +1685,7 @@ const isSet = {
1682
1685
  iteratee: false,
1683
1686
  args: 1
1684
1687
  };
1685
- const isString = {
1688
+ const isString$1 = {
1686
1689
  wrapper: false,
1687
1690
  shorthand: false,
1688
1691
  chainable: false,
@@ -2889,8 +2892,7 @@ const zipWith = {
2889
2892
  *
2890
2893
  */
2891
2894
  function methodSupportsShorthand(method$1, shorthandType) {
2892
- const path = `${method$1}.shorthand`;
2893
- const methodShorthandData = (0, lodash_es.get)(methodData_exports, path);
2895
+ const methodShorthandData = methodData_exports[method$1].shorthand;
2894
2896
  const isShorthandObject = (0, lodash_es.isObject)(methodShorthandData);
2895
2897
  return isShorthandObject ? Boolean(shorthandType && methodShorthandData[shorthandType]) : Boolean(methodShorthandData);
2896
2898
  }
@@ -3088,8 +3090,9 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
3088
3090
  let iterateeIndex;
3089
3091
  if (remedaContext.isRemedaCall(node)) {
3090
3092
  const method$1 = astUtil_default.getMethodName(node);
3093
+ if (!(0, lodash_es.isString)(method$1)) return;
3091
3094
  iterateeIndex = getIterateeIndex(method$1);
3092
- reporter(node, node.arguments[iterateeIndex], {
3095
+ if ((0, lodash_es.isNumber)(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
3093
3096
  callType: "method",
3094
3097
  method: method$1,
3095
3098
  remedaContext
@@ -3098,7 +3101,7 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
3098
3101
  const method$1 = remedaContext.getImportedRemedaMethod(node);
3099
3102
  if (method$1) {
3100
3103
  iterateeIndex = getIterateeIndex(method$1);
3101
- reporter(node, node.arguments[iterateeIndex], {
3104
+ if ((0, lodash_es.isNumber)(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
3102
3105
  method: method$1,
3103
3106
  callType: "single",
3104
3107
  remedaContext
@@ -3108,10 +3111,11 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
3108
3111
  };
3109
3112
  }
3110
3113
  function isRemedaCallToMethod(node, method$1, remedaContext) {
3114
+ if (!node) return false;
3111
3115
  return remedaContext.isRemedaCall(node) && isCallToMethod(node, method$1);
3112
3116
  }
3113
3117
  function isCallToRemedaMethod(node, method$1, remedaContext) {
3114
- if (!node || node.type !== "CallExpression") return false;
3118
+ if (!node || node.type !== __typescript_eslint_utils.AST_NODE_TYPES.CallExpression) return false;
3115
3119
  return isRemedaCallToMethod(node, method$1, remedaContext) || method$1 === remedaContext.getImportedRemedaMethod(node);
3116
3120
  }
3117
3121
  function getRemedaMethodVisitors(context, remedaCallExpVisitor) {
@@ -3141,7 +3145,7 @@ function isSideEffectIterationMethod(method$1) {
3141
3145
  return (0, lodash_es.includes)(getSideEffectIterationMethods(), method$1);
3142
3146
  }
3143
3147
  function isParentCommit(node, callType) {
3144
- return callType === "chained" && isCallToMethod(node.parent.parent, "commit");
3148
+ return callType === "chained" && node.parent.parent && isCallToMethod(node.parent.parent, "commit");
3145
3149
  }
3146
3150
  var collection_method_value_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
3147
3151
  name: RULE_NAME$14,
@@ -3193,18 +3197,22 @@ var collection_return_default = __typescript_eslint_utils.ESLintUtils.RuleCreato
3193
3197
  create(context) {
3194
3198
  const remedaContext = getRemedaContext(context);
3195
3199
  return {
3196
- "CallExpression:exit": getRemedaMethodCallExpVisitor(remedaContext, (node, iteratee$1, { method: method$1 }) => {
3197
- if (!isCollectionMethod(method$1)) return;
3198
- if (!astUtil_default.isFunctionDefinitionWithBlock(iteratee$1) || iteratee$1.async || iteratee$1.generator) return;
3199
- const hasReturnStatement = iteratee$1.body.type === __typescript_eslint_utils.AST_NODE_TYPES.BlockStatement && iteratee$1.body.body.some((statement) => {
3200
- return statement.type === __typescript_eslint_utils.AST_NODE_TYPES.ReturnStatement;
3201
- });
3202
- if (!hasReturnStatement) context.report({
3203
- node,
3204
- messageId: "no-return",
3205
- data: { method: method$1 }
3206
- });
3207
- }),
3200
+ "CallExpression:exit": getRemedaMethodCallExpVisitor(
3201
+ remedaContext,
3202
+ // @ts-expect-error
3203
+ (node, iteratee$1, { method: method$1 }) => {
3204
+ if (!isCollectionMethod(method$1)) return;
3205
+ if (!astUtil_default.isFunctionDefinitionWithBlock(iteratee$1) || iteratee$1.async || iteratee$1.generator) return;
3206
+ const hasReturnStatement = iteratee$1.body.type === __typescript_eslint_utils.AST_NODE_TYPES.BlockStatement && iteratee$1.body.body.some((statement) => {
3207
+ return statement.type === __typescript_eslint_utils.AST_NODE_TYPES.ReturnStatement;
3208
+ });
3209
+ if (!hasReturnStatement) context.report({
3210
+ node,
3211
+ messageId: "no-return",
3212
+ data: { method: method$1 }
3213
+ });
3214
+ }
3215
+ ),
3208
3216
  ...remedaContext.getImportVisitors()
3209
3217
  };
3210
3218
  }
@@ -3232,8 +3240,14 @@ var prefer_constant_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(
3232
3240
  description: "enforce using R.constant over functions returning literals",
3233
3241
  url: getDocsUrl(RULE_NAME$12)
3234
3242
  },
3235
- schema: [{ type: "boolean" }, { type: "boolean" }],
3236
- defaultOptions: [],
3243
+ schema: [{
3244
+ type: "boolean",
3245
+ description: "Whether to check arrow functions for literals in return statements. Default: true."
3246
+ }, {
3247
+ type: "boolean",
3248
+ description: "Whether to check function declarations for literals in return statements. Default: false."
3249
+ }],
3250
+ defaultOptions: [true, false],
3237
3251
  messages: { [MESSAGE_ID$1]: "Prefer R.constant over a function returning a literal" }
3238
3252
  },
3239
3253
  defaultOptions: [true, false],
@@ -3321,7 +3335,7 @@ var prefer_filter_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(ge
3321
3335
  defaultOptions: [{ maxPropertyPathLength: 3 }],
3322
3336
  messages: { "prefer-filter": MESSAGE$2 }
3323
3337
  },
3324
- defaultOptions: [{}],
3338
+ defaultOptions: [{ maxPropertyPathLength: 3 }],
3325
3339
  create(context, [options]) {
3326
3340
  const DEFAULT_MAX_PROPERTY_PATH_LENGTH = 3;
3327
3341
  const maxLength = options.maxPropertyPathLength ?? DEFAULT_MAX_PROPERTY_PATH_LENGTH;
@@ -3353,7 +3367,7 @@ function isZeroIndexAccess(node) {
3353
3367
  return node.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && node.property.type === __typescript_eslint_utils.AST_NODE_TYPES.Literal && node.property.value === 0;
3354
3368
  }
3355
3369
  function isChainedBeforeMethod(callType, node, method$1) {
3356
- return callType === "chained" && isCallToMethod(node.parent?.parent, method$1);
3370
+ return callType === "chained" && node.parent?.parent !== void 0 && isCallToMethod(node.parent.parent, method$1);
3357
3371
  }
3358
3372
  var prefer_find_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
3359
3373
  name: RULE_NAME$9,
@@ -3373,7 +3387,7 @@ var prefer_find_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getD
3373
3387
  create(context) {
3374
3388
  return getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1, callType, remedaContext }) => {
3375
3389
  if (method$1 === "filter") {
3376
- if (isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
3390
+ if (node.parent && isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
3377
3391
  node,
3378
3392
  messageId: "prefer-find"
3379
3393
  });
@@ -3391,7 +3405,8 @@ var prefer_find_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getD
3391
3405
  const { getCaller } = astUtil_default;
3392
3406
  const RULE_NAME$8 = "prefer-flat-map";
3393
3407
  function isChainedMapFlatten(node) {
3394
- return isCallToMethod(getCaller(node), "map");
3408
+ const caller = getCaller(node);
3409
+ return caller ? isCallToMethod(caller, "map") : false;
3395
3410
  }
3396
3411
  var prefer_flat_map_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
3397
3412
  name: RULE_NAME$8,
@@ -3406,12 +3421,16 @@ var prefer_flat_map_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(
3406
3421
  },
3407
3422
  defaultOptions: [],
3408
3423
  create(context) {
3409
- return getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1, remedaContext }) => {
3410
- if (method$1 === "flat" && (isChainedMapFlatten(node) || isCallToRemedaMethod(node.arguments[0], "map", remedaContext))) context.report({
3411
- node,
3412
- messageId: "prefer-flat-map"
3413
- });
3414
- });
3424
+ return getRemedaMethodVisitors(
3425
+ context,
3426
+ // @ts-expect-error
3427
+ (node, iteratee$1, { method: method$1, remedaContext }) => {
3428
+ if (method$1 === "flat" && (isChainedMapFlatten(node) || isCallToRemedaMethod(node.arguments[0], "map", remedaContext))) context.report({
3429
+ node,
3430
+ messageId: "prefer-flat-map"
3431
+ });
3432
+ }
3433
+ );
3415
3434
  }
3416
3435
  });
3417
3436
 
@@ -3647,12 +3666,21 @@ var prefer_is_nullish_default = __typescript_eslint_utils.ESLintUtils.RuleCreato
3647
3666
  return isNegationExpression(node) && checkExpression(nil, "===", node.argument) || checkExpression(nil, "!==", node);
3648
3667
  }
3649
3668
  function isEquivalentExistingExpression(node, leftNil, rightNil) {
3669
+ if (node.type !== __typescript_eslint_utils.AST_NODE_TYPES.LogicalExpression) return false;
3650
3670
  const leftExp = checkExpression(leftNil, "===", node.left);
3651
- return leftExp && isEquivalentMemberExp(leftExp, checkExpression(rightNil, "===", node.right));
3671
+ return leftExp && isEquivalentMemberExp(
3672
+ leftExp,
3673
+ // @ts-expect-error
3674
+ checkExpression(rightNil, "===", node.right)
3675
+ );
3652
3676
  }
3653
3677
  function isEquivalentExistingNegation(node, leftNil, rightNil) {
3654
3678
  const leftExp = checkNegatedExpression(leftNil, node.left);
3655
- return leftExp && isEquivalentMemberExp(leftExp, checkNegatedExpression(rightNil, node.right));
3679
+ return leftExp && isEquivalentMemberExp(
3680
+ leftExp,
3681
+ // @ts-expect-error
3682
+ checkNegatedExpression(rightNil, node.right)
3683
+ );
3656
3684
  }
3657
3685
  const visitors = remedaContext.getImportVisitors();
3658
3686
  visitors.LogicalExpression = function(node) {
@@ -3674,11 +3702,11 @@ var prefer_is_nullish_default = __typescript_eslint_utils.ESLintUtils.RuleCreato
3674
3702
  //#region src/rules/prefer-map.ts
3675
3703
  const { getFirstFunctionLine, hasOnlyOneStatement, getMethodName, isFunctionDefinitionWithBlock, collectParameterValues } = astUtil_default;
3676
3704
  const RULE_NAME$4 = "prefer-map";
3677
- function onlyHasPush(func) {
3678
- const firstLine = getFirstFunctionLine(func);
3679
- const firstParam = (0, lodash_es.get)(func, "params[0]");
3680
- const exp = func && !isFunctionDefinitionWithBlock(func) ? firstLine : firstLine?.expression;
3681
- return func && hasOnlyOneStatement(func) && getMethodName(exp) === "push" && !(0, lodash_es.includes)(collectParameterValues(firstParam), (0, lodash_es.get)(exp, "callee.object.name"));
3705
+ function onlyHasPush(node) {
3706
+ const firstLine = getFirstFunctionLine(node);
3707
+ const firstParam = (0, lodash_es.get)(node, "params[0]");
3708
+ const exp = node && !isFunctionDefinitionWithBlock(node) ? firstLine : firstLine?.expression;
3709
+ return node && (node.type === __typescript_eslint_utils.AST_NODE_TYPES.ArrowFunctionExpression ? true : hasOnlyOneStatement(node)) && getMethodName(exp) === "push" && !(0, lodash_es.includes)(collectParameterValues(firstParam), (0, lodash_es.get)(exp, "callee.object.name"));
3682
3710
  }
3683
3711
  var prefer_map_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
3684
3712
  name: RULE_NAME$4,
@@ -3829,7 +3857,7 @@ var prefer_some_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getD
3829
3857
  defaultOptions: [],
3830
3858
  create(context) {
3831
3859
  const visitors = getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1 }) => {
3832
- if (method$1 === "findIndex" && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
3860
+ if (method$1 === "findIndex" && node.parent?.type === __typescript_eslint_utils.AST_NODE_TYPES.BinaryExpression && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
3833
3861
  node,
3834
3862
  messageId: "prefer-some"
3835
3863
  });
@@ -3904,7 +3932,7 @@ const configs = { recommended: {
3904
3932
  [`${pluginShortName}/prefer-constant`]: 2,
3905
3933
  [`${pluginShortName}/prefer-remeda-typecheck`]: 2,
3906
3934
  [`${pluginShortName}/prefer-nullish-coalescing`]: 2,
3907
- [`${pluginShortName}/prefer-filter`]: [2, 3],
3935
+ [`${pluginShortName}/prefer-filter`]: 2,
3908
3936
  [`${pluginShortName}/prefer-has-atleast`]: 2,
3909
3937
  [`${pluginShortName}/collection-method-value`]: 2,
3910
3938
  [`${pluginShortName}/collection-return`]: 2,
package/dist/index.d.cts CHANGED
@@ -60,7 +60,7 @@ declare const configs: {
60
60
  };
61
61
  };
62
62
  rules: {
63
- [x: string]: number | number[];
63
+ [x: string]: number;
64
64
  };
65
65
  };
66
66
  };
package/dist/index.d.ts CHANGED
@@ -60,7 +60,7 @@ declare const configs: {
60
60
  };
61
61
  };
62
62
  rules: {
63
- [x: string]: number | number[];
63
+ [x: string]: number;
64
64
  };
65
65
  };
66
66
  };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { capitalize, cond, defaults, find, flatMap, get, has, includes, isEmpty, isEqualWith, isMatch, isNumber, isObject, last, map, matches, matchesProperty, overEvery, overSome, property, some } from "lodash-es";
1
+ import { capitalize, cond, defaults, find, flatMap, get, has, includes, isEmpty, isEqualWith, isMatch, isNumber, isObject, isString, last, map, matches, matchesProperty, overEvery, overSome, property, some } from "lodash-es";
2
2
  import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
3
3
 
4
4
  //#region rolldown:runtime
@@ -21,12 +21,13 @@ var main = "dist/index.js";
21
21
  var scripts = {
22
22
  "build": "tsdown",
23
23
  "typecheck": "tsc",
24
- "lint": "eslint",
24
+ "lint": "eslint --max-warnings=0",
25
25
  "knip": "knip",
26
26
  "test:watch": "vitest --ui",
27
27
  "test": "vitest run",
28
- "attw": "attw --pack .",
29
- "qa": "pnpm typecheck && pnpm test && pnpm knip && attw",
28
+ "check-sheriff-inconsistencies": "sheriff",
29
+ "attw": "attw --ignore-rules=false-export-default --pack .",
30
+ "qa": "pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm knip && pnpm attw && pnpm check-sheriff-inconsistencies",
30
31
  "nuke": "rm -rf node_modules pnpm-lock.yaml",
31
32
  "update:eslint-docs": "eslint-doc-generator",
32
33
  "lint:eslint-docs": "pnpm update:eslint-docs -- --check",
@@ -60,7 +61,7 @@ var bugs = "https://github.com/AndreaPontrandolfo/eslint-plugin-remeda/issues";
60
61
  var peerDependencies = { "eslint": ">=9.0.0" };
61
62
  var devDependencies = {
62
63
  "@arethetypeswrong/cli": "^0.17.4",
63
- "@sherifforg/cli": "^8.2.0",
64
+ "@sherifforg/cli": "^8.3.0",
64
65
  "@types/lodash-es": "^4.17.12",
65
66
  "@types/node": "^22.14.0",
66
67
  "@typescript-eslint/utils": "^8.29.0",
@@ -182,8 +183,8 @@ function isMemberExpOf$1(node, objectName, { maxLength = Number.MAX_VALUE, allow
182
183
  let currentNode = node;
183
184
  let depth = maxLength;
184
185
  while (currentNode && depth) if (allowComputed || isPropAccess(currentNode)) {
185
- if (currentNode.type === AST_NODE_TYPES.MemberExpression && "name" in currentNode.object && currentNode.object.name === objectName) return true;
186
- currentNode = "object" in currentNode ? currentNode.object : void 0;
186
+ if (currentNode.type === AST_NODE_TYPES.MemberExpression && currentNode.object.type === AST_NODE_TYPES.Identifier && currentNode.object.name === objectName) return true;
187
+ currentNode = currentNode.type === AST_NODE_TYPES.MemberExpression ? currentNode.object : void 0;
187
188
  depth = depth - 1;
188
189
  } else return false;
189
190
  return false;
@@ -219,7 +220,7 @@ function hasOnlyOneStatement$2(func) {
219
220
  * @param node - The node to check.
220
221
  */
221
222
  function isObjectOfMethodCall(node) {
222
- return get(node, "parent.object") === node && get(node, "parent.parent.type") === "CallExpression";
223
+ return get(node, "parent.object") === node && get(node, "parent.parent.type") === AST_NODE_TYPES.CallExpression;
223
224
  }
224
225
  /**
225
226
  * Returns whether the node is a literal.
@@ -385,7 +386,9 @@ function getExpressionComparedToInt$1(node, value$1, checkOver) {
385
386
  *
386
387
  * @param node - The node to check.
387
388
  */
388
- const isIndexOfCall = (node) => isMethodCall$1(node) && getMethodName$2(node) === "indexOf";
389
+ const isIndexOfCall = (node) => {
390
+ return isMethodCall$1(node) && getMethodName$2(node) === "indexOf";
391
+ };
389
392
  /**
390
393
  * Returns whether the node is a call to findIndex.
391
394
  *
@@ -580,7 +583,7 @@ __export(methodData_exports, {
580
583
  isRegExp: () => isRegExp,
581
584
  isSafeInteger: () => isSafeInteger,
582
585
  isSet: () => isSet,
583
- isString: () => isString,
586
+ isString: () => isString$1,
584
587
  isSymbol: () => isSymbol,
585
588
  isTypedArray: () => isTypedArray,
586
589
  isUndefined: () => isUndefined,
@@ -1662,7 +1665,7 @@ const isSet = {
1662
1665
  iteratee: false,
1663
1666
  args: 1
1664
1667
  };
1665
- const isString = {
1668
+ const isString$1 = {
1666
1669
  wrapper: false,
1667
1670
  shorthand: false,
1668
1671
  chainable: false,
@@ -2869,8 +2872,7 @@ const zipWith = {
2869
2872
  *
2870
2873
  */
2871
2874
  function methodSupportsShorthand(method$1, shorthandType) {
2872
- const path = `${method$1}.shorthand`;
2873
- const methodShorthandData = get(methodData_exports, path);
2875
+ const methodShorthandData = methodData_exports[method$1].shorthand;
2874
2876
  const isShorthandObject = isObject(methodShorthandData);
2875
2877
  return isShorthandObject ? Boolean(shorthandType && methodShorthandData[shorthandType]) : Boolean(methodShorthandData);
2876
2878
  }
@@ -3068,8 +3070,9 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
3068
3070
  let iterateeIndex;
3069
3071
  if (remedaContext.isRemedaCall(node)) {
3070
3072
  const method$1 = astUtil_default.getMethodName(node);
3073
+ if (!isString(method$1)) return;
3071
3074
  iterateeIndex = getIterateeIndex(method$1);
3072
- reporter(node, node.arguments[iterateeIndex], {
3075
+ if (isNumber(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
3073
3076
  callType: "method",
3074
3077
  method: method$1,
3075
3078
  remedaContext
@@ -3078,7 +3081,7 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
3078
3081
  const method$1 = remedaContext.getImportedRemedaMethod(node);
3079
3082
  if (method$1) {
3080
3083
  iterateeIndex = getIterateeIndex(method$1);
3081
- reporter(node, node.arguments[iterateeIndex], {
3084
+ if (isNumber(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
3082
3085
  method: method$1,
3083
3086
  callType: "single",
3084
3087
  remedaContext
@@ -3088,10 +3091,11 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
3088
3091
  };
3089
3092
  }
3090
3093
  function isRemedaCallToMethod(node, method$1, remedaContext) {
3094
+ if (!node) return false;
3091
3095
  return remedaContext.isRemedaCall(node) && isCallToMethod(node, method$1);
3092
3096
  }
3093
3097
  function isCallToRemedaMethod(node, method$1, remedaContext) {
3094
- if (!node || node.type !== "CallExpression") return false;
3098
+ if (!node || node.type !== AST_NODE_TYPES.CallExpression) return false;
3095
3099
  return isRemedaCallToMethod(node, method$1, remedaContext) || method$1 === remedaContext.getImportedRemedaMethod(node);
3096
3100
  }
3097
3101
  function getRemedaMethodVisitors(context, remedaCallExpVisitor) {
@@ -3121,7 +3125,7 @@ function isSideEffectIterationMethod(method$1) {
3121
3125
  return includes(getSideEffectIterationMethods(), method$1);
3122
3126
  }
3123
3127
  function isParentCommit(node, callType) {
3124
- return callType === "chained" && isCallToMethod(node.parent.parent, "commit");
3128
+ return callType === "chained" && node.parent.parent && isCallToMethod(node.parent.parent, "commit");
3125
3129
  }
3126
3130
  var collection_method_value_default = ESLintUtils.RuleCreator(getDocsUrl)({
3127
3131
  name: RULE_NAME$14,
@@ -3173,18 +3177,22 @@ var collection_return_default = ESLintUtils.RuleCreator(getDocsUrl)({
3173
3177
  create(context) {
3174
3178
  const remedaContext = getRemedaContext(context);
3175
3179
  return {
3176
- "CallExpression:exit": getRemedaMethodCallExpVisitor(remedaContext, (node, iteratee$1, { method: method$1 }) => {
3177
- if (!isCollectionMethod(method$1)) return;
3178
- if (!astUtil_default.isFunctionDefinitionWithBlock(iteratee$1) || iteratee$1.async || iteratee$1.generator) return;
3179
- const hasReturnStatement = iteratee$1.body.type === AST_NODE_TYPES.BlockStatement && iteratee$1.body.body.some((statement) => {
3180
- return statement.type === AST_NODE_TYPES.ReturnStatement;
3181
- });
3182
- if (!hasReturnStatement) context.report({
3183
- node,
3184
- messageId: "no-return",
3185
- data: { method: method$1 }
3186
- });
3187
- }),
3180
+ "CallExpression:exit": getRemedaMethodCallExpVisitor(
3181
+ remedaContext,
3182
+ // @ts-expect-error
3183
+ (node, iteratee$1, { method: method$1 }) => {
3184
+ if (!isCollectionMethod(method$1)) return;
3185
+ if (!astUtil_default.isFunctionDefinitionWithBlock(iteratee$1) || iteratee$1.async || iteratee$1.generator) return;
3186
+ const hasReturnStatement = iteratee$1.body.type === AST_NODE_TYPES.BlockStatement && iteratee$1.body.body.some((statement) => {
3187
+ return statement.type === AST_NODE_TYPES.ReturnStatement;
3188
+ });
3189
+ if (!hasReturnStatement) context.report({
3190
+ node,
3191
+ messageId: "no-return",
3192
+ data: { method: method$1 }
3193
+ });
3194
+ }
3195
+ ),
3188
3196
  ...remedaContext.getImportVisitors()
3189
3197
  };
3190
3198
  }
@@ -3212,8 +3220,14 @@ var prefer_constant_default = ESLintUtils.RuleCreator(getDocsUrl)({
3212
3220
  description: "enforce using R.constant over functions returning literals",
3213
3221
  url: getDocsUrl(RULE_NAME$12)
3214
3222
  },
3215
- schema: [{ type: "boolean" }, { type: "boolean" }],
3216
- defaultOptions: [],
3223
+ schema: [{
3224
+ type: "boolean",
3225
+ description: "Whether to check arrow functions for literals in return statements. Default: true."
3226
+ }, {
3227
+ type: "boolean",
3228
+ description: "Whether to check function declarations for literals in return statements. Default: false."
3229
+ }],
3230
+ defaultOptions: [true, false],
3217
3231
  messages: { [MESSAGE_ID$1]: "Prefer R.constant over a function returning a literal" }
3218
3232
  },
3219
3233
  defaultOptions: [true, false],
@@ -3301,7 +3315,7 @@ var prefer_filter_default = ESLintUtils.RuleCreator(getDocsUrl)({
3301
3315
  defaultOptions: [{ maxPropertyPathLength: 3 }],
3302
3316
  messages: { "prefer-filter": MESSAGE$2 }
3303
3317
  },
3304
- defaultOptions: [{}],
3318
+ defaultOptions: [{ maxPropertyPathLength: 3 }],
3305
3319
  create(context, [options]) {
3306
3320
  const DEFAULT_MAX_PROPERTY_PATH_LENGTH = 3;
3307
3321
  const maxLength = options.maxPropertyPathLength ?? DEFAULT_MAX_PROPERTY_PATH_LENGTH;
@@ -3333,7 +3347,7 @@ function isZeroIndexAccess(node) {
3333
3347
  return node.type === AST_NODE_TYPES.MemberExpression && node.property.type === AST_NODE_TYPES.Literal && node.property.value === 0;
3334
3348
  }
3335
3349
  function isChainedBeforeMethod(callType, node, method$1) {
3336
- return callType === "chained" && isCallToMethod(node.parent?.parent, method$1);
3350
+ return callType === "chained" && node.parent?.parent !== void 0 && isCallToMethod(node.parent.parent, method$1);
3337
3351
  }
3338
3352
  var prefer_find_default = ESLintUtils.RuleCreator(getDocsUrl)({
3339
3353
  name: RULE_NAME$9,
@@ -3353,7 +3367,7 @@ var prefer_find_default = ESLintUtils.RuleCreator(getDocsUrl)({
3353
3367
  create(context) {
3354
3368
  return getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1, callType, remedaContext }) => {
3355
3369
  if (method$1 === "filter") {
3356
- if (isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
3370
+ if (node.parent && isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
3357
3371
  node,
3358
3372
  messageId: "prefer-find"
3359
3373
  });
@@ -3371,7 +3385,8 @@ var prefer_find_default = ESLintUtils.RuleCreator(getDocsUrl)({
3371
3385
  const { getCaller } = astUtil_default;
3372
3386
  const RULE_NAME$8 = "prefer-flat-map";
3373
3387
  function isChainedMapFlatten(node) {
3374
- return isCallToMethod(getCaller(node), "map");
3388
+ const caller = getCaller(node);
3389
+ return caller ? isCallToMethod(caller, "map") : false;
3375
3390
  }
3376
3391
  var prefer_flat_map_default = ESLintUtils.RuleCreator(getDocsUrl)({
3377
3392
  name: RULE_NAME$8,
@@ -3386,12 +3401,16 @@ var prefer_flat_map_default = ESLintUtils.RuleCreator(getDocsUrl)({
3386
3401
  },
3387
3402
  defaultOptions: [],
3388
3403
  create(context) {
3389
- return getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1, remedaContext }) => {
3390
- if (method$1 === "flat" && (isChainedMapFlatten(node) || isCallToRemedaMethod(node.arguments[0], "map", remedaContext))) context.report({
3391
- node,
3392
- messageId: "prefer-flat-map"
3393
- });
3394
- });
3404
+ return getRemedaMethodVisitors(
3405
+ context,
3406
+ // @ts-expect-error
3407
+ (node, iteratee$1, { method: method$1, remedaContext }) => {
3408
+ if (method$1 === "flat" && (isChainedMapFlatten(node) || isCallToRemedaMethod(node.arguments[0], "map", remedaContext))) context.report({
3409
+ node,
3410
+ messageId: "prefer-flat-map"
3411
+ });
3412
+ }
3413
+ );
3395
3414
  }
3396
3415
  });
3397
3416
 
@@ -3627,12 +3646,21 @@ var prefer_is_nullish_default = ESLintUtils.RuleCreator(getDocsUrl)({
3627
3646
  return isNegationExpression(node) && checkExpression(nil, "===", node.argument) || checkExpression(nil, "!==", node);
3628
3647
  }
3629
3648
  function isEquivalentExistingExpression(node, leftNil, rightNil) {
3649
+ if (node.type !== AST_NODE_TYPES.LogicalExpression) return false;
3630
3650
  const leftExp = checkExpression(leftNil, "===", node.left);
3631
- return leftExp && isEquivalentMemberExp(leftExp, checkExpression(rightNil, "===", node.right));
3651
+ return leftExp && isEquivalentMemberExp(
3652
+ leftExp,
3653
+ // @ts-expect-error
3654
+ checkExpression(rightNil, "===", node.right)
3655
+ );
3632
3656
  }
3633
3657
  function isEquivalentExistingNegation(node, leftNil, rightNil) {
3634
3658
  const leftExp = checkNegatedExpression(leftNil, node.left);
3635
- return leftExp && isEquivalentMemberExp(leftExp, checkNegatedExpression(rightNil, node.right));
3659
+ return leftExp && isEquivalentMemberExp(
3660
+ leftExp,
3661
+ // @ts-expect-error
3662
+ checkNegatedExpression(rightNil, node.right)
3663
+ );
3636
3664
  }
3637
3665
  const visitors = remedaContext.getImportVisitors();
3638
3666
  visitors.LogicalExpression = function(node) {
@@ -3654,11 +3682,11 @@ var prefer_is_nullish_default = ESLintUtils.RuleCreator(getDocsUrl)({
3654
3682
  //#region src/rules/prefer-map.ts
3655
3683
  const { getFirstFunctionLine, hasOnlyOneStatement, getMethodName, isFunctionDefinitionWithBlock, collectParameterValues } = astUtil_default;
3656
3684
  const RULE_NAME$4 = "prefer-map";
3657
- function onlyHasPush(func) {
3658
- const firstLine = getFirstFunctionLine(func);
3659
- const firstParam = get(func, "params[0]");
3660
- const exp = func && !isFunctionDefinitionWithBlock(func) ? firstLine : firstLine?.expression;
3661
- return func && hasOnlyOneStatement(func) && getMethodName(exp) === "push" && !includes(collectParameterValues(firstParam), get(exp, "callee.object.name"));
3685
+ function onlyHasPush(node) {
3686
+ const firstLine = getFirstFunctionLine(node);
3687
+ const firstParam = get(node, "params[0]");
3688
+ const exp = node && !isFunctionDefinitionWithBlock(node) ? firstLine : firstLine?.expression;
3689
+ return node && (node.type === AST_NODE_TYPES.ArrowFunctionExpression ? true : hasOnlyOneStatement(node)) && getMethodName(exp) === "push" && !includes(collectParameterValues(firstParam), get(exp, "callee.object.name"));
3662
3690
  }
3663
3691
  var prefer_map_default = ESLintUtils.RuleCreator(getDocsUrl)({
3664
3692
  name: RULE_NAME$4,
@@ -3809,7 +3837,7 @@ var prefer_some_default = ESLintUtils.RuleCreator(getDocsUrl)({
3809
3837
  defaultOptions: [],
3810
3838
  create(context) {
3811
3839
  const visitors = getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1 }) => {
3812
- if (method$1 === "findIndex" && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
3840
+ if (method$1 === "findIndex" && node.parent?.type === AST_NODE_TYPES.BinaryExpression && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
3813
3841
  node,
3814
3842
  messageId: "prefer-some"
3815
3843
  });
@@ -3884,7 +3912,7 @@ const configs = { recommended: {
3884
3912
  [`${pluginShortName}/prefer-constant`]: 2,
3885
3913
  [`${pluginShortName}/prefer-remeda-typecheck`]: 2,
3886
3914
  [`${pluginShortName}/prefer-nullish-coalescing`]: 2,
3887
- [`${pluginShortName}/prefer-filter`]: [2, 3],
3915
+ [`${pluginShortName}/prefer-filter`]: 2,
3888
3916
  [`${pluginShortName}/prefer-has-atleast`]: 2,
3889
3917
  [`${pluginShortName}/collection-method-value`]: 2,
3890
3918
  [`${pluginShortName}/collection-return`]: 2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-remeda",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "author": "Andrea Pontrandolfo <andrea.pontra@gmail.com>",
5
5
  "description": "ESLint plugin for Remeda library.",
6
6
  "type": "module",
@@ -8,12 +8,13 @@
8
8
  "scripts": {
9
9
  "build": "tsdown",
10
10
  "typecheck": "tsc",
11
- "lint": "eslint",
11
+ "lint": "eslint --max-warnings=0",
12
12
  "knip": "knip",
13
13
  "test:watch": "vitest --ui",
14
14
  "test": "vitest run",
15
- "attw": "attw --pack .",
16
- "qa": "pnpm typecheck && pnpm test && pnpm knip && attw",
15
+ "check-sheriff-inconsistencies": "sheriff",
16
+ "attw": "attw --ignore-rules=false-export-default --pack .",
17
+ "qa": "pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm knip && pnpm attw && pnpm check-sheriff-inconsistencies",
17
18
  "nuke": "rm -rf node_modules pnpm-lock.yaml",
18
19
  "update:eslint-docs": "eslint-doc-generator",
19
20
  "lint:eslint-docs": "pnpm update:eslint-docs -- --check",
@@ -49,7 +50,7 @@
49
50
  },
50
51
  "devDependencies": {
51
52
  "@arethetypeswrong/cli": "^0.17.4",
52
- "@sherifforg/cli": "^8.2.0",
53
+ "@sherifforg/cli": "^8.3.0",
53
54
  "@types/lodash-es": "^4.17.12",
54
55
  "@types/node": "^22.14.0",
55
56
  "@typescript-eslint/utils": "^8.29.0",