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

@bastidood/eslint-plugin-slopstopper

v0.6.0

Published

Custom lint rules against sloppy code, for both Oxlint and ESLint.

Readme

@bastidood/eslint-plugin-slopstopper

Custom lint rules against sloppy code. One plugin runs in both Oxlint (as a JS plugin) and ESLint.

Installation

pnpm add --save-dev @bastidood/eslint-plugin-slopstopper

@bastidood/oxlint-config/core and @bastidood/eslint-config/core enable these rules. Install the plugin next to them.

Rules

Rules marked as derived from anti-slop are vendored from dmmulroy/anti-slop under the MIT License. THIRD-PARTY-NOTICES.md lists them with the license text.

| Rule | Reports | | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | stepdown-order | A function or method declared above a function or statement in the same scope that uses it; autofixes the order | | no-private-modifier | The TypeScript private modifier; autofixes to #private members | | handle-or-rethrow | A catch that swallows the error, logs and rethrows it, or leaves it unbound | | needless-type-intersection | A type alias of object intersections that can be an interface ... extends | | no-inferrable-return-type | An explicit return type that TypeScript can infer; suggests removing it | | no-type-predicates | is and asserts type predicates, which TypeScript does not check | | no-positional-scalars | Too many positional parameters of one scalar kind (two booleans or three of another kind by default) | | no-multiple-optional-parameters | Two or more optional parameters | | prefer-switch | An if chain of two or more === comparisons against the same value | | no-equality-chain | An \|\| chain of two or more === comparisons against the same value that no prefer-switch chain claims | | prefer-de-morgan | A logical chain that De Morgan's law rewrites with fewer negations, where another rule then removes the outer !; autofixes the rewrite | | no-negated-group | A ! applied to an && or \|\| group, outside the positions that prefer-de-morgan owns; autofixes with De Morgan's law | | no-negated-quantifier-callback | A .some or .every callback that returns !p; rewrites to the dual quantifier with one ! outside the call, autofixed where types prove the standard method | | merge-exclusive-branches | Two adjacent if statements whose tests split on one condition and its negation; autofixes the merge into one if-else where safe | | prefer-typeof-undefined | A === or !== comparison against undefined or void 0; autofixes to typeof x === 'undefined' | | no-temporary-access | A field read off the unnamed result of a call, as in f().x; autofixes to a const destructuring where safe | | no-plain-template-literal | An untagged template literal without expressions on one line; autofixes to a quoted string | | no-alias-object-type | An object type literal nested in a type alias, other than the alias's whole type or a needless-type-intersection report | | prefer-class-over-factory | A module-level function whose every return is an object literal with a function-valued member | | prefer-prefix-increment | x += 1, x -= 1, or a postfix update whose value is discarded; autofixes to ++x or --x where x is proven to be a number | | prefer-while-true | A for (;;) loop; autofixes to while (true) | | destructure-on-sight | A parameter or const whose every use reads a static property off it; suggests destructuring it at the binding | | no-array-filter-map | A .filter(…).map(…) or .map(…).filter(…) chain on a known array, which walks the elements twice (derived from anti-slop) | | no-reduce-accumulator-copy | A copy of the .reduce accumulator with Object.assign, Array.from, or an array copy method on every step (derived from anti-slop) | | no-conditional-empty-object-spread | An object spread of a conditional with an empty object branch, as in ...(c ? { v } : {}) (derived from anti-slop) | | no-known-value-widening | An explicit type or assertion that discards the known type of a value, such as unknown, object, or an open dictionary; suggests satisfies for as (derived from anti-slop) | | no-unknown-returns | An explicit return type that resolves to unknown or Promise<unknown> (derived from anti-slop) | | no-unknown-type-aliases | A type alias that resolves to unknown (derived from anti-slop) | | no-unsafe-dictionary-type | A dictionary type whose value type is unknown, any, object, {}, or a union or alias that holds one (derived from anti-slop) | | no-untyped-empty-initializer | A binding without an annotation that has no initializer or starts as [], {}, or null, a new Map(), new WeakMap(), or new Set() without type arguments, or an assertion on an empty literal | | prefer-query-key-context | A TanStack Query queryFn that captures a value its sibling queryKey also holds, instead of reading it from the query function context | | no-defaulted-query-key | A ??, \|\|, or defaulted binding in a TanStack Query queryKey, which shares a cache entry with a real value | | no-standalone-mutate-async | A TanStack Query mutateAsync outside a Promise.all, allSettled, race, or any of concurrent mutations, tracked through renames and aliases | | no-mutate-callback-cache-update | A QueryClient cache update in the per-call callbacks of a TanStack Query mutate, tracked through renames and aliases | | prefer-table-atoms | A TanStack Table table.store snapshot or raw use, a store selector that reads one slice, a React useSelector on the store that returns a fresh literal without compare, a Svelte useSelector on the store, or a table.Subscribe without source or selector; suggests the slice atom | | require-table-state-pairs | A TanStack Table state slice without its on<Slice>Change handler, or a handler without its slice | | no-render-scoped-table-schema | A TanStack Table tableFeatures, createColumnHelper, or helper.columns call inside a component, hook, or Svelte instance script | | require-exclusive-indeterminate | A TanStack Table getIsSomeRowsSelected() indeterminate value without && !getIsAllRowsSelected(); suggests the exclusion |

Compatibility

  • Every rule uses the ESLint rule API, so the same rule runs in Oxlint and ESLint.
  • The plugin is typed for Oxlint. In ESLint, use the rules through @bastidood/eslint-config, which registers the plugin for you.
  • Rules check syntax only by default. Where a rule benefits from type information, it uses it when the linter provides TypeScript's program (typescript-eslint's parserServices), and falls back to syntax otherwise. Oxlint's JS plugins do not provide type information, so the same code can pass Oxlint and still fail ESLint with typescript-eslint.

Configuration

no-positional-scalars reports a signature once any scalar kind reaches its threshold of positional parameters. The defaults are { boolean: 2, string: 3, number: 3, bigint: 3, symbol: 3 }; each threshold is at least 2:

{ 'slopstopper/no-positional-scalars': ['error', { string: 2 }] }

Limitations

  • Apart from the no-positional-scalars thresholds, rules are not configurable.