lodash-walk-object
Version:
Walk all properties deep in object with lodash help
386 lines (382 loc) • 14.4 kB
JavaScript
import { _ } from 'tnp-core/websql';
import { CLASS } from 'typescript-class-helpers/websql';
function findChildren(ver, lp, walkGetters) {
const obj = ver.v;
if (_.isArray(obj)) {
return obj.map((v, i) => {
return { v, p: `${lp}[${i}]`, parent: ver, isGetter: false };
});
}
else if (_.isObject(obj)) {
const allKeys = !walkGetters ? [] : Object.getOwnPropertyNames(obj);
const children = [];
for (const key in obj) {
if (_.isObject(obj) &&
_.isFunction(obj.hasOwnProperty) &&
obj.hasOwnProperty(key)) {
_.pull(allKeys, key);
children.push({
v: obj[key],
p: `${lp === '' ? '' : `${lp}.`}${key}`,
parent: ver,
isGetter: false,
});
}
}
if (walkGetters) {
for (let index = 0; index < allKeys.length; index++) {
if (_.isObject(obj)) {
const key = allKeys[index];
children.push({
v: obj[key],
p: `${lp === '' ? '' : `${lp}.`}${key}`,
parent: ver,
isGetter: true,
});
}
}
}
return children;
}
return [];
}
class Helpers {
static get Walk() {
const self = this;
return {
Object(json, iterator, optionsOrWalkGettersValue) {
if (_.isUndefined(optionsOrWalkGettersValue)) {
optionsOrWalkGettersValue = {};
}
optionsOrWalkGettersValue.hasIterator =
_.isFunction(iterator);
if (_.isUndefined(optionsOrWalkGettersValue.breadthWalk)) {
optionsOrWalkGettersValue.breadthWalk = false;
}
let { circural } = self._walk(json, json, iterator, void 0, optionsOrWalkGettersValue);
return { circs: circural };
},
ObjectBy(property, inContext, iterator, options) {
if (_.isFunction(iterator)) {
iterator(inContext, '', self._changeValue(inContext, property, true)); // TODO Add optoins
}
// @ts-ignore
const json = inContext[property];
return self.Walk.Object(json, iterator, options);
},
};
}
static _changeValue(json, lodahPath, simpleChange = false, options) {
var { contextPath, property } = this._prepareParams(lodahPath);
var context = _.get(json, contextPath);
return (newValue) => {
if (contextPath === '') {
simpleChange = true;
}
if (simpleChange) {
// @ts-ignore
json[property] = newValue;
}
else {
// console.log(`CONTEXT VALUE CHANGE! "${contextPath}" + "${property}" `, newValue)
// console.log('context', context)
if (context) {
context[property] = newValue;
}
}
if (options) {
options._valueChanged = true;
}
};
}
static _prepareParams(lodashPath) {
// console.log('contextPath before', lodashPath)
const contextPath = this._Helpers.Path.getContextPath(lodashPath);
// console.log('contextPath after', contextPath)
let property = this._Helpers.Path.getPropertyPath(lodashPath, contextPath);
// console.log('property after process', property)
if (_.isString(property) &&
property.trim() !== '' &&
!_.isNaN(Number(property))) {
property = Number(property);
}
return {
contextPath,
property,
};
}
static get _Helpers() {
return {
get Path() {
return {
// @ts-ignore
getPropertyPath(lodahPath, contetPath) {
return lodahPath
.replace(contetPath, '')
.replace(/^\./, '')
.replace(/\[/, '')
.replace(/\]/, '');
},
getContextPath(p) {
let res;
if (p.endsWith(']')) {
res = p.replace(/\[(\"|\')?[0-9]+(\"|\')?\]$/, '');
}
else {
res = p.replace(/\.([a-zA-Z0-9]|\$|\_|\@|\-|\/|\:)+$/, '');
}
return res === p ? '' : res;
},
};
},
};
}
static _shoudlReturn(include = [], exclude = [], lodashPath) {
let res = false;
if (lodashPath.replace(/^\[(\'|\")?[0-9]*(\'|\")?\]/, '').trim() !== '') {
lodashPath = lodashPath.replace(/^\[(\'|\")?[0-9]*(\'|\")?\]\./, '');
res =
(_.isArray(include) &&
include.length > 0 &&
!include.find(p => lodashPath.startsWith(p))) ||
(_.isArray(exclude) &&
exclude.length > 0 &&
!!exclude.find(p => lodashPath.startsWith(p)));
}
return res;
}
// @ts-ignore
static prepareOptions(options, obj, lodashPath) {
if (options._exit) {
return;
}
if (_.isUndefined(options.walkGetters)) {
options.walkGetters = true;
}
if (_.isUndefined(options.checkCircural)) {
options.checkCircural = false;
}
if (_.isUndefined(options.isGetter)) {
// @ts-ignore
options.isGetter = false;
}
if (_.isUndefined(options._valueChanged)) {
options._valueChanged = false;
}
if (_.isUndefined(options._exit)) {
// @ts-ignore
options._exit = false;
}
if (_.isUndefined(options.exit)) {
options.exit = () => {
options._exit = true;
};
}
if (_.isUndefined(options._skip)) {
// @ts-ignore
options._skip = false;
}
if (_.isUndefined(options.skipObject)) {
options.skipObject = () => {
options._skip = true;
};
}
if (options.checkCircural) {
if (_.isUndefined(options.db)) {
options.db = {};
}
if (_.isUndefined(options.stack)) {
options.stack = [];
}
if (_.isUndefined(options.circural)) {
options.circural = [];
}
}
const { db, stack } = options;
options.isCircural = false;
if (options.checkCircural && _.isObject(obj)) {
let indexValue = CLASS.OBJECT(obj).indexValue;
if (CLASS.OBJECT(obj).isClassObject && !_.isUndefined(indexValue)) {
let className = CLASS.getNameFromObject(obj);
let p = `${className}.id_${indexValue}`;
const inDB = _.get(db, p);
if (inDB && CLASS.OBJECT(inDB.target).isEqual(obj)) {
const circ = {
pathToObj: lodashPath,
circuralTargetPath: inDB.path,
};
// @ts-ignore
options.circural.push(circ);
options.isCircural = true;
}
else {
_.set(db, p, {
path: lodashPath,
target: obj,
});
}
}
else {
// @ts-ignore
const inStack = stack.find((c) => c.target == obj);
if (!_.isUndefined(inStack)) {
const circ = {
pathToObj: lodashPath,
circuralTargetPath: inStack.path,
};
// @ts-ignore
options.circural.push(circ);
options.isCircural = true;
}
else {
// @ts-ignore
stack.push({
path: lodashPath,
target: obj,
});
}
}
}
return options;
}
static _walk(json, objOrWhatever, iterator, lodashPath = '', options, depthLevel = 0) {
if (!options) {
options = {};
}
// @ts-ignore
if (!options.breadthWalk) {
// @ts-ignore
options = this.prepareOptions(options, objOrWhatever, lodashPath);
// @ts-ignore
if (this._shoudlReturn(options.include, options.exclude, lodashPath)) {
return;
}
// @ts-ignore
if (options.hasIterator && lodashPath !== '') {
iterator(objOrWhatever, lodashPath, this._changeValue(json, lodashPath, false, options), options);
}
// @ts-ignore
if (options._valueChanged) {
objOrWhatever = _.get(json, lodashPath);
}
options._valueChanged = false;
if (options.isCircural) {
options._skip = true;
}
if (options._skip) {
// @ts-ignore
options._skip = false;
return;
}
}
if (options.breadthWalk) {
let queue = [{ v: json, p: lodashPath, parent: void 0 }];
// const pathesToSkip = {};
while (queue.length > 0) {
const ver = queue.shift();
// console.log(`pathes to skip`, pathesToSkip);
// if (!_.isUndefined(Object.keys(pathesToSkip).find(key => ver.p.startsWith(pathesToSkip[key])))) {
// console.log(`skip: ${ver.p}`)
// continue;
// }
// @ts-ignore
if (this._shoudlReturn(options.include, options.exclude, ver.p)) {
// pathesToSkip[ver.p] = true;
// console.log(`skip2: ${ver.p}`)
continue;
}
// console.log(`not skip value ${ver.p}`)
// @ts-ignore
let { v, p } = ver;
// @ts-ignore
options = this.prepareOptions(options, v, p);
if (options._exit) {
console.log('EXIT');
return options;
}
if (options.hasIterator && p !== '') {
iterator(v, p, this._changeValue(json, p, false, options), options);
}
// @ts-ignore
if (options._valueChanged) {
ver.v = _.get(json, p);
}
options._valueChanged = false;
if (options.isCircural) {
// pathesToSkip[ver.p] = true;
continue;
}
if (options._skip) {
// @ts-ignore
options._skip = false;
// pathesToSkip[ver.p] = true;
continue;
}
// console.log(`LOOK FOR CHILDREN OF ${ver.p}`)
if (_.isArray(v)) {
// @ts-ignore
queue = queue.concat(findChildren(ver, p, options.walkGetters));
}
else if (_.isObject(v)) {
// @ts-ignore
queue = queue.concat(findChildren(ver, p, options.walkGetters));
}
}
}
else {
// @ts-ignore
const { walkGetters } = options;
if (Array.isArray(objOrWhatever)) {
objOrWhatever.forEach((o, i) => {
// @ts-ignore
this._walk(json, objOrWhatever[i], iterator, `${lodashPath}[${i}]`, options, depthLevel + 1);
});
}
else if (_.isObject(objOrWhatever)) {
const allKeys = !walkGetters
? []
: Object.getOwnPropertyNames(objOrWhatever);
// @ts-ignore
for (const key in objOrWhatever) {
// console.log('KEY', key)
if (_.isObject(objOrWhatever) && objOrWhatever.hasOwnProperty(key)) {
_.pull(allKeys, key);
let newPropKey = key;
options.isGetter = false;
if (newPropKey.includes('.')) {
newPropKey = `['${newPropKey}']`;
}
// @ts-ignore
this._walk(json, objOrWhatever[newPropKey], iterator, `${lodashPath === '' ? '' : `${lodashPath}.`}${newPropKey}`, options, depthLevel + 1);
}
}
if (walkGetters) {
for (let index = 0; index < allKeys.length; index++) {
if (_.isObject(objOrWhatever)) {
const key = allKeys[index];
// @ts-ignore
options.isGetter = true;
// @ts-ignore
this._walk(json, objOrWhatever[key], iterator, `${lodashPath === '' ? '' : `${lodashPath}.`}${key}`, options, depthLevel + 1);
}
}
}
}
// @ts-ignore
if (options._exit && json === objOrWhatever) {
// @ts-ignore
options._exit = false;
}
}
return options;
}
}
const walk = {
Object: Helpers.Walk.Object,
ObjectBy: Helpers.Walk.ObjectBy,
};
/**
* Generated bundle index. Do not edit.
*/
export { Helpers, walk };
//# sourceMappingURL=lodash-walk-object.mjs.map