@crimsonsunset/jsg-logger 1.4.0 → 1.5.3

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 CHANGED
@@ -8,13 +8,169 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  ## [Unreleased]
9
9
 
10
10
  ### Added
11
- - None
11
+ - **Conditional DevTools Bundling** - DevTools panel now optional via config, with tree-shaking support
12
+ - Added `devtools.enabled` config flag (default: `false`)
13
+ - Moved Preact & Evergreen UI to optional peerDependencies
14
+ - When disabled, devtools code is tree-shaken out (zero bundle impact)
15
+ - When enabled, requires peer dependencies: `npm install preact evergreen-ui`
16
+ - Function constructor used for dynamic imports to bypass Vite static analysis
12
17
 
13
- ### Changed
14
- - None
18
+ ### Changed
19
+ - **DevTools Dependencies** - Preact and Evergreen UI moved to peerDependencies for optional installation
20
+ - **DevTools Import** - Uses Function constructor instead of template literals to prevent Vite static analysis failures
21
+
22
+ ### Fixed
23
+ - **Vite Build Failures** - Fixed dynamic import issues that caused Vite dev server startup failures
24
+ - **DevTools Bundle Size** - Zero impact when disabled (default), only loads when explicitly enabled
25
+
26
+ ## [1.5.2] - 2025-10-25 🐛 **PATCH: CLI Formatter Custom Component Display**
27
+
28
+ ### Fixed
29
+ - **CLI formatter custom component names** - Formatter was using hardcoded `COMPONENT_SCHEME` instead of `configManager`, causing custom component names to display as `[JSG-CORE]` instead of user-defined names like `[SETUP]`
30
+ - **Browser formatter** - Removed redundant component name transformation
31
+
32
+ ### Technical Changes
33
+ - `formatters/cli-formatter.js` - Use `configManager.getComponentConfig()` instead of static `COMPONENT_SCHEME`
34
+ - `formatters/browser-formatter.js` - Remove redundant name transformation
35
+ - `tests/custom-components.test.js` - Added Test 6 for formatter output validation
36
+
37
+ ## [1.5.1] - 2025-10-25 🔧 **PATCH: Component Initialization Optimization**
15
38
 
16
39
  ### Fixed
