exadev-eslint-config 2.19.3 → 2.19.4

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/README.md CHANGED
@@ -16,14 +16,14 @@ Multiple ExaDev repos carried identical copies of a handful of custom ESLint rul
16
16
  pnpm add -D @exadev/eslint-config typescript-eslint eslint
17
17
  ```
18
18
 
19
- Requires `eslint >=10.0.0` and `typescript-eslint >=8.0.0` as peer dependencies. Importing anything from this package resolves `typescript-eslint`, since the default export and the `plugin` named export share one root module — see [Architecture](#architecture).
19
+ Requires [`eslint`](https://eslint.org) `>=10.0.0` and [`typescript-eslint`](https://typescript-eslint.io/packages/typescript-eslint) `>=8.0.0` as peer dependencies. Importing anything from this package resolves `typescript-eslint`, since the default export and the `plugin` named export share one root module — see [Architecture](#architecture).
20
20
 
21
21
  ```ts
22
22
  // eslint.config.ts
23
+ import { defineConfig } from 'eslint/config';
23
24
  import exadev from '@exadev/eslint-config';
24
- import tseslint from 'typescript-eslint';
25
25
 
26
- export default tseslint.config(
26
+ export default defineConfig(
27
27
  {
28
28
  languageOptions: {
29
29
  parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname },
@@ -34,13 +34,15 @@ export default tseslint.config(
34
34
  );
35
35
  ```
36
36
 
37
- **Remove your own `tseslint.configs.recommended`/`recommendedTypeChecked`/`strictTypeChecked`/`stylisticTypeChecked` spreads.** The default export already includes `strictTypeChecked` (which subsumes both plain `recommended` and `recommendedTypeChecked`) plus `stylisticTypeChecked`, and registers the `@typescript-eslint` plugin/parser itself flat config rejects two different plugin object instances registered under the same namespace. You still supply your own `languageOptions.parserOptions.project`/`projectService` pointing at your tsconfig(s).
37
+ **Why [`defineConfig()`](https://eslint.org/docs/latest/use/configure/configuration-files#defineconfig-utility) rather than `tseslint.config()` here:** [`tseslint.config()`](https://typescript-eslint.io/packages/typescript-eslint/#config-deprecated) is now `@deprecated` upstream in favour of ESLint core's own `defineConfig()`, so this package's default export is typed against ESLint core's own config type specifically so it satisfies `defineConfig()` directly. If you haven't migrated off `tseslint.config()` yet, it still works exactly the same this package's exported config array is typed to satisfy either wrapper, and that compatibility is itself covered by a real regression test (`src/consumer-compatibility.ts`) but new consumers should reach for `defineConfig()`.
38
+
39
+ **Remove your own `tseslint.configs.recommended`/`recommendedTypeChecked`/`strictTypeChecked`/`stylisticTypeChecked` spreads.** The default export already includes [`strictTypeChecked`](https://typescript-eslint.io/users/configs/#strict-type-checked) (which subsumes both plain [`recommended`](https://typescript-eslint.io/users/configs/#recommended) and [`recommendedTypeChecked`](https://typescript-eslint.io/users/configs/#recommended-type-checked)) plus [`stylisticTypeChecked`](https://typescript-eslint.io/users/configs/#stylistic-type-checked), and registers the `@typescript-eslint` plugin/parser itself — [flat config](https://eslint.org/docs/latest/use/configure/configuration-files) rejects two different plugin object instances registered under the same namespace. You still supply your own `languageOptions.parserOptions.project`/`projectService` pointing at your tsconfig(s).
38
40
 
39
41
  ### What the default export includes
40
42
 
41
43
  **typescript-eslint presets:**
42
44
 
43
- - `strictTypeChecked` + `stylisticTypeChecked` — already covers [`no-deprecated`](https://typescript-eslint.io/rules/no-deprecated/), [`no-misused-spread`](https://typescript-eslint.io/rules/no-misused-spread/), [`no-mixed-enums`](https://typescript-eslint.io/rules/no-mixed-enums/), [`no-unnecessary-condition`](https://typescript-eslint.io/rules/no-unnecessary-condition/), [`use-unknown-in-catch-callback-variable`](https://typescript-eslint.io/rules/use-unknown-in-catch-callback-variable/), [`return-await`](https://typescript-eslint.io/rules/return-await/), [`related-getter-setter-pairs`](https://typescript-eslint.io/rules/related-getter-setter-pairs/), [`no-unnecessary-type-parameters`](https://typescript-eslint.io/rules/no-unnecessary-type-parameters/), and more (not re-listed individually below).
45
+ - [`strictTypeChecked`](https://typescript-eslint.io/users/configs/#strict-type-checked) + [`stylisticTypeChecked`](https://typescript-eslint.io/users/configs/#stylistic-type-checked) — already covers [`no-deprecated`](https://typescript-eslint.io/rules/no-deprecated/), [`no-misused-spread`](https://typescript-eslint.io/rules/no-misused-spread/), [`no-mixed-enums`](https://typescript-eslint.io/rules/no-mixed-enums/), [`no-unnecessary-condition`](https://typescript-eslint.io/rules/no-unnecessary-condition/), [`use-unknown-in-catch-callback-variable`](https://typescript-eslint.io/rules/use-unknown-in-catch-callback-variable/), [`return-await`](https://typescript-eslint.io/rules/return-await/), [`related-getter-setter-pairs`](https://typescript-eslint.io/rules/related-getter-setter-pairs/), [`no-unnecessary-type-parameters`](https://typescript-eslint.io/rules/no-unnecessary-type-parameters/), and more (not re-listed individually below).
44
46
 
45
47
  **This package's own rules** (full details in [Rules](#rules)):
46
48
 
@@ -72,7 +74,7 @@ export default tseslint.config(
72
74
  - *Why:* `let`/`const`/`class`/enum bindings have a genuine temporal-dead-zone crash risk, but function declarations are fully hoisted and safe to call before their point of textual declaration — this codebase's own rule files consistently define helper functions after the logic that calls them.
73
75
  - **[`ban-ts-comment`](https://typescript-eslint.io/rules/ban-ts-comment/)** — bans `@ts-expect-error` outright (relaxed in test files, see below).
74
76
  - **[`method-signature-style`](https://typescript-eslint.io/rules/method-signature-style/)** set to `'property'`.
75
- - *Why:* method-shorthand signatures are checked bivariantly under `strictFunctionTypes`, which is unsound.
77
+ - *Why:* method-shorthand signatures are checked bivariantly under [`strictFunctionTypes`](https://www.typescriptlang.org/tsconfig/#strictFunctionTypes), which is unsound.
76
78
  - **[`prefer-readonly`](https://typescript-eslint.io/rules/prefer-readonly/)**, **[`promise-function-async`](https://typescript-eslint.io/rules/promise-function-async/)**, **[`require-array-sort-compare`](https://typescript-eslint.io/rules/require-array-sort-compare/)** — plain presence, no extra config.
77
79
  - **[`strict-void-return`](https://typescript-eslint.io/rules/strict-void-return/)** — bans passing a value-returning function where a void-returning one is expected (e.g. `arr.forEach(x => otherArray.push(x))`).
78
80
  - *Why:* not yet in any typescript-eslint preset; this typechecks today only because of TS's own void-return contravariance leniency.
@@ -100,10 +102,10 @@ For a project that wants only this package's own rules without the full type-che
100
102
 
101
103
  ```ts
102
104
  // eslint.config.ts
105
+ import { defineConfig } from 'eslint/config';
103
106
  import { plugin } from '@exadev/eslint-config';
104
- import tseslint from 'typescript-eslint';
105
107
 
106
- export default tseslint.config(
108
+ export default defineConfig(
107
109
  // ...your own config...
108
110
  {
109
111
  files: ['src/**/*.ts'],
@@ -132,7 +134,7 @@ export default defineConfig([
132
134
  ]);
133
135
  ```
134
136
 
135
- `tseslint.config()` does **not** accept string `extends` (only `defineConfig()` does); pass the config value directly instead:
137
+ [`tseslint.config()`](https://typescript-eslint.io/packages/typescript-eslint#config) does **not** accept string `extends` (only [`defineConfig()`](https://eslint.org/docs/latest/use/configure/configuration-files#defineconfig-utility) does); pass the config value directly instead:
136
138
 
137
139
  ```ts
138
140
  import { plugin } from '@exadev/eslint-config';
@@ -163,10 +165,10 @@ Every tri-state option above (`true`/`false`/`undefined`) is passed through the
163
165
 
164
166
  ```ts
165
167
  // eslint.config.ts
168
+ import { defineConfig } from 'eslint/config';
166
169
  import { exadevConfig } from '@exadev/eslint-config';
167
- import tseslint from 'typescript-eslint';
168
170
 
169
- export default tseslint.config(
171
+ export default defineConfig(
170
172
  {
171
173
  languageOptions: {
172
174
  parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname },
@@ -183,7 +185,7 @@ Trailing arguments are arbitrary flat-config objects, appended in order after ev
183
185
 
184
186
  React/hooks/a11y and Next.js rule blocks fold in automatically, with no separate import or config needed, gated on two independent, always-both-required conditions:
185
187
 
186
- 1. **The corresponding package must actually be resolvable.** `eslint-plugin-react`, `eslint-plugin-react-hooks`, `eslint-plugin-jsx-a11y`, and `@next/eslint-plugin-next` are all *optional* peer dependencies (`peerDependenciesMeta.<pkg>.optional: true`) — install only whichever your project actually needs:
188
+ 1. **The corresponding package must actually be resolvable.** [`eslint-plugin-react`](https://github.com/jsx-eslint/eslint-plugin-react), [`eslint-plugin-react-hooks`](https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks), [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y), and [`@next/eslint-plugin-next`](https://github.com/vercel/next.js/tree/canary/packages/eslint-plugin-next) are all *optional* peer dependencies (`peerDependenciesMeta.<pkg>.optional: true`) — install only whichever your project actually needs:
187
189
  ```sh
188
190
  pnpm add -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y # React support
189
191
  pnpm add -D @next/eslint-plugin-next # Next.js support
@@ -197,10 +199,10 @@ React support pairs `eslint-plugin-react`'s `flat/recommended` with its own `fla
197
199
 
198
200
  - **`plugin.configs.react`/`plugin.configs.nextjs`** — explicit tier selection, mirroring `plugin.configs.recommended`/`.barrel`. Unlike those two, selecting `.react`/`.nextjs` is itself an explicit request: it **throws** a clear, actionable error if the underlying peer isn't installed, rather than silently returning nothing.
199
201
  ```ts
202
+ import { defineConfig } from 'eslint/config';
200
203
  import { plugin } from '@exadev/eslint-config';
201
- import tseslint from 'typescript-eslint';
202
204
 
203
- export default tseslint.config(
205
+ export default defineConfig(
204
206
  // ...your own config...
205
207
  {
206
208
  files: ['**/*.tsx'],
@@ -237,7 +239,7 @@ Every JSON file is linted against [`eslint-plugin-json-canonical`](https://githu
237
239
 
238
240
  The plugin's own full-canonicalization rule ([`no-insignificant-whitespace`](https://github.com/ExaDev/eslint-plugin-json-canonical/blob/main/src/rules/no-insignificant-whitespace.ts), which collapses a document to a single compacted line with no whitespace at all) is deliberately not part of the config this package extends — it stays available for a consumer to opt into directly for their own genuine canonicalization pass (hashing, signing, byte-for-byte comparison).
239
241
 
240
- `**/*.jsonc`, `**/tsconfig*.json`, and `**/turbo.json` get the plugin's `configs.contentOnlyJsonc` instead of the plain-JSON config: they genuinely carry comments (TypeScript and turbo both accept them), which `@eslint/json`'s `json/json` language has no concept of and fails to parse, and neither pretty-printing nor whitespace-collapsing has a well-defined answer for a comment's own attachment to a member once its surrounding whitespace is rewritten. Content canonicalization (key order, number/string formatting) still applies to these files under `json/jsonc`.
242
+ `**/*.jsonc`, `**/tsconfig*.json`, and `**/turbo.json` get the plugin's `configs.contentOnlyJsonc` instead of the plain-JSON config: they genuinely carry comments (TypeScript and turbo both accept them), which [`@eslint/json`](https://github.com/eslint/json#readme)'s `json/json` language has no concept of and fails to parse, and neither pretty-printing nor whitespace-collapsing has a well-defined answer for a comment's own attachment to a member once its surrounding whitespace is rewritten. Content canonicalization (key order, number/string formatting) still applies to these files under `json/jsonc`.
241
243
 
242
244
  `**/package.json` gets everything the plain-JSON config gives every other file — including pretty-printed layout — except [`json/sort-keys`](https://github.com/eslint/json/blob/main/docs/rules/sort-keys.md), turned back off in its own override block, since its key order is the separate, syncpack-aware concern the next section covers.
243
245
 
@@ -316,11 +318,13 @@ pnpm test
316
318
  pnpm build
317
319
  ```
318
320
 
319
- - Each rule has a co-located `*.unit.test.ts` exercising it with ESLint's `RuleTester` under Vitest. [`vitest.setup.ts`](vitest.setup.ts) wires `RuleTester.describe`/`.it`/`.itOnly` to Vitest's `describe`/`it` explicitly (no `test.globals`). Each test uses typescript-eslint's parser for TypeScript-only fixtures; none need type information.
321
+ [`pnpm`](https://pnpm.io) is this repo's own package manager, pinned via `packageManager`.
322
+
323
+ - Each rule has a co-located `*.unit.test.ts` exercising it with ESLint's [`RuleTester`](https://eslint.org/docs/latest/integrate/nodejs-api#ruletester) under [Vitest](https://vitest.dev). [`vitest.setup.ts`](vitest.setup.ts) wires `RuleTester.describe`/`.it`/`.itOnly` to Vitest's `describe`/`it` explicitly (no `test.globals`). Each test uses typescript-eslint's parser for TypeScript-only fixtures; none need type information.
320
324
  - Every test file's own name declares its kind via a filename suffix immediately before `.test`/`.spec` — `.unit`, `.integration`, or `.e2e` by default (`exadev/test-file-kind`, part of `recommended`; see [Rules](#rules)) — so a file's test kind is always visible from its name alone, without opening it, and downstream tooling (e.g. a Vitest project split by test kind) can select by filename glob rather than by convention nobody enforces. This package's own tests are exclusively `.unit.test.ts` today (a `.internal.unit.test.ts` variant exists for a handful of files that also test non-exported internals directly, `internal` just being an ordinary extra name segment — see [`no-mutable-union-array-param.internal.unit.test.ts`](src/rules/no-mutable-union-array-param.internal.unit.test.ts)).
321
- - `pnpm test` always measures coverage (`@vitest/coverage-v8`), scoped to `src/**/*.ts` excluding `*.test.ts`. Text output in terminal; `html`/`lcov` in `coverage/` (gitignored alongside `.eslintcache` and `dist/`).
322
- - The `lint`/`typecheck`/`test`/`build` npm scripts wrap turbo tasks named `_lint`/`_typecheck`/`_test`/`_build` — run `pnpm build`, not `turbo run build`.
323
- - `pnpm build` runs `tsdown` from [`src/index.ts`](src/index.ts), bundling the whole module graph into ESM + CJS + declarations. `prepublishOnly` re-runs lint, typecheck, `test`, `tsdown`, `publint`, and `attw --pack`.
325
+ - `pnpm test` always measures [coverage](https://vitest.dev/guide/coverage) (`@vitest/coverage-v8`), scoped to `src/**/*.ts` excluding `*.test.ts`. Text output in terminal; `html`/`lcov` in `coverage/` (gitignored alongside `.eslintcache` and `dist/`).
326
+ - The `lint`/`typecheck`/`test`/`build` npm scripts wrap [turbo](https://turborepo.dev) tasks named `_lint`/`_typecheck`/`_test`/`_build` — run `pnpm build`, not `turbo run build`.
327
+ - `pnpm build` runs [`tsdown`](https://tsdown.dev) from [`src/index.ts`](src/index.ts), bundling the whole module graph into ESM + CJS + declarations. `prepublishOnly` re-runs lint, typecheck, `test`, `tsdown`, [`publint`](https://publint.dev), and [`attw`](https://github.com/arethetypeswrong/arethetypeswrong.github.io) `--pack`.
324
328
 
325
329
  ### Architecture
326
330
 
@@ -328,13 +332,13 @@ pnpm build
328
332
  <summary>Expand for implementation internals (not needed for ordinary consumption)</summary>
329
333
 
330
334
  - [`src/plugin.ts`](src/plugin.ts) builds a `TSESLint.FlatConfig.Plugin` combining [`src/rules/`](src/rules) into a flat `rules` map.
331
- - That's `@typescript-eslint/utils`'s own type, not ESLint's own `ESLint.Plugin` — the latter can't hold a rule built with `ESLintUtils.RuleCreator`.
335
+ - That's [`@typescript-eslint/utils`](https://typescript-eslint.io/packages/utils)'s own type, not ESLint's own `ESLint.Plugin` — the latter can't hold a rule built with [`ESLintUtils.RuleCreator`](https://typescript-eslint.io/developers/custom-rules).
332
336
  - `configs.recommended`, `.barrel`, `.react`, and `.nextjs` are getters in the object literal, since each references the fully-built `plugin` (`plugins: { exadev: plugin }`), which a plain property initializer can't do mid-construction.
333
337
  - `recommended` ships `barrel-policy` at `mode: 'banned'`; `barrel` at `mode: 'single'`; `.react`/`.nextjs` call `buildReactConfig`/`buildNextjsConfig` with `enabled: true` (see below).
334
338
  - [`src/config-types.ts`](src/config-types.ts) holds `ConfigValue`/`ConfigArrayValue` (`ConfigArrayValue = Extract<ConfigValue, unknown[]>`, the array-only member of ESLint's own config-value union), shared by every file below rather than redefined per file.
335
339
  - *Why:* annotating a config array with the wider `ConfigValue` union directly broke `...exadev` with `TS2488` ("must have a Symbol.iterator method").
336
340
  - [`src/optional-plugin.ts`](src/optional-plugin.ts) is the lazy-resolution helper behind React/Next.js support.
337
- - `tryRequire` wraps `createRequire(import.meta.url)` in try/catch, returning `unknown` (never a cast) so every call site narrows explicitly before use.
341
+ - `tryRequire` wraps [`createRequire(import.meta.url)`](https://nodejs.org/api/module.html#modulecreaterequirefilename) in try/catch, returning `unknown` (never a cast) so every call site narrows explicitly before use.
338
342
  - `readFlatConfig` walks a property path through that `unknown` value via a real type guard, normalizing a stray legacy top-level `parserOptions` key into `languageOptions.parserOptions` along the way.
339
343
  - Confirmed necessary: `eslint-plugin-jsx-a11y`'s own `configs.recommended` export carries exactly this legacy shape, which flat config's schema rejects outright rather than ignores.
340
344
  - [`src/react.ts`](src/react.ts)/[`src/nextjs.ts`](src/nextjs.ts) each export a `build*Config(options)` function: resolve the relevant optional peer(s) via `tryRequire`, extract their real flat config via `readFlatConfig`, and return an array of 0-or-more config blocks.
@@ -354,15 +358,15 @@ pnpm build
354
358
  ### Conventions
355
359
 
356
360
  - [`eslint.config.ts`](eslint.config.ts) dogfoods this package's own factory export on itself (`import { exadevConfig } from './src/index'`), spreading `exadevConfig({ react: false, nextjs: false })` — forced off explicitly, not the plain auto-detecting default, since `eslint-plugin-react`/`@next/eslint-plugin-next` are real devDependencies of *this* repo (needed to test [`src/react.ts`](src/react.ts)/[`src/nextjs.ts`](src/nextjs.ts)'s own "package is resolvable" branch) even though this repo is neither a React nor a Next.js project. `no-side-effects-in-index` and `no-non-barrel-reexport` self-scope to [`src/index.ts`](src/index.ts) internally, so no `files`/`ignores` wiring is needed here. Plugin construction lives in [`src/plugin.ts`](src/plugin.ts) specifically so `src/index.ts` stays a pure re-export point.
357
- - [`tsconfig.json`](tsconfig.json) enables `verbatimModuleSyntax` (`import type`/`export type` required for type-only imports — also enforced by `consistent-type-imports`) and `noUncheckedIndexedAccess` (narrow indexed access before use rather than asserting).
358
- - Conventional commits are enforced by commitlint, restricted to the type-enum defined once in [`release.config.ts`](release.config.ts)'s `commitTypes` — both commitlint and semantic-release derive from that single list.
361
+ - [`tsconfig.json`](tsconfig.json) enables [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) (`import type`/`export type` required for type-only imports — also enforced by `consistent-type-imports`) and [`noUncheckedIndexedAccess`](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess) (narrow indexed access before use rather than asserting).
362
+ - Conventional commits are enforced by [commitlint](https://commitlint.js.org), restricted to the type-enum defined once in [`release.config.ts`](release.config.ts)'s `commitTypes` — both commitlint and semantic-release derive from that single list.
359
363
 
360
364
  ### Gotchas and quirks
361
365
 
362
- - [`.attw.json`](.attw.json) ignores `false-export-default`: tsdown/rolldown's CJS output for this plugin's sole default export doesn't emit the `export =` form `arethetypeswrong` wants under legacy `node10` resolution. The modes ESLint flat config uses (`node16`, `bundler`) are unaffected, so the rule is suppressed rather than changing the default-export shape.
366
+ - [`.attw.json`](.attw.json) ignores `false-export-default`: tsdown/[rolldown](https://rolldown.rs)'s CJS output for this plugin's sole default export doesn't emit the `export =` form [`arethetypeswrong`](https://github.com/arethetypeswrong/arethetypeswrong.github.io) wants under legacy `node10` resolution. The modes ESLint flat config uses (`node16`, `bundler`) are unaffected, so the rule is suppressed rather than changing the default-export shape.
363
367
  - [`src/index.ts`](src/index.ts) mixing a default export with a named one triggers rolldown's `MIXED_EXPORTS` warning: a raw CommonJS `require()` would see the raw exports object instead of the default. ESM `import` (the actual consumer path) resolves both correctly; `attw --pack` and `publint` report no problems, so the warning is accepted (see [`tsdown.config.ts`](tsdown.config.ts)).
364
- - Husky hooks: `pre-commit` runs lint-staged (`eslint --fix` on staged `*.ts`), `commit-msg` runs commitlint, `pre-push` runs typecheck + test + build.
365
- - The CI release job sets `HUSKY=0` (commit-msg hook skips the automated release commit) and blanks `NPM_TOKEN`/`NODE_AUTH_TOKEN` explicitly so an inherited token can't win over OIDC trusted publishing.
368
+ - [Husky](https://github.com/typicode/husky) hooks: `pre-commit` runs [lint-staged](https://github.com/lint-staged/lint-staged#readme) (`eslint --fix` on staged `*.ts`), `commit-msg` runs commitlint, `pre-push` runs typecheck + test + build.
369
+ - The CI release job sets `HUSKY=0` (commit-msg hook skips the automated release commit) and blanks `NPM_TOKEN`/`NODE_AUTH_TOKEN` explicitly so an inherited token can't win over [OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers).
366
370
  - A consumer who already has `eslint-plugin-react`/`@next/eslint-plugin-next` resolvable for unrelated reasons (e.g. hoisted in a monorepo) and writes `.jsx`/`.tsx` files may see new rule activity the moment they upgrade to a version of this package that ships React/Next.js support — with zero action on their part. See the compatibility note under [Optional React and Next.js support](#optional-react-and-nextjs-support).
367
371
 
368
372
  ### Contributing
@@ -371,7 +375,7 @@ Conventional commits are enforced by a husky `commit-msg` hook and re-checked in
371
375
 
372
376
  ### Release
373
377
 
374
- Conventional commits drive [semantic-release](https://semantic-release.gitbook.io/semantic-release) on every push to `main`: version bump, `CHANGELOG.md`, GitHub Release, and npm publish via OIDC (no stored token). A second CI job republishes the identical build under the unscoped alias `exadev-eslint-config`.
378
+ Conventional commits drive [semantic-release](https://semantic-release.gitbook.io/semantic-release) on every push to `main`: version bump, `CHANGELOG.md`, GitHub Release, and npm publish via [OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers) (no stored token). A second CI job republishes the identical build under the unscoped alias `exadev-eslint-config`.
375
379
 
376
380
  ## License
377
381
 
package/dist/index.cjs CHANGED
@@ -295,7 +295,7 @@ function buildNextjsConfig(options = {}) {
295
295
  }
296
296
  //#endregion
297
297
  //#region package.json
298
- var version = "2.19.3";
298
+ var version = "2.19.4";
299
299
  //#endregion
300
300
  //#region src/react.ts
301
301
  const JSX_FILE_PATTERNS = ["**/*.jsx", "**/*.tsx"];
package/dist/index.js CHANGED
@@ -261,7 +261,7 @@ function buildNextjsConfig(options = {}) {
261
261
  }
262
262
  //#endregion
263
263
  //#region package.json
264
- var version = "2.19.3";
264
+ var version = "2.19.4";
265
265
  //#endregion
266
266
  //#region src/react.ts
267
267
  const JSX_FILE_PATTERNS = ["**/*.jsx", "**/*.tsx"];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "exadev-eslint-config",
3
3
  "description": "Shared custom ESLint rules and plugin for ExaDev projects",
4
- "version": "2.19.3",
4
+ "version": "2.19.4",
5
5
  "dependencies": {
6
6
  "@eslint/js": "^10.0.1",
7
7
  "@typescript-eslint/utils": "8.67.0",