npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eslint-config-proedis

v3.0.0

Published

Proedis ESLint flat configuration for TypeScript and React projects

Readme

eslint-config-proedis

One package, one line of config, the whole Proedis house style. No list of peer plugins to keep in sync. 🧹

npm license


✨ What's in the box

  • Two presetsbase for anything without React, react for anything with it
  • Every plugin included as a real dependency: typescript-eslint, @stylistic, eslint-plugin-import, eslint-plugin-react, eslint-plugin-react-hooks, globals, @eslint/js. You install this, and nothing else. 📦
  • The Airbnb rule decisions, vendored — the curated part, without the frozen package
  • All formatting through @stylistic, so the config survives ESLint 10 and understands TypeScript and JSX syntax instead of guessing at it
  • Composable by construction — the presets return plain flat config arrays, plus the individual blocks and the plugin instances, so nothing is a closed box 🔓

Flat config only, ESLint 9. No type aware linting: it needs a tsconfig per lint run and turns a two second lint into a full typecheck, which your build already does, and does better.

📦 Installation

yarn add --dev eslint-config-proedis eslint

That is the entire dependency list. typescript is an optional peer — you need it only if you are linting TypeScript, which you almost certainly are.

🚀 Quick start

// eslint.config.mjs
import proedis from 'eslint-config-proedis';

export default proedis.react();

Non React project? proedis.base(). Done. 🎉

🔧 Making it yours

A flat config is an array, and for any given file the last entry that matches it wins. So overriding anything is a matter of appending, and defineConfig is there to flatten whatever you pass it — nested arrays, single objects, conditionals that evaluate to nothing.

import proedis from 'eslint-config-proedis';
import tanstack from '@tanstack/eslint-plugin-query';

export default proedis.defineConfig(
  proedis.react({
    reactVersion: '19',
    ignores     : [ 'src/generated/**' ]
  }),

  // 1. relax a rule of the shared config
  { rules: { 'no-console': [ 'off' ] } },

  // 2. add a plugin of your own — installed by your project, not by this one
  {
    plugins: { '@tanstack/query': tanstack },
    rules  : { '@tanstack/query/exhaustive-deps': [ 'error' ] }
  },

  // 3. loosen something for one directory only
  {
    files: [ 'src/legacy/**' ],
    rules: { '@stylistic/max-len': [ 'off' ] }
  },

  // 4. a conditional entry: falsy entries are dropped
  process.env.CI && { rules: { 'no-console': [ 'error' ] } }
);

💡 Want to reconfigure a rule of a plugin the presets already ship? You do not need to install that plugin — it is here, exposed as proedis.plugins['@stylistic'], proedis.plugins.react, and so on. proedis.globals re-exports the globals package for the same reason.

Preset options

| Option | Default | What it does | | --- | --- | --- | | files | every JS and TS extension | The patterns to lint. This is what makes eslint . pick up .ts and .tsx at all. | | ignores | [] | Extra ignore patterns, appended to the defaults (build, dist, out, coverage, node_modules, .git, .yarn, .next, .turbo, .nx, .cache) | | defaultIgnores | true | Set it to false to start the ignore list from scratch | | globals | 'node' (base) / 'browser' (react) | A set name from the globals package, an array of them, or a raw object | | reactVersion | 'detect' | React preset only. Pin it to skip the detection. |

Composing from scratch

If the presets are not the shape you want, build your own from the blocks. They are applied in this order for a reason: the upstream recommended sets first, the Airbnb decisions on top, the Proedis adjustments last.

import proedis from 'eslint-config-proedis';

export default proedis.defineConfig(
  proedis.configs.ignores(),
  proedis.configs.files(),
  proedis.configs.languageOptions('node'),

  proedis.configs.javascript,               // eslint recommended
  proedis.configs.imports,                  // import plugin recommended
  proedis.configs.typescript,               // typescript-eslint recommended

  proedis.configs.airbnb,                   // the vendored Airbnb decisions

  proedis.configs.typescriptCoreOverrides,  // core rules the compiler already enforces, off again
  proedis.configs.importOverrides,
  proedis.configs.style,                    // the Proedis house style
  proedis.configs.typescriptOverrides
);

