UNPKG

pathos

Version:

Decompose a javascript object into a set of path/value slices.

161 lines (146 loc) 3.42 kB
module.exports = slice; module.exports.slice = slice; function slice(data) { var paths = []; function storePaths(key, value) { paths.push({ key: key, value: value }); } visit(data, storePaths); return paths; } module.exports.visit = visit; function visit(data, fn, parts) { if (typeof parts === 'undefined') { parts = []; } if (Array.isArray(data)) { fn(parts, []); } if (data !== null && typeof data === 'object') { return visitChildren(); } else { fn(parts, data); return; } function visitChildren() { var keys = Object.keys(data); keys.forEach(function (key) { var value = data[key]; if (Array.isArray(data)) { key = parseInt(key, 10); } if (typeof value === 'object') { visit(value, fn, parts.concat(key)); } else { fn(parts.concat(key), data[key]); } }); return; } } module.exports.rewrite = rewrite; function rewrite(data, fn, parts, root) { if (typeof parts === 'undefined') { parts = []; root = data; } if (data !== null && typeof data === 'object') { return visitChildren(); } else { fn(parts, data); return; } function visitChildren() { var keys = Object.keys(data); keys.forEach(function (key) { var value = data[key]; if (typeof value === 'object') { rewrite(value, fn, parts.concat(key), root); } else { var result = fn(parts.concat(key), data[key]); if (result === true || typeof result === 'undefined') { // do nothing return; } else if (result === false) { // explicitly remove this path delete data[key]; } else if (typeof result.key !== 'undefined') { if (typeof result.value === 'undefined' || result.key !== key) { // ask to remove key, or key name has changed delete data[key]; } set(root, result.key, result.value); } } }); return; } } module.exports.walk = walk; function walk(obj, path) { path = path.slice(); while (path.length > 0) { var prop = path.shift(); if (obj && obj[prop] !== undefined) { obj = obj[prop]; } else { return; } } return obj; } module.exports.build = build; function build(paths) { var o = { }; paths.forEach(function (path) { o = buildPath(o, path.key, path.value); }); return o; } function buildPath(obj, path, value) { var root = obj; path = path.slice(); if (path.length === 0 && typeof value !== 'undefined') { root = value; } while (path.length > 0) { var prop = path.shift(); if (obj[prop] !== undefined) { obj = obj[prop]; } else if (path.length) { if (typeof path[0] === 'number') { obj[prop] = []; } else { obj[prop] = {}; } obj = obj[prop]; } else { obj[prop] = value; } } return root; } module.exports.set = set; function set(o, path, value) { var obj = o; path = path.slice(); while (path.length > 1) { var prop = path.shift(); if (obj[prop] !== undefined) { obj = obj[prop]; } else { obj[prop] = {}; obj = obj[prop]; } } if (path.length === 1) { var prop = path.shift(); if (typeof value === 'undefined') { delete obj[prop]; } else { obj[prop] = value; } } return o; }