@polyn/immutable
Version:
Define object schema's for validation, and construction of immutable objects
49 lines • 13.6 kB
JavaScript
;function _typeof(obj){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj},_typeof(obj)}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function")}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});Object.defineProperty(subClass,"prototype",{writable:false});if(superClass)_setPrototypeOf(subClass,superClass)}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf?Object.setPrototypeOf.bind():function _setPrototypeOf(o,p){o.__proto__=p;return o};return _setPrototypeOf(o,p)}function _createSuper(Derived){var hasNativeReflectConstruct=_isNativeReflectConstruct();return function _createSuperInternal(){var Super=_getPrototypeOf(Derived),result;if(hasNativeReflectConstruct){var NewTarget=_getPrototypeOf(this).constructor;result=Reflect.construct(Super,arguments,NewTarget)}else{result=Super.apply(this,arguments)}return _possibleConstructorReturn(this,result)}}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call}else if(call!==void 0){throw new TypeError("Derived constructors may only return object or undefined")}return _assertThisInitialized(self)}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return self}function _isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));return true}catch(e){return false}}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf.bind():function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o)};return _getPrototypeOf(o)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,_toPropertyKey(descriptor.key),descriptor)}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);Object.defineProperty(Constructor,"prototype",{writable:false});return Constructor}function _toConsumableArray(arr){return _arrayWithoutHoles(arr)||_iterableToArray(arr)||_unsupportedIterableToArray(arr)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _iterableToArray(iter){if(typeof Symbol!=="undefined"&&iter[Symbol.iterator]!=null||iter["@@iterator"]!=null)return Array.from(iter)}function _arrayWithoutHoles(arr){if(Array.isArray(arr))return _arrayLikeToArray(arr)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function ownKeys(object,enumerableOnly){var keys=Object.keys(object);if(Object.getOwnPropertySymbols){var symbols=Object.getOwnPropertySymbols(object);enumerableOnly&&(symbols=symbols.filter(function(sym){return Object.getOwnPropertyDescriptor(object,sym).enumerable})),keys.push.apply(keys,symbols)}return keys}function _objectSpread(target){for(var i=1;i<arguments.length;i++){var source=null!=arguments[i]?arguments[i]:{};i%2?ownKeys(Object(source),!0).forEach(function(key){_defineProperty(target,key,source[key])}):Object.getOwnPropertyDescriptors?Object.defineProperties(target,Object.getOwnPropertyDescriptors(source)):ownKeys(Object(source)).forEach(function(key){Object.defineProperty(target,key,Object.getOwnPropertyDescriptor(source,key))})}return target}function _defineProperty(obj,key,value){key=_toPropertyKey(key);if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _toPropertyKey(arg){var key=_toPrimitive(arg,"string");return _typeof(key)==="symbol"?key:String(key)}function _toPrimitive(input,hint){if(_typeof(input)!=="object"||input===null)return input;var prim=input[Symbol.toPrimitive];if(prim!==undefined){var res=prim.call(input,hint||"default");if(_typeof(res)!=="object")return res;throw new TypeError("@@toPrimitive must return a primitive value.")}return(hint==="string"?String:Number)(input)}// Node, or global
;(function(root){// eslint-disable-line no-extra-semi
;var module={factories:{}};Object.defineProperty(module,"exports",{get:function get(){return null},set:function set(val){module.factories[val.name]=val.factory},// this property should show up when this object's property names are enumerated
enumerable:true,// this property may not be deleted
configurable:false});module.exports={name:"immutable",factory:function factory(Blueprint){"use strict";var is=Blueprint.is,blueprint=Blueprint.blueprint;/**
* Returns true if the object matches the (@polyn/blueprint).blueprint signature
* @param {any} input - the value to test
*/var isBlueprint=function isBlueprint(input){return is.object(input)&&is.string(input.name)&&is.function(input.validate)&&is.object(input.schema)};/**
* Returns true if the object matches the (@polyn/immutable).immutable signature
* @param {any} input - the value to test
*/var isImmutable=function isImmutable(input){var proto=Object.getPrototypeOf(input);return is.object(input)&&(is.function(input.isPolynImmutable)||is.function(proto&&proto.isPolynImmutable))};/**
* The default validator uses @polyn/blueprint for vaidation
* This can be overrided, to use things like ajv and JSON Schemas
* @param {string} name - the name of the model
* @param {object} schema - the blueprint schema
*/function Validator(name,schema){var bp;if(isBlueprint(name)){// a blueprint was passed as the first argument
bp=name}else{bp=blueprint(name,schema)}return{validate:function validate(input){var validationResult=bp.validate(input);if(validationResult.err){throw validationResult.err}return validationResult}}}/**
* Creates a new object from the given, `that`, and overwrites properties
* on it with the given, `input`
* @curried
* @param {any} that - the object being patched
* @param {any} input - the properties being written
*/var _patch=function patch(that){return function(input){var output=Object.assign({},that);Object.keys(input).forEach(function(key){if(is.array(input[key])){output[key]=input[key]}else if(is.object(input[key])){output[key]=_patch(output[key])(input[key])}else{output[key]=input[key]}});return output}};/**
* Creates a new, mutable object from the given, `that`
* @curried
* @param {any} that - the object being patched
* @param {any} options - whether or not to remove functions
*/var _toObject=function toObject(that,options){var shallowClone=Object.assign({},that);var output={};var _removeFunctions$opti=_objectSpread(_objectSpread({},{removeFunctions:false}),options),removeFunctions=_removeFunctions$opti.removeFunctions;Object.keys(shallowClone).forEach(function(key){if(shallowClone[key]&&typeof shallowClone[key].toObject==="function"){output[key]=shallowClone[key].toObject(options)}else if(is.array(shallowClone[key])){output[key]=Object.assign([],shallowClone[key])}else if(is.object(shallowClone[key])){output[key]=Object.assign({},shallowClone[key])}else if(is.function(shallowClone[key])&&removeFunctions===true){// do nothing
}else{output[key]=shallowClone[key]}});return output};var push=function push(arr){return function(){for(var _len=arguments.length,newEntry=new Array(_len),_key=0;_key<_len;_key++){newEntry[_key]=arguments[_key]}return[].concat(_toConsumableArray(arr),newEntry)}};var pop=function pop(arr){return function(){return arr.slice(0,-1)}};var shift=function shift(arr){return function(){return arr.slice(1)}};var unshift=function unshift(arr){return function(){for(var _len2=arguments.length,newEntry=new Array(_len2),_key2=0;_key2<_len2;_key2++){newEntry[_key2]=arguments[_key2]}return[].concat(newEntry,_toConsumableArray(arr))}};var sort=function sort(arr){return function(compareFunction){return _toConsumableArray(arr).sort(compareFunction)}};var reverse=function reverse(arr){return function(){return _toConsumableArray(arr).reverse()}};var copy=function copy(arr){return function(){return _toConsumableArray(arr)}};var slice=function slice(arr){return function(){return arr.slice.apply(arr,arguments)}};var splice=function splice(arr){return function(start,deleteCount){for(var _len3=arguments.length,items=new Array(_len3>2?_len3-2:0),_key3=2;_key3<_len3;_key3++){items[_key3-2]=arguments[_key3]}return[].concat(_toConsumableArray(arr.slice(0,start)),items,_toConsumableArray(arr.slice(start+deleteCount)))}};var remove=function remove(arr){return function(index){return arr.slice(0,index).concat(arr.slice(index+1))}};function PolynImmutable(config){config=_objectSpread(_objectSpread({},{Validator:Validator}),config);/**
* Creates a Validator (@polyn/blueprint by default) and returns a
* function for creating new instances of objects that get validated
* against the given schema. All of the properties on the returned
* value are immutable
* @curried
* @param {string|blueprint} name - the name of the immutable, or an existing blueprint
* @param {object} schema - the blueprint schema
*/var immutable=function immutable(name,schema,options){var validator=new config.Validator(name,schema);var _functionsOnPrototype=_objectSpread(_objectSpread({},{functionsOnPrototype:false}),options),functionsOnPrototype=_functionsOnPrototype.functionsOnPrototype;// NOTE the classes, and freezeArray are in here, so their
// prototypes don't cross-contaminate
/**
* Freezes an array, and all of the array's values, recursively
* @param {array} input - the array to freeze
*/var freezeArray=function freezeArray(input){return Object.freeze(input.map(function(val){if(is.array(val)){return freezeArray(val)}else if(is.object(val)&&!isImmutable(val)){return new Immutable(val)}else{return val}}))};/**
* Freezes an object, and all of it's values, recursively
* @param {object} input - the object to freeze
*/var Immutable=/*#__PURE__*/function(){function Immutable(input){var _this=this;_classCallCheck(this,Immutable);Object.keys(input).forEach(function(key){if(is.array(input[key])){_this[key]=freezeArray(input[key])}else if(is.object(input[key])&&!isImmutable(input[key])){_this[key]=new Immutable(input[key])}else if(functionsOnPrototype&&is.function(input[key])){Immutable.prototype[key]=input[key]}else{_this[key]=input[key]}});if((this instanceof Immutable?this.constructor:void 0)===Immutable){Object.freeze(this)}}_createClass(Immutable,[{key:"toObject",value:function toObject(options){return _toObject(this,options)}},{key:"isPolynImmutable",value:function isPolynImmutable(){return true}}]);return Immutable}();/**
* Validates, and then freezes an object, and all of it's values, recursively
* @param {object} input - the object to freeze
*/var ValidatedImmutable=/*#__PURE__*/function(_Immutable){_inherits(ValidatedImmutable,_Immutable);var _super=_createSuper(ValidatedImmutable);function ValidatedImmutable(input){var _this2;_classCallCheck(this,ValidatedImmutable);var result=validator.validate(input);_this2=_super.call(this,result&&result.value||input);if((this instanceof ValidatedImmutable?this.constructor:void 0)===ValidatedImmutable){Object.freeze(_assertThisInitialized(_this2))}return _this2}_createClass(ValidatedImmutable,[{key:"patch",value:function patch(input){return new ValidatedImmutable(_patch(this)(input))}},{key:"getSchema",value:function getSchema(){return schema}}]);return ValidatedImmutable}(Immutable);return ValidatedImmutable};return{immutable:immutable}}return{immutable:new PolynImmutable().immutable,PolynImmutable:PolynImmutable,patch:_patch,makeMutableClone:_toObject,array:function array(arr){return{push:push(arr),pop:pop(arr),shift:shift(arr),unshift:unshift(arr),sort:sort(arr),reverse:reverse(arr),splice:splice(arr),slice:slice(arr),remove:remove(arr),copy:copy(arr)}}}}};root.polyn=root.polyn||{};if(!root.polyn.blueprint){throw new Error("@polyn/immutable requires @polyn/blueprint to be included before it")}var immutable=module.factories.immutable(root.polyn.blueprint);root.polyn.immutable=Object.freeze(_objectSpread({},immutable));// we don't need these anymore
delete module.factories})(window);