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

@basenative/admin

v2.3.2

Published

Pluggable admin & moderation surface — protected-route helpers, role/permission primitives, audit-log middleware, and queue-review UI components for BaseNative apps

Downloads

687

Readme

@basenative/admin

A pluggable admin & moderation surface for BaseNative apps. Brings together the four pieces that every "users-can-submit-stuff, mods-can-approve-it" app rebuilds from scratch:

  1. Roles — hierarchical (user < moderator < admin) with seedable admin promotion from a deployment-time allowlist.
  2. Queues — submission table → approved target table, with per-row decide audit columns populated automatically.
  3. Audit log — every protected action records who did what, when, and to which target — without ever crashing the request when the audit write fails.
  4. UI — server-rendered building blocks (<AdminQueueList>, <AdminUserList>) that compose with @basenative/components and theme via CSS custom properties.

Worker-runtime first; works fine on Node where storage adapters allow.

Install

pnpm add @basenative/admin
# Optional — gets you sessions/cookies for `getCurrentUser`
pnpm add @basenative/auth

Roles

import { defineRoles, requireRole, roleSeed } from '@basenative/admin/roles';

const roles = defineRoles({ hierarchy: ['user', 'moderator', 'admin'] });

roles.isAdmin(user);        // top tier?
roles.isModerator(user);    // ≥ moderator (admin counts)
roles.hasRole(user, 'moderator');

// Inside a handler:
const guard = requireRole('moderator');
const { user, error } = guard(currentUser);
if (error) return error;

Seeding admins from env

Promote handles listed in ADMIN_HANDLES (comma-separated) on first sight:

user = await roleSeed({
  env, envKey: 'ADMIN_HANDLES',
  user,
  setRole: (id, role, by) => d1Users(env.DB).setRole(id, role, by),
});

Submission queue

import { defineQueue } from '@basenative/admin/queue';

const queue = defineQueue({
  db: env.DB,
  tables: { submissions: 'submissions', target: 'phrases', columns: ['category', 'phrase'] },
});

await queue.submit({ category: 'Foods', phrase: 'apple pie', submittedBy: 'alice' });
const pending = await queue.listPending();
await queue.decide(pending[0].id, 'approved', 'mod1');

On approval the row is copied into the target table with created_at / created_by populated from the moderator's decision. Override onApprove if you need bespoke promotion logic.

Drop-in handlers

import { defineAdminHandlers } from '@basenative/admin/handlers';
import { currentUser } from '@basenative/auth';

const admin = defineAdminHandlers({
  queue,
  users: d1Users(env.DB),
  getCurrentUser: currentUser,
});

// functions/api/moderate/pending.js
export const onRequestGet = admin.listPending;

// functions/api/moderate/decide.js
export const onRequestPost = admin.decide;

// functions/api/moderate/users.js
export const onRequestGet = admin.users;

// functions/api/moderate/promote.js
export const onRequestPost = admin.promote;

Audit log

import { auditAction } from '@basenative/admin/audit';

await auditAction(env, {
  user,
  action: 'submission.approved',
  target: { type: 'submission', id: 42 },
  meta: { reason: 'duplicate' },
});

Audit failures are caught and logged — they never bubble up to the user.

UI components

import { renderAdminQueueList, renderAdminUserList } from '@basenative/admin/components';

const html = renderAdminQueueList({ items: pending });
const usersHtml = renderAdminUserList({
  users: elevated,
  results,
  query: q,
  currentHandle: me.handle,
});

Themable via CSS variables — --bn-admin-bg, --bn-admin-fg, --bn-admin-accent, --bn-admin-ok, --bn-admin-bad, --bn-admin-danger.

Action delegation: each button carries data-action="bn-admin-decide" (or bn-admin-set-role) plus data-id / data-decision / data-role. Wire a single document-level click handler that dispatches to your API.

Migration

Apply migrations/0001_audit_and_roles.sql (also exported as AUDIT_MIGRATION).

Adopting incrementally

You can pull in the bits in any order:

  1. Start with roles — the cheapest surface area; just wraps role checks.
  2. Add audit next to start recording protected actions you already have.
  3. Replace your queue endpoints with handlers once the data shape lines up.
  4. Swap your queue UI for components last.

Links

  • BaseNative monorepo — https://github.com/DuganLabs/basenative
  • Issues — https://github.com/DuganLabs/basenative/issues
  • Docs — https://github.com/DuganLabs/basenative#readme

License

Apache-2.0.