4.1 KiB
4.1 KiB
Patterns d'utilisation IndexedDB
Date : 2024-12-19 Auteur : Équipe 4NK
Introduction
Ce document décrit les patterns à utiliser pour interagir avec IndexedDB dans le projet. Tous les services IndexedDB doivent utiliser IndexedDBHelper pour garantir la cohérence et réduire la duplication.
Pattern recommandé : Utilisation de IndexedDBHelper
Création d'un service IndexedDB
import { createIndexedDBHelper } from '@/lib/helpers/indexedDBHelper'
const dbHelper = createIndexedDBHelper({
dbName: 'my_database',
version: 1,
storeName: 'my_store',
keyPath: 'id',
indexes: [
{ name: 'timestamp', keyPath: 'timestamp', unique: false },
{ name: 'type', keyPath: 'type', unique: false },
],
onUpgrade: (db, event) => {
// Migration logic if needed
},
})
// Utilisation
await dbHelper.init()
const store = await dbHelper.getStore('readwrite')
await dbHelper.add({ id: '1', data: 'value' })
Opérations courantes
Ajouter un objet
await dbHelper.add(object)
Récupérer un objet par clé
const obj = await dbHelper.get<MyType>(key)
Récupérer par index
const obj = await dbHelper.getByIndex<MyType>('indexName', value)
Récupérer tous les objets
const all = await dbHelper.getAll<MyType>()
Compter par index
const count = await dbHelper.countByIndex('indexName', IDBKeyRange.only(value))
Mettre à jour un objet
await dbHelper.update(object)
Supprimer un objet
await dbHelper.delete(key)
Supprimer tous les objets
await dbHelper.clear()
Gestion des erreurs
Toutes les erreurs IndexedDB sont automatiquement wrappées dans IndexedDBError avec :
- Message d'erreur
- Nom de l'opération
- Nom du store (si applicable)
- Cause originale
try {
await dbHelper.add(object)
} catch (error) {
if (error instanceof IndexedDBError) {
console.error(`Operation: ${error.operation}, Store: ${error.storeName}`)
}
throw error
}
Transactions
Les transactions sont gérées automatiquement par IndexedDBHelper. Chaque opération utilise une transaction appropriée.
Pour des opérations multiples dans une seule transaction :
const store = await dbHelper.getStore('readwrite')
// Toutes les opérations sur store sont dans la même transaction
await store.add(object1)
await store.add(object2)
// Transaction se ferme automatiquement à la fin de la fonction
Migrations
Les migrations sont gérées dans onUpgrade :
const dbHelper = createIndexedDBHelper({
// ...
onUpgrade: (db, event) => {
const transaction = event.target.transaction
const store = transaction.objectStore('my_store')
// Ajouter un index si nécessaire
if (!store.indexNames.contains('newIndex')) {
store.createIndex('newIndex', 'newField', { unique: false })
}
},
})
Bonnes pratiques
- Toujours utiliser IndexedDBHelper : Ne pas créer de code d'initialisation IndexedDB personnalisé
- Gérer les erreurs : Toujours utiliser try/catch avec IndexedDBError
- Typage strict : Utiliser les génériques TypeScript pour le typage
- Transactions : Regrouper les opérations liées dans une seule transaction
- Migrations : Tester les migrations sur des données réelles avant déploiement
Exemples complets
Service de cache simple
import { createIndexedDBHelper } from '@/lib/helpers/indexedDBHelper'
class MyCacheService {
private dbHelper = createIndexedDBHelper({
dbName: 'my_cache',
version: 1,
storeName: 'items',
keyPath: 'id',
indexes: [
{ name: 'timestamp', keyPath: 'timestamp', unique: false },
],
})
async init(): Promise<void> {
await this.dbHelper.init()
}
async addItem(item: MyItem): Promise<void> {
await this.dbHelper.add(item)
}
async getItem(id: string): Promise<MyItem | null> {
return await this.dbHelper.get<MyItem>(id)
}
async getAllItems(): Promise<MyItem[]> {
return await this.dbHelper.getAll<MyItem>()
}
}