eslint-plugin-nextfriday 3.1.0 → 3.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 3.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#118](https://github.com/next-friday/eslint-plugin-nextfriday/pull/118) [`143eee9`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/143eee9fd0c6aed00e10677a6cad448dbdc9136e) Thanks [@joetakara](https://github.com/joetakara)! - Add `index-export-only` rule. Restricts `index.{js,jsx,ts,tsx}` files to imports, re-exports, and type/interface declarations only — flagging local function/class/variable declarations, inline `export const`/`export function`/`export class`, top-level expressions, and control flow. Type aliases, interfaces, and `export type` are allowed since they have no runtime cost. Included in `base`, `react`, and `nextjs` presets.
8
+
9
+ - [#118](https://github.com/next-friday/eslint-plugin-nextfriday/pull/118) [`143eee9`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/143eee9fd0c6aed00e10677a6cad448dbdc9136e) Thanks [@joetakara](https://github.com/joetakara)! - Add `no-inline-type-import` rule. Disallows inline `type` markers on import specifiers (`import { type Foo }` and `import { value, type Foo }`); auto-fix hoists single inline-type imports to `import type { ... }` and splits mixed value/type imports into two separate statements while preserving aliases, default specifiers, and quote style. Also strips redundant inline markers from existing `import type { ... }` statements. Included in `base`, `react`, and `nextjs` presets.
10
+
3
11
  ## 3.1.0
4
12
 
5
13
  ### Minor Changes
package/README.md CHANGED
@@ -434,6 +434,7 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
434
434
  | [enforce-sorted-destructuring](docs/rules/ENFORCE_SORTED_DESTRUCTURING.md) | Enforce alphabetical sorting of destructured properties | ✅ |
435
435
  | [no-env-fallback](docs/rules/NO_ENV_FALLBACK.md) | Disallow fallback values for environment variables | ❌ |
436
436
  | [no-inline-default-export](docs/rules/NO_INLINE_DEFAULT_EXPORT.md) | Disallow inline default exports - declare first, then export | ❌ |
437
+ | [index-export-only](docs/rules/INDEX_EXPORT_ONLY.md) | Restrict index files to imports, re-exports, and type declarations | ❌ |
437
438
  | [no-direct-date](docs/rules/NO_DIRECT_DATE.md) | Disallow direct usage of Date constructor and methods | ❌ |
438
439
  | [newline-after-multiline-block](docs/rules/NEWLINE_AFTER_MULTILINE_BLOCK.md) | Require a blank line after multi-line statements | ✅ |
439
440
  | [newline-before-return](docs/rules/NEWLINE_BEFORE_RETURN.md) | Require a blank line before return statements | ✅ |
@@ -449,6 +450,7 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
449
450
  | Rule | Description | Fixable |
450
451
  | -------------------------------------------------------------------- | --------------------------------------------------------- | ------- |
451
452
  | [no-relative-imports](docs/rules/NO_RELATIVE_IMPORTS.md) | Disallow relative imports with ../ - use absolute imports | ❌ |
453
+ | [no-inline-type-import](docs/rules/NO_INLINE_TYPE_IMPORT.md) | Disallow inline 'type' markers - hoist or split imports | ✅ |
452
454
  | [prefer-import-type](docs/rules/PREFER_IMPORT_TYPE.md) | Enforce using 'import type' for type-only imports | ✅ |
453
455
  | [prefer-react-import-types](docs/rules/PREFER_REACT_IMPORT_TYPES.md) | Enforce direct imports from 'react' instead of React.X | ✅ |
454
456
  | [sort-exports](docs/rules/SORT_EXPORTS.md) | Enforce a consistent ordering of export groups | ✅ |
@@ -498,16 +500,16 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
498
500
 
499
501
  | Preset | Severity | Base Rules | JSX Rules | Next.js Rules | Total Rules |
500
502
  | -------------------- | -------- | ---------- | --------- | ------------- | ----------- |
501
- | `base` | warn | 40 | 0 | 0 | 40 |
502
- | `base/recommended` | error | 40 | 0 | 0 | 40 |
503
- | `react` | warn | 40 | 16 | 0 | 56 |
504
- | `react/recommended` | error | 40 | 16 | 0 | 56 |
505
- | `nextjs` | warn | 40 | 16 | 1 | 57 |
506
- | `nextjs/recommended` | error | 40 | 16 | 1 | 57 |
503
+ | `base` | warn | 42 | 0 | 0 | 42 |
504
+ | `base/recommended` | error | 42 | 0 | 0 | 42 |
505
+ | `react` | warn | 42 | 16 | 0 | 58 |
506
+ | `react/recommended` | error | 42 | 16 | 0 | 58 |
507
+ | `nextjs` | warn | 42 | 16 | 1 | 59 |
508
+ | `nextjs/recommended` | error | 42 | 16 | 1 | 59 |
507
509
 
508
510
  The `nextjs` and `nextjs/recommended` presets ship as an array of two flat-config objects: the rule set above, plus a routing override that disables `nextfriday/file-kebab-case` and `nextfriday/jsx-pascal-case` for files matching `app/**/*.{js,jsx,ts,tsx}`, `src/app/**/*.{js,jsx,ts,tsx}`, `pages/**/*.{js,jsx,ts,tsx}`, and `src/pages/**/*.{js,jsx,ts,tsx}`. Next.js owns the filenames in those directories (`page.tsx`, `layout.tsx`, `route.ts`, `middleware.ts`, etc.), so the plugin steps out of the way. ESLint 9+ flattens nested config arrays automatically, so spreading the preset works as expected.
509
511
 
510
- ### Base Configuration Rules (40 rules)
512
+ ### Base Configuration Rules (42 rules)
511
513
 
512
514
  Included in `base`, `base/recommended`, and all other presets:
513
515
 
@@ -521,6 +523,7 @@ Included in `base`, `base/recommended`, and all other presets:
521
523
  - `nextfriday/enforce-sorted-destructuring`
522
524
  - `nextfriday/enforce-type-declaration-order`
523
525
  - `nextfriday/file-kebab-case`
526
+ - `nextfriday/index-export-only`
524
527
  - `nextfriday/newline-after-multiline-block`
525
528
  - `nextfriday/newline-before-return`
526
529
  - `nextfriday/no-complex-inline-return`
@@ -530,6 +533,7 @@ Included in `base`, `base/recommended`, and all other presets:
530
533
  - `nextfriday/no-inline-default-export`
531
534
  - `nextfriday/no-inline-nested-object`
532
535
  - `nextfriday/no-inline-return-properties`
536
+ - `nextfriday/no-inline-type-import`
533
537
  - `nextfriday/no-lazy-identifiers`
534
538
  - `nextfriday/no-logic-in-params`
535
539
  - `nextfriday/no-misleading-constant-case`
@@ -0,0 +1,88 @@
1
+ # index-export-only
2
+
3
+ Restrict `index` files to imports, re-exports, and type declarations only.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces that `index.{js,jsx,ts,tsx}` files act purely as barrel files. Any runtime declaration — functions, classes, variables, top-level expressions, or inline `export const`/`export function`/`export class` — must live in its own module and be re-exported from the index.
8
+
9
+ The rule applies only when the basename of the file is `index`. Files like `index.test.ts`, `index.spec.ts`, or `index.d.ts` are not affected.
10
+
11
+ ### Why?
12
+
13
+ Index files are entry points. Mixing implementation into them obscures where behavior lives, breaks file-based code navigation, and makes the import surface harder to refactor. A barrel file should describe the public API of a directory — nothing more.
14
+
15
+ ## Examples
16
+
17
+ ### Incorrect
18
+
19
+ ```ts
20
+ import { clsx, type ClassValue } from "clsx";
21
+ import { twMerge } from "tailwind-merge";
22
+
23
+ function cn(...inputs: ClassValue[]): string {
24
+ return twMerge(clsx(inputs));
25
+ }
26
+
27
+ export { cn };
28
+ ```
29
+
30
+ ```ts
31
+ export const VERSION = "1.0.0";
32
+
33
+ export function helper() {
34
+ return 1;
35
+ }
36
+
37
+ export class Service {}
38
+ ```
39
+
40
+ ```ts
41
+ console.log("loaded");
42
+ ```
43
+
44
+ ### Correct
45
+
46
+ ```ts
47
+ export { cn } from "./cn";
48
+ export * from "./types";
49
+ export type { Props } from "./props";
50
+ export { default as Button } from "./button";
51
+ ```
52
+
53
+ ```ts
54
+ import button from "./button";
55
+
56
+ export default button;
57
+ ```
58
+
59
+ ```ts
60
+ export type Foo = string;
61
+ export interface Bar {
62
+ id: string;
63
+ }
64
+ ```
65
+
66
+ ## What This Rule Allows
67
+
68
+ - `import` statements (including side-effect imports like `import "./styles.css"`)
69
+ - Specifier-only `export` and `export ... from` re-exports
70
+ - `export *` and `export * as ns` re-exports
71
+ - `export default identifier` where the identifier comes from an import
72
+ - Top-level `type` aliases and `interface` declarations (they have no runtime cost)
73
+ - `export type` and `export interface` declarations
74
+
75
+ ## What This Rule Disallows
76
+
77
+ - `function`, `class`, and `const`/`let`/`var` declarations at the top level
78
+ - Inline `export function`, `export class`, `export const`, `export let`, `export var`
79
+ - `export default` of a function/class/literal/object expression
80
+ - Top-level expression statements and control flow (`console.log(...)`, `if`, `for`, etc.)
81
+
82
+ ## When Not To Use It
83
+
84
+ If your project intentionally mixes implementation and re-exports in index files — for example, a single-file utility library where `index.ts` is the only source file — disable this rule.
85
+
86
+ ## Related Rules
87
+
88
+ - [no-inline-default-export](./NO_INLINE_DEFAULT_EXPORT.md) - Disallow inline default and named exports across all files
@@ -0,0 +1,86 @@
1
+ # no-inline-type-import
2
+
3
+ Disallow inline `type` markers on import specifiers. Use `import type` or split into a separate type-only import statement.
4
+
5
+ > This rule is auto-fixable using `--fix`.
6
+
7
+ ## Rule Details
8
+
9
+ This rule forbids the inline-`type` form `import { type Foo }` and the mixed form `import { value, type Foo }`. Type-only imports must be expressed at the statement level with `import type { ... }`. When value and type imports come from the same module, the rule splits them into two separate statements.
10
+
11
+ ### Why?
12
+
13
+ Statement-level `import type` makes the runtime cost of every import unambiguous at a glance, simplifies tooling that distinguishes erased imports from real ones (bundlers, type-only emit, transpilers), and removes the need for readers to scan each specifier for an inline keyword.
14
+
15
+ ## Examples
16
+
17
+ ### Incorrect
18
+
19
+ ```ts
20
+ import { type foo } from "bar";
21
+
22
+ import { baz, type moo } from "mee";
23
+
24
+ import Default, { value, type Foo } from "src";
25
+ ```
26
+
27
+ ### Correct
28
+
29
+ ```ts
30
+ import type { foo } from "bar";
31
+
32
+ import { baz } from "mee";
33
+ import type { moo } from "mee";
34
+
35
+ import Default, { value } from "src";
36
+ import type { Foo } from "src";
37
+ ```
38
+
39
+ ## Auto-fixing
40
+
41
+ The rule's `--fix` produces these transformations:
42
+
43
+ ```ts
44
+ // Single inline type → hoisted
45
+ import { type foo } from "bar";
46
+ // becomes
47
+ import type { foo } from "bar";
48
+
49
+ // All inline types → hoisted
50
+ import { type foo, type bar } from "src";
51
+ // becomes
52
+ import type { foo, bar } from "src";
53
+
54
+ // Mixed value + inline type → split
55
+ import { baz, type moo } from "mee";
56
+ // becomes
57
+ import { baz } from "mee";
58
+ import type { moo } from "mee";
59
+
60
+ // Default + inline type → split
61
+ import Default, { type Foo } from "src";
62
+ // becomes
63
+ import Default from "src";
64
+ import type { Foo } from "src";
65
+
66
+ // Aliases are preserved
67
+ import { foo as bar, type baz as qux } from "src";
68
+ // becomes
69
+ import { foo as bar } from "src";
70
+ import type { baz as qux } from "src";
71
+
72
+ // Redundant inline markers inside `import type` are stripped
73
+ import type { foo, type bar } from "src";
74
+ // becomes
75
+ import type { foo, bar } from "src";
76
+ ```
77
+
78
+ After auto-fix, other import-ordering rules (such as `sort-imports`) may re-order the resulting statements according to their own grouping rules.
79
+
80
+ ## When Not To Use It
81
+
82
+ If your codebase intentionally uses the inline `type` form to keep value and type imports adjacent in a single statement, disable this rule.
83
+
84
+ ## Related Rules
85
+
86
+ - [prefer-import-type](./PREFER_IMPORT_TYPE.md) - Hoists imports that are used only as types to `import type`. Complements this rule for usage-based detection.