Files
picpeak/backend/src/utils/errors.js
T
Paul Nothaft 0da45e699a feat: Add CSS template system with custom gallery styling support
## Changes

### CSS Template System
- Added CSS class hooks to gallery components for custom template targeting
- Gallery sidebar, header, footer, and photo cards can now be styled via CSS templates
- CSS variables on :root allow themes to override colors, effects, and spacing

### Gallery Component CSS Classes Added
- `.gallery-page` - Main gallery container
- `.gallery-header` - Top header bar
- `.gallery-sidebar` - Filter/download sidebar
- `.gallery-sidebar-header`, `.gallery-sidebar-title`, `.gallery-sidebar-close`
- `.gallery-sidebar-content`, `.gallery-sidebar-section`
- `.gallery-sidebar-search-input`, `.gallery-sidebar-search-icon`
- `.gallery-sidebar-backdrop` - Mobile overlay
- `.gallery-btn`, `.gallery-btn-download` - Sidebar buttons
- `.gallery-footer` - Footer section
- `.photo-card`, `.photo-grid` - Photo display elements

### CSS Templates (Database)
- Elegant Dark (id=1): Dark navy theme with light text and red accents
- Liquid Glass Light (id=2): iOS 26 frosted glass effect with gradient background

### Bug Fixes
- Fixed CSS variables not inheriting (moved from .gallery-page to :root)
- Fixed sidebar position breaking layout (removed position: relative override)
- Fixed Elegant Dark sidebar text visibility (white on white issue)

### Other Changes
- Settings page refactoring and cleanup
- i18n locale updates for new gallery features
- Vite proxy port configuration fix
- Admin auth route improvements
- CSS templates service updates
2026-01-03 08:59:01 +01:00

122 lines
2.9 KiB
JavaScript

/**
* Custom error classes for standardized error handling across the application.
* These errors are caught by the global error handler and converted to appropriate HTTP responses.
*/
/**
* Base class for operational errors (expected errors that can occur during normal operation)
*/
class AppError extends Error {
constructor(message, statusCode = 500, code = 'INTERNAL_ERROR') {
super(message);
this.statusCode = statusCode;
this.code = code;
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
toJSON() {
return {
error: this.message,
code: this.code,
...(process.env.NODE_ENV === 'development' && { stack: this.stack })
};
}
}
/**
* Validation error - for invalid input data (400 Bad Request)
*/
class ValidationError extends AppError {
constructor(message = 'Validation failed', details = null) {
super(message, 400, 'VALIDATION_ERROR');
this.details = details;
}
toJSON() {
return {
...super.toJSON(),
...(this.details && { details: this.details })
};
}
}
/**
* Not found error - for resources that don't exist (404 Not Found)
*/
class NotFoundError extends AppError {
constructor(resource = 'Resource', identifier = null) {
const message = identifier
? `${resource} with identifier '${identifier}' not found`
: `${resource} not found`;
super(message, 404, 'NOT_FOUND');
this.resource = resource;
this.identifier = identifier;
}
}
/**
* Unauthorized error - for missing or invalid authentication (401 Unauthorized)
*/
class UnauthorizedError extends AppError {
constructor(message = 'Authentication required') {
super(message, 401, 'UNAUTHORIZED');
}
}
/**
* Forbidden error - for insufficient permissions (403 Forbidden)
*/
class ForbiddenError extends AppError {
constructor(message = 'Access denied') {
super(message, 403, 'FORBIDDEN');
}
}
/**
* Conflict error - for resource conflicts (409 Conflict)
*/
class ConflictError extends AppError {
constructor(message = 'Resource conflict', field = null) {
super(message, 409, 'CONFLICT');
this.field = field;
}
toJSON() {
return {
...super.toJSON(),
...(this.field && { field: this.field })
};
}
}
/**
* Rate limit error - for too many requests (429 Too Many Requests)
*/
class RateLimitError extends AppError {
constructor(message = 'Too many requests', retryAfter = null) {
super(message, 429, 'RATE_LIMIT_EXCEEDED');
this.retryAfter = retryAfter;
}
}
/**
* Service unavailable error - for maintenance mode or service issues (503 Service Unavailable)
*/
class ServiceUnavailableError extends AppError {
constructor(message = 'Service temporarily unavailable') {
super(message, 503, 'SERVICE_UNAVAILABLE');
}
}
module.exports = {
AppError,
ValidationError,
NotFoundError,
UnauthorizedError,
ForbiddenError,
ConflictError,
RateLimitError,
ServiceUnavailableError
};