Skip to content

Commit c27939f

Browse files
refactor: use classes (#137)
BREAKING CHANGE: library rewritten using classes to boost performance improve signatures.
1 parent a2f57bf commit c27939f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+616
-588
lines changed

.codeclimate.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exclude_patterns:
2+
- "**/*.spec.ts"

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License
22

3-
Copyright (c) Patrick Michalina
3+
Copyright (c) Patrick Michalina 2018
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

package-lock.json

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

package.json

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
"typings": "index.d.ts",
99
"sideEffects": false,
1010
"author": "Patrick Michalina <patrickmichalina@mac.com> (https://patrickmichalina.com)",
11+
"contributors": [
12+
"Williama Reynolds"
13+
],
1114
"license": "MIT",
1215
"repository": {
1316
"type": "git",
@@ -35,27 +38,27 @@
3538
},
3639
"devDependencies": {
3740
"@rollup/plugin-typescript": "^3.1.1",
38-
"@types/fs-extra": "^8.1.0",
39-
"@types/jest": "^25.2.1",
41+
"@types/fs-extra": "^9.0.0",
42+
"@types/jest": "^25.2.2",
4043
"@types/node": "^14.0.1",
4144
"codecov": "^3.6.5",
4245
"fast-check": "^1.24.2",
4346
"fs-extra": "^9.0.0",
4447
"istanbul": "^0.4.5",
4548
"jest": "26.0.1",
4649
"jest-junit": "^10.0.0",
47-
"rollup": "^2.10.0",
50+
"rollup": "^2.10.2",
4851
"rxjs": "^6.5.4",
4952
"semantic-release": "^17.0.7",
5053
"terser": "^4.6.13",
51-
"ts-jest": "^25.5.1",
54+
"ts-jest": "^26.0.0",
5255
"ts-node": "^8.10.1",
5356
"tslint": "^6.1.2",
5457
"tslint-immutable": "^6.0.1",
5558
"typescript": "^3.9.2"
5659
},
5760
"peerDependencies": {
58-
"tslib": "^1.12.0",
61+
"tslib": "^2.0.0",
5962
"rxjs": "^6.5"
6063
},
6164
"jest": {
@@ -70,7 +73,7 @@
7073
"coverageThreshold": {
7174
"global": {
7275
"branches": 100,
73-
"functions": 95,
76+
"functions": 100,
7477
"lines": 100,
7578
"statements": 100
7679
}
@@ -80,7 +83,8 @@
8083
},
8184
"testPathIgnorePatterns": [
8285
"/node_modules/",
83-
"/dist/"
86+
"/dist/",
87+
"public_api.ts"
8488
],
8589
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(ts?)$",
8690
"moduleFileExtensions": [
@@ -92,4 +96,4 @@
9296
"node"
9397
]
9498
}
95-
}
99+
}

rollup.config.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ export default [
2020
]
2121
},
2222
{
23-
input: 'src/index.ts',
24-
output: [
25-
{ file: `dist/${pkg.module}`, format: 'es', sourcemap: true },
26-
{ file: `dist/${pkg.commonJs}`, format: 'cjs', sourcemap: true }
27-
],
28-
external: [
29-
'rxjs',
30-
'rxjs/operators'
31-
],
32-
plugins: [typescript()]
33-
}]
23+
input: 'src/index.ts',
24+
output: [
25+
{ file: `dist/${pkg.module}`, format: 'es', sourcemap: true },
26+
{ file: `dist/${pkg.commonJs}`, format: 'cjs', sourcemap: true }
27+
],
28+
external: [
29+
'rxjs',
30+
'rxjs/operators'
31+
],
32+
plugins: [typescript()]
33+
}]

src/either/either.factory.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Either } from './either'
2+
3+
export function either<L, R>(left?: L, right?: R) {
4+
return new Either(left, right)
5+
}
File renamed without changes.

test/monads/either.spec.ts renamed to src/either/either.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { either } from '../../src'
1+
import { either } from './either.factory'
22