17
- - None
40
+ - **Component initialization pollution** - `getAvailableComponents()` no longer initializes all 13 default COMPONENT_SCHEME components when user defines custom components (3 defined → 3 initialized instead of 16)
41
+ - **Component name formatting** - Changed from PascalCase (`MyComponent`) to uppercase with separators (`MY-COMPONENT`)
42
+
43
+ ### Technical Changes
44
+ - `config/config-manager.js` - Return only user components when defined, fallback to COMPONENT_SCHEME if empty; components replaced instead of merged; enhanced `_formatComponentName()`
45
+ - `index.js` - Clean reinitialization: reset config, clear loggers, normalize inline config
46
+ - `tests/custom-components.test.js` - New comprehensive test suite (5 tests)
47
+
48
+ ## [1.5.0] - 2025-10-25 🎯 **CRITICAL FIX: CLI Tool Support**
49
+
50
+ ### 🚨 **Critical Fixes**
51
+ These fixes resolve major blockers for CLI tool usage reported in production.
52
+
53
+ #### **Fixed: CLI Formatter Context Data Display** (Critical)
54
+ - **Replaced pino-colada** with custom formatter that displays context data
55
+ - Context objects now render as indented tree format in terminal
56
+ - Example output:
57
+ ```
58
+ 21:32:11.6 ✨ [SYSTEM] ✓ macOS version compatible
59
+ ├─ version: 14.2
60
+ ├─ build: 23C64
61
+ └─ command: sw_vers
62
+ ```
63
+ - **Problem solved**: Context data was being silently ignored by pino-colada
64
+ - **Impact**: Terminal applications now show full diagnostic information, not just messages
65
+
66
+ #### **Fixed: Environment Detection for CLI Tools** (Critical)
67
+ - **Enhanced `isCLI()` detection** - Now checks multiple signals:
68
+ - `process.stdout.isTTY` OR `process.stderr.isTTY` (not just stdout)
69
+ - `process.env.TERM` or `process.env.COLORTERM` environment variables
70
+ - Not running in CI/GitHub Actions context
71
+ - **Problem solved**: CLI tools were being detected as "server" mode → outputting JSON instead of pretty terminal formatting
72
+ - **Impact**: Terminal applications now properly display colored, formatted output instead of raw JSON blobs
73
+
74
+ #### **Added: Force Environment Override** (Critical)
75
+ - **New config option**: `forceEnvironment: 'cli' | 'browser' | 'server'`
76
+ - Allows explicit environment override when auto-detection fails
77
+ - Works in both inline config and `logger-config.json`
78
+ - **Use case**: Essential for CLI tools in non-TTY contexts (piped output, automation scripts, etc.)
79
+
80
+ #### **Added: Custom Component Name Support** (High Priority)
81
+ - **Auto-create loggers for ANY component name** - No longer restricted to `COMPONENT_SCHEME`
82
+ - Components not in config get auto-generated with sensible defaults:
83
+ - Default emoji: 📦
84
+ - Default color: #999999
85
+ - Uppercase display name
86
+ - Global level inheritance
87
+ - **Problem solved**: Custom components like 'system', 'installer', 'nvm' now work without pre-definition
88
+ - **Impact**: True zero-configuration for component names
89
+
90
+ ### ✨ **API Enhancements**
91
+
92
+ #### **Updated: `getComponent()` Method**
93
+ - Now auto-creates loggers for undefined components instead of returning error loggers
94
+ - Adds new components to auto-discovery getters dynamically
95
+ - Seamless experience for custom component names
96
+
97
+ #### **Updated: `getComponentConfig()` Method**
98
+ - Added 3-tier priority system:
99
+ 1. Config components (project-defined)
100
+ 2. COMPONENT_SCHEME defaults (built-in)
101
+ 3. Auto-generated (for custom components)
102
+ - Always returns valid config, never null/undefined
103
+
104
+ #### **Updated: `init()` and `initSync()` Methods**
105
+ - Now load config BEFORE environment detection
106
+ - Apply `forceEnvironment` config before determining environment
107
+ - `initSync()` properly handles inline config objects
108
+
109
+ ### 📚 **Documentation**
110
+ - **Updated README** - New v1.5.0 Quick Start section highlighting CLI tool fixes
111
+ - **Added Force Environment docs** - When and how to override environment detection
112
+ - **Added Custom Components docs** - Examples of using arbitrary component names
113
+ - **Updated Environment Detection section** - Document enhanced CLI detection logic
114
+
115
+ ### 🎯 **Real-World Impact**
116
+ **Before v1.5.0 (Broken for CLI tools):**
117
+ ```javascript
118
+ const logger = JSGLogger.getInstanceSync({ components: { system: {...} } });
119
+ logger.getComponent('system').info('✓ macOS compatible', { version: '14.2', build: '23C64' });
120
+ // Output: {"level":30,"time":...,"msg":"✓ macOS compatible"} ❌ JSON blob
121
+ // Component 'system' not found error ❌
122
+ // Context data not visible ❌
123
+ ```
124
+
125
+ **After v1.5.0 (All Fixed!):**
126
+ ```javascript
127
+ const logger = JSGLogger.getInstanceSync({
128
+ forceEnvironment: 'cli',
129
+ components: { system: { emoji: '⚙️' } }
130
+ });
131
+ logger.getComponent('system').info('✓ macOS compatible', { version: '14.2', build: '23C64' });
132
+ // Output:
133
+ // 21:32:11.6 ⚙️ [SYSTEM] ✓ macOS compatible ✅ Pretty formatted
134
+ // ├─ version: 14.2 ✅ Context data visible
135
+ // └─ build: 23C64 ✅ Tree formatting
136
+ // Custom component works ✅
137
+ ```
138
+
139
+ ### 🔧 **Technical Changes**
140
+ - **File**: `formatters/cli-formatter.js` ⭐ NEW FIX
141
+ - Removed pino-colada dependency (wasn't showing context data)
142
+ - Implemented custom formatter with context tree rendering
143
+ - Context data now displays with tree formatting (├─ and └─)
144
+ - Filters out pino internal fields (level, time, msg, pid, hostname, name, v, environment)
145
+
146
+ - **File**: `utils/environment-detector.js`
147
+ - Added `forceEnvironment()` function for manual override
148
+ - Enhanced `isCLI()` with multi-signal detection
149
+ - All detection functions now respect forced environment
150
+
151
+ - **File**: `config/config-manager.js`
152
+ - `getComponentConfig()` now has 3-tier fallback with auto-generation
153
+
154
+ - **File**: `index.js`
155
+ - Import `forceEnvironment` from environment detector
156
+ - Config loading moved BEFORE environment detection
157
+ - `getComponent()` auto-creates loggers instead of error loggers
158
+ - Added dynamic auto-discovery getter registration
159
+
160
+ - **File**: `package.json`
161
+ - Removed pino-colada from dependencies (no longer required)
162
+
163
+ ### 📋 **Migration Guide**
164
+ **No breaking changes** - This is a backward-compatible enhancement.
165
+
166
+ **Recommended for CLI tools:**
167
+ ```javascript
168
+ // Add this to your config for reliable terminal output
169
+ const logger = JSGLogger.getInstanceSync({
170
+ forceEnvironment: 'cli', // ← Add this line
171
+ // ... rest of your config
172
+ });
173
+ ```
18
174
 
19
175
  ## [1.2.0] - 2025-08-21 🎯 **MAJOR: Fully Generic Logger**
20
176
 
package/README.md CHANGED
@@ -4,14 +4,19 @@
4
4
 
5
5
  A sophisticated, fully generic logging system that automatically detects its environment (browser, CLI, server) and provides optimal logging experience for any JavaScript project, with powerful file-level overrides and granular control.
6
6
 
7
+ > 🎮 **[Try the Interactive DevTools Playground →](https://logger.joesangiorgio.com/)**
8
+ > Test all features in your browser with live examples and real-time controls!
9
+
7
10
  ## ✨ Features
8
11
 
9
- - 🎯 **100% Generic** - *New in v1.2.0!* Zero hardcoded assumptions, works with any project type
12
+ - 🎯 **100% Generic** - Zero hardcoded assumptions, works with any project type
10
13
  - 🚀 **Zero-Boilerplate Integration** - Eliminates 200+ lines of project setup code
11
14
  - 🔧 **Auto-Discovery Components** - Both camelCase and kebab-case component access
12
15
  - ⚡ **Built-in Performance Logging** - Static utilities with auto-getInstance
13
16
  - 🛡️ **Non-Destructive Error Handling** - Missing components log but don't break apps
14
- - 🧠 **Smart Environment Detection** - Auto-adapts to browser, CLI, or server
17
+ - 🎨 **Custom Component Names** - Use ANY component name, auto-generated styling
18
+ - 🔧 **Force Environment Override** - Override auto-detection for CLI tools
19
+ - 🧠 **Enhanced Environment Detection** - Robust CLI detection with fallbacks
15
20
  - 🎨 **Beautiful Visual Output** - Emoji, colors, and structured context display
16
21
  - 📱 **Multi-Environment** - Browser console, terminal, and production JSON
17
22
  - 🏪 **Log Store** - In-memory storage for debugging and popup interfaces
@@ -25,9 +30,40 @@ A sophisticated, fully generic logging system that automatically detects its env
25
30
 
26
31
  ## 🚀 Quick Start
27
32
 
28
- ### **v1.2.0: Fully Generic Design - Works with Any Project!**
33
+ ### **Custom Components & Force Environment for CLI Tools**
34
+
35
+ ```javascript
36
+ import JSGLogger from '@crimsonsunset/jsg-logger';
37
+
38
+ // Force environment for CLI tools (fixes terminal detection)
39
+ const logger = JSGLogger.getInstanceSync({
40
+ forceEnvironment: 'cli', // Forces pretty terminal output
41
+ globalLevel: 'info',
42
+ components: {
43
+ system: { emoji: '⚙️', level: 'info' }, // Custom component names!
44
+ installer: { emoji: '📦', level: 'info' }, // No need to pre-define
45
+ ssh: { emoji: '🔑', level: 'info' }, // Auto-generated styling
46
+ nvm: { emoji: '🟢', level: 'info' }
47
+ }
48
+ });
49
+
50
+ // Custom components work immediately
51
+ const sysLog = logger.getComponent('system');
52
+ sysLog.info('✓ macOS version compatible', { version: '14.2', build: '23C64' });
53
+ // Output: Pretty formatted terminal output with colors AND context data!
54
+ // 21:32:11.6 ⚙️ [SYSTEM] ✓ macOS version compatible
55
+ // ├─ version: 14.2
56
+ // └─ build: 23C64
57
+
58
+ const installLog = logger.getComponent('installer');
59
+ installLog.info('✓ Applications installed', { installed: 25, duration: '5m' });
60
+ // 21:32:11.8 📦 [INSTALLER] ✓ Applications installed
61
+ // ├─ installed: 25
62
+ // └─ duration: 5m
63
+ // No more JSON blobs in terminal!
64
+ ```
29
65
 
30
- > **⚠️ Breaking Change:** v1.2.0 requires defining components in your logger-config.json. The logger is now 100% generic with no hardcoded assumptions.
66
+ ### **Standard Usage**
31
67
 
32
68
  ```javascript
33
69
  import JSGLogger from '@crimsonsunset/jsg-logger';
@@ -47,12 +83,12 @@ const startTime = performance.now();
47
83
  // ... do work ...
48
84
  JSGLogger.logPerformance('Page Generation', startTime, 'api');
49
85
 
50
- // Non-destructive error handling - missing components auto-created
86
+ // Custom components auto-created on demand
51
87
  const dynamicLogger = logger.getComponent('new-feature');
52
88
  dynamicLogger.info('Auto-created component!'); // Works immediately
53
89
  ```
54
90
 
55
- ### **Traditional Usage (Still Supported)**
91
+ ### **Alternative Usage**
56
92
 
57
93
  ```javascript
58
94
  import logger from '@crimsonsunset/jsg-logger';
@@ -82,10 +118,68 @@ This allows surgical debugging - you can turn on trace logging for just one prob
82
118
 
83
119
  ## ⚙️ **Advanced Configuration**
84
120
 
121
+ ### **Force Environment Override**
122
+
123
+ Perfect for CLI tools that get mis-detected as "server" mode:
124
+
125
+ ```javascript
126
+ // Inline config approach (recommended for CLI tools)
127
+ const logger = JSGLogger.getInstanceSync({
128
+ forceEnvironment: 'cli', // Options: 'browser', 'cli', 'server'
129
+ globalLevel: 'info',
130
+ components: {
131
+ system: { emoji: '⚙️', level: 'info' }
132
+ }
133
+ });
134
+ ```
135
+
136
+ Or in `logger-config.json`:
137
+
138
+ ```json
139
+ {
140
+ "forceEnvironment": "cli",
141
+ "projectName": "My CLI Tool",
142
+ "globalLevel": "info",
143
+ "components": {
144
+ "system": { "emoji": "⚙️", "level": "info" }
145
+ }
146
+ }
147
+ ```
148
+
149
+ **When to use `forceEnvironment`:**
150
+ - CLI tools running in non-TTY contexts (CI, piped output, etc.)
151
+ - Override incorrect environment detection
152
+ - Testing different output formats
153
+ - Production deployments with specific requirements
154
+
155
+ ### **Custom Component Names**
156
+
157
+ Use ANY component name - no need to pre-define in COMPONENT_SCHEME:
158
+
159
+ ```javascript
160
+ const logger = JSGLogger.getInstanceSync({
161
+ components: {
162
+ 'my-custom-component': { emoji: '🎯', level: 'debug' },
163
+ 'another-one': { emoji: '🚀', level: 'info' },
164
+ 'system-checker': { emoji: '⚙️', level: 'trace' }
165
+ }
166
+ });
167
+
168
+ // All these work immediately - auto-created with sensible defaults
169
+ const log1 = logger.getComponent('my-custom-component');
170
+ const log2 = logger.getComponent('another-one');
171
+ const log3 = logger.getComponent('system-checker');
172
+
173
+ // Even undefined components work (auto-generated with 📦 emoji)
174
+ const log4 = logger.getComponent('undefined-component');
175
+ log4.info('This works!'); // Uses auto-generated styling
176
+ ```
177
+
85
178
  ### **Full Configuration Example**
86
179
 
87
180
  ```json
88
181
  {
182
+ "forceEnvironment": "cli",
89
183
  "projectName": "My Advanced Project",
90
184
  "globalLevel": "info",
91
185
  "timestampMode": "absolute",
@@ -134,6 +228,9 @@ This allows surgical debugging - you can turn on trace logging for just one prob
134
228
  "jsonPayload": false
135
229
  }
136
230
  }
231
+ },
232
+ "devtools": {
233
+ "enabled": false
137
234
  }
