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

@infinitetoken/lumber

v2.2.5

Published

TypeScript Node.js logging plugin for Lumber — AES-256-GCM encrypted, async queue, zero dependencies

Readme

@infinitetoken/lumber

Node.js client for Lumber — cloud logging with full E2E encryption, async queue, and zero runtime dependencies.

All log content is encrypted with AES-256-GCM before leaving the process. The API stores only opaque blobs — it cannot read your logs.

Installation

npm install @infinitetoken/lumber

Quick start

Call lumber.config() once at app startup. Every other import in your project shares the same configured client automatically.

Warning: Calling lumber.config() a second time replaces the client immediately. Any logs queued in the previous client that have not yet been sent are silently dropped. Call await lumber.flush() before reconfiguring if you need to preserve them.

// ESM
import lumber from '@infinitetoken/lumber'

// CJS
const { default: lumber } = require('@infinitetoken/lumber')

lumber.config({
  apiKey:        process.env.LUMBER_API_KEY,
  encryptionKey: process.env.LUMBER_ENCRYPTION_KEY, // required — 32-byte key, base64-encoded
})

lumber.info('Server started', { port: 3000 })
lumber.warn('Rate limit approaching', { requestId: 'req-123', metadata: { userId: '456' } })
lumber.error('Payment failed', { traceId: 'trace-abc', orderId: '789' })

// Drain the queue before process exit
await lumber.flush()

Generate an encryption key:

node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

Log methods

| Method | Level | |--------|-------| | lumber.debug(message, data?) | Debug | | lumber.info(message, data?) | Info | | lumber.log(message, data?) | Info (alias) | | lumber.warn(message, data?) | Warn | | lumber.error(message, data?) | Error | | lumber.fatal(message, data?) | Fatal | | lumber.flush() | Returns Promise<void> — waits for queue to drain |

LogData

The second argument is an optional LogData object. Named fields are routed to specific parts of the encrypted payload; any other keys are merged into metadata.

lumber.info('User action', {
  requestId: 'req-abc',          // → payload.requestId
  traceId:   'trace-xyz',        // → payload.traceId
  context:   { code: 'app.ts' }, // → payload.context (merged with auto-context)
  metadata:  { version: 2 },     // → payload.metadata
  userId:    '123',              // → payload.metadata.userId (extra key)
  action:    'login',            // → payload.metadata.action (extra key)
})

Explicit metadata keys win over colliding extra keys. The entire payload — including message, requestId, context, and metadata — is encrypted before it leaves the process.

Config

lumber.config({
  apiKey:        string,  // API key from Lumber app settings
  encryptionKey: string,  // 32-byte AES key, base64-encoded — required
  endpoint?:     string,  // override API base URL (default: official Lumber API)
  console?:      boolean | ConsoleConfig,
  context?:      boolean | ContextConfig,
})

Console mirroring

Echo logs to the terminal as they are enqueued.

// Simple — all levels, badge only
lumber.config({ ..., console: true })

// Fine-grained
lumber.config({
  ...,
  console: {
    levels:    { warn: true, error: true, fatal: true }, // omit = all levels
    prefix:    true,      // show [LEVEL] badge (default: true)
    color:     true,      // ANSI color when TTY (default: true, auto-detected)
    data:      true,      // append metadata/context as second console arg
    pretty:    true,      // pretty-print data with indentation (implies data)
    timestamp: true,      // prepend HH:MM:SS.mmm timestamp
    // timestamp: 'time'     → HH:MM:SS.mmm (same as true)
    // timestamp: 'iso'      → full ISO 8601
    // timestamp: 'relative' → +1.234s since process start
  },
})

Example output with timestamp: true:

14:32:01.000 [DEBUG] Cache miss
14:32:02.105 [INFO]  User signed in
14:32:03.820 [WARN]  Rate limit approaching
14:32:05.001 [ERROR] Payment failed
14:32:05.002 [FATAL] DB connection lost

Auto-context

Lumber captures pid, hostname, and NODE_ENV once at config() time and attaches them to every log's encrypted payload. No per-call overhead.

// Default: on
lumber.config({ ... })

// Disable entirely
lumber.config({ ..., context: false })

// Also capture file/line/column from the call site
lumber.config({ ..., context: { caller: true } })

// If lumber is wrapped in a project-level logger, shift the stack frame
lumber.config({ ..., context: { caller: true, callerDepth: 1 } })

User-supplied context in LogData is merged on top of auto-context, so you can always override specific fields per call.

Queue behavior

Logs are enqueued in memory and sent sequentially in the background. Failed sends are retried up to 5 times with exponential backoff (1 s → 2 s → 4 s → 8 s). Call flush() before process exit to ensure all queued logs are delivered.

process.on('SIGINT', async () => {
  await lumber.flush()
  process.exit(0)
})

Power users: multiple instances

LumberClient is exported for cases where you need more than one configured instance.

import { LumberClient } from '@infinitetoken/lumber'

const client = new LumberClient({ apiKey, encryptionKey, console: true })
client.info('hello')
await client.flush()

Requirements

Node 18.17 or later.

License

MIT — See LICENSE