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

@bernierllc/session-manager

v1.0.6

Published

Secure session management with multiple storage backends and authentication integration

Readme

@bernierllc/session-manager

Secure session management with multiple storage backends and authentication integration.

Installation

npm install @bernierllc/session-manager @bernierllc/crypto-utils

For Redis support:

npm install @bernierllc/session-manager redis

For Express middleware:

npm install @bernierllc/session-manager cookie

Quick Start

import { SessionManager, MemorySessionStorage } from '@bernierllc/session-manager';

// Create session manager
const sessionManager = new SessionManager({
  storage: new MemorySessionStorage(),
  secret: process.env.SESSION_SECRET!,
  maxAge: 24 * 60 * 60 * 1000 // 24 hours
});

// Create new session
const session = await sessionManager.create({
  userId: '123',
  roles: ['user'],
  loginTime: new Date()
});

// Retrieve session
const retrievedSession = await sessionManager.get(session.id);

console.log('Session data:', retrievedSession?.data);

Core Features

  • Multiple Storage: Memory, Redis, database, encrypted cookies
  • Security: Secure session IDs, CSRF protection, session fixation prevention
  • Lifecycle Management: TTL, sliding expiration, automatic cleanup
  • Authentication Integration: User binding, role-based sessions
  • Framework Support: Express, Fastify, Next.js middleware
  • Serialization: JSON, encrypted, compressed session data
  • Monitoring: Session analytics and security tracking

API Reference

SessionManager

Constructor

const sessionManager = new SessionManager(options: SessionOptions)

Options:

  • storage: SessionStorage - Storage backend (required)
  • secret: string - Signing/encryption secret (required)
  • name?: string - Session cookie name (default: 'sessionId')
  • maxAge?: number - Session TTL in milliseconds (default: 24 hours)
  • secure?: boolean - HTTPS only cookies (default: false)
  • httpOnly?: boolean - HTTP only cookies (default: true)
  • sameSite?: 'strict' | 'lax' | 'none' - SameSite cookie attribute (default: 'lax')
  • rolling?: boolean - Refresh TTL on access (default: true)
  • genid?: () => string - Custom session ID generator

Core Methods

// Session operations
await sessionManager.create(initialData?: SessionData): Promise<Session>
await sessionManager.get(sessionId: string): Promise<Session | null>
await sessionManager.destroy(sessionId: string): Promise<void>
await sessionManager.destroyAll(): Promise<void>

// User session management
await sessionManager.getSessionsForUser(userId: string): Promise<Session[]>
await sessionManager.destroyUserSessions(userId: string): Promise<void>
await sessionManager.destroyAllButCurrent(currentSessionId: string, userId: string): Promise<void>

// Security
await sessionManager.regenerateId(session: Session): Promise<void>
await sessionManager.validateSession(sessionId: string, ipAddress?: string, userAgent?: string): Promise<boolean>

// Cleanup
await sessionManager.cleanup(): Promise<number>
sessionManager.startCleanupInterval(intervalMs?: number): void
sessionManager.stopCleanupInterval(): void

// Statistics
await sessionManager.getStats(): Promise<SessionStats>

Session

// Data operations
session.get<T>(key: string): T | undefined
session.set<T>(key: string, value: T): void
session.has(key: string): boolean
session.delete(key: string): boolean
session.clear(): void
session.touch(): void

// Persistence
await session.save(): Promise<void>
await session.reload(): Promise<void>
await session.destroy(): Promise<void>

Usage Examples

Basic Session Management

import { SessionManager, MemorySessionStorage } from '@bernierllc/session-manager';

const sessionManager = new SessionManager({
  storage: new MemorySessionStorage({ maxSessions: 1000 }),
  secret: process.env.SESSION_SECRET!,
  maxAge: 60 * 60 * 1000, // 1 hour
  rolling: true
});

// Create session with user data
const session = await sessionManager.create({
  userId: '123',
  username: 'john_doe',
  roles: ['user', 'premium']
});

// Use session
session.set('lastActivity', new Date());
session.set('preferences', { theme: 'dark', lang: 'en' });

await session.save();

Redis-backed Distributed Sessions

import { SessionManager, RedisSessionStorage } from '@bernierllc/session-manager';

const sessionManager = new SessionManager({
  storage: new RedisSessionStorage({
    host: 'localhost',
    port: 6379,
    keyPrefix: 'sess:',
    password: process.env.REDIS_PASSWORD
  }),
  secret: process.env.SESSION_SECRET!,
  maxAge: 30 * 60 * 1000, // 30 minutes
  rolling: true
});

