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

@zerotal/auth

v1.7.4

Published

Authentication and authorization for Zerotal — sessions, tokens, 2FA, OAuth, gates, and policies.

Readme

@zerotal/auth

Session authentication, API tokens, and DB-backed authorization for Zerotal.

@zerotal/auth authenticates users against the HTTP session, issues and verifies bearer API tokens, and provides Gate/policy authorization with relational roles and permissions. It also ships password hashing, password reset, magic-link login, TOTP two-factor authentication, and WebAuthn passkeys. It builds on @zerotal/session — register both providers.

Part of the Zerotal framework. Requires Bun ≥ 1.3.14.

Installation

bun add @zerotal/session @zerotal/auth

Setup

Register the provider in bootstrap/providers.ts (after SessionProvider):

import { SessionProvider } from "@zerotal/session";
import { AuthProvider } from "@zerotal/auth";

export default [
  // …other providers
  SessionProvider,
  AuthProvider,
];

That's it — AuthProvider discovers your authenticatable model from the registry, so ctx.user / Auth.user() work with no further wiring. To override how a user is loaded from the session ID (in bootstrap/app.ts, before Application.create()):

import { AuthProvider } from "@zerotal/auth";
import { User } from "../app/models/User.ts";

AuthProvider.resolveUsing((id) => User.find(id)); // optional

Usage

The User model

Extend AuthUser instead of Model:

import { column, table } from "@zerotal/orm";
import { AuthUser } from "@zerotal/auth";

@table("users")
export class User extends AuthUser {
  @column() name!: string;
  @column() email!: string;
  @column() password!: string;
}

The Auth facade

import { Auth, Hash } from "@zerotal/auth";

Auth.check(); // boolean — authenticated?
Auth.user(); // User    — throws UnauthorizedError for guests
Auth.userOrNull(); // User | undefined
Auth.id(); // number

await Auth.login(user); // write user_id to the session
await Auth.logout(); // clear it

// Verify a password during login:
if (!(await Hash.check(password, user.password))) {
  /* invalid */
}

Authorization (Gate, roles & permissions)

Compose the Authenticatable / Roles / Permissions mixins onto your model with Model.using (flat, left-to-right — no wrapper nesting):

import { Authenticatable, Roles, Permissions } from "@zerotal/auth";
import { Model, column } from "@zerotal/orm";

export class User extends Model.using(Authenticatable, Permissions, Roles) {
  @column() name!: string;
  @column() email!: string;
}

// `extends Roles(Permissions(AuthUser))` still works — AuthUser is
// just Authenticatable(Model).

// Then:
await user.assignRole("editor");
user.can("post.update"); // synchronous — resolves direct + role-derived grants
Auth.authorize("post.delete"); // throws ForbiddenError when denied

// Policy-based checks:
Gate.allows("update", post);
Gate.authorize("update", post);

API tokens & route protection

import { createToken, BearerTokenMiddleware } from "@zerotal/auth";

const { plaintext, row } = await createToken({
  tokenableId: user.id,
  name: "cli",
  abilities: ["*"],
});
// store `row`, return `plaintext` to the client once

Router.group({ prefix: "/api", middleware: [BearerTokenMiddleware] }, () => {
  Router.get("/me", UserController, "show");
});

Exports

  • Models & facadesAuthUser, Authenticatable, Auth, Hash
  • Provider & configAuthProvider, AuthConfig
  • MiddlewarePersistUserMiddleware (auto-wired; populates ctx.user), AuthMiddleware (guard — require auth), GuestMiddleware, BearerTokenMiddleware, TwoFactorMiddleware, ValidateSignatureMiddleware
  • AuthorizationGate, GateService, Policy, RequireRoleMiddleware, RequirePermissionMiddleware
  • Relational RBACRole, Permission, Roles, Permissions (mixins), PermissionRegistry, definePermission
  • HashingHashService
  • TokenscreateToken, hashToken, tokenCan
  • Password resetPasswordBroker, PASSWORDS
  • Magic linksMagicLinkBroker, MAGIC
  • Two-factorTwoFactorService, TwoFactor
  • WebAuthn / passkeysPasskeyService

Documentation