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

@imola-solutions/audit-trail

v0.1.0

Published

Compliance-grade audit trail sink for @imola-solutions/* onAudit events. Buffers, batches, and persists to Supabase, HTTP, or console.

Readme

@imola-solutions/audit-trail

Compliance-grade audit trail sink. Wire it once; pass auditTrail.record as the onAudit prop to every other @imola-solutions/* package. It buffers, batches, and persists to Supabase (or HTTP or console).

Install

Normally installed via npx @imola-solutions/setup. To install manually:

npm install @imola-solutions/audit-trail

Usage

import { createAuditTrail } from "@imola-solutions/audit-trail";
import { createChatService } from "@imola-solutions/chat";
import { client } from "./lib/imola-client";

// One-time wiring
const auditTrail = createAuditTrail({
  apiClient: client,                            // Supabase-compatible
  actorResolver: async () => {
    const { data: { user } } = await client.auth.getUser();
    return { id: user?.id ?? "unknown", name: user?.email };
  },
  transport: "supabase",                        // or "console" | "http"
  bufferSize: 50,
  flushIntervalMs: 5000,
  tags: ["bopc", "prod"],                       // stamped on every event
});

// Then feed .record to every service that emits audit events
const chatService = createChatService({
  apiClient: client,
  currentUser: { id: "USR-1", name: "Alice" },
  onAudit: auditTrail.record,
});

API

createAuditTrail(options)

Returns { record, flush, shutdown, stats }.

Options:

  • apiClient (required for transport: "supabase") — Supabase-compatible client
  • actorResolver (required) — async () => ({ id, name? }). Called at record-time so the actor is snapshotted at the moment the event happened.
  • transport"supabase" (default) | "console" | "http"
  • httpEndpoint (required for transport: "http") — POSTs { events: [...] }
  • bufferSize (default 50) — flush trigger; events accumulate in memory until this many buffered
  • flushIntervalMs (default 5000) — periodic flush interval (ignored for console)
  • onAudit (optional) — receives self-audit events (audit-trail.record, audit-trail.flush, audit-trail.flush-error) so you can monitor the trail itself
  • tags (default []) — string tags attached to every event (product/env)

Methods

  • record(event) — Non-blocking. Buffers (or writes inline for console). Never awaits. Never throws.
  • flush() — Force a flush now. Returns a promise. Safe to call anytime.
  • shutdown() — Stops the periodic timer + flushes. Call before your process exits.
  • stats — Live counters: { buffered, flushed, failed, lastFlushAt, lastError }.

Resilience

  • Non-blocking: record() never blocks the calling flow. Domain services can safely await their own logic without ever waiting on the audit trail.
  • Retention on failure: Flush errors keep the events in the buffer for the next attempt. No silent data loss.
  • Self-audit events: every buffered event, every flush success, every flush error emits a self-audit so consumers can see when the trail itself misbehaves.
  • Broken meta-logger safe: if the onAudit callback (used for self-audit) throws, it's swallowed — never breaks the primary trail.

Event shape written to audit_events

{
  "id": "uuid",
  "action": "chat.message.send",
  "actor_id": "USR-1",
  "actor_name": "Alice",
  "target_type": "message",
  "target_id": "MSG-42",
  "metadata": { "threadId": "T-1", "contentLength": 22 },
  "success": true,
  "tags": ["bopc", "prod"],
  "timestamp": "2026-07-06T04:20:00Z"
}

SQL

Applied automatically by npx @imola-solutions/setup. Files:

  • sql/init.sql — table + indexes
  • sql/rls.sql — RLS policies (writers insert, readers see own events)

Peer dependencies

None hard peer deps. If using transport: "supabase" you'll want @supabase/supabase-js for typing purposes but the factory itself only requires that the injected apiClient exposes .from(table).insert(rows).