138
235
  }
139
236
  ```
@@ -255,6 +352,9 @@ logger.controls.addFileOverride('src/popup.js', {
255
352
  ```
256
353
 
257
354
  ### **Context Data**
355
+
356
+ Context data displays in CLI/terminal mode with tree formatting:
357
+
258
358
  ```javascript
259
359
  logger.api.error('Request failed', {
260
360
  url: window.location.href,
@@ -267,7 +367,15 @@ logger.api.error('Request failed', {
267
367
  userAgent: navigator.userAgent
268
368
  });
269
369
 
270
- // With file override for src/sites/soundcloud.js level: "trace":
370
+ // CLI/Terminal output (v1.5.0+):
371
+ // 22:15:30.1 🚨 [API] Request failed
372
+ // ├─ url: https://soundcloud.com/track/example
373
+ // ├─ selectors: {"title":".track-title","artist":".track-artist"}
374
+ // ├─ retryCount: 3
375
+ // ├─ lastError: Element not found
376
+ // └─ userAgent: Mozilla/5.0...
377
+
378
+ // Browser Console output:
271
379
  // 22:15:30.123 🚨 [API] Request failed
272
380
  // ├─ url: https://soundcloud.com/track/example
273
381
  // ├─ selectors: {title: ".track-title", artist: ".track-artist"}
@@ -308,12 +416,10 @@ logger.controls.getTimestampMode() // Get current mode
308
416
  logger.controls.getTimestampModes() // List available modes
309
417
  ```
