npm package: @friendsoftheweb/eslint-plugin
Description: ```bash yarn add -D @friendsoftheweb/eslint-plugin ```
Latest version: 0.0.5

# @friendsoftheweb/eslint-plugin

## Installation

```bash
yarn add -D @friendsoftheweb/eslint-plugin
```

## Rules

### Recommended Rules

#### `friendsoftheweb/ban-chalk`

Enforces using `styleText` from `node:util` instead of the `chalk` package.

This rule helps remove the `chalk` dependency by replacing it with the built-in
`styleText` utility available in Node.js 20+.

##### Examples

❌ **Incorrect:**

```javascript
import chalk from 'chalk';

chalk.red('error');
chalk.bold.red('error');
```

✅ **Correct:**

```javascript
import { styleText } from 'node:util';

styleText('red', 'error');
styleText(['bold', 'red'], 'error');
```

**Note:** This rule provides automatic fixes for default imports and most
usages. Chained styles (e.g. `chalk.bold.red`) are converted to an array of
formats. Named imports (e.g. `import { red } from 'chalk'`) are flagged but
require manual migration.

#### `friendsoftheweb/ban-lodash-import`

Enforces importing functions from `lodash-es` instead of `lodash`.

This rule helps ensure tree shaking works properly by preferring ES module
imports from `lodash-es` over CommonJS imports from `lodash`.

##### Examples

❌ **Incorrect:**

```javascript
import _ from 'lodash';
import { map } from 'lodash';
import debounce from 'lodash/debounce';
```

✅ **Correct:**

```javascript
import { map } from 'lodash-es';
import debounce from 'lodash-es/debounce';
```

**Note:** This rule provides automatic fixes for most cases, except for
`lodash/fp` imports which require manual migration.

#### `friendsoftheweb/css-module-class-exists`

Enforces that class names used from an imported CSS module exist in the module
file.

#### `friendsoftheweb/css-module-name-matches`

Enforces that a CSS module's filename matches the filename of the importing
file.

This rule ensures consistent naming conventions by requiring CSS module files to
have the same base name as the file importing them.

#### `friendsoftheweb/valid-server-actions-path`

Enforces server actions are exported from file paths that match
`app/**/_actions.ts` or `app/**/_actions/**/*.ts`.

This rule helps maintain a consistent file structure for Next.js server actions
by ensuring they are placed in designated locations.

### Future Rules

#### `friendsoftheweb/react-named-func-components`

Enforces using named functions when defining React components instead of arrow
functions. Component definitions that are wrapped in a function call (e.g.
`forwardRef()`) are allowed to use arrow functions.

This rule promotes better debugging and development experience by ensuring React
components are defined as named functions, which provide clearer stack traces
and better display names in React DevTools.

##### Examples

❌ **Incorrect:**

```tsx
const Button: FC<PropsWithChildren> = (props) => {
  const { children } = props;

  return <button>{children}</button>;
};
```

✅ **Correct:**

```tsx
function Button(props: PropsWithChildren) {
  const { children } = props;

  return <button>{children}</button>;
}
```

```tsx
const Button = forwardRef<HTMLButtonElement, PropsWithChildren>(
  (props, ref) => {
    const { children } = props;

    return <button ref={ref}>{children}</button>;
  },
);

Button.displayName = 'Button';
```

## Example Configurations

### Recommended Configuration

```javascript
import friendsOfTheWeb from '@friendsoftheweb/eslint-plugin';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';

export default defineConfig([
  { ignores: ['.yarn/**/*'] },
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    extends: [
      tseslint.configs.recommended,
      friendsOfTheWeb.configs['flat/recommended'],
    ],
  },
]);
```

#### Recommended Configuration with React

```javascript
import friendsOfTheWeb from '@friendsoftheweb/eslint-plugin';
import react from 'eslint-plugin-react';
import reactCompiler from 'eslint-plugin-react-compiler';
import reactHooks from 'eslint-plugin-react-hooks';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';

export default defineConfig([
  { ignores: ['.yarn/**/*'] },
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    extends: [
      tseslint.configs.recommended,
      react.configs.flat.recommended,
      react.configs.flat['jsx-runtime'],
      reactHooks.configs.flat.recommended,
      reactCompiler.configs.recommended,
      friendsOfTheWeb.configs['flat/recommended'],
    ],
    settings: {
      react: {
        version: 'detect',
      },
    },
  },
]);
```

#### Gradual Adoption

There is an additional configuration that makes it easier to adopt this plugin
by only warning about violations.

```javascript
import friendsOfTheWeb from '@friendsoftheweb/eslint-plugin';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';

export default defineConfig([
  { ignores: ['.yarn/**/*'] },
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    extends: [
      tseslint.configs.recommended,
      friendsOfTheWeb.configs['flat/migrate'],
    ],
  },
]);
```

### Future Configuration

This configuration includes all of the [recommended rules](#recommended-rules)
and [additional rules](#future-rules) that will be considered violations in the
future.

Future rule violations are considered warnings with this configuration.

```javascript
import friendsOfTheWeb from '@friendsoftheweb/eslint-plugin';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';

export default defineConfig([
  { ignores: ['.yarn/**/*'] },
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    extends: [
      tseslint.configs.recommended,
      friendsOfTheWeb.configs['flat/future'],
    ],
  },
]);
```