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

@meyerzon/verbose-log

v0.1.0

Published

A console proxy gated by a VERBOSE threshold. Drop-in console for Node and the browser with per-call verbosity levels.

Readme

@meyerzon/verbose-log

CI npm types zero dependencies coverage

A console proxy gated by a VERBOSE threshold. Use it exactly like the built-in console, but attach a verbosity level to any call and let the environment decide what actually prints.

  • Zero dependencies, dual ESM + CJS with full .d.ts types.
  • Node ≥ 20 and browsers.
  • Higher VERBOSE = more output, just like -v / -vv / -vvv.
  • Live: change VERBOSE (or localStorage) at runtime, next call obeys — no restart, no page refresh.
  • Devtools-friendly: passing calls keep your original file/line.
  • Typed named levels with autocomplete and typo protection.

Install

npm install @meyerzon/verbose-log

Usage

import { log } from "@meyerzon/verbose-log";

log.info("always shown");          // rank 0 (base)
log.v(1).info("shown at VERBOSE>=1");
log.v(2).warn("shown at VERBOSE>=2");

// The full console surface is proxied:
log.v(1).table([{ a: 1 }]);
log.group("scope");
log.v(2).debug("deep detail");
log.groupEnd();

.v(n) scopes the next call to verbosity level n. A plain call is level 0.

Gating rules

VERBOSE is a threshold: a call at rank L prints when L <= VERBOSE. Higher VERBOSE = more output (the -v / -vv mental model). Levels are ranks 0..max-1 (max defaults to 3, so ranks 0, 1, 2).

| VERBOSE | Prints | Like | | -------------- | --------------------------------------- | ------ | | unset or 0 | base (rank 0) only | | | 1 | ranks 0–1 | -v | | 2 | ranks 0–2 (everything, at default max) | -vv | | n | ranks 0..n | | | true / all | every level | | | off / false| nothing — silences even the base | |

node app.js             # base only
VERBOSE=1 node app.js   # base + level 1
VERBOSE=2 node app.js   # everything (default max)
VERBOSE=off node app.js # silence completely

Named levels

Give levels names instead of bare numbers. They are an ordered list (low -> high verbosity); the index is the rank, and levels[0] is the base. Names are fully typed — autocomplete at call sites, typos rejected by the compiler. VERBOSE accepts a name or a number.

import { createLogger } from "@meyerzon/verbose-log";

const log = createLogger({ levels: ["info", "debug", "trace"] });
//                          info=0 (base), debug=1, trace=2

log.info("always shown");        // rank 0
log.v("debug").info("detail");   // rank 1
log.v("trace").info("deep");     // rank 2
log.v(1).info("same as debug");  // numbers still work

// @ts-expect-error — not a configured level
log.v("trcae").info("typo caught at compile time");
VERBOSE=info  node app.js   # base only
VERBOSE=debug node app.js   # info + debug
VERBOSE=trace node app.js   # everything
VERBOSE=1     node app.js   # same as VERBOSE=debug

Why this is useful

  • Readable call sitesv("trace") says what v(2) cannot.

  • Typo protection — an unknown level fails tsc; at runtime .v() throws a RangeError that lists the valid names.

  • CLI -v / -vv / -vvv — count the flags and feed the rank in:

    const verbosity = (process.argv.join(" ").match(/-v/g) ?? []).length;
    const log = createLogger({ maxLevels: 3, level: Math.min(verbosity, 2) });
  • Per-module namespaces — there is no debug-style namespace selector, but a distinct env var per module gives the same selective control:

    const log = createLogger({ envVar: "VERBOSE_DB" }); // VERBOSE_DB=2 node app.js
  • Bounded granularity for library authorsmaxLevels (or a fixed levels list) caps how verbose consumers can get, keeping the VERBOSE vocabulary small and stable.

Strict vs lenient

  • .v() is strict — an out-of-range number, a non-integer, or an unknown name throws RangeError. This is your code; mistakes should surface.
  • VERBOSE / level / resolve are lenient — out-of-range numbers are clamped into [-1, max-1] and unrecognized values fall back gracefully. External input must never crash the app.

Browser

There is no process.env in the browser, so the threshold is resolved from, in order:

  1. a global variable — globalThis.VERBOSE
  2. localStorage.getItem("VERBOSE")
