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

@ashulab/universal-logger

v0.1.0

Published

Isomorphic logger for Node.js and the browser — log levels, scoped loggers, structured server output and provider-agnostic error reporting, with zero config.

Downloads

43

Readme

universal-logger

Isomorphic logger for Node.js and the browser. It auto-detects the execution context and adjusts behavior — structured object logs on the server, formatted strings on the client — with a single, consistent API and no configuration required.

  • 🌐 Universal: same import works on server and client (import-safe even when process is not defined in the browser).
  • 🎚️ Log levels: debug, info, warn, error behind a single min-level threshold.
  • 🏷️ Scoped loggers: prefix every log with a module/service name.
  • 🧱 Structured server output: JSON in production, readable objects in dev.
  • 🪝 Provider-agnostic error reporting: wire any sink — Sentry, Datadog, a custom endpoint.
  • 📦 ESM-only, zero runtime dependencies.

Install

npm install universal-logger

Requires Node.js >= 18. ESM only — use import, not require.

Usage

import { logInfo, logError, createScopedLogger } from 'universal-logger';

logInfo('Server started', { port: 3000 });

try {
  await fetchData();
} catch (err) {
  logError('Failed to fetch data', err, { url: '/api/data' });
}

const log = createScopedLogger('AuthService');
log.debug('Checking token');
log.info('User authenticated');

Behavior by environment

| | Server (Node.js) | Client (browser) | |---|---|---| | Format | Structured object / JSON | Formatted string | | Default min level | debug in dev, warn in prod | debug in dev, warn in prod | | Prefix | none | [App] |

A single min-level threshold governs what is logged, with the same model on server and client: in development (NODE_ENV=development) everything from debug up; in production only warn and error. Override it anytime via configureUniversalLogger({ minLevel }) or the LOG_LEVEL env var.

On the server, dev mode prints readable objects; otherwise it emits one-line JSON suitable for log collectors.

Configuration

import { configureUniversalLogger, LogLevel } from 'universal-logger';

configureUniversalLogger({
  enabled: true,
  minLevel: LogLevel.INFO,
  prefix: '[MyApp]',
});

Environment variables

| Variable | Effect | |---|---| | LOG_LEVEL | Sets the default min level (debug | info | warn | error). Read on the server; on the client set the level via configureUniversalLogger. | | NODE_ENV=development | When LOG_LEVEL is unset, lowers the default to debug and switches server output to readable objects. |

Error reporting (provider-agnostic)

logError forwards exceptions to a reporter of your choosing — Sentry, Datadog, Rollbar, a custom endpoint, anything — on both server and client. Only configureUniversalLogger({ enabled: false }) stops it.

The reporter receives the original error untouched (or a synthetic Error when logError is called without one) plus { message, context }, and is responsible for shaping it for its provider. Register it once at startup:

import * as Sentry from '@sentry/node';
import { setErrorReporter } from 'universal-logger';

setErrorReporter((error, { message, context }) => {
  Sentry.captureException(error instanceof Error ? error : new Error(message), {
    extra: { message, ...context },
  });
});

Any other provider follows the same shape:

setErrorReporter((error, { message, context }) => {
  myMonitoring.report({ error, message, ...context });
});

API

| Export | Description | |---|---| | logDebug(message, context?) | Debug-level log | | logInfo(message, context?) | Info-level log | | logWarn(message, context?) | Warning-level log | | logError(message, error?, context?) | Error-level log; forwards to the error reporter | | createScopedLogger(scope) | Returns { debug, info, warn, error } prefixed with [scope] | | configureUniversalLogger(config) | Override enabled / minLevel / prefix | | setErrorReporter(fn) | Register a provider-agnostic error reporter | | LogLevel | Enum: DEBUG, INFO, WARN, ERROR |

Scripts

npm run build      # bundle to dist/ (ESM + .d.ts) with tsup
npm run dev        # build in watch mode
npm run typecheck  # tsc --noEmit
npm test           # build + run the node:test suite

License

MIT © Diego Ghersi