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

biome-plugin-payload

v0.1.4

Published

Biome lint plugin (GritQL) that enforces Payload CMS best practices on Local API calls

Readme

biome-plugin-payload

Biome lint plugin (GritQL) that enforces Payload CMS best practices on Local API calls — so code written by hand or generated by AI agents is caught by biome check instead of manual review.

Rules

| Rule | What it catches | Severity | | --- | --- | --- | | no-find-without-select | payload.find / payload.findByID / payload.findGlobal / payload.findVersions / payload.findVersionByID calls that do not pass a select object, causing more fields than needed to be fetched from the database | error | | no-find-without-depth | The same read operations that do not set depth explicitly — omitting it uses the application default (1), silently populating one level of relationships | error | | no-missing-override-access | Any Local API call that does not declare overrideAccess explicitly — the Local API bypasses access control by default (overrideAccess: true) | error | | prefer-explicit-populate | Read operations with depth > 0 (numeric literal) that do not pass a populate object, so populated related documents return more fields than intended | error | | require-user-with-override-false | Any Local API call with overrideAccess: false that does not pass user, req, or user: null — without a user object, access control functions receive undefined and behave unpredictably | error |

All rules match any receiver that is the identifier payload or a member expression ending in .payload (e.g. req.payload, this.payload).

prefer-explicit-populate is a heuristic: it only fires when depth is a positive numeric literal (depth: 2). Shorthand (depth) and computed values (depth: opts?.depth ?? 0) cannot be verified statically and are skipped. If the target collection defines defaultPopulate in its config, Payload already limits which fields are returned during population — suppress the diagnostic in that case with a biome-ignore comment.

Install

npm install --save-dev biome-plugin-payload
# or
bun add -d biome-plugin-payload
# or
pnpm add -D biome-plugin-payload

Enable

Add each rule to the plugins array in your biome.json or biome.jsonc. Paths must be the literal path to the .grit file — Biome does not resolve plugin entries by package name.

// biome.jsonc
{
  "plugins": [
    "./node_modules/biome-plugin-payload/rules/no-find-without-select.grit",
    "./node_modules/biome-plugin-payload/rules/no-find-without-depth.grit",
    "./node_modules/biome-plugin-payload/rules/no-missing-override-access.grit",
    "./node_modules/biome-plugin-payload/rules/prefer-explicit-populate.grit",
    "./node_modules/biome-plugin-payload/rules/require-user-with-override-false.grit"
  ]
}

Each file becomes one rule named after the file, in the plugin group (e.g. lint/plugin/no-find-without-select).

Intentional Anonymous Access (overrideAccess: false)

When making an intentional anonymous query in public Server Components (where no user or req session exists), pass user: null explicitly to communicate unauthenticated access without needing biome-ignore:

// Explicit unauthenticated query — access control functions run with user = null
const pages = await payload.find({
  collection: "pages",
  overrideAccess: false,
  user: null,
});

Suppress an intentional violation

// biome-ignore lint/plugin/no-find-without-select: full document intentionally needed here
const post = await payload.find({ collection: "posts" });

// biome-ignore lint/plugin/prefer-explicit-populate: collection defines defaultPopulate
const post = await payload.find({ collection: "posts", depth: 1, select: { title: true } });

Known limitations

  • Only calls whose argument is an object literal without spread are analyzed. payload.find(args) and payload.find({ ...base }) are skipped because the keys cannot be verified statically.
  • payload.db.* direct-database calls are intentionally not covered.
  • prefer-explicit-populate only fires when depth is a positive numeric literal — variable or computed depth values are skipped.
  • The Biome CLI does not support --only for individual plugin rules. Use --only=plugin to run all plugin rules, or a temporary config with a single plugin entry to isolate one rule.

Development

git clone https://github.com/erikenz/biome-plugin-payload
cd biome-plugin-payload
bun install
bun test

Rules are plain GritQL files in rules/. Tests in test/plugin.test.ts run biome lint against fixtures in test/fixtures/ and assert the emitted diagnostics. Fixtures violating a rule produce expected diagnostics; negative fixtures must produce zero diagnostics.

Roadmap

  • no-top-level-get-payload — getPayload() must not be called at module top level
  • no-hook-query-without-req — nested Local API calls inside hooks must pass req
  • no-query-without-limit-on-slug — unique-field lookups (where: { slug: { equals } }) should use limit: 1 + pagination: false