UNPKG

react-json-editor-ajrmnew

Version:

A stylish, editor-like, modular, react component for viewing, editing, and debugging javascript object syntax!

884 lines (846 loc) 39.1 kB
/** * @author Andrew Redican <andrew.redican.mejia@gmail.com> */ /** * Performs deep search on object tree, removes all properties with matching key, returns a new identity without the specified property * @param {Any} identity * @param {string} keyName * @param {Optional Number} maxDepth * @return {Any} identity */ function deepRemoveAll_Key(identity,keyName,maxDepth){ if(getType(keyName)!=='string') return undefined; if(keyName==='') return undefined; let clonedIdentity = deepClone(identity); var paths = locateAll_Key(clonedIdentity,keyName,maxDepth); if(paths===[]||paths===false) return clonedIdentity; paths.forEach( path => { if(path === '') path = keyName; else path += ('.' + keyName); path = path.split('.'); var ref = clonedIdentity; if(!Array.isArray(path)) delete ref[path]; for(var i = 0; i < path.length; i++){ var key = path[i]; if(key in ref){ if(i<path.length-1) ref = ref[key]; else delete ref[key]; } else break; } }); return clonedIdentity; } /** * Performs deep search on object tree, removes the first property with matching key, returns a new identity without the specified property * @param {Any} identity * @param {string} keyName * @param {Optional Number} maxDepth * @return {Any} identity */ function deepRemove_Key(identity,keyName,maxDepth){ if(getType(keyName)!=='string') return undefined; if(keyName==='') return undefined; let clonedIdentity = deepClone(identity); var path = locate_Key(clonedIdentity,keyName,maxDepth); if(path === false) return clonedIdentity; if(path === '') path = keyName; else path += ('.' + keyName); path = path.split('.'); var ref = clonedIdentity; if(!Array.isArray(path)) delete ref[path]; path.forEach( (key,i) => { if(i<path.length-1) ref = ref[key]; else delete ref[key]; }); return clonedIdentity; } /** * Performs deep search on object tree, and renames the all matching keys * @param {Any} identity * @param {string} keyName * @param {string} newKeyName * @param {Optional Number} maxDepth * @return {Any} identity */ function renameKeys(identity,keyName,newKeyName,maxDepth=null){ if(getType(keyName)!=='string') return undefined; if(getType(newKeyName)!=='string') return undefined; if(keyName==='') return undefined; if(newKeyName==='') return undefined; function _renameKeys(identity,keyName,newKeyName,maxDepth,currentDepth=0){ let keys; switch(getType(identity)){ case 'array': var Arr = []; keys = Object.keys(identity); for(var i = 0, l = keys.length; i < l; i++){ let key = keys[i], subIdentity = identity[key]; Arr[key] = _renameKeys(subIdentity,keyName,newKeyName,maxDepth,currentDepth + 1); } return Arr; case 'object': var Obj = {}; keys = Object.keys(identity); for(var i = 0, l = keys.length; i < l; i++){ let key = keys[i], subIdentity = identity[key]; if( maxDepth !== null ? currentDepth < maxDepth : true) if(key===keyName) key = newKeyName; Obj[key] = _renameKeys(subIdentity,keyName,newKeyName,maxDepth,currentDepth + 1); } return Obj; case 'string': return '' + identity; case 'number': return 0 + identity; case 'boolean': if(identity) return true; return false; case 'null': return null; case 'undefined': return undefined; } } return _renameKeys(identity,keyName,newKeyName,maxDepth,0); } /** * Performs deep search on object tree, then renames the first matching key * @param {Any} identity * @param {string} keyName * @param {string} newKeyName * @param {Optional Number} maxDepth * @return {Any} identity */ function renameKey(identity,keyName,newKeyName,maxDepth=null){ if(getType(keyName)!=='string') return undefined; if(getType(newKeyName)!=='string') return undefined; if(keyName==='') return undefined; if(newKeyName==='') return undefined; var applied=false; function _renameKey(identity,keyName,newKeyName,maxDepth,currentDepth=0){ let keys; switch(getType(identity)){ case 'array': var Arr = []; keys = Object.keys(identity); for(var i = 0, l = keys.length; i < l; i++){ let key = keys[i], subIdentity = identity[key]; Arr[key] = _renameKey(subIdentity,keyName,newKeyName,maxDepth,currentDepth + 1); } return Arr; case 'object': var Obj = {}; keys = Object.keys(identity); for(var i = 0, l = keys.length; i < l; i++){ let key = keys[i], subIdentity = identity[key]; if( maxDepth !== null ? currentDepth < maxDepth : true) if(!applied) if(key===keyName){ key = newKeyName; applied = true; } Obj[key] = _renameKey(subIdentity,keyName,newKeyName,maxDepth,currentDepth + 1); } return Obj; case 'string': return '' + identity; case 'number': return 0 + identity; case 'boolean': if(identity) return true; return false; case 'null': return null; case 'undefined': return undefined; } } return _renameKey(identity,keyName,newKeyName,maxDepth,0); } /** * Creates a non-reference clone that is an exact copy to the identity provided. * @param {Any} identity * @param {Optional Number} maxDepth * @param {Optional Number} startDepth * @return {Any} identity */ function deepClone(identity,maxDepth=null,startDepth=null){ var R = []; function _deepClone(identity,maxDepth,startDepth,currentDepth=0){ let keys; if( startDepth !== null ? currentDepth < startDepth : false){ if(isIterable(identity)){ keys = Object.keys(identity); keys.forEach( key => { _deepClone(identity[key],maxDepth,startDepth,currentDepth + 1); }); } return; } if( startDepth !== null ? currentDepth == startDepth : false){ if(startDepth==0){ R = _deepClone(identity,maxDepth,null,currentDepth); return; } if(isIterable(identity)) R.push(_deepClone(identity,maxDepth,startDepth,currentDepth + 1)); return; } switch(getType(identity)){ case 'array': var Arr = []; keys = Object.keys(identity); if( maxDepth !== null ? currentDepth < maxDepth : true) for(var i = 0, l = keys.length; i < l; i++){ const key = keys[i], subIdentity = identity[key]; Arr[key] = _deepClone(subIdentity,maxDepth,startDepth,currentDepth + 1); } return Arr; case 'object': var Obj = {}; keys = Object.keys(identity); if( maxDepth !== null ? currentDepth < maxDepth : true) for(var i = 0, l = keys.length; i < l; i++){ const key = keys[i], subIdentity = identity[key]; Obj[key] = _deepClone(subIdentity,maxDepth,startDepth,currentDepth + 1); } return Obj; case 'string': return '' + identity; case 'number': return 0 + identity; case 'boolean': if(identity) return true; return false; case 'null': return null; case 'undefined': return undefined; } } if(startDepth === null) return _deepClone(identity,maxDepth,startDepth,0); _deepClone(identity,maxDepth,startDepth,0); return R; } /** * Performs deep search on collection to find all matches to the key name, and returns a list of identities containing the matched instances. If no matches found, it returns `undefined`. * @param {Any} collection * @param {Any} keyName * @param {Optional Number} maxDepth * @return {Array || undefined} Identities */ function deepFilter_Key(collection,keyName,maxDepth=null){ if(getType(keyName)!=='string') return undefined; if(keyName==='') return undefined; var paths = locateAll_Key(collection,keyName,maxDepth); if(paths === false) return undefined; const results = paths.map(path => { if(path === false) return undefined; if(path === '') path = keyName; else path += ('.' + keyName); path = path.split('.'); var result = collection; if(!Array.isArray(path)) return result[path]; path.forEach( key => { result = result[key]; }); return result; }) return results; } /** * Performs deep search on collection to find all matches to the key name, returns the location of each match in a string array. If no matches found, it returns `false`. * @param {Any} collection * @param {Any} keyName * @param {Optional Number} maxDepth * @return {Array || false} Paths */ function locateAll_Key(collection,keyName,maxDepth=null){ if(getType(keyName)!=='string') return undefined; if(keyName==='') return undefined; var R = []; function _locateAll_Key(collection,keyName,xKey='',path='',maxDepth=null,currentDepth=0){ if(xKey===keyName) R[R.length] = path; var result = false; if(maxDepth!==null)if(currentDepth>=maxDepth) return result; if(isIterable(collection)) for(var i = 0, keys = Object.keys(collection), l = keys.length; i < l; i++ ){ const key = keys[i], subcollection = collection[key]; _locateAll_Key(subcollection,keyName,key,(path === '' ? path : path + '.') + key,maxDepth,currentDepth + 1); } } _locateAll_Key(collection,keyName,'','',maxDepth); R = R.map( path => { if(getType(path)==='boolean') return path; if(path==='') return path; path = path.split('.'); path.pop(); path = path.join('.'); return path; }); return R.length === 0 ? false : R; } /** * Performs deep search on collection to find a match to the key name, and returns the first identity containing the match. If no match found, it returns `undefined`. * @param {Any} collection * @param {Any} keyName * @param {Optional number} maxDepth * @return {Identity || undefined} identity */ function deepGet_Key(collection,keyName,maxDepth=null){ if(getType(keyName)!=='string') return undefined; if(keyName==='') return undefined; var path = locate_Key(collection,keyName,maxDepth); if(path === false) return undefined; if(path === '') path = keyName; else path += ('.' + keyName); path = path.split('.'); var result = collection; if(!Array.isArray(path)) return result[path]; path.forEach( key => { result = result[key]; }); return result; } /** * Performs deep search on collection to find a match to the key name, will return the path of the first instance matched. If no match found, it returns `false`. * @param {Any} collection * @param {Any} keyName * @param {Optional number} maxDepth * @return {String || false} Path */ function locate_Key(collection,keyName,maxDepth=null){ if(getType(keyName)!=='string') return undefined; if(keyName==='') return undefined; function _locate_Key(collection,keyName,path='',maxDepth,currentDepth=0){ if(path===keyName) return path; var result = false; if(maxDepth!==null)if(currentDepth>=maxDepth) return result; if(isIterable(collection)) for(var i = 0, keys = Object.keys(collection), l = keys.length; i < l; i++ ){ const key = keys[i], subcollection = collection[key], res = _locate_Key(subcollection,keyName,key,maxDepth,currentDepth + 1); if(res) { path = path === '' ? path : path + '.'; result = path + res; break; } } return result; } var path = _locate_Key(collection,keyName,'',maxDepth,0); if(getType(path)==='boolean') return path; if(path==='') return path; path = path.split('.'); path.pop(); path = path.join('.'); return path; } /** * Performs deep search for identity on collection to return the location's depth of the first match. If no match found, it returns `false`. * @param {Any} collection * @param {Any} identity * @param {Optional Number} maxDepth * @return {boolean} */ function matchDepth(collection,identity,maxDepth=null){ var path = locate(collection, identity, maxDepth); if(path === false) return false; if(path === '') return 0; path = path.split('.'); return path.length; } /** * Walks through the entire object tree to return the maximum number of layers it contains. * @param {Any} identity * @param {Optional Number} maxDepth */ function maxDepth(identity,maxLayer=null){ let R = 0; function _maxDepth(identity,maxLayer,currentDepth=0){ if(R < currentDepth) R = currentDepth; if(maxLayer!==null) if(currentDepth >= maxLayer) return; if(isIterable(identity)){ var keys = Object.keys(identity); keys.forEach( key => { var subIdentity = identity[key]; _maxDepth(subIdentity,maxLayer,currentDepth + 1); }); } } _maxDepth(identity,maxLayer); return R; } /** * Performs deep search for identity on collection, returns the number of matches found. * @param {Any} collection * @param {Any} identity * @param {Number} nthDepth * @param {Optional Number} maxDepth * @return {Any} Returns number of matches found. */ function countMatches(collection,identity,nthDepth=null,maxDepth=null){ var depth, nthDepth_isNull = nthDepth === null, maxDepth_isNull = maxDepth === null; if(nthDepth_isNull && maxDepth_isNull) depth = null; else if(!nthDepth_isNull && !maxDepth_isNull) if(nthDepth < maxDepth) depth = nthDepth; else depth = maxDepth; else if(nthDepth) depth = nthDepth; else depth = maxDepth; var paths = locateAll(collection,identity,depth); if(paths===false) return 0; if(nthDepth===null) return paths.length; if(getType(nthDepth)==='number'){ let count = 0; paths.forEach( path => { path = path.split('.'); if(path.length===nthDepth) count++; }); return count; } return undefined; } /** * Performs deep search for each identity on collection, to shorten the identities to those that meets the match criteria * @param {Any} collection * @param {Any} identities * @param {Any} property * @param {Optional Number} maxDepth * @return {Any} Returns a collection of the same type as the 'identities' parameter provided with only the identities that matched. */ function onlyFalsy(collection,identities,property,maxDepth=null){ if(getType(identities)==='array'){ let result = []; identities.forEach( identity => { const subCollection = deepFilter(collection,identity); if(isTruthy(subCollection)) if(foundFalsy(subCollection,property,maxDepth)) result.push(identity); }); return result; } if(getType(identities)==='object'){ let result = {}; Object.keys(identities).forEach( key => { const identity = identities[key], subCollection = deepFilter(collection,identity); if(isTruthy(subCollection)) if(foundFalsy(subCollection,property,maxDepth)) result[key] = identity; }); return result; } if(foundFalsy(collection,property,maxDepth)) return identities; } /** * Performs deep search on collection to find any match to the property and evalutates if truthy * @param {Any} collection * @param {Property} identity * @param {Optional Number} maxDepth * @return {boolean} If match confirmed and truthy will return true, otherwise false */ function foundFalsy(collection,identity,maxDepth=null){ identity = singleProperty(identity); if(isFalsy(identity)) return undefined; function _foundFalsy(collection,identity,maxDepth,currentDepth=0){ if(containsKeys(collection,[identity])) return isFalsy(collection[identity]); if(maxDepth!==null) if(currentDepth >= maxDepth) return false; if(isIterable(collection)) for(var i = 0, keys = Object.keys(collection), l = keys.length; i < l; i++ ){ const key = keys[i], subcollection = collection[key], res = _foundFalsy(subcollection,identity,maxDepth,currentDepth + 1); if(res) return true; } return false; } return _foundFalsy(collection,identity,maxDepth); } /** * Performs deep search for each identity on collection, to shorten the identities to those that meets the match criteria * @param {Any} collection * @param {Any} identities * @param {Any} property * @param {Optional Number} maxDepth * @return {Any} Returns a collection of the same type as the 'identities' parameter provided with only the identities that matched. */ function onlyTruthy(collection,identities,property,maxDepth=null){ if(getType(identities)==='array'){ let result = []; identities.forEach( identity => { const subCollection = deepFilter(collection,identity); if(isTruthy(subCollection)) if(foundTruthy(subCollection,property,maxDepth)) result.push(identity); }); return result; } if(getType(identities)==='object'){ let result = {}; Object.keys(identities).forEach( key => { const identity = identities[key], subCollection = deepFilter(collection,identity); if(isTruthy(subCollection)) if(foundTruthy(subCollection,property,maxDepth)) result[key] = identity; }); return result; } if(foundTruthy(collection,property,maxDepth)) return identities; } /** * Performs deep search on collection to find any match to the property and evalutates if truthy * @param {Any} collection * @param {Property} identity * @param {Optional Number} maxDepth * @return {boolean} If match confirmed and truthy will return true, otherwise false */ function foundTruthy(collection,identity,maxDepth=null){ identity = singleProperty(identity); if(isFalsy(identity)) return undefined; function _foundTruthy(collection,identity,maxDepth,currentDepth=0){ if(containsKeys(collection,[identity])) return isTruthy(collection[identity]); if(maxDepth!==null) if(currentDepth >= maxDepth) return false; if(isIterable(collection)) for(var i = 0, keys = Object.keys(collection), l = keys.length; i < l; i++ ){ const key = keys[i], subcollection = collection[key], res = _foundTruthy(subcollection,identity,maxDepth,currentDepth + 1); if(res) return true; } return false; } return _foundTruthy(collection,identity,maxDepth,0); } /** * Validates if identity is equal to a property definition or contains a single property key. * @param {Property} identity * @return {String || boolean} If criteria matched will return property name as string, otherwise false */ function singleProperty(identity){ const propCount = length(identity); if(propCount > 1) return false; if(propCount===1) return Object.keys(identity)[0]; if(propCount===0) if(['string','number'].indexOf(getType(identity))>-1) return identity; return false; } /** * Determines if identity is non-falsy * @param {Any} identity * @return {boolean} Returns true if criteria matched, otherwise false. */ function isTruthy(identity){ return !isFalsy(identity); } /** * Determines if identity is falsy * @param {Any} identity * @return {boolean} Returns true if criteria matched, otherwise false. */ function isFalsy(identity){ if(falser(identity)===false) return true; return false; } /** * Converts false-like values into actual boolean value of false * @param {Any} identity * @return {Any || boolean} Returns false is value is falsy, otherwise returns original value. */ function falser(identity){ if(isIterable(identity)) return identity; if(['null','undefined'].indexOf(getType(identity))>-1) return false; if(['',0,false].indexOf(identity)>-1) return false; return identity; } /** * Check the length of the top-most depth of the identity * @param {Any} identity * @return {integer} Greater than or equal to 0. */ function length(identity){ if(['array','object'].indexOf(getType(identity)) === -1) return 0; return Object.keys(identity).length; } /** * Performs deep search for each identity on collection, to shorten the identities to those that does meets the match criteria * @param {Any} collection * @param {Any} identities * @param {Optional Number} maxDepth * @return {Any} Returns a collection of the same type as the 'identities' parameter provided with only the identities that were not matched. */ function onlyMissing(collection,identities,maxDepth=null){ if(getType(identities)==='array'){ let result = []; identities.forEach( identity => { if(!exists(collection,identity,maxDepth)) result.push(identity); }); return result; } if(getType(identities)==='object'){ let result = {}; Object.keys(identities).forEach( key => { let identity = identities[key]; if(!exists(collection,identity,maxDepth)) result[key] = identity; }); return result; } if(!exists(collection,identities,maxDepth)) return identities; } /** * Performs deep search for each identity on collection, to shorten the identities to those that meets the match criteria * @param {Any} collection * @param {Any} identities * @param {Optional Number} maxDepth * @return {Any} Returns a collection of the same type as the 'identities' parameter provided with only the identities that matched. */ function onlyExisting(collection,identities,maxDepth=null){ if(getType(identities)==='array'){ let result = []; identities.forEach( identity => { if(exists(collection,identity,maxDepth)) result.push(identity); }); return result; } if(getType(identities)==='object'){ let result = {}; Object.keys(identities).forEach( key => { let identity = identities[key]; if(exists(collection,identity,maxDepth)) result[key] = identity; }); return result; } if(exists(collection,identities,maxDepth)) return identities; } /** * Performs deep search on collection to find any match to the identity * @param {Any} collection * @param {Any} identity * @param {Optional Number} maxDepth * @return {boolean} If a match is confirmed will return true, otherwise false */ function exists(collection, identity, maxDepth=null, currentDepth=0){ if(identical(collection,identity)) return true; if(isIterable(identity)) if(sameType(collection,identity)) if(containsKeys(collection,Object.keys(identity))){ const trimmed = trim(collection,Object.keys(identity)); if(identical(trimmed,identity)) return true; } if(maxDepth === null ? true: (currentDepth < maxDepth)) if(isIterable(collection)) for(var i = 0, keys = Object.keys(collection), l = keys.length; i < l; i++ ){ const key = keys[i], subcollection = collection[key], res = exists(subcollection,identity,maxDepth,currentDepth + 1); if(res) return true; } return false; } /** * Performs deep search on collection to find all matches to the identity, will return a list of identities containing the match. If no matches found, it returns `undefined`. * @param {Any} collection * @param {Any} identity * @param {Optional Number} maxDepth * @return {Array || undefined} identities */ function deepFilter(collection, identity, maxDepth=null){ var paths = locateAll(collection, identity, maxDepth); if(paths === false) return undefined; const results = paths.map(path => { if(path === '') return collection; path = path.split('.'); if(['array','object'].indexOf(getType(identity)) === - 1) path.splice(-1,1); var result = collection; if(!Array.isArray(path)) return result[path]; path.forEach( key => { result = result[key]; }); return result; }) return results; } /** * Performs deep search on collection to find all matches to the identity, returns a string array containing the location of all matches. If no matches found, it returns `false`. * @param {Any} collection * @param {Any} identity * @param {Optional Number} maxDepth * @return {Array || false} Paths */ function locateAll(collection, identity, maxDepth=null){ var R = []; function _locateAll(collection, identity, path = '',maxDepth,currentDepth){ if(isIterable(identity)) if(sameType(collection,identity)) if(containsKeys(collection,Object.keys(identity))){ const trimmed = trim(collection,Object.keys(identity)); if(identical(trimmed,identity)) R[R.length] = path; } if(identical(collection,identity)) R[R.length] = path; var result = false; if(maxDepth!==null)if(currentDepth>=maxDepth) return result; if(isIterable(collection)) for(var i = 0, keys = Object.keys(collection), l = keys.length; i < l; i++ ){ const key = keys[i], subcollection = collection[key]; _locateAll(subcollection,identity,(path === '' ? path : path + '.') + key,maxDepth,currentDepth + 1); } } _locateAll(collection, identity, '', maxDepth, 0); return R.length === 0 ? false : R; } /** * Performs deep search on collection to find a match to the identity, will return the identity containing of the first instance matched. If no matches found, it returns `undefined`. * @param {Any} collection * @param {Any} identity * @param {Optional Number} maxDepth * @return {identity || undefined} identity */ function deepGet(collection, identity, maxDepth=null){ var path = locate(collection, identity, maxDepth); if(path === false) return undefined; if(path === '') return collection; path = path.split('.'); if(['array','object'].indexOf(getType(identity)) === - 1) path.splice(-1,1); var result = collection; if(!Array.isArray(path)) return result[path]; path.forEach( key => { result = result[key]; }); return result; } /** * Performs deep search on collection to find a match to the identity, will return the path of the first instance matched as string. If no matches found, returns `false`. * @param {Any} collection * @param {Any} identity * @param {Optional number} maxDepth * @return {string || false} path */ function locate(collection, identity, maxDepth=null){ function _locate(collection, identity, path = '', maxDepth,currentDepth){ if(isIterable(identity)) if(sameType(collection,identity)) if(containsKeys(collection,Object.keys(identity))){ const trimmed = trim(collection,Object.keys(identity)); if(identical(trimmed,identity)) return path; } if(identical(collection,identity)) return path; var result = false; if(maxDepth!==null)if(currentDepth>=maxDepth) return result; if(isIterable(collection)) for(var i = 0, keys = Object.keys(collection), l = keys.length; i < l; i++ ){ const key = keys[i], subcollection = collection[key], res = _locate(subcollection,identity,key,maxDepth,currentDepth + 1); if(res) { path = path === '' ? path : path + '.'; result = path + res; break; } } return result; } return _locate(collection, identity,'', maxDepth,0); } /** * Trims an identity to only contain the specified properties. * @param {Any} identity * @param {Any} keyList * @return {Object or Array} Returns , otherwise false */ function trim(identity,keyList){ const identityType = getType(identity); if(['array','object'].indexOf(identityType) === -1) return undefined; const keyCount = keyList.length; if(keyCount === 0) return undefined; var newIdentity; switch(identityType){ case 'object' : newIdentity = {}; keyList.forEach(key => { if(key in identity) newIdentity[key] = identity[key]; }); break; case 'array' : newIdentity = []; keyList.forEach(key => { if(key in identity) newIdentity.push(identity[key]); }); break; } return newIdentity; } /** * Check if identity contains all of the specified keys * @param {Any} identity * @param {Array} keyList * @return {boolean} true || false */ function containsKeys(identity,keyList){ const keyCount = keyList.length; if(keyCount === 0 || !isIterable(identity)) return false; const identitykeys = Object.keys(identity); var result = true; for(var i = 0; i < keyCount; i++){ const key = '' + keyList[i]; if(identitykeys.indexOf(key) === -1){ result = false; break; } } return result; } /** * Check if identity has one or more keys to iterate * @param {Any} identity * @return {boolean} true || false */ function isIterable(identity){ if(['array','object'].indexOf(getType(identity)) === -1) return false; if(Object.keys(identity).length === 0) return false; return true; } /** * Compares two identities, will return either true if identical, otherwise false. * @param {Any} identityA * @param {Any} identityB * @return {boolean} true || false */ function identical(identityA,identityB){ const structureMatch = sameStructure(identityA,identityB); if(structureMatch === false) return structureMatch; if(['array','object'].indexOf(structureMatch) === -1) return identityA === identityB; const Keys = Object.keys(identityA), KeyCount = Keys.length; var childMatch = true; for(var i = 0; i < KeyCount; i++) { const Key = Keys[i], identicalMatch = identical(identityA[Key],identityB[Key]); if(identicalMatch === false){ childMatch = identicalMatch; break; }; } return childMatch; } /** * Compares data structure of two identities, will return either the dataType or true/false. * @param {Any} identityA * @param {Any} identityB * @return {String || False} DataType as string for positive match, otherwise false */ function sameStructure(identityA,identityB){ const typeMatch = sameType(identityA,identityB); if(typeMatch === false) return false; if(['array','object'].indexOf(typeMatch) > -1){ const AKeys = Object.keys(identityA), BKeys = Object.keys(identityB), AKeyCount = AKeys.length, BKeyCount = BKeys.length; if(!(AKeyCount === BKeyCount)) return false; if(AKeyCount === 0) return true; for (var i = 0; i < AKeyCount; i++) { if(AKeys[i] !== BKeys[i]) return false; } } return typeMatch; } /** * Compares data type of two identities, will dataType if true. * @param {Any} identityA * @param {Any} identityB * @return {boolean} true || false */ function sameType(identityA,identityB){ const typeA = getType(identityA); return typeA === getType(identityB) ? typeA : false; } /** * Gets data type; makes distintion between object, array, and null. * @param {Any} identity * @return {String} dataType */ function getType(identity) { if(identity === null) return 'null'; const it = typeof identity; if(it === 'object') if(Array.isArray(identity)) return 'array'; return it; } var mitsuketa = { getType : function(identity) { return getType(identity); }, sameType : function(identityA,identityB) { return sameType(identityA,identityB); }, sameStructure : function(identityA,identityB) { return sameStructure(identityA,identityB); }, identical : function(identityA,identityB) { return identical(identityA,identityB); }, isIterable : function(identity) { return isIterable(identity); }, containsKeys : function(identity,keyList) { return containsKeys(identity,keyList); }, trim : function(identity,keyList) { return trim(identity,keyList); }, locate : function(collection,identity,maxDepth) { return locate(collection,identity,maxDepth); }, deepGet : function(collection,identity,maxDepth) { return deepGet(collection,identity,maxDepth); }, locateAll : function(collection,identity,maxDepth) { return locateAll(collection,identity,maxDepth); }, deepFilter : function(collection,identity,maxDepth) { return deepFilter(collection,identity,maxDepth); }, exists : function(collection,identity,maxDepth) { return exists(collection,identity,maxDepth); }, onlyExisting : function(collection,identities,maxDepth) { return onlyExisting(collection,identities,maxDepth); }, onlyMissing : function(collection,identities,maxDepth) { return onlyMissing(collection,identities,maxDepth); }, length : function(identity) { return length(identity); }, isFalsy : function(identity) { return isFalsy(identity); }, isTruthy : function(identity) { return isTruthy(identity); }, foundTruthy : function(collection,identity,maxDepth) { return foundTruthy(collection,identity,maxDepth); }, onlyTruthy : function(collection,identities,property,maxDepth) { return onlyTruthy(collection,identities,property,maxDepth); }, foundFalsy : function(collection,identity,maxDepth) { return foundFalsy(collection,identity,maxDepth); }, onlyFalsy : function(collection,identities,property,maxDepth) { return onlyFalsy(collection,identities,property,maxDepth); }, countMatches : function(collection,identity,nthDepth,maxDepth) { return countMatches(collection,identity,nthDepth,maxDepth); }, matchDepth : function(collection,identity,maxDepth) { return matchDepth(collection,identity,maxDepth); }, maxDepth : function(identity,maxLayer) { return maxDepth(identity,maxLayer); }, locate_Key : function(collection,keyName,maxDepth) { return locate_Key(collection,keyName,maxDepth); }, deepGet_Key : function(collection,keyName,maxDepth) { return deepGet_Key(collection,keyName,maxDepth); }, locateAll_Key : function(collection,keyName,maxDepth) { return locateAll_Key(collection,keyName,maxDepth); }, deepFilter_Key : function(collection,keyName,maxDepth) { return deepFilter_Key(collection,keyName,maxDepth); }, deepClone : function(identity,maxDepth,startDepth) { return deepClone(identity,maxDepth,startDepth); }, renameKey : function(identity,keyName,newKeyName,maxDepth) { return renameKey(identity,keyName,newKeyName,maxDepth); }, renameKeys : function(identity,keyName,newKeyName,maxDepth) { return renameKeys(identity,keyName,newKeyName,maxDepth); }, deepRemove_Key : function(identity,keyName,maxDepth) { return deepRemove_Key(identity,keyName,maxDepth); }, deepRemoveAll_Key : function(identity,keyName,maxDepth) { return deepRemoveAll_Key(identity,keyName,maxDepth); } } module.exports = exports = mitsuketa;