UNPKG

abstract-type

Version:

The abstract-type library includes the abstract `Type` class and `Value` class for streamable type info and validating value.

515 lines (438 loc) 14.2 kB
(function() { var Attributes, Type, Value, attributes, createObject, defineProperty, extend, factory, getObjectKeys, isArray, isFunction, isInheritedFrom, isObject, isString, isUndefined, objectToString, properties; properties = require('property-manager/ability'); factory = require('custom-factory'); createObject = require('inherits-ex/lib/createObject'); isInheritedFrom = require('inherits-ex/lib/isInheritedFrom'); isObject = require('util-ex/lib/is/type/object'); isFunction = require('util-ex/lib/is/type/function'); isString = require('util-ex/lib/is/type/string'); isArray = require('util-ex/lib/is/type/array'); isUndefined = require('util-ex/lib/is/type/undefined'); defineProperty = require('util-ex/lib/defineProperty'); extend = require('util-ex/lib/_extend'); Attributes = require('./attributes/'); attributes = new Attributes(); objectToString = Object.prototype.toString; getObjectKeys = Object.keys; Value = (function() { Value.tryGetTypeName = function(aValue) { var i, result; if (aValue instanceof Object) { result = objectToString.call(aValue); i = result.lastIndexOf(' '); if (i >= 0) { result = result.substring(i + 1, result.length - 1); } } else { result = typeof aValue; result = result.charAt(0).toUpperCase() + result.substring(1); } return result; }; function Value(aValue, aType, aOptions) { var vTypeName; if (!(aType instanceof Type)) { aOptions = aType; vTypeName = Value.tryGetTypeName(aValue); if (aOptions) { aType = Type.create(vTypeName, aOptions); } else { aType = Type(vTypeName); } if (!aType) { throw new TypeError('can not determine the value type.'); } } if (!(this instanceof Value)) { return createObject(aType.ValueType, aValue, aType, aOptions); } defineProperty(this, '$type', aType); this._initialize(aValue, aType, aOptions); this.assign(aValue, aOptions); } Value.prototype.isValid = function(aOptions) { return this.$type.isValid(this.valueOf(), aOptions); }; Value.prototype._initialize = function(aValue, aType, aOptions) { return defineProperty(this, 'value', null); }; Value.prototype._assign = function(aValue) { this.value = aValue; }; Value.prototype.assign = function(aValue, aOptions) { var checkValidity, vType; if (aOptions) { checkValidity = aOptions.checkValidity; } vType = this.$type; if (isFunction(vType.toValue)) { aValue = vType.toValue(aValue, aOptions); } else if (aValue instanceof Value) { aValue = aValue.valueOf(); } if (checkValidity !== false) { this.$type.validate(aValue, checkValidity); } this._assign(aValue); return this; }; Value.prototype.create = function(aValue, aOptions) { return this.$type.createValue(aValue, aOptions); }; Value.prototype.clone = function(aOptions) { return this.create(this.valueOf(), aOptions); }; Value.prototype.toString = function() { return String(this.valueOf()); }; Value.prototype.valueOf = function() { return this.value; }; Value.prototype._toObject = function(aOptions) { return this.valueOf(); }; Value.prototype.toObject = function(aOptions) { var result; if (aOptions && aOptions.withType) { delete aOptions.withType; result = this.toObjectWithType(aOptions); } else { result = this._toObject(aOptions); } return result; }; Value.prototype.toObjectWithType = function(aOptions) { var result, value; value = this._toObject(aOptions); result = this.$type.toObject(aOptions); result.value = value; return result; }; Value.prototype.fromJson = function(aString) { aString = JSON.parse(aString); return this.assign(aString); }; Value.prototype.createFromJson = function(aString) { var vType; aString = JSON.parse(aString); vType = this.$type; if (vType.toValue) { aString = vType.toValue(aString); } return createObject(this.$type.ValueType, aString, vType); }; Value.prototype.toJSON = function(aOptions) { var result, vType; result = this.toObject(aOptions); vType = this.$type; if (vType.valueToString) { if (result.hasOwnProperty('value')) { result.value = vType.valueToString(result.value); } else { result = vType.valueToString(result); } } return result; }; Value.prototype.toJson = function(aOptions) { var result; result = this.toJSON(aOptions); return JSON.stringify(result); }; Value.prototype.inspect = function() { return '<type ' + this.$type._inspect({ value: this._toObject() }) + '>'; }; return Value; })(); module.exports = Type = (function() { var oldAssign; factory(Type); properties(Type, { name: 'advance' }); Type.ROOT_NAME = 'type'; Type.Value = Value; Type.prototype.ValueType = Value; Type.prototype.$attributes = attributes; function Type(aTypeName, aOptions) { var vCaller, vTypeClass; if (!(this instanceof Type) && !(aTypeName instanceof Type)) { if (aTypeName) { if (isObject(aTypeName)) { aOptions = aTypeName; aTypeName = attributes.getValue(aOptions, 'name'); } else if (!isString(aTypeName)) { aOptions = aTypeName; aTypeName = void 0; } } if (!aTypeName) { try { vCaller = arguments.callee.caller; } catch (_error) {} if (vCaller && isInheritedFrom(vCaller, Type)) { aTypeName = vCaller; vCaller = vCaller.caller; while (isInheritedFrom(vCaller, aTypeName)) { aTypeName = vCaller; vCaller = vCaller.caller; } if (aTypeName) { aTypeName = Type.getNameFromClass(aTypeName); } } if (!aTypeName) { return; } } vTypeClass = Type.registeredClass(aTypeName); if (vTypeClass && aOptions && !vTypeClass.prototype.$attributes.isDefaultObject(aOptions)) { return createObject(vTypeClass, aOptions); } } return Type.__super__.constructor.apply(this, arguments); } Type.prototype.initialize = function(aOptions) { defineProperty(this, 'errors', null); if (this.$attributes) { this.$attributes.initializeTo(this); } if (this._initialize) { this._initialize(aOptions); } if (aOptions != null) { return this.assign(aOptions); } }; Type.prototype.finalize = function(aOptions) { if (this.errors) { this.errors = null; } if (this._finalize) { return this._finalize(aOptions); } }; Type.validators = {}; Type.registerValidator = function(aValidator, aValidatorFn) { var result, vIsFn; vIsFn = null; if (isObject(aValidator)) { if (vIsFn = isFunction(aValidator.validate)) { aValidatorFn = aValidator.validate; } if (aValidator.name) { aValidator = aValidator.name; } } if (vIsFn === null) { vIsFn = isFunction(aValidatorFn); } result = vIsFn && isString(aValidator) && !Type.validators[aValidator]; if (result) { Type.validators[aValidator] = aValidatorFn; } return result; }; Type.unregisterValidator = function(aValidatorName) { return delete Type.validators[aValidatorName]; }; Type.prototype._checkValidator = function(aValue, aOptions) { var result, vFn, vName, _ref; if (!isObject(aOptions)) { aOptions = this; } result = true; _ref = Type.validators; for (vName in _ref) { vFn = _ref[vName]; if ((aOptions[vName] != null) || this.$attributes.getRealAttrName(vName)) { result = vFn.call(this, aValue, aOptions); if (!result) { break; } } } return result; }; oldAssign = Type.prototype.assign; Type.prototype.assign = function(aOptions, aExclude) { this.errors = []; return oldAssign.call(this, aOptions, aExclude); }; Type.prototype._validate = function(aValue, aOptions) { return true; }; Type.prototype.error = function(aMessage, aOptions) { var name; name = (aOptions && this.$attributes.getValue(aOptions, 'name')) || String(this); this.errors.push({ name: name, message: aMessage }); }; Type.prototype.isRequired = function(aValue, aOptions) { var result, vRequired; if (!isObject(aOptions)) { aOptions = this; } vRequired = this.$attributes.getValue(aOptions, 'required'); return result = !vRequired || (vRequired === true && (aValue != null)); }; Type.prototype.validateRequired = function(aValue, aOptions) { var result; result = this.isRequired(aValue, aOptions); if (!result) { this.error('is required', aOptions); } return result; }; Type.prototype.validate = function(aValue, raiseError, aOptions) { var customValidate, result; this.errors = []; if (isObject(raiseError)) { aOptions = raiseError; raiseError = aOptions.raiseError; } if (aOptions) { customValidate = this.$attributes.getValue(aOptions, 'customValidate'); } aOptions = this.mergeTo(aOptions, 'name'); if (!customValidate) { customValidate = aOptions.customValidate; } if (raiseError) { aOptions.raiseError = true; } result = this.validateRequired(aValue, aOptions); if (result) { result = this._checkValidator(aValue, aOptions); } if (result && isFunction(customValidate)) { result = customValidate.call(this, aValue, aOptions); } if (result && (aValue != null)) { result = this._validate(aValue, aOptions); } if (raiseError !== false && !result) { throw new TypeError('"' + aValue + '" is an invalid ' + this.name); } return result; }; Type.prototype.isValid = function(aValue, aOptions) { return this.validate(aValue, false, aOptions); }; Type.prototype.createValue = function(aValue, aOptions) { var vType; if (aOptions && !this.isSame(aOptions)) { aOptions = this.mergeTo(aOptions, 'name'); if (isFunction(Type.getCacheItem)) { if (aOptions.cached == null) { aOptions.cached = true; } vType = Factory.getCacheItem(this.Class, aOptions); } else { vType = this.createType(aOptions); } } else { vType = this; } return createObject(vType.ValueType, aValue, vType, aOptions); }; Type.prototype.create = Type.prototype.createValue; Type.prototype.createType = function(aOptions) { var result; if (aOptions) { delete aOptions.value; } result = createObject(this.Class, aOptions); return result; }; Type.prototype.cloneType = function(aOptions) { aOptions = this.exportTo(aOptions, 'name', true, true); if (!aOptions.name) { aOptions.name = this.name; } return this.createType(aOptions); }; Type.prototype.clone = Type.prototype.cloneType; Type.fromJson = function(aString) { return Type.from(JSON.parse(aString)); }; Type.createFromJson = function(aString) { return Type.createFrom(JSON.parse(aString)); }; Type.from = function(aObject) { var result; result = Type(aObject); if ((aObject.value != null) && result) { result = result.createValue(aObject.value); } return result; }; Type.createFrom = function(aObject) { var result, value; value = aObject.value; result = Type.create(aObject.name, aObject); if ((value != null) && result) { result = result.createValue(value); } return result; }; Type.prototype.toString = function(aOptions) { return '[type ' + this.name + ']'; }; Type.prototype._inspect = function(aOptions, aNameRequired) { var result, vAttrs; if (aNameRequired == null) { aNameRequired = false; } result = '"' + this.name + '"'; vAttrs = this.toJson(aOptions, aNameRequired).slice(1, -1); if (vAttrs) { result += ': ' + vAttrs; } return result; }; Type.prototype.inspect = function() { return '<type ' + this._inspect() + '>'; }; Type.prototype.toJson = function(aOptions, aNameRequired) { var result; result = this.toObject(aOptions, aNameRequired); result = JSON.stringify(result); return result; }; Type.prototype._toObject = function(aOptions, aNameRequired) { var result, vExclude; if (aNameRequired == null) { aNameRequired = true; } if (!aNameRequired) { vExclude = 'name'; } result = this.exportTo(aOptions, vExclude, true, true); return result; }; Type.prototype.toObject = function(aOptions, aNameRequired) { var result, value; if (aOptions) { if (!(aOptions.typeOnly || isUndefined(aOptions.value))) { value = aOptions.value; } aOptions = extend({}, aOptions); delete aOptions.typeOnly; delete aOptions.value; } result = this._toObject(aOptions, aNameRequired); if (!isUndefined(value)) { result.value = value; } return result; }; return Type; })(); }).call(this); //# sourceMappingURL=index.js.map