UNPKG

svelte-ux

Version:

- Increment version in `package.json` and commit as `Version bump to x.y.z` - `npm run publish`

142 lines (141 loc) 4.84 kB
import { get, camelCase, mergeWith } from 'lodash-es'; import { entries } from '../types/typeHelpers'; export function isLiteralObject(obj) { return obj && typeof obj === 'object' && obj.constructor === Object; } export function camelCaseKeys(obj) { return Object.keys(obj).reduce((acc, key) => ((acc[camelCase(key)] = obj[key]), acc), {}); } // https://codereview.stackexchange.com/questions/73714/find-a-nested-property-in-an-object // https://github.com/dominik791/obj-traverse export function nestedFindByPredicate(obj, predicate, childrenProp) { const getChildrenProp = propAccessor(childrenProp !== null && childrenProp !== void 0 ? childrenProp : 'children'); if (predicate(obj)) { return obj; } else { const children = getChildrenProp(obj); if (children) { for (let o of children) { const match = nestedFindByPredicate(o, predicate, childrenProp); if (match) { return match; } } } } } export function propAccessor(prop) { return typeof prop === 'function' ? prop : typeof prop === 'string' ? (d) => get(d, prop) : (x) => x; } /** * Produce a unique Id for an object (helpful for debugging) * See: https://stackoverflow.com/a/35306050/191902 */ var objIdMap = new WeakMap(), objectCount = 0; export function objectId(object) { if (!objIdMap.has(object)) objIdMap.set(object, ++objectCount); return objIdMap.get(object); } export function distinctKeys(...objs) { const keys = [...new Set(flatten(objs.map((x) => Object.keys(x))))]; return keys; } // Copied from `array.ts` to remove circular dependency function flatten(items) { return items.reduce((prev, next) => prev.concat(next), []); } /** * Recursive merge objects * @param object The destination object * @param source The source object * @returns */ export function merge(object, source) { return mergeWith(object, source, (objValue, srcValue) => { if (Array.isArray(srcValue)) { // Overwrite instead of merging by index with objValue (like standard lodash `merge` does) return srcValue; } }); } /** * Remove properties from object based on expiration */ export function expireObject(object, expiry) { const now = new Date(); if (expiry instanceof Date && expiry < now) { // Expired return null; } else if (typeof expiry === 'object') { for (let [prop, propExpiry] of Object.entries(expiry)) { if (propExpiry instanceof Date) { // Check if expired if (propExpiry < now) { if (prop === '$default') { // Delete all properties which do not have explicit expiry to check for (let [objProp, value] of Object.entries(object)) { if (!(objProp in expiry)) { delete object[objProp]; } } // Remove expired `$default` property delete object[prop]; } else { // Remove expired property delete object[prop]; } } else { // Keep value } } else { // Check expiry for each property in object. Skip if prop not in object (expiry only) if (prop in object) { expireObject(object[prop], propExpiry); } // Remove property if empty object (all properties removed) if (isLiteralObject(object[prop]) && Object.keys(object[prop]).length === 0) { delete object[prop]; } } } } return isLiteralObject(object) && Object.keys(object).length === 0 ? null : object; } /** * Remove properties from an object. See also lodash `_.omit()` */ export function omit(obj, keys) { if (keys.length === 0) { return obj; } else { return Object.fromEntries(Object.entries(obj).filter(([key, value]) => !keys.includes(key))); } } /** * Pick properties from an object. See also lodash `_.pick()` */ export function pick(obj, keys) { if (keys.length === 0) { return obj; } else { return Object.fromEntries(keys.filter((key) => key in obj).map((key) => [key, obj[key]])); } } /** * Create new object with keys and values swapped. Last value's key is used if duplicated */ export function keysByValues(obj) { return Object.fromEntries(entries(obj).map(([key, value]) => [value, key])); }