@crimsonsunset/jsg-logger 1.0.8
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 +55 -0
- package/CONTRIBUTING.md +58 -0
- package/LICENSE +15 -0
- package/README.md +428 -0
- package/config/component-schemes.js +26 -0
- package/config/config-manager.js +378 -0
- package/config/default-config.json +92 -0
- package/docs/next-session.md +136 -0
- package/docs/roadmap.md +404 -0
- package/examples/advanced-config.json +151 -0
- package/formatters/browser-formatter.js +227 -0
- package/formatters/cli-formatter.js +43 -0
- package/formatters/server-formatter.js +42 -0
- package/index.js +413 -0
- package/package.json +74 -0
- package/stores/log-store.js +148 -0
- package/utils/environment-detector.js +38 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Manager for CACP Logger
|
|
3
|
+
* Handles loading, merging, and validation of logger configurations
|
|
4
|
+
* Implements smart level resolution and file override system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import defaultConfig from './default-config.json';
|
|
8
|
+
import {COMPONENT_SCHEME, LEVEL_SCHEME} from './component-schemes.js';
|
|
9
|
+
|
|
10
|
+
export class ConfigManager {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.config = {...defaultConfig};
|
|
13
|
+
this.loadedPaths = [];
|
|
14
|
+
this.currentFile = null; // Track current file for overrides
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Load configuration from a file path or object
|
|
19
|
+
* @param {string|Object} configSource - File path or config object
|
|
20
|
+
* @returns {Promise<Object>} Merged configuration
|
|
21
|
+
*/
|
|
22
|
+
async loadConfig(configSource) {
|
|
23
|
+
try {
|
|
24
|
+
let externalConfig = {};
|
|
25
|
+
|
|
26
|
+
if (typeof configSource === 'string') {
|
|
27
|
+
// Load from file path
|
|
28
|
+
if (configSource.startsWith('./') || configSource.startsWith('../')) {
|
|
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
|
+
}
|
|
40
|
+
} else if (typeof configSource === 'object') {
|
|
41
|
+
// Direct config object
|
|
42
|
+
externalConfig = configSource;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Merge configurations
|
|
46
|
+
this.config = this.mergeConfigs(this.config, externalConfig);
|
|
47
|
+
|
|
48
|
+
return this.config;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('ConfigManager: Error loading configuration:', error);
|
|
51
|
+
return this.config; // Return default config on error
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Set current file context for override resolution
|
|
57
|
+
* @param {string} filePath - Current file path being logged from
|
|
58
|
+
*/
|
|
59
|
+
setCurrentFile(filePath) {
|
|
60
|
+
this.currentFile = filePath;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Deep merge two configuration objects
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
mergeConfigs(base, override) {
|
|
68
|
+
const merged = {...base};
|
|
69
|
+
|
|
70
|
+
for (const key in override) {
|
|
71
|
+
if (override.hasOwnProperty(key)) {
|
|
72
|
+
if (typeof override[key] === 'object' && !Array.isArray(override[key])) {
|
|
73
|
+
merged[key] = this.mergeConfigs(merged[key] || {}, override[key]);
|
|
74
|
+
} else {
|
|
75
|
+
merged[key] = override[key];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return merged;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get effective log level using hierarchy: file override > component level > global level
|
|
85
|
+
* @param {string} componentName - Component identifier
|
|
86
|
+
* @param {string} filePath - Optional file path for override checking
|
|
87
|
+
* @returns {string} Effective log level
|
|
88
|
+
*/
|
|
89
|
+
getEffectiveLevel(componentName, filePath = null) {
|
|
90
|
+
const checkFile = filePath || this.currentFile;
|
|
91
|
+
|
|
92
|
+
// 1. Check file overrides first (highest priority)
|
|
93
|
+
if (checkFile && this.config.fileOverrides) {
|
|
94
|
+
const fileOverride = this.getFileOverride(checkFile);
|
|
95
|
+
if (fileOverride && fileOverride.level) {
|
|
96
|
+
return fileOverride.level;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 2. Check component-specific level
|
|
101
|
+
if (this.config.components && this.config.components[componentName] && this.config.components[componentName].level) {
|
|
102
|
+
return this.config.components[componentName].level;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 3. Fall back to global level
|
|
106
|
+
return this.config.globalLevel || 'info';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get file override configuration for a given file path
|
|
111
|
+
* @param {string} filePath - File path to check
|
|
112
|
+
* @returns {Object|null} File override config or null
|
|
113
|
+
*/
|
|
114
|
+
getFileOverride(filePath) {
|
|
115
|
+
if (!this.config.fileOverrides || !filePath) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Normalize file path (remove leading ./ and ../)
|
|
120
|
+
const normalizedPath = filePath.replace(/^\.\.?\//g, '');
|
|
121
|
+
|
|
122
|
+
// Check exact matches first
|
|
123
|
+
if (this.config.fileOverrides[normalizedPath]) {
|
|
124
|
+
return this.config.fileOverrides[normalizedPath];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check pattern matches
|
|
128
|
+
for (const pattern in this.config.fileOverrides) {
|
|
129
|
+
if (this.matchFilePattern(normalizedPath, pattern)) {
|
|
130
|
+
return this.config.fileOverrides[pattern];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Match file path against a pattern (supports wildcards)
|
|
139
|
+
* @param {string} filePath - File path to test
|
|
140
|
+
* @param {string} pattern - Pattern to match against
|
|
141
|
+
* @returns {boolean} Whether the file matches the pattern
|
|
142
|
+
* @private
|
|
143
|
+
*/
|
|
144
|
+
matchFilePattern(filePath, pattern) {
|
|
145
|
+
// Convert glob pattern to regex
|
|
146
|
+
const regexPattern = pattern
|
|
147
|
+
.replace(/\./g, '\\.') // Escape dots
|
|
148
|
+
.replace(/\*/g, '.*') // Convert * to .*
|
|
149
|
+
.replace(/\?/g, '.') // Convert ? to .
|
|
150
|
+
+ '$'; // End of string
|
|
151
|
+
|
|
152
|
+
const regex = new RegExp(regexPattern);
|
|
153
|
+
return regex.test(filePath);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get component configuration with file override support
|
|
158
|
+
* @param {string} componentName - Component identifier
|
|
159
|
+
* @param {string} filePath - Optional file path for override checking
|
|
160
|
+
* @returns {Object} Component configuration
|
|
161
|
+
*/
|
|
162
|
+
getComponentConfig(componentName, filePath = null) {
|
|
163
|
+
const baseComponent = this.config.components?.[componentName] || COMPONENT_SCHEME[componentName] || COMPONENT_SCHEME['cacp'];
|
|
164
|
+
|
|
165
|
+
// Check for file-specific overrides
|
|
166
|
+
const checkFile = filePath || this.currentFile;
|
|
167
|
+
if (checkFile) {
|
|
168
|
+
const fileOverride = this.getFileOverride(checkFile);
|
|
169
|
+
if (fileOverride) {
|
|
170
|
+
return {
|
|
171
|
+
...baseComponent,
|
|
172
|
+
...fileOverride,
|
|
173
|
+
level: this.getEffectiveLevel(componentName, checkFile)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
...baseComponent,
|
|
180
|
+
level: this.getEffectiveLevel(componentName, checkFile)
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get level configuration
|
|
186
|
+
* @param {number} level - Log level number
|
|
187
|
+
* @returns {Object} Level configuration
|
|
188
|
+
*/
|
|
189
|
+
getLevelConfig(level) {
|
|
190
|
+
// Check if level exists in loaded config
|
|
191
|
+
if (this.config.levels && this.config.levels[level]) {
|
|
192
|
+
return this.config.levels[level];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Fallback to default schemes
|
|
196
|
+
return LEVEL_SCHEME[level] || LEVEL_SCHEME[30];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get global log level
|
|
201
|
+
* @returns {string} Global log level
|
|
202
|
+
*/
|
|
203
|
+
getGlobalLevel() {
|
|
204
|
+
return this.config.globalLevel || 'info';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Get timestamp mode
|
|
209
|
+
* @returns {string} Timestamp mode ('absolute', 'readable', 'relative', 'disable')
|
|
210
|
+
*/
|
|
211
|
+
getTimestampMode() {
|
|
212
|
+
return this.config.timestampMode || 'absolute';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get display configuration with file override support
|
|
217
|
+
* @param {string} filePath - Optional file path for override checking
|
|
218
|
+
* @returns {Object} Display configuration
|
|
219
|
+
*/
|
|
220
|
+
getDisplayConfig(filePath = null) {
|
|
221
|
+
const baseDisplay = this.config.display || {
|
|
222
|
+
timestamp: true,
|
|
223
|
+
emoji: true,
|
|
224
|
+
component: true,
|
|
225
|
+
level: false,
|
|
226
|
+
message: true,
|
|
227
|
+
jsonPayload: true,
|
|
228
|
+
stackTrace: true
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// Check for file-specific display overrides
|
|
232
|
+
const checkFile = filePath || this.currentFile;
|
|
233
|
+
if (checkFile) {
|
|
234
|
+
const fileOverride = this.getFileOverride(checkFile);
|
|
235
|
+
if (fileOverride && fileOverride.display) {
|
|
236
|
+
return {
|
|
237
|
+
...baseDisplay,
|
|
238
|
+
...fileOverride.display
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return baseDisplay;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Get project name
|
|
248
|
+
* @returns {string} Project name
|
|
249
|
+
*/
|
|
250
|
+
getProjectName() {
|
|
251
|
+
return this.config.projectName || 'CACP Logger';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Check if auto-registration is enabled
|
|
256
|
+
* @returns {boolean} Auto-registration flag
|
|
257
|
+
*/
|
|
258
|
+
isAutoRegisterEnabled() {
|
|
259
|
+
return this.config.autoRegister !== false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get formatting configuration
|
|
264
|
+
* @returns {Object} Format configuration
|
|
265
|
+
*/
|
|
266
|
+
getFormatConfig() {
|
|
267
|
+
return this.config.format || {
|
|
268
|
+
style: 'brackets',
|
|
269
|
+
componentCase: 'upper',
|
|
270
|
+
timestamp: 'HH:mm:ss.SSS'
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get all available components
|
|
276
|
+
* @returns {Array} Array of component names
|
|
277
|
+
*/
|
|
278
|
+
getAvailableComponents() {
|
|
279
|
+
const configComponents = Object.keys(this.config.components || {});
|
|
280
|
+
const schemeComponents = Object.keys(COMPONENT_SCHEME);
|
|
281
|
+
|
|
282
|
+
// Combine and deduplicate
|
|
283
|
+
return [...new Set([...configComponents, ...schemeComponents])];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Add or update a component configuration
|
|
288
|
+
* @param {string} componentName - Component identifier
|
|
289
|
+
* @param {Object} componentConfig - Component configuration
|
|
290
|
+
*/
|
|
291
|
+
addComponent(componentName, componentConfig) {
|
|
292
|
+
if (!this.config.components) {
|
|
293
|
+
this.config.components = {};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
this.config.components[componentName] = {
|
|
297
|
+
...this.getComponentConfig(componentName),
|
|
298
|
+
...componentConfig
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Add or update a file override
|
|
304
|
+
* @param {string} filePath - File path or pattern
|
|
305
|
+
* @param {Object} overrideConfig - Override configuration
|
|
306
|
+
*/
|
|
307
|
+
addFileOverride(filePath, overrideConfig) {
|
|
308
|
+
if (!this.config.fileOverrides) {
|
|
309
|
+
this.config.fileOverrides = {};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
this.config.fileOverrides[filePath] = overrideConfig;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Format timestamp based on mode
|
|
317
|
+
* @param {number} timestamp - Unix timestamp
|
|
318
|
+
* @param {string} mode - Timestamp mode
|
|
319
|
+
* @returns {string} Formatted timestamp
|
|
320
|
+
*/
|
|
321
|
+
formatTimestamp(timestamp, mode = null) {
|
|
322
|
+
const timestampMode = mode || this.getTimestampMode();
|
|
323
|
+
const date = new Date(timestamp);
|
|
324
|
+
|
|
325
|
+
switch (timestampMode) {
|
|
326
|
+
case 'readable':
|
|
327
|
+
return date.toLocaleTimeString('en-US', {
|
|
328
|
+
hour: 'numeric',
|
|
329
|
+
minute: '2-digit',
|
|
330
|
+
hour12: true
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
case 'relative':
|
|
334
|
+
const now = Date.now();
|
|
335
|
+
const diff = now - timestamp;
|
|
336
|
+
|
|
337
|
+
if (diff < 1000) return 'now';
|
|
338
|
+
if (diff < 60000) return `${Math.floor(diff / 1000)}s ago`;
|
|
339
|
+
if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
|
|
340
|
+
return `${Math.floor(diff / 3600000)}h ago`;
|
|
341
|
+
|
|
342
|
+
case 'disable':
|
|
343
|
+
return '';
|
|
344
|
+
|
|
345
|
+
case 'absolute':
|
|
346
|
+
default:
|
|
347
|
+
return date.toLocaleTimeString('en-US', {
|
|
348
|
+
hour12: false,
|
|
349
|
+
hour: '2-digit',
|
|
350
|
+
minute: '2-digit',
|
|
351
|
+
second: '2-digit',
|
|
352
|
+
fractionalSecondDigits: 3
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Get configuration summary for debugging
|
|
359
|
+
* @returns {Object} Configuration summary
|
|
360
|
+
*/
|
|
361
|
+
getSummary() {
|
|
362
|
+
return {
|
|
363
|
+
projectName: this.getProjectName(),
|
|
364
|
+
globalLevel: this.getGlobalLevel(),
|
|
365
|
+
timestampMode: this.getTimestampMode(),
|
|
366
|
+
loadedPaths: this.loadedPaths,
|
|
367
|
+
componentCount: this.getAvailableComponents().length,
|
|
368
|
+
fileOverrideCount: Object.keys(this.config.fileOverrides || {}).length,
|
|
369
|
+
autoRegister: this.isAutoRegisterEnabled(),
|
|
370
|
+
format: this.getFormatConfig(),
|
|
371
|
+
display: this.getDisplayConfig(),
|
|
372
|
+
currentFile: this.currentFile
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Create singleton instance
|
|
378
|
+
export const configManager = new ConfigManager();
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"projectName": "CACP Logger",
|
|
3
|
+
"globalLevel": "info",
|
|
4
|
+
"autoRegister": true,
|
|
5
|
+
"format": {
|
|
6
|
+
"style": "brackets",
|
|
7
|
+
"componentCase": "upper",
|
|
8
|
+
"timestamp": "HH:mm:ss.SSS"
|
|
9
|
+
},
|
|
10
|
+
"timestampMode": "absolute",
|
|
11
|
+
"display": {
|
|
12
|
+
"timestamp": true,
|
|
13
|
+
"emoji": true,
|
|
14
|
+
"component": true,
|
|
15
|
+
"level": false,
|
|
16
|
+
"message": true,
|
|
17
|
+
"jsonPayload": true,
|
|
18
|
+
"stackTrace": true
|
|
19
|
+
},
|
|
20
|
+
"levels": {
|
|
21
|
+
"10": { "name": "TRACE", "emoji": "π", "color": "#6C7B7F" },
|
|
22
|
+
"20": { "name": "DEBUG", "emoji": "π", "color": "#74B9FF" },
|
|
23
|
+
"30": { "name": "INFO", "emoji": "β¨", "color": "#00B894" },
|
|
24
|
+
"40": { "name": "WARN", "emoji": "β οΈ", "color": "#FDCB6E" },
|
|
25
|
+
"50": { "name": "ERROR", "emoji": "π¨", "color": "#E17055" },
|
|
26
|
+
"60": { "name": "FATAL", "emoji": "π", "color": "#D63031" }
|
|
27
|
+
},
|
|
28
|
+
"components": {
|
|
29
|
+
"cacp": {
|
|
30
|
+
"emoji": "π―",
|
|
31
|
+
"color": "#4A90E2",
|
|
32
|
+
"name": "CACP-Core",
|
|
33
|
+
"level": "info"
|
|
34
|
+
},
|
|
35
|
+
"soundcloud": {
|
|
36
|
+
"emoji": "π΅",
|
|
37
|
+
"color": "#FF5500",
|
|
38
|
+
"name": "SoundCloud",
|
|
39
|
+
"level": "info"
|
|
40
|
+
},
|
|
41
|
+
"youtube": {
|
|
42
|
+
"emoji": "πΉ",
|
|
43
|
+
"color": "#FF0000",
|
|
44
|
+
"name": "YouTube",
|
|
45
|
+
"level": "info"
|
|
46
|
+
},
|
|
47
|
+
"site-detector": {
|
|
48
|
+
"emoji": "π",
|
|
49
|
+
"color": "#00C896",
|
|
50
|
+
"name": "SiteDetector",
|
|
51
|
+
"level": "info"
|
|
52
|
+
},
|
|
53
|
+
"websocket": {
|
|
54
|
+
"emoji": "π",
|
|
55
|
+
"color": "#9B59B6",
|
|
56
|
+
"name": "WebSocket",
|
|
57
|
+
"level": "info"
|
|
58
|
+
},
|
|
59
|
+
"popup": {
|
|
60
|
+
"emoji": "ποΈ",
|
|
61
|
+
"color": "#FF6B6B",
|
|
62
|
+
"name": "Popup",
|
|
63
|
+
"level": "info"
|
|
64
|
+
},
|
|
65
|
+
"background": {
|
|
66
|
+
"emoji": "π§",
|
|
67
|
+
"color": "#4ECDC4",
|
|
68
|
+
"name": "Background",
|
|
69
|
+
"level": "info"
|
|
70
|
+
},
|
|
71
|
+
"priority-manager": {
|
|
72
|
+
"emoji": "βοΈ",
|
|
73
|
+
"color": "#45B7D1",
|
|
74
|
+
"name": "PriorityManager",
|
|
75
|
+
"level": "info"
|
|
76
|
+
},
|
|
77
|
+
"settings": {
|
|
78
|
+
"emoji": "βοΈ",
|
|
79
|
+
"color": "#96CEB4",
|
|
80
|
+
"name": "Settings",
|
|
81
|
+
"level": "info"
|
|
82
|
+
},
|
|
83
|
+
"test": {
|
|
84
|
+
"emoji": "π§ͺ",
|
|
85
|
+
"color": "#FFEAA7",
|
|
86
|
+
"name": "Test",
|
|
87
|
+
"level": "debug"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"fileOverrides": {
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# JSG Logger - Session Summary
|
|
2
|
+
|
|
3
|
+
## π How to Update This Doc
|
|
4
|
+
|
|
5
|
+
**This is a working document that gets refreshed each session:**
|
|
6
|
+
1. **Wipe accomplished items** - Remove completed tasks and achievements
|
|
7
|
+
2. **Keep undone items** - Leave incomplete tasks for tracking purposes
|
|
8
|
+
3. **Add new priorities** - Include new tasks and blockers that emerge
|
|
9
|
+
4. **Update current state** - Reflect what's working vs what needs attention
|
|
10
|
+
|
|
11
|
+
**Key difference from roadmap.md:**
|
|
12
|
+
- **This file:** Working session notes, gets refreshed as tasks complete
|
|
13
|
+
- **Roadmap.md:** Permanent historical record, accumulates progress over time
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
**Date:** August 6, 2025
|
|
18
|
+
**Session Goal:** π― **COMPLETE** - β
Logger extraction, NPM publication, and documentation structure
|
|
19
|
+
**Next Session Goal:** π¨ **DevTools Panel Implementation** - Browser-based log filtering interface (optional enhancement)
|
|
20
|
+
|
|
21
|
+
## π MAJOR ACCOMPLISHMENTS THIS SESSION
|
|
22
|
+
|
|
23
|
+
### β
Logger Extraction & NPM Publication COMPLETE
|
|
24
|
+
- **π¦ NPM Package** - Published `@crimsonsunset/jsg-logger` v1.0.6 to registry
|
|
25
|
+
- **π§ Automated Scripts** - Added `npm run release` for easy version management
|
|
26
|
+
- **π Repository Migration** - Successfully extracted from DeskThing-Apps to standalone repo
|
|
27
|
+
- **π Integration Success** - DeskThing-Apps now uses published package instead of local folder
|
|
28
|
+
- **π§Ή Cleanup Complete** - Removed old logger folder from DeskThing-Apps
|
|
29
|
+
|
|
30
|
+
### β
Documentation Structure COMPLETE
|
|
31
|
+
- **π LICENSE** - Added ISC license file with proper copyright
|
|
32
|
+
- **π CHANGELOG.md** - Version history tracking with semantic versioning
|
|
33
|
+
- **π€ CONTRIBUTING.md** - Guidelines for future contributors
|
|
34
|
+
- **π docs/ Folder** - Professional documentation structure
|
|
35
|
+
- **πΊοΈ roadmap.md** - Comprehensive project roadmap with phases
|
|
36
|
+
- **π next-session.md** - Working session tracking template
|
|
37
|
+
|
|
38
|
+
### β
Legal & Professional Polish COMPLETE
|
|
39
|
+
- **βοΈ ISC License** - "AS IS" liability protection with permissive usage
|
|
40
|
+
- **π‘οΈ Disclaimer** - Clear legal protection in README
|
|
41
|
+
- **π Package Metadata** - Professional NPM package with proper keywords
|
|
42
|
+
- **π Repository Links** - GitHub links for issues, bugs, and homepage
|
|
43
|
+
|
|
44
|
+
## π― Current Status
|
|
45
|
+
|
|
46
|
+
### **Project State: Feature Complete & Stable** β
|
|
47
|
+
- **Core Logger**: Multi-environment logging working perfectly
|
|
48
|
+
- **NPM Package**: Published and successfully integrated
|
|
49
|
+
- **Documentation**: Comprehensive and professional
|
|
50
|
+
- **Legal Protection**: ISC license with "AS IS" disclaimer
|
|
51
|
+
|
|
52
|
+
### **What's Working Well**
|
|
53
|
+
- β
**Beautiful Console Output** - Direct browser logger with perfect formatting
|
|
54
|
+
- β
**Runtime Controls** - Dynamic configuration without restarts
|
|
55
|
+
- β
**File-Level Precision** - Surgical debugging capabilities
|
|
56
|
+
- β
**Multi-Environment** - Seamless browser/CLI/server support
|
|
57
|
+
- β
**Professional Package** - NPM-ready with automated publishing
|
|
58
|
+
|
|
59
|
+
### **No Known Issues**
|
|
60
|
+
- **Zero critical bugs** - Logger is stable and tested
|
|
61
|
+
- **Clean Integration** - DeskThing-Apps migration successful
|
|
62
|
+
- **Documentation Complete** - All standard files in place
|
|
63
|
+
|
|
64
|
+
## π CURRENT PRIORITIES
|
|
65
|
+
|
|
66
|
+
### **No Immediate Tasks** β
|
|
67
|
+
- **Logger is feature complete** - Core functionality fully implemented
|
|
68
|
+
- **Documentation structure complete** - All standard files added
|
|
69
|
+
- **NPM package stable** - Version 1.0.6 published and working
|
|
70
|
+
|
|
71
|
+
### **Optional Future Enhancements** (Low Priority)
|
|
72
|
+
- [ ] **DevTools Panel** - Browser-based log filtering interface
|
|
73
|
+
- Runtime-injected widget with Preact
|
|
74
|
+
- Collapsible sidebar from left side
|
|
75
|
+
- Controls console filtering without displaying logs
|
|
76
|
+
- IndexedDB persistence for panel state
|
|
77
|
+
- [ ] **Performance Monitoring** - Track logging overhead metrics
|
|
78
|
+
- [ ] **Export Utilities** - Save logs to file formats
|
|
79
|
+
- [ ] **Framework Integration Guides** - React, Vue, Svelte examples
|
|
80
|
+
|
|
81
|
+
## π§ Technical Notes
|
|
82
|
+
|
|
83
|
+
### **NPM Publishing Lessons Learned**
|
|
84
|
+
- **Scoped Packages** - Need `--access public` for free publishing
|
|
85
|
+
- **Internal Imports** - Required multiple patch versions (1.0.1-1.0.4) to fix relative paths
|
|
86
|
+
- **Automated Scripts** - `npm run release` handles version bump + publish in one command
|
|
87
|
+
|
|
88
|
+
### **Architecture Highlights**
|
|
89
|
+
- **Browser Logger Breakthrough** - Bypassing Pino for 100% console control
|
|
90
|
+
- **Hierarchical Config** - File > Component > Global precedence
|
|
91
|
+
- **Environment Detection** - Feature detection over user agent parsing
|
|
92
|
+
- **Runtime API** - Complete `logger.controls` interface for dynamic changes
|
|
93
|
+
|
|
94
|
+
### **Integration Success**
|
|
95
|
+
- **Vite Alias Removal** - Cleanly replaced `@logger` alias with NPM import
|
|
96
|
+
- **Build Compatibility** - Extension builds successfully with published package
|
|
97
|
+
- **Zero Disruption** - Existing DeskThing functionality unchanged
|
|
98
|
+
|
|
99
|
+
## π― Next Session Possibilities
|
|
100
|
+
|
|
101
|
+
### **If Continuing Development** (Optional)
|
|
102
|
+
1. **DevTools Panel** - Browser interface for log filtering
|
|
103
|
+
- Use existing `logger.controls` API (no custom filter engine needed)
|
|
104
|
+
- Preact for minimal bundle size
|
|
105
|
+
- IndexedDB for persistence
|
|
106
|
+
- Runtime injection pattern
|
|
107
|
+
|
|
108
|
+
2. **Community Features** (If demand exists)
|
|
109
|
+
- Framework integration examples
|
|
110
|
+
- Performance monitoring dashboard
|
|
111
|
+
- Export/import configuration utilities
|
|
112
|
+
|
|
113
|
+
### **If Project Maintenance Mode**
|
|
114
|
+
- **Monitor NPM usage** - See if package gains adoption
|
|
115
|
+
- **Address issues** - Respond to bug reports or feature requests
|
|
116
|
+
- **Version updates** - Maintain dependencies and compatibility
|
|
117
|
+
|
|
118
|
+
## π Session Metrics
|
|
119
|
+
|
|
120
|
+
### **Documentation Added**
|
|
121
|
+
- LICENSE (ISC) - 15 lines
|
|
122
|
+
- CHANGELOG.md - 45 lines with full version history
|
|
123
|
+
- CONTRIBUTING.md - 65 lines with guidelines
|
|
124
|
+
- docs/roadmap.md - 280+ lines comprehensive roadmap
|
|
125
|
+
- docs/next-session.md - 130+ lines session template
|
|
126
|
+
|
|
127
|
+
### **NPM Package Health**
|
|
128
|
+
- **Version**: 1.0.6 (stable)
|
|
129
|
+
- **Size**: 16.1 kB compressed, 65.0 kB unpacked
|
|
130
|
+
- **Files**: 12 files published
|
|
131
|
+
- **Dependencies**: Only pino for server environments
|
|
132
|
+
- **License**: ISC with "AS IS" protection
|
|
133
|
+
|
|
134
|
+
### **Project Completion Status**: 100% Core Features β
|
|
135
|
+
|
|
136
|
+
**The JSG Logger is now a complete, professional, reusable NPM package with comprehensive documentation and legal protection.**
|