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

@thejob/auth

v1.0.0

Published

Shared auth for The Job services: Better Auth JWT verification middleware + user lifecycle events over Redis Streams.

Readme

@thejob/auth

Shared auth for The Job backend services. Two concerns, split across subpath exports so a service only pulls the module (and dependencies) it uses:

| Import | Contains | Extra deps | | --- | --- | --- | | @thejob/auth | Better Auth JWT verification + Hono guards | jose | | @thejob/auth/events | event names + payload types/schema | none | | @thejob/auth/events/producer | emit() over a Redis Stream | ioredis | | @thejob/auth/events/consumer | on()/start() consumer group | ioredis |

The package lives inside the thejob-hono-auth repo (packages/auth/) and is consumed via yalc locally or the registry — the same pattern data-processor uses for its client/ package.

Verification (@thejob/auth)

Replaces the byte-identical lib/auth.ts that used to be copy-pasted into every Hono service. Build the helpers once with your service's config, then use the returned Hono middleware:

import { createAuth } from '@thejob/auth';

const auth = createAuth({ authUrl: env.AUTH_URL, logger });

app.get('/me',   auth.requireUser,  (c) => c.json(auth.getUser(c)));
app.get('/pub',  auth.attachUser,   (c) => c.json({ user: auth.getUser(c) ?? null }));
app.patch('/x',  auth.requireAdmin, (c) => c.json({ ok: true }));
  • attachUser — best-effort; sets c.var.user when a valid token is present.
  • requireUser — 401 unless a valid token identifies a user.
  • requireAdmin — 401 unauthenticated, 403 unless the user has the admin role.

Tokens are EdDSA JWTs verified against Better Auth's JWKS at ${authUrl}/api/auth/jwks. Config is injected via createAuth(...); the package never reads process.env itself.

Events (@thejob/auth/events/*)

Better Auth publishes user-lifecycle events onto a Redis Stream (thejob:auth.events); downstream services consume them with a consumer group. The producer knows nothing about consumers. No signing — the stream is internal infra (trust = network + Redis auth); consumers still schema-validate every event.

Producer (auth):

import { createAuthEventsProducer } from '@thejob/auth/events/producer';

const producer = createAuthEventsProducer({ url: env.AUTH_REDIS_URL });
await producer.emit('user.created', { authAccountId: user.id, data: { email, name, roles } });

Consumer (e.g. user-service):

import { createAuthEventsConsumer } from '@thejob/auth/events/consumer';

const consumer = createAuthEventsConsumer({ url: env.AUTH_REDIS_URL, group: 'user-service', logger });
consumer.on('user.created', applyEvent);
consumer.on('user.updated', applyEvent);
consumer.on('user.deleted', applyEvent);
await consumer.start();

Event types: user.created, user.updated, user.deleted. Each carries { type, id, occurredAt, authAccountId, data? } where authAccountId is Better Auth's user.id (the trusted join key) and data holds auth-managed fields (email, name, roles).

Durability

  • Consumer group — each event is delivered to the group once; a backlog accumulated while a consumer was down is drained on restart.
  • At-least-once — an entry is XACK'd only after its handler resolves; a throwing handler leaves it pending and it is redelivered via XAUTOCLAIM. Handlers must therefore be idempotent.
  • Bounded — XADD … MAXLEN ~ self-trims the stream.

Config

Every Redis URL is injected via the constructor from the calling service's own AUTH_REDIS_URL env — the library never reads it from process.env. This keeps each service's config self-contained and the package transport-agnostic.

Build & test

pnpm build       # tsc -> dist (with .d.ts)
pnpm test        # vitest (verification guards + Redis Streams behaviour)
pnpm typecheck

The events tests need a local Redis on localhost:6379 (override with TEST_REDIS_URL); they skip cleanly when none is reachable.