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

@vevkit/saga

v0.1.3

Published

A functional, composable logging library for JavaScript/TypeScript applications

Readme

@vevkit/saga

A lightweight, modular logging system designed to be flexible and efficient. Saga provides structured logging with support for custom transports, configurable timestamps, metadata handling, and robust error management.

Features

  • 🎯 Multiple Log Levels: Support for debug, info, warning, and success levels
  • 🕒 Flexible Timestamp Formats: Multiple built-in formats and custom formatting support
  • 🔧 Extensible Transport System: Write logs to any destination with custom transports
  • 📦 Metadata Support: Attach structured data to your logs
  • 👶 Child Loggers: Create loggers with inherited and extended metadata
  • Error Handling: Built-in transport error handling and recovery
  • 🪶 Lightweight: Zero external dependencies

Installation

npm install @vevkit/saga

@vevkit/saga

A powerful, Nordic-inspired logging library for JavaScript/TypeScript applications

Part of the VevKit ecosystem, @vevkit/saga provides a lightweight, pattern-based logging system that emphasizes clarity and meaningful status indicators.

Features

  • 🌟 Six distinct log levels with Nordic-inspired symbols
  • 🧬 Class-based architecture
  • 🎨 Visual log hierarchy
  • 🧩 Composable logging patterns
  • 🎯 TypeScript-first development
  • 🔍 Structured metadata support
  • 🌳 Hierarchical logger creation
  • 🎭 Flexible formatting options

Installation

npm install @vevkit/saga

Quick Start

import { createLogger } from '@vevkit/saga';

// Create a base logger
const logger = createLogger({ level: 'info' });

// Log at different levels
logger.critical('System crash imminent');     // ⚡ System crash imminent
logger.error('Database connection failed');   // ✕ Database connection failed
logger.success('Operation completed');        // ▲ Operation completed
logger.warning('Resource running low');       // ▼ Resource running low
logger.info('Processing request');           // ◆ Processing request
logger.debug('Cache miss');                  // ● Cache miss

// Add metadata
logger.error('Authentication failed', { 
  userId: '123', 
  reason: 'invalid_token' 
});

// Create specialized logger
const apiLogger = logger.child({
  metadata: { service: 'api' }
});

apiLogger.warning('Rate limit approaching');

Log Levels

@vevkit/saga uses Nordic-inspired symbols to provide clear visual hierarchy in logs:

| Level | Symbol | Usage | Example | |----------|--------|----------------------------------------------|-----------------------------------| | Critical | ⚡ | System-wide emergencies requiring immediate action | "Service completely unavailable" | | Error | ✕ | Error conditions that need attention | "Failed to connect to database" | | Success | ▲ | Successful operations and completions | "Payment processed successfully" | | Warning | ▼ | Warning conditions or potential issues | "High memory usage detected" | | Info | ◆ | General informational messages | "Application started" | | Debug | ● | Detailed debug information | "Cache hit for key: user:123" |

Configuration

interface LoggerConfig {
  level?: 'critical' | 'error' | 'success' | 'warning' | 'info' | 'debug';
  pattern?: string;
  metadata?: Record<string, any>;
  formatters?: {
    timestamp?: (date: Date) => string;
    message?: (entry: LogEntry) => string;
  };
}

// Example configuration
const logger = createLogger({
  level: 'info',            // Minimum log level
  metadata: {               // Global metadata
    service: 'auth',
    version: '1.0.0'
  },
  formatters: {            // Custom formatters
    timestamp: (date) => date.toISOString(),
    message: (entry) => `[${entry.timestamp}] ${entry.symbol} ${entry.message}`
  }
});

Basic Usage

Simple Logging

import { Logger } from '@vevkit/saga';

// Create a default logger
const logger = new Logger();

// Log at different levels
logger.info('Application started');
logger.success('Operation completed successfully');
logger.warning('Resource usage high');
logger.debug('Connection details:', { host: 'localhost', port: 3000 });

Custom Timestamp Formats

import { Logger } from '@vevkit/saga';

// Available timestamp presets
const logger1 = new Logger({ timestamp: 'short' });     // 14:32:24
const logger2 = new Logger({ timestamp: 'time' });      // 14:32:24.432
const logger3 = new Logger({ timestamp: 'date' });      // 2024-11-22
const logger4 = new Logger({ timestamp: 'datetime' });  // 2024-11-22 14:32:24
const logger5 = new Logger({ timestamp: 'iso' });       // 2024-11-22T14:32:24.432Z
const logger6 = new Logger({ timestamp: 'compact' });   // 20241122143224
const logger7 = new Logger({ timestamp: 'relative' });  // 2s ago
const logger8 = new Logger({ timestamp: 'none' });      // No timestamp

