Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Setup Node.js and Yarn
uses: actions/setup-node@v4
with:
node-version: '18'
node-version: '22'

- uses: actions/cache@v4
id: cache
Expand Down
201 changes: 63 additions & 138 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# @callstack/eslint-config

Callstack ESLint config for React Native, React and Node.js projects, utilizing Flow, TypeScript, Prettier and Jest with sensible defaults. Supports both eslintrc and flat config.
Callstack ESLint config for React Native, React and Node.js projects, utilizing TypeScript, Prettier and Jest with sensible defaults.

Starting with v16 this package ships **flat config only** (`eslint.config.*`). The legacy eslintrc format is no longer supported.

## Requirements

- ESLint `^10.0.0`
- Node.js `^22.13.0` or `>=24.3.0`

## Installation

Expand All @@ -12,30 +19,26 @@ yarn add --dev eslint @callstack/eslint-config

Or with npm:

```
```bash
npm install --save-dev eslint @callstack/eslint-config
```

## Usage

You can choose one of the following environments to work with by extending your ESLint config (`eslint.config.mjs` for flat config, or `.eslintrc` / `eslintConfig` field in `package.json` for the eslintrc config style) with `@callstack` config tailored to your project.
Pick the config that matches your project and spread it into your `eslint.config.mjs`:

### React Native config

Usage:
| Config | Import path |
| ------------ | -------------------------------- |
| React Native | `@callstack/eslint-config` |
| React | `@callstack/eslint-config/react` |
| Node.js | `@callstack/eslint-config/node` |

#### eslintrc format (ESLint < v9)
`@callstack/eslint-config/react-native` is an alias for the root import.

```json
{
"extends": "@callstack"
}
```

#### flat config format (`eslint.config.mjs`, ESLint 9+)
### React Native config

```js
import callstackConfig from '@callstack/eslint-config/react-native.flat.js';
import callstackConfig from '@callstack/eslint-config';

