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

@biref/scanner

v0.2.0

Published

Paradigm-agnostic database introspection and typed query builder. Bidirectional reference detection, codegen-driven autocomplete, and Prisma-style fluent queries against any table the scanner finds.

Readme

@biref/scanner

CI Node TypeScript License

Scan any database, inspect every relationship in both directions, generate a typed schema, and write Prisma-style fluent queries with fully hydrated nested results. Zero runtime dependencies.

Supported adapters

| Adapter | Driver | Status | | --- | --- | --- | | Postgres | pg | Stable | | MySQL / MariaDB | mysql2 | Stable |

Install

# Postgres
pnpm add @biref/scanner pg

# MySQL
pnpm add @biref/scanner mysql2

Quick start

Postgres

import pg from 'pg';
import { Biref, postgresAdapter } from '@biref/scanner';
import type { BirefSchema } from './biref/biref.schema';

const client = new pg.Client({ connectionString: 'postgres://localhost/mydb' });
await client.connect();

const biref = Biref.builder()
  .withAdapter(postgresAdapter.create(client))
  .build();

const model = await biref.scan({ namespaces: 'all' });

const rows = await biref
  .query<BirefSchema>(model)
  .public.users
  .select('id', 'email')
  .where('status', 'eq', 'active')
  .include('orders', (order) =>
    order
      .select('id', 'total')
      .include('order_items', (item) => item.select('variant_id', 'quantity')),
  )
  .findMany();

MySQL

import mysql from 'mysql2/promise';
import { Biref, mysqlAdapter } from '@biref/scanner';
import type { BirefSchema } from './biref/biref.schema';

const connection = await mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'secret',
  database: 'mydb',
});

const biref = Biref.builder()
  .withAdapter(mysqlAdapter.create(connection))
  .build();

const model = await biref.scan();

const rows = await biref
  .query<BirefSchema>(model)
  .mydb.users
  .select('id', 'email')
  .where('is_active', 'eq', 1)
  .include('orders', (order) => order.select('id', 'total'))
  .findMany();

What makes it different

Most introspection tools only surface the foreign keys an entity declares. @biref/scanner walks the graph once and attaches relationships in both directions:

  • outbound: this entity holds the FK pointing outward
  • inbound: another entity holds a FK pointing here
// Who references users?
const incoming = model.inboundRelationshipsOf('public', 'users');
// -> orders, invoices, sessions, api_keys, ...

// The query builder exposes both directions under friendly names.
// .include('orders', ...) on users walks the inbound hop.
// .include('user', ...) on orders walks the outbound hop.

Pipeline

  1. Wire an adapter (bring your own driver)
  2. Scan the data store into a paradigm-neutral DataModel
  3. Generate a typed schema via biref gen CLI
  4. Query with a Prisma-style fluent API with full type narrowing

Codegen

# Postgres
pnpm exec biref gen --url postgres://user:pass@localhost/mydb --all-namespaces

# MySQL
pnpm exec biref gen --url mysql://user:pass@localhost/mydb

# Split mode (one file per entity)
pnpm exec biref gen --url postgres://localhost/mydb --split --all-namespaces

Output:

biref/
  biref.schema.ts             # regenerated every run
  biref.schema.overrides.ts   # scaffolded once, yours to edit

Type your JSON columns via overrides:

// biref.schema.overrides.ts
export interface Overrides {
  'public.users': {
    profile: { plan: 'free' | 'pro'; prefs: { darkMode: boolean } };
  };
}

Core concepts

| Concept | Description | | --- | --- | | Adapter | Bundles an Introspector, QueryEngine, RawQueryRunner, and RecordParser for a specific database | | DataModel | Paradigm-neutral schema produced by a scan. Every entity with relationships in both directions | | TypedChain | Fluent query builder with compile-time narrowing on select, where, include | | QueryPlan | Immutable tree built by the chain. One SQL query per include level |

Query builder

const q = biref.query<BirefSchema>(model);

// Select + filter + order + limit
const active = await q.public.products
  .select('id', 'sku', 'name')
  .where('active', 'eq', true)
  .orderBy('sku', 'asc')
  .limit(10)
  .findMany();

// Nested includes (recursive)
const usersWithOrders = await q.public.users
  .select('id', 'email')
  .include('orders', (order) =>
    order
      .select('id', 'total', 'status')
      .include('order_items', (item) =>
        item.select('product_id', 'quantity'),
      ),
  )
  .findMany();

// Wildcard include
const everything = await q.public.users
  .select('id', 'email')
  .include('*')
  .findMany();

Filter operators

| Category | Operators | | --- | --- | | string, uuid, enum | eq, neq, in, not-in, like, ilike, is-null, is-not-null | | integer, decimal, date, timestamp, time | eq, neq, lt, lte, gt, gte, between, in, not-in, is-null, is-not-null | | boolean | eq, neq, is-null, is-not-null |

Local development

# Docker containers for testing
docker compose -f docker/postgres/docker-compose.yml up -d  # localhost:5432
docker compose -f docker/mysql/docker-compose.yml up -d      # localhost:3306

# Both use: user=biref password=biref_pass database=biref_demo

Requirements

  • Node.js 20+
  • Your own database driver (pg or mysql2). Zero runtime dependencies.

License

MIT