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

@12-apps/auth

v2.19.0

Published

Plug-and-play authentication plugin: Auth.js wiring and the e-mail + password flow (.), host-mounted backend surface (./server: routes, messages, mail templates, the duck-typed credential and settings store seams), auth UI (./react: screens, whole login/s

Readme

@12-apps/auth

Authentication as a plug-in: Auth.js wiring, the e-mail + password flow, the screens and whole pages that flow needs, a mountable backend surface, and the three tables it all runs on — with no host's vocabulary anywhere in it.

Same shape as @12-apps/report-builder, deliberately. If you have adopted that one, you already know this one's layout.

| Entry point | Needs | What is in it | |---|---|---| | . | nothing | createEmailCredentials, password policy, tokens, the admin allowlist, the rate limiter, device detection | | ./server | nothing (Node) | the Auth.js bridge (createApiAuth, auth, handlers, authConfig, credentialsProvider), routes, status vocabulary, mail templates, and the duck-typed credential + settings store seams | | ./react | react, react-dom, @12-apps/ui | the screens, the whole login/sign-up pages, the platform settings screen | | ./hono | hono | one mount call for the whole backend surface | | ./notifications | @12-apps/notifications | createAuthMailer — the four auth e-mails over an EmailDriver | | ./e2e | @playwright/test, playwright-bdd | the packaged Gherkin journeys and their steps |

An entry point marks a distinct peer, never merely a module. Every peer is optional, so a backend that never renders a page installs no react.

. is the light half, and that is enforced. It value-imports nothing — no @auth/core, no react, no hono — so a background job that expires stale tokens can import { hashToken } from '@12-apps/auth' and load only that. The Auth.js runtime lives in ./server for the same reason report-builder keeps createReportBuilder there. src/__tests__/light-root.test.ts walks the root's import graph and fails if that ever stops being true.

The tables are the package's

prisma/auth.prisma owns auth_credentials, auth_tokens and auth_platform_settings, with migrations beside them.

pnpm --filter @12-apps/auth prisma:sync        # copy the partial into your schema
pnpm --filter @12-apps/auth prisma:sync:check  # CI: fail if the copy drifted

The partial is copied, never symlinked: npm pack drops symlinked entries, turbo prune dangles a link whose owner is not a declared dependency, and Prisma lstats a migration directory — so a symlinked one is silently skipped, which is a green deploy that applied no schema.

Every user reference is an opaque user_id with no foreign key into any host table. These migrations therefore apply in a repo whose users live under another name, in another database, or do not exist yet.

What stays yours

One thing, because it is the one thing a package cannot know: who your users are. EmailIdentityDelegate is three methods — findByEmail, findById, upsert — over your own user table. Everything else is here.

Alongside that, the choices that are genuinely a product's:

  • the words — every copy pack is required, never defaulted (PT_BR_* ships as one for each surface);
  • the branding — a slot on the pages, completely opaque to this package;
  • the providers — a node you render, because an OAuth button carries a callback URL, a consent gate and a redirect this package cannot own;
  • the mail vendor — you name the environment VARIABLES; which service, which key and which from-address are yours. The resolution between them is not: createEnvAuthMailer owns the sink / vendor / refuse tree, because every branch of it is a correctness property rather than a preference.

Config, and only config. The origin host's whole wiring is now:

export const authMailer = createEnvAuthMailer({
  env: { provider: "NOTIFICATIONS_EMAIL_PROVIDER", apiKey: "RESEND_API_KEY",
         from: "NOTIFICATIONS_EMAIL_FROM", sinkFile: "AUTH_EMAIL_LOG_FILE",
         origin: ["APP_PUBLIC_URL", "AUTH_URL"] },
  drivers: EMAIL_DRIVERS,
  log: createFeatureLogger("auth-email"),
});

export const { GET, POST, PUT } = mountEmailAuth({
  path: "/api/auth/email",
  credentials, messages: PT_BR_MESSAGES, resolveUserId, onSignedUp,
});

Security model

  • consumeToken must be a conditional write (UPDATE … WHERE consumed_at IS NULL) reporting whether it affected a row. That return value is the single-use guarantee.
  • Sign-up and password-reset answers are identical whether or not the address exists, and whether or not the mail left. That is why the mailer resolves rather than throws.
  • A deployment with no mail provider refuses loudly instead of falling back to logging: a reset link in a log aggregator is a credential in a log aggregator.
  • requireEmailVerification changes the sign-up contract, not just its security — see ADOPTING.md.

Conventions

  • Every surface is a create* factory taking one config object.
  • Nothing here reads an environment variable.
  • The database client is duck-typed (AuthDb, AuthSettingsDb); this package never resolves a generated Prisma client.
  • Developer-facing text is English; the shipped copy packs are pt-BR.

Full wiring, endpoint list and the decisions that are not obvious: ADOPTING.md. Journeys and harness notes: E2E.md.