@pencroff-lab/kore 0.1.2 → 0.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.
- package/README.md +32 -1
- package/dist/cjs/src/utils/format_dt.d.ts +16 -15
- package/dist/cjs/src/utils/format_dt.d.ts.map +1 -1
- package/dist/cjs/src/utils/format_dt.js +20 -16
- package/dist/cjs/src/utils/format_dt.js.map +1 -1
- package/dist/cjs/src/utils/index.d.ts +1 -0
- package/dist/cjs/src/utils/index.d.ts.map +1 -1
- package/dist/cjs/src/utils/index.js +1 -0
- package/dist/cjs/src/utils/index.js.map +1 -1
- package/dist/cjs/src/utils/logger.d.ts +271 -0
- package/dist/cjs/src/utils/logger.d.ts.map +1 -0
- package/dist/cjs/src/utils/logger.js +340 -0
- package/dist/cjs/src/utils/logger.js.map +1 -0
- package/dist/esm/src/utils/format_dt.d.ts +16 -15
- package/dist/esm/src/utils/format_dt.d.ts.map +1 -1
- package/dist/esm/src/utils/format_dt.js +20 -16
- package/dist/esm/src/utils/format_dt.js.map +1 -1
- package/dist/esm/src/utils/index.d.ts +1 -0
- package/dist/esm/src/utils/index.d.ts.map +1 -1
- package/dist/esm/src/utils/index.js +1 -0
- package/dist/esm/src/utils/index.js.map +1 -1
- package/dist/esm/src/utils/logger.d.ts +271 -0
- package/dist/esm/src/utils/logger.d.ts.map +1 -0
- package/dist/esm/src/utils/logger.js +335 -0
- package/dist/esm/src/utils/logger.js.map +1 -0
- package/docs/format_dt.md +42 -22
- package/docs/logger.md +342 -0
- package/docs/logging_guide.md +427 -0
- package/llms.txt +3 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -19,6 +19,8 @@ Detailed API documentation for each module:
|
|
|
19
19
|
- [Err](docs/err.md) -- Immutable, value-based error type with wrapping, aggregation, and serialization
|
|
20
20
|
- [Outcome\<T\>](docs/outcome.md) -- Monadic container for type-safe error handling with tuple-first API
|
|
21
21
|
- [dtStamp](docs/format_dt.md) -- Filesystem/log-safe date formatting utility
|
|
22
|
+
- [Logger](docs/logger.md) -- Structured logging with transport DI and Err integration
|
|
23
|
+
- [Logging Guide](docs/logging_guide.md) -- Patterns, conventions, and integration strategies
|
|
22
24
|
|
|
23
25
|
## API
|
|
24
26
|
|
|
@@ -209,10 +211,39 @@ import { dtStamp } from "@pencroff-lab/kore";
|
|
|
209
211
|
dtStamp(); // "20260218_153045"
|
|
210
212
|
dtStamp(new Date(), { parts: "date" }); // "20260218"
|
|
211
213
|
dtStamp(new Date(), { parts: "time", ms: true }); // "153045_123"
|
|
212
|
-
dtStamp(new Date(), {
|
|
214
|
+
dtStamp(new Date(), { readable: true }); // "2026-02-18_15:30:45"
|
|
213
215
|
dtStamp(new Date(), { tz: "local" }); // uses local timezone
|
|
214
216
|
```
|
|
215
217
|
|
|
218
|
+
#### Logger
|
|
219
|
+
|
|
220
|
+
Structured, callable logger with transport DI, child loggers, and automatic `Err` formatting.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { log, createLogger } from "@pencroff-lab/kore";
|
|
224
|
+
|
|
225
|
+
// Default logger
|
|
226
|
+
log("Application started");
|
|
227
|
+
log(log.WARN, "Connection slow");
|
|
228
|
+
log(log.ERROR, "Failed to save", { userId: "123" });
|
|
229
|
+
|
|
230
|
+
// Module-specific logger
|
|
231
|
+
const dbLog = createLogger("database");
|
|
232
|
+
dbLog("Connected to postgres");
|
|
233
|
+
|
|
234
|
+
// Child loggers with inherited context
|
|
235
|
+
const userLog = dbLog.child("users", { version: "1.0" });
|
|
236
|
+
userLog("User created");
|
|
237
|
+
// Output: [database] [users] User created {"version":"1.0"}
|
|
238
|
+
|
|
239
|
+
// Err instances rendered automatically
|
|
240
|
+
const [data, err] = fetchData();
|
|
241
|
+
if (err) {
|
|
242
|
+
log(log.ERROR, "Fetch failed", err);
|
|
243
|
+
// Output includes indented Err.toString() below the log line
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
216
247
|
## Development
|
|
217
248
|
|
|
218
249
|
```bash
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
export interface DtStampOptions {
|
|
5
5
|
/**
|
|
6
6
|
* Character(s) between date/time segments.
|
|
7
|
-
* Ignored when `compact` is `true`.
|
|
8
7
|
* @default "_"
|
|
9
8
|
*/
|
|
10
9
|
delimiter?: string;
|
|
@@ -23,16 +22,18 @@ export interface DtStampOptions {
|
|
|
23
22
|
/**
|
|
24
23
|
* Which parts of the stamp to include.
|
|
25
24
|
* - `"datetime"` -- full stamp (date + time)
|
|
26
|
-
* - `"date"` -- date only
|
|
27
|
-
* - `"time"` -- time only
|
|
25
|
+
* - `"date"` -- date only
|
|
26
|
+
* - `"time"` -- time only
|
|
28
27
|
* @default "datetime"
|
|
29
28
|
*/
|
|
30
29
|
parts?: "datetime" | "date" | "time";
|
|
31
30
|
/**
|
|
32
|
-
* When `true`,
|
|
31
|
+
* When `true`, formats with human-readable separators:
|
|
32
|
+
* dashes in date (`YYYY-MM-DD`), colons in time (`HH:MM:SS`),
|
|
33
|
+
* and `.` before milliseconds in time-only mode (`HH:MM:SS.mmm`).
|
|
33
34
|
* @default false
|
|
34
35
|
*/
|
|
35
|
-
|
|
36
|
+
readable?: boolean;
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
39
|
* Format a `Date` into a filesystem/log-safe timestamp string.
|
|
@@ -41,7 +42,7 @@ export interface DtStampOptions {
|
|
|
41
42
|
* and anywhere a human-readable but machine-sortable date/time is needed.
|
|
42
43
|
*
|
|
43
44
|
* @param date - Date to format. Defaults to `new Date()` when `null` or omitted.
|
|
44
|
-
* @param options - Formatting options (delimiter, milliseconds, timezone, parts,
|
|
45
|
+
* @param options - Formatting options (delimiter, milliseconds, timezone, parts, readable)
|
|
45
46
|
* @returns Formatted timestamp string
|
|
46
47
|
*
|
|
47
48
|
* @example Default (UTC datetime with underscore delimiter)
|
|
@@ -50,22 +51,22 @@ export interface DtStampOptions {
|
|
|
50
51
|
* // "20240315_103045"
|
|
51
52
|
* ```
|
|
52
53
|
*
|
|
53
|
-
* @example
|
|
54
|
+
* @example Readable datetime with milliseconds
|
|
54
55
|
* ```typescript
|
|
55
|
-
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), {
|
|
56
|
-
* // "
|
|
56
|
+
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { readable: true, ms: true });
|
|
57
|
+
* // "2024-03-15_10:30:45_123"
|
|
57
58
|
* ```
|
|
58
59
|
*
|
|
59
|
-
* @example
|
|
60
|
+
* @example Readable date only
|
|
60
61
|
* ```typescript
|
|
61
|
-
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { parts: "date" });
|
|
62
|
-
* // "
|
|
62
|
+
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { readable: true, parts: "date" });
|
|
63
|
+
* // "2024-03-15"
|
|
63
64
|
* ```
|
|
64
65
|
*
|
|
65
|
-
* @example
|
|
66
|
+
* @example Readable time with milliseconds
|
|
66
67
|
* ```typescript
|
|
67
|
-
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { parts: "time", ms: true });
|
|
68
|
-
* // "
|
|
68
|
+
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { readable: true, parts: "time", ms: true });
|
|
69
|
+
* // "10:30:45.123"
|
|
69
70
|
* ```
|
|
70
71
|
*
|
|
71
72
|
* @example Custom delimiter
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format_dt.d.ts","sourceRoot":"","sources":["../../../../src/utils/format_dt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B
|
|
1
|
+
{"version":3,"file":"format_dt.d.ts","sourceRoot":"","sources":["../../../../src/utils/format_dt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,EAAE,CAAC,EAAE,OAAO,CAAC;IACb;;;;;OAKG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAkD5E"}
|
|
@@ -8,7 +8,7 @@ exports.dtStamp = dtStamp;
|
|
|
8
8
|
* and anywhere a human-readable but machine-sortable date/time is needed.
|
|
9
9
|
*
|
|
10
10
|
* @param date - Date to format. Defaults to `new Date()` when `null` or omitted.
|
|
11
|
-
* @param options - Formatting options (delimiter, milliseconds, timezone, parts,
|
|
11
|
+
* @param options - Formatting options (delimiter, milliseconds, timezone, parts, readable)
|
|
12
12
|
* @returns Formatted timestamp string
|
|
13
13
|
*
|
|
14
14
|
* @example Default (UTC datetime with underscore delimiter)
|
|
@@ -17,22 +17,22 @@ exports.dtStamp = dtStamp;
|
|
|
17
17
|
* // "20240315_103045"
|
|
18
18
|
* ```
|
|
19
19
|
*
|
|
20
|
-
* @example
|
|
20
|
+
* @example Readable datetime with milliseconds
|
|
21
21
|
* ```typescript
|
|
22
|
-
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), {
|
|
23
|
-
* // "
|
|
22
|
+
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { readable: true, ms: true });
|
|
23
|
+
* // "2024-03-15_10:30:45_123"
|
|
24
24
|
* ```
|
|
25
25
|
*
|
|
26
|
-
* @example
|
|
26
|
+
* @example Readable date only
|
|
27
27
|
* ```typescript
|
|
28
|
-
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { parts: "date" });
|
|
29
|
-
* // "
|
|
28
|
+
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { readable: true, parts: "date" });
|
|
29
|
+
* // "2024-03-15"
|
|
30
30
|
* ```
|
|
31
31
|
*
|
|
32
|
-
* @example
|
|
32
|
+
* @example Readable time with milliseconds
|
|
33
33
|
* ```typescript
|
|
34
|
-
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { parts: "time", ms: true });
|
|
35
|
-
* // "
|
|
34
|
+
* dtStamp(new Date("2024-03-15T10:30:45.123Z"), { readable: true, parts: "time", ms: true });
|
|
35
|
+
* // "10:30:45.123"
|
|
36
36
|
* ```
|
|
37
37
|
*
|
|
38
38
|
* @example Custom delimiter
|
|
@@ -43,8 +43,7 @@ exports.dtStamp = dtStamp;
|
|
|
43
43
|
*/
|
|
44
44
|
function dtStamp(date, options) {
|
|
45
45
|
const d = date ?? new Date();
|
|
46
|
-
const { delimiter = "_", ms = false, tz = "utc", parts = "datetime",
|
|
47
|
-
const sep = compact ? "" : delimiter;
|
|
46
|
+
const { delimiter = "_", ms = false, tz = "utc", parts = "datetime", readable = false, } = options ?? {};
|
|
48
47
|
const utc = tz === "utc";
|
|
49
48
|
const year = utc ? d.getUTCFullYear() : d.getFullYear();
|
|
50
49
|
const month = String((utc ? d.getUTCMonth() : d.getMonth()) + 1).padStart(2, "0");
|
|
@@ -52,11 +51,16 @@ function dtStamp(date, options) {
|
|
|
52
51
|
const hours = String(utc ? d.getUTCHours() : d.getHours()).padStart(2, "0");
|
|
53
52
|
const minutes = String(utc ? d.getUTCMinutes() : d.getMinutes()).padStart(2, "0");
|
|
54
53
|
const seconds = String(utc ? d.getUTCSeconds() : d.getSeconds()).padStart(2, "0");
|
|
55
|
-
const datePart =
|
|
56
|
-
|
|
54
|
+
const datePart = readable
|
|
55
|
+
? `${year}-${month}-${day}`
|
|
56
|
+
: `${year}${month}${day}`;
|
|
57
|
+
let timePart = readable
|
|
58
|
+
? `${hours}:${minutes}:${seconds}`
|
|
59
|
+
: `${hours}${minutes}${seconds}`;
|
|
57
60
|
if (ms) {
|
|
58
61
|
const millis = String(utc ? d.getUTCMilliseconds() : d.getMilliseconds()).padStart(3, "0");
|
|
59
|
-
|
|
62
|
+
const msSep = readable && parts === "time" ? "." : delimiter;
|
|
63
|
+
timePart = `${timePart}${msSep}${millis}`;
|
|
60
64
|
}
|
|
61
65
|
if (parts === "date") {
|
|
62
66
|
return datePart;
|
|
@@ -64,6 +68,6 @@ function dtStamp(date, options) {
|
|
|
64
68
|
if (parts === "time") {
|
|
65
69
|
return timePart;
|
|
66
70
|
}
|
|
67
|
-
return `${datePart}${
|
|
71
|
+
return `${datePart}${delimiter}${timePart}`;
|
|
68
72
|
}
|
|
69
73
|
//# sourceMappingURL=format_dt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format_dt.js","sourceRoot":"","sources":["../../../../src/utils/format_dt.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"format_dt.js","sourceRoot":"","sources":["../../../../src/utils/format_dt.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./format_dt"), exports);
|
|
18
|
+
__exportStar(require("./logger"), exports);
|
|
18
19
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,2CAAyB"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Structured logging utility with transport DI and Err integration.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a flexible, callable logger with a transport abstraction,
|
|
5
|
+
* built-in pretty console transport, and zero external runtime dependencies
|
|
6
|
+
* beyond `fast-safe-stringify`.
|
|
7
|
+
*
|
|
8
|
+
* ## Design Philosophy
|
|
9
|
+
*
|
|
10
|
+
* The logger is designed as a callable function with overloaded signatures.
|
|
11
|
+
* Transports are injectable, making the logger testable without streams or
|
|
12
|
+
* process-level side effects. The built-in pretty transport renders to stderr
|
|
13
|
+
* with ANSI colors and automatic Err formatting.
|
|
14
|
+
*
|
|
15
|
+
* ## Basic Usage
|
|
16
|
+
*
|
|
17
|
+
* @example Simple logging
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { log } from './utils/logger';
|
|
20
|
+
*
|
|
21
|
+
* log('Application started'); // INFO level by default
|
|
22
|
+
* log(log.WARN, 'Connection slow'); // Explicit level
|
|
23
|
+
* log(log.ERROR, 'Failed to save', { userId: '123' }); // With context
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example Logging with Err instances
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { Err } from './types/err';
|
|
29
|
+
* import { log } from './utils/logger';
|
|
30
|
+
*
|
|
31
|
+
* const [data, err] = fetchData();
|
|
32
|
+
* if (err) {
|
|
33
|
+
* log(log.ERROR, 'Data fetch failed', err);
|
|
34
|
+
* return;
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example Child loggers with module context
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const dbLogger = log.child('database', { version: '1.0' });
|
|
41
|
+
* dbLogger('Connected to postgres');
|
|
42
|
+
* // Output: [database] Connected to postgres
|
|
43
|
+
*
|
|
44
|
+
* const userLogger = dbLogger.child('users');
|
|
45
|
+
* userLogger('User created');
|
|
46
|
+
* // Output: [database] [users] User created
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example Custom transport for testing
|
|
50
|
+
* ```typescript
|
|
51
|
+
* import { createLogger, lvl } from './utils/logger';
|
|
52
|
+
* import type { LogEntry, LogTransport } from './utils/logger';
|
|
53
|
+
*
|
|
54
|
+
* const entries: LogEntry[] = [];
|
|
55
|
+
* const spy: LogTransport = { write(e) { entries.push(e); } };
|
|
56
|
+
* const testLogger = createLogger('test', { transports: [spy], level: lvl.TRACE });
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* ## Configuration
|
|
60
|
+
*
|
|
61
|
+
* The logger reads configuration from environment variables:
|
|
62
|
+
* - `LOG_LEVEL`: Minimum level to log (trace|debug|info|warn|error|fatal). Default: 'info'
|
|
63
|
+
*
|
|
64
|
+
* @module logger
|
|
65
|
+
*/
|
|
66
|
+
import { Err } from "../types/err";
|
|
67
|
+
/**
|
|
68
|
+
* Log level constants for type-safe level specification.
|
|
69
|
+
*
|
|
70
|
+
* **Level Hierarchy** (lowest to highest):
|
|
71
|
+
* - `TRACE`: Detailed debugging information
|
|
72
|
+
* - `DEBUG`: Debugging information
|
|
73
|
+
* - `INFO`: General informational messages
|
|
74
|
+
* - `WARN`: Warning messages
|
|
75
|
+
* - `ERROR`: Error messages for failures
|
|
76
|
+
* - `FATAL`: Fatal errors causing termination
|
|
77
|
+
*/
|
|
78
|
+
declare const lvl: {
|
|
79
|
+
readonly TRACE: "trace";
|
|
80
|
+
readonly DEBUG: "debug";
|
|
81
|
+
readonly INFO: "info";
|
|
82
|
+
readonly WARN: "warn";
|
|
83
|
+
readonly ERROR: "error";
|
|
84
|
+
readonly FATAL: "fatal";
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Type representing valid log level values.
|
|
88
|
+
*/
|
|
89
|
+
type LevelValue = (typeof lvl)[keyof typeof lvl];
|
|
90
|
+
/**
|
|
91
|
+
* A single structured log entry passed to transports.
|
|
92
|
+
*/
|
|
93
|
+
interface LogEntry {
|
|
94
|
+
/** Log level */
|
|
95
|
+
level: LevelValue;
|
|
96
|
+
/** Unix timestamp in milliseconds (Date.now()) */
|
|
97
|
+
timestamp: number;
|
|
98
|
+
/** Log message */
|
|
99
|
+
message: string;
|
|
100
|
+
/** Merged bindings + call-site context */
|
|
101
|
+
context: Record<string, unknown>;
|
|
102
|
+
/** Module chain accumulated by child() calls */
|
|
103
|
+
modules: string[];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Transport interface — receives a `LogEntry` for each log call that passes
|
|
107
|
+
* the level filter. Implement this to integrate any logging backend.
|
|
108
|
+
*
|
|
109
|
+
* @example Pino transport
|
|
110
|
+
* ```typescript
|
|
111
|
+
* import pino from 'pino';
|
|
112
|
+
* import type { LogTransport, LogEntry } from '@pencroff-lab/kore';
|
|
113
|
+
*
|
|
114
|
+
* const pinoInstance = pino();
|
|
115
|
+
* const pinoTransport: LogTransport = {
|
|
116
|
+
* write(entry: LogEntry) {
|
|
117
|
+
* const prefix = entry.modules.map(m => `[${m}] `).join('');
|
|
118
|
+
* pinoInstance[entry.level](entry.context, prefix + entry.message);
|
|
119
|
+
* }
|
|
120
|
+
* };
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
interface LogTransport {
|
|
124
|
+
write(entry: LogEntry): void;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Options for the built-in pretty console transport.
|
|
128
|
+
*/
|
|
129
|
+
interface PrettyOptions {
|
|
130
|
+
/** Output stream. Default: `process.stderr` */
|
|
131
|
+
output?: {
|
|
132
|
+
write(data: string): void;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Enable ANSI colors.
|
|
136
|
+
* - `'auto'` (default): enable when output is a TTY
|
|
137
|
+
* - `true`: always enable
|
|
138
|
+
* - `false`: always disable
|
|
139
|
+
*/
|
|
140
|
+
colors?: boolean | "auto";
|
|
141
|
+
/** Override default level colors (ANSI escape sequences) */
|
|
142
|
+
levelColors?: Partial<Record<LevelValue, string>>;
|
|
143
|
+
/**
|
|
144
|
+
* Timestamp format.
|
|
145
|
+
* - `'short'` (default): `HH:MM:SS.mmm` local time
|
|
146
|
+
* - `'iso'`: ISO 8601 string
|
|
147
|
+
* - Custom function receiving `Date.now()` timestamp
|
|
148
|
+
*/
|
|
149
|
+
timestamp?: "short" | "iso" | ((ts: number) => string);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Options for `createLogger`.
|
|
153
|
+
*/
|
|
154
|
+
interface LoggerOptions {
|
|
155
|
+
/** Minimum log level. Default: from `LOG_LEVEL` env or `'info'` */
|
|
156
|
+
level?: LevelValue;
|
|
157
|
+
/** Transports to write entries to. Default: `[prettyTransport()]` */
|
|
158
|
+
transports?: LogTransport[];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Callable logger interface with overloaded signatures.
|
|
162
|
+
*
|
|
163
|
+
* The Logger is both a function (for logging) and an object (with level
|
|
164
|
+
* constants and the `child` method).
|
|
165
|
+
*
|
|
166
|
+
* ## Call Signatures
|
|
167
|
+
* 1. `log(message)` - Log at INFO level
|
|
168
|
+
* 2. `log(message, context)` - Log at INFO level with context object or Err
|
|
169
|
+
* 3. `log(message, detail)` - Log at INFO level with detail string
|
|
170
|
+
* 4. `log(level, message)` - Log at specific level
|
|
171
|
+
* 5. `log(level, message, context)` - Log at specific level with context
|
|
172
|
+
*/
|
|
173
|
+
interface Logger {
|
|
174
|
+
/** Trace level constant */
|
|
175
|
+
readonly TRACE: "trace";
|
|
176
|
+
/** Debug level constant */
|
|
177
|
+
readonly DEBUG: "debug";
|
|
178
|
+
/** Info level constant */
|
|
179
|
+
readonly INFO: "info";
|
|
180
|
+
/** Warning level constant */
|
|
181
|
+
readonly WARN: "warn";
|
|
182
|
+
/** Error level constant */
|
|
183
|
+
readonly ERROR: "error";
|
|
184
|
+
/** Fatal level constant */
|
|
185
|
+
readonly FATAL: "fatal";
|
|
186
|
+
/** Log a message at INFO level. */
|
|
187
|
+
(message: string): void;
|
|
188
|
+
/** Log a message at INFO level with context. */
|
|
189
|
+
(message: string, context: object | Err): void;
|
|
190
|
+
/** Log a message at INFO level with detail string. */
|
|
191
|
+
(message: string, detail: string): void;
|
|
192
|
+
/** Log a message at a specific level. */
|
|
193
|
+
(level: LevelValue, message: string): void;
|
|
194
|
+
/** Log a message at a specific level with context. */
|
|
195
|
+
(level: LevelValue, message: string, context: object | Err): void;
|
|
196
|
+
/**
|
|
197
|
+
* Create a child logger with module-specific context.
|
|
198
|
+
*
|
|
199
|
+
* @param module - Module name added to the modules array
|
|
200
|
+
* @param bindings - Optional bindings merged into every log entry's context
|
|
201
|
+
* @returns New Logger instance
|
|
202
|
+
*/
|
|
203
|
+
child(module: string, bindings?: object): Logger;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Create a built-in pretty console transport.
|
|
207
|
+
*
|
|
208
|
+
* Renders log entries to a human-readable format with optional ANSI colors.
|
|
209
|
+
*
|
|
210
|
+
* Output format:
|
|
211
|
+
* ```
|
|
212
|
+
* {dim timestamp} {colored TAG} {[mod] [mod]} {message} {dim context}
|
|
213
|
+
* ```
|
|
214
|
+
*
|
|
215
|
+
* Err instances in context are rendered via `Err.toString()` on their own
|
|
216
|
+
* indented line below the main line.
|
|
217
|
+
*
|
|
218
|
+
* @param options - Optional configuration
|
|
219
|
+
*/
|
|
220
|
+
declare function prettyTransport(options?: PrettyOptions): LogTransport;
|
|
221
|
+
/**
|
|
222
|
+
* Create a logger instance with optional module name and configuration.
|
|
223
|
+
*
|
|
224
|
+
* @param module - Optional module name added as the first entry in `modules`
|
|
225
|
+
* @param options - Optional configuration
|
|
226
|
+
* @returns New Logger instance
|
|
227
|
+
*
|
|
228
|
+
* @example Basic usage
|
|
229
|
+
* ```typescript
|
|
230
|
+
* const logger = createLogger();
|
|
231
|
+
* logger('Application ready');
|
|
232
|
+
* ```
|
|
233
|
+
*
|
|
234
|
+
* @example Module-specific logger
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const dbLogger = createLogger('database');
|
|
237
|
+
* dbLogger('Connected');
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @example Testing with spy transport
|
|
241
|
+
* ```typescript
|
|
242
|
+
* import type { LogEntry, LogTransport } from './utils/logger';
|
|
243
|
+
*
|
|
244
|
+
* const entries: LogEntry[] = [];
|
|
245
|
+
* const spy: LogTransport = { write(e) { entries.push(e); } };
|
|
246
|
+
* const testLogger = createLogger('test', { transports: [spy], level: lvl.TRACE });
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
declare function createLogger(module?: string, options?: LoggerOptions): Logger;
|
|
250
|
+
/**
|
|
251
|
+
* Default logger instance for application-wide logging.
|
|
252
|
+
*
|
|
253
|
+
* @example Basic usage
|
|
254
|
+
* ```typescript
|
|
255
|
+
* import { log } from './utils/logger';
|
|
256
|
+
*
|
|
257
|
+
* log('Application started');
|
|
258
|
+
* log(log.INFO, 'Server listening', { port: 3000 });
|
|
259
|
+
* log(log.ERROR, 'Startup failed', err);
|
|
260
|
+
* ```
|
|
261
|
+
*
|
|
262
|
+
* @example Module-specific logging via child
|
|
263
|
+
* ```typescript
|
|
264
|
+
* const dbLogger = log.child('database');
|
|
265
|
+
* dbLogger('Connection pool initialized');
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
export declare const log: Logger;
|
|
269
|
+
export { createLogger, prettyTransport, lvl };
|
|
270
|
+
export type { Logger, LevelValue, LogEntry, LogTransport, LoggerOptions, PrettyOptions, };
|
|
271
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|