Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | 14x 14x 14x 14x 14x 1x 2x 1x 1x 3x 1x 8x 17x 17x 1x 1x 16x 15x 1x | // SPDX-License-Identifier: MIT
/**
* Centralized error handling for Turbo Themes.
*
* Provides a consistent error logging strategy with standardized message
* formatting, error levels, and optional context for debugging.
*/
/** Log prefix for all theme-related messages */
export const LOG_PREFIX = '[turbo-themes]';
/** Error severity levels */
export enum ErrorLevel {
WARN = 'warn',
ERROR = 'error',
}
/** Structured theme error with code, message, level, and optional context */
export interface ThemeError {
code: string;
message: string;
level: ErrorLevel;
context?: Record<string, unknown>;
}
/**
* Factory functions for creating structured theme errors.
* Each function returns a ThemeError with appropriate code, message, and level.
*/
export const ThemeErrors = {
/** Invalid theme ID provided */
INVALID_THEME_ID: (themeId: string): ThemeError => ({
code: 'INVALID_THEME_ID',
message: `Invalid theme ID "${themeId}" not saved to storage`,
level: ErrorLevel.WARN,
context: { themeId },
}),
/** No themes available in registry */
NO_THEMES_AVAILABLE: (): ThemeError => ({
code: 'NO_THEMES_AVAILABLE',
message: 'No themes available',
level: ErrorLevel.ERROR,
}),
/** Invalid theme icon path */
INVALID_ICON_PATH: (themeId: string): ThemeError => ({
code: 'INVALID_ICON_PATH',
message: `Invalid theme icon path for ${themeId}`,
level: ErrorLevel.WARN,
context: { themeId },
}),
/** Theme initialization failed */
INIT_FAILED: (error: unknown): ThemeError => ({
code: 'INIT_FAILED',
message: 'Theme switcher initialization failed',
level: ErrorLevel.ERROR,
context: { error: error instanceof Error ? error.message : String(error) },
}),
/** Protocol-relative URL rejected for security */
PROTOCOL_REJECTED: (): ThemeError => ({
code: 'PROTOCOL_REJECTED',
message: 'Protocol-relative base URL rejected for security',
level: ErrorLevel.WARN,
}),
/** Insecure HTTP URL rejected */
INSECURE_HTTP_REJECTED: (): ThemeError => ({
code: 'INSECURE_HTTP_REJECTED',
message: 'Insecure HTTP base URL rejected',
level: ErrorLevel.WARN,
}),
/** Cross-origin URL rejected */
CROSS_ORIGIN_REJECTED: (origin: string): ThemeError => ({
code: 'CROSS_ORIGIN_REJECTED',
message: `Cross-origin base URL rejected: ${origin}`,
level: ErrorLevel.WARN,
context: { origin },
}),
/** Invalid CSS path for theme */
INVALID_CSS_PATH: (themeId: string): ThemeError => ({
code: 'INVALID_CSS_PATH',
message: `Invalid theme CSS path for ${themeId}`,
level: ErrorLevel.WARN,
context: { themeId },
}),
/** CSS failed to load */
CSS_LOAD_FAILED: (themeId: string, error: unknown): ThemeError => ({
code: 'CSS_LOAD_FAILED',
message: `Theme CSS failed to load for ${themeId}`,
level: ErrorLevel.WARN,
context: {
themeId,
error: error instanceof Error ? error.message : String(error),
},
}),
/** Storage unavailable (private browsing or disabled) */
STORAGE_UNAVAILABLE: (operation: string, error: unknown): ThemeError => ({
code: 'STORAGE_UNAVAILABLE',
message: `localStorage ${operation} failed - storage may be unavailable`,
level: ErrorLevel.WARN,
context: {
operation,
error: error instanceof Error ? error.message : String(error),
},
}),
};
/**
* Log a theme error to the console with consistent formatting.
*
* @param themeError - The structured error to log
*/
export function logThemeError(themeError: ThemeError): void {
const prefixedMessage = `${LOG_PREFIX} ${themeError.message}`;
if (themeError.level === ErrorLevel.ERROR) {
if (themeError.context) {
console.error(prefixedMessage, themeError.context);
} else E{
console.error(prefixedMessage);
}
} else {
if (themeError.context) {
console.warn(prefixedMessage, themeError.context);
} else {
console.warn(prefixedMessage);
}
}
}
/**
* Convenience function to log a ThemeError.
*
* @param error - The ThemeError instance to log
*/
export function logError<T extends ThemeError>(error: T): void {
logThemeError(error);
}
|