@warlock.js/logger 4.1.14 → 4.2.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +146 -145
  4. package/cjs/index.cjs +276 -11
  5. package/cjs/index.cjs.map +1 -1
  6. package/esm/channels/console-log.d.mts +1 -1
  7. package/esm/channels/console-log.d.mts.map +1 -1
  8. package/esm/channels/console-log.mjs +4 -1
  9. package/esm/channels/console-log.mjs.map +1 -1
  10. package/esm/channels/file-log.d.mts +13 -3
  11. package/esm/channels/file-log.d.mts.map +1 -1
  12. package/esm/channels/file-log.mjs +15 -1
  13. package/esm/channels/file-log.mjs.map +1 -1
  14. package/esm/channels/index.mjs +1 -0
  15. package/esm/channels/json-file-log.d.mts +1 -1
  16. package/esm/channels/json-file-log.d.mts.map +1 -1
  17. package/esm/channels/json-file-log.mjs +1 -1
  18. package/esm/channels/json-file-log.mjs.map +1 -1
  19. package/esm/channels/sentry-log.d.mts +182 -0
  20. package/esm/channels/sentry-log.d.mts.map +1 -0
  21. package/esm/channels/sentry-log.mjs +202 -0
  22. package/esm/channels/sentry-log.mjs.map +1 -0
  23. package/esm/index.d.mts +2 -1
  24. package/esm/index.mjs +2 -1
  25. package/esm/log-channel.d.mts +9 -1
  26. package/esm/log-channel.d.mts.map +1 -1
  27. package/esm/log-channel.mjs +1 -1
  28. package/esm/log-channel.mjs.map +1 -1
  29. package/esm/logger.d.mts +32 -1
  30. package/esm/logger.d.mts.map +1 -1
  31. package/esm/logger.mjs +44 -2
  32. package/esm/logger.mjs.map +1 -1
  33. package/esm/redact/redact.d.mts +1 -1
  34. package/esm/redact/redact.d.mts.map +1 -1
  35. package/esm/redact/redact.mjs +1 -1
  36. package/esm/redact/redact.mjs.map +1 -1
  37. package/esm/types.d.mts +19 -3
  38. package/esm/types.d.mts.map +1 -1
  39. package/esm/utils/capture-unhandled-errors.d.mts +9 -1
  40. package/esm/utils/capture-unhandled-errors.d.mts.map +1 -1
  41. package/esm/utils/capture-unhandled-errors.mjs +10 -2
  42. package/esm/utils/capture-unhandled-errors.mjs.map +1 -1
  43. package/esm/utils/clear-message.d.mts +1 -1
  44. package/esm/utils/clear-message.d.mts.map +1 -1
  45. package/esm/utils/clear-message.mjs +1 -1
  46. package/esm/utils/clear-message.mjs.map +1 -1
  47. package/esm/utils/safe-json-stringify.d.mts +1 -1
  48. package/esm/utils/safe-json-stringify.d.mts.map +1 -1
  49. package/esm/utils/safe-json-stringify.mjs +1 -1
  50. package/esm/utils/safe-json-stringify.mjs.map +1 -1
  51. package/llms-full.txt +1497 -1296
  52. package/llms.txt +20 -19
  53. package/package.json +5 -2
  54. package/skills/capture-unhandled-errors/SKILL.md +103 -103
  55. package/skills/filter-log-entries/SKILL.md +120 -120
  56. package/skills/flush-logs-on-shutdown/SKILL.md +117 -91
  57. package/skills/logger-basics/SKILL.md +88 -85
  58. package/skills/overview/SKILL.md +90 -86
  59. package/skills/pick-log-channel/SKILL.md +155 -139
  60. package/skills/ship-logs-to-sentry/SKILL.md +118 -0
  61. package/skills/write-custom-log-channel/SKILL.md +190 -160