There is also proedis.configs.commonjs(patterns), for the paths you know are CommonJS — a linter reading one file at a time cannot tell, since a .js file's module system comes from the nearest package.json:

proedis.configs.commonjs([ 'scripts/**/*.js' ])

🎨 The house style, in one table

The parts you will actually notice, all of them enforced:

| | | | --- | --- | | Indentation | 2 spaces, with decorators and type unions left alone | | Braces | Stroustrup — } on its own line, else below it | | Arrays | spaces inside brackets: [ 'a', 'b' ] | | Objects | colons aligned by handkey-spacing is off precisely so you can | | Line length | 130 columns; strings, template literals, URLs and regexes exempt | | Trailing commas | never | | Blank lines | at most two in a row | | Type imports | import type required | | console | console.error only | | Underscore prefix | allowed everywhere — it is the marker for anything private |

🧠 Three decisions worth knowing about

Formatting comes from @stylistic, not from ESLint core. Core deprecated every formatting rule in 9 and removed them in 10, and @typescript-eslint dropped its own copies in v8. The @stylistic ports are the maintained path, and they also see TypeScript: semi checks a type alias declaration, indent handles a conditional type, operator-linebreak inspects a union. Which means they report things the core rules never looked at.

Airbnb is vendored, not depended on. eslint-config-airbnb-base never shipped a flat config, and its manifest still declares a peer dependency on ESLint 7 or 8 — which npm treats as an ERESOLVE failure, not a warning, next to a current ESLint. Its rule decisions are still good, so they live here under lib/airbnb, regenerated with yarn rules:sync, with the formatting half remapped to @stylistic and two rules ESLint has since deleted dropped.

Some rules the compiler already enforces are switched off — deliberately, and after the Airbnb layer, because whichever entry comes last wins. typescript-eslint publishes exactly this list, and leaving it on means every DOM type used in a type position is reported as an undefined variable.

🔀 Migrating from 2.x

Version 2 was an eslintrc config. This is a flat config, so the shape of your project's setup changes:

| Then | Now | | --- | --- | | .eslintrc.js with extends: [ 'proedis' ] | eslint.config.mjs with export default proedis.react() | | extends: [ 'proedis/base' ] | export default proedis.base() | | .eslintignore | the ignores option, or an { ignores: [ … ] } entry | | eslint --ext .ts,.tsx . | eslint . — the --ext flag was removed in ESLint 9 | | ESLint 8, @typescript-eslint 6 | ESLint 9, typescript-eslint 8 | | plugins installed by your project | plugins installed by this package |

Two things to grep for afterwards:

  1. eslint-disable comments naming a formatting rule. // eslint-disable-next-line max-len no longer suppresses anything, because the active rule is now @stylistic/max-len. ESLint points every one of them out for you as an unused disable directive — rename them and the warnings go.
  2. @typescript-eslint/indent, @typescript-eslint/brace-style and friends in your own overrides. Those rules were removed in typescript-eslint v8; use the @stylistic/ versions.

⚠️ Version 2 extended eslint-config-airbnb-typescript/base, which carries only the TypeScript overrides and not the Airbnb rule sets themselves. So v2 never actually applied the Airbnb decisions, and this is the first version that does. Expect real findings on a codebase that was "clean" under v2 — eslint . --fix handles most of them.

🤝 Compatibility

| Requirement | Range | | --- | --- | | eslint | >=9.0.0 <10.0.0 (peer) | | typescript | >=5.2.0 (optional peer) | | Config format | flat config only — eslint.config.mjs / .js / .ts |

ESLint 10 is not supported yet, and the reason is not this config: eslint-plugin-react and eslint-plugin-import still cap their peer range at ESLint 9. Everything else here already accepts 10, and because the formatting rules come from @stylistic rather than from a core that removed them, that upgrade will be a dependency bump.

📄 License

MIT © Proedis S.r.l.