UNPKG

foop

Version:

interfaces that describe their intentions.

208 lines (196 loc) 4.88 kB
/* FROM-TO: src/TraverseChain.js */ /* remapped from ./ChainedMapBase */ const ChainedMapBase = require('./ChainedMapBase.js') /* remapped from ./deps/traverse */ const traverse = require('./traverse.js') /* remapped from ./deps/is/true */ const isTrue = require('./true.js') /* remapped from ./deps/matcher/testKeysVals */ const matchFactory = require('./testKeysVals.js') /* remapped from ./deps/env/debug */ const ENV_DEBUG = require('./debug.js') const TRAVERSED_KEY = 1 const EXTENSION_KEYS = ['obj', 'keys', 'vals', 'onNonMatch', 'onMatch', 'clone'] /** * @since 1.0.0 * @type {Map} * @extends {ChainedMapBase} * * @memberOf Chainable * @memberOf Traverse * @see deps/traverse * @category traverse * @types TraverseChain * @tests TraverseChain * @symb 👣 * * @prop {Object} obj * @prop {Array<Matcher>} [keys] * @prop {Array<Matcher>} [vals] * @prop {Function} [onMatch] * @prop {Function} [onNonMatch] * @prop {boolean} [clone] */ module.exports = class Traverser extends ChainedMapBase { /** * @inheritdoc * @modifies this.call * * @example * * new Traverser({}) * */ constructor(parent) { super(parent) this.call = this.traverse.bind(this) /* prettier-ignore */ this .extend(EXTENSION_KEYS) .keys([]) .vals([]) // key, .onMatch((arg, traverser) => { // no return needed traverser.remove() }) } /** * @desc runs traverser, checks the tests, calls the onMatch * @modifies this.cleaned * * @memberOf TraverseChain * @alias call * @since 1.0.0 * * @param {boolean} [shouldReturn=false] returns traversed object * @return {any} this.obj/data cleaned * * @example * * const traversed = new Chain() * .merge({flat: 0, one: {two: true}}) * .traverse(false) * .vals([/true/]) * .onMatch((current, traverser) => { * traverser.path.join('.') * //=> 'one.two' * * current * //=> true * * typeof traverser.update === typeof traverser.remove * typeof traverser.update === 'function' * //=> true * * traverser.remove() * //=> void * }) * .onNonMatch(val => { * // ignore * }) * .call(true) * * traversed * //=> {flat: 0} * */ traverse(shouldReturn) { const {obj, keys, vals, onMatch, onNonMatch, clone} = this.entries() let result = clone ? traverse(obj).clone() : obj // diff between keys and val is order of arg in ^ tester const matcher = matchFactory(keys, vals) /* istanbul ignore next: debug */ if (ENV_DEBUG) { console.log('matcher for traverse...', keys, vals) } // bound to the traverser traverse(result).forEach(function(key, x, traverser) { if (traverser.isRoot) { // nothing } else if (matcher(key, x)) { /* istanbul ignore next: debug */ if (ENV_DEBUG) { console.log('------- match ------- ', key, x) } onMatch(x, traverser) } else if (onNonMatch) { /* istanbul ignore next: debug */ if (ENV_DEBUG) { console.log('------- NONmatch ------- ', key, x) } onNonMatch(x, traverser) } }) this.set(TRAVERSED_KEY, result) return isTrue(shouldReturn) ? result : this } /** * @ignore * @version 5.0.0-beta.5 @depreciated * value traversed in traverse * @since 1.0.0 * @see TraverseChain.traverse * @return {Object | Array | any} traversed * * @example * * const traverser = new Traverser() * traverser.obj(['duck', 'duck', 'goose']) * traverser.vals(['g**se']) * traverser.traverse() * * traverser.traversed() * //=> ['goose'] * * @example * * const eh = { * me: true, * nested: { * really: { * deep: { * super: false, * not: 'eh', * canada: true, * modules: [{parser: 'hi'}], * }, * matchme: 'minime', * notme: 'eh', * }, * }, * } * * const chain = new Chain() * Object.assign(chain, eh) * * const traverser = chain * .merge(eh) * .traverse(true) * .keys([/super/, /parser/, /store/, /meta/]) * .vals([/minime/]) * .call(false) * * traverser.traversed() * //=> { * className: 'DotProp', * me: true, * nested: { * really: { * deep: { * not: 'eh', * canada: true, * modules: [{}], * }, * notme: 'eh', * }, * }, * } * */ // traversed() { // return this.get(TRAVERSED_KEY) // } }