feat(extension): complete VS Code extension with kanban board interface (#997)
--------- Co-authored-by: DavidMaliglowka <13022280+DavidMaliglowka@users.noreply.github.com> Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
155
apps/extension/src/webview/utils/logger.ts
Normal file
155
apps/extension/src/webview/utils/logger.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Webview Logger Utility
|
||||
* Provides conditional logging based on environment
|
||||
*/
|
||||
|
||||
type LogLevel = 'log' | 'warn' | 'error' | 'debug' | 'info';
|
||||
|
||||
interface LogEntry {
|
||||
level: LogLevel;
|
||||
message: string;
|
||||
data?: any;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
class WebviewLogger {
|
||||
private static instance: WebviewLogger;
|
||||
private enabled: boolean;
|
||||
private logHistory: LogEntry[] = [];
|
||||
private maxHistorySize = 100;
|
||||
|
||||
private constructor() {
|
||||
// Enable logging in development, disable in production
|
||||
// Check for development mode via various indicators
|
||||
this.enabled = this.isDevelopment();
|
||||
}
|
||||
|
||||
static getInstance(): WebviewLogger {
|
||||
if (!WebviewLogger.instance) {
|
||||
WebviewLogger.instance = new WebviewLogger();
|
||||
}
|
||||
return WebviewLogger.instance;
|
||||
}
|
||||
|
||||
private isDevelopment(): boolean {
|
||||
// Check various indicators for development mode
|
||||
// VS Code webviews don't have process.env, so we check other indicators
|
||||
return (
|
||||
// Check if running in localhost (development server)
|
||||
window.location.hostname === 'localhost' ||
|
||||
// Check for development query parameter
|
||||
window.location.search.includes('debug=true') ||
|
||||
// Check for VS Code development mode indicator
|
||||
(window as any).__VSCODE_DEV_MODE__ === true ||
|
||||
// Default to false in production
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
private addToHistory(entry: LogEntry): void {
|
||||
this.logHistory.push(entry);
|
||||
if (this.logHistory.length > this.maxHistorySize) {
|
||||
this.logHistory.shift();
|
||||
}
|
||||
}
|
||||
|
||||
private logMessage(level: LogLevel, message: string, ...args: any[]): void {
|
||||
const entry: LogEntry = {
|
||||
level,
|
||||
message,
|
||||
data: args.length > 0 ? args : undefined,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
this.addToHistory(entry);
|
||||
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the message with timestamp
|
||||
const timestamp = new Date().toISOString();
|
||||
const prefix = `[${timestamp}] [${level.toUpperCase()}]`;
|
||||
|
||||
// Use appropriate console method
|
||||
switch (level) {
|
||||
case 'error':
|
||||
console.error(prefix, message, ...args);
|
||||
break;
|
||||
case 'warn':
|
||||
console.warn(prefix, message, ...args);
|
||||
break;
|
||||
case 'debug':
|
||||
console.debug(prefix, message, ...args);
|
||||
break;
|
||||
case 'info':
|
||||
console.info(prefix, message, ...args);
|
||||
break;
|
||||
default:
|
||||
console.log(prefix, message, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
log(message: string, ...args: any[]): void {
|
||||
this.logMessage('log', message, ...args);
|
||||
}
|
||||
|
||||
error(message: string, ...args: any[]): void {
|
||||
// Always log errors, even in production
|
||||
const entry: LogEntry = {
|
||||
level: 'error',
|
||||
message,
|
||||
data: args.length > 0 ? args : undefined,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
this.addToHistory(entry);
|
||||
console.error(`[${new Date().toISOString()}] [ERROR]`, message, ...args);
|
||||
}
|
||||
|
||||
warn(message: string, ...args: any[]): void {
|
||||
this.logMessage('warn', message, ...args);
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
this.logMessage('debug', message, ...args);
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
this.logMessage('info', message, ...args);
|
||||
}
|
||||
|
||||
// Enable/disable logging dynamically
|
||||
setEnabled(enabled: boolean): void {
|
||||
this.enabled = enabled;
|
||||
if (enabled) {
|
||||
console.log('[WebviewLogger] Logging enabled');
|
||||
}
|
||||
}
|
||||
|
||||
// Get log history (useful for debugging)
|
||||
getHistory(): LogEntry[] {
|
||||
return [...this.logHistory];
|
||||
}
|
||||
|
||||
// Clear log history
|
||||
clearHistory(): void {
|
||||
this.logHistory = [];
|
||||
}
|
||||
|
||||
// Export logs as string (useful for bug reports)
|
||||
exportLogs(): string {
|
||||
return this.logHistory
|
||||
.map((entry) => {
|
||||
const timestamp = new Date(entry.timestamp).toISOString();
|
||||
const data = entry.data ? JSON.stringify(entry.data) : '';
|
||||
return `[${timestamp}] [${entry.level.toUpperCase()}] ${entry.message} ${data}`;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
export const logger = WebviewLogger.getInstance();
|
||||
|
||||
// Export type for use in other files
|
||||
export type { WebviewLogger };
|
||||
Reference in New Issue
Block a user