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

flexiguard

v1.0.0

Published

Ultra-flexible authentication library for modern frameworks. ORM-agnostic, Database-agnostic, Framework-agnostic.

Readme


✨ Features

  • 🔐 Complete Auth — Register, login, logout, password reset, email verification
  • 🎭 OAuth Providers — Google, GitHub, Facebook, Apple, custom providers
  • 🔄 Session Management — Database sessions or stateless JWT
  • 🛡️ Security First — Argon2 hashing, HMAC signing, CSRF protection
  • 🔌 Any ORM — Prisma, Drizzle, Sequelize, Mongoose, Kysely, or custom
  • 🗄️ Any Database — PostgreSQL, MySQL, SQLite, MongoDB, PlanetScale, Neon
  • Any Framework — Express, Fastify, Hono, Next.js, SvelteKit, Remix
  • 🧩 Plugin System — Extend with custom hooks and events
  • 📱 Device Tracking — Track sessions across devices
  • 🚦 Rate Limiting — Built-in protection against brute force

📦 Installation

npm install @flexireact/flexiguard
pnpm add @flexireact/flexiguard
yarn add @flexireact/flexiguard

🚀 Quick Start

1. Setup with Prisma

// lib/auth.ts
import { createAuth } from '@flexireact/flexiguard';
import { PrismaAdapter } from '@flexireact/flexiguard/adapters/prisma';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export const auth = createAuth({
  adapter: PrismaAdapter(prisma),
  secret: process.env.AUTH_SECRET!,
  session: {
    strategy: 'database', // or 'jwt'
    maxAge: 30 * 24 * 60 * 60, // 30 days
  },
  password: {
    minLength: 8,
    requireUppercase: true,
    requireNumbers: true,
  },
});

2. Create Database Schema

// schema.prisma
model User {
  id            String    @id @default(cuid())
  email         String    @unique
  emailVerified Boolean   @default(false)
  passwordHash  String?
  name          String?
  image         String?
  role          String    @default("user")
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt

  sessions Session[]
  accounts Account[]
}

