Transformer rule
bcx-validation uses transformer to simplify the shape of the rule. You will rarely need to define a new transformer. But if you understand it, a new type of transformer can provide you maximum flexibility.
We have learnt if transformer in conditional validation. Let’s define a new ifNot transformer by reusing if transformer.
const ifNotTester = rule => (rule && _.isString(rule.ifNot) && !_.isEmpty(_.omit(rule, 'ifNot')));
validation.addTransformer(
ifNotTester,
rule => {
const {ifNot, ...others} = rule;
return {if: `!(${ifNot})`, ...others};
}
);
The first argument for addTransformer is a tester function, it tests whether a rule can be processed by ifNot transformer. You would like to design the tester as defensive as possible to avoid false hit.
The second argument is the transformer function itself, with the rule as input, return a transformed rule object as output. Here we rewrite the rule with if transformer.
When
bcx-validationresolves a rule, it recursively expands into understandable validators. Here the output ofifNottransformer is another rule need to be transformed byiftransformer. There is no limit of the depth of the resolution, as long as your transformers/validators design did not end up in infinite loop.
Here is another example of transformer. This is how we support bare regex as validation rule.
validation.validate('ab', /[A-Z]/); // => ['invalid format']
// the bare regex validator is implemented by following code
// copied from standard-validators.js
// transform regex
validation.addTransformer(
_.isRegExp,
rule => ({validate: 'isTrue', value: rule, message: 'invalid format'})
);
In summary, for flexibility, we use transformer to accept rule not matching the shape requirement ({validate: "validatorName", ...}). Have a look of all the transformers defined in standard validators, you should able to understand all of them except switch and foreach transformers.
When
bcx-validationresolves a rule, it tests against all transformers before trying any validator implementations. That’s how{if: 'condition', validate: 'isTrue'}is processed byiftransformer first. Ifbcx-validationtries validators before transformers,{if: 'condition', validate: 'isTrue'}will be wrongly treated as “isTrue” validator with option “if” with static value “condition”.
switchandforeachtransformers are different, they are “readyToUse” transformer. As for now, we would not document how to implement a “readyToUse” transformer, it involves understanding howbcx-validationinternally uses contextual-proxy. We will just document the usage ofswitchandforeachtransformers, they are quite useful.
Let’s move on to the switch transformer.