Skip to content

Commit

Permalink
chore: BIM-43424 add docs for rxjs operators
Browse files Browse the repository at this point in the history
  • Loading branch information
= authored and Zlaylink committed Jan 18, 2024
1 parent 26d0188 commit 5a0f654
Show file tree
Hide file tree
Showing 24 changed files with 255 additions and 47 deletions.
12 changes: 12 additions & 0 deletions packages/rxjs/src/operators/concat-boolean.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ import { map } from 'rxjs/operators';

type MergeType = 'and' | 'or';

/**
* Concatenates an array of boolean values into a single boolean value based on the specified merge type.
*
* @typedef {'and' | 'or'} MergeType - The type of merging to be applied ('and' for logical AND, 'or' for logical OR).
* @param [mergeType='and'] - The type of merging to be applied. Defaults to 'and'.
* @returns - An operator that concatenates boolean values based on the specified merge type.
* @example
* // Concatenates an array of boolean values into a single boolean value based on logical AND
* const input$: Observable<boolean[]> = of([true, false, true]);
*
* input$.pipe(concatBoolean('and')).subscribe((result: boolean) => { ... })
*/
export const concatBoolean =
(mergeType?: MergeType): OperatorFunction<boolean[], boolean> =>
(source$: Observable<boolean[]>): Observable<boolean> =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import { from, Observable } from 'rxjs';
import { distinctUntilSerializedChanged } from '@bimeister/utilities.rxjs';
import { from, Observable } from 'rxjs';

interface User {
id: number;
name: string;
}

describe('buffer-from-to.operator.ts', () => {
it('should leave one element', () => {
const source$: Observable<number> = from([1, 1, 1]);
const source$: Observable<User> = from([
{ id: 1, name: 'test' },
{ id: 1, name: 'test' },
{ id: 1, name: 'test' }
]);

const emits: unknown[] = [];

source$.pipe(distinctUntilSerializedChanged()).subscribe((output: number) => {
source$.pipe(distinctUntilSerializedChanged()).subscribe((output: User) => {
emits.push(output);
});

expect(emits).toEqual([1]);
expect(emits).toEqual([{ id: 1, name: 'test' }]);
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
import type { MonoTypeOperatorFunction, Observable } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

/**
* Filters out consecutive emissions from the source observable that have the same serialized representation.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that filters out consecutive equal values based on their serialized representation.
* @example
* // Filters out consecutive emissions from the source observable
* // that have the same serialized representation of an object with type User
* const source$: Observable<User> = from([
{ id: 1, name: 'test' },
{ id: 1, name: 'test' },
{ id: 1, name: 'test' }
]);
source$.pipe(distinctUntilSerializedChanged()).subscribe((output: User) => { ... })
*/
export const distinctUntilSerializedChanged =
<T>(): MonoTypeOperatorFunction<T> =>
(source: Observable<T>): Observable<T> =>
Expand Down
13 changes: 13 additions & 0 deletions packages/rxjs/src/operators/filter-by-instance-of.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@ import type { Constructor } from 'packages/types/src/constructor.type';
import type { Observable, OperatorFunction } from 'rxjs';
import { filter } from 'rxjs/operators';

/**
* Filters the values emitted by the source observable based on the instance of specified types.
*
* @template I - The type of instances to filter for in the source observable.
* @param types - The types to filter for instance of in the source observable.
* @returns - An operator that filters the source observable based on the specified types.
* @example
* // Filters the values produced by the source observable based on an instance of the specified SomeClass instance type
* const input$: Observable<unknown> = from([1, 'string', { name: 'Some name' }, new SomeClass()]);
input$
.pipe(filterByInstanceOf(SomeClass))
*/
export function filterByInstanceOf<I>(...types: Constructor<I>[]): OperatorFunction<unknown, I> {
return (source$: Observable<unknown>) =>
source$.pipe(filter((value: unknown): value is I => types.some((type: Constructor<I>) => value instanceof type)));
Expand Down
2 changes: 1 addition & 1 deletion packages/rxjs/src/operators/filter-falsy.operator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { from, Observable } from 'rxjs';
import { filterFalsy } from '@bimeister/utilities.rxjs';
import { from, Observable } from 'rxjs';

describe('filter-falsy.operator.ts', () => {
it('should filter truth value', () => {
Expand Down
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/filter-falsy.operator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import type { MonoTypeOperatorFunction, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';

export const filterFalsy =
<T>(): MonoTypeOperatorFunction<T> =>
/**
* Filters out truthy values from the source observable.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that filters out truthy values from the source observable.
* @example
* const input$: Observable<unknown> = from([1, 'string', false, true]);
input$
.pipe(filterFalsy())
.subscribe((output: unknown) => { ... })
*/
export const filterFalsy: <T>() => MonoTypeOperatorFunction<T> =
<T>() =>
(source: Observable<T>): Observable<T> =>
source.pipe(filter<T>((value: T) => !Boolean(value)));
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { from, Observable } from 'rxjs';
import { filterNotEmpty } from '@bimeister/utilities.rxjs';
import { from, Observable } from 'rxjs';

describe('filter-not-empty.operator.ts', () => {
it('should return not empty values', () => {
Expand Down
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/filter-not-empty.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@ import { isEmpty } from '@bimeister/utilities.common';
import type { MonoTypeOperatorFunction, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';

export const filterNotEmpty =
<T>(): MonoTypeOperatorFunction<T> =>
/**
* Filters out values that are considered empty from the source observable.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that filters out values considered empty from the source observable.
* @example
* const input$: Observable<unknown> = from([null, undefined, '', 'string', [], {}]);
input$
.pipe(filterNotEmpty())
.subscribe((output: unknown) => { ... })
*/
export const filterNotEmpty: <T>() => MonoTypeOperatorFunction<T> =
<T>() =>
(source: Observable<T>): Observable<T> =>
source.pipe(filter<T>((value: T) => !isEmpty(value)));
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/filter-not-nil.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@ import { isNil } from '@bimeister/utilities.common';
import type { Observable, OperatorFunction } from 'rxjs';
import { filter } from 'rxjs/operators';

/**
* Filters out values that are considered `null` or `undefined` from the source observable.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that filters out values considered `null` or `undefined` from the source observable.
* @example
* const input$: Observable<unknown> = from([null, undefined, '', 'string']);
input$
.pipe(filterNotNil())
.subscribe((output: unknown) => { ... })
*/
export const filterNotNil: <T>() => OperatorFunction<T, NonNullable<T>> =
<L>(): OperatorFunction<L, NonNullable<L>> =>
<T>(source$: Observable<T>): Observable<NonNullable<T>> =>
<T>() =>
(source$: Observable<T>): Observable<NonNullable<T>> =>
source$.pipe(filter((value: T): value is NonNullable<T> => !isNil(value)));
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/filter-truthy.operator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import type { MonoTypeOperatorFunction, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';

export const filterTruthy =
<T>(): MonoTypeOperatorFunction<T> =>
/**
* Filters out falsy values from the source observable.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that filters out falsy values from the source observable.
* @example
* const input$: Observable<unknown> = from([1, 'string', false, true]);
input$
.pipe(filterTruthy())
.subscribe((output: unknown) => { ... })
*/
export const filterTruthy: <T>() => MonoTypeOperatorFunction<T> =
<T>() =>
(source: Observable<T>): Observable<T> =>
source.pipe(filter<T>((value: T) => Boolean(value)));
11 changes: 11 additions & 0 deletions packages/rxjs/src/operators/filter-uuid.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ import type { Uuid } from '@bimeister/utilities.types';
import type { Observable, OperatorFunction } from 'rxjs';
import { filter } from 'rxjs/operators';

/**
* Filters out non-UUID values from the source observable.
*
* @returns - An operator that filters out non-UUID values from the source observable.
* @example
* const input$: Observable<unknown> = from([1, 'string', {}, 'afa05a7a-a6e0-4687-b293-a2dec7c66ee0]);
input$
.pipe(filterUuid())
.subscribe((output: unknown) => { ... })
*/
export function filterUuid(): OperatorFunction<string, Uuid> {
return (source$: Observable<string>): Observable<Uuid> =>
source$.pipe(filter((value: string): value is Uuid => isUuid(value)));
Expand Down
13 changes: 11 additions & 2 deletions packages/rxjs/src/operators/invert-boolean.operator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import type { Observable, OperatorFunction } from 'rxjs';
import { map } from 'rxjs/operators';

export const invertBoolean =
(): OperatorFunction<boolean, boolean> =>
/**
* Inverts boolean values emitted by the source observable.
*
* @returns - An operator that inverts boolean values emitted by the source observable.
* @example
* const input$: Observable<boolean> = of(true, true, true);
input$.pipe(invertBoolean()).subscribe((result: boolean) => { ... })
*/
export const invertBoolean: () => OperatorFunction<boolean, boolean> =
() =>
(source$: Observable<boolean>): Observable<boolean> =>
source$.pipe(map((value: boolean) => !value));
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/map-to-is-empty.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@ import { isEmpty } from '@bimeister/utilities.common';
import type { Observable, OperatorFunction } from 'rxjs';
import { map } from 'rxjs/operators';

export const mapToIsEmpty =
<T>(): OperatorFunction<T, boolean> =>
/**
* Maps values emitted by the source observable to a boolean indicating whether the value is considered empty.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that maps values to a boolean indicating whether they are considered empty.
* @example
* const input$: Observable<unknown> = from([null, '', 0, undefined, [], new Map(), {}, [1]]
input$
.pipe(mapToIsEmpty())
.subscribe((output: unknown) => { ... } )
*/
export const mapToIsEmpty: <T>() => OperatorFunction<T, boolean> =
<T>() =>
(source: Observable<T>): Observable<boolean> =>
source.pipe(map<T, boolean>((value: T) => isEmpty(value)));
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { from, Observable } from 'rxjs';
import { mapToIsFalsy } from '@bimeister/utilities.rxjs';
import { from, Observable } from 'rxjs';

describe('map-to-is-falsy.operator.spec.ts', () => {
it('should values map to is falsy', () => {
Expand Down
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/map-to-is-falsy.operator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import type { Observable, OperatorFunction } from 'rxjs';
import { map } from 'rxjs/operators';

export const mapToIsFalsy =
<T>(): OperatorFunction<T, boolean> =>
/**
* Maps values emitted by the source observable to a boolean indicating whether the value is falsy.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that maps values to a boolean indicating whether they are falsy.
* @example
* const input$: Observable<unknown> = from([1, '', 0, 'string']);
input$
.pipe(mapToIsFalsy())
.subscribe((output: unknown) => { ... })
*/
export const mapToIsFalsy: <T>() => OperatorFunction<T, boolean> =
<T>() =>
(source: Observable<T>): Observable<boolean> =>
source.pipe(map<T, boolean>((value: T) => !Boolean(value)));
2 changes: 1 addition & 1 deletion packages/rxjs/src/operators/map-to-is-nil.operator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { from, Observable } from 'rxjs';
import { mapToIsNil } from '@bimeister/utilities.rxjs';
import { from, Observable } from 'rxjs';

describe('map-to-is-nil.operator.spec.ts', () => {
it('should values map to is nil', () => {
Expand Down
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/map-to-is-nil.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@ import { isNil } from '@bimeister/utilities.common';
import type { Observable, OperatorFunction } from 'rxjs';
import { map } from 'rxjs/operators';

export const mapToIsNil =
<T>(): OperatorFunction<T, boolean> =>
/**
* Maps values emitted by the source observable to a boolean indicating whether the value is `null` or `undefined`.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that maps values to a boolean indicating whether they are `null` or `undefined`.
* @example
* const input$: Observable<unknown> = from([null, '', 0, undefined]);
input$
.pipe(mapToIsNil())
.subscribe((output: unknown) => { ... })
*/
export const mapToIsNil: <T>() => OperatorFunction<T, boolean> =
<T>() =>
(source: Observable<T>): Observable<boolean> =>
source.pipe(map<T, boolean>((value: T) => isNil(value)));
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { from, Observable } from 'rxjs';
import { mapToIsTruthy } from '@bimeister/utilities.rxjs';
import { from, Observable } from 'rxjs';

describe('map-to-is-truthy.operator.spec.ts', () => {
it('should values map to is true', () => {
Expand Down
16 changes: 14 additions & 2 deletions packages/rxjs/src/operators/map-to-is-truthy.operator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import type { Observable, OperatorFunction } from 'rxjs';
import { map } from 'rxjs/operators';

export const mapToIsTruthy =
<T>(): OperatorFunction<T, boolean> =>
/**
* Maps values emitted by the source observable to a boolean indicating whether the value is truthy.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that maps values to a boolean indicating whether they are truthy.
* @example
* const input$: Observable<unknown> = from([1, '', 0, 'string']);
input$
.pipe(mapToIsTruthy())
.subscribe((output: unknown) => { ... })
*/
export const mapToIsTruthy: <T>() => OperatorFunction<T, boolean> =
<T>() =>
(source: Observable<T>): Observable<boolean> =>
source.pipe(map<T, boolean>((value: T) => Boolean(value)));
12 changes: 12 additions & 0 deletions packages/rxjs/src/operators/map-to-void.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ import { VOID } from '@bimeister/utilities.constants';
import type { Observable, OperatorFunction } from 'rxjs';
import { mapTo } from 'rxjs/operators';

/**
* Maps values emitted by the source observable to `void`.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that maps values to `void`.
* @example
* const input$: Observable<number[]> = of([1, 2, 3]);
input$
.pipe(mapToVoid())
.subscribe(() => { ... })
*/
export const mapToVoid =
<T>(): OperatorFunction<T, void> =>
(source: Observable<T>): Observable<void> =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import type { MonoTypeOperatorFunction, Observable } from 'rxjs';
import { shareReplay } from 'rxjs/operators';

/**
* Shares and replays the values emitted by the source observable with reference counting.
*
* @template T - The type of elements emitted by the source observable.
* @returns - An operator that shares and replays values with reference counting.
*/
export const shareReplayWithRefCount =
<T>(): MonoTypeOperatorFunction<T> =>
(source: Observable<T>): Observable<T> =>
Expand Down
10 changes: 3 additions & 7 deletions packages/rxjs/src/operators/tap-on-condition.operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,11 @@ import { tap } from 'rxjs/operators';
* @param condition - The condition to check before invoking the callback.
* @param callback - The callback function to be invoked when the condition is true.
* @returns - An operator that performs a side effect for each emission on the source observable.
* @example
* // Displays a successful toast of saved settings if the isSaved flag is true.
* source$.pipe(..., tapOnCondition(this.isSaved, () => this.showSuccessToast()), ...)
*/
export function tapOnCondition<T>(condition: boolean, callback: VoidFunction): OperatorFunction<T, T> {
/**
* Returns a new observable that, when subscribed, taps into the source observable
* and invokes the callback if the specified condition is true.
*
* @param source$ - The source observable to tap into.
* @returns - An observable that emits the same values as the source observable.
*/
return (source$: Observable<T>) =>
source$.pipe(
tap(() => {
Expand Down
Loading

0 comments on commit 5a0f654

Please sign in to comment.