velvet-auth

0.1.9 · active · verified Wed Apr 22

velvet-auth is a production-ready authentication plugin specifically designed for Elysia.js applications running on Bun. It provides a comprehensive solution for common authentication patterns, including JWT rotation, secure password hashing using native Argon2id (via `Bun.password`), and session management with RESP-compatible stores like Redis for refresh token invalidation and JTI blacklisting. The current stable version is 0.1.9, with frequent minor releases addressing bug fixes and introducing improvements. Key differentiators include its tight integration with Bun's native features, an adapter pattern for database and email provider flexibility, and a focus on type safety with Zod validation. It aims to reduce boilerplate for setting up robust auth stacks in the Bun/Elysia ecosystem.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to integrate `velvet-auth` into an Elysia application, showing the setup of `UserStoreAdapter` and `EmailAdapter` mocks, and mounting the `velvetAuth` plugin with essential JWT and Redis configuration. It also includes a basic Elysia route to confirm server operation.

import { Elysia } from "elysia";
import { velvetAuth } from "velvet-auth";
import { BunFileRouter } from 'bun-file-router'; // Assuming a simple db mock for demonstration

const db = {
  users: {
    data: [] as any[], // In-memory mock for demonstration
    findOne: async ({ id, username, email }: { id?: string; username?: string; email?: string }) => {
      if (id) return db.users.data.find(u => u.id === id);
      if (username) return db.users.data.find(u => u.username === username);
      if (email) return db.users.data.find(u => u.email === email);
      return undefined;
    },
    insert: async (data: any) => { db.users.data.push({ ...data, id: Date.now().toString() }); return data; },
    update: async ({ id }: { id: string }, updates: any) => {
      const userIndex = db.users.data.findIndex(u => u.id === id);
      if (userIndex !== -1) {
        db.users.data[userIndex] = { ...db.users.data[userIndex], ...updates };
      }
    },
  },
};

// 1. Implement the UserStoreAdapter for your database
const userStore = {
  findById:       async (id) => db.users.findOne({ id }),
  findByUsername: async (username) => db.users.findOne({ username }),
  findByEmail:    async (email) => db.users.findOne({ email }),
  create:         async (data) => db.users.insert(data),
  updatePassword: async (id, hash) => db.users.update({ id }, { password: hash }),
  setEmailVerified: async (id) => db.users.update({ id }, { emailVerified: true }),
};

// 2. Implement the EmailAdapter for your email provider
const emailAdapter = {
  sendOtp:          async (to, otp) => { console.log(`Sending OTP to ${to}: ${otp}`); return true; },
  sendVerification: async (to, url) => { console.log(`Sending verification to ${to}: ${url}`); return true; },
  checkStatus:      async () => true,
};

// 3. Mount the plugin
const app = new Elysia()
  .use(
    velvetAuth(userStore, emailAdapter, {
      jwt: {
        secret: process.env.JWT_SECRET ?? 'super-secret-jwt-key-that-is-at-least-32-chars-long',
      },
      redis: {
        url: process.env.REDIS_URL ?? 'redis://localhost:6379'
      },
      password: {
        minLength: 8, // Example: enforce min length
      }
    }),
  )
  .get('/', () => 'Welcome to velvet-auth example!')
  .listen(3000);

console.log(
  `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
);

view raw JSON →