WoodyLabBuild with UIMS

Documentazione · src/engine/dal

La lettura del dato

Tredici file fra la pagina e il database. Ogni lettura è in cache, e ogni cache sa da cosa dipende — comprese le cose che stanno dentro il documento che ha letto.

Ogni lettura porta i suoi tag

Ogni fetcher avvolge la propria query in unstable_cache con i tag definiti in un punto solo, e gli stessi tag li invalidano gli hook revalidateCollection e revalidateDelete quando un documento cambia. Il patto vale solo se le due parti usano la stessa funzione per costruire il tag: per questo cache-tags.ts è tre righe e non è inline.

dal/cache-tags.ts

i nomi dei tag, in un punto solo

I tre tag, per nome

getCollectionTag('pages')                 // 'pages-list'
getDocumentIdTag('pages', '6a6d…')        // 'pages_6a6d…'
getDocumentSlugTag('pages', 'chi-siamo')  // 'pages_chi-siamo'
dal/index.ts

la porta dell’area: i fetcher e i registri

dal/getEntityById.ts

un documento per id

Come si chiama

const doc = await getEntityById(await context.getPayload(), 'pages', id, 2)

Cosa torna se non c'e

null   // e non un'eccezione: uno slot puo legittimamente non contenere niente
dal/getEntityBySlug.ts

un documento per slug

dal/getEntitiesByQuery.ts

N documenti da una query

Due letture, quando la dipendenza è dentro il documento

Una pagina dipende anche da quello che ha dentro: il menu incastonato nel blocco navigation dell’header, il record riferito da una card. Se cambia il menu, la pagina che lo mostra è stantia — ma il tag del menu la cache della pagina non ce l’ha, perché Next non sa derivare i tag dal risultato di una lettura.

La soluzione sono due livelli. Una lettura superficiale (depth: 0) restituisce gli id dei riferimenti; da quelli si costruiscono i tag; poi si fa la lettura profonda in cache con TUTTI i tag, il proprio e quelli delle dipendenze. Costa una lettura in più, ed è l’unico modo per avere invalidazione corretta senza svuotare tutto a ogni modifica.

dal/collectDependencyTags.ts

ricava i tag dei record incastonati (relazioni polimorfe: { relationTo, value })

dal/getEntityBySlugWithDeps.ts

la versione a due livelli per i documenti

dal/getCachedGlobalWithDeps.ts

la versione a due livelli per i global (header, footer)

Le sorgenti esterne invecchiano a tempo

Un JSON che sta altrove non ha un afterChange che ci avvisi: nessun hook scatterà mai per invalidarlo. Quindi non si invalida per evento ma per tempo — revalidateSec limita quanto può essere vecchio — e resta un tag dedicato per poterlo forzare a mano quando si sa che è cambiato.

dal/getExternalJson.ts

una sorgente HTTP dentro la DAL: cache a tempo più tag manuale

I registri: la forma letta dagli store, non dal database

Il registro dei viewMode legge db.viewmodes.json, applica l’override del tema attivo e restituisce la definizione pronta per il renderer. L’override è una FUSIONE, non una sostituzione: con la sostituzione un tema che dichiarava solo className buttava via quello base, che quindi non garantiva più niente e andava ricopiato in ogni tema.

Il registro delle animazioni fa lo stesso per le ricette. La versione precedente prendeva un BasePayload e faceva una payload.find per OGNI reazione, al momento della risoluzione, senza cache — la cache era stata rinunciata di proposito per evitare un altro problema. Leggendo dallo store il problema non si pone: non c’è query da mettere in cache.

slotsByViewMode risolve le aperture ESATTAMENTE come le risolve il renderer. È usato dall’interfaccia per proporre i nomi veri, e la ragione per cui condivide il codice invece di riprodurlo è che una divergenza fra i due produrrebbe elementi che non appaiono.

dal/viewModeRegistry.ts

il viewMode fuso con il tema, pronto per il renderer

dal/applyThemeOverride.ts

la fusione base ⊕ tema (merge, non replace)

dal/animationRegistry.ts

le ricette di animazione, lette dallo store

dal/slotsByViewMode.ts

le aperture di ogni viewMode, risolte come le risolve il renderer