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

@bsuite/dry-lint

v0.4.0

Published

ESLint plugin enforcing BSuite one-shot architecture (single-owner Supabase entity tables) and the OAuth callback bridge contract.

Readme

@bsuite/dry-lint

ESLint flat-config plugin that enforces the BSuite one-shot architecture — every Supabase entity table has a single canonical owner app, and other apps may READ but never WRITE to it.

The plugin currently ships one rule:

| Rule | Purpose | |------|---------| | bsuite/no-cross-app-write | Errors when an app calls .from('<table>').{insert,update,upsert,delete}() against a table owned by a different app per the ownership map. |

The ownership map lives at src/ownership-map.json and is sourced from docs/20260227-dry-one-shot-architecture-v1.01A.md §1 plus the V5–V10 findings in docs/20260423-cross-app-write-audit-v1.00W.md.


Install

pnpm add -D @bsuite/dry-lint

The plugin is ESLint v9 flat-config compatible. It declares eslint >=9 as a peer dependency.


Usage

Recommended — one-line wire-up

// eslint.config.ts
import bsuiteDryLint from '@bsuite/dry-lint';

export default [
  bsuiteDryLint.configs.recommended, // bsuite/no-cross-app-write: error
  // ...rest of your config
];

Warn-only (useful during phased rollout)

import bsuiteDryLint from '@bsuite/dry-lint';

export default [
  bsuiteDryLint.configs.warn, // bsuite/no-cross-app-write: warn
];

Manual wiring with options

import bsuiteDryLint from '@bsuite/dry-lint';

export default [
  {
    plugins: { bsuite: bsuiteDryLint },
    rules: {
      'bsuite/no-cross-app-write': [
        'error',
        {
          // Override the auto-detected app (default: inferred from file path)
          appOverride: 'crm7',
          // Also report writes to tables not in the ownership map (default: false)
          warnOnUnknownTable: true,
        },
      ],
    },
  },
];

How app detection works

The rule needs to know which app a file belongs to so it can compare against the ownership map. Detection walks the file's absolute path looking for the first directory segment matching one of:

| Segment | App key | |---------|---------| | business-suite-unified, bsu | bsu | | crm7 | crm7 | | conduit | conduit | | braden | braden | | R80.3, r80, r8 | r80 | | throughput | throughput |

If no segment matches (e.g. when linting packages/theme/src/), the rule no-ops on that file.

You can override detection per-config-block via the appOverride option.


How write detection works

The rule walks the AST for any call expression where the callee is a member access ending in one of insert, update, upsert, or delete. It then walks back along the query-builder chain until it finds the closest .from('<literal>') call and resolves the table name.

The chain walk handles:

  • Direct calls — supabase.from('x').insert(...)
  • Chained query-builder calls — supabase.from('x').select('*').eq('id', 1).update(...)
  • await-wrapped calls
  • Calls preceded by any number of intermediate .from()-irrelevant query methods

It does NOT report:

  • Reads (.select(...))
  • Calls where the table name is a non-literal expression (e.g. a variable). This is intentional — we'd rather miss a few cases than spam false positives.
  • Calls in files outside any known app.

Adding a new table to the ownership map

Each entry uses EXACTLY ONE of owner (single canonical write surface) or writers (multi-writer admin co-ownership, @bsuite/[email protected]+). Setting both is a schema error.

Single-owner entry (most common)

  1. Open src/ownership-map.json.

  2. Add an entry under tables:

    {
      "tables": {
        "your_new_table": {
          "owner": "crm7",        // one of: bsu, crm7, conduit, braden, r80, throughput, shared, all
          "readers": ["bsu"],     // apps that may .select() but never write
          "$comment": "Optional context, e.g. audit reference."
        }
      }
    }
  3. Use "shared" if the table is co-owned by 2+ apps with a documented audit-trail / append-only pattern (e.g. wage_calculation_snapshots).

  4. Use "all" for explicit event-sink tables (e.g. bi_metrics).

Multi-writer entry (PHASE-3c, v0.2.0+)

For admin-CRUD tables co-owned by an explicit allow-list of apps (e.g. tenants + user_tenants, where BSU is the platform owner and CRM7's tenant-management edge function performs legitimate org-admin operations under RLS):

{
  "tables": {
    "your_co_owned_table": {
      "writers": ["bsu", "crm7"],   // explicit allow-list — at least one app
      "readers": ["r80", "conduit"], // apps that may .select() only
      "$comment": "Why this is multi-writer rather than single-owner."
    }
  }
}

The rule will pass writes from any listed app and flag writes from non-listed apps with a crossAppWriteMultiWriter message.

Versioning

Bump the @bsuite/dry-lint version (patch for new tables, minor for owner moves or schema additions) and republish.


Owner keys

| Key | App | Repo | |-----|-----|------| | bsu | business-suite-unified | business-suite-unified/ | | crm7 | CRM7 | crm7/ | | conduit | Conduit (recruitment ATS) | conduit/ | | braden | braden.com.au corporate site | braden/ | | r80 | R80.3 wage calculator | R80.3/ | | throughput | Throughput (idea management) | throughput/ | | shared | Co-owned by multiple apps (audit-trail / append-only) | n/a | | all | Event sink — any app may write | n/a |


Known violations and enforcement posture

Consumer apps should wire bsuite/no-cross-app-write as error. Pre-existing legacy write paths must be isolated with narrow per-file overrides in the consumer ESLint config; do not keep the base rule in warn-mode.

The 2026-04-27 Phase 2D promotion moved BSU, CRM7, Conduit, R80.3, Braden, and Throughput to error-level enforcement while preserving documented exception sets for the Phase 5 ownership-relocation work.

Run the dry-run helper after ownership-map edits to identify any exception list that can be removed:

pnpm --filter @bsuite/dry-lint build
node packages/dry-lint/scripts/dry-run.mjs

Development

# Install (use --ignore-workspace until package is added to pnpm-workspace.yaml)
cd packages/dry-lint && pnpm install --ignore-workspace

# Build
pnpm build

# Run tests
pnpm test