Quick Start
Tre approcci
@pzeta/postgrest espone tre punti di ingresso, dal più semplice al più strutturato. Scegli in base alla complessità del progetto:
| Approccio | Quando |
|---|---|
Opzione 1 — Facade PostgRESTClient | Prototipi, app piccole, script |
Opzione 2 — EnhancedPostgRESTRepository manuale | Controllo fine, repository singolo, configurazione custom di HTTP/auth/cache |
Opzione 3 — BasePostgrestService (consigliato) | Progetti enterprise, DDD, dependency injection |
Definiamo prima il tipo di dominio usato negli esempi:
interface User {
iduser: number
nome: string
email: string
datacreazione: string
}
Opzione 1 — Facade PostgRESTClient
import { PostgRESTClient } from '@pzeta/postgrest'
const client = new PostgRESTClient({
apiUrl: 'https://api.example.com',
schema: 'public',
})
await client.init() // obbligatorio prima dell'uso
// Login
await client.login({
email: 'mario@example.com',
password: 'password123',
})
// Repository factory: lega tipo + path + chiave primaria
const userRepo = client.repository<User, number>('/users', 'iduser')
// CRUD
const utenti = await userRepo.readAll()
const utente = await userRepo.read(1)
const nuovo = await userRepo.create({
nome: 'Mario Rossi',
email: 'mario@example.com',
})
const aggiornato = await userRepo.update(1, { nome: 'Mario R.' })
await userRepo.delete(1)
// Logout
await client.logout()
// Cleanup OBBLIGATORIO (ferma timer cache, previene memory leak)
client.destroy()
Filtering avanzato con FilterCriteria
import type { FilterCriteria } from '@pzeta/postgrest'
const filters: FilterCriteria<User> = {
nome: { operator: 'ilike', value: '%mario%' },
iduser: { operator: 'gte', value: 100 },
sort: { field: 'datacreazione', direction: 'desc' },
pagination: { limit: 20, offset: 0 },
}
const risultato = await userRepo.readPaginated(filters)
console.log('Records:', risultato.data)
console.log('Totale:', risultato.totalCount)
Operatori supportati: eq, neq, in, gt, lt, gte, lte, like, ilike, is, not, fts, plfts, phfts, cs, cd, sl, sr, nxl, nxr, adj, between.
Configurazione facade
import {
PostgRESTClient,
AuthStrategyType,
CacheStrategyType,
HttpClientType,
} from '@pzeta/postgrest'
const client = new PostgRESTClient({
apiUrl: 'https://api.example.com',
schema: 'api', // schema PostgreSQL (default: 'public')
httpClientType: HttpClientType.FETCH, // FETCH (default) | AXIOS
authType: AuthStrategyType.JWT, // JWT (default) | COOKIE | API_KEY | NONE
cacheType: CacheStrategyType.INDEXEDDB, // INDEXEDDB (default, auto-fallback)
cacheTTL: 3_600_000, // 1 ora in ms (default)
timeout: 10_000, // 10 secondi (default)
})
Override per repository
// Repository senza cache (dati sempre freschi) e senza auth
const logRepo = client.repository<LogEntry, string>('/logs', 'idlog', {
useCache: false,
isAuthRequired: false,
})
// Repository con schema diverso da quello globale del client
const adminRepo = client.repository<AdminUser, number>('/users', 'iduser', {
schema: 'admin',
})
Opzione 2 — EnhancedPostgRESTRepository manuale
Salta il facade e costruisci direttamente il repository. Utile per casi mono-tabella o test isolati.
import { EnhancedPostgRESTRepository } from '@pzeta/postgrest'
const userRepo = new EnhancedPostgRESTRepository<User, number>({
baseUrl: 'https://api.example.com',
path: '/users',
keyName: 'iduser',
isAuthRequired: true,
useCache: true,
cacheTTL: 3_600_000,
useBackgroundRefresh: true,
})
const utenti = await userRepo.readAll({
email: { operator: 'ilike', value: '%@example.com' },
})
Per scenari multi-repository con auth/cache condivisi, l'EnhancedPostgRESTRepository manuale non condivide il CacheService singleton con un eventuale facade: in quel caso usa il facade.
Opzione 3 — BasePostgrestService (consigliato)
Pattern di adozione canonico nei progetti PZeta. Estendi BasePostgrestService per ogni entità di dominio: la classe figlia incapsula il repository, espone CRUD omogeneo con error messages italiani e può aggiungere metodi business + chiamate RPC.
import { BasePostgrestService, type PostgRESTClient } from '@pzeta/postgrest'
interface Cliente {
idcliente: number
ragionesociale: string
email: string
codicefiscale: string
}
class ClientiService extends BasePostgrestService<Cliente, number> {
constructor(client: PostgRESTClient) {
super(client, '/clienti', 'idcliente', 'Cliente')
}
// Metodo di dominio aggiuntivo
async cercaPerRagioneSociale(ragione: string): Promise<Cliente[]> {
return this.getAll({
ragionesociale: { operator: 'ilike', value: `%${ragione}%` },
})
}
// RPC PostgREST tipizzata (stored procedure)
async aggiornaSaldo(idcliente: number, importo: number): Promise<number> {
return this.callRpc<number>('/rpc/aggiorna_saldo_cliente', {
p_idcliente: idcliente,
p_importo: importo,
})
}
}
// Uso
const service = new ClientiService(client)
const elenco = await service.getAll()
const cliente = await service.getById(1) // throw se non trovato
const nuovo = await service.create({ ragionesociale: 'Acme S.r.l.' })
await service.update(1, { email: 'info@acme.it' })
await service.delete(1)
const nuovoSaldo = await service.aggiornaSaldo(1, 150.50)
Vedi la guida completa al Service Pattern per integrazione con Inversify DI, override dei metodi e pattern multi-progetto.
Prossimi passi
- Architettura — Layer Clean Architecture + DDD
- Service Pattern (BasePostgrestService) — Pattern canonico per progetti strutturati
- Installazione — Subpath exports e peer dependencies
Installazione
Installazione di @pzeta/postgrest, peer dependencies opzionali (axios, vue, @pzeta/mfe-contracts), subpath exports core e /mfe, verifica con esempio minimo.
Service Pattern (BasePostgrestService)
Classe base astratta per service applicativi PostgREST. CRUD omogeneo, error messages italiani, RPC helpers, integrazione Inversify DI. Pattern di adozione canonico nei progetti PZeta.