Remove SyncService and introduce context-based offline mode and state management
- Delete `SyncService` and its associated bidirectional synchronization logic. - Add multiple context providers (`OfflineProvider`, `AlertProvider`, `LangContext`, `UserContext`, `SessionContext`, `WorldContext`, `SettingBookContext`) for contextual state management. - Implement `SecureStorage` for OS-level secure data encryption and replace dependency on `SyncService` synchronization. - Update localization files (`en.json`, `fr.json`) with offline mode and error-related strings.
This commit is contained in:
106
lib/utils/db-error-handler.ts
Normal file
106
lib/utils/db-error-handler.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Database Error Handler for Frontend
|
||||
* Handles errors from Electron IPC calls
|
||||
*/
|
||||
|
||||
export interface SerializedError {
|
||||
name: string;
|
||||
message: string;
|
||||
messageFr: string;
|
||||
messageEn: string;
|
||||
statusCode: number;
|
||||
stack?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if error is a serialized database error
|
||||
*/
|
||||
export function isDbError(error: unknown): error is SerializedError {
|
||||
return (
|
||||
typeof error === 'object' &&
|
||||
error !== null &&
|
||||
'name' in error &&
|
||||
'messageFr' in error &&
|
||||
'messageEn' in error &&
|
||||
'statusCode' in error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error message based on current language
|
||||
*/
|
||||
export function getErrorMessage(error: SerializedError, lang: 'fr' | 'en' = 'fr'): string {
|
||||
return lang === 'fr' ? error.messageFr : error.messageEn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle database operation with error catching
|
||||
* Use this to wrap all IPC calls
|
||||
*/
|
||||
export async function handleDbOperation<T>(
|
||||
operation: () => Promise<T>,
|
||||
onError?: (error: SerializedError) => void,
|
||||
lang: 'fr' | 'en' = 'fr'
|
||||
): Promise<T> {
|
||||
try {
|
||||
return await operation();
|
||||
} catch (error: unknown) {
|
||||
if (isDbError(error)) {
|
||||
const errorMessage = getErrorMessage(error, lang);
|
||||
console.error(`[DB Error ${error.statusCode}]: ${errorMessage}`);
|
||||
|
||||
if (onError) {
|
||||
onError(error);
|
||||
} else {
|
||||
// Default: throw with localized message
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// Not a database error, rethrow as-is
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* React Hook for database operations
|
||||
* Example usage in a React component:
|
||||
*
|
||||
* const { data, error, loading, execute } = useDbOperation();
|
||||
*
|
||||
* const loadBooks = async () => {
|
||||
* await execute(() => window.electron.invoke('db:book:getAll'));
|
||||
* };
|
||||
*/
|
||||
export function useDbOperation<T>() {
|
||||
const [data, setData] = React.useState<T | null>(null);
|
||||
const [error, setError] = React.useState<SerializedError | null>(null);
|
||||
const [loading, setLoading] = React.useState<boolean>(false);
|
||||
|
||||
const execute = async (
|
||||
operation: () => Promise<T>,
|
||||
lang: 'fr' | 'en' = 'fr'
|
||||
): Promise<T | null> => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const result = await handleDbOperation(
|
||||
operation,
|
||||
(err) => setError(err),
|
||||
lang
|
||||
);
|
||||
setData(result);
|
||||
setLoading(false);
|
||||
return result;
|
||||
} catch (err) {
|
||||
setLoading(false);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return { data, error, loading, execute };
|
||||
}
|
||||
|
||||
// For non-React usage
|
||||
import React from 'react';
|
||||
Reference in New Issue
Block a user