@warlock.js/logger 5.24.0 → 5.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `@warlock.js/logger` are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
6
6
 
7
+ ## 5.25.0 - 2026-09-28
8
+
9
+ ### Changed
10
+
11
+ - Lockstep release; package APIs are unchanged.
12
+
7
13
  ## 5.24.0 - 2026-09-27
8
14
 
9
15
  ### Changed
package/README.md CHANGED
@@ -1,154 +1,154 @@
1
- # @warlock.js/logger
2
-
3
- Structured, multi-channel logging for Node.js — six severity levels (debug / info / warn / error / success / fatal), a clean three-argument API, and full TypeScript support. Non-blocking by default; synchronous or async flush on demand.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install @warlock.js/logger
9
- # or
10
- yarn add @warlock.js/logger
11
- ```
12
-
13
- ## Server-only package
14
-
15
- `@warlock.js/logger`'s entire runtime surface is server-only. Its `package.json` declares `"warlock": { "environment": "server" }` — build-boundary metadata that `@warlock.js/web`'s Gate A (import resolution) and Gate C (emitted-bundle verification) read to keep it out of the browser bundle.
16
-
1
+ # @warlock.js/logger
2
+
3
+ Structured, multi-channel logging for Node.js — six severity levels (debug / info / warn / error / success / fatal), a clean three-argument API, and full TypeScript support. Non-blocking by default; synchronous or async flush on demand.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @warlock.js/logger
9
+ # or
10
+ yarn add @warlock.js/logger
11
+ ```
12
+
13
+ ## Server-only package
14
+
15
+ `@warlock.js/logger`'s entire runtime surface is server-only. Its `package.json` declares `"warlock": { "environment": "server" }` — build-boundary metadata that `@warlock.js/web`'s Gate A (import resolution) and Gate C (emitted-bundle verification) read to keep it out of the browser bundle.
16
+
17
17
  - App code that reaches the client bundle (including page and layout modules) must not value-import `@warlock.js/logger` — Gate A refuses the build.