33
describe(either.name, () => {
44
it('when calling should throw if both sides are defined', () => {

src/either/either.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { IEitherPattern, IEither } from './either.interface'
2+
3+
export class Either<L, R> implements IEither<L, R> {
4+
constructor(private readonly left?: L, private readonly right?: R) {
5+
if (this.neitherExist()) {
6+
throw new TypeError('Either requires a left or a right')
7+
}
8+
if (this.bothExist()) {
9+
throw new TypeError('Either cannot have both a left and a right')
10+
}
11+
}
12+
13+
private static exists<T>(value?: T): boolean {
14+
return typeof value !== 'undefined' && value !== null
15+
}
16+
17+
private bothExist(): boolean {
18+
return this.isLeft() && this.isRight()
19+
}
20+
21+
private neitherExist(): boolean {
22+
return !this.isLeft() && !this.isRight()
23+
}
24+
25+
public isLeft(): boolean {
26+
return Either.exists(this.left)
27+
}
28+
29+
public isRight(): boolean {
30+
return Either.exists(this.right)
31+
}
32+
33+
public match<T>(pattern: IEitherPattern<L, R, T>): T {
34+
return this.isRight()
35+
? pattern.right(this.right as R)
36+
: pattern.left(this.left as L)
37+
}
38+
39+
public tap<T>(pattern: Partial<IEitherPattern<L, R, T>>): void {
40+
this.isRight()
41+
? typeof pattern.right === 'function' && pattern.right(this.right as R)
42+
: typeof pattern.left === 'function' && pattern.left(this.left as L)
43+
}
44+
45+
public map<T>(fn: (r: R) => T): IEither<L, T> {
46+
return this.isRight()
47+
? new Either<L, T>(undefined, fn(this.right as R))
48+
: new Either<L, T>(this.left)
49+
}
50+
51+
public flatMap<T>(fn: (r: R) => IEither<L, T>): IEither<L, T> {
52+
return this.isRight()
53+
? fn(this.right as R)
54+
: new Either<L, T>(this.left)
55+
}
56+
}

src/either/public_api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './either'
2+
export * from './either.factory'
3+
export * from './either.interface'

src/index.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { maybe, Maybe, either, Either, ok, fail, Result, reader, Reader } from './index'
2+
3+
describe('package api', () => {
4+
it('should export maybe', () => {
5+
expect(maybe(1)).toBeInstanceOf(Maybe)
6+
})
7+
8+
it('should export either', () => {
9+
expect(either(1)).toBeInstanceOf(Either)
10+
})
11+
12+
it('should export result', () => {
13+
expect(ok(1)).toBeInstanceOf(Result)
14+
expect(fail(1)).toBeInstanceOf(Result)
15+
})
16+
17+
it('should export reader', () => {
18+
expect(reader(_cfg => 1)).toBeInstanceOf(Reader)
19+
})
20+
})

src/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
export * from './monads/index'
2-
export * from './interfaces/index'
3-
export {
4-
maybeToObservable
5-
} from './util/index'
1+
export * from './maybe/public_api'
2+
export * from './reader/public_api'
3+
export * from './either/public_api'
4+
export * from './result/public_api'
5+
export * from './monad/public_api'

src/interfaces/index.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/interfaces/monad.interface.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/interfaces/reader.interface.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/interfaces/result.interface.ts

Whitespace-only changes.

src/maybe/maybe.factory.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { maybe, none, some } from './maybe.factory'
2+
3+
describe('should construct maybes', () => {
4+
it('should handle "maybe" case', () => {
5+
const sut = 'asdasd' as string | undefined
6+
expect(maybe(sut).isSome()).toEqual(true)
7+
})
8+
9+
it('should handle "none" case', () => {
10+
expect(none().isNone()).toEqual(true)
11+
})
12+
13+
it('should handle "some" case', () => {
14+
expect(some('test').isSome()).toEqual(true)
15+
})
16+
})

src/maybe/maybe.factory.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Maybe } from './maybe'
2+
3+
export function maybe<T>(value?: T) {
4+
return new Maybe<T>(value)
5+
}
6+
7+
export function none<T>() {
8+
return Maybe.none<T>()
9+
}
10+
11+
export function some<T>(value: T) {
12+
return maybe(value)
13+
}

src/interfaces/maybe.interface.ts renamed to src/maybe/maybe.interface.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IMonad } from './monad.interface'
1+
import { IMonad } from '../monad/monad.interface'
22

33
/**
44
* Define a contract to unwrap Maybe object
@@ -21,7 +21,7 @@ export interface IMaybePattern<TIn, TOut> {
2121
export interface IMaybe<T> extends IMonad<T> {
2222

2323
// tslint:disable-next-line:readonly-array
24-
of(x?: T, ...args: any[]): IMaybe<T>
24+
of(x: T, ...args: any[]): IMaybe<T>
2525

2626
/**
2727
* Unwrap a Maybe with a default value
@@ -96,7 +96,7 @@ export interface IMaybe<T> extends IMonad<T> {
9696
/**
9797
* Combine multiple Maybe, automatically wrapping predicate
9898
*/
99-
flatMapAuto<R>(f: (t: T) => R): IMaybe<NonNullable<R>>
99+
flatMapAuto<R>(fn: (v: T) => R): IMaybe<NonNullable<R>>
100100

101101
/**
102102
* Apply a predicate which if met, continues the Maybe chain,

0 commit comments

Comments
 (0)