From c232b471aca493628bec14c55e3ebed70561ece9 Mon Sep 17 00:00:00 2001 From: NetanelBasal Date: Sun, 26 May 2024 18:30:46 +0300 Subject: [PATCH] =?UTF-8?q?fix(query):=20=F0=9F=90=9E=20support=20throwOnE?= =?UTF-8?q?rror?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit throwOnError true calls observer.error now ✅ Closes: #180 --- query/src/lib/base-query.ts | 22 +++++++++++++++++----- query/src/lib/mutation.ts | 15 +++++++++++++-- query/src/lib/utils.ts | 18 ++++++++++++++++-- src/app/app.config.ts | 9 ++++++++- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/query/src/lib/base-query.ts b/query/src/lib/base-query.ts index 8f76587..6e93a9f 100644 --- a/query/src/lib/base-query.ts +++ b/query/src/lib/base-query.ts @@ -12,6 +12,7 @@ import { } from '@tanstack/query-core'; import { Observable, shareReplay } from 'rxjs'; import { normalizeOptions } from './query-options'; +import { shouldThrowError } from './utils'; export type QueryFunctionWithObservable< T = unknown, @@ -121,11 +122,22 @@ export function createBaseQuery< const queryObserverDispose = queryObserver.subscribe( notifyManager.batchCalls((result) => { - observer.next( - defaultedOptions.notifyOnChangeProps - ? result - : queryObserver?.trackResult(result), - ); + if ( + !result.isFetching && + result.isError && + shouldThrowError(queryObserver!.options.throwOnError, [ + result.error, + queryObserver!.getCurrentQuery(), + ]) + ) { + observer.error(result.error); + } else { + observer.next( + defaultedOptions.notifyOnChangeProps + ? result + : queryObserver?.trackResult(result), + ); + } }), ); diff --git a/query/src/lib/mutation.ts b/query/src/lib/mutation.ts index b234cbe..f625595 100644 --- a/query/src/lib/mutation.ts +++ b/query/src/lib/mutation.ts @@ -10,7 +10,7 @@ import { } from '@tanstack/query-core'; import { isObservable, Observable, shareReplay } from 'rxjs'; import { toSignal } from '@angular/core/rxjs-interop'; -import { toPromise } from './utils'; +import { shouldThrowError, toPromise } from './utils'; export type CreateMutationOptions< TData = unknown, @@ -89,7 +89,18 @@ class Mutation { notifyManager.batchCalls( ( result: MutationObserverResult, - ) => observer.next(result), + ) => { + if ( + result.isError && + shouldThrowError(mutationObserver!.options.throwOnError, [ + result.error, + ]) + ) { + observer.error(result.error); + } else { + observer.next(result); + } + }, ), ); diff --git a/query/src/lib/utils.ts b/query/src/lib/utils.ts index 70f61e5..cd04fad 100644 --- a/query/src/lib/utils.ts +++ b/query/src/lib/utils.ts @@ -1,7 +1,7 @@ import { DefaultError, QueryObserverResult, - QueryObserverSuccessResult + QueryObserverSuccessResult, } from '@tanstack/query-core'; import { Observable, Subject, firstValueFrom, takeUntil } from 'rxjs'; @@ -38,7 +38,10 @@ export function createSuccessObserverResult( } as QueryObserverSuccessResult; } -export function createPendingObserverResult(): QueryObserverResult { +export function createPendingObserverResult< + T = unknown, + Error = DefaultError, +>(): QueryObserverResult { return { isError: false, isLoading: true, @@ -49,3 +52,14 @@ export function createPendingObserverResult() status: 'pending', } as QueryObserverResult; } + +export function shouldThrowError) => boolean>( + throwError: boolean | T | undefined, + params: Parameters, +): boolean { + if (typeof throwError === 'function') { + return throwError(...params); + } + + return !!throwError; +} diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 52a9078..d91e0c9 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,5 +1,5 @@ import { provideHttpClient } from '@angular/common/http'; -import { ApplicationConfig, inject } from '@angular/core'; +import { ApplicationConfig, ErrorHandler, inject } from '@angular/core'; import { provideRouter, withComponentInputBinding } from '@angular/router'; import { @@ -22,8 +22,15 @@ const withFunctionaFactory: QueryClientConfigFn = () => { }; }; +class MyErrorHandler extends ErrorHandler { + override handleError(error: any) { + return super.handleError(error); + } +} + export const appConfig: ApplicationConfig = { providers: [ + { provide: ErrorHandler, useClass: MyErrorHandler }, provideRouter(appRoutes, withComponentInputBinding()), provideHttpClient(), provideQueryClientOptions(withFunctionaFactory),