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

@napp/logger

v5.0.3

Published

low level log archigture. minimum resources, user friendly, powerfull logger library. supported browser & nodejs

Readme

@napp/logger

Lightweight, dependency-free logger core for Node.js and modern browsers.
Node.js болон browser орчинд ажиллах, хамаарал багатай хөнгөн logger library.

  • Zero runtime dependencies — Runtime хамаарал байхгүй
  • Tree-based hierarchical log level config — Tree бүтэцтэй шаталсан log level тохиргоо
  • onWrite event stream — app controls where logs go — Гаралтыг апп өөрөө удирдана
  • baseAttr inheritance across parent → child loggers — Parent → child хооронд metadata дамжина
  • Full + short methods: trace/debug/info/warn/error/fatal and t/d/i/w/e/f
  • ESM + CJS dual build, TypeScript types included — ESM + CJS хоёуланд ажиллана

Install

npm install @napp/logger

Quick Start

import { LogContext, LogLevel, getLogger } from '@napp/logger';

// One-time setup at app startup
// Апп эхлэхэд нэг удаа тохируулна
LogContext.defaultContext.config.set(['app'], LogLevel.Info);
LogContext.defaultContext.onWrite.subscribe(log => {
    console.log(`[${log.level}] ${log.logpath.join('.')} — ${log.message}`, log.attr);
});

// Use anywhere in the app — аппын хаана ч дуудаж болно
const log = getLogger('app.route');
log.info('server started', { port: 3000 });
log.debug('skipped — below Info');  // Info-с доош тул гарахгүй

Core Concepts / Үндсэн ойлголтууд

Log Level

Log levels control which events are emitted.
Log level нь ямар event гарахыг шийдэнэ.

| Level | Value | Description | |-------|-------|-------------| | Off | 0 | Logging disabled / Унтраасан | | Trace | 1 | Most verbose / Хамгийн дэлгэрэнгүй | | Debug | 5 | Debug info / Debug мэдээлэл | | Info | 9 | General info / Ерөнхий мэдээлэл | | Warn | 13 | Warnings / Анхааруулга | | Error | 17 | Errors / Алдаа | | Fatal | 21 | Critical failures / Хэрэглэх боломжгүй алдаа |

Parse a level from string or number:
String эсвэл тоогоор level авах:

import { parseLogLevel, LogLevel } from '@napp/logger';

parseLogLevel('warn', LogLevel.Info)    // → LogLevel.Warn
parseLogLevel(11, LogLevel.Off)         // → LogLevel.Info  (nearest band / ойр түвшин)
parseLogLevel('unknown', LogLevel.Info) // → LogLevel.Info  (default)

Log Name — Prefix Tree Config

Log нэр — Prefix Tree тохиргоо

Log names use . as a separator and form a tree. Config inherits down the tree.
Log нэр нь .-ээр тусгаарлагдаж tree бүтэц үүсгэнэ. Тохиргоо дээрээс доош өвлөгдөнө.

const ctx = new LogContext();

ctx.config.set(['app'], LogLevel.Info);
ctx.config.set(['app', 'db'], LogLevel.Error);

// app.route   → Info  (inherits from 'app' / 'app'-аас өвлөнө)
// app.db      → Error (exact match / яг тохирсон)
// app.db.pool → Error (inherits from 'app.db')
// other       → Off   (no config → silent / тохиргоо байхгүй → гарахгүй)

Root config-г хоосон path буюу []-ээр тохируулна. Энэ нь бүх log name-д үйлчлэх global default level болно.
Root config uses an empty path []. It becomes the global default level for every log name.

ctx.config.set([], LogLevel.Info);
ctx.config.set(['app', 'db'], LogLevel.Error);

// app.route   → Info  (inherits from root / root-оос өвлөнө)
// app.db      → Error (branch override / салбарын override)
// other       → Info  (inherits from root / root-оос өвлөнө)

LogLevel.Off means no logs are emitted for that branch.
LogLevel.Off бол тухайн салбарт log бичигдэхгүй.


onWrite — App Handles Output / Апп гаралтыг хэрэгжүүлнэ

The library only decides whether to emit. The app subscribes to onWrite and writes wherever it needs.
Library нь зөвхөн emit хийх эсэхийг шийднэ. Бичих үйлдлийг апп onWrite-д subscribe хийж өөрөө хэрэгжүүлнэ.

ctx.onWrite.subscribe(log => {
    console.log(log);                              // stdout
    fs.appendFileSync('app.log', JSON.stringify(log)) // disk / файл
    fetch('/logs', { body: JSON.stringify(log) })  // remote / сервер
});

baseAttr — Structured Metadata / Бүтэцтэй metadata

Attach shared metadata to a logger. Every log event from that logger automatically includes it.
Logger-т нэг удаа metadata оноовол тухайн logger-ийн бүх event-д автоматаар дагалдана.

const log = ctx.getLogger('app.route', { service: 'api', env: 'prod' });
log.info('request received', { requestId: 'abc' });
// attr → { service: 'api', env: 'prod', requestId: 'abc' }

Merge order / Merge дараалал: ctx.baseAttrlogger.baseAttrevent attr
Later values override earlier ones for the same key.
Ижил нэртэй талбарт сүүлийн утга өмнөхийг дарна.


child() — Scoped Child Logger / Дэд logger

