Skip to content

Commit

Permalink
refactor: use classes (#137)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: library rewritten using classes to boost performance improve signatures.
  • Loading branch information
patrickmichalina authored May 16, 2020
1 parent a2f57bf commit c27939f
Show file tree
Hide file tree
Showing 58 changed files with 616 additions and 588 deletions.
2 changes: 2 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exclude_patterns:
- "**/*.spec.ts"
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) Patrick Michalina
Copyright (c) Patrick Michalina 2018

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
42 changes: 28 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 12 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"typings": "index.d.ts",
"sideEffects": false,
"author": "Patrick Michalina <[email protected]> (https://patrickmichalina.com)",
"contributors": [
"Williama Reynolds"
],
"license": "MIT",
"repository": {
"type": "git",
Expand Down Expand Up @@ -35,27 +38,27 @@
},
"devDependencies": {
"@rollup/plugin-typescript": "^3.1.1",
"@types/fs-extra": "^8.1.0",
"@types/jest": "^25.2.1",
"@types/fs-extra": "^9.0.0",
"@types/jest": "^25.2.2",
"@types/node": "^14.0.1",
"codecov": "^3.6.5",
"fast-check": "^1.24.2",
"fs-extra": "^9.0.0",
"istanbul": "^0.4.5",
"jest": "26.0.1",
"jest-junit": "^10.0.0",
"rollup": "^2.10.0",
"rollup": "^2.10.2",
"rxjs": "^6.5.4",
"semantic-release": "^17.0.7",
"terser": "^4.6.13",
"ts-jest": "^25.5.1",
"ts-jest": "^26.0.0",
"ts-node": "^8.10.1",
"tslint": "^6.1.2",
"tslint-immutable": "^6.0.1",
"typescript": "^3.9.2"
},
"peerDependencies": {
"tslib": "^1.12.0",
"tslib": "^2.0.0",
"rxjs": "^6.5"
},
"jest": {
Expand All @@ -70,7 +73,7 @@
"coverageThreshold": {
"global": {
"branches": 100,
"functions": 95,
"functions": 100,
"lines": 100,
"statements": 100
}
Expand All @@ -80,7 +83,8 @@
},
"testPathIgnorePatterns": [
"/node_modules/",
"/dist/"
"/dist/",
"public_api.ts"
],
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(ts?)$",
"moduleFileExtensions": [
Expand All @@ -92,4 +96,4 @@
"node"
]
}
}
}
22 changes: 11 additions & 11 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ export default [
]
},
{
input: 'src/index.ts',
output: [
{ file: `dist/${pkg.module}`, format: 'es', sourcemap: true },
{ file: `dist/${pkg.commonJs}`, format: 'cjs', sourcemap: true }
],
external: [
'rxjs',
'rxjs/operators'
],
plugins: [typescript()]
}]
input: 'src/index.ts',
output: [
{ file: `dist/${pkg.module}`, format: 'es', sourcemap: true },
{ file: `dist/${pkg.commonJs}`, format: 'cjs', sourcemap: true }
],
external: [
'rxjs',
'rxjs/operators'
],
plugins: [typescript()]
}]
5 changes: 5 additions & 0 deletions src/either/either.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Either } from './either'

export function either<L, R>(left?: L, right?: R) {
return new Either(left, right)
}
File renamed without changes.
2 changes: 1 addition & 1 deletion test/monads/either.spec.ts → src/either/either.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { either } from '../../src'
import { either } from './either.factory'

