{"_id":"@emdzej/bimmerz-logger","_rev":"4-699200da8cbba28d90127751079f63f3","name":"@emdzej/bimmerz-logger","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@emdzej/bimmerz-logger","version":"0.1.0","_id":"@emdzej/bimmerz-logger@0.1.0","maintainers":[{"name":"emdzej","email":"michal@jaskolski.pro"}],"homepage":"https://github.com/emdzej/bimmerz#readme","bugs":{"url":"https://github.com/emdzej/bimmerz/issues"},"dist":{"shasum":"10eac139affde1d95602b63e861263e42c02d025","tarball":"https://registry.npmjs.org/@emdzej/bimmerz-logger/-/bimmerz-logger-0.1.0.tgz","fileCount":47,"integrity":"sha512-jLUqYusyu1u/NmbBGPL5IS+DhqsS4EvEUl8OQUNIoIsvOFtzVqZyNAab2xXfjBlRBTTAxG2vZTfvf0dmr2pvDA==","signatures":[{"sig":"MEUCIQDwr9Y+W1ix+ev8FT4wuI2/Re7PIfcNyqqHmH37/onAaAIgS+ae9gYCK8A2mTyKsULBgkUK1iqDFeci4hAe/ACdBj4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76766},"main":"dist/index.js","type":"module","_from":"file:emdzej-bimmerz-logger-0.1.0.tgz","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sinks/pino":{"types":"./dist/sinks/pino.d.ts","import":"./dist/sinks/pino.js"}},"scripts":{"dev":"tsc --watch","lint":"eslint .","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist .turbo *.tsbuildinfo","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"emdzej","email":"michal@jaskolski.pro"},"_resolved":"/private/var/folders/7h/x_w_580x4s9dq3sq11tpvzkwy3nbj8/T/24f226f79a60aea010af13315d3d1a8d/emdzej-bimmerz-logger-0.1.0.tgz","_integrity":"sha512-jLUqYusyu1u/NmbBGPL5IS+DhqsS4EvEUl8OQUNIoIsvOFtzVqZyNAab2xXfjBlRBTTAxG2vZTfvf0dmr2pvDA==","repository":{"url":"git+https://github.com/emdzej/bimmerz.git","type":"git","directory":"packages/logger"},"_npmVersion":"11.14.1","description":"Shared structured logger for the bimmerz family — pino-shape API, hierarchical categories, runtime-mutable config, pluggable sinks. No env reads, isomorphic (Node + browser), tree-shake-friendly.","directories":{},"_nodeVersion":"22.22.1","dependencies":{"pino":"^9.0.0","pino-pretty":"^11.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","typescript":"^5.7.3","@types/node":"^22.13.1"},"_npmOperationalInternal":{"tmp":"tmp/bimmerz-logger_0.1.0_1779560523986_0.13465369883920975","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@emdzej/bimmerz-logger","version":"0.1.1","_id":"@emdzej/bimmerz-logger@0.1.1","maintainers":[{"name":"emdzej","email":"michal@jaskolski.pro"}],"homepage":"https://github.com/emdzej/bimmerz#readme","bugs":{"url":"https://github.com/emdzej/bimmerz/issues"},"dist":{"shasum":"a54f2cf119ab847fe20ef6fb5ad59976734bdfae","tarball":"https://registry.npmjs.org/@emdzej/bimmerz-logger/-/bimmerz-logger-0.1.1.tgz","fileCount":47,"integrity":"sha512-YLn+qAsjtWaG9RZWeHeQVHJ8FjG5eATn+yMF6kzK44aZBP9CAaiQzXqtLwpz3L9CwiClGDwxcCzvH8GqGBJWRg==","signatures":[{"sig":"MEQCIHQrF07+fC+CU+TwcnCrIh17YssNq/c1ZORE/M6+8EcFAiBeYWW0ohgQzEB2LknDxp54KTSAUuw/J6J6yqz73QFTZA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76843},"main":"dist/index.js","type":"module","_from":"file:emdzej-bimmerz-logger-0.1.1.tgz","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./sinks/pino":{"types":"./dist/sinks/pino.d.ts","import":"./dist/sinks/pino.js","default":"./dist/sinks/pino.js"}},"scripts":{"dev":"tsc --watch","lint":"eslint .","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist .turbo *.tsbuildinfo","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"emdzej","email":"michal@jaskolski.pro"},"_resolved":"/private/var/folders/7h/x_w_580x4s9dq3sq11tpvzkwy3nbj8/T/2ec3651d4c3954a0597044380051f6c5/emdzej-bimmerz-logger-0.1.1.tgz","_integrity":"sha512-YLn+qAsjtWaG9RZWeHeQVHJ8FjG5eATn+yMF6kzK44aZBP9CAaiQzXqtLwpz3L9CwiClGDwxcCzvH8GqGBJWRg==","repository":{"url":"git+https://github.com/emdzej/bimmerz.git","type":"git","directory":"packages/logger"},"_npmVersion":"11.14.1","description":"Shared structured logger for the bimmerz family — pino-shape API, hierarchical categories, runtime-mutable config, pluggable sinks. No env reads, isomorphic (Node + browser), tree-shake-friendly.","directories":{},"_nodeVersion":"22.22.1","dependencies":{"pino":"^9.0.0","pino-pretty":"^11.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","typescript":"^5.7.3","@types/node":"^22.13.1"},"_npmOperationalInternal":{"tmp":"tmp/bimmerz-logger_0.1.1_1779562426266_0.9909375712248678","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@emdzej/bimmerz-logger","version":"0.1.2","_id":"@emdzej/bimmerz-logger@0.1.2","maintainers":[{"name":"emdzej","email":"michal@jaskolski.pro"}],"homepage":"https://github.com/emdzej/bimmerz#readme","bugs":{"url":"https://github.com/emdzej/bimmerz/issues"},"dist":{"shasum":"323059cc78e8fcf7564cbf9eba87751906994013","tarball":"https://registry.npmjs.org/@emdzej/bimmerz-logger/-/bimmerz-logger-0.1.2.tgz","fileCount":47,"integrity":"sha512-RPlnIAxo1+uLSTH97VifBCRAxjhylagKqyiyUDYtQSzB7fkgtJh4fedBxvB/T8T5Pr/bQKE68NUi6/o6Op21LQ==","signatures":[{"sig":"MEUCIQDxzrryC4I1kv+eiOpQnTC41+oDlaNpApMkw98HlZ8piQIgV2W/3s2zIVM1ePJJmfYjVr34gYz/as7JiZ8p3cQoRMc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":78280},"main":"dist/index.js","type":"module","_from":"file:emdzej-bimmerz-logger-0.1.2.tgz","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./sinks/pino":{"types":"./dist/sinks/pino.d.ts","import":"./dist/sinks/pino.js","default":"./dist/sinks/pino.js"}},"scripts":{"dev":"tsc --watch","lint":"eslint .","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist .turbo *.tsbuildinfo","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"emdzej","email":"michal@jaskolski.pro"},"_resolved":"/private/var/folders/7h/x_w_580x4s9dq3sq11tpvzkwy3nbj8/T/7c441934486fb4106b9c3c7a183487d8/emdzej-bimmerz-logger-0.1.2.tgz","_integrity":"sha512-RPlnIAxo1+uLSTH97VifBCRAxjhylagKqyiyUDYtQSzB7fkgtJh4fedBxvB/T8T5Pr/bQKE68NUi6/o6Op21LQ==","repository":{"url":"git+https://github.com/emdzej/bimmerz.git","type":"git","directory":"packages/logger"},"_npmVersion":"11.14.1","description":"Shared structured logger for the bimmerz family — pino-shape API, hierarchical categories, runtime-mutable config, pluggable sinks. No env reads, isomorphic (Node + browser), tree-shake-friendly.","directories":{},"_nodeVersion":"22.22.1","dependencies":{"pino":"^9.0.0","pino-pretty":"^11.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","typescript":"^5.7.3","@types/node":"^22.13.1"},"_npmOperationalInternal":{"tmp":"tmp/bimmerz-logger_0.1.2_1779563766078_0.4318823257330131","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"_id":"@emdzej/bimmerz-logger@0.3.0","bugs":{"url":"https://github.com/emdzej/bimmerz-core/issues"},"dist":{"shasum":"08889fdd71edad5dd7076402e67703ceb008c457","tarball":"https://registry.npmjs.org/@emdzej/bimmerz-logger/-/bimmerz-logger-0.3.0.tgz","fileCount":43,"integrity":"sha512-SnZnazIEVEX44XWWO/vW1rhiS/ZreRGNTQjBQEf9GKHmH2xB2iQuTuA5v6eDQ+mlTHJBCyOOBXraKdSzklFogA==","signatures":[{"sig":"MEQCIBZJm1trlDVzPrHfQY1YK8PKL0M6Q9nGgjrNjFV8Na64AiBjavjhwxAl1RO5+Rk4AnbOp4BbqxmhxLOh4N8wr02Vog==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD6/AKxRlDqSZGWv0+tI1f0/tndn74EevtYMLe7sBH1oQIgKH9du0Z9sdKRg4YhwNrLrdoKKN0sBxbOtodq+VizU2g="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@emdzej%2fbimmerz-logger@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":59836},"main":"dist/index.js","name":"@emdzej/bimmerz-logger","type":"module","_from":"file:emdzej-bimmerz-logger-0.3.0.tgz","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./sinks/pino":{"types":"./dist/sinks/pino.d.ts","import":"./dist/sinks/pino.js","default":"./dist/sinks/pino.js"}},"license":"PolyForm-Noncommercial-1.0.0","scripts":{"dev":"tsc --watch","lint":"eslint .","test":"vitest run --passWithNoTests","build":"tsc","clean":"rm -rf dist .turbo *.tsbuildinfo","typecheck":"tsc --noEmit","test:watch":"vitest"},"version":"0.3.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:fabb2917-3b48-4e9c-b900-7ded385ee3ab"}},"homepage":"https://github.com/emdzej/bimmerz-core#readme","_resolved":"/tmp/19457bbf1bcdbacab1d91a553bbad0ce/emdzej-bimmerz-logger-0.3.0.tgz","_integrity":"sha512-SnZnazIEVEX44XWWO/vW1rhiS/ZreRGNTQjBQEf9GKHmH2xB2iQuTuA5v6eDQ+mlTHJBCyOOBXraKdSzklFogA==","repository":{"url":"git+https://github.com/emdzej/bimmerz-core.git","type":"git","directory":"packages/logger"},"_npmVersion":"12.1.0","description":"Shared structured logger for the bimmerz family — pino-shape API, hierarchical categories, runtime-mutable config, pluggable sinks. No env reads, isomorphic (Node + browser), tree-shake-friendly.","directories":{},"maintainers":[{"name":"emdzej","email":"michal@jaskolski.pro"}],"_nodeVersion":"22.23.2","dependencies":{"pino":"^10.3.1","pino-pretty":"^13.1.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^5.0.1","typescript":"^5.7.3","@types/node":"^22.13.1"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bimmerz-logger_0.3.0_1790327502987_0.1528197032466727"}}},"time":{"created":"2026-05-23T18:22:03.776Z","modified":"2026-09-25T09:11:43.382Z","0.1.0":"2026-05-23T18:22:04.198Z","0.1.1":"2026-05-23T18:53:46.408Z","0.1.2":"2026-05-23T19:16:06.233Z","0.3.0":"2026-09-25T09:11:43.067Z"},"bugs":{"url":"https://github.com/emdzej/bimmerz-core/issues"},"homepage":"https://github.com/emdzej/bimmerz-core#readme","repository":{"url":"git+https://github.com/emdzej/bimmerz-core.git","type":"git","directory":"packages/logger"},"description":"Shared structured logger for the bimmerz family — pino-shape API, hierarchical categories, runtime-mutable config, pluggable sinks. No env reads, isomorphic (Node + browser), tree-shake-friendly.","maintainers":[{"name":"emdzej","email":"michal@jaskolski.pro"}],"readme":"# @emdzej/bimmerz-logger\n\nShared structured logger for the bimmerz family of tools\n([`ediabasx`](https://github.com/emdzej/ediabasx),\n[`inpax`](https://github.com/emdzej/inpax),\n[`ncsx`](https://github.com/emdzej/ncsx), and the apps that build on\nthem).\n\n**Pino-shape API**, hierarchical categories, runtime-mutable central\nconfig, pluggable sinks. No environment variables. Works in both\nNode and the browser; tree-shake-friendly so web bundles don't ship\npino.\n\n## TL;DR\n\n```ts\nimport { configureLogger, getLogger } from '@emdzej/bimmerz-logger';\n\n// App start — configure once, anywhere.\nconfigureLogger({\n  level: 'info',\n  categories: {\n    EDIABASX: 'debug',\n    'EDIABASX.parser': 'trace',\n    INPAX: 'info',\n  },\n});\n\n// Anywhere in the codebase — log with or without a category.\nconst log = getLogger('EDIABASX.parser');\nlog.debug({ jobId: 'C_S_LESEN' }, 'parsing request packet');\nlog.info('parser ready');\n\n// Want to flip on debug for one subsystem at runtime?\nconfigureLogger({ categories: { ...prev, INPAX: 'debug' } });\n// — every previously-handed-out INPAX logger sees the new level immediately.\n```\n\n## Design\n\nThe interface is the same shape as pino — `log.debug(bindings, msg)`,\nlevels `trace` through `fatal`, `log.child(bindings)`. We don't\nre-export pino's types because we don't want our public API locked\nto one implementation. The default sink is a small console wrapper\n(works in browser + Node); apps that want pino's pretty-print, JSON,\nor file destinations opt in via `@emdzej/bimmerz-logger/sinks/pino`.\n\nLogger handles are **proxies**, not snapshots — they consult the live\nconfig on every call. So once an app calls `configureLogger(…)`, every\nlogger handle anyone ever cached picks up the new settings on its next\nemit. No need to \"refetch\" loggers from callers.\n\nCategories are **hierarchical** by dot. A rule for `EDIABASX` applies\nto `EDIABASX.parser` and `EDIABASX.parser.lexer` unless a more\nspecific rule wins. Most specific match always wins:\n\n```ts\nconfigureLogger({\n  level: 'warn',\n  categories: {\n    EDIABASX: 'debug',          // covers EDIABASX, EDIABASX.runner, …\n    'EDIABASX.parser': 'trace', // overrides for parser sub-tree\n    INPAX: 'info',\n  },\n});\n\ngetLogger('EDIABASX.parser.lexer').trace('hit');  // matches EDIABASX.parser → 'trace' → emitted\ngetLogger('EDIABASX.runner').debug('hit');        // matches EDIABASX → 'debug' → emitted\ngetLogger('INPAX.dispatcher').debug('miss');      // matches INPAX → 'info' → dropped\ngetLogger().debug('miss');                        // root → 'warn' fallback → dropped\n```\n\n## API\n\n### `configureLogger(partial: Partial<LoggerConfig>)`\n\nReplace or merge into the active configuration. Shallow merge —\n`categories` and `sink` are replaced wholesale when present in the\npartial.\n\n```ts\nconfigureLogger({ level: 'debug' });                    // bump default level\nconfigureLogger({ categories: { EDIABASX: 'trace' } }); // change category rules\nconfigureLogger({ categories: {} });                    // clear all category rules\n```\n\nApply early in your app's entry point. You can re-apply at any time\n— the change is immediate for every existing logger handle.\n\n### `getLogger(category?: string): Logger`\n\nReturns a logger handle. With no argument, the root logger\n(category = `null`). With a dot-separated string, a category-scoped\nlogger.\n\n```ts\nconst root = getLogger();\nconst parser = getLogger('EDIABASX.parser');\nconst job = parser.child({ jobId: 'C_S_LESEN' });\n```\n\n### `Logger`\n\n```ts\ninterface Logger {\n  readonly level: LogLevel;     // currently-effective threshold (live)\n\n  trace(msg: string): void;\n  trace(bindings: object, msg: string): void;\n  debug(msg: string): void;\n  debug(bindings: object, msg: string): void;\n  info(msg: string): void;\n  info(bindings: object, msg: string): void;\n  warn(...): void;\n  error(...): void;\n  fatal(...): void;\n\n  child(bindings: object): Logger;\n}\n```\n\nTwo call forms — string-only `log.info(\"done\")`, or bindings-first\n`log.info({ jobId, count }, \"done\")`. Bindings are merged with any\npermanent `child()` bindings; call bindings win on key conflicts.\n\n`log.level` is a read-only getter that returns the live effective\nlevel for this logger's category. Cheap to call — use it as an\nescape hatch for hot paths where formatting the message is expensive:\n\n```ts\nif (log.level === 'trace') {\n  log.trace({ details: expensiveDump() }, 'sg op');\n}\n```\n\n### Sinks\n\nBundled sinks (importable from the main entry):\n\n| Function | Use |\n|---|---|\n| `consoleSink({ colors?, relativeTime? })` | Default. Routes through `console.{debug,info,warn,error}`. ANSI colour when TTY. |\n| `bufferSink({ capacity? })` | In-memory ring of last N records. `.snapshot()` returns them — drives \"Download log\" UIs. |\n| `multiSink(a, b, …)` | Fan one record out to every wrapped sink. Failures in one sink don't poison the others. |\n| `nullSink()` | Drops everything. Tests, or to disable logging without changing level. |\n\nOptional pino sink — import from the subpath so it's not in the\ndefault tree-shake graph:\n\n```ts\nimport { pinoSink } from '@emdzej/bimmerz-logger/sinks/pino';\n\nconfigureLogger({\n  level: 'info',\n  sink: pinoSink({ pretty: true }),     // pino-pretty when TTY\n  // or: pinoSink({ destination: '/var/log/app.log' })\n});\n```\n\n## Sink contract\n\n```ts\ninterface Sink {\n  write(record: LogRecord): void;\n}\n\ninterface LogRecord {\n  level: LogLevel;\n  category: string | null;\n  bindings: Record<string, unknown>;\n  msg: string;\n  time: number;  // Date.now()\n}\n```\n\nRoll your own sink for special destinations:\n\n```ts\nconst httpSink: Sink = {\n  write(rec) {\n    if (rec.level === 'error' || rec.level === 'fatal') {\n      navigator.sendBeacon('/log', JSON.stringify(rec));\n    }\n  },\n};\n\nconfigureLogger({\n  sink: multiSink(consoleSink(), httpSink),\n});\n```\n\n## What we don't do\n\n- **No environment-variable reads.** Apps are responsible for\n  mapping their CLI flags / wizard config / settings panel onto\n  `configureLogger(…)`. Keeps the library portable and\n  predictable.\n- **No printf-style formatting.** Use template literals or\n  bindings:\n  ```ts\n  log.debug({ a, b }, 'compared');                   // ✅ bindings\n  log.debug(`compared ${a} vs ${b}`);                // ✅ template literal\n  log.debug({}, 'compared %s vs %s', a, b);          // ❌ not supported\n  ```\n- **No async sinks.** All sinks are sync. If you need network or\n  storage shipping, wrap a sync sink that enqueues to your own\n  async pipeline.\n\n## Migration from `@emdzej/ediabasx-logger` / `@emdzej/inpax-logger`\n\nThose packages will be retired once the codebases here are migrated.\nThe shapes are similar — `configureLogger({...})` plus\n`getLogger(\"module\")` — so most call sites need only an import path\nchange:\n\n```ts\n// old\nimport { getLogger, configureLogger } from '@emdzej/ediabasx-logger';\n// new\nimport { getLogger, configureLogger } from '@emdzej/bimmerz-logger';\n```\n\nBehavioural differences worth knowing:\n\n- `configureLogger` now takes effect on **existing** logger handles.\n  ediabasx-logger only affected new ones.\n- pino types are no longer in the public surface. `Logger` is our own\n  interface (same shape). If you typed something as `pino.Logger`,\n  swap to `Logger` from this package.\n- `pretty` / `destination` options moved off the package-level config\n  and into the pino sink. Get them by switching the sink:\n  ```ts\n  import { pinoSink } from '@emdzej/bimmerz-logger/sinks/pino';\n  configureLogger({ sink: pinoSink({ pretty: true }) });\n  ```\n","readmeFilename":"README.md","license":"PolyForm-Noncommercial-1.0.0"}