model Session {
  id           String   @id @default(cuid())
  userId       String
  token        String   @unique
  refreshToken String?
  expiresAt    DateTime
  userAgent    String?
  ipAddress    String?
  deviceId     String?
  createdAt    DateTime @default(now())
  lastActiveAt DateTime @default(now())

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model Account {
  id                String    @id @default(cuid())
  userId            String
  provider          String
  providerAccountId String
  accessToken       String?
  refreshToken      String?
  expiresAt         DateTime?
  tokenType         String?
  scope             String?
  createdAt         DateTime  @default(now())

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
}

model VerificationToken {
  id         String   @id @default(cuid())
  identifier String
  token      String
  type       String
  expiresAt  DateTime
  createdAt  DateTime @default(now())

  @@unique([identifier, token])
}

3. Use in Express

// server.ts
import express from 'express';
import { createExpressAuth } from '@flexireact/flexiguard/express';
import { auth } from './lib/auth';

const app = express();
app.use(express.json());

const expressAuth = createExpressAuth(auth.getConfig());

// Apply session middleware
app.use(expressAuth.session());

// Auth routes
app.post('/auth/register', expressAuth.handleRegister);
app.post('/auth/login', expressAuth.handleLogin);
app.post('/auth/logout', expressAuth.handleLogout);
app.get('/auth/me', expressAuth.handleMe);
app.post('/auth/change-password', expressAuth.handleChangePassword);

// Protected routes
app.get('/dashboard', expressAuth.requireUser(), (req, res) => {
  res.json({ user: req.user });
});

app.get('/admin', expressAuth.requireRole('admin'), (req, res) => {
  res.json({ message: 'Admin area' });
});

app.listen(3000);

4. Use in Next.js

// app/api/auth/[...flexiguard]/route.ts
import { createNextAuth } from '@flexireact/flexiguard/next';
import { auth } from '@/lib/auth';

const nextAuth = createNextAuth(auth.getConfig());

export const GET = nextAuth.handlers.GET;
export const POST = nextAuth.handlers.POST;
// app/dashboard/page.tsx
import { createNextAuth } from '@flexireact/flexiguard/next';
import { auth } from '@/lib/auth';
import { cookies } from 'next/headers';

export default async function DashboardPage() {
  const nextAuth = createNextAuth(auth.getConfig());
  const session = await nextAuth.getSessionFromCookies(cookies());

  if (!session) {
    redirect('/login');
  }

  return <div>Welcome, {session.user.name}!</div>;
}

🔌 Adapters

Prisma

import { PrismaAdapter } from '@flexireact/flexiguard/adapters/prisma';
import { PrismaClient } from '@prisma/client';

const adapter = PrismaAdapter(new PrismaClient());

Drizzle

import { DrizzleAdapter } from '@flexireact/flexiguard/adapters/drizzle';
import { db } from './db';
import * as schema from './schema';

const adapter = DrizzleAdapter({ db, schema });

Custom Adapter

import type { FlexiGuardAdapter } from '@flexireact/flexiguard';

const customAdapter: FlexiGuardAdapter = {
  async createUser(data) { /* ... */ },
  async getUserById(id) { /* ... */ },
  async getUserByEmail(email) { /* ... */ },
  // ... implement all methods
};

🔐 API Reference

Core Methods

// Register a new user
const result = await auth.register(email, password, {
  name: 'John Doe',
  role: 'user',
});

// Login
const result = await auth.login(email, password, {
  requireEmailVerified: true,
});

// Logout
await auth.logout(session);

// Validate session
const result = await auth.validateRequest(request);

// Change password
await auth.changePassword(userId, currentPassword, newPassword);

// Request password reset
await auth.requestPasswordReset(email);

// Reset password with token
await auth.resetPassword(email, token, newPassword);

// Verify email
await auth.verifyEmail(email, token);

Session Management

const sessionManager = auth.getSessionManager();

// Create session
const { session, cookies } = await sessionManager.createSession(user, {
  userAgent: 'Mozilla/5.0...',
  ipAddress: '192.168.1.1',
});

// Validate session
const session = await sessionManager.validateSession(cookies);

// Refresh session
const { session, cookies } = await sessionManager.refreshSession(oldSession);

// Destroy session
const cookies = await sessionManager.destroySession(session);

// Get all user sessions
const sessions = await sessionManager.getUserSessions(userId);

🧩 Plugins

import { createAuth, FlexiGuardPlugin } from '@flexireact/flexiguard';

const loggingPlugin: FlexiGuardPlugin = {
  name: 'logging',
  
  async afterRegister(user) {
    console.log(`New user registered: ${user.email}`);
  },
  
  async afterLogin(user, session) {
    console.log(`User logged in: ${user.email}`);
  },
  
  async onPasswordChanged(user) {
    // Send notification email
  },
};

const auth = createAuth({
  adapter,
  secret: process.env.AUTH_SECRET!,
  plugins: [loggingPlugin],
});

Available Hooks

| Hook | Description | |------|-------------| | beforeRegister | Modify user data before registration | | afterRegister | Called after successful registration | | beforeLogin | Called before login attempt | | afterLogin | Called after successful login | | beforeLogout | Called before logout | | afterLogout | Called after logout | | beforeSession | Modify session before validation | | validateRequest | Custom request validation | | onEmailVerified | Called when email is verified | | onPasswordChanged | Called when password is changed | | onPasswordReset | Called when password is reset | | onAccountLinked | Called when OAuth account is linked |


🛡️ Security Features

Password Hashing

import { hashPassword, verifyPassword } from '@flexireact/flexiguard';

// Hash with Argon2id (default)
const hash = await hashPassword('mypassword');

// Verify
const isValid = await verifyPassword('mypassword', hash);

HMAC Signing

import { signHmac, verifyHmac, signCookie, verifyCookie } from '@flexireact/flexiguard';

// Sign data
const signature = signHmac('data', secret);

// Verify
const isValid = verifyHmac('data', signature, secret);

// Signed cookies
const signedValue = signCookie('value', secret);
const value = verifyCookie(signedValue, secret);

JWT

import { encodeJWT, decodeJWT } from '@flexireact/flexiguard';

// Encode
const token = await encodeJWT(
  { sub: userId, email, role },
  { secret, maxAge: 3600 }
);

// Decode & verify
const payload = await decodeJWT(token, { secret });

🆚 Comparison

| Feature | FlexiGuard | Auth.js | Lucia | Clerk | |---------|:----------:|:-------:|:-----:|:-----:| | Self-hosted | ✅ | ✅ | ✅ | ❌ | | ORM-agnostic | ✅ | ⚠️ | ✅ | N/A | | Database sessions | ✅ | ✅ | ✅ | N/A | | JWT sessions | ✅ | ✅ | ❌ | N/A | | OAuth providers | ✅ | ✅ | ✅ | ✅ | | Plugin system | ✅ | ⚠️ | ❌ | ❌ | | Device tracking | ✅ | ❌ | ✅ | ✅ | | Rate limiting | ✅ | ❌ | ❌ | ✅ | | TypeScript | ✅ | ✅ | ✅ | ✅ | | Bundle size | ~15kb | ~50kb | ~10kb | N/A |


🏗️ Architecture

┌─────────────────────────────────────────────────────────────┐
│                      FlexiGuard Core                        │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │   Auth      │  │  Session    │  │   Token Manager     │  │
│  │  Manager    │  │  Manager    │  │  (JWT/HMAC)         │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
├─────────────────────────────────────────────────────────────┤
│                      Plugin System                          │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐   │
│  │ Logging │ │  Rate   │ │  Email  │ │ Custom Plugins  │   │
│  │         │ │ Limiter │ │ Sender  │ │                 │   │
│  └─────────┘ └─────────┘ └─────────┘ └─────────────────┘   │
├─────────────────────────────────────────────────────────────┤
│                      Adapter Layer                          │
│  ┌────────┐ ┌────────┐ ┌──────────┐ ┌────────┐ ┌────────┐  │
│  │ Prisma │ │Drizzle │ │Sequelize │ │Mongoose│ │ Custom │  │
│  └────────┘ └────────┘ └──────────┘ └────────┘ └────────┘  │
├─────────────────────────────────────────────────────────────┤
│                    Framework Bindings                       │
│  ┌─────────┐ ┌─────────┐ ┌──────┐ ┌────────┐ ┌──────────┐  │
│  │ Express │ │ Fastify │ │ Hono │ │Next.js │ │SvelteKit │  │
│  └─────────┘ └─────────┘ └──────┘ └────────┘ └──────────┘  │
└─────────────────────────────────────────────────────────────┘

📋 Configuration

interface FlexiGuardConfig {
  // Required
  adapter: FlexiGuardAdapter;
  secret: string;

  // Session
  session?: {
    strategy?: 'database' | 'jwt';
    maxAge?: number; // seconds
    updateAge?: number; // sliding window
  };

  // Cookies
  cookies?: {
    sessionToken?: {
      name?: string;
      options?: CookieOptions;
    };
  };

  // JWT (if using JWT strategy)
  jwt?: {
    maxAge?: number;
  };

  // Password requirements
  password?: {
    minLength?: number;
    requireUppercase?: boolean;
    requireLowercase?: boolean;
    requireNumbers?: boolean;
    requireSpecialChars?: boolean;
    hashAlgorithm?: 'argon2' | 'bcrypt';
  };

  // OAuth providers
  providers?: OAuthProvider[];

  // Plugins
  plugins?: FlexiGuardPlugin[];

  // Rate limiting
  rateLimit?: {
    enabled?: boolean;
    maxAttempts?: number;
    windowMs?: number;
  };

  // Callbacks
  callbacks?: {
    signIn?: (user, account?) => Promise<boolean>;
    session?: (session) => Promise<session>;
  };

  // Pages (for redirects)
  pages?: {
    signIn?: string;
    signOut?: string;
    error?: string;
  };

  // Debug mode
  debug?: boolean;
}

📄 License

MIT © FlexiReact Team