UNPKG

map-transform

Version:

Map and transform objects with mapping definitions

86 lines 3.3 kB
import { pathGetter, pathSetter } from '../operations/getSet.js'; import { defToDataMapper } from '../utils/definitionHelpers.js'; import { revFromState, isNonvalue } from '../utils/stateHelpers.js'; import { ensureArray } from '../utils/array.js'; import { isObject } from '../utils/is.js'; function addToBucket(value, buckets, key) { const bucket = buckets.get(key); if (bucket) { bucket.push(value); } else { buckets.set(key, [value]); } } async function sortIntoBuckets(getFn, pipelines, getGroupFn, data, state, nonvalues) { const arr = ensureArray(getFn(data, state)); const retBucket = new Map(); if (pipelines.length > 0) { for (const value of arr) { for (const [pipeline, key] of pipelines) { const result = await pipeline(value, state); if (result) { addToBucket(value, retBucket, key); break; } } } } else if (getGroupFn) { for (const value of arr) { const key = await getGroupFn(value, state); if (!isNonvalue(key, nonvalues)) { addToBucket(value, retBucket, String(key)); } } } return Object.fromEntries(retBucket.entries()); } function shouldGoInBucket(options, condition, size) { let inBucket = 0; const mapper = condition ? defToDataMapper(condition, options) : undefined; return async function considerItemForBucket(item, state) { if (size === undefined || inBucket < size) { if (!mapper || (await mapper(item, state))) { inBucket++; return true; } } return false; }; } const extractArrayFromBuckets = (buckets, keys, nonvalues) => isObject(buckets) ? (keys || Object.keys(buckets)) .flatMap((key) => buckets[key]) .filter((key) => !isNonvalue(key, nonvalues)) : []; const prepareGroupByPathFn = (pipeline, options) => typeof pipeline === 'string' ? pathGetter(pipeline) : pipeline === undefined ? undefined : defToDataMapper(pipeline, options); const extractBucketKeys = (buckets, hasGroupFn) => buckets.length === 0 && hasGroupFn ? undefined : buckets.map(({ key }) => key); const transformer = function bucket({ path = '.', buckets = [], groupByPath, }) { return (options) => { const getFn = pathGetter(path); const setFn = pathSetter(path, options); const getGroupByPathFn = prepareGroupByPathFn(groupByPath, options); const pipelines = buckets .filter(({ key }) => typeof key === 'string') .map((bucket) => [ shouldGoInBucket(options, bucket.condition ?? bucket.pipeline, bucket.size), bucket.key, ]); const keys = extractBucketKeys(buckets, !!getGroupByPathFn); return async (data, state) => { if (revFromState(state)) { return setFn(extractArrayFromBuckets(data, keys, options.nonvalues), state); } else { return sortIntoBuckets(getFn, pipelines, getGroupByPathFn, data, state, options.nonvalues); } }; }; }; export default transformer; //# sourceMappingURL=bucket.js.map