Skip to content

Instantly share code, notes, and snippets.

@saaage
Created September 8, 2020 14:09
Show Gist options
  • Save saaage/142adc7fddb4769e734208461632141e to your computer and use it in GitHub Desktop.
Save saaage/142adc7fddb4769e734208461632141e to your computer and use it in GitHub Desktop.
import get from 'lodash.get'
import isEqual from 'lodash.isequal'
import v from 'voca'
export const titleCase = s => v.titleCase(s, ["'", /[A-Z]/])
export const isArray = val => Array.isArray(val)
// returns collection that is unique on the provided key
// eg: uniqueOn([{ id: 1, name: "stefan"}, { id: 1, name: "john" }], "id") => [{ id: 1, name "stefan"}]
export const uniqueOn = (coll, path) => {
return coll.reduce((newColl, item) => {
return newColl.find(i => isEqual(get(i, path), get(item, path)))
? newColl
: [...newColl, item]
}, [])
}
// takes a collection of objects and returns a string containing the error value of each
export const combineMessages = coll => {
const clone = Array.from(coll).map(obj => get(obj, 'message', ''))
return clone.join(' - ')
}
export const asyncForEach = async (array, callback) => {
const errors = []
const resolutions = []
for (let index = 0; index < array.length; index++) {
await callback(array[index])
.then(resolution => resolutions.push(resolution))
.catch(err => errors.push(err))
}
if (errors.length > 0) return Promise.reject(errors)
return Promise.resolve(resolutions)
}
export const isObject = arg =>
Object.prototype.toString.call(arg) === '[object Object]'
// is a thing null/undefined?
export const isNil = arg => arg === null || arg === undefined
// is a thing NOT null and NOT undefined
export const notNil = arg => !isNil(arg)
export const isEmptyString = arg => arg === ''
export const renderFallback = (arg, fallback) => {
if (isNil(arg) || isEmptyString(arg)) {
return fallback
} else return arg
}
// returns a new object containing only the keys selected
export const selectKeys = (obj, keys) => {
const map = {}
keys.forEach(k => (map[k] = obj[k]))
return map
}
// returns a new object with keys removed
export const removeKeys = (obj, keys) => {
const clone = { ...obj }
keys.forEach(k => delete clone[k])
return clone
}
// if arg is null or undefined, returns value
export const ifNil = (arg, fallback) => {
if (isNil(arg)) {
return fallback
} else return arg
}
export const ifNotNil = (arg, fallback) => {
if (notNil(arg)) {
return fallback
} else return arg
}
// mock some fn that takes a specific amount of time
export const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
// does every member of a collection satisfy the given predicate
export const allTrue = (pred, coll) => {
const failure = coll.find(m => pred(m) === false)
return isNil(failure)
}
// does the collection contain the value? (using f to derive comparison value as it iterates over collection)
// if derive fn is not provided, checks collection for value itself
export const contains = (coll, value, derive) => {
if (derive) {
let result = false
coll.forEach(i => {
if (derive(i) === value) result = true
})
return result
}
return coll.indexOf(value) > -1 ? true : false
}
// takes a key value pair and returns true if value is an empty string
export const objectValueIsEmptyString = (k, v) => v === ''
// remove all members of an enumerable object where fn(i) returns true (where i is an iterable value of coll)
export const remove = (obj, fn) => {
if (Array.isArray(obj)) {
const clone = Array.from(obj)
return clone.filter(m => fn(m) === false)
}
if (isObject(obj)) {
const clone = { ...obj }
for (const key in clone) {
if (fn(key, clone[key]) === true) delete clone[key]
}
return clone
} else return obj
}
// removes the first instance of value from the collection
export const removeValue = (coll, val) => {
const result = Array.from(coll)
const index = result.indexOf(val)
if (index !== -1) result.splice(index, 1)
return result
}
// mutates obj[key] using fn and returns obj
export const update = (obj, key, fn) => {
obj[key] = fn(obj[key])
return obj
}
// mutates obj[key] using fn and returns obj
export const updateAsync = async (obj, key, fn) => {
try {
obj[key] = fn(obj[key])
return obj
} catch (err) {
throw new Error(err)
}
}
export const compareNums = (a, b) => {
if (isNaN(parseInt(a, 10)) || isNaN(parseInt(b, 10)))
throw new Error(
'compareNums called with one or more non-parseable number values'
)
const A = parseInt(a, 10)
const B = parseInt(b, 10)
if (A < B) return -1
if (A > B) return 1
return 0
}
// compares two strings returns a value to be passed to Array.sort()
export const compareStrings = (a, b) => {
if (typeof a !== 'string' || typeof b !== 'string')
throw new Error('compareStrings called with one or more non-string values')
if (a.toLowerCase() < b.toLowerCase()) return -1
if (a.toLowerCase() > b.toLowerCase()) return 1
return 0
}
// compares two objects using their value at `key`, returns a value to be passed to Array.sort()
export const compareUsingKey = (a, b, key) => {
if (typeof a[key] === 'string' && typeof b[key] === 'string') {
if (get(a, key).toLowerCase() < get(b, key).toLowerCase()) return -1
if (get(a, key).toLowerCase() > get(b, key).toLowerCase()) return 1
return 0
}
if (get(a, key) < get(b, key)) return -1
if (get(a, key) > get(b, key)) return 1
return 0
}
// if string, array, or object is empty returns true. if arg is null/undefined, returns true.
export const isEmpty = arg => {
if (isNil(arg)) return true
if (typeof arg === 'object' || typeof arg === 'string')
return Object.entries(arg).length === 0
else return false
}
export const some = v => !isEmpty(v)
// if arg is empty, returns fallback, otherwise returns arg
export const ifEmpty = (arg, fallback) => {
if (isEmpty(arg)) return fallback
else return arg
}
// takes an object, location, value x - returns new object with value inserted at location
export const assoc = (obj, location, x) => {
let clone
if (isArray(obj)) {
clone = Array.from(obj)
return clone
} else if (isObject(obj)) {
clone = { ...obj }
clone[location] = x
return clone
} else
return new Error(
`argument passed to assoc should be an array or object. received ${typeof obj}: ${obj}`
)
}
export const keyOn = (coll, path) => {
const newObj = {}
coll.forEach(i => newObj[get(i, path)] = i)
return newObj
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment