Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/koheing/stream-executor
functional stream programming library
https://github.com/koheing/stream-executor
functional-programming library typescript
Last synced: 8 days ago
JSON representation
functional stream programming library
- Host: GitHub
- URL: https://github.com/koheing/stream-executor
- Owner: koheing
- License: mit
- Created: 2020-02-27T12:28:12.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T02:45:57.000Z (almost 2 years ago)
- Last Synced: 2024-04-25T05:02:53.013Z (7 months ago)
- Topics: functional-programming, library, typescript
- Language: TypeScript
- Homepage:
- Size: 555 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# stream-executor
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
![Main](https://github.com/nor-ko-hi-jp/stream-executor/workflows/Main/badge.svg)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/nor-ko-hi-jp/stream-executor/issues)- functional stream programming library
- This library is inspired by [RxJS](https://github.com/ReactiveX/rxjs)
- This library is effective for
- managing and reusing processes in actions in fine-grained
- the processing in the action becomes complicated
- asynchronous execution sequentially```
npm i stream-executor
```# Usage
## 1. chain stream (like RxJS)
### using stream-executor
```ts
import { createStream, map, which, filter, tap } from 'stream-executor'
let isSucceeded = falseconst chainResult = createStream(1)
.chain(
map((it) => it * 10),
which(
(it) => it > 1,
tap((it) => (isSucceeded = true)),
tap((it) => console.log('not succeeded'))
),
filter((it) => it >= 10)
)
.execute()console.log(isSucceeded) // true
console.log(chainResult) // 10
```### Not using stream-executor
```ts
let isSucceeded = falseconst initialValue = 1
let value = 0if (value >= 0) {
value = initialValue * 10
}if (value > 1) {
isSucceeded = true
} else {
console.log('not succeeded')
}if (value < 10) {
return
}
const result = valueconsole.log(isSucceeded) // true
console.log(result) // 10
```## 2. batch stream (like switch without break)
### using stream-executor
```ts
import { createStream, ifRight, which } from 'stream-executor'const mammal = { no: 999, name: 'UNKNOWN', type: 'bird' }
let isLoading = truecreateStream(mammal)
.batch(
(_) => (isLoading = true),
which(
({ type }) => type === 'bird',
(it) => calculateSize(it),
(_) => console.log('Not Bird')
),
ifRight(
({ type, name }) => type === 'bird' && name === 'UNKNOWN',
(mammal) => registerDB(mammal)
),
(_) => (isLoading = false),
(_) => console.log('end')
)
.execute()console.log(isLoading) // false
```### not using stream-executor
```ts
let isLoading: boolean
const mammal = { no: 999, name: 'UNKNOWN', type: 'bird' }isLoading = true
if (mammal.type === 'bird') {
calculateSize(mammal)
} else {
console.log('Not Bird')
}if (mammal.type == 'bird' && mammal.name !== 'UNKNOWN') {
console.log('maybe new species')
registerDB(mammal)
}isLoading = false
console.log('end')
console.log(isLoading) // false
```# 3. asyncChain stream
### using stream-executor
```ts
import { createStream, tap, map } from 'stream-executor'
const result = await createStream(1)
.asyncChain(
tap(async (it) => console.log(await it)), // 1
map(async (it) => await callAPI(it)),
map(async (it) => parseToModel(await it)) // Record
)
.execute()
console.log(result) // Record
```
### not using stream-executor
```ts
(async () => {
let result
const value = 1
result = await callAPI(value)
result = await parseToModel(result)
console.log(result)
})()
```# Important
## 1. About `createStream`
- The argument of createStream is not deep copied. use `deepCopy` method if you'd like to do deep copy, please.
```ts
import { createStream, tap, deepCopy } from 'stream-executor'
const input = { value: 1 }
const result = createStream(input)
.chain(tap((it) => (it.value += 9)))
.execute()console.log(input) // { value: 10 }
console.log(result) // { value: 10 }const input2 = { value: 1 }
const result2 = createStream(deepCopy(input2))
.chain(tap((it) => (it.value += 9)))
.execute()console.log(input2) // { value: 1 }
console.log(result2) // { value: 10 }
```
## 2. About `deepCopy`
- Getter and function in object are removed.
```ts
import { createStream, tap, deepCopy } from 'stream-executor'
class Wrapper {
value: T
constructor(value: T) {
this.value = value
}
get doubledValue() {
return this.value * 2
}
hello() {
console.log('world')
}
}
const input = new Wrapper(1)
const result = createStream(deepCopy(input))
.chain(tap((it) => (it.value += 9)))
.execute()console.log(input) // Wrapper{ value: 1, doubledValue: 2, __proto__: { hello: () => console.log('world') } }
console.log(result) // { value: 10, __proto__: {} }
```
## 3. About `createStream().chain()`:
- Further process is not called if `undefined` returned
```ts
import { createStream, tap, filter, map } from 'stream-executor'
const result = createStream(1)
.chain(
tap((it) => console.log(it)), // 1
filter((it) => it > 2), // return undefined
map((it) => it + 9) // not called
)
.execute()
console.log(result) // undefined
```## 4. Abount the arguments of execute()
- Set the arguments of execute method if you'd like to customize error handling, please
```ts
let error: any
createStream(1)
.batch(
(it) => console.log(it),
..
)
.execute((err: any) => {
console.error(error)
error = err
})
```## 5. Replace `chain` or `batch` executor
- Set `option.chainClass` or `option.batchClass` if you would change execution process, please
- These Classes are initialized with initialValue as an argument
```ts
import { BaseExecutor, createStream } from 'stream-executor'
class MockChainExecutor implements BaseExecutor {
constructor(public initialValue: any) {}
stream(...args: any[]) {
return this
}
execute() {
console.log('MockChainExecutor called')
}
}class MockBatchExecutor implements BaseExecutor {
constructor(public initialValue: any) {}
stream(...args: any[]) {
return this
}
execute() {
console.log('MockBatchExecutor called')
}
}createStream(1, { chainClass: MockChainExecutor })
.chain((it) => it)
.execute() // 'MockChainExecutor called'createStream(1, { batchClass: MockBatchExecutor })
.batch((it) => it)
.execute() // 'MockBatchExecutor called'
```
# Utils
## helper methods and those descriptions in createStream are
1. [map](./src/executors/helpers/index.ts#L1)
2. [tap](./src/executors/helpers/index.ts#L16)
3. [filter](./src/executors/helpers/index.ts#L31)
4. [which](./src/executors/helpers/index.ts#L46)
5. [ifRight](./src/executors/helpers/index.ts#L72)
6. [asTypeOf](./src/executors/helpers/index.ts#L97)
7. [asInstanceOf](./src/executors/helpers/index.ts#L120)
8. [stop](./src/executors/helpers/index.ts#L142)