describe(either.name, () => {
it('when calling should throw if both sides are defined', () => {
Expand Down
56 changes: 56 additions & 0 deletions src/either/either.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { IEitherPattern, IEither } from './either.interface'

export class Either<L, R> implements IEither<L, R> {
constructor(private readonly left?: L, private readonly right?: R) {
if (this.neitherExist()) {
throw new TypeError('Either requires a left or a right')
}
if (this.bothExist()) {
throw new TypeError('Either cannot have both a left and a right')
}
}

private static exists<T>(value?: T): boolean {
return typeof value !== 'undefined' && value !== null
}

private bothExist(): boolean {
return this.isLeft() && this.isRight()
}

private neitherExist(): boolean {
return !this.isLeft() && !this.isRight()
}

public isLeft(): boolean {
return Either.exists(this.left)
}

public isRight(): boolean {
return Either.exists(this.right)
}

public match<T>(pattern: IEitherPattern<L, R, T>): T {
return this.isRight()
? pattern.right(this.right as R)
: pattern.left(this.left as L)
}

public tap<T>(pattern: Partial<IEitherPattern<L, R, T>>): void {
this.isRight()
? typeof pattern.right === 'function' && pattern.right(this.right as R)
: typeof pattern.left === 'function' && pattern.left(this.left as L)
}

public map<T>(fn: (r: R) => T): IEither<L, T> {
return this.isRight()
? new Either<L, T>(undefined, fn(this.right as R))
: new Either<L, T>(this.left)
}

public flatMap<T>(fn: (r: R) => IEither<L, T>): IEither<L, T> {
return this.isRight()
? fn(this.right as R)
: new Either<L, T>(this.left)
}
}
3 changes: 3 additions & 0 deletions src/either/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './either'
export * from './either.factory'
export * from './either.interface'
20 changes: 20 additions & 0 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { maybe, Maybe, either, Either, ok, fail, Result, reader, Reader } from './index'

describe('package api', () => {
it('should export maybe', () => {
expect(maybe(1)).toBeInstanceOf(Maybe)
})

it('should export either', () => {
expect(either(1)).toBeInstanceOf(Either)
})

it('should export result', () => {
expect(ok(1)).toBeInstanceOf(Result)
expect(fail(1)).toBeInstanceOf(Result)
})

it('should export reader', () => {
expect(reader(_cfg => 1)).toBeInstanceOf(Reader)
})
})
10 changes: 5 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './monads/index'
export * from './interfaces/index'
export {
maybeToObservable
} from './util/index'
export * from './maybe/public_api'
export * from './reader/public_api'
export * from './either/public_api'
export * from './result/public_api'
export * from './monad/public_api'
4 changes: 0 additions & 4 deletions src/interfaces/index.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/interfaces/monad.interface.ts

This file was deleted.

6 changes: 0 additions & 6 deletions src/interfaces/reader.interface.ts

This file was deleted.

Empty file removed src/interfaces/result.interface.ts
Empty file.
16 changes: 16 additions & 0 deletions src/maybe/maybe.factory.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { maybe, none, some } from './maybe.factory'

describe('should construct maybes', () => {
it('should handle "maybe" case', () => {
const sut = 'asdasd' as string | undefined
expect(maybe(sut).isSome()).toEqual(true)
})

it('should handle "none" case', () => {
expect(none().isNone()).toEqual(true)
})

it('should handle "some" case', () => {
expect(some('test').isSome()).toEqual(true)
})
})
13 changes: 13 additions & 0 deletions src/maybe/maybe.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Maybe } from './maybe'

export function maybe<T>(value?: T) {
return new Maybe<T>(value)
}

export function none<T>() {
return Maybe.none<T>()
}

export function some<T>(value: T) {
return maybe(value)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IMonad } from './monad.interface'
import { IMonad } from '../monad/monad.interface'

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

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

/**
* Unwrap a Maybe with a default value
Expand Down Expand Up @@ -96,7 +96,7 @@ export interface IMaybe<T> extends IMonad<T> {
/**
* Combine multiple Maybe, automatically wrapping predicate
*/
flatMapAuto<R>(f: (t: T) => R): IMaybe<NonNullable<R>>
flatMapAuto<R>(fn: (v: T) => R): IMaybe<NonNullable<R>>

/**
* Apply a predicate which if met, continues the Maybe chain,
Expand Down
Loading

0 comments on commit c27939f

Please sign in to comment.