// Sessions work across multiple application instances
const session = await sessionManager.create({ userId: '456' });

Express Middleware Integration

import express from 'express';
import { createSessionMiddleware, RedisSessionStorage } from '@bernierllc/session-manager';

const app = express();

const sessionMiddleware = createSessionMiddleware({
  storage: new RedisSessionStorage({
    host: 'localhost',
    port: 6379
  }),
  secret: process.env.SESSION_SECRET!,
  name: 'sid',
  maxAge: 24 * 60 * 60 * 1000, // 24 hours
  secure: process.env.NODE_ENV === 'production',
  rolling: true
});

app.use(sessionMiddleware);

// Login route
app.post('/login', async (req, res) => {
  const { username, password } = req.body;
  
  if (await validateCredentials(username, password)) {
    const user = await getUserByUsername(username);
    
    req.session.set('userId', user.id);
    req.session.set('roles', user.roles);
    req.session.set('loginTime', new Date());
    
    await req.session.save();
    res.json({ success: true });
  } else {
    res.status(401).json({ error: 'Invalid credentials' });
  }
});

// Logout route
app.post('/logout', async (req, res) => {
  await req.session.destroy();
  res.clearCookie('sid');
  res.json({ success: true });
});

// Protected route
app.get('/profile', async (req, res) => {
  const userId = req.session.get('userId');
  
  if (!userId) {
    return res.status(401).json({ error: 'Not authenticated' });
  }
  
  const user = await getUserById(userId);
  res.json(user);
});

Advanced Security Features

import { SessionManager } from '@bernierllc/session-manager';

const sessionManager = new SessionManager({
  // ... configuration
});

// Session validation with security checks
async function secureSessionValidation(sessionId: string, req: any) {
  const isValid = await sessionManager.validateSession(
    sessionId,
    req.ip,
    req.headers['user-agent']
  );
  
  if (!isValid) {
    throw new Error('Session validation failed');
  }
  
  const session = await sessionManager.get(sessionId);
  
  // Additional security checks
  if (session && session.data.ipAddress !== req.ip) {
    console.warn(`Suspicious activity: IP changed for session ${sessionId}`);
    await sessionManager.destroy(sessionId);
    throw new Error('Session terminated due to security concerns');
  }
  
  return session;
}

// Session regeneration for privilege escalation
async function escalatePrivileges(session: Session, newRoles: string[]) {
  // Regenerate session ID for security
  await sessionManager.regenerateId(session);
  
  // Update roles
  session.set('roles', newRoles);
  session.set('privilegeEscalation', new Date());
  
  await session.save();
}

Multi-Device Session Management

// Limit concurrent sessions per user
async function enforceSessionLimit(userId: string, maxSessions: number = 3) {
  const userSessions = await sessionManager.getSessionsForUser(userId);
  
  if (userSessions.length >= maxSessions) {
    // Sort by last accessed time, keep most recent
    userSessions.sort((a, b) => 
      b.lastAccessedAt.getTime() - a.lastAccessedAt.getTime()
    );
    
    // Destroy oldest sessions
    const sessionsToDestroy = userSessions.slice(maxSessions - 1);
    for (const session of sessionsToDestroy) {
      await session.destroy();
    }
  }
}

// Logout from all devices except current
app.post('/logout-all-devices', async (req, res) => {
  const currentSessionId = req.sessionID;
  const userId = req.session.get('userId');
  
  await sessionManager.destroyAllButCurrent(currentSessionId, userId);
  
  res.json({ 
    success: true, 
    message: 'Logged out from all other devices' 
  });
});

Session Analytics and Monitoring

// Monitor session activity
setInterval(async () => {
  const stats = await sessionManager.getStats();
  
  console.log(`Session Statistics:
    Active Sessions: ${stats.active}
    Total Created: ${stats.totalCreated}
    Peak Concurrent: ${stats.peakConcurrent}
    Average Duration: ${Math.round(stats.averageDuration / 1000)}s
  `);
  
  // Alert on suspicious activity
  if (stats.active > stats.peakConcurrent * 1.2) {
    console.warn('Unusually high session activity detected');
  }
}, 60000); // Check every minute

// Automatic cleanup
sessionManager.startCleanupInterval(15 * 60 * 1000); // Clean every 15 minutes

// Graceful shutdown
process.on('SIGTERM', async () => {
  console.log('Shutting down session manager...');
  await sessionManager.close();
  process.exit(0);
});

Configuration

Storage Backends

MemorySessionStorage

new MemorySessionStorage({
  maxSessions: 1000        // Maximum number of sessions in memory
})

