- 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.
107 lines
2.8 KiB
TypeScript
107 lines
2.8 KiB
TypeScript
/**
|
|
* 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';
|