Skip to content

Commit

Permalink
Merge branch 'master' of github.com:selfrefactor/rambda into 8.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Deyan Totev committed Aug 20, 2023
2 parents 4476082 + daae49b commit 14035af
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 105 deletions.
159 changes: 132 additions & 27 deletions files/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3481,8 +3481,8 @@ Notes: It passes index of the list as third argument to `reducer` function.
// @SINGLE_MARKER
export function reduce<T, TResult>(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult, list: T[]): TResult;
export function reduce<T, TResult>(reducer: (prev: TResult, current: T) => TResult, initialValue: TResult, list: T[]): TResult;
export function reduce<T, TResult>(reducer: (prev: TResult, current: T, i?: number) => TResult): (initialValue: TResult, list: T[]) => TResult;
export function reduce<T, TResult>(reducer: (prev: TResult, current: T, i?: number) => TResult, initialValue: TResult): (list: T[]) => TResult;
export function reduce<T, TResult>(reducer: (prev: TResult, current: T, i: number) => TResult): (initialValue: TResult, list: T[]) => TResult;
export function reduce<T, TResult>(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult): (list: T[]) => TResult;

/*
Method: reject
Expand Down Expand Up @@ -5733,7 +5733,7 @@ export function anyType(targetType: RambdaTypes): (...input: any[]) => boolean;
/*
Method: composeAsync
Explanation: Asynchronous version of `R.compose`
Explanation: Asynchronous version of `R.compose`. `await`s the result of each function before passing it to the next. Returns a `Promise` of the result.
Example:
Expand All @@ -5756,21 +5756,77 @@ const result = await R.composeAsync(
Categories: Logic, Async
Notes: It doesn't work with promises or function returning promises such as `const foo = input => new Promise(...)`.
*/
// @SINGLE_MARKER
export function composeAsync<Out>(
...fns: (Async<any> | Func<any>)[]
): (input: any) => Promise<Out>;
export function composeAsync<Out>(
...fns: (Async<any> | Func<any>)[]
): (input: any) => Promise<Out>;
export function composeAsync<TArg, R1, R2, R3, R4, R5, R6, R7, TResult>(
...func: [
fnLast: (a: any) => TResult,
...func: Array<(a: any) => any>,
f7: (a: Awaited<R6>) => R7,
f6: (a: Awaited<R5>) => R6,
f5: (a: Awaited<R4>) => R5,
f4: (a: Awaited<R3>) => R4,
f3: (a: Awaited<R2>) => R3,
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
]
): (a: TArg | Promise<TArg>) => TResult; // fallback overload if number of composed functions greater than 7
export function composeAsync<TArg, R1, R2, R3, R4, R5, R6, R7, TResult>(
f7: (a: Awaited<R6>) => R7,
f6: (a: Awaited<R5>) => R6,
f5: (a: Awaited<R4>) => R5,
f4: (a: Awaited<R3>) => R4,
f3: (a: Awaited<R2>) => R3,
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R7;
export function composeAsync<TArg, R1, R2, R3, R4, R5, R6, R7>(
f7: (a: Awaited<R6>) => R7,
f6: (a: Awaited<R5>) => R6,
f5: (a: Awaited<R4>) => R5,
f4: (a: Awaited<R3>) => R4,
f3: (a: Awaited<R2>) => R3,
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R7;
export function composeAsync<TArg, R1, R2, R3, R4, R5, R6>(
f6: (a: Awaited<R5>) => R6,
f5: (a: Awaited<R4>) => R5,
f4: (a: Awaited<R3>) => R4,
f3: (a: Awaited<R2>) => R3,
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R6;
export function composeAsync<TArg, R1, R2, R3, R4, R5>(
f5: (a: Awaited<R4>) => R5,
f4: (a: Awaited<R3>) => R4,
f3: (a: Awaited<R2>) => R3,
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R5;
export function composeAsync<TArg, R1, R2, R3, R4>(
f4: (a: Awaited<R3>) => R4,
f3: (a: Awaited<R2>) => R3,
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R4;
export function composeAsync<TArg, R1, R2, R3>(
f3: (a: Awaited<R2>) => R3,
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R3;
export function composeAsync<TArg, R1, R2>(
f2: (a: Awaited<R1>) => R2,
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R2;
export function composeAsync<TArg, R1>(
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R1;

/*
Method: pipeAsync
Explanation: Asynchronous version of `R.pipe`
Explanation: Asynchronous version of `R.pipe`. `await`s the result of each function before passing it to the next. Returns a `Promise` of the result.
Example:
Expand All @@ -5793,16 +5849,63 @@ const result = await R.pipeAsync(
Categories: Logic, Async
Notes: It doesn't work with promises or function returning promises such as `const foo = input => new Promise(...)`.
*/
// @SINGLE_MARKER
export function pipeAsync<Out>(
...fns: (Async<any> | Func<any>)[]
): (input: any) => Promise<Out>;
export function pipeAsync<Out>(
...fns: (Async<any> | Func<any>)[]
): (input: any) => Promise<Out>;
export function pipeAsync<TArg, R1, R2, R3, R4, R5, R6, R7, TResult>(
...funcs: [
f1: (a: Awaited<TArg>) => R1,
f2: (a: Awaited<R1>) => R2,
f3: (a: Awaited<R2>) => R3,
f4: (a: Awaited<R3>) => R4,
f5: (a: Awaited<R4>) => R5,
f6: (a: Awaited<R5>) => R6,
f7: (a: Awaited<R6>) => R7,
...func: Array<(a: any) => any>,
fnLast: (a: any) => TResult
]
): (a: TArg | Promise<TArg>) => TResult; // fallback overload if number of piped functions greater than 7
export function pipeAsync<TArg, R1, R2, R3, R4, R5, R6, R7>(
f1: (a: Awaited<TArg>) => R1,
f2: (a: Awaited<R1>) => R2,
f3: (a: Awaited<R2>) => R3,
f4: (a: Awaited<R3>) => R4,
f5: (a: Awaited<R4>) => R5,
f6: (a: Awaited<R5>) => R6,
f7: (a: Awaited<R6>) => R7
): (a: TArg | Promise<TArg>) => R7;
export function pipeAsync<TArg, R1, R2, R3, R4, R5, R6>(
f1: (a: Awaited<TArg>) => R1,
f2: (a: Awaited<R1>) => R2,
f3: (a: Awaited<R2>) => R3,
f4: (a: Awaited<R3>) => R4,
f5: (a: Awaited<R4>) => R5,
f6: (a: Awaited<R5>) => R6
): (a: TArg | Promise<TArg>) => R6;
export function pipeAsync<TArg, R1, R2, R3, R4, R5>(
f1: (a: Awaited<TArg>) => R1,
f2: (a: Awaited<R1>) => R2,
f3: (a: Awaited<R2>) => R3,
f4: (a: Awaited<R3>) => R4,
f5: (a: Awaited<R4>) => R5
): (a: TArg | Promise<TArg>) => R5;
export function pipeAsync<TArg, R1, R2, R3, R4>(
f1: (a: Awaited<TArg>) => R1,
f2: (a: Awaited<R1>) => R2,
f3: (a: Awaited<R2>) => R3,
f4: (a: Awaited<R3>) => R4
): (a: TArg | Promise<TArg>) => R4;
export function pipeAsync<TArg, R1, R2, R3>(
f1: (a: Awaited<TArg>) => R1,
f2: (a: Awaited<R1>) => R2,
f3: (a: Awaited<R2>) => R3
): (a: TArg | Promise<TArg>) => R3;
export function pipeAsync<TArg, R1, R2>(
f1: (a: Awaited<TArg>) => R1,
f2: (a: Awaited<R1>) => R2
): (a: TArg | Promise<TArg>) => R2;
export function pipeAsync<TArg, R1>(
f1: (a: Awaited<TArg>) => R1
): (a: TArg | Promise<TArg>) => R1;

/*
Method: debounce
Expand Down Expand Up @@ -6578,7 +6681,7 @@ export function piped<A, B, C, D, E, F, G, H, I>(input: A, fn0: (x: A) => B, fn1
/*
Method: pipedAsync
Explanation: It accepts input as first argument and series of functions as next arguments. It is same as `R.pipe` but with support for asynchronous functions.
Explanation: It accepts input as first argument and series of functions as next arguments. It is same as `R.piped` but with support for asynchronous functions like `R.pipeAsync`.
Example:
Expand All @@ -6600,14 +6703,16 @@ const result = await R.pipedAsync(
Categories: Async
Notes: Functions that return `Promise` will be handled as regular function not asynchronous. Such example is `const foo = input => new Promise(...)`.
*/
// @SINGLE_MARKER
export function pipedAsync<T>(
input: any,
...fns: (Func<any> | Async<any>)[]
): Promise<T>;
export function pipedAsync<A, B>(input: A, fn0: (x: Awaited<A>) => B) : B;
export function pipedAsync<A, B, C>(input: A, fn0: (x: Awaited<A>) => B, fn1: (x: Awaited<B>) => C) : C;
export function pipedAsync<A, B, C, D>(input: A, fn0: (x: Awaited<A>) => B, fn1: (x: Awaited<B>) => C, fn2: (x: Awaited<C>) => D) : D;
export function pipedAsync<A, B, C, D, E>(input: A, fn0: (x: Awaited<A>) => B, fn1: (x: Awaited<B>) => C, fn2: (x: Awaited<C>) => D, fn3: (x: Awaited<D>) => E) : E;
export function pipedAsync<A, B, C, D, E, F>(input: A, fn0: (x: Awaited<A>) => B, fn1: (x: Awaited<B>) => C, fn2: (x: Awaited<C>) => D, fn3: (x: Awaited<D>) => E, fn4: (x: Awaited<E>) => F) : F;
export function pipedAsync<A, B, C, D, E, F, G>(input: A, fn0: (x: Awaited<A>) => B, fn1: (x: Awaited<B>) => C, fn2: (x: Awaited<C>) => D, fn3: (x: Awaited<D>) => E, fn4: (x: Awaited<E>) => F, fn5: (x: Awaited<F>) => G) : G;
export function pipedAsync<A, B, C, D, E, F, G, H>(input: A, fn0: (x: Awaited<A>) => B, fn1: (x: Awaited<B>) => C, fn2: (x: Awaited<C>) => D, fn3: (x: Awaited<D>) => E, fn4: (x: Awaited<E>) => F, fn5: (x: Awaited<F>) => G, fn6: (x: Awaited<G>) => H) : H;
export function pipedAsync<A, B, C, D, E, F, G, H, I>(input: A, fn0: (x: Awaited<A>) => B, fn1: (x: Awaited<B>) => C, fn2: (x: Awaited<C>) => D, fn3: (x: Awaited<D>) => E, fn4: (x: Awaited<E>) => F, fn5: (x: Awaited<F>) => G, fn6: (x: Awaited<G>) => H, fn7: (x: Awaited<H>) => I) : I;

/*
Method: produce
Expand Down
30 changes: 24 additions & 6 deletions source/composeAsync-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,32 @@ import {delay, composeAsync} from 'rambda'

describe('R.composeAsync', () => {
it('happy', async() => {
const result = await composeAsync<number>(
async x => {
const fn = composeAsync(
// Notice the type parameter here. Because of the order of the functions,
// TypeScript won't infer the type of `x` from later functions, but using
// a type parameter we can leave it generic and properly compute the
// result type at the end.
<T>(x: T) => {
x // $ExpectType T
return Promise.resolve([x])
},
x => {
x // $ExpectType number
return new Promise<string>((resolve) => {
resolve(x.toString())
})
},
async (x: 4) => {
x // $ExpectType 4
await delay(100)
return x + 2
return x + 1
},
x => x.length + 10
)([1, 2])
)

const result1 = await fn(4)
const result2 = await fn(Promise.resolve(4))

result // $ExpectType number
result1 // $ExpectType string[]
result2 // $ExpectType string[]
})
})
21 changes: 4 additions & 17 deletions source/composeAsync.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
import { type } from './type.js'
import { pipeAsync } from './pipeAsync.js'

export function composeAsync(...inputArguments){
return async function (startArgument){
let argumentsToPass = startArgument

while (inputArguments.length !== 0){
const fn = inputArguments.pop()

argumentsToPass = fn(argumentsToPass)
if (type(argumentsToPass) === 'Promise'){
argumentsToPass = await argumentsToPass
}
}

return argumentsToPass
}
}
export function composeAsync(...fnList){
return pipeAsync(...fnList.reverse())
}
4 changes: 2 additions & 2 deletions source/mapToObjectAsync-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ describe('R.mapToObjectAsync', () => {
result // $ExpectType Output
})
it('with R.composeAsync', async() => {
const result = await composeAsync<Output>(
mapToObjectAsync(fn),
const result = await composeAsync(
mapToObjectAsync<number, Output>(fn),
(x: number[]) => x.filter((xx: number) => xx > 2)
)(list)

Expand Down
26 changes: 20 additions & 6 deletions source/pipeAsync-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@ import {delay, pipeAsync} from 'rambda'

describe('R.pipeAsync', () => {
it('happy', async() => {
const result = await pipeAsync<number>(
async x => {
const fn = pipeAsync(
async (x: 4) => {
x // $ExpectType 4
await delay(100)
return x + 2
return x + 1
},
x => x.length + 10
)([1, 2])
x => {
x // $ExpectType number
return new Promise<string>((resolve) => {
resolve(x.toString())
})
},
x => {
x // $ExpectType string
return Promise.resolve([x])
}
)

const result1 = await fn(4)
const result2 = await fn(Promise.resolve(4))

result // $ExpectType number
result1 // $ExpectType string[]
result2 // $ExpectType string[]
})
})
19 changes: 4 additions & 15 deletions source/pipeAsync.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
import { type } from './type.js'
import { reduce } from "./reduce";

export function pipeAsync(...inputArguments){
return async function (startArgument){
let argumentsToPass = startArgument

while (inputArguments.length !== 0){
const fn = inputArguments.shift()

argumentsToPass = fn(argumentsToPass)
if (type(argumentsToPass) === 'Promise'){
argumentsToPass = await argumentsToPass
}
}

return argumentsToPass
export function pipeAsync(...fnList){
return function (startArgument){
return reduce(async (value, fn) => fn(await value), startArgument, fnList)
}
}
4 changes: 1 addition & 3 deletions source/pipeAsync.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { delay } from './delay.js'
import { equals } from './equals.js'
import { map } from './map.js'
import { pipeAsync } from './pipeAsync.js'

async function identity(x){
Expand Down Expand Up @@ -31,7 +29,7 @@ const delayFn = ms =>
resolve(ms + 1)
})

test('with function returning promise', async () => {
test.only('with function returning promise', async () => {
const result = await pipeAsync(
x => x,
x => x + 1,
Expand Down
19 changes: 13 additions & 6 deletions source/pipedAsync-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ import {pipedAsync, delay} from 'rambda'

describe('R.pipedAsync', () => {
it('happy', async() => {
const result = await pipedAsync<number>(
4,
const result = await pipedAsync(
4 as const,
async x => {
x // $ExpectType 4
await delay(100)
return x + 1
},
async x => {
await delay(100)
return x + 10
x => {
x // $ExpectType number
return new Promise<string>((resolve) => {
resolve(x.toString())
})
},
x => {
x // $ExpectType string
return Promise.resolve([x])
}
)

result // $ExpectType number
result // $ExpectType string[]
})
})
Loading

0 comments on commit 14035af

Please sign in to comment.