svger-cli 2.0.0 → 2.0.2
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/dist/cli.js +0 -0
- package/dist/core/error-handler.d.ts +63 -0
- package/dist/core/error-handler.js +224 -0
- package/dist/core/framework-templates.d.ts +17 -0
- package/{src/core/framework-templates.ts → dist/core/framework-templates.js} +100 -137
- package/dist/core/logger.d.ts +22 -0
- package/dist/core/logger.js +85 -0
- package/dist/core/performance-engine.d.ts +67 -0
- package/dist/core/performance-engine.js +251 -0
- package/dist/core/plugin-manager.d.ts +56 -0
- package/dist/core/plugin-manager.js +189 -0
- package/dist/core/style-compiler.d.ts +88 -0
- package/dist/core/style-compiler.js +466 -0
- package/dist/core/template-manager.d.ts +64 -0
- package/{src/core/template-manager.ts → dist/core/template-manager.js} +172 -255
- package/dist/index.d.ts +151 -0
- package/{src/index.ts → dist/index.js} +30 -108
- package/dist/processors/svg-processor.d.ts +67 -0
- package/dist/processors/svg-processor.js +225 -0
- package/dist/services/config.d.ts +55 -0
- package/dist/services/config.js +209 -0
- package/dist/services/file-watcher.d.ts +54 -0
- package/dist/services/file-watcher.js +180 -0
- package/dist/services/svg-service.d.ts +81 -0
- package/dist/services/svg-service.js +383 -0
- package/dist/types/index.d.ts +140 -0
- package/dist/types/index.js +4 -0
- package/dist/utils/native.d.ts +74 -0
- package/dist/utils/native.js +305 -0
- package/package.json +9 -3
- package/.svgconfig.json +0 -3
- package/CODE_OF_CONDUCT.md +0 -79
- package/CONTRIBUTING.md +0 -146
- package/TESTING.md +0 -143
- package/cli-framework.test.js +0 -16
- package/cli-test-angular/Arrowbenddownleft.component.ts +0 -27
- package/cli-test-angular/Vite.component.ts +0 -27
- package/cli-test-angular/index.ts +0 -25
- package/cli-test-output/Arrowbenddownleft.vue +0 -33
- package/cli-test-output/Vite.vue +0 -33
- package/cli-test-output/index.ts +0 -25
- package/cli-test-react/Arrowbenddownleft.tsx +0 -39
- package/cli-test-react/Vite.tsx +0 -39
- package/cli-test-react/index.ts +0 -25
- package/cli-test-svelte/Arrowbenddownleft.svelte +0 -22
- package/cli-test-svelte/Vite.svelte +0 -22
- package/cli-test-svelte/index.ts +0 -25
- package/docs/ADR-SVG-INTRGRATION-METHODS-001.adr.md +0 -157
- package/docs/ADR-SVG-INTRGRATION-METHODS-002.adr.md +0 -550
- package/docs/FRAMEWORK-GUIDE.md +0 -768
- package/docs/IMPLEMENTATION-SUMMARY.md +0 -376
- package/docs/TDR-SVG-INTRGRATION-METHODS-001.tdr.md +0 -115
- package/frameworks.test.js +0 -170
- package/my-svgs/ArrowBendDownLeft.svg +0 -6
- package/my-svgs/vite.svg +0 -1
- package/src/builder.ts +0 -104
- package/src/clean.ts +0 -21
- package/src/cli.ts +0 -221
- package/src/config.ts +0 -81
- package/src/core/error-handler.ts +0 -303
- package/src/core/logger.ts +0 -104
- package/src/core/performance-engine.ts +0 -327
- package/src/core/plugin-manager.ts +0 -228
- package/src/core/style-compiler.ts +0 -605
- package/src/lock.ts +0 -74
- package/src/processors/svg-processor.ts +0 -288
- package/src/services/config.ts +0 -241
- package/src/services/file-watcher.ts +0 -218
- package/src/services/svg-service.ts +0 -468
- package/src/templates/ComponentTemplate.ts +0 -57
- package/src/types/index.ts +0 -169
- package/src/utils/native.ts +0 -352
- package/src/watch.ts +0 -88
- package/test-output-mulit/TestIcon-angular-module.component.ts +0 -26
- package/test-output-mulit/TestIcon-angular-standalone.component.ts +0 -27
- package/test-output-mulit/TestIcon-lit.ts +0 -35
- package/test-output-mulit/TestIcon-preact.tsx +0 -38
- package/test-output-mulit/TestIcon-react.tsx +0 -35
- package/test-output-mulit/TestIcon-solid.tsx +0 -27
- package/test-output-mulit/TestIcon-svelte.svelte +0 -22
- package/test-output-mulit/TestIcon-vanilla.ts +0 -37
- package/test-output-mulit/TestIcon-vue-composition.vue +0 -33
- package/test-output-mulit/TestIcon-vue-options.vue +0 -31
- package/tsconfig.json +0 -18
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import { logger } from '../core/logger.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Enhanced error handling system with detailed error tracking and recovery
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export interface SVGError {
|
|
8
|
-
code: string;
|
|
9
|
-
message: string;
|
|
10
|
-
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
11
|
-
context?: Record<string, any>;
|
|
12
|
-
timestamp: number;
|
|
13
|
-
stack?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ErrorRecoveryStrategy {
|
|
17
|
-
canRecover(error: SVGError): boolean;
|
|
18
|
-
recover(error: SVGError, context?: any): Promise<any>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class SVGErrorHandler {
|
|
22
|
-
private static instance: SVGErrorHandler;
|
|
23
|
-
private errorHistory: SVGError[] = [];
|
|
24
|
-
private recoveryStrategies: Map<string, ErrorRecoveryStrategy> = new Map();
|
|
25
|
-
private readonly maxHistorySize = 100;
|
|
26
|
-
|
|
27
|
-
private constructor() {
|
|
28
|
-
this.setupDefaultStrategies();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public static getInstance(): SVGErrorHandler {
|
|
32
|
-
if (!SVGErrorHandler.instance) {
|
|
33
|
-
SVGErrorHandler.instance = new SVGErrorHandler();
|
|
34
|
-
}
|
|
35
|
-
return SVGErrorHandler.instance;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Handle an error with context and attempted recovery
|
|
40
|
-
*/
|
|
41
|
-
public async handleError(
|
|
42
|
-
error: Error | SVGError,
|
|
43
|
-
context?: Record<string, any>
|
|
44
|
-
): Promise<{ recovered: boolean; result?: any }> {
|
|
45
|
-
const svgError = this.normalizeError(error, context);
|
|
46
|
-
|
|
47
|
-
// Log error based on severity
|
|
48
|
-
this.logError(svgError);
|
|
49
|
-
|
|
50
|
-
// Add to history
|
|
51
|
-
this.addToHistory(svgError);
|
|
52
|
-
|
|
53
|
-
// Attempt recovery
|
|
54
|
-
const recoveryResult = await this.attemptRecovery(svgError, context);
|
|
55
|
-
|
|
56
|
-
return recoveryResult;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Register a custom error recovery strategy
|
|
61
|
-
*/
|
|
62
|
-
public registerRecoveryStrategy(errorCode: string, strategy: ErrorRecoveryStrategy): void {
|
|
63
|
-
this.recoveryStrategies.set(errorCode, strategy);
|
|
64
|
-
logger.debug(`Recovery strategy registered for error code: ${errorCode}`);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Get error statistics
|
|
69
|
-
*/
|
|
70
|
-
public getErrorStats(): {
|
|
71
|
-
total: number;
|
|
72
|
-
bySeverity: Record<string, number>;
|
|
73
|
-
byCode: Record<string, number>;
|
|
74
|
-
recentErrors: SVGError[];
|
|
75
|
-
} {
|
|
76
|
-
const bySeverity: Record<string, number> = {};
|
|
77
|
-
const byCode: Record<string, number> = {};
|
|
78
|
-
|
|
79
|
-
this.errorHistory.forEach(error => {
|
|
80
|
-
bySeverity[error.severity] = (bySeverity[error.severity] || 0) + 1;
|
|
81
|
-
byCode[error.code] = (byCode[error.code] || 0) + 1;
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
total: this.errorHistory.length,
|
|
86
|
-
bySeverity,
|
|
87
|
-
byCode,
|
|
88
|
-
recentErrors: this.errorHistory.slice(-10)
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Clear error history
|
|
94
|
-
*/
|
|
95
|
-
public clearHistory(): void {
|
|
96
|
-
this.errorHistory = [];
|
|
97
|
-
logger.debug('Error history cleared');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Private methods
|
|
101
|
-
|
|
102
|
-
private normalizeError(error: Error | SVGError, context?: Record<string, any>): SVGError {
|
|
103
|
-
if ('code' in error && 'severity' in error) {
|
|
104
|
-
return error as SVGError;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Convert regular Error to SVGError
|
|
108
|
-
const regularError = error as Error;
|
|
109
|
-
return {
|
|
110
|
-
code: this.categorizeError(regularError),
|
|
111
|
-
message: regularError.message,
|
|
112
|
-
severity: this.determineSeverity(regularError),
|
|
113
|
-
context: context || {},
|
|
114
|
-
timestamp: Date.now(),
|
|
115
|
-
stack: regularError.stack
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
private categorizeError(error: Error): string {
|
|
120
|
-
const message = error.message.toLowerCase();
|
|
121
|
-
|
|
122
|
-
if (message.includes('file not found') || message.includes('enoent')) {
|
|
123
|
-
return 'FILE_NOT_FOUND';
|
|
124
|
-
}
|
|
125
|
-
if (message.includes('permission') || message.includes('eacces')) {
|
|
126
|
-
return 'PERMISSION_DENIED';
|
|
127
|
-
}
|
|
128
|
-
if (message.includes('parse') || message.includes('syntax')) {
|
|
129
|
-
return 'PARSE_ERROR';
|
|
130
|
-
}
|
|
131
|
-
if (message.includes('timeout')) {
|
|
132
|
-
return 'TIMEOUT_ERROR';
|
|
133
|
-
}
|
|
134
|
-
if (message.includes('network') || message.includes('connection')) {
|
|
135
|
-
return 'NETWORK_ERROR';
|
|
136
|
-
}
|
|
137
|
-
if (message.includes('svg') && message.includes('invalid')) {
|
|
138
|
-
return 'INVALID_SVG';
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return 'UNKNOWN_ERROR';
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private determineSeverity(error: Error): SVGError['severity'] {
|
|
145
|
-
const message = error.message.toLowerCase();
|
|
146
|
-
|
|
147
|
-
if (message.includes('critical') || message.includes('fatal')) {
|
|
148
|
-
return 'critical';
|
|
149
|
-
}
|
|
150
|
-
if (message.includes('file not found') || message.includes('permission')) {
|
|
151
|
-
return 'high';
|
|
152
|
-
}
|
|
153
|
-
if (message.includes('parse') || message.includes('invalid')) {
|
|
154
|
-
return 'medium';
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return 'low';
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private logError(error: SVGError): void {
|
|
161
|
-
const logMessage = `[${error.code}] ${error.message}`;
|
|
162
|
-
|
|
163
|
-
switch (error.severity) {
|
|
164
|
-
case 'critical':
|
|
165
|
-
logger.error('CRITICAL:', logMessage, error.context);
|
|
166
|
-
break;
|
|
167
|
-
case 'high':
|
|
168
|
-
logger.error('HIGH:', logMessage, error.context);
|
|
169
|
-
break;
|
|
170
|
-
case 'medium':
|
|
171
|
-
logger.warn('MEDIUM:', logMessage, error.context);
|
|
172
|
-
break;
|
|
173
|
-
case 'low':
|
|
174
|
-
logger.info('LOW:', logMessage, error.context);
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
private addToHistory(error: SVGError): void {
|
|
180
|
-
this.errorHistory.push(error);
|
|
181
|
-
|
|
182
|
-
// Maintain history size limit
|
|
183
|
-
if (this.errorHistory.length > this.maxHistorySize) {
|
|
184
|
-
this.errorHistory = this.errorHistory.slice(-this.maxHistorySize);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private async attemptRecovery(
|
|
189
|
-
error: SVGError,
|
|
190
|
-
context?: any
|
|
191
|
-
): Promise<{ recovered: boolean; result?: any }> {
|
|
192
|
-
const strategy = this.recoveryStrategies.get(error.code);
|
|
193
|
-
|
|
194
|
-
if (!strategy) {
|
|
195
|
-
logger.debug(`No recovery strategy found for error code: ${error.code}`);
|
|
196
|
-
return { recovered: false };
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
if (!strategy.canRecover(error)) {
|
|
201
|
-
logger.debug(`Recovery strategy declined to handle error: ${error.code}`);
|
|
202
|
-
return { recovered: false };
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
logger.info(`Attempting recovery for error: ${error.code}`);
|
|
206
|
-
const result = await strategy.recover(error, context);
|
|
207
|
-
|
|
208
|
-
logger.success(`Successfully recovered from error: ${error.code}`);
|
|
209
|
-
return { recovered: true, result };
|
|
210
|
-
|
|
211
|
-
} catch (recoveryError) {
|
|
212
|
-
logger.error(`Recovery failed for error ${error.code}:`, recoveryError);
|
|
213
|
-
return { recovered: false };
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
private setupDefaultStrategies(): void {
|
|
218
|
-
// File not found recovery
|
|
219
|
-
this.registerRecoveryStrategy('FILE_NOT_FOUND', {
|
|
220
|
-
canRecover: (error) => error.context?.filePath && error.context?.canSkip === true,
|
|
221
|
-
recover: async (error, context) => {
|
|
222
|
-
logger.warn(`Skipping missing file: ${error.context?.filePath}`);
|
|
223
|
-
return { skipped: true, filePath: error.context?.filePath };
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// Invalid SVG recovery
|
|
228
|
-
this.registerRecoveryStrategy('INVALID_SVG', {
|
|
229
|
-
canRecover: (error) => error.context?.svgContent,
|
|
230
|
-
recover: async (error, context) => {
|
|
231
|
-
logger.info('Attempting to clean invalid SVG content');
|
|
232
|
-
|
|
233
|
-
// Basic SVG cleanup
|
|
234
|
-
let cleaned = error.context?.svgContent || '';
|
|
235
|
-
|
|
236
|
-
// Remove potentially problematic content
|
|
237
|
-
cleaned = cleaned
|
|
238
|
-
.replace(/<script[\s\S]*?<\/script>/gi, '') // Remove scripts
|
|
239
|
-
.replace(/<style[\s\S]*?<\/style>/gi, '') // Remove styles
|
|
240
|
-
.replace(/on\w+="[^"]*"/gi, '') // Remove event handlers
|
|
241
|
-
.replace(/javascript:[^"']*/gi, ''); // Remove javascript: URLs
|
|
242
|
-
|
|
243
|
-
return { cleanedContent: cleaned };
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// Permission denied recovery
|
|
248
|
-
this.registerRecoveryStrategy('PERMISSION_DENIED', {
|
|
249
|
-
canRecover: (error) => error.context?.alternative,
|
|
250
|
-
recover: async (error, context) => {
|
|
251
|
-
logger.warn(`Using alternative path due to permission issue: ${error.context?.alternative}`);
|
|
252
|
-
return { alternativePath: error.context?.alternative };
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
logger.debug('Default error recovery strategies loaded');
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Export singleton instance and utilities
|
|
261
|
-
export const errorHandler = SVGErrorHandler.getInstance();
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Utility function to wrap async operations with error handling
|
|
265
|
-
*/
|
|
266
|
-
export async function withErrorHandling<T>(
|
|
267
|
-
operation: () => Promise<T>,
|
|
268
|
-
context?: Record<string, any>
|
|
269
|
-
): Promise<T | null> {
|
|
270
|
-
try {
|
|
271
|
-
return await operation();
|
|
272
|
-
} catch (error) {
|
|
273
|
-
const result = await errorHandler.handleError(error as Error, context);
|
|
274
|
-
|
|
275
|
-
if (result.recovered) {
|
|
276
|
-
return result.result as T;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Re-throw if not recovered and severity is high
|
|
280
|
-
const svgError = error as any;
|
|
281
|
-
if (svgError.severity === 'high' || svgError.severity === 'critical') {
|
|
282
|
-
throw error;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Decorator for automatic error handling
|
|
291
|
-
*/
|
|
292
|
-
export function handleErrors(context?: Record<string, any>) {
|
|
293
|
-
return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
|
|
294
|
-
const method = descriptor.value;
|
|
295
|
-
|
|
296
|
-
descriptor.value = async function (...args: any[]) {
|
|
297
|
-
return withErrorHandling(
|
|
298
|
-
() => method.apply(this, args),
|
|
299
|
-
{ method: propertyName, ...context }
|
|
300
|
-
);
|
|
301
|
-
};
|
|
302
|
-
};
|
|
303
|
-
}
|
package/src/core/logger.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { Logger, LogLevel } from '../types/index.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Professional logging service with configurable levels and formatted output
|
|
5
|
-
*/
|
|
6
|
-
export class LoggerService implements Logger {
|
|
7
|
-
private static instance: LoggerService;
|
|
8
|
-
private logLevel: LogLevel = 'info';
|
|
9
|
-
private enableColors: boolean = true;
|
|
10
|
-
|
|
11
|
-
private constructor() {}
|
|
12
|
-
|
|
13
|
-
public static getInstance(): LoggerService {
|
|
14
|
-
if (!LoggerService.instance) {
|
|
15
|
-
LoggerService.instance = new LoggerService();
|
|
16
|
-
}
|
|
17
|
-
return LoggerService.instance;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public setLogLevel(level: LogLevel): void {
|
|
21
|
-
this.logLevel = level;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
public setColors(enabled: boolean): void {
|
|
25
|
-
this.enableColors = enabled;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
private shouldLog(level: LogLevel): boolean {
|
|
29
|
-
const levels: LogLevel[] = ['debug', 'info', 'warn', 'error'];
|
|
30
|
-
const currentIndex = levels.indexOf(this.logLevel);
|
|
31
|
-
const messageIndex = levels.indexOf(level);
|
|
32
|
-
return messageIndex >= currentIndex;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
private formatMessage(level: LogLevel, message: string): string {
|
|
36
|
-
const timestamp = new Date().toISOString();
|
|
37
|
-
const prefix = this.getPrefix(level);
|
|
38
|
-
return `${timestamp} ${prefix} ${message}`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private getPrefix(level: LogLevel): string {
|
|
42
|
-
if (!this.enableColors) {
|
|
43
|
-
return `[${level.toUpperCase()}]`;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const colors = {
|
|
47
|
-
debug: '\x1b[36m', // Cyan
|
|
48
|
-
info: '\x1b[34m', // Blue
|
|
49
|
-
warn: '\x1b[33m', // Yellow
|
|
50
|
-
error: '\x1b[31m', // Red
|
|
51
|
-
success: '\x1b[32m', // Green
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const reset = '\x1b[0m';
|
|
55
|
-
const color = colors[level as keyof typeof colors] || colors.info;
|
|
56
|
-
|
|
57
|
-
const icons = {
|
|
58
|
-
debug: '🔍',
|
|
59
|
-
info: 'ℹ️',
|
|
60
|
-
warn: '⚠️',
|
|
61
|
-
error: '❌',
|
|
62
|
-
success: '✅',
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const icon = icons[level as keyof typeof icons] || icons.info;
|
|
66
|
-
return `${color}${icon} [${level.toUpperCase()}]${reset}`;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public debug(message: string, ...args: any[]): void {
|
|
70
|
-
if (this.shouldLog('debug')) {
|
|
71
|
-
console.debug(this.formatMessage('debug', message), ...args);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public info(message: string, ...args: any[]): void {
|
|
76
|
-
if (this.shouldLog('info')) {
|
|
77
|
-
console.info(this.formatMessage('info', message), ...args);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public warn(message: string, ...args: any[]): void {
|
|
82
|
-
if (this.shouldLog('warn')) {
|
|
83
|
-
console.warn(this.formatMessage('warn', message), ...args);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public error(message: string, ...args: any[]): void {
|
|
88
|
-
if (this.shouldLog('error')) {
|
|
89
|
-
console.error(this.formatMessage('error', message), ...args);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public success(message: string, ...args: any[]): void {
|
|
94
|
-
if (this.shouldLog('info')) {
|
|
95
|
-
const timestamp = new Date().toISOString();
|
|
96
|
-
const prefix = this.getPrefix('info');
|
|
97
|
-
const successPrefix = this.enableColors ? '✅ [SUCCESS]' : '[SUCCESS]';
|
|
98
|
-
console.log(`${timestamp} ${successPrefix} ${message}`, ...args);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Export singleton instance
|
|
104
|
-
export const logger = LoggerService.getInstance();
|