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

biab

v1.0.77

Published

A TypeScript/Node.js library that provides a complete, opinionated backend foundation: database queries and mutations via [Orma](https://github.com/mendeljacks/orma), JWT authentication, Google OAuth, Apple Sign-In, and role-based access control — all wir

Downloads

3,755

Readme

biab – Backend in a Box

A TypeScript/Node.js library that provides a complete, opinionated backend foundation: database queries and mutations via Orma, JWT authentication, Google OAuth, Apple Sign-In, and role-based access control — all wired together and ready to drop into any Express-style server.


Table of Contents


Features

  • Orma-powered queries & mutations – type-safe, relational database access over PostgreSQL
  • JWT authentication – issue and verify tokens with a single secret
  • Google OAuth – redirect-based and headless (mobile) flows
  • Apple Sign-In – headless token verification and callback handler
  • Role-based access control – declarative per-table CRUD permissions
  • Ownership enforcement – pluggable hook to restrict rows by owner
  • Database migrations – reset and re-apply via db-migrate
  • Prepopulate – idempotently seed a database from plain JavaScript objects
  • Extra macros – automatic resource_id generation with cuid

Installation

npm install biab

For local development with hot-reload:

npm install -g nodemon
npm install
npm run dev

Quick Start

import express from 'express'
import { query, mutate } from 'biab/src/api/controllers'
import { orma_schema } from './orma_schema'   // generated by introspect()
import { connection_edges } from './edges'
import { role_has_perms } from './perms'
import { byo_query_fn, pool, trans } from './db'
import { ensure_ownership } from './ownership'
import { add_resource_ids } from 'biab/src/config/extra_macros'

const app = express()
app.use(express.json())

const JWT_SECRET = process.env.JWT_SECRET!

app.post('/query', async (req, res) => {
    try {
        const result = await query(
            req, JWT_SECRET, pool, connection_edges,
            role_has_perms, orma_schema, ensure_ownership, byo_query_fn
        )
        res.status(200).json(result)
    } catch (err) {
        res.status(400).json(err)
    }
})

app.post('/mutate', async (req, res) => {
    try {
        const result = await mutate(
            req, JWT_SECRET, pool, connection_edges,
            role_has_perms, orma_schema, ensure_ownership,
            byo_query_fn, trans, add_resource_ids
        )
        res.status(200).json(result)
    } catch (err) {
        res.status(400).json(err)
    }
})

app.listen(3000)

Core Concepts

Query

import { query } from 'biab/src/api/controllers'

const result = await query(
    req,              // Express request – body contains the Orma query, headers contain the JWT
    jwt_secret,
    pool,             // pg Pool
    connection_edges, // ConnectionEdges from Orma
    role_has_perms,   // RoleHasPerms – see Role-Based Permissions
    orma_schema,      // OrmaSchema – generated by introspect()
    ensure_ownership, // EnsureOwnershipFn – your custom ownership check
    byo_query_fn      // (sqls, pool) => Promise<results[]> – your query executor
)

The handler authenticates the request, validates the Orma query against the schema, enforces permissions and ownership, then executes the query.

Mutate

import { mutate } from 'biab/src/api/controllers'

const result = await mutate(
    req,
    jwt_secret,
    pool,
    connection_edges,
    role_has_perms,
    orma_schema,
    ensure_ownership,
    byo_query_fn,
    trans,        // (fn, pool) => Promise – your transaction wrapper
    extra_macros  // (mutation) => void – called before the mutation runs
)

The handler applies the supersede macro (so users can only supersede data they can read), authenticates, enforces permissions and ownership, then runs the mutation inside your transaction wrapper.

Authentication

import { make_token, authenticate } from 'biab/src/api/auth/auth'

// Issue a token
const token = await make_token(user_id, role_ids, jwt_secret)

// Verify a token (reads Authorization: Bearer <token> header)
const { user_id, role_ids } = await authenticate(req, jwt_secret)

Role-Based Permissions

Define which role IDs are allowed to perform each CRUD operation on each table:

import { RoleHasPerms } from 'biab/src/api/auth/perms'

const role_has_perms: RoleHasPerms = {
    posts: {
        create: [1],       // only role 1 can create
        read:   [1, 2],    // roles 1 and 2 can read
        update: [1],
        delete: [1]
    },
    comments: {
        create: [1, 2],
        read:   [1, 2],
        update: [1, 2],
        delete: [1]
    }
}

Google OAuth

Redirect flow:

import { google_login, google_login_callback } from 'biab/src/api/auth/auth_google'

// Redirect the user to Google
app.get('/auth/google', (req, res) => google_login(res, SERVER_ROOT_URI, GOOGLE_CLIENT_ID))

// Handle the callback
app.get('/auth/google/callback', async (req, res) => {
    const { token, user_id } = await google_login_callback(
        req.query.code as string,
        GOOGLE_CLIENT_ID,
        GOOGLE_CLIENT_SECRET,
        SERVER_ROOT_URI,
        ensure_user_exists,  // (google_user) => Promise<{ id, user_has_roles }>
        JWT_SECRET
    )
    res.json({ token, user_id })
})

Headless (mobile) flow:

import { google_auth_headless } from 'biab/src/api/auth/auth_google'

app.post('/auth/google/headless', async (req, res) => {
    const { token, user_id } = await google_auth_headless(
        req.body,           // { id_token, access_token }
        ensure_user_exists,
        JWT_SECRET
    )
    res.json({ token, user_id })
})

Apple Sign-In

Headless (mobile) flow:

import { apple_auth_headless } from 'biab/src/api/auth/auth_apple'

app.post('/auth/apple/headless', async (req, res) => {
    const { token, user_id } = await apple_auth_headless(
        req.body,                  // { id_token, access_token }
        ensure_apple_user_exists,  // (apple_user) => Promise<{ id, user_has_roles }>
        JWT_SECRET,
        BUNDLE_ID
    )
    res.json({ token, user_id })
})

Callback flow:

import { sign_in_with_apple } from 'biab/src/api/auth/auth_apple_callback'

app.get('/callbacks/sign_in_with_apple', async (req, res) => {
    const result = await sign_in_with_apple(
        req, SERVER_ROOT_URI, BUNDLE_ID, SERVICE_ID,
        TEAM_ID, KEY_CONTENTS, KEY_ID
    )
    res.json(result)
})

Database Utilities

Introspect

Generate an orma_schema file from your live PostgreSQL database:

import { introspect } from 'biab/src/config/orma'

await introspect('./src/orma_schema.ts', pool, byo_query_fn)

Prepopulate

Idempotently seed tables – rows are created or updated but never deleted:

import { prepopulate } from 'biab/src/scripts/prepopulate'

await prepopulate(
    {
        roles: [{ id: 1, name: 'admin' }, { id: 2, name: 'user' }]
    },
    pool, orma_schema, byo_query_fn, trans, connection_edges
)

Reset Migrations

Drop and re-apply all db-migrate migrations:

import { reset } from 'biab/src/scripts/reset'

await reset(db_migrate_config)

Or via the CLI:

npm run reset

Scripts

| Script | Description | |---|---| | npm run dev | Start the server with hot-reload via nodemon | | npm start | Start the server (production) | | npm test | Run the Mocha test suite | | npm run coverage | Run tests with NYC coverage report | | npm run reset | Drop and re-apply all database migrations | | npm run deploy | Publish the package to npm |


Environment Variables

| Variable | Description | |---|---| | JWT_SECRET | Secret used to sign and verify JWT tokens | | DATABASE_URL | PostgreSQL connection string | | GOOGLE_CLIENT_ID | Google OAuth client ID | | GOOGLE_CLIENT_SECRET | Google OAuth client secret | | NPM_TOKEN | npm publish token (used by npm run deploy) |

Create a .env file in the project root. The dev, test, and reset scripts load it automatically via dotenv.


License

ISC