UNPKG

golden-path

Version:
102 lines (73 loc) 2.81 kB
import { assocPath, path as rPath, curry } from 'ramda'; const shallowEqual = require('shallowequal'); import resolvePath from './resolvePath'; import { TOKEN_HASH } from './constants'; const pathResolverCache = new Map(); const cachedResolvePath = (unResolvedPath, object) => { const isPathResolutionCached = pathResolverCache.has(unResolvedPath); if (isPathResolutionCached) { return pathResolverCache.get(unResolvedPath); } let resolved; try { resolved = resolvePath(unResolvedPath, object); } catch (err) { throw new Error(`Golden Path :: Error while resolving the path "${unResolvedPath}" - Please check the Golden Path Syntax`); } const { isCacheablePath, ...resolvedPathConfig } = resolved; if (isCacheablePath) { pathResolverCache.set(unResolvedPath, resolvedPathConfig); } return resolvedPathConfig; }; const update = curry((unResolvedPath, value, object) => { let { path, paths, notExist } = cachedResolvePath(unResolvedPath, object); if (notExist) { return object; } if (path && !paths) { paths = [path]; } let objectResult = object; let newVal = value; if (paths) { paths.forEach((p) => { if (typeof value === 'function') { newVal = value( rPath(p, object) ); } const isSameValue = shallowEqual(rPath(p, objectResult), newVal); if (isSameValue) { return; } objectResult = assocPath(p, newVal, objectResult) }); } return objectResult; }); const weakMap = new WeakMap(); const EMPTY_ARRAY = []; Object.freeze(EMPTY_ARRAY); const get = curry((unResolvedPath, object) => { const objectsWeakMap = weakMap.get(object); if (objectsWeakMap) { const isValueCached = objectsWeakMap.has(unResolvedPath); if (isValueCached) { return objectsWeakMap.get(unResolvedPath); } } const value = (() => { let { path, paths, notExist, isGreedy } = cachedResolvePath(unResolvedPath, object); if (notExist) { return isGreedy ? EMPTY_ARRAY : undefined; } if (path) { return rPath(path, object); } if (paths) { return paths.map((p) => rPath(p, object)); } })(); if (!objectsWeakMap) { if (typeof object === 'object' && !!object) { const map = new Map(); map.set(unResolvedPath, value); weakMap.set(object, map); } } else { objectsWeakMap.set(unResolvedPath, value); } return value; }); const v = (value) => `${TOKEN_HASH}${value}${TOKEN_HASH}`; const clearPathResolverCache = () => pathResolverCache.clear(); export { get, update, v, TOKEN_HASH, clearPathResolverCache };