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

@cmtlyt/logger

v0.5.0

Published

[中文文档](./README-zh.md) | English

Downloads

566

Readme

@cmtlyt/logger

中文文档 | English

Introduction

@cmtlyt/logger is a modern, lightweight, cross-platform logging library that focuses on beautifying console output and providing flexible extensibility. It supports both Node.js and Web environments, offering advanced features like data reporting, custom adapters, nested call protection, and output control mechanisms.

Features

  • 🌍 Cross-Platform Support - Works seamlessly in both Node.js and Web environments
  • 📊 Data Reporting Capability - Supports custom data transformation and reporting mechanisms
  • 🔌 Plugin Adapters - Supports custom output adapters for flexible extension
  • 🎨 Beautified Output - Built-in adapters provide beautiful console styling with customizable themes
  • 🛡️ Nested Call Protection - Advanced state machine to prevent stack overflow with configurable depth limits
  • 🎛️ Output Control - Fine-grained control over log output with enableOutput option
  • 📦 Lightweight - No external dependencies, small footprint
  • 🛠️ TypeScript Support - Complete type definition support with comprehensive JSDoc documentation
  • 🎯 Environment Detection - Automatic environment detection and validation
  • 🔄 Circular Reference Handling - Safe handling of circular references in logged objects
  • 🎨 Rich Styling - Support for colors, gradients, and custom themes (Web adapter)

Installation

npm

npm i @cmtlyt/logger

yarn

yarn add @cmtlyt/logger

pnpm

pnpm add @cmtlyt/logger

Quick Start

Basic Usage

import { createLogger } from "@cmtlyt/logger";

const logger = createLogger();

// Output logs of different levels
logger.debug("This is a debug message");
logger.info("This is an info message");
logger.warn("This is a warning message");
logger.error("This is an error message");

Using Web Adapter (Browser)

import { createLogger } from "@cmtlyt/logger";
import { webConsoleAdapter } from "@cmtlyt/logger/adapters/web";

const logger = createLogger({
  outputAdapters: [webConsoleAdapter()],
});

logger.info("This will be output with beautified styling");

Using Node.js Adapter (Server)

import { createLogger } from "@cmtlyt/logger";
import { nodeConsoleAdapter } from "@cmtlyt/logger/adapters/node";

const logger = createLogger({
  outputAdapters: [nodeConsoleAdapter({
    enableColors: true,
    format: "[%type][%date] %message",
  })],
});

logger.info("This will be output with colors in Node.js");

Advanced Configuration

import { createLogger } from "@cmtlyt/logger";
import { webConsoleAdapter } from "@cmtlyt/logger/adapters/web";

const logger = createLogger({
  // Output control - can be boolean or function
  enableOutput: ({ type }) => type !== 'debug' || process.env.NODE_ENV === 'development',

  // Maximum nesting depth to prevent stack overflow
  maxNestingDepth: 3,

  // Data transformation function
  transform({ type, messages, isNestingCall }) {
    const [point, params, ...otherMessages] = messages;
    return {
      type,
      point,
      params,
      messages: otherMessages,
      isNesting: isNestingCall,
      timestamp: Date.now(),
    };
  },

  // Data reporting function
  report({ data }) {
    // Send data to analytics service
    if (data.type === 'error') {
      fetch('/api/error-tracking', {
        method: 'POST',
        body: JSON.stringify(data)
      });
    }
  },

  // Output adapters
  outputAdapters: [
    webConsoleAdapter({
      group: {
        enable: true,
        collapsed: false,
      },
      consoleLevel: "info",
      allowTypes: ['info', 'warn', 'error'], // Filter log types
      getSubTitle: (info) => info.transformData?.point || "",
      getMessages: (info) => info.messages.slice(1),
      customStyle: (info) => {
        // Customize theme colors
        info.theme.primary = "#007bff";
        info.baseStyle.fontSize = "12px";
        return info;
      },
    }),
  ],
});

logger.info("user_login", { userId: 123 }, "User login", "Extra info");

Core Features

Output Control with enableOutput

The enableOutput option provides fine-grained control over log output while preserving data processing:

