From 8c0fb63f123151395d0c7afcffe2af1869a71e41 Mon Sep 17 00:00:00 2001 From: pimlie Date: Mon, 17 May 2021 02:04:33 +0200 Subject: [PATCH] feat: add support for recomputing nested paths --- src/object-merge/recompute.ts | 42 ++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/object-merge/recompute.ts b/src/object-merge/recompute.ts index 68e04b8..30574d8 100644 --- a/src/object-merge/recompute.ts +++ b/src/object-merge/recompute.ts @@ -25,14 +25,27 @@ export const allKeys = (source?: MergeSource, ...sources: MergeSource[] return keys } -export const recompute = (context: MergeContext, sources?: MergeSource[], target?: MergedObject, path: PathSegments = []): void => { - if (!path.length) { - if (!target) { - target = context.active - } +export const recompute = (context: MergeContext, path: PathSegments = [], target?: MergedObject, sources?: MergeSource[]): void => { + const setTargetAndSources = !target && !sources + if (setTargetAndSources) { + ({ active: target, sources } = context) - if (!sources) { - sources = context.sources + if (path.length) { + for (let i = 0; i < path.length; i++) { + const seg = path[i] + + if (!target || !target[seg]) { + if (__DEV__) { + // eslint-disable-next-line no-console + console.error(`recompute: segment ${seg} not found on target`, path, target) + } + return + } + + target = target[seg] + + sources = sources.map(source => (source as Record)[seg]).filter(Boolean) + } } } @@ -53,7 +66,17 @@ export const recompute = (context: MergeContext, sources?: MergeSource[ for (const key of keys) { // This assumes consistent types usages for keys across sources // @ts-ignore - if (isPlainObject(sources[0][key])) { + let isObject = false + for (let i = 0; i < sources.length; i++) { + const source = sources[i] as Record + + if (source && key in source && source[key] !== undefined) { + isObject = isPlainObject(source[key]) + break + } + } + + if (isObject) { if (!target[key]) { target[key] = {} } @@ -66,7 +89,7 @@ export const recompute = (context: MergeContext, sources?: MergeSource[ } } - recompute(context, keySources, target[key], [...path, key]) + recompute(context, [...path, key], target[key], keySources) continue } @@ -91,7 +114,6 @@ export const recompute = (context: MergeContext, sources?: MergeSource[ resolved = clone(resolved) } - // console.log('RESOLVED', key, resolved, 'was', target[key]) target[key] = resolved } }