@resq-sw/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 +185 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +3 -0
- package/lib/logger.d.ts +210 -0
- package/lib/logger.d.ts.map +1 -0
- package/lib/logger.decorators.d.ts +77 -0
- package/lib/logger.decorators.d.ts.map +1 -0
- package/lib/logger.decorators.js +208 -0
- package/lib/logger.decorators.js.map +1 -0
- package/lib/logger.js +268 -0
- package/lib/logger.js.map +1 -0
- package/lib/logger.types.d.ts +144 -0
- package/lib/logger.types.d.ts.map +1 -0
- package/lib/logger.types.js +0 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# @resq-sw/logger
|
|
2
|
+
|
|
3
|
+
> Structured logging with log levels, decorators, and singleton management for Node.js and Bun.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @resq-sw/logger
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Zero runtime dependencies.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { Logger, LogLevel } from "@resq-sw/logger";
|
|
17
|
+
|
|
18
|
+
const log = Logger.getLogger("[MyService]");
|
|
19
|
+
|
|
20
|
+
log.info("Server started", { port: 3000 });
|
|
21
|
+
log.warn("Disk usage high", { percent: 92 });
|
|
22
|
+
log.error("Connection failed", new Error("timeout"), { host: "db" });
|
|
23
|
+
log.debug("Cache hit", { key: "user:123" });
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Output format: `YYYY-MM-DD HH:mm:ss.SSS LEVEL [context] message {data}`
|
|
27
|
+
|
|
28
|
+
## API Reference
|
|
29
|
+
|
|
30
|
+
### Logger Class
|
|
31
|
+
|
|
32
|
+
#### `Logger.getLogger(context, options?): Logger`
|
|
33
|
+
|
|
34
|
+
Returns a singleton Logger instance for the given context. Subsequent calls with the same context return the same instance.
|
|
35
|
+
|
|
36
|
+
#### `new Logger(context, options?)`
|
|
37
|
+
|
|
38
|
+
Creates a new Logger instance.
|
|
39
|
+
|
|
40
|
+
| Option | Type | Default | Description |
|
|
41
|
+
|--------|------|---------|-------------|
|
|
42
|
+
| `minLevel` | `LogLevel` | env-based | Minimum log level |
|
|
43
|
+
| `includeTimestamp` | `boolean` | -- | Include timestamps |
|
|
44
|
+
| `colorize` | `boolean` | -- | Colorize output |
|
|
45
|
+
| `logToFile` | `boolean` | -- | Write to file (server-side) |
|
|
46
|
+
| `filePath` | `string` | -- | Log file path |
|
|
47
|
+
|
|
48
|
+
**Level resolution priority**: `options.minLevel` > `LOG_LEVEL` env > `BUN_LOG_LEVEL` env > `LogLevel.ERROR` (production) / `LogLevel.ALL` (development).
|
|
49
|
+
|
|
50
|
+
#### `Logger.setGlobalLogLevel(level: LogLevel): void`
|
|
51
|
+
|
|
52
|
+
Sets the minimum log level for all existing logger instances.
|
|
53
|
+
|
|
54
|
+
### Log Levels
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
enum LogLevel {
|
|
58
|
+
NONE = 0, // No logging
|
|
59
|
+
ERROR = 1, // Errors only
|
|
60
|
+
WARN = 2, // Errors + warnings
|
|
61
|
+
INFO = 3, // + informational
|
|
62
|
+
DEBUG = 4, // + debug messages
|
|
63
|
+
TRACE = 5, // + trace messages
|
|
64
|
+
ALL = 6, // Everything
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Logging Methods
|
|
69
|
+
|
|
70
|
+
All methods accept an optional `data` parameter (`Record<string, unknown>`).
|
|
71
|
+
|
|
72
|
+
| Method | Min Level | Console Method | Description |
|
|
73
|
+
|--------|-----------|----------------|-------------|
|
|
74
|
+
| `info(message, data?)` | `INFO` | `console.info` | Informational messages |
|
|
75
|
+
| `error(message, error?, data?)` | `ERROR` | `console.error` | Errors (auto-serializes Error objects) |
|
|
76
|
+
| `warn(message, data?)` | `WARN` | `console.warn` | Warnings |
|
|
77
|
+
| `debug(message, data?)` | `DEBUG` | `console.debug` | Debug messages |
|
|
78
|
+
| `trace(message, data?)` | `TRACE` | `console.debug` | Trace messages (most verbose) |
|
|
79
|
+
| `action(message, data?)` | `INFO` | `console.info` | Server actions / user interactions |
|
|
80
|
+
| `success(message, data?)` | `INFO` | `console.info` | Success confirmations |
|
|
81
|
+
|
|
82
|
+
### Grouping
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
log.group("Request Processing");
|
|
86
|
+
log.info("Step 1");
|
|
87
|
+
log.info("Step 2");
|
|
88
|
+
log.groupEnd();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Timing
|
|
92
|
+
|
|
93
|
+
#### `logger.time<T>(label, fn): Promise<T>`
|
|
94
|
+
|
|
95
|
+
Measures and logs execution time of a sync or async function.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const result = await log.time("DB query", async () => {
|
|
99
|
+
return await db.query("SELECT * FROM users");
|
|
100
|
+
});
|
|
101
|
+
// Logs: "DB query completed" { duration: "12.34ms" }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
On error, logs the failure with duration and rethrows.
|
|
105
|
+
|
|
106
|
+
## Decorators
|
|
107
|
+
|
|
108
|
+
### `@Log(options?)`
|
|
109
|
+
|
|
110
|
+
Logs method entry and exit with optional argument and return value logging.
|
|
111
|
+
|
|
112
|
+
| Option | Type | Default | Description |
|
|
113
|
+
|--------|------|---------|-------------|
|
|
114
|
+
| `logArgs` | `boolean` | `true` | Log method arguments |
|
|
115
|
+
| `logResult` | `boolean` | `false` | Log return value |
|
|
116
|
+
| `message` | `string` | method name | Custom message prefix |
|
|
117
|
+
| `level` | `LogLevelString` | `"debug"` | Log level to use |
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
class UserService {
|
|
121
|
+
@Log({ logArgs: true, logResult: true, level: "info" })
|
|
122
|
+
async getUser(id: string) { return { id, name: "John" }; }
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `@LogTiming(options?)`
|
|
127
|
+
|
|
128
|
+
Logs method execution time. Works with both sync and async methods.
|
|
129
|
+
|
|
130
|
+
| Option | Type | Default | Description |
|
|
131
|
+
|--------|------|---------|-------------|
|
|
132
|
+
| `label` | `string` | `ClassName.methodName` | Custom timing label |
|
|
133
|
+
| `threshold` | `number` | `0` | Only log if duration exceeds this (ms) |
|
|
134
|
+
| `level` | `LogLevelString` | `"info"` | Log level to use |
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
class DataService {
|
|
138
|
+
@LogTiming({ threshold: 100 })
|
|
139
|
+
async fetchData() { /* only logged if > 100ms */ }
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### `@LogError(options?)`
|
|
144
|
+
|
|
145
|
+
Wraps method in try/catch, logs errors with stack traces.
|
|
146
|
+
|
|
147
|
+
| Option | Type | Default | Description |
|
|
148
|
+
|--------|------|---------|-------------|
|
|
149
|
+
| `rethrow` | `boolean` | `true` | Rethrow after logging |
|
|
150
|
+
| `message` | `string` | `"<method> error"` | Custom error prefix |
|
|
151
|
+
| `includeStack` | `boolean` | `true` | Include stack trace in log |
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
class Api {
|
|
155
|
+
@LogError({ rethrow: false, message: "API call failed" })
|
|
156
|
+
async callApi() { throw new Error("Network error"); }
|
|
157
|
+
// Error is logged but swallowed; method returns undefined
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `@LogClass(options?)`
|
|
162
|
+
|
|
163
|
+
Class decorator that applies logging to all methods on the prototype.
|
|
164
|
+
|
|
165
|
+
| Option | Type | Default | Description |
|
|
166
|
+
|--------|------|---------|-------------|
|
|
167
|
+
| `exclude` | `string[]` | `[]` | Method names to skip |
|
|
168
|
+
| `logCalls` | `boolean` | `true` | Log method entry/exit |
|
|
169
|
+
| `timing` | `boolean` | `false` | Log execution times |
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
@LogClass({ exclude: ["internalHelper"], timing: true })
|
|
173
|
+
class MyService {
|
|
174
|
+
publicMethod() { /* logged with timing */ }
|
|
175
|
+
internalHelper() { /* not logged */ }
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Types
|
|
180
|
+
|
|
181
|
+
Exported types: `LogData`, `LoggerOptions`, `LogLevel`, `LogLevelString`, `ColorKey`, `LogEntry`, `LogTransport`, `LogMethodOptions`, `LogTimingOptions`, `LogErrorOptions`, `LogClassOptions`.
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
Apache-2.0
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ColorKey, LogData, LogLevel, Logger, LoggerOptions, logger } from "./logger.js";
|
|
2
|
+
import { LogClassOptions, LogEntry, LogErrorOptions, LogLevelString, LogMethodOptions, LogTimingOptions, LogTransport } from "./logger.types.js";
|
|
3
|
+
import { Log, LogClass, LogError, LogTiming } from "./logger.decorators.js";
|
|
4
|
+
export { ColorKey, Log, LogClass, type LogClassOptions, LogData, type LogEntry, LogError, type LogErrorOptions, LogLevel, type LogLevelString, type LogMethodOptions, LogTiming, type LogTimingOptions, type LogTransport, Logger, LoggerOptions, logger };
|
package/lib/index.js
ADDED
package/lib/logger.d.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
//#region src/logger.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @fileoverview A comprehensive logging utility for both client and server environments.
|
|
19
|
+
* Provides structured logging with support for different log levels, colorization,
|
|
20
|
+
* and contextual information.
|
|
21
|
+
*
|
|
22
|
+
* This logger uses native console methods with structured formatting — no external
|
|
23
|
+
* dependencies are required. Log output follows the pattern:
|
|
24
|
+
* TIMESTAMP LEVEL [CONTEXT] message { data }
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Enum representing different logging levels with their priority values.
|
|
28
|
+
* Higher values indicate more verbose logging.
|
|
29
|
+
* @enum {number}
|
|
30
|
+
*/
|
|
31
|
+
declare enum LogLevel {
|
|
32
|
+
/** No logging */
|
|
33
|
+
NONE = 0,
|
|
34
|
+
/** Only error messages */
|
|
35
|
+
ERROR = 1,
|
|
36
|
+
/** Errors and warnings */
|
|
37
|
+
WARN = 2,
|
|
38
|
+
/** Errors, warnings, and informational messages */
|
|
39
|
+
INFO = 3,
|
|
40
|
+
/** Errors, warnings, info, and debug messages */
|
|
41
|
+
DEBUG = 4,
|
|
42
|
+
/** Errors, warnings, info, debug, and trace messages */
|
|
43
|
+
TRACE = 5,
|
|
44
|
+
/** All possible log messages */
|
|
45
|
+
ALL = 6
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Available color keys for log formatting
|
|
49
|
+
* @typedef {'reset' | 'red' | 'yellow' | 'blue' | 'green' | 'gray' | 'bold' | 'magenta' | 'cyan' | 'white'} ColorKey
|
|
50
|
+
*/
|
|
51
|
+
type ColorKey = 'reset' | 'red' | 'yellow' | 'blue' | 'green' | 'gray' | 'bold' | 'magenta' | 'cyan' | 'white';
|
|
52
|
+
/**
|
|
53
|
+
* Interface for structured data that can be attached to log messages
|
|
54
|
+
* @interface
|
|
55
|
+
*/
|
|
56
|
+
interface LogData {
|
|
57
|
+
/**
|
|
58
|
+
* Any key-value pairs to include in the log
|
|
59
|
+
*/
|
|
60
|
+
[key: string]: unknown;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Configuration options for the Logger
|
|
64
|
+
* @interface
|
|
65
|
+
*/
|
|
66
|
+
interface LoggerOptions {
|
|
67
|
+
/**
|
|
68
|
+
* The minimum level of messages to log
|
|
69
|
+
*/
|
|
70
|
+
minLevel?: LogLevel;
|
|
71
|
+
/**
|
|
72
|
+
* Whether to include timestamps in log messages
|
|
73
|
+
*/
|
|
74
|
+
includeTimestamp?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Whether to colorize log output
|
|
77
|
+
*/
|
|
78
|
+
colorize?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Whether to write logs to a file (server-side only)
|
|
81
|
+
*/
|
|
82
|
+
logToFile?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Path to the log file if logToFile is enabled
|
|
85
|
+
*/
|
|
86
|
+
filePath?: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A versatile logging utility that works in both browser and Node.js environments.
|
|
90
|
+
* Supports multiple log levels, colorized output, and structured data logging.
|
|
91
|
+
*/
|
|
92
|
+
declare class Logger {
|
|
93
|
+
/** The context/category name for this logger instance */
|
|
94
|
+
private readonly context;
|
|
95
|
+
/** The minimum log level that will be output */
|
|
96
|
+
private minLevel;
|
|
97
|
+
/**
|
|
98
|
+
* Parse log level from string or return default
|
|
99
|
+
*/
|
|
100
|
+
private static parseLevel;
|
|
101
|
+
/** Registry of logger instances to implement the singleton pattern */
|
|
102
|
+
private static readonly instances;
|
|
103
|
+
/**
|
|
104
|
+
* Create a new Logger instance or return an existing one for the given context
|
|
105
|
+
* @param {string} context - The context name for this logger (e.g., component or service name)
|
|
106
|
+
* @param {LoggerOptions} [options={}] - Optional logger configuration
|
|
107
|
+
*/
|
|
108
|
+
constructor(context: string, options?: LoggerOptions);
|
|
109
|
+
/**
|
|
110
|
+
* Get a logger instance for the given context.
|
|
111
|
+
* If a logger with this context already exists, returns the existing instance.
|
|
112
|
+
*
|
|
113
|
+
* @param {string} context - The context name
|
|
114
|
+
* @param {LoggerOptions} [options] - Optional logger configuration
|
|
115
|
+
* @returns {Logger} A logger instance for the specified context
|
|
116
|
+
*/
|
|
117
|
+
static getLogger(context: string, options?: LoggerOptions): Logger;
|
|
118
|
+
/**
|
|
119
|
+
* Set global minimum log level for all logger instances
|
|
120
|
+
*
|
|
121
|
+
* @param {LogLevel} level - The minimum level to log across all loggers
|
|
122
|
+
*/
|
|
123
|
+
static setGlobalLogLevel(level: LogLevel): void;
|
|
124
|
+
/**
|
|
125
|
+
* Format a timestamp for log output
|
|
126
|
+
*/
|
|
127
|
+
private formatTimestamp;
|
|
128
|
+
/**
|
|
129
|
+
* Format structured log data into a readable suffix string.
|
|
130
|
+
* Returns empty string if data is null/empty.
|
|
131
|
+
*/
|
|
132
|
+
private formatData;
|
|
133
|
+
/**
|
|
134
|
+
* Emit a log entry using the appropriate console method
|
|
135
|
+
*/
|
|
136
|
+
private emit;
|
|
137
|
+
/**
|
|
138
|
+
* Log an informational message
|
|
139
|
+
*
|
|
140
|
+
* @param {string} message - The message to log
|
|
141
|
+
* @param {LogData} [data] - Optional data to include
|
|
142
|
+
*/
|
|
143
|
+
info(message: string, data?: LogData): void;
|
|
144
|
+
/**
|
|
145
|
+
* Log an error message
|
|
146
|
+
*
|
|
147
|
+
* @param {string} message - The error message
|
|
148
|
+
* @param {Error|unknown} [error] - Optional Error object or unknown error
|
|
149
|
+
* @param {LogData} [data] - Optional additional data
|
|
150
|
+
*/
|
|
151
|
+
error(message: string, error?: unknown, data?: LogData): void;
|
|
152
|
+
/**
|
|
153
|
+
* Log a warning message
|
|
154
|
+
*
|
|
155
|
+
* @param {string} message - The warning message
|
|
156
|
+
* @param {LogData} [data] - Optional data to include
|
|
157
|
+
*/
|
|
158
|
+
warn(message: string, data?: LogData): void;
|
|
159
|
+
/**
|
|
160
|
+
* Log a debug message
|
|
161
|
+
*
|
|
162
|
+
* @param {string} message - The debug message
|
|
163
|
+
* @param {LogData} [data] - Optional data to include
|
|
164
|
+
*/
|
|
165
|
+
debug(message: string, data?: LogData): void;
|
|
166
|
+
/**
|
|
167
|
+
* Log a trace message (most verbose level)
|
|
168
|
+
*
|
|
169
|
+
* @param {string} message - The trace message
|
|
170
|
+
* @param {LogData} [data] - Optional data to include
|
|
171
|
+
*/
|
|
172
|
+
trace(message: string, data?: LogData): void;
|
|
173
|
+
/**
|
|
174
|
+
* Log an action message (for server actions or important user interactions)
|
|
175
|
+
*
|
|
176
|
+
* @param {string} message - The action message
|
|
177
|
+
* @param {LogData} [data] - Optional data to include
|
|
178
|
+
*/
|
|
179
|
+
action(message: string, data?: LogData): void;
|
|
180
|
+
/**
|
|
181
|
+
* Log a success message
|
|
182
|
+
*
|
|
183
|
+
* @param {string} message - The success message
|
|
184
|
+
* @param {LogData} [data] - Optional data to include
|
|
185
|
+
*/
|
|
186
|
+
success(message: string, data?: LogData): void;
|
|
187
|
+
/**
|
|
188
|
+
* Group related log messages (console.group wrapper)
|
|
189
|
+
*
|
|
190
|
+
* @param {string} label - The group label
|
|
191
|
+
*/
|
|
192
|
+
group(label: string): void;
|
|
193
|
+
/**
|
|
194
|
+
* End a log group (console.groupEnd wrapper)
|
|
195
|
+
*/
|
|
196
|
+
groupEnd(): void;
|
|
197
|
+
/**
|
|
198
|
+
* Log execution time of a function
|
|
199
|
+
*
|
|
200
|
+
* @template T - The return type of the function being timed
|
|
201
|
+
* @param {string} label - Description of the operation being timed
|
|
202
|
+
* @param {() => Promise<T> | T} fn - Function to execute and time
|
|
203
|
+
* @returns {Promise<T>} The result of the function execution
|
|
204
|
+
*/
|
|
205
|
+
time<T>(label: string, fn: () => Promise<T> | T): Promise<T>;
|
|
206
|
+
}
|
|
207
|
+
declare const logger: Logger;
|
|
208
|
+
//#endregion
|
|
209
|
+
export { ColorKey, LogData, LogLevel, Logger, LoggerOptions, logger };
|
|
210
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","names":[],"sources":["../src/logger.ts"],"mappings":";;AA+BA;;;;;;;;;;;;;AAqBA;;;;;AAgBA;;;;;AAWA;;;;;AAAA,aAhDY,QAAA;EAyDV;EAvDA,IAAA;EAiEA;EA/DA,KAAA;EAoEQ;EAlER,IAAA;EAyEW;EAvEX,IAAA;EAuEiB;EArEjB,KAAA;EA2HmD;EAzHnD,KAAA;EAyIuC;EAvIvC,GAAA;AAAA;;;;;KAOU,QAAA;;;;;UAgBK,OAAA;EAgRgD;;;EAAA,CA5Q9D,GAAA;AAAA;;;;;UAOc,aAAA;EAqFD;;;EAjFd,QAAA,GAAW,QAAA;EAiFwD;;;EA5EnE,gBAAA;EAqGQ;;;EAhGR,QAAA;EA6IK;;;EAxIL,SAAA;EAoJM;;;EA/IN,QAAA;AAAA;;;;;cAOW,MAAA;EAsKmB;EAAA,iBApKb,OAAA;EA+KjB;EAAA,QA5KQ,QAAA;EA4KsB;;;EAAA,eAvKf,UAAA;EAkLgB;EAAA,wBAlKP,SAAA;EA6KxB;;;;;cAtKY,OAAA,UAAiB,OAAA,GAAS,aAAA;EAwLtC;;;;;;;;EAAA,OAnKc,SAAA,CAAU,OAAA,UAAiB,OAAA,GAAU,aAAA,GAAgB,MAAA;EAgLH;;;AAmBlE;;EAnBkE,OAhKlD,iBAAA,CAAkB,KAAA,EAAO,QAAA;EAmLtB;;;EAAA,QA1KT,eAAA;;;;;UAgBA,UAAA;;;;UAYA,IAAA;;;;;;;EAiBR,IAAA,CAAK,OAAA,UAAiB,IAAA,GAAO,OAAA;;;;;;;;EAY7B,KAAA,CAAM,OAAA,UAAiB,KAAA,YAAiB,IAAA,GAAO,OAAA;;;;;;;EAmB/C,IAAA,CAAK,OAAA,UAAiB,IAAA,GAAO,OAAA;;;;;;;EAW7B,KAAA,CAAM,OAAA,UAAiB,IAAA,GAAO,OAAA;;;;;;;EAW9B,KAAA,CAAM,OAAA,UAAiB,IAAA,GAAO,OAAA;;;;;;;EAW9B,MAAA,CAAO,OAAA,UAAiB,IAAA,GAAO,OAAA;;;;;;;EAW/B,OAAA,CAAQ,OAAA,UAAiB,IAAA,GAAO,OAAA;;;;;;EAUhC,KAAA,CAAM,KAAA;;;;EAQN,QAAA,CAAA;;;;;;;;;EAaM,IAAA,GAAA,CAAQ,KAAA,UAAe,EAAA,QAAU,OAAA,CAAQ,CAAA,IAAK,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA;AAAA,cAmBrD,MAAA,EAAM,MAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LogClassOptions, LogErrorOptions, LogMethodOptions, LogTimingOptions } from "./logger.types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/logger.decorators.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Decorator that logs method entry and exit.
|
|
6
|
+
* Can optionally log arguments and return values.
|
|
7
|
+
*
|
|
8
|
+
* @param {LogMethodOptions} [options={}] - Configuration options
|
|
9
|
+
* @returns {MethodDecorator} The decorator function
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* class UserService {
|
|
14
|
+
* @Log({ logArgs: true, logResult: true })
|
|
15
|
+
* async getUser(id: string) {
|
|
16
|
+
* return { id, name: 'John' };
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare function Log(options?: LogMethodOptions): MethodDecorator;
|
|
22
|
+
/**
|
|
23
|
+
* Decorator that logs method execution time.
|
|
24
|
+
* Useful for performance monitoring.
|
|
25
|
+
*
|
|
26
|
+
* @param {LogTimingOptions} [options={}] - Configuration options
|
|
27
|
+
* @returns {MethodDecorator} The decorator function
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* class DataService {
|
|
32
|
+
* @LogTiming({ threshold: 100 }) // Only log if execution > 100ms
|
|
33
|
+
* async fetchData() {
|
|
34
|
+
* // ... slow operation
|
|
35
|
+
* }
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
declare function LogTiming(options?: LogTimingOptions): MethodDecorator;
|
|
40
|
+
/**
|
|
41
|
+
* Decorator that wraps method in try/catch and logs errors.
|
|
42
|
+
* Can optionally suppress the error or rethrow it.
|
|
43
|
+
*
|
|
44
|
+
* @param {LogErrorOptions} [options={}] - Configuration options
|
|
45
|
+
* @returns {MethodDecorator} The decorator function
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* class ApiService {
|
|
50
|
+
* @LogError({ rethrow: false, message: 'API call failed' })
|
|
51
|
+
* async callApi() {
|
|
52
|
+
* throw new Error('Network error');
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function LogError(options?: LogErrorOptions): MethodDecorator;
|
|
58
|
+
/**
|
|
59
|
+
* Class decorator that applies logging to all methods of a class.
|
|
60
|
+
* Can be configured to exclude specific methods.
|
|
61
|
+
*
|
|
62
|
+
* @param {LogClassOptions} [options={}] - Configuration options
|
|
63
|
+
* @returns {ClassDecorator} The decorator function
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* @LogClass({ exclude: ['privateMethod'], timing: true })
|
|
68
|
+
* class MyService {
|
|
69
|
+
* publicMethod() { ... }
|
|
70
|
+
* privateMethod() { ... } // Won't be logged
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function LogClass(options?: LogClassOptions): <T extends new (...args: unknown[]) => object>(target: T) => T;
|
|
75
|
+
//#endregion
|
|
76
|
+
export { Log, LogClass, LogError, LogTiming };
|
|
77
|
+
//# sourceMappingURL=logger.decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.decorators.d.ts","names":[],"sources":["../src/logger.decorators.ts"],"mappings":";;;;;;;;AAqLA;;;;;;;;;AAgEA;;;iBAvMgB,GAAA,CAAI,OAAA,GAAS,gBAAA,GAAwB,eAAA;;;;;;;;;;;;;;;;;;iBA2ErC,SAAA,CAAU,OAAA,GAAS,gBAAA,GAAwB,eAAA;;;;;;;;;;;;;;;;;;iBA4D3C,QAAA,CAAS,OAAA,GAAS,eAAA,GAAuB,eAAA;;;;;;;;;;;;;;;;;iBAgEzC,QAAA,CACd,OAAA,GAAS,eAAA,sBACW,IAAA,wBAA4B,MAAA,EAAQ,CAAA,KAAM,CAAA"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { Logger } from "./logger.js";
|
|
2
|
+
//#region src/logger.decorators.ts
|
|
3
|
+
/**
|
|
4
|
+
* Copyright 2026 ResQ
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* @fileoverview TypeScript decorators for logging method calls, timing, and errors.
|
|
20
|
+
* These decorators integrate with the Logger class to provide declarative logging.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Decorator that logs method entry and exit.
|
|
24
|
+
* Can optionally log arguments and return values.
|
|
25
|
+
*
|
|
26
|
+
* @param {LogMethodOptions} [options={}] - Configuration options
|
|
27
|
+
* @returns {MethodDecorator} The decorator function
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* class UserService {
|
|
32
|
+
* @Log({ logArgs: true, logResult: true })
|
|
33
|
+
* async getUser(id: string) {
|
|
34
|
+
* return { id, name: 'John' };
|
|
35
|
+
* }
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
function Log(options = {}) {
|
|
40
|
+
const { logArgs = true, logResult = false, message, level = "debug" } = options;
|
|
41
|
+
return (target, propertyKey, descriptor) => {
|
|
42
|
+
const originalMethod = descriptor.value;
|
|
43
|
+
const methodName = String(propertyKey);
|
|
44
|
+
const className = target.constructor.name;
|
|
45
|
+
descriptor.value = function(...args) {
|
|
46
|
+
const logger = Logger.getLogger(`[${className}]`);
|
|
47
|
+
const prefix = message || `${methodName}`;
|
|
48
|
+
if (logArgs && args.length > 0) logger[level](`${prefix} called`, { arguments: args });
|
|
49
|
+
else logger[level](`${prefix} called`);
|
|
50
|
+
const result = originalMethod.apply(this, args);
|
|
51
|
+
if (result instanceof Promise) return result.then((value) => {
|
|
52
|
+
if (logResult) logger[level](`${prefix} returned`, { result: value });
|
|
53
|
+
else logger[level](`${prefix} completed`);
|
|
54
|
+
return value;
|
|
55
|
+
}, (error) => {
|
|
56
|
+
logger.error(`${prefix} failed`, error);
|
|
57
|
+
throw error;
|
|
58
|
+
});
|
|
59
|
+
if (logResult) logger[level](`${prefix} returned`, { result });
|
|
60
|
+
else logger[level](`${prefix} completed`);
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
return descriptor;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Decorator that logs method execution time.
|
|
68
|
+
* Useful for performance monitoring.
|
|
69
|
+
*
|
|
70
|
+
* @param {LogTimingOptions} [options={}] - Configuration options
|
|
71
|
+
* @returns {MethodDecorator} The decorator function
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* class DataService {
|
|
76
|
+
* @LogTiming({ threshold: 100 }) // Only log if execution > 100ms
|
|
77
|
+
* async fetchData() {
|
|
78
|
+
* // ... slow operation
|
|
79
|
+
* }
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
function LogTiming(options = {}) {
|
|
84
|
+
const { label, threshold = 0, level = "info" } = options;
|
|
85
|
+
return (target, propertyKey, descriptor) => {
|
|
86
|
+
const originalMethod = descriptor.value;
|
|
87
|
+
const methodName = String(propertyKey);
|
|
88
|
+
const className = target.constructor.name;
|
|
89
|
+
descriptor.value = function(...args) {
|
|
90
|
+
const logger = Logger.getLogger(`[${className}]`);
|
|
91
|
+
const timerLabel = label || `${className}.${methodName}`;
|
|
92
|
+
const startTime = performance.now();
|
|
93
|
+
const result = originalMethod.apply(this, args);
|
|
94
|
+
if (result instanceof Promise) return result.finally(() => {
|
|
95
|
+
const duration = performance.now() - startTime;
|
|
96
|
+
if (duration >= threshold) logger[level](`${timerLabel} completed in ${duration.toFixed(2)}ms`);
|
|
97
|
+
});
|
|
98
|
+
const duration = performance.now() - startTime;
|
|
99
|
+
if (duration >= threshold) logger[level](`${timerLabel} completed in ${duration.toFixed(2)}ms`);
|
|
100
|
+
return result;
|
|
101
|
+
};
|
|
102
|
+
return descriptor;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Decorator that wraps method in try/catch and logs errors.
|
|
107
|
+
* Can optionally suppress the error or rethrow it.
|
|
108
|
+
*
|
|
109
|
+
* @param {LogErrorOptions} [options={}] - Configuration options
|
|
110
|
+
* @returns {MethodDecorator} The decorator function
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* class ApiService {
|
|
115
|
+
* @LogError({ rethrow: false, message: 'API call failed' })
|
|
116
|
+
* async callApi() {
|
|
117
|
+
* throw new Error('Network error');
|
|
118
|
+
* }
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
function LogError(options = {}) {
|
|
123
|
+
const { rethrow = true, message, includeStack = true } = options;
|
|
124
|
+
return (target, propertyKey, descriptor) => {
|
|
125
|
+
const originalMethod = descriptor.value;
|
|
126
|
+
const methodName = String(propertyKey);
|
|
127
|
+
const className = target.constructor.name;
|
|
128
|
+
descriptor.value = function(...args) {
|
|
129
|
+
const logger = Logger.getLogger(`[${className}]`);
|
|
130
|
+
const errorPrefix = message || `${methodName} error`;
|
|
131
|
+
try {
|
|
132
|
+
const result = originalMethod.apply(this, args);
|
|
133
|
+
if (result instanceof Promise) return result.catch((error) => {
|
|
134
|
+
const errorData = { method: methodName };
|
|
135
|
+
if (error instanceof Error && includeStack) errorData["stack"] = error.stack;
|
|
136
|
+
logger.error(errorPrefix, error, errorData);
|
|
137
|
+
if (rethrow) throw error;
|
|
138
|
+
});
|
|
139
|
+
return result;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
const errorData = { method: methodName };
|
|
142
|
+
if (error instanceof Error && includeStack) errorData["stack"] = error.stack;
|
|
143
|
+
logger.error(errorPrefix, error, errorData);
|
|
144
|
+
if (rethrow) throw error;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
return descriptor;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Class decorator that applies logging to all methods of a class.
|
|
153
|
+
* Can be configured to exclude specific methods.
|
|
154
|
+
*
|
|
155
|
+
* @param {LogClassOptions} [options={}] - Configuration options
|
|
156
|
+
* @returns {ClassDecorator} The decorator function
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* @LogClass({ exclude: ['privateMethod'], timing: true })
|
|
161
|
+
* class MyService {
|
|
162
|
+
* publicMethod() { ... }
|
|
163
|
+
* privateMethod() { ... } // Won't be logged
|
|
164
|
+
* }
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
function LogClass(options = {}) {
|
|
168
|
+
const { exclude = [], logCalls = true, timing = false } = options;
|
|
169
|
+
return (target) => {
|
|
170
|
+
const className = target.name;
|
|
171
|
+
const prototype = target.prototype;
|
|
172
|
+
if (prototype) {
|
|
173
|
+
const methodNames = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor" && typeof prototype[name] === "function" && !exclude.includes(name));
|
|
174
|
+
for (const methodName of methodNames) {
|
|
175
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
|
|
176
|
+
if (!descriptor) continue;
|
|
177
|
+
const originalMethod = descriptor.value;
|
|
178
|
+
descriptor.value = function(...args) {
|
|
179
|
+
const logger = Logger.getLogger(`[${className}]`);
|
|
180
|
+
const startTime = timing ? performance.now() : 0;
|
|
181
|
+
if (logCalls) logger.debug(`${methodName} called`, { arguments: args });
|
|
182
|
+
const result = originalMethod.apply(this, args);
|
|
183
|
+
if (result instanceof Promise) return result.then((value) => {
|
|
184
|
+
if (timing) {
|
|
185
|
+
const duration = performance.now() - startTime;
|
|
186
|
+
logger.debug(`${methodName} completed in ${duration.toFixed(2)}ms`);
|
|
187
|
+
} else if (logCalls) logger.debug(`${methodName} completed`);
|
|
188
|
+
return value;
|
|
189
|
+
}, (error) => {
|
|
190
|
+
logger.error(`${methodName} failed`, error);
|
|
191
|
+
throw error;
|
|
192
|
+
});
|
|
193
|
+
if (timing) {
|
|
194
|
+
const duration = performance.now() - startTime;
|
|
195
|
+
logger.debug(`${methodName} completed in ${duration.toFixed(2)}ms`);
|
|
196
|
+
} else if (logCalls) logger.debug(`${methodName} completed`);
|
|
197
|
+
return result;
|
|
198
|
+
};
|
|
199
|
+
Object.defineProperty(prototype, methodName, descriptor);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return target;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
//#endregion
|
|
206
|
+
export { Log, LogClass, LogError, LogTiming };
|
|
207
|
+
|
|
208
|
+
//# sourceMappingURL=logger.decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.decorators.js","names":[],"sources":["../src/logger.decorators.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview TypeScript decorators for logging method calls, timing, and errors.\n * These decorators integrate with the Logger class to provide declarative logging.\n */\n\nimport { Logger } from './logger.js';\nimport type {\n LogClassOptions,\n LogErrorOptions,\n LogMethodOptions,\n LogTimingOptions,\n} from './logger.types.js';\n\n/**\n * Decorator that logs method entry and exit.\n * Can optionally log arguments and return values.\n *\n * @param {LogMethodOptions} [options={}] - Configuration options\n * @returns {MethodDecorator} The decorator function\n *\n * @example\n * ```typescript\n * class UserService {\n * @Log({ logArgs: true, logResult: true })\n * async getUser(id: string) {\n * return { id, name: 'John' };\n * }\n * }\n * ```\n */\nexport function Log(options: LogMethodOptions = {}): MethodDecorator {\n const { logArgs = true, logResult = false, message, level = 'debug' } = options;\n\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n const originalMethod = descriptor.value;\n const methodName = String(propertyKey);\n const className = target.constructor.name;\n\n descriptor.value = function (...args: unknown[]) {\n const logger = Logger.getLogger(`[${className}]`);\n const prefix = message || `${methodName}`;\n\n // Log method entry\n if (logArgs && args.length > 0) {\n logger[level](`${prefix} called`, { arguments: args });\n } else {\n logger[level](`${prefix} called`);\n }\n\n // Execute the original method\n const result = originalMethod.apply(this, args);\n\n // Handle async methods\n if (result instanceof Promise) {\n return result.then(\n (value: unknown) => {\n if (logResult) {\n logger[level](`${prefix} returned`, { result: value });\n } else {\n logger[level](`${prefix} completed`);\n }\n return value;\n },\n (error: unknown) => {\n logger.error(`${prefix} failed`, error);\n throw error;\n },\n );\n }\n\n // Log sync method result\n if (logResult) {\n logger[level](`${prefix} returned`, { result });\n } else {\n logger[level](`${prefix} completed`);\n }\n\n return result;\n };\n\n return descriptor;\n };\n}\n\n/**\n * Decorator that logs method execution time.\n * Useful for performance monitoring.\n *\n * @param {LogTimingOptions} [options={}] - Configuration options\n * @returns {MethodDecorator} The decorator function\n *\n * @example\n * ```typescript\n * class DataService {\n * @LogTiming({ threshold: 100 }) // Only log if execution > 100ms\n * async fetchData() {\n * // ... slow operation\n * }\n * }\n * ```\n */\nexport function LogTiming(options: LogTimingOptions = {}): MethodDecorator {\n const { label, threshold = 0, level = 'info' } = options;\n\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n const originalMethod = descriptor.value;\n const methodName = String(propertyKey);\n const className = target.constructor.name;\n\n descriptor.value = function (...args: unknown[]) {\n const logger = Logger.getLogger(`[${className}]`);\n const timerLabel = label || `${className}.${methodName}`;\n const startTime = performance.now();\n\n // Execute the original method\n const result = originalMethod.apply(this, args);\n\n // Handle async methods\n if (result instanceof Promise) {\n return result.finally(() => {\n const duration = performance.now() - startTime;\n if (duration >= threshold) {\n logger[level](`${timerLabel} completed in ${duration.toFixed(2)}ms`);\n }\n });\n }\n\n // Log sync method timing\n const duration = performance.now() - startTime;\n if (duration >= threshold) {\n logger[level](`${timerLabel} completed in ${duration.toFixed(2)}ms`);\n }\n\n return result;\n };\n\n return descriptor;\n };\n}\n\n/**\n * Decorator that wraps method in try/catch and logs errors.\n * Can optionally suppress the error or rethrow it.\n *\n * @param {LogErrorOptions} [options={}] - Configuration options\n * @returns {MethodDecorator} The decorator function\n *\n * @example\n * ```typescript\n * class ApiService {\n * @LogError({ rethrow: false, message: 'API call failed' })\n * async callApi() {\n * throw new Error('Network error');\n * }\n * }\n * ```\n */\nexport function LogError(options: LogErrorOptions = {}): MethodDecorator {\n const { rethrow = true, message, includeStack = true } = options;\n\n return (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor => {\n const originalMethod = descriptor.value;\n const methodName = String(propertyKey);\n const className = target.constructor.name;\n\n descriptor.value = function (...args: unknown[]) {\n const logger = Logger.getLogger(`[${className}]`);\n const errorPrefix = message || `${methodName} error`;\n\n try {\n const result = originalMethod.apply(this, args);\n\n // Handle async methods\n if (result instanceof Promise) {\n return result.catch((error: unknown) => {\n const errorData: Record<string, unknown> = { method: methodName };\n if (error instanceof Error && includeStack) {\n errorData['stack'] = error.stack;\n }\n logger.error(errorPrefix, error, errorData);\n if (rethrow) throw error;\n return undefined;\n });\n }\n\n return result;\n } catch (error) {\n const errorData: Record<string, unknown> = { method: methodName };\n if (error instanceof Error && includeStack) {\n errorData['stack'] = error.stack;\n }\n logger.error(errorPrefix, error, errorData);\n if (rethrow) throw error;\n return undefined;\n }\n };\n\n return descriptor;\n };\n}\n\n/**\n * Class decorator that applies logging to all methods of a class.\n * Can be configured to exclude specific methods.\n *\n * @param {LogClassOptions} [options={}] - Configuration options\n * @returns {ClassDecorator} The decorator function\n *\n * @example\n * ```typescript\n * @LogClass({ exclude: ['privateMethod'], timing: true })\n * class MyService {\n * publicMethod() { ... }\n * privateMethod() { ... } // Won't be logged\n * }\n * ```\n */\nexport function LogClass(\n options: LogClassOptions = {},\n): <T extends new (...args: unknown[]) => object>(target: T) => T {\n const { exclude = [], logCalls = true, timing = false } = options;\n\n return <T extends new (...args: unknown[]) => object>(target: T): T => {\n const className = target.name;\n const prototype = target.prototype;\n\n // Only apply decorators if prototype exists\n if (prototype) {\n // Get all method names from the prototype\n const methodNames = Object.getOwnPropertyNames(prototype).filter(\n (name) =>\n name !== 'constructor' &&\n typeof prototype[name] === 'function' &&\n !exclude.includes(name),\n );\n\n // Apply decorators to each method\n for (const methodName of methodNames) {\n const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);\n if (!descriptor) continue;\n\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: unknown[]) {\n const logger = Logger.getLogger(`[${className}]`);\n const startTime = timing ? performance.now() : 0;\n\n if (logCalls) {\n logger.debug(`${methodName} called`, { arguments: args });\n }\n\n const result = originalMethod.apply(this, args);\n\n if (result instanceof Promise) {\n return result.then(\n (value: unknown) => {\n if (timing) {\n const duration = performance.now() - startTime;\n logger.debug(`${methodName} completed in ${duration.toFixed(2)}ms`);\n } else if (logCalls) {\n logger.debug(`${methodName} completed`);\n }\n return value;\n },\n (error: unknown) => {\n logger.error(`${methodName} failed`, error);\n throw error;\n },\n );\n }\n\n if (timing) {\n const duration = performance.now() - startTime;\n logger.debug(`${methodName} completed in ${duration.toFixed(2)}ms`);\n } else if (logCalls) {\n logger.debug(`${methodName} completed`);\n }\n\n return result;\n };\n\n Object.defineProperty(prototype, methodName, descriptor);\n }\n }\n\n return target;\n };\n}\n"],"mappings":"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"}
|
package/lib/logger.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
//#region src/logger.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @fileoverview A comprehensive logging utility for both client and server environments.
|
|
19
|
+
* Provides structured logging with support for different log levels, colorization,
|
|
20
|
+
* and contextual information.
|
|
21
|
+
*
|
|
22
|
+
* This logger uses native console methods with structured formatting — no external
|
|
23
|
+
* dependencies are required. Log output follows the pattern:
|
|
24
|
+
* TIMESTAMP LEVEL [CONTEXT] message { data }
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Enum representing different logging levels with their priority values.
|
|
28
|
+
* Higher values indicate more verbose logging.
|
|
29
|
+
* @enum {number}
|
|
30
|
+
*/
|
|
31
|
+
let LogLevel = /* @__PURE__ */ function(LogLevel) {
|
|
32
|
+
/** No logging */
|
|
33
|
+
LogLevel[LogLevel["NONE"] = 0] = "NONE";
|
|
34
|
+
/** Only error messages */
|
|
35
|
+
LogLevel[LogLevel["ERROR"] = 1] = "ERROR";
|
|
36
|
+
/** Errors and warnings */
|
|
37
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
38
|
+
/** Errors, warnings, and informational messages */
|
|
39
|
+
LogLevel[LogLevel["INFO"] = 3] = "INFO";
|
|
40
|
+
/** Errors, warnings, info, and debug messages */
|
|
41
|
+
LogLevel[LogLevel["DEBUG"] = 4] = "DEBUG";
|
|
42
|
+
/** Errors, warnings, info, debug, and trace messages */
|
|
43
|
+
LogLevel[LogLevel["TRACE"] = 5] = "TRACE";
|
|
44
|
+
/** All possible log messages */
|
|
45
|
+
LogLevel[LogLevel["ALL"] = 6] = "ALL";
|
|
46
|
+
return LogLevel;
|
|
47
|
+
}({});
|
|
48
|
+
/**
|
|
49
|
+
* A versatile logging utility that works in both browser and Node.js environments.
|
|
50
|
+
* Supports multiple log levels, colorized output, and structured data logging.
|
|
51
|
+
*/
|
|
52
|
+
var Logger = class Logger {
|
|
53
|
+
/** The context/category name for this logger instance */
|
|
54
|
+
context;
|
|
55
|
+
/** The minimum log level that will be output */
|
|
56
|
+
minLevel;
|
|
57
|
+
/**
|
|
58
|
+
* Parse log level from string or return default
|
|
59
|
+
*/
|
|
60
|
+
static parseLevel(level) {
|
|
61
|
+
if (!level) return void 0;
|
|
62
|
+
switch (level.toUpperCase()) {
|
|
63
|
+
case "NONE": return LogLevel.NONE;
|
|
64
|
+
case "ERROR": return LogLevel.ERROR;
|
|
65
|
+
case "WARN": return LogLevel.WARN;
|
|
66
|
+
case "INFO": return LogLevel.INFO;
|
|
67
|
+
case "DEBUG": return LogLevel.DEBUG;
|
|
68
|
+
case "TRACE": return LogLevel.TRACE;
|
|
69
|
+
case "ALL": return LogLevel.ALL;
|
|
70
|
+
default: return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Registry of logger instances to implement the singleton pattern */
|
|
74
|
+
static instances = /* @__PURE__ */ new Map();
|
|
75
|
+
/**
|
|
76
|
+
* Create a new Logger instance or return an existing one for the given context
|
|
77
|
+
* @param {string} context - The context name for this logger (e.g., component or service name)
|
|
78
|
+
* @param {LoggerOptions} [options={}] - Optional logger configuration
|
|
79
|
+
*/
|
|
80
|
+
constructor(context, options = {}) {
|
|
81
|
+
this.context = context;
|
|
82
|
+
const env = typeof process !== "undefined" ? process.env : {};
|
|
83
|
+
const envLevel = Logger.parseLevel(env["LOG_LEVEL"] || env["BUN_LOG_LEVEL"]);
|
|
84
|
+
this.minLevel = options.minLevel ?? envLevel ?? (env["NODE_ENV"] === "production" ? LogLevel.ERROR : LogLevel.ALL);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get a logger instance for the given context.
|
|
88
|
+
* If a logger with this context already exists, returns the existing instance.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} context - The context name
|
|
91
|
+
* @param {LoggerOptions} [options] - Optional logger configuration
|
|
92
|
+
* @returns {Logger} A logger instance for the specified context
|
|
93
|
+
*/
|
|
94
|
+
static getLogger(context, options) {
|
|
95
|
+
let instance = Logger.instances.get(context);
|
|
96
|
+
if (!instance) {
|
|
97
|
+
instance = new Logger(context, options);
|
|
98
|
+
Logger.instances.set(context, instance);
|
|
99
|
+
}
|
|
100
|
+
return instance;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Set global minimum log level for all logger instances
|
|
104
|
+
*
|
|
105
|
+
* @param {LogLevel} level - The minimum level to log across all loggers
|
|
106
|
+
*/
|
|
107
|
+
static setGlobalLogLevel(level) {
|
|
108
|
+
Logger.instances.forEach((logger) => {
|
|
109
|
+
logger.minLevel = level;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Format a timestamp for log output
|
|
114
|
+
*/
|
|
115
|
+
formatTimestamp() {
|
|
116
|
+
const now = /* @__PURE__ */ new Date();
|
|
117
|
+
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}:${String(now.getSeconds()).padStart(2, "0")}.${String(now.getMilliseconds()).padStart(3, "0")}`;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Format structured log data into a readable suffix string.
|
|
121
|
+
* Returns empty string if data is null/empty.
|
|
122
|
+
*/
|
|
123
|
+
formatData(data) {
|
|
124
|
+
if (!data || Object.keys(data).length === 0) return "";
|
|
125
|
+
try {
|
|
126
|
+
return ` ${JSON.stringify(data)}`;
|
|
127
|
+
} catch {
|
|
128
|
+
return " [unserializable data]";
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Emit a log entry using the appropriate console method
|
|
133
|
+
*/
|
|
134
|
+
emit(consoleFn, level, message, data) {
|
|
135
|
+
const ts = this.formatTimestamp();
|
|
136
|
+
const suffix = this.formatData(data);
|
|
137
|
+
consoleFn(`${ts} ${level} [${this.context}] ${message}${suffix}`);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Log an informational message
|
|
141
|
+
*
|
|
142
|
+
* @param {string} message - The message to log
|
|
143
|
+
* @param {LogData} [data] - Optional data to include
|
|
144
|
+
*/
|
|
145
|
+
info(message, data) {
|
|
146
|
+
if (this.minLevel < LogLevel.INFO) return;
|
|
147
|
+
this.emit(console.info, "INFO", message, data);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Log an error message
|
|
151
|
+
*
|
|
152
|
+
* @param {string} message - The error message
|
|
153
|
+
* @param {Error|unknown} [error] - Optional Error object or unknown error
|
|
154
|
+
* @param {LogData} [data] - Optional additional data
|
|
155
|
+
*/
|
|
156
|
+
error(message, error, data) {
|
|
157
|
+
if (this.minLevel < LogLevel.ERROR) return;
|
|
158
|
+
let errorObj = error;
|
|
159
|
+
if (error instanceof Error) {
|
|
160
|
+
const errorMessage = error.message || ("cause" in error && error.cause instanceof Error ? error.cause.message : "");
|
|
161
|
+
errorObj = {
|
|
162
|
+
name: error.name,
|
|
163
|
+
message: errorMessage,
|
|
164
|
+
stack: error.stack
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
this.emit(console.error, "ERROR", message, {
|
|
168
|
+
...data,
|
|
169
|
+
error: errorObj
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Log a warning message
|
|
174
|
+
*
|
|
175
|
+
* @param {string} message - The warning message
|
|
176
|
+
* @param {LogData} [data] - Optional data to include
|
|
177
|
+
*/
|
|
178
|
+
warn(message, data) {
|
|
179
|
+
if (this.minLevel < LogLevel.WARN) return;
|
|
180
|
+
this.emit(console.warn, "WARN", message, data);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Log a debug message
|
|
184
|
+
*
|
|
185
|
+
* @param {string} message - The debug message
|
|
186
|
+
* @param {LogData} [data] - Optional data to include
|
|
187
|
+
*/
|
|
188
|
+
debug(message, data) {
|
|
189
|
+
if (this.minLevel < LogLevel.DEBUG) return;
|
|
190
|
+
this.emit(console.debug, "DEBUG", message, data);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Log a trace message (most verbose level)
|
|
194
|
+
*
|
|
195
|
+
* @param {string} message - The trace message
|
|
196
|
+
* @param {LogData} [data] - Optional data to include
|
|
197
|
+
*/
|
|
198
|
+
trace(message, data) {
|
|
199
|
+
if (this.minLevel < LogLevel.TRACE) return;
|
|
200
|
+
this.emit(console.debug, "TRACE", message, data);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Log an action message (for server actions or important user interactions)
|
|
204
|
+
*
|
|
205
|
+
* @param {string} message - The action message
|
|
206
|
+
* @param {LogData} [data] - Optional data to include
|
|
207
|
+
*/
|
|
208
|
+
action(message, data) {
|
|
209
|
+
if (this.minLevel < LogLevel.INFO) return;
|
|
210
|
+
this.emit(console.info, "ACTION", message, data);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Log a success message
|
|
214
|
+
*
|
|
215
|
+
* @param {string} message - The success message
|
|
216
|
+
* @param {LogData} [data] - Optional data to include
|
|
217
|
+
*/
|
|
218
|
+
success(message, data) {
|
|
219
|
+
if (this.minLevel < LogLevel.INFO) return;
|
|
220
|
+
this.emit(console.info, "SUCCESS", message, data);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Group related log messages (console.group wrapper)
|
|
224
|
+
*
|
|
225
|
+
* @param {string} label - The group label
|
|
226
|
+
*/
|
|
227
|
+
group(label) {
|
|
228
|
+
if (this.minLevel < LogLevel.INFO) return;
|
|
229
|
+
console.group(label);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* End a log group (console.groupEnd wrapper)
|
|
233
|
+
*/
|
|
234
|
+
groupEnd() {
|
|
235
|
+
if (this.minLevel < LogLevel.INFO) return;
|
|
236
|
+
console.groupEnd();
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Log execution time of a function
|
|
240
|
+
*
|
|
241
|
+
* @template T - The return type of the function being timed
|
|
242
|
+
* @param {string} label - Description of the operation being timed
|
|
243
|
+
* @param {() => Promise<T> | T} fn - Function to execute and time
|
|
244
|
+
* @returns {Promise<T>} The result of the function execution
|
|
245
|
+
*/
|
|
246
|
+
async time(label, fn) {
|
|
247
|
+
if (this.minLevel < LogLevel.DEBUG) return fn();
|
|
248
|
+
const startTime = performance.now();
|
|
249
|
+
try {
|
|
250
|
+
const result = await fn();
|
|
251
|
+
const duration = (performance.now() - startTime).toFixed(2);
|
|
252
|
+
this.info(`${label} completed`, { duration: `${duration}ms` });
|
|
253
|
+
return result;
|
|
254
|
+
} catch (error) {
|
|
255
|
+
const duration = (performance.now() - startTime).toFixed(2);
|
|
256
|
+
this.error(`${label} failed`, error, { duration: `${duration}ms` });
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const logger = new Logger("[LOGGER]", {
|
|
262
|
+
includeTimestamp: true,
|
|
263
|
+
colorize: true
|
|
264
|
+
});
|
|
265
|
+
//#endregion
|
|
266
|
+
export { LogLevel, Logger, logger };
|
|
267
|
+
|
|
268
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","names":[],"sources":["../src/logger.ts"],"sourcesContent":["/**\n * Copyright (c) 2026 ResQ\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview A comprehensive logging utility for both client and server environments.\n * Provides structured logging with support for different log levels, colorization,\n * and contextual information.\n *\n * This logger uses native console methods with structured formatting — no external\n * dependencies are required. Log output follows the pattern:\n * TIMESTAMP LEVEL [CONTEXT] message { data }\n */\n\n/**\n * Enum representing different logging levels with their priority values.\n * Higher values indicate more verbose logging.\n * @enum {number}\n */\nexport enum LogLevel {\n /** No logging */\n NONE = 0,\n /** Only error messages */\n ERROR = 1,\n /** Errors and warnings */\n WARN = 2,\n /** Errors, warnings, and informational messages */\n INFO = 3,\n /** Errors, warnings, info, and debug messages */\n DEBUG = 4,\n /** Errors, warnings, info, debug, and trace messages */\n TRACE = 5,\n /** All possible log messages */\n ALL = 6,\n}\n\n/**\n * Available color keys for log formatting\n * @typedef {'reset' | 'red' | 'yellow' | 'blue' | 'green' | 'gray' | 'bold' | 'magenta' | 'cyan' | 'white'} ColorKey\n */\nexport type ColorKey =\n | 'reset'\n | 'red'\n | 'yellow'\n | 'blue'\n | 'green'\n | 'gray'\n | 'bold'\n | 'magenta'\n | 'cyan'\n | 'white';\n\n/**\n * Interface for structured data that can be attached to log messages\n * @interface\n */\nexport interface LogData {\n /**\n * Any key-value pairs to include in the log\n */\n [key: string]: unknown;\n}\n\n/**\n * Configuration options for the Logger\n * @interface\n */\nexport interface LoggerOptions {\n /**\n * The minimum level of messages to log\n */\n minLevel?: LogLevel;\n\n /**\n * Whether to include timestamps in log messages\n */\n includeTimestamp?: boolean;\n\n /**\n * Whether to colorize log output\n */\n colorize?: boolean;\n\n /**\n * Whether to write logs to a file (server-side only)\n */\n logToFile?: boolean;\n\n /**\n * Path to the log file if logToFile is enabled\n */\n filePath?: string;\n}\n\n/**\n * A versatile logging utility that works in both browser and Node.js environments.\n * Supports multiple log levels, colorized output, and structured data logging.\n */\nexport class Logger {\n /** The context/category name for this logger instance */\n private readonly context: string;\n\n /** The minimum log level that will be output */\n private minLevel: LogLevel;\n\n /**\n * Parse log level from string or return default\n */\n private static parseLevel(level?: string): LogLevel | undefined {\n if (!level) return undefined;\n const upper = level.toUpperCase();\n switch (upper) {\n case 'NONE': return LogLevel.NONE;\n case 'ERROR': return LogLevel.ERROR;\n case 'WARN': return LogLevel.WARN;\n case 'INFO': return LogLevel.INFO;\n case 'DEBUG': return LogLevel.DEBUG;\n case 'TRACE': return LogLevel.TRACE;\n case 'ALL': return LogLevel.ALL;\n default: return undefined;\n }\n }\n\n /** Registry of logger instances to implement the singleton pattern */\n private static readonly instances: Map<string, Logger> = new Map();\n\n /**\n * Create a new Logger instance or return an existing one for the given context\n * @param {string} context - The context name for this logger (e.g., component or service name)\n * @param {LoggerOptions} [options={}] - Optional logger configuration\n */\n constructor(context: string, options: LoggerOptions = {}) {\n this.context = context;\n\n // Priority: options.minLevel > LOG_LEVEL env > BUN_LOG_LEVEL env > Default\n const env = typeof process !== 'undefined' ? process.env : {};\n const envLevel = Logger.parseLevel(env['LOG_LEVEL'] || env['BUN_LOG_LEVEL']);\n\n this.minLevel =\n options.minLevel ??\n envLevel ??\n (env['NODE_ENV'] === 'production' ? LogLevel.ERROR : LogLevel.ALL);\n }\n\n /**\n * Get a logger instance for the given context.\n * If a logger with this context already exists, returns the existing instance.\n *\n * @param {string} context - The context name\n * @param {LoggerOptions} [options] - Optional logger configuration\n * @returns {Logger} A logger instance for the specified context\n */\n public static getLogger(context: string, options?: LoggerOptions): Logger {\n let instance = Logger.instances.get(context);\n\n if (!instance) {\n instance = new Logger(context, options);\n Logger.instances.set(context, instance);\n }\n\n return instance;\n }\n\n /**\n * Set global minimum log level for all logger instances\n *\n * @param {LogLevel} level - The minimum level to log across all loggers\n */\n public static setGlobalLogLevel(level: LogLevel): void {\n Logger.instances.forEach((logger) => {\n logger.minLevel = level;\n });\n }\n\n /**\n * Format a timestamp for log output\n */\n private formatTimestamp(): string {\n const now = new Date();\n const y = now.getFullYear();\n const mo = String(now.getMonth() + 1).padStart(2, '0');\n const d = String(now.getDate()).padStart(2, '0');\n const h = String(now.getHours()).padStart(2, '0');\n const mi = String(now.getMinutes()).padStart(2, '0');\n const s = String(now.getSeconds()).padStart(2, '0');\n const ms = String(now.getMilliseconds()).padStart(3, '0');\n return `${y}-${mo}-${d} ${h}:${mi}:${s}.${ms}`;\n }\n\n /**\n * Format structured log data into a readable suffix string.\n * Returns empty string if data is null/empty.\n */\n private formatData(data?: Record<string, unknown>): string {\n if (!data || Object.keys(data).length === 0) return '';\n try {\n return ` ${JSON.stringify(data)}`;\n } catch {\n return ' [unserializable data]';\n }\n }\n\n /**\n * Emit a log entry using the appropriate console method\n */\n private emit(\n consoleFn: (...args: unknown[]) => void,\n level: string,\n message: string,\n data?: Record<string, unknown>,\n ): void {\n const ts = this.formatTimestamp();\n const suffix = this.formatData(data);\n consoleFn(`${ts} ${level} [${this.context}] ${message}${suffix}`);\n }\n\n /**\n * Log an informational message\n *\n * @param {string} message - The message to log\n * @param {LogData} [data] - Optional data to include\n */\n info(message: string, data?: LogData): void {\n if (this.minLevel < LogLevel.INFO) return;\n this.emit(console.info, 'INFO', message, data);\n }\n\n /**\n * Log an error message\n *\n * @param {string} message - The error message\n * @param {Error|unknown} [error] - Optional Error object or unknown error\n * @param {LogData} [data] - Optional additional data\n */\n error(message: string, error?: unknown, data?: LogData): void {\n if (this.minLevel < LogLevel.ERROR) return;\n\n let errorObj: unknown = error;\n if (error instanceof Error) {\n const errorMessage =\n error.message || ('cause' in error && error.cause instanceof Error ? error.cause.message : '');\n errorObj = { name: error.name, message: errorMessage, stack: error.stack };\n }\n\n this.emit(console.error, 'ERROR', message, { ...data, error: errorObj });\n }\n\n /**\n * Log a warning message\n *\n * @param {string} message - The warning message\n * @param {LogData} [data] - Optional data to include\n */\n warn(message: string, data?: LogData): void {\n if (this.minLevel < LogLevel.WARN) return;\n this.emit(console.warn, 'WARN', message, data);\n }\n\n /**\n * Log a debug message\n *\n * @param {string} message - The debug message\n * @param {LogData} [data] - Optional data to include\n */\n debug(message: string, data?: LogData): void {\n if (this.minLevel < LogLevel.DEBUG) return;\n this.emit(console.debug, 'DEBUG', message, data);\n }\n\n /**\n * Log a trace message (most verbose level)\n *\n * @param {string} message - The trace message\n * @param {LogData} [data] - Optional data to include\n */\n trace(message: string, data?: LogData): void {\n if (this.minLevel < LogLevel.TRACE) return;\n this.emit(console.debug, 'TRACE', message, data);\n }\n\n /**\n * Log an action message (for server actions or important user interactions)\n *\n * @param {string} message - The action message\n * @param {LogData} [data] - Optional data to include\n */\n action(message: string, data?: LogData): void {\n if (this.minLevel < LogLevel.INFO) return;\n this.emit(console.info, 'ACTION', message, data);\n }\n\n /**\n * Log a success message\n *\n * @param {string} message - The success message\n * @param {LogData} [data] - Optional data to include\n */\n success(message: string, data?: LogData): void {\n if (this.minLevel < LogLevel.INFO) return;\n this.emit(console.info, 'SUCCESS', message, data);\n }\n\n /**\n * Group related log messages (console.group wrapper)\n *\n * @param {string} label - The group label\n */\n group(label: string): void {\n if (this.minLevel < LogLevel.INFO) return;\n console.group(label);\n }\n\n /**\n * End a log group (console.groupEnd wrapper)\n */\n groupEnd(): void {\n if (this.minLevel < LogLevel.INFO) return;\n console.groupEnd();\n }\n\n /**\n * Log execution time of a function\n *\n * @template T - The return type of the function being timed\n * @param {string} label - Description of the operation being timed\n * @param {() => Promise<T> | T} fn - Function to execute and time\n * @returns {Promise<T>} The result of the function execution\n */\n async time<T>(label: string, fn: () => Promise<T> | T): Promise<T> {\n if (this.minLevel < LogLevel.DEBUG) return fn();\n\n const startTime = performance.now();\n try {\n const result = await fn();\n const endTime = performance.now();\n const duration = (endTime - startTime).toFixed(2);\n this.info(`${label} completed`, { duration: `${duration}ms` });\n return result;\n } catch (error) {\n const endTime = performance.now();\n const duration = (endTime - startTime).toFixed(2);\n this.error(`${label} failed`, error, { duration: `${duration}ms` });\n throw error;\n }\n }\n}\n\nexport const logger = new Logger('[LOGGER]', {\n includeTimestamp: true,\n colorize: true,\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { LogLevel } from "./logger.js";
|
|
2
|
+
|
|
3
|
+
//#region src/logger.types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Copyright 2026 ResQ
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Interface for structured data that can be attached to log messages
|
|
21
|
+
* @interface
|
|
22
|
+
*/
|
|
23
|
+
interface LogData {
|
|
24
|
+
/**
|
|
25
|
+
* Any key-value pairs to include in the log
|
|
26
|
+
*/
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Configuration options for the Logger
|
|
31
|
+
* @interface
|
|
32
|
+
*/
|
|
33
|
+
interface LoggerOptions {
|
|
34
|
+
/**
|
|
35
|
+
* The minimum level of messages to log
|
|
36
|
+
*/
|
|
37
|
+
minLevel?: LogLevel;
|
|
38
|
+
/**
|
|
39
|
+
* Whether to include timestamps in log messages
|
|
40
|
+
*/
|
|
41
|
+
includeTimestamp?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether to colorize log output
|
|
44
|
+
*/
|
|
45
|
+
colorize?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to write logs to a file (server-side only)
|
|
48
|
+
*/
|
|
49
|
+
logToFile?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Path to the log file if logToFile is enabled
|
|
52
|
+
*/
|
|
53
|
+
filePath?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Available color keys for log formatting
|
|
57
|
+
* @typedef ColorKey
|
|
58
|
+
*/
|
|
59
|
+
type ColorKey = 'reset' | 'red' | 'yellow' | 'blue' | 'green' | 'gray' | 'bold' | 'magenta' | 'cyan' | 'white';
|
|
60
|
+
/**
|
|
61
|
+
* Log level strings for type safety
|
|
62
|
+
*/
|
|
63
|
+
type LogLevelString = 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'action' | 'success';
|
|
64
|
+
/**
|
|
65
|
+
* Structured log entry for transport/storage
|
|
66
|
+
* @interface
|
|
67
|
+
*/
|
|
68
|
+
interface LogEntry {
|
|
69
|
+
/** ISO timestamp of the log */
|
|
70
|
+
timestamp: string;
|
|
71
|
+
/** Log level */
|
|
72
|
+
level: LogLevelString;
|
|
73
|
+
/** Logger context/category */
|
|
74
|
+
context: string;
|
|
75
|
+
/** Log message */
|
|
76
|
+
message: string;
|
|
77
|
+
/** Optional structured data */
|
|
78
|
+
data?: LogData;
|
|
79
|
+
/** Environment (client/server) */
|
|
80
|
+
environment: 'client' | 'server';
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Interface for custom log transports
|
|
84
|
+
* @interface
|
|
85
|
+
*/
|
|
86
|
+
interface LogTransport {
|
|
87
|
+
/** Transport name for identification */
|
|
88
|
+
name: string;
|
|
89
|
+
/** Method to write a log entry */
|
|
90
|
+
write(entry: LogEntry): void | Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Options for the @Log decorator
|
|
94
|
+
* @interface
|
|
95
|
+
*/
|
|
96
|
+
interface LogMethodOptions {
|
|
97
|
+
/** Whether to log method arguments (default: true) */
|
|
98
|
+
logArgs?: boolean;
|
|
99
|
+
/** Whether to log return value (default: false) */
|
|
100
|
+
logResult?: boolean;
|
|
101
|
+
/** Custom message prefix */
|
|
102
|
+
message?: string;
|
|
103
|
+
/** Log level to use (default: 'debug') */
|
|
104
|
+
level?: LogLevelString;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Options for the @LogTiming decorator
|
|
108
|
+
* @interface
|
|
109
|
+
*/
|
|
110
|
+
interface LogTimingOptions {
|
|
111
|
+
/** Custom label for timing logs */
|
|
112
|
+
label?: string;
|
|
113
|
+
/** Threshold in ms - only log if execution exceeds this (default: 0) */
|
|
114
|
+
threshold?: number;
|
|
115
|
+
/** Log level to use (default: 'info') */
|
|
116
|
+
level?: LogLevelString;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Options for the @LogError decorator
|
|
120
|
+
* @interface
|
|
121
|
+
*/
|
|
122
|
+
interface LogErrorOptions {
|
|
123
|
+
/** Whether to rethrow the error after logging (default: true) */
|
|
124
|
+
rethrow?: boolean;
|
|
125
|
+
/** Custom error message prefix */
|
|
126
|
+
message?: string;
|
|
127
|
+
/** Whether to log the stack trace (default: true) */
|
|
128
|
+
includeStack?: boolean;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Options for the @LogClass decorator
|
|
132
|
+
* @interface
|
|
133
|
+
*/
|
|
134
|
+
interface LogClassOptions {
|
|
135
|
+
/** Methods to exclude from logging */
|
|
136
|
+
exclude?: string[];
|
|
137
|
+
/** Whether to log all method calls (default: true) */
|
|
138
|
+
logCalls?: boolean;
|
|
139
|
+
/** Whether to time all method calls (default: false) */
|
|
140
|
+
timing?: boolean;
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
export { ColorKey, LogClassOptions, LogData, LogEntry, LogErrorOptions, LogLevelString, LogMethodOptions, LogTimingOptions, LogTransport, LoggerOptions };
|
|
144
|
+
//# sourceMappingURL=logger.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.types.d.ts","names":[],"sources":["../src/logger.types.ts"],"mappings":";;;;;;AAoBA;;;;;AAWA;;;;;;;;;;;UAXiB,OAAA;EAsCL;;;EAAA,CAlCT,GAAA;AAAA;AAiDH;;;;AAAA,UA1CiB,aAAA;EAgDA;;;EA5Cf,QAAA,GAJ4B,QAAA;EAkD5B;;;EA1CA,gBAAA;EAgDA;;;EA5CA,QAAA;EAgDW;;AAOb;EAnDE,SAAA;;;;EAIA,QAAA;AAAA;;;;;KAOU,QAAA;;;;KAeA,cAAA;;;;;UAMK,QAAA;EAsCO;EApCtB,SAAA;EA2C+B;EAzC/B,KAAA,EAAO,cAAA;EA+Ce;EA7CtB,OAAA;EA2CA;EAzCA,OAAA;EA2CQ;EAzCR,IAAA,GAAO,OAAA;EAyCe;EAvCtB,WAAA;AAAA;;;;;UAOe,YAAA;EA6CH;EA3CZ,IAAA;EAkDe;EAhDf,KAAA,CAAM,KAAA,EAAO,QAAA,UAAkB,OAAA;AAAA;;;;;UAOhB,gBAAA;EA+CT;EA7CN,OAAA;;EAEA,SAAA;;EAEA,OAAA;;EAEA,KAAA,GAAQ,cAAA;AAAA;;;;;UAOO,gBAAA;;EAEf,KAAA;;EAEA,SAAA;;EAEA,KAAA,GAAQ,cAAA;AAAA;;;;;UAOO,eAAA;;EAEf,OAAA;;EAEA,OAAA;;EAEA,YAAA;AAAA;;;;;UAOe,eAAA;;EAEf,OAAA;;EAEA,QAAA;;EAEA,MAAA;AAAA"}
|
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@resq-sw/logger",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Structured logging with log levels for Node.js and Bun",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./lib/index.d.ts",
|
|
10
|
+
"import": "./lib/index.js",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/index.d.ts",
|
|
16
|
+
"files": ["lib", "README.md"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsdown",
|
|
19
|
+
"test": "vitest run"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"tsdown": "^0.21.7",
|
|
23
|
+
"typescript": "5.9.3",
|
|
24
|
+
"vitest": "3.2.4"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public",
|
|
28
|
+
"provenance": true,
|
|
29
|
+
"registry": "https://registry.npmjs.org/"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/resq-software/npm.git",
|
|
34
|
+
"directory": "packages/logger"
|
|
35
|
+
},
|
|
36
|
+
"keywords": ["logger", "logging", "structured-logging"],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20.19.0"
|
|
39
|
+
}
|
|
40
|
+
}
|