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
JavaScript
/**
* @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;