mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
2.13.0 code, but not yet released. Manifest version not updated
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
This commit is contained in:
137
src/utils/ErrorHandler.ts
Normal file
137
src/utils/ErrorHandler.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { Notice } from "obsidian";
|
||||
import { debug, DEBUGGING } from "./debugHelper";
|
||||
|
||||
/**
|
||||
* Centralized error handling for the Excalidraw plugin
|
||||
*/
|
||||
export class ErrorHandler {
|
||||
private static instance: ErrorHandler;
|
||||
private errorLog: Array<{error: Error, context: string, timestamp: number}> = [];
|
||||
private errorNoticeTimeout: number = 10000; // 10 seconds
|
||||
private maxLogEntries: number = 100;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
/**
|
||||
* Get singleton instance of ErrorHandler
|
||||
*/
|
||||
public static getInstance(): ErrorHandler {
|
||||
if (!ErrorHandler.instance) {
|
||||
ErrorHandler.instance = new ErrorHandler();
|
||||
}
|
||||
return ErrorHandler.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles errors consistently across the plugin
|
||||
* @param error The error object
|
||||
* @param context Context information about where the error occurred
|
||||
* @param showNotice Whether to show a user-facing notice
|
||||
* @param timeout How long to show the notice (in ms)
|
||||
*/
|
||||
public handleError(
|
||||
error: Error | string,
|
||||
context: string,
|
||||
showNotice = true,
|
||||
timeout?: number
|
||||
): void {
|
||||
const errorObj = typeof error === 'string' ? new Error(error) : error;
|
||||
|
||||
// Log to console with better formatting
|
||||
console.error(`[Excalidraw Error] in ${context}:`, errorObj);
|
||||
|
||||
// Add to error log with timestamp
|
||||
this.errorLog.push({
|
||||
error: errorObj,
|
||||
context,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Trim log if it gets too large
|
||||
if (this.errorLog.length > this.maxLogEntries) {
|
||||
this.errorLog = this.errorLog.slice(this.errorLog.length - this.maxLogEntries);
|
||||
}
|
||||
|
||||
// Show notice to user if required
|
||||
if (showNotice) {
|
||||
const formattedError = this.formatErrorForUser(errorObj, context);
|
||||
new Notice(formattedError, timeout || this.errorNoticeTimeout);
|
||||
}
|
||||
|
||||
// Debug output if debugging is enabled
|
||||
if ((process.env.NODE_ENV === 'development') && DEBUGGING) {
|
||||
debug(this.handleError, `ErrorHandler.handleError: ${context}`, errorObj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely evaluates code with error handling
|
||||
* @param code The code to evaluate
|
||||
* @param context The context where evaluation is happening
|
||||
* @param win The window object for evaluation context
|
||||
* @param fallback Optional fallback value if evaluation fails
|
||||
*/
|
||||
public safeEval<T>(code: string, context: string, win: Window, fallback?: T): T {
|
||||
try {
|
||||
return win.eval.call(win, code) as T;
|
||||
} catch (error) {
|
||||
this.handleError(error, `SafeEval in ${context}`);
|
||||
if (fallback !== undefined) {
|
||||
return fallback;
|
||||
}
|
||||
throw error; // Re-throw if no fallback provided
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a function with try/catch and error handling
|
||||
* @param fn Function to wrap
|
||||
* @param context Context for error reporting
|
||||
* @param fallback Optional fallback value if function fails
|
||||
*/
|
||||
public wrapWithTryCatch<T>(fn: () => T, context: string, fallback?: T): T {
|
||||
try {
|
||||
return fn();
|
||||
} catch (error) {
|
||||
this.handleError(error, context);
|
||||
if (fallback !== undefined) return fallback;
|
||||
throw error; // Re-throw if no fallback provided
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format error message for user-facing notifications
|
||||
*/
|
||||
private formatErrorForUser(error: Error, context: string): string {
|
||||
// Shorten and simplify the message for users
|
||||
let message = error.message;
|
||||
|
||||
// Special handling for common error types
|
||||
if (message.includes("Cannot read properties of undefined")) {
|
||||
message = "A required object was not available. This might be due to a plugin loading issue.";
|
||||
} else if (message.includes("is not a function")) {
|
||||
message = "A required function was not available. This might be due to a plugin version mismatch.";
|
||||
} else if (message.length > 100) {
|
||||
// Truncate very long messages
|
||||
message = message.substring(0, 100) + "...";
|
||||
}
|
||||
|
||||
return `Excalidraw Error: ${message} (in ${context})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recent errors for debugging
|
||||
*/
|
||||
public getErrorLog(): Array<{error: Error, context: string, timestamp: number}> {
|
||||
return [...this.errorLog];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear error log
|
||||
*/
|
||||
public clearErrorLog(): void {
|
||||
this.errorLog = [];
|
||||
}
|
||||
}
|
||||
|
||||
export const errorHandler = ErrorHandler.getInstance();
|
||||
Reference in New Issue
Block a user