@crimsonsunset/jsg-logger 1.6.0 → 1.7.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/CHANGELOG.md +174 -5
- package/README.md +84 -36
- package/config/config-manager.js +42 -11
- package/config/default-config.json +3 -0
- package/devtools/dist/panel-entry.js +11418 -0
- package/devtools/dist/panel-entry.js.map +1 -0
- package/devtools/dist/vite.svg +1 -0
- package/docs/devtools-roadmap.md +6 -3
- package/docs/next-session.md +65 -3
- package/docs/roadmap.md +174 -17
- package/examples/advanced-config.json +3 -0
- package/formatters/browser-formatter.js +1 -1
- package/formatters/cli-formatter.js +5 -4
- package/index.d.ts +192 -0
- package/index.js +203 -58
- package/package.json +33 -16
package/index.js
CHANGED
|
@@ -6,13 +6,38 @@
|
|
|
6
6
|
import pino from 'pino';
|
|
7
7
|
import {configManager} from './config/config-manager.js';
|
|
8
8
|
import {COMPONENT_SCHEME} from './config/component-schemes.js';
|
|
9
|
-
import defaultConfig from './config/default-config.json' with {
|
|
10
|
-
import {getEnvironment, isBrowser, isCLI
|
|
9
|
+
import defaultConfig from './config/default-config.json' with {type: 'json'};
|
|
10
|
+
import {forceEnvironment, getEnvironment, isBrowser, isCLI} from './utils/environment-detector.js';
|
|
11
11
|
import {createBrowserFormatter} from './formatters/browser-formatter.js';
|
|
12
12
|
import {createCLIFormatter} from './formatters/cli-formatter.js';
|
|
13
13
|
import {createServerFormatter, getServerConfig} from './formatters/server-formatter.js';
|
|
14
14
|
import {LogStore} from './stores/log-store.js';
|
|
15
15
|
|
|
16
|
+
// Check default config for devtools at module load time
|
|
17
|
+
// This allows bundlers to tree-shake if disabled
|
|
18
|
+
const defaultDevtoolsEnabled = defaultConfig.devtools?.enabled ?? false;
|
|
19
|
+
|
|
20
|
+
// Conditional static import - bundlers can eliminate if condition is false
|
|
21
|
+
// If defaultDevtoolsEnabled is false, bundler removes this entire block
|
|
22
|
+
// Use lazy initialization to avoid top-level await (which would make module async)
|
|
23
|
+
let devtoolsModule = null;
|
|
24
|
+
let devtoolsModulePromise = null;
|
|
25
|
+
if (defaultDevtoolsEnabled) {
|
|
26
|
+
console.log('[JSG-LOGGER] DevTools module pre-loading started (default config enabled)');
|
|
27
|
+
// Start loading immediately but don't await (non-blocking)
|
|
28
|
+
// Bundlers can still analyze this static import for tree-shaking
|
|
29
|
+
devtoolsModulePromise = import('./devtools/dist/panel-entry.js').then(module => {
|
|
30
|
+
devtoolsModule = module;
|
|
31
|
+
console.log('[JSG-LOGGER] DevTools module pre-loaded successfully');
|
|
32
|
+
return module;
|
|
33
|
+
}).catch(error => {
|
|
34
|
+
console.error('[JSG-LOGGER] DevTools module pre-load failed:', error);
|
|
35
|
+
return null;
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
console.log('[JSG-LOGGER] DevTools module NOT pre-loaded (default config disabled - will tree-shake)');
|
|
39
|
+
}
|
|
40
|
+
|
|
16
41
|
/**
|
|
17
42
|
* Main Logger Class
|
|
18
43
|
* Manages logger instances and provides the public API
|
|
@@ -28,6 +53,9 @@ class JSGLogger {
|
|
|
28
53
|
this.environment = null; // Will be set after config loads
|
|
29
54
|
this.initialized = false;
|
|
30
55
|
this.components = {}; // Auto-discovery getters
|
|
56
|
+
|
|
57
|
+
// Initialize component getters with safe factories that always return loggers
|
|
58
|
+
this._initializeSafeComponentGetters();
|
|
31
59
|
}
|
|
32
60
|
|
|
33
61
|
/**
|
|
@@ -36,21 +64,39 @@ class JSGLogger {
|
|
|
36
64
|
* @returns {Promise<Object>} Enhanced logger exports with controls API
|
|
37
65
|
*/
|
|
38
66
|
static async getInstance(options = {}) {
|
|
67
|
+
const hasOptions = options && Object.keys(options).length > 0;
|
|
68
|
+
|
|
39
69
|
if (!JSGLogger._instance) {
|
|
70
|
+
// First time initialization
|
|
40
71
|
JSGLogger._instance = new JSGLogger();
|
|
41
72
|
JSGLogger._enhancedLoggers = await JSGLogger._instance.init(options);
|
|
73
|
+
|
|
74
|
+
// Make runtime controls available globally in browser for debugging
|
|
75
|
+
if (isBrowser() && typeof window !== 'undefined' && JSGLogger._enhancedLoggers?.controls) {
|
|
76
|
+
window.JSG_Logger = JSGLogger._enhancedLoggers.controls;
|
|
77
|
+
}
|
|
78
|
+
} else if (hasOptions) {
|
|
79
|
+
// Instance exists but new options provided - reinitialize
|
|
80
|
+
JSGLogger._enhancedLoggers = await JSGLogger._instance.init(options);
|
|
81
|
+
|
|
82
|
+
// Make runtime controls available globally in browser for debugging
|
|
83
|
+
// (same as getInstanceSync behavior)
|
|
84
|
+
if (isBrowser() && typeof window !== 'undefined' && JSGLogger._enhancedLoggers?.controls) {
|
|
85
|
+
window.JSG_Logger = JSGLogger._enhancedLoggers.controls;
|
|
86
|
+
}
|
|
42
87
|
}
|
|
88
|
+
|
|
43
89
|
return JSGLogger._enhancedLoggers;
|
|
44
90
|
}
|
|
45
91
|
|
|
46
92
|
/**
|
|
47
93
|
* Get singleton instance synchronously (for environments without async support)
|
|
48
|
-
* @param {Object} options - Initialization options (only used on first call)
|
|
94
|
+
* @param {Object} options - Initialization options (only used on first call)
|
|
49
95
|
* @returns {Object} Enhanced logger exports with controls API
|
|
50
96
|
*/
|
|
51
97
|
static getInstanceSync(options = {}) {
|
|
52
98
|
const hasOptions = options && Object.keys(options).length > 0;
|
|
53
|
-
|
|
99
|
+
|
|
54
100
|
if (!JSGLogger._instance) {
|
|
55
101
|
// First time initialization
|
|
56
102
|
JSGLogger._instance = new JSGLogger();
|
|
@@ -59,7 +105,7 @@ class JSGLogger {
|
|
|
59
105
|
// Instance exists but new options provided - reinitialize
|
|
60
106
|
JSGLogger._enhancedLoggers = JSGLogger._instance.initSync(options);
|
|
61
107
|
}
|
|
62
|
-
|
|
108
|
+
|
|
63
109
|
return JSGLogger._enhancedLoggers;
|
|
64
110
|
}
|
|
65
111
|
|
|
@@ -70,6 +116,8 @@ class JSGLogger {
|
|
|
70
116
|
*/
|
|
71
117
|
async init(options = {}) {
|
|
72
118
|
try {
|
|
119
|
+
console.log('[JSG-LOGGER] Initializing logger...', options.configPath ? `configPath: ${options.configPath}` : options.config ? 'inline config provided' : 'using defaults');
|
|
120
|
+
|
|
73
121
|
// Load configuration FIRST (before environment detection)
|
|
74
122
|
if (options.configPath || options.config) {
|
|
75
123
|
await configManager.loadConfig(options.configPath || options.config);
|
|
@@ -132,8 +180,14 @@ class JSGLogger {
|
|
|
132
180
|
try {
|
|
133
181
|
// Load inline config if provided (sync loading for objects)
|
|
134
182
|
if (options && Object.keys(options).length > 0) {
|
|
135
|
-
//
|
|
136
|
-
|
|
183
|
+
// Reset to default config for clean reinitialization
|
|
184
|
+
// This ensures each reinit starts from a known state
|
|
185
|
+
configManager.config = {...defaultConfig};
|
|
186
|
+
|
|
187
|
+
// Normalize the inline config first
|
|
188
|
+
const normalizedOptions = configManager._normalizeConfigStructure(options);
|
|
189
|
+
// Merge inline config with default config
|
|
190
|
+
configManager.config = configManager.mergeConfigs(configManager.config, normalizedOptions);
|
|
137
191
|
}
|
|
138
192
|
|
|
139
193
|
// Apply forceEnvironment if specified in config
|
|
@@ -144,6 +198,10 @@ class JSGLogger {
|
|
|
144
198
|
// NOW determine environment (after config is loaded and forceEnvironment is applied)
|
|
145
199
|
this.environment = getEnvironment();
|
|
146
200
|
|
|
201
|
+
// Clear existing loggers for clean reinitialization
|
|
202
|
+
this.loggers = {};
|
|
203
|
+
this.components = {};
|
|
204
|
+
|
|
147
205
|
// Create loggers for all available components using default config
|
|
148
206
|
const components = configManager.getAvailableComponents();
|
|
149
207
|
|
|
@@ -287,7 +345,7 @@ class JSGLogger {
|
|
|
287
345
|
addUtilityMethods() {
|
|
288
346
|
// Store reference to original createLogger before overriding
|
|
289
347
|
const originalCreateLogger = this.createLogger.bind(this);
|
|
290
|
-
|
|
348
|
+
|
|
291
349
|
// Create logger on demand (reuses existing loggers)
|
|
292
350
|
this.createLogger = (componentName) => {
|
|
293
351
|
if (!this.loggers[componentName]) {
|
|
@@ -295,7 +353,7 @@ class JSGLogger {
|
|
|
295
353
|
}
|
|
296
354
|
return this.loggers[componentName];
|
|
297
355
|
};
|
|
298
|
-
|
|
356
|
+
|
|
299
357
|
// Store the original for internal use
|
|
300
358
|
this._createLoggerOriginal = originalCreateLogger;
|
|
301
359
|
}
|
|
@@ -412,6 +470,8 @@ class JSGLogger {
|
|
|
412
470
|
|
|
413
471
|
// Statistics and debugging
|
|
414
472
|
getStats: () => this.logStore.getStats(),
|
|
473
|
+
subscribe: (callback) => this.logStore.subscribe(callback),
|
|
474
|
+
clearLogs: () => this.logStore.clear(),
|
|
415
475
|
getConfigSummary: () => configManager.getSummary(),
|
|
416
476
|
|
|
417
477
|
// Advanced configuration
|
|
@@ -428,42 +488,64 @@ class JSGLogger {
|
|
|
428
488
|
|
|
429
489
|
// DevTools panel controls
|
|
430
490
|
enableDevPanel: async () => {
|
|
491
|
+
// Early config check - uses consumer's runtime config
|
|
492
|
+
const runtimeDevtoolsEnabled = configManager.config.devtools?.enabled ?? false;
|
|
493
|
+
|
|
494
|
+
console.log(`[JSG-LOGGER] enableDevPanel() called - runtime config: ${runtimeDevtoolsEnabled ? 'ENABLED' : 'DISABLED'}`);
|
|
495
|
+
|
|
496
|
+
if (!runtimeDevtoolsEnabled) {
|
|
497
|
+
console.warn('[JSG-LOGGER] DevTools disabled via config. Set devtools.enabled: true to enable.');
|
|
498
|
+
return null;
|
|
499
|
+
}
|
|
500
|
+
|
|
431
501
|
if (typeof window === 'undefined') {
|
|
432
502
|
console.warn('[JSG-LOGGER] DevTools panel only available in browser environments');
|
|
433
503
|
return null;
|
|
434
504
|
}
|
|
435
505
|
|
|
436
506
|
try {
|
|
437
|
-
//
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
//
|
|
446
|
-
|
|
447
|
-
console.log('
|
|
448
|
-
|
|
449
|
-
console.log('✅ Source import successful:', module);
|
|
450
|
-
} catch (sourceError) {
|
|
451
|
-
console.error('❌ Source import failed, falling back to bundle:', sourceError);
|
|
452
|
-
const cacheBuster = Date.now();
|
|
453
|
-
module = await import(`./devtools/dist/panel-entry.js?v=${cacheBuster}`);
|
|
507
|
+
// Use pre-loaded module (from default config) or load dynamically (consumer's runtime config override)
|
|
508
|
+
if (!devtoolsModule) {
|
|
509
|
+
// Check if we have a promise for pre-loading
|
|
510
|
+
if (devtoolsModulePromise) {
|
|
511
|
+
console.log('[JSG-LOGGER] Waiting for pre-loaded DevTools module...');
|
|
512
|
+
// Wait for pre-load to complete
|
|
513
|
+
devtoolsModule = await devtoolsModulePromise;
|
|
514
|
+
} else {
|
|
515
|
+
// Runtime config override: consumer enabled devtools but default was disabled
|
|
516
|
+
// Load on demand via dynamic import
|
|
517
|
+
console.log('[JSG-LOGGER] Loading DevTools module dynamically (runtime config override)...');
|
|
518
|
+
devtoolsModule = await import('./devtools/dist/panel-entry.js');
|
|
454
519
|
}
|
|
455
520
|
} else {
|
|
456
|
-
console.log('
|
|
457
|
-
|
|
458
|
-
|
|
521
|
+
console.log('[JSG-LOGGER] Using pre-loaded DevTools module');
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (!devtoolsModule || !devtoolsModule.initializePanel) {
|
|
525
|
+
throw new Error('DevTools panel module missing initializePanel export');
|
|
459
526
|
}
|
|
460
|
-
|
|
527
|
+
|
|
528
|
+
console.log('[JSG-LOGGER] Initializing DevTools panel...');
|
|
529
|
+
const panel = devtoolsModule.initializePanel();
|
|
530
|
+
console.log('[JSG-LOGGER] DevTools panel initialized successfully');
|
|
531
|
+
return panel;
|
|
461
532
|
} catch (error) {
|
|
462
533
|
console.error('[JSG-LOGGER] Failed to load DevTools panel:', error);
|
|
534
|
+
console.error('[JSG-LOGGER] If using npm link, ensure Vite config has: server.fs.allow: [\'..\']');
|
|
463
535
|
return null;
|
|
464
536
|
}
|
|
465
537
|
},
|
|
466
538
|
|
|
539
|
+
disableDevPanel: () => {
|
|
540
|
+
if (typeof window !== 'undefined' && window.JSG_DevTools?.destroy) {
|
|
541
|
+
window.JSG_DevTools.destroy();
|
|
542
|
+
console.log('[JSG-LOGGER] DevTools panel disabled and destroyed');
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
console.warn('[JSG-LOGGER] DevTools panel not loaded or already destroyed');
|
|
546
|
+
return false;
|
|
547
|
+
},
|
|
548
|
+
|
|
467
549
|
// System controls
|
|
468
550
|
refresh: () => this.refreshLoggers(),
|
|
469
551
|
reset: () => {
|
|
@@ -483,19 +565,19 @@ class JSGLogger {
|
|
|
483
565
|
createDirectBrowserLogger(componentName) {
|
|
484
566
|
const formatter = createBrowserFormatter(componentName, this.logStore);
|
|
485
567
|
const levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
|
|
486
|
-
const levelMap = {
|
|
487
|
-
|
|
568
|
+
const levelMap = {trace: 10, debug: 20, info: 30, warn: 40, error: 50, fatal: 60};
|
|
569
|
+
|
|
488
570
|
const logger = {};
|
|
489
|
-
|
|
571
|
+
|
|
490
572
|
levels.forEach(level => {
|
|
491
573
|
logger[level] = (first, ...args) => {
|
|
492
574
|
const logLevel = levelMap[level];
|
|
493
|
-
|
|
575
|
+
|
|
494
576
|
// Check if level should be logged
|
|
495
577
|
const effectiveLevel = configManager.getEffectiveLevel(componentName);
|
|
496
578
|
const minLevel = levelMap[effectiveLevel] || 30;
|
|
497
579
|
if (logLevel < minLevel) return;
|
|
498
|
-
|
|
580
|
+
|
|
499
581
|
// Create log data object
|
|
500
582
|
let logData = {
|
|
501
583
|
level: logLevel,
|
|
@@ -503,7 +585,7 @@ class JSGLogger {
|
|
|
503
585
|
name: componentName,
|
|
504
586
|
v: 1
|
|
505
587
|
};
|
|
506
|
-
|
|
588
|
+
|
|
507
589
|
// Handle different argument patterns
|
|
508
590
|
if (typeof first === 'string') {
|
|
509
591
|
logData.msg = first;
|
|
@@ -519,18 +601,18 @@ class JSGLogger {
|
|
|
519
601
|
logData.msg = args[0];
|
|
520
602
|
}
|
|
521
603
|
}
|
|
522
|
-
|
|
604
|
+
|
|
523
605
|
// Use our beautiful formatter
|
|
524
606
|
formatter.write(JSON.stringify(logData));
|
|
525
607
|
};
|
|
526
608
|
});
|
|
527
|
-
|
|
609
|
+
|
|
528
610
|
// Add Pino-compatible properties
|
|
529
611
|
logger._componentEmoji = configManager.getComponentConfig(componentName).emoji;
|
|
530
612
|
logger._componentName = componentName;
|
|
531
613
|
logger._effectiveLevel = configManager.getEffectiveLevel(componentName);
|
|
532
614
|
logger.level = configManager.getEffectiveLevel(componentName);
|
|
533
|
-
|
|
615
|
+
|
|
534
616
|
return logger;
|
|
535
617
|
}
|
|
536
618
|
|
|
@@ -558,9 +640,13 @@ class JSGLogger {
|
|
|
558
640
|
fatal: console.error
|
|
559
641
|
};
|
|
560
642
|
|
|
643
|
+
// No-op logger factory for getComponent
|
|
644
|
+
const noOpLogger = () => fallback;
|
|
645
|
+
|
|
561
646
|
return {
|
|
562
647
|
core: fallback,
|
|
563
648
|
createLogger: () => fallback,
|
|
649
|
+
getComponent: noOpLogger,
|
|
564
650
|
config: {environment: 'fallback'},
|
|
565
651
|
logStore: {getRecent: () => [], clear: () => {}},
|
|
566
652
|
controls: {
|
|
@@ -574,20 +660,46 @@ class JSGLogger {
|
|
|
574
660
|
}
|
|
575
661
|
|
|
576
662
|
/**
|
|
577
|
-
*
|
|
578
|
-
*
|
|
663
|
+
* Initialize safe component getters that always return logger factories
|
|
664
|
+
* This ensures components can be accessed even before initialization
|
|
579
665
|
* @private
|
|
580
666
|
*/
|
|
667
|
+
_initializeSafeComponentGetters() {
|
|
668
|
+
// Create safe getters for common components that always return a logger factory
|
|
669
|
+
// These will work even if logger isn't initialized yet
|
|
670
|
+
const commonComponents = [
|
|
671
|
+
'reactComponents', 'react-components',
|
|
672
|
+
'astroComponents', 'astro-components',
|
|
673
|
+
'astroBuild', 'astro-build',
|
|
674
|
+
'astroIntegration', 'astro-integration',
|
|
675
|
+
'contentProcessing', 'content-processing',
|
|
676
|
+
'textUtils', 'text-utils',
|
|
677
|
+
'dateUtils', 'date-utils',
|
|
678
|
+
'pages', 'webComponents', 'web-components',
|
|
679
|
+
'core', 'api', 'ui', 'database', 'test', 'preact',
|
|
680
|
+
'auth', 'analytics', 'performance', 'websocket',
|
|
681
|
+
'notification', 'router', 'cache',
|
|
682
|
+
'config', 'seo', 'devServer', 'dev-server'
|
|
683
|
+
];
|
|
684
|
+
|
|
685
|
+
commonComponents.forEach(name => {
|
|
686
|
+
// Create getter that always returns a logger (no-op if not initialized)
|
|
687
|
+
this.components[name] = () => this.getComponent(name);
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
|
|
581
691
|
_createAutoDiscoveryGetters() {
|
|
582
|
-
|
|
583
|
-
|
|
692
|
+
// Don't reset components - preserve safe getters created in constructor
|
|
693
|
+
// Only add getters for newly created loggers
|
|
584
694
|
Object.keys(this.loggers).forEach(name => {
|
|
585
|
-
//
|
|
586
|
-
this.components[name]
|
|
587
|
-
|
|
695
|
+
// Only add if not already exists (preserve safe getters)
|
|
696
|
+
if (!this.components[name]) {
|
|
697
|
+
this.components[name] = () => this.getComponent(name);
|
|
698
|
+
}
|
|
699
|
+
|
|
588
700
|
// camelCase convenience getter
|
|
589
701
|
const camelName = name.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
|
|
590
|
-
if (camelName !== name) {
|
|
702
|
+
if (camelName !== name && !this.components[camelName]) {
|
|
591
703
|
this.components[camelName] = () => this.getComponent(name);
|
|
592
704
|
}
|
|
593
705
|
});
|
|
@@ -595,35 +707,68 @@ class JSGLogger {
|
|
|
595
707
|
|
|
596
708
|
/**
|
|
597
709
|
* Get a specific component logger with auto-creation for custom components
|
|
710
|
+
* Always returns a logger instance (no-op if initialization failed)
|
|
598
711
|
* @param {string} componentName - Component name to retrieve
|
|
599
|
-
* @returns {Object} Logger instance (
|
|
712
|
+
* @returns {Object} Logger instance (always returns logger, never undefined)
|
|
600
713
|
*/
|
|
601
714
|
getComponent(componentName) {
|
|
602
|
-
// If logger
|
|
603
|
-
if (!this.loggers
|
|
715
|
+
// If logger instance isn't initialized, return no-op logger
|
|
716
|
+
if (!this.initialized || !this.loggers) {
|
|
717
|
+
return this._createNoOpLogger(componentName);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// If logger exists, return it
|
|
721
|
+
if (this.loggers[componentName]) {
|
|
722
|
+
return this.loggers[componentName];
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Try to create logger - if it fails, return no-op logger
|
|
726
|
+
try {
|
|
604
727
|
// Check if this is a configured component or custom component
|
|
605
728
|
const hasConfig = configManager.config.components?.[componentName];
|
|
606
729
|
const hasScheme = COMPONENT_SCHEME[componentName];
|
|
607
|
-
|
|
730
|
+
|
|
608
731
|
if (!hasConfig && !hasScheme) {
|
|
609
732
|
// Custom component - log info and auto-create
|
|
610
733
|
if (this.loggers.core) {
|
|
611
734
|
this.loggers.core.debug(`Auto-creating custom component logger: ${componentName}`);
|
|
612
735
|
}
|
|
613
736
|
}
|
|
614
|
-
|
|
737
|
+
|
|
615
738
|
// Create the logger (getComponentConfig will auto-generate config for custom components)
|
|
616
739
|
this.loggers[componentName] = this.createLogger(componentName);
|
|
617
|
-
|
|
740
|
+
|
|
618
741
|
// Also add to auto-discovery getters
|
|
619
742
|
this.components[componentName] = () => this.getComponent(componentName);
|
|
620
743
|
const camelName = componentName.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
|
|
621
744
|
if (camelName !== componentName) {
|
|
622
745
|
this.components[camelName] = () => this.getComponent(componentName);
|
|
623
746
|
}
|
|
747
|
+
|
|
748
|
+
return this.loggers[componentName];
|
|
749
|
+
} catch (error) {
|
|
750
|
+
// If logger creation fails, return no-op logger to prevent crashes
|
|
751
|
+
console.warn(`[JSG-LOGGER] Failed to create logger for component '${componentName}', using no-op logger:`, error);
|
|
752
|
+
return this._createNoOpLogger(componentName);
|
|
624
753
|
}
|
|
625
|
-
|
|
626
|
-
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Create a silent no-op logger that can be safely used when logger isn't available
|
|
758
|
+
* @param {string} componentName - Component name (for consistency)
|
|
759
|
+
* @returns {Object} Logger instance with all methods as no-ops
|
|
760
|
+
* @private
|
|
761
|
+
*/
|
|
762
|
+
_createNoOpLogger(componentName) {
|
|
763
|
+
// Silent no-op logger - all methods do nothing
|
|
764
|
+
return {
|
|
765
|
+
trace: () => {},
|
|
766
|
+
debug: () => {},
|
|
767
|
+
info: () => {},
|
|
768
|
+
warn: () => {},
|
|
769
|
+
error: () => {},
|
|
770
|
+
fatal: () => {}
|
|
771
|
+
};
|
|
627
772
|
}
|
|
628
773
|
|
|
629
774
|
/**
|
|
@@ -635,7 +780,7 @@ class JSGLogger {
|
|
|
635
780
|
_createErrorLogger(componentName) {
|
|
636
781
|
const prefix = `[${componentName.toUpperCase()}]`;
|
|
637
782
|
const errorMsg = '⚠️ Component not configured -';
|
|
638
|
-
|
|
783
|
+
|
|
639
784
|
return {
|
|
640
785
|
trace: (msg, ...args) => console.log(`${prefix} ${errorMsg}`, msg, ...args),
|
|
641
786
|
debug: (msg, ...args) => console.log(`${prefix} ${errorMsg}`, msg, ...args),
|
|
@@ -658,7 +803,7 @@ class JSGLogger {
|
|
|
658
803
|
const instance = await JSGLogger.getInstance();
|
|
659
804
|
const logger = instance.getComponent(component);
|
|
660
805
|
const duration = performance.now() - startTime;
|
|
661
|
-
|
|
806
|
+
|
|
662
807
|
if (duration > 1000) {
|
|
663
808
|
logger.warn(`${operation} took ${duration.toFixed(2)}ms (slow)`);
|
|
664
809
|
} else if (duration > 100) {
|
|
@@ -666,7 +811,7 @@ class JSGLogger {
|
|
|
666
811
|
} else {
|
|
667
812
|
logger.debug(`${operation} took ${duration.toFixed(2)}ms (fast)`);
|
|
668
813
|
}
|
|
669
|
-
|
|
814
|
+
|
|
670
815
|
return duration;
|
|
671
816
|
} catch (error) {
|
|
672
817
|
// Fallback to console if logger fails
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crimsonsunset/jsg-logger",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Multi-environment logger with smart detection, file-level overrides, and beautiful console formatting. Test it live: https://logger.joesangiorgio.com/",
|
|
6
6
|
"main": "index.js",
|
|
7
|
+
"types": "./index.d.ts",
|
|
7
8
|
"keywords": [
|
|
8
9
|
"logging",
|
|
9
10
|
"pino",
|
|
@@ -27,30 +28,48 @@
|
|
|
27
28
|
},
|
|
28
29
|
"homepage": "https://github.com/crimsonsunset/jsg-logger#readme",
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"@preact/preset-vite": "^2.10.2",
|
|
31
|
-
"evergreen-ui": "^7.1.9",
|
|
32
31
|
"lodash.merge": "^4.6.2",
|
|
33
|
-
"pino": "^9.7.0"
|
|
34
|
-
|
|
32
|
+
"pino": "^9.7.0"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"preact": "^10.27.1",
|
|
36
|
+
"evergreen-ui": "^7.1.9"
|
|
37
|
+
},
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"preact": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
42
|
+
"evergreen-ui": {
|
|
43
|
+
"optional": true
|
|
44
|
+
}
|
|
35
45
|
},
|
|
36
46
|
"devDependencies": {
|
|
47
|
+
"@preact/preset-vite": "^2.10.2",
|
|
48
|
+
"evergreen-ui": "^7.1.9",
|
|
49
|
+
"preact": "^10.27.1",
|
|
37
50
|
"vite": "^5.1.3"
|
|
38
51
|
},
|
|
39
52
|
"files": [
|
|
40
53
|
"index.js",
|
|
54
|
+
"index.d.ts",
|
|
41
55
|
"config/",
|
|
42
56
|
"formatters/",
|
|
43
57
|
"stores/",
|
|
44
58
|
"utils/",
|
|
45
59
|
"examples/",
|
|
46
60
|
"docs/",
|
|
61
|
+
"devtools/dist/",
|
|
47
62
|
"README.md",
|
|
48
63
|
"CHANGELOG.md",
|
|
49
64
|
"CONTRIBUTING.md",
|
|
50
65
|
"LICENSE"
|
|
51
66
|
],
|
|
52
67
|
"exports": {
|
|
53
|
-
".":
|
|
68
|
+
".": {
|
|
69
|
+
"import": "./index.js",
|
|
70
|
+
"require": "./index.js",
|
|
71
|
+
"types": "./index.d.ts"
|
|
72
|
+
},
|
|
54
73
|
"./config": "./config/config-manager.js",
|
|
55
74
|
"./config/manager": "./config/config-manager.js",
|
|
56
75
|
"./config/schemes": "./config/component-schemes.js",
|
|
@@ -62,25 +81,23 @@
|
|
|
62
81
|
"./stores/log-store": "./stores/log-store.js",
|
|
63
82
|
"./utils": "./utils/environment-detector.js",
|
|
64
83
|
"./utils/environment": "./utils/environment-detector.js",
|
|
84
|
+
"./devtools": "./devtools/dist/panel-entry.js",
|
|
65
85
|
"./examples/*": "./examples/*"
|
|
66
86
|
},
|
|
67
87
|
"scripts": {
|
|
68
88
|
"test": "node tests/run-all.js",
|
|
69
89
|
"test:watch": "nodemon --watch . --ext js --exec 'npm test'",
|
|
70
90
|
"dev": "vite",
|
|
71
|
-
"dev:devtools": "
|
|
91
|
+
"dev:devtools": "cd devtools && npm run dev",
|
|
72
92
|
"test:devtools": "vite",
|
|
73
93
|
"build:devtools": "cd devtools && npm run build",
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"release:
|
|
77
|
-
"release": "
|
|
94
|
+
"build:devtools:netlify": "npm install && cd devtools && npm install && npm run build:netlify",
|
|
95
|
+
"preview:devtools": "cd devtools && npm run preview",
|
|
96
|
+
"release:patch": "node scripts/release.js patch",
|
|
97
|
+
"release:minor": "node scripts/release.js minor",
|
|
98
|
+
"release:major": "node scripts/release.js major",
|
|
78
99
|
"publish:public": "npm publish --access public",
|
|
79
100
|
"publish:github": "npm publish --registry=https://npm.pkg.github.com/ --access public",
|
|
80
|
-
"publish:dual": "npm publish --access public && npm publish --registry=https://npm.pkg.github.com/ --access public",
|
|
81
|
-
"release:dual:patch": "npm version patch && npm run publish:dual",
|
|
82
|
-
"release:dual:minor": "npm version minor && npm run publish:dual",
|
|
83
|
-
"release:dual:major": "npm version major && npm run publish:dual",
|
|
84
101
|
"check": "npm run test && echo 'Package ready for publishing'"
|
|
85
102
|
}
|
|
86
103
|
}
|