Documentazione · le cuciture
Estendere
Il motore è aperto in dodici punti. Questa pagina li mette in fila: cosa si aggiunge, dove, e cosa NON serve toccare per farlo.
La regola generale
Ogni cucitura ha la stessa forma: un oggetto o una mappa che il pacchetto esporta, che il consumer estende con `{ ...quelli del pacchetto, ...i propri }`, e che poi PASSA al provider o alla configurazione. Chi arriva dopo vince sui conflitti.
Il fatto che l’insieme attivo sia quello passato — e non quello del pacchetto più qualcosa — significa che si può anche POTARE: un progetto che non usa i trigger di viewport li toglie, e non ne paga il codice.
Nessuna delle estensioni richiede di modificare il pacchetto, e nessuna richiede una registrazione con decoratori o convenzioni magiche. Sono oggetti.
Aggiungere una forma
Un componente nuovo si aggiunge alla mappa dei componenti; un viewMode che lo nomina si aggiunge allo store dallo Studio. Da quel momento un blocco può scegliere quella forma. Il motore non cambia.
Uno stile nuovo si aggiunge alla style guide dallo Studio, e Tailwind genera le sue classi al build successivo. Un tema nuovo è una palette più dei font; la differenziazione strutturale sta nei `themeStyles` dei viewMode, quindi un tema non è una copia della style guide.
react/uimsComponents.ts— estendi la mappa: `{ ...uimsComponents, MioComponente }`db.viewmodes.json— un viewMode che nomina il componente — dallo Studiodb.styles.json— uno stile nominato — dallo Studiodb.themes.json— un tema: palette più font
Aggiungere un tipo di contenuto
Un blocco nuovo è un file che dichiara i propri campi e il viewMode di default; entra nel registro e da lì nella configurazione di Payload. Il campo del viewMode, le classi, gli stili e il gruppo `uiState` arrivano dall’iniezione comune: non vanno dichiarati.
Un resolver dedicato serve solo se quel blocco ha bisogno di qualcosa che nel blocco non c’è — un documento da dereferenziare, dei record da leggere. Altrimenti passa dal default e non c’è niente da scrivere.
Se il blocco espone uno stato proprio, la sua forma si dichiara nella mappa delle slice: è il dato che permette all’admin di mostrarlo e allo store di conoscerlo.
config/blocks/— il blocco, e la sua voce nel registro del livello giustoengine/resolver/— un resolver dedicato, solo se serveconfig/slices/blockSlices.ts— la forma dello stato esposto, se il blocco ne ha
Aggiungere un comportamento
Una CAUSA nuova è un trigger: sa mettersi in ascolto di qualcosa e chiamare `fire`. Non deve sapere cosa succederà dopo — è quello che lo rende componibile con qualunque conseguenza.
Una CONSEGUENZA nuova è un’azione: riceve la configurazione e la esegue. Le quattro del pacchetto coprono animare, annunciare, comandare ed eseguire; una quinta si aggiunge allo stesso modo.
Un HANDLER nuovo serve quando il comportamento è un effetto sul BROWSER — scorrere, mettere a fuoco, stampare. Se invece è esprimibile come «una chiave cambia e qualcosa si ri-stila», non è un handler: è un reducer più un binding.
Un MIDDLEWARE intercetta tutto ciò che passa dal kernel: lo trasforma restituendolo, lo annulla restituendo `null`, o lo lascia passare. È il posto per la logica trasversale.
react/triggers/uimsTriggers.ts— la causa: `{ ...uimsTriggers, 'on:mio': … }`react/actions/uimsActions.ts— la conseguenza: `{ ...uimsActions, mia: … }`react/events/uimsEventHandlers.ts— l’handler, se è un effetto sul browserkernel.use(...)— il middlewaredb.events.json— il nome, perché compaia nelle tendine dell’admin
Aggiungere logica di dominio
I reducer sono il posto della logica applicativa, e vivono nel progetto — non nel pacchetto. `app-state.ts`, scaffoldato da `init`, è dove si vedono e si estendono: un reducer riceve un evento e produce mutazioni, ognuna con la sua chiave.
Gli effetti registrati sul kernel sono l’altra metà: implementazioni invocabili per nome, che ricevono il nodo — cosa che un messaggio sul bus non porta. Servono quando la conseguenza ha bisogno di sapere SU CHI agire.
Entrambi sono contratto pubblico, quindi la loro forma è stabile per scelta: `Reducer`, `Wiring`, `Effect` e `Mutation` non cambiano senza un cambio di versione maggiore.
app-state.ts— nel progetto: i reducer attivi, estendibili e potabilikernel.registerEffect(...)— un effetto invocabile per nome, che riceve il nodo
Quando la forma cambia
Cambiare la forma di un dato già inserito non è un refactor: il contenuto scritto ieri resta nella forma vecchia, e nessun tipo lo protegge perché è JSON in database.
La risposta è una migrazione: una funzione pura che riconosce la forma vecchia e produce quella nuova. Il pacchetto non ne spedisce e non ne impone la forma — a percorrere i documenti e a riscriverli ci pensa uno script del progetto, che è anche l’unico posto in cui si sa quali collection guardare.
La regola che conviene tenere: prima si scrive il caso di prova con un documento nella forma vecchia, poi la funzione. Una migrazione che sbaglia non lancia un errore — scrive un dato che nessun ramo riconosce, e l’elemento smette di apparire.