globalThis.VERBOSE = 1;
// or, persisted across reloads:
localStorage.setItem("VERBOSE", "2");

Both honor a custom envVar, so createLogger({ envVar: "DEBUG_X" }) reads globalThis.DEBUG_X / localStorage.DEBUG_X. Unlike debug, a change takes effect on the next call — no page refresh.

Chrome/Edge gotcha: console.debug output is hidden unless the devtools console Verbose log level is enabled. If log.v(n).debug(...) passes the threshold but you see nothing, check that filter — it's a devtools default, not this library.

Stripping logs in production

log.* calls are ordinary function calls with side effects, so bundlers cannot tree-shake them away. To drop them from a production build, use your minifier:

// terser / esbuild minify options
{ compress: { drop_console: true } }
// or target only this lib's entry point via pure_funcs / a wrapper

Or gate at the source by pointing resolve/level at your build mode.

Customizing

import { createLogger } from "@meyerzon/verbose-log";

const log = createLogger({
  envVar: "MY_VERBOSE",       // read a different env var (default "VERBOSE")
  level: 1,                   // hard-code the threshold; skips env lookup
  console: myConsole,         // proxy a custom console
  resolve: () => getLevel(),  // custom resolver: number | undefined
  levels: ["info", "debug"],  // named, ordered levels (sets max = length)
  maxLevels: 3,               // numeric cap when `levels` is omitted (default 3)
});
  • level accepts a number, a level name, 0 for base-only, or -1 to silence.
  • resolve returning undefined (or a non-finite number) falls through to the env / browser lookup.
  • levels sets the cap to its length; otherwise maxLevels (default 3) caps the numeric range.
  • The threshold is read fresh on every call, so changing VERBOSE (or the global var) at runtime takes effect immediately. Caveat: if you toggle it between the halves of a paired op (group/groupEnd, time/timeEnd, count/countReset) one half may be suppressed and the other not — toggle between logical sections, not inside a pair.

Resolution order

For each call the threshold is resolved in this order, first hit wins: level option → resolve() (a non-finite return is skipped) → the env var (if actually set) → globalThis[envVar]localStorage → base only. A bundler-polyfilled process.env without the var does not shadow the browser sources, and a non-primitive global (object/function set by another script) is ignored rather than coerced.

Examples

Runnable snippets live in examples/: Node ESM, Node CJS, named levels in TypeScript, and a browser page.

API

  • log — default logger reading VERBOSE.
  • createLogger(options?) — make a configured logger. Generic over the level names, so createLogger({ levels: ["a", "b"] }) types .v() to "a" | "b" | number.
  • Types: VerboseConsole<L>, VerboseLogOptions<L>, Threshold.

Note: v is reserved on the proxy for level scoping; everything else passes through to the underlying console.

Alternatives — when to use this, when not

Logging tools sort along two independent axes: how much to log (verbosity depth) and where it came from (which subsystem). verbose-log does the first — one VERBOSE knob over a drop-in console, zero deps. It deliberately does not do namespaces, severity routing, structured output, or transports.

| Library | Focus | Reach for it when… | | -------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------- | | verbose-log | Verbosity depth via one VERBOSE env; drop-in console | You want a single knob to dial how much console output an app/CLI emits, with no new API to learn | | debug | Namespaces (DEBUG=app:db,app:api) | You want to switch subsystems on/off, not depth | | loglevel | Severity levels (trace→error), tiny, per-module loggers | You want standard severity methods in the browser, with named loggers | | consola | Pretty reporters, tags, prompts (Node + browser) | You want nicely formatted, colorful dev output | | pino | Fast structured JSON logging | You need production logs / observability at high throughput | | winston | Transports + formats (files, HTTP, services) | You need to route logs to multiple destinations in production | | if (process.env.VERBOSE) console.log(...) | Nothing — hand-rolled | …never again; that boilerplate is exactly what this replaces |

The axes compose: it's common to run pino (or plain console) for production and reach for verbose-log as the dev-time verbosity dial, or to pair it with debug when you also need per-subsystem switches. If you find yourself wanting namespaces, child loggers with bound context, or JSON output, you've outgrown this library — use one of the above.

License

MIT