export default [
{
Expand All @@ -52,179 +55,101 @@ export default [
];
```

Plugins used:
Includes everything from the **React config**, plus:

- **React config**
- [eslint-plugin-react-native](https://yarnpkg.com/en/package/eslint-plugin-react-native)
- [eslint-plugin-react-native-a11y](https://classic.yarnpkg.com/en/package/eslint-plugin-react-native-a11y)
- [eslint-plugin-react-native](https://www.npmjs.com/package/eslint-plugin-react-native)
- [eslint-plugin-react-native-a11y](https://www.npmjs.com/package/eslint-plugin-react-native-a11y)
- [@react-native/eslint-plugin](https://www.npmjs.com/package/@react-native/eslint-plugin)

Additionally, it sets `"react-native/react-native"` environment and native platform extensions to resolve.
Additionally, it adds React Native globals and resolves platform-specific extensions (`.ios.*`, `.android.*`, `.native.*`).

### React config

Usage:

#### eslintrc format (ESLint < v9)

```json
{
"extends": "@callstack/eslint-config/react"
}
```

#### flat config format (`eslint.config.mjs`, ESLint 9+)

```js
import callstackConfigReact from '@callstack/eslint-config/react.flat.js';
import callstackConfig from '@callstack/eslint-config/react';

export default [
{
ignores: [
// ignored files go here
],
},
...callstackConfigReact,
{
rules: {
// your custom rules
},
},
];
export default [...callstackConfig];
```

Plugins used:
Includes everything from the **Node.js config**, plus:

- **Node config**
- [eslint-plugin-react](https://yarnpkg.com/en/package/eslint-plugin-react)
- [eslint-plugin-react-hooks](https://yarnpkg.com/en/package/eslint-plugin-react-hooks)
- [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react)
- [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks)

### Node config

Usage:

#### eslintrc format (ESLint < v9)

```json
{
"extends": "@callstack/eslint-config/node"
}
```
Additionally, it adds browser globals.

#### flat config format (`eslint.config.mjs`, ESLint 9+)
### Node.js config

```js
import callstackConfigNode from '@callstack/eslint-config/node.flat.js';
import callstackConfig from '@callstack/eslint-config/node';

export default [
{
ignores: [
// ignored files go here
],
},
...callstackConfigNode,
{
rules: {
// your custom rules
},
},
];
export default [...callstackConfig];
```

Plugins used:
Includes:

- [eslint-config-prettier](https://yarnpkg.com/en/package/eslint-config-prettier)
- [eslint-plugin-prettier](https://yarnpkg.com/en/package/eslint-plugin-prettier)
- [eslint-plugin-jest](https://yarnpkg.com/en/package/eslint-plugin-jest) (applied for tests only, based on Jest's `testMatch` config)
- [eslint-plugin-import](https://yarnpkg.com/en/package/eslint-plugin-import)
- [eslint-plugin-promise](https://yarnpkg.com/en/package/eslint-plugin-promise)
- [eslint-plugin-flowtype](https://yarnpkg.com/en/package/eslint-plugin-flowtype)
- [@typescript-eslint/eslint-plugin](https://yarnpkg.com/en/package/@typescript-eslint/eslint-plugin) (only for `.tsx?` files)
- [@typescript-eslint/parser](https://yarnpkg.com/en/package/@typescript-eslint/parser) (only for `.tsx?` files)
- [@eslint/js](https://www.npmjs.com/package/@eslint/js) recommended rules
- [eslint-config-prettier](https://www.npmjs.com/package/eslint-config-prettier) and [eslint-plugin-prettier](https://www.npmjs.com/package/eslint-plugin-prettier)
- [eslint-plugin-import-x](https://www.npmjs.com/package/eslint-plugin-import-x)
- [eslint-plugin-promise](https://www.npmjs.com/package/eslint-plugin-promise)
- [eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest) (applied for tests only, based on Jest's default `testMatch`)
- [@typescript-eslint/eslint-plugin](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin) and [@typescript-eslint/parser](https://www.npmjs.com/package/@typescript-eslint/parser) (only for `.ts`/`.tsx` files)

Additionally, it sets `es6` and `node` environments.
Additionally, it adds Node.js globals.

### Example of extending the configuration
### Extending the configuration

##### eslintrc format (ESLint < v9)

```json
{
"extends": "@callstack",
"rules": {
"global-require": 0,
"prefer-destructuring": 0
}
}
```

##### flat config format (`eslint.config.mjs`, ESLint 9+)
Append your own config objects after the Callstack config:

```js
import callstackConfig from '@callstack/eslint-config/react-native.flat.js';
import callstackConfig from '@callstack/eslint-config';

export default [
...callstackConfig,
{
rules: {
'global-require': 0,
'prefer-destructuring': 0,
'global-require': 'off',
'prefer-destructuring': 'off',
},
},
];
```

### TypeScript

TypeScript is supported out-of-the-box, including importing JS files from TS files and vice-versa. All you need to do is to make sure you have [`typescript`](https://yarnpkg.com/en/package/typescript) module installed.

Then when running ESLint add `--ext '.js,.ts'` (you might need also `.jsx, .tsx`) option, for example:

```bash
yarn eslint --ext '.js,.ts' ./src
```

`parserOptions.project` is set to `./tsconfig.json`. You may need to [adjust that](https://typescript-eslint.io/architecture/parser#project).

To do so, you'll need to override our setup for TS files in your ESLint config:

##### eslintrc format (ESLint < v9)
TypeScript is supported out of the box, including importing JS files from TS files and vice versa. Make sure you have [`typescript`](https://www.npmjs.com/package/typescript) installed.

```json
{
"overrides": [
{
"files": ["*.ts", "*.tsx"],
"parserOptions": {
"project": "./packages/**/tsconfig.json"
}
}
]
}
```

##### flat config format (`eslint.config.mjs`, ESLint 9+)

In the flat config, just append another configuration object to the array and be sure to import the `/react-native.flat` file:
Type-aware rules use the typescript-eslint [project service](https://typescript-eslint.io/packages/parser#projectservice) (`parserOptions.projectService: true`), which finds the nearest `tsconfig.json` for each linted file. This works in monorepos without extra setup. To customize it, override the parser options for TS files:

```js
import callstackConfig from '@callstack/eslint-config/react-native.flat.js';
import tsEslintParser from '@typescript-eslint/parser';
import callstackConfig from '@callstack/eslint-config';

export default [
...callstackConfig,
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: tsEslintParser,
parserOptions: { project: './packages/**/tsconfig.json' },
parserOptions: {
tsconfigRootDir: import.meta.dirname,
},
},
},
];
```

#### VSCode
## Migrating from v15

- **eslintrc is no longer supported.** Move your `.eslintrc*` / `eslintConfig` setup to `eslint.config.mjs` (see the [ESLint migration guide](https://eslint.org/docs/latest/use/configure/migration-guide)).
- **Import paths.** Use `@callstack/eslint-config`, `@callstack/eslint-config/react` and `@callstack/eslint-config/node`. The old `*.flat.js` paths still work as aliases.
- **`eslint-plugin-import` → `eslint-plugin-import-x`.** Rename `import/*` rules to `import-x/*` in your overrides and `eslint-disable` comments.
- **Flow is no longer supported.** `eslint-plugin-flowtype` and `@babel/eslint-parser` were removed; `.js`/`.jsx` files are now parsed by ESLint's default parser (espree). Remove `flowtype/*` rules from your config. If you still need Flow, add [`hermes-eslint`](https://www.npmjs.com/package/hermes-eslint) and [`eslint-plugin-ft-flow`](https://www.npmjs.com/package/eslint-plugin-ft-flow) yourself.
- **TypeScript** now uses `projectService` instead of `project: './tsconfig.json'`.
- **ESLint 10** is required. Since ESLint 8 and 9 were deprecated.
- **Node.js `^22.13.0` or `>=24.3.0`** is required.

## VSCode

If you're VSCode user, you may find adding this config to your `.vscode/settings.json` helpful:
If you're a VSCode user, you may find adding this config to your `.vscode/settings.json` helpful:

```json
{
Expand Down
2 changes: 1 addition & 1 deletion extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const JS = ['.js', '.jsx'];
const TS = ['.ts', '.tsx', '.d.ts'];

function generateExtensionsForPlatform(baseExts, platform) {
return baseExts.map(ext => `.${platform}${ext}`);
return baseExts.map((ext) => `.${platform}${ext}`);
}

const JS_REACT_NATIVE = [
Expand Down
Loading
Loading