Skip to content

Latest commit

 

History

History
253 lines (201 loc) · 8.72 KB

validator.md

File metadata and controls

253 lines (201 loc) · 8.72 KB

Validation

fluid.schema.validator

This package provides a global validator that is instantiated when requiring this package from node, or when including the validator source from a browser. Once you have done either, you can access the global validator using an IoC reference, as shown in the example at end of this page.

Component Invokers

{fluid.schema.validator}.validate(toValidate, fssSchema, [schemaHash])

  • {Object} fssSchema: An FSS schema definition.
  • {Any} toValidate: The material to be validated.
  • {String} [schemaHash]: An optional schema hash precomputed using fluid.schema.hashSchema (see below).
  • Returns: An {Object} that describes the validation results. See below for details.

This function validates material against a "Fluid Schema System" schema, and returns an object describing the results. If there are no validation errors, the return value should look like:

{ "isValid": true }

If there are validation errors, the return value should look like:

{
 "isValid": false,
 "errors": [
     {
         "dataPath": ["requiredField"],
         "schemaPath": ["properties", "requiredField", "required"],
         "rule": { "required": true },
         "message": "fluid.schema.messages.validationErrors.required"
     },
     {
         "dataPath": ["deep", "booleanField"],
         "schemaPath": ["properties", "deep", "properties", "booleanField", "type"],
         "rule": { "type": "boolean" },
         "message": "fluid.schema.messages.validationErrors.type"
     }
 ]
}

The message values are "keys" that can be resolved to human-readable text using the fluid.schema.validator.localiseErrors function described below.

If a low-level error occurs while attempting to validate the data, a separate isError property will be set to true and the raw error message will be displayed in a top-level messages element, as in:

{
  "isError": true,
  "message": "Invalid FSS Schema."
}

{fluid.schema.validator}.clearCache()

  • Returns: Nothing.

As the compilation of a schema is quite expensive, the global validator has an internal cache that stores a compiled version of each schema that has been used for validation. This cache can be cleared by calling the validation component's clearCache invoker. You can also add or remove single schemas from the cache, see below for details.

{fluid.schema.validator}.cacheSchema(fssSchema, [schemaHash])

  • {Object} fssSchema: An FSS schema definition.
  • {String} [schemaHash]: An optional schema hash precomputed using fluid.schema.stringify.
  • Returns: The validator created by compiling the schema.

If a schema has not already been cached, it is cached the first time it is used by {fluid.schema.validator}.validate (see above). You can use this invoker to cache a schema ahead of time.

{fluid.schema.validator}.forgetSchema(fssSchema, [schemaHash])

  • {Object} fssSchema: An FSS schema definition.
  • {String} [schemaHash]: An optional schema hash precomputed using fluid.schema.stringify.
  • Returns: Nothing.

Remove a single schema from the internal cache.

Error Message Internationalisation/Localisation

fluid.schema.validator.localiseErrors(validationErrors, [validatedData], [messages], [localisationTransform])

  • {Array<Object>} validationErrors:An array of validation errors.
  • {Any} validatedData:The (optional) data that was validated.
  • {Object} messages:An (optional) map of message templates (see below). Will always fail over to the default message bundle provided by this package (see below).
  • {Object} localisationTransform:An optional set of rules that control what information is available when localising validation errors (see above).
  • Returns: An {Array} containing one or more validation errors, with all message keys replaced with localised strings.

This function takes the validation output returned by fluid.schema.validator.validate (see above) and replaces all message keys with strings rendered using fluid.stringTemplate.

If you want to pass a custom message bundle to this function, it should only contain top-level elements, see ./src/js/validation-errors.js in this package for an example.

By default, this rendering process has access to an object like the following:

{
    "data": "Not a number!",
    "errors": [{
       "dataPath": [
           "foo"
       ],
       "schemaPath": [
           "properties",
           "foo",
           "type"
       ],
       "rule": {
           "type": "number"
       },
       "message": "my.namespace.messages.customError"
   }]
}

You can refer to each of these in your message template using an EL Path. So, for example, you might define a message bundle that looked like:

{
    "my.namespace.messages.customError": "The value you provided (%data) is not a number."
}

You can control what is exposed and how by passing in a localisationTransform option. By default, the error itself is exposed as an error element, and the data that failed validation is exposed as data. If you wanted to avoid exposing the data in logs or onscreen (for example, when working with passwords), you could use a transform like the following:

{
  "error": "error"
}

Defaults

fluid.schema.validator.defaultI18nKeysByRule

For each type of error there is a default message key. This bundle of defaults has a string template for each of these. Any message keys that cannot be found in your message bundle will be looked up against this map and the default string template will be used instead.

fluid.schema.validator.defaultLocalisationTransformRules

By default, the error (validation error) and data (the value that broke the rule) are exposed. See above for an example of changing this behaviour.

fluid.schema.hashSchema(fssSchema)

  • {Object} fssSchema: An FSS schema definition.
  • Returns: A unique {String} hash representing the FSS Schema.

Many of the global validation component's invokers accept a "schema hash", which is used to look up the schema in the validation component's internal cache. This static API function is provided to allow you to hash your schema content yourself. If this value is supplied to one of the above invokers, a small amount of time is saved versus calculating the hash multiple times from the raw schema. Each hash typically takes less than 1 millisecond, so the default invokers and grades do not store the hashed value. This function is provided for use cases where an additional 1ms makes a real difference in perceived performance, and the process of storing and passing around the schema hash is left up to the implementer.

Example Usage

Here is an example of how you might make use of the global validator in your own component.

/* eslint-env node */
"use strict";
var fluid = require("infusion");

fluid.require("%fluid-json-schema");

var my = fluid.registerNamespace("my");

fluid.registerNamespace("my.validating.component");

my.validating.component.validateInput = function (that, globalValidator, toValidate) {
    var validationResults = globalValidator.validate(that.options.schema, toValidate);
    if (validationResults.isValid) {
        return { isValid: true };
    }
    else {
        return { isValid: false, errors: fluid.schema.validator.localiseErrors(validationResults.errors, toValidate) };
    }
};

fluid.defaults("my.validating.component", {
    gradeNames: ["fluid.component"],
    schema: {
        "$schema": "fss-v7-full#",
        type: "object",
        properties: {
            foo: {
                type: "boolean",
                required: true
            }
        }
    },
    invokers: {
        validateInput: {
            funcName: "my.validating.component.validateInput",
            args: ["{that}", "{fluid.schema.validator}", "{arguments}.0"]
        }
    }
});

var myValidatingComponent = my.validating.component();

var validationResults = myValidatingComponent.validateInput({});
fluid.log(JSON.stringify(validationResults, null, 2));
/*
    {
      "isValid": false,
      "errors": [
        {
          "message": "This value is required.",
          "dataPath": [
            "foo"
          ],
          "schemaPath": [
            "properties",
            "foo",
            "required"
          ],
          "rule": {
            "type": "boolean",
            "required": true
          }
        }
      ]
    }
*/

var secondValidationResults = myValidatingComponent.validateInput({ foo: true});
fluid.log(JSON.stringify(secondValidationResults, null, 2));
/*
    {
      isValid: true
    }
*/

In the above example, the invoker definition includes an IoC reference to the global component in its args block.