Salta ai contenuti

Validazione e condizioni

Utilizzato con proprietà di tipo stringa o numero per renderizzare menu a tendina (select):

import type { StringProperty } from "@rebasepro/types";
// Simple: each value mapped to its label
const simple: StringProperty = {
type: "string",
name: "Status",
enum: { draft: "Draft", published: "Published", archived: "Archived" }
};
// As a list, which keeps the order you write
const listed: StringProperty = {
type: "string",
name: "Status",
enum: [
{ id: "draft", label: "Draft" },
{ id: "published", label: "Published" },
{ id: "archived", label: "Archived" }
]
};
// With colors (for Kanban columns and chips)
const colored: StringProperty = {
type: "string",
name: "Status",
enum: [
{ id: "draft", label: "Draft", color: "grayDark" },
{ id: "published", label: "Published", color: "greenDark" },
{ id: "archived", label: "Archived", color: "orangeDark" }
]
};

Un semplice elenco di valori, enum: ["draft", "published", "archived"], non fa parte del tipo. Una configurazione JavaScript che ne scrive uno funziona comunque: l’enum del database, i tipi generati e il menu a tendina dell’admin lo leggono come quei valori, ciascuno con sé stesso come etichetta.

Ogni regola risiede nel blocco validation della proprietà, e le regole accettate da una proprietà dipendono dal suo tipo: min conta i caratteri in una stringa, confronta grandezze in un numero e conta gli elementi in un array.

properties: {
title: {
type: "string",
name: "Title",
validation: { required: true, min: 2, max: 200 }
},
slug: {
type: "string",
name: "Slug",
validation: {
unique: true,
matches: /^[a-z0-9-]+$/,
matchesMessage: "Lowercase letters, digits and hyphens only",
trim: true,
lowercase: true
}
},
readingMinutes: {
type: "number",
name: "Reading time",
validation: { integer: true, moreThan: 0, max: 120 }
}
}

Il server controlla validation al confine della richiesta — REST, il socket realtime e MCP — su ciò che il chiamante ha inviato, prima che venga eseguito beforeSave, e risponde a una scrittura che viola una regola con un 400 che nomina ogni campo non valido. Il codice server che scrive in-process è considerato attendibile e non viene controllato rispetto a queste regole: rebase.data e rebase.dataAsAdmin in una function o in un cron job, context.data in un callback, uno script di seed. Ciò che vale lì è ciò che il database applica — required (NOT NULL), unique (un indice univoco), il tipo di un enum e la larghezza di una colonna varchar o char. Qualsiasi altra cosa scritta dal tuo codice server va controllata nel codice che la scrive.

Il pannello di amministrazione controlla le stesse regole prima di salvare, nel form del record e nell’editor in linea della tabella della collection. Una cella della tabella giudica un valore una volta che lo modifichi: un valore memorizzato che viola una regola aggiunta in seguito non mostra alcun errore nella tabella finché qualcuno non modifica quella cella.

