eslint-plugin-nextfriday 1.6.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/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.6.0",
43
+ version: "1.8.0",
44
44
  description: "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
45
45
  keywords: [
46
46
  "eslint",
@@ -154,12 +154,143 @@ var package_default = {
154
154
  }
155
155
  };
156
156
 
157
- // src/rules/enforce-readonly-component-props.ts
157
+ // src/rules/boolean-naming-prefix.ts
158
158
  var import_utils = require("@typescript-eslint/utils");
159
159
  var createRule = import_utils.ESLintUtils.RuleCreator(
160
160
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
161
161
  );
162
- var enforceReadonlyComponentProps = createRule({
162
+ var BOOLEAN_PREFIXES = ["is", "has", "should", "can", "did", "will", "was", "are", "does", "had"];
163
+ var startsWithBooleanPrefix = (name) => {
164
+ const lowerName = name.toLowerCase();
165
+ return BOOLEAN_PREFIXES.some((prefix) => {
166
+ if (!lowerName.startsWith(prefix)) {
167
+ return false;
168
+ }
169
+ if (name.length === prefix.length) {
170
+ return true;
171
+ }
172
+ const nextChar = name.charAt(prefix.length);
173
+ return nextChar === nextChar.toUpperCase();
174
+ });
175
+ };
176
+ var isBooleanLiteral = (node) => node.type === import_utils.AST_NODE_TYPES.Literal && typeof node.value === "boolean";
177
+ var isBooleanExpression = (node) => {
178
+ if (isBooleanLiteral(node)) {
179
+ return true;
180
+ }
181
+ if (node.type === import_utils.AST_NODE_TYPES.UnaryExpression && node.operator === "!") {
182
+ return true;
183
+ }
184
+ if (node.type === import_utils.AST_NODE_TYPES.BinaryExpression) {
185
+ const comparisonOperators = ["===", "!==", "==", "!=", "<", ">", "<=", ">=", "in", "instanceof"];
186
+ return comparisonOperators.includes(node.operator);
187
+ }
188
+ if (node.type === import_utils.AST_NODE_TYPES.LogicalExpression) {
189
+ return node.operator === "&&" || node.operator === "||";
190
+ }
191
+ return false;
192
+ };
193
+ var hasBooleanTypeAnnotation = (node) => {
194
+ if (node.type === import_utils.AST_NODE_TYPES.Identifier) {
195
+ const { typeAnnotation } = node;
196
+ if (typeAnnotation?.typeAnnotation.type === import_utils.AST_NODE_TYPES.TSBooleanKeyword) {
197
+ return true;
198
+ }
199
+ }
200
+ if ("id" in node && node.id.type === import_utils.AST_NODE_TYPES.Identifier) {
201
+ const { typeAnnotation } = node.id;
202
+ if (typeAnnotation?.typeAnnotation.type === import_utils.AST_NODE_TYPES.TSBooleanKeyword) {
203
+ return true;
204
+ }
205
+ }
206
+ return false;
207
+ };
208
+ var booleanNamingPrefix = createRule({
209
+ name: "boolean-naming-prefix",
210
+ meta: {
211
+ type: "suggestion",
212
+ docs: {
213
+ description: "Enforce boolean variables and parameters to have a prefix like is, has, should, can, did, will for better readability"
214
+ },
215
+ messages: {
216
+ missingPrefix: "Boolean variable '{{name}}' should have a prefix like is, has, should, can, did, or will. Example: 'is{{suggestedName}}' or 'has{{suggestedName}}'."
217
+ },
218
+ schema: []
219
+ },
220
+ defaultOptions: [],
221
+ create(context) {
222
+ const checkBooleanNaming = (name, node) => {
223
+ if (startsWithBooleanPrefix(name)) {
224
+ return;
225
+ }
226
+ const suggestedName = name.charAt(0).toUpperCase() + name.slice(1);
227
+ context.report({
228
+ node,
229
+ messageId: "missingPrefix",
230
+ data: { name, suggestedName }
231
+ });
232
+ };
233
+ return {
234
+ VariableDeclarator(node) {
235
+ if (node.id.type !== import_utils.AST_NODE_TYPES.Identifier) {
236
+ return;
237
+ }
238
+ const { name } = node.id;
239
+ if (hasBooleanTypeAnnotation(node)) {
240
+ checkBooleanNaming(name, node.id);
241
+ return;
242
+ }
243
+ if (node.init && isBooleanExpression(node.init)) {
244
+ checkBooleanNaming(name, node.id);
245
+ }
246
+ },
247
+ FunctionDeclaration(node) {
248
+ node.params.forEach((param) => {
249
+ if (param.type === import_utils.AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
250
+ checkBooleanNaming(param.name, param);
251
+ }
252
+ if (param.type === import_utils.AST_NODE_TYPES.AssignmentPattern) {
253
+ if (param.left.type === import_utils.AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
254
+ checkBooleanNaming(param.left.name, param.left);
255
+ }
256
+ }
257
+ });
258
+ },
259
+ FunctionExpression(node) {
260
+ node.params.forEach((param) => {
261
+ if (param.type === import_utils.AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
262
+ checkBooleanNaming(param.name, param);
263
+ }
264
+ if (param.type === import_utils.AST_NODE_TYPES.AssignmentPattern) {
265
+ if (param.left.type === import_utils.AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
266
+ checkBooleanNaming(param.left.name, param.left);
267
+ }
268
+ }
269
+ });
270
+ },
271
+ ArrowFunctionExpression(node) {
272
+ node.params.forEach((param) => {
273
+ if (param.type === import_utils.AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
274
+ checkBooleanNaming(param.name, param);
275
+ }
276
+ if (param.type === import_utils.AST_NODE_TYPES.AssignmentPattern) {
277
+ if (param.left.type === import_utils.AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
278
+ checkBooleanNaming(param.left.name, param.left);
279
+ }
280
+ }
281
+ });
282
+ }
283
+ };
284
+ }
285
+ });
286
+ var boolean_naming_prefix_default = booleanNamingPrefix;
287
+
288
+ // src/rules/enforce-readonly-component-props.ts
289
+ var import_utils2 = require("@typescript-eslint/utils");
290
+ var createRule2 = import_utils2.ESLintUtils.RuleCreator(
291
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
292
+ );
293
+ var enforceReadonlyComponentProps = createRule2({
163
294
  name: "enforce-readonly-component-props",
164
295
  meta: {
165
296
  type: "suggestion",
@@ -175,54 +306,54 @@ var enforceReadonlyComponentProps = createRule({
175
306
  defaultOptions: [],
176
307
  create(context) {
177
308
  function hasJSXInConditional(node) {
178
- return node.consequent.type === import_utils.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils.AST_NODE_TYPES.JSXFragment;
309
+ return node.consequent.type === import_utils2.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils2.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils2.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils2.AST_NODE_TYPES.JSXFragment;
179
310
  }
180
311
  function hasJSXInLogical(node) {
181
- return node.right.type === import_utils.AST_NODE_TYPES.JSXElement || node.right.type === import_utils.AST_NODE_TYPES.JSXFragment;
312
+ return node.right.type === import_utils2.AST_NODE_TYPES.JSXElement || node.right.type === import_utils2.AST_NODE_TYPES.JSXFragment;
182
313
  }
183
314
  function hasJSXReturn(block) {
184
315
  return block.body.some((stmt) => {
185
- if (stmt.type === import_utils.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
186
- return stmt.argument.type === import_utils.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
316
+ if (stmt.type === import_utils2.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
317
+ return stmt.argument.type === import_utils2.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils2.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils2.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils2.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
187
318
  }
188
319
  return false;
189
320
  });
190
321
  }
191
- function isReactComponent(node) {
192
- if (node.type === import_utils.AST_NODE_TYPES.ArrowFunctionExpression) {
193
- if (node.body.type === import_utils.AST_NODE_TYPES.JSXElement || node.body.type === import_utils.AST_NODE_TYPES.JSXFragment) {
322
+ function isReactComponent2(node) {
323
+ if (node.type === import_utils2.AST_NODE_TYPES.ArrowFunctionExpression) {
324
+ if (node.body.type === import_utils2.AST_NODE_TYPES.JSXElement || node.body.type === import_utils2.AST_NODE_TYPES.JSXFragment) {
194
325
  return true;
195
326
  }
196
- if (node.body.type === import_utils.AST_NODE_TYPES.BlockStatement) {
327
+ if (node.body.type === import_utils2.AST_NODE_TYPES.BlockStatement) {
197
328
  return hasJSXReturn(node.body);
198
329
  }
199
- } else if (node.type === import_utils.AST_NODE_TYPES.FunctionExpression || node.type === import_utils.AST_NODE_TYPES.FunctionDeclaration) {
200
- if (node.body && node.body.type === import_utils.AST_NODE_TYPES.BlockStatement) {
330
+ } else if (node.type === import_utils2.AST_NODE_TYPES.FunctionExpression || node.type === import_utils2.AST_NODE_TYPES.FunctionDeclaration) {
331
+ if (node.body && node.body.type === import_utils2.AST_NODE_TYPES.BlockStatement) {
201
332
  return hasJSXReturn(node.body);
202
333
  }
203
334
  }
204
335
  return false;
205
336
  }
206
337
  function isNamedType(node) {
207
- return node.type === import_utils.AST_NODE_TYPES.TSTypeReference;
338
+ return node.type === import_utils2.AST_NODE_TYPES.TSTypeReference;
208
339
  }
209
340
  function isAlreadyReadonly(node) {
210
- if (node.type === import_utils.AST_NODE_TYPES.TSTypeReference && node.typeName) {
211
- if (node.typeName.type === import_utils.AST_NODE_TYPES.Identifier && node.typeName.name === "Readonly") {
341
+ if (node.type === import_utils2.AST_NODE_TYPES.TSTypeReference && node.typeName) {
342
+ if (node.typeName.type === import_utils2.AST_NODE_TYPES.Identifier && node.typeName.name === "Readonly") {
212
343
  return true;
213
344
  }
214
345
  }
215
346
  return false;
216
347
  }
217
348
  function checkFunction(node) {
218
- if (!isReactComponent(node)) {
349
+ if (!isReactComponent2(node)) {
219
350
  return;
220
351
  }
221
352
  if (node.params.length !== 1) {
222
353
  return;
223
354
  }
224
355
  const param = node.params[0];
225
- if (param.type === import_utils.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
356
+ if (param.type === import_utils2.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
226
357
  const { typeAnnotation } = param.typeAnnotation;
227
358
  if (isNamedType(typeAnnotation) && !isAlreadyReadonly(typeAnnotation)) {
228
359
  const { sourceCode } = context;
@@ -247,11 +378,11 @@ var enforceReadonlyComponentProps = createRule({
247
378
  var enforce_readonly_component_props_default = enforceReadonlyComponentProps;
248
379
 
249
380
  // src/rules/enforce-sorted-destructuring.ts
250
- var import_utils2 = require("@typescript-eslint/utils");
251
- var createRule2 = import_utils2.ESLintUtils.RuleCreator(
381
+ var import_utils3 = require("@typescript-eslint/utils");
382
+ var createRule3 = import_utils3.ESLintUtils.RuleCreator(
252
383
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
253
384
  );
254
- var enforceSortedDestructuring = createRule2({
385
+ var enforceSortedDestructuring = createRule3({
255
386
  name: "enforce-sorted-destructuring",
256
387
  meta: {
257
388
  type: "suggestion",
@@ -266,16 +397,16 @@ var enforceSortedDestructuring = createRule2({
266
397
  defaultOptions: [],
267
398
  create(context) {
268
399
  function getPropertyName(property) {
269
- if (property.type === import_utils2.AST_NODE_TYPES.RestElement) {
400
+ if (property.type === import_utils3.AST_NODE_TYPES.RestElement) {
270
401
  return null;
271
402
  }
272
- if (property.key.type === import_utils2.AST_NODE_TYPES.Identifier) {
403
+ if (property.key.type === import_utils3.AST_NODE_TYPES.Identifier) {
273
404
  return property.key.name;
274
405
  }
275
406
  return null;
276
407
  }
277
408
  function hasDefaultValue(property) {
278
- return property.value.type === import_utils2.AST_NODE_TYPES.AssignmentPattern && Boolean(property.value.right);
409
+ return property.value.type === import_utils3.AST_NODE_TYPES.AssignmentPattern && Boolean(property.value.right);
279
410
  }
280
411
  function getDefaultValueType(property) {
281
412
  if (!hasDefaultValue(property)) {
@@ -287,7 +418,7 @@ var enforceSortedDestructuring = createRule2({
287
418
  return "none";
288
419
  }
289
420
  switch (right.type) {
290
- case import_utils2.AST_NODE_TYPES.Literal:
421
+ case import_utils3.AST_NODE_TYPES.Literal:
291
422
  if (typeof right.value === "string") {
292
423
  return "string";
293
424
  }
@@ -298,10 +429,10 @@ var enforceSortedDestructuring = createRule2({
298
429
  return "boolean";
299
430
  }
300
431
  return "other";
301
- case import_utils2.AST_NODE_TYPES.TemplateLiteral:
432
+ case import_utils3.AST_NODE_TYPES.TemplateLiteral:
302
433
  return "string";
303
- case import_utils2.AST_NODE_TYPES.ObjectExpression:
304
- case import_utils2.AST_NODE_TYPES.ArrayExpression:
434
+ case import_utils3.AST_NODE_TYPES.ObjectExpression:
435
+ case import_utils3.AST_NODE_TYPES.ArrayExpression:
305
436
  return "object";
306
437
  default:
307
438
  return "other";
@@ -319,7 +450,7 @@ var enforceSortedDestructuring = createRule2({
319
450
  return order[type] ?? 5;
320
451
  }
321
452
  function checkVariableDeclarator(node) {
322
- if (node.id.type !== import_utils2.AST_NODE_TYPES.ObjectPattern) {
453
+ if (node.id.type !== import_utils3.AST_NODE_TYPES.ObjectPattern) {
323
454
  return;
324
455
  }
325
456
  const { properties } = node.id;
@@ -327,7 +458,7 @@ var enforceSortedDestructuring = createRule2({
327
458
  return;
328
459
  }
329
460
  const propertyInfo = properties.map((prop) => {
330
- if (prop.type === import_utils2.AST_NODE_TYPES.RestElement) {
461
+ if (prop.type === import_utils3.AST_NODE_TYPES.RestElement) {
331
462
  return null;
332
463
  }
333
464
  return {
@@ -369,8 +500,8 @@ var enforce_sorted_destructuring_default = enforceSortedDestructuring;
369
500
 
370
501
  // src/rules/file-kebab-case.ts
371
502
  var import_path = __toESM(require("path"), 1);
372
- var import_utils3 = require("@typescript-eslint/utils");
373
- var createRule3 = import_utils3.ESLintUtils.RuleCreator(
503
+ var import_utils4 = require("@typescript-eslint/utils");
504
+ var createRule4 = import_utils4.ESLintUtils.RuleCreator(
374
505
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
375
506
  );
376
507
  var isKebabCase = (str) => {
@@ -379,7 +510,7 @@ var isKebabCase = (str) => {
379
510
  }
380
511
  return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(str);
381
512
  };
382
- var fileKebabCase = createRule3({
513
+ var fileKebabCase = createRule4({
383
514
  name: "file-kebab-case",
384
515
  meta: {
385
516
  type: "problem",
@@ -415,12 +546,12 @@ var file_kebab_case_default = fileKebabCase;
415
546
 
416
547
  // src/rules/jsx-pascal-case.ts
417
548
  var import_path2 = __toESM(require("path"), 1);
418
- var import_utils4 = require("@typescript-eslint/utils");
419
- var createRule4 = import_utils4.ESLintUtils.RuleCreator(
549
+ var import_utils5 = require("@typescript-eslint/utils");
550
+ var createRule5 = import_utils5.ESLintUtils.RuleCreator(
420
551
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
421
552
  );
422
553
  var isPascalCase = (str) => /^[A-Z][a-zA-Z0-9]*$/.test(str) && !/^[A-Z]+$/.test(str);
423
- var jsxPascalCase = createRule4({
554
+ var jsxPascalCase = createRule5({
424
555
  name: "jsx-pascal-case",
425
556
  meta: {
426
557
  type: "problem",
@@ -454,12 +585,64 @@ var jsxPascalCase = createRule4({
454
585
  });
455
586
  var jsx_pascal_case_default = jsxPascalCase;
456
587
 
588
+ // src/rules/no-direct-date.ts
589
+ var import_utils6 = require("@typescript-eslint/utils");
590
+ var createRule6 = import_utils6.ESLintUtils.RuleCreator(
591
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
592
+ );
593
+ var noDirectDate = createRule6({
594
+ name: "no-direct-date",
595
+ meta: {
596
+ type: "problem",
597
+ docs: {
598
+ description: "Disallow direct usage of Date constructor and methods to enforce centralized date utilities"
599
+ },
600
+ messages: {
601
+ noNewDate: "Avoid using 'new Date()'. Use a centralized date utility like dayjs instead.",
602
+ noDateNow: "Avoid using 'Date.now()'. Use a centralized date utility like dayjs instead.",
603
+ noDateParse: "Avoid using 'Date.parse()'. Use a centralized date utility like dayjs instead."
604
+ },
605
+ schema: []
606
+ },
607
+ defaultOptions: [],
608
+ create(context) {
609
+ return {
610
+ NewExpression(node) {
611
+ if (node.callee.type === import_utils6.AST_NODE_TYPES.Identifier && node.callee.name === "Date") {
612
+ context.report({
613
+ node,
614
+ messageId: "noNewDate"
615
+ });
616
+ }
617
+ },
618
+ CallExpression(node) {
619
+ if (node.callee.type === import_utils6.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils6.AST_NODE_TYPES.Identifier && node.callee.object.name === "Date" && node.callee.property.type === import_utils6.AST_NODE_TYPES.Identifier) {
620
+ const methodName = node.callee.property.name;
621
+ if (methodName === "now") {
622
+ context.report({
623
+ node,
624
+ messageId: "noDateNow"
625
+ });
626
+ }
627
+ if (methodName === "parse") {
628
+ context.report({
629
+ node,
630
+ messageId: "noDateParse"
631
+ });
632
+ }
633
+ }
634
+ }
635
+ };
636
+ }
637
+ });
638
+ var no_direct_date_default = noDirectDate;
639
+
457
640
  // src/rules/jsx-no-variable-in-callback.ts
458
- var import_utils5 = require("@typescript-eslint/utils");
459
- var createRule5 = import_utils5.ESLintUtils.RuleCreator(
641
+ var import_utils7 = require("@typescript-eslint/utils");
642
+ var createRule7 = import_utils7.ESLintUtils.RuleCreator(
460
643
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
461
644
  );
462
- var jsxNoVariableInCallback = createRule5({
645
+ var jsxNoVariableInCallback = createRule7({
463
646
  name: "jsx-no-variable-in-callback",
464
647
  meta: {
465
648
  type: "suggestion",
@@ -476,7 +659,7 @@ var jsxNoVariableInCallback = createRule5({
476
659
  function isInsideJSX(node) {
477
660
  let current = node.parent;
478
661
  while (current) {
479
- if (current.type === import_utils5.AST_NODE_TYPES.JSXElement || current.type === import_utils5.AST_NODE_TYPES.JSXFragment) {
662
+ if (current.type === import_utils7.AST_NODE_TYPES.JSXElement || current.type === import_utils7.AST_NODE_TYPES.JSXFragment) {
480
663
  return true;
481
664
  }
482
665
  current = current.parent;
@@ -490,11 +673,11 @@ var jsxNoVariableInCallback = createRule5({
490
673
  if (!isInsideJSX(node)) {
491
674
  return false;
492
675
  }
493
- if (node.parent.type === import_utils5.AST_NODE_TYPES.CallExpression || node.parent.type === import_utils5.AST_NODE_TYPES.JSXExpressionContainer) {
676
+ if (node.parent.type === import_utils7.AST_NODE_TYPES.CallExpression || node.parent.type === import_utils7.AST_NODE_TYPES.JSXExpressionContainer) {
494
677
  return true;
495
678
  }
496
- if (node.parent.type === import_utils5.AST_NODE_TYPES.ArrayExpression && node.parent.parent) {
497
- if (node.parent.parent.type === import_utils5.AST_NODE_TYPES.CallExpression || node.parent.parent.type === import_utils5.AST_NODE_TYPES.JSXExpressionContainer) {
679
+ if (node.parent.type === import_utils7.AST_NODE_TYPES.ArrayExpression && node.parent.parent) {
680
+ if (node.parent.parent.type === import_utils7.AST_NODE_TYPES.CallExpression || node.parent.parent.type === import_utils7.AST_NODE_TYPES.JSXExpressionContainer) {
498
681
  return true;
499
682
  }
500
683
  }
@@ -505,11 +688,11 @@ var jsxNoVariableInCallback = createRule5({
505
688
  return;
506
689
  }
507
690
  const { body } = node;
508
- if (body.type !== import_utils5.AST_NODE_TYPES.BlockStatement) {
691
+ if (body.type !== import_utils7.AST_NODE_TYPES.BlockStatement) {
509
692
  return;
510
693
  }
511
694
  body.body.forEach((statement) => {
512
- if (statement.type === import_utils5.AST_NODE_TYPES.VariableDeclaration) {
695
+ if (statement.type === import_utils7.AST_NODE_TYPES.VariableDeclaration) {
513
696
  context.report({
514
697
  node: statement,
515
698
  messageId: "noVariableInCallback"
@@ -527,11 +710,11 @@ var jsx_no_variable_in_callback_default = jsxNoVariableInCallback;
527
710
 
528
711
  // src/rules/md-filename-case-restriction.ts
529
712
  var import_path3 = __toESM(require("path"), 1);
530
- var import_utils6 = require("@typescript-eslint/utils");
531
- var createRule6 = import_utils6.ESLintUtils.RuleCreator(
713
+ var import_utils8 = require("@typescript-eslint/utils");
714
+ var createRule8 = import_utils8.ESLintUtils.RuleCreator(
532
715
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
533
716
  );
534
- var mdFilenameCaseRestriction = createRule6({
717
+ var mdFilenameCaseRestriction = createRule8({
535
718
  name: "md-filename-case-restriction",
536
719
  meta: {
537
720
  type: "problem",
@@ -572,11 +755,11 @@ var mdFilenameCaseRestriction = createRule6({
572
755
  var md_filename_case_restriction_default = mdFilenameCaseRestriction;
573
756
 
574
757
  // src/rules/no-complex-inline-return.ts
575
- var import_utils7 = require("@typescript-eslint/utils");
576
- var createRule7 = import_utils7.ESLintUtils.RuleCreator(
758
+ var import_utils9 = require("@typescript-eslint/utils");
759
+ var createRule9 = import_utils9.ESLintUtils.RuleCreator(
577
760
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
578
761
  );
579
- var noComplexInlineReturn = createRule7({
762
+ var noComplexInlineReturn = createRule9({
580
763
  name: "no-complex-inline-return",
581
764
  meta: {
582
765
  type: "suggestion",
@@ -592,13 +775,13 @@ var noComplexInlineReturn = createRule7({
592
775
  create(context) {
593
776
  const isComplexExpression = (node) => {
594
777
  if (!node) return false;
595
- if (node.type === import_utils7.AST_NODE_TYPES.ConditionalExpression) {
778
+ if (node.type === import_utils9.AST_NODE_TYPES.ConditionalExpression) {
596
779
  return true;
597
780
  }
598
- if (node.type === import_utils7.AST_NODE_TYPES.LogicalExpression) {
781
+ if (node.type === import_utils9.AST_NODE_TYPES.LogicalExpression) {
599
782
  return true;
600
783
  }
601
- if (node.type === import_utils7.AST_NODE_TYPES.NewExpression) {
784
+ if (node.type === import_utils9.AST_NODE_TYPES.NewExpression) {
602
785
  return true;
603
786
  }
604
787
  return false;
@@ -619,11 +802,11 @@ var no_complex_inline_return_default = noComplexInlineReturn;
619
802
 
620
803
  // src/rules/no-emoji.ts
621
804
  var import_emoji_regex = __toESM(require("emoji-regex"), 1);
622
- var import_utils8 = require("@typescript-eslint/utils");
623
- var createRule8 = import_utils8.ESLintUtils.RuleCreator(
805
+ var import_utils10 = require("@typescript-eslint/utils");
806
+ var createRule10 = import_utils10.ESLintUtils.RuleCreator(
624
807
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
625
808
  );
626
- var noEmoji = createRule8({
809
+ var noEmoji = createRule10({
627
810
  name: "no-emoji",
628
811
  meta: {
629
812
  type: "problem",
@@ -657,11 +840,11 @@ var noEmoji = createRule8({
657
840
  var no_emoji_default = noEmoji;
658
841
 
659
842
  // src/rules/no-env-fallback.ts
660
- var import_utils9 = require("@typescript-eslint/utils");
661
- var createRule9 = import_utils9.ESLintUtils.RuleCreator(
843
+ var import_utils11 = require("@typescript-eslint/utils");
844
+ var createRule11 = import_utils11.ESLintUtils.RuleCreator(
662
845
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
663
846
  );
664
- var noEnvFallback = createRule9({
847
+ var noEnvFallback = createRule11({
665
848
  name: "no-env-fallback",
666
849
  meta: {
667
850
  type: "problem",
@@ -676,16 +859,16 @@ var noEnvFallback = createRule9({
676
859
  defaultOptions: [],
677
860
  create(context) {
678
861
  const isProcessEnvAccess = (node) => {
679
- if (node.type !== import_utils9.AST_NODE_TYPES.MemberExpression) {
862
+ if (node.type !== import_utils11.AST_NODE_TYPES.MemberExpression) {
680
863
  return false;
681
864
  }
682
865
  const { object } = node;
683
- if (object.type !== import_utils9.AST_NODE_TYPES.MemberExpression) {
866
+ if (object.type !== import_utils11.AST_NODE_TYPES.MemberExpression) {
684
867
  return false;
685
868
  }
686
869
  const processNode = object.object;
687
870
  const envNode = object.property;
688
- return processNode.type === import_utils9.AST_NODE_TYPES.Identifier && processNode.name === "process" && envNode.type === import_utils9.AST_NODE_TYPES.Identifier && envNode.name === "env";
871
+ return processNode.type === import_utils11.AST_NODE_TYPES.Identifier && processNode.name === "process" && envNode.type === import_utils11.AST_NODE_TYPES.Identifier && envNode.name === "env";
689
872
  };
690
873
  return {
691
874
  LogicalExpression(node) {
@@ -709,38 +892,93 @@ var noEnvFallback = createRule9({
709
892
  });
710
893
  var no_env_fallback_default = noEnvFallback;
711
894
 
712
- // src/rules/no-explicit-return-type.ts
713
- var import_utils10 = require("@typescript-eslint/utils");
714
- var createRule10 = import_utils10.ESLintUtils.RuleCreator(
895
+ // src/rules/require-explicit-return-type.ts
896
+ var import_utils12 = require("@typescript-eslint/utils");
897
+ var createRule12 = import_utils12.ESLintUtils.RuleCreator(
715
898
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
716
899
  );
717
- var noExplicitReturnType = createRule10({
718
- name: "no-explicit-return-type",
900
+ var isReactComponent = (node) => {
901
+ if (node.type === import_utils12.AST_NODE_TYPES.ArrowFunctionExpression) {
902
+ const { parent } = node;
903
+ if (parent?.type === import_utils12.AST_NODE_TYPES.VariableDeclarator) {
904
+ const { id } = parent;
905
+ if (id.type === import_utils12.AST_NODE_TYPES.Identifier) {
906
+ return /^[A-Z]/.test(id.name);
907
+ }
908
+ }
909
+ }
910
+ if (node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration && node.id) {
911
+ return /^[A-Z]/.test(node.id.name);
912
+ }
913
+ return false;
914
+ };
915
+ var isCallbackFunction = (node) => {
916
+ if (node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration) {
917
+ return false;
918
+ }
919
+ const { parent } = node;
920
+ if (!parent) {
921
+ return false;
922
+ }
923
+ if (parent.type === import_utils12.AST_NODE_TYPES.CallExpression && parent.arguments.includes(node)) {
924
+ return true;
925
+ }
926
+ if (parent.type === import_utils12.AST_NODE_TYPES.Property) {
927
+ return true;
928
+ }
929
+ if (parent.type === import_utils12.AST_NODE_TYPES.ArrayExpression) {
930
+ return true;
931
+ }
932
+ return false;
933
+ };
934
+ var getFunctionName = (node) => {
935
+ if (node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration && node.id) {
936
+ return node.id.name;
937
+ }
938
+ if (node.type === import_utils12.AST_NODE_TYPES.FunctionExpression && node.id) {
939
+ return node.id.name;
940
+ }
941
+ if ((node.type === import_utils12.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils12.AST_NODE_TYPES.FunctionExpression) && node.parent?.type === import_utils12.AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === import_utils12.AST_NODE_TYPES.Identifier) {
942
+ return node.parent.id.name;
943
+ }
944
+ return null;
945
+ };
946
+ var requireExplicitReturnType = createRule12({
947
+ name: "require-explicit-return-type",
719
948
  meta: {
720
949
  type: "suggestion",
721
950
  docs: {
722
- description: "Disallow explicit return types on functions"
951
+ description: "Require explicit return types on functions for better code documentation and type safety"
723
952
  },
724
- fixable: "code",
725
- schema: [],
726
953
  messages: {
727
- noExplicitReturnType: "Remove explicit return type '{{returnType}}' - TypeScript can infer it automatically"
728
- }
954
+ missingReturnType: "Function '{{name}}' is missing an explicit return type. Add a return type annotation for better documentation.",
955
+ missingReturnTypeAnonymous: "Function is missing an explicit return type. Add a return type annotation for better documentation."
956
+ },
957
+ schema: []
729
958
  },
730
959
  defaultOptions: [],
731
960
  create(context) {
732
961
  const checkFunction = (node) => {
733
962
  if (node.returnType) {
734
- const returnTypeText = context.sourceCode.getText(node.returnType);
963
+ return;
964
+ }
965
+ if (isCallbackFunction(node)) {
966
+ return;
967
+ }
968
+ if (isReactComponent(node)) {
969
+ return;
970
+ }
971
+ const functionName = getFunctionName(node);
972
+ if (functionName) {
735
973
  context.report({
736
- node: node.returnType,
737
- messageId: "noExplicitReturnType",
738
- data: {
739
- returnType: returnTypeText
740
- },
741
- fix(fixer) {
742
- return fixer.remove(node.returnType);
743
- }
974
+ node,
975
+ messageId: "missingReturnType",
976
+ data: { name: functionName }
977
+ });
978
+ } else {
979
+ context.report({
980
+ node,
981
+ messageId: "missingReturnTypeAnonymous"
744
982
  });
745
983
  }
746
984
  };
@@ -751,21 +989,21 @@ var noExplicitReturnType = createRule10({
751
989
  };
752
990
  }
753
991
  });
754
- var no_explicit_return_type_default = noExplicitReturnType;
992
+ var require_explicit_return_type_default = requireExplicitReturnType;
755
993
 
756
994
  // src/rules/jsx-no-non-component-function.ts
757
- var import_utils12 = require("@typescript-eslint/utils");
995
+ var import_utils14 = require("@typescript-eslint/utils");
758
996
 
759
997
  // src/utils.ts
760
998
  var import_node_path = require("path");
761
- var import_utils11 = require("@typescript-eslint/utils");
999
+ var import_utils13 = require("@typescript-eslint/utils");
762
1000
  var getFileExtension = (filename) => (0, import_node_path.extname)(filename).slice(1);
763
1001
 
764
1002
  // src/rules/jsx-no-non-component-function.ts
765
- var createRule11 = import_utils12.ESLintUtils.RuleCreator(
1003
+ var createRule13 = import_utils14.ESLintUtils.RuleCreator(
766
1004
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
767
1005
  );
768
- var jsxNoNonComponentFunction = createRule11({
1006
+ var jsxNoNonComponentFunction = createRule13({
769
1007
  name: "jsx-no-non-component-function",
770
1008
  meta: {
771
1009
  type: "problem",
@@ -784,14 +1022,14 @@ var jsxNoNonComponentFunction = createRule11({
784
1022
  if (extension !== "tsx" && extension !== "jsx") {
785
1023
  return {};
786
1024
  }
787
- function isReactComponent(node) {
788
- const functionName = node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration && node.id ? node.id.name : null;
1025
+ function isReactComponent2(node) {
1026
+ const functionName = node.type === import_utils14.AST_NODE_TYPES.FunctionDeclaration && node.id ? node.id.name : null;
789
1027
  if (functionName && /^[A-Z]/.test(functionName)) {
790
1028
  return true;
791
1029
  }
792
1030
  if (node.returnType?.typeAnnotation) {
793
1031
  const returnTypeNode = node.returnType.typeAnnotation;
794
- if (returnTypeNode.type === import_utils12.AST_NODE_TYPES.TSTypeReference && returnTypeNode.typeName.type === import_utils12.AST_NODE_TYPES.Identifier) {
1032
+ if (returnTypeNode.type === import_utils14.AST_NODE_TYPES.TSTypeReference && returnTypeNode.typeName.type === import_utils14.AST_NODE_TYPES.Identifier) {
795
1033
  const typeName = returnTypeNode.typeName.name;
796
1034
  if (typeName === "JSX" || typeName === "ReactElement" || typeName === "ReactNode") {
797
1035
  return true;
@@ -801,20 +1039,20 @@ var jsxNoNonComponentFunction = createRule11({
801
1039
  return false;
802
1040
  }
803
1041
  function checkTopLevelFunction(node, declaratorNode) {
804
- if (isReactComponent(node)) {
1042
+ if (isReactComponent2(node)) {
805
1043
  return;
806
1044
  }
807
1045
  const { parent } = node;
808
1046
  if (!parent) {
809
1047
  return;
810
1048
  }
811
- if (parent.type === import_utils12.AST_NODE_TYPES.ExportDefaultDeclaration || parent.type === import_utils12.AST_NODE_TYPES.ExportNamedDeclaration) {
1049
+ if (parent.type === import_utils14.AST_NODE_TYPES.ExportDefaultDeclaration || parent.type === import_utils14.AST_NODE_TYPES.ExportNamedDeclaration) {
812
1050
  return;
813
1051
  }
814
- if (declaratorNode?.parent?.parent?.type === import_utils12.AST_NODE_TYPES.ExportNamedDeclaration) {
1052
+ if (declaratorNode?.parent?.parent?.type === import_utils14.AST_NODE_TYPES.ExportNamedDeclaration) {
815
1053
  return;
816
1054
  }
817
- if (declaratorNode?.id.type === import_utils12.AST_NODE_TYPES.Identifier) {
1055
+ if (declaratorNode?.id.type === import_utils14.AST_NODE_TYPES.Identifier) {
818
1056
  const varName = declaratorNode.id.name;
819
1057
  if (/^[A-Z]/.test(varName)) {
820
1058
  return;
@@ -839,11 +1077,11 @@ var jsxNoNonComponentFunction = createRule11({
839
1077
  var jsx_no_non_component_function_default = jsxNoNonComponentFunction;
840
1078
 
841
1079
  // src/rules/no-logic-in-params.ts
842
- var import_utils14 = require("@typescript-eslint/utils");
843
- var createRule12 = import_utils14.ESLintUtils.RuleCreator(
1080
+ var import_utils16 = require("@typescript-eslint/utils");
1081
+ var createRule14 = import_utils16.ESLintUtils.RuleCreator(
844
1082
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
845
1083
  );
846
- var noLogicInParams = createRule12({
1084
+ var noLogicInParams = createRule14({
847
1085
  name: "no-logic-in-params",
848
1086
  meta: {
849
1087
  type: "suggestion",
@@ -858,20 +1096,20 @@ var noLogicInParams = createRule12({
858
1096
  defaultOptions: [],
859
1097
  create(context) {
860
1098
  const isComplexExpression = (node) => {
861
- if (node.type === import_utils14.AST_NODE_TYPES.SpreadElement) {
1099
+ if (node.type === import_utils16.AST_NODE_TYPES.SpreadElement) {
862
1100
  return false;
863
1101
  }
864
- if (node.type === import_utils14.AST_NODE_TYPES.ConditionalExpression) {
1102
+ if (node.type === import_utils16.AST_NODE_TYPES.ConditionalExpression) {
865
1103
  return true;
866
1104
  }
867
- if (node.type === import_utils14.AST_NODE_TYPES.LogicalExpression) {
1105
+ if (node.type === import_utils16.AST_NODE_TYPES.LogicalExpression) {
868
1106
  return true;
869
1107
  }
870
- if (node.type === import_utils14.AST_NODE_TYPES.BinaryExpression) {
1108
+ if (node.type === import_utils16.AST_NODE_TYPES.BinaryExpression) {
871
1109
  const logicalOperators = ["==", "===", "!=", "!==", "<", ">", "<=", ">=", "in", "instanceof"];
872
1110
  return logicalOperators.includes(node.operator);
873
1111
  }
874
- if (node.type === import_utils14.AST_NODE_TYPES.UnaryExpression) {
1112
+ if (node.type === import_utils16.AST_NODE_TYPES.UnaryExpression) {
875
1113
  return node.operator === "!";
876
1114
  }
877
1115
  return false;
@@ -902,12 +1140,263 @@ var noLogicInParams = createRule12({
902
1140
  });
903
1141
  var no_logic_in_params_default = noLogicInParams;
904
1142
 
1143
+ // src/rules/no-lazy-identifiers.ts
1144
+ var import_utils17 = require("@typescript-eslint/utils");
1145
+ var createRule15 = import_utils17.ESLintUtils.RuleCreator(
1146
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1147
+ );
1148
+ var KEYBOARD_ROWS = ["qwertyuiop", "asdfghjkl", "zxcvbnm", "1234567890"];
1149
+ var MIN_LENGTH = 3;
1150
+ var MIN_SEQUENCE_LENGTH = 4;
1151
+ var hasRepeatedChars = (name) => {
1152
+ const lowerName = name.toLowerCase();
1153
+ return lowerName.split("").some((char, index) => {
1154
+ if (index > lowerName.length - 3) {
1155
+ return false;
1156
+ }
1157
+ return char === lowerName[index + 1] && char === lowerName[index + 2];
1158
+ });
1159
+ };
1160
+ var hasKeyboardSequence = (name) => {
1161
+ const lowerName = name.toLowerCase();
1162
+ if (lowerName.length < MIN_SEQUENCE_LENGTH) {
1163
+ return false;
1164
+ }
1165
+ return KEYBOARD_ROWS.some((row) => {
1166
+ const positions = Array.from({ length: row.length - MIN_SEQUENCE_LENGTH + 1 }, (_, i) => i);
1167
+ return positions.some((start) => {
1168
+ const sequence = row.slice(start, start + MIN_SEQUENCE_LENGTH);
1169
+ const reverseSequence = sequence.split("").reverse().join("");
1170
+ return lowerName.includes(sequence) || lowerName.includes(reverseSequence);
1171
+ });
1172
+ });
1173
+ };
1174
+ var isLazyIdentifier = (name) => {
1175
+ if (name.length < MIN_LENGTH) {
1176
+ return false;
1177
+ }
1178
+ if (name.startsWith("_")) {
1179
+ return false;
1180
+ }
1181
+ if (hasRepeatedChars(name)) {
1182
+ return true;
1183
+ }
1184
+ if (hasKeyboardSequence(name)) {
1185
+ return true;
1186
+ }
1187
+ return false;
1188
+ };
1189
+ var noLazyIdentifiers = createRule15({
1190
+ name: "no-lazy-identifiers",
1191
+ meta: {
1192
+ type: "problem",
1193
+ docs: {
1194
+ description: "Disallow lazy, meaningless variable names that hurt code readability"
1195
+ },
1196
+ messages: {
1197
+ noLazyIdentifier: "Avoid lazy identifier '{{name}}'. Use a descriptive name that clearly indicates the purpose."
1198
+ },
1199
+ schema: []
1200
+ },
1201
+ defaultOptions: [],
1202
+ create(context) {
1203
+ const checkIdentifier = (node) => {
1204
+ const { name } = node;
1205
+ if (!isLazyIdentifier(name)) {
1206
+ return;
1207
+ }
1208
+ context.report({
1209
+ node,
1210
+ messageId: "noLazyIdentifier",
1211
+ data: { name }
1212
+ });
1213
+ };
1214
+ const checkPattern = (pattern) => {
1215
+ if (pattern.type === import_utils17.AST_NODE_TYPES.Identifier) {
1216
+ checkIdentifier(pattern);
1217
+ } else if (pattern.type === import_utils17.AST_NODE_TYPES.ObjectPattern) {
1218
+ pattern.properties.forEach((prop) => {
1219
+ if (prop.type === import_utils17.AST_NODE_TYPES.Property && prop.value.type === import_utils17.AST_NODE_TYPES.Identifier) {
1220
+ checkIdentifier(prop.value);
1221
+ } else if (prop.type === import_utils17.AST_NODE_TYPES.RestElement && prop.argument.type === import_utils17.AST_NODE_TYPES.Identifier) {
1222
+ checkIdentifier(prop.argument);
1223
+ }
1224
+ });
1225
+ } else if (pattern.type === import_utils17.AST_NODE_TYPES.ArrayPattern) {
1226
+ pattern.elements.forEach((element) => {
1227
+ if (element?.type === import_utils17.AST_NODE_TYPES.Identifier) {
1228
+ checkIdentifier(element);
1229
+ } else if (element?.type === import_utils17.AST_NODE_TYPES.RestElement && element.argument.type === import_utils17.AST_NODE_TYPES.Identifier) {
1230
+ checkIdentifier(element.argument);
1231
+ }
1232
+ });
1233
+ } else if (pattern.type === import_utils17.AST_NODE_TYPES.AssignmentPattern && pattern.left.type === import_utils17.AST_NODE_TYPES.Identifier) {
1234
+ checkIdentifier(pattern.left);
1235
+ } else if (pattern.type === import_utils17.AST_NODE_TYPES.RestElement && pattern.argument.type === import_utils17.AST_NODE_TYPES.Identifier) {
1236
+ checkIdentifier(pattern.argument);
1237
+ }
1238
+ };
1239
+ return {
1240
+ VariableDeclarator(node) {
1241
+ checkPattern(node.id);
1242
+ },
1243
+ FunctionDeclaration(node) {
1244
+ if (node.id) {
1245
+ checkIdentifier(node.id);
1246
+ }
1247
+ node.params.forEach((param) => checkPattern(param));
1248
+ },
1249
+ FunctionExpression(node) {
1250
+ if (node.id) {
1251
+ checkIdentifier(node.id);
1252
+ }
1253
+ node.params.forEach((param) => checkPattern(param));
1254
+ },
1255
+ ArrowFunctionExpression(node) {
1256
+ node.params.forEach((param) => checkPattern(param));
1257
+ },
1258
+ CatchClause(node) {
1259
+ if (node.param) {
1260
+ checkPattern(node.param);
1261
+ }
1262
+ },
1263
+ ClassDeclaration(node) {
1264
+ if (node.id) {
1265
+ checkIdentifier(node.id);
1266
+ }
1267
+ },
1268
+ TSTypeAliasDeclaration(node) {
1269
+ checkIdentifier(node.id);
1270
+ },
1271
+ TSInterfaceDeclaration(node) {
1272
+ checkIdentifier(node.id);
1273
+ }
1274
+ };
1275
+ }
1276
+ });
1277
+ var no_lazy_identifiers_default = noLazyIdentifiers;
1278
+
1279
+ // src/rules/no-single-char-variables.ts
1280
+ var import_utils18 = require("@typescript-eslint/utils");
1281
+ var createRule16 = import_utils18.ESLintUtils.RuleCreator(
1282
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1283
+ );
1284
+ var ALLOWED_IN_FOR_LOOPS = /* @__PURE__ */ new Set(["i", "j", "k", "n"]);
1285
+ var ALLOWED_UNDERSCORE = "_";
1286
+ var isForLoopInit = (node) => {
1287
+ let current = node;
1288
+ while (current) {
1289
+ const parentNode = current.parent;
1290
+ if (!parentNode) {
1291
+ return false;
1292
+ }
1293
+ if (parentNode.type === import_utils18.AST_NODE_TYPES.ForStatement) {
1294
+ const { init } = parentNode;
1295
+ if (init && init === current) {
1296
+ return true;
1297
+ }
1298
+ }
1299
+ current = parentNode;
1300
+ }
1301
+ return false;
1302
+ };
1303
+ var isAllowedInContext = (name, node) => {
1304
+ if (name === ALLOWED_UNDERSCORE) {
1305
+ return true;
1306
+ }
1307
+ if (ALLOWED_IN_FOR_LOOPS.has(name) && isForLoopInit(node)) {
1308
+ return true;
1309
+ }
1310
+ return false;
1311
+ };
1312
+ var noSingleCharVariables = createRule16({
1313
+ name: "no-single-char-variables",
1314
+ meta: {
1315
+ type: "suggestion",
1316
+ docs: {
1317
+ description: "Disallow single character variable and parameter names for better code readability"
1318
+ },
1319
+ messages: {
1320
+ noSingleChar: "Avoid single character variable name '{{name}}'. Use a descriptive name that clearly indicates the purpose."
1321
+ },
1322
+ schema: []
1323
+ },
1324
+ defaultOptions: [],
1325
+ create(context) {
1326
+ const checkIdentifier = (node, declarationNode) => {
1327
+ const { name } = node;
1328
+ if (name.length !== 1) {
1329
+ return;
1330
+ }
1331
+ if (isAllowedInContext(name, declarationNode)) {
1332
+ return;
1333
+ }
1334
+ context.report({
1335
+ node,
1336
+ messageId: "noSingleChar",
1337
+ data: { name }
1338
+ });
1339
+ };
1340
+ const checkPattern = (pattern, declarationNode) => {
1341
+ if (pattern.type === import_utils18.AST_NODE_TYPES.Identifier) {
1342
+ checkIdentifier(pattern, declarationNode);
1343
+ } else if (pattern.type === import_utils18.AST_NODE_TYPES.ObjectPattern) {
1344
+ pattern.properties.forEach((prop) => {
1345
+ if (prop.type === import_utils18.AST_NODE_TYPES.Property && prop.value.type === import_utils18.AST_NODE_TYPES.Identifier) {
1346
+ checkIdentifier(prop.value, declarationNode);
1347
+ } else if (prop.type === import_utils18.AST_NODE_TYPES.RestElement && prop.argument.type === import_utils18.AST_NODE_TYPES.Identifier) {
1348
+ checkIdentifier(prop.argument, declarationNode);
1349
+ }
1350
+ });
1351
+ } else if (pattern.type === import_utils18.AST_NODE_TYPES.ArrayPattern) {
1352
+ pattern.elements.forEach((element) => {
1353
+ if (element?.type === import_utils18.AST_NODE_TYPES.Identifier) {
1354
+ checkIdentifier(element, declarationNode);
1355
+ } else if (element?.type === import_utils18.AST_NODE_TYPES.RestElement && element.argument.type === import_utils18.AST_NODE_TYPES.Identifier) {
1356
+ checkIdentifier(element.argument, declarationNode);
1357
+ }
1358
+ });
1359
+ } else if (pattern.type === import_utils18.AST_NODE_TYPES.AssignmentPattern && pattern.left.type === import_utils18.AST_NODE_TYPES.Identifier) {
1360
+ checkIdentifier(pattern.left, declarationNode);
1361
+ } else if (pattern.type === import_utils18.AST_NODE_TYPES.RestElement && pattern.argument.type === import_utils18.AST_NODE_TYPES.Identifier) {
1362
+ checkIdentifier(pattern.argument, declarationNode);
1363
+ }
1364
+ };
1365
+ return {
1366
+ VariableDeclarator(node) {
1367
+ checkPattern(node.id, node);
1368
+ },
1369
+ FunctionDeclaration(node) {
1370
+ if (node.id) {
1371
+ checkIdentifier(node.id, node);
1372
+ }
1373
+ node.params.forEach((param) => checkPattern(param, node));
1374
+ },
1375
+ FunctionExpression(node) {
1376
+ if (node.id) {
1377
+ checkIdentifier(node.id, node);
1378
+ }
1379
+ node.params.forEach((param) => checkPattern(param, node));
1380
+ },
1381
+ ArrowFunctionExpression(node) {
1382
+ node.params.forEach((param) => checkPattern(param, node));
1383
+ },
1384
+ CatchClause(node) {
1385
+ if (node.param) {
1386
+ checkPattern(node.param, node);
1387
+ }
1388
+ }
1389
+ };
1390
+ }
1391
+ });
1392
+ var no_single_char_variables_default = noSingleCharVariables;
1393
+
905
1394
  // src/rules/prefer-destructuring-params.ts
906
- var import_utils15 = require("@typescript-eslint/utils");
907
- var createRule13 = import_utils15.ESLintUtils.RuleCreator(
1395
+ var import_utils19 = require("@typescript-eslint/utils");
1396
+ var createRule17 = import_utils19.ESLintUtils.RuleCreator(
908
1397
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
909
1398
  );
910
- var preferDestructuringParams = createRule13({
1399
+ var preferDestructuringParams = createRule17({
911
1400
  name: "prefer-destructuring-params",
912
1401
  meta: {
913
1402
  type: "suggestion",
@@ -921,20 +1410,20 @@ var preferDestructuringParams = createRule13({
921
1410
  },
922
1411
  defaultOptions: [],
923
1412
  create(context) {
924
- const isCallbackFunction = (node) => {
1413
+ const isCallbackFunction2 = (node) => {
925
1414
  const { parent } = node;
926
- return parent?.type === import_utils15.AST_NODE_TYPES.CallExpression;
1415
+ return parent?.type === import_utils19.AST_NODE_TYPES.CallExpression;
927
1416
  };
928
1417
  const isDeveloperFunction = (node) => {
929
- if (node.type === import_utils15.AST_NODE_TYPES.FunctionDeclaration) {
1418
+ if (node.type === import_utils19.AST_NODE_TYPES.FunctionDeclaration) {
930
1419
  return true;
931
1420
  }
932
- if (node.type === import_utils15.AST_NODE_TYPES.FunctionExpression || node.type === import_utils15.AST_NODE_TYPES.ArrowFunctionExpression) {
933
- if (isCallbackFunction(node)) {
1421
+ if (node.type === import_utils19.AST_NODE_TYPES.FunctionExpression || node.type === import_utils19.AST_NODE_TYPES.ArrowFunctionExpression) {
1422
+ if (isCallbackFunction2(node)) {
934
1423
  return false;
935
1424
  }
936
1425
  const { parent } = node;
937
- return parent?.type === import_utils15.AST_NODE_TYPES.VariableDeclarator || parent?.type === import_utils15.AST_NODE_TYPES.AssignmentExpression || parent?.type === import_utils15.AST_NODE_TYPES.Property || parent?.type === import_utils15.AST_NODE_TYPES.MethodDefinition;
1426
+ return parent?.type === import_utils19.AST_NODE_TYPES.VariableDeclarator || parent?.type === import_utils19.AST_NODE_TYPES.AssignmentExpression || parent?.type === import_utils19.AST_NODE_TYPES.Property || parent?.type === import_utils19.AST_NODE_TYPES.MethodDefinition;
938
1427
  }
939
1428
  return false;
940
1429
  };
@@ -946,7 +1435,7 @@ var preferDestructuringParams = createRule13({
946
1435
  if (!isDeveloperFunction(node)) {
947
1436
  return;
948
1437
  }
949
- if (node.type === import_utils15.AST_NODE_TYPES.FunctionDeclaration && node.id) {
1438
+ if (node.type === import_utils19.AST_NODE_TYPES.FunctionDeclaration && node.id) {
950
1439
  const functionName = node.id.name;
951
1440
  if (functionName.startsWith("_") || functionName.includes("$") || /^[A-Z][a-zA-Z]*$/.test(functionName)) {
952
1441
  return;
@@ -956,7 +1445,7 @@ var preferDestructuringParams = createRule13({
956
1445
  return;
957
1446
  }
958
1447
  const hasNonDestructuredParams = node.params.some(
959
- (param) => param.type !== import_utils15.AST_NODE_TYPES.ObjectPattern && param.type !== import_utils15.AST_NODE_TYPES.RestElement
1448
+ (param) => param.type !== import_utils19.AST_NODE_TYPES.ObjectPattern && param.type !== import_utils19.AST_NODE_TYPES.RestElement
960
1449
  );
961
1450
  if (hasNonDestructuredParams) {
962
1451
  context.report({
@@ -974,12 +1463,103 @@ var preferDestructuringParams = createRule13({
974
1463
  });
975
1464
  var prefer_destructuring_params_default = preferDestructuringParams;
976
1465
 
1466
+ // src/rules/prefer-function-declaration.ts
1467
+ var import_utils20 = require("@typescript-eslint/utils");
1468
+ var createRule18 = import_utils20.ESLintUtils.RuleCreator(
1469
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1470
+ );
1471
+ var isTsFile = (filename) => filename.endsWith(".ts") && !filename.endsWith(".d.ts");
1472
+ var isCallbackContext = (node) => {
1473
+ const { parent } = node;
1474
+ if (!parent) {
1475
+ return false;
1476
+ }
1477
+ if (parent.type === import_utils20.AST_NODE_TYPES.CallExpression && parent.arguments.includes(node)) {
1478
+ return true;
1479
+ }
1480
+ if (parent.type === import_utils20.AST_NODE_TYPES.NewExpression && parent.arguments.includes(node)) {
1481
+ return true;
1482
+ }
1483
+ if (parent.type === import_utils20.AST_NODE_TYPES.ReturnStatement) {
1484
+ return true;
1485
+ }
1486
+ if (parent.type === import_utils20.AST_NODE_TYPES.Property) {
1487
+ return true;
1488
+ }
1489
+ if (parent.type === import_utils20.AST_NODE_TYPES.ArrayExpression) {
1490
+ return true;
1491
+ }
1492
+ if (parent.type === import_utils20.AST_NODE_TYPES.ConditionalExpression) {
1493
+ return true;
1494
+ }
1495
+ if (parent.type === import_utils20.AST_NODE_TYPES.LogicalExpression) {
1496
+ return true;
1497
+ }
1498
+ if (parent.type === import_utils20.AST_NODE_TYPES.AssignmentExpression && parent.left !== node) {
1499
+ return true;
1500
+ }
1501
+ return false;
1502
+ };
1503
+ var preferFunctionDeclaration = createRule18({
1504
+ name: "prefer-function-declaration",
1505
+ meta: {
1506
+ type: "suggestion",
1507
+ docs: {
1508
+ description: "Enforce function declarations over arrow functions assigned to variables in .ts files for better readability and hoisting"
1509
+ },
1510
+ messages: {
1511
+ preferDeclaration: "Use function declaration instead of arrow function. Replace 'const {{name}} = () => ...' with 'function {{name}}() ...'",
1512
+ preferDeclarationExpr: "Use function declaration instead of function expression. Replace 'const {{name}} = function() ...' with 'function {{name}}() ...'"
1513
+ },
1514
+ schema: []
1515
+ },
1516
+ defaultOptions: [],
1517
+ create(context) {
1518
+ const { filename } = context;
1519
+ if (!isTsFile(filename)) {
1520
+ return {};
1521
+ }
1522
+ return {
1523
+ VariableDeclarator(node) {
1524
+ if (node.id.type !== import_utils20.AST_NODE_TYPES.Identifier) {
1525
+ return;
1526
+ }
1527
+ const { init } = node;
1528
+ if (!init) {
1529
+ return;
1530
+ }
1531
+ if (init.type === import_utils20.AST_NODE_TYPES.ArrowFunctionExpression) {
1532
+ if (isCallbackContext(init)) {
1533
+ return;
1534
+ }
1535
+ context.report({
1536
+ node: init,
1537
+ messageId: "preferDeclaration",
1538
+ data: { name: node.id.name }
1539
+ });
1540
+ }
1541
+ if (init.type === import_utils20.AST_NODE_TYPES.FunctionExpression) {
1542
+ if (isCallbackContext(init)) {
1543
+ return;
1544
+ }
1545
+ context.report({
1546
+ node: init,
1547
+ messageId: "preferDeclarationExpr",
1548
+ data: { name: node.id.name }
1549
+ });
1550
+ }
1551
+ }
1552
+ };
1553
+ }
1554
+ });
1555
+ var prefer_function_declaration_default = preferFunctionDeclaration;
1556
+
977
1557
  // src/rules/prefer-import-type.ts
978
- var import_utils16 = require("@typescript-eslint/utils");
979
- var createRule14 = import_utils16.ESLintUtils.RuleCreator(
1558
+ var import_utils21 = require("@typescript-eslint/utils");
1559
+ var createRule19 = import_utils21.ESLintUtils.RuleCreator(
980
1560
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
981
1561
  );
982
- var preferImportType = createRule14({
1562
+ var preferImportType = createRule19({
983
1563
  name: "prefer-import-type",
984
1564
  meta: {
985
1565
  type: "suggestion",
@@ -998,22 +1578,22 @@ var preferImportType = createRule14({
998
1578
  let current = node;
999
1579
  while (current) {
1000
1580
  switch (current.type) {
1001
- case import_utils16.AST_NODE_TYPES.TSTypeReference:
1002
- case import_utils16.AST_NODE_TYPES.TSTypeAnnotation:
1003
- case import_utils16.AST_NODE_TYPES.TSTypeParameterInstantiation:
1004
- case import_utils16.AST_NODE_TYPES.TSInterfaceHeritage:
1005
- case import_utils16.AST_NODE_TYPES.TSClassImplements:
1006
- case import_utils16.AST_NODE_TYPES.TSTypeQuery:
1007
- case import_utils16.AST_NODE_TYPES.TSTypeAssertion:
1008
- case import_utils16.AST_NODE_TYPES.TSAsExpression:
1009
- case import_utils16.AST_NODE_TYPES.TSSatisfiesExpression:
1010
- case import_utils16.AST_NODE_TYPES.TSTypeAliasDeclaration:
1011
- case import_utils16.AST_NODE_TYPES.TSInterfaceDeclaration:
1012
- case import_utils16.AST_NODE_TYPES.TSTypeParameter:
1013
- case import_utils16.AST_NODE_TYPES.TSQualifiedName:
1581
+ case import_utils21.AST_NODE_TYPES.TSTypeReference:
1582
+ case import_utils21.AST_NODE_TYPES.TSTypeAnnotation:
1583
+ case import_utils21.AST_NODE_TYPES.TSTypeParameterInstantiation:
1584
+ case import_utils21.AST_NODE_TYPES.TSInterfaceHeritage:
1585
+ case import_utils21.AST_NODE_TYPES.TSClassImplements:
1586
+ case import_utils21.AST_NODE_TYPES.TSTypeQuery:
1587
+ case import_utils21.AST_NODE_TYPES.TSTypeAssertion:
1588
+ case import_utils21.AST_NODE_TYPES.TSAsExpression:
1589
+ case import_utils21.AST_NODE_TYPES.TSSatisfiesExpression:
1590
+ case import_utils21.AST_NODE_TYPES.TSTypeAliasDeclaration:
1591
+ case import_utils21.AST_NODE_TYPES.TSInterfaceDeclaration:
1592
+ case import_utils21.AST_NODE_TYPES.TSTypeParameter:
1593
+ case import_utils21.AST_NODE_TYPES.TSQualifiedName:
1014
1594
  return true;
1015
- case import_utils16.AST_NODE_TYPES.MemberExpression:
1016
- case import_utils16.AST_NODE_TYPES.Identifier:
1595
+ case import_utils21.AST_NODE_TYPES.MemberExpression:
1596
+ case import_utils21.AST_NODE_TYPES.Identifier:
1017
1597
  current = current.parent;
1018
1598
  break;
1019
1599
  default:
@@ -1043,26 +1623,26 @@ var preferImportType = createRule14({
1043
1623
  return false;
1044
1624
  }
1045
1625
  switch (parent.type) {
1046
- case import_utils16.AST_NODE_TYPES.CallExpression:
1047
- case import_utils16.AST_NODE_TYPES.NewExpression:
1048
- case import_utils16.AST_NODE_TYPES.JSXOpeningElement:
1049
- case import_utils16.AST_NODE_TYPES.JSXClosingElement:
1050
- case import_utils16.AST_NODE_TYPES.MemberExpression:
1051
- case import_utils16.AST_NODE_TYPES.VariableDeclarator:
1052
- case import_utils16.AST_NODE_TYPES.TaggedTemplateExpression:
1053
- case import_utils16.AST_NODE_TYPES.SpreadElement:
1054
- case import_utils16.AST_NODE_TYPES.ExportSpecifier:
1055
- case import_utils16.AST_NODE_TYPES.ArrayExpression:
1056
- case import_utils16.AST_NODE_TYPES.ObjectExpression:
1057
- case import_utils16.AST_NODE_TYPES.BinaryExpression:
1058
- case import_utils16.AST_NODE_TYPES.LogicalExpression:
1059
- case import_utils16.AST_NODE_TYPES.UnaryExpression:
1060
- case import_utils16.AST_NODE_TYPES.ReturnStatement:
1061
- case import_utils16.AST_NODE_TYPES.ArrowFunctionExpression:
1062
- case import_utils16.AST_NODE_TYPES.ConditionalExpression:
1063
- case import_utils16.AST_NODE_TYPES.AwaitExpression:
1064
- case import_utils16.AST_NODE_TYPES.YieldExpression:
1065
- case import_utils16.AST_NODE_TYPES.Property:
1626
+ case import_utils21.AST_NODE_TYPES.CallExpression:
1627
+ case import_utils21.AST_NODE_TYPES.NewExpression:
1628
+ case import_utils21.AST_NODE_TYPES.JSXOpeningElement:
1629
+ case import_utils21.AST_NODE_TYPES.JSXClosingElement:
1630
+ case import_utils21.AST_NODE_TYPES.MemberExpression:
1631
+ case import_utils21.AST_NODE_TYPES.VariableDeclarator:
1632
+ case import_utils21.AST_NODE_TYPES.TaggedTemplateExpression:
1633
+ case import_utils21.AST_NODE_TYPES.SpreadElement:
1634
+ case import_utils21.AST_NODE_TYPES.ExportSpecifier:
1635
+ case import_utils21.AST_NODE_TYPES.ArrayExpression:
1636
+ case import_utils21.AST_NODE_TYPES.ObjectExpression:
1637
+ case import_utils21.AST_NODE_TYPES.BinaryExpression:
1638
+ case import_utils21.AST_NODE_TYPES.LogicalExpression:
1639
+ case import_utils21.AST_NODE_TYPES.UnaryExpression:
1640
+ case import_utils21.AST_NODE_TYPES.ReturnStatement:
1641
+ case import_utils21.AST_NODE_TYPES.ArrowFunctionExpression:
1642
+ case import_utils21.AST_NODE_TYPES.ConditionalExpression:
1643
+ case import_utils21.AST_NODE_TYPES.AwaitExpression:
1644
+ case import_utils21.AST_NODE_TYPES.YieldExpression:
1645
+ case import_utils21.AST_NODE_TYPES.Property:
1066
1646
  return true;
1067
1647
  default:
1068
1648
  return false;
@@ -1086,13 +1666,13 @@ var preferImportType = createRule14({
1086
1666
  }
1087
1667
  const scope = context.sourceCode.getScope(node);
1088
1668
  const isTypeOnlyImport = node.specifiers.every((specifier) => {
1089
- if (specifier.type === import_utils16.AST_NODE_TYPES.ImportDefaultSpecifier) {
1669
+ if (specifier.type === import_utils21.AST_NODE_TYPES.ImportDefaultSpecifier) {
1090
1670
  return false;
1091
1671
  }
1092
- if (specifier.type === import_utils16.AST_NODE_TYPES.ImportNamespaceSpecifier) {
1672
+ if (specifier.type === import_utils21.AST_NODE_TYPES.ImportNamespaceSpecifier) {
1093
1673
  return false;
1094
1674
  }
1095
- if (specifier.type === import_utils16.AST_NODE_TYPES.ImportSpecifier) {
1675
+ if (specifier.type === import_utils21.AST_NODE_TYPES.ImportSpecifier) {
1096
1676
  const localName = specifier.local.name;
1097
1677
  return !isUsedAsValue(localName, scope);
1098
1678
  }
@@ -1118,11 +1698,11 @@ var preferImportType = createRule14({
1118
1698
  var prefer_import_type_default = preferImportType;
1119
1699
 
1120
1700
  // src/rules/prefer-interface-over-inline-types.ts
1121
- var import_utils17 = require("@typescript-eslint/utils");
1122
- var createRule15 = import_utils17.ESLintUtils.RuleCreator(
1701
+ var import_utils22 = require("@typescript-eslint/utils");
1702
+ var createRule20 = import_utils22.ESLintUtils.RuleCreator(
1123
1703
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1124
1704
  );
1125
- var preferInterfaceOverInlineTypes = createRule15({
1705
+ var preferInterfaceOverInlineTypes = createRule20({
1126
1706
  name: "prefer-interface-over-inline-types",
1127
1707
  meta: {
1128
1708
  type: "suggestion",
@@ -1138,67 +1718,67 @@ var preferInterfaceOverInlineTypes = createRule15({
1138
1718
  defaultOptions: [],
1139
1719
  create(context) {
1140
1720
  function hasJSXInConditional(node) {
1141
- return node.consequent.type === import_utils17.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils17.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils17.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils17.AST_NODE_TYPES.JSXFragment;
1721
+ return node.consequent.type === import_utils22.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils22.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils22.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils22.AST_NODE_TYPES.JSXFragment;
1142
1722
  }
1143
1723
  function hasJSXInLogical(node) {
1144
- return node.right.type === import_utils17.AST_NODE_TYPES.JSXElement || node.right.type === import_utils17.AST_NODE_TYPES.JSXFragment;
1724
+ return node.right.type === import_utils22.AST_NODE_TYPES.JSXElement || node.right.type === import_utils22.AST_NODE_TYPES.JSXFragment;
1145
1725
  }
1146
1726
  function hasJSXReturn(block) {
1147
1727
  return block.body.some((stmt) => {
1148
- if (stmt.type === import_utils17.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
1149
- return stmt.argument.type === import_utils17.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils17.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils17.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils17.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
1728
+ if (stmt.type === import_utils22.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
1729
+ return stmt.argument.type === import_utils22.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils22.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils22.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils22.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
1150
1730
  }
1151
1731
  return false;
1152
1732
  });
1153
1733
  }
1154
- function isReactComponent(node) {
1155
- if (node.type === import_utils17.AST_NODE_TYPES.ArrowFunctionExpression) {
1156
- if (node.body.type === import_utils17.AST_NODE_TYPES.JSXElement || node.body.type === import_utils17.AST_NODE_TYPES.JSXFragment) {
1734
+ function isReactComponent2(node) {
1735
+ if (node.type === import_utils22.AST_NODE_TYPES.ArrowFunctionExpression) {
1736
+ if (node.body.type === import_utils22.AST_NODE_TYPES.JSXElement || node.body.type === import_utils22.AST_NODE_TYPES.JSXFragment) {
1157
1737
  return true;
1158
1738
  }
1159
- if (node.body.type === import_utils17.AST_NODE_TYPES.BlockStatement) {
1739
+ if (node.body.type === import_utils22.AST_NODE_TYPES.BlockStatement) {
1160
1740
  return hasJSXReturn(node.body);
1161
1741
  }
1162
- } else if (node.type === import_utils17.AST_NODE_TYPES.FunctionExpression || node.type === import_utils17.AST_NODE_TYPES.FunctionDeclaration) {
1163
- if (node.body && node.body.type === import_utils17.AST_NODE_TYPES.BlockStatement) {
1742
+ } else if (node.type === import_utils22.AST_NODE_TYPES.FunctionExpression || node.type === import_utils22.AST_NODE_TYPES.FunctionDeclaration) {
1743
+ if (node.body && node.body.type === import_utils22.AST_NODE_TYPES.BlockStatement) {
1164
1744
  return hasJSXReturn(node.body);
1165
1745
  }
1166
1746
  }
1167
1747
  return false;
1168
1748
  }
1169
1749
  function isInlineTypeAnnotation(node) {
1170
- if (node.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral) {
1750
+ if (node.type === import_utils22.AST_NODE_TYPES.TSTypeLiteral) {
1171
1751
  return true;
1172
1752
  }
1173
- if (node.type === import_utils17.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
1174
- return node.typeArguments.params.some((param) => param.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral);
1753
+ if (node.type === import_utils22.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
1754
+ return node.typeArguments.params.some((param) => param.type === import_utils22.AST_NODE_TYPES.TSTypeLiteral);
1175
1755
  }
1176
- if (node.type === import_utils17.AST_NODE_TYPES.TSUnionType) {
1756
+ if (node.type === import_utils22.AST_NODE_TYPES.TSUnionType) {
1177
1757
  return node.types.some((type) => isInlineTypeAnnotation(type));
1178
1758
  }
1179
1759
  return false;
1180
1760
  }
1181
1761
  function hasInlineObjectType(node) {
1182
- if (node.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral) {
1762
+ if (node.type === import_utils22.AST_NODE_TYPES.TSTypeLiteral) {
1183
1763
  return true;
1184
1764
  }
1185
- if (node.type === import_utils17.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
1186
- return node.typeArguments.params.some((param) => param.type === import_utils17.AST_NODE_TYPES.TSTypeLiteral);
1765
+ if (node.type === import_utils22.AST_NODE_TYPES.TSTypeReference && node.typeArguments) {
1766
+ return node.typeArguments.params.some((param) => param.type === import_utils22.AST_NODE_TYPES.TSTypeLiteral);
1187
1767
  }
1188
- if (node.type === import_utils17.AST_NODE_TYPES.TSUnionType) {
1768
+ if (node.type === import_utils22.AST_NODE_TYPES.TSUnionType) {
1189
1769
  return node.types.some((type) => hasInlineObjectType(type));
1190
1770
  }
1191
1771
  return false;
1192
1772
  }
1193
1773
  function checkFunction(node) {
1194
- if (!isReactComponent(node)) {
1774
+ if (!isReactComponent2(node)) {
1195
1775
  return;
1196
1776
  }
1197
1777
  if (node.params.length !== 1) {
1198
1778
  return;
1199
1779
  }
1200
1780
  const param = node.params[0];
1201
- if (param.type === import_utils17.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
1781
+ if (param.type === import_utils22.AST_NODE_TYPES.Identifier && param.typeAnnotation) {
1202
1782
  const { typeAnnotation } = param.typeAnnotation;
1203
1783
  if (isInlineTypeAnnotation(typeAnnotation) && hasInlineObjectType(typeAnnotation)) {
1204
1784
  context.report({
@@ -1218,11 +1798,11 @@ var preferInterfaceOverInlineTypes = createRule15({
1218
1798
  var prefer_interface_over_inline_types_default = preferInterfaceOverInlineTypes;
1219
1799
 
1220
1800
  // src/rules/prefer-jsx-template-literals.ts
1221
- var import_utils18 = require("@typescript-eslint/utils");
1222
- var createRule16 = import_utils18.ESLintUtils.RuleCreator(
1801
+ var import_utils23 = require("@typescript-eslint/utils");
1802
+ var createRule21 = import_utils23.ESLintUtils.RuleCreator(
1223
1803
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1224
1804
  );
1225
- var preferJSXTemplateLiterals = createRule16({
1805
+ var preferJSXTemplateLiterals = createRule21({
1226
1806
  name: "prefer-jsx-template-literals",
1227
1807
  meta: {
1228
1808
  type: "suggestion",
@@ -1291,9 +1871,9 @@ var preferJSXTemplateLiterals = createRule16({
1291
1871
  if (!child || !nextChild) {
1292
1872
  return;
1293
1873
  }
1294
- if (child.type === import_utils18.AST_NODE_TYPES.JSXText && nextChild.type === import_utils18.AST_NODE_TYPES.JSXExpressionContainer) {
1874
+ if (child.type === import_utils23.AST_NODE_TYPES.JSXText && nextChild.type === import_utils23.AST_NODE_TYPES.JSXExpressionContainer) {
1295
1875
  handleTextBeforeExpression(child, nextChild);
1296
- } else if (child.type === import_utils18.AST_NODE_TYPES.JSXExpressionContainer && nextChild.type === import_utils18.AST_NODE_TYPES.JSXText) {
1876
+ } else if (child.type === import_utils23.AST_NODE_TYPES.JSXExpressionContainer && nextChild.type === import_utils23.AST_NODE_TYPES.JSXText) {
1297
1877
  handleExpressionBeforeText(child, nextChild);
1298
1878
  }
1299
1879
  }
@@ -1306,11 +1886,11 @@ var preferJSXTemplateLiterals = createRule16({
1306
1886
  var prefer_jsx_template_literals_default = preferJSXTemplateLiterals;
1307
1887
 
1308
1888
  // src/rules/prefer-named-param-types.ts
1309
- var import_utils19 = require("@typescript-eslint/utils");
1310
- var createRule17 = import_utils19.ESLintUtils.RuleCreator(
1889
+ var import_utils24 = require("@typescript-eslint/utils");
1890
+ var createRule22 = import_utils24.ESLintUtils.RuleCreator(
1311
1891
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1312
1892
  );
1313
- var preferNamedParamTypes = createRule17({
1893
+ var preferNamedParamTypes = createRule22({
1314
1894
  name: "prefer-named-param-types",
1315
1895
  meta: {
1316
1896
  type: "suggestion",
@@ -1325,16 +1905,16 @@ var preferNamedParamTypes = createRule17({
1325
1905
  defaultOptions: [],
1326
1906
  create(context) {
1327
1907
  function hasInlineObjectType(param) {
1328
- if (param.type === import_utils19.AST_NODE_TYPES.AssignmentPattern) {
1908
+ if (param.type === import_utils24.AST_NODE_TYPES.AssignmentPattern) {
1329
1909
  return hasInlineObjectType(param.left);
1330
1910
  }
1331
- if (param.type === import_utils19.AST_NODE_TYPES.ObjectPattern) {
1332
- if (param.typeAnnotation?.typeAnnotation.type === import_utils19.AST_NODE_TYPES.TSTypeLiteral) {
1911
+ if (param.type === import_utils24.AST_NODE_TYPES.ObjectPattern) {
1912
+ if (param.typeAnnotation?.typeAnnotation.type === import_utils24.AST_NODE_TYPES.TSTypeLiteral) {
1333
1913
  return true;
1334
1914
  }
1335
1915
  }
1336
- if (param.type === import_utils19.AST_NODE_TYPES.Identifier) {
1337
- if (param.typeAnnotation?.typeAnnotation.type === import_utils19.AST_NODE_TYPES.TSTypeLiteral) {
1916
+ if (param.type === import_utils24.AST_NODE_TYPES.Identifier) {
1917
+ if (param.typeAnnotation?.typeAnnotation.type === import_utils24.AST_NODE_TYPES.TSTypeLiteral) {
1338
1918
  return true;
1339
1919
  }
1340
1920
  }
@@ -1368,11 +1948,11 @@ var preferNamedParamTypes = createRule17({
1368
1948
  var prefer_named_param_types_default = preferNamedParamTypes;
1369
1949
 
1370
1950
  // src/rules/prefer-react-import-types.ts
1371
- var import_utils20 = require("@typescript-eslint/utils");
1372
- var createRule18 = import_utils20.ESLintUtils.RuleCreator(
1951
+ var import_utils25 = require("@typescript-eslint/utils");
1952
+ var createRule23 = import_utils25.ESLintUtils.RuleCreator(
1373
1953
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1374
1954
  );
1375
- var preferReactImportTypes = createRule18({
1955
+ var preferReactImportTypes = createRule23({
1376
1956
  name: "prefer-react-import-types",
1377
1957
  meta: {
1378
1958
  type: "suggestion",
@@ -1448,7 +2028,7 @@ var preferReactImportTypes = createRule18({
1448
2028
  ]);
1449
2029
  const allReactExports = /* @__PURE__ */ new Set([...reactTypes, ...reactRuntimeExports]);
1450
2030
  function checkMemberExpression(node) {
1451
- if (node.object.type === import_utils20.AST_NODE_TYPES.Identifier && node.object.name === "React" && node.property.type === import_utils20.AST_NODE_TYPES.Identifier && allReactExports.has(node.property.name)) {
2031
+ if (node.object.type === import_utils25.AST_NODE_TYPES.Identifier && node.object.name === "React" && node.property.type === import_utils25.AST_NODE_TYPES.Identifier && allReactExports.has(node.property.name)) {
1452
2032
  const typeName = node.property.name;
1453
2033
  const isType = reactTypes.has(typeName);
1454
2034
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -1465,7 +2045,7 @@ var preferReactImportTypes = createRule18({
1465
2045
  return {
1466
2046
  MemberExpression: checkMemberExpression,
1467
2047
  "TSTypeReference > TSQualifiedName": (node) => {
1468
- if (node.left.type === import_utils20.AST_NODE_TYPES.Identifier && node.left.name === "React" && node.right.type === import_utils20.AST_NODE_TYPES.Identifier && allReactExports.has(node.right.name)) {
2048
+ if (node.left.type === import_utils25.AST_NODE_TYPES.Identifier && node.left.name === "React" && node.right.type === import_utils25.AST_NODE_TYPES.Identifier && allReactExports.has(node.right.name)) {
1469
2049
  const typeName = node.right.name;
1470
2050
  const isType = reactTypes.has(typeName);
1471
2051
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -1485,11 +2065,11 @@ var preferReactImportTypes = createRule18({
1485
2065
  var prefer_react_import_types_default = preferReactImportTypes;
1486
2066
 
1487
2067
  // src/rules/react-props-destructure.ts
1488
- var import_utils21 = require("@typescript-eslint/utils");
1489
- var createRule19 = import_utils21.ESLintUtils.RuleCreator(
2068
+ var import_utils26 = require("@typescript-eslint/utils");
2069
+ var createRule24 = import_utils26.ESLintUtils.RuleCreator(
1490
2070
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1491
2071
  );
1492
- var reactPropsDestructure = createRule19({
2072
+ var reactPropsDestructure = createRule24({
1493
2073
  name: "react-props-destructure",
1494
2074
  meta: {
1495
2075
  type: "suggestion",
@@ -1505,45 +2085,45 @@ var reactPropsDestructure = createRule19({
1505
2085
  defaultOptions: [],
1506
2086
  create(context) {
1507
2087
  function hasJSXInConditional(node) {
1508
- return node.consequent.type === import_utils21.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils21.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils21.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils21.AST_NODE_TYPES.JSXFragment;
2088
+ return node.consequent.type === import_utils26.AST_NODE_TYPES.JSXElement || node.consequent.type === import_utils26.AST_NODE_TYPES.JSXFragment || node.alternate.type === import_utils26.AST_NODE_TYPES.JSXElement || node.alternate.type === import_utils26.AST_NODE_TYPES.JSXFragment;
1509
2089
  }
1510
2090
  function hasJSXInLogical(node) {
1511
- return node.right.type === import_utils21.AST_NODE_TYPES.JSXElement || node.right.type === import_utils21.AST_NODE_TYPES.JSXFragment;
2091
+ return node.right.type === import_utils26.AST_NODE_TYPES.JSXElement || node.right.type === import_utils26.AST_NODE_TYPES.JSXFragment;
1512
2092
  }
1513
2093
  function hasJSXReturn(block) {
1514
2094
  return block.body.some((stmt) => {
1515
- if (stmt.type === import_utils21.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
1516
- return stmt.argument.type === import_utils21.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils21.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils21.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils21.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
2095
+ if (stmt.type === import_utils26.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
2096
+ return stmt.argument.type === import_utils26.AST_NODE_TYPES.JSXElement || stmt.argument.type === import_utils26.AST_NODE_TYPES.JSXFragment || stmt.argument.type === import_utils26.AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === import_utils26.AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
1517
2097
  }
1518
2098
  return false;
1519
2099
  });
1520
2100
  }
1521
- function isReactComponent(node) {
1522
- if (node.type === import_utils21.AST_NODE_TYPES.ArrowFunctionExpression) {
1523
- if (node.body.type === import_utils21.AST_NODE_TYPES.JSXElement || node.body.type === import_utils21.AST_NODE_TYPES.JSXFragment) {
2101
+ function isReactComponent2(node) {
2102
+ if (node.type === import_utils26.AST_NODE_TYPES.ArrowFunctionExpression) {
2103
+ if (node.body.type === import_utils26.AST_NODE_TYPES.JSXElement || node.body.type === import_utils26.AST_NODE_TYPES.JSXFragment) {
1524
2104
  return true;
1525
2105
  }
1526
- if (node.body.type === import_utils21.AST_NODE_TYPES.BlockStatement) {
2106
+ if (node.body.type === import_utils26.AST_NODE_TYPES.BlockStatement) {
1527
2107
  return hasJSXReturn(node.body);
1528
2108
  }
1529
- } else if (node.type === import_utils21.AST_NODE_TYPES.FunctionExpression || node.type === import_utils21.AST_NODE_TYPES.FunctionDeclaration) {
1530
- if (node.body && node.body.type === import_utils21.AST_NODE_TYPES.BlockStatement) {
2109
+ } else if (node.type === import_utils26.AST_NODE_TYPES.FunctionExpression || node.type === import_utils26.AST_NODE_TYPES.FunctionDeclaration) {
2110
+ if (node.body && node.body.type === import_utils26.AST_NODE_TYPES.BlockStatement) {
1531
2111
  return hasJSXReturn(node.body);
1532
2112
  }
1533
2113
  }
1534
2114
  return false;
1535
2115
  }
1536
2116
  function checkFunction(node) {
1537
- if (!isReactComponent(node)) {
2117
+ if (!isReactComponent2(node)) {
1538
2118
  return;
1539
2119
  }
1540
2120
  if (node.params.length !== 1) {
1541
2121
  return;
1542
2122
  }
1543
2123
  const param = node.params[0];
1544
- if (param.type === import_utils21.AST_NODE_TYPES.ObjectPattern) {
1545
- const properties = param.properties.filter((prop) => prop.type === import_utils21.AST_NODE_TYPES.Property).map((prop) => {
1546
- if (prop.key.type === import_utils21.AST_NODE_TYPES.Identifier) {
2124
+ if (param.type === import_utils26.AST_NODE_TYPES.ObjectPattern) {
2125
+ const properties = param.properties.filter((prop) => prop.type === import_utils26.AST_NODE_TYPES.Property).map((prop) => {
2126
+ if (prop.key.type === import_utils26.AST_NODE_TYPES.Identifier) {
1547
2127
  return prop.key.name;
1548
2128
  }
1549
2129
  return null;
@@ -1575,6 +2155,7 @@ var meta = {
1575
2155
  version: package_default.version
1576
2156
  };
1577
2157
  var rules = {
2158
+ "boolean-naming-prefix": boolean_naming_prefix_default,
1578
2159
  "enforce-readonly-component-props": enforce_readonly_component_props_default,
1579
2160
  "enforce-sorted-destructuring": enforce_sorted_destructuring_default,
1580
2161
  "file-kebab-case": file_kebab_case_default,
@@ -1583,11 +2164,15 @@ var rules = {
1583
2164
  "jsx-no-variable-in-callback": jsx_no_variable_in_callback_default,
1584
2165
  "md-filename-case-restriction": md_filename_case_restriction_default,
1585
2166
  "no-complex-inline-return": no_complex_inline_return_default,
2167
+ "no-direct-date": no_direct_date_default,
1586
2168
  "no-emoji": no_emoji_default,
1587
2169
  "no-env-fallback": no_env_fallback_default,
1588
- "no-explicit-return-type": no_explicit_return_type_default,
2170
+ "require-explicit-return-type": require_explicit_return_type_default,
2171
+ "no-lazy-identifiers": no_lazy_identifiers_default,
1589
2172
  "no-logic-in-params": no_logic_in_params_default,
2173
+ "no-single-char-variables": no_single_char_variables_default,
1590
2174
  "prefer-destructuring-params": prefer_destructuring_params_default,
2175
+ "prefer-function-declaration": prefer_function_declaration_default,
1591
2176
  "prefer-import-type": prefer_import_type_default,
1592
2177
  "prefer-interface-over-inline-types": prefer_interface_over_inline_types_default,
1593
2178
  "prefer-jsx-template-literals": prefer_jsx_template_literals_default,
@@ -1600,32 +2185,42 @@ var plugin = {
1600
2185
  rules
1601
2186
  };
1602
2187
  var baseRules = {
2188
+ "nextfriday/boolean-naming-prefix": "warn",
1603
2189
  "nextfriday/no-emoji": "warn",
1604
2190
  "nextfriday/enforce-sorted-destructuring": "warn",
1605
2191
  "nextfriday/file-kebab-case": "warn",
1606
2192
  "nextfriday/md-filename-case-restriction": "warn",
1607
2193
  "nextfriday/prefer-destructuring-params": "warn",
1608
- "nextfriday/no-explicit-return-type": "warn",
2194
+ "nextfriday/prefer-function-declaration": "warn",
2195
+ "nextfriday/require-explicit-return-type": "warn",
1609
2196
  "nextfriday/prefer-import-type": "warn",
1610
2197
  "nextfriday/prefer-named-param-types": "warn",
1611
2198
  "nextfriday/prefer-react-import-types": "warn",
1612
2199
  "nextfriday/no-complex-inline-return": "warn",
2200
+ "nextfriday/no-direct-date": "warn",
1613
2201
  "nextfriday/no-logic-in-params": "warn",
1614
- "nextfriday/no-env-fallback": "warn"
2202
+ "nextfriday/no-env-fallback": "warn",
2203
+ "nextfriday/no-lazy-identifiers": "warn",
2204
+ "nextfriday/no-single-char-variables": "warn"
1615
2205
  };
1616
2206
  var baseRecommendedRules = {
2207
+ "nextfriday/boolean-naming-prefix": "error",
1617
2208
  "nextfriday/no-emoji": "error",
1618
2209
  "nextfriday/enforce-sorted-destructuring": "error",
1619
2210
  "nextfriday/file-kebab-case": "error",
1620
2211
  "nextfriday/md-filename-case-restriction": "error",
1621
2212
  "nextfriday/prefer-destructuring-params": "error",
1622
- "nextfriday/no-explicit-return-type": "error",
2213
+ "nextfriday/prefer-function-declaration": "error",
2214
+ "nextfriday/require-explicit-return-type": "error",
1623
2215
  "nextfriday/prefer-import-type": "error",
1624
2216
  "nextfriday/prefer-named-param-types": "error",
1625
2217
  "nextfriday/prefer-react-import-types": "error",
1626
2218
  "nextfriday/no-complex-inline-return": "error",
2219
+ "nextfriday/no-direct-date": "error",
1627
2220
  "nextfriday/no-logic-in-params": "error",
1628
- "nextfriday/no-env-fallback": "error"
2221
+ "nextfriday/no-env-fallback": "error",
2222
+ "nextfriday/no-lazy-identifiers": "error",
2223
+ "nextfriday/no-single-char-variables": "error"
1629
2224
  };
1630
2225
  var jsxRules = {
1631
2226
  "nextfriday/jsx-pascal-case": "warn",