@adaas/a-utils 0.1.15 → 0.1.16

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.
@@ -1,197 +1,436 @@
1
1
  import { A_Component, A_Error, A_Inject, A_Scope } from "@adaas/a-concept";
2
2
  import { A_Config } from "../A-Config/A-Config.context";
3
-
4
-
5
-
3
+ import { A_LoggerEnvVariablesType } from "./A-Logger.env";
4
+ import { A_LoggerLevel } from "./A-Logger.types";
5
+ import {
6
+ A_LOGGER_DEFAULT_SCOPE_LENGTH,
7
+ A_LOGGER_COLORS,
8
+ A_LOGGER_ANSI,
9
+ A_LOGGER_TIME_FORMAT,
10
+ A_LOGGER_FORMAT,
11
+ A_LOGGER_ENV_KEYS
12
+ } from "./A-Logger.constants";
13
+
14
+ /**
15
+ * A_Logger - Advanced Logging Component with Scope-based Output Formatting
16
+ *
17
+ * This component provides comprehensive logging capabilities with:
18
+ * - Color-coded console output for different log levels
19
+ * - Scope-based message formatting with consistent alignment
20
+ * - Support for multiple data types (objects, errors, strings)
21
+ * - Configurable log levels for filtering output
22
+ * - Special handling for A_Error and native Error objects
23
+ * - Timestamp inclusion for better debugging
24
+ *
25
+ * Key Features:
26
+ * - **Scope Integration**: Uses A_Scope for consistent message prefixing
27
+ * - **Color Support**: Terminal color codes for visual distinction
28
+ * - **Object Formatting**: Pretty-prints JSON objects with proper indentation
29
+ * - **Error Handling**: Special formatting for A_Error and Error objects
30
+ * - **Log Level Filtering**: Configurable filtering based on severity
31
+ * - **Multi-line Support**: Proper alignment for multi-line messages
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // Basic usage with dependency injection
36
+ * class MyService {
37
+ * constructor(@A_Inject(A_Logger) private logger: A_Logger) {}
38
+ *
39
+ * doSomething() {
40
+ * this.logger.log('Processing started');
41
+ * this.logger.log('blue', 'Custom color message');
42
+ * this.logger.warning('Something might be wrong');
43
+ * this.logger.error(new Error('Something failed'));
44
+ * }
45
+ * }
46
+ *
47
+ * // Advanced usage with objects
48
+ * logger.log('green', 'User data:', { id: 1, name: 'John' });
49
+ * logger.error(new A_Error('VALIDATION_FAILED', 'Invalid input data'));
50
+ * ```
51
+ */
6
52
  export class A_Logger extends A_Component {
7
53
 
8
- protected config?: A_Config<any>
9
-
54
+ // =============================================
55
+ // Configuration and Constants
56
+ // =============================================
57
+
58
+ /**
59
+ * Terminal color codes for different log levels and custom styling
60
+ * These codes work with ANSI escape sequences for colored terminal output
61
+ */
62
+ readonly COLORS;
63
+
64
+ /**
65
+ * Standard scope length for consistent formatting
66
+ * This ensures all log messages align properly regardless of scope name length
67
+ */
68
+ private readonly STANDARD_SCOPE_LENGTH;
69
+
70
+ // =============================================
71
+ // Constructor and Initialization
72
+ // =============================================
73
+
74
+ /**
75
+ * Initialize A_Logger with dependency injection
76
+ *
77
+ * @param scope - The current scope context for message prefixing
78
+ * @param config - Optional configuration for log level filtering
79
+ */
10
80
  constructor(
11
81
  @A_Inject(A_Scope) protected scope: A_Scope,
82
+ @A_Inject(A_Config) protected config?: A_Config<A_LoggerEnvVariablesType>,
12
83
  ) {
13
84
  super();
85
+ this.COLORS = A_LOGGER_COLORS;
86
+ this.STANDARD_SCOPE_LENGTH = config?.get('A_LOGGER_DEFAULT_SCOPE_LENGTH') || A_LOGGER_DEFAULT_SCOPE_LENGTH;
87
+ }
14
88
 
15
- this.config = this.scope.has(A_Config)
16
- ? this.scope.resolve<A_Config<any>>(A_Config)
17
- : undefined;
89
+ // =============================================
90
+ // Scope and Formatting Utilities
91
+ // =============================================
92
+
93
+ /**
94
+ * Get the formatted scope length for consistent message alignment
95
+ * Uses a standard length to ensure all messages align properly regardless of scope name
96
+ *
97
+ * @returns The scope length to use for padding calculations
98
+ */
99
+ get scopeLength(): number {
100
+ return Math.max(this.scope.name.length, this.STANDARD_SCOPE_LENGTH);
18
101
  }
19
102
 
20
- readonly colors = {
21
- green: '32',
22
- blue: '34',
23
- red: '31',
24
- yellow: '33',
25
- gray: '90',
26
- magenta: '35',
27
- cyan: '36',
28
- white: '37',
29
- pink: '95',
30
- } as const
31
-
32
-
33
- get scopeLength() {
34
- return this.scope.name.length;
103
+ /**
104
+ * Get the formatted scope name with proper padding
105
+ * Ensures consistent width for all scope names in log output
106
+ *
107
+ * @returns Padded scope name for consistent formatting
108
+ */
109
+ get formattedScope(): string {
110
+ return this.scope.name.padEnd(this.STANDARD_SCOPE_LENGTH);
35
111
  }
36
112
 
37
113
 
114
+ // =============================================
115
+ // Message Compilation and Formatting
116
+ // =============================================
117
+
118
+ /**
119
+ * Compile log arguments into formatted console output with colors and proper alignment
120
+ *
121
+ * This method handles the core formatting logic for all log messages:
122
+ * - Applies terminal color codes for visual distinction
123
+ * - Formats scope names with consistent padding
124
+ * - Handles different data types appropriately
125
+ * - Maintains proper indentation for multi-line content
126
+ *
127
+ * @param color - The color key to apply to the message
128
+ * @param args - Variable arguments to format and display
129
+ * @returns Array of formatted strings ready for console output
130
+ */
38
131
  compile(
39
- color: keyof typeof this.colors,
132
+ color: keyof typeof this.COLORS,
40
133
  ...args: any[]
41
134
  ): Array<string> {
135
+ const timeString = this.getTime();
136
+ const scopePadding = ' '.repeat(this.scopeLength + 3);
137
+ const isMultiArg = args.length > 1;
42
138
 
43
139
  return [
44
- `\x1b[${this.colors[color]}m[${this.scope.name}] |${this.getTime()}|`,
45
- (
46
- args.length > 1
47
- ? '\n' + `${' '.repeat(this.scopeLength + 3)}|-------------------------------`
48
- : ''
140
+ // Header with color, scope, and timestamp
141
+ `${A_LOGGER_ANSI.PREFIX}${this.COLORS[color]}${A_LOGGER_ANSI.SUFFIX}${A_LOGGER_FORMAT.SCOPE_OPEN}${this.formattedScope}${A_LOGGER_FORMAT.SCOPE_CLOSE} ${A_LOGGER_FORMAT.TIME_OPEN}${timeString}${A_LOGGER_FORMAT.TIME_CLOSE}`,
142
+
143
+ // Top separator for multi-argument messages
144
+ isMultiArg ? '\n' + `${scopePadding}${A_LOGGER_FORMAT.TIME_OPEN}${A_LOGGER_FORMAT.SEPARATOR}` : '',
49
145
 
50
- ),
51
- ...(args
52
- .map((arg, i) => {
146
+ // Process each argument with appropriate formatting
147
+ ...args.map((arg, i) => {
148
+ const shouldAddNewline = i > 0 || isMultiArg;
53
149
 
150
+ switch (true) {
151
+ case arg instanceof A_Error:
152
+ return this.compile_A_Error(arg);
54
153
 
55
- switch (true) {
56
- case arg instanceof A_Error:
57
- return this.compile_A_Error(arg);
154
+ case arg instanceof Error:
155
+ return this.compile_Error(arg);
58
156
 
59
- case arg instanceof Error:
60
- return this.compile_Error(arg);
157
+ case typeof arg === 'object' && arg !== null:
158
+ return this.formatObject(arg, shouldAddNewline, scopePadding);
61
159
 
62
- case typeof arg === 'object':
63
- return JSON.stringify(arg, null, 2)
64
- .replace(/\n/g, '\n' + `${' '.repeat(this.scopeLength + 3)}| `);
160
+ default:
161
+ return this.formatString(String(arg), shouldAddNewline, scopePadding);
162
+ }
163
+ }),
164
+
165
+ // Bottom separator and color reset
166
+ isMultiArg
167
+ ? '\n' + `${scopePadding}${A_LOGGER_FORMAT.TIME_OPEN}${A_LOGGER_FORMAT.SEPARATOR}${A_LOGGER_ANSI.RESET}`
168
+ : A_LOGGER_ANSI.RESET
169
+ ];
170
+ }
65
171
 
66
- default:
67
- return String(
68
- ((i > 0 || args.length > 1) ? '\n' : '')
69
- + arg)
70
- .replace(/\n/g, '\n' + `${' '.repeat(this.scopeLength + 3)}| `)
172
+ /**
173
+ * Format an object for display with proper JSON indentation
174
+ *
175
+ * @param obj - The object to format
176
+ * @param shouldAddNewline - Whether to add a newline prefix
177
+ * @param scopePadding - The padding string for consistent alignment
178
+ * @returns Formatted object string
179
+ */
180
+ private formatObject(obj: any, shouldAddNewline: boolean, scopePadding: string): string {
181
+ let jsonString: string;
182
+ try {
183
+ jsonString = JSON.stringify(obj, null, 2);
184
+ } catch (error) {
185
+ // Handle circular references
186
+ const seen = new WeakSet();
187
+ jsonString = JSON.stringify(obj, (key, value) => {
188
+ if (typeof value === 'object' && value !== null) {
189
+ if (seen.has(value)) {
190
+ return '[Circular Reference]';
71
191
  }
72
- })),
73
- (
74
- args.length > 1
75
- ? '\n' + `${' '.repeat(this.scopeLength + 3)}|-------------------------------\x1b[0m`
76
- : '\x1b[0m'
77
- )
78
- ]
192
+ seen.add(value);
193
+ }
194
+ return value;
195
+ }, 2);
196
+ }
197
+ const formatted = jsonString.replace(/\n/g, '\n' + `${scopePadding}${A_LOGGER_FORMAT.PIPE}`);
198
+ return shouldAddNewline ? '\n' + `${scopePadding}${A_LOGGER_FORMAT.PIPE}` + formatted : formatted;
79
199
  }
80
200
 
81
- protected get allowedToLog() {
82
- return this.config
83
- ? this.config.get('CONFIG_VERBOSE') !== undefined
84
- && this.config.get('CONFIG_VERBOSE') !== 'false'
85
- && this.config.get('CONFIG_VERBOSE') !== false
86
- : true;
201
+ /**
202
+ * Format a string for display with proper indentation
203
+ *
204
+ * @param str - The string to format
205
+ * @param shouldAddNewline - Whether to add a newline prefix
206
+ * @param scopePadding - The padding string for consistent alignment
207
+ * @returns Formatted string
208
+ */
209
+ private formatString(str: string, shouldAddNewline: boolean, scopePadding: string): string {
210
+ const prefix = shouldAddNewline ? '\n' : '';
211
+ return (prefix + str).replace(/\n/g, '\n' + `${scopePadding}${A_LOGGER_FORMAT.PIPE}`);
87
212
  }
88
213
 
214
+ // =============================================
215
+ // Log Level Management
216
+ // =============================================
217
+
218
+ /**
219
+ * Determine if a log message should be output based on configured log level
220
+ *
221
+ * Log level hierarchy:
222
+ * - debug: Shows all messages
223
+ * - info: Shows info, warning, and error messages
224
+ * - warn: Shows warning and error messages only
225
+ * - error: Shows error messages only
226
+ * - all: Shows all messages (alias for debug)
227
+ *
228
+ * @param logMethod - The type of log method being called
229
+ * @returns True if the message should be logged, false otherwise
230
+ */
231
+ protected shouldLog(logMethod: 'log' | 'warning' | 'error'): boolean {
232
+ const shouldLog: A_LoggerLevel = this.config?.get(A_LOGGER_ENV_KEYS.LOG_LEVEL) || 'all';
233
+
234
+ switch (shouldLog) {
235
+ case 'debug':
236
+ return true;
237
+ case 'info':
238
+ return logMethod === 'log' || logMethod === 'warning' || logMethod === 'error';
239
+ case 'warn':
240
+ return logMethod === 'warning' || logMethod === 'error';
241
+ case 'error':
242
+ return logMethod === 'error';
243
+ case 'all':
244
+ return true;
245
+ default:
246
+ return false;
247
+ }
248
+ }
89
249
 
90
- log(
91
- color: keyof typeof this.colors,
92
- ...args: any[]
93
- )
94
- log(
95
- ...args: any[]
96
- )
97
- log(
98
- param1: any,
99
- ...args: any[]
100
- ) {
101
- if (!this.allowedToLog)
102
- return;
103
250
 
104
- if (typeof param1 === 'string' && this.colors[param1]) {
105
- console.log(...this.compile(param1 as keyof typeof this.colors, ...args));
106
- return;
107
- }
108
- else {
251
+ // =============================================
252
+ // Public Logging Methods
253
+ // =============================================
254
+
255
+ /**
256
+ * General purpose logging method with optional color specification
257
+ *
258
+ * Supports two usage patterns:
259
+ * 1. log(message, ...args) - Uses default blue color
260
+ * 2. log(color, message, ...args) - Uses specified color
261
+ *
262
+ * @param color - Optional color key or the first message argument
263
+ * @param args - Additional arguments to log
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * logger.log('Hello World');
268
+ * logger.log('green', 'Success message');
269
+ * logger.log('Processing user:', { id: 1, name: 'John' });
270
+ * ```
271
+ */
272
+ log(color: keyof typeof this.COLORS, ...args: any[]): void;
273
+ log(...args: any[]): void;
274
+ log(param1: any, ...args: any[]): void {
275
+ if (!this.shouldLog('log')) return;
276
+
277
+ // Check if first parameter is a valid color key
278
+ if (typeof param1 === 'string' && this.COLORS[param1 as keyof typeof this.COLORS]) {
279
+ console.log(...this.compile(param1 as keyof typeof this.COLORS, ...args));
280
+ } else {
281
+ // Use default blue color and treat param1 as first message argument
109
282
  console.log(...this.compile('blue', param1, ...args));
110
283
  }
111
284
  }
112
285
 
113
- warning(...args) {
114
- if (!this.allowedToLog)
115
- return;
116
-
286
+ /**
287
+ * Log warning messages with yellow color coding
288
+ *
289
+ * Use for non-critical issues that should be brought to attention
290
+ * but don't prevent normal operation
291
+ *
292
+ * @param args - Arguments to log as warnings
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * logger.warning('Deprecated method used');
297
+ * logger.warning('Rate limit approaching:', { current: 95, limit: 100 });
298
+ * ```
299
+ */
300
+ warning(...args: any[]): void {
301
+ if (!this.shouldLog('warning')) return;
117
302
  console.log(...this.compile('yellow', ...args));
118
303
  }
119
304
 
120
- error(...args) {
121
- if (this.config && this.config.get('CONFIG_IGNORE_ERRORS'))
122
- return;
123
-
124
- return console.log(...this.compile('red', ...args));
305
+ /**
306
+ * Log error messages with red color coding
307
+ *
308
+ * Use for critical issues, exceptions, and failures that need immediate attention
309
+ *
310
+ * @param args - Arguments to log as errors
311
+ * @returns void (for compatibility with console.log)
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * logger.error('Database connection failed');
316
+ * logger.error(new Error('Validation failed'));
317
+ * logger.error('Critical error:', error, { context: 'user-registration' });
318
+ * ```
319
+ */
320
+ error(...args: any[]): void {
321
+ if (!this.shouldLog('error')) return;
322
+ console.log(...this.compile('red', ...args));
125
323
  }
126
324
 
127
-
128
- protected log_A_Error(error: A_Error) {
325
+ // =============================================
326
+ // Specialized Error Formatting
327
+ // =============================================
328
+
329
+ /**
330
+ * Legacy method for A_Error logging (kept for backward compatibility)
331
+ *
332
+ * @deprecated Use error() method instead which handles A_Error automatically
333
+ * @param error - The A_Error instance to log
334
+ */
335
+ protected log_A_Error(error: A_Error): void {
129
336
  const time = this.getTime();
130
-
131
- console.log(`\x1b[31m[${this.scope.name}] |${time}| ERROR ${error.code}
132
- ${' '.repeat(this.scopeLength + 3)}| ${error.message}
133
- ${' '.repeat(this.scopeLength + 3)}| ${error.description}
134
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
135
- ${' '.repeat(this.scopeLength + 3)}| ${error.stack?.split('\n').map((line, index) => index === 0 ? line : `${' '.repeat(this.scopeLength + 3)}| ${line}`).join('\n') || 'No stack trace'}
136
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
337
+ const scopePadding = ' '.repeat(this.scopeLength + 3);
338
+
339
+ console.log(`\x1b[31m[${this.formattedScope}] |${time}| ERROR ${error.code}
340
+ ${scopePadding}| ${error.message}
341
+ ${scopePadding}| ${error.description}
342
+ ${scopePadding}|-------------------------------
343
+ ${scopePadding}| ${error.stack?.split('\n').map((line, index) => index === 0 ? line : `${scopePadding}| ${line}`).join('\n') || 'No stack trace'}
344
+ ${scopePadding}|-------------------------------
137
345
  \x1b[0m`
138
- + (error.originalError ? `\x1b[31m${' '.repeat(this.scopeLength + 3)}| Wrapped From ${error.originalError.message}
139
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
140
- ${' '.repeat(this.scopeLength + 3)}| ${error.originalError.stack?.split('\n').map((line, index) => index === 0 ? line : `${' '.repeat(this.scopeLength + 3)}| ${line}`).join('\n') || 'No stack trace'}
141
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
346
+ + (error.originalError ? `\x1b[31m${scopePadding}| Wrapped From ${error.originalError.message}
347
+ ${scopePadding}|-------------------------------
348
+ ${scopePadding}| ${error.originalError.stack?.split('\n').map((line, index) => index === 0 ? line : `${scopePadding}| ${line}`).join('\n') || 'No stack trace'}
349
+ ${scopePadding}|-------------------------------
142
350
  \x1b[0m`: '')
143
- + (error.link ? `\x1b[31m${' '.repeat(this.scopeLength + 3)}| Read in docs: ${error.link}
144
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
351
+ + (error.link ? `\x1b[31m${scopePadding}| Read in docs: ${error.link}
352
+ ${scopePadding}|-------------------------------
145
353
  \x1b[0m`: ''));
146
-
147
354
  }
148
355
 
356
+ /**
357
+ * Format A_Error instances for inline display within compiled messages
358
+ *
359
+ * Provides detailed formatting for A_Error objects including:
360
+ * - Error code and message
361
+ * - Description and stack trace
362
+ * - Original error information (if wrapped)
363
+ * - Documentation links (if available)
364
+ *
365
+ * @param error - The A_Error instance to format
366
+ * @returns Formatted string ready for display
367
+ */
149
368
  protected compile_A_Error(error: A_Error): string {
150
- const time = this.getTime();
369
+ const scopePadding = ' '.repeat(this.scopeLength + 3);
151
370
 
152
371
  return '\n' +
153
-
154
- `${' '.repeat(this.scopeLength + 3)}|-------------------------------` +
372
+ `${scopePadding}|-------------------------------` +
155
373
  '\n' +
156
- `${' '.repeat(this.scopeLength + 3)}| Error: | ${error.code}
157
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
158
- ${' '.repeat(this.scopeLength + 3)}|${' '.repeat(10)}| ${error.message}
159
- ${' '.repeat(this.scopeLength + 3)}|${' '.repeat(10)}| ${error.description}
160
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
161
- ${' '.repeat(this.scopeLength + 3)}| ${error.stack?.split('\n').map((line, index) => index === 0 ? line : `${' '.repeat(this.scopeLength + 3)}| ${line}`).join('\n') || 'No stack trace'}
162
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------`
374
+ `${scopePadding}| Error: | ${error.code}
375
+ ${scopePadding}|-------------------------------
376
+ ${scopePadding}|${' '.repeat(10)}| ${error.message}
377
+ ${scopePadding}|${' '.repeat(10)}| ${error.description}
378
+ ${scopePadding}|-------------------------------
379
+ ${scopePadding}| ${error.stack?.split('\n').map((line, index) => index === 0 ? line : `${scopePadding}| ${line}`).join('\n') || 'No stack trace'}
380
+ ${scopePadding}|-------------------------------`
163
381
  +
164
- (error.originalError ? `${' '.repeat(this.scopeLength + 3)}| Wrapped From ${error.originalError.message}
165
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------
166
- ${' '.repeat(this.scopeLength + 3)}| ${error.originalError.stack?.split('\n').map((line, index) => index === 0 ? line : `${' '.repeat(this.scopeLength + 3)}| ${line}`).join('\n') || 'No stack trace'}
167
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------` : '')
382
+ (error.originalError ? `${scopePadding}| Wrapped From ${error.originalError.message}
383
+ ${scopePadding}|-------------------------------
384
+ ${scopePadding}| ${error.originalError.stack?.split('\n').map((line, index) => index === 0 ? line : `${scopePadding}| ${line}`).join('\n') || 'No stack trace'}
385
+ ${scopePadding}|-------------------------------` : '')
168
386
  +
169
- (error.link ? `${' '.repeat(this.scopeLength + 3)}| Read in docs: ${error.link}
170
- ${' '.repeat(this.scopeLength + 3)}|-------------------------------` : '');
171
-
387
+ (error.link ? `${scopePadding}| Read in docs: ${error.link}
388
+ ${scopePadding}|-------------------------------` : '');
172
389
  }
173
390
 
174
-
391
+ /**
392
+ * Format standard Error instances for inline display within compiled messages
393
+ *
394
+ * Converts standard JavaScript Error objects into a readable JSON format
395
+ * with proper indentation and stack trace formatting
396
+ *
397
+ * @param error - The Error instance to format
398
+ * @returns Formatted string ready for display
399
+ */
175
400
  protected compile_Error(error: Error): string {
401
+ const scopePadding = ' '.repeat(this.scopeLength + 3);
402
+
176
403
  return JSON.stringify({
177
404
  name: error.name,
178
405
  message: error.message,
179
406
  stack: error.stack?.split('\n')
180
- .map((line, index) => index === 0 ? line : `${' '.repeat(this.scopeLength + 3)}| ${line}`)
407
+ .map((line, index) => index === 0 ? line : `${scopePadding}| ${line}`)
181
408
  .join('\n')
182
-
183
409
  }, null, 2)
184
- .replace(/\n/g, '\n' + `${' '.repeat(this.scopeLength + 3)}| `)
185
- .replace(/\\n/g, '\n')
410
+ .replace(/\n/g, '\n' + `${scopePadding}| `)
411
+ .replace(/\\n/g, '\n');
186
412
  }
187
413
 
188
-
189
-
190
- protected getTime() {
414
+ // =============================================
415
+ // Utility Methods
416
+ // =============================================
417
+
418
+ /**
419
+ * Generate timestamp string for log messages
420
+ *
421
+ * Format: MM:SS:mmm (minutes:seconds:milliseconds)
422
+ * This provides sufficient precision for debugging while remaining readable
423
+ *
424
+ * @returns Formatted timestamp string
425
+ *
426
+ * @example
427
+ * Returns: "15:42:137" for 3:42:15 PM and 137 milliseconds
428
+ */
429
+ protected getTime(): string {
191
430
  const now = new Date();
192
- const minutes = String(now.getMinutes()).padStart(2, '0');
193
- const seconds = String(now.getSeconds()).padStart(2, '0');
194
- const milliseconds = String(now.getMilliseconds()).padStart(4, '0');
195
- return `${minutes}:${seconds}:${milliseconds}`;
431
+ const minutes = String(now.getMinutes()).padStart(A_LOGGER_TIME_FORMAT.MINUTES_PAD, '0');
432
+ const seconds = String(now.getSeconds()).padStart(A_LOGGER_TIME_FORMAT.SECONDS_PAD, '0');
433
+ const milliseconds = String(now.getMilliseconds()).padStart(A_LOGGER_TIME_FORMAT.MILLISECONDS_PAD, '0');
434
+ return `${minutes}${A_LOGGER_TIME_FORMAT.SEPARATOR}${seconds}${A_LOGGER_TIME_FORMAT.SEPARATOR}${milliseconds}`;
196
435
  }
197
436
  }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * A-Logger Constants
3
+ *
4
+ * Configuration constants and default values for the A_Logger component
5
+ */
6
+
7
+ /**
8
+ * Default scope length for consistent message alignment
9
+ */
10
+ export const A_LOGGER_DEFAULT_SCOPE_LENGTH = 20;
11
+
12
+ /**
13
+ * Default log level when none is specified
14
+ */
15
+ export const A_LOGGER_DEFAULT_LEVEL = 'all';
16
+
17
+ /**
18
+ * Terminal color codes mapping
19
+ */
20
+ export const A_LOGGER_COLORS = {
21
+ green: '32', // Success, completion messages
22
+ blue: '34', // Info, general messages
23
+ red: '31', // Errors, critical issues
24
+ yellow: '33', // Warnings, caution messages
25
+ gray: '90', // Debug, less important info
26
+ magenta: '35', // Special highlighting
27
+ cyan: '36', // Headers, titles
28
+ white: '37', // Default text
29
+ pink: '95', // Custom highlighting
30
+ } as const;
31
+
32
+ /**
33
+ * ANSI escape codes
34
+ */
35
+ export const A_LOGGER_ANSI = {
36
+ RESET: '\x1b[0m',
37
+ PREFIX: '\x1b[',
38
+ SUFFIX: 'm'
39
+ } as const;
40
+
41
+ /**
42
+ * Timestamp format configuration
43
+ */
44
+ export const A_LOGGER_TIME_FORMAT = {
45
+ MINUTES_PAD: 2,
46
+ SECONDS_PAD: 2,
47
+ MILLISECONDS_PAD: 3,
48
+ SEPARATOR: ':'
49
+ } as const;
50
+
51
+ /**
52
+ * Log message structure constants
53
+ */
54
+ export const A_LOGGER_FORMAT = {
55
+ SCOPE_OPEN: '[',
56
+ SCOPE_CLOSE: ']',
57
+ TIME_OPEN: '|',
58
+ TIME_CLOSE: '|',
59
+ SEPARATOR: '-------------------------------',
60
+ INDENT_BASE: 3,
61
+ PIPE: '| '
62
+ } as const;
63
+
64
+ /**
65
+ * Environment variable keys
66
+ */
67
+ export const A_LOGGER_ENV_KEYS = {
68
+ LOG_LEVEL: 'A_LOGGER_LEVEL'
69
+ } as const;
@@ -0,0 +1,27 @@
1
+
2
+
3
+ export const A_LoggerEnvVariables = {
4
+ /**
5
+ * Sets the log level for the logger
6
+ *
7
+ * @example 'debug', 'info', 'warn', 'error'
8
+ */
9
+ A_LOGGER_LEVEL: 'A_LOGGER_LEVEL',
10
+
11
+
12
+ /**
13
+ * Sets the default scope length for log messages
14
+ *
15
+ * @example 'A_LOGGER_DEFAULT_SCOPE_LENGTH'
16
+ */
17
+ A_LOGGER_DEFAULT_SCOPE_LENGTH: 'A_LOGGER_DEFAULT_SCOPE_LENGTH',
18
+ } as const;
19
+
20
+
21
+
22
+ export const A_LoggerEnvVariablesArray = [
23
+ A_LoggerEnvVariables.A_LOGGER_LEVEL,
24
+ ] as const;
25
+
26
+
27
+ export type A_LoggerEnvVariablesType = (typeof A_LoggerEnvVariables)[keyof typeof A_LoggerEnvVariables][];
@@ -0,0 +1,3 @@
1
+
2
+
3
+ export type A_LoggerLevel = 'debug' | 'info' | 'warn' | 'error' | 'all';