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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@majee/logger

v1.0.2

Published

A modular, TypeScript-first logger for Node.js applications with:

Downloads

1,116

Readme

@majee/logger

A modular, TypeScript-first logger for Node.js applications with:

  • Pluggable transports (console, file, MongoDB, custom)
  • Configurable formatters (JSON, pretty)
  • Global and per-transport log level filtering
  • Async context support (request-scoped metadata, requestId, userId, etc.)
  • A clean split between:
    • @majee/logger-core – low-level primitives (transports, formatters, context)
    • @majee/logger – ergonomic API and public surface

Consumers only import from @majee/logger.
The internal @majee/logger-core package is published separately for infrastructure / tooling reuse.


Installation

npm install @majee/logger
# or
pnpm add @majee/logger
# or
yarn add @majee/logger

If you plan to use the MongoDB transport, also install the MongoDB driver:

npm install mongodb

Quick Start

import {
  Logger,
  ConsoleTransport,
  JsonFormatter
} from "@majee/logger";

const logger = new Logger({
  level: "info",
  formatter: new JsonFormatter(),
  transports: [
    { transport: new ConsoleTransport() }
  ]
});

logger.info("Application started");
logger.debug("This will not be shown at level=info");
logger.error("Something went wrong");
await logger.flush();

Concepts

Logger

Logger is the main entry point. It:

  • creates structured log entries (ILogEntry)
  • applies formatter(s) to convert them to strings
  • fans out to one or more transports
import { Logger, JsonFormatter } from "@majee/logger";

const logger = new Logger({
  level: "debug",                // global minimum log level
  formatter: new JsonFormatter(),// global default formatter
  transports: [ /* see below */ ]
});

Transports

A transport is anything that receives a string and writes it somewhere:

  • ConsoleTransport – writes to stdout
  • FileTransport – appends to a file
  • MongoTransport – inserts documents into MongoDB
import {
  Logger,
  ConsoleTransport,
  FileTransport,
  MongoTransport,
  JsonFormatter,
  PrettyFormatter
} from "@majee/logger";
import { MongoClient } from "mongodb";

async function main() {
  const client = new MongoClient("mongodb://localhost:27017");
  await client.connect();

  const logger = new Logger({
    level: "debug",
    formatter: new JsonFormatter(), // default for transports without custom formatter
    transports: [
      {
        transport: new ConsoleTransport(),
        formatter: new PrettyFormatter(), // console: pretty-colored single-line logs
        minLevel: "info"                  // console logs >= info
      },
      {
        transport: new FileTransport("logs/app.log"),
        // inherits global JsonFormatter
        minLevel: "debug"                 // file logs everything >= debug
      },
      {
        transport: new MongoTransport({
          client,
          dbName: "logs_db",
          collectionName: "app_logs"
        }),
        // inherits global JsonFormatter (Mongo expects JSON)
        minLevel: "warn"                  // Mongo logs >= warn
      }
    ]
  });

  logger.debug("Debug log (file only)");
  logger.info("Info log (console + file)");
  logger.warn("Warn log (console + file + Mongo)");
  logger.error("Error log (console + file + Mongo)");
  await logger.flush();
  await client.close();
}

main().catch(err => {
  console.error("Failed to run logger demo", err);
});

Formatters

Formatters convert structured log entries (ILogEntry) into strings.

Built-ins:

  • JsonFormatter – log entries as JSON lines
  • PrettyFormatter – human-readable, colored console output
import {
  JsonFormatter,
  PrettyFormatter
} from "@majee/logger";

// Global formatter:
const logger = new Logger({
  formatter: new JsonFormatter(),
  transports: [
    { transport: new ConsoleTransport() } // JSON to console
  ]
});

// Per-transport formatter:
const logger2 = new Logger({
  formatter: new JsonFormatter(), // default
  transports: [
    {
      transport: new ConsoleTransport(),
      formatter: new PrettyFormatter()
    },
    {
      transport: new FileTransport("logs/app.log") // uses JsonFormatter
    }
  ]
});

Levels

Available log levels:

  • debug
  • info
  • warn
  • error

Global level is configured on Logger:

const logger = new Logger({ level: "info" }); // debug is filtered out

Each transport can also specify a minLevel:

const logger = new Logger({
  level: "debug",
  transports: [
    {
      transport: new ConsoleTransport(),
      formatter: new PrettyFormatter(),
      minLevel: "info"
    },
    {
      transport: new FileTransport("logs/app.log"),
      minLevel: "debug"
    }
  ]
});

Context (request-scoped metadata)

The logger supports async context (via AsyncLocalStorage):

  • Attach a context (e.g. requestId, userId) to an async flow.
  • All logs in that flow will automatically carry that context into formatters/JSON.
import { Logger, JsonFormatter } from "@majee/logger";

const logger = new Logger({
  level: "info",
  formatter: new JsonFormatter(),
  transports: [{ transport: new ConsoleTransport() }]
});

// Wrap a request/operation in a context
logger.runWithContext({ requestId: "req-123", userId: "u-42" }, async () => {
  logger.info("Handling request");
  await doSomething();
  logger.error("Something failed");
});

Inside formatters, entry.context is available for inclusion in output (e.g. JSON or pretty formatting).


API Overview

new Logger(options?: LoggerOptions)

interface TransportConfig {
  transport: ITransport;
  formatter?: IFormatter;
  minLevel?: LogLevel;
}

interface LoggerOptions {
  level?: LogLevel;               // default "info"
  transports?: TransportConfig[]; // default: ConsoleTransport + JsonFormatter
  formatter?: IFormatter;         // default: JsonFormatter
  contextManager?: ContextManager;// optional custom context manager
}

Logging methods

logger.debug(message: string): void;
logger.info(message: string): void;
logger.warn(message: string): void;
logger.error(message: string): void;

Context methods

logger.runWithContext(ctx: Context, fn: () => any): any;
logger.mergeContext(partial: Context): void;
logger.getContext(): Context;

Types and Low-Level APIs

For advanced usage:

import {
  Logger,
  ConsoleTransport,
  FileTransport,
  MongoTransport,
  JsonFormatter,
  PrettyFormatter,
  LogLevels,
  type LogLevel,
  type ILogEntry,
  type ITransport,
  type IFormatter,
  type Context,
  ContextManager
} from "@majee/logger";

You can use ContextManager directly if you need more control, or write your own transports/formatters.