@theholocron/logger 3.53.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Newton Koumantzelis
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 ADDED
@@ -0,0 +1,123 @@
1
+ # `@theholocron/logger`
2
+
3
+ Structured logging for the Holocron CLI and its plugins. A `Logger` adapter interface backed by [Pino](https://getpino.io), with `pino-pretty` for local dev, plain JSON for CI, and an [Axiom](https://axiom.co) transport for log aggregation.
4
+
5
+ Call sites depend on the `Logger` interface — never on Pino directly. Swapping the logging library is a one-file change.
6
+
7
+ > `logger` is the operational-output channel (internal state, debug traces, errors, structured context). It is **not** `print` — the user-facing UX output surface — and does not wrap or replace it. The two are parallel concerns.
8
+
9
+ ## Installation
10
+
11
+ ```sh
12
+ pnpm add @theholocron/logger
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```ts
18
+ import { createLogger } from "@theholocron/logger";
19
+
20
+ const { logger, runId } = createLogger({
21
+ level: "info",
22
+ axiom: process.env.HOLOCRON_AXIOM_TOKEN
23
+ ? {
24
+ dataset: process.env.HOLOCRON_AXIOM_DATASET!,
25
+ token: process.env.HOLOCRON_AXIOM_TOKEN,
26
+ }
27
+ : undefined,
28
+ });
29
+
30
+ const log = logger.child({ command: "sync-github", repo: "theholocron/configs" });
31
+ log.info({ branch: "main" }, "opening PR");
32
+ // → { level, time, runId, env, command, repo, branch, msg: "opening PR" }
33
+ ```
34
+
35
+ Pass child loggers down into modules so every line carries its context automatically:
36
+
37
+ ```ts
38
+ export async function runSyncGithub(input: { logger: Logger }) {
39
+ const log = input.logger.child({ module: "sync-github" });
40
+ log.debug("resolving remote");
41
+ }
42
+ ```
43
+
44
+ ## `Logger` interface
45
+
46
+ ```ts
47
+ interface Logger {
48
+ debug(obj: Record<string, unknown>, msg?: string): void;
49
+ debug(msg: string): void;
50
+ info(obj: Record<string, unknown>, msg?: string): void;
51
+ info(msg: string): void;
52
+ warn(obj: Record<string, unknown>, msg?: string): void;
53
+ warn(msg: string): void;
54
+ error(obj: Record<string, unknown>, msg?: string): void;
55
+ error(msg: string): void;
56
+ child(bindings: Record<string, unknown>): Logger;
57
+ }
58
+ ```
59
+
60
+ The overloads mirror Pino: object-first for structured lines, bare string for simple ones.
61
+
62
+ ## `createLogger(config?)`
63
+
64
+ Returns `{ logger, runId }`. `runId` is a UUID bound to every line the logger and its children emit — surface it via `print` when `--debug` or `--verbose` is set so a whole run can be pulled back out of Axiom.
65
+
66
+ | `config` field | Type | Notes |
67
+ | --------------- | ---------------------------------------- | ---------------------------------------------------------- |
68
+ | `level` | `"debug" \| "info" \| "warn" \| "error"` | Highest-priority level source. Optional. |
69
+ | `axiom.dataset` | `string` | Axiom dataset name. Supply from env vars only. |
70
+ | `axiom.token` | `string` | Axiom API token. Supply from env vars only — never config. |
71
+
72
+ ### Level resolution
73
+
74
+ 1. `config.level` — the resolved `--verbose` (`debug`) / `--quiet` (`error`) CLI flag, or `holocron.config` `log.level`, passed by the command layer
75
+ 2. `HOLOCRON_LOG_LEVEL` env var
76
+ 3. `"info"` (default)
77
+
78
+ An unrecognised value at any tier is ignored and resolution falls through. The resolved level applies to **every** transport — there is no separate Axiom gate.
79
+
80
+ ## Transports
81
+
82
+ | Environment | Output |
83
+ | ----------------------- | --------------------------------------------- |
84
+ | Local, TTY | `pino-pretty` — colourised, human-readable |
85
+ | CI (`CI` truthy) | Newline-delimited JSON to stdout |
86
+ | `config.axiom` supplied | Axiom, in a Pino worker thread (non-blocking) |
87
+
88
+ The Axiom transport is added only when `config.axiom` is supplied **and** `HOLOCRON_TELEMETRY` is not `"false"`. When Axiom is the only non-console transport, console JSON is kept alongside it so CI logs stay readable.
89
+
90
+ ### Axiom datasets
91
+
92
+ Selected by `HOLOCRON_AXIOM_DATASET` — one env var, one value per environment:
93
+
94
+ | Value | When |
95
+ | ---------------- | ---------------- |
96
+ | `holocron-ci` | CI (org secret) |
97
+ | `holocron-local` | local (optional) |
98
+
99
+ If `HOLOCRON_AXIOM_DATASET` is unset locally, local runs write only to `pino-pretty` — no Axiom connection is attempted.
100
+
101
+ ## Redaction
102
+
103
+ Sensitive field paths are stripped in Pino's serialisation layer, before any transport — pino-pretty, CI stdout, and Axiom alike. Redacted values become `[Redacted]`.
104
+
105
+ `token`, `secret`, `password`, `apiKey`, `secrets[*].value`, `headers.authorization`, `headers["x-api-key"]`, and the same keys one level down (`*.token`, `*.secret`, …). The full list is exported as `REDACTED_PATHS`.
106
+
107
+ ## Development
108
+
109
+ | Script | Description |
110
+ | -------------------- | ----------------------- |
111
+ | `pnpm build` | Bundle with tsdown |
112
+ | `pnpm test` | Run the vitest suite |
113
+ | `pnpm test:coverage` | Run tests with coverage |
114
+ | `pnpm typecheck` | `tsc --noEmit` |
115
+ | `pnpm lint` | ESLint |
116
+
117
+ ## Releases
118
+
119
+ Automated via semantic-release. See [CHANGELOG.md](../../CHANGELOG.md).
120
+
121
+ ## Documentation
122
+
123
+ <https://theholocron.github.io/holocron/logging/>
@@ -0,0 +1,128 @@
1
+ import "pino";
2
+ //#region src/interface.d.ts
3
+ /**
4
+ * The logging surface every Holocron command and plugin depends on.
5
+ *
6
+ * Call sites import `Logger` — never Pino directly. The concrete
7
+ * implementation ({@link PinoLogger}) is hidden behind this interface so the
8
+ * logging library can be swapped without touching a single call site.
9
+ *
10
+ * The overloads mirror Pino's native API: pass a context object first for
11
+ * structured logging (`log.info({ repo }, "sync complete")`) or a bare string
12
+ * for a simple line (`log.info("sync complete")`).
13
+ */
14
+ interface Logger {
15
+ debug(obj: Record<string, unknown>, msg?: string): void;
16
+ debug(msg: string): void;
17
+ info(obj: Record<string, unknown>, msg?: string): void;
18
+ info(msg: string): void;
19
+ warn(obj: Record<string, unknown>, msg?: string): void;
20
+ warn(msg: string): void;
21
+ error(obj: Record<string, unknown>, msg?: string): void;
22
+ error(msg: string): void;
23
+ /**
24
+ * Derive a child logger that inherits every binding from its parent and
25
+ * adds its own. Used to attach per-module context (`module`, `repo`, …)
26
+ * without threading extra fields through every call.
27
+ */
28
+ child(bindings: Record<string, unknown>): Logger;
29
+ }
30
+ /** Log levels, ordered least to most severe. */
31
+ type LogLevel = "debug" | "info" | "warn" | "error";
32
+ /** The four levels, in ascending severity — useful for validation. */
33
+ declare const LOG_LEVELS: readonly LogLevel[];
34
+ /** Runtime environment a logger was constructed in. */
35
+ type LogEnv = "ci" | "local";
36
+ //#endregion
37
+ //#region src/transports.d.ts
38
+ /** Axiom credentials — never read from `holocron.config`, only from env vars. */
39
+ interface AxiomTransportConfig {
40
+ dataset: string;
41
+ token: string;
42
+ }
43
+ //#endregion
44
+ //#region src/context.d.ts
45
+ /**
46
+ * A fresh correlation id for one command invocation. Every log line from a
47
+ * single `holocron` run carries this `runId`, so a whole run can be pulled
48
+ * back out of Axiom with one query.
49
+ */
50
+ declare function generateRunId(): string;
51
+ /**
52
+ * True when running inside CI. GitHub Actions (and most other providers) set
53
+ * `CI=true`; we also accept any other non-empty, non-`false` value.
54
+ */
55
+ declare function isCI(env?: NodeJS.ProcessEnv): boolean;
56
+ /** `"ci"` inside CI, otherwise `"local"` — bound on every root logger. */
57
+ declare function detectEnv(env?: NodeJS.ProcessEnv): LogEnv;
58
+ /** Narrow an arbitrary string to a {@link LogLevel}, or `undefined`. */
59
+ declare function parseLogLevel(value: string | undefined): LogLevel | undefined;
60
+ /**
61
+ * Resolve the effective log level in priority order:
62
+ *
63
+ * 1. `explicit` — already-resolved CLI flag (`--verbose` → `debug`,
64
+ * `--quiet` → `error`) or `holocron.config` `log.level`, passed by the
65
+ * command layer.
66
+ * 2. `HOLOCRON_LOG_LEVEL` env var.
67
+ * 3. `"info"` default.
68
+ *
69
+ * An unrecognised value at any tier is ignored and resolution falls through.
70
+ */
71
+ declare function resolveLevel(explicit?: LogLevel, env?: NodeJS.ProcessEnv): LogLevel;
72
+ /** True when the Axiom transport must be suppressed via `HOLOCRON_TELEMETRY=false`. */
73
+ declare function isTelemetryDisabled(env?: NodeJS.ProcessEnv): boolean;
74
+ //#endregion
75
+ //#region src/redact.d.ts
76
+ /**
77
+ * Sensitive field paths stripped from every log line before any transport —
78
+ * pino-pretty, CI stdout, and Axiom alike. Redaction happens in Pino's
79
+ * serialisation layer, so a raw token never leaves the process.
80
+ *
81
+ * Paths use Pino's redaction syntax: dotted access, `[*]` wildcards for
82
+ * arrays, and bracket-quoted keys for names that are not valid identifiers.
83
+ *
84
+ * @see https://getpino.io/#/docs/redaction
85
+ */
86
+ declare const REDACTED_PATHS: readonly string[];
87
+ /** Replacement string Pino writes in place of a redacted value. */
88
+ declare const REDACT_CENSOR = "[Redacted]";
89
+ //#endregion
90
+ //#region src/index.d.ts
91
+ interface LoggerConfig {
92
+ /**
93
+ * Explicit level — the highest-priority source. The command layer passes
94
+ * the resolved `--verbose` / `--quiet` flag or `holocron.config`
95
+ * `log.level` here. Falls through to `HOLOCRON_LOG_LEVEL`, then `"info"`.
96
+ */
97
+ level?: LogLevel;
98
+ /**
99
+ * Axiom credentials. Supply only from env vars (`HOLOCRON_AXIOM_TOKEN` /
100
+ * `HOLOCRON_AXIOM_DATASET`) — never from config files. Omit to skip the
101
+ * Axiom transport. Also skipped when `HOLOCRON_TELEMETRY=false`.
102
+ */
103
+ axiom?: AxiomTransportConfig;
104
+ }
105
+ interface CreateLoggerResult {
106
+ /** The logger to thread through commands and modules via `child()`. */
107
+ logger: Logger;
108
+ /**
109
+ * Correlation id bound to every line this logger (and its children) emit.
110
+ * Surface it to the user via `print` when `--debug` or `--verbose` is set
111
+ * so they can pull the run out of Axiom.
112
+ */
113
+ runId: string;
114
+ }
115
+ /**
116
+ * The single entry point for building a logger. Generates a `runId`, detects
117
+ * the environment, resolves the level, wires the right transports, and
118
+ * returns a ready {@link Logger}.
119
+ *
120
+ * ```ts
121
+ * const { logger, runId } = createLogger({ level, axiom });
122
+ * const log = logger.child({ command: "sync-github", repo });
123
+ * log.info({ branch }, "opening PR");
124
+ * ```
125
+ */
126
+ declare function createLogger(config?: LoggerConfig): CreateLoggerResult;
127
+ //#endregion
128
+ export { type AxiomTransportConfig, CreateLoggerResult, LOG_LEVELS, type LogEnv, type LogLevel, type Logger, LoggerConfig, REDACTED_PATHS, REDACT_CENSOR, createLogger, detectEnv, generateRunId, isCI, isTelemetryDisabled, parseLogLevel, resolveLevel };
package/dist/index.mjs ADDED
@@ -0,0 +1,235 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import pino from "pino";
3
+ //#region src/interface.ts
4
+ /** The four levels, in ascending severity — useful for validation. */
5
+ const LOG_LEVELS = [
6
+ "debug",
7
+ "info",
8
+ "warn",
9
+ "error"
10
+ ];
11
+ //#endregion
12
+ //#region src/context.ts
13
+ /**
14
+ * A fresh correlation id for one command invocation. Every log line from a
15
+ * single `holocron` run carries this `runId`, so a whole run can be pulled
16
+ * back out of Axiom with one query.
17
+ */
18
+ function generateRunId() {
19
+ return randomUUID();
20
+ }
21
+ /**
22
+ * True when running inside CI. GitHub Actions (and most other providers) set
23
+ * `CI=true`; we also accept any other non-empty, non-`false` value.
24
+ */
25
+ function isCI(env = process.env) {
26
+ const ci = env.CI;
27
+ if (!ci) return false;
28
+ return ci !== "false" && ci !== "0";
29
+ }
30
+ /** `"ci"` inside CI, otherwise `"local"` — bound on every root logger. */
31
+ function detectEnv(env = process.env) {
32
+ return isCI(env) ? "ci" : "local";
33
+ }
34
+ /** Narrow an arbitrary string to a {@link LogLevel}, or `undefined`. */
35
+ function parseLogLevel(value) {
36
+ return value && LOG_LEVELS.includes(value) ? value : void 0;
37
+ }
38
+ /**
39
+ * Resolve the effective log level in priority order:
40
+ *
41
+ * 1. `explicit` — already-resolved CLI flag (`--verbose` → `debug`,
42
+ * `--quiet` → `error`) or `holocron.config` `log.level`, passed by the
43
+ * command layer.
44
+ * 2. `HOLOCRON_LOG_LEVEL` env var.
45
+ * 3. `"info"` default.
46
+ *
47
+ * An unrecognised value at any tier is ignored and resolution falls through.
48
+ */
49
+ function resolveLevel(explicit, env = process.env) {
50
+ return explicit ?? parseLogLevel(env.HOLOCRON_LOG_LEVEL) ?? "info";
51
+ }
52
+ /** True when the Axiom transport must be suppressed via `HOLOCRON_TELEMETRY=false`. */
53
+ function isTelemetryDisabled(env = process.env) {
54
+ return env.HOLOCRON_TELEMETRY === "false";
55
+ }
56
+ //#endregion
57
+ //#region src/redact.ts
58
+ /**
59
+ * Sensitive field paths stripped from every log line before any transport —
60
+ * pino-pretty, CI stdout, and Axiom alike. Redaction happens in Pino's
61
+ * serialisation layer, so a raw token never leaves the process.
62
+ *
63
+ * Paths use Pino's redaction syntax: dotted access, `[*]` wildcards for
64
+ * arrays, and bracket-quoted keys for names that are not valid identifiers.
65
+ *
66
+ * @see https://getpino.io/#/docs/redaction
67
+ */
68
+ const REDACTED_PATHS = [
69
+ "token",
70
+ "secret",
71
+ "password",
72
+ "apiKey",
73
+ "secrets[*].value",
74
+ "headers.authorization",
75
+ "headers[\"x-api-key\"]",
76
+ "*.token",
77
+ "*.secret",
78
+ "*.password",
79
+ "*.apiKey"
80
+ ];
81
+ /** Replacement string Pino writes in place of a redacted value. */
82
+ const REDACT_CENSOR = "[Redacted]";
83
+ /** Ready-to-use Pino `redact` option. */
84
+ const redactOptions = {
85
+ paths: [...REDACTED_PATHS],
86
+ censor: REDACT_CENSOR
87
+ };
88
+ //#endregion
89
+ //#region src/transports.ts
90
+ const prettyTarget = (level) => ({
91
+ target: "pino-pretty",
92
+ level,
93
+ options: {
94
+ colorize: true,
95
+ translateTime: "SYS:HH:MM:ss",
96
+ ignore: "pid,hostname"
97
+ }
98
+ });
99
+ const stdoutJsonTarget = (level) => ({
100
+ target: "pino/file",
101
+ level,
102
+ options: { destination: 1 }
103
+ });
104
+ const axiomTarget = (level, axiom) => ({
105
+ target: "@axiomhq/pino",
106
+ level,
107
+ options: {
108
+ dataset: axiom.dataset,
109
+ token: axiom.token
110
+ }
111
+ });
112
+ /**
113
+ * Build the Pino `transport` option for the current environment.
114
+ *
115
+ * | Environment | Output |
116
+ * | -------------------------- | --------------------------------------------------- |
117
+ * | Local, TTY, no Axiom | `pino-pretty` only |
118
+ * | CI, no Axiom | `undefined` — Pino's default NDJSON to stdout |
119
+ * | Local, TTY, with Axiom | `pino-pretty` + Axiom |
120
+ * | CI, with Axiom | NDJSON to stdout + Axiom |
121
+ *
122
+ * The Axiom transport is dropped entirely when `telemetryDisabled` is set,
123
+ * regardless of whether credentials were supplied. Every transport runs on
124
+ * the same resolved `level` — there is no Axiom-only gate.
125
+ *
126
+ * Returning `undefined` lets `createLogger` fall back to a plain
127
+ * `pino({ ... })` with no worker thread — the cheapest path, and exactly
128
+ * what CI wants.
129
+ */
130
+ function buildTransport(input) {
131
+ const { level, axiom, ci, tty, telemetryDisabled } = input;
132
+ const pretty = !ci && tty;
133
+ const targets = [];
134
+ if (pretty) targets.push(prettyTarget(level));
135
+ if (axiom && !telemetryDisabled) targets.push(axiomTarget(level, axiom));
136
+ if (targets.length === 0) return void 0;
137
+ if (!pretty) targets.unshift(stdoutJsonTarget(level));
138
+ if (targets.length === 1) return targets[0];
139
+ return { targets };
140
+ }
141
+ //#endregion
142
+ //#region src/pino.ts
143
+ /**
144
+ * The one concrete {@link Logger}. Nothing outside this package should name
145
+ * it — construct loggers with `createLogger`. It is a thin pass-through to a
146
+ * Pino instance; the interface overloads mirror Pino's own, so each method is
147
+ * a single delegated call.
148
+ */
149
+ var PinoLogger = class PinoLogger {
150
+ #pino;
151
+ constructor(instance) {
152
+ this.#pino = instance;
153
+ }
154
+ debug(objOrMsg, msg) {
155
+ this.#emit("debug", objOrMsg, msg);
156
+ }
157
+ info(objOrMsg, msg) {
158
+ this.#emit("info", objOrMsg, msg);
159
+ }
160
+ warn(objOrMsg, msg) {
161
+ this.#emit("warn", objOrMsg, msg);
162
+ }
163
+ error(objOrMsg, msg) {
164
+ this.#emit("error", objOrMsg, msg);
165
+ }
166
+ child(bindings) {
167
+ return new PinoLogger(this.#pino.child(bindings));
168
+ }
169
+ #emit(level, objOrMsg, msg) {
170
+ if (typeof objOrMsg === "string") this.#pino[level](objOrMsg);
171
+ else this.#pino[level](objOrMsg, msg);
172
+ }
173
+ };
174
+ /**
175
+ * Assemble the Pino `LoggerOptions`: resolved level, `runId` / `env` on every
176
+ * line, ISO timestamps, sensitive-field redaction, and — unless a capture
177
+ * `destination` is in play — the environment-appropriate transport from
178
+ * {@link buildTransport}.
179
+ */
180
+ function buildPinoOptions(input) {
181
+ const options = {
182
+ level: input.level,
183
+ base: input.base,
184
+ timestamp: pino.stdTimeFunctions.isoTime,
185
+ redact: {
186
+ paths: [...redactOptions.paths],
187
+ censor: redactOptions.censor
188
+ }
189
+ };
190
+ if (input.destination) return options;
191
+ const transport = buildTransport(input);
192
+ if (transport) options.transport = transport;
193
+ return options;
194
+ }
195
+ /**
196
+ * Construct the underlying Pino instance. Writes to `destination` when one is
197
+ * supplied (tests), otherwise to the transports {@link buildPinoOptions} wired.
198
+ */
199
+ function createPinoInstance(input) {
200
+ const options = buildPinoOptions(input);
201
+ return input.destination ? pino(options, input.destination) : pino(options);
202
+ }
203
+ //#endregion
204
+ //#region src/index.ts
205
+ /**
206
+ * The single entry point for building a logger. Generates a `runId`, detects
207
+ * the environment, resolves the level, wires the right transports, and
208
+ * returns a ready {@link Logger}.
209
+ *
210
+ * ```ts
211
+ * const { logger, runId } = createLogger({ level, axiom });
212
+ * const log = logger.child({ command: "sync-github", repo });
213
+ * log.info({ branch }, "opening PR");
214
+ * ```
215
+ */
216
+ function createLogger(config = {}) {
217
+ const runId = generateRunId();
218
+ const env = detectEnv();
219
+ return {
220
+ logger: new PinoLogger(createPinoInstance({
221
+ level: resolveLevel(config.level),
222
+ axiom: config.axiom,
223
+ ci: isCI(),
224
+ tty: Boolean(process.stdout.isTTY),
225
+ telemetryDisabled: isTelemetryDisabled(),
226
+ base: {
227
+ runId,
228
+ env
229
+ }
230
+ })),
231
+ runId
232
+ };
233
+ }
234
+ //#endregion
235
+ export { LOG_LEVELS, REDACTED_PATHS, REDACT_CENSOR, createLogger, detectEnv, generateRunId, isCI, isTelemetryDisabled, parseLogLevel, resolveLevel };
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@theholocron/logger",
3
+ "version": "3.53.0",
4
+ "description": "Structured logging for Holocron — a Pino-backed Logger adapter interface with pino-pretty, CI JSON, and Axiom transports.",
5
+ "keywords": [
6
+ "axiom",
7
+ "holocron",
8
+ "logging",
9
+ "logger",
10
+ "pino",
11
+ "structured-logging",
12
+ "theholocron"
13
+ ],
14
+ "homepage": "https://github.com/theholocron/holocron/tree/main/packages/logger#readme",
15
+ "bugs": "https://github.com/theholocron/holocron/issues",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/theholocron/holocron.git",
19
+ "directory": "packages/logger"
20
+ },
21
+ "license": "MIT",
22
+ "author": "Newton Koumantzelis",
23
+ "sideEffects": false,
24
+ "type": "module",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.mts",
28
+ "import": "./dist/index.mjs",
29
+ "default": "./dist/index.mjs"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "dependencies": {
36
+ "@axiomhq/pino": "^2.0.0",
37
+ "pino": "^10.3.1",
38
+ "pino-pretty": "^13.1.3"
39
+ },
40
+ "devDependencies": {
41
+ "@theholocron/eslint-config": "^7.32.1",
42
+ "@theholocron/tsconfig": "^7.32.1",
43
+ "@theholocron/tsdown-config": "^7.32.1",
44
+ "@theholocron/vitest-config": "^7.32.1",
45
+ "@types/node": "^26",
46
+ "@vitest/coverage-v8": "^4.1.11",
47
+ "@vitest/eslint-plugin": "^1.6.27",
48
+ "eslint": "^10.8.1",
49
+ "eslint-plugin-n": "^18.3.0",
50
+ "globals": "^17.11.0",
51
+ "tsdown": "^0.22.14",
52
+ "typescript": "^5.9.3",
53
+ "vitest": "^4.1.11"
54
+ },
55
+ "engines": {
56
+ "node": ">=22"
57
+ },
58
+ "publishConfig": {
59
+ "access": "public"
60
+ },
61
+ "scripts": {
62
+ "build": "tsdown",
63
+ "lint": "eslint .",
64
+ "typecheck": "tsc --noEmit",
65
+ "test": "vitest run",
66
+ "test:watch": "vitest",
67
+ "test:coverage": "vitest run --coverage"
68
+ }
69
+ }