Skip to content

Commit 07ff80b

Browse files
feat(maybe): add a function to convert maybe to an rxjs observable (#128)
* feat(maybe): add a function to convert maybe to an rxjs observable * chore: update package-lock
1 parent ceda9ec commit 07ff80b

File tree

8 files changed

+249
-98
lines changed

8 files changed

+249
-98
lines changed

package-lock.json

Lines changed: 158 additions & 94 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@
3939
"@types/jest": "^25.1.3",
4040
"@types/node": "^13.7.4",
4141
"codecov": "^3.6.5",
42+
"fast-check": "^1.22.2",
4243
"fs-extra": "^8.1.0",
4344
"istanbul": "^0.4.5",
4445
"jest": "25.1.0",
4546
"jest-junit": "^10.0.0",
4647
"rollup": "^1.31.1",
48+
"rxjs": "^6.5.4",
4749
"semantic-release": "^17.0.4",
4850
"terser": "^4.6.3",
4951
"ts-jest": "^25.2.1",
@@ -53,7 +55,8 @@
5355
"typescript": "^3.7.5"
5456
},
5557
"peerDependencies": {
56-
"tslib": "^1.11.0"
58+
"tslib": "^1.11.0",
59+
"rxjs": "^6.0"
5760
},
5861
"jest": {
5962
"testURL": "http://localhost",

rollup.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,26 @@ export default [
88
name: 'monads',
99
file: `dist/${pkg.main}`,
1010
format: 'umd',
11+
globals: {
12+
rxjs: 'rxjs',
13+
'rxjs/operators': 'rxjs/operators'
14+
},
1115
sourcemap: true
1216
},
17+
external: [
18+
'rxjs',
19+
'rxjs/operators'
20+
]
1321
},
1422
{
1523
input: 'src/index.ts',
1624
output: [
1725
{ file: `dist/${pkg.module}`, format: 'es', sourcemap: true },
1826
{ file: `dist/${pkg.commonJs}`, format: 'cjs', sourcemap: true }
1927
],
28+
external: [
29+
'rxjs',
30+
'rxjs/operators'
31+
],
2032
plugins: [typescript()]
2133
}]

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
export * from './monads/index'
22
export * from './interfaces/index'
3+
export {
4+
maybeToObservable
5+
} from './util/index'

src/util/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ export {
66
curry5,
77
curry6,
88
curry7
9-
} from './curry'
9+
} from './curry'
10+
export {
11+
maybeToObservable
12+
} from './maybe/maybe-to-observable'

src/util/maybe-env.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { reader, maybe } from '..'
1+
import { reader, maybe } from '../monads/index'
22

33
export interface GetFromEnvironmentReader {
44
readEnv(key: string): string | undefined
@@ -15,4 +15,4 @@ const maybeFromEnvReader = (key: string) => (reader: GetFromEnvironmentReader) =
1515
export function maybeEnv(key: string, config?: GetFromEnvironmentReader) {
1616
return reader(maybeFromEnvReader(key))
1717
.run(maybe(config).valueOr(DEFAULT_NODE_ENV_READER))
18-
}
18+
}

src/util/maybe/maybe-to-observable.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { IMaybe } from '../../interfaces'
2+
import { EMPTY, Observable, of } from 'rxjs'
3+
import { take } from 'rxjs/operators'
4+
5+
/**
6+
* Convert a Maybe into an observable
7+
*
8+
* If the Maybe is empty, the observable will immediately complete without emitting a value, otherwise it will emit
9+
* the value contained and complete.
10+
*
11+
* @requires rxjs@^6.0
12+
* @example
13+
* of(maybe(5)).pipe(
14+
* flatMap(maybeToObservable)
15+
* ).subscribe(a => console.log(a))
16+
* // prints 5 and completes
17+
*
18+
* of(maybe()).pipe(
19+
* flatMap(maybeToObservable)
20+
* ).subscribe(a => console.log(a))
21+
* // immediately completes with no emitted value
22+
*/
23+
export const maybeToObservable = <A>(m: IMaybe<A>): Observable<A> => {
24+
return m.isNone()
25+
? EMPTY
26+
: of(m.valueOrThrow('isNone returned false for empty IMaybe.'))
27+
.pipe(take(1))
28+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { assert, integer, property } from 'fast-check'
2+
import { maybe } from '../../../src/monads'
3+
import { maybeToObservable } from '../../../src/util'
4+
import { merge, of } from 'rxjs'
5+
import { count } from 'rxjs/operators'
6+
7+
describe('maybeToObservable', () => {
8+
const numRuns = 100
9+
it('emits a value when containing a value', () => {
10+
expect.assertions(numRuns)
11+
assert(
12+
property(
13+
integer(),
14+
a => {
15+
const m = maybe(a)
16+
const o = maybeToObservable(m)
17+
o.subscribe(val => expect(val).toBe(a))
18+
}
19+
), {
20+
numRuns
21+
}
22+
)
23+
})
24+
25+
it('immediately completes if there is no contained value', done => {
26+
27+
const m = maybe()
28+
const o = maybeToObservable(m)
29+
const c = of(1)
30+
31+
merge(o, c)
32+
.pipe(count())
33+
.subscribe(count => {
34+
expect(count).toBe(1)
35+
done()
36+
})
37+
})
38+
})

0 commit comments

Comments
 (0)