18
- - A type-only import (`import type { ... } from "@warlock.js/logger"`) is allowed — it carries no runtime edge.
19
- - Server loaders, controllers, and modules may import it freely.
20
-
21
- ## 30-second tour
22
-
23
- ```ts
24
- import { log, ConsoleLog, FileLog } from "@warlock.js/logger";
25
-
26
- log.setChannels([
27
- new ConsoleLog(),
28
- new FileLog({ chunk: "daily" }),
29
- ]);
30
-
31
- await log.info("users", "register", "New user created");
32
- await log.error("payments", "charge", new Error("Card declined"));
33
- ```
34
-
35
- The logger starts with no channels — nothing is printed or written until you register at least one.
36
-
37
- ## The module · action · message pattern
38
-
39
- Every call carries three pieces of context. Modules and actions become searchable keys in file and JSON channels:
40
-
41
- ```ts
42
- await log.info("auth", "login", "User signed in");
43
- await log.warn("api", "rateLimitApproaching", "80% of quota used");
44
- await log.success("payments", "captured", "Payment of $49.99 captured");
45
- ```
46
-
47
- Pass an object instead of positional args when you need `context` metadata:
48
-
49
- ```ts
50
- await log.error({
51
- module: "orders",
52
- action: "checkout",
53
- message: "Card declined",
54
- context: { orderId: "ord_9f2a", amount: 4999 },
55
- });
56
- ```
57
-
58
- ## Levels
59
-
60
- `debug` · `info` · `warn` · `error` · `success` · `fatal` — each has a shorthand method on the `log` singleton (and on every `Logger` instance). `fatal` is strictly above `error` for unrecoverable failures where the app is going down (failed bootstrap, `uncaughtException`); it does not auto-flush or exit on its own.
61
-
62
- ## Built-in channels
63
-
64
- | Channel | Name | Purpose |
65
- |---|---|---|
66
- | `ConsoleLog` | `"console"` | Colorized terminal output |
67
- | `FileLog` | `"file"` | Plain-text files, optional chunking + rotation + grouping |
68
- | `JSONFileLog` | `"fileJson"` | Structured JSON files — ideal for aggregators |
69
- | `SentryLog` | `"sentry"` | Forwards to Sentry (events + breadcrumbs); needs the optional `@sentry/node` peer |
70
-
71
- All channels share the `BasicLogConfigurations` options (`levels`, `filter`, `dateFormat`); `FileLog` / `JSONFileLog` add storage, chunking, rotation, and grouping options, and `SentryLog` adds `client` / `options` / `eventLevels`.
72
-
73
- ## `log` and `Logger`
74
-
75
- The package exports one default singleton and one class:
76
-
77
- - **`log`** — a pre-instantiated `Logger`. Day-to-day logging *and* configuration both go through it: `log.info(...)`, `log.configure(...)`, `log.flush()` / `log.flushSync()`, `log.addChannel(...)`.
78
- - **`Logger`** — the class. Use it when you need an isolated logger (libraries, sandboxes, parallel test suites).
79
-
80
- `log` is a `Logger` instance, not a function — every level shortcut and configuration method is reachable on it. The bare-callable `log(data)` form was removed; use `log.log(data)` for the data-object form, or `log.info(...)` / `log.error(...)` / etc. for the positional form.
81
-
82
- ## Graceful shutdown
83
-
84
- `FileLog` and `JSONFileLog` buffer entries. Tell the logger to drain them on exit:
85
-
86
- ```ts
87
- log.configure({
88
- channels: [new ConsoleLog(), new FileLog({ chunk: "daily" })],
89
- autoFlushOn: ["SIGINT", "SIGTERM", "beforeExit"],
90
- });
91
- ```
92
-
93
- Signal events flush then re-raise (so Node exits with its normal signal semantics); `beforeExit` flushes in place. For full control, call `log.flushSync()` (sync) — or `await log.flush()` (async, for network/async channels) — inside your own handler instead.
94
-
95
- ## Capturing unhandled errors
96
-
97
- ```ts
98
- import { captureAnyUnhandledRejection } from "@warlock.js/logger";
99
-
100
- captureAnyUnhandledRejection();
101
- ```
102
-
103
- Registers process-level handlers for `unhandledRejection` (→ `log.error("app", ...)`, process kept alive) and `uncaughtException` (→ `log.fatal("app", ...)`, then `process.exit(1)` so a fatal crash is never silently swallowed into `exit 0`). Pass `{ exitOnUncaughtException: false }` to log without exiting. Call once at startup, after channels are registered.
104
-
105
- ## Custom channels
106
-
107
- Extend `LogChannel` and implement `log(data)`:
108
-
109
- ```ts
110
- import { LogChannel, type LoggingData } from "@warlock.js/logger";
111
-
112
- export class SlackLog extends LogChannel<{ webhookUrl: string }> {
113
- public name = "slack";
114
-
115
- public async log(data: LoggingData) {
116
- if (!this.shouldBeLogged(data)) return;
117
- await fetch(this.config("webhookUrl"), {
118
- method: "POST",
119
- headers: { "Content-Type": "application/json" },
120
- body: JSON.stringify({
121
- text: `[${data.type}] [${data.module}][${data.action}]: ${data.message}`,
122
- }),
123
- });
124
- }
125
- }
126
- ```
127
-
128
- Set `terminal = true` on the class if your channel writes to a TTY — otherwise ANSI codes are auto-stripped from string messages.
129
-
130
- ## Full documentation
131
-
132
- The complete guide lives in the project docs:
133
-
134
- - Getting Started
135
- - Configuration
136
- - Channels (ConsoleLog, FileLog, JSONFileLog, SentryLog)
137
- - Lifecycle & Flushing
138
- - Capturing Unhandled Errors
139
- - Custom Channels
140
- - Recipes
141
- - API Reference
142
- - Types
143
-
144
- ## Tests
145
-
146
- This package uses Vitest. From the repo root:
147
-
148
- ```bash
149
- npx vitest run --root @warlock.js/logger
150
- ```
151
-
152
- ## License
153
-
154
- MIT
18
+ - A type-only import (`import type { ... } from "@warlock.js/logger"`) is allowed — it carries no runtime edge.
19
+ - Server loaders, controllers, and modules may import it freely.
20
+
21
+ ## 30-second tour
22
+
23
+ ```ts
24
+ import { log, ConsoleLog, FileLog } from "@warlock.js/logger";
25
+
26
+ log.setChannels([
27
+ new ConsoleLog(),
28
+ new FileLog({ chunk: "daily" }),
29
+ ]);
30
+
31
+ await log.info("users", "register", "New user created");
32
+ await log.error("payments", "charge", new Error("Card declined"));
33
+ ```
34
+
35
+ The logger starts with no channels — nothing is printed or written until you register at least one.
36
+
37
+ ## The module · action · message pattern
38
+
39
+ Every call carries three pieces of context. Modules and actions become searchable keys in file and JSON channels:
40
+
41
+ ```ts
42
+ await log.info("auth", "login", "User signed in");
43
+ await log.warn("api", "rateLimitApproaching", "80% of quota used");
44
+ await log.success("payments", "captured", "Payment of $49.99 captured");
45
+ ```
46
+
47
+ Pass an object instead of positional args when you need `context` metadata:
48
+
49
+ ```ts
50
+ await log.error({
51
+ module: "orders",
52
+ action: "checkout",
53
+ message: "Card declined",
54
+ context: { orderId: "ord_9f2a", amount: 4999 },
55
+ });
56
+ ```
57
+
58
+ ## Levels
59
+
60
+ `debug` · `info` · `warn` · `error` · `success` · `fatal` — each has a shorthand method on the `log` singleton (and on every `Logger` instance). `fatal` is strictly above `error` for unrecoverable failures where the app is going down (failed bootstrap, `uncaughtException`); it does not auto-flush or exit on its own.
61
+
62
+ ## Built-in channels
63
+
64
+ | Channel | Name | Purpose |
65
+ |---|---|---|
66
+ | `ConsoleLog` | `"console"` | Colorized terminal output |
67
+ | `FileLog` | `"file"` | Plain-text files, optional chunking + rotation + grouping |
68
+ | `JSONFileLog` | `"fileJson"` | Structured JSON files — ideal for aggregators |
69
+ | `SentryLog` | `"sentry"` | Forwards to Sentry (events + breadcrumbs); needs the optional `@sentry/node` peer |
70
+
71
+ All channels share the `BasicLogConfigurations` options (`levels`, `filter`, `dateFormat`); `FileLog` / `JSONFileLog` add storage, chunking, rotation, and grouping options, and `SentryLog` adds `client` / `options` / `eventLevels`.
72
+
73
+ ## `log` and `Logger`
74
+
75
+ The package exports one default singleton and one class:
76
+
77
+ - **`log`** — a pre-instantiated `Logger`. Day-to-day logging *and* configuration both go through it: `log.info(...)`, `log.configure(...)`, `log.flush()` / `log.flushSync()`, `log.addChannel(...)`.
78
+ - **`Logger`** — the class. Use it when you need an isolated logger (libraries, sandboxes, parallel test suites).
79
+
80
+ `log` is a `Logger` instance, not a function — every level shortcut and configuration method is reachable on it. The bare-callable `log(data)` form was removed; use `log.log(data)` for the data-object form, or `log.info(...)` / `log.error(...)` / etc. for the positional form.
81
+
82
+ ## Graceful shutdown
83
+
84
+ `FileLog` and `JSONFileLog` buffer entries. Tell the logger to drain them on exit:
85
+
86
+ ```ts
87
+ log.configure({
88
+ channels: [new ConsoleLog(), new FileLog({ chunk: "daily" })],
89
+ autoFlushOn: ["SIGINT", "SIGTERM", "beforeExit"],
90
+ });
91
+ ```
92
+
93
+ Signal events flush then re-raise (so Node exits with its normal signal semantics); `beforeExit` flushes in place. For full control, call `log.flushSync()` (sync) — or `await log.flush()` (async, for network/async channels) — inside your own handler instead.
94
+
95
+ ## Capturing unhandled errors
96
+
97
+ ```ts
98
+ import { captureAnyUnhandledRejection } from "@warlock.js/logger";
99
+
100
+ captureAnyUnhandledRejection();
101
+ ```
102
+
103
+ Registers process-level handlers for `unhandledRejection` (→ `log.error("app", ...)`, process kept alive) and `uncaughtException` (→ `log.fatal("app", ...)`, then `process.exit(1)` so a fatal crash is never silently swallowed into `exit 0`). Pass `{ exitOnUncaughtException: false }` to log without exiting. Call once at startup, after channels are registered.
104
+
105
+ ## Custom channels
106
+
107
+ Extend `LogChannel` and implement `log(data)`:
108
+
109
+ ```ts
110
+ import { LogChannel, type LoggingData } from "@warlock.js/logger";
111
+
112
+ export class SlackLog extends LogChannel<{ webhookUrl: string }> {
113
+ public name = "slack";
114
+
115
+ public async log(data: LoggingData) {
116
+ if (!this.shouldBeLogged(data)) return;
117
+ await fetch(this.config("webhookUrl"), {
118
+ method: "POST",
119
+ headers: { "Content-Type": "application/json" },
120
+ body: JSON.stringify({
121
+ text: `[${data.type}] [${data.module}][${data.action}]: ${data.message}`,
122
+ }),
123
+ });
124
+ }
125
+ }
126
+ ```
127
+
128
+ Set `terminal = true` on the class if your channel writes to a TTY — otherwise ANSI codes are auto-stripped from string messages.
129
+
130
+ ## Full documentation
131
+
132
+ The complete guide lives in the project docs:
133
+
134
+ - Getting Started
135
+ - Configuration
136
+ - Channels (ConsoleLog, FileLog, JSONFileLog, SentryLog)
137
+ - Lifecycle & Flushing
138
+ - Capturing Unhandled Errors
139
+ - Custom Channels
140
+ - Recipes
141
+ - API Reference
142
+ - Types
143
+
144
+ ## Tests
145
+
146
+ This package uses Vitest. From the repo root:
147
+
148
+ ```bash
149
+ npx vitest run --root @warlock.js/logger
150
+ ```
151
+
152
+ ## License
153
+
154
+ MIT