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

better-waitlist

v1.1.3

Published

Waitlist plugin for Better Auth - manage waitlists with email signup, position tracking, and admin approval

Readme

Better Waitlist

npm version License: MIT GitHub Repo Better Auth GitHub Stars

Stars Over Time

Waitlist plugin for Better Auth

Made by haxurn

Installation

npm install better-waitlist
pnpm add better-waitlist
yarn add better-waitlist

Usage

Server

Add the plugin to your Better Auth configuration:

import { betterAuth } from 'better-auth';
import { waitlist } from 'better-waitlist';

export const auth = betterAuth({
  plugins: [waitlist()],
});

Database Migration

Run the migration to add the waitlist table to your database:

npx @better-auth/cli migrate

Or generate the schema for your ORM:

npx @better-auth/cli generate

Client

Add the client plugin:

import { createAuthClient } from 'better-auth/client';
import { waitlistClient } from 'better-waitlist';

export const authClient = createAuthClient({
  plugins: [waitlistClient()],
});

Options

import { waitlist } from 'better-waitlist';

export const auth = betterAuth({
  plugins: [
    waitlist({
      // Authentication
      requireAdmin: true, // require session for admin endpoints (default: true)

      // Entry Management
      maxEntries: 0, // maximum entries allowed (0 = unlimited, default: 0)
      enabled: true, // allow new waitlist joins (default: true)

      // Public Features
      allowStatusCheck: true, // allow public status checks (default: true)
      showPosition: false, // show position in status response (default: false)

      // Invitations
      markInvitedOnApprove: false, // mark as invited when approving (default: false)

      // Position Management
      recalculatePositionOnApprove: false, // recalculate positions when entries are approved/rejected (default: false)

      // Callbacks
      onJoin: async (entry) => {
        // Called when user joins waitlist
        console.log('New entry:', entry.email);
      },
      onApprove: async (entry) => {
        // Called when entry is approved
        console.log('Approved:', entry.email);
      },
      onReject: async (entry) => {
        // Called when entry is rejected
        console.log('Rejected:', entry.email);
      },
      onComplete: async (entry) => {
        // Called when entry is completed (user signs up)
        console.log('Completed:', entry.email);
      },
    }),
  ],
});

API

Join Waitlist

// Anonymous user
await authClient.waitlist.join({ email: '[email protected]' });

// Logged-in user
await authClient.waitlist.join({
  email: '[email protected]',
  userId: 'user-123',
});

Check Status

const { data, error } = await authClient.waitlist.getStatus({
  email: '[email protected]',
});

if (data) {
  console.log(data.status); // "pending" | "approved" | "rejected"
}

Check Position

const { data, error } = await authClient.waitlist.getPosition({
  email: '[email protected]',
});

if (data) {
  console.log(data.position); // real-time position among pending entries
}

Admin: List Entries

const { data, error } = await authClient.waitlist.list({
  status: 'pending', // optional filter
  limit: 20,
  offset: 0,
});

if (data) {
  console.log(data.entries);
  console.log(data.total);
}

Admin: Get Stats

const { data, error } = await authClient.waitlist.stats();

if (data) {
  console.log(data.total);
  console.log(data.pending);
  console.log(data.approved);
  console.log(data.rejected);
}

Admin: Approve Entry

const { data, error } = await authClient.waitlist.approve({
  email: '[email protected]',
});

// With mark as invited
const { data: data2 } = await authClient.waitlist.approve({
  email: '[email protected]',
  sendInvite: true, // override plugin setting for this call
});

Admin: Reject Entry

const { data, error } = await authClient.waitlist.reject({
  email: '[email protected]',
});

Admin: Promote Entry

Send an invite to an approved user:

const { data, error } = await authClient.waitlist.promote({
  email: '[email protected]',
});

Admin: Promote All

Send invites to all approved users:

const { data, error } = await authClient.waitlist.promoteAll({
  status: 'approved', // default: 'approved'
});

if (data) {
  console.log(data.promoted); // count of promoted entries
}

Admin: Complete Entry

Mark an entry as complete (e.g., after user signs up):

const { data, error } = await authClient.waitlist.complete({
  email: '[email protected]',
});

if (data) {
  console.log(data.entry); // the completed entry data
}

Schema

The plugin adds a waitlist table with the following fields:

| Field | Type | Description | | ------------ | -------- | ------------------------------------- | | id | string | Unique identifier | | email | string | User's email (unique) | | status | string | pending | approved | rejected | | position | number | Position in queue | | userId | string? | Optional relation to user | | invitedAt | date? | Timestamp when invite was sent | | createdAt | date | Timestamp when joined |

API Endpoints

| Method | Endpoint | Auth | Description | | ------ | ---------------------- | ------- | ------------------------- | | POST | /waitlist/join | None | Join waitlist | | GET | /waitlist/status | None | Check status | | GET | /waitlist/position | None | Get position | | GET | /waitlist/list | Session | List entries | | GET | /waitlist/stats | Session | Get waitlist statistics | | POST | /waitlist/approve | Session | Approve entry | | POST | /waitlist/reject | Session | Reject entry | | POST | /waitlist/promote | Session | Send invite to user | | POST | /waitlist/promote-all | Session | Send invites to all | | POST | /waitlist/complete | Session | Complete entry |

TypeScript

The plugin provides full TypeScript support. Types are automatically inferred when using the client:

// Full type inference
const result = await authClient.waitlist.join({
  email: '[email protected]',
});

// result.data is typed as WaitlistEntry
// result.error is typed as { message: string }

Contributing

Contributions are welcome! Please see our CONTRIBUTING.md for details.

Code of Conduct

Please read our CODE_OF_CONDUCT.md before participating in our community.

License

MIT