eslint-plugin-nextfriday 1.6.0 → 1.7.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.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "eslint-plugin-nextfriday",
4
- version: "1.6.0",
4
+ version: "1.7.0",
5
5
  description: "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
6
6
  keywords: [
7
7
  "eslint",
@@ -115,12 +115,143 @@ var package_default = {
115
115
  }
116
116
  };
117
117
 
118
- // src/rules/enforce-readonly-component-props.ts
119
- import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
118
+ // src/rules/boolean-naming-prefix.ts
119
+ import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
120
120
  var createRule = ESLintUtils.RuleCreator(
121
121
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
122
122
  );
123
- var enforceReadonlyComponentProps = createRule({
123
+ var BOOLEAN_PREFIXES = ["is", "has", "should", "can", "did", "will", "was", "are", "does", "had"];
124
+ var startsWithBooleanPrefix = (name) => {
125
+ const lowerName = name.toLowerCase();
126
+ return BOOLEAN_PREFIXES.some((prefix) => {
127
+ if (!lowerName.startsWith(prefix)) {
128
+ return false;
129
+ }
130
+ if (name.length === prefix.length) {
131
+ return true;
132
+ }
133
+ const nextChar = name.charAt(prefix.length);
134
+ return nextChar === nextChar.toUpperCase();
135
+ });
136
+ };
137
+ var isBooleanLiteral = (node) => node.type === AST_NODE_TYPES.Literal && typeof node.value === "boolean";
138
+ var isBooleanExpression = (node) => {
139
+ if (isBooleanLiteral(node)) {
140
+ return true;
141
+ }
142
+ if (node.type === AST_NODE_TYPES.UnaryExpression && node.operator === "!") {
143
+ return true;
144
+ }
145
+ if (node.type === AST_NODE_TYPES.BinaryExpression) {
146
+ const comparisonOperators = ["===", "!==", "==", "!=", "<", ">", "<=", ">=", "in", "instanceof"];
147
+ return comparisonOperators.includes(node.operator);
148
+ }
149
+ if (node.type === AST_NODE_TYPES.LogicalExpression) {
150
+ return node.operator === "&&" || node.operator === "||";
151
+ }
152
+ return false;
153
+ };
154
+ var hasBooleanTypeAnnotation = (node) => {
155
+ if (node.type === AST_NODE_TYPES.Identifier) {
156
+ const { typeAnnotation } = node;
157
+ if (typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES.TSBooleanKeyword) {
158
+ return true;
159
+ }
160
+ }
161
+ if ("id" in node && node.id.type === AST_NODE_TYPES.Identifier) {
162
+ const { typeAnnotation } = node.id;
163
+ if (typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES.TSBooleanKeyword) {
164
+ return true;
165
+ }
166
+ }
167
+ return false;
168
+ };
169
+ var booleanNamingPrefix = createRule({
170
+ name: "boolean-naming-prefix",
171
+ meta: {
172
+ type: "suggestion",
173
+ docs: {
174
+ description: "Enforce boolean variables and parameters to have a prefix like is, has, should, can, did, will for better readability"
175
+ },
176
+ messages: {
177
+ missingPrefix: "Boolean variable '{{name}}' should have a prefix like is, has, should, can, did, or will. Example: 'is{{suggestedName}}' or 'has{{suggestedName}}'."
178
+ },
179
+ schema: []
180
+ },
181
+ defaultOptions: [],
182
+ create(context) {
183
+ const checkBooleanNaming = (name, node) => {
184
+ if (startsWithBooleanPrefix(name)) {
185
+ return;
186
+ }
187
+ const suggestedName = name.charAt(0).toUpperCase() + name.slice(1);
188
+ context.report({
189
+ node,
190
+ messageId: "missingPrefix",
191
+ data: { name, suggestedName }
192
+ });
193
+ };
194
+ return {
195
+ VariableDeclarator(node) {
196
+ if (node.id.type !== AST_NODE_TYPES.Identifier) {
197
+ return;
198
+ }
199
+ const { name } = node.id;
200
+ if (hasBooleanTypeAnnotation(node)) {
201
+ checkBooleanNaming(name, node.id);
202
+ return;
203
+ }
204
+ if (node.init && isBooleanExpression(node.init)) {
205
+ checkBooleanNaming(name, node.id);
206
+ }
207
+ },
208
+ FunctionDeclaration(node) {
209
+ node.params.forEach((param) => {
210
+ if (param.type === AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
211
+ checkBooleanNaming(param.name, param);
212
+ }
213
+ if (param.type === AST_NODE_TYPES.AssignmentPattern) {
214
+ if (param.left.type === AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
215
+ checkBooleanNaming(param.left.name, param.left);
216
+ }
217
+ }
218
+ });
219
+ },
220
+ FunctionExpression(node) {
221
+ node.params.forEach((param) => {
222
+ if (param.type === AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
223
+ checkBooleanNaming(param.name, param);
224
+ }
225
+ if (param.type === AST_NODE_TYPES.AssignmentPattern) {
226
+ if (param.left.type === AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
227
+ checkBooleanNaming(param.left.name, param.left);
228
+ }
229
+ }
230
+ });
231
+ },
232
+ ArrowFunctionExpression(node) {
233
+ node.params.forEach((param) => {
234
+ if (param.type === AST_NODE_TYPES.Identifier && hasBooleanTypeAnnotation(param)) {
235
+ checkBooleanNaming(param.name, param);
236
+ }
237
+ if (param.type === AST_NODE_TYPES.AssignmentPattern) {
238
+ if (param.left.type === AST_NODE_TYPES.Identifier && param.right && isBooleanLiteral(param.right)) {
239
+ checkBooleanNaming(param.left.name, param.left);
240
+ }
241
+ }
242
+ });
243
+ }
244
+ };
245
+ }
246
+ });
247
+ var boolean_naming_prefix_default = booleanNamingPrefix;
248
+
249
+ // src/rules/enforce-readonly-component-props.ts
250
+ import { AST_NODE_TYPES as AST_NODE_TYPES2, ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
251
+ var createRule2 = ESLintUtils2.RuleCreator(
252
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
253
+ );
254
+ var enforceReadonlyComponentProps = createRule2({
124
255
  name: "enforce-readonly-component-props",
125
256
  meta: {
126
257
  type: "suggestion",
@@ -136,54 +267,54 @@ var enforceReadonlyComponentProps = createRule({
136
267
  defaultOptions: [],
137
268
  create(context) {
138
269
  function hasJSXInConditional(node) {
139
- return node.consequent.type === AST_NODE_TYPES.JSXElement || node.consequent.type === AST_NODE_TYPES.JSXFragment || node.alternate.type === AST_NODE_TYPES.JSXElement || node.alternate.type === AST_NODE_TYPES.JSXFragment;
270
+ return node.consequent.type === AST_NODE_TYPES2.JSXElement || node.consequent.type === AST_NODE_TYPES2.JSXFragment || node.alternate.type === AST_NODE_TYPES2.JSXElement || node.alternate.type === AST_NODE_TYPES2.JSXFragment;
140
271
  }
141
272
  function hasJSXInLogical(node) {
142
- return node.right.type === AST_NODE_TYPES.JSXElement || node.right.type === AST_NODE_TYPES.JSXFragment;
273
+ return node.right.type === AST_NODE_TYPES2.JSXElement || node.right.type === AST_NODE_TYPES2.JSXFragment;
143
274
  }
144
275
  function hasJSXReturn(block) {
145
276
  return block.body.some((stmt) => {
146
- if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument) {
147
- return stmt.argument.type === AST_NODE_TYPES.JSXElement || stmt.argument.type === AST_NODE_TYPES.JSXFragment || stmt.argument.type === AST_NODE_TYPES.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES.LogicalExpression && hasJSXInLogical(stmt.argument);
277
+ if (stmt.type === AST_NODE_TYPES2.ReturnStatement && stmt.argument) {
278
+ return stmt.argument.type === AST_NODE_TYPES2.JSXElement || stmt.argument.type === AST_NODE_TYPES2.JSXFragment || stmt.argument.type === AST_NODE_TYPES2.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES2.LogicalExpression && hasJSXInLogical(stmt.argument);
148
279
  }
149
280
  return false;
150
281
  });
151
282
  }
152
- function isReactComponent(node) {
153
- if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {
154
- if (node.body.type === AST_NODE_TYPES.JSXElement || node.body.type === AST_NODE_TYPES.JSXFragment) {
283
+ function isReactComponent2(node) {
284
+ if (node.type === AST_NODE_TYPES2.ArrowFunctionExpression) {
285
+ if (node.body.type === AST_NODE_TYPES2.JSXElement || node.body.type === AST_NODE_TYPES2.JSXFragment) {
155
286
  return true;
156
287
  }
157
- if (node.body.type === AST_NODE_TYPES.BlockStatement) {
288
+ if (node.body.type === AST_NODE_TYPES2.BlockStatement) {
158
289
  return hasJSXReturn(node.body);
159
290
  }
160
- } else if (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.FunctionDeclaration) {
161
- if (node.body && node.body.type === AST_NODE_TYPES.BlockStatement) {
291
+ } else if (node.type === AST_NODE_TYPES2.FunctionExpression || node.type === AST_NODE_TYPES2.FunctionDeclaration) {
292
+ if (node.body && node.body.type === AST_NODE_TYPES2.BlockStatement) {
162
293
  return hasJSXReturn(node.body);
163
294
  }
164
295
  }
165
296
  return false;
166
297
  }
167
298
  function isNamedType(node) {
168
- return node.type === AST_NODE_TYPES.TSTypeReference;
299
+ return node.type === AST_NODE_TYPES2.TSTypeReference;
169
300
  }
170
301
  function isAlreadyReadonly(node) {
171
- if (node.type === AST_NODE_TYPES.TSTypeReference && node.typeName) {
172
- if (node.typeName.type === AST_NODE_TYPES.Identifier && node.typeName.name === "Readonly") {
302
+ if (node.type === AST_NODE_TYPES2.TSTypeReference && node.typeName) {
303
+ if (node.typeName.type === AST_NODE_TYPES2.Identifier && node.typeName.name === "Readonly") {
173
304
  return true;
174
305
  }
175
306
  }
176
307
  return false;
177
308
  }
178
309
  function checkFunction(node) {
179
- if (!isReactComponent(node)) {
310
+ if (!isReactComponent2(node)) {
180
311
  return;
181
312
  }
182
313
  if (node.params.length !== 1) {
183
314
  return;
184
315
  }
185
316
  const param = node.params[0];
186
- if (param.type === AST_NODE_TYPES.Identifier && param.typeAnnotation) {
317
+ if (param.type === AST_NODE_TYPES2.Identifier && param.typeAnnotation) {
187
318
  const { typeAnnotation } = param.typeAnnotation;
188
319
  if (isNamedType(typeAnnotation) && !isAlreadyReadonly(typeAnnotation)) {
189
320
  const { sourceCode } = context;
@@ -208,11 +339,11 @@ var enforceReadonlyComponentProps = createRule({
208
339
  var enforce_readonly_component_props_default = enforceReadonlyComponentProps;
209
340
 
210
341
  // src/rules/enforce-sorted-destructuring.ts
211
- import { AST_NODE_TYPES as AST_NODE_TYPES2, ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
212
- var createRule2 = ESLintUtils2.RuleCreator(
342
+ import { AST_NODE_TYPES as AST_NODE_TYPES3, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
343
+ var createRule3 = ESLintUtils3.RuleCreator(
213
344
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
214
345
  );
215
- var enforceSortedDestructuring = createRule2({
346
+ var enforceSortedDestructuring = createRule3({
216
347
  name: "enforce-sorted-destructuring",
217
348
  meta: {
218
349
  type: "suggestion",
@@ -227,16 +358,16 @@ var enforceSortedDestructuring = createRule2({
227
358
  defaultOptions: [],
228
359
  create(context) {
229
360
  function getPropertyName(property) {
230
- if (property.type === AST_NODE_TYPES2.RestElement) {
361
+ if (property.type === AST_NODE_TYPES3.RestElement) {
231
362
  return null;
232
363
  }
233
- if (property.key.type === AST_NODE_TYPES2.Identifier) {
364
+ if (property.key.type === AST_NODE_TYPES3.Identifier) {
234
365
  return property.key.name;
235
366
  }
236
367
  return null;
237
368
  }
238
369
  function hasDefaultValue(property) {
239
- return property.value.type === AST_NODE_TYPES2.AssignmentPattern && Boolean(property.value.right);
370
+ return property.value.type === AST_NODE_TYPES3.AssignmentPattern && Boolean(property.value.right);
240
371
  }
241
372
  function getDefaultValueType(property) {
242
373
  if (!hasDefaultValue(property)) {
@@ -248,7 +379,7 @@ var enforceSortedDestructuring = createRule2({
248
379
  return "none";
249
380
  }
250
381
  switch (right.type) {
251
- case AST_NODE_TYPES2.Literal:
382
+ case AST_NODE_TYPES3.Literal:
252
383
  if (typeof right.value === "string") {
253
384
  return "string";
254
385
  }
@@ -259,10 +390,10 @@ var enforceSortedDestructuring = createRule2({
259
390
  return "boolean";
260
391
  }
261
392
  return "other";
262
- case AST_NODE_TYPES2.TemplateLiteral:
393
+ case AST_NODE_TYPES3.TemplateLiteral:
263
394
  return "string";
264
- case AST_NODE_TYPES2.ObjectExpression:
265
- case AST_NODE_TYPES2.ArrayExpression:
395
+ case AST_NODE_TYPES3.ObjectExpression:
396
+ case AST_NODE_TYPES3.ArrayExpression:
266
397
  return "object";
267
398
  default:
268
399
  return "other";
@@ -280,7 +411,7 @@ var enforceSortedDestructuring = createRule2({
280
411
  return order[type] ?? 5;
281
412
  }
282
413
  function checkVariableDeclarator(node) {
283
- if (node.id.type !== AST_NODE_TYPES2.ObjectPattern) {
414
+ if (node.id.type !== AST_NODE_TYPES3.ObjectPattern) {
284
415
  return;
285
416
  }
286
417
  const { properties } = node.id;
@@ -288,7 +419,7 @@ var enforceSortedDestructuring = createRule2({
288
419
  return;
289
420
  }
290
421
  const propertyInfo = properties.map((prop) => {
291
- if (prop.type === AST_NODE_TYPES2.RestElement) {
422
+ if (prop.type === AST_NODE_TYPES3.RestElement) {
292
423
  return null;
293
424
  }
294
425
  return {
@@ -330,8 +461,8 @@ var enforce_sorted_destructuring_default = enforceSortedDestructuring;
330
461
 
331
462
  // src/rules/file-kebab-case.ts
332
463
  import path from "path";
333
- import { ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
334
- var createRule3 = ESLintUtils3.RuleCreator(
464
+ import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
465
+ var createRule4 = ESLintUtils4.RuleCreator(
335
466
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
336
467
  );
337
468
  var isKebabCase = (str) => {
@@ -340,7 +471,7 @@ var isKebabCase = (str) => {
340
471
  }
341
472
  return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(str);
342
473
  };
343
- var fileKebabCase = createRule3({
474
+ var fileKebabCase = createRule4({
344
475
  name: "file-kebab-case",
345
476
  meta: {
346
477
  type: "problem",
@@ -376,12 +507,12 @@ var file_kebab_case_default = fileKebabCase;
376
507
 
377
508
  // src/rules/jsx-pascal-case.ts
378
509
  import path2 from "path";
379
- import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
380
- var createRule4 = ESLintUtils4.RuleCreator(
510
+ import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
511
+ var createRule5 = ESLintUtils5.RuleCreator(
381
512
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
382
513
  );
383
514
  var isPascalCase = (str) => /^[A-Z][a-zA-Z0-9]*$/.test(str) && !/^[A-Z]+$/.test(str);
384
- var jsxPascalCase = createRule4({
515
+ var jsxPascalCase = createRule5({
385
516
  name: "jsx-pascal-case",
386
517
  meta: {
387
518
  type: "problem",
@@ -415,12 +546,64 @@ var jsxPascalCase = createRule4({
415
546
  });
416
547
  var jsx_pascal_case_default = jsxPascalCase;
417
548
 
549
+ // src/rules/no-direct-date.ts
550
+ import { ESLintUtils as ESLintUtils6, AST_NODE_TYPES as AST_NODE_TYPES4 } from "@typescript-eslint/utils";
551
+ var createRule6 = ESLintUtils6.RuleCreator(
552
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
553
+ );
554
+ var noDirectDate = createRule6({
555
+ name: "no-direct-date",
556
+ meta: {
557
+ type: "problem",
558
+ docs: {
559
+ description: "Disallow direct usage of Date constructor and methods to enforce centralized date utilities"
560
+ },
561
+ messages: {
562
+ noNewDate: "Avoid using 'new Date()'. Use a centralized date utility like dayjs instead.",
563
+ noDateNow: "Avoid using 'Date.now()'. Use a centralized date utility like dayjs instead.",
564
+ noDateParse: "Avoid using 'Date.parse()'. Use a centralized date utility like dayjs instead."
565
+ },
566
+ schema: []
567
+ },
568
+ defaultOptions: [],
569
+ create(context) {
570
+ return {
571
+ NewExpression(node) {
572
+ if (node.callee.type === AST_NODE_TYPES4.Identifier && node.callee.name === "Date") {
573
+ context.report({
574
+ node,
575
+ messageId: "noNewDate"
576
+ });
577
+ }
578
+ },
579
+ CallExpression(node) {
580
+ if (node.callee.type === AST_NODE_TYPES4.MemberExpression && node.callee.object.type === AST_NODE_TYPES4.Identifier && node.callee.object.name === "Date" && node.callee.property.type === AST_NODE_TYPES4.Identifier) {
581
+ const methodName = node.callee.property.name;
582
+ if (methodName === "now") {
583
+ context.report({
584
+ node,
585
+ messageId: "noDateNow"
586
+ });
587
+ }
588
+ if (methodName === "parse") {
589
+ context.report({
590
+ node,
591
+ messageId: "noDateParse"
592
+ });
593
+ }
594
+ }
595
+ }
596
+ };
597
+ }
598
+ });
599
+ var no_direct_date_default = noDirectDate;
600
+
418
601
  // src/rules/jsx-no-variable-in-callback.ts
419
- import { AST_NODE_TYPES as AST_NODE_TYPES3, ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
420
- var createRule5 = ESLintUtils5.RuleCreator(
602
+ import { AST_NODE_TYPES as AST_NODE_TYPES5, ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
603
+ var createRule7 = ESLintUtils7.RuleCreator(
421
604
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
422
605
  );
423
- var jsxNoVariableInCallback = createRule5({
606
+ var jsxNoVariableInCallback = createRule7({
424
607
  name: "jsx-no-variable-in-callback",
425
608
  meta: {
426
609
  type: "suggestion",
@@ -437,7 +620,7 @@ var jsxNoVariableInCallback = createRule5({
437
620
  function isInsideJSX(node) {
438
621
  let current = node.parent;
439
622
  while (current) {
440
- if (current.type === AST_NODE_TYPES3.JSXElement || current.type === AST_NODE_TYPES3.JSXFragment) {
623
+ if (current.type === AST_NODE_TYPES5.JSXElement || current.type === AST_NODE_TYPES5.JSXFragment) {
441
624
  return true;
442
625
  }
443
626
  current = current.parent;
@@ -451,11 +634,11 @@ var jsxNoVariableInCallback = createRule5({
451
634
  if (!isInsideJSX(node)) {
452
635
  return false;
453
636
  }
454
- if (node.parent.type === AST_NODE_TYPES3.CallExpression || node.parent.type === AST_NODE_TYPES3.JSXExpressionContainer) {
637
+ if (node.parent.type === AST_NODE_TYPES5.CallExpression || node.parent.type === AST_NODE_TYPES5.JSXExpressionContainer) {
455
638
  return true;
456
639
  }
457
- if (node.parent.type === AST_NODE_TYPES3.ArrayExpression && node.parent.parent) {
458
- if (node.parent.parent.type === AST_NODE_TYPES3.CallExpression || node.parent.parent.type === AST_NODE_TYPES3.JSXExpressionContainer) {
640
+ if (node.parent.type === AST_NODE_TYPES5.ArrayExpression && node.parent.parent) {
641
+ if (node.parent.parent.type === AST_NODE_TYPES5.CallExpression || node.parent.parent.type === AST_NODE_TYPES5.JSXExpressionContainer) {
459
642
  return true;
460
643
  }
461
644
  }
@@ -466,11 +649,11 @@ var jsxNoVariableInCallback = createRule5({
466
649
  return;
467
650
  }
468
651
  const { body } = node;
469
- if (body.type !== AST_NODE_TYPES3.BlockStatement) {
652
+ if (body.type !== AST_NODE_TYPES5.BlockStatement) {
470
653
  return;
471
654
  }
472
655
  body.body.forEach((statement) => {
473
- if (statement.type === AST_NODE_TYPES3.VariableDeclaration) {
656
+ if (statement.type === AST_NODE_TYPES5.VariableDeclaration) {
474
657
  context.report({
475
658
  node: statement,
476
659
  messageId: "noVariableInCallback"
@@ -488,11 +671,11 @@ var jsx_no_variable_in_callback_default = jsxNoVariableInCallback;
488
671
 
489
672
  // src/rules/md-filename-case-restriction.ts
490
673
  import path3 from "path";
491
- import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
492
- var createRule6 = ESLintUtils6.RuleCreator(
674
+ import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
675
+ var createRule8 = ESLintUtils8.RuleCreator(
493
676
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
494
677
  );
495
- var mdFilenameCaseRestriction = createRule6({
678
+ var mdFilenameCaseRestriction = createRule8({
496
679
  name: "md-filename-case-restriction",
497
680
  meta: {
498
681
  type: "problem",
@@ -533,11 +716,11 @@ var mdFilenameCaseRestriction = createRule6({
533
716
  var md_filename_case_restriction_default = mdFilenameCaseRestriction;
534
717
 
535
718
  // src/rules/no-complex-inline-return.ts
536
- import { ESLintUtils as ESLintUtils7, AST_NODE_TYPES as AST_NODE_TYPES4 } from "@typescript-eslint/utils";
537
- var createRule7 = ESLintUtils7.RuleCreator(
719
+ import { ESLintUtils as ESLintUtils9, AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
720
+ var createRule9 = ESLintUtils9.RuleCreator(
538
721
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
539
722
  );
540
- var noComplexInlineReturn = createRule7({
723
+ var noComplexInlineReturn = createRule9({
541
724
  name: "no-complex-inline-return",
542
725
  meta: {
543
726
  type: "suggestion",
@@ -553,13 +736,13 @@ var noComplexInlineReturn = createRule7({
553
736
  create(context) {
554
737
  const isComplexExpression = (node) => {
555
738
  if (!node) return false;
556
- if (node.type === AST_NODE_TYPES4.ConditionalExpression) {
739
+ if (node.type === AST_NODE_TYPES6.ConditionalExpression) {
557
740
  return true;
558
741
  }
559
- if (node.type === AST_NODE_TYPES4.LogicalExpression) {
742
+ if (node.type === AST_NODE_TYPES6.LogicalExpression) {
560
743
  return true;
561
744
  }
562
- if (node.type === AST_NODE_TYPES4.NewExpression) {
745
+ if (node.type === AST_NODE_TYPES6.NewExpression) {
563
746
  return true;
564
747
  }
565
748
  return false;
@@ -580,11 +763,11 @@ var no_complex_inline_return_default = noComplexInlineReturn;
580
763
 
581
764
  // src/rules/no-emoji.ts
582
765
  import emojiRegex from "emoji-regex";
583
- import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
584
- var createRule8 = ESLintUtils8.RuleCreator(
766
+ import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
767
+ var createRule10 = ESLintUtils10.RuleCreator(
585
768
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
586
769
  );
587
- var noEmoji = createRule8({
770
+ var noEmoji = createRule10({
588
771
  name: "no-emoji",
589
772
  meta: {
590
773
  type: "problem",
@@ -618,11 +801,11 @@ var noEmoji = createRule8({
618
801
  var no_emoji_default = noEmoji;
619
802
 
620
803
  // src/rules/no-env-fallback.ts
621
- import { ESLintUtils as ESLintUtils9, AST_NODE_TYPES as AST_NODE_TYPES5 } from "@typescript-eslint/utils";
622
- var createRule9 = ESLintUtils9.RuleCreator(
804
+ import { ESLintUtils as ESLintUtils11, AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
805
+ var createRule11 = ESLintUtils11.RuleCreator(
623
806
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
624
807
  );
625
- var noEnvFallback = createRule9({
808
+ var noEnvFallback = createRule11({
626
809
  name: "no-env-fallback",
627
810
  meta: {
628
811
  type: "problem",
@@ -637,16 +820,16 @@ var noEnvFallback = createRule9({
637
820
  defaultOptions: [],
638
821
  create(context) {
639
822
  const isProcessEnvAccess = (node) => {
640
- if (node.type !== AST_NODE_TYPES5.MemberExpression) {
823
+ if (node.type !== AST_NODE_TYPES7.MemberExpression) {
641
824
  return false;
642
825
  }
643
826
  const { object } = node;
644
- if (object.type !== AST_NODE_TYPES5.MemberExpression) {
827
+ if (object.type !== AST_NODE_TYPES7.MemberExpression) {
645
828
  return false;
646
829
  }
647
830
  const processNode = object.object;
648
831
  const envNode = object.property;
649
- return processNode.type === AST_NODE_TYPES5.Identifier && processNode.name === "process" && envNode.type === AST_NODE_TYPES5.Identifier && envNode.name === "env";
832
+ return processNode.type === AST_NODE_TYPES7.Identifier && processNode.name === "process" && envNode.type === AST_NODE_TYPES7.Identifier && envNode.name === "env";
650
833
  };
651
834
  return {
652
835
  LogicalExpression(node) {
@@ -670,38 +853,93 @@ var noEnvFallback = createRule9({
670
853
  });
671
854
  var no_env_fallback_default = noEnvFallback;
672
855
 
673
- // src/rules/no-explicit-return-type.ts
674
- import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
675
- var createRule10 = ESLintUtils10.RuleCreator(
856
+ // src/rules/require-explicit-return-type.ts
857
+ import { ESLintUtils as ESLintUtils12, AST_NODE_TYPES as AST_NODE_TYPES8 } from "@typescript-eslint/utils";
858
+ var createRule12 = ESLintUtils12.RuleCreator(
676
859
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
677
860
  );
678
- var noExplicitReturnType = createRule10({
679
- name: "no-explicit-return-type",
861
+ var isReactComponent = (node) => {
862
+ if (node.type === AST_NODE_TYPES8.ArrowFunctionExpression) {
863
+ const { parent } = node;
864
+ if (parent?.type === AST_NODE_TYPES8.VariableDeclarator) {
865
+ const { id } = parent;
866
+ if (id.type === AST_NODE_TYPES8.Identifier) {
867
+ return /^[A-Z]/.test(id.name);
868
+ }
869
+ }
870
+ }
871
+ if (node.type === AST_NODE_TYPES8.FunctionDeclaration && node.id) {
872
+ return /^[A-Z]/.test(node.id.name);
873
+ }
874
+ return false;
875
+ };
876
+ var isCallbackFunction = (node) => {
877
+ if (node.type === AST_NODE_TYPES8.FunctionDeclaration) {
878
+ return false;
879
+ }
880
+ const { parent } = node;
881
+ if (!parent) {
882
+ return false;
883
+ }
884
+ if (parent.type === AST_NODE_TYPES8.CallExpression && parent.arguments.includes(node)) {
885
+ return true;
886
+ }
887
+ if (parent.type === AST_NODE_TYPES8.Property) {
888
+ return true;
889
+ }
890
+ if (parent.type === AST_NODE_TYPES8.ArrayExpression) {
891
+ return true;
892
+ }
893
+ return false;
894
+ };
895
+ var getFunctionName = (node) => {
896
+ if (node.type === AST_NODE_TYPES8.FunctionDeclaration && node.id) {
897
+ return node.id.name;
898
+ }
899
+ if (node.type === AST_NODE_TYPES8.FunctionExpression && node.id) {
900
+ return node.id.name;
901
+ }
902
+ if ((node.type === AST_NODE_TYPES8.ArrowFunctionExpression || node.type === AST_NODE_TYPES8.FunctionExpression) && node.parent?.type === AST_NODE_TYPES8.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES8.Identifier) {
903
+ return node.parent.id.name;
904
+ }
905
+ return null;
906
+ };
907
+ var requireExplicitReturnType = createRule12({
908
+ name: "require-explicit-return-type",
680
909
  meta: {
681
910
  type: "suggestion",
682
911
  docs: {
683
- description: "Disallow explicit return types on functions"
912
+ description: "Require explicit return types on functions for better code documentation and type safety"
684
913
  },
685
- fixable: "code",
686
- schema: [],
687
914
  messages: {
688
- noExplicitReturnType: "Remove explicit return type '{{returnType}}' - TypeScript can infer it automatically"
689
- }
915
+ missingReturnType: "Function '{{name}}' is missing an explicit return type. Add a return type annotation for better documentation.",
916
+ missingReturnTypeAnonymous: "Function is missing an explicit return type. Add a return type annotation for better documentation."
917
+ },
918
+ schema: []
690
919
  },
691
920
  defaultOptions: [],
692
921
  create(context) {
693
922
  const checkFunction = (node) => {
694
923
  if (node.returnType) {
695
- const returnTypeText = context.sourceCode.getText(node.returnType);
924
+ return;
925
+ }
926
+ if (isCallbackFunction(node)) {
927
+ return;
928
+ }
929
+ if (isReactComponent(node)) {
930
+ return;
931
+ }
932
+ const functionName = getFunctionName(node);
933
+ if (functionName) {
696
934
  context.report({
697
- node: node.returnType,
698
- messageId: "noExplicitReturnType",
699
- data: {
700
- returnType: returnTypeText
701
- },
702
- fix(fixer) {
703
- return fixer.remove(node.returnType);
704
- }
935
+ node,
936
+ messageId: "missingReturnType",
937
+ data: { name: functionName }
938
+ });
939
+ } else {
940
+ context.report({
941
+ node,
942
+ messageId: "missingReturnTypeAnonymous"
705
943
  });
706
944
  }
707
945
  };
@@ -712,21 +950,21 @@ var noExplicitReturnType = createRule10({
712
950
  };
713
951
  }
714
952
  });
715
- var no_explicit_return_type_default = noExplicitReturnType;
953
+ var require_explicit_return_type_default = requireExplicitReturnType;
716
954
 
717
955
  // src/rules/jsx-no-non-component-function.ts
718
- import { AST_NODE_TYPES as AST_NODE_TYPES7, ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
956
+ import { AST_NODE_TYPES as AST_NODE_TYPES10, ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
719
957
 
720
958
  // src/utils.ts
721
959
  import { basename, extname } from "path";
722
- import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
960
+ import { AST_NODE_TYPES as AST_NODE_TYPES9 } from "@typescript-eslint/utils";
723
961
  var getFileExtension = (filename) => extname(filename).slice(1);
724
962
 
725
963
  // src/rules/jsx-no-non-component-function.ts
726
- var createRule11 = ESLintUtils11.RuleCreator(
964
+ var createRule13 = ESLintUtils13.RuleCreator(
727
965
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
728
966
  );
729
- var jsxNoNonComponentFunction = createRule11({
967
+ var jsxNoNonComponentFunction = createRule13({
730
968
  name: "jsx-no-non-component-function",
731
969
  meta: {
732
970
  type: "problem",
@@ -745,14 +983,14 @@ var jsxNoNonComponentFunction = createRule11({
745
983
  if (extension !== "tsx" && extension !== "jsx") {
746
984
  return {};
747
985
  }
748
- function isReactComponent(node) {
749
- const functionName = node.type === AST_NODE_TYPES7.FunctionDeclaration && node.id ? node.id.name : null;
986
+ function isReactComponent2(node) {
987
+ const functionName = node.type === AST_NODE_TYPES10.FunctionDeclaration && node.id ? node.id.name : null;
750
988
  if (functionName && /^[A-Z]/.test(functionName)) {
751
989
  return true;
752
990
  }
753
991
  if (node.returnType?.typeAnnotation) {
754
992
  const returnTypeNode = node.returnType.typeAnnotation;
755
- if (returnTypeNode.type === AST_NODE_TYPES7.TSTypeReference && returnTypeNode.typeName.type === AST_NODE_TYPES7.Identifier) {
993
+ if (returnTypeNode.type === AST_NODE_TYPES10.TSTypeReference && returnTypeNode.typeName.type === AST_NODE_TYPES10.Identifier) {
756
994
  const typeName = returnTypeNode.typeName.name;
757
995
  if (typeName === "JSX" || typeName === "ReactElement" || typeName === "ReactNode") {
758
996
  return true;
@@ -762,20 +1000,20 @@ var jsxNoNonComponentFunction = createRule11({
762
1000
  return false;
763
1001
  }
764
1002
  function checkTopLevelFunction(node, declaratorNode) {
765
- if (isReactComponent(node)) {
1003
+ if (isReactComponent2(node)) {
766
1004
  return;
767
1005
  }
768
1006
  const { parent } = node;
769
1007
  if (!parent) {
770
1008
  return;
771
1009
  }
772
- if (parent.type === AST_NODE_TYPES7.ExportDefaultDeclaration || parent.type === AST_NODE_TYPES7.ExportNamedDeclaration) {
1010
+ if (parent.type === AST_NODE_TYPES10.ExportDefaultDeclaration || parent.type === AST_NODE_TYPES10.ExportNamedDeclaration) {
773
1011
  return;
774
1012
  }
775
- if (declaratorNode?.parent?.parent?.type === AST_NODE_TYPES7.ExportNamedDeclaration) {
1013
+ if (declaratorNode?.parent?.parent?.type === AST_NODE_TYPES10.ExportNamedDeclaration) {
776
1014
  return;
777
1015
  }
778
- if (declaratorNode?.id.type === AST_NODE_TYPES7.Identifier) {
1016
+ if (declaratorNode?.id.type === AST_NODE_TYPES10.Identifier) {
779
1017
  const varName = declaratorNode.id.name;
780
1018
  if (/^[A-Z]/.test(varName)) {
781
1019
  return;
@@ -800,11 +1038,11 @@ var jsxNoNonComponentFunction = createRule11({
800
1038
  var jsx_no_non_component_function_default = jsxNoNonComponentFunction;
801
1039
 
802
1040
  // src/rules/no-logic-in-params.ts
803
- import { ESLintUtils as ESLintUtils12, AST_NODE_TYPES as AST_NODE_TYPES8 } from "@typescript-eslint/utils";
804
- var createRule12 = ESLintUtils12.RuleCreator(
1041
+ import { ESLintUtils as ESLintUtils14, AST_NODE_TYPES as AST_NODE_TYPES11 } from "@typescript-eslint/utils";
1042
+ var createRule14 = ESLintUtils14.RuleCreator(
805
1043
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
806
1044
  );
807
- var noLogicInParams = createRule12({
1045
+ var noLogicInParams = createRule14({
808
1046
  name: "no-logic-in-params",
809
1047
  meta: {
810
1048
  type: "suggestion",
@@ -819,20 +1057,20 @@ var noLogicInParams = createRule12({
819
1057
  defaultOptions: [],
820
1058
  create(context) {
821
1059
  const isComplexExpression = (node) => {
822
- if (node.type === AST_NODE_TYPES8.SpreadElement) {
1060
+ if (node.type === AST_NODE_TYPES11.SpreadElement) {
823
1061
  return false;
824
1062
  }
825
- if (node.type === AST_NODE_TYPES8.ConditionalExpression) {
1063
+ if (node.type === AST_NODE_TYPES11.ConditionalExpression) {
826
1064
  return true;
827
1065
  }
828
- if (node.type === AST_NODE_TYPES8.LogicalExpression) {
1066
+ if (node.type === AST_NODE_TYPES11.LogicalExpression) {
829
1067
  return true;
830
1068
  }
831
- if (node.type === AST_NODE_TYPES8.BinaryExpression) {
1069
+ if (node.type === AST_NODE_TYPES11.BinaryExpression) {
832
1070
  const logicalOperators = ["==", "===", "!=", "!==", "<", ">", "<=", ">=", "in", "instanceof"];
833
1071
  return logicalOperators.includes(node.operator);
834
1072
  }
835
- if (node.type === AST_NODE_TYPES8.UnaryExpression) {
1073
+ if (node.type === AST_NODE_TYPES11.UnaryExpression) {
836
1074
  return node.operator === "!";
837
1075
  }
838
1076
  return false;
@@ -863,12 +1101,127 @@ var noLogicInParams = createRule12({
863
1101
  });
864
1102
  var no_logic_in_params_default = noLogicInParams;
865
1103
 
1104
+ // src/rules/no-single-char-variables.ts
1105
+ import { ESLintUtils as ESLintUtils15, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
1106
+ var createRule15 = ESLintUtils15.RuleCreator(
1107
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1108
+ );
1109
+ var ALLOWED_IN_FOR_LOOPS = /* @__PURE__ */ new Set(["i", "j", "k", "n"]);
1110
+ var ALLOWED_UNDERSCORE = "_";
1111
+ var isForLoopInit = (node) => {
1112
+ let current = node;
1113
+ while (current) {
1114
+ const parentNode = current.parent;
1115
+ if (!parentNode) {
1116
+ return false;
1117
+ }
1118
+ if (parentNode.type === AST_NODE_TYPES12.ForStatement) {
1119
+ const { init } = parentNode;
1120
+ if (init && init === current) {
1121
+ return true;
1122
+ }
1123
+ }
1124
+ current = parentNode;
1125
+ }
1126
+ return false;
1127
+ };
1128
+ var isAllowedInContext = (name, node) => {
1129
+ if (name === ALLOWED_UNDERSCORE) {
1130
+ return true;
1131
+ }
1132
+ if (ALLOWED_IN_FOR_LOOPS.has(name) && isForLoopInit(node)) {
1133
+ return true;
1134
+ }
1135
+ return false;
1136
+ };
1137
+ var noSingleCharVariables = createRule15({
1138
+ name: "no-single-char-variables",
1139
+ meta: {
1140
+ type: "suggestion",
1141
+ docs: {
1142
+ description: "Disallow single character variable and parameter names for better code readability"
1143
+ },
1144
+ messages: {
1145
+ noSingleChar: "Avoid single character variable name '{{name}}'. Use a descriptive name that clearly indicates the purpose."
1146
+ },
1147
+ schema: []
1148
+ },
1149
+ defaultOptions: [],
1150
+ create(context) {
1151
+ const checkIdentifier = (node, declarationNode) => {
1152
+ const { name } = node;
1153
+ if (name.length !== 1) {
1154
+ return;
1155
+ }
1156
+ if (isAllowedInContext(name, declarationNode)) {
1157
+ return;
1158
+ }
1159
+ context.report({
1160
+ node,
1161
+ messageId: "noSingleChar",
1162
+ data: { name }
1163
+ });
1164
+ };
1165
+ const checkPattern = (pattern, declarationNode) => {
1166
+ if (pattern.type === AST_NODE_TYPES12.Identifier) {
1167
+ checkIdentifier(pattern, declarationNode);
1168
+ } else if (pattern.type === AST_NODE_TYPES12.ObjectPattern) {
1169
+ pattern.properties.forEach((prop) => {
1170
+ if (prop.type === AST_NODE_TYPES12.Property && prop.value.type === AST_NODE_TYPES12.Identifier) {
1171
+ checkIdentifier(prop.value, declarationNode);
1172
+ } else if (prop.type === AST_NODE_TYPES12.RestElement && prop.argument.type === AST_NODE_TYPES12.Identifier) {
1173
+ checkIdentifier(prop.argument, declarationNode);
1174
+ }
1175
+ });
1176
+ } else if (pattern.type === AST_NODE_TYPES12.ArrayPattern) {
1177
+ pattern.elements.forEach((element) => {
1178
+ if (element?.type === AST_NODE_TYPES12.Identifier) {
1179
+ checkIdentifier(element, declarationNode);
1180
+ } else if (element?.type === AST_NODE_TYPES12.RestElement && element.argument.type === AST_NODE_TYPES12.Identifier) {
1181
+ checkIdentifier(element.argument, declarationNode);
1182
+ }
1183
+ });
1184
+ } else if (pattern.type === AST_NODE_TYPES12.AssignmentPattern && pattern.left.type === AST_NODE_TYPES12.Identifier) {
1185
+ checkIdentifier(pattern.left, declarationNode);
1186
+ } else if (pattern.type === AST_NODE_TYPES12.RestElement && pattern.argument.type === AST_NODE_TYPES12.Identifier) {
1187
+ checkIdentifier(pattern.argument, declarationNode);
1188
+ }
1189
+ };
1190
+ return {
1191
+ VariableDeclarator(node) {
1192
+ checkPattern(node.id, node);
1193
+ },
1194
+ FunctionDeclaration(node) {
1195
+ if (node.id) {
1196
+ checkIdentifier(node.id, node);
1197
+ }
1198
+ node.params.forEach((param) => checkPattern(param, node));
1199
+ },
1200
+ FunctionExpression(node) {
1201
+ if (node.id) {
1202
+ checkIdentifier(node.id, node);
1203
+ }
1204
+ node.params.forEach((param) => checkPattern(param, node));
1205
+ },
1206
+ ArrowFunctionExpression(node) {
1207
+ node.params.forEach((param) => checkPattern(param, node));
1208
+ },
1209
+ CatchClause(node) {
1210
+ if (node.param) {
1211
+ checkPattern(node.param, node);
1212
+ }
1213
+ }
1214
+ };
1215
+ }
1216
+ });
1217
+ var no_single_char_variables_default = noSingleCharVariables;
1218
+
866
1219
  // src/rules/prefer-destructuring-params.ts
867
- import { AST_NODE_TYPES as AST_NODE_TYPES9, ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
868
- var createRule13 = ESLintUtils13.RuleCreator(
1220
+ import { AST_NODE_TYPES as AST_NODE_TYPES13, ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
1221
+ var createRule16 = ESLintUtils16.RuleCreator(
869
1222
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
870
1223
  );
871
- var preferDestructuringParams = createRule13({
1224
+ var preferDestructuringParams = createRule16({
872
1225
  name: "prefer-destructuring-params",
873
1226
  meta: {
874
1227
  type: "suggestion",
@@ -882,20 +1235,20 @@ var preferDestructuringParams = createRule13({
882
1235
  },
883
1236
  defaultOptions: [],
884
1237
  create(context) {
885
- const isCallbackFunction = (node) => {
1238
+ const isCallbackFunction2 = (node) => {
886
1239
  const { parent } = node;
887
- return parent?.type === AST_NODE_TYPES9.CallExpression;
1240
+ return parent?.type === AST_NODE_TYPES13.CallExpression;
888
1241
  };
889
1242
  const isDeveloperFunction = (node) => {
890
- if (node.type === AST_NODE_TYPES9.FunctionDeclaration) {
1243
+ if (node.type === AST_NODE_TYPES13.FunctionDeclaration) {
891
1244
  return true;
892
1245
  }
893
- if (node.type === AST_NODE_TYPES9.FunctionExpression || node.type === AST_NODE_TYPES9.ArrowFunctionExpression) {
894
- if (isCallbackFunction(node)) {
1246
+ if (node.type === AST_NODE_TYPES13.FunctionExpression || node.type === AST_NODE_TYPES13.ArrowFunctionExpression) {
1247
+ if (isCallbackFunction2(node)) {
895
1248
  return false;
896
1249
  }
897
1250
  const { parent } = node;
898
- return parent?.type === AST_NODE_TYPES9.VariableDeclarator || parent?.type === AST_NODE_TYPES9.AssignmentExpression || parent?.type === AST_NODE_TYPES9.Property || parent?.type === AST_NODE_TYPES9.MethodDefinition;
1251
+ return parent?.type === AST_NODE_TYPES13.VariableDeclarator || parent?.type === AST_NODE_TYPES13.AssignmentExpression || parent?.type === AST_NODE_TYPES13.Property || parent?.type === AST_NODE_TYPES13.MethodDefinition;
899
1252
  }
900
1253
  return false;
901
1254
  };
@@ -907,7 +1260,7 @@ var preferDestructuringParams = createRule13({
907
1260
  if (!isDeveloperFunction(node)) {
908
1261
  return;
909
1262
  }
910
- if (node.type === AST_NODE_TYPES9.FunctionDeclaration && node.id) {
1263
+ if (node.type === AST_NODE_TYPES13.FunctionDeclaration && node.id) {
911
1264
  const functionName = node.id.name;
912
1265
  if (functionName.startsWith("_") || functionName.includes("$") || /^[A-Z][a-zA-Z]*$/.test(functionName)) {
913
1266
  return;
@@ -917,7 +1270,7 @@ var preferDestructuringParams = createRule13({
917
1270
  return;
918
1271
  }
919
1272
  const hasNonDestructuredParams = node.params.some(
920
- (param) => param.type !== AST_NODE_TYPES9.ObjectPattern && param.type !== AST_NODE_TYPES9.RestElement
1273
+ (param) => param.type !== AST_NODE_TYPES13.ObjectPattern && param.type !== AST_NODE_TYPES13.RestElement
921
1274
  );
922
1275
  if (hasNonDestructuredParams) {
923
1276
  context.report({
@@ -935,12 +1288,103 @@ var preferDestructuringParams = createRule13({
935
1288
  });
936
1289
  var prefer_destructuring_params_default = preferDestructuringParams;
937
1290
 
1291
+ // src/rules/prefer-function-declaration.ts
1292
+ import { ESLintUtils as ESLintUtils17, AST_NODE_TYPES as AST_NODE_TYPES14 } from "@typescript-eslint/utils";
1293
+ var createRule17 = ESLintUtils17.RuleCreator(
1294
+ (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1295
+ );
1296
+ var isTsFile = (filename) => filename.endsWith(".ts") && !filename.endsWith(".d.ts");
1297
+ var isCallbackContext = (node) => {
1298
+ const { parent } = node;
1299
+ if (!parent) {
1300
+ return false;
1301
+ }
1302
+ if (parent.type === AST_NODE_TYPES14.CallExpression && parent.arguments.includes(node)) {
1303
+ return true;
1304
+ }
1305
+ if (parent.type === AST_NODE_TYPES14.NewExpression && parent.arguments.includes(node)) {
1306
+ return true;
1307
+ }
1308
+ if (parent.type === AST_NODE_TYPES14.ReturnStatement) {
1309
+ return true;
1310
+ }
1311
+ if (parent.type === AST_NODE_TYPES14.Property) {
1312
+ return true;
1313
+ }
1314
+ if (parent.type === AST_NODE_TYPES14.ArrayExpression) {
1315
+ return true;
1316
+ }
1317
+ if (parent.type === AST_NODE_TYPES14.ConditionalExpression) {
1318
+ return true;
1319
+ }
1320
+ if (parent.type === AST_NODE_TYPES14.LogicalExpression) {
1321
+ return true;
1322
+ }
1323
+ if (parent.type === AST_NODE_TYPES14.AssignmentExpression && parent.left !== node) {
1324
+ return true;
1325
+ }
1326
+ return false;
1327
+ };
1328
+ var preferFunctionDeclaration = createRule17({
1329
+ name: "prefer-function-declaration",
1330
+ meta: {
1331
+ type: "suggestion",
1332
+ docs: {
1333
+ description: "Enforce function declarations over arrow functions assigned to variables in .ts files for better readability and hoisting"
1334
+ },
1335
+ messages: {
1336
+ preferDeclaration: "Use function declaration instead of arrow function. Replace 'const {{name}} = () => ...' with 'function {{name}}() ...'",
1337
+ preferDeclarationExpr: "Use function declaration instead of function expression. Replace 'const {{name}} = function() ...' with 'function {{name}}() ...'"
1338
+ },
1339
+ schema: []
1340
+ },
1341
+ defaultOptions: [],
1342
+ create(context) {
1343
+ const { filename } = context;
1344
+ if (!isTsFile(filename)) {
1345
+ return {};
1346
+ }
1347
+ return {
1348
+ VariableDeclarator(node) {
1349
+ if (node.id.type !== AST_NODE_TYPES14.Identifier) {
1350
+ return;
1351
+ }
1352
+ const { init } = node;
1353
+ if (!init) {
1354
+ return;
1355
+ }
1356
+ if (init.type === AST_NODE_TYPES14.ArrowFunctionExpression) {
1357
+ if (isCallbackContext(init)) {
1358
+ return;
1359
+ }
1360
+ context.report({
1361
+ node: init,
1362
+ messageId: "preferDeclaration",
1363
+ data: { name: node.id.name }
1364
+ });
1365
+ }
1366
+ if (init.type === AST_NODE_TYPES14.FunctionExpression) {
1367
+ if (isCallbackContext(init)) {
1368
+ return;
1369
+ }
1370
+ context.report({
1371
+ node: init,
1372
+ messageId: "preferDeclarationExpr",
1373
+ data: { name: node.id.name }
1374
+ });
1375
+ }
1376
+ }
1377
+ };
1378
+ }
1379
+ });
1380
+ var prefer_function_declaration_default = preferFunctionDeclaration;
1381
+
938
1382
  // src/rules/prefer-import-type.ts
939
- import { AST_NODE_TYPES as AST_NODE_TYPES10, ESLintUtils as ESLintUtils14 } from "@typescript-eslint/utils";
940
- var createRule14 = ESLintUtils14.RuleCreator(
1383
+ import { AST_NODE_TYPES as AST_NODE_TYPES15, ESLintUtils as ESLintUtils18 } from "@typescript-eslint/utils";
1384
+ var createRule18 = ESLintUtils18.RuleCreator(
941
1385
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
942
1386
  );
943
- var preferImportType = createRule14({
1387
+ var preferImportType = createRule18({
944
1388
  name: "prefer-import-type",
945
1389
  meta: {
946
1390
  type: "suggestion",
@@ -959,22 +1403,22 @@ var preferImportType = createRule14({
959
1403
  let current = node;
960
1404
  while (current) {
961
1405
  switch (current.type) {
962
- case AST_NODE_TYPES10.TSTypeReference:
963
- case AST_NODE_TYPES10.TSTypeAnnotation:
964
- case AST_NODE_TYPES10.TSTypeParameterInstantiation:
965
- case AST_NODE_TYPES10.TSInterfaceHeritage:
966
- case AST_NODE_TYPES10.TSClassImplements:
967
- case AST_NODE_TYPES10.TSTypeQuery:
968
- case AST_NODE_TYPES10.TSTypeAssertion:
969
- case AST_NODE_TYPES10.TSAsExpression:
970
- case AST_NODE_TYPES10.TSSatisfiesExpression:
971
- case AST_NODE_TYPES10.TSTypeAliasDeclaration:
972
- case AST_NODE_TYPES10.TSInterfaceDeclaration:
973
- case AST_NODE_TYPES10.TSTypeParameter:
974
- case AST_NODE_TYPES10.TSQualifiedName:
1406
+ case AST_NODE_TYPES15.TSTypeReference:
1407
+ case AST_NODE_TYPES15.TSTypeAnnotation:
1408
+ case AST_NODE_TYPES15.TSTypeParameterInstantiation:
1409
+ case AST_NODE_TYPES15.TSInterfaceHeritage:
1410
+ case AST_NODE_TYPES15.TSClassImplements:
1411
+ case AST_NODE_TYPES15.TSTypeQuery:
1412
+ case AST_NODE_TYPES15.TSTypeAssertion:
1413
+ case AST_NODE_TYPES15.TSAsExpression:
1414
+ case AST_NODE_TYPES15.TSSatisfiesExpression:
1415
+ case AST_NODE_TYPES15.TSTypeAliasDeclaration:
1416
+ case AST_NODE_TYPES15.TSInterfaceDeclaration:
1417
+ case AST_NODE_TYPES15.TSTypeParameter:
1418
+ case AST_NODE_TYPES15.TSQualifiedName:
975
1419
  return true;
976
- case AST_NODE_TYPES10.MemberExpression:
977
- case AST_NODE_TYPES10.Identifier:
1420
+ case AST_NODE_TYPES15.MemberExpression:
1421
+ case AST_NODE_TYPES15.Identifier:
978
1422
  current = current.parent;
979
1423
  break;
980
1424
  default:
@@ -1004,26 +1448,26 @@ var preferImportType = createRule14({
1004
1448
  return false;
1005
1449
  }
1006
1450
  switch (parent.type) {
1007
- case AST_NODE_TYPES10.CallExpression:
1008
- case AST_NODE_TYPES10.NewExpression:
1009
- case AST_NODE_TYPES10.JSXOpeningElement:
1010
- case AST_NODE_TYPES10.JSXClosingElement:
1011
- case AST_NODE_TYPES10.MemberExpression:
1012
- case AST_NODE_TYPES10.VariableDeclarator:
1013
- case AST_NODE_TYPES10.TaggedTemplateExpression:
1014
- case AST_NODE_TYPES10.SpreadElement:
1015
- case AST_NODE_TYPES10.ExportSpecifier:
1016
- case AST_NODE_TYPES10.ArrayExpression:
1017
- case AST_NODE_TYPES10.ObjectExpression:
1018
- case AST_NODE_TYPES10.BinaryExpression:
1019
- case AST_NODE_TYPES10.LogicalExpression:
1020
- case AST_NODE_TYPES10.UnaryExpression:
1021
- case AST_NODE_TYPES10.ReturnStatement:
1022
- case AST_NODE_TYPES10.ArrowFunctionExpression:
1023
- case AST_NODE_TYPES10.ConditionalExpression:
1024
- case AST_NODE_TYPES10.AwaitExpression:
1025
- case AST_NODE_TYPES10.YieldExpression:
1026
- case AST_NODE_TYPES10.Property:
1451
+ case AST_NODE_TYPES15.CallExpression:
1452
+ case AST_NODE_TYPES15.NewExpression:
1453
+ case AST_NODE_TYPES15.JSXOpeningElement:
1454
+ case AST_NODE_TYPES15.JSXClosingElement:
1455
+ case AST_NODE_TYPES15.MemberExpression:
1456
+ case AST_NODE_TYPES15.VariableDeclarator:
1457
+ case AST_NODE_TYPES15.TaggedTemplateExpression:
1458
+ case AST_NODE_TYPES15.SpreadElement:
1459
+ case AST_NODE_TYPES15.ExportSpecifier:
1460
+ case AST_NODE_TYPES15.ArrayExpression:
1461
+ case AST_NODE_TYPES15.ObjectExpression:
1462
+ case AST_NODE_TYPES15.BinaryExpression:
1463
+ case AST_NODE_TYPES15.LogicalExpression:
1464
+ case AST_NODE_TYPES15.UnaryExpression:
1465
+ case AST_NODE_TYPES15.ReturnStatement:
1466
+ case AST_NODE_TYPES15.ArrowFunctionExpression:
1467
+ case AST_NODE_TYPES15.ConditionalExpression:
1468
+ case AST_NODE_TYPES15.AwaitExpression:
1469
+ case AST_NODE_TYPES15.YieldExpression:
1470
+ case AST_NODE_TYPES15.Property:
1027
1471
  return true;
1028
1472
  default:
1029
1473
  return false;
@@ -1047,13 +1491,13 @@ var preferImportType = createRule14({
1047
1491
  }
1048
1492
  const scope = context.sourceCode.getScope(node);
1049
1493
  const isTypeOnlyImport = node.specifiers.every((specifier) => {
1050
- if (specifier.type === AST_NODE_TYPES10.ImportDefaultSpecifier) {
1494
+ if (specifier.type === AST_NODE_TYPES15.ImportDefaultSpecifier) {
1051
1495
  return false;
1052
1496
  }
1053
- if (specifier.type === AST_NODE_TYPES10.ImportNamespaceSpecifier) {
1497
+ if (specifier.type === AST_NODE_TYPES15.ImportNamespaceSpecifier) {
1054
1498
  return false;
1055
1499
  }
1056
- if (specifier.type === AST_NODE_TYPES10.ImportSpecifier) {
1500
+ if (specifier.type === AST_NODE_TYPES15.ImportSpecifier) {
1057
1501
  const localName = specifier.local.name;
1058
1502
  return !isUsedAsValue(localName, scope);
1059
1503
  }
@@ -1079,11 +1523,11 @@ var preferImportType = createRule14({
1079
1523
  var prefer_import_type_default = preferImportType;
1080
1524
 
1081
1525
  // src/rules/prefer-interface-over-inline-types.ts
1082
- import { AST_NODE_TYPES as AST_NODE_TYPES11, ESLintUtils as ESLintUtils15 } from "@typescript-eslint/utils";
1083
- var createRule15 = ESLintUtils15.RuleCreator(
1526
+ import { AST_NODE_TYPES as AST_NODE_TYPES16, ESLintUtils as ESLintUtils19 } from "@typescript-eslint/utils";
1527
+ var createRule19 = ESLintUtils19.RuleCreator(
1084
1528
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1085
1529
  );
1086
- var preferInterfaceOverInlineTypes = createRule15({
1530
+ var preferInterfaceOverInlineTypes = createRule19({
1087
1531
  name: "prefer-interface-over-inline-types",
1088
1532
  meta: {
1089
1533
  type: "suggestion",
@@ -1099,67 +1543,67 @@ var preferInterfaceOverInlineTypes = createRule15({
1099
1543
  defaultOptions: [],
1100
1544
  create(context) {
1101
1545
  function hasJSXInConditional(node) {
1102
- return node.consequent.type === AST_NODE_TYPES11.JSXElement || node.consequent.type === AST_NODE_TYPES11.JSXFragment || node.alternate.type === AST_NODE_TYPES11.JSXElement || node.alternate.type === AST_NODE_TYPES11.JSXFragment;
1546
+ return node.consequent.type === AST_NODE_TYPES16.JSXElement || node.consequent.type === AST_NODE_TYPES16.JSXFragment || node.alternate.type === AST_NODE_TYPES16.JSXElement || node.alternate.type === AST_NODE_TYPES16.JSXFragment;
1103
1547
  }
1104
1548
  function hasJSXInLogical(node) {
1105
- return node.right.type === AST_NODE_TYPES11.JSXElement || node.right.type === AST_NODE_TYPES11.JSXFragment;
1549
+ return node.right.type === AST_NODE_TYPES16.JSXElement || node.right.type === AST_NODE_TYPES16.JSXFragment;
1106
1550
  }
1107
1551
  function hasJSXReturn(block) {
1108
1552
  return block.body.some((stmt) => {
1109
- if (stmt.type === AST_NODE_TYPES11.ReturnStatement && stmt.argument) {
1110
- return stmt.argument.type === AST_NODE_TYPES11.JSXElement || stmt.argument.type === AST_NODE_TYPES11.JSXFragment || stmt.argument.type === AST_NODE_TYPES11.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES11.LogicalExpression && hasJSXInLogical(stmt.argument);
1553
+ if (stmt.type === AST_NODE_TYPES16.ReturnStatement && stmt.argument) {
1554
+ return stmt.argument.type === AST_NODE_TYPES16.JSXElement || stmt.argument.type === AST_NODE_TYPES16.JSXFragment || stmt.argument.type === AST_NODE_TYPES16.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES16.LogicalExpression && hasJSXInLogical(stmt.argument);
1111
1555
  }
1112
1556
  return false;
1113
1557
  });
1114
1558
  }
1115
- function isReactComponent(node) {
1116
- if (node.type === AST_NODE_TYPES11.ArrowFunctionExpression) {
1117
- if (node.body.type === AST_NODE_TYPES11.JSXElement || node.body.type === AST_NODE_TYPES11.JSXFragment) {
1559
+ function isReactComponent2(node) {
1560
+ if (node.type === AST_NODE_TYPES16.ArrowFunctionExpression) {
1561
+ if (node.body.type === AST_NODE_TYPES16.JSXElement || node.body.type === AST_NODE_TYPES16.JSXFragment) {
1118
1562
  return true;
1119
1563
  }
1120
- if (node.body.type === AST_NODE_TYPES11.BlockStatement) {
1564
+ if (node.body.type === AST_NODE_TYPES16.BlockStatement) {
1121
1565
  return hasJSXReturn(node.body);
1122
1566
  }
1123
- } else if (node.type === AST_NODE_TYPES11.FunctionExpression || node.type === AST_NODE_TYPES11.FunctionDeclaration) {
1124
- if (node.body && node.body.type === AST_NODE_TYPES11.BlockStatement) {
1567
+ } else if (node.type === AST_NODE_TYPES16.FunctionExpression || node.type === AST_NODE_TYPES16.FunctionDeclaration) {
1568
+ if (node.body && node.body.type === AST_NODE_TYPES16.BlockStatement) {
1125
1569
  return hasJSXReturn(node.body);
1126
1570
  }
1127
1571
  }
1128
1572
  return false;
1129
1573
  }
1130
1574
  function isInlineTypeAnnotation(node) {
1131
- if (node.type === AST_NODE_TYPES11.TSTypeLiteral) {
1575
+ if (node.type === AST_NODE_TYPES16.TSTypeLiteral) {
1132
1576
  return true;
1133
1577
  }
1134
- if (node.type === AST_NODE_TYPES11.TSTypeReference && node.typeArguments) {
1135
- return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES11.TSTypeLiteral);
1578
+ if (node.type === AST_NODE_TYPES16.TSTypeReference && node.typeArguments) {
1579
+ return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES16.TSTypeLiteral);
1136
1580
  }
1137
- if (node.type === AST_NODE_TYPES11.TSUnionType) {
1581
+ if (node.type === AST_NODE_TYPES16.TSUnionType) {
1138
1582
  return node.types.some((type) => isInlineTypeAnnotation(type));
1139
1583
  }
1140
1584
  return false;
1141
1585
  }
1142
1586
  function hasInlineObjectType(node) {
1143
- if (node.type === AST_NODE_TYPES11.TSTypeLiteral) {
1587
+ if (node.type === AST_NODE_TYPES16.TSTypeLiteral) {
1144
1588
  return true;
1145
1589
  }
1146
- if (node.type === AST_NODE_TYPES11.TSTypeReference && node.typeArguments) {
1147
- return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES11.TSTypeLiteral);
1590
+ if (node.type === AST_NODE_TYPES16.TSTypeReference && node.typeArguments) {
1591
+ return node.typeArguments.params.some((param) => param.type === AST_NODE_TYPES16.TSTypeLiteral);
1148
1592
  }
1149
- if (node.type === AST_NODE_TYPES11.TSUnionType) {
1593
+ if (node.type === AST_NODE_TYPES16.TSUnionType) {
1150
1594
  return node.types.some((type) => hasInlineObjectType(type));
1151
1595
  }
1152
1596
  return false;
1153
1597
  }
1154
1598
  function checkFunction(node) {
1155
- if (!isReactComponent(node)) {
1599
+ if (!isReactComponent2(node)) {
1156
1600
  return;
1157
1601
  }
1158
1602
  if (node.params.length !== 1) {
1159
1603
  return;
1160
1604
  }
1161
1605
  const param = node.params[0];
1162
- if (param.type === AST_NODE_TYPES11.Identifier && param.typeAnnotation) {
1606
+ if (param.type === AST_NODE_TYPES16.Identifier && param.typeAnnotation) {
1163
1607
  const { typeAnnotation } = param.typeAnnotation;
1164
1608
  if (isInlineTypeAnnotation(typeAnnotation) && hasInlineObjectType(typeAnnotation)) {
1165
1609
  context.report({
@@ -1179,11 +1623,11 @@ var preferInterfaceOverInlineTypes = createRule15({
1179
1623
  var prefer_interface_over_inline_types_default = preferInterfaceOverInlineTypes;
1180
1624
 
1181
1625
  // src/rules/prefer-jsx-template-literals.ts
1182
- import { AST_NODE_TYPES as AST_NODE_TYPES12, ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
1183
- var createRule16 = ESLintUtils16.RuleCreator(
1626
+ import { AST_NODE_TYPES as AST_NODE_TYPES17, ESLintUtils as ESLintUtils20 } from "@typescript-eslint/utils";
1627
+ var createRule20 = ESLintUtils20.RuleCreator(
1184
1628
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1185
1629
  );
1186
- var preferJSXTemplateLiterals = createRule16({
1630
+ var preferJSXTemplateLiterals = createRule20({
1187
1631
  name: "prefer-jsx-template-literals",
1188
1632
  meta: {
1189
1633
  type: "suggestion",
@@ -1252,9 +1696,9 @@ var preferJSXTemplateLiterals = createRule16({
1252
1696
  if (!child || !nextChild) {
1253
1697
  return;
1254
1698
  }
1255
- if (child.type === AST_NODE_TYPES12.JSXText && nextChild.type === AST_NODE_TYPES12.JSXExpressionContainer) {
1699
+ if (child.type === AST_NODE_TYPES17.JSXText && nextChild.type === AST_NODE_TYPES17.JSXExpressionContainer) {
1256
1700
  handleTextBeforeExpression(child, nextChild);
1257
- } else if (child.type === AST_NODE_TYPES12.JSXExpressionContainer && nextChild.type === AST_NODE_TYPES12.JSXText) {
1701
+ } else if (child.type === AST_NODE_TYPES17.JSXExpressionContainer && nextChild.type === AST_NODE_TYPES17.JSXText) {
1258
1702
  handleExpressionBeforeText(child, nextChild);
1259
1703
  }
1260
1704
  }
@@ -1267,11 +1711,11 @@ var preferJSXTemplateLiterals = createRule16({
1267
1711
  var prefer_jsx_template_literals_default = preferJSXTemplateLiterals;
1268
1712
 
1269
1713
  // src/rules/prefer-named-param-types.ts
1270
- import { AST_NODE_TYPES as AST_NODE_TYPES13, ESLintUtils as ESLintUtils17 } from "@typescript-eslint/utils";
1271
- var createRule17 = ESLintUtils17.RuleCreator(
1714
+ import { AST_NODE_TYPES as AST_NODE_TYPES18, ESLintUtils as ESLintUtils21 } from "@typescript-eslint/utils";
1715
+ var createRule21 = ESLintUtils21.RuleCreator(
1272
1716
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1273
1717
  );
1274
- var preferNamedParamTypes = createRule17({
1718
+ var preferNamedParamTypes = createRule21({
1275
1719
  name: "prefer-named-param-types",
1276
1720
  meta: {
1277
1721
  type: "suggestion",
@@ -1286,16 +1730,16 @@ var preferNamedParamTypes = createRule17({
1286
1730
  defaultOptions: [],
1287
1731
  create(context) {
1288
1732
  function hasInlineObjectType(param) {
1289
- if (param.type === AST_NODE_TYPES13.AssignmentPattern) {
1733
+ if (param.type === AST_NODE_TYPES18.AssignmentPattern) {
1290
1734
  return hasInlineObjectType(param.left);
1291
1735
  }
1292
- if (param.type === AST_NODE_TYPES13.ObjectPattern) {
1293
- if (param.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES13.TSTypeLiteral) {
1736
+ if (param.type === AST_NODE_TYPES18.ObjectPattern) {
1737
+ if (param.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES18.TSTypeLiteral) {
1294
1738
  return true;
1295
1739
  }
1296
1740
  }
1297
- if (param.type === AST_NODE_TYPES13.Identifier) {
1298
- if (param.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES13.TSTypeLiteral) {
1741
+ if (param.type === AST_NODE_TYPES18.Identifier) {
1742
+ if (param.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES18.TSTypeLiteral) {
1299
1743
  return true;
1300
1744
  }
1301
1745
  }
@@ -1329,11 +1773,11 @@ var preferNamedParamTypes = createRule17({
1329
1773
  var prefer_named_param_types_default = preferNamedParamTypes;
1330
1774
 
1331
1775
  // src/rules/prefer-react-import-types.ts
1332
- import { AST_NODE_TYPES as AST_NODE_TYPES14, ESLintUtils as ESLintUtils18 } from "@typescript-eslint/utils";
1333
- var createRule18 = ESLintUtils18.RuleCreator(
1776
+ import { AST_NODE_TYPES as AST_NODE_TYPES19, ESLintUtils as ESLintUtils22 } from "@typescript-eslint/utils";
1777
+ var createRule22 = ESLintUtils22.RuleCreator(
1334
1778
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1335
1779
  );
1336
- var preferReactImportTypes = createRule18({
1780
+ var preferReactImportTypes = createRule22({
1337
1781
  name: "prefer-react-import-types",
1338
1782
  meta: {
1339
1783
  type: "suggestion",
@@ -1409,7 +1853,7 @@ var preferReactImportTypes = createRule18({
1409
1853
  ]);
1410
1854
  const allReactExports = /* @__PURE__ */ new Set([...reactTypes, ...reactRuntimeExports]);
1411
1855
  function checkMemberExpression(node) {
1412
- if (node.object.type === AST_NODE_TYPES14.Identifier && node.object.name === "React" && node.property.type === AST_NODE_TYPES14.Identifier && allReactExports.has(node.property.name)) {
1856
+ if (node.object.type === AST_NODE_TYPES19.Identifier && node.object.name === "React" && node.property.type === AST_NODE_TYPES19.Identifier && allReactExports.has(node.property.name)) {
1413
1857
  const typeName = node.property.name;
1414
1858
  const isType = reactTypes.has(typeName);
1415
1859
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -1426,7 +1870,7 @@ var preferReactImportTypes = createRule18({
1426
1870
  return {
1427
1871
  MemberExpression: checkMemberExpression,
1428
1872
  "TSTypeReference > TSQualifiedName": (node) => {
1429
- if (node.left.type === AST_NODE_TYPES14.Identifier && node.left.name === "React" && node.right.type === AST_NODE_TYPES14.Identifier && allReactExports.has(node.right.name)) {
1873
+ if (node.left.type === AST_NODE_TYPES19.Identifier && node.left.name === "React" && node.right.type === AST_NODE_TYPES19.Identifier && allReactExports.has(node.right.name)) {
1430
1874
  const typeName = node.right.name;
1431
1875
  const isType = reactTypes.has(typeName);
1432
1876
  const importStatement = isType ? `import type { ${typeName} } from "react"` : `import { ${typeName} } from "react"`;
@@ -1446,11 +1890,11 @@ var preferReactImportTypes = createRule18({
1446
1890
  var prefer_react_import_types_default = preferReactImportTypes;
1447
1891
 
1448
1892
  // src/rules/react-props-destructure.ts
1449
- import { AST_NODE_TYPES as AST_NODE_TYPES15, ESLintUtils as ESLintUtils19 } from "@typescript-eslint/utils";
1450
- var createRule19 = ESLintUtils19.RuleCreator(
1893
+ import { AST_NODE_TYPES as AST_NODE_TYPES20, ESLintUtils as ESLintUtils23 } from "@typescript-eslint/utils";
1894
+ var createRule23 = ESLintUtils23.RuleCreator(
1451
1895
  (name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`
1452
1896
  );
1453
- var reactPropsDestructure = createRule19({
1897
+ var reactPropsDestructure = createRule23({
1454
1898
  name: "react-props-destructure",
1455
1899
  meta: {
1456
1900
  type: "suggestion",
@@ -1466,45 +1910,45 @@ var reactPropsDestructure = createRule19({
1466
1910
  defaultOptions: [],
1467
1911
  create(context) {
1468
1912
  function hasJSXInConditional(node) {
1469
- return node.consequent.type === AST_NODE_TYPES15.JSXElement || node.consequent.type === AST_NODE_TYPES15.JSXFragment || node.alternate.type === AST_NODE_TYPES15.JSXElement || node.alternate.type === AST_NODE_TYPES15.JSXFragment;
1913
+ return node.consequent.type === AST_NODE_TYPES20.JSXElement || node.consequent.type === AST_NODE_TYPES20.JSXFragment || node.alternate.type === AST_NODE_TYPES20.JSXElement || node.alternate.type === AST_NODE_TYPES20.JSXFragment;
1470
1914
  }
1471
1915
  function hasJSXInLogical(node) {
1472
- return node.right.type === AST_NODE_TYPES15.JSXElement || node.right.type === AST_NODE_TYPES15.JSXFragment;
1916
+ return node.right.type === AST_NODE_TYPES20.JSXElement || node.right.type === AST_NODE_TYPES20.JSXFragment;
1473
1917
  }
1474
1918
  function hasJSXReturn(block) {
1475
1919
  return block.body.some((stmt) => {
1476
- if (stmt.type === AST_NODE_TYPES15.ReturnStatement && stmt.argument) {
1477
- return stmt.argument.type === AST_NODE_TYPES15.JSXElement || stmt.argument.type === AST_NODE_TYPES15.JSXFragment || stmt.argument.type === AST_NODE_TYPES15.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES15.LogicalExpression && hasJSXInLogical(stmt.argument);
1920
+ if (stmt.type === AST_NODE_TYPES20.ReturnStatement && stmt.argument) {
1921
+ return stmt.argument.type === AST_NODE_TYPES20.JSXElement || stmt.argument.type === AST_NODE_TYPES20.JSXFragment || stmt.argument.type === AST_NODE_TYPES20.ConditionalExpression && hasJSXInConditional(stmt.argument) || stmt.argument.type === AST_NODE_TYPES20.LogicalExpression && hasJSXInLogical(stmt.argument);
1478
1922
  }
1479
1923
  return false;
1480
1924
  });
1481
1925
  }
1482
- function isReactComponent(node) {
1483
- if (node.type === AST_NODE_TYPES15.ArrowFunctionExpression) {
1484
- if (node.body.type === AST_NODE_TYPES15.JSXElement || node.body.type === AST_NODE_TYPES15.JSXFragment) {
1926
+ function isReactComponent2(node) {
1927
+ if (node.type === AST_NODE_TYPES20.ArrowFunctionExpression) {
1928
+ if (node.body.type === AST_NODE_TYPES20.JSXElement || node.body.type === AST_NODE_TYPES20.JSXFragment) {
1485
1929
  return true;
1486
1930
  }
1487
- if (node.body.type === AST_NODE_TYPES15.BlockStatement) {
1931
+ if (node.body.type === AST_NODE_TYPES20.BlockStatement) {
1488
1932
  return hasJSXReturn(node.body);
1489
1933
  }
1490
- } else if (node.type === AST_NODE_TYPES15.FunctionExpression || node.type === AST_NODE_TYPES15.FunctionDeclaration) {
1491
- if (node.body && node.body.type === AST_NODE_TYPES15.BlockStatement) {
1934
+ } else if (node.type === AST_NODE_TYPES20.FunctionExpression || node.type === AST_NODE_TYPES20.FunctionDeclaration) {
1935
+ if (node.body && node.body.type === AST_NODE_TYPES20.BlockStatement) {
1492
1936
  return hasJSXReturn(node.body);
1493
1937
  }
1494
1938
  }
1495
1939
  return false;
1496
1940
  }
1497
1941
  function checkFunction(node) {
1498
- if (!isReactComponent(node)) {
1942
+ if (!isReactComponent2(node)) {
1499
1943
  return;
1500
1944
  }
1501
1945
  if (node.params.length !== 1) {
1502
1946
  return;
1503
1947
  }
1504
1948
  const param = node.params[0];
1505
- if (param.type === AST_NODE_TYPES15.ObjectPattern) {
1506
- const properties = param.properties.filter((prop) => prop.type === AST_NODE_TYPES15.Property).map((prop) => {
1507
- if (prop.key.type === AST_NODE_TYPES15.Identifier) {
1949
+ if (param.type === AST_NODE_TYPES20.ObjectPattern) {
1950
+ const properties = param.properties.filter((prop) => prop.type === AST_NODE_TYPES20.Property).map((prop) => {
1951
+ if (prop.key.type === AST_NODE_TYPES20.Identifier) {
1508
1952
  return prop.key.name;
1509
1953
  }
1510
1954
  return null;
@@ -1536,6 +1980,7 @@ var meta = {
1536
1980
  version: package_default.version
1537
1981
  };
1538
1982
  var rules = {
1983
+ "boolean-naming-prefix": boolean_naming_prefix_default,
1539
1984
  "enforce-readonly-component-props": enforce_readonly_component_props_default,
1540
1985
  "enforce-sorted-destructuring": enforce_sorted_destructuring_default,
1541
1986
  "file-kebab-case": file_kebab_case_default,
@@ -1544,11 +1989,14 @@ var rules = {
1544
1989
  "jsx-no-variable-in-callback": jsx_no_variable_in_callback_default,
1545
1990
  "md-filename-case-restriction": md_filename_case_restriction_default,
1546
1991
  "no-complex-inline-return": no_complex_inline_return_default,
1992
+ "no-direct-date": no_direct_date_default,
1547
1993
  "no-emoji": no_emoji_default,
1548
1994
  "no-env-fallback": no_env_fallback_default,
1549
- "no-explicit-return-type": no_explicit_return_type_default,
1995
+ "require-explicit-return-type": require_explicit_return_type_default,
1550
1996
  "no-logic-in-params": no_logic_in_params_default,
1997
+ "no-single-char-variables": no_single_char_variables_default,
1551
1998
  "prefer-destructuring-params": prefer_destructuring_params_default,
1999
+ "prefer-function-declaration": prefer_function_declaration_default,
1552
2000
  "prefer-import-type": prefer_import_type_default,
1553
2001
  "prefer-interface-over-inline-types": prefer_interface_over_inline_types_default,
1554
2002
  "prefer-jsx-template-literals": prefer_jsx_template_literals_default,
@@ -1561,32 +2009,40 @@ var plugin = {
1561
2009
  rules
1562
2010
  };
1563
2011
  var baseRules = {
2012
+ "nextfriday/boolean-naming-prefix": "warn",
1564
2013
  "nextfriday/no-emoji": "warn",
1565
2014
  "nextfriday/enforce-sorted-destructuring": "warn",
1566
2015
  "nextfriday/file-kebab-case": "warn",
1567
2016
  "nextfriday/md-filename-case-restriction": "warn",
1568
2017
  "nextfriday/prefer-destructuring-params": "warn",
1569
- "nextfriday/no-explicit-return-type": "warn",
2018
+ "nextfriday/prefer-function-declaration": "warn",
2019
+ "nextfriday/require-explicit-return-type": "warn",
1570
2020
  "nextfriday/prefer-import-type": "warn",
1571
2021
  "nextfriday/prefer-named-param-types": "warn",
1572
2022
  "nextfriday/prefer-react-import-types": "warn",
1573
2023
  "nextfriday/no-complex-inline-return": "warn",
2024
+ "nextfriday/no-direct-date": "warn",
1574
2025
  "nextfriday/no-logic-in-params": "warn",
1575
- "nextfriday/no-env-fallback": "warn"
2026
+ "nextfriday/no-env-fallback": "warn",
2027
+ "nextfriday/no-single-char-variables": "warn"
1576
2028
  };
1577
2029
  var baseRecommendedRules = {
2030
+ "nextfriday/boolean-naming-prefix": "error",
1578
2031
  "nextfriday/no-emoji": "error",
1579
2032
  "nextfriday/enforce-sorted-destructuring": "error",
1580
2033
  "nextfriday/file-kebab-case": "error",
1581
2034
  "nextfriday/md-filename-case-restriction": "error",
1582
2035
  "nextfriday/prefer-destructuring-params": "error",
1583
- "nextfriday/no-explicit-return-type": "error",
2036
+ "nextfriday/prefer-function-declaration": "error",
2037
+ "nextfriday/require-explicit-return-type": "error",
1584
2038
  "nextfriday/prefer-import-type": "error",
1585
2039
  "nextfriday/prefer-named-param-types": "error",
1586
2040
  "nextfriday/prefer-react-import-types": "error",
1587
2041
  "nextfriday/no-complex-inline-return": "error",
2042
+ "nextfriday/no-direct-date": "error",
1588
2043
  "nextfriday/no-logic-in-params": "error",
1589
- "nextfriday/no-env-fallback": "error"
2044
+ "nextfriday/no-env-fallback": "error",
2045
+ "nextfriday/no-single-char-variables": "error"
1590
2046
  };
1591
2047
  var jsxRules = {
1592
2048
  "nextfriday/jsx-pascal-case": "warn",