package/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog — @warlock.js/logger
2
+
3
+ All notable changes to `@warlock.js/logger` are documented in this file.
4
+
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
+
7
+ ## [Unreleased]
8
+
9
+ ## 4.2.0
10
+
11
+ ### Added
12
+
13
+ - `log.flush()` — awaitable async counterpart to `flushSync()`. Drains every channel that implements `flush()` via `Promise.allSettled` with per-channel isolation, so one channel's failure can't break shutdown. `FileLog` / `JSONFileLog` implement it; `ConsoleLog` writes synchronously and doesn't need it.
14
+ - `SentryLog` channel — forwards entries to Sentry. `eventLevels` (`fatal` / `error` / `warn` by default) become events (`captureException` for `Error` messages, `captureMessage` otherwise); every other level becomes a breadcrumb. `module` / `action` are tags, `context` is a structured Sentry context. `@sentry/node` is an **optional peer**, lazily imported — pass an existing `client` or `options`.
15
+ - `log.fatal()` + `fatal` log level — ranked strictly above `error` for unrecoverable failures (failed bootstrap, `uncaughtException`). Does not auto-flush or exit; caller decides.
16
+ - `ConsoleLog` renders `fatal` with a `☠` icon on a bright-red background and bold red-bright message, distinct from `error`'s `✗`.
17
+
18
+ ### Changed
19
+
20
+ - `captureAnyUnhandledRejection()` now escalates `uncaughtException` to `log.fatal` (was `log.error`). Node terminates the process by default, so it's semantically fatal — makes "page only on fatal" alerting clean. `unhandledRejection` stays at `error`.
21
+ - `LoggingData.type` is now typed as `LogLevel` (was a duplicated inline union — code-standards cleanup).
22
+ - `LogContract` and the `LogChannel` base now expose an optional `flush?()` alongside the existing `flushSync?()`.
23
+
24
+ ### Fixed
25
+
26
+ - `@sentry/node` is now referenced only via local minimal types + an indirect dynamic import, so source-served consumers (the package's `main` → `./src/index.ts`) no longer get a `TS2307: Cannot find module '@sentry/node'` when they (correctly) don't install the optional peer. Proven by pruning the SDK and running the full suite + `tsc --noEmit` clean.
27
+
28
+ ## 4.1.15
29
+
30
+ - Baseline — per-package changelog tracking starts at this version.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Hassan Zohdy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,145 +1,146 @@
1
- # @warlock.js/logger
2
-
3
- Structured, multi-channel logging for Node.js — five severity levels, a clean three-argument API, and full TypeScript support. Non-blocking by default; synchronous 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
- ## 30-second tour
14
-
15
- ```ts
16
- import { log, ConsoleLog, FileLog } from "@warlock.js/logger";
17
-
18
- log.setChannels([
19
- new ConsoleLog(),
20
- new FileLog({ chunk: "daily" }),
21
- ]);
22
-
23
- await log.info("users", "register", "New user created");
24
- await log.error("payments", "charge", new Error("Card declined"));
25
- ```
26
-
27
- The logger starts with no channels — nothing is printed or written until you register at least one.
28
-
29
- ## The module · action · message pattern
30
-
31
- Every call carries three pieces of context. Modules and actions become searchable keys in file and JSON channels:
32
-
33
- ```ts
34
- await log.info("auth", "login", "User signed in");
35
- await log.warn("api", "rateLimitApproaching", "80% of quota used");
36
- await log.success("payments", "captured", "Payment of $49.99 captured");
37
- ```
38
-
39
- Pass an object instead of positional args when you need `context` metadata:
40
-
41
- ```ts
42
- await log.error({
43
- module: "orders",
44
- action: "checkout",
45
- message: "Card declined",
46
- context: { orderId: "ord_9f2a", amount: 4999 },
47
- });
48
- ```
49
-
50
- ## Levels
51
-
52
- `debug` · `info` · `warn` · `error` · `success` — each has a shorthand method on the `log` singleton (and on every `Logger` instance).
53
-
54
- ## Built-in channels
55
-
56
- | Channel | Name | Purpose |
57
- |---|---|---|
58
- | `ConsoleLog` | `"console"` | Colorized terminal output |
59
- | `FileLog` | `"file"` | Plain-text files, optional chunking + rotation + grouping |
60
- | `JSONFileLog` | `"fileJson"` | Structured JSON files — ideal for aggregators |
61
-
62
- All three share the `BasicLogConfigurations` options (`levels`, `filter`, `dateFormat`); `FileLog` / `JSONFileLog` add storage, chunking, rotation, and grouping options on top.
63
-
64
- ## `log` and `Logger`
65
-
66
- The package exports one default singleton and one class:
67
-
68
- - **`log`** — a pre-instantiated `Logger`. Day-to-day logging *and* configuration both go through it: `log.info(...)`, `log.configure(...)`, `log.flushSync()`, `log.addChannel(...)`.
69
- - **`Logger`** — the class. Use it when you need an isolated logger (libraries, sandboxes, parallel test suites).
70
-
71
- `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.
72
-
73
- ## Graceful shutdown
74
-
75
- `FileLog` and `JSONFileLog` buffer entries. Tell the logger to drain them on exit:
76
-
77
- ```ts
78
- log.configure({
79
- channels: [new ConsoleLog(), new FileLog({ chunk: "daily" })],
80
- autoFlushOn: ["SIGINT", "SIGTERM", "beforeExit"],
81
- });
82
- ```
83
-
84
- Signal events flush then re-raise (so Node exits with its normal signal semantics); `beforeExit` flushes in place. For full control, call `log.flushSync()` manually inside your own handler instead.
85
-
86
- ## Capturing unhandled errors
87
-
88
- ```ts
89
- import { captureAnyUnhandledRejection } from "@warlock.js/logger";
90
-
91
- captureAnyUnhandledRejection();
92
- ```
93
-
94
- Registers process-level handlers for `unhandledRejection` and `uncaughtException`, forwarding both to `log.error("app", ...)`. Call once at startup, after channels are registered.
95
-
96
- ## Custom channels
97
-
98
- Extend `LogChannel` and implement `log(data)`:
99
-
100
- ```ts
101
- import { LogChannel, type LoggingData } from "@warlock.js/logger";
102
-
103
- export class SlackLog extends LogChannel<{ webhookUrl: string }> {
104
- public name = "slack";
105
-
106
- public async log(data: LoggingData) {
107
- if (!this.shouldBeLogged(data)) return;
108
- await fetch(this.config("webhookUrl"), {
109
- method: "POST",
110
- headers: { "Content-Type": "application/json" },
111
- body: JSON.stringify({
112
- text: `[${data.type}] [${data.module}][${data.action}]: ${data.message}`,
113
- }),
114
- });
115
- }
116
- }
117
- ```
118
-
119
- Set `terminal = true` on the class if your channel writes to a TTY — otherwise ANSI codes are auto-stripped from string messages.
120
-
121
- ## Full documentation
122
-
123
- The complete guide lives in the project docs:
124
-
125
- - Getting Started
126
- - Configuration
127
- - Channels (ConsoleLog, FileLog, JSONFileLog)
128
- - Lifecycle & Flushing
129
- - Capturing Unhandled Errors
130
- - Custom Channels
131
- - Recipes
132
- - API Reference
133
- - Types
134
-
135
- ## Tests
136
-
137
- This package uses Vitest. From the repo root:
138
-
139
- ```bash
140
- npx vitest run --root @warlock.js/logger
141
- ```
142
-
143
- ## License
144
-
145
- MIT
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
+ ## 30-second tour
14
+
15
+ ```ts
16
+ import { log, ConsoleLog, FileLog } from "@warlock.js/logger";
17
+
18
+ log.setChannels([
19
+ new ConsoleLog(),
20
+ new FileLog({ chunk: "daily" }),
21
+ ]);
22
+
23
+ await log.info("users", "register", "New user created");
24
+ await log.error("payments", "charge", new Error("Card declined"));
25
+ ```
26
+
27
+ The logger starts with no channels — nothing is printed or written until you register at least one.
28
+
29
+ ## The module · action · message pattern
30
+
31
+ Every call carries three pieces of context. Modules and actions become searchable keys in file and JSON channels:
32
+
33
+ ```ts
34
+ await log.info("auth", "login", "User signed in");
35
+ await log.warn("api", "rateLimitApproaching", "80% of quota used");
36
+ await log.success("payments", "captured", "Payment of $49.99 captured");
37
+ ```
38
+
39
+ Pass an object instead of positional args when you need `context` metadata:
40
+
41
+ ```ts
42
+ await log.error({
43
+ module: "orders",
44
+ action: "checkout",
45
+ message: "Card declined",
46
+ context: { orderId: "ord_9f2a", amount: 4999 },
47
+ });
48
+ ```
49
+
50
+ ## Levels
51
+
52
+ `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.
53
+
54
+ ## Built-in channels
55
+
56
+ | Channel | Name | Purpose |
57
+ |---|---|---|
58
+ | `ConsoleLog` | `"console"` | Colorized terminal output |
59
+ | `FileLog` | `"file"` | Plain-text files, optional chunking + rotation + grouping |
60
+ | `JSONFileLog` | `"fileJson"` | Structured JSON files — ideal for aggregators |
61
+ | `SentryLog` | `"sentry"` | Forwards to Sentry (events + breadcrumbs); needs the optional `@sentry/node` peer |
62
+
63
+ All channels share the `BasicLogConfigurations` options (`levels`, `filter`, `dateFormat`); `FileLog` / `JSONFileLog` add storage, chunking, rotation, and grouping options, and `SentryLog` adds `client` / `options` / `eventLevels`.
64
+
65
+ ## `log` and `Logger`
66
+
67
+ The package exports one default singleton and one class:
68
+
69
+ - **`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(...)`.
70
+ - **`Logger`** — the class. Use it when you need an isolated logger (libraries, sandboxes, parallel test suites).
71
+
72
+ `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.
73
+
74
+ ## Graceful shutdown
75
+
76
+ `FileLog` and `JSONFileLog` buffer entries. Tell the logger to drain them on exit:
77
+
78
+ ```ts
79
+ log.configure({
80
+ channels: [new ConsoleLog(), new FileLog({ chunk: "daily" })],
81
+ autoFlushOn: ["SIGINT", "SIGTERM", "beforeExit"],
82
+ });
83
+ ```
84
+
85
+ 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.
86
+
87
+ ## Capturing unhandled errors
88
+
89
+ ```ts
90
+ import { captureAnyUnhandledRejection } from "@warlock.js/logger";
91
+
92
+ captureAnyUnhandledRejection();
93
+ ```
94
+
95
+ Registers process-level handlers for `unhandledRejection` and `uncaughtException`, forwarding both to `log.error("app", ...)`. Call once at startup, after channels are registered.
96
+
97
+ ## Custom channels
98
+
99
+ Extend `LogChannel` and implement `log(data)`:
100
+
101
+ ```ts
102
+ import { LogChannel, type LoggingData } from "@warlock.js/logger";
103
+
104
+ export class SlackLog extends LogChannel<{ webhookUrl: string }> {
105
+ public name = "slack";
106
+
107
+ public async log(data: LoggingData) {
108
+ if (!this.shouldBeLogged(data)) return;
109
+ await fetch(this.config("webhookUrl"), {
110
+ method: "POST",
111
+ headers: { "Content-Type": "application/json" },
112
+ body: JSON.stringify({
113
+ text: `[${data.type}] [${data.module}][${data.action}]: ${data.message}`,
114
+ }),
115
+ });
116
+ }
117
+ }
118
+ ```
119
+
120
+ Set `terminal = true` on the class if your channel writes to a TTY — otherwise ANSI codes are auto-stripped from string messages.
121
+
122
+ ## Full documentation
123
+
124
+ The complete guide lives in the project docs:
125
+
126
+ - Getting Started
127
+ - Configuration
128
+ - Channels (ConsoleLog, FileLog, JSONFileLog, SentryLog)
129
+ - Lifecycle & Flushing
130
+ - Capturing Unhandled Errors
131
+ - Custom Channels
132
+ - Recipes
133
+ - API Reference
134
+ - Types
135
+
136
+ ## Tests
137
+
138
+ This package uses Vitest. From the repo root:
139
+
140
+ ```bash
141
+ npx vitest run --root @warlock.js/logger
142
+ ```
143
+
144
+ ## License
145
+
146
+ MIT