@crimsonsunset/jsg-logger 1.1.1 → 1.1.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/config/config-manager.js +261 -15
- package/docs/roadmap.md +153 -4
- package/formatters/cli-formatter.js +36 -23
- package/package.json +1 -1
package/config/config-manager.js
CHANGED
|
@@ -24,26 +24,18 @@ export class ConfigManager {
|
|
|
24
24
|
let externalConfig = {};
|
|
25
25
|
|
|
26
26
|
if (typeof configSource === 'string') {
|
|
27
|
-
// Load from file path
|
|
28
|
-
|
|
29
|
-
// Relative path - attempt to load
|
|
30
|
-
try {
|
|
31
|
-
const response = await fetch(configSource);
|
|
32
|
-
if (response.ok) {
|
|
33
|
-
externalConfig = await response.json();
|
|
34
|
-
this.loadedPaths.push(configSource);
|
|
35
|
-
}
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.warn(`Failed to load config from ${configSource}:`, error.message);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
27
|
+
// Load from file path - handle all path formats
|
|
28
|
+
externalConfig = await this._loadConfigFromPath(configSource);
|
|
40
29
|
} else if (typeof configSource === 'object') {
|
|
41
30
|
// Direct config object
|
|
42
31
|
externalConfig = configSource;
|
|
43
32
|
}
|
|
44
33
|
|
|
45
|
-
//
|
|
46
|
-
|
|
34
|
+
// Normalize external config to match expected structure
|
|
35
|
+
const normalizedConfig = this._normalizeConfigStructure(externalConfig);
|
|
36
|
+
|
|
37
|
+
// Merge configurations - project configs override defaults
|
|
38
|
+
this.config = this.mergeConfigs(this.config, normalizedConfig);
|
|
47
39
|
|
|
48
40
|
return this.config;
|
|
49
41
|
} catch (error) {
|
|
@@ -52,6 +44,260 @@ export class ConfigManager {
|
|
|
52
44
|
}
|
|
53
45
|
}
|
|
54
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Load configuration from a file path with environment detection
|
|
49
|
+
* @param {string} configPath - File path to load
|
|
50
|
+
* @returns {Promise<Object>} Configuration object
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
async _loadConfigFromPath(configPath) {
|
|
54
|
+
try {
|
|
55
|
+
// Normalize path - add ./ prefix if missing for relative paths
|
|
56
|
+
const normalizedPath = this._normalizePath(configPath);
|
|
57
|
+
|
|
58
|
+
// Try different loading strategies based on environment
|
|
59
|
+
let config = null;
|
|
60
|
+
|
|
61
|
+
// Strategy 1: Browser environment with fetch
|
|
62
|
+
if (typeof window !== 'undefined' && typeof fetch !== 'undefined') {
|
|
63
|
+
config = await this._loadConfigBrowser(normalizedPath);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Strategy 2: Node.js environment with dynamic import
|
|
67
|
+
if (!config && typeof process !== 'undefined') {
|
|
68
|
+
config = await this._loadConfigNode(normalizedPath);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Strategy 3: Fallback browser import (for bundlers like Vite)
|
|
72
|
+
if (!config && typeof window !== 'undefined') {
|
|
73
|
+
config = await this._loadConfigBrowserImport(normalizedPath);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (config) {
|
|
77
|
+
this.loadedPaths.push(configPath);
|
|
78
|
+
console.log(`[JSG-LOGGER] Successfully loaded config from: ${configPath}`);
|
|
79
|
+
return config;
|
|
80
|
+
} else {
|
|
81
|
+
console.warn(`[JSG-LOGGER] Could not load config from: ${configPath} - using defaults`);
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.warn(`[JSG-LOGGER] Failed to load config from ${configPath}:`, error.message);
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Normalize file path for consistent handling
|
|
92
|
+
* @param {string} path - Original path
|
|
93
|
+
* @returns {string} Normalized path
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
_normalizePath(path) {
|
|
97
|
+
// Add ./ prefix for relative paths that don't have it
|
|
98
|
+
if (!path.startsWith('./') && !path.startsWith('../') && !path.startsWith('/')) {
|
|
99
|
+
return `./${path}`;
|
|
100
|
+
}
|
|
101
|
+
return path;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Load config in browser environment using fetch
|
|
106
|
+
* @param {string} path - File path
|
|
107
|
+
* @returns {Promise<Object|null>} Configuration object or null
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
async _loadConfigBrowser(path) {
|
|
111
|
+
try {
|
|
112
|
+
const response = await fetch(path);
|
|
113
|
+
if (response.ok) {
|
|
114
|
+
return await response.json();
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Load config in Node.js environment
|
|
124
|
+
* @param {string} path - File path
|
|
125
|
+
* @returns {Promise<Object|null>} Configuration object or null
|
|
126
|
+
* @private
|
|
127
|
+
*/
|
|
128
|
+
async _loadConfigNode(path) {
|
|
129
|
+
// Only use Node.js APIs when actually in Node.js environment
|
|
130
|
+
if (typeof process === 'undefined' || !process.versions || !process.versions.node) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
// Try dynamic import first (works with ES modules)
|
|
136
|
+
const module = await import(path, { assert: { type: 'json' } });
|
|
137
|
+
return module.default || module;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
try {
|
|
140
|
+
// Fallback to fs.readFile for broader compatibility
|
|
141
|
+
const fs = await import('fs/promises');
|
|
142
|
+
const fileContent = await fs.readFile(path, 'utf-8');
|
|
143
|
+
return JSON.parse(fileContent);
|
|
144
|
+
} catch (fsError) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Load config in browser using dynamic import (for bundlers)
|
|
152
|
+
* @param {string} path - File path
|
|
153
|
+
* @returns {Promise<Object|null>} Configuration object or null
|
|
154
|
+
* @private
|
|
155
|
+
*/
|
|
156
|
+
async _loadConfigBrowserImport(path) {
|
|
157
|
+
try {
|
|
158
|
+
// Some bundlers can handle dynamic imports of JSON files
|
|
159
|
+
const module = await import(path);
|
|
160
|
+
return module.default || module;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Normalize config structure to handle different field naming conventions
|
|
168
|
+
* @param {Object} config - Raw configuration object
|
|
169
|
+
* @returns {Object} Normalized configuration
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
_normalizeConfigStructure(config) {
|
|
173
|
+
const normalized = {...config};
|
|
174
|
+
|
|
175
|
+
// Handle displayOptions -> display mapping
|
|
176
|
+
if (config.displayOptions && !config.display) {
|
|
177
|
+
normalized.display = this._mapDisplayOptions(config.displayOptions);
|
|
178
|
+
delete normalized.displayOptions;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Handle environment-specific configurations
|
|
182
|
+
if (config.environments) {
|
|
183
|
+
// For now, just log that environment configs exist
|
|
184
|
+
// TODO: Implement environment-based config selection
|
|
185
|
+
console.log(`[JSG-LOGGER] Found environment configs for: ${Object.keys(config.environments).join(', ')}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Normalize component configurations
|
|
189
|
+
if (config.components) {
|
|
190
|
+
normalized.components = this._normalizeComponents(config.components);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return normalized;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Map displayOptions to display format
|
|
198
|
+
* @param {Object} displayOptions - Original display options
|
|
199
|
+
* @returns {Object} Normalized display configuration
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
_mapDisplayOptions(displayOptions) {
|
|
203
|
+
return {
|
|
204
|
+
timestamp: displayOptions.showTimestamp ?? true,
|
|
205
|
+
emoji: true, // Always enabled for JSG Logger
|
|
206
|
+
component: displayOptions.showComponent ?? true,
|
|
207
|
+
level: displayOptions.showLevel ?? false,
|
|
208
|
+
message: true, // Always enabled
|
|
209
|
+
jsonPayload: true, // Default enabled
|
|
210
|
+
stackTrace: true, // Default enabled
|
|
211
|
+
environment: displayOptions.showEnvironment ?? false
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Normalize component configurations
|
|
217
|
+
* @param {Object} components - Raw component config
|
|
218
|
+
* @returns {Object} Normalized component config
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
221
|
+
_normalizeComponents(components) {
|
|
222
|
+
const normalized = {};
|
|
223
|
+
|
|
224
|
+
for (const [name, config] of Object.entries(components)) {
|
|
225
|
+
normalized[name] = {
|
|
226
|
+
emoji: config.emoji || this._getDefaultEmoji(name),
|
|
227
|
+
color: config.color || this._getDefaultColor(name),
|
|
228
|
+
name: config.name || this._formatComponentName(name),
|
|
229
|
+
level: config.level || 'info',
|
|
230
|
+
enabled: config.enabled ?? true,
|
|
231
|
+
description: config.description // Preserve description for documentation
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return normalized;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get default emoji for component
|
|
240
|
+
* @param {string} componentName - Component name
|
|
241
|
+
* @returns {string} Default emoji
|
|
242
|
+
* @private
|
|
243
|
+
*/
|
|
244
|
+
_getDefaultEmoji(componentName) {
|
|
245
|
+
const emojiMap = {
|
|
246
|
+
'astro-build': '🚀',
|
|
247
|
+
'astro-integration': '⚙️',
|
|
248
|
+
'content-processing': '📝',
|
|
249
|
+
'text-utils': '📄',
|
|
250
|
+
'date-utils': '📅',
|
|
251
|
+
'react-components': '⚛️',
|
|
252
|
+
'astro-components': '🌟',
|
|
253
|
+
'pages': '📄',
|
|
254
|
+
'config': '⚙️',
|
|
255
|
+
'seo': '🔍',
|
|
256
|
+
'performance': '⚡',
|
|
257
|
+
'dev-server': '🛠️'
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
return emojiMap[componentName] || '🎯';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Get default color for component
|
|
265
|
+
* @param {string} componentName - Component name
|
|
266
|
+
* @returns {string} Default color
|
|
267
|
+
* @private
|
|
268
|
+
*/
|
|
269
|
+
_getDefaultColor(componentName) {
|
|
270
|
+
const colorMap = {
|
|
271
|
+
'astro-build': '#FF5D01',
|
|
272
|
+
'astro-integration': '#4A90E2',
|
|
273
|
+
'content-processing': '#00C896',
|
|
274
|
+
'text-utils': '#9B59B6',
|
|
275
|
+
'date-utils': '#3498DB',
|
|
276
|
+
'react-components': '#61DAFB',
|
|
277
|
+
'astro-components': '#FF5D01',
|
|
278
|
+
'pages': '#2ECC71',
|
|
279
|
+
'config': '#95A5A6',
|
|
280
|
+
'seo': '#E74C3C',
|
|
281
|
+
'performance': '#F39C12',
|
|
282
|
+
'dev-server': '#8E44AD'
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
return colorMap[componentName] || '#4A90E2';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Format component name for display
|
|
290
|
+
* @param {string} componentName - Raw component name
|
|
291
|
+
* @returns {string} Formatted display name
|
|
292
|
+
* @private
|
|
293
|
+
*/
|
|
294
|
+
_formatComponentName(componentName) {
|
|
295
|
+
return componentName
|
|
296
|
+
.split('-')
|
|
297
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
298
|
+
.join('');
|
|
299
|
+
}
|
|
300
|
+
|
|
55
301
|
/**
|
|
56
302
|
* Set current file context for override resolution
|
|
57
303
|
* @param {string} filePath - Current file path being logged from
|
package/docs/roadmap.md
CHANGED
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
|
|
22
22
|
## 🎯 Current Status
|
|
23
23
|
**Last Updated:** August 21, 2025
|
|
24
|
-
**Current Phase:** Phase
|
|
25
|
-
**Status:**
|
|
26
|
-
**
|
|
24
|
+
**Current Phase:** Phase 9 - Genericize Logger (Remove CACP Hardcoding)
|
|
25
|
+
**Status:** 🚀 **IN PROGRESS** - Making JSG Logger truly generic by removing CACP-specific hardcoded components
|
|
26
|
+
**Current Issue:** Logger still loads CACP defaults instead of project-specific `logger-config.json` files
|
|
27
27
|
|
|
28
28
|
### Progress Overview
|
|
29
29
|
- ✅ **COMPLETED:** Multi-environment logger with smart detection
|
|
@@ -339,6 +339,19 @@ Console filtering updates
|
|
|
339
339
|
|
|
340
340
|
## 📈 Recent Progress
|
|
341
341
|
|
|
342
|
+
### August 21, 2025 - Phase 9 Discovery: CACP Hardcoding Issues 🔍
|
|
343
|
+
- 🐛 **Critical Discovery**: JSG Logger still deeply hardcoded for CACP use cases
|
|
344
|
+
- 🔍 **Issue Identified**: `logger-config.json` files being ignored, falling back to CACP defaults
|
|
345
|
+
- 📋 **Root Causes Documented**: 6 major areas requiring genericization
|
|
346
|
+
1. `CACPLogger` class name and all references
|
|
347
|
+
2. Default config with 10 hardcoded CACP components
|
|
348
|
+
3. Component schemes duplication
|
|
349
|
+
4. Hardcoded legacy aliases for CACP components
|
|
350
|
+
5. Core component dependency on 'cacp' logger
|
|
351
|
+
6. Config loading path resolution issues
|
|
352
|
+
- 🎯 **Phase 9 Planned**: Complete roadmap for making logger truly generic
|
|
353
|
+
- ✅ **Testing Successful**: JSG Logger v1.1.0 API features work, but components wrong
|
|
354
|
+
|
|
342
355
|
### August 21, 2025 - Phase 8 API Enhancement Complete ✅
|
|
343
356
|
- ✅ **JSG Logger v1.1.0** - Major API simplification enhancements shipped
|
|
344
357
|
- ✅ **Static Singleton Pattern** - `CACPLogger.getInstance()` with auto-initialization
|
|
@@ -403,7 +416,7 @@ Console filtering updates
|
|
|
403
416
|
|
|
404
417
|
## 🎯 Next Steps
|
|
405
418
|
|
|
406
|
-
### **Phase 8: API Enhancement for Project Simplification**
|
|
419
|
+
### **Phase 8: API Enhancement for Project Simplification** ✅ COMPLETED
|
|
407
420
|
**Goal**: Eliminate boilerplate code that every project needs to implement when using JSG Logger
|
|
408
421
|
|
|
409
422
|
#### **Background - The Problem**
|
|
@@ -553,6 +566,142 @@ export { logger, JSGLogger };
|
|
|
553
566
|
5. Test and validate 93% boilerplate reduction
|
|
554
567
|
6. Document new API in README examples
|
|
555
568
|
|
|
569
|
+
#### **🎯 Actual Impact Achieved**
|
|
570
|
+
- ✅ **82% Boilerplate Reduction**: 220 lines → 40 lines in jsg-tech-check-site
|
|
571
|
+
- ✅ **Version Published**: JSG Logger v1.1.0 live on NPM
|
|
572
|
+
- ✅ **All Features Working**: Singleton pattern, auto-discovery, performance logging, non-destructive errors
|
|
573
|
+
- ✅ **Build Integration**: Works in both Astro build-time and client-side contexts
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
### **Phase 9: Genericize Logger (Remove CACP Hardcoding)** 🚀 IN PROGRESS
|
|
578
|
+
**Goal**: Make JSG Logger truly generic by removing all CACP-specific hardcoded components and references
|
|
579
|
+
|
|
580
|
+
#### **Background - The Problem**
|
|
581
|
+
During Phase 8 integration testing with jsg-tech-check-site, we discovered the logger is still deeply hardcoded for CACP (Chrome Audio Control Panel) use cases:
|
|
582
|
+
|
|
583
|
+
**Observable Issues:**
|
|
584
|
+
```
|
|
585
|
+
[JSG-LOGGER] Component 'astro-build' not found. Available: cacp, soundcloud, youtube, site-detector, websocket, popup, background, priority-manager, settings, test, siteDetector, priorityManager
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
Despite providing a proper `logger-config.json` with Astro-specific components, the logger falls back to CACP defaults instead of loading the project's configuration.
|
|
589
|
+
|
|
590
|
+
#### **Root Causes - What Makes It CACP-Specific**
|
|
591
|
+
|
|
592
|
+
##### **1. Class Name & Core References**
|
|
593
|
+
- `CACPLogger` class name should be `JSGLogger` or `GenericLogger`
|
|
594
|
+
- All static method references (`CACPLogger.getInstance()`, etc.)
|
|
595
|
+
- Error messages mentioning "CACP Logger"
|
|
596
|
+
- `window.CACP_Logger` global should be `window.JSG_Logger`
|
|
597
|
+
|
|
598
|
+
##### **2. Default Configuration Hardcoding**
|
|
599
|
+
**File:** `/config/default-config.json`
|
|
600
|
+
- **Hardcoded project name**: `"CACP Logger"`
|
|
601
|
+
- **10 CACP-specific components**:
|
|
602
|
+
- `cacp` (🎯 CACP-CORE) - should be generic `core`
|
|
603
|
+
- `soundcloud` (🎵 SoundCloud)
|
|
604
|
+
- `youtube` (📹 YouTube)
|
|
605
|
+
- `site-detector` (🔍 SiteDetector)
|
|
606
|
+
- `websocket` (🌐 WebSocket)
|
|
607
|
+
- `popup` (🎛️ Popup)
|
|
608
|
+
- `background` (🔧 Background)
|
|
609
|
+
- `priority-manager` (⚖️ PriorityManager)
|
|
610
|
+
- `settings` (⚙️ Settings)
|
|
611
|
+
- `test` (🧪 Test)
|
|
612
|
+
|
|
613
|
+
##### **3. Component Schemes Duplication**
|
|
614
|
+
**File:** `/config/component-schemes.js`
|
|
615
|
+
- Duplicates the same 10 hardcoded CACP components
|
|
616
|
+
- Should be empty/minimal by default for generic usage
|
|
617
|
+
|
|
618
|
+
##### **4. Hardcoded Legacy Aliases**
|
|
619
|
+
```javascript
|
|
620
|
+
// In createAliases() method:
|
|
621
|
+
this.loggers.siteDetector = this.loggers['site-detector'];
|
|
622
|
+
this.loggers.priorityManager = this.loggers['priority-manager'];
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
##### **5. Core Component Dependency**
|
|
626
|
+
```javascript
|
|
627
|
+
// Initialization requires 'cacp' component:
|
|
628
|
+
if (this.loggers.cacp) {
|
|
629
|
+
this.loggers.cacp.info('CACP Logger initialized', {...});
|
|
630
|
+
}
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
##### **6. Config Loading Path Issue**
|
|
634
|
+
- **Critical**: The logger isn't loading our `logger-config.json` properly
|
|
635
|
+
- Falls back to default CACP config instead of using project-specific configurations
|
|
636
|
+
- **Why our Astro config is ignored**: Path resolution or config merging logic issues
|
|
637
|
+
|
|
638
|
+
#### **🔧 Implementation Plan**
|
|
639
|
+
|
|
640
|
+
##### **Fix 1: Make Default Config Truly Generic**
|
|
641
|
+
**Target**: `/config/default-config.json`
|
|
642
|
+
```json
|
|
643
|
+
{
|
|
644
|
+
"projectName": "JSG Logger",
|
|
645
|
+
"globalLevel": "info",
|
|
646
|
+
"components": {
|
|
647
|
+
"core": {
|
|
648
|
+
"emoji": "🎯",
|
|
649
|
+
"color": "#4A90E2",
|
|
650
|
+
"name": "Logger-Core",
|
|
651
|
+
"level": "info"
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
##### **Fix 2: Rename Core Class**
|
|
658
|
+
**Target**: `/index.js`
|
|
659
|
+
- `CACPLogger` → `JSGLogger`
|
|
660
|
+
- Update all static method references
|
|
661
|
+
- Update error messages
|
|
662
|
+
- Update browser global: `window.CACP_Logger` → `window.JSG_Logger`
|
|
663
|
+
|
|
664
|
+
##### **Fix 3: Fix Config Loading**
|
|
665
|
+
**Target**: Config manager and initialization
|
|
666
|
+
- Debug why `configPath: 'logger-config.json'` isn't loading properly
|
|
667
|
+
- Ensure project configs override defaults instead of falling back
|
|
668
|
+
- Fix path resolution for various environments (Node.js vs browser)
|
|
669
|
+
|
|
670
|
+
##### **Fix 4: Remove CACP-Specific Logic**
|
|
671
|
+
**Target**: `/index.js` `createAliases()` method
|
|
672
|
+
- Remove hardcoded legacy aliases for `siteDetector`, `priorityManager`
|
|
673
|
+
- Make aliases configurable if needed, not hardcoded
|
|
674
|
+
|
|
675
|
+
##### **Fix 5: Use Configurable Core Component**
|
|
676
|
+
**Target**: Initialization logging
|
|
677
|
+
- Replace `this.loggers.cacp.info()` with configurable core component
|
|
678
|
+
- Use `this.loggers.core` or first available component
|
|
679
|
+
- Graceful fallback if no components configured
|
|
680
|
+
|
|
681
|
+
##### **Fix 6: Clean Component Schemes**
|
|
682
|
+
**Target**: `/config/component-schemes.js`
|
|
683
|
+
- Remove all CACP-specific hardcoded components
|
|
684
|
+
- Keep only minimal example or make it empty
|
|
685
|
+
- Let projects define their own components
|
|
686
|
+
|
|
687
|
+
#### **🎯 Success Criteria**
|
|
688
|
+
1. ✅ **Generic by Default**: Fresh installations work without CACP references
|
|
689
|
+
2. ✅ **Config Loading Works**: Project-specific `logger-config.json` files are properly loaded
|
|
690
|
+
3. ✅ **No CACP Dependencies**: Logger works without any CACP-specific components
|
|
691
|
+
4. ✅ **Clean API**: `JSGLogger.getInstance()` instead of `CACPLogger.getInstance()`
|
|
692
|
+
5. ✅ **Test with Real Project**: jsg-tech-check-site loads Astro components correctly
|
|
693
|
+
|
|
694
|
+
#### **📋 Implementation Steps**
|
|
695
|
+
1. **Debug config loading** - Fix why `logger-config.json` is ignored
|
|
696
|
+
2. **Rename core class** - `CACPLogger` → `JSGLogger`
|
|
697
|
+
3. **Replace default config** - Remove 10 CACP components, use minimal generic
|
|
698
|
+
4. **Remove hardcoded aliases** - Make legacy aliases configurable
|
|
699
|
+
5. **Fix core component** - Use configurable core for init logging
|
|
700
|
+
6. **Update browser global** - `window.JSG_Logger`
|
|
701
|
+
7. **Test with jsg-tech-check-site** - Verify Astro components load correctly
|
|
702
|
+
8. **Version bump** - Patch or minor version for breaking changes
|
|
703
|
+
9. **Publish updated package** - Deploy generic version to NPM
|
|
704
|
+
|
|
556
705
|
---
|
|
557
706
|
|
|
558
707
|
### **Previous Optional Enhancements** (Lower Priority)
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { COMPONENT_SCHEME, LEVEL_SCHEME } from '../config/component-schemes.js';
|
|
7
|
+
import pinoColada from 'pino-colada';
|
|
8
|
+
// Note: pino-pretty imported conditionally to avoid browser bundle issues
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Create CLI formatter using pino-colada or pino-pretty
|
|
@@ -11,33 +13,44 @@ import { COMPONENT_SCHEME, LEVEL_SCHEME } from '../config/component-schemes.js';
|
|
|
11
13
|
*/
|
|
12
14
|
export const createCLIFormatter = () => {
|
|
13
15
|
try {
|
|
14
|
-
// Try
|
|
15
|
-
const
|
|
16
|
-
|
|
16
|
+
// Try pino-colada first (best formatting)
|
|
17
|
+
const colada = pinoColada();
|
|
18
|
+
colada.pipe(process.stdout);
|
|
19
|
+
return colada;
|
|
17
20
|
} catch (error) {
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
// Ultimate fallback - basic formatted output (works in all environments)
|
|
22
|
+
return {
|
|
23
|
+
write: (chunk) => {
|
|
24
|
+
try {
|
|
25
|
+
const log = JSON.parse(chunk);
|
|
26
|
+
|
|
27
|
+
// Get component info
|
|
25
28
|
const component = COMPONENT_SCHEME[log.name] || COMPONENT_SCHEME['cacp'];
|
|
26
29
|
const componentName = component.name.toUpperCase().replace(/([a-z])([A-Z])/g, '$1-$2');
|
|
30
|
+
|
|
31
|
+
// Get level info
|
|
27
32
|
const level = LEVEL_SCHEME[log.level] || LEVEL_SCHEME[30];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
// Format timestamp like pino-pretty
|
|
35
|
+
const timestamp = new Date(log.time).toLocaleTimeString('en-US', {
|
|
36
|
+
hour12: false,
|
|
37
|
+
hour: '2-digit',
|
|
38
|
+
minute: '2-digit',
|
|
39
|
+
second: '2-digit',
|
|
40
|
+
fractionalSecondDigits: 1
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Format message like pino-pretty messageFormat
|
|
44
|
+
const message = `${level.emoji} [${componentName}] ${log.msg || ''}`;
|
|
45
|
+
|
|
46
|
+
// Output with timestamp prefix
|
|
47
|
+
console.log(`${timestamp} ${message}`);
|
|
48
|
+
|
|
49
|
+
} catch (error) {
|
|
50
|
+
// Raw fallback
|
|
51
|
+
console.log(chunk);
|
|
34
52
|
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Ultimate fallback - basic JSON
|
|
38
|
-
return {
|
|
39
|
-
write: (data) => console.log(data)
|
|
40
|
-
};
|
|
41
|
-
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
42
55
|
}
|
|
43
56
|
};
|
package/package.json
CHANGED