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

@slices.sh/auth.betterauth

v0.3.4

Published

slices v2: the auth service, backed by Better Auth inside the app. Memory here; MongoDB, Neon, Supabase and AuthLocker each in a package of their own.

Readme

@slices.sh/auth.betterauth

Sign-in, sessions, passkeys, two-factor and organizations run inside the app, on Better Auth. This is v1's services/auth/BACKEND.md, for the package.

export default auth({
  provider: betterauth({ database: "memory", methods: ["password"] }),
})

This package holds no database driver and no AuthLocker client. Each is a package of its own, which the config imports and passes in, so an app installs only what its configuration uses:

| Package | Passed as | Brings | |---|---|---| | @slices.sh/auth.betterauth.mongo | database: mongo() | mongodb, @extraorbital/mongo | | @slices.sh/auth.betterauth.neon | database: neon() | @neondatabase/serverless, drizzle-orm, @extraorbital/neon | | @slices.sh/auth.betterauth.supabase | database: supabase() | pg, drizzle-orm, @extraorbital/supabase | | @slices.sh/auth.betterauth.authlocker | codes: authlocker() | @authlocker/better-auth, @extraorbital/authlocker |

import { mongo } from "@slices.sh/auth.betterauth.mongo"
import { authlocker } from "@slices.sh/auth.betterauth.authlocker"

export default auth({
  provider: betterauth({ database: mongo(), methods: ["email-otp", "google"], codes: authlocker() }),
})

Only the ways in listed in methods are served: an app without password has no /api/auth/<config>/sign-up/email, and one without passkeys (passkeys, or passkey among methods) has no WebAuthn endpoints. Two-factor needs password sign-in: the authenticator app is the second factor to a password, so twoFactor without password fails when the config loads. Email and SMS codes, Google and GitHub go through AuthLocker: listing one without codes fails when the config loads too, and says which package to install. So does a config from 0.2 that names its database as a string (database: "mongo").

Environment

| Variable | What it is | |---|---| | BETTER_AUTH_SECRET | Signs every session. Generated into .env.local by the setup item; changing it signs everyone out. | | BETTER_AUTH_URL | Optional. The public origin, such as https://acme.com: callback URLs and the passkey domain come from it. Unset, it is the deployment's own on Vercel (VERCEL_PROJECT_PRODUCTION_URL in production, the branch and deployment URLs in a preview), and in development the origin each request comes to, on localhost only. Set it behind a proxy or on another host. | | MONGODB_URI, MONGODB_DB | database: mongo(). MONGODB_DB defaults to the database in the URI, then app. | | POSTGRES_URL, POSTGRES_URL_NON_POOLING | database: neon(). The second, the direct connection, is optional and only migrations use it. | | SUPABASE_DB_URL (with SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY) | database: supabase(). | | AUTHLOCKER_CLIENT_ID, AUTHLOCKER_CLIENT_SECRET | Email codes, SMS codes, Google, GitHub. Server only. | | AUTHLOCKER_ISSUER | Optional. Defaults to https://authlocker.dev. | | AUTHLOCKER_CAPABILITIES | Optional. socials.google,socials.github,otp.email,otp.phone. The server refuses any way in not listed here and in methods. |

Register {BETTER_AUTH_URL}/api/auth/<config>/callback/google and /github with your AuthLocker client; a localhost origin needs no registration. AuthLocker enforces the limits the screen shows: a code lives 10 minutes and allows 5 wrong attempts; a new code comes no sooner than 60 seconds after the last, 3 times per verification; SMS needs a claimed client and stops at its daily cap.

Storage

  • memory: everything lives in this process and is gone on restart. It refuses to run in production unless BETTER_AUTH_URL is a localhost origin.
  • mongo: collections are created on first write, so there is no migration. The namespace option is the MongoDB database.
  • neon, supabase: tables live in the namespace Postgres schema (slices_auth), outside the schemas Supabase exposes. Run npm run db:migrate after the URL is set; it generates and applies Drizzle migrations from services/auth/schema.ts. All tables, organizations included, are in the schema, so turning a feature on later needs no new migration.

Invitations and domains

Invitations are stored, not emailed, until sendInvitationEmail is given: the cards offer a link to share. A recipient must sign in with that verified email before accepting or declining it. An owner or admin whose verified email matches a private domain can claim it (public mail providers are refused); a verified sign-in joins matching organizations once. Password and SMS sign-ups do not verify an email and never auto-join.

The profile

Name and picture can always be changed. The address needs proof: a code sent to the new address through AuthLocker (email-otp in methods), or a link through sendChangeEmailVerification. The number needs phone-otp.

Account deletion

The core delete endpoint verifies a password or requires a fresh session. An account that is an organization's only owner is refused, across all membership pages. Passkeys, second-factor records, memberships and invitations issued by the deleted user are cleaned up. Application records and uploaded files belong to the host's deletion lifecycle.

Access requests

With organizations, one durable request is stored per organization and account; only that organization's owners and admins read or decide them, and approvals always grant member through Better Auth's addMember. Approvals use a durable claim before the membership write; a process interruption can leave a request approving, and an explicit retry after five minutes rechecks membership first.