const logger = createLogger({
  // Boolean control
  enableOutput: false, // Disables all output but keeps transform/report

  // Function control for dynamic behavior
  enableOutput: ({ type, messages, data }) => {
    // Only output errors in production
    if (process.env.NODE_ENV === 'production') {
      return type === 'error';
    }
    // Output everything in development
    return true;
  },

  transform({ type, messages }) {
    return { type, messages, timestamp: Date.now() };
  },

  report({ data }) {
    // This still executes even when enableOutput is false
    sendToAnalytics(data);
  }
});

Nested Call Protection

The logger includes advanced protection against stack overflow through a sophisticated state machine. This prevents infinite recursion when logger functions are called within transform/report functions:

const logger = createLogger({
  maxNestingDepth: 3, // Maximum allowed nesting depth
  transform({ type, messages, isNestingCall }) {
    // This could potentially cause nested calls
    if (!isNestingCall) {
      logger.debug("Transform called for", type); // Nesting level 1
    }
    return { type, messages, isNesting: isNestingCall };
  },
  report({ data }) {
    // This could also cause nested calls
    if (!data.isNesting) {
      logger.info("Reporting data", data); // Nesting level 2
    }
  }
});

// The logger automatically tracks nesting depth and discards calls
// that exceed the maximum depth to prevent stack overflow
logger.info("This triggers transform and report functions");

Cross-Platform Adapters

Web Adapter Features

  • Beautiful console styling with CSS
  • Support for gradients and custom themes
  • Grouping and collapsing
  • Custom window width detection

Node.js Adapter Features

  • Color support via yoctocolors
  • Customizable output formats
  • Text cleaning and formatting
  • Environment-specific optimizations

Custom Adapters

Create your own output adapters:

import { defineAdapter } from "@cmtlyt/logger/adapters";

const customAdapter = defineAdapter((options) => {
  return (type) => {
    // Return null to skip this type
    if (type === 'debug' && !options.enableDebug) {
      return null;
    }

    // Return output function
    return (info) => {
      // Custom output logic
      const timestamp = new Date().toISOString();
      console.log(`[${timestamp}] [${type.toUpperCase()}]`, ...info.messages);
    };
  };
});

const logger = createLogger({
  outputAdapters: [customAdapter({ enableDebug: false })],
});

Environment Detection

Both adapters automatically detect their respective environments:

import { webConsoleAdapter, isWeb } from "@cmtlyt/logger/adapters/web";
import { nodeConsoleAdapter, isNode } from "@cmtlyt/logger/adapters/node";

// Manual environment checks
if (isWeb()) {
  console.log("Running in browser");
}

if (isNode()) {
  console.log("Running in Node.js");
}

// Automatic environment validation in adapters
const logger = createLogger({
  outputAdapters: [
    webConsoleAdapter({
      isEnvironmentValid: () => typeof window !== 'undefined',
    }),
    nodeConsoleAdapter({
      isEnvironmentValid: () => typeof process !== 'undefined',
    }),
  ],
});

API Reference

createLogger(options)

Creates a logger instance.

Parameters:

  • options.enableOutput (Boolean|Function, optional): Controls log output, default true
  • options.maxNestingDepth (Number, optional): Maximum nesting depth, default 3
  • options.transform (Function, optional): Data transformation function that receives ({ type, messages, isNestingCall }) parameters
  • options.report (Function, optional): Data reporting function that receives ({ type, messages, isNestingCall, data }) parameters
  • options.outputAdapters (Array, optional): Array of output adapters

Return Value:

A logger object with methods for different log levels: debug, info, warn, error, etc.

webConsoleAdapter(options)

Creates a Web console adapter with advanced styling and configuration options.

Parameters:

  • options.group (Object, optional): Group configuration
    • enable (Boolean): Whether to enable grouping, default true
    • collapsed (Boolean): Whether to collapse groups, default false
  • options.consoleLevel (String, optional): Console output level, options 'debug' | 'info' | 'log' | 'warn', default 'log'
  • options.allowTypes (Array|Set|Function, optional): Allowed log types filter
  • options.getSubTitle (Function, optional): Function to get subtitle
  • options.getMessages (Function, optional): Function to get messages
  • options.customStyle (Function, optional): Function to customize styles and themes
  • options.getWindowWidth (Function, optional): Function to get window width for layout
  • options.isEnvironmentValid (Function, optional): Environment validation function

nodeConsoleAdapter(options)

Creates a Node.js console adapter with color support and formatting options.

