eslint-plugin-nextfriday 2.0.0 → 3.0.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,51 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 3.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#114](https://github.com/next-friday/eslint-plugin-nextfriday/pull/114) [`7933269`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/793326971cbbf15aaf2015f13622b7eff0fd51b2) Thanks [@joetakara](https://github.com/joetakara)! - Remove bundled `configs.sonarjs` and `configs.unicorn`. These configs are no longer exported. Consumers that previously did `...nextfriday.configs.sonarjs` or `...nextfriday.configs.unicorn` must install `eslint-plugin-sonarjs` and/or `eslint-plugin-unicorn` directly and configure them in their own flat config.
8
+
9
+ Migration:
10
+
11
+ ```js
12
+ import sonarjs from "eslint-plugin-sonarjs";
13
+ import unicorn from "eslint-plugin-unicorn";
14
+
15
+ export default [
16
+ {
17
+ plugins: { sonarjs },
18
+ rules: { ...sonarjs.configs.recommended.rules },
19
+ },
20
+ {
21
+ plugins: { unicorn },
22
+ rules: { ...unicorn.configs.recommended.rules },
23
+ },
24
+ ];
25
+ ```
26
+
27
+ The remaining six presets (`base`, `base/recommended`, `react`, `react/recommended`, `nextjs`, `nextjs/recommended`) are unchanged.
28
+
29
+ - [#114](https://github.com/next-friday/eslint-plugin-nextfriday/pull/114) [`7933269`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/793326971cbbf15aaf2015f13622b7eff0fd51b2) Thanks [@joetakara](https://github.com/joetakara)! - `nextjs` and `nextjs/recommended` presets are now arrays of flat-config objects instead of a single object. The first object enables the rules; the second disables `nextfriday/jsx-pascal-case` for files matching `app/**/*.{jsx,tsx}`, `src/app/**/*.{jsx,tsx}`, `pages/**/*.{jsx,tsx}`, and `src/pages/**/*.{jsx,tsx}` — Next.js's official routing directories where filenames are owned by the framework (`page.tsx`, `layout.tsx`, `error.tsx`, etc.).
30
+
31
+ `base`, `base/recommended`, `react`, and `react/recommended` are unchanged — they remain single config objects and `jsx-pascal-case` is enforced everywhere when those presets are used.
32
+
33
+ The `jsx-pascal-case` rule itself no longer special-cases any filename or directory. Scope is expressed in the preset via ESLint's `files` glob, not via rule-internal allowlists. Consumers using `react`/`react/recommended` on a Next.js project must either switch to the `nextjs` preset or add their own `files`-scoped override.
34
+
35
+ Migration:
36
+
37
+ ```js
38
+ import nextfriday from "eslint-plugin-nextfriday";
39
+
40
+ export default [nextfriday.configs["nextjs/recommended"]];
41
+ ```
42
+
43
+ ESLint 9+ flattens nested config arrays automatically, so existing usage continues to work.
44
+
45
+ ### Patch Changes
46
+
47
+ - [#114](https://github.com/next-friday/eslint-plugin-nextfriday/pull/114) [`7933269`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/793326971cbbf15aaf2015f13622b7eff0fd51b2) Thanks [@joetakara](https://github.com/joetakara)! - Fix `enforce-constant-case` flagging conventional names in framework config files. The rule now skips entirely when run on `*.config.{ts,mjs,cjs,js}`, `*.rc.*`, `*.setup.*`, `*.spec.*`, `*.test.*`, `.eslintrc*`, `.babelrc*`, and `.prettierrc*`. Frameworks like Next.js require `nextConfig` in `next.config.ts`, Vite/Tailwind require `config`, etc. — these conventions can no longer be incorrectly flagged as needing `SCREAMING_SNAKE_CASE`.
48
+
3
49
  ## 2.0.0
4
50
 
5
51
  ### Major Changes
package/README.md CHANGED
@@ -46,24 +46,49 @@ export default [nextfriday.configs.nextjs];
46
46
  export default [nextfriday.configs["nextjs/recommended"]];
47
47
  ```
48
48
 
49
- #### Bundled Plugin Configs
49
+ ### Extending a Preset with Rule Overrides
50
50
 
51
- Pre-configured configs for popular plugins. No extra install needed they ship as dependencies. These configs are arrays, so use the spread operator (`...`) to merge them into your flat config.
51
+ To use a preset and adjust individual rules, append a second config object after the preset. Later objects override earlier ones, so you can change severity, swap options, or add rules without re-declaring the entire preset.
52
+
53
+ For example, enforce PascalCase for React components via the `react/recommended` preset (which already runs `nextfriday/jsx-pascal-case` and `nextfriday/enforce-camel-case` as errors), and add a rule override on top:
52
54
 
53
55
  ```js
54
56
  import nextfriday from "eslint-plugin-nextfriday";
55
57
 
56
- export default [nextfriday.configs["react/recommended"], ...nextfriday.configs.sonarjs, ...nextfriday.configs.unicorn];
58
+ export default [
59
+ nextfriday.configs["react/recommended"],
60
+
61
+ {
62
+ rules: {
63
+ "nextfriday/jsx-pascal-case": "error",
64
+ "nextfriday/enforce-props-suffix": "error",
65
+ "nextfriday/sort-imports": "warn",
66
+ },
67
+ },
68
+ ];
57
69
  ```
58
70
 
59
- | Config | Plugin | Description |
60
- | --------- | --------------------- | ---------------------------------------------------------------------------------------------------------- |
61
- | `sonarjs` | eslint-plugin-sonarjs | SonarJS recommended rules for bug detection and code quality |
62
- | `unicorn` | eslint-plugin-unicorn | Unicorn recommended rules (with `filename-case` and `prevent-abbreviations` off, `no-null` off in JSX/TSX) |
71
+ The first object enables every rule in `react/recommended`. The second object reaffirms `jsx-pascal-case` (already enforced — useful when you want it loud and explicit), enables `enforce-props-suffix`, and downgrades `sort-imports` from error to warning.
63
72
 
64
73
  ### Manual Configuration
65
74
 
66
- If you prefer to configure rules manually:
75
+ #### When to use manual configuration vs a preset
76
+
77
+ Reach for a preset (`base`, `react`, `nextjs`, or any `/recommended` variant) by default. Presets are curated, kept in sync with new rules as the plugin grows, and require almost no maintenance on your side.
78
+
79
+ Choose manual configuration when one of these applies:
80
+
81
+ | Scenario | Why manual fits better |
82
+ | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
83
+ | You only need a few specific rules | Presets enable the full set; manual lets you adopt rules one at a time. |
84
+ | You want to opt out of new rules added in future plugin releases | Manual configs are explicit — new rules added to a preset would automatically apply, manual configs don't change without your edit. |
85
+ | You're consolidating multiple ESLint plugins and want fine-grained per-rule control | Avoids preset rules conflicting with rules from other plugins. |
86
+ | You're building a higher-level shared config for your org | You can hand-pick exactly which NextFriday rules to bundle into your own preset. |
87
+ | You're debugging a rule conflict | Manual makes the active rule set unambiguous. |
88
+
89
+ For every other case — new projects, gradual adoption, library code, application code — start from a preset and use [Extending a Preset with Rule Overrides](#extending-a-preset-with-rule-overrides) when you need to adjust specific rules.
90
+
91
+ #### Manual configuration example
67
92
 
68
93
  ```js
69
94
  import nextfriday from "eslint-plugin-nextfriday";
@@ -151,8 +176,109 @@ export default [
151
176
 
152
177
  > **Note:** This plugin requires ESLint 9+ and only supports the flat config format. Legacy `.eslintrc` configurations are not supported.
153
178
 
179
+ ### Per-Directory Configuration
180
+
181
+ ESLint flat config is an array of config objects. Each object's `files` and `ignores` glob patterns scope its rules to a subset of the project. Use this to apply different rule severities to different directories.
182
+
183
+ ```js
184
+ import nextfriday from "eslint-plugin-nextfriday";
185
+
186
+ export default [
187
+ {
188
+ files: ["src/components/**/*.{ts,tsx}"],
189
+ ...nextfriday.configs["react/recommended"],
190
+ },
191
+
192
+ {
193
+ files: ["src/utils/**/*.ts"],
194
+ ...nextfriday.configs.base,
195
+ },
196
+
197
+ {
198
+ files: ["src/legacy/**/*.{ts,tsx}"],
199
+ ignores: ["src/legacy/**/*"],
200
+ },
201
+
202
+ {
203
+ files: ["**/*.test.{ts,tsx}"],
204
+ rules: {
205
+ "nextfriday/require-explicit-return-type": "off",
206
+ "nextfriday/no-single-char-variables": "off",
207
+ },
208
+ },
209
+ ];
210
+ ```
211
+
212
+ The first config block applies the strict `react/recommended` preset (errors) to component files. The second applies the looser `base` preset (warnings) to utilities. The third excludes legacy code from linting entirely. The fourth keeps lint enabled for tests but turns off rules that conflict with common test patterns.
213
+
214
+ ### Migration Strategy
215
+
216
+ For an existing codebase with many violations, enable rules gradually instead of all at once. Three patterns, in order of how disruptive each is to your team:
217
+
218
+ **1. Start with the warn-level preset.** All rules surface as warnings, so the build still passes. Fix issues at your own pace, then switch to `/recommended`.
219
+
220
+ ```js
221
+ import nextfriday from "eslint-plugin-nextfriday";
222
+
223
+ export default [nextfriday.configs.react];
224
+ ```
225
+
226
+ **2. Lock-in a clean directory at a time.** Use `files` to apply `/recommended` (errors) only where the code is already clean, and the warn-level preset everywhere else.
227
+
228
+ ```js
229
+ import nextfriday from "eslint-plugin-nextfriday";
230
+
231
+ export default [
232
+ nextfriday.configs.react,
233
+
234
+ {
235
+ files: ["src/components/v2/**/*.{ts,tsx}", "src/lib/**/*.ts"],
236
+ ...nextfriday.configs["react/recommended"],
237
+ },
238
+ ];
239
+ ```
240
+
241
+ **3. Disable individual rules until the codebase is ready.** Re-declare specific rules with a lower severity (or `"off"`) after spreading the preset. Useful when one rule produces too much noise to fix at once.
242
+
243
+ ```js
244
+ import nextfriday from "eslint-plugin-nextfriday";
245
+
246
+ export default [
247
+ nextfriday.configs["react/recommended"],
248
+
249
+ {
250
+ rules: {
251
+ "nextfriday/require-explicit-return-type": "warn",
252
+ "nextfriday/sort-imports": "off",
253
+ },
254
+ },
255
+ ];
256
+ ```
257
+
258
+ Pair these with `ignores` to skip vendored or generated files entirely:
259
+
260
+ ```js
261
+ {
262
+ ignores: ["dist/**", "build/**", "**/*.generated.ts"],
263
+ }
264
+ ```
265
+
266
+ #### Prioritize rules by impact
267
+
268
+ When the warn-level preset surfaces hundreds of violations, fix them in this order — high-impact rules catch real bugs, while low-impact rules are style preferences that can wait.
269
+
270
+ | Tier | Examples | Why first |
271
+ | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
272
+ | High — correctness and runtime safety | `no-direct-date`, `no-env-fallback`, `nextjs-require-public-env`, `enforce-readonly-component-props`, `jsx-no-non-component-function`, `enforce-hook-naming`, `no-logic-in-params` | Each violation can mask a bug, leak config, or break React's rules of hooks. Fix before they ship. |
273
+ | Medium — structure and naming | `boolean-naming-prefix`, `enforce-camel-case`, `enforce-constant-case`, `file-kebab-case`, `jsx-pascal-case`, `enforce-props-suffix`, `prefer-import-type` | No runtime impact, but inconsistent naming compounds review and onboarding cost. Fix once the high tier is clean. |
274
+ | Low — formatting and ordering | `sort-imports`, `sort-exports`, `sort-type-alphabetically`, `jsx-sort-props`, `newline-before-return`, `newline-after-multiline-block`, `no-emoji` | Cosmetic. Most are auto-fixable, so a single `pnpm eslint --fix` pass typically clears the whole codebase. Save these for last. |
275
+
276
+ In practice: turn the high tier on as `"error"` first, leave the medium tier as `"warn"` while you migrate, and run the auto-fixers for the low tier in a single dedicated PR.
277
+
154
278
  ## Rules
155
279
 
280
+ > All rules in this plugin have no configurable options (`schema: []`). The only knob is severity — set each rule to `"error"`, `"warn"`, or `"off"`. Behavior is intentionally fixed so that the same rule means the same thing across every project.
281
+
156
282
  ### Variable Naming Rules
157
283
 
158
284
  | Rule | Description | Fixable |
@@ -80,6 +80,19 @@ The rule identifies boolean variables and parameters by:
80
80
  | `does` | Action capability | `doesExist`, `doesMatch`, `doesContain` |
81
81
  | `had` | Past possession | `hadError`, `hadAccess`, `hadPrevious` |
82
82
 
83
+ ## Not Checked
84
+
85
+ To keep the rule unobtrusive on patterns that are usually shaped by external APIs or framework conventions, these locations are intentionally ignored:
86
+
87
+ - **Class methods, getters, and setters.** `class Foo { get valid() {...} }` and `class Foo { set valid(v) {...} }` are not checked.
88
+ - **Class fields (property definitions).** `class Foo { valid = true }` is not checked.
89
+ - **Object literal properties.** `{ valid: true }` and `{ open: true, closed: false }` are not checked. Object keys often mirror an external schema (API responses, config payloads, DB rows) where renaming would be incorrect.
90
+ - **Computed property names.** `{ [key]: true }` is not checked because the name is dynamic.
91
+ - **Destructuring patterns.** `const { valid } = result;` is not checked — rename at the source instead, or use a destructuring alias (`const { valid: isValid } = result;`).
92
+ - **Property access.** `if (user.valid) {}` is not checked.
93
+
94
+ If you need stricter coverage of object/class members, pair this rule with [`@typescript-eslint/naming-convention`](https://typescript-eslint.io/rules/naming-convention/), which can target `classProperty`, `objectLiteralProperty`, `accessor`, and other selectors with custom prefix patterns.
95
+
83
96
  ## When Not To Use It
84
97
 
85
98
  - When working with external APIs that return boolean fields with different naming conventions
@@ -8,6 +8,8 @@ This rule ensures that global-scope `const` declarations with static values use
8
8
 
9
9
  Only global scope (top-level of a file) is checked. Local scope constants inside functions are not checked by this rule.
10
10
 
11
+ **Config files are exempt.** Files matching `*.config.{ts,mjs,cjs,js}`, `*.rc.*`, `*.setup.*`, `*.spec.*`, `*.test.*`, `.eslintrc*`, `.babelrc*`, and `.prettierrc*` skip this rule entirely. This avoids conflicts with framework conventions that require specific identifier names — e.g. Next.js expects `nextConfig` (not `NEXT_CONFIG`) in `next.config.ts`, Vite expects `config`, Tailwind expects `config`, etc.
12
+
11
13
  ## Examples
12
14
 
13
15
  ### Incorrect
@@ -54,6 +56,35 @@ function foo() {
54
56
  }
55
57
  ```
56
58
 
59
+ ## Configuration
60
+
61
+ This rule pairs with [`no-misleading-constant-case`](./NO_MISLEADING_CONSTANT_CASE.md) so that static globals use `SCREAMING_SNAKE_CASE` while local scopes and dynamic values keep `camelCase`. ESLint 9+ flat config:
62
+
63
+ ```js
64
+ import nextfriday from "eslint-plugin-nextfriday";
65
+
66
+ export default [
67
+ {
68
+ plugins: { nextfriday },
69
+ rules: {
70
+ "nextfriday/enforce-constant-case": "error",
71
+ "nextfriday/no-misleading-constant-case": "error",
72
+ "nextfriday/enforce-camel-case": "error",
73
+ },
74
+ },
75
+ ];
76
+ ```
77
+
78
+ Or via a preset (every preset already enables all three at the configured severity):
79
+
80
+ ```js
81
+ import nextfriday from "eslint-plugin-nextfriday";
82
+
83
+ export default [nextfriday.configs["base/recommended"]];
84
+ ```
85
+
86
+ This plugin only supports ESLint 9+ flat config — legacy `.eslintrc` is not supported.
87
+
57
88
  ## When Not To Use It
58
89
 
59
90
  - If your project uses different naming conventions for constants
@@ -28,6 +28,37 @@ This rule enforces that all TypeScript (.ts) and JavaScript (.js) files use keba
28
28
  - `user-service.ts`
29
29
  - `api-utils.ts`
30
30
 
31
+ ## Allowed Patterns and Edge Cases
32
+
33
+ - **Only `.ts` and `.js` are checked.** `.tsx` and `.jsx` files are ignored — use [`jsx-pascal-case`](./JSX_PASCAL_CASE.md) for React component filenames.
34
+ - **Compound extensions are allowed when each segment is kebab-case.** Both the basename and the trailing token before the file extension are validated independently. This pattern is useful for config, setup, spec, test, and rc files:
35
+ - `next.config.ts` ✓
36
+ - `vitest.setup.ts` ✓
37
+ - `user-service.test.ts` ✓
38
+ - `auth.spec.ts` ✓
39
+ - `eslint.rc.ts` ✓
40
+ - **Numbers are allowed inside segments.** `file-with-numbers-123.ts` ✓
41
+ - **Single-word filenames are valid.** `single.ts` ✓ (no hyphens needed)
42
+
43
+ ## Disabling the Rule
44
+
45
+ To opt out for a specific directory or file pattern, add an override in your flat config:
46
+
47
+ ```js
48
+ import nextfriday from "eslint-plugin-nextfriday";
49
+
50
+ export default [
51
+ nextfriday.configs["base/recommended"],
52
+
53
+ {
54
+ files: ["src/legacy/**/*.ts", "src/vendor/**/*.js"],
55
+ rules: {
56
+ "nextfriday/file-kebab-case": "off",
57
+ },
58
+ },
59
+ ];
60
+ ```
61
+
31
62
  ## When Not To Use It
32
63
 
33
64
  If your project has established naming conventions that conflict with kebab-case, or if you're working with frameworks that require specific filename patterns, you may want to disable this rule.
@@ -28,6 +28,36 @@ This rule enforces that JSX and TSX files use PascalCase naming convention for t
28
28
  - `LoginForm.tsx`
29
29
  - `UserProfile2.jsx` (PascalCase with numbers)
30
30
 
31
+ ## Scoping the Rule
32
+
33
+ This rule has **no built-in framework detection** and no allowlist of "known" filenames. It checks every `.jsx`/`.tsx` it sees. If your project mixes component files with framework routing files that use lowercase names (e.g. Next.js App Router `page.tsx`, `layout.tsx`, `error.tsx`, or Pages Router `_app.tsx`), scope the rule explicitly via ESLint's `files` glob in flat config:
34
+
35
+ ```js
36
+ import nextfriday from "eslint-plugin-nextfriday";
37
+
38
+ export default [
39
+ nextfriday.configs.react,
40
+
41
+ {
42
+ files: ["src/components/**/*.{jsx,tsx}", "components/**/*.{jsx,tsx}"],
43
+ rules: {
44
+ "nextfriday/jsx-pascal-case": "error",
45
+ },
46
+ },
47
+
48
+ {
49
+ files: ["src/app/**/*.{jsx,tsx}", "app/**/*.{jsx,tsx}", "src/pages/**/*.{jsx,tsx}", "pages/**/*.{jsx,tsx}"],
50
+ rules: {
51
+ "nextfriday/jsx-pascal-case": "off",
52
+ },
53
+ },
54
+ ];
55
+ ```
56
+
57
+ The first override turns the rule on only inside component directories where PascalCase is the convention. The second override explicitly disables the rule for Next.js routing directories where the framework owns the filename.
58
+
59
+ The plugin deliberately does not try to detect Next.js, Remix, or other framework conventions automatically — folder structures vary across projects (monorepos, custom `app` locations, hybrid Pages + App Router setups), and a built-in allowlist would inevitably go stale. ESLint's `files` glob is the deterministic way to express the scope you actually want.
60
+
31
61
  ## When Not To Use It
32
62
 
33
63
  If your project uses different naming conventions for JSX/TSX files, you can disable this rule.