UNPKG

himanshu-react-jsonschema-form

Version:

A simple React component capable of building HTML forms out of a JSON schema.

176 lines (154 loc) 5.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; exports.toErrorList = toErrorList; exports.default = validateFormData; var _jsonschema = require("jsonschema"); var _utils = require("./utils"); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var RE_ERROR_ARRAY_PATH = /\[\d+]/g; function errorPropertyToPath(property) { // Parse array indices, eg. "instance.level1.level2[2].level3" // => ["instance", "level1", "level2", 2, "level3"] return property.split(".").reduce(function (path, node) { var match = node.match(RE_ERROR_ARRAY_PATH); if (match) { var nodeName = node.slice(0, node.indexOf("[")); var indices = match.map(function (str) { return parseInt(str.slice(1, -1), 10); }); path = path.concat(nodeName, indices); } else { path.push(node); } return path; }, []); } function toErrorSchema(errors) { // Transforms a jsonschema validation errors list: // [ // {property: "instance.level1.level2[2].level3", message: "err a"}, // {property: "instance.level1.level2[2].level3", message: "err b"}, // {property: "instance.level1.level2[4].level3", message: "err b"}, // ] // Into an error tree: // { // level1: { // level2: { // 2: {level3: {errors: ["err a", "err b"]}}, // 4: {level3: {errors: ["err b"]}}, // } // } // }; if (!errors.length) { return {}; } return errors.reduce(function (errorSchema, error) { var property = error.property, message = error.message; var path = errorPropertyToPath(property); var parent = errorSchema; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = path.slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var segment = _step.value; if (!(segment in parent)) { parent[segment] = {}; } parent = parent[segment]; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } if (Array.isArray(parent.__errors)) { // We store the list of errors for this node in a property named __errors // to avoid name collision with a possible sub schema field named // "errors" (see `validate.createErrorHandler`). parent.__errors = parent.__errors.concat(message); } else { parent.__errors = [message]; } return errorSchema; }, {}); } function toErrorList(errorSchema) { var fieldName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "root"; // XXX: We should transform fieldName as a full field path string. var errorList = []; if ("__errors" in errorSchema) { errorList = errorList.concat(errorSchema.__errors.map(function (stack) { return { stack: fieldName + ": " + stack }; })); } return Object.keys(errorSchema).reduce(function (acc, key) { if (key !== "__errors") { acc = acc.concat(toErrorList(errorSchema[key], key)); } return acc; }, errorList); } function createErrorHandler(formData) { var handler = { // We store the list of errors for this node in a property named __errors // to avoid name collision with a possible sub schema field named // "errors" (see `utils.toErrorSchema`). __errors: [], addError: function addError(message) { this.__errors.push(message); } }; if ((0, _utils.isObject)(formData)) { return Object.keys(formData).reduce(function (acc, key) { return _extends({}, acc, _defineProperty({}, key, createErrorHandler(formData[key]))); }, handler); } return handler; } function unwrapErrorHandler(errorHandler) { return Object.keys(errorHandler).reduce(function (acc, key) { if (key === "addError") { return acc; } else if (key === "__errors") { return _extends({}, acc, _defineProperty({}, key, errorHandler[key])); } return _extends({}, acc, _defineProperty({}, key, unwrapErrorHandler(errorHandler[key]))); }, {}); } /** * This function processes the formData with a user `validate` contributed * function, which receives the form data and an `errorHandler` object that * will be used to add custom validation errors for each field. */ function validateFormData(formData, schema, customValidate) { var _jsonValidate = (0, _jsonschema.validate)(formData, schema), errors = _jsonValidate.errors; var errorSchema = toErrorSchema(errors); if (typeof customValidate !== "function") { return { errors: errors, errorSchema: errorSchema }; } var errorHandler = customValidate(formData, createErrorHandler(formData)); var userErrorSchema = unwrapErrorHandler(errorHandler); var newErrorSchema = (0, _utils.mergeObjects)(errorSchema, userErrorSchema, true); // XXX: The errors list produced is not fully compliant with the format // exposed by the jsonschema lib, which contains full field paths and other // properties. var newErrors = toErrorList(newErrorSchema); return { errors: newErrors, errorSchema: newErrorSchema }; }