@santana-org/logger 0.1.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 ADDED
@@ -0,0 +1,77 @@
1
+ # @santa-org/logger
2
+
3
+ A lightweight, configurable logger for Node.js and modern JavaScript environments.
4
+
5
+ ## Features
6
+
7
+ - Log levels: `debug`, `info`, `success`, `warn`, `error`
8
+ - Configurable minimum level
9
+ - Optional timestamps
10
+ - Optional label / namespace
11
+ - Colorized output (auto-detected TTY)
12
+ - Custom formatter support
13
+ - ESM-first, CJS-compatible
14
+ - Zero dependencies
15
+
16
+ ## Installation
17
+
18
+ ```sh
19
+ npm install @santa-org/logger
20
+ # or
21
+ pnpm add @santa-org/logger
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```ts
27
+ import { createLogger } from "@santa-org/logger"
28
+
29
+ const logger = createLogger({
30
+ level: "info",
31
+ label: "app",
32
+ timestamps: true,
33
+ })
34
+
35
+ logger.info("Server started")
36
+ logger.warn("Low memory")
37
+ logger.error("Unhandled exception", { code: 500 })
38
+ ```
39
+
40
+ ### Child logger
41
+
42
+ ```ts
43
+ const dbLogger = logger.child("db")
44
+ dbLogger.debug("Query executed")
45
+ ```
46
+
47
+ ### Custom formatter
48
+
49
+ ```ts
50
+ import { createLogger, type LogEntry } from "@santa-org/logger"
51
+
52
+ const logger = createLogger({
53
+ formatter: (entry: LogEntry, _colors: boolean) =>
54
+ `[${entry.level.toUpperCase()}] ${entry.message}`,
55
+ })
56
+ ```
57
+
58
+ ## API
59
+
60
+ ### `createLogger(options?)`
61
+
62
+ | Option | Type | Default | Description |
63
+ |-------------|-------------|---------------|--------------------------------------------|
64
+ | `level` | `LogLevel` | `"debug"` | Minimum log level |
65
+ | `label` | `string` | — | Label/namespace prepended to each message |
66
+ | `timestamps`| `boolean` | `false` | Include ISO timestamps |
67
+ | `colors` | `boolean` | auto (TTY) | Colorize output |
68
+ | `formatter` | `Formatter` | built-in | Custom formatter function |
69
+ | `writer` | `Writer` | stdout/stderr | Custom output writer |
70
+
71
+ ### Log Levels
72
+
73
+ `debug` < `info` < `success` < `warn` < `error`
74
+
75
+ ## License
76
+
77
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,118 @@
1
+ 'use strict';
2
+
3
+ const ANSI_RESET = "\x1B[0m";
4
+ const LEVEL_COLORS = {
5
+ debug: "\x1B[90m",
6
+ // gray
7
+ info: "\x1B[36m",
8
+ // cyan
9
+ success: "\x1B[32m",
10
+ // green
11
+ warn: "\x1B[33m",
12
+ // yellow
13
+ error: "\x1B[31m"
14
+ // red
15
+ };
16
+ const LEVEL_LABELS = {
17
+ debug: "DBG",
18
+ info: "INF",
19
+ success: "SUC",
20
+ warn: "WRN",
21
+ error: "ERR"
22
+ };
23
+ function colorize(text, color, enabled) {
24
+ return enabled ? `${color}${text}${ANSI_RESET}` : text;
25
+ }
26
+ const defaultFormatter = (entry, colors) => {
27
+ const parts = [];
28
+ if (entry.timestamp) {
29
+ const ts = entry.timestamp.toISOString();
30
+ parts.push(colorize(ts, "\x1B[2m", colors));
31
+ }
32
+ const levelColor = LEVEL_COLORS[entry.level];
33
+ const levelLabel = LEVEL_LABELS[entry.level];
34
+ parts.push(colorize(levelLabel, levelColor, colors));
35
+ if (entry.label) {
36
+ parts.push(colorize(`[${entry.label}]`, "\x1B[35m", colors));
37
+ }
38
+ parts.push(entry.message);
39
+ if (entry.args.length > 0) {
40
+ const extras = entry.args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ");
41
+ parts.push(extras);
42
+ }
43
+ return parts.join(" ");
44
+ };
45
+
46
+ const LOG_LEVELS = {
47
+ debug: 0,
48
+ info: 1,
49
+ success: 2,
50
+ warn: 3,
51
+ error: 4
52
+ };
53
+ function isLevelEnabled(current, minimum) {
54
+ return LOG_LEVELS[current] >= LOG_LEVELS[minimum];
55
+ }
56
+
57
+ function isTTY() {
58
+ return process.stdout.isTTY === true;
59
+ }
60
+ function defaultWriter() {
61
+ return {
62
+ out: (message) => process.stdout.write(`${message}
63
+ `),
64
+ err: (message) => process.stderr.write(`${message}
65
+ `)
66
+ };
67
+ }
68
+ function isErrorLevel(level) {
69
+ return level === "error" || level === "warn";
70
+ }
71
+ function createLogger(options = {}) {
72
+ const {
73
+ level: minLevel = "debug",
74
+ label,
75
+ timestamps = false,
76
+ colors = isTTY(),
77
+ formatter = defaultFormatter,
78
+ writer = defaultWriter()
79
+ } = options;
80
+ function log(level, message, ...args) {
81
+ if (!isLevelEnabled(level, minLevel)) {
82
+ return;
83
+ }
84
+ const entry = {
85
+ level,
86
+ message,
87
+ ...label !== void 0 ? { label } : {},
88
+ ...timestamps ? { timestamp: /* @__PURE__ */ new Date() } : {},
89
+ args
90
+ };
91
+ const formatted = formatter(entry, colors);
92
+ if (isErrorLevel(level)) {
93
+ writer.err(formatted);
94
+ } else {
95
+ writer.out(formatted);
96
+ }
97
+ }
98
+ return {
99
+ debug: (message, ...args) => log("debug", message, ...args),
100
+ info: (message, ...args) => log("info", message, ...args),
101
+ warn: (message, ...args) => log("warn", message, ...args),
102
+ error: (message, ...args) => log("error", message, ...args),
103
+ success: (message, ...args) => log("success", message, ...args),
104
+ child: (childLabel) => createLogger({
105
+ level: minLevel,
106
+ label: childLabel,
107
+ timestamps,
108
+ colors,
109
+ formatter,
110
+ writer
111
+ })
112
+ };
113
+ }
114
+
115
+ exports.LOG_LEVELS = LOG_LEVELS;
116
+ exports.createLogger = createLogger;
117
+ exports.defaultFormatter = defaultFormatter;
118
+ exports.isLevelEnabled = isLevelEnabled;
@@ -0,0 +1,46 @@
1
+ type LogLevel = "debug" | "info" | "warn" | "error" | "success";
2
+ interface LogEntry {
3
+ level: LogLevel;
4
+ message: string;
5
+ label?: string;
6
+ timestamp?: Date;
7
+ args: unknown[];
8
+ }
9
+ interface LoggerOptions {
10
+ /** Minimum log level to output. Defaults to "debug". */
11
+ level?: LogLevel;
12
+ /** Optional label/namespace prepended to each message. */
13
+ label?: string;
14
+ /** Whether to include timestamps in output. Defaults to false. */
15
+ timestamps?: boolean;
16
+ /** Whether to colorize output. Defaults to true when a TTY is detected. */
17
+ colors?: boolean;
18
+ /** Custom formatter. Overrides the built-in formatter when provided. */
19
+ formatter?: Formatter;
20
+ /** Output writer. Defaults to process.stdout / process.stderr. */
21
+ writer?: Writer;
22
+ }
23
+ type Formatter = (entry: LogEntry, colors: boolean) => string;
24
+ interface Writer {
25
+ out: (message: string) => void;
26
+ err: (message: string) => void;
27
+ }
28
+ interface Logger {
29
+ debug: (message: string, ...args: unknown[]) => void;
30
+ info: (message: string, ...args: unknown[]) => void;
31
+ warn: (message: string, ...args: unknown[]) => void;
32
+ error: (message: string, ...args: unknown[]) => void;
33
+ success: (message: string, ...args: unknown[]) => void;
34
+ /** Create a child logger with a specific label. */
35
+ child: (label: string) => Logger;
36
+ }
37
+
38
+ declare const defaultFormatter: Formatter;
39
+
40
+ declare const LOG_LEVELS: Record<LogLevel, number>;
41
+ declare function isLevelEnabled(current: LogLevel, minimum: LogLevel): boolean;
42
+
43
+ declare function createLogger(options?: LoggerOptions): Logger;
44
+
45
+ export { LOG_LEVELS, createLogger, defaultFormatter, isLevelEnabled };
46
+ export type { Formatter, LogEntry, LogLevel, Logger, LoggerOptions, Writer };
@@ -0,0 +1,46 @@
1
+ type LogLevel = "debug" | "info" | "warn" | "error" | "success";
2
+ interface LogEntry {
3
+ level: LogLevel;
4
+ message: string;
5
+ label?: string;
6
+ timestamp?: Date;
7
+ args: unknown[];
8
+ }
9
+ interface LoggerOptions {
10
+ /** Minimum log level to output. Defaults to "debug". */
11
+ level?: LogLevel;
12
+ /** Optional label/namespace prepended to each message. */
13
+ label?: string;
14
+ /** Whether to include timestamps in output. Defaults to false. */
15
+ timestamps?: boolean;
16
+ /** Whether to colorize output. Defaults to true when a TTY is detected. */
17
+ colors?: boolean;
18
+ /** Custom formatter. Overrides the built-in formatter when provided. */
19
+ formatter?: Formatter;
20
+ /** Output writer. Defaults to process.stdout / process.stderr. */
21
+ writer?: Writer;
22
+ }
23
+ type Formatter = (entry: LogEntry, colors: boolean) => string;
24
+ interface Writer {
25
+ out: (message: string) => void;
26
+ err: (message: string) => void;
27
+ }
28
+ interface Logger {
29
+ debug: (message: string, ...args: unknown[]) => void;
30
+ info: (message: string, ...args: unknown[]) => void;
31
+ warn: (message: string, ...args: unknown[]) => void;
32
+ error: (message: string, ...args: unknown[]) => void;
33
+ success: (message: string, ...args: unknown[]) => void;
34
+ /** Create a child logger with a specific label. */
35
+ child: (label: string) => Logger;
36
+ }
37
+
38
+ declare const defaultFormatter: Formatter;
39
+
40
+ declare const LOG_LEVELS: Record<LogLevel, number>;
41
+ declare function isLevelEnabled(current: LogLevel, minimum: LogLevel): boolean;
42
+
43
+ declare function createLogger(options?: LoggerOptions): Logger;
44
+
45
+ export { LOG_LEVELS, createLogger, defaultFormatter, isLevelEnabled };
46
+ export type { Formatter, LogEntry, LogLevel, Logger, LoggerOptions, Writer };
@@ -0,0 +1,46 @@
1
+ type LogLevel = "debug" | "info" | "warn" | "error" | "success";
2
+ interface LogEntry {
3
+ level: LogLevel;
4
+ message: string;
5
+ label?: string;
6
+ timestamp?: Date;
7
+ args: unknown[];
8
+ }
9
+ interface LoggerOptions {
10
+ /** Minimum log level to output. Defaults to "debug". */
11
+ level?: LogLevel;
12
+ /** Optional label/namespace prepended to each message. */
13
+ label?: string;
14
+ /** Whether to include timestamps in output. Defaults to false. */
15
+ timestamps?: boolean;
16
+ /** Whether to colorize output. Defaults to true when a TTY is detected. */
17
+ colors?: boolean;
18
+ /** Custom formatter. Overrides the built-in formatter when provided. */
19
+ formatter?: Formatter;
20
+ /** Output writer. Defaults to process.stdout / process.stderr. */
21
+ writer?: Writer;
22
+ }
23
+ type Formatter = (entry: LogEntry, colors: boolean) => string;
24
+ interface Writer {
25
+ out: (message: string) => void;
26
+ err: (message: string) => void;
27
+ }
28
+ interface Logger {
29
+ debug: (message: string, ...args: unknown[]) => void;
30
+ info: (message: string, ...args: unknown[]) => void;
31
+ warn: (message: string, ...args: unknown[]) => void;
32
+ error: (message: string, ...args: unknown[]) => void;
33
+ success: (message: string, ...args: unknown[]) => void;
34
+ /** Create a child logger with a specific label. */
35
+ child: (label: string) => Logger;
36
+ }
37
+
38
+ declare const defaultFormatter: Formatter;
39
+
40
+ declare const LOG_LEVELS: Record<LogLevel, number>;
41
+ declare function isLevelEnabled(current: LogLevel, minimum: LogLevel): boolean;
42
+
43
+ declare function createLogger(options?: LoggerOptions): Logger;
44
+
45
+ export { LOG_LEVELS, createLogger, defaultFormatter, isLevelEnabled };
46
+ export type { Formatter, LogEntry, LogLevel, Logger, LoggerOptions, Writer };
package/dist/index.mjs ADDED
@@ -0,0 +1,113 @@
1
+ const ANSI_RESET = "\x1B[0m";
2
+ const LEVEL_COLORS = {
3
+ debug: "\x1B[90m",
4
+ // gray
5
+ info: "\x1B[36m",
6
+ // cyan
7
+ success: "\x1B[32m",
8
+ // green
9
+ warn: "\x1B[33m",
10
+ // yellow
11
+ error: "\x1B[31m"
12
+ // red
13
+ };
14
+ const LEVEL_LABELS = {
15
+ debug: "DBG",
16
+ info: "INF",
17
+ success: "SUC",
18
+ warn: "WRN",
19
+ error: "ERR"
20
+ };
21
+ function colorize(text, color, enabled) {
22
+ return enabled ? `${color}${text}${ANSI_RESET}` : text;
23
+ }
24
+ const defaultFormatter = (entry, colors) => {
25
+ const parts = [];
26
+ if (entry.timestamp) {
27
+ const ts = entry.timestamp.toISOString();
28
+ parts.push(colorize(ts, "\x1B[2m", colors));
29
+ }
30
+ const levelColor = LEVEL_COLORS[entry.level];
31
+ const levelLabel = LEVEL_LABELS[entry.level];
32
+ parts.push(colorize(levelLabel, levelColor, colors));
33
+ if (entry.label) {
34
+ parts.push(colorize(`[${entry.label}]`, "\x1B[35m", colors));
35
+ }
36
+ parts.push(entry.message);
37
+ if (entry.args.length > 0) {
38
+ const extras = entry.args.map((a) => typeof a === "object" ? JSON.stringify(a, null, 2) : String(a)).join(" ");
39
+ parts.push(extras);
40
+ }
41
+ return parts.join(" ");
42
+ };
43
+
44
+ const LOG_LEVELS = {
45
+ debug: 0,
46
+ info: 1,
47
+ success: 2,
48
+ warn: 3,
49
+ error: 4
50
+ };
51
+ function isLevelEnabled(current, minimum) {
52
+ return LOG_LEVELS[current] >= LOG_LEVELS[minimum];
53
+ }
54
+
55
+ function isTTY() {
56
+ return process.stdout.isTTY === true;
57
+ }
58
+ function defaultWriter() {
59
+ return {
60
+ out: (message) => process.stdout.write(`${message}
61
+ `),
62
+ err: (message) => process.stderr.write(`${message}
63
+ `)
64
+ };
65
+ }
66
+ function isErrorLevel(level) {
67
+ return level === "error" || level === "warn";
68
+ }
69
+ function createLogger(options = {}) {
70
+ const {
71
+ level: minLevel = "debug",
72
+ label,
73
+ timestamps = false,
74
+ colors = isTTY(),
75
+ formatter = defaultFormatter,
76
+ writer = defaultWriter()
77
+ } = options;
78
+ function log(level, message, ...args) {
79
+ if (!isLevelEnabled(level, minLevel)) {
80
+ return;
81
+ }
82
+ const entry = {
83
+ level,
84
+ message,
85
+ ...label !== void 0 ? { label } : {},
86
+ ...timestamps ? { timestamp: /* @__PURE__ */ new Date() } : {},
87
+ args
88
+ };
89
+ const formatted = formatter(entry, colors);
90
+ if (isErrorLevel(level)) {
91
+ writer.err(formatted);
92
+ } else {
93
+ writer.out(formatted);
94
+ }
95
+ }
96
+ return {
97
+ debug: (message, ...args) => log("debug", message, ...args),
98
+ info: (message, ...args) => log("info", message, ...args),
99
+ warn: (message, ...args) => log("warn", message, ...args),
100
+ error: (message, ...args) => log("error", message, ...args),
101
+ success: (message, ...args) => log("success", message, ...args),
102
+ child: (childLabel) => createLogger({
103
+ level: minLevel,
104
+ label: childLabel,
105
+ timestamps,
106
+ colors,
107
+ formatter,
108
+ writer
109
+ })
110
+ };
111
+ }
112
+
113
+ export { LOG_LEVELS, createLogger, defaultFormatter, isLevelEnabled };
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@santana-org/logger",
3
+ "version": "0.1.0",
4
+ "description": "A lightweight, configurable logger for Node.js and modern JavaScript environments",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/santana-org/uxie.git",
9
+ "directory": "packages/logger"
10
+ },
11
+ "keywords": [
12
+ "logger",
13
+ "logging",
14
+ "typescript",
15
+ "esm",
16
+ "colorized",
17
+ "santa-org"
18
+ ],
19
+ "type": "module",
20
+ "exports": {
21
+ ".": {
22
+ "import": {
23
+ "types": "./dist/index.d.mts",
24
+ "default": "./dist/index.mjs"
25
+ },
26
+ "require": {
27
+ "types": "./dist/index.d.cts",
28
+ "default": "./dist/index.cjs"
29
+ }
30
+ }
31
+ },
32
+ "main": "./dist/index.cjs",
33
+ "module": "./dist/index.mjs",
34
+ "types": "./dist/index.d.ts",
35
+ "files": [
36
+ "dist",
37
+ "README.md"
38
+ ],
39
+ "devDependencies": {
40
+ "@types/node": "^22.13.10",
41
+ "publint": "^0.3.4",
42
+ "typescript": "^5.8.2",
43
+ "unbuild": "^3.3.1",
44
+ "vitest": "^3.0.8"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public",
48
+ "registry": "https://registry.npmjs.org/"
49
+ },
50
+ "engines": {
51
+ "node": ">=25"
52
+ },
53
+ "scripts": {
54
+ "build": "unbuild",
55
+ "dev": "unbuild --stub",
56
+ "test": "vitest run",
57
+ "test:watch": "vitest",
58
+ "typecheck": "tsc --noEmit",
59
+ "packcheck": "publint"
60
+ }
61
+ }