310
418
 
311
- ### **System Controls**
419
+ ### **DevTools Panel Controls**
312
420
  ```javascript
313
- logger.controls.refresh() // Refresh all loggers
314
- logger.controls.reset() // Reset to defaults
315
- logger.controls.getConfigSummary() // Get config summary
316
- logger.controls.getStats() // Get logging stats
421
+ logger.controls.enableDevPanel() // Enable DevTools panel (requires devtools.enabled: true)
422
+ logger.controls.disableDevPanel() // Disable DevTools panel
317
423
  ```
318
424
 
319
425
  ## 📊 **Log Store & Statistics**
@@ -393,7 +499,7 @@ const stats = logger.controls.getStats();
393
499
  npm install @crimsonsunset/jsg-logger
394
500
  ```
395
501
 
396
- **Latest**: v1.1.0 includes major project simplification enhancements!
502
+ **Latest**: v1.5.0 includes critical CLI tool fixes and custom component support!
397
503
 
398
504
  ## 🎯 Environment Detection
399
505
 
@@ -403,6 +509,15 @@ The logger automatically detects its environment and uses optimal implementation
403
509
  - **CLI**: Uses pino-colada for beautiful terminal output
404
510
  - **Server**: Uses structured JSON for production logging
405
511
 
512
+ ### **Enhanced CLI Detection**
513
+
514
+ The CLI detection checks multiple signals:
515
+ 1. **TTY Check**: `process.stdout.isTTY` or `process.stderr.isTTY`
516
+ 2. **Terminal Environment**: `process.env.TERM` or `process.env.COLORTERM`
517
+ 3. **Non-CI Context**: Not running in CI/GitHub Actions
518
+
519
+ This fixes detection issues in various terminal contexts where `isTTY` may be undefined.
520
+
406
521
  **Why Browser is Different:**
407
522
  Our testing revealed that Pino's browser detection was interfering with custom formatters, especially in Chrome extensions. By creating a custom direct browser logger that bypasses Pino entirely, we achieved:
408
523
  - Perfect emoji and color display
@@ -441,6 +556,42 @@ logger.controls.addFileOverride('src/popup.js', { // Debug popup
441
556
  });
442
557
  ```
