UNPKG

objecture

Version:

❂ Objecture ⏣ Object Watcher, Property Manager ⊚ Capture property changes for object, array mutator methods. ⊚ Schematize and validate object, array properties. ⊚ Browser, NodeJS compatible. ⁘ Uses Core-Plex - Event Listener Manage

351 lines (330 loc) 12 kB
const Primitives = { 'string': String, 'number': Number, 'boolean': Boolean, 'bigint': BigInt, 'undefined': undefined, 'null': null, }; const PrimitiveKeys = Object.keys(Primitives); const PrimitiveValues = Object.values(Primitives); const Objects = { 'object': Object, 'array': Array, }; const ObjectKeys = Object.keys(Objects); const ObjectValues = Object.values(Objects); const Types = Object.assign({}, Primitives, Objects); const TypeKeys = Object.keys(Types); const TypeValues = Object.values(Types); const TypeMethods = [ Primitives.String, Primitives.Number, Primitives.Boolean, Objects.Object, Objects.Array ]; var index = /*#__PURE__*/Object.freeze({ __proto__: null, ObjectKeys: ObjectKeys, ObjectValues: ObjectValues, Objects: Objects, PrimitiveKeys: PrimitiveKeys, PrimitiveValues: PrimitiveValues, Primitives: Primitives, TypeKeys: TypeKeys, TypeMethods: TypeMethods, TypeValues: TypeValues, Types: Types }); var typeOf = ($data) => Object .prototype .toString .call($data).slice(8, -1).toLowerCase(); function typedObjectLiteral($value) { let _typedObjectLiteral; const typeOfValue = typeOf($value); if(typeOfValue === 'string') { const value = $value.toLowerCase(); if(value === 'object') { _typedObjectLiteral = {}; } else if(value === 'array') { _typedObjectLiteral = []; } } else { if(typeOfValue === 'object') { _typedObjectLiteral = {}; } else if(typeOfValue === 'array') { _typedObjectLiteral = []; } } return _typedObjectLiteral } var regularExpressions = { quotationEscape: /\.(?=(?:[^"]*"[^"]*")*[^"]*$)/, }; function get($path, $source) { const subpaths = $path.split(new RegExp(regularExpressions.quotationEscape)); const key = subpaths.pop(); let subtarget = $source; for(const $subpath of subpaths) { subtarget = subtarget[$subpath]; } return subtarget[key] } function set($path, $source) { const subpaths = $path.split(new RegExp(regularExpressions.quotationEscape)); const key = subpaths.pop(); const target = (key && !isNaN(key)) ? [] : {}; let subtarget = target; let subpathIndex = 0; while(subpathIndex < subpaths.length - 2) { const $subpath = keypaths[subpathIndex]; if(isNaN($subpath)) { subtarget[$subpath] = {}; } else { subtarget[$subpath] = {}; } subtarget = subtarget[$subpath]; subpathIndex++; } subtarget[key] = $source; return target } const ValidPropertyTypes = ['string', 'function']; function expandTree($source, $property) { const typeOfProperty = typeOf($property); const typeOfSource = typeOf($source); if( !ValidPropertyTypes.includes(typeOfProperty) || !ObjectKeys.includes(typeOfSource) ) { return $source } let target = typedObjectLiteral($source); for(const [$sourceKey, $sourceValue] of Object.entries($source)) { const sourceValue = ( ObjectKeys.includes(typeOf($sourceValue)) ) ? expandTree($sourceValue, $property) : $sourceValue; if(typeOfProperty === ValidPropertyTypes[0]) { target[$sourceKey] = set($property, sourceValue); } else if(typeOfProperty === ValidPropertyTypes[1]) { target[$sourceKey] = $property(sourceValue); } } return target } function impandTree($source, $property) { const typeOfProperty = typeOf($property); const typeOfSource = typeOf($source); if( !['string', 'function'].includes(typeOfProperty) || !['array', 'object'].includes(typeOfSource) ) { return $source } let target = typedObjectLiteral($source); for(const [$sourceKey, $sourceValue] of Object.entries($source)) { if(typeOfProperty === 'string') { target[$sourceKey] = get($property, $sourceValue); } else if(typeOfProperty === 'function') { target[$sourceKey] = $property($sourceValue); } if(target[$sourceKey] && typeof target[$sourceKey] === 'object') { target[$sourceKey] = impandTree(target[$sourceKey], $property); } } return target } var isArrayLike = ($source) => { let isArrayLike; const typeOfSource = typeOf($source); if(typeOfSource === 'array') { isArrayLike = true; } else if( typeOfSource === 'object' && Number.isInteger($source.length) && $source.length >= 0 ) { iterateSourceKeys: for(const $sourceKey of Object.keys( Object.getOwnPropertyDescriptors($source) )) { if($sourceKey === 'length') { continue iterateSourceKeys } isArrayLike = !isNaN($sourceKey); if(!isArrayLike) { break iterateSourceKeys } } } else { isArrayLike = false; } return isArrayLike }; const defaultAccessor = ($target, $property) => { if($property === undefined) { return $target } else { return $target[$property] } }; var Accessors = { default: defaultAccessor}; const Options$2 = { depth: 0, maxDepth: 10, accessors: [Accessors.default], ancestors: [], }; function compandTree($object, $options) { const _compandTree = []; const options = Object.assign({}, Options$2, $options, { ancestors: [].concat($options.ancestors) }); options.depth++; if(options.depth > options.maxDepth) { return _compandTree } iterateAccessors: for(const $accessor of options.accessors) { const accessor = $accessor.bind($object); const object = accessor($object); if(!object) { continue iterateAccessors } if(!options.ancestors.includes(object)) { options.ancestors.unshift(object); } for(const [$key, $value] of Object.entries(object)) { if(!options.values) { _compandTree.push($key); } else if(options.values) { _compandTree.push([$key, $value]); } if( typeof $value === 'object' && $value !== null && !Object.is($value, object) && !options.ancestors.includes($value) ) { const subtargets = compandTree($value, options); if(!options.values) { for(const $subtarget of subtargets) { const path = [$key, $subtarget].join('.'); _compandTree.push(path); } } else if(options.values) { for(const [$subtargetKey, $subtarget] of subtargets) { const path = [$key, $subtargetKey].join('.'); _compandTree.push([path, $subtarget]); } } } } } return _compandTree } function assign($target, ...$sources) { if(!$target) { return $target} iterateSources: for(const $source of $sources) { if(!$source) continue iterateSources for(const [ $sourcePropertyKey, $sourcePropertyValue ] of Object.entries($source)) { const typeOfTargetPropertyValue = typeOf($target[$sourcePropertyKey]); const typeOfSourcePropertyValue = typeOf($sourcePropertyValue); if( typeOfTargetPropertyValue === 'object' && typeOfSourcePropertyValue === 'object' ) { $target[$sourcePropertyKey] = assign($target[$sourcePropertyKey], $sourcePropertyValue); } else { $target[$sourcePropertyKey] = $sourcePropertyValue; } } } return $target } function assignConcat($target, ...$sources) { if(!$target) { return $target} iterateSources: for(const $source of $sources) { if(!$source) continue iterateSources for(const [ $sourcePropertyKey, $sourcePropertyValue ] of Object.entries($source)) { const typeOfTargetPropertyValue = typeOf($target[$sourcePropertyKey]); const typeOfSourcePropertyValue = typeOf($sourcePropertyValue); if( typeOfTargetPropertyValue === 'object' && typeOfSourcePropertyValue === 'object' ) { $target[$sourcePropertyKey] = assignConcat($target[$sourcePropertyKey], $sourcePropertyValue); } else if( typeOfTargetPropertyValue === 'array' && typeOfSourcePropertyValue === 'array' ) { $target[$sourcePropertyKey] = $target[$sourcePropertyKey].concat($sourcePropertyValue); } else { $target[$sourcePropertyKey] = $sourcePropertyValue; } } } return $target } var Options$1 = { ancestors: [], delimiter: '.', depth: 0, frozen: false, maxDepth: 10, nonenumerable: true, path: false, sealed: false, type: false, }; function getOwnPropertyDescriptor($properties, $propertyKey, $options) { const options = Object.assign({}, Options$1, $options, { ancestors: Object.assign([], $options.ancestors) }); const propertyDescriptor = Object.getOwnPropertyDescriptor($properties, $propertyKey); if(!options.nonenumerable && !propertyDescriptor.enumerable) { return } if(!options.ancestors.includes($properties)) { options.ancestors.unshift($properties); } if(options.ancestors.includes(propertyDescriptor.value)) { return } if(options.path) { options.path = (typeOf(options.path) === 'string') ? [options.path, $propertyKey].join(options.delimiter) : $propertyKey; propertyDescriptor.path = options.path; } if(options.type) { propertyDescriptor.type = typeOf(propertyDescriptor.value); } if(options.frozen) { propertyDescriptor.frozen = Object.isFrozen(propertyDescriptor.value); } if(options.sealed) { propertyDescriptor.sealed = Object.isSealed(propertyDescriptor.value); } if(['array', 'object'].includes(typeOf(propertyDescriptor.value))) { propertyDescriptor.value = getOwnPropertyDescriptors(propertyDescriptor.value, options); } return propertyDescriptor } function getOwnPropertyDescriptors($properties, $options) { const propertyDescriptors = {}; const options = Object.assign({}, Options$1, $options); if(options.depth >= options.maxDepth) { return propertyDescriptors } else { options.depth++; } for(const [$propertyKey, $propertyDescriptor] of Object.entries(Object.getOwnPropertyDescriptors($properties))) { const propertyDescriptor = getOwnPropertyDescriptor($properties, $propertyKey, options); if(propertyDescriptor !== undefined) { propertyDescriptors[$propertyKey] = propertyDescriptor; } } return propertyDescriptors } var Options = { typeCoercion: false, }; function defineProperty($target, $propertyKey, $propertyDescriptor, $options) { const propertyDescriptor = Object.assign({}, $propertyDescriptor); const options = Object.assign({}, Options, $options); const typeOfPropertyValue = typeOf(propertyDescriptor.value); if(['array', 'object'].includes(typeOfPropertyValue)) { const propertyValue = isArrayLike(Object.defineProperties( typedObjectLiteral(typeOfPropertyValue), propertyDescriptor.value )) ? [] : {}; propertyDescriptor.value = defineProperties(propertyValue, propertyDescriptor.value, options); } else if( options.typeCoercion && Object.getOwnPropertyDescriptor(propertyDescriptor, 'type') !== undefined && !['undefined', 'null'].includes(typeOfPropertyValue) ) { propertyDescriptor.value = Primitives[propertyDescriptor.type](propertyDescriptor.value); } Object.defineProperty($target, $propertyKey, propertyDescriptor); if($propertyDescriptor.sealed) { Object.seal($target[$propertyKey]); } if($propertyDescriptor.frozen) { Object.freeze($target[$propertyKey]); } return $target } function defineProperties($target, $propertyDescriptors, $options) { const options = Object.assign({}, Options, $options); for(const [ $propertyKey, $propertyDescriptor ] of Object.entries($propertyDescriptors)) { defineProperty($target, $propertyKey, $propertyDescriptor, options); } return $target } function freeze($target) { for(const [$propertyKey, $propertyValue] of Object.entries($target)) { if(Object.is($propertyValue, $target)) { continue } if($propertyValue && typeof $propertyValue === 'object') { freeze($propertyValue); } } return Object.freeze($target) } export { assign, assignConcat, compandTree, defineProperties, defineProperty, expandTree, freeze, getOwnPropertyDescriptor, getOwnPropertyDescriptors, impandTree, isArrayLike, regularExpressions, typeOf, typedObjectLiteral, index as variables }; //# sourceMappingURL=recourse.js.map