// Custom timestamp format
const logger9 = new Logger({
  timestamp: {
    custom: (date) => `[${date.getHours()}:${date.getMinutes()}]`
  }
});

Working with Metadata

// Base logger with common metadata
const logger = new Logger({
  metadata: {
    service: 'user-service',
    version: '1.0.0'
  }
});

// Add request-specific metadata
logger.info('Processing request', {
  requestId: '123',
  userId: '456'
});
// Output: 2024-11-22 14:32:24 ◆ Processing request
// Metadata: { service: 'user-service', version: '1.0.0', requestId: '123', userId: '456' }

// Create a child logger with additional metadata
const requestLogger = logger.child({
  metadata: {
    requestId: '123',
    route: '/api/users'
  }
});

requestLogger.info('Request received');
// Output: 2024-11-22 14:32:24 ◆ Request received
// Metadata: { service: 'user-service', version: '1.0.0', requestId: '123', route: '/api/users' }

Custom Transports

import { Logger, Transport, LogEntry } from '@vevkit/saga';

// Create a custom transport
class FileTransport implements Transport {
  constructor(private filepath: string) {}

  log(entry: LogEntry): void {
    // Implementation for writing to file
    const logLine = `${entry.formattedMessage}\n`;
    // Write logLine to this.filepath
  }

  // Optional cleanup method
  async close(): Promise<void> {
    // Cleanup resources
  }
}

// Use multiple transports
const logger = new Logger({
  transports: [
    new ConsoleTransport(),
    new FileTransport('./app.log')
  ]
});

// Add/remove transports dynamically
const fileTransport = new FileTransport('./errors.log');
logger.addTransport(fileTransport);
logger.removeTransport(fileTransport);

Error Handling

const logger = new Logger({
  transports: [myTransport],
  failureThreshold: 3,  // Remove transport after 3 failures
  onTransportError: (error) => {
    console.error('Transport error:', error.message);
  }
});

Transport System

Saga uses a transport system to handle log output. Each transport implements the Transport interface:

interface Transport {
  log(entry: LogEntry): void;
  close?(): Promise<void>;
}

Built-in transports:

  • ConsoleTransport: Outputs logs to the console (default)
  • MemoryTransport: Stores logs in memory (useful for testing)

Creating Custom Transports

import { Transport, LogEntry } from '@vevkit/saga';

class CustomTransport implements Transport {
  log(entry: LogEntry): void {
    // Access various properties of the log entry
    const {
      level,          // 'debug' | 'info' | 'warning' | 'success'
      message,        // The log message
      timestamp,      // Date object
      metadata,       // Additional metadata object
      formattedMessage // Pre-formatted message string
    } = entry;

    // Implement custom logging logic
  }

  // Optional cleanup method
  async close(): Promise<void> {
    // Cleanup any resources
  }
}

Configuration Options

interface LoggerConfig {
  // Log level filtering
  level?: 'debug' | 'info' | 'warning' | 'success';
  
  // Timestamp configuration
  timestamp?: TimestampPreset | {
    preset?: TimestampPreset;
    custom?: (date: Date) => string;
  };
  
  // Base metadata for all logs
  metadata?: Record<string, any>;
  
  // Transport configuration
  transports?: Transport[];
  failureThreshold?: number;
  
  // Error handling
  onTransportError?: (error: TransportError) => void;
  
  // Transport validation
  validation?: {
    throwOnInvalid?: boolean;
    requireClose?: boolean;
  };
}

Log Levels

  • debug: Detailed information for debugging
  • info: General information about system operation
  • warning: Potentially harmful situations
  • success: Successful operations or positive outcomes

Each level has its own symbol in the output:

  • Debug: ●
  • Info: ◆
  • Warning: ▼
  • Success: ▲

Best Practices

  1. Use Child Loggers: Create child loggers for different components or request contexts:

    const apiLogger = logger.child({ metadata: { component: 'api' }});
    const dbLogger = logger.child({ metadata: { component: 'database' }});
  2. Structured Metadata: Use metadata for structured data instead of string interpolation:

    // Good
    logger.info('User created', { userId: '123', email: '[email protected]' });
       
    // Avoid
    logger.info(`User created: ${userId} with email ${email}`);
  3. Transport Error Handling: Always configure error handling for custom transports:

    const logger = new Logger({
      transports: [myTransport],
      failureThreshold: 3,
      onTransportError: (error) => {
        // Handle or report error
      }
    });

License

MIT

Contributing

VevKit is an organization of independent, specialized libraries. If you'd like to contribute to Saga, please:

  1. Fork the repository
  2. Create a feature branch
  3. Submit a pull request

For bugs, questions, and discussions, please use the GitHub Issues.