443
558
 
559
+ ## 🎛️ **DevTools Panel (Optional)**
560
+
561
+ JSG Logger includes an optional DevTools panel for visual debugging. The panel is **disabled by default** to keep bundle size minimal.
562
+
563
+ ### **Enabling DevTools**
564
+
565
+ 1. **Enable in config:**
566
+ ```json
567
+ {
568
+ "devtools": {
569
+ "enabled": true
570
+ }
571
+ }
572
+ ```
573
+
574
+ 2. **Install peer dependencies** (only needed when devtools enabled):
575
+ ```bash
576
+ npm install preact evergreen-ui
577
+ ```
578
+
579
+ 3. **Enable the panel:**
580
+ ```javascript
581
+ // Enable DevTools panel (only works if devtools.enabled: true in config)
582
+ await logger.controls.enableDevPanel();
583
+ ```
584
+
585
+ ### **DevTools Features**
586
+
587
+ - 🎛️ Visual component filter controls
588
+ - 📊 Real-time log statistics
589
+ - 🔧 Runtime level adjustment
590
+ - ⚙️ Display option toggles
591
+ - 📈 Component-level monitoring
592
+
593
+ **Note:** When `devtools.enabled: false` (default), devtools dependencies are completely tree-shaken out, resulting in zero bundle impact. Only enable when you need the visual debugging interface.
594
+
444
595
  ## 🔧 **Browser Developer Tools**
