Postgrest

buildPostgrestQuery / buildPostgrestQueryFromState

Utility per convertire i valori filtri (o l'intero SearchState) in query parameters PostgREST.

Panoramica

La libreria espone due utility complementari:

  • buildPostgrestQuery(values, fields) — solo i filtri base (output di state.filters).
  • buildPostgrestQueryFromState(state, config) — lo stato completo (SearchState) coi 4 layer combinati (filtri + preset + rule builder + group-by).

Entrambe ritornano Record<string, string>, pronto da passare come URLSearchParams o agli headers PostgREST.

buildPostgrestQuery

import { buildPostgrestQuery } from '@pzeta/vue-ricerca'

function onApply(state: SearchState) {
  const query = buildPostgrestQuery(state.filters, fields)

  const url = new URL('/api/prodotti')
  for (const [key, value] of Object.entries(query)) {
    url.searchParams.set(key, value)
  }
  fetch(url)
}

Comportamento per tipo campo

TipoOperatore defaultFormato output
text (singola colonna)ilikecol.ilike.*val*
text (multi-colonna)ilikeor=(col1.ilike.*val*,col2.ilike.*val*)
selecteqcol.eq.val
numbereqcol.eq.val
dateeqcol.eq.YYYY-MM-DD
boolean (true/false)iscol.is.true / col.is.false
boolean (null)campo omesso
daterange (entrambi)gte/lteand=(col.gte.from,col.lte.to)
daterange (solo from)gtecol.gte.from
daterange (solo to)ltecol.lte.to
numberrangeidem daterangeidem

PostgrestConfig

Ogni campo può personalizzare la query tramite la prop postgrest:

interface PostgrestConfig {
  column?: string | string[]   // default: field.key (string[] → OR multi-colonna per text)
  operator?: PostgrestOperator // override operatore default
  negate?: boolean             // prefissa con 'not.' (es. not.eq.val)
  ignore?: boolean             // esclude il campo dalla query
}

Esempio output completo

const filters = {
  search: 'mario',
  stato: 'attivo',
  dataCreazioneDa: new Date('2024-01-01'),
  dataCreazioneA: new Date('2024-12-31'),
  attivo: true,
}

const query = buildPostgrestQuery(filters, fields)
// {
//   or: '(nome.ilike.*mario*,descrizione.ilike.*mario*)',
//   stato: 'eq.attivo',
//   and: '(datacreazione.gte.2024-01-01,datacreazione.lte.2024-12-31)',
//   attivo: 'is.true',
// }

buildPostgrestQueryFromState

Combina tutti i layer dello SearchState in una singola query. Utile quando usi i layer avanzati (preset, rule builder, group-by).

import { buildPostgrestQueryFromState } from '@pzeta/vue-ricerca'
import type { SearchState } from '@pzeta/vue-ricerca'

function onApply(state: SearchState) {
  const query = buildPostgrestQueryFromState(state, {
    fields,
    presets,
    ruleBuilderFields,
    groupByFields,
  })
  // → { and: '(stato.eq.attivo,nome.ilike.*mario*)', order: 'datacreazione.desc' }
}

Composizione dei 4 layer

Ordine in cui vengono combinati:

  1. Filtri base (state.filters) → output di buildPostgrestQuery
  2. Preset attivi (state.activePresets):
    • Stesso gruppo → OR tra le condizioni dei preset attivi
    • Gruppi diversi → AND tra i gruppi
  3. Rule builder AST (state.rules) → tradotto da buildRuleGroupQuery
  4. Group-by (state.groupByFields) → parametro order con concatenazione col1.asc,col2.desc

I primi 3 vengono combinati in un unico parametro and=(...); il group-by produce sempre il parametro order.

Esempio combinato

const state: SearchState = {
  filters: { search: 'mario' },           // filtro testo multi-colonna
  activePresets: ['solo-attivi'],         // → stato.eq.attivo
  rules: { /* RuleGroup AND con eta.gte.18 */ },
  groupByFields: [
    { column: 'datacreazione', order: 'desc' },
    { column: 'categoria', order: 'asc' },
  ],
}

const query = buildPostgrestQueryFromState(state, { fields, presets, ruleBuilderFields, groupByFields })
// {
//   and: '(or=(nome.ilike.*mario*,descrizione.ilike.*mario*),stato.eq.attivo,eta.gte.18)',
//   order: 'datacreazione.desc,categoria.asc',
// }

Operatori PostgREST disponibili

type PostgrestOperator =
  // Comparison
  | 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte'
  // Pattern matching
  | 'like' | 'ilike' | 'match' | 'imatch'
  // Set / null
  | 'in' | 'is' | 'isdistinct'
  // Full-text search
  | 'fts' | 'plfts' | 'phfts' | 'wfts'
  // JSON / Array containment
  | 'cs' | 'cd'
  // Range / overlap
  | 'ov' | 'sl' | 'sr' | 'nxl' | 'nxr' | 'adj'

Riferimento: PostgREST horizontal filtering.

Helper rule builder

buildRuleGroupQuery(group) e buildRuleCondition(rule) sono le utility usate internamente per tradurre l'AST del rule builder in stringhe PostgREST. Sono esportate per usi avanzati (es. costruire query a mano da un AST persistito):

import { buildRuleGroupQuery, buildRuleCondition } from '@pzeta/vue-ricerca'

const condition = buildRuleCondition({
  id: '...', column: 'eta', operator: 'gte', value: 18
})
// → 'eta.gte.18'

const groupCondition = buildRuleGroupQuery(myRuleGroup)
// → 'and=(eta.gte.18,or=(stato.eq.attivo,stato.eq.sospeso))'