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/audit

v1.11.1

Published

Model audit logging for Zerotal — record who changed what, and when.

Readme

@zerotal/audit

Automatic, zero-boilerplate audit logging for Zerotal models and custom events.

Captures every create, update, and delete on audited models — with old and new values, the authenticated actor, and request metadata — and stores them in a queryable audit_logs table. Custom events can be logged manually via the Audit facade. Stable — the public API follows SemVer strictly for the rest of the 1.x line.

Part of the Zerotal framework. Requires Bun ≥ 1.3.14.

Installation

bun add @zerotal/audit

Setup

Register the provider in bootstrap/providers.ts:

import { AuditProvider } from "@zerotal/audit";

export default [
  DatabaseProvider,
  SessionProvider,
  AuthProvider,
  AuditProvider, // add after DatabaseProvider
];

The audit_logs table is created automatically on boot — no migration needed. Configure the driver and table in config/audit.ts:

// config/audit.ts
import { AuditConfig } from "@zerotal/audit";

export default AuditConfig({
  driver: "database", // 'database' | 'null'
  table: "audit_logs",
  pruneKeep: 0, // 0 = unlimited; set e.g. 100 to keep last N per model
  captureRequest: true, // attach IP, user-agent, URL automatically
});

Usage

Compose Auditable with Model.using (like any other mixin) to record created, updated, and deleted automatically. Configure it with overridable static fields:

import { Model, column, table } from "@zerotal/orm";
import { Authenticatable } from "@zerotal/auth";
import { Auditable } from "@zerotal/audit";

@table("users")
export class User extends Model.using(Authenticatable, Auditable) {
  protected static auditExcept = ["password", "rememberToken"];

  @column() name!: string;
  @column() email!: string;
  @column() password?: string;
}

For a model you'd rather not wrap, register it at boot in a provider's onBooted():

import { registerAudit } from "@zerotal/audit";

registerAudit(User);

Log custom events via the Audit facade. Within a request it reads the authenticated user and request details automatically; outside one, pass the actor explicitly:

import { Audit } from "@zerotal/audit";

// Pass the model instance — auditable_type/id are derived from it (no orphans):
await Audit.log("login.success", user, { tags: { method: "github_oauth" } });

// On an Auditable instance, the shorthand reads even cleaner:
await user.auditLog("login.success", { tags: { method: "github_oauth" } });

// Outside a request (queue job, CLI) — pass the actor explicitly:
await Audit.log("subscription.renewed", sub, { actor_type: "user", actor_id: sub.userId });

Query through the Audit facade or an instance — both return a chainable AuditLog builder (where · orderBy · desc() / asc() · limit · get · paginate):

import { Audit } from "@zerotal/audit";

const history = await Audit.logs(User, user.id).desc().limit(25).get();
const fromInstance = await user.auditLogs().desc().limit(25).get();
const logins = await Audit.logsOfEvent("login.success").get();
const byUser = await Audit.logsByActor(user.id).get();
const page = await Audit.logs(User, user.id).orderBy("id", "desc").paginate(20, 1);

Exports

  • Auditor — the core service: records events and exposes logs() / logsByActor() / logsOfEvent().
  • Audit — facade over the Auditor (Audit.log(...), Audit.logs(...)).
  • AuditLog — the queryable Model behind the builders.
  • AuditObserver — ORM lifecycle observer that emits model events.
  • AuditProvider — wires the auditor, driver, and observer.
  • Auditable, registerAudit — opt a model in via mixin (adds auditLog() / auditLogs()) or at boot.
  • Drivers: AuditDriver (interface), DatabaseDriver, NullDriver.
  • AuditConfig / AuditConfigShape — config factory and shape.
  • Types: AuditEvent, AuditRecord, AuditPayload, AuditableOptions, AuditableRef, InstanceAuditPayload.

Documentation