@decaf-ts/logging 0.3.5 → 0.3.7

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 CHANGED
@@ -1,8 +1,11 @@
1
- ![Banner](./workdocs/assets/Banner.png)
1
+ <!-- AUTO-GENERATED: logging/workdocs/1-Header.md -->
2
+ # Logging Library (decaf-ts/logging)
2
3
 
3
- ## Decaf's Logging
4
-
5
- A comprehensive, flexible, and type-safe logging library for TypeScript applications that provides hierarchical context-aware logging, configurable styling, multiple output formats, and method decorators. It offers a lightweight built-in logger and seamless Winston integration, enabling developers to easily add structured logging with different verbosity levels to their applications.
4
+ A small, flexible TypeScript logging library designed for framework-agnostic projects. It provides:
5
+ - Context-aware loggers with hierarchical contexts (class.method) via MiniLogger and the static Logging facade.
6
+ - Configurable output (level filtering, verbosity, separators, timestamps) and optional ANSI styling/theming.
7
+ - Simple method decorators (log/debug/info/verbose/silly) to instrument class methods without boilerplate.
8
+ - Extensibility through a pluggable LoggerFactory (e.g., WinstonLogger) while keeping a minimal default runtime.
6
9
 
7
10
 
8
11
  ![Licence](https://img.shields.io/github/license/decaf-ts/logging.svg?style=plastic)
@@ -34,377 +37,290 @@ A comprehensive, flexible, and type-safe logging library for TypeScript applicat
34
37
 
35
38
  Documentation available [here](https://decaf-ts.github.io/logging/)
36
39
 
37
- ### Description
38
-
39
- Decaf's Logging is a powerful TypeScript logging library designed to provide flexible, context-aware logging capabilities for applications of any size. The library is built with a focus on type safety, configurability, and ease of use.
40
-
41
- #### Core Architecture
42
-
43
- The library follows a modular architecture with several key components:
44
-
45
- 1. **Logging System**:
46
- - `Logging`: A static class that serves as the central entry point for the logging system. It manages global configuration, provides factory methods for creating loggers, and offers static logging methods.
47
- - `MiniLogger`: A lightweight logger implementation that provides the core logging functionality with support for different log levels, context-aware logging, and customizable formatting.
48
- - `Logger` interface: Defines the standard methods that all logger implementations must provide, ensuring consistency across different logger types.
49
-
50
- 2. **Configuration System**:
51
- - `LoggingConfig`: Defines configuration options for the logging system, including log level, verbosity, styling, timestamp format, and more.
52
- - `DefaultLoggingConfig`: Provides sensible default settings that can be overridden as needed.
53
-
54
- 3. **Log Levels**:
55
- - `LogLevel` enum: Defines standard log levels (error, info, verbose, debug, silly) for categorizing log messages.
56
- - `NumericLogLevels`: Maps log levels to numeric values for comparison and filtering.
57
-
58
- 4. **Styling System**:
59
- - `Theme` interface: Defines a comprehensive theming system for styling log output with colors and formatting.
60
- - `DefaultTheme`: Provides a default color scheme for log output.
61
- - `LoggingMode` enum: Supports different output formats (RAW, JSON) for log messages.
62
-
63
- 5. **Decorator System**:
64
- - Method decorators (`@log`, `@debug`, `@info`, `@verbose`, `@silly`): Allow for easy integration of logging into class methods with options for benchmarking and verbosity control.
65
-
66
- 6. **Winston Integration**:
67
- - `WinstonLogger`: Extends the core logging functionality to leverage the Winston logging library.
68
- - `WinstonFactory`: A factory function for creating Winston-based loggers.
69
-
70
- #### Key Features
71
-
72
- 1. **Hierarchical Context-Aware Logging**:
73
- The library allows creating loggers for specific classes and methods, maintaining a hierarchy of contexts. This makes it easy to trace log messages back to their source and filter logs by context.
74
-
75
- 2. **Configurable Styling**:
76
- Extensive support for styling log output with colors and formatting, with a theme system that allows customizing the appearance of different log components.
77
-
78
- 3. **Multiple Output Formats**:
79
- Support for both human-readable (RAW) and machine-parseable (JSON) output formats.
80
-
81
- 4. **Method Decorators**:
82
- Easy-to-use decorators for adding logging to class methods, with support for benchmarking execution time.
83
-
84
- 5. **Verbosity Control**:
85
- Fine-grained control over log verbosity, allowing developers to adjust the detail level of logs without changing code.
86
-
87
- 6. **Type Safety**:
88
- Comprehensive TypeScript type definitions ensure type safety and enable IDE autocompletion.
89
-
90
- 7. **Winston Integration**:
91
- Seamless integration with the popular Winston logging library, providing access to its advanced features while maintaining the same interface.
92
-
93
- 8. **Error Handling**:
94
- Special support for logging errors with stack traces for better debugging.
95
-
96
- #### Usage Patterns
97
-
98
- The library supports several usage patterns:
99
-
100
- 1. **Global Logging**:
101
- Using the static `Logging` class methods for simple, application-wide logging.
40
+ # Logging Library — Detailed Description
41
+
42
+ The logging package is a lightweight, extensible logging solution for TypeScript projects. It centers on two main constructs:
43
+ - MiniLogger — a minimal, context-aware logger used by default.
44
+ - Logging — a static facade that manages global configuration, creates loggers for classes/functions/strings, and applies optional theming.
45
+
46
+ It also offers:
47
+ - A concise set of decorators (log, debug, info, verbose, silly) to instrument methods with consistent logging and optional benchmarking.
48
+ - Pluggable factories so that alternate implementations (e.g., WinstonLogger) can be used without changing call sites.
49
+ - Strong typing for configuration and theming primitives.
50
+
51
+ Core files and their roles
52
+ - src/types.ts: Type definitions and contracts
53
+ - Logger: the runtime contract with methods silly, verbose, info, debug, error, for, setConfig.
54
+ - LoggingConfig: runtime configuration for filtering, formatting, and styling.
55
+ - LoggerFactory: factory signature returning a Logger for a given context and optional config.
56
+ - Theme/ThemeOption/ThemeOptionByLogLevel: shape of color and style configuration, optionally varying by LogLevel.
57
+ - Additional helpers: StringLike, AnyFunction, Class, LoggingContext.
58
+
59
+ - src/constants.ts: Defaults and enums
60
+ - LogLevel: error | info | verbose | debug | silly (string values), plus NumericLogLevels for filtering.
61
+ - LoggingMode: RAW | JSON (current implementation focuses on RAW; JSON is available for adapters like Winston).
62
+ - DefaultTheme: sensible default colors/styles per component and per log level.
63
+ - DefaultLoggingConfig: default global configuration (info level, no styling, timestamp on, etc.).
64
+
65
+ - src/logging.ts: Implementations and static facade
66
+ - MiniLogger: A small, dependency-light logger that:
67
+ - Generates formatted log strings (timestamp, log level, context, correlation id, message, stack) according to config.
68
+ - Supports child loggers via .for(method|config) with a Proxy to overlay per-child config and extend the context (class.method).
69
+ - Emits to console.log/console.debug/console.error based on level. Verbosity controls .silly output (gated by config.verbose).
70
+ - Logging: The static entry point that:
71
+ - Holds global configuration (Logging.getConfig(), Logging.setConfig()).
72
+ - Creates loggers for arbitrary contexts (Logging.for(object|class|function|string, config?)).
73
+ - Provides convenience static logging methods (info, debug, error, verbose, silly) delegating to a global logger instance.
74
+ - Supports theming (Logging.theme) by applying Theme options through styled-string-builder when style=true.
75
+ - Allows replacing the logger factory (Logging.setFactory) to integrate with other backends (e.g., Winston).
76
+
77
+ - src/decorators.ts: Method decorators
78
+ - log(level=info, benchmark=false, verbosity=0): wraps a method to emit a call log and optionally a completion time; supports Promise-returning methods.
79
+ - debug/info/silly/verbose: concise wrappers around log() for common patterns.
80
+
81
+ - src/LoggedClass.ts: Base convenience class
82
+ - LoggedClass exposes a protected this.log getter returning a context-aware Logger built via Logging.for(this), simplifying logging inside class methods.
83
+
84
+ - src/winston/winston.ts: Optional Winston adapter
85
+ - WinstonLogger: extends MiniLogger but delegates emission to a configured Winston instance.
86
+ - WinstonFactory: a LoggerFactory you can install with Logging.setFactory(WinstonFactory) to globally route logs through Winston.
87
+
88
+ Design principles
89
+ - Minimal by default: Console output with small surface area and no heavy dependencies (except styled-string-builder when style is enabled).
90
+ - Config-driven: Behavior (level thresholds, verbosity, timestamps, separators, theming) is controlled via LoggingConfig.
91
+ - Context-first: Log context is explicit ("MyClass" or "MyClass.method"), aiding filtering and debugging.
92
+ - Extensible: Swap logger implementations via a factory; MiniLogger serves as a reference implementation.
93
+ - Safe theming: Logging.theme guards against invalid theme keys and values and logs errors instead of throwing.
94
+
95
+ Key behaviors
96
+ - Level filtering: NumericLogLevels are used to compare configured level with the message level and decide emission.
97
+ - Verbosity: .silly obeys LoggingConfig.verbose; only messages with <= configured verbosity are emitted.
98
+ - Theming and styling: When style=true, Logging.theme applies Theme rules per component (class, message, logLevel, id, stack, timestamp). Theme can vary per LogLevel via ThemeOptionByLogLevel.
99
+ - Correlation IDs: If correlationId is configured in a logger or child logger, it is included in output for easier traceability.
100
+
101
+ Public API surface
102
+ - Classes: MiniLogger, Logging, LoggedClass; WinstonLogger (optional).
103
+ - Decorators: log, debug, info, verbose, silly.
104
+ - Enums/Consts: LogLevel, LoggingMode, NumericLogLevels, DefaultTheme, DefaultLoggingConfig.
105
+ - Types: Logger, LoggingConfig, LoggerFactory, Theme, ThemeOption, ThemeOptionByLogLevel, LoggingContext.
106
+
107
+ Intended usage
108
+ - Use Logging.setConfig() at application startup to set level/style/timestamps.
109
+ - Create class- or method-scoped loggers via Logging.for(MyClass) or logger.for('method').
110
+ - Adopt LoggedClass to remove boilerplate in classes.
111
+ - Add decorators to methods for automatic call/benchmark logs.
112
+ - For advanced deployments, swap to WinstonFactory.
113
+
114
+
115
+ # How to Use the Logging Library
116
+
117
+ This guide provides concise, non-redundant examples for each public API. Examples are inspired by the package’s unit tests and reflect real usage.
118
+
119
+ Note: Replace the import path with your actual package name. In this monorepo, tests import from "../../src".
120
+
121
+ - import { ... } from "@your-scope/logging" // typical
122
+ - import { ... } from "../../src" // inside this repo while developing
123
+
124
+
125
+ Basic setup and global logging via Logging
126
+ Description: Configure global logging and write messages through the static facade, similar to unit tests that verify console output and level filtering.
127
+
128
+ ```ts
129
+ import { Logging, LogLevel } from "@decaf-ts/logging";
130
+
131
+ // Set global configuration
132
+ Logging.setConfig({
133
+ level: LogLevel.debug, // allow debug and above
134
+ style: false, // plain output (tests use both styled and themeless)
135
+ timestamp: false, // omit timestamp for simplicity in this example
136
+ });
102
137
 
103
- 2. **Class-Specific Logging**:
104
- Creating loggers for specific classes to provide context for log messages.
138
+ // Log using the global logger
139
+ Logging.info("Application started");
140
+ Logging.debug("Debug details");
141
+ Logging.error("Something went wrong");
105
142
 
106
- 3. **Method-Specific Logging**:
107
- Creating child loggers for specific methods to further refine the context.
143
+ // Verbosity-controlled logs (silly delegates to verbose internally)
144
+ Logging.setConfig({ verbose: 2 });
145
+ Logging.silly("Extra details at verbosity 1"); // emitted when verbose >= 1
146
+ Logging.verbose("Even more details", 2); // only with verbose >= 2
147
+ ```
108
148
 
109
- 4. **Decorator-Based Logging**:
110
- Using method decorators to automatically log method calls and execution times.
111
149
 
112
- 5. **Winston-Based Logging**:
113
- Leveraging Winston's advanced features while maintaining the same interface.
150
+ Create a class-scoped logger and child method logger
151
+ Description: Create a logger bound to a specific context (class) and derive a child logger for a method, matching patterns used in tests.
114
152
 
115
- This flexible design makes the library suitable for a wide range of applications, from simple scripts to complex enterprise systems.
153
+ ```ts
154
+ import { Logging, LogLevel } from "@decaf-ts/logging";
116
155
 
156
+ Logging.setConfig({ level: LogLevel.debug });
117
157
 
118
- ### How to Use
158
+ // A class-scoped logger
159
+ const classLogger = Logging.for("UserService");
160
+ classLogger.info("Fetching users");
119
161
 
120
- - [Initial Setup](./tutorials/For%20Developers.md#_initial-setup_)
121
- - [Installation](./tutorials/For%20Developers.md#installation)
162
+ // A child logger for a specific method with temporary config overrides
163
+ const methodLogger = classLogger.for("list", { style: false });
164
+ methodLogger.debug("Querying repository...");
165
+ ```
122
166
 
123
- ## Basic Usage
124
167
 
125
- ### Global Logging
168
+ MiniLogger: direct use and per-instance config
169
+ Description: Instantiate MiniLogger directly (the default implementation behind Logging.setFactory). Tests create MiniLogger with and without custom config.
126
170
 
127
- The simplest way to use the library is through the static `Logging` class:
171
+ ```ts
172
+ import { MiniLogger, LogLevel, type LoggingConfig } from "@decaf-ts/logging";
128
173
 
129
- ```typescript
130
- import { Logging, LogLevel } from 'decaf-logging';
174
+ const logger = new MiniLogger("TestContext");
175
+ logger.info("Info from MiniLogger");
131
176
 
132
- // Configure global logging settings
133
- Logging.setConfig({
134
- level: LogLevel.debug,
135
- style: true,
136
- timestamp: true
137
- });
177
+ // With custom configuration
178
+ const custom: Partial<LoggingConfig> = { level: LogLevel.debug, verbose: 2 };
179
+ const customLogger = new MiniLogger("TestContext", custom);
180
+ customLogger.debug("Debug with custom level");
138
181
 
139
- // Log messages at different levels
140
- Logging.info('Application started');
141
- Logging.debug('Debug information');
142
- Logging.error('An error occurred');
143
- Logging.verbose('Detailed information', 1); // With verbosity level
182
+ // Child logger with correlation id
183
+ const traced = customLogger.for("run", { correlationId: "req-123" });
184
+ traced.info("Tracing this operation");
144
185
  ```
145
186
 
146
- ### Class-Specific Logging
147
187
 
148
- For more context-aware logging, create loggers for specific classes:
188
+ Decorators: log, debug, info, verbose, silly
189
+ Description: Instrument methods to log calls and optional benchmarks. Tests validate decorator behavior for call and completion messages.
149
190
 
150
- ```typescript
151
- import { Logging, Logger } from 'decaf-logging';
191
+ ```ts
192
+ import { log, debug, info as infoDecor, verbose as verboseDecor, silly as sillyDecor, LogLevel, Logging } from "@decaf-ts/logging";
152
193
 
153
- class UserService {
154
- private logger: Logger;
194
+ // Configure logging for demo
195
+ Logging.setConfig({ level: LogLevel.debug, style: false, timestamp: false });
155
196
 
156
- constructor() {
157
- // Create a logger for this class
158
- this.logger = Logging.for(UserService);
159
- // Or with string name: Logging.for('UserService');
197
+ class AccountService {
198
+ @log(LogLevel.info) // logs method call with args
199
+ create(name: string) {
200
+ return { id: "1", name };
160
201
  }
161
202
 
162
- getUser(id: string) {
163
- this.logger.info(`Getting user with ID: ${id}`);
164
- // ... implementation
165
- this.logger.debug('User retrieved successfully');
203
+ @debug(true) // logs call and completion time at debug level
204
+ rebuildIndex() {
205
+ // heavy work...
206
+ return true;
166
207
  }
167
208
 
168
- updateUser(id: string, data: any) {
169
- try {
170
- this.logger.info(`Updating user with ID: ${id}`);
171
- // ... implementation
172
- this.logger.debug('User updated successfully');
173
- } catch (error) {
174
- this.logger.error(error); // Logs error with stack trace
175
- }
209
+ @info() // convenience wrapper for info level
210
+ enable() {
211
+ return true;
176
212
  }
177
- }
178
- ```
179
-
180
- ### Method-Specific Logging
181
-
182
- Create child loggers for specific methods to further refine the context:
183
-
184
- ```typescript
185
- import { Logging, Logger } from 'decaf-logging';
186
213
 
187
- class DataProcessor {
188
- private logger: Logger;
189
-
190
- constructor() {
191
- this.logger = Logging.for(DataProcessor);
214
+ @verbose(1, true) // verbose with verbosity threshold and benchmark
215
+ syncAll() {
216
+ return Promise.resolve("ok");
192
217
  }
193
218
 
194
- processData(data: any[]) {
195
- // Create a method-specific logger
196
- const methodLogger = this.logger.for('processData');
197
-
198
- methodLogger.info(`Processing ${data.length} items`);
199
-
200
- // With custom configuration
201
- const verboseLogger = methodLogger.for('details', { verbose: 2 });
202
- verboseLogger.verbose('Starting detailed processing', 1);
203
-
204
- // ... implementation
219
+ @silly() // very chatty, only emitted when verbose allows
220
+ ping() {
221
+ return "pong";
205
222
  }
206
223
  }
207
- ```
208
-
209
- ### Using Decorators
210
-
211
- Decorators provide an easy way to add logging to class methods:
212
224
 
213
- ```typescript
214
- import { debug, info, log, LogLevel, verbose } from 'decaf-logging';
225
+ const svc = new AccountService();
226
+ svc.create("Alice");
227
+ svc.rebuildIndex();
228
+ svc.enable();
229
+ await svc.syncAll();
230
+ svc.ping();
231
+ ```
215
232
 
216
- class PaymentProcessor {
217
- // Basic logging with info level
218
- @info()
219
- processPayment(amount: number, userId: string) {
220
- // Method implementation
221
- return true;
222
- }
223
233
 
224
- // Debug level logging with benchmarking
225
- @debug(true)
226
- validatePayment(paymentData: any) {
227
- // Method implementation
228
- return true;
229
- }
234
+ LoggedClass: zero-boilerplate logging inside classes
235
+ Description: Extend LoggedClass to gain a protected this.log with the correct context (class name). Tests use Logging.for to build similar context.
230
236
 
231
- // Verbose logging with custom verbosity
232
- @verbose(2)
233
- recordTransaction(transactionData: any) {
234
- // Method implementation
235
- }
237
+ ```ts
238
+ import { LoggedClass } from "@your-scope/logging";
236
239
 
237
- // Custom log level with benchmarking and verbosity
238
- @log(LogLevel.error, true, 1)
239
- handleFailure(error: Error) {
240
- // Method implementation
240
+ class UserRepository extends LoggedClass {
241
+ findById(id: string) {
242
+ this.log.info(`Finding ${id}`);
243
+ return { id };
241
244
  }
242
245
  }
243
- ```
244
246
 
245
- ### Winston Integration
247
+ const repo = new UserRepository();
248
+ repo.findById("42");
249
+ ```
246
250
 
247
- To use Winston for logging:
248
251
 
249
- ```typescript
250
- import { Logging, LogLevel } from 'decaf-logging';
251
- import { WinstonFactory } from 'decaf-logging/winston';
252
- import winston from 'winston';
252
+ Winston integration: swap the logger factory
253
+ Description: Route all logging through WinstonLogger by installing WinstonFactory. This mirrors the optional adapter in src/winston.
253
254
 
254
- // Configure Winston transports
255
- const transports = [
256
- new winston.transports.Console(),
257
- new winston.transports.File({ filename: 'app.log' })
258
- ];
255
+ ```ts
256
+ import { Logging } from "@your-scope/logging";
257
+ import { WinstonFactory } from "@your-scope/logging/winston/winston";
259
258
 
260
- // Set Winston as the logger factory
259
+ // Install Winston as the logger factory
261
260
  Logging.setFactory(WinstonFactory);
262
261
 
263
- // Configure global logging
264
- Logging.setConfig({
265
- level: LogLevel.info,
266
- timestamp: true,
267
- timestampFormat: 'YYYY-MM-DD HH:mm:ss'
268
- });
269
-
270
- // Create a Winston logger for a class
271
- const logger = Logging.for('MyService');
272
- logger.info('Service initialized');
262
+ // Now any logger created will use Winston under the hood
263
+ const log = Logging.for("ApiGateway");
264
+ log.info("Gateway started");
273
265
  ```
274
266
 
275
- ## Advanced Usage
276
267
 
277
- ### Custom Styling
268
+ Theming and styling with Logging.theme and config
269
+ Description: Enable style and customize theme to colorize parts of the log (tests check styled output patterns).
278
270
 
279
- Configure custom styling for log output:
271
+ ```ts
272
+ import { Logging, LogLevel, DefaultTheme, type Theme } from "@your-scope/logging";
280
273
 
281
- ```typescript
282
- import { Logging, LogLevel, Theme } from 'decaf-logging';
274
+ // Enable styling globally
275
+ Logging.setConfig({ style: true, timestamp: true, context: false });
283
276
 
284
- // Define a custom theme
285
- const customTheme: Theme = {
286
- class: {
287
- fg: 35, // Magenta
288
- },
289
- id: {
290
- fg: 36, // Cyan
291
- },
292
- stack: {},
293
- timestamp: {
294
- fg: 90, // Gray
295
- },
296
- message: {
297
- error: {
298
- fg: 31, // Red
299
- style: ['bold'],
300
- },
301
- },
302
- method: {},
277
+ // Optionally override theme: make debug level yellow (fg:33) and error red+bold
278
+ const theme: Theme = {
279
+ ...DefaultTheme,
303
280
  logLevel: {
304
- error: {
305
- fg: 31, // Red
306
- style: ['bold'],
307
- },
308
- info: {
309
- fg: 32, // Green
310
- },
311
- verbose: {
312
- fg: 34, // Blue
313
- },
314
- debug: {
315
- fg: 33, // Yellow
316
- },
281
+ ...DefaultTheme.logLevel,
282
+ debug: { fg: 33 },
283
+ error: { fg: 31, style: ["bold"] },
317
284
  },
318
285
  };
319
286
 
320
- // Apply the custom theme
321
- Logging.setConfig({
322
- style: true,
323
- theme: customTheme
324
- });
325
- ```
326
-
327
- ### Correlation IDs
328
-
329
- Track related log messages with correlation IDs:
330
-
331
- ```typescript
332
- import { Logging } from 'decaf-logging';
333
-
334
- function processRequest(requestId: string, data: any) {
335
- // Create a logger with correlation ID
336
- const logger = Logging.for('RequestProcessor', {
337
- correlationId: requestId
338
- });
287
+ // Apply at runtime by passing to Logging.theme where needed (MiniLogger does this internally)
288
+ const styled = Logging.theme("debug", "logLevel", LogLevel.debug, theme);
339
289
 
340
- logger.info('Processing request');
341
-
342
- // All log messages from this logger will include the correlation ID
343
- processRequestData(data, logger);
344
-
345
- logger.info('Request processing completed');
346
- }
347
-
348
- function processRequestData(data: any, logger: Logger) {
349
- // Child loggers inherit the correlation ID
350
- const dataLogger = logger.for('DataProcessor');
351
- dataLogger.debug('Processing data');
352
- // ...
353
- }
290
+ // Regular logging picks up style=true and formats output accordingly
291
+ Logging.debug("This is a styled debug message");
354
292
  ```
355
293
 
356
- ### JSON Output Mode
357
294
 
358
- For machine-readable logs:
295
+ Factory basics and because(reason, id)
296
+ Description: Create ad-hoc, labeled loggers and use factory semantics.
359
297
 
360
- ```typescript
361
- import { Logging, LoggingMode } from 'decaf-logging';
298
+ ```ts
299
+ import { Logging } from "@your-scope/logging";
362
300
 
363
- // Configure for JSON output
364
- Logging.setConfig({
365
- mode: LoggingMode.JSON,
366
- timestamp: true
367
- });
368
-
369
- Logging.info('This will be output in JSON format');
301
+ // Ad-hoc logger labeled with a reason and optional id (handy for correlation)
302
+ const jobLog = Logging.because("reindex", "job-77");
303
+ jobLog.info("Starting reindex");
370
304
  ```
371
305
 
372
- ### Custom Logger Factory
373
306
 
374
- Create a custom logger implementation:
307
+ Types: Logger and LoggingConfig in your code
308
+ Description: Use the library’s types for better APIs.
375
309
 
376
- ```typescript
377
- import { Logger, LoggerFactory, Logging, MiniLogger } from 'decaf-logging';
378
-
379
- // Custom logger that adds prefix to all messages
380
- class PrefixedLogger extends MiniLogger {
381
- constructor(context: string, prefix: string, conf?: Partial<LoggingConfig>) {
382
- super(context, conf);
383
- this.prefix = prefix;
384
- }
310
+ ```ts
311
+ import type { Logger, LoggingConfig } from "@your-scope/logging";
385
312
 
386
- private prefix: string;
313
+ export interface ServiceDeps {
314
+ log: Logger;
315
+ config?: Partial<LoggingConfig>;
316
+ }
387
317
 
388
- protected override createLog(level: LogLevel, message: StringLike | Error, stack?: string): string {
389
- const msg = typeof message === 'string' ? message : message.message;
390
- const prefixedMsg = `${this.prefix}: ${msg}`;
391
- return super.createLog(level, prefixedMsg, stack);
318
+ export class PaymentService {
319
+ constructor(private deps: ServiceDeps) {}
320
+ charge(amount: number) {
321
+ this.deps.log.info(`Charging ${amount}`);
392
322
  }
393
323
  }
394
-
395
- // Custom factory function
396
- const PrefixedLoggerFactory: LoggerFactory = (
397
- context: string,
398
- conf?: Partial<LoggingConfig>,
399
- ...args: any[]
400
- ) => new PrefixedLogger(context, args[0] || '[APP]', conf);
401
-
402
- // Set the custom factory
403
- Logging.setFactory(PrefixedLoggerFactory);
404
-
405
- // Create a logger with the custom factory
406
- const logger = Logging.for('MyClass', undefined, '[CUSTOM]');
407
- logger.info('Hello world'); // Outputs: "[CUSTOM]: Hello world"
408
324
  ```
409
325
 
410
326