IndexedDBStore
Cosa fa
IndexedDBStore<T> e un'astrazione low-level type-safe sopra IndexedDB: incapsula apertura DB, transazioni, gestione errori e callback onupgradeneeded dietro un'API Promise-based con generics.
E utilizzata internamente da IndexedDBCacheStrategy — di norma non serve usarla direttamente. Casi d'uso diretti:
- Persistenza di dati di dominio (non solo cache HTTP)
- Pattern offline-first con sincronizzazione manuale
- Store applicativi paralleli alla cache HTTP
Costruttore
class IndexedDBStore<T extends Record<string, unknown>> {
constructor(
dbName: string,
storeName: string,
config: StoreConfig,
version?: number
)
}
| Parametro | Tipo | Default | Descrizione |
|---|---|---|---|
dbName | string | — | Nome del database IndexedDB |
storeName | string | — | Nome dell'object store nel database |
config | StoreConfig | — | Configurazione store (keyPath, indici) |
version | number | 1 | Versione DB. Incrementare per migrazioni schema |
StoreConfig
interface StoreConfig {
keyPath: string
autoIncrement?: boolean
indexes?: Array<{
name: string
keyPath: string | string[]
options?: { unique?: boolean; multiEntry?: boolean }
}>
}
API CRUD
| Metodo | Descrizione |
|---|---|
add(item) | Inserisce. Throw se la chiave esiste gia. Ritorna la chiave generata |
addOrUpdate(item) | Upsert. Inserisce se assente, aggiorna se presente (per primary key) |
get(key) | Recupera per chiave primaria. Ritorna undefined se assente |
getAll() | Recupera tutti i record. Costoso su store grandi |
update(key, partial) | Merge parziale con il record esistente |
delete(key) | Rimuove per chiave primaria. Non throw se assente |
getByIndex(name, key) | Recupera tramite indice secondario |
Tutte le operazioni:
- Sono
async(Promise) - Aprono il DB automaticamente al primo uso (
initDB()interno) - Gestiscono la transazione (
readonlyper le letture,readwriteper scritture) - Throw
Errorcon messaggio derivato darequest.error?.message
Esempio
import { IndexedDBStore } from '@pzeta/postgrest'
interface User extends Record<string, unknown> {
userId?: number
email: string
name: string
createdAt: number
}
const userStore = new IndexedDBStore<User>('myApp', 'users', {
keyPath: 'userId',
autoIncrement: true,
indexes: [
{ name: 'email', keyPath: 'email', options: { unique: true } },
{ name: 'createdAt', keyPath: 'createdAt' },
],
})
// Inserimento
const key = await userStore.add({
email: 'mario@example.com',
name: 'Mario',
createdAt: Date.now(),
})
// Lookup per indice secondario
const user = await userStore.getByIndex('email', 'mario@example.com')
// Update parziale
await userStore.update(1, { name: 'Mario Rossi' })
Migrazioni schema
Per modificare lo schema (aggiungere indici, store), incrementare version. Il callback onupgradeneeded viene rieseguito.
!db.objectStoreNames.contains(storeName)). Modifiche a indici di uno store esistente richiedono logica di migrazione custom: questa classe non gestisce migrazioni complesse.Quando NON usarla
- Per cache HTTP: usa
IndexedDBCacheStrategytramiteCacheService - Per dati strutturati complessi con query relazionali: valuta soluzioni dedicate (Dexie, idb)
- Quando IndexedDB non e disponibile (vecchi browser, SSR): usa
MemoryCacheStrategy
Vedi anche
IndexedDBCacheStrategy— usa internamente questa classeCacheStrategyFactory— auto-fallback se IndexedDB non disponibile
IndexedDBCacheStrategy
Strategia di cache default basata su IndexedDB. Capacita elevata (~50MB+), persistente, async non-blocking. Ideale per produzione e dataset grandi.
LocalStorageCacheStrategy
Strategia di cache basata su localStorage. ~5-10MB, persistenza permanente, API sincrona. Utile come fallback IndexedDB per dataset piccoli.