Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions libs/nodejs/rxjs/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"extends": ["../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
}
}
]
}
69 changes: 69 additions & 0 deletions libs/nodejs/rxjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# RxJS Utilities (`@studiohyperdrive/rxjs-utils`)

Install the package first:
```shell
npm install @studiohyperdrive/rxjs-utils
```

## 1. Operators

A set of custom operators.

### catchAndCallThrough
An operator that wraps around the default `catchError` and returns a new observable with the error to continue the stream.

[Full documentation.](./docs/operators/catch-and-call-through/catch-and-call-through.operator.md)

### combineBoolean
An operator that wraps around the default `combineLatest` and returns a boolean to indicate that all streams have values.

[Full documentation.](./docs/operators/combine-boolean/combine-boolean.operator.md)


### populate
An operator that will populate provided values in an observable, if the provided values are empty or match with a populateIf function.

[Full documentation.](./docs/operators/populate/populate.operator.md)

### fetchIf
An operator that will return a value from an observable source when present or fetch it when not.

[Full documentation.](./docs/operators/fetch-if/fetch-if.operator.md)

### pluck
An operator that is a custom implementation of the RxJS version, the original one is deprecated in favour of map.

[Full documentation.](./docs/operators/pluck/pluck.operator.md)

### pluckOr
An operator that will pluck a value based on its existence, with a list of property names in case the property is empty.

[Full documentation.](./docs/operators/pluck-or/pluck-or.operator.md)

### validateContent
An operator that wraps around the default `filter` and returns a boolean depending on the existence of a value in the stream.

[Full documentation.](./docs/operators/validate-content/validate-content.operator.md)

## 2. Types

### Observables
A collection of types that extend the default Observable interface.

[Full documentation.](./docs/types/observable/observable.types.md)

## build information
This project has been build with:
- nodejs: `18.17.0`
- npm: `9.6.7`

For a complete list of packages and version check out the `package.json` file.

## Team

