npm package: @javalce/eslint-config
Description: Javier's eslint configuration
Author: Javier Valero
Latest version: 0.24.2

# @javalce/eslint-config

[![NPM version](https://img.shields.io/npm/v/@javalce/eslint-config.svg?style=flat-square&labelColor=000000)](https://www.npmjs.com/package/@javalce/eslint-config)
[![License](https://img.shields.io/npm/l/@javalce/eslint-config.svg?style=flat-square&labelColor=000000)](https://github.com/javalce/eslint-config/blob/main/LICENSE)

This configuration is opinionated and it may not fit your needs. You can extend it and override the rules that you don't like.

- [@javalce/eslint-config](#javalceeslint-config)
  - [Features](#features)
  - [Installation](#installation)
  - [Basic Usage](#basic-usage)
  - [Configuration](#configuration)
    - [Overriding rules and extended config](#overriding-rules-and-extended-config)
    - [Ignore files](#ignore-files)
    - [Custom path aliases](#custom-path-aliases)
    - [TypeScript](#typescript)
    - [JSX](#jsx)
    - [Angular](#angular)
      - [Customizing selectors](#customizing-selectors)
    - [NgRx](#ngrx)
    - [React](#react)
    - [Next.js](#nextjs)
    - [Svelte](#svelte)
    - [Solidjs](#solidjs)
    - [Vue](#vue)
      - [Vue 2](#vue-2)
    - [TanStack](#tanstack)
    - [Astro](#astro)
    - [Testing](#testing)
      - [Testing with Jest](#testing-with-jest)
      - [Testing with Vitest](#testing-with-vitest)
      - [Testing Library](#testing-library)
  - [Additional configuration](#additional-configuration)
    - [Presets](#presets)
  - [Credits](#credits)
  - [License](#license)

## Features

- Supports ESLint v9
- [ESLint Flat Config](https://eslint.org/docs/latest/use/configure/configuration-files) file format
- Does not lint `.gitignore` listed files (I think that if you don't want to track a file, you don't want to lint it)
- Designed to work with TypeScript, React, Next.js, Node.js, and more smoothly out of the box
- Some rules can be auto-fixed with `eslint --fix`
- Uses some stylistic rules to make your code more readable and consistent

> [!IMPORTANT]
> I like to use Prettier to format my code, so the enabled stylistic rules are the ones that Prettier doesn't format.
>
> If you want to use Prettier, you can use my personal config [@javalce/prettier-config](https://www.npmjs.com/package/@javalce/prettier-config).

## Installation

Install ESLint and this config as dev dependencies:

```bash
pnpm add --save-dev eslint @javalce/eslint-config
```

## Basic Usage

Create an `eslint.config.mjs` file in the root of your project with the following content:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig();
```

By default it uses the ecmaVersion `2023`. If you want to use a different version, you can specify it in the configuration:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  js: {
    ecmaVersion: 2022,
  },
});
```

## Configuration

To configure ESLint, you have to use the `defineConfig` function, as shown in the previous section. This function will return the ESLint configuration object.

You have to enable each framework configuration explicitly, otherwise it will not be loaded except for the TypeScript config, which is loaded automatically.

After you enable a framework, if you don't have the required ESLint plugins for this framework installed, ESLint will throw an error when you run it showing you the missing plugins.

For more information about each configuration option, check the respective section.

### Overriding rules and extended config

Some rules are only enabled when you enable specific framework configurations. For example, in TypeScript rules (see [TypeScript](#typescript) for more information) if you want to force functions and methods to have a return type, you can enable the `@typescript-eslint/explicit-function-return-type` rule:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  ts: {
    overrides: {
      '@typescript-eslint/explicit-function-return-type': 'error',
    },
  },
});
```

You can also extends the config by adding a plugin that it was not previously included in the preset:

```js
import { defineConfig } from '@javalce/eslint-config';
import { GLOBS_TS_FILES } from '@javalce/eslint-config/globs';
import perfectionist from 'eslint-plugin-perfectionist'

export default defineConfig({
  extends: [
    perfectionist.configs.['recommended-natural'],
  ],
});
```

This way we added a Perfectionist plugin configuration.

### Ignore files

By default, the ESLint configuration will ignore all files in the `.gitignore` file. If you want to ignore additional files, you can pass the `ignores` option to the configuration:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  ignores: ['src/types.d.ts'],
});
```

### Custom path aliases

By default, the configuration sets up two path alias patterns: `@/**` and `~/**`. These aliases are used to group and automatically order imports in your project, making it easier to organize internal modules.

You can customize these aliases using the `import.pathAliases` option in your configuration:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  import: {
    // You can use a string or an array of strings
    pathAliases: ['@/**', '#/**'],
  },
});
```

This will affect the "internal" import group and the order in which they appear according to the `import-x/order` rule. If you don't configure this option, the default aliases will be `@/**` and `~/**`.

### TypeScript

To enable TypeScript support, you only need to install the `typescript` package:

```bash
pnpm add --save-dev typescript
```

By default, the TypeScript configuration is enabled automatically is the `typescript` package is installed in your project. If you want to enable it explicitly, you can do it like this:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  ts: true,
});
```

Also by default, it will use the `tsconfig.json` file in the root of your project to configure the `projectService` option of the `@typescript-eslint/parser` (see [https://typescript-eslint.io/packages/parser#projectservice](https://typescript-eslint.io/packages/parser#projectservice)). This is the default configuration:

```js
{
  parserOptions: {
    projectService: {
      allowDefaultProject: ['./*.js'],
      defaultProject: 'tsconfig.json',
    },
    tsconfigRootDir: 'the/path/to/your/project',
  }
}
```

If you want to customize the `defaultProject` file, you can specify the `tsconfigPath` option in the configuration:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  ts: {
    tsconfigPath: './path/to/tsconfig.custom.json',
  },
});
```

### JSX

The `jsx` configuration enables basic JSX support (parsing) for `.jsx` and `.tsx` files and can optionally enable accessibility rules from `eslint-plugin-jsx-a11y`.

Basic usage (parses JSX files):

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  jsx: true,
});
```

Enable accessibility rules (requires installing `eslint-plugin-jsx-a11y`):

```bash
pnpm add --save-dev eslint-plugin-jsx-a11y
```

Then enable accessibility rules in the config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  jsx: {
    a11y: true,
  },
});
```

You can also pass an object to `a11y` to customize or override specific rules provided by `eslint-plugin-jsx-a11y`:

```js
export default defineConfig({
  jsx: {
    a11y: {
      overrides: {
        // provide rule overrides using the plugin rule keys
        'jsx-a11y/anchor-is-valid': 'off',
      },
    },
  },
});
```

### Angular

To enable Angular support, install the following package:

```bash
pnpm add --save-dev angular-eslint
```

Then, update your ESLint configuration file to enable Angular:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  angular: true,
});
```

This enables the recommended rules for Angular and its template parser.

#### Customizing selectors

The eslint plugin for Angular provides two rules to enforce a consistent style for Angular component and directive selectors: `@angular-eslint/directive-selector` and `@angular-eslint/component-selector`.

By default, the configuration enforces the use of `app` as the prefix for both Angular component and directive selectors. It also recommends using an `attribute` selector type with `camelCase` style for directives, and an `element` selector type with `kebab-case` style for components.

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  angular: true,
});
```

This will enforce the following conventions:

- Directives: `<div appMyDirective></div>` (attribute selector, camelCase style)
- Components: `<app-my-component></app-my-component>` (element selector, kebab-case style)

If you want to use a different prefix, selector type, or style, you can customize it using the `angular` option.

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  angular: {
    directive: {
      type: 'attribute',
      prefix: 'ng',
      style: 'camelCase',
    },
    component: {
      type: 'element',
      prefix: 'ng',
      style: 'kebab-case',
    },
  },
});
```

This will enforce the following conventions:

- Directives: `<div ngMyDirective></div>` (attribute selector, camelCase style)
- Components: `<ng-my-component></ng-my-component>` (element selector, kebab-case style)

### NgRx

NgRx is a Reactive State Management library for Angular applications and it provides an ESLint plugin to enforce best practices while using it.

NgRx has rules for:

- Store: RxJS powered global state management for Angular apps, inspired by Redux
- Effects: Side effect model for @ngrx/store
- ComponentStore: Standalone library for managing local/component state
- Operators: Shared RxJS operators for NgRx libraries
- Signals: Reactive store and set of utilities for Angular Signals

To enable NgRx support, you need to install the `eslint-plugin-ngrx` package:

```bash
pnpm add --save-dev eslint-plugin-ngrx
```

Then enable the rules you want:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  ngrx: {
    store: true,
    effects: true,
    componentStore: true,
    operators: true,
    signals: true,
  },
});
```

### React

To enable React support, you need to install the `@eslint-react/eslint-plugin`, `eslint-plugin-react-hooks` and `eslint-plugin-jsx-a11y` packages:

```bash
pnpm add --save-dev @eslint-react/eslint-plugin eslint-plugin-react-hooks eslint-plugin-react-refresh eslint-plugin-jsx-a11y
```

Then, update your ESLint configuration file to enable the React config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  react: true,
});
```

### Next.js

To enable Next.js support, you need to install all the react plugins and the `@next/eslint-plugin-next` packages:

```bash
pnpm add --save-dev @eslint-react/eslint-plugin eslint-plugin-react-hooks eslint-plugin-react-refresh eslint-plugin-jsx-a11y @next/eslint-plugin-next
```

Then, update your ESLint configuration file to enable the react and Next.js config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  react: true,
  next: true,
});
```

This will enable the react rules and the Next.js specific rules.

### Svelte

To enable Svelte support, you need to install the `eslint-plugin-svelte` and `svelte-eslint-parser` packages:

```bash
pnpm add --save-dev eslint-plugin-svelte svelte-eslint-parser
```

Then, update your ESLint configuration file to enable the Svelte config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  svelte: true,
});
```

### Solidjs

To enable Solidjs support, you need to install the `eslint-plugin-solid` package:

```bash
pnpm add --save-dev eslint-plugin-solid
```

Then, update your ESLint configuration file to enable the Solidjs config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  solidjs: true,
});
```

### Vue

To enable Vue support, you need to install the `eslint-plugin-vue` and `vue-eslint-parser` package:

```bash
pnpm add --save-dev eslint-plugin-vue vue-eslint-parser
```

Then, update your ESLint configuration file to enable the Vue config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  vue: true,
});
```

#### Vue 2

Vue 2 has [reached EOL](https://v2.vuejs.org/eol/) and it's not recommended to use it. However, if you still want to use it, you can enable the Vue 2 config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  vue: {
    version: 2,
  },
});
```

### TanStack

[TanStack](https://tanstack.com/) provides powerful tools for building web applications.

The [@tanstack/query](https://tanstack.com/query/latest) and [@tanstack/router](https://tanstack.com/router/latest) libraries have ESLint plugins to enforce best practices while using them.

To enable TanStack Query and Router support, you need to install the `@tanstack/eslint-plugin-query` and `@tanstack/eslint-plugin-router` packages:

```bash
pnpm add --save-dev @tanstack/eslint-plugin-query @tanstack/eslint-plugin-router
```

Then enable the rules you want:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  tanstack: {
    query: true,
    router: true,
  },
});
```

### Astro

To enable Astro support, you need to install the `astro-eslint-plugin`, `astro-eslint-parser` and `eslint-plugin-jsx-a11y` package:

```bash
pnpm add --save-dev astro-eslint-plugin astro-eslint-parser eslint-plugin-jsx-a11y
```

Then, update your ESLint configuration file to enable the Astro config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  astro: true,
});
```

Astro can be integrated with other frameworks like React, Vue, Svelte, Solidjs, etc. You can enable the respective configs to lint the code of the framework.

### Testing

To enable testing support, you must enable the `test` option in the configuration. You can choose between `jest` or `vitest` and it will load the recommended rules for each testing library.

#### Testing with Jest

If you are using Jest, install the `eslint-plugin-jest` package:

```bash
pnpm add --save-dev eslint-plugin-jest
```

Then, update your ESLint configuration file to enable the Jest config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  test: {
    runner: 'jest',
  },
});
```

#### Testing with Vitest

If you are using Vitest, install the `@vitest/eslint-plugin` package:

```bash
pnpm add --save-dev @vitest/eslint-plugin
```

Then, update your ESLint configuration file to enable the Vitest config:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  test: {
    runner: 'vitest',
  },
});
```

#### Testing Library

Testing Library helps you to test UI components, so to enable it you need to install the `eslint-plugin-testing-library` package:

```bash
pnpm add --save-dev eslint-plugin-testing-library
```

Then, enable the testing library:

```js
import { defineConfig } from '@javalce/eslint-config';

export default defineConfig({
  angular: true,
  react: true,
  vue: true,
  svelte: true,
  test: {
    runner: 'vitest',
    testingLibrary: true,
  },
});
```

Testing Library will enable the recommended rules for the specific framework you are using.

## Additional configuration

This section documents helpers for composing and reusing configuration blocks: presets and mergeConfig.

### Presets

The package exports a set of presets that generate ESLint Flat Config blocks. Each preset is a function that returns an array of ESLint Flat Config objects (returned as a Promise/awaitable). You can use presets directly or compose them with `mergeConfig` or `defineConfig`.

Available presets:

| Preset       | Description                                                                                   |
| ------------ | --------------------------------------------------------------------------------------------- |
| `base`       | Base configuration with common rules and settings for JavaScript projects.                    |
| `typescript` | TypeScript-specific configuration with rules and settings for TypeScript projects.            |
| `angular`    | Angular-specific configuration with rules and settings for Angular projects.                  |
| `react`      | React-specific configuration with rules and settings for React projects.                      |
| `nextjs`     | Next.js-specific configuration with rules and settings for Next.js projects.                  |
| `astro`      | Astro-specific configuration with rules and settings for Astro projects.                      |
| `svelte`     | Svelte-specific configuration with rules and settings for Svelte projects.                    |
| `solid`      | Solidjs-specific configuration with rules and settings for Solidjs projects.                  |
| `vue`        | Vue-specific configuration with rules and settings for Vue projects.                          |
| `tanstack`   | TanStack-specific configuration with rules and settings for TanStack Query and Router.        |
| `test`       | Testing-specific configuration with rules and settings for testing frameworks (Jest, Vitest). |

Behavior and recommendations:

- Presets are designed to be composed together to build a complete ESLint configuration for your project.
- Presets are functions which return promises, so they can perform asynchronous operations if needed
- Because presets returns promises, it is recommended to use them with `mergeConfig` as it handles awaitables automatically.
- You need to include explicitly the presets you want to use in your project. For example, if you are using TypeScript and React, you need to include `base`, `typescript`, and `react` presets.
- Next.js preset includes React preset internally, so you don't need to add both when using Next.js.

Usage examples:

```js
import { presets, mergeConfig } from '@javalce/eslint-config';

// Compose presets directly with mergeConfig
export default mergeConfig(
  presets.base(),
  presets.typescript({
    type: 'lib',
  }),
  presets.react({
    jsx: { a11y: true },
  }),
);
```

You can also add custom config blocks when composing presets:

```js
import { presets, mergeConfig } from '@javalce/eslint-config';

export default mergeConfig(
  presets.base(),
  presets.typescript({
    type: 'lib',
  }),
  {
    files: ['**/*.ts'],
    rules: {
      'no-console': 'warn',
    },
  },
);
```

## Credits

- [@antfu/eslint-config](https://github.com/antfu/eslint-config) - source codes [MIT](https://github.com/antfu/eslint-config/blob/main/LICENSE)

## License

[MIT](./LICENSE) License &copy; 2024-PRESENT [Javier Valero](https://github.com/javalce)