lodash-ny-util
Version:
Lodash mixin for generic list, map, string functionality.
122 lines (110 loc) • 3.6 kB
JavaScript
/**
* Lodash mixins for generic functions for New York Magazine.
*
* File format inspired by lodash-deep.
* @license MIT
*/
(function (root, factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['lodash'], factory);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('lodash').runInContext());
} else {
// Browser globals (root is window)
root._ = factory(root._.runInContext());
}
}(this, function (_) {
'use strict';
/**
*
* @param {string|function} fn
* @returns {function(this:null)}
*/
function convertToPromisePartial(fn) {
fn = _.isFunction(fn) ? fn : _[fn];
var result = _.partial.bind(null, fn, _);
if (arguments.length > 1) {
result = result.apply(null, _.slice(arguments, 1));
}
return result;
}
var mixins = /** @lends _ */ {
/**
* Maps the first row to become the property names of every following row, returning a list of maps.
*
* Example: [['a', 'b'], ['c', 'd']] becomes {a: 'c', b: 'd'}
* @param {[[]]} list rows containing columns as arrays
* @returns {[{}]} rows containing columns as objects
*/
mapToHeaders: function (list) {
if (!_.isArray(list)) {
throw new Error('first parameter must be array');
}
if (list.length < 1) {
throw new Error('first parameter must have at least one row (headers)');
}
var headers = _.map(list.shift(), function (header, index) {
if (header === null) {
throw new Error('Missing header name of column ' + index);
}
return _.camelCase(header.toString());
});
return _.map(list, function (row) {
return _.reduce(headers, function (obj, header, index) {
obj[header] = row[index];
return obj;
}, {});
});
},
/**
* Shorthand for using lodash functions with A+ Promise's `.then` function
*
* @param {string|function} fn
* @example return Promise.resolve(thing).then(_.promise(_.indexBy)('name')))
* @example return Promise.resolve(thing).then(_.promise('indexBy')('name')))
* @example return Promise.resolve(thing).then(_.promise(_.indexBy, 'name')))
* @example return Promise.resolve(thing).then(_.promise('indexBy', 'name')))
* @returns {function}
*/
promise: convertToPromisePartial,
/**
* Takes an object that contains other objects, and flips the keys of the object and the inner object
* @param {{}} map
* @returns {{}}
*/
invertKeys: function (map) {
return _.reduce(map, function (obj, innerObj, key) {
_.each(innerObj, function (value, innerKey) {
obj[innerKey] = obj[innerKey] || {};
obj[innerKey][key] = value;
});
return obj;
}, {});
},
/**
* @param obj
* @param [filter=_.identity] Optional filter
*
* NOTE: Should probably put this in our lodash utils
*/
listDeepObjects: function (obj, filter) {
var cursor, items,
list = [],
queue = [obj];
while (queue.length) {
cursor = queue.pop();
items = _.filter(cursor, _.isObject);
list = list.concat(_.filter(items, filter || _.identity));
queue = queue.concat(items);
}
return list;
}
};
_.mixin(mixins);
return mixins;
}));