Regola Tipo Descrizione
required boolean Il valore deve essere presente. Su una string, "" conta come assente: l’API la rifiuta a ogni scrittura, una creazione o un aggiornamento, con la stessa violazione required (a meno che la collection abbia un beforeSave, che può compilarla)
requiredMessage string Cosa viene detto quando non è presente: dal modulo di amministrazione, e come message della voce required del campo nel 400 dell’API. Il NOT NULL del database non porta alcun messaggio
unique boolean Solo una riga nella tabella può contenere questo valore. Il modulo di amministrazione lo controlla anche quando salva un valore che la modifica ha cambiato, così un duplicato viene segnalato sul suo campo prima della scrittura
uniqueInArray boolean Solo una voce per array può contenerlo. Si applica a un figlio diretto di una proprietà array, o a un figlio di primo livello di una map al suo interno. Solo modulo di amministrazione — non applicato dall’API o dal database.
Regola Tipo Descrizione
min / max number Numero minimo / massimo di caratteri, inclusi. Con columnType: "varchar" o "char", max definisce anche la dimensione della colonna (VARCHAR(max)), quindi ridurlo su una tabella che contiene già righe più lunghe è una migrazione che il database rifiuterà, e l’editor di collection avvisa quando una modifica lo riduce. La colonna predefinita è TEXT, che max lascia senza limite — il vincolo resta allora solo il controllo della richiesta del server
length number Esattamente questo numero di caratteri — un codice paese, un riferimento a lunghezza fissa
matches string | RegExp Un pattern che l’intero valore deve rispettare. Una stringa viene compilata per richiesta, quindi una che non si compila viene rifiutata all’avvio anziché trasformarsi silenziosamente in nessuna regola
matchesMessage string Cosa mostra il modulo quando matches fallisce
trim boolean Rimuove gli spazi vuoti iniziali e finali prima del salvataggio. Una trasformazione, non un controllo — modifica ciò che viene scritto, il che lo rende la soluzione per “lo stesso tag due volte, uno con uno spazio finale”. Solo modulo di amministrazione — non applicato dall’API o dal database.
lowercase / uppercase boolean Converte il valore in minuscolo/maiuscolo prima del salvataggio, come trim. Solo modulo di amministrazione — non applicato dall’API o dal database.

I formati email e URL non sono regole di validazione. email e url sono flag sulla proprietà stessa, accanto a type — dichiarazioni sui dati a partire dalle quali viene generato il contratto OpenAPI, piuttosto che comportamenti del modulo:

properties: {
email: { type: "string", name: "Email", email: true },
website: { type: "string", name: "Website", url: true }
}

Vedi Proprietà stringa.

Regola Tipo Descrizione
min / max number Valore minimo / massimo accettato, incluso
moreThan / lessThan number I corrispettivi esclusivi di min e max
positive / negative boolean Rigorosamente superiore / inferiore a zero. 0 viene rifiutato da entrambi — usa min: 0 per consentirlo
integer boolean Nessuna parte frazionaria. Non modifica il tipo di colonna; lo fa columnType
Regola Tipo Descrizione
min / max Date Data minima / massima accettata, inclusa. Un istante fisso, non “oggi”
Regola Tipo Descrizione
min / max number Numero minimo / massimo di elementi, inclusi. Elementi, non caratteri

È possibile rendere i campi dinamici in modo che reagiscano ai valori dell’entità. Esistono due modi per farlo:

Puoi utilizzare la proprietà conditions per definire regole dichiarative in JSON Logic che possono essere serializzate e modificate visivamente nell’editor delle collezioni.

price: {
type: "number",
name: "Price",
conditions: {
disabled: { "==": [{ "var": "values.is_free" }, true] },
required: { "!=": [{ "var": "values.is_free" }, true] },
min: 0,
clearOnDisabled: true // Set to null if field gets disabled
}
}

L’oggetto conditions ti dà accesso a:

  • disabled, disabledMessage, clearOnDisabled, hidden, readOnly
  • required, requiredMessage, min, max
  • defaultValue
  • enumConditions, allowedEnumValues, excludedEnumValues
  • referencePath, referenceFilter
  • canAddElements, sortable (per gli array)
  • acceptedFiles, maxFileSize (per i caricamenti)

disabledMessage è la frase che l’utente vede al posto del controllo. Senza di essa, un campo disattivato non spiega nulla, e questa è la differenza tra un modulo che guida l’utente e uno che lo blocca senza spiegazioni.

Per comportamenti complessi che non possono essere espressi tramite JSON Logic, puoi utilizzare dynamicProps, che valuta una funzione Javascript.

price: {
type: "number",
name: "Price",
dynamicProps: ({ values, authController }) => ({
admin: { disabled: values.is_free === true || !authController.user?.roles?.includes("admin") },
validation: values.is_free ? {} : { required: true, min: 0 }
})
}

Si applica la stessa avvertenza, e in modo ancora più netto: la funzione viene inclusa nel bundle del pannello ed eseguita a ogni render del modulo. Solo modulo di amministrazione — non applicato dall’API o dal database.