Facade & Services
BasePostgrestService
Classe base astratta per service applicativi PostgREST. Wrapper di alto livello su EnhancedPostgRESTRepository con API CRUD omogenea, error messages italiani e helper RPC.
Cos'è
BasePostgrestService<T, K> è la classe base astratta che ogni service di dominio dovrebbe estendere quando integra PostgREST in un progetto PZeta. Fornisce:
- API CRUD omogenea (
getAll,getById,create,update,delete) - Error messages user-facing in italiano configurabili via
entityName - Helper protetto
callRpc<R>()per stored procedure PostgREST - Accesso al client sottostante via
this.client(per HTTP low-level) e al repository viathis.repo(per query avanzate)
Promossa da
vue-magazzino per garantire un pattern uniforme tra tutti i progetti che integrano @pzeta/postgrest. Per la variante MFE basata su MFEHttpClient vedi BaseMfePostgrestService in @pzeta/postgrest/mfe.Contratto
abstract class BasePostgrestService<
T extends Record<string, unknown>,
K extends string | number = number,
> {
protected readonly repo: EnhancedPostgRESTRepository<T, K>
protected readonly client: PostgRESTClient
protected readonly entityName: string
constructor(
client: PostgRESTClient,
endpoint: string,
primaryKey: keyof T & string,
entityName?: string,
)
getAll(filters?: FilterCriteria<T>): Promise<T[]>
getById(id: K): Promise<T>
create(data: Partial<T>): Promise<T>
update(id: K, data: Partial<T>): Promise<T>
delete(id: K): Promise<void>
protected callRpc<R>(rpcPath: string, params: Record<string, unknown>): Promise<R>
}
Costruttore
| Parametro | Tipo | Required | Descrizione |
|---|---|---|---|
client | PostgRESTClient | ✓ | Client PostgREST già inizializzato (await client.init()) |
endpoint | string | ✓ | Path della risorsa PostgREST (es. /clienti, /v_fatture_lista) |
primaryKey | keyof T & string | ✓ | Nome della colonna chiave primaria (es. idcliente) |
entityName | string | — | Nome user-facing per error messages (default: 'Record') |
API CRUD
| Metodo | Firma | Note |
|---|---|---|
getAll | (filters?: FilterCriteria<T>) => Promise<T[]> | Delega a repo.readAll() |
getById | (id: K) => Promise<T> | Lancia Error: {entityName} non trovato: {id} se non esiste |
create | (data: Partial<T>) => Promise<T> | Lancia Error: Impossibile creare {entityName} se fallisce |
update | (id: K, data: Partial<T>) => Promise<T> | Lancia Error: Impossibile aggiornare {entityName}: {id} se fallisce |
delete | (id: K) => Promise<void> | Non lancia su record non esistente |
callRpc<R> | (rpcPath, params) => Promise<R> | Protetto — esposto solo a classi figlie |
Error messages italiani: i messaggi di errore sono pensati per essere catturati e mostrati direttamente all'utente finale. Il template è
{Entita} non trovato, Impossibile creare {entita}, Impossibile aggiornare {entita}: {id}. Il parametro entityName viene normalizzato a lowercase per create/update.Esempio — Service di dominio
import { BasePostgrestService, type PostgRESTClient } from '@pzeta/postgrest'
interface Cliente {
idcliente: number
ragionesociale: string
email: string
pivacf: string
}
export class ClientiService extends BasePostgrestService<Cliente, number> {
constructor(client: PostgRESTClient) {
super(client, '/clienti', 'idcliente', 'Cliente')
}
// Metodo di dominio aggiuntivo — usa `this.repo` per query avanzate
async cercaPerRagioneSociale(ragione: string): Promise<Cliente[]> {
return this.getAll({
ragionesociale: { operator: 'ilike', value: `%${ragione}%` },
sort: { field: 'ragionesociale', direction: 'asc' },
})
}
// RPC custom — usa `this.callRpc<R>` per stored procedure
async aggiornaSaldo(idcliente: number, importo: number): Promise<number> {
return this.callRpc<number>('/rpc/aggiorna_saldo_cliente', {
p_idcliente: idcliente,
p_importo: importo,
})
}
}
Utilizzo nel layer applicativo
const client = new PostgRESTClient({ apiUrl: 'https://api.example.com' })
await client.init()
await client.login({ email: 'admin@pzeta.it', password: '...' })
const clientiService = new ClientiService(client)
try {
const trovati = await clientiService.cercaPerRagioneSociale('rossi')
const cliente = await clientiService.getById(42)
await clientiService.update(42, { email: 'nuovo@example.com' })
} catch (err) {
// err.message → "Cliente non trovato: 99"
showErrorToast((err as Error).message)
}
Integrazione con Dependency Injection
BasePostgrestService è compatibile out-of-the-box con qualsiasi container DI (Inversify, tsyringe, Pinia, ecc.). Esempio Inversify:
import { injectable, inject } from '@inversify/core'
@injectable()
export class ClientiService extends BasePostgrestService<Cliente, number> {
constructor(@inject('PostgRESTClient') client: PostgRESTClient) {
super(client, '/clienti', 'idcliente', 'Cliente')
}
}
In Vue con Pinia:
import { defineStore } from 'pinia'
export const useClientiStore = defineStore('clienti', () => {
const service = new ClientiService(usePostgRESTClient())
return { service }
})
Convenzione naming RPC PostgREST
Per callRpc<R> rispetta la convenzione PostgREST:
- Path:
/rpc/{nome_funzione} - Parametri: prefisso
p_(es.p_idcliente,p_importo) - Ritorno: tipizza con il type parameter
R
// Stored procedure: aggiorna_ticket(p_idticket int, p_stato text) RETURNS json
const result = await this.callRpc<{ ok: boolean; idticket: number }>(
'/rpc/aggiorna_ticket',
{ p_idticket: 42, p_stato: 'chiuso' },
)
BasePostgrestService vs BaseMfePostgrestService
| Aspetto | BasePostgrestService | BaseMfePostgrestService |
|---|---|---|
| Package | @pzeta/postgrest | @pzeta/postgrest/mfe |
| HTTP client | PostgRESTClient (gestisce auth/cache internamente) | MFEHttpClient (auth gestita dalla shell host) |
| Auth | Strategie native (JWT, Cookie, ApiKey, None) | Token gestito dalla shell |
| Cache | CacheService interno | Delegata alla shell / no cache |
| Use case | App standalone, backend, microservizi | Microfrontend integrati in shell |
Tipi correlati
PostgRESTClient— facade richiesto dal costruttoreFilterCriteria— input digetAll()ICrudRepository— contratto del repository sottostante
Facade & Services
Punto di ingresso applicativo della libreria — facade PostgRESTClient per setup rapido e BasePostgrestService come classe base per service di dominio CRUD + RPC.
PostgRESTClient
Facade Pattern di @pzeta/postgrest. Punto di ingresso principale — nasconde la complessità di HTTP client, autenticazione, cache e repository factory.