New release is coming soon! If you want to try out the latest features, simply run npm i -s moleculer@next. The docs for the latest version are available here.

Validação de parâmetros

Um middleware de validação é usado para validações de parâmetros de Ações e Eventos.

Fastest Validator

Por padrão, Moleculer usa a biblioteca fastest-validator.

Uso padrão

//moleculer.config.js
module.exports = {
nodeID: "node-100",
validator: true // Using the default Fastest Validator
}

Configurando o validador pelo nome

//moleculer.config.js
module.exports = {
nodeID: "node-100",
validator: "Fastest" // Using the Fastest Validator
}

Exemplo com opções

//moleculer.config.js
module.exports = {
nodeID: "node-100",
validator: {
type: "Fastest",
options: {
useNewCustomCheckerFunction: true,
defaults: { /*...*/ },
messages: { /*...*/ },
aliases: { /*...*/ }
}
}
}

Validação de ações

Para realizar a validação de parâmetros você precisa definir a propriedade params na definição da ação e criar um esquema de validação para a ctx.params recebida.

Exemplo

const { ServiceBroker } = require("moleculer");

const broker = new ServiceBroker({
validator: true // Default is true
});

broker.createService({
name: "say",
actions: {
hello: {
// Validator schema for params
params: {
name: { type: "string", min: 2 }
},
handler(ctx) {
return "Hello " + ctx.params.name;
}
}
}
});

broker.call("say.hello").then(console.log)
.catch(err => console.error(err.message));
// -> throw ValidationError: "The 'name' field is required!"

broker.call("say.hello", { name: 123 }).then(console.log)
.catch(err => console.error(err.message));
// -> throw ValidationError: "The 'name' field must be a string!"

broker.call("say.hello", { name: "Walter" }).then(console.log)
.catch(err => console.error(err.message));
// -> "Hello Walter"

Experimente no Runkit

Exemplo de esquema de validação

{
id: { type: "number", positive: true, integer: true },
name: { type: "string", min: 3, max: 255 },
status: "boolean" // short-hand def
}
Documentation

Encontre mais informações sobre o esquema de validação na documentação da biblioteca

Validador personalizado assíncrono

FastestValidator (>= v1.11.0) suporta validadores personalizados assíncronos, o que significa que você pode passar metadados para funções de validador personalizadas. No Moleculer, o FastestValidator passa o ctx como metadados. Isso significa que você pode acessar o context atual, serviço, broker. Isso permite que você faça chamadas assíncronas (por exemplo, chamar outro serviço) em funções de validações personalizadas. Para habilitar isso, você deve definir o useNewCustomCheckerFunction como true em moleculer.config.js

Ativando validação assíncrona personalizada

//moleculer.config.js
module.exports = {
validator: {
type: "FastestValidator",
options: {
useNewCustomCheckerFunction: true,
defaults: { /*...*/ },
messages: { /*...*/ },
aliases: { /*...*/ }
}
}
}

Usando validação assíncrona personalizada

// posts.service.js
module.exports = {
name: "posts",
actions: {
params: {
$$async: true,
owner: { type: "string", custom: async (value, errors, schema, name, parent, context) => {
const ctx = context.meta;

const res = await ctx.call("users.isValid", { id: value });
if (res !== true)
errors.push({ type: "invalidOwner", field: "owner", actual: value });
return value;
} },
},
/* ... */
}
}

Validação de Eventos

A validação dos parâmetros de evento também é suportada. Para habilitá-la, defina params na definição do evento.

Por favor, note que os erros de validação não são enviados de volta para o requisitante, como acontece com os erros de ação. Erros de validação de evento são registrados, mas você também pode recuperá-los com o manipulador de erro global.

// mailer.service.js
module.exports = {
name: "mailer",
events: {
"send.mail": {
// Validation schema with shorthand notation
// More info: https://github.com/icebob/fastest-validator#shorthand-definitions
params: {
from: "string|optional",
to: "email",
subject: "string"
},
handler(ctx) {
this.logger.info("Event received, parameters OK!", ctx.params);
}
}
}
};

Validador personalizado

Você também pode implementar validadores personalizados. Recomendamos copiar o código fonte de Fastest Validator e implementar os métodos compile e validate.

Criar validador personalizado

//moleculer.config.js
const BaseValidator = require("moleculer").Validators.Base;

class MyValidator extends BaseValidator {}

module.exports = {
nodeID: "node-100",
validator: new MyValidator()
}

Criar validador Joi

const { ServiceBroker } = require("moleculer");
const BaseValidator = require("moleculer").Validators.Base;
const { ValidationError } = require("moleculer").Errors;
const Joi = require("joi");

// --- JOI VALIDATOR CLASS ---
class JoiValidator extends BaseValidator {
constructor() {
super();
}

compile(schema) {
return (params) => this.validate(params, schema);
}

validate(params, schema) {
const res = schema.validate(params);
if (res.error)
throw new ValidationError(res.error.message, null, res.error.details);

return true;
}
}

let broker = new ServiceBroker({
logger: true,
validator: new JoiValidator // Use Joi validator
});

// --- TEST BROKER ---

broker.createService({
name: "greeter",
actions: {
hello: {
/*params: {
name: { type: "string", min: 4 }
},*/
params: Joi.object().keys({
name: Joi.string().min(4).max(30).required()
}),
handler(ctx) {
return `Hello ${ctx.params.name}`;
}
}
}
});

broker.start()
.then(() => broker.call("greeter.hello").then(res => broker.logger.info(res)))
.catch(err => broker.logger.error(err.message, err.data))
// -> "name" is required ...
.then(() => broker.call("greeter.hello", { name: 100 }).then(res => broker.logger.info(res)))
.catch(err => broker.logger.error(err.message, err.data))
// -> "name" must be a string ...
.then(() => broker.call("greeter.hello", { name: "Joe" }).then(res => broker.logger.info(res)))
.catch(err => broker.logger.error(err.message, err.data))
// -> "name" length must be at least 4 characters long ...
.then(() => broker.call("greeter.hello", { name: "John" }).then(res => broker.logger.info(res)))
.catch(err => broker.logger.error(err.message, err.data));
Find more validators

Verifique a página de módulos e encontre mais validadores.