445
596
 
446
597
  In browser environments, runtime controls are available globally:
@@ -451,6 +602,7 @@ JSG_Logger.enableDebugMode();
451
602
  JSG_Logger.setDisplayOption('level', true);
452
603
  JSG_Logger.addFileOverride('src/popup.js', { level: 'trace' });
453
604
  JSG_Logger.getStats();
605
+ JSG_Logger.enableDevPanel(); // Enable DevTools panel (requires devtools.enabled: true)
454
606
  ```
455
607
 
456
608
  ## ⚠️ **Disclaimer**
@@ -133,7 +133,7 @@ export class ConfigManager {
133
133
 
134
134
  try {
135
135
  // Try dynamic import first (works with ES modules)
136
- const module = await import(path, { assert: { type: 'json' } });
136
+ const module = await import(/* @vite-ignore */ path, { assert: { type: 'json' } });
137
137
  return module.default || module;
138
138
  } catch (error) {
139
139
  try {
@@ -156,7 +156,7 @@ export class ConfigManager {
156
156
  async _loadConfigBrowserImport(path) {
157
157
  try {
158
158
  // Some bundlers can handle dynamic imports of JSON files
159
- const module = await import(path);
159
+ const module = await import(/* @vite-ignore */ path);
160
160
  return module.default || module;
161
161
  } catch (error) {
162
162
  return null;
@@ -292,10 +292,16 @@ export class ConfigManager {
292
292
  * @private
293
293
  */
294
294
  _formatComponentName(componentName) {
295
+ // If already uppercase, return as-is
296
+ if (componentName === componentName.toUpperCase()) {
297
+ return componentName;
298
+ }
299
+
300
+ // Convert to uppercase and preserve separators for readability
295
301
  return componentName
296
- .split('-')
297
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
298
- .join('');
302
+ .replace(/([a-z])([A-Z])/g, '$1-$2') // camelCase → kebab-case
303
+ .replace(/_/g, '-') // snake_case → kebab-case
304
+ .toUpperCase();
299
305
  }
300
306
 
301
307
  /**
@@ -315,7 +321,11 @@ export class ConfigManager {
315
321
 
316
322
  for (const key in override) {
317
323
  if (override.hasOwnProperty(key)) {
318
- if (typeof override[key] === 'object' && !Array.isArray(override[key])) {
324
+ // Special case: 'components' should be replaced, not merged
325
+ // This allows users to define their own components without getting defaults
326
+ if (key === 'components' && typeof override[key] === 'object') {
327
+ merged[key] = override[key];
328
+ } else if (typeof override[key] === 'object' && !Array.isArray(override[key])) {
319
329
  merged[key] = this.mergeConfigs(merged[key] || {}, override[key]);
320
330
  } else {
321
331
  merged[key] = override[key];
@@ -406,7 +416,23 @@ export class ConfigManager {
406
416
  * @returns {Object} Component configuration
407
417
  */
408
418
  getComponentConfig(componentName, filePath = null) {
409
- const baseComponent = this.config.components?.[componentName] || COMPONENT_SCHEME[componentName] || COMPONENT_SCHEME['core'];
419
+ // Priority 1: Config components
420
+ let baseComponent = this.config.components?.[componentName];
421
+
422
+ // Priority 2: COMPONENT_SCHEME defaults
423
+ if (!baseComponent) {
424
+ baseComponent = COMPONENT_SCHEME[componentName];
425
+ }
426
+
427
+ // Priority 3: Auto-generate for custom components
428
+ if (!baseComponent) {
429
+ baseComponent = {
430
+ emoji: '📦',
431
+ color: '#999999',
432
+ name: this._formatComponentName(componentName),
433
+ level: this.config.globalLevel || 'info'
434
+ };
435
+ }
410
436
 
411
437
  // Check for file-specific overrides
412
438
  const checkFile = filePath || this.currentFile;
@@ -523,10 +549,14 @@ export class ConfigManager {
523
549
  */
524
550
  getAvailableComponents() {
525
551
  const configComponents = Object.keys(this.config.components || {});
526
- const schemeComponents = Object.keys(COMPONENT_SCHEME);
527
-
528
- // Combine and deduplicate
529
- return [...new Set([...configComponents, ...schemeComponents])];
552
+
553
+ // If user has defined components, only return those
554
+ if (configComponents.length > 0) {
555
+ return configComponents;
556
+ }
557
+
558
+ // Fallback to COMPONENT_SCHEME if no components configured (backward compatibility)
559
+ return Object.keys(COMPONENT_SCHEME);
530
560
  }
531
561
 
532
562
  /**
@@ -29,10 +29,12 @@
29
29
  "core": {
30
30
  "emoji": "🎯",
31
31
  "color": "#4A90E2",
32
- "name": "JSG-CORE",
33
- "level": "info"
32
+ "name": "JSG-CORE"
34
33
  }
35
34
  },
36
35
  "fileOverrides": {
36
+ },
37
+ "devtools": {
38
+ "enabled": false
37
39
  }
38
40
  }