Parameters:

  • options.enableColors (Boolean, optional): Enable color output, default true
  • options.outputLevel (String, optional): Console output level, options 'log' | 'info' | 'warn' | 'error', default 'log'
  • options.allowTypes (Array|Set|Function, optional): Allowed log types filter
  • options.format (String, optional): Output format string with placeholders
  • options.getLabel (Function, optional): Function to get label
  • options.getMessages (Function, optional): Function to get messages
  • options.formatDate (Function, optional): Function to format date
  • options.customColors (Function, optional): Function to customize colors
  • options.customColorizer (Function, optional): Function to customize color application
  • options.textCleaner (Function, optional): Function to clean formatted text
  • options.isEnvironmentValid (Function, optional): Environment validation function

Utility Functions

defineAdapter(callback)

Helper function for creating type-safe adapters.

objectStringify(obj)

Safely stringify objects with function and circular reference handling.

isWeb()

Detect if running in a web browser environment.

isNode()

Detect if running in a Node.js environment.

Examples

Basic Cross-Platform Usage

import { createLogger } from "@cmtlyt/logger";
import { webConsoleAdapter } from "@cmtlyt/logger/adapters/web";
import { nodeConsoleAdapter } from "@cmtlyt/logger/adapters/node";

const logger = createLogger({
  outputAdapters: [
    // Will only work in browser
    webConsoleAdapter(),
    // Will only work in Node.js
    nodeConsoleAdapter({ enableColors: true }),
  ],
});

logger.info("This works in both environments!");

Conditional Output Control

const logger = createLogger({
  enableOutput: ({ type, data }) => {
    // Only log errors in production
    if (process.env.NODE_ENV === 'production') {
      return type === 'error';
    }
    
    // Log everything in development
    return true;
  },
  
  transform({ type, messages }) {
    return {
      level: type,
      message: messages.join(' '),
      timestamp: Date.now(),
      environment: process.env.NODE_ENV
    };
  },
  
  report({ data }) {
    // Always report to analytics, regardless of enableOutput
    if (data.level === 'error') {
      sendErrorToService(data);
    }
  }
});

Advanced Node.js Formatting

import { nodeConsoleAdapter } from "@cmtlyt/logger/adapters/node";

const logger = createLogger({
  outputAdapters: [
    nodeConsoleAdapter({
      format: "[%type][%label][%date] %message %othermessages",
      getLabel: (info) => `APP-${info.type.toUpperCase()}`,
      formatDate: (date) => date.toLocaleString('en-US'),
      customColors: ({ type }) => {
        const colorMap = {
          info: { type: 'cyan', message: 'white' },
          warn: { type: 'yellow', message: 'yellow' },
          error: { type: 'red', message: 'red' },
        };
        return colorMap[type] || {};
      },
      textCleaner: (text) => text.replace(/\s+/g, ' ').trim(),
    }),
  ],
});

Web Styling with Gradients

import { webConsoleAdapter } from "@cmtlyt/logger/adapters/web";

const logger = createLogger({
  outputAdapters: [
    webConsoleAdapter({
      customStyle: ({ type, theme, baseStyle }) => {
        if (type === 'info') {
          theme.primary = 'linear-gradient(45deg, #007bff, #0056b3)';
        } else if (type === 'error') {
          theme.primary = 'linear-gradient(45deg, #dc3545, #c82333)';
        }
        return { theme, baseStyle };
      },
    }),
  ],
});

See example files for more comprehensive usage examples.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Changelog

v0.5.0

  • 🌍 Cross-Platform Support - Added Node.js adapter with full feature parity
  • 🎛️ Output Control - New enableOutput option for fine-grained output control
  • 🎨 Enhanced Styling - Improved gradient support and custom theme capabilities
  • 🔧 Better TypeScript - Enhanced type definitions and JSDoc documentation
  • Performance - Optimized nested call handling and adapter selection
  • 🐛 Bug Fixes - Fixed nested depth control logic and circular reference handling

v0.4.0

  • 🛡️ Implemented nested call protection with state machine to prevent stack overflow
  • ⚡ Performance optimizations for nested call handling
  • 🔧 Enhanced TypeScript support with comprehensive JSDoc documentation
  • 🐛 Fixed circular reference handling in object serialization

v0.3.1

  • 📚 Initial JSDoc documentation coverage
  • 🔧 Basic TypeScript improvements
  • 🐛 Minor bug fixes