El framework gate

L'esquema i la capa de dades de svitrio estan construïts sobre gate — un petit llenguatge declaratiu d'esquemes (fitxers .gate) i gate-go, un toolkit propi que converteix aquests fitxers en SQL i Go en temps de compilació. Entendre gate explica molt sobre per què svitrio es comporta com ho fa.

Què és

Un fitxer .gate declara tipus, camps, relacions i restriccions. A partir d'un sol esquema, gate-go emet tant el SQL DDL (CREATE TABLE IF NOT EXISTS + índexs + claus foranes) com el store de Go (la struct, un escàner de files i un CRUD complet amb àmbit).

type ai_provider {
  @index(project_id, is_default)
  project_id:   ref<project> @external @on_delete(cascade) @scoped(project_id)
  name:         string  @required
  kind:         string  @required
  api_key:      string  @default("") @sealed
  is_default:   bool    @default(false) @exclusive
}

Les anotacions aporten comportament: @scoped injecta WHERE project_id = ? a cada consulta; @sealed xifra un camp en repòs (segella en escriure, obre en llegir); @exclusive manté com a màxim una fila en true per àmbit dins d'una transacció; @external + @on_delete(cascade) enllaça amb FK a la taula d'un altre mòdul i neteja quan s'elimina un tenant.

Com l'usa svitrio

Cada mòdul col·loca el seu esquema .gate al costat del seu codi Go i l'incrusta. go generate produeix un store *_generated.go (un guardià de deriva a CI fa fallar la compilació si queda obsolet). A l'arrencada, l'amfitrió carrega l'esquema de cada mòdul i executa CREATE TABLE IF NOT EXISTS — de manera que compondre l'esquema complet és idempotent i el binari arrenca des d'una base de dades en blanc. Afegir un mòdul nou consisteix a: lliurar el seu .gate, el seu gen.go i un import en blanc — mai no s'edita cap fitxer SQL central.

Què obtens

  • Única font de veritat — el fitxer .gate impulsa tant la taula com el store tipat; no poden derivar.

  • Boilerplate gairebé nul — un tipus de ~30 línies produeix una struct, un escàner, cinc mètodes CRUD, segellat transaccional i l'invariant d'exclusivitat per defecte.

  • Sense ball de migracions — cada migració és IF NOT EXISTS; les columnes additives usen AddColumnIfMissing. Sense taula de versions, sense scripts up/down.

  • Multitenancy de franc@scoped + un ref<project> en cascada significa que cada mòdul està aïllat per tenant per construcció.

  • La base de la capa de producte — l'admin ja construeix la UI a partir d'un esquema .gate més una capa de presentació. Convertir «escriure un esquema» en una superfície que un client pugui usar per modelar el seu propi producte és el pas següent natural.