RedisSessionStorage

new RedisSessionStorage({
  host: 'localhost',
  port: 6379,
  password: 'secret',       // Optional
  db: 0,                    // Database number
  keyPrefix: 'sess:',       // Key prefix for sessions
  connectionString: 'redis://localhost:6379' // Alternative to host/port
})

Security Best Practices

  1. Use Strong Secrets: Generate cryptographically secure secrets
  2. Enable Secure Cookies: Set secure: true in production
  3. Regular Cleanup: Enable automatic session cleanup
  4. Session Regeneration: Regenerate session IDs after authentication
  5. IP Validation: Consider IP address validation for high-security apps
  6. Rolling Sessions: Use rolling expiration to maintain active sessions

Performance Optimization

// Optimize for high-traffic applications
const sessionManager = new SessionManager({
  storage: new RedisSessionStorage({
    // Redis connection pooling
    host: 'redis-cluster',
    port: 6379
  }),
  // Shorter cleanup intervals for active cleanup
  maxAge: 30 * 60 * 1000,   // 30 minutes
  rolling: true,             // Keep active sessions alive
  saveUninitialized: false,  // Don't save empty sessions
  resave: false             // Don't resave unchanged sessions
});

// Efficient cleanup
sessionManager.startCleanupInterval(5 * 60 * 1000); // 5 minutes

Error Handling

try {
  const session = await sessionManager.get(sessionId);
  
  if (!session) {
    throw new Error('Session not found or expired');
  }
  
  // Use session...
} catch (error) {
  console.error('Session error:', error);
  // Handle session errors appropriately
}

Testing

The package includes comprehensive tests covering:

  • Session lifecycle management
  • Security features and validation
  • Storage backend implementations
  • Memory management and cleanup
  • Express middleware integration

Run tests:

npm test
npm run test:coverage

Integration Documentation

Logger Integration

The session manager supports optional logger integration using @bernierllc/logger:

import { SessionManager } from '@bernierllc/session-manager';
import { detectLogger } from '@bernierllc/logger';

const sessionManager = new SessionManager({
  storage: new MemorySessionStorage(),
  secret: process.env.SESSION_SECRET!
});

// Auto-detect logger if available
const logger = await detectLogger();
if (logger) {
  // Enhanced logging for session events
  sessionManager.on('sessionCreated', (sessionId) => {
    logger.info('Session created', { sessionId });
  });
  
  sessionManager.on('sessionDestroyed', (sessionId) => {
    logger.info('Session destroyed', { sessionId });
  });
}

NeverHub Integration

The session manager integrates with NeverHub when available for enhanced service discovery and event communication:

import { SessionManager } from '@bernierllc/session-manager';
import { detectNeverHub } from '@bernierllc/neverhub-adapter';

async function initializeSessionManager() {
  const sessionManager = new SessionManager({
    storage: new MemorySessionStorage(),
    secret: process.env.SESSION_SECRET!
  });

  // Auto-detect NeverHub
  const neverhub = await detectNeverHub();
  if (neverhub) {
    // Register session manager as a service
    await neverhub.register({
      type: 'session-manager',
      name: '@bernierllc/session-manager',
      version: '1.0.0',
      capabilities: [
        { type: 'session', name: 'management', version: '1.0.0' },
        { type: 'auth', name: 'session-auth', version: '1.0.0' }
      ]
    });

    // Publish session events
    sessionManager.on('sessionCreated', async (data) => {
      await neverhub.publishEvent({
        type: 'session.created',
        data: { sessionId: data.sessionId, userId: data.userId }
      });
    });

    // Subscribe to authentication events
    await neverhub.subscribe('auth.login', async (event) => {
      // Create session for authenticated user
      await sessionManager.create({
        userId: event.data.userId,
        roles: event.data.roles
      });
    });
  }

  return sessionManager;
}

Graceful Degradation

The session manager implements graceful degradation patterns:

  • Works without external services: Core functionality operates independently
  • Logger integration: Enhanced logging when logger service is available
  • NeverHub integration: Service discovery and events when NeverHub is present
  • Storage flexibility: Falls back to memory storage if Redis is unavailable

Dependencies

  • Required: @bernierllc/crypto-utils for secure session ID generation
  • Optional: redis for Redis storage backend
  • Optional: cookie for Express middleware support
  • Optional: @bernierllc/logger for enhanced logging capabilities
  • Optional: @bernierllc/neverhub-adapter for service discovery integration

License

Copyright (c) 2025 Bernier LLC. All rights reserved.