diff --git a/query/src/lib/operators.ts b/query/src/lib/operators.ts index d4af75e..3a4db26 100644 --- a/query/src/lib/operators.ts +++ b/query/src/lib/operators.ts @@ -118,6 +118,7 @@ type UnifiedTypes = T extends Array> * * This operator is used to merge multiple queries into one. * It will return a new base query result that will merge the results of all the queries. + * If you pass the 'intersectStaleData' flag, it will also intersect unsuccessful result in case data for all queries is present. * * @example * @@ -128,13 +129,25 @@ type UnifiedTypes = T extends Array> * intersectResults$(({ todos, posts }) => { * return { ... } * }) - * ) + * ); + * * @example * * const query = combineLatest([todos.result$, posts.result$]).pipe( * intersectResults$(([todos, posts]) => { * return { ... } * }) + * ); + * + * @example + * + * const query = combineLatest({ + * todos: todos.result$, + * posts: posts.result$, + * }).pipe( + * intersectResults$(({ todos, posts }) => { + * return { ... } + * }, { intersectStaleData: true }); * ) */ export function intersectResults$< @@ -144,6 +157,7 @@ export function intersectResults$< R, >( mapFn: (values: UnifiedTypes) => R, + options?: { intersectStaleData: boolean }, ): OperatorFunction & { all: T }> { return map((values) => { const isArray = Array.isArray(values); @@ -162,20 +176,14 @@ export function intersectResults$< refetch, } as unknown as QueryObserverResult & { all: T }; - if (mappedResult.isSuccess) { - if (isArray) { - mappedResult.data = mapFn( - toArray.map((r) => r.data) as UnifiedTypes, - ); - } else { - const data = Object.entries(values).reduce((acc, [key, value]) => { + if (mappedResult.isSuccess || (options?.intersectStaleData && toArray.every((r) => !!r.data))) { + const data = isArray + ? toArray.map((r) => r.data) as UnifiedTypes + : Object.entries(values).reduce((acc, [key, value]) => { acc[key as keyof UnifiedTypes] = value.data; - return acc; }, {} as UnifiedTypes); - - mappedResult.data = mapFn(data); - } + mappedResult.data = mapFn(data); } return mappedResult; diff --git a/query/src/lib/signals.ts b/query/src/lib/signals.ts index 3412177..9667d79 100644 --- a/query/src/lib/signals.ts +++ b/query/src/lib/signals.ts @@ -26,7 +26,8 @@ type UnifiedTypes = T extends Array>> * * This function is used to merge multiple signal queries into one. * It will return a new base query result that will merge the results of all the queries. - * Note that it should be used inside injection context + * Note that it should be used inside injection context. + * If you pass the 'intersectStaleData' flag, it will also intersect unsuccessful result in case data for all queries is present. * * @example * @@ -35,8 +36,7 @@ type UnifiedTypes = T extends Array>> * posts: posts.result$, * }, ({ todos, posts }) => { * return todos + posts; - * }) - * + * }); * * @example * @@ -49,6 +49,15 @@ type UnifiedTypes = T extends Array>> * return todoOne.title + todoTwo.title; * } * ); + * + * @example + * + * const query = intersetResults({ + * todos: todos.result$, + * posts: posts.result$, + * }, ({ todos, posts }) => { + * return todos + posts; + * }, { intersectStaleData: true }); */ export function intersectResults< T extends @@ -58,10 +67,17 @@ export function intersectResults< >( signals: T, mapFn: (values: UnifiedTypes) => R, + options?: { intersectStaleData: boolean } ): Signal & { all: T }> { const isArray = Array.isArray(signals); const toArray = isArray ? signals : Object.values(signals); const refetch = () => Promise.all(toArray.map(v => v().refetch())); + const intersectData = isArray + ? () => toArray.map((r) => r().data) as UnifiedTypes + : () => Object.entries(signals).reduce((acc, [key, value]) => { + acc[key as keyof UnifiedTypes] = value().data; + return acc; + }, {} as UnifiedTypes); return computed(() => { const mappedResult = { @@ -76,20 +92,8 @@ export function intersectResults< refetch, } as unknown as QueryObserverResult & { all: T }; - if (mappedResult.isSuccess) { - if (isArray) { - mappedResult.data = mapFn( - toArray.map((r) => r().data) as UnifiedTypes, - ); - } else { - const data = Object.entries(signals).reduce((acc, [key, value]) => { - acc[key as keyof UnifiedTypes] = value().data; - - return acc; - }, {} as UnifiedTypes); - - mappedResult.data = mapFn(data); - } + if (mappedResult.isSuccess || (options?.intersectStaleData && toArray.every((v) => !!v().data))) { + mappedResult.data = mapFn(intersectData()); } return mappedResult;