This bundle of tools has been created and is maintained by [Studio Hyperdrive](https://studiohyperdrive.be).

Contributors:
- [Denis Valcke](https://github.com/DenisValcke)
- [Iben Van de Veire](https://github.com/IbenTesara)
- [Wouter Heirstrate](https://github.com/WHeirstrate)
41 changes: 41 additions & 0 deletions libs/nodejs/rxjs/docs/operators/array/array-operators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Array Operators

`rxjs-utils` provides a series of common array operators as operators for ObservableArrays.

These are analogue to the existing array operators.

## mapArray

```typescript
import { mapArray } from '@studiohyperdrive/rxjs-utils';

of(['a', 'b'])
.pipe(mapArray((item) => ({ item })))
.subscribe((result) => {
// => result: [{item: 'a'}, {item: 'b'}]
});
```

## sliceArray

```typescript
import { sliceArray } from '@studiohyperdrive/rxjs-utils';

of(['a', 'b', 'c'])
.pipe(sliceArray(0, 2))
.subscribe((result) => {
// => result: ['a', 'b']
});
```

## sortArray

```typescript
import { sortArray } from '@studiohyperdrive/rxjs-utils';

of(['a', 'c', 'b'])
.pipe(sortArray((a, b) => a.localeCompare(b)))
.subscribe((result) => {
// => result: ['a', 'b', 'c']
});
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# catchAndCallThrough

The catchAndCallThrough operator will enrich the catchError operator with a return of the error.

It expects a callback function.

## How to use

```typescript
import { catchAndCallThrough } from "@studiohyperdrive/rxjs-utils";
import { throwError } from "rxjs";

of(throwError('Something went wrong'))
.pipe(
catchAndCallThrough((error) => {
console.log({ error });
})
)
.subscribe(() => {
// The subscription will still be triggered.
});
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# combineBooleans

Combines a series of ObservableBooleans using 'AND' and returns a single ObservableBoolean.

It expects an array of `Observable<boolean>`.

## How to use

```typescript
import { combineBooleans } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

combineBooleans([
of(true),
of(false)
])
.subscribe((result) => {
// => result: true
});
```
22 changes: 22 additions & 0 deletions libs/nodejs/rxjs/docs/operators/fetch-if/fetch-if.operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# fetchIf

`fetchIf` is an operator that will search for a value through a provided source, and if the value is can be found, will return it. If the value cannot be found, the provided fetch method will be run and the result of said method will be returned.

Aside from a source observable, the `fetchIf` method requires a `search` function that will be used to search for the requested value and a `fetch` function that will be run when the `search` returns `undefined`.

A common use-case for `fetchIf` is to check whether a property already exists within the current state of the application, and when not found it can use an API call to fetch it instead.

## How to use

```typescript
import { fetchIf } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

fetchIf(
of([{ id: 'hello' }]),
(data) => data.find((item) => item.id === 'world'),
() => of({ id: 'world' })
).subscribe((result) => {
// => result: {id: 'world'}
});

16 changes: 16 additions & 0 deletions libs/nodejs/rxjs/docs/operators/pluck-or/pluck-or.operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# pluckOr

Selects a property from a provided Observable value if exists and emits the property. If the property does not exist, the operator will select the next provided property.

## How to use

```typescript
import { pluckOr } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

of({name: undefined, firstName: 'Hello'})
.pipe(pluckOr('name', 'firstName'))
.subscribe((result) => {
// => result: Hello
});
```
16 changes: 16 additions & 0 deletions libs/nodejs/rxjs/docs/operators/pluck/pluck.operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# pluck

Selects a property from the provided Observable value and emits the property

## How to use

```typescript
import { pluck } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

of({name: 'World', firstName: 'Hello'})
.pipe(pluck('name'))
.subscribe((result) => {
// => result: World
});
```
22 changes: 22 additions & 0 deletions libs/nodejs/rxjs/docs/operators/populate/populate.operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# populate

Populates the missing values within data provided by observables provided in a key-based record.

It expects a record of Observables that match with the keys of the object. An optional matching function can be presented to define when data should be populated

## How to use

```typescript
import { populate } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

of({hello: 'world'}).pipe(
populate({
world: () => of('hello'),
'foo.bar': (data) => of(data.hello)
})
)
.subscribe((result) => {
// => result: {hello: 'world', world: 'hello', foo: {bar: 'world'}}
});
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# validateContent

The following custom operator can be used to validate if content in the stream is valid.

It will, by default, check for `null` or `undefined`.
If strict is set to `false`, it will also allow falsy content to pass the check.

A `customValidatorFn` can be passed which will overwrite the internal checks with custom validation logic.

## How to use

### Strict
```typescript
import { validateContent } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

of(undefined)
.pipe(
validateContent()
)
.subscribe((result) => {
// => will not be triggered
});

of(0)
.pipe(
validateContent()
)
.subscribe((result) => {
// => will be triggered
});
```

### Non-strict
```typescript
import { validateContent } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

of(undefined)
.pipe(
validateContent({ strict: false })
)
.subscribe((result) => {
// => will not be triggered
});

of(0)
.pipe(
validateContent({ strict: false })
)
.subscribe((result) => {
// => will not be triggered
});
```

### With custom comparator

The `strict` flag will be ignored when adding a `customValidatorFn`.

```typescript
import { validateContent } from "@studiohyperdrive/rxjs-utils";
import { of } from "rxjs";

of(0)
.pipe(
validateContent({}, (value: number): boolean => {
return value === 2;
})
)
.subscribe((result) => {
// => will not be triggered
});

of(2)
.pipe(
validateContent({}, (value: number): boolean => {
return value === 2;
})
)
.subscribe((result) => {
// => will be triggered
});
```
47 changes: 47 additions & 0 deletions libs/nodejs/rxjs/docs/types/observable/observable.types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Observable types

A collection of interfaces that extend the default Observable.

## Interfaces
### ObservableBoolean
```typescript
type ObservableBoolean = Observable<boolean>;
```

### ObservableArray
```typescript
type ObservableArray<T> = Observable<T[]>;
```

### ObservableString
```typescript
type ObservableString = Observable<string>;
```

### ObservableNumber
```typescript
type ObservableNumber = Observable<number>;
```

### ObservableRecord
```typescript
type ObservableRecord<DataType, DataId extends string | symbol | number = string> = Observable<
Record<DataId, DataType>
>;
```

### ObservableBooleanRecord
```typescript
type BooleanRecord = Record<string, boolean>;
type ObservableBooleanRecord = Observable<BooleanRecord>;
```

### ObservableBlob
```typescript
type ObservableBlob = Observable<{ fileType: string; blob: Blob }>;
```

### ObservableStringRecord
```typescript
type ObservableStringRecord<ValueType> = Observable<Record<string, ValueType>>;
```
Loading