diff --git a/libs/cdk/fetch-cache/services/fetch-cache.service.ts b/libs/cdk/fetch-cache/services/fetch-cache.service.ts index dac6df40..e9e59e56 100644 --- a/libs/cdk/fetch-cache/services/fetch-cache.service.ts +++ b/libs/cdk/fetch-cache/services/fetch-cache.service.ts @@ -1,34 +1,33 @@ import { inject, Injectable } from '@angular/core'; -import { AsyncResult, completableToObservable, loading, success } from '@cognizone/model-utils'; +import { completableToObservable, Result, ok } from '@cognizone/model-utils'; import { shareReplaySafe } from '@cognizone/ng-core'; -import { Observable, of, startWith, switchMap } from 'rxjs'; +import { Observable, of, switchMap } from 'rxjs'; import { CacheService } from './cache.service'; @Injectable({ providedIn: 'root' }) export class FetchCache { private cache: CacheService = inject(CacheService); - private currentFetchMap: { [key: string]: Observable } = {}; + private currentFetchMap: { [key: string]: Observable } = {}; - get(key: string, fetch: () => Observable>, options?: FetchCacheOptions): Observable> { - if (this.currentFetchMap[key]) return this.currentFetchMap[key] as Observable>; + get(key: string, fetch: () => Observable>, options?: FetchCacheOptions): Observable> { + if (this.currentFetchMap[key]) return this.currentFetchMap[key] as Observable>; const cache = (options?.cache ?? this.cache) as CacheService; return this.getFromCache(key, cache).pipe( switchMap(cached => { if (cached) { - return of(success(cached)); + return of(ok(cached)); } return (this.currentFetchMap[key] = fetch().pipe( switchMap(async result => { - if (result.type === 'success') { + if (result.type === 'ok') { await cache.set(key, result.content); } delete this.currentFetchMap[key]; return result; }), - startWith(loading()), shareReplaySafe(1) )); }) diff --git a/libs/cdk/result/index.ts b/libs/cdk/result/index.ts index b99d13f3..aa8519a1 100644 --- a/libs/cdk/result/index.ts +++ b/libs/cdk/result/index.ts @@ -1,3 +1,2 @@ -export * from './pipes/get-success.pipe'; export * from './pipes/is-error.pipe'; -export * from './pipes/is-loading.pipe'; +export * from './pipes/unwrap.pipe'; diff --git a/libs/cdk/result/pipes/get-success.pipe.ts b/libs/cdk/result/pipes/get-success.pipe.ts deleted file mode 100644 index 9102a712..00000000 --- a/libs/cdk/result/pipes/get-success.pipe.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { AsyncResult, Nil } from '@cognizone/model-utils'; - -@Pipe({ - name: 'getSuccess', - standalone: true, -}) -export class GetSuccessPipe implements PipeTransform { - transform(value: Nil>): T | undefined { - return value?.type === 'success' ? value.content : undefined; - } -} diff --git a/libs/cdk/result/pipes/is-error.pipe.ts b/libs/cdk/result/pipes/is-error.pipe.ts index d76662d5..ff800ea2 100644 --- a/libs/cdk/result/pipes/is-error.pipe.ts +++ b/libs/cdk/result/pipes/is-error.pipe.ts @@ -1,12 +1,12 @@ import { Pipe, PipeTransform } from '@angular/core'; -import { AsyncResult, Nil, ResultError } from '@cognizone/model-utils'; +import { Result, Nil, ResultError } from '@cognizone/model-utils'; @Pipe({ name: 'isError', standalone: true, }) export class IsErrorPipe implements PipeTransform { - transform(value: Nil): value is ResultError { + transform(value: Nil): value is ResultError { return value?.type === 'error'; } } diff --git a/libs/cdk/result/pipes/is-loading.pipe.ts b/libs/cdk/result/pipes/is-loading.pipe.ts deleted file mode 100644 index 123e3c90..00000000 --- a/libs/cdk/result/pipes/is-loading.pipe.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { AsyncResult, Nil, ResultLoading } from '@cognizone/model-utils'; - -@Pipe({ - name: 'isLoading', - standalone: true, -}) -export class IsLoadingPipe implements PipeTransform { - transform(value: Nil): value is ResultLoading { - return value?.type === 'loading'; - } -} diff --git a/libs/cdk/result/pipes/unwrap.pipe.ts b/libs/cdk/result/pipes/unwrap.pipe.ts new file mode 100644 index 00000000..97ada5ce --- /dev/null +++ b/libs/cdk/result/pipes/unwrap.pipe.ts @@ -0,0 +1,12 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { Result } from '@cognizone/model-utils'; + +@Pipe({ + name: 'unwrap', + standalone: true, +}) +export class UnwrapPipe implements PipeTransform { + transform(value: Result, defaultValue: T): T { + return value.type === 'ok' ? value.content : defaultValue; + } +} diff --git a/libs/model-utils/src/lib/models/result.ts b/libs/model-utils/src/lib/models/result.ts index ec1ff774..7ace7143 100644 --- a/libs/model-utils/src/lib/models/result.ts +++ b/libs/model-utils/src/lib/models/result.ts @@ -1,19 +1,19 @@ /** - * @description Represents a remote data and its related state + * @description Wraps a value in an ok if the related operations went well, otherwise wrap the result in an error. + * The idea is to force consumers for `Result` to handle error cases, and not be dependant on try/catch behaviors */ -export type AsyncResult = ResultSuccess | ResultError | ResultLoading; -export type Result = ResultSuccess | ResultError; +export type Result = ResultOk | ResultError; /** * @description the resource has been successfully retrieved and is stored in `content` */ -export type ResultSuccess = { - type: 'success'; +export type ResultOk = { + type: 'ok'; content: T; }; -export function success(content: T): ResultSuccess { - return { type: 'success', content }; +export function ok(content: T): ResultOk { + return { type: 'ok', content }; } /** @@ -27,16 +27,3 @@ export type ResultError = { export function error(err: T): ResultError { return { type: 'error', error: err }; } - -/** - * @description the query to fetch the resource has been started but the response did not arrive yet - */ -export type ResultLoading = { - type: 'loading'; -}; - -// always the same, no need to re-create it every time -const _loading = { type: 'loading' as const }; -export function loading(): ResultLoading { - return _loading; -}