Esta biblioteca fornece um motor de validação declarativo inspirado em bibliotecas como Yup.
O foco é mantê-la simples de usar.
Um Schema descreve como um dado deve ser validado. Ele não transforma o dado final, apenas valida.
Exemplo 1:
const schema = new Schema({
age: SR.number().min(18)
});
const data = {age: 27};
await schema.validate(data);Exemplo 2:
const age = SR.number().min(18);
const schema = new Schema(age);
const data = 27;
await schema.validate(data);Exemplo 3
// Definição de regras novas
SR.extend({
age: SR.number().min(18),
password: SR
.string()
.min(8)
.matches(/[A-Z]/)
.matches(/[a-z]/)
.matches(/[0-9]/)
.matches(/[@#$%!*]/)
});
// Definição de schema
const formRules = {
age: SR.age(),
userPassword: SR.password(),
confirmPassword: SR.equal(SR.ref('userPassword')),
email: SR.email()
};
const formSchema = new Schema(formRules);
// utilização do schema
await schema.validate(profileData);Se a validação falhar, uma exceção DataTypeError será lançada.
SR é a API fluente usada para construir regras de validação.
Cada chamada retorna uma nova instância imutável de regra.
SR.string().min(3).required()| Regra | Descrição |
|---|---|
SR.string() |
Valor deve ser string |
SR.number() |
Valor deve ser número |
SR.integer() |
Número inteiro |
SR.object() |
Objeto (não array) |
SR.array() |
Array |
SR.email() |
Email válido |
Exemplo:
const schema = new Schema({
email: SR.string().email()
});| Regra | Descrição |
|---|---|
.min(value) |
Valor >= value (ou length para string) |
.max(value) |
Valor <= value |
.equal(value) |
Igualdade estrita |
.oneOf(array) |
Deve pertencer à lista |
.matches(regex) |
Regex |
SR.number().min(10).max(100)Falha se o valor for:
nullundefined- string vazia (
'')
SR.string().required()Permite que o valor seja nulo.
Quando o valor é nulo:
- todas as regras subsequentes são ignoradas
SR.number().nullable().min(10)
⚠️ required()enullable()não podem coexistir.
Usado para validar objetos com estrutura interna.
const schema = new Schema({
user: SR.shape({
name: SR.string().required(),
age: SR.number().min(18)
})
});Regras não podem ser aplicadas antes ou depois de shape().
Valida cada item de um array usando outro schema.
const schema = new Schema({
scores: SR.array().of(
SR.number().min(0).max(100)
)
});Se algum item falhar, o erro será retornado por índice:
{
scores: [undefined, ['This value exceeds the allowed maximum.']]
}Permite referenciar valores do root do schema.
SR.number().min(SR.ref('minValue'))- Sempre resolve a partir do root original
- Não observa valores transformados
- Paths profundos são permitidos:
SR.ref('user.profile.age')Se o caminho não existir, retorna undefined.
custom(value, ...resolvedParams, data)Onde:
value: valor atual do camporesolvedParams: parâmetros passados (incluindoSR.ref()resolvido)data: root completo
SR.custom((value, min, data) => {
return value >= min;
}, SR.ref('minValue'))SR.custom(async (value) => {
await delay(50);
return value !== 'admin';
})Se um custom lançar uma exceção:
- a validação é abortada
- não é considerado erro de dado
- a exceção é propagada
Isso indica bug na validação, não no input.
Permite modificar o valor apenas para regras subsequentes do mesmo campo.
SR.string()
.transform(v => v.trim())
.min(3)- Não altera o dado original
- Não afeta
SR.ref() - Modifica apenas
ctx.value
SR.register('between', (value, min, max)=>{
if (value < min){
return false;
}
return (value <= max);
},'{name} must be between {0} and {1}');Uso:
SR.between(10, 20);Registra múltiplas regras de uma vez.
SR.extend({
positive: SR.number().min(0),
shortText: SR.string().max(10)
});Cada regra possui uma mensagem default.
SR.string().min(8).error('{name} must have {0} chars')Tokens suportados:
{name}— nome do campo{value}— valor atual{0},{1}— parâmetros resolvidos
SR.string().error((ctx, params) => {
return `${ctx.name} must be at least ${params[0]}`;
})try {
await schema.validate(data);
} catch (err) {
if (err instanceof DataTypeError) {
console.log(err.report);
}
}{
fieldName: [ 'error message' ],
nested: {
field: ['error']
}
}SR.ref()sempre lê do root originaltransformnão altera o root- Regras são executadas em ordem
ctxé mutável apenas dentro do campo- Exceções em regras indicam erro de implementação
DataTypeErrorindica erro de dado
Esta camada fornece uma integração direta entre HTML Forms e o motor de validação de schemas (Schema / SR).
O objetivo do FV é:
- ler dados diretamente do DOM
- normalizar os valores de inputs HTML
- construir um schema temporário a partir de atributos do formulário
- executar a validação usando o core da biblioteca
O FV não interpreta regras, não executa lógica de validação própria e não mascara erros de schema.
O fluxo completo é:
- Desenvolvedor descreve regras diretamente no HTML (via atributos)
FVlê o formulárioFVconstrói um schema comSRSchema.validateé executado- Resultado normalizado é retornado para uso no front-end
flowchart TD
A[HTMLFormElement] -->B(FV)
B --> C[Data representation]
B --> D[Inferred schema]
C --> E(Validation)
D --> E(Validation)
E --> F[Result]
E --> G[Error list]
G --> H[Error message]
G --> I[HTMLInputElement]
style A stroke:#333,stroke-width:3px
style F stroke:#333,stroke-width:3px
style H stroke:#333,stroke-width:3px
style I stroke:#333,stroke-width:3px
new FV(formElement)| Nome | Tipo | Descrição |
|---|---|---|
formElement |
HTMLFormElement |
Referência obrigatória para um <form> |
const form = document.querySelector('#user-form');
const fv = new FV(form);Se o parâmetro não for um HTMLFormElement, uma exceção será lançada.
Lê os valores atuais do formulário e retorna um objeto normalizado.
const data = fv.readForm();| Elemento | Resultado |
|---|---|
input[type=text] |
string |
input[type=radio] |
valor selecionado ou null |
input[type=checkbox] (1 campo) |
valor ou null |
input[type=checkbox] (grupo) |
array |
select[multiple] |
array |
disabled |
ignorado |
<input type="checkbox" name="agree" value="yes">{ agree: null } // não marcadoConstrói um schema temporário com base nos atributos dos elementos do formulário.
const schema = fv.buildSchema();O schema é criado uma única vez e reutilizado nas validações subsequentes.
Todo campo validado deve possuir name.
<input name="email">Campos sem name são ignorados.
Define a regra base a ser usada a partir de SR.
<input name="email" data-type="email">Equivale a:
SR.email()Se o valor não existir em SR, um BadSchemaError será lançado.
Campo obrigatório.
<input name="username" required>Equivale a:
SR.required()Permite valor null.
<input name="nickname" nullable>
⚠️ A presença do atributo ativanullable, independentemente do valor.
Cria uma igualdade estrita com outro campo do formulário.
<input name="password" data-type="string" required>
<input name="confirm" data-type="string" data-ref="password" required>Equivale a:
SR.equal(SR.ref('password'))- comparação estrita (
===) - valor lido do root original
- não observa
transform
A ordem de aplicação das regras é fixa:
requirednullabledata-ref(equal(ref))data-type
Essa ordem não depende da posição dos atributos no HTML.
Campos que possuem name, mas nenhum atributo de validação, são aceitos automaticamente.
<input name="comments">Equivale a:
SR.noop()Executa a validação completa do formulário.
const result = await fv.validate();{
valid: boolean,
errors: null | Record<string, {
element: HTMLElement,
messages: string[]
}>
}<form id="login">
<input name="email" data-type="email" required>
<input name="password" data-type="string" required>
</form>const fv = new FV(document.querySelector('#login'));
const result = await fv.validate();
if (!result.valid) {
Object.values(result.errors).forEach(err => {
err.element.classList.add('error');
console.log(err.messages);
});
}await fv.validate(true);Quando true, a validação para no primeiro erro encontrado.
- Representado por
DataTypeError - Retornado como
{ valid: false }
- Exceção normal (
Error) - Indica bug de schema ou regra
- Não é capturado nem convertido
<input type="checkbox" name="roles" value="admin">
<input type="checkbox" name="roles" value="user">{ roles: ['admin'] }<select name="tags" multiple>
<option value="a" selected>A</option>
<option value="b">B</option>
</select>{ tags: ['a'] }- FV não altera o DOM
- FV não transforma dados além da normalização
- Schema é criado uma única vez
- Erros de schema são propagados
- HTML descreve regras, não lógica