UNPKG

rubico

Version:

[a]synchronous functional programming

121 lines (116 loc) 3.54 kB
const isArray = require('../_internal/isArray') /** * @name arrayDefaultsDeepFromArray * * @synopsis * ```coffeescript [specscript] * var array Array<Array|Object|any>, * defaultArray Array<Array|Object|any>, * * arrayDefaultsDeepFromArray(array, defaultArray) -> Array * ``` */ const arrayDefaultsDeepFromArray = function (array, defaultArray) { const defaultArrayLength = defaultArray.length, result = array.slice() let index = -1 while (++index < defaultArrayLength) { const item = array[index], defaultItem = defaultArray[index] if (isArray(item) && isArray(defaultItem)) { result[index] = arrayDefaultsDeepFromArray(item, defaultItem) } else if (item == null) { result[index] = defaultItem } else if (defaultItem == null) { result[index] = item } else if (item.constructor == Object && defaultItem.constructor == Object) { result[index] = objectDefaultsDeepFromObject(item, defaultItem) } else { result[index] = item } } return result } /** * @name objectDefaultsDeepFromObject * * @synopsis * ```coffeescript [specscript] * var object Object<Array|Object|any>, * defaultObject Object<Array|Object|any> * * objectDefaultsDeepFromObject(object, defaultObject) -> Object * ``` */ const objectDefaultsDeepFromObject = function (object, defaultObject) { const result = { ...object } for (const key in defaultObject) { const item = object[key], defaultItem = defaultObject[key] if (isArray(item) && isArray(defaultItem)) { result[key] = arrayDefaultsDeepFromArray(item, defaultItem) } else if (item == null) { result[key] = defaultItem } else if (defaultItem == null) { result[key] = item } else if (item.constructor == Object && defaultItem.constructor == Object) { result[key] = objectDefaultsDeepFromObject(item, defaultItem) } else { result[key] = item } } return result } /** * @name defaultsDeep * * @synopsis * ```coffeescript [specscript] * var defaultCollection Array|Object, * value Array|Object * * defaultsDeep(defaultCollection)(value) -> Array|Object * ``` * * @description * Deeply assign default values to an array or object by an array or object of possibly nested default values. * * ```javascript [playground] * import defaultsDeep from 'https://unpkg.com/rubico/dist/x/defaultsDeep.es.js' * * const defaultUser = defaultsDeep({ * name: 'placeholder', * images: [ * { url: 'https://via.placeholder.com/150' }, * { url: 'https://via.placeholder.com/150' }, * { url: 'https://via.placeholder.com/150' }, * ], * }) * * console.log(defaultUser({ * name: 'George', * images: [{ url: 'https://via.placeholder.com/150/0000FF/808080%20?Text=Digital.com' }], * })) * // { * // name: 'George', * // images: [ * // { url: 'https://via.placeholder.com/150/0000FF/808080%20?Text=Digital.com' }, * // { url: 'https://via.placeholder.com/150' }, * // { url: 'https://via.placeholder.com/150' }, * // ], * // } * ``` */ const defaultsDeep = defaultCollection => function defaulting(value) { if (isArray(value) && isArray(defaultCollection)) { return arrayDefaultsDeepFromArray(value, defaultCollection) } if (value == null || defaultCollection == null) { return value } if (value.constructor == Object && defaultCollection.constructor == Object) { return objectDefaultsDeepFromObject(value, defaultCollection) } return value } module.exports = defaultsDeep