Compare commits
No commits in common. "de0160fd9e9d56cf856438b77d301abcbad5ce28" and "d88075c16997ad34163fc74b51229038866419f9" have entirely different histories.
de0160fd9e
...
d88075c169
154
src/either.ts
154
src/either.ts
@ -106,26 +106,6 @@ export class DoEither<T extends Record<string, unknown>, E> {
|
|||||||
return new DoEither(newEither)
|
return new DoEither(newEither)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a new value to the scope using a lazily evaluated Either
|
|
||||||
* @typeParam K - The key to bind to
|
|
||||||
* @typeParam A - The type of the value to bind
|
|
||||||
* @param key - The property name to bind to
|
|
||||||
* @param f - Function returning the Either value to bind (receives current scope)
|
|
||||||
* @returns A new DoEither instance with the extended scope
|
|
||||||
*/
|
|
||||||
bindL<K extends string, A>(
|
|
||||||
key: K,
|
|
||||||
f: (scope: T) => Either<A, E>,
|
|
||||||
): DoEither<T & Record<K, A>, E> {
|
|
||||||
const newEither = eitherChain<T, T & Record<K, A>, E>((scope: T) =>
|
|
||||||
eitherMap<A, T & Record<K, A>, E>((a: A) => ({...scope, [key]: a}))(
|
|
||||||
f(scope),
|
|
||||||
)
|
|
||||||
)(this.either)
|
|
||||||
return new DoEither(newEither)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the final result from the scope
|
* Returns the final result from the scope
|
||||||
* @typeParam B - The return type
|
* @typeParam B - The return type
|
||||||
@ -176,137 +156,3 @@ export class DoEither<T extends Record<string, unknown>, E> {
|
|||||||
return new DoEither(right({}))
|
return new DoEither(right({}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for working with Either in a do-notation style with asynchronous computations
|
|
||||||
* @typeParam T - The type of the accumulated scope
|
|
||||||
* @typeParam E - The error type
|
|
||||||
*/
|
|
||||||
export class AsyncDoEither<T extends Record<string, unknown>, E> {
|
|
||||||
/**
|
|
||||||
* @param promise - The current Promise of an Either value
|
|
||||||
*/
|
|
||||||
constructor(private readonly promise: Promise<Either<T, E>>) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a new value to the scope synchronously
|
|
||||||
* @typeParam K - The key to bind to
|
|
||||||
* @typeParam A - The type of the value to bind
|
|
||||||
* @param key - The property name to bind to
|
|
||||||
* @param fa - The Either value to bind
|
|
||||||
* @returns A new AsyncDoEither instance with the extended scope
|
|
||||||
*/
|
|
||||||
bind<K extends string, A>(
|
|
||||||
key: K,
|
|
||||||
fa: Either<A, E>,
|
|
||||||
): AsyncDoEither<T & Record<K, A>, E> {
|
|
||||||
return this.bindL(key, () => fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a new value to the scope asynchronously
|
|
||||||
* @typeParam K - The key to bind to
|
|
||||||
* @typeParam A - The type of the value to bind
|
|
||||||
* @param key - The property name to bind to
|
|
||||||
* @param f - Function returning Either or Promise of Either
|
|
||||||
* @returns A new AsyncDoEither instance with the extended scope
|
|
||||||
*/
|
|
||||||
bindL<K extends string, A>(
|
|
||||||
key: K,
|
|
||||||
f: (scope: T) => Either<A, E> | Promise<Either<A, E>>,
|
|
||||||
): AsyncDoEither<T & Record<K, A>, E> {
|
|
||||||
const newPromise = this.promise.then(async (currentEither) => {
|
|
||||||
if (isLeft(currentEither)) {
|
|
||||||
return currentEither as unknown as Either<T & Record<K, A>, E>
|
|
||||||
}
|
|
||||||
|
|
||||||
const scope = currentEither.right
|
|
||||||
try {
|
|
||||||
const nextEither = await f(scope)
|
|
||||||
|
|
||||||
if (isLeft(nextEither)) {
|
|
||||||
return nextEither as unknown as Either<T & Record<K, A>, E>
|
|
||||||
}
|
|
||||||
|
|
||||||
return right({
|
|
||||||
...scope,
|
|
||||||
[key]: nextEither.right,
|
|
||||||
}) as Either<T & Record<K, A>, E>
|
|
||||||
} catch (err) {
|
|
||||||
return left(err as E) as Either<T & Record<K, A>, E>
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return new AsyncDoEither(newPromise)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the final result from the scope
|
|
||||||
* @typeParam B - The return type
|
|
||||||
* @param f - The function to transform the scope
|
|
||||||
* @returns A Promise of Either containing the result
|
|
||||||
*/
|
|
||||||
return<B>(f: (scope: T) => B): Promise<Either<B, E>> {
|
|
||||||
return this.promise.then(either => {
|
|
||||||
if (isLeft(either)) {
|
|
||||||
return either as unknown as Either<B, E>
|
|
||||||
}
|
|
||||||
return right(f(either.right))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current scope
|
|
||||||
* @returns A Promise of the current Either scope
|
|
||||||
*/
|
|
||||||
done(): Promise<Either<T, E>> {
|
|
||||||
return this.promise
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes an effect without modifying the scope
|
|
||||||
* @param fa - The Either effect to execute
|
|
||||||
* @returns A new AsyncDoEither instance with the same scope
|
|
||||||
*/
|
|
||||||
do(fa: Either<unknown, E>): AsyncDoEither<T, E> {
|
|
||||||
return this.doL(() => fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes an effect that depends on the current scope
|
|
||||||
* @param f - Function returning Either or Promise of Either
|
|
||||||
* @returns A new AsyncDoEither instance with the same scope
|
|
||||||
*/
|
|
||||||
doL(f:
|
|
||||||
(scope: T) =>
|
|
||||||
| Either<unknown, E>
|
|
||||||
| Promise<Either<unknown, E>>): AsyncDoEither<T, E>
|
|
||||||
{
|
|
||||||
const newPromise = this.promise.then(async (currentEither) => {
|
|
||||||
if (isLeft(currentEither)) {
|
|
||||||
return currentEither
|
|
||||||
}
|
|
||||||
|
|
||||||
const scope = currentEither.right
|
|
||||||
try {
|
|
||||||
const effectEither = await f(scope)
|
|
||||||
if (isLeft(effectEither)) {
|
|
||||||
return effectEither as unknown as Either<T, E>
|
|
||||||
}
|
|
||||||
return currentEither
|
|
||||||
} catch (err) {
|
|
||||||
return left(err as E)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return new AsyncDoEither(newPromise)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a new AsyncDoEither chain with an empty scope
|
|
||||||
* @returns A new AsyncDoEither instance with an empty scope
|
|
||||||
*/
|
|
||||||
static start<E>(): AsyncDoEither<{}, E> {
|
|
||||||
return new AsyncDoEither(Promise.resolve(right({})))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user