@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
enableOutputoption - 📦 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/loggeryarn
yarn add @cmtlyt/loggerpnpm
pnpm add @cmtlyt/loggerQuick 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, defaulttrueoptions.maxNestingDepth(Number, optional): Maximum nesting depth, default3options.transform(Function, optional): Data transformation function that receives({ type, messages, isNestingCall })parametersoptions.report(Function, optional): Data reporting function that receives({ type, messages, isNestingCall, data })parametersoptions.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 configurationenable(Boolean): Whether to enable grouping, defaulttruecollapsed(Boolean): Whether to collapse groups, defaultfalse
options.consoleLevel(String, optional): Console output level, options'debug'|'info'|'log'|'warn', default'log'options.allowTypes(Array|Set|Function, optional): Allowed log types filteroptions.getSubTitle(Function, optional): Function to get subtitleoptions.getMessages(Function, optional): Function to get messagesoptions.customStyle(Function, optional): Function to customize styles and themesoptions.getWindowWidth(Function, optional): Function to get window width for layoutoptions.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, defaulttrueoptions.outputLevel(String, optional): Console output level, options'log'|'info'|'warn'|'error', default'log'options.allowTypes(Array|Set|Function, optional): Allowed log types filteroptions.format(String, optional): Output format string with placeholdersoptions.getLabel(Function, optional): Function to get labeloptions.getMessages(Function, optional): Function to get messagesoptions.formatDate(Function, optional): Function to format dateoptions.customColors(Function, optional): Function to customize colorsoptions.customColorizer(Function, optional): Function to customize color applicationoptions.textCleaner(Function, optional): Function to clean formatted textoptions.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
enableOutputoption 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