const appLog = ctx.getLogger('app');
const dbLog  = appLog.child('db');        // logpath: ['app', 'db']
const sqlLog = appLog.child('db.query');  // logpath: ['app', 'db', 'query']

Child inherits parent baseAttr and can add or override fields.
Child нь parent-ийн baseAttr-ийг өвлөж, нэмэх эсвэл дарж болно.

const parent = ctx.getLogger('app', { service: 'api' });
const child  = parent.child('route', { module: 'user' });
// child baseAttr → { service: 'api', module: 'user' }

LogContext

LogContext holds the config tree and onWrite stream for the entire app.
LogContext нь апп дахь config tree болон onWrite stream-ийг нэгтгэн хадгална.

import { LogContext, LogLevel } from '@napp/logger';

const ctx = new LogContext({ env: 'prod' }); // optional baseAttr

ctx.config.set(['app'], LogLevel.Info);
ctx.onWrite.subscribe(log => console.log(log));

const log = ctx.getLogger('app.route');
log.warn('slow response', { ms: 420 });

Default Context (Singleton) / Үндсэн context

LogContext.defaultContext is a pre-created singleton. getLogger() without a ctx argument uses it automatically.
LogContext.defaultContext нь урьдчилан үүссэн singleton. ctx заахгүй бол getLogger() үүнийг автоматаар ашиглана.

// Setup once at startup — эхлэхэд нэг удаа
LogContext.defaultContext.config.set(['app'], LogLevel.Debug);
LogContext.defaultContext.onWrite.subscribe(log => console.log(log));

// Use anywhere — хаана ч ctx заахгүйгээр
const log = getLogger('app.worker');
log.info('ready');

Custom Context (Testing / Isolation) / Тусгай context

Useful for tests or isolated modules where you don't want to share the default context.
Test болон тусгаарлагдсан модульд default context-ийг хуваалцахгүйгээр ашиглах боломж.

const testCtx = new LogContext();
testCtx.config.set(['app'], LogLevel.Trace);

const captured: ILogItem[] = [];
testCtx.onWrite.subscribe(log => captured.push(log));

const log = getLogger('app', undefined, testCtx);
log.info('test event');

Attr Serialization — toJSON / Attr-ийн JSON хөрвүүлэлт

The library passes attr values as-is. It does not serialize Error objects or any other type automatically.
Library нь attr-ийн утгыг шууд дамжуулна. Error болон бусад object-ийг автоматаар боловсруулахгүй.

Serialization is the app's responsibility — controlled via toJSON().
JSON болгох үйлдэл нь хэрэглэгчийн хариуцлагаtoJSON() тусламжтайгаар удирдана.

// ❌ Without toJSON — toJSON байхгүй бол
log.error('failed', { error: new Error('timeout') });
// attr.error → {}  ← Error object JSON-д хоосон болно

// ✅ With toJSON — toJSON нэмсэн бол
class AppError extends Error {
    toJSON() {
        return { name: this.name, message: this.message, stack: this.stack };
    }
}
log.error('failed', { error: new AppError('timeout') });
// attr.error → { name: 'AppError', message: 'timeout', stack: '...' }

Same applies to any custom object — toJSON() gives you full control over what gets logged.
Ямар ч custom object-д toJSON() нэмж, ямар мэдээлэл log-д орохыг өөрөө тодорхойлно.

class User {
    constructor(public id: number, public name: string, private password: string) {}
    toJSON() {
        return { id: this.id, name: this.name }; // password орохгүй / password excluded
    }
}

log.info('login', { user: new User(1, 'bat', 's3cr3t') });
// attr.user → { id: 1, name: 'bat' }

Safe JSON + Redaction / Аюулгүй JSON ба нууцлал

@napp/logger нь attr дээр mask, hide, redact автоматаар хийхгүй. Энэ нь app талын policy байна.
@napp/logger does not automatically mask, hide, or redact attr. This is an app-side policy.

Writer руу дамжуулахын өмнө app нь log event-ийг safe plain JSON object болгон хувиргаж, sensitive талбаруудыг нуух эсвэл маск хийх ёстой.
Before passing a log event to a writer, the app should convert it to a safe plain JSON object and hide or mask sensitive fields.

ctx.onWrite.subscribe(log => {
    const safeLog = toSafeJsonLog(log, {
        hide: ['password', 'token', 'headers.authorization'],
        mask: ['user.email', 'user.phone'],
    });

    writer.write(safeLog);
});

Recommended flow / Зөвлөмж болгож буй урсгал:

logger → raw structured event → app serializer/redactor → writer

Message string-д secret утга шууд оруулахгүй. Sensitive мэдээллийг attr дээр бүтэцтэй өгч, app serializer/redactor дээр policy хэрэгжүүлнэ.
Do not put secrets directly into the message string. Pass sensitive values as structured attr fields and apply policy in the app serializer/redactor.


API Reference / Дэлгэрэнгүй лавлах

For full interface details, method signatures, and type definitions, see:
Бүх interface, method, type-ийн дэлгэрэнгүй тайлбарыг доорх файлаас үзнэ үү:

docs/api-reference.md


Notes / Тэмдэглэл

  • Dual build: ESM (dist/index.js) + CJS (dist/index.cjs) — хоёуланд ажиллана
  • TypeScript types: dist/index.d.ts
  • Target runtime: Node.js ≥ 22, modern browsers
  • No runtime dependencies — runtime хамаарал байхгүй

License

MIT