BaseEnhancedRepository
Overview
BaseEnhancedRepository<T, K> è la classe base astratta che incapsula un'istanza interna di PostgRESTRepository e ne espone l'API con path e keyName già fissati. Elimina il boilerplate (DRY) e garantisce type safety completa su entità e chiave primaria.
abstract class BaseEnhancedRepository<T extends Record<string, unknown>, K>
EnhancedPostgRESTRepository è una sottoclasse "vuota" che esiste solo per stabilizzare il nome pubblico. Estendi BaseEnhancedRepository direttamente quando hai bisogno di aggiungere metodi custom di dominio.
Quando estenderla
- Repository di dominio con metodi specifici (
findByEmail,searchByTags,getActiveOnly) - Service che incapsula logica di business + accesso dati su una singola aggregate root
- Override di metodi CRUD per aggiungere logica (audit logging, validazione)
*Repository di dominio è tipicamente una sottoclasse di BaseEnhancedRepository con path e keyName impliciti, più i metodi del Repository contract DDD (findByEmail, findActiveOnly, ecc.).Stato protetto
| Campo | Tipo | Descrizione |
|---|---|---|
keyName | keyof T | Nome chiave primaria (immutabile) |
path | string | Path base senza query string |
queryArgs | string | Query string statica (se path contiene ?) |
crudService | PostgRESTRepository | Istanza interna che esegue le operazioni HTTP |
Il metodo helper protetto getFullPath() ricostruisce il path completo (path + ?queryArgs) per ogni operazione.
EnhancedRepositoryOptions<T>
export interface EnhancedRepositoryOptions<T extends Record<string, unknown>> {
baseUrl: string
path: string
keyName: keyof T
isAuthRequired?: boolean // default: false
useCache?: boolean // default: false
cacheTTL?: number // ms
useBackgroundRefresh?: boolean // default: true
schema?: string // default: 'public'
}
| Opzione | Tipo | Default | Descrizione |
|---|---|---|---|
baseUrl | string | — | URL base PostgREST |
path | string | — | Path tabella (può includere ?select=...) |
keyName | keyof T | — | Colonna chiave primaria |
isAuthRequired | boolean? | false | Token JWT/cookie incluso nelle richieste |
useCache | boolean? | false | Cache read abilitata |
cacheTTL | number? | undefined | TTL cache in ms |
useBackgroundRefresh | boolean? | true | Stale-while-revalidate |
schema | string? | 'public' | Schema PostgreSQL |
API ereditata
Tutti i metodi di EnhancedPostgRESTRepository (CRUD, bulk, RPC, cache, prefetch) sono definiti qui. Tornano automaticamente disponibili nelle sottoclassi senza override.
Esempio: repository di dominio con metodi custom
import { BaseEnhancedRepository } from '@pzeta/postgrest'
interface User extends Record<string, unknown> {
idutente: number
nome: string
email: string
status: 'active' | 'inactive'
ultimoaccesso: string | null
}
class UserRepository extends BaseEnhancedRepository<User, number> {
constructor(baseUrl: string) {
super({
baseUrl,
path: '/utenti',
keyName: 'idutente',
isAuthRequired: true,
useCache: true,
cacheTTL: 3_600_000,
schema: 'app',
})
}
/**
* Trova un utente per email (caso d'uso DDD)
*/
async findByEmail(email: string): Promise<User | undefined> {
const utenti = await this.readAll({
email: { operator: 'eq', value: email },
})
return utenti[0]
}
/**
* Tutti gli utenti attivi degli ultimi 30 giorni
*/
async findActiveRecent(): Promise<User[]> {
const trentaGiorniFa = new Date(Date.now() - 30 * 86_400_000).toISOString()
return await this.readAll({
status: { operator: 'eq', value: 'active' },
ultimoaccesso: { operator: 'gte', value: trentaGiorniFa },
sort: { field: 'ultimoaccesso', direction: 'desc' },
})
}
/**
* Override di update: aggiunge audit log prima dell'operazione
*/
override async update(
key: number,
element: Partial<User>,
): Promise<User | undefined> {
await this.rpcRawPost<void>('audit_log_user_update', {
idutente: key,
changes: element,
})
return super.update(key, element)
}
}
// Uso
const userRepo = new UserRepository('https://api.example.com')
const mario = await userRepo.findByEmail('mario@example.com')
const recenti = await userRepo.findActiveRecent()
override di un metodo CRUD, ricorda di chiamare super.<metodo>(...) per non perdere la invalidazione cache automatica e la gestione errori centralizzata di PostgRESTRepository.Path con query parameters statici
Il path accetta query string PostgREST (es. select, or, embedded resources) che vengono preservate su ogni operazione:
class UserWithRoleRepository extends BaseEnhancedRepository<UserWithRole, number> {
constructor(baseUrl: string) {
super({
baseUrl,
// Embedded resource PostgREST: include sempre il ruolo
path: '/utenti?select=idutente,nome,email,ruolo(idruolo,nome)',
keyName: 'idutente',
})
}
}
Cross-reference
EnhancedPostgRESTRepository— sottoclasse non astratta, usata per istanze "as-is"PostgRESTRepository— implementazione interna, accessibile viathis.crudServicein casi avanzatiRepositoryFactory— alternativa rapida senza ereditarietàBasePostgrestService— wrapper di service-layer ancora più alto livello
Repositories
Repository Pattern type-safe per PostgREST — classi CRUD generiche, wrapper semplificati, factory con preset e utility runtime per errori, path e type guards.
CrudRepositoryBase
Classe base astratta che definisce il contratto CRUD implements ICrudRepository — punto di estensione per backend non-PostgREST mantenendo l'API uniforme.