UNPKG

angular2-json-schema-form

Version:
450 lines 20.1 kB
"use strict"; var _ = require("lodash"); var validator_functions_1 = require("./validator.functions"); var utility_functions_1 = require("./utility.functions"); var jsonpointer_functions_1 = require("./jsonpointer.functions"); var json_validators_1 = require("./json.validators"); function buildSchemaFromLayout(layout) { return; } exports.buildSchemaFromLayout = buildSchemaFromLayout; function buildSchemaFromData(data, requireAllFields, isRoot) { if (requireAllFields === void 0) { requireAllFields = false; } if (isRoot === void 0) { isRoot = true; } var newSchema = {}; if (isRoot) { newSchema.$schema = 'http://json-schema.org/draft-04/schema#'; } var getFieldType = function (value) { var fieldType = validator_functions_1.getType(value, 'strict'); if (fieldType === 'integer') { return 'number'; } if (fieldType === 'null') { return 'string'; } return fieldType; }; newSchema.type = getFieldType(data); if (newSchema.type === 'object') { newSchema.properties = {}; if (requireAllFields) { newSchema.required = []; } for (var _i = 0, _a = Object.keys(data); _i < _a.length; _i++) { var key = _a[_i]; newSchema.properties[key] = buildSchemaFromData(data[key], requireAllFields, false); if (requireAllFields) { newSchema.required.push(key); } } } else if (newSchema.type === 'array') { var itemTypes = data.map(getFieldType).reduce(function (types, type) { return types.concat(types.indexOf(type) === -1 ? type : []); }, []); var buildSubSchemaFromData = function (value) { return buildSchemaFromData(value, requireAllFields, false); }; if (itemTypes.length === 1) { newSchema.items = data.map(buildSubSchemaFromData).reduce(function (combined, item) { return Object.assign(combined, item); }, {}); } else { newSchema.items = data.map(buildSubSchemaFromData); } if (requireAllFields) { newSchema.minItems = 1; } } return newSchema; } exports.buildSchemaFromData = buildSchemaFromData; function getFromSchema(schema, dataPointer, returnContainer) { if (returnContainer === void 0) { returnContainer = false; } var dataPointerArray = jsonpointer_functions_1.JsonPointer.parse(dataPointer); var subSchema = schema; if (dataPointerArray === null) { console.error('getFromSchema error: Invalid JSON Pointer: ' + dataPointer); return null; } var l = returnContainer ? dataPointerArray.length - 1 : dataPointerArray.length; for (var i = 0; i < l; ++i) { var parentSchema = subSchema; var key = dataPointerArray[i]; var subSchemaArray = false; var subSchemaObject = false; if (typeof subSchema !== 'object') { console.error('getFromSchema error: Unable to find "' + key + '" key in schema.'); console.error(schema); console.error(dataPointer); return null; } if (subSchema['type'] === 'array' && subSchema.hasOwnProperty('items') && (!isNaN(key) || key === '-')) { subSchema = subSchema['items']; subSchemaArray = true; } if (subSchema['type'] === 'object' && subSchema.hasOwnProperty('properties')) { subSchema = subSchema['properties']; subSchemaObject = true; } if (!subSchemaArray || !subSchemaObject) { if (subSchemaArray && key === '-') { subSchema = (parentSchema.hasOwnProperty('additionalItems')) ? parentSchema.additionalItems : {}; } else if (typeof subSchema === 'object' && subSchema.hasOwnProperty(key)) { subSchema = subSchema[key]; } else { console.error('getFromSchema error: Unable to find "' + key + '" item in schema.'); console.error(schema); console.error(dataPointer); return; } } } return subSchema; } exports.getFromSchema = getFromSchema; function getSchemaReference(schema, reference, schemaRefLibrary, recursiveRefMap) { if (schemaRefLibrary === void 0) { schemaRefLibrary = null; } if (recursiveRefMap === void 0) { recursiveRefMap = null; } var schemaPointer; var newSchema; if (validator_functions_1.isArray(reference) || typeof reference === 'string') { schemaPointer = jsonpointer_functions_1.JsonPointer.compile(reference); } else if (validator_functions_1.isObject(reference) && Object.keys(reference).length === 1 && reference.hasOwnProperty('$ref') && typeof reference.$ref === 'string') { schemaPointer = jsonpointer_functions_1.JsonPointer.compile(reference.$ref); } else { console.error('getSchemaReference error: ' + 'reference must be a JSON Pointer or $ref link'); console.error(reference); return reference; } if (recursiveRefMap) { schemaPointer = resolveRecursiveReferences(schemaPointer, recursiveRefMap); } if (schemaPointer === '') { return _.cloneDeep(schema); } else if (schemaRefLibrary && schemaRefLibrary.hasOwnProperty(schemaPointer)) { return _.cloneDeep(schemaRefLibrary[schemaPointer]); } else { newSchema = _.cloneDeep(jsonpointer_functions_1.JsonPointer.get(schema, schemaPointer)); if (validator_functions_1.isObject(newSchema) && Object.keys(newSchema).length === 1 && utility_functions_1.hasOwn(newSchema, 'allOf') && validator_functions_1.isArray(newSchema.allOf)) { newSchema = newSchema.allOf .map(function (object) { return getSchemaReference(schema, object, schemaRefLibrary, recursiveRefMap); }) .reduce(function (schema1, schema2) { return Object.assign(schema1, schema2); }, {}); } if (schemaRefLibrary) { schemaRefLibrary[schemaPointer] = _.cloneDeep(newSchema); } return newSchema; } } exports.getSchemaReference = getSchemaReference; function resolveRecursiveReferences(pointer, recursiveRefMap, arrayMap) { if (arrayMap === void 0) { arrayMap = new Map(); } var genericPointer = jsonpointer_functions_1.JsonPointer.toGenericPointer(jsonpointer_functions_1.JsonPointer.compile(pointer), arrayMap); var possibleReferences = true; var previousPointerValues = []; var catchCircularLinks = function (newPointer) { if (previousPointerValues.indexOf(newPointer) !== -1) { console.error('resolveRecursiveReferences error: ' + 'recursive reference map contains circular links'); console.error(recursiveRefMap); return; } previousPointerValues.push(genericPointer); return newPointer; }; while (possibleReferences) { possibleReferences = false; recursiveRefMap.forEach(function (toPointer, fromPointer) { if (jsonpointer_functions_1.JsonPointer.isSubPointer(toPointer, fromPointer)) { while (jsonpointer_functions_1.JsonPointer.isSubPointer(fromPointer, genericPointer)) { genericPointer = catchCircularLinks(jsonpointer_functions_1.JsonPointer.toGenericPointer(toPointer + genericPointer.slice(fromPointer.length), arrayMap)); possibleReferences = true; } } }); } return genericPointer; } exports.resolveRecursiveReferences = resolveRecursiveReferences; function getInputType(schema, layoutNode) { if (layoutNode === void 0) { layoutNode = null; } var controlType = jsonpointer_functions_1.JsonPointer.getFirst([ [schema, '/x-schema-form/type'], [schema, '/x-schema-form/widget/component'], [schema, '/x-schema-form/widget'], [schema, '/widget/component'], [schema, '/widget'] ]); if (validator_functions_1.isString(controlType)) { return checkInlineType(controlType, schema, layoutNode); } var schemaType = schema.type; if (schemaType) { if (validator_functions_1.isArray(schemaType)) { if (validator_functions_1.inArray('object', schemaType) && utility_functions_1.hasOwn(schema, 'properties')) { schemaType = 'object'; } else if (validator_functions_1.inArray('array', schemaType) && utility_functions_1.hasOwn(schema, 'items')) { schemaType = 'array'; } else if (validator_functions_1.inArray('string', schemaType)) { schemaType = 'string'; } else if (validator_functions_1.inArray('number', schemaType)) { schemaType = 'number'; } else if (validator_functions_1.inArray('integer', schemaType)) { schemaType = 'integer'; } else if (validator_functions_1.inArray('boolean', schemaType)) { schemaType = 'boolean'; } else { schemaType = 'null'; } } if (schemaType === 'boolean') { return 'checkbox'; } if (schemaType === 'object') { if (utility_functions_1.hasOwn(schema, 'properties')) { return 'fieldset'; } if (utility_functions_1.hasOwn(schema, '$ref') || jsonpointer_functions_1.JsonPointer.has(schema, '/additionalProperties/$ref')) { return '$ref'; } return null; } if (schemaType === 'array') { var itemsObject = jsonpointer_functions_1.JsonPointer.getFirst([ [schema, '/items'], [schema, '/additionalItems'] ]); if (!itemsObject) { return null; } if (utility_functions_1.hasOwn(itemsObject, 'enum')) { return checkInlineType('checkboxes', schema, layoutNode); } else { return 'array'; } } if (schemaType === 'null') { return 'hidden'; } if (utility_functions_1.hasOwn(schema, 'enum')) { return 'select'; } if (schemaType === 'number' || schemaType === 'integer') { if (utility_functions_1.hasOwn(schema, 'maximum') && utility_functions_1.hasOwn(schema, 'minimum') && (schemaType === 'integer' || utility_functions_1.hasOwn(schema, 'multipleOf'))) { return 'range'; } return schemaType; } if (schemaType === 'string') { if (utility_functions_1.hasOwn(schema, 'format')) { if (schema.format === 'color') { return 'color'; } if (schema.format === 'date') { return 'date'; } if (schema.format === 'date-time') { return 'datetime-local'; } if (schema.format === 'email') { return 'email'; } if (schema.format === 'uri') { return 'url'; } } return 'text'; } } if (utility_functions_1.hasOwn(schema, '$ref')) { return '$ref'; } return 'text'; } exports.getInputType = getInputType; function checkInlineType(controlType, schema, layoutNode) { if (layoutNode === void 0) { layoutNode = null; } if (!validator_functions_1.isString(controlType) || (controlType.slice(0, 8) !== 'checkbox' && controlType.slice(0, 5) !== 'radio')) { return controlType; } if (jsonpointer_functions_1.JsonPointer.getFirst([ [layoutNode, '/inline'], [layoutNode, '/options/inline'], [schema, '/inline'], [schema, '/x-schema-form/inline'], [schema, '/x-schema-form/options/inline'], [schema, '/x-schema-form/widget/inline'], [schema, '/x-schema-form/widget/component/inline'], [schema, '/x-schema-form/widget/component/options/inline'], [schema, '/widget/inline'], [schema, '/widget/component/inline'], [schema, '/widget/component/options/inline'], ]) === true) { return controlType.slice(0, 5) === 'radio' ? 'radios-inline' : 'checkboxes-inline'; } else { return controlType; } } exports.checkInlineType = checkInlineType; function isInputRequired(schema, pointer) { if (!validator_functions_1.isObject(schema)) { console.error('isInputRequired error: Input schema must be an object.'); return false; } var listPointerArray = jsonpointer_functions_1.JsonPointer.parse(pointer); if (validator_functions_1.isArray(listPointerArray) && listPointerArray.length) { var keyName = listPointerArray.pop(); var requiredList = void 0; if (listPointerArray.length) { if (listPointerArray[listPointerArray.length - 1] === '-') { requiredList = jsonpointer_functions_1.JsonPointer.get(schema, listPointerArray.slice(-1).concat(['items', 'required'])); } else { requiredList = jsonpointer_functions_1.JsonPointer.get(schema, listPointerArray.concat('required')); } } else { requiredList = schema['required']; } if (validator_functions_1.isArray(requiredList)) { return requiredList.indexOf(keyName) !== -1; } } return false; } exports.isInputRequired = isInputRequired; ; function updateInputOptions(layoutNode, schema, jsf) { if (!validator_functions_1.isObject(layoutNode)) { return; } var templatePointer = jsonpointer_functions_1.JsonPointer.get(jsf, ['dataMap', layoutNode.dataPointer, 'templatePointer']); Object.keys(layoutNode).forEach(function (option) { if (option !== 'type' && validator_functions_1.isFunction(json_validators_1.JsonValidators[option]) && (!utility_functions_1.hasOwn(schema, option) || (schema[option] !== layoutNode[option] && !(option.slice(0, 3) === 'min' && schema[option] < layoutNode[option]) && !(option.slice(0, 3) === 'max' && schema[option] > layoutNode[option])))) { var validatorPointer = templatePointer + '/validators/' + option; jsf.formGroupTemplate = jsonpointer_functions_1.JsonPointer.set(jsf.formGroupTemplate, validatorPointer, [layoutNode[option]]); } }); var newOptions = {}; var fixUiKeys = function (key) { return key.slice(0, 3) === 'ui:' ? key.slice(3) : key; }; utility_functions_1.mergeFilteredObject(newOptions, jsf.globalOptions.formDefaults, [], fixUiKeys); if (jsonpointer_functions_1.JsonPointer.has(schema, '/items/enum')) { newOptions.enum = schema.items.enum; } if (jsonpointer_functions_1.JsonPointer.has(schema, '/items/titleMap')) { newOptions.enum = schema.items.titleMap; } utility_functions_1.mergeFilteredObject(newOptions, jsonpointer_functions_1.JsonPointer.get(schema, '/ui:widget/options'), [], fixUiKeys); utility_functions_1.mergeFilteredObject(newOptions, jsonpointer_functions_1.JsonPointer.get(schema, '/ui:widget'), [], fixUiKeys); utility_functions_1.mergeFilteredObject(newOptions, schema, ['properties', 'items', 'required', 'type', 'x-schema-form', '$ref'], fixUiKeys); utility_functions_1.mergeFilteredObject(newOptions, jsonpointer_functions_1.JsonPointer.get(schema, '/x-schema-form/options'), [], fixUiKeys); utility_functions_1.mergeFilteredObject(newOptions, jsonpointer_functions_1.JsonPointer.get(schema, '/x-schema-form'), ['items', 'options'], fixUiKeys); utility_functions_1.mergeFilteredObject(newOptions, layoutNode, ['arrayItem', 'dataPointer', 'dataType', 'items', 'layoutPointer', 'listItems', 'name', 'options', 'tupleItems', 'type', 'widget', '_id', '$ref'], fixUiKeys); utility_functions_1.mergeFilteredObject(newOptions, layoutNode.options, [], fixUiKeys); layoutNode.options = newOptions; if (schema.type === 'integer' && !validator_functions_1.hasValue(layoutNode.options.multipleOf)) { layoutNode.options.multipleOf = 1; } if (jsonpointer_functions_1.JsonPointer.has(newOptions, '/autocomplete/source')) { newOptions.typeahead = newOptions.autocomplete; } else if (jsonpointer_functions_1.JsonPointer.has(newOptions, '/tagsinput/source')) { newOptions.typeahead = newOptions.tagsinput; } else if (jsonpointer_functions_1.JsonPointer.has(newOptions, '/tagsinput/typeahead/source')) { newOptions.typeahead = newOptions.tagsinput.typeahead; } if (templatePointer && schema.type !== 'array' && schema.type !== 'object') { var layoutNodeValue = jsonpointer_functions_1.JsonPointer.getFirst([ [jsf.defaultValues, layoutNode.dataPointer], [layoutNode, '/value'], [layoutNode, '/default'] ]); var templateValue = jsonpointer_functions_1.JsonPointer.get(jsf.formGroupTemplate, templatePointer + '/value/value'); if (validator_functions_1.hasValue(layoutNodeValue) && layoutNodeValue !== templateValue) { jsf.formGroupTemplate = jsonpointer_functions_1.JsonPointer.set(jsf.formGroupTemplate, templatePointer + '/value/value', layoutNodeValue); } delete layoutNode.value; delete layoutNode.default; } } exports.updateInputOptions = updateInputOptions; function getControlValidators(schema) { if (!validator_functions_1.isObject(schema)) { return null; } var validators = {}; if (utility_functions_1.hasOwn(schema, 'type')) { switch (schema.type) { case 'string': utility_functions_1.forEach(['pattern', 'format', 'minLength', 'maxLength'], function (prop) { if (utility_functions_1.hasOwn(schema, prop)) { validators[prop] = [schema[prop]]; } }); break; case 'number': case 'integer': utility_functions_1.forEach(['Minimum', 'Maximum'], function (Limit) { var eLimit = 'exclusive' + Limit; var limit = Limit.toLowerCase(); if (utility_functions_1.hasOwn(schema, limit)) { var exclusive = utility_functions_1.hasOwn(schema, eLimit) && schema[eLimit] === true; validators[limit] = [schema[limit], exclusive]; } }); utility_functions_1.forEach(['multipleOf', 'type'], function (prop) { if (utility_functions_1.hasOwn(schema, prop)) { validators[prop] = [schema[prop]]; } }); break; case 'object': utility_functions_1.forEach(['minProperties', 'maxProperties', 'dependencies'], function (prop) { if (utility_functions_1.hasOwn(schema, prop)) { validators[prop] = [schema[prop]]; } }); break; case 'array': utility_functions_1.forEach(['minItems', 'maxItems', 'uniqueItems'], function (prop) { if (utility_functions_1.hasOwn(schema, prop)) { validators[prop] = [schema[prop]]; } }); break; } } if (utility_functions_1.hasOwn(schema, 'enum')) { validators['enum'] = [schema['enum']]; } return validators; } exports.getControlValidators = getControlValidators; //# sourceMappingURL=json-schema.functions.js.map