From b0ac5c8528ebb6ee936453d0920203420c124fa0 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Fri, 4 Jul 2025 08:33:07 +0300 Subject: [PATCH 01/54] chore@small --- CHANGELOG.md | 6 +++--- README.md | 36 ++++++++---------------------------- docs/README.md | 36 ++++++++---------------------------- files/README_START.md | 2 ++ files/index.d.ts | 24 ------------------------ index.d.cts | 24 ------------------------ index.d.ts | 24 ------------------------ source/mapAsync-spec.ts | 8 +++----- 8 files changed, 24 insertions(+), 136 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85536ce0..b220db21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ -10.4.0 +10.3.0 -fix `R.pluck` +Fix `R.pluck` Add `R.duplicateBy` @@ -10,7 +10,7 @@ Add `R.indexBy` Restore `R.replaceAll` -10.3.0 +Remove option for `R.mapAsync` to be called outside of `R.pipeAsync` Add `R.mapPropObject` diff --git a/README.md b/README.md index 540a7b70..3a8a2b16 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,8 @@ it('within Ramda.pipe requires explicit types', () => { }); ``` +IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. + ### Keep only the most useful methods The idea is to give `TypeScript` users only the most useful methods and let them implement the rest. No magic logic methods that are hard to remember. You shouldn't need to read the documentation to understand what a method does. Its name and signature should be enough. @@ -5809,16 +5811,6 @@ mapAsync( mapAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -mapAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -mapAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; -... -... ``` @@ -5904,14 +5896,12 @@ test('error', async () => { TypeScript test ```typescript -import { mapAsync, pipeAsync } from 'rambda' -import { delay } from 'rambdax' +import { mapAsync, pipeAsync, map } from 'rambda' const list = ['a', 'bc', 'def'] +const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) it('R.mapAsync', async () => { - const fn = async (x:unknown) => x as number + 1 - const result = await pipeAsync( list, mapAsync(async x => { @@ -5920,7 +5910,7 @@ it('R.mapAsync', async () => { return x.length % 2 ? x.length + 1 : x.length + 10 }), x => x, - mapAsync(fn), + map(x => x +1), mapAsync(async x => { await delay(100) return x + 1 @@ -6296,16 +6286,6 @@ mapParallelAsync( mapParallelAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -mapParallelAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -mapParallelAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; -... -... ``` @@ -13228,9 +13208,9 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -10.4.0 +10.3.0 -fix `R.pluck` +Fix `R.pluck` Add `R.duplicateBy` @@ -13240,7 +13220,7 @@ Add `R.indexBy` Restore `R.replaceAll` -10.3.0 +Remove option for `R.mapAsync` to be called outside of `R.pipeAsync` Add `R.mapPropObject` diff --git a/docs/README.md b/docs/README.md index 540a7b70..3a8a2b16 100644 --- a/docs/README.md +++ b/docs/README.md @@ -76,6 +76,8 @@ it('within Ramda.pipe requires explicit types', () => { }); ``` +IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. + ### Keep only the most useful methods The idea is to give `TypeScript` users only the most useful methods and let them implement the rest. No magic logic methods that are hard to remember. You shouldn't need to read the documentation to understand what a method does. Its name and signature should be enough. @@ -5809,16 +5811,6 @@ mapAsync( mapAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -mapAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -mapAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; -... -... ``` @@ -5904,14 +5896,12 @@ test('error', async () => { TypeScript test ```typescript -import { mapAsync, pipeAsync } from 'rambda' -import { delay } from 'rambdax' +import { mapAsync, pipeAsync, map } from 'rambda' const list = ['a', 'bc', 'def'] +const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) it('R.mapAsync', async () => { - const fn = async (x:unknown) => x as number + 1 - const result = await pipeAsync( list, mapAsync(async x => { @@ -5920,7 +5910,7 @@ it('R.mapAsync', async () => { return x.length % 2 ? x.length + 1 : x.length + 10 }), x => x, - mapAsync(fn), + map(x => x +1), mapAsync(async x => { await delay(100) return x + 1 @@ -6296,16 +6286,6 @@ mapParallelAsync( mapParallelAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -mapParallelAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -mapParallelAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; -... -... ``` @@ -13228,9 +13208,9 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -10.4.0 +10.3.0 -fix `R.pluck` +Fix `R.pluck` Add `R.duplicateBy` @@ -13240,7 +13220,7 @@ Add `R.indexBy` Restore `R.replaceAll` -10.3.0 +Remove option for `R.mapAsync` to be called outside of `R.pipeAsync` Add `R.mapPropObject` diff --git a/files/README_START.md b/files/README_START.md index 38d7fa33..5494ee0e 100644 --- a/files/README_START.md +++ b/files/README_START.md @@ -76,6 +76,8 @@ it('within Ramda.pipe requires explicit types', () => { }); ``` +IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. + ### Keep only the most useful methods The idea is to give `TypeScript` users only the most useful methods and let them implement the rest. No magic logic methods that are hard to remember. You shouldn't need to read the documentation to understand what a method does. Its name and signature should be enough. diff --git a/files/index.d.ts b/files/index.d.ts index 9d8d843b..772d4685 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -4171,7 +4171,6 @@ export function pipeAsync( fn10: (x: Awaited) => L, fn11: (x: Awaited) => M, ): M; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4188,7 +4187,6 @@ export function pipeAsync( fn11: (x: Awaited) => M, fn12: (x: Awaited) => N, ): N; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4206,7 +4204,6 @@ export function pipeAsync( fn12: (x: Awaited) => N, fn13: (x: Awaited) => O, ): O; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4225,7 +4222,6 @@ export function pipeAsync( fn13: (x: Awaited) => O, fn14: (x: Awaited) => P, ): P; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4245,7 +4241,6 @@ export function pipeAsync( fn14: (x: Awaited) => P, fn15: (x: Awaited

) => Q, ): Q; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4266,7 +4261,6 @@ export function pipeAsync( fn15: (x: Awaited

) => Q, fn16: (x: Awaited) => R, ): R; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4288,7 +4282,6 @@ export function pipeAsync) => R, fn17: (x: Awaited) => S, ): S; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4311,7 +4304,6 @@ export function pipeAsync) => S, fn18: (x: Awaited) => T, ): T; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -4366,14 +4358,6 @@ export function mapAsync( export function mapAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -export function mapAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -export function mapAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; /* Method: mapParallelAsync @@ -4397,14 +4381,6 @@ export function mapParallelAsync( export function mapParallelAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -export function mapParallelAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -export function mapParallelAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; /* Method: mapObjectAsync diff --git a/index.d.cts b/index.d.cts index 541cf6a6..f9a405be 100644 --- a/index.d.cts +++ b/index.d.cts @@ -520,14 +520,6 @@ export function mapAsync( export function mapAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -export function mapAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -export function mapAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; /** * It returns a copy of `obj` with keys transformed by `fn`. @@ -559,14 +551,6 @@ export function mapParallelAsync( export function mapParallelAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -export function mapParallelAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -export function mapParallelAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; /** * It maps over a property of object that is a list. @@ -1582,7 +1566,6 @@ export function pipeAsync( fn10: (x: Awaited) => L, fn11: (x: Awaited) => M, ): M; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1599,7 +1582,6 @@ export function pipeAsync( fn11: (x: Awaited) => M, fn12: (x: Awaited) => N, ): N; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1617,7 +1599,6 @@ export function pipeAsync( fn12: (x: Awaited) => N, fn13: (x: Awaited) => O, ): O; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1636,7 +1617,6 @@ export function pipeAsync( fn13: (x: Awaited) => O, fn14: (x: Awaited) => P, ): P; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1656,7 +1636,6 @@ export function pipeAsync( fn14: (x: Awaited) => P, fn15: (x: Awaited

) => Q, ): Q; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1677,7 +1656,6 @@ export function pipeAsync( fn15: (x: Awaited

) => Q, fn16: (x: Awaited) => R, ): R; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1699,7 +1677,6 @@ export function pipeAsync) => R, fn17: (x: Awaited) => S, ): S; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1722,7 +1699,6 @@ export function pipeAsync) => S, fn18: (x: Awaited) => T, ): T; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, diff --git a/index.d.ts b/index.d.ts index 541cf6a6..f9a405be 100644 --- a/index.d.ts +++ b/index.d.ts @@ -520,14 +520,6 @@ export function mapAsync( export function mapAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -export function mapAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -export function mapAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; /** * It returns a copy of `obj` with keys transformed by `fn`. @@ -559,14 +551,6 @@ export function mapParallelAsync( export function mapParallelAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; -export function mapParallelAsync( - fn: (value: T[number], index: number) => Promise, - data: T -): Promise>; -export function mapParallelAsync( - fn: (value: T[number]) => Promise, - data: T -): Promise>; /** * It maps over a property of object that is a list. @@ -1582,7 +1566,6 @@ export function pipeAsync( fn10: (x: Awaited) => L, fn11: (x: Awaited) => M, ): M; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1599,7 +1582,6 @@ export function pipeAsync( fn11: (x: Awaited) => M, fn12: (x: Awaited) => N, ): N; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1617,7 +1599,6 @@ export function pipeAsync( fn12: (x: Awaited) => N, fn13: (x: Awaited) => O, ): O; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1636,7 +1617,6 @@ export function pipeAsync( fn13: (x: Awaited) => O, fn14: (x: Awaited) => P, ): P; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1656,7 +1636,6 @@ export function pipeAsync( fn14: (x: Awaited) => P, fn15: (x: Awaited

) => Q, ): Q; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1677,7 +1656,6 @@ export function pipeAsync( fn15: (x: Awaited

) => Q, fn16: (x: Awaited) => R, ): R; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1699,7 +1677,6 @@ export function pipeAsync) => R, fn17: (x: Awaited) => S, ): S; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, @@ -1722,7 +1699,6 @@ export function pipeAsync) => S, fn18: (x: Awaited) => T, ): T; - export function pipeAsync( input: A, fn0: (x: Awaited) => B, diff --git a/source/mapAsync-spec.ts b/source/mapAsync-spec.ts index 8c5ccf1c..2f1ce89c 100644 --- a/source/mapAsync-spec.ts +++ b/source/mapAsync-spec.ts @@ -1,11 +1,9 @@ -import { mapAsync, pipeAsync } from 'rambda' -import { delay } from 'rambdax' +import { mapAsync, pipeAsync, map } from 'rambda' const list = ['a', 'bc', 'def'] +const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) it('R.mapAsync', async () => { - const fn = async (x:unknown) => x as number + 1 - const result = await pipeAsync( list, mapAsync(async x => { @@ -14,7 +12,7 @@ it('R.mapAsync', async () => { return x.length % 2 ? x.length + 1 : x.length + 10 }), x => x, - mapAsync(fn), + map(x => x +1), mapAsync(async x => { await delay(100) return x + 1 From 91c41f8ec06c2d6c0bb5bfd07f6ff07e66c7d915 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Fri, 4 Jul 2025 08:40:23 +0300 Subject: [PATCH 02/54] chore@small --- files/NEXT_VERSION_CHECKLIST.md | 3 --- files/index.d.ts | 26 ++++++++++++++++++++++++++ source/transformPropObject-spec.ts | 15 +++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 source/transformPropObject-spec.ts diff --git a/files/NEXT_VERSION_CHECKLIST.md b/files/NEXT_VERSION_CHECKLIST.md index 65496e09..97cd4c37 100644 --- a/files/NEXT_VERSION_CHECKLIST.md +++ b/files/NEXT_VERSION_CHECKLIST.md @@ -1,7 +1,6 @@ === ABOVE IS DONE === -transformPropObject document scripts @@ -14,5 +13,3 @@ use functor as a word https://github.com/hemanth/functional-programming-jargon?utm_source=hackernewsletter&utm_medium=email&utm_term=code#functor === -Add matched version at this point -Up until version `9.4.2`, the aim of Rambda was to match as much as possible the Ramda API. diff --git a/files/index.d.ts b/files/index.d.ts index 772d4685..20192d4f 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -1033,6 +1033,32 @@ export function mapObject( ) => Value, ): (data: T) => MappedValues; +/* +Method: transformPropObject + +Explanation: + +Example: + +``` +const fn = (x) => x > 2 +const obj = {a: 1, b: 2} + +const result = R.transformPropObject(fn, 'a')(obj) +// => {a: false, b: 2} +``` + +Categories: Object + +Notes: + +*/ +// @SINGLE_MARKER +export function transformPropObject( + valueMapper: (value: T[K]) => Value, + prop: K, +): (data: T) => MergeTypes & { [P in K]: Value }>; + /* Method: mapPropObject diff --git a/source/transformPropObject-spec.ts b/source/transformPropObject-spec.ts new file mode 100644 index 00000000..9a0779cf --- /dev/null +++ b/source/transformPropObject-spec.ts @@ -0,0 +1,15 @@ +import { transformPropObject, pipe } from 'rambda' + +describe('R.transformPropObject', () => { + it('iterable with one arguments', () => { + const result = pipe( + { a: 1, b: 'foo' }, + transformPropObject(x => { + x // $ExpectType number + return x > 2 + }, 'a'), + ) + + result // $ExpectType { a: boolean; b: string; } + }) +}) From 7107fd704f6f6ea582b25b160291e4135174c822 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 5 Jul 2025 12:19:37 +0300 Subject: [PATCH 03/54] chore@small --- CHANGELOG.md | 8 +++---- files/NEXT_VERSION_CHECKLIST.md | 7 ++++-- files/check-ramda-diff.js | 11 --------- files/index.d.ts | 42 +++++++++++++++++++++++++++++++++ source/filter-spec.ts | 2 +- source/filter.spec.js | 4 ++++ source/filterAsync-spec.ts | 16 +++++++++++++ source/filterAsync.js | 14 +++++++++++ source/filterAsync.spec.js | 8 +++++++ source/mapAsync.js | 4 ++-- 10 files changed, 96 insertions(+), 20 deletions(-) delete mode 100644 files/check-ramda-diff.js create mode 100644 source/filterAsync-spec.ts create mode 100644 source/filterAsync.js create mode 100644 source/filterAsync.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index b220db21..3a4fa16a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ 10.3.0 -Fix `R.pluck` +- Fix `R.pluck` to work without `R.pipe` -Add `R.duplicateBy` +- Add `R.duplicateBy` -Add `R.filterAsync` +- Add `R.filterAsync` -Add `R.indexBy` +- Add `R.indexBy` Restore `R.replaceAll` diff --git a/files/NEXT_VERSION_CHECKLIST.md b/files/NEXT_VERSION_CHECKLIST.md index 97cd4c37..c98a1b64 100644 --- a/files/NEXT_VERSION_CHECKLIST.md +++ b/files/NEXT_VERSION_CHECKLIST.md @@ -1,13 +1,16 @@ === ABOVE IS DONE === - - document scripts ABOVE IS IN PROGRESS === +export function maybe(thunk: () => T): T | undefined { + try { + return thunk(); + } catch {} +} === use functor as a word https://github.com/hemanth/functional-programming-jargon?utm_source=hackernewsletter&utm_medium=email&utm_term=code#functor diff --git a/files/check-ramda-diff.js b/files/check-ramda-diff.js deleted file mode 100644 index c02731bb..00000000 --- a/files/check-ramda-diff.js +++ /dev/null @@ -1,11 +0,0 @@ -const R = require('../dist/rambda.js'); -const Ramda = require('ramda'); - -const ramdaKeys = Object.keys(Ramda); -const rambdaKeys = Object.keys(R); - -const shared = rambdaKeys.filter(x => ramdaKeys.includes(x)); -const diff = rambdaKeys.filter(x => !ramdaKeys.includes(x)); - -console.log(diff.length , 'methods are different') -console.log(shared.length , 'methods are shared') \ No newline at end of file diff --git a/files/index.d.ts b/files/index.d.ts index 20192d4f..87f7a477 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -4354,6 +4354,26 @@ export function pipeAsync) => U, ): U; +/* +Method: filterAsync + +Explanation: + +Example: + +``` +``` + +Categories: Async, List + +Notes: + +*/ +// @SINGLE_MARKER +export function filterAsync( + predicate: (value: T) => Promise, +): (list: T[]) => Promise; + /* Method: mapAsync @@ -4716,6 +4736,28 @@ Notes: // @SINGLE_MARKER export function interpolate(inputWithTags: string): (templateArguments: object) => string; +/* +Method: indexBy + +Explanation: It transforms list of objects to object using specified property as the base for the returned object. + +Example: + +``` +const result = R.indexBy( + 'id' +)([{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}]) +// => {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} +``` + +Categories: List, Object + +Notes: + +*/ +// @SINGLE_MARKER +export function interpolate(inputWithTags: string): (templateArguments: object) => string; + // API_MARKER_END // ============================================ diff --git a/source/filter-spec.ts b/source/filter-spec.ts index 67aaf015..f71a05ec 100644 --- a/source/filter-spec.ts +++ b/source/filter-spec.ts @@ -1,4 +1,4 @@ -import { filter, mergeTypes, pipe } from 'rambda' +import { filter, pipe } from 'rambda' const list = [1, 2, 3] diff --git a/source/filter.spec.js b/source/filter.spec.js index 1bf9114d..459e7b89 100644 --- a/source/filter.spec.js +++ b/source/filter.spec.js @@ -5,3 +5,7 @@ test('happy', () => { expect(filter(isEven)([1, 2, 3, 4])).toEqual([2, 4]) }) + +test('using Boolean', () => { + expect(filter(Boolean)([null, 0, 1, 2])).toEqual([1,2]) +}) diff --git a/source/filterAsync-spec.ts b/source/filterAsync-spec.ts new file mode 100644 index 00000000..2c65f02c --- /dev/null +++ b/source/filterAsync-spec.ts @@ -0,0 +1,16 @@ +import { filterAsync, pipeAsync } from 'rambda' + +const list = [1, 2, 3] + +describe('R.filter with array', () => { + it('within pipe', async () => { + const result = await pipeAsync( + list, + filterAsync(async x => { + x // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] + }) +}) diff --git a/source/filterAsync.js b/source/filterAsync.js new file mode 100644 index 00000000..7b0a480f --- /dev/null +++ b/source/filterAsync.js @@ -0,0 +1,14 @@ +export function filterAsync(predicate) { + return async list => { + const willReturn = [] + let index = 0 + for (const x of list) { + if (await predicate(x, index)) { + willReturn.push(list[index]) + } + index++ + } + + return willReturn + } +} diff --git a/source/filterAsync.spec.js b/source/filterAsync.spec.js new file mode 100644 index 00000000..cd9fb530 --- /dev/null +++ b/source/filterAsync.spec.js @@ -0,0 +1,8 @@ +import { filterAsync } from './filterAsync.js' + +test('happy', async () => { + const isEven = async n => n % 2 === 0 + + expect(await filterAsync(isEven)([1, 2, 3, 4])).toEqual([2, 4]) +}) + diff --git a/source/mapAsync.js b/source/mapAsync.js index 469624df..43887f46 100644 --- a/source/mapAsync.js +++ b/source/mapAsync.js @@ -2,8 +2,8 @@ export function mapAsync(fn) { return async list => { const willReturn = [] let i = 0 - for (const a of list) { - willReturn.push(await fn(a, i++)) + for (const x of list) { + willReturn.push(await fn(x, i++)) } return willReturn From d70b5f7a74b5df0ac0805e5a9ad90aabc98652b8 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 20:56:46 +0300 Subject: [PATCH 04/54] chore@small --- CHANGELOG.md | 8 +- README.md | 294 ++++++++++++++++++++++++++++++++++++++--- dist/rambda.cjs | 36 ++++- dist/rambda.js | 36 ++++- dist/rambda.umd.js | 36 ++++- docs/README.md | 294 ++++++++++++++++++++++++++++++++++++++--- files/index.d.ts | 8 +- index.d.cts | 26 +++- index.d.ts | 26 +++- rambda.js | 2 + source/indexBy-spec.ts | 23 ++++ source/indexBy.js | 14 ++ source/indexBy.spec.js | 11 ++ source/indexOf.spec.js | 6 +- source/tsconfig.json | 2 +- src/filterAsync.js | 14 ++ src/indexBy.js | 14 ++ src/mapAsync.js | 4 +- 18 files changed, 795 insertions(+), 59 deletions(-) create mode 100644 source/indexBy-spec.ts create mode 100644 source/indexBy.js create mode 100644 source/indexBy.spec.js create mode 100644 src/filterAsync.js create mode 100644 src/indexBy.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a4fa16a..c0d3b788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ 10.3.0 -- Fix `R.pluck` to work without `R.pipe` +- Add `R.mapPropObject` - Add `R.duplicateBy` @@ -8,11 +8,11 @@ - Add `R.indexBy` -Restore `R.replaceAll` +- Restore `R.replaceAll` -Remove option for `R.mapAsync` to be called outside of `R.pipeAsync` +- Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. -Add `R.mapPropObject` +- Fix `R.pluck` to work without `R.pipe` 10.2.0 diff --git a/README.md b/README.md index 3a8a2b16..b35c3caa 100644 --- a/README.md +++ b/README.md @@ -3368,6 +3368,10 @@ test('happy', () => { expect(filter(isEven)([1, 2, 3, 4])).toEqual([2, 4]) }) + +test('using Boolean', () => { + expect(filter(Boolean)([null, 0, 1, 2])).toEqual([1,2]) +}) ``` @@ -3377,7 +3381,7 @@ test('happy', () => {

TypeScript test ```typescript -import { filter, mergeTypes, pipe } from 'rambda' +import { filter, pipe } from 'rambda' const list = [1, 2, 3] @@ -3451,6 +3455,93 @@ describe('R.filter with array', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filter) +### filterAsync + +```typescript + +filterAsync( + predicate: (value: T) => Promise, +): (list: T[]) => Promise +``` + +
+ +All TypeScript definitions + +```typescript +filterAsync( + predicate: (value: T) => Promise, +): (list: T[]) => Promise; +``` + +
+ +
+ +R.filterAsync source + +```javascript +export function filterAsync(predicate) { + return async list => { + const willReturn = [] + let index = 0 + for (const x of list) { + if (await predicate(x, index)) { + willReturn.push(list[index]) + } + index++ + } + + return willReturn + } +} +``` + +
+ +
+ +Tests + +```javascript +import { filterAsync } from './filterAsync.js' + +test('happy', async () => { + const isEven = async n => n % 2 === 0 + + expect(await filterAsync(isEven)([1, 2, 3, 4])).toEqual([2, 4]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { filterAsync, pipeAsync } from 'rambda' + +const list = [1, 2, 3] + +describe('R.filter with array', () => { + it('within pipe', async () => { + const result = await pipeAsync( + list, + filterAsync(async x => { + x // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) + ### filterObject ```typescript @@ -4789,6 +4880,121 @@ describe('R.includes', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#includes) +### indexBy + +```typescript + +indexBy( + property: K +): (list: readonly T[]) => Record +``` + +It transforms list of objects to object using specified property as the base for the returned object. + +```javascript +const result = R.indexBy( + 'id' +)([{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}]) +// => {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} +``` + +
Try this R.indexBy example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +indexBy( + property: K +): (list: readonly T[]) => Record; +indexBy( + property: K +): (list: T[]) => Record; + +// API_MARKER_END +// ============================================ +``` + +
+ +
+ +R.indexBy source + +```javascript +export function indexBy(property){ + return list => { + const toReturn = {} + for (let i = 0; i < list.length; i++){ + const item = list[ i ] + const key = item[property] + if(key !== undefined){ + toReturn[ key ] = item + } + } + + return toReturn + } +} +``` + +
+ +
+ +Tests + +```javascript +import { indexBy } from './indexBy.js' + +test('happy', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + + expect( + indexBy('id')(list) + ).toEqual( + {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} + ) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { pipe, indexBy } from 'rambda' + +describe('R.indexBy', () => { + it('using `as const`', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] as const + const result = pipe( + list, + indexBy('id') + ) + + result.abc // $ExpectType {id: string, title: string} + result.xyz // $ExpectType {id: string, title: string} + }) + it('general case', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + const result = pipe( + list, + indexBy('id') + ) + result.abc // $ExpectType {id: string, title: string} + result.foo // $ExpectType {id: string, title: string} + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexBy) + ### indexOf ```typescript @@ -4847,18 +5053,18 @@ test('will throw with bad input', () => { expect(() => indexOf([])(true)).toThrow() }) -test('without list of objects - no R.equals', () => { +test('with numbers', () => { expect(indexOf(3)([1, 2, 3, 4])).toBe(2) expect(indexOf(10)([1, 2, 3, 4])).toBe(-1) }) -test('list of objects uses R.equals', () => { +test('list of objects use R.equals', () => { const listOfObjects = [{ a: 1 }, { b: 2 }, { c: 3 }] expect(indexOf({ c: 4 })(listOfObjects)).toBe(-1) expect(indexOf({ c: 3 })(listOfObjects)).toBe(2) }) -test('list of arrays uses R.equals', () => { +test('list of arrays use R.equals', () => { const listOfLists = [[1], [2, 3], [2, 3, 4], [2, 3], [1], []] expect(indexOf([])(listOfLists)).toBe(5) expect(indexOf([1])(listOfLists)).toBe(0) @@ -5142,9 +5348,6 @@ const expected = 'foo is BAR even 1 more' ```typescript interpolate(inputWithTags: string): (templateArguments: object) => string; - -// API_MARKER_END -// ============================================ ``` @@ -5824,8 +6027,8 @@ export function mapAsync(fn) { return async list => { const willReturn = [] let i = 0 - for (const a of list) { - willReturn.push(await fn(a, i++)) + for (const x of list) { + willReturn.push(await fn(x, i++)) } return willReturn @@ -11680,6 +11883,65 @@ it('R.test', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#test) +### transformPropObject + +```typescript + +transformPropObject( + valueMapper: (value: T[K]) => Value, + prop: K, +): (data: T) => MergeTypes & { [P in K]: Value }> +``` + +```javascript +const fn = (x) => x > 2 +const obj = {a: 1, b: 2} + +const result = R.transformPropObject(fn, 'a')(obj) +// => {a: false, b: 2} +``` + +Try this R.transformPropObject example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +transformPropObject( + valueMapper: (value: T[K]) => Value, + prop: K, +): (data: T) => MergeTypes & { [P in K]: Value }>; +``` + +
+ +
+ +TypeScript test + +```typescript +import { transformPropObject, pipe } from 'rambda' + +describe('R.transformPropObject', () => { + it('iterable with one arguments', () => { + const result = pipe( + { a: 1, b: 'foo' }, + transformPropObject(x => { + x // $ExpectType number + return x > 2 + }, 'a'), + ) + + result // $ExpectType { a: boolean; b: string; } + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#transformPropObject) + ### tryCatch ```typescript @@ -13210,19 +13472,19 @@ describe('R.zipWith', () => { 10.3.0 -Fix `R.pluck` +- Add `R.mapPropObject` -Add `R.duplicateBy` +- Add `R.duplicateBy` -Add `R.filterAsync` +- Add `R.filterAsync` -Add `R.indexBy` +- Add `R.indexBy` -Restore `R.replaceAll` +- Restore `R.replaceAll` -Remove option for `R.mapAsync` to be called outside of `R.pipeAsync` +- Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. -Add `R.mapPropObject` +- Fix `R.pluck` to work without `R.pipe` 10.2.0 diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 06b5c426..cebd5dd4 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -633,6 +633,21 @@ function excludes(valueToFind) { return iterable => !includes(valueToFind)(iterable) } +function filterAsync(predicate) { + return async list => { + const willReturn = []; + let index = 0; + for (const x of list) { + if (await predicate(x, index)) { + willReturn.push(list[index]); + } + index++; + } + + return willReturn + } +} + function filterObject(predicate) { return obj => { const willReturn = {}; @@ -845,6 +860,21 @@ function head(listOrString) { return listOrString[0] } +function indexBy(property){ + return list => { + const toReturn = {}; + for (let i = 0; i < list.length; i++){ + const item = list[ i ]; + const key = item[property]; + if(key !== undefined){ + toReturn[ key ] = item; + } + } + + return toReturn + } +} + function indexOf(valueToFind) { return list => _indexOf(valueToFind, list) } @@ -983,8 +1013,8 @@ function mapAsync(fn) { return async list => { const willReturn = []; let i = 0; - for (const a of list) { - willReturn.push(await fn(a, i++)); + for (const x of list) { + willReturn.push(await fn(x, i++)); } return willReturn @@ -1882,6 +1912,7 @@ exports.equalsFn = equalsFn; exports.evolve = evolve; exports.excludes = excludes; exports.filter = filter; +exports.filterAsync = filterAsync; exports.filterObject = filterObject; exports.find = find; exports.findIndex = findIndex; @@ -1896,6 +1927,7 @@ exports.groupBy = groupBy; exports.groupByFallback = groupByFallback; exports.head = head; exports.includes = includes; +exports.indexBy = indexBy; exports.indexOf = indexOf; exports.init = init; exports.innerJoin = innerJoin; diff --git a/dist/rambda.js b/dist/rambda.js index 22b33a13..09827336 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -631,6 +631,21 @@ function excludes(valueToFind) { return iterable => !includes(valueToFind)(iterable) } +function filterAsync(predicate) { + return async list => { + const willReturn = []; + let index = 0; + for (const x of list) { + if (await predicate(x, index)) { + willReturn.push(list[index]); + } + index++; + } + + return willReturn + } +} + function filterObject(predicate) { return obj => { const willReturn = {}; @@ -843,6 +858,21 @@ function head(listOrString) { return listOrString[0] } +function indexBy(property){ + return list => { + const toReturn = {}; + for (let i = 0; i < list.length; i++){ + const item = list[ i ]; + const key = item[property]; + if(key !== undefined){ + toReturn[ key ] = item; + } + } + + return toReturn + } +} + function indexOf(valueToFind) { return list => _indexOf(valueToFind, list) } @@ -981,8 +1011,8 @@ function mapAsync(fn) { return async list => { const willReturn = []; let i = 0; - for (const a of list) { - willReturn.push(await fn(a, i++)); + for (const x of list) { + willReturn.push(await fn(x, i++)); } return willReturn @@ -1844,4 +1874,4 @@ function zipWith(fn, x) { ) } -export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, filter, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexOf, init, innerJoin, interpolate, intersection, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; +export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, innerJoin, interpolate, intersection, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index e6b08ac7..6e3c784d 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -637,6 +637,21 @@ return iterable => !includes(valueToFind)(iterable) } + function filterAsync(predicate) { + return async list => { + const willReturn = []; + let index = 0; + for (const x of list) { + if (await predicate(x, index)) { + willReturn.push(list[index]); + } + index++; + } + + return willReturn + } + } + function filterObject(predicate) { return obj => { const willReturn = {}; @@ -849,6 +864,21 @@ return listOrString[0] } + function indexBy(property){ + return list => { + const toReturn = {}; + for (let i = 0; i < list.length; i++){ + const item = list[ i ]; + const key = item[property]; + if(key !== undefined){ + toReturn[ key ] = item; + } + } + + return toReturn + } + } + function indexOf(valueToFind) { return list => _indexOf(valueToFind, list) } @@ -987,8 +1017,8 @@ return async list => { const willReturn = []; let i = 0; - for (const a of list) { - willReturn.push(await fn(a, i++)); + for (const x of list) { + willReturn.push(await fn(x, i++)); } return willReturn @@ -1886,6 +1916,7 @@ exports.evolve = evolve; exports.excludes = excludes; exports.filter = filter; + exports.filterAsync = filterAsync; exports.filterObject = filterObject; exports.find = find; exports.findIndex = findIndex; @@ -1900,6 +1931,7 @@ exports.groupByFallback = groupByFallback; exports.head = head; exports.includes = includes; + exports.indexBy = indexBy; exports.indexOf = indexOf; exports.init = init; exports.innerJoin = innerJoin; diff --git a/docs/README.md b/docs/README.md index 3a8a2b16..b35c3caa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3368,6 +3368,10 @@ test('happy', () => { expect(filter(isEven)([1, 2, 3, 4])).toEqual([2, 4]) }) + +test('using Boolean', () => { + expect(filter(Boolean)([null, 0, 1, 2])).toEqual([1,2]) +}) ``` @@ -3377,7 +3381,7 @@ test('happy', () => { TypeScript test ```typescript -import { filter, mergeTypes, pipe } from 'rambda' +import { filter, pipe } from 'rambda' const list = [1, 2, 3] @@ -3451,6 +3455,93 @@ describe('R.filter with array', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filter) +### filterAsync + +```typescript + +filterAsync( + predicate: (value: T) => Promise, +): (list: T[]) => Promise +``` + +
+ +All TypeScript definitions + +```typescript +filterAsync( + predicate: (value: T) => Promise, +): (list: T[]) => Promise; +``` + +
+ +
+ +R.filterAsync source + +```javascript +export function filterAsync(predicate) { + return async list => { + const willReturn = [] + let index = 0 + for (const x of list) { + if (await predicate(x, index)) { + willReturn.push(list[index]) + } + index++ + } + + return willReturn + } +} +``` + +
+ +
+ +Tests + +```javascript +import { filterAsync } from './filterAsync.js' + +test('happy', async () => { + const isEven = async n => n % 2 === 0 + + expect(await filterAsync(isEven)([1, 2, 3, 4])).toEqual([2, 4]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { filterAsync, pipeAsync } from 'rambda' + +const list = [1, 2, 3] + +describe('R.filter with array', () => { + it('within pipe', async () => { + const result = await pipeAsync( + list, + filterAsync(async x => { + x // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) + ### filterObject ```typescript @@ -4789,6 +4880,121 @@ describe('R.includes', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#includes) +### indexBy + +```typescript + +indexBy( + property: K +): (list: readonly T[]) => Record +``` + +It transforms list of objects to object using specified property as the base for the returned object. + +```javascript +const result = R.indexBy( + 'id' +)([{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}]) +// => {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} +``` + +Try this R.indexBy example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +indexBy( + property: K +): (list: readonly T[]) => Record; +indexBy( + property: K +): (list: T[]) => Record; + +// API_MARKER_END +// ============================================ +``` + +
+ +
+ +R.indexBy source + +```javascript +export function indexBy(property){ + return list => { + const toReturn = {} + for (let i = 0; i < list.length; i++){ + const item = list[ i ] + const key = item[property] + if(key !== undefined){ + toReturn[ key ] = item + } + } + + return toReturn + } +} +``` + +
+ +
+ +Tests + +```javascript +import { indexBy } from './indexBy.js' + +test('happy', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + + expect( + indexBy('id')(list) + ).toEqual( + {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} + ) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { pipe, indexBy } from 'rambda' + +describe('R.indexBy', () => { + it('using `as const`', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] as const + const result = pipe( + list, + indexBy('id') + ) + + result.abc // $ExpectType {id: string, title: string} + result.xyz // $ExpectType {id: string, title: string} + }) + it('general case', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + const result = pipe( + list, + indexBy('id') + ) + result.abc // $ExpectType {id: string, title: string} + result.foo // $ExpectType {id: string, title: string} + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexBy) + ### indexOf ```typescript @@ -4847,18 +5053,18 @@ test('will throw with bad input', () => { expect(() => indexOf([])(true)).toThrow() }) -test('without list of objects - no R.equals', () => { +test('with numbers', () => { expect(indexOf(3)([1, 2, 3, 4])).toBe(2) expect(indexOf(10)([1, 2, 3, 4])).toBe(-1) }) -test('list of objects uses R.equals', () => { +test('list of objects use R.equals', () => { const listOfObjects = [{ a: 1 }, { b: 2 }, { c: 3 }] expect(indexOf({ c: 4 })(listOfObjects)).toBe(-1) expect(indexOf({ c: 3 })(listOfObjects)).toBe(2) }) -test('list of arrays uses R.equals', () => { +test('list of arrays use R.equals', () => { const listOfLists = [[1], [2, 3], [2, 3, 4], [2, 3], [1], []] expect(indexOf([])(listOfLists)).toBe(5) expect(indexOf([1])(listOfLists)).toBe(0) @@ -5142,9 +5348,6 @@ const expected = 'foo is BAR even 1 more' ```typescript interpolate(inputWithTags: string): (templateArguments: object) => string; - -// API_MARKER_END -// ============================================ ``` @@ -5824,8 +6027,8 @@ export function mapAsync(fn) { return async list => { const willReturn = [] let i = 0 - for (const a of list) { - willReturn.push(await fn(a, i++)) + for (const x of list) { + willReturn.push(await fn(x, i++)) } return willReturn @@ -11680,6 +11883,65 @@ it('R.test', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#test) +### transformPropObject + +```typescript + +transformPropObject( + valueMapper: (value: T[K]) => Value, + prop: K, +): (data: T) => MergeTypes & { [P in K]: Value }> +``` + +```javascript +const fn = (x) => x > 2 +const obj = {a: 1, b: 2} + +const result = R.transformPropObject(fn, 'a')(obj) +// => {a: false, b: 2} +``` + +Try this R.transformPropObject example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +transformPropObject( + valueMapper: (value: T[K]) => Value, + prop: K, +): (data: T) => MergeTypes & { [P in K]: Value }>; +``` + +
+ +
+ +TypeScript test + +```typescript +import { transformPropObject, pipe } from 'rambda' + +describe('R.transformPropObject', () => { + it('iterable with one arguments', () => { + const result = pipe( + { a: 1, b: 'foo' }, + transformPropObject(x => { + x // $ExpectType number + return x > 2 + }, 'a'), + ) + + result // $ExpectType { a: boolean; b: string; } + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#transformPropObject) + ### tryCatch ```typescript @@ -13210,19 +13472,19 @@ describe('R.zipWith', () => { 10.3.0 -Fix `R.pluck` +- Add `R.mapPropObject` -Add `R.duplicateBy` +- Add `R.duplicateBy` -Add `R.filterAsync` +- Add `R.filterAsync` -Add `R.indexBy` +- Add `R.indexBy` -Restore `R.replaceAll` +- Restore `R.replaceAll` -Remove option for `R.mapAsync` to be called outside of `R.pipeAsync` +- Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. -Add `R.mapPropObject` +- Fix `R.pluck` to work without `R.pipe` 10.2.0 diff --git a/files/index.d.ts b/files/index.d.ts index 87f7a477..1035c9ab 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -4756,8 +4756,12 @@ Notes: */ // @SINGLE_MARKER -export function interpolate(inputWithTags: string): (templateArguments: object) => string; - +export function indexBy( + property: K +): (list: readonly T[]) => Record; +export function indexBy( + property: K +): (list: T[]) => Record; // API_MARKER_END // ============================================ diff --git a/index.d.cts b/index.d.cts index f9a405be..99d14d5d 100644 --- a/index.d.cts +++ b/index.d.cts @@ -342,6 +342,10 @@ export function filter( predicate: (value: T) => boolean, ): (list: T[]) => T[]; +export function filterAsync( + predicate: (value: T) => Promise, +): (list: T[]) => Promise; + /** * It loops over each property of `obj` and returns a new object with only those properties that satisfy the `predicate`. */ @@ -427,6 +431,19 @@ export function head(listOrString: T): T extends string ? string : export function includes(valueToFind: T): (input: string) => boolean; export function includes(valueToFind: T): (input: T[]) => boolean; +/** + * It transforms list of objects to object using specified property as the base for the returned object. + */ +export function indexBy( + property: K +): (list: readonly T[]) => Record; +export function indexBy( + property: K +): (list: T[]) => Record; + +// API_MARKER_END +// ============================================ + /** * It uses `R.equals` for list of objects/arrays or native `indexOf` for any other case. */ @@ -451,10 +468,6 @@ export function innerJoin( */ export function interpolate(inputWithTags: string): (templateArguments: object) => string; - -// API_MARKER_END -// ============================================ - /** * It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. */ @@ -2231,6 +2244,11 @@ export function tap(fn: (x: T) => void): (input: T) => T; */ export function test(regExpression: RegExp): (str: string) => boolean; +export function transformPropObject( + valueMapper: (value: T[K]) => Value, + prop: K, +): (data: T) => MergeTypes & { [P in K]: Value }>; + /** * It returns function that runs `fn` in `try/catch` block. If there was an error, then `fallback` is used to return the result. */ diff --git a/index.d.ts b/index.d.ts index f9a405be..99d14d5d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -342,6 +342,10 @@ export function filter( predicate: (value: T) => boolean, ): (list: T[]) => T[]; +export function filterAsync( + predicate: (value: T) => Promise, +): (list: T[]) => Promise; + /** * It loops over each property of `obj` and returns a new object with only those properties that satisfy the `predicate`. */ @@ -427,6 +431,19 @@ export function head(listOrString: T): T extends string ? string : export function includes(valueToFind: T): (input: string) => boolean; export function includes(valueToFind: T): (input: T[]) => boolean; +/** + * It transforms list of objects to object using specified property as the base for the returned object. + */ +export function indexBy( + property: K +): (list: readonly T[]) => Record; +export function indexBy( + property: K +): (list: T[]) => Record; + +// API_MARKER_END +// ============================================ + /** * It uses `R.equals` for list of objects/arrays or native `indexOf` for any other case. */ @@ -451,10 +468,6 @@ export function innerJoin( */ export function interpolate(inputWithTags: string): (templateArguments: object) => string; - -// API_MARKER_END -// ============================================ - /** * It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. */ @@ -2231,6 +2244,11 @@ export function tap(fn: (x: T) => void): (input: T) => T; */ export function test(regExpression: RegExp): (str: string) => boolean; +export function transformPropObject( + valueMapper: (value: T[K]) => Value, + prop: K, +): (data: T) => MergeTypes & { [P in K]: Value }>; + /** * It returns function that runs `fn` in `try/catch` block. If there was an error, then `fallback` is used to return the result. */ diff --git a/rambda.js b/rambda.js index fe2f9c17..7fb71999 100644 --- a/rambda.js +++ b/rambda.js @@ -29,6 +29,7 @@ export * from './src/equals.js' export * from './src/evolve.js' export * from './src/excludes.js' export * from './src/filter.js' +export * from './src/filterAsync.js' export * from './src/filterObject.js' export * from './src/find.js' export * from './src/findIndex.js' @@ -41,6 +42,7 @@ export * from './src/flattenObject.js' export * from './src/groupBy.js' export * from './src/head.js' export * from './src/includes.js' +export * from './src/indexBy.js' export * from './src/indexOf.js' export * from './src/init.js' export * from './src/innerJoin.js' diff --git a/source/indexBy-spec.ts b/source/indexBy-spec.ts new file mode 100644 index 00000000..a1555cc6 --- /dev/null +++ b/source/indexBy-spec.ts @@ -0,0 +1,23 @@ +import { pipe, indexBy } from 'rambda' + +describe('R.indexBy', () => { + it('using `as const`', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] as const + const result = pipe( + list, + indexBy('id') + ) + + result.abc // $ExpectType {id: string, title: string} + result.xyz // $ExpectType {id: string, title: string} + }) + it('general case', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + const result = pipe( + list, + indexBy('id') + ) + result.abc // $ExpectType {id: string, title: string} + result.foo // $ExpectType {id: string, title: string} + }) +}) diff --git a/source/indexBy.js b/source/indexBy.js new file mode 100644 index 00000000..10783317 --- /dev/null +++ b/source/indexBy.js @@ -0,0 +1,14 @@ +export function indexBy(property){ + return list => { + const toReturn = {} + for (let i = 0; i < list.length; i++){ + const item = list[ i ] + const key = item[property] + if(key !== undefined){ + toReturn[ key ] = item + } + } + + return toReturn + } +} diff --git a/source/indexBy.spec.js b/source/indexBy.spec.js new file mode 100644 index 00000000..d6105fed --- /dev/null +++ b/source/indexBy.spec.js @@ -0,0 +1,11 @@ +import { indexBy } from './indexBy.js' + +test('happy', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + + expect( + indexBy('id')(list) + ).toEqual( + {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} + ) +}) \ No newline at end of file diff --git a/source/indexOf.spec.js b/source/indexOf.spec.js index b6d6afab..b0eb2a4d 100644 --- a/source/indexOf.spec.js +++ b/source/indexOf.spec.js @@ -8,18 +8,18 @@ test('will throw with bad input', () => { expect(() => indexOf([])(true)).toThrow() }) -test('without list of objects - no R.equals', () => { +test('with numbers', () => { expect(indexOf(3)([1, 2, 3, 4])).toBe(2) expect(indexOf(10)([1, 2, 3, 4])).toBe(-1) }) -test('list of objects uses R.equals', () => { +test('list of objects use R.equals', () => { const listOfObjects = [{ a: 1 }, { b: 2 }, { c: 3 }] expect(indexOf({ c: 4 })(listOfObjects)).toBe(-1) expect(indexOf({ c: 3 })(listOfObjects)).toBe(2) }) -test('list of arrays uses R.equals', () => { +test('list of arrays use R.equals', () => { const listOfLists = [[1], [2, 3], [2, 3, 4], [2, 3], [1], []] expect(indexOf([])(listOfLists)).toBe(5) expect(indexOf([1])(listOfLists)).toBe(0) diff --git a/source/tsconfig.json b/source/tsconfig.json index 14b9359d..a763d57b 100644 --- a/source/tsconfig.json +++ b/source/tsconfig.json @@ -11,5 +11,5 @@ "paths": { "rambda": ["../files/index.d.ts"], "rambdax": ["../files/rambdax.d.ts"], "ramda": ["../node_modules/types-ramda/es/index.d.ts"] }, "allowJs": false }, - "include": ["./**/*.ts"] + "include": ["./**/*.ts", "indexBy.js"] } diff --git a/src/filterAsync.js b/src/filterAsync.js new file mode 100644 index 00000000..7b0a480f --- /dev/null +++ b/src/filterAsync.js @@ -0,0 +1,14 @@ +export function filterAsync(predicate) { + return async list => { + const willReturn = [] + let index = 0 + for (const x of list) { + if (await predicate(x, index)) { + willReturn.push(list[index]) + } + index++ + } + + return willReturn + } +} diff --git a/src/indexBy.js b/src/indexBy.js new file mode 100644 index 00000000..10783317 --- /dev/null +++ b/src/indexBy.js @@ -0,0 +1,14 @@ +export function indexBy(property){ + return list => { + const toReturn = {} + for (let i = 0; i < list.length; i++){ + const item = list[ i ] + const key = item[property] + if(key !== undefined){ + toReturn[ key ] = item + } + } + + return toReturn + } +} diff --git a/src/mapAsync.js b/src/mapAsync.js index 469624df..43887f46 100644 --- a/src/mapAsync.js +++ b/src/mapAsync.js @@ -2,8 +2,8 @@ export function mapAsync(fn) { return async list => { const willReturn = [] let i = 0 - for (const a of list) { - willReturn.push(await fn(a, i++)) + for (const x of list) { + willReturn.push(await fn(x, i++)) } return willReturn From 44f715b2bab5801f45d56274a1ce0bdad6d4ad6b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 21:18:33 +0300 Subject: [PATCH 05/54] chore@small --- README.md | 20 ++++++++++---------- docs/README.md | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b35c3caa..150e99d9 100644 --- a/README.md +++ b/README.md @@ -14207,25 +14207,25 @@ Fix wrong versions in changelog > Most influential contributors(in alphabetical order) -- ![farwayer avatar](https://avatars.githubusercontent.com/farwayer) [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; +- [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; -- ![thejohnfreeman avatar](https://avatars.githubusercontent.com/thejohnfreeman) [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; +- [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; -- ![peeja avatar](https://avatars.githubusercontent.com/peeja) [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation +- [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation -- ![helmuthdu avatar](https://avatars.githubusercontent.com/helmuthdu) [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; +- [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; -- ![jpgorman avatar](https://avatars.githubusercontent.com/jpgorman) [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; +- [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; -- ![ku8ar avatar](https://avatars.githubusercontent.com/ku8ar) [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; +- [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; -- ![romgrk avatar](https://avatars.githubusercontent.com/romgrk) [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; +- [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; -- ![squidfunk avatar](https://avatars.githubusercontent.com/squidfunk) [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; +- [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; -- ![synthet1c avatar](https://avatars.githubusercontent.com/synthet1c) [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; +- [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; -- ![vlad-zhukov avatar](https://avatars.githubusercontent.com/vlad-zhukov) [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; +- [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; > Rambda references diff --git a/docs/README.md b/docs/README.md index b35c3caa..150e99d9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14207,25 +14207,25 @@ Fix wrong versions in changelog > Most influential contributors(in alphabetical order) -- ![farwayer avatar](https://avatars.githubusercontent.com/farwayer) [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; +- [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; -- ![thejohnfreeman avatar](https://avatars.githubusercontent.com/thejohnfreeman) [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; +- [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; -- ![peeja avatar](https://avatars.githubusercontent.com/peeja) [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation +- [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation -- ![helmuthdu avatar](https://avatars.githubusercontent.com/helmuthdu) [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; +- [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; -- ![jpgorman avatar](https://avatars.githubusercontent.com/jpgorman) [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; +- [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; -- ![ku8ar avatar](https://avatars.githubusercontent.com/ku8ar) [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; +- [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; -- ![romgrk avatar](https://avatars.githubusercontent.com/romgrk) [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; +- [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; -- ![squidfunk avatar](https://avatars.githubusercontent.com/squidfunk) [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; +- [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; -- ![synthet1c avatar](https://avatars.githubusercontent.com/synthet1c) [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; +- [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; -- ![vlad-zhukov avatar](https://avatars.githubusercontent.com/vlad-zhukov) [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; +- [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; > Rambda references From 5d38fde3e8380d205f62583caf47478813e4f666 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 21:23:02 +0300 Subject: [PATCH 06/54] chore@small --- files/index.d.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/files/index.d.ts b/files/index.d.ts index 1035c9ab..f82b1a58 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -135,7 +135,7 @@ Example: ``` const result = R.pipe( [1, 2, 3], - R.modifyItemAtIndex(1, R.add(1)) + R.modifyItemAtIndex(1, x => x + 1) ) // => [1, 3, 3] ``` @@ -3281,21 +3281,19 @@ If the `predicate` returns `false`, then it will simply return `input`. Example: ``` const predicate = x => typeof x === 'number' -const whenTrueFn = R.add(11) - -const fn = when(predicate, whenTrueResult) +const fn = R.when(predicate)(x => x + 1) const positiveInput = 88 const negativeInput = 'foo' const result = [ fn(positiveInput), - fn(positiveInput), + fn(negativeInput), ] const expected = [ - 99, - 'foo', + 89, + 'foo1', ] // => `result` is equal to `expected` ``` @@ -3407,7 +3405,7 @@ Example: const list1 = [ 10, 20, 30, 40 ] const list2 = [ 100, 200 ] -const result = R.zipWith(R.add, list1)(list2) +const result = R.zipWith((x, y) => x + y, list1)(list2) // => [110, 220] ``` @@ -3672,7 +3670,7 @@ Example: ``` const list = [{a:1}, {a:2}, {a:1}] -const result = R.uniqBy(x => x, list) +const result = R.uniqBy(x => x)(list) // => [{a:1}, {a:2}] ``` @@ -4022,7 +4020,7 @@ const index = 2 const newValue = 88 const list = [1, 2, 3, 4, 5] -const result = R.update(index, newValue, list) +const result = R.update(index, newValue)(list) // => [1, 2, 88, 4, 5] ``` @@ -4120,7 +4118,7 @@ const result = await R.pipeAsync( await R.delay(100) return x + 2 }, - R.add(2), + x => x +2, async x => { const delayed = await R.delay(100) return delayed + x From 25d19039831dcc9888afd037e4d4e3ca2f6dfbc5 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 21:54:31 +0300 Subject: [PATCH 07/54] chore@small --- files/index.d.ts | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/files/index.d.ts b/files/index.d.ts index f82b1a58..f47db5a1 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -2530,6 +2530,20 @@ Explanation: Example: ``` +const list = [ + {a: 2}, + {a: 3}, + {a: 1} +] +const sortFn = x => x.a + +const result = R.sortByDescending(sortFn)(list) +const expected = [ + {a: 3}, + {a: 2}, + {a: 1} +] +// => `result` is equal to `expected` ``` Categories: List @@ -2949,8 +2963,8 @@ Example: ``` const result = [ - R.splitEvery(2, [1, 2, 3]), - R.splitEvery(3, 'foobar') + R.splitEvery(2)([1, 2, 3]), + R.splitEvery(3)('foobar') ] const expected = [ @@ -2981,7 +2995,7 @@ Example: const x = [ 1, 2, 3, 4 ] const y = [ 3, 4, 5, 6 ] -const result = R.symmetricDifference(x, y) +const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` @@ -3088,11 +3102,11 @@ Example: ``` const list = [1, 2, 3] -R.pipe( +const result = R.pipe( list, - R.map(x => x * 2) + R.filter(x => x > 1), R.tap(console.log), - R.filter(x => x > 1) + R.map(x => x * 2) ) // => `2` and `3` will be logged ``` @@ -3198,7 +3212,7 @@ Explanation: It takes two lists and return a new list containing a merger of bot Example: ``` -const result = R.union([1,2,3], [3,4,5]); +const result = R.union([1,2,3])([3,4,5]); // => [1, 2, 3, 4, 5] ``` @@ -4460,7 +4474,7 @@ Example: ``` const predicate = (propA, propB, valueA, valueB) => valueA > valueB ? -1 : 1 -const result = R.sortObject(predicate, {a:1, b: 4, c: 2}) +const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) // => {b: 4, c: 2, a: 1} ``` From ba690cc5ae1440aea50fdb3df49114214f2fb60b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 21:59:15 +0300 Subject: [PATCH 08/54] chore@small --- files/index.d.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/files/index.d.ts b/files/index.d.ts index f47db5a1..8e1497ff 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -2562,6 +2562,18 @@ Explanation: It sorts `list` by the value of `path` property. Example: ``` +const list = [ + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, + {a: {b: 3}, id:3}, +] +const result = R.sortByPath('a.b')(list) +const expected = [ + {a: {b: 1}, id:2}, + {a: {b: 2}, id:1}, + {a: {b: 3}, id:3} +] +// => `result` is equal to `expected` ``` Categories: List @@ -2745,6 +2757,18 @@ Explanation: Example: ``` +const list = [ + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, + {a: {b: 3}, id:3}, +] +const result = R.sortByPathDescending('a.b')(list) +const expected = [ + {a: {b: 3}, id:3} + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, +] +// => `result` is equal to `expected` ``` Categories: List From 367983010a018182a3ff33ff95d7b7922684070e Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 21:59:47 +0300 Subject: [PATCH 09/54] chore@small --- README.md | 111 ++++++++++++++++++++++++++++++++++++------------- docs/README.md | 111 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 162 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 150e99d9..290df23b 100644 --- a/README.md +++ b/README.md @@ -7007,11 +7007,11 @@ It replaces `index` in array `list` with the result of `replaceFn(list[i])`. ```javascript const result = R.pipe( [1, 2, 3], - R.modifyItemAtIndex(1, R.add(1)) + R.modifyItemAtIndex(1, x => x + 1) ) // => [1, 3, 3] ``` -Try this R.modifyItemAtIndex example in Rambda REPL +Try this R.modifyItemAtIndex example in Rambda REPL
@@ -8926,7 +8926,7 @@ const result = await R.pipeAsync( await R.delay(100) return x + 2 }, - R.add(2), + x => x +2, async x => { const delayed = await R.delay(100) return delayed + x @@ -8935,7 +8935,7 @@ const result = await R.pipeAsync( // `result` resolves to `RAMBDAX_DELAY104` ``` -Try this R.pipeAsync example in Rambda REPL +Try this R.pipeAsync example in Rambda REPL
@@ -10522,6 +10522,25 @@ describe('R.sortBy', () => { sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[] ``` +```javascript +const list = [ + {a: 2}, + {a: 3}, + {a: 1} +] +const sortFn = x => x.a + +const result = R.sortByDescending(sortFn)(list) +const expected = [ + {a: 3}, + {a: 2}, + {a: 1} +] +// => `result` is equal to `expected` +``` + +Try this R.sortByDescending example in Rambda REPL +
All TypeScript definitions @@ -10559,6 +10578,23 @@ sortByPath( It sorts `list` by the value of `path` property. +```javascript +const list = [ + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, + {a: {b: 3}, id:3}, +] +const result = R.sortByPath('a.b')(list) +const expected = [ + {a: {b: 1}, id:2}, + {a: {b: 2}, id:1}, + {a: {b: 3}, id:3} +] +// => `result` is equal to `expected` +``` + +Try this R.sortByPath example in Rambda REPL +
All TypeScript definitions @@ -10663,6 +10699,23 @@ sortByPathDescending( ): (list: S[]) => S[] ``` +```javascript +const list = [ + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, + {a: {b: 3}, id:3}, +] +const result = R.sortByPathDescending('a.b')(list) +const expected = [ + {a: {b: 3}, id:3} + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, +] +// => `result` is equal to `expected` +``` + +Try this R.sortByPathDescending example in Rambda REPL +
All TypeScript definitions @@ -10736,11 +10789,11 @@ It returns a sorted version of `input` object. ```javascript const predicate = (propA, propB, valueA, valueB) => valueA > valueB ? -1 : 1 -const result = R.sortObject(predicate, {a:1, b: 4, c: 2}) +const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) // => {b: 4, c: 2, a: 1} ``` -Try this R.sortObject example in Rambda REPL +Try this R.sortObject example in Rambda REPL
@@ -11101,8 +11154,8 @@ It splits `input` into slices of `sliceLength`. ```javascript const result = [ - R.splitEvery(2, [1, 2, 3]), - R.splitEvery(3, 'foobar') + R.splitEvery(2)([1, 2, 3]), + R.splitEvery(3)('foobar') ] const expected = [ @@ -11112,7 +11165,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.splitEvery example in Rambda REPL +Try this R.splitEvery example in Rambda REPL
@@ -11199,11 +11252,11 @@ It returns a merged list of `x` and `y` with all equal elements removed. const x = [ 1, 2, 3, 4 ] const y = [ 3, 4, 5, 6 ] -const result = R.symmetricDifference(x, y) +const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` -Try this R.symmetricDifference example in Rambda REPL +Try this R.symmetricDifference example in Rambda REPL
@@ -11770,16 +11823,16 @@ One use case is debugging in the middle of `R.pipe` chain. ```javascript const list = [1, 2, 3] -R.pipe( +const result = R.pipe( list, - R.map(x => x * 2) + R.filter(x => x > 1), R.tap(console.log), - R.filter(x => x > 1) + R.map(x => x * 2) ) // => `2` and `3` will be logged ``` -Try this R.tap example in Rambda REPL +Try this R.tap example in Rambda REPL
@@ -12341,11 +12394,11 @@ It takes two lists and return a new list containing a merger of both list with r `R.equals` is used to compare for duplication. ```javascript -const result = R.union([1,2,3], [3,4,5]); +const result = R.union([1,2,3])([3,4,5]); // => [1, 2, 3, 4, 5] ``` -Try this R.union example in Rambda REPL +Try this R.union example in Rambda REPL
@@ -12556,12 +12609,12 @@ It applies uniqueness to input list based on function that defines what to be us ```javascript const list = [{a:1}, {a:2}, {a:1}] -const result = R.uniqBy(x => x, list) +const result = R.uniqBy(x => x)(list) // => [{a:1}, {a:2}] ``` -Try this R.uniqBy example in Rambda REPL +Try this R.uniqBy example in Rambda REPL
@@ -13038,11 +13091,11 @@ const index = 2 const newValue = 88 const list = [1, 2, 3, 4, 5] -const result = R.update(index, newValue, list) +const result = R.update(index, newValue)(list) // => [1, 2, 88, 4, 5] ``` -Try this R.update example in Rambda REPL +Try this R.update example in Rambda REPL
@@ -13126,26 +13179,24 @@ If the `predicate` returns `false`, then it will simply return `input`. ```javascript const predicate = x => typeof x === 'number' -const whenTrueFn = R.add(11) - -const fn = when(predicate, whenTrueResult) +const fn = R.when(predicate)(x => x + 1) const positiveInput = 88 const negativeInput = 'foo' const result = [ fn(positiveInput), - fn(positiveInput), + fn(negativeInput), ] const expected = [ - 99, - 'foo', + 89, + 'foo1', ] // => `result` is equal to `expected` ``` -Try this R.when example in Rambda REPL +Try this R.when example in Rambda REPL
@@ -13377,11 +13428,11 @@ zipWith( const list1 = [ 10, 20, 30, 40 ] const list2 = [ 100, 200 ] -const result = R.zipWith(R.add, list1)(list2) +const result = R.zipWith((x, y) => x + y, list1)(list2) // => [110, 220] ``` -Try this R.zipWith example in Rambda REPL +Try this R.zipWith example in Rambda REPL
diff --git a/docs/README.md b/docs/README.md index 150e99d9..290df23b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7007,11 +7007,11 @@ It replaces `index` in array `list` with the result of `replaceFn(list[i])`. ```javascript const result = R.pipe( [1, 2, 3], - R.modifyItemAtIndex(1, R.add(1)) + R.modifyItemAtIndex(1, x => x + 1) ) // => [1, 3, 3] ``` -Try this R.modifyItemAtIndex example in Rambda REPL +Try this R.modifyItemAtIndex example in Rambda REPL
@@ -8926,7 +8926,7 @@ const result = await R.pipeAsync( await R.delay(100) return x + 2 }, - R.add(2), + x => x +2, async x => { const delayed = await R.delay(100) return delayed + x @@ -8935,7 +8935,7 @@ const result = await R.pipeAsync( // `result` resolves to `RAMBDAX_DELAY104` ``` -Try this R.pipeAsync example in Rambda REPL +Try this R.pipeAsync example in Rambda REPL
@@ -10522,6 +10522,25 @@ describe('R.sortBy', () => { sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[] ``` +```javascript +const list = [ + {a: 2}, + {a: 3}, + {a: 1} +] +const sortFn = x => x.a + +const result = R.sortByDescending(sortFn)(list) +const expected = [ + {a: 3}, + {a: 2}, + {a: 1} +] +// => `result` is equal to `expected` +``` + +Try this R.sortByDescending example in Rambda REPL +
All TypeScript definitions @@ -10559,6 +10578,23 @@ sortByPath( It sorts `list` by the value of `path` property. +```javascript +const list = [ + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, + {a: {b: 3}, id:3}, +] +const result = R.sortByPath('a.b')(list) +const expected = [ + {a: {b: 1}, id:2}, + {a: {b: 2}, id:1}, + {a: {b: 3}, id:3} +] +// => `result` is equal to `expected` +``` + +Try this R.sortByPath example in Rambda REPL +
All TypeScript definitions @@ -10663,6 +10699,23 @@ sortByPathDescending( ): (list: S[]) => S[] ``` +```javascript +const list = [ + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, + {a: {b: 3}, id:3}, +] +const result = R.sortByPathDescending('a.b')(list) +const expected = [ + {a: {b: 3}, id:3} + {a: {b: 2}, id:1}, + {a: {b: 1}, id:2}, +] +// => `result` is equal to `expected` +``` + +Try this R.sortByPathDescending example in Rambda REPL +
All TypeScript definitions @@ -10736,11 +10789,11 @@ It returns a sorted version of `input` object. ```javascript const predicate = (propA, propB, valueA, valueB) => valueA > valueB ? -1 : 1 -const result = R.sortObject(predicate, {a:1, b: 4, c: 2}) +const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) // => {b: 4, c: 2, a: 1} ``` -Try this R.sortObject example in Rambda REPL +Try this R.sortObject example in Rambda REPL
@@ -11101,8 +11154,8 @@ It splits `input` into slices of `sliceLength`. ```javascript const result = [ - R.splitEvery(2, [1, 2, 3]), - R.splitEvery(3, 'foobar') + R.splitEvery(2)([1, 2, 3]), + R.splitEvery(3)('foobar') ] const expected = [ @@ -11112,7 +11165,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.splitEvery example in Rambda REPL +Try this R.splitEvery example in Rambda REPL
@@ -11199,11 +11252,11 @@ It returns a merged list of `x` and `y` with all equal elements removed. const x = [ 1, 2, 3, 4 ] const y = [ 3, 4, 5, 6 ] -const result = R.symmetricDifference(x, y) +const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` -Try this R.symmetricDifference example in Rambda REPL +Try this R.symmetricDifference example in Rambda REPL
@@ -11770,16 +11823,16 @@ One use case is debugging in the middle of `R.pipe` chain. ```javascript const list = [1, 2, 3] -R.pipe( +const result = R.pipe( list, - R.map(x => x * 2) + R.filter(x => x > 1), R.tap(console.log), - R.filter(x => x > 1) + R.map(x => x * 2) ) // => `2` and `3` will be logged ``` -Try this R.tap example in Rambda REPL +Try this R.tap example in Rambda REPL
@@ -12341,11 +12394,11 @@ It takes two lists and return a new list containing a merger of both list with r `R.equals` is used to compare for duplication. ```javascript -const result = R.union([1,2,3], [3,4,5]); +const result = R.union([1,2,3])([3,4,5]); // => [1, 2, 3, 4, 5] ``` -Try this R.union example in Rambda REPL +Try this R.union example in Rambda REPL
@@ -12556,12 +12609,12 @@ It applies uniqueness to input list based on function that defines what to be us ```javascript const list = [{a:1}, {a:2}, {a:1}] -const result = R.uniqBy(x => x, list) +const result = R.uniqBy(x => x)(list) // => [{a:1}, {a:2}] ``` -Try this R.uniqBy example in Rambda REPL +Try this R.uniqBy example in Rambda REPL
@@ -13038,11 +13091,11 @@ const index = 2 const newValue = 88 const list = [1, 2, 3, 4, 5] -const result = R.update(index, newValue, list) +const result = R.update(index, newValue)(list) // => [1, 2, 88, 4, 5] ``` -Try this R.update example in Rambda REPL +Try this R.update example in Rambda REPL
@@ -13126,26 +13179,24 @@ If the `predicate` returns `false`, then it will simply return `input`. ```javascript const predicate = x => typeof x === 'number' -const whenTrueFn = R.add(11) - -const fn = when(predicate, whenTrueResult) +const fn = R.when(predicate)(x => x + 1) const positiveInput = 88 const negativeInput = 'foo' const result = [ fn(positiveInput), - fn(positiveInput), + fn(negativeInput), ] const expected = [ - 99, - 'foo', + 89, + 'foo1', ] // => `result` is equal to `expected` ``` -Try this R.when example in Rambda REPL +Try this R.when example in Rambda REPL
@@ -13377,11 +13428,11 @@ zipWith( const list1 = [ 10, 20, 30, 40 ] const list2 = [ 100, 200 ] -const result = R.zipWith(R.add, list1)(list2) +const result = R.zipWith((x, y) => x + y, list1)(list2) // => [110, 220] ``` -Try this R.zipWith example in Rambda REPL +Try this R.zipWith example in Rambda REPL
From 2e067fb1067c495a9f03f6594a328a3ff53cfdcf Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 22:25:04 +0300 Subject: [PATCH 10/54] chore@small --- README.md | 32 ++++++++++---------------------- docs/README.md | 32 ++++++++++---------------------- files/index.d.ts | 2 +- index.d.cts | 2 +- index.d.ts | 2 +- source/indexBy-spec.ts | 28 ++++++++-------------------- 6 files changed, 31 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 290df23b..36bff73b 100644 --- a/README.md +++ b/README.md @@ -4886,7 +4886,7 @@ describe('R.includes', () => { indexBy( property: K -): (list: readonly T[]) => Record +): (list: readonly T[]) => Record ``` It transforms list of objects to object using specified property as the base for the returned object. @@ -4907,7 +4907,7 @@ const result = R.indexBy( ```typescript indexBy( property: K -): (list: readonly T[]) => Record; +): (list: readonly T[]) => Record; indexBy( property: K ): (list: T[]) => Record; @@ -4968,26 +4968,14 @@ test('happy', () => { ```typescript import { pipe, indexBy } from 'rambda' -describe('R.indexBy', () => { - it('using `as const`', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] as const - const result = pipe( - list, - indexBy('id') - ) - - result.abc // $ExpectType {id: string, title: string} - result.xyz // $ExpectType {id: string, title: string} - }) - it('general case', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] - const result = pipe( - list, - indexBy('id') - ) - result.abc // $ExpectType {id: string, title: string} - result.foo // $ExpectType {id: string, title: string} - }) +it('R.indexBy', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + const result = pipe( + list, + indexBy('id') + ) + result.abc // $ExpectType {id: string, title: string} + result.foo // $ExpectType {id: string, title: string} }) ``` diff --git a/docs/README.md b/docs/README.md index 290df23b..36bff73b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4886,7 +4886,7 @@ describe('R.includes', () => { indexBy( property: K -): (list: readonly T[]) => Record +): (list: readonly T[]) => Record ``` It transforms list of objects to object using specified property as the base for the returned object. @@ -4907,7 +4907,7 @@ const result = R.indexBy( ```typescript indexBy( property: K -): (list: readonly T[]) => Record; +): (list: readonly T[]) => Record; indexBy( property: K ): (list: T[]) => Record; @@ -4968,26 +4968,14 @@ test('happy', () => { ```typescript import { pipe, indexBy } from 'rambda' -describe('R.indexBy', () => { - it('using `as const`', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] as const - const result = pipe( - list, - indexBy('id') - ) - - result.abc // $ExpectType {id: string, title: string} - result.xyz // $ExpectType {id: string, title: string} - }) - it('general case', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] - const result = pipe( - list, - indexBy('id') - ) - result.abc // $ExpectType {id: string, title: string} - result.foo // $ExpectType {id: string, title: string} - }) +it('R.indexBy', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + const result = pipe( + list, + indexBy('id') + ) + result.abc // $ExpectType {id: string, title: string} + result.foo // $ExpectType {id: string, title: string} }) ``` diff --git a/files/index.d.ts b/files/index.d.ts index 8e1497ff..02c9052d 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -4794,7 +4794,7 @@ Notes: // @SINGLE_MARKER export function indexBy( property: K -): (list: readonly T[]) => Record; +): (list: readonly T[]) => Record; export function indexBy( property: K ): (list: T[]) => Record; diff --git a/index.d.cts b/index.d.cts index 99d14d5d..4c5a888d 100644 --- a/index.d.cts +++ b/index.d.cts @@ -436,7 +436,7 @@ export function includes(valueToFind: T): (input: T[]) => boolean; */ export function indexBy( property: K -): (list: readonly T[]) => Record; +): (list: readonly T[]) => Record; export function indexBy( property: K ): (list: T[]) => Record; diff --git a/index.d.ts b/index.d.ts index 99d14d5d..4c5a888d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -436,7 +436,7 @@ export function includes(valueToFind: T): (input: T[]) => boolean; */ export function indexBy( property: K -): (list: readonly T[]) => Record; +): (list: readonly T[]) => Record; export function indexBy( property: K ): (list: T[]) => Record; diff --git a/source/indexBy-spec.ts b/source/indexBy-spec.ts index a1555cc6..85d0147c 100644 --- a/source/indexBy-spec.ts +++ b/source/indexBy-spec.ts @@ -1,23 +1,11 @@ import { pipe, indexBy } from 'rambda' -describe('R.indexBy', () => { - it('using `as const`', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] as const - const result = pipe( - list, - indexBy('id') - ) - - result.abc // $ExpectType {id: string, title: string} - result.xyz // $ExpectType {id: string, title: string} - }) - it('general case', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] - const result = pipe( - list, - indexBy('id') - ) - result.abc // $ExpectType {id: string, title: string} - result.foo // $ExpectType {id: string, title: string} - }) +it('R.indexBy', () => { + const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] + const result = pipe( + list, + indexBy('id') + ) + result.abc // $ExpectType {id: string, title: string} + result.foo // $ExpectType {id: string, title: string} }) From e3524b7ca2ea34aacf67fef302708c9456b9d5d3 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 6 Jul 2025 22:32:06 +0300 Subject: [PATCH 11/54] chore@small --- README.md | 24 +++++++++++------------- docs/README.md | 24 +++++++++++------------- source/indexBy-spec.ts | 4 ++-- source/transformPropObject-spec.ts | 20 +++++++++----------- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 36bff73b..f44876b0 100644 --- a/README.md +++ b/README.md @@ -4974,8 +4974,8 @@ it('R.indexBy', () => { list, indexBy('id') ) - result.abc // $ExpectType {id: string, title: string} - result.foo // $ExpectType {id: string, title: string} + result.abc // $ExpectType { id: string; title: string; } + result.foo // $ExpectType { id: string; title: string; } }) ``` @@ -11964,18 +11964,16 @@ transformPropObject( ```typescript import { transformPropObject, pipe } from 'rambda' -describe('R.transformPropObject', () => { - it('iterable with one arguments', () => { - const result = pipe( - { a: 1, b: 'foo' }, - transformPropObject(x => { - x // $ExpectType number - return x > 2 - }, 'a'), - ) +it('R.transformPropObject', () => { + const result = pipe( + { a: 1, b: 'foo' }, + transformPropObject(x => { + x // $ExpectType number + return x > 2 + }, 'a'), + ) - result // $ExpectType { a: boolean; b: string; } - }) + result // $ExpectType { b: string; a: boolean; } }) ``` diff --git a/docs/README.md b/docs/README.md index 36bff73b..f44876b0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4974,8 +4974,8 @@ it('R.indexBy', () => { list, indexBy('id') ) - result.abc // $ExpectType {id: string, title: string} - result.foo // $ExpectType {id: string, title: string} + result.abc // $ExpectType { id: string; title: string; } + result.foo // $ExpectType { id: string; title: string; } }) ``` @@ -11964,18 +11964,16 @@ transformPropObject( ```typescript import { transformPropObject, pipe } from 'rambda' -describe('R.transformPropObject', () => { - it('iterable with one arguments', () => { - const result = pipe( - { a: 1, b: 'foo' }, - transformPropObject(x => { - x // $ExpectType number - return x > 2 - }, 'a'), - ) +it('R.transformPropObject', () => { + const result = pipe( + { a: 1, b: 'foo' }, + transformPropObject(x => { + x // $ExpectType number + return x > 2 + }, 'a'), + ) - result // $ExpectType { a: boolean; b: string; } - }) + result // $ExpectType { b: string; a: boolean; } }) ``` diff --git a/source/indexBy-spec.ts b/source/indexBy-spec.ts index 85d0147c..0f0e1b19 100644 --- a/source/indexBy-spec.ts +++ b/source/indexBy-spec.ts @@ -6,6 +6,6 @@ it('R.indexBy', () => { list, indexBy('id') ) - result.abc // $ExpectType {id: string, title: string} - result.foo // $ExpectType {id: string, title: string} + result.abc // $ExpectType { id: string; title: string; } + result.foo // $ExpectType { id: string; title: string; } }) diff --git a/source/transformPropObject-spec.ts b/source/transformPropObject-spec.ts index 9a0779cf..68fc5827 100644 --- a/source/transformPropObject-spec.ts +++ b/source/transformPropObject-spec.ts @@ -1,15 +1,13 @@ import { transformPropObject, pipe } from 'rambda' -describe('R.transformPropObject', () => { - it('iterable with one arguments', () => { - const result = pipe( - { a: 1, b: 'foo' }, - transformPropObject(x => { - x // $ExpectType number - return x > 2 - }, 'a'), - ) +it('R.transformPropObject', () => { + const result = pipe( + { a: 1, b: 'foo' }, + transformPropObject(x => { + x // $ExpectType number + return x > 2 + }, 'a'), + ) - result // $ExpectType { a: boolean; b: string; } - }) + result // $ExpectType { b: string; a: boolean; } }) From e4d38be78f02bc69bb3e4aa32ea0ecc53adce5e3 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 10 Jul 2025 09:09:37 +0300 Subject: [PATCH 12/54] Fix R.includes --- CHANGELOG.md | 2 ++ files/index.d.ts | 4 ++-- source/includes-spec.ts | 13 ++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 877bbc8b..4910b6b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ - Fix issue with wrong order of inputs in `R.propOr` - [Issue #768](https://github.com/selfrefactor/rambda/discussions/768) +- Fix issue with TypeScript definitions for `R.includes`- [Issue #768](https://github.com/selfrefactor/rambda/discussions/768) + 10.3.0 - Add `R.mapPropObject` diff --git a/files/index.d.ts b/files/index.d.ts index 93774d29..1a5b52a4 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -766,8 +766,8 @@ Notes: */ // @SINGLE_MARKER -export function includes(valueToFind: T): (input: string) => boolean; -export function includes(valueToFind: T): (input: T[]) => boolean; +export function includes(s: string): (list: readonly string[] | string) => boolean; +export function includes(target: T): (list: readonly T[]) => boolean; /* Method: excludes diff --git a/source/includes-spec.ts b/source/includes-spec.ts index 39b87313..855e69d4 100644 --- a/source/includes-spec.ts +++ b/source/includes-spec.ts @@ -1,4 +1,5 @@ -import { includes, pipe } from 'rambda' +import { includes } from 'ramda' +import { pipe } from 'rambda' describe('R.includes', () => { it('happy', () => { @@ -10,4 +11,14 @@ describe('R.includes', () => { const result = pipe('foo', includes('bar')) result // $ExpectType boolean }) + it('with array of strings', () => { + const result = pipe(['1','2'], includes('1')) + result // $ExpectType boolean + }) + it('without R.pipe', () => { + const result1 = includes('1')(['1', '2']) + const result2 = includes(1)([1, 2]) + result1 // $ExpectType boolean + result2 // $ExpectType boolean + }) }) From 8337fe9fff2ac159b332e69a4800e380fe97f4e2 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 10 Jul 2025 09:13:11 +0300 Subject: [PATCH 13/54] chore@small --- source/modifyPath.spec.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/modifyPath.spec.js b/source/modifyPath.spec.js index 5b5186e1..3a7bbfd9 100644 --- a/source/modifyPath.spec.js +++ b/source/modifyPath.spec.js @@ -4,3 +4,8 @@ test('happy', () => { const result = modifyPath('a.b.c', x => x + 1)({ a: { b: { c: 1 } } }) expect(result).toEqual({ a: { b: { c: 2 } } }) }) + +test('works only on existing paths', () => { + const result = modifyPath('a.b.d', x => x + 1)({ a: { b: { c: 1 } } }) + expect(result).toEqual({ a: { b: { c: 1 } } }) +}) From f553d1526b62e443a97d7dd2ca7e66afabeaeae4 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 12 Jul 2025 08:18:14 +0300 Subject: [PATCH 14/54] d --- CHANGELOG.md | 776 +------------------------------------- README.md | 659 +++----------------------------- docs/README.md | 663 +++----------------------------- files/CHANGELOG_v8.md | 765 +++++++++++++++++++++++++++++++++++++ files/README_START.md | 23 +- index.d.cts | 4 +- index.d.ts | 4 +- source/modifyPath.spec.js | 8 +- 8 files changed, 898 insertions(+), 2004 deletions(-) create mode 100644 files/CHANGELOG_v8.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 4910b6b3..43832c8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,11 @@ 10.3.1 -- Fix issue with wrong order of inputs in `R.propOr` - [Issue #768](https://github.com/selfrefactor/rambda/discussions/768) +- Fix issue with wrong order of inputs in `R.propOr` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) -- Fix issue with TypeScript definitions for `R.includes`- [Issue #768](https://github.com/selfrefactor/rambda/discussions/768) +- Fix issue with TypeScript definitions for `R.includes`- [Issue #781](https://github.com/selfrefactor/rambda/issues/781) 10.3.0 -- Add `R.mapPropObject` -10.3.0 - - Add `R.mapPropObject` - Add `R.duplicateBy` @@ -489,771 +486,4 @@ Add the following methods: > Reason for breaking change - synchronize with Ramda `0.29.0` release: -- change order of `R.propEq` - [Ramda MR](https://github.com/ramda/ramda/pull/2938/files) - - -7.5.0 - -- IMPORTANT: Remove `export` property in `package.json` in order to allow `Rambda` support for projects with `"type": "module"` in `package.json` - [Issue #667](https://github.com/selfrefactor/rambda/issues/657) - -- Add `R.unnest` - [Rambdax issue 89](https://github.com/selfrefactor/rambdax/issues/89) - -- `R.uniq` is not using `R.equals` as Ramda does - [Issue #88](https://github.com/selfrefactor/rambdax/issues/88) - -- Fix `R.path(['non','existing','path'], obj)` TS definition as 7.4.0 release caused TS errors - [Issue #668](https://github.com/selfrefactor/rambda/issues/668) - -7.4.0 - -- Synchronize with `@types/ramda` - `R.prop`, `R.path`, `R.pickAll` - -- Remove `esm` Rollup output due to tree-shaking issues. - -- Upgrade all dev dependencies. - -7.3.0 - -- Important - changing import declaration in `package.json` in order to fix tree-shaking issue - [Issue #647](https://github.com/selfrefactor/rambda/issues/647) - -- Add `R.modify` - -- Allow multiple inputs in TypeScript versions of `R.anyPass` and `R.allPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/604) - -- Using wrong clone of object in `R.mergeDeepRight` - [Issue #650](https://github.com/selfrefactor/rambda/issues/650) - -- Missing early return in `R.where` - [Issue #648](https://github.com/selfrefactor/rambda/issues/648) - -- `R.allPass` doesn't accept more than 1 parameters for function predicates- [Issue #604](https://github.com/selfrefactor/rambda/issues/604) - -7.2.1 - -- Remove bad typings of `R.propIs` which caused the library to cannot be build with TypeScript. - -- Drop support for `Wallaby` as per [https://github.com/wallabyjs/public/issues/3037](https://github.com/wallabyjs/public/issues/3037) - -7.2.0 - -- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) - -- Wrong curried typings in `R.anyPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/642) - -- `R.modifyPath` not exported - [Issue #640](https://github.com/selfrefactor/rambda/issues/640) - -- Add new method `R.uniqBy`. Implementation is coming from [Ramda MR#2641](https://github.com/ramda/ramda/pull/2641) - -- Apply the following changes from `@types/rambda`: - --- [https://github.com/DefinitelyTyped/DefinitelyTyped/commit/bab47272d52fc7bb81e85da36dbe9c905a04d067](add `AnyFunction` and `AnyConstructor`) - --- Improve `R.ifElse` typings - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59291 - --- Make `R.propEq` safe for `null/undefined` arguments - https://github.com/ramda/ramda/pull/2594/files - -7.1.4 - -- `R.mergeRight` not found on `Deno` import - [Issue #633](https://github.com/selfrefactor/rambda/issues/633) - -7.1.0 - -- Add `R.mergeRight` - introduced by Ramda's latest release. While Ramda renames `R.merge`, Rambda will keep `R.merge`. - -- Rambda's `pipe/compose` doesn't return proper length of composed function which leads to issue with `R.applySpec`. It was fixed by using Ramda's `pipe/compose` logic - [Issue #627](https://github.com/selfrefactor/rambda/issues/627) - -- Replace `Async` with `Promise` as return type of `R.type`. - -- Add new types as TypeScript output for `R.type` - "Map", "WeakMap", "Generator", "GeneratorFunction", "BigInt", "ArrayBuffer" - -- Add `R.juxt` method - -- Add `R.propSatisfies` method - -- Add new methods after `Ramda` version upgrade to `0.28.0`: - --- R.count --- R.modifyPath --- R.on --- R.whereAny --- R.partialObject - -7.0.3 - -Rambda.none has wrong logic introduced in version `7.0.0` - [Issue #625](https://github.com/selfrefactor/rambda/issues/625) - -7.0.2 - -Rambda doesn't work with `pnpm` due to wrong export configuration - [Issue #619](https://github.com/selfrefactor/rambda/issues/619) - -7.0.1 - -- Wrong ESM export configuration in `package.json` - [Issue #614](https://github.com/selfrefactor/rambda/issues/614) - -7.0.0 - -- Breaking change - sync `R.compose`/`R.pipe` with `@types/ramda`. That is significant change so as safeguard, it will lead a major bump. Important - this lead to raising required TypeScript version to `4.2.2`. In other words, to use `Rambda` you'll need TypeScript version `4.2.2` or newer. - -Related commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1 - -There are several other changes in `@types/ramda` as stated in [this comment](https://github.com/ramda/ramda/issues/2976#issuecomment-990408945). This leads to change of typings for the following methods in **Rambda**: - --- R.unless - --- R.toString - --- R.ifElse - --- R.always - --- R.complement - --- R.cond - --- R.is - --- R.sortBy - --- R.dissoc - --- R.toPairs - --- R.assoc - --- R.toLower - --- R.toUpper - -- One more reason for the breaking change is changing of export declarations in `package.json` based on [this blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing) and [this merged Ramda's PR](https://github.com/ramda/ramda/pull/2999). This also led to renaming of `babel.config.js` to `babel.config.cjs`. - -- Add `R.apply`, `R.bind` and `R.unapply` - -- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior. - -- Remove unused typing for `R.chain`. - -- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws. - -- Make `R.lastIndexOf` follow the logic of `R.indexOf`. - -- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results. - -- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599) - -- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595) - -- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604) - -- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606). - -- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt). - -- Improve performance of `R.uniqWith`. - -- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) - -- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943). - -- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608) - -- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609) - -6.9.0 - -- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581) - -Fixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`: - -- R.includes -- R.intersection -- R.difference -- R.excludes -- R.symmetricDifference -- R.union - -- R.without no longer support the following case - `without('0:1', ['0', '0:1']) // => ['0']`. Now it throws as the first argument should be a list, not a string. Ramda, on the other hand, returns an empty list - https://github.com/ramda/ramda/issues/3086. - -6.8.3 - -- Fix TypeScript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572) - -- Add `R.objOf` method - -- Add `R.mapObjIndexed` method - -- Publish shorter README.md version to NPM - -6.8.0 - -- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572) - -- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565) - -- Fix `R.intersection` wrong order compared to Ramda. - -- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577) - -6.7.0 - -- Remove `ts-toolbelt` types from TypeScript definitions. Most affected are the following methods, which lose one of its curried definitions: - -1. R.maxBy -2. R.minBy -3. R.pathEq -4. R.viewOr -5. R.when -6. R.merge -7. R.mergeDeepRight -8. R.mergeLeft - -6.6.0 - -- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions. - -- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`. - -- Use uglify plugin for UMD bundle. - -- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570) - -- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567) - -6.5.3 - -- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes` - -This is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086 - -6.5.2 - -- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent. - -- Update dependencies - -6.5.1 - -Fix wrong versions in changelog - -6.5.0 - -- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation. - -- `R.equals` supports equality of functions. - -- `R.pipe` doesn't use `R.compose`. - -- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types - -- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings - -- Add `CHANGELOG.md` file in release files list - -6.4.0 - -- Close [Issue #560](https://github.com/selfrefactor/rambda/issues/560) - apply immutable lint to TypeScript definitions - -- Close [Issue #553](https://github.com/selfrefactor/rambda/issues/553) - fix problem with curried typings of `R.prop` - -- Fix wrong `R.last` typing - -- Upgrade all `rollup` related dependencies - -- `R.type` supports `Symbol` just like *Ramda*. - -- Remove file extension in `main` property in `package.json` in order to allow `experimental-modules`. See also this Ramda's PR - https://github.com/ramda/ramda/pull/2678/files - -- Import `R.indexBy`/`R.when`/`R.zipObj`/`R.propEq`/`R.complement` changes from recent `@types/ramda` release. - -- `R.tryCatch` stop supporting asynchronous functions; the previous behaviour is exported to *Rambdax* as `R.tryCatchAsync` - -6.3.1 - -- Fix missing `Evolved` declaration in TypeScript definition - -6.3.0 - -- Add `R.takeLastWhile` - -- Add `R.dropWhile` - -- Add `R.eqProps` - -- Add `R.dropLastWhile` - -- Add `R.dropRepeats` - -- Add `R.dropRepeatsWith` - -- Add `R.evolve` - -- Add typings for `R.takeWhile` when iterable is a string - -6.2.0 - -- Add `R.props` - -- Add `R.zipWith` - -- Add `R.splitAt` - -- Add `R.splitWhen` - -- Close [Issue #547](https://github.com/selfrefactor/rambda/issues/547) - restore `readonly` declaration in TypeScript definitions. - -- `R.append`/`R.prepend` now work only with arrays just like Ramda. Previous behaviour was for them to work with both arrays and strings. - -- Sync `R.pluck` typings with `@types/ramda` as there was a tiny difference. - -6.1.0 - -- Fix `R.and` wrong definition, because the function doesn't convert the result to boolean. This introduce another difference with `@types/ramda`. - -- Add `R.once` - -- Add `R.or` - -6.0.1 - -- Fix typing of `R.reject` as it wrongly declares that with object, it pass property to predicate. - -6.0.0 - -- Breaking change - `R.map`/`R.filter`/`R.reject`/`R.forEach`/`R.partition` doesn't pass index as second argument to the predicate, when looping over arrays. The old behaviour of *map*, *filter* and *forEach* can be found in Rambdax methods *R.mapIndexed*, *R.filterIndexed* and *R.forEachIndexed*. - -- Breaking change - `R.all`/`R.none`/`R.any`/`R.find`/`R.findLast`/`R.findIndex`/`R.findLastIndex` doesn't pass index as second argument to the predicate. - -- Change `R.assocPath` typings so the user can explicitly sets type of the new object - -- Typings of `R.assoc` match its `@types/ramda` counterpart. - -- Simplify `R.forEach` typings - -- Remove `ReadonlyArray` pattern from TypeScript definitions - not enough value for the noise it adds. - -5.13.1 - -- Fix wrong `R.takeWhile` - -5.13.0 - -- Add `R.takeWhile` method - -- Fix `R.lensPath` issue when using string as path input. The issue was introduced when fixing [Issue #524](https://github.com/selfrefactor/rambda/issues/524) in the previous release. - -5.12.1 - -- Close [Issue #524](https://github.com/selfrefactor/rambda/issues/524) - - wrong `R.assocPath` when path includes numbers - -- `R.includes` throws on wrong input, i.e. `R.includes(1, null)` - -5.12.0 - -- Add `R.move` method - -- Add `R.union` method - -- Close [Issue #519](https://github.com/selfrefactor/rambda/issues/519) - -`ts-toolbelt` needs other type of export with `--isolatedModules` flag - -- Change `R.when` implementation and typings to match those of `Ramda` - -- `R.over` and `R.set` use `R.curry` instead of manual currying - -- `R.lensPath` typings support string as path, i.e. `'a.b'` instead of `['a', 'b']` - -- `R.equals` now supports negative zero just like `Ramda.equals` - -- `R.replace` uses `R.curry` - -5.11.0 - -Forgot to export `R.of` because of wrong marker in `files/index.d.ts` - -5.10.0 - -Close [Issue #514](https://github.com/selfrefactor/rambda/issues/514) - -wrong `R.length` with empty string - -Close [Issue #511](https://github.com/selfrefactor/rambda/issues/511) - error in `ts-toolbelt` library - -Close [Issue #510](https://github.com/selfrefactor/rambda/issues/510) - `R.clamp` should throw if min argument is greater than max argument - -- [PR #508](https://github.com/selfrefactor/rambda/pull/508) - add `R.of` - -- Definition of `R.curry` are not same as those of `@types/ramda` - -- Definitions of `R.either` is same as that of `R.both` - -- Definitions of `R.ifElse` no longer use `any` type - -- Definition of `R.flatten` requires passing type for the output - -- Fix definition of `R.propOr`, `R.dissoc` - -- Fix curried definitions of `R.take`, `R.takeLast`, `R.drop` and `R.dropLast` - -- 5.9.0 - -- `R.pickAll` definition allows passing string as path to search. - -- `R.propEq` definition is now similar to that in `@types/ramda`. - -- `R.none` matches `R.all` implementation and pass index as second argument to predicate input. - -- `R.reduce` - drop support for object as iterable. Now it throws the same error as Ramda. Also instead of returning the initial value when iterable is `undefined`, now it throws. - -Add index as additional argument to the TypeScript definitions of the following methods: - -- R.all -- R.find -- R.findLast -- R.findIndex -- R.findLastIndex - -- 5.8.0 - -Add `R.mergeAll` -Add `R.mergeDeepRight` -Add `R.mergeLeft` -Add `R.partition` -Add `R.pathEq` -Add `R.tryCatch` -Add `R.unless` -Add `R.whereEq` -Add `R.where` - -- Add `R.last` typing for empty array - -- 5.7.0 Revert [PR #469](https://github.com/selfrefactor/rambda/pull/469) as `R.curry` was slow | Also now `R.flip` throws if arity is greater than or equal to 5 - -- 5.6.3 Merge several PRs of [@farwayer](https://github.com/farwayer) - -- [PR #482](https://github.com/selfrefactor/rambda/pull/482) - improve `R.forEach` performance by not using `R.map` - -- [PR #485](https://github.com/selfrefactor/rambda/pull/485) - improve `R.map` performance - -- [PR #482](https://github.com/selfrefactor/rambda/pull/486) - improve `R.reduce` performance - -- Fix missing high arity typings for `R.compose/pipe` - -- `R.merge` definitions match those of `@types/ramda` - -- Remove `dist` folder from Rambda repo - -- 5.6.2 - -Close [Issue #476](https://github.com/selfrefactor/rambda/issues/476) - typesafe `R.propEq` definitions - -Approve [PR #477](https://github.com/selfrefactor/rambda/pull/477) - fix `R.groupWith` when list length is 1 - -- 5.6.1 - -Update `ts-toolbelt` files as now there is update pipeline for it. - -Approve [PR #474](https://github.com/selfrefactor/rambda/pull/474) - intruduce internal `isArray` helper - -- 5.6.0 - -Approve [PR #469](https://github.com/selfrefactor/rambda/pull/469) - R.flip supports any arity | implement `R.curry` with `R.curryN` add `R.applySpec` - -- 5.5.0 - -Close [Issue #464](https://github.com/selfrefactor/rambda/issues/464) - `R.flip` should handle functions with arity above 2 - -Close [Issue #468](https://github.com/selfrefactor/rambda/issues/468) - `fs-extra` should be dev dependency as it was wrongly added as production dependency in `5.2.0` - -`R.flip` typings now match `@types/ramda` typings - -Add `R.hasPath` method - -Add `R.mathMod` typings - -- 5.4.3 - -Fix `R.omit` typings - -- 5.4.2 - -Fix `R.pick` typings - -> Close [Issue #460](https://github.com/selfrefactor/rambda/issues/460) - `R.paths` should be curried - -- 5.4.1 - -> Close [Issue #458](https://github.com/selfrefactor/rambda/issues/458) - wrong `R.propIs` typing - -- 5.4.0 - -> Close [Issue #408](https://github.com/selfrefactor/rambda/issues/408) - add `R.chain` - -- 5.3.0 - -> Close [Issue #430](https://github.com/selfrefactor/rambda/issues/430) - add `R.when` - -Also restore `R.converge`, `R.findLast`, `R.findLastIndex` and `R.curryN` as I have forgotten to export them when releasing `5.2.0`. - -- 5.2.1 - -Fix TypeScript comment for every method - -- 5.2.0 - -Release new documentation site - -`Ramda` repo now holds all `Rambdax` methods and tests - -- 5.1.1 - -Add `R.converge` and `R.curryN` from [PR #412](https://github.com/selfrefactor/rambda/pull/412) - -Close [Issue #410](https://github.com/selfrefactor/rambda/issues/410) - wrong implementation of `R.groupWith` - -Close [Issue #411](https://github.com/selfrefactor/rambda/issues/411) - change the order of declared `R.map` typings rules - -- 5.0.0 - -Move `R.partialCurry` to Rambdax(reason for major bump). - -Use new type of export in TypeScript definitions. - -Approve [PR #381](https://github.com/selfrefactor/rambda/pull/381) - add `R.applySpec` - -- 4.6.0 - -Approve [PR #375](https://github.com/selfrefactor/rambda/pull/375) - add lenses(Thank you [@synthet1c](https://github.com/synthet1c)) - -Add `R.lens` - -Add `R.lensIndex` - -Add `R.lensPath` - -Add `R.lensProp` - -Add `R.over` - -Add `R.set` - -Add `R.view` - -> Sync with Ramda 0.27 - -Add `R.paths` - -Add `R.xor` - -> Close [Issue #373](https://github.com/selfrefactor/rambda/issues/373) - -Add `R.cond` - -- 4.5.0 Add `R.clamp` - -- 4.4.2 Improve `R.propOr` typings - -- 4.4.1 Make `R.reject` has the same typing as `R.filter` - -- 4.4.0 Several changes: - -Close [Issue #317](https://github.com/selfrefactor/rambda/issues/317) - add `R.transpose` - -Close [Issue #325](https://github.com/selfrefactor/rambda/issues/325) - `R.filter` should return equal values for bad inputs `null` and `undefined` - -Approve suggestion for `R.indexBy` to accept string not only function as first argument. - -Edit of `R.path` typings - -- 4.2.0 Approve [PR #314](https://github.com/selfrefactor/rambda/pull/314) - add `R.and` - -- 4.1.1 Add missing typings for `R.slice` - -- 4.1.0 Add `R.findLast` and `R.findLastIndex` - -- 4.0.2 Fix `R.isEmpty` wrong behaviour compared to the Ramda method - -- 4.0.1 Approve [PR #289](https://github.com/selfrefactor/rambda/pull/289) - remove console.log in `R.values` method - -- 4.0.0 Multiple breaking changes as Rambda methods are changed in order to increase the similarity between with Ramda - -Add to `Differences`: - -```text -R.type can return 'NaN' - -R.compose doesn't pass `this` context - -R.clone doesn't work with number, booleans and strings as input -``` - -All breaking changes: - --- R.add works only with numbers - --- Fix R.adjust which had wrong order of arguments - --- R.adjust works when index is out of bounds - --- R.complement support function with multiple arguments - --- R.compose/pipe throws when called with no argument - --- R.clone works with `Date` value as input - --- R.drop/dropLast/take/takeLast always return new copy of the list/string - --- R.take/takeLast return original list/string with negative index - --- R.equals handles `NaN` and `RegExp` types - --- R.type/R.equals supports `new Boolean/new Number/new Date/new String` expressions - --- R.has works with non-object - --- R.ifElse pass all arguments - --- R.length works with bad input - --- R.propEq work with bad input for object argument - --- R.range work with bad inputs - --- R.times work with bad inputs - --- R.reverse works with strings - --- R.splitEvery throws on non-positive integer index - --- R.test throws just like Ramda when first argument is not regex - --- R.values works with bad inputs - --- R.zipObj ignores extra keys - -- 3.3.0 - -This is pre `4.0.0` release and it contains all of the above changes - -Close [issue #287](https://github.com/selfrefactor/rambda/issues/287) - `ts-toolbelt` directory was changed but not reflected in `files` property in `package.json` - -- 3.2.5 - -Close [issue #273](https://github.com/selfrefactor/rambda/issues/273) - ts-toolbelt needs other type of export when `isolatedModules` TypeScript property - -Close [issue #245](https://github.com/selfrefactor/rambda/issues/245) - complete typings tests for methods that have more specific TypeScript definitions - -- 3.2.1 Fast fix for [issue #273](https://github.com/selfrefactor/rambda/issues/273) - messed up typings - -- 3.2.0 There are several changes: - -Close [issue #263](https://github.com/selfrefactor/rambda/issues/263) - broken curry typing solved by `ts-toolbelt` local dependency. - -Add `R.partialCurry` typings. - -Approve [PR #266](https://github.com/selfrefactor/rambda/pull/266) that adds `R.slice` method. - -- 3.1.0 This might be breaking change for TypeScript users, as very different definitions are introduced. With the previous state of the definitions, it was not possible to pass `dtslint` typings tests. - -- `R.either` and `R.both` supports multiple arguments as they should. - -- Several methods added by [@squidfunk](https://github.com/squidfunk) - `R.assocPath`, `R.symmetricDifference`, `R.intersperse`, `R.intersection` and `R.difference` - -- 3.0.1 Close [issue #234](https://github.com/selfrefactor/rambda/issues/234) - wrong curry typing - -- 3.0.0 Deprecate `R.contains`, while `R.includes` is now following Ramda API(it uses `R.equals` for comparision) - -- 2.14.5 `R.without` needs currying - -- 2.14.4 Close [issue #227](https://github.com/selfrefactor/rambda/issues/227) - add index as third argument of `R.reduce` typings - -- 2.14.2 Use `R.curry` with `R.reduce` as manual curry there didn't work as expected. - -- 2.14.1 Fix wrong typescript with `R.head` - [PR #228](https://github.com/selfrefactor/rambda/pull/228) pushed by [@tonivj5](https://github.com/tonivj5) - -- 2.14.0 Add `R.groupWith` by @selfrefactor | Add `R.propOr`, `R.mathMod`, `R.mean`, `R.median`, `R.negate`, `R.product` by [@ku8ar](https://github.com/ku8ar) - -- 2.13.0 Add `R.identical` - [PR #217](https://github.com/selfrefactor/rambda/pull/217) pushed by [@ku8ar](https://github.com/ku8ar) - -- 2.12.0 Add `R.propIs` - [PR #213](https://github.com/selfrefactor/rambda/pull/213) and add `R.sum` - [issue #207](https://github.com/selfrefactor/rambda/issues/207) - -- 2.11.2 Close Rambdax [issue #32](https://github.com/selfrefactor/rambdax/issues/32) - wrong `R.type` when function is input - -- 2.11.1 Approve [PR #182](https://github.com/selfrefactor/rambda/pull/182) - Changed typings to allow object as input to `R.forEach` and `R.map` - -- 2.11.0 Approve [PR #179](https://github.com/selfrefactor/rambda/pull/179) - `R.adjust` handles negative index; `R.all` doesn't need `R.filter` - -- 2.10.2 Close [issue #175](https://github.com/selfrefactor/rambda/issues/175) - missing typescript file - -- 2.10.0 Approve huge and important [PR #171](https://github.com/selfrefactor/rambda/pull/171) submitted by [@helmuthdu](https://github.com/helmuthdu) - Add comments to each method, improve TypeScript support - -- 2.9.0 `R.toPairs` and `R.fromPairs` - -- 2.8.0 Approve [PR #165](https://github.com/selfrefactor/rambda/pull/165) `R.clone` - -- 2.7.1 expose `src` | Discussed at [issue #147](https://github.com/selfrefactor/rambda/issues/147) - -- 2.7.0 Approve [PR #161](https://github.com/selfrefactor/rambda/pull/161) `R.isEmpty` - -- 2.6.0 `R.map`, `R.filter` and `R.forEach` pass original object to iterator as third argument | Discussed at [issue #147](https://github.com/selfrefactor/rambda/issues/147) - -- 2.5.0 Close [issue #149](https://github.com/selfrefactor/rambda/issues/149) Add `R.partial` | `R.type` handles `NaN` - -- 2.4.0 Major bump of `Rollup`; Stop building for ES5 - -- 2.3.1 Close [issue #90](https://github.com/selfrefactor/rambda/issues/90) | Add string type of path in `R.pathOr` - -- 2.3.0 Close [issue #89](https://github.com/selfrefactor/rambda/issues/89) | Fix missing `Number` TS definition in `R.type` - -- 2.2.0 `R.defaultTo` accepts indefinite number of input arguments. So the following is valid expression: `const x = defaultTo('foo',null, null, 'bar')` - -- 2.1.0 Restore `R.zip` using [WatermelonDB](https://github.com/Nozbe/WatermelonDB/) implementation. - -- 2.0.0 Major version caused by removing of `R.zip` and `R.addIndex`. [Issue #85](https://github.com/selfrefactor/rambda/issues/85) rightfully finds that the implementation of `R.addIndex` is not correct. This led to removing this method and also of `R.zip` as it had depended on it. The second change is that `R.map`, `R.filter` are passing array index as second argument when looping over arrays. The third change is that `R.includes` will return `false` if input is neigher `string` nor `array`. The previous behaviour was to throw an error. The last change is to increase the number of methods that are passing index as second argument to the predicate function. - -- 1.2.6 Use `src` folder instead of `modules` -- 1.2.5 Fix `omit` typing -- 1.2.4 Add missing TypeScript definitions - [PR#82](https://github.com/selfrefactor/rambda/pull/82) -- 1.2.2 Change curry method used across most of library methods -- 1.2.1 Add `R.assoc` | fix passing `undefined` to `R.map` and `R.merge` [issue #77](https://github.com/selfrefactor/rambda/issues/77) -- 1.2.0 Add `R.min`, `R.minBy`, `R.max`, `R.maxBy`, `R.nth` and `R.keys` -- 1.1.5 Close [issue #74](https://github.com/selfrefactor/rambda/issues/74) `R.zipObj` -- 1.1.4 Close [issue #71](https://github.com/selfrefactor/rambda/issues/71) CRA fail to build `rambda` -- 1.1.3 Approve [PR #70](https://github.com/selfrefactor/rambda/pull/67) implement `R.groupBy` | Close [issue #69](https://github.com/selfrefactor/rambda/issues/69) -- 1.1.2 Approve [PR #67](https://github.com/selfrefactor/rambda/pull/67) use `babel-plugin-annotate-pure-calls` -- 1.1.1 Approve [PR #66](https://github.com/selfrefactor/rambda/pull/66) `R.zip` -- 1.1.0 `R.compose` accepts more than one input argument [issue #65](https://github.com/selfrefactor/rambda/issues/65) -- 1.0.13 Approve [PR #64](https://github.com/selfrefactor/rambda/pull/64) `R.indexOf` -- 1.0.12 Close [issue #61](https://github.com/selfrefactor/rambda/issues/61) make all functions modules -- 1.0.11 Close [issue #60](https://github.com/selfrefactor/rambda/issues/60) problem with babelrc -- 1.0.10 Close [issue #59](https://github.com/selfrefactor/rambda/issues/59) add R.dissoc -- 1.0.9 Close [issue #58](https://github.com/selfrefactor/rambda/issues/58) - Incorrect `R.equals` -- 1.0.8 `R.map` and `R.filter` pass object properties when mapping over objects -- 1.0.7 Add `R.uniqWith` -- 1.0.6 Close [issue #52](https://github.com/selfrefactor/rambda/issues/52) - ES5 compatible code -- 1.0.5 Close [issue #51](https://github.com/selfrefactor/rambda/issues/51) -- 1.0.4 Close [issue #50](https://github.com/selfrefactor/rambda/issues/50) - add `R.pipe` typings -- 1.0.3 `R.ifElse` accept also boolean as condition argument -- 1.0.2 Remove `typedDefaultTo` and `typedPathOr` | Add `R.pickAll` and `R.none` -- 1.0.0 Major change as build is now ES6 not ES5 compatible (Related to [issue #46](https://github.com/selfrefactor/rambda/issues/46))| Making `Rambda` fully tree-shakeable| Edit TypeScript definition -- 0.9.8 Revert to ES5 compatible build - [issue #46](https://github.com/selfrefactor/rambda/issues/46) -- 0.9.7 Refactor for `Rollup` tree-shake | Remove `R.padEnd` and `R.padStart` -- 0.9.6 Close [issue #44](https://github.com/selfrefactor/rambda/issues/44) - `R.reverse` mutates the array -- 0.9.5 Close [issue #45](https://github.com/selfrefactor/rambda/issues/45) - invalid TypeScript typings -- 0.9.4 Add `R.reject` and `R.without` ([PR#41](https://github.com/selfrefactor/rambda/pull/41) [PR#42](https://github.com/selfrefactor/rambda/pull/42)) | Remove 'browser' field in `package.json` due to Webpack bug [4674](https://github.com/webpack/webpack/issues/4674) -- 0.9.3 Add `R.forEach` and `R.times` -- 0.9.2 Add `TypeScript` definitions -- 0.9.1 Close [issue #36](https://github.com/selfrefactor/rambda/issues/36) - move current behaviour of `defaultTo` to a new method `typedDefaultTo`; make `defaultTo` follow Ramda spec; add `pathOr`; add `typedPathOr`. -- 0.9.0 Add `R.pipe` [PR#35](https://github.com/selfrefactor/rambda/pull/35) -- 0.8.9 Add `R.isNil` -- 0.8.8 Migrate to ES modules [PR33](https://github.com/selfrefactor/rambda/pull/33) | Add R.flip to the API | R.map/filter works with objects -- 0.8.7 Change `Webpack` with `Rollup` - [PR29](https://github.com/selfrefactor/rambda/pull/29) -- 0.8.6 Add `R.tap` and `R.identity` -- 0.8.5 Add `R.all`, `R.allPass`, `R.both`, `R.either` and `R.complement` -- 0.8.4 Learning to run `yarn test` before `yarn publish` the hard way -- 0.8.3 Add `R.always`, `R.T` and `R.F` -- 0.8.2 Add `concat`, `padStart`, `padEnd`, `lastIndexOf`, `toString`, `reverse`, `endsWith` and `startsWith` methods -- 0.8.1 Add `R.ifElse` -- 0.8.0 Add `R.not`, `R.includes` | Take string as condition for `R.pick` and `R.omit` -- 0.7.6 Fix incorrect implementation of `R.values` -- 0.7.5 Fix incorrect implementation of `R.omit` -- 0.7.4 [issue #13](https://github.com/selfrefactor/rambda/issues/13) - Fix `R.curry`, which used to return incorrectly `function` when called with more arguments -- 0.7.3 Close [issue #9](https://github.com/selfrefactor/rambda/issues/9) - Compile to `es2015`; Approve [PR #10](https://github.com/selfrefactor/rambda/pull/10) - add `R.addIndex` to the API -- 0.7.2 Add `Promise` support for `R.type` -- 0.7.1 Close [issue #7](https://github.com/selfrefactor/rambda/issues/7) - add `R.reduce` to the API -- 0.7.0 Close [issue #5](https://github.com/selfrefactor/rambda/issues/5) - change name of `curry` to `partialCurry`; add new method `curry`, which works just like Ramda's `curry` -- 0.6.2 Add separate documentation site via `docsify` +- change order of `R.propEq` - [Ramda MR](https://github.com/ramda/ramda/pull/2938/files) \ No newline at end of file diff --git a/README.md b/README.md index c5aa3410..13e47d2f 100644 --- a/README.md +++ b/README.md @@ -76,9 +76,28 @@ it('within Ramda.pipe requires explicit types', () => { }); ``` -IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. +:exclamation: IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. -IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. +In other words: + +```typescript +R.filter(x => x > 1)([1,2,3]) +``` + +might trigger TS error as it not the same as + +```typescript + +R.pipe([1,2,3], R.filter(x => x > 1) +``` + +### :exclamation: All methods are curried + +There is one way to use `Rambda` methods and it is with currying, i.e. using `R.filter(fn, list)` will not work as it is inteded to be `R.filter(fn)(list)`. + +The reason is that all methods are supposed to be used inside `R.pipe`. After all, building chains is the very base of functional programming. + +Of course, there is value in supporting the case where you can pass all inputs at once, but I find that the price in terms of maintainability is not worth it. ### Keep only the most useful methods @@ -3371,10 +3390,6 @@ test('happy', () => { expect(filter(isEven)([1, 2, 3, 4])).toEqual([2, 4]) }) -test('using Boolean', () => { - expect(filter(Boolean)([null, 0, 1, 2])).toEqual([1,2]) -}) - test('using Boolean', () => { expect(filter(Boolean)([null, 0, 1, 2])).toEqual([1,2]) }) @@ -3388,7 +3403,6 @@ test('using Boolean', () => { ```typescript import { filter, pipe } from 'rambda' -import { filter, pipe } from 'rambda' const list = [1, 2, 3] @@ -3549,93 +3563,6 @@ describe('R.filter with array', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) -### filterAsync - -```typescript - -filterAsync( - predicate: (value: T) => Promise, -): (list: T[]) => Promise -``` - -
- -All TypeScript definitions - -```typescript -filterAsync( - predicate: (value: T) => Promise, -): (list: T[]) => Promise; -``` - -
- -
- -R.filterAsync source - -```javascript -export function filterAsync(predicate) { - return async list => { - const willReturn = [] - let index = 0 - for (const x of list) { - if (await predicate(x, index)) { - willReturn.push(list[index]) - } - index++ - } - - return willReturn - } -} -``` - -
- -
- -Tests - -```javascript -import { filterAsync } from './filterAsync.js' - -test('happy', async () => { - const isEven = async n => n % 2 === 0 - - expect(await filterAsync(isEven)([1, 2, 3, 4])).toEqual([2, 4]) -}) -``` - -
- -
- -TypeScript test - -```typescript -import { filterAsync, pipeAsync } from 'rambda' - -const list = [1, 2, 3] - -describe('R.filter with array', () => { - it('within pipe', async () => { - const result = await pipeAsync( - list, - filterAsync(async x => { - x // $ExpectType number - return x > 1 - }), - ) - result // $ExpectType number[] - }) -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) - ### filterObject ```typescript @@ -4855,7 +4782,7 @@ describe('R.head', () => { ```typescript -includes(valueToFind: T): (input: string) => boolean +includes(s: string): (list: readonly string[] | string) => boolean ``` If `input` is string, then this method work as native `String.includes`. @@ -4877,8 +4804,8 @@ const result = [ All TypeScript definitions ```typescript -includes(valueToFind: T): (input: string) => boolean; -includes(valueToFind: T): (input: T[]) => boolean; +includes(s: string): (list: readonly string[] | string) => boolean; +includes(target: T): (list: readonly T[]) => boolean; ```
@@ -4955,7 +4882,8 @@ test('with wrong input that does not throw', () => { TypeScript test ```typescript -import { includes, pipe } from 'rambda' +import { includes } from 'ramda' +import { pipe } from 'rambda' describe('R.includes', () => { it('happy', () => { @@ -4967,6 +4895,16 @@ describe('R.includes', () => { const result = pipe('foo', includes('bar')) result // $ExpectType boolean }) + it('with array of strings', () => { + const result = pipe(['1','2'], includes('1')) + result // $ExpectType boolean + }) + it('without R.pipe', () => { + const result1 = includes('1')(['1', '2']) + const result2 = includes(1)([1, 2]) + result1 // $ExpectType boolean + result2 // $ExpectType boolean + }) }) ``` @@ -5077,109 +5015,6 @@ it('R.indexBy', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexBy) -### indexBy - -```typescript - -indexBy( - property: K -): (list: readonly T[]) => Record -``` - -It transforms list of objects to object using specified property as the base for the returned object. - -```javascript -const result = R.indexBy( - 'id' -)([{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}]) -// => {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} -``` - -Try this R.indexBy example in Rambda REPL - -
- -All TypeScript definitions - -```typescript -indexBy( - property: K -): (list: readonly T[]) => Record; -indexBy( - property: K -): (list: T[]) => Record; - -// API_MARKER_END -// ============================================ -``` - -
- -
- -R.indexBy source - -```javascript -export function indexBy(property){ - return list => { - const toReturn = {} - for (let i = 0; i < list.length; i++){ - const item = list[ i ] - const key = item[property] - if(key !== undefined){ - toReturn[ key ] = item - } - } - - return toReturn - } -} -``` - -
- -
- -Tests - -```javascript -import { indexBy } from './indexBy.js' - -test('happy', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] - - expect( - indexBy('id')(list) - ).toEqual( - {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} - ) -}) -``` - -
- -
- -TypeScript test - -```typescript -import { pipe, indexBy } from 'rambda' - -it('R.indexBy', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] - const result = pipe( - list, - indexBy('id') - ) - result.abc // $ExpectType { id: string; title: string; } - result.foo // $ExpectType { id: string; title: string; } -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexBy) - ### indexOf ```typescript @@ -5238,20 +5073,17 @@ test('will throw with bad input', () => { expect(() => indexOf([])(true)).toThrow() }) -test('with numbers', () => { test('with numbers', () => { expect(indexOf(3)([1, 2, 3, 4])).toBe(2) expect(indexOf(10)([1, 2, 3, 4])).toBe(-1) }) -test('list of objects use R.equals', () => { test('list of objects use R.equals', () => { const listOfObjects = [{ a: 1 }, { b: 2 }, { c: 3 }] expect(indexOf({ c: 4 })(listOfObjects)).toBe(-1) expect(indexOf({ c: 3 })(listOfObjects)).toBe(2) }) -test('list of arrays use R.equals', () => { test('list of arrays use R.equals', () => { const listOfLists = [[1], [2, 3], [2, 3, 4], [2, 3], [1], []] expect(indexOf([])(listOfLists)).toBe(5) @@ -6215,8 +6047,6 @@ export function mapAsync(fn) { return async list => { const willReturn = [] let i = 0 - for (const x of list) { - willReturn.push(await fn(x, i++)) for (const x of list) { willReturn.push(await fn(x, i++)) } @@ -6290,11 +6120,9 @@ test('error', async () => { ```typescript import { mapAsync, pipeAsync, map } from 'rambda' -import { mapAsync, pipeAsync, map } from 'rambda' const list = ['a', 'bc', 'def'] const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) -const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) it('R.mapAsync', async () => { const result = await pipeAsync( @@ -6306,7 +6134,6 @@ it('R.mapAsync', async () => { }), x => x, map(x => x +1), - map(x => x +1), mapAsync(async x => { await delay(100) return x + 1 @@ -7201,11 +7028,9 @@ It replaces `index` in array `list` with the result of `replaceFn(list[i])`. const result = R.pipe( [1, 2, 3], R.modifyItemAtIndex(1, x => x + 1) - R.modifyItemAtIndex(1, x => x + 1) ) // => [1, 3, 3] ``` -Try this R.modifyItemAtIndex example in Rambda REPL Try this R.modifyItemAtIndex example in Rambda REPL
@@ -7363,10 +7188,17 @@ export function modifyPath(pathInput, fn) { ```javascript import { modifyPath } from './modifyPath.js' +const obj = { a: { b: { c: 1 } } } + test('happy', () => { - const result = modifyPath('a.b.c', x => x + 1)({ a: { b: { c: 1 } } }) + const result = modifyPath('a.b.c', x => x + 1)(obj) expect(result).toEqual({ a: { b: { c: 2 } } }) }) + +test('works only on existing paths', () => { + const result = modifyPath('a.b.d', x => x + 1)(obj) + expect(result).toEqual(obj) +}) ```
@@ -9122,7 +8954,6 @@ const result = await R.pipeAsync( return x + 2 }, x => x +2, - x => x +2, async x => { const delayed = await R.delay(100) return delayed + x @@ -9131,7 +8962,6 @@ const result = await R.pipeAsync( // `result` resolves to `RAMBDAX_DELAY104` ``` -Try this R.pipeAsync example in Rambda REPL Try this R.pipeAsync example in Rambda REPL
@@ -10736,25 +10566,6 @@ const expected = [ Try this R.sortByDescending example in Rambda REPL -```javascript -const list = [ - {a: 2}, - {a: 3}, - {a: 1} -] -const sortFn = x => x.a - -const result = R.sortByDescending(sortFn)(list) -const expected = [ - {a: 3}, - {a: 2}, - {a: 1} -] -// => `result` is equal to `expected` -``` - -Try this R.sortByDescending example in Rambda REPL -
All TypeScript definitions @@ -10809,23 +10620,6 @@ const expected = [ Try this R.sortByPath example in Rambda REPL -```javascript -const list = [ - {a: {b: 2}, id:1}, - {a: {b: 1}, id:2}, - {a: {b: 3}, id:3}, -] -const result = R.sortByPath('a.b')(list) -const expected = [ - {a: {b: 1}, id:2}, - {a: {b: 2}, id:1}, - {a: {b: 3}, id:3} -] -// => `result` is equal to `expected` -``` - -Try this R.sortByPath example in Rambda REPL -
All TypeScript definitions @@ -10947,23 +10741,6 @@ const expected = [ Try this R.sortByPathDescending example in Rambda REPL -```javascript -const list = [ - {a: {b: 2}, id:1}, - {a: {b: 1}, id:2}, - {a: {b: 3}, id:3}, -] -const result = R.sortByPathDescending('a.b')(list) -const expected = [ - {a: {b: 3}, id:3} - {a: {b: 2}, id:1}, - {a: {b: 1}, id:2}, -] -// => `result` is equal to `expected` -``` - -Try this R.sortByPathDescending example in Rambda REPL -
All TypeScript definitions @@ -11037,12 +10814,10 @@ It returns a sorted version of `input` object. ```javascript const predicate = (propA, propB, valueA, valueB) => valueA > valueB ? -1 : 1 -const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) // => {b: 4, c: 2, a: 1} ``` -Try this R.sortObject example in Rambda REPL Try this R.sortObject example in Rambda REPL
@@ -11406,8 +11181,6 @@ It splits `input` into slices of `sliceLength`. const result = [ R.splitEvery(2)([1, 2, 3]), R.splitEvery(3)('foobar') - R.splitEvery(2)([1, 2, 3]), - R.splitEvery(3)('foobar') ] const expected = [ @@ -11417,7 +11190,6 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.splitEvery example in Rambda REPL Try this R.splitEvery example in Rambda REPL
@@ -11505,12 +11277,10 @@ It returns a merged list of `x` and `y` with all equal elements removed. const x = [ 1, 2, 3, 4 ] const y = [ 3, 4, 5, 6 ] -const result = R.symmetricDifference(x)(y) const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` -Try this R.symmetricDifference example in Rambda REPL Try this R.symmetricDifference example in Rambda REPL
@@ -12078,19 +11848,15 @@ One use case is debugging in the middle of `R.pipe` chain. ```javascript const list = [1, 2, 3] -const result = R.pipe( const result = R.pipe( list, R.filter(x => x > 1), - R.filter(x => x > 1), R.tap(console.log), R.map(x => x * 2) - R.map(x => x * 2) ) // => `2` and `3` will be logged ``` -Try this R.tap example in Rambda REPL Try this R.tap example in Rambda REPL
@@ -12252,63 +12018,6 @@ it('R.transformPropObject', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#transformPropObject) -### transformPropObject - -```typescript - -transformPropObject( - valueMapper: (value: T[K]) => Value, - prop: K, -): (data: T) => MergeTypes & { [P in K]: Value }> -``` - -```javascript -const fn = (x) => x > 2 -const obj = {a: 1, b: 2} - -const result = R.transformPropObject(fn, 'a')(obj) -// => {a: false, b: 2} -``` - -Try this R.transformPropObject example in Rambda REPL - -
- -All TypeScript definitions - -```typescript -transformPropObject( - valueMapper: (value: T[K]) => Value, - prop: K, -): (data: T) => MergeTypes & { [P in K]: Value }>; -``` - -
- -
- -TypeScript test - -```typescript -import { transformPropObject, pipe } from 'rambda' - -it('R.transformPropObject', () => { - const result = pipe( - { a: 1, b: 'foo' }, - transformPropObject(x => { - x // $ExpectType number - return x > 2 - }, 'a'), - ) - - result // $ExpectType { b: string; a: boolean; } -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#transformPropObject) - ### tryCatch ```typescript @@ -12709,11 +12418,9 @@ It takes two lists and return a new list containing a merger of both list with r ```javascript const result = R.union([1,2,3])([3,4,5]); -const result = R.union([1,2,3])([3,4,5]); // => [1, 2, 3, 4, 5] ``` -Try this R.union example in Rambda REPL Try this R.union example in Rambda REPL
@@ -12926,12 +12633,10 @@ It applies uniqueness to input list based on function that defines what to be us ```javascript const list = [{a:1}, {a:2}, {a:1}] const result = R.uniqBy(x => x)(list) -const result = R.uniqBy(x => x)(list) // => [{a:1}, {a:2}] ``` -Try this R.uniqBy example in Rambda REPL Try this R.uniqBy example in Rambda REPL
@@ -13409,12 +13114,10 @@ const index = 2 const newValue = 88 const list = [1, 2, 3, 4, 5] -const result = R.update(index, newValue)(list) const result = R.update(index, newValue)(list) // => [1, 2, 88, 4, 5] ``` -Try this R.update example in Rambda REPL Try this R.update example in Rambda REPL
@@ -13500,7 +13203,6 @@ If the `predicate` returns `false`, then it will simply return `input`. ```javascript const predicate = x => typeof x === 'number' const fn = R.when(predicate)(x => x + 1) -const fn = R.when(predicate)(x => x + 1) const positiveInput = 88 const negativeInput = 'foo' @@ -13508,19 +13210,15 @@ const negativeInput = 'foo' const result = [ fn(positiveInput), fn(negativeInput), - fn(negativeInput), ] const expected = [ 89, 'foo1', - 89, - 'foo1', ] // => `result` is equal to `expected` ``` -Try this R.when example in Rambda REPL Try this R.when example in Rambda REPL
@@ -13753,12 +13451,10 @@ zipWith( const list1 = [ 10, 20, 30, 40 ] const list2 = [ 100, 200 ] -const result = R.zipWith((x, y) => x + y, list1)(list2) const result = R.zipWith((x, y) => x + y, list1)(list2) // => [110, 220] ``` -Try this R.zipWith example in Rambda REPL Try this R.zipWith example in Rambda REPL
@@ -13850,11 +13546,10 @@ describe('R.zipWith', () => { 10.3.1 -- Fix issue with wrong order of inputs in `R.propOr` - [Issue #768](https://github.com/selfrefactor/rambda/discussions/768) +- Fix issue with wrong order of inputs in `R.propOr` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) -10.3.0 +- Fix issue with TypeScript definitions for `R.includes`- [Issue #781](https://github.com/selfrefactor/rambda/issues/781) -- Add `R.mapPropObject` 10.3.0 - Add `R.mapPropObject` @@ -14339,258 +14034,6 @@ Add the following methods: - change order of `R.propEq` - [Ramda MR](https://github.com/ramda/ramda/pull/2938/files) -7.5.0 - -- IMPORTANT: Remove `export` property in `package.json` in order to allow `Rambda` support for projects with `"type": "module"` in `package.json` - [Issue #667](https://github.com/selfrefactor/rambda/issues/657) - -- Add `R.unnest` - [Rambdax issue 89](https://github.com/selfrefactor/rambdax/issues/89) - -- `R.uniq` is not using `R.equals` as Ramda does - [Issue #88](https://github.com/selfrefactor/rambdax/issues/88) - -- Fix `R.path(['non','existing','path'], obj)` TS definition as 7.4.0 release caused TS errors - [Issue #668](https://github.com/selfrefactor/rambda/issues/668) - -7.4.0 - -- Synchronize with `@types/ramda` - `R.prop`, `R.path`, `R.pickAll` - -- Remove `esm` Rollup output due to tree-shaking issues. - -- Upgrade all dev dependencies. - -7.3.0 - -- Important - changing import declaration in `package.json` in order to fix tree-shaking issue - [Issue #647](https://github.com/selfrefactor/rambda/issues/647) - -- Add `R.modify` - -- Allow multiple inputs in TypeScript versions of `R.anyPass` and `R.allPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/604) - -- Using wrong clone of object in `R.mergeDeepRight` - [Issue #650](https://github.com/selfrefactor/rambda/issues/650) - -- Missing early return in `R.where` - [Issue #648](https://github.com/selfrefactor/rambda/issues/648) - -- `R.allPass` doesn't accept more than 1 parameters for function predicates- [Issue #604](https://github.com/selfrefactor/rambda/issues/604) - -7.2.1 - -- Remove bad typings of `R.propIs` which caused the library to cannot be build with TypeScript. - -- Drop support for `Wallaby` as per [https://github.com/wallabyjs/public/issues/3037](https://github.com/wallabyjs/public/issues/3037) - -7.2.0 - -- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) - -- Wrong curried typings in `R.anyPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/642) - -- `R.modifyPath` not exported - [Issue #640](https://github.com/selfrefactor/rambda/issues/640) - -- Add new method `R.uniqBy`. Implementation is coming from [Ramda MR#2641](https://github.com/ramda/ramda/pull/2641) - -- Apply the following changes from `@types/rambda`: - --- [https://github.com/DefinitelyTyped/DefinitelyTyped/commit/bab47272d52fc7bb81e85da36dbe9c905a04d067](add `AnyFunction` and `AnyConstructor`) - --- Improve `R.ifElse` typings - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59291 - --- Make `R.propEq` safe for `null/undefined` arguments - https://github.com/ramda/ramda/pull/2594/files - -7.1.4 - -- `R.mergeRight` not found on `Deno` import - [Issue #633](https://github.com/selfrefactor/rambda/issues/633) - -7.1.0 - -- Add `R.mergeRight` - introduced by Ramda's latest release. While Ramda renames `R.merge`, Rambda will keep `R.merge`. - -- Rambda's `pipe/compose` doesn't return proper length of composed function which leads to issue with `R.applySpec`. It was fixed by using Ramda's `pipe/compose` logic - [Issue #627](https://github.com/selfrefactor/rambda/issues/627) - -- Replace `Async` with `Promise` as return type of `R.type`. - -- Add new types as TypeScript output for `R.type` - "Map", "WeakMap", "Generator", "GeneratorFunction", "BigInt", "ArrayBuffer" - -- Add `R.juxt` method - -- Add `R.propSatisfies` method - -- Add new methods after `Ramda` version upgrade to `0.28.0`: - --- R.count --- R.modifyPath --- R.on --- R.whereAny --- R.partialObject - -7.0.3 - -Rambda.none has wrong logic introduced in version `7.0.0` - [Issue #625](https://github.com/selfrefactor/rambda/issues/625) - -7.0.2 - -Rambda doesn't work with `pnpm` due to wrong export configuration - [Issue #619](https://github.com/selfrefactor/rambda/issues/619) - -7.0.1 - -- Wrong ESM export configuration in `package.json` - [Issue #614](https://github.com/selfrefactor/rambda/issues/614) - -7.0.0 - -- Breaking change - sync `R.compose`/`R.pipe` with `@types/ramda`. That is significant change so as safeguard, it will lead a major bump. Important - this lead to raising required TypeScript version to `4.2.2`. In other words, to use `Rambda` you'll need TypeScript version `4.2.2` or newer. - -Related commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1 - -There are several other changes in `@types/ramda` as stated in [this comment](https://github.com/ramda/ramda/issues/2976#issuecomment-990408945). This leads to change of typings for the following methods in **Rambda**: - --- R.unless - --- R.toString - --- R.ifElse - --- R.always - --- R.complement - --- R.cond - --- R.is - --- R.sortBy - --- R.dissoc - --- R.toPairs - --- R.assoc - --- R.toLower - --- R.toUpper - -- One more reason for the breaking change is changing of export declarations in `package.json` based on [this blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing) and [this merged Ramda's PR](https://github.com/ramda/ramda/pull/2999). This also led to renaming of `babel.config.js` to `babel.config.cjs`. - -- Add `R.apply`, `R.bind` and `R.unapply` - -- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior. - -- Remove unused typing for `R.chain`. - -- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws. - -- Make `R.lastIndexOf` follow the logic of `R.indexOf`. - -- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results. - -- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599) - -- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595) - -- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604) - -- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606). - -- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt). - -- Improve performance of `R.uniqWith`. - -- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) - -- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943). - -- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608) - -- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609) - -6.9.0 - -- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581) - -Fixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`: - -- R.includes -- R.intersection -- R.difference -- R.excludes -- R.symmetricDifference -- R.union - -- R.without no longer support the following case - `without('0:1', ['0', '0:1']) // => ['0']`. Now it throws as the first argument should be a list, not a string. Ramda, on the other hand, returns an empty list - https://github.com/ramda/ramda/issues/3086. - -6.8.3 - -- Fix TypeScript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572) - -- Add `R.objOf` method - -- Add `R.mapObjIndexed` method - -- Publish shorter README.md version to NPM - -6.8.0 - -- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572) - -- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565) - -- Fix `R.intersection` wrong order compared to Ramda. - -- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577) - -6.7.0 - -- Remove `ts-toolbelt` types from TypeScript definitions. Most affected are the following methods, which lose one of its curried definitions: - -1. R.maxBy -2. R.minBy -3. R.pathEq -4. R.viewOr -5. R.when -6. R.merge -7. R.mergeDeepRight -8. R.mergeLeft - -6.6.0 - -- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions. - -- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`. - -- Use uglify plugin for UMD bundle. - -- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570) - -- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567) - -6.5.3 - -- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes` - -This is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086 - -6.5.2 - -- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent. - -- Update dependencies - -6.5.1 - -Fix wrong versions in changelog - -6.5.0 - -- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation. - -- `R.equals` supports equality of functions. - -- `R.pipe` doesn't use `R.compose`. - -- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types - -- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings - -- Add `CHANGELOG.md` file in release files list - > This is only part of the changelog. You can read the full text in [CHANGELOG.md](CHANGELOG.md) file. [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-changelog) @@ -14599,34 +14042,24 @@ Fix wrong versions in changelog > Most influential contributors(in alphabetical order) -- [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; - [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; -- [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; - [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; -- [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation - [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation -- [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; - [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; -- [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; - [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; -- [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; - [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; -- [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; - [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; -- [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; - [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; -- [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; - [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; -- [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; - [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; > Rambda references diff --git a/docs/README.md b/docs/README.md index 6a3c959f..13e47d2f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -76,9 +76,28 @@ it('within Ramda.pipe requires explicit types', () => { }); ``` -IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. +:exclamation: IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. -IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. +In other words: + +```typescript +R.filter(x => x > 1)([1,2,3]) +``` + +might trigger TS error as it not the same as + +```typescript + +R.pipe([1,2,3], R.filter(x => x > 1) +``` + +### :exclamation: All methods are curried + +There is one way to use `Rambda` methods and it is with currying, i.e. using `R.filter(fn, list)` will not work as it is inteded to be `R.filter(fn)(list)`. + +The reason is that all methods are supposed to be used inside `R.pipe`. After all, building chains is the very base of functional programming. + +Of course, there is value in supporting the case where you can pass all inputs at once, but I find that the price in terms of maintainability is not worth it. ### Keep only the most useful methods @@ -3371,10 +3390,6 @@ test('happy', () => { expect(filter(isEven)([1, 2, 3, 4])).toEqual([2, 4]) }) -test('using Boolean', () => { - expect(filter(Boolean)([null, 0, 1, 2])).toEqual([1,2]) -}) - test('using Boolean', () => { expect(filter(Boolean)([null, 0, 1, 2])).toEqual([1,2]) }) @@ -3388,7 +3403,6 @@ test('using Boolean', () => { ```typescript import { filter, pipe } from 'rambda' -import { filter, pipe } from 'rambda' const list = [1, 2, 3] @@ -3549,93 +3563,6 @@ describe('R.filter with array', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) -### filterAsync - -```typescript - -filterAsync( - predicate: (value: T) => Promise, -): (list: T[]) => Promise -``` - -
- -All TypeScript definitions - -```typescript -filterAsync( - predicate: (value: T) => Promise, -): (list: T[]) => Promise; -``` - -
- -
- -R.filterAsync source - -```javascript -export function filterAsync(predicate) { - return async list => { - const willReturn = [] - let index = 0 - for (const x of list) { - if (await predicate(x, index)) { - willReturn.push(list[index]) - } - index++ - } - - return willReturn - } -} -``` - -
- -
- -Tests - -```javascript -import { filterAsync } from './filterAsync.js' - -test('happy', async () => { - const isEven = async n => n % 2 === 0 - - expect(await filterAsync(isEven)([1, 2, 3, 4])).toEqual([2, 4]) -}) -``` - -
- -
- -TypeScript test - -```typescript -import { filterAsync, pipeAsync } from 'rambda' - -const list = [1, 2, 3] - -describe('R.filter with array', () => { - it('within pipe', async () => { - const result = await pipeAsync( - list, - filterAsync(async x => { - x // $ExpectType number - return x > 1 - }), - ) - result // $ExpectType number[] - }) -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) - ### filterObject ```typescript @@ -4855,7 +4782,7 @@ describe('R.head', () => { ```typescript -includes(valueToFind: T): (input: string) => boolean +includes(s: string): (list: readonly string[] | string) => boolean ``` If `input` is string, then this method work as native `String.includes`. @@ -4877,8 +4804,8 @@ const result = [ All TypeScript definitions ```typescript -includes(valueToFind: T): (input: string) => boolean; -includes(valueToFind: T): (input: T[]) => boolean; +includes(s: string): (list: readonly string[] | string) => boolean; +includes(target: T): (list: readonly T[]) => boolean; ```
@@ -4955,7 +4882,8 @@ test('with wrong input that does not throw', () => { TypeScript test ```typescript -import { includes, pipe } from 'rambda' +import { includes } from 'ramda' +import { pipe } from 'rambda' describe('R.includes', () => { it('happy', () => { @@ -4967,6 +4895,16 @@ describe('R.includes', () => { const result = pipe('foo', includes('bar')) result // $ExpectType boolean }) + it('with array of strings', () => { + const result = pipe(['1','2'], includes('1')) + result // $ExpectType boolean + }) + it('without R.pipe', () => { + const result1 = includes('1')(['1', '2']) + const result2 = includes(1)([1, 2]) + result1 // $ExpectType boolean + result2 // $ExpectType boolean + }) }) ``` @@ -5077,109 +5015,6 @@ it('R.indexBy', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexBy) -### indexBy - -```typescript - -indexBy( - property: K -): (list: readonly T[]) => Record -``` - -It transforms list of objects to object using specified property as the base for the returned object. - -```javascript -const result = R.indexBy( - 'id' -)([{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}]) -// => {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} -``` - -Try this R.indexBy example in Rambda REPL - -
- -All TypeScript definitions - -```typescript -indexBy( - property: K -): (list: readonly T[]) => Record; -indexBy( - property: K -): (list: T[]) => Record; - -// API_MARKER_END -// ============================================ -``` - -
- -
- -R.indexBy source - -```javascript -export function indexBy(property){ - return list => { - const toReturn = {} - for (let i = 0; i < list.length; i++){ - const item = list[ i ] - const key = item[property] - if(key !== undefined){ - toReturn[ key ] = item - } - } - - return toReturn - } -} -``` - -
- -
- -Tests - -```javascript -import { indexBy } from './indexBy.js' - -test('happy', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] - - expect( - indexBy('id')(list) - ).toEqual( - {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} - ) -}) -``` - -
- -
- -TypeScript test - -```typescript -import { pipe, indexBy } from 'rambda' - -it('R.indexBy', () => { - const list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}] - const result = pipe( - list, - indexBy('id') - ) - result.abc // $ExpectType { id: string; title: string; } - result.foo // $ExpectType { id: string; title: string; } -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexBy) - ### indexOf ```typescript @@ -5238,20 +5073,17 @@ test('will throw with bad input', () => { expect(() => indexOf([])(true)).toThrow() }) -test('with numbers', () => { test('with numbers', () => { expect(indexOf(3)([1, 2, 3, 4])).toBe(2) expect(indexOf(10)([1, 2, 3, 4])).toBe(-1) }) -test('list of objects use R.equals', () => { test('list of objects use R.equals', () => { const listOfObjects = [{ a: 1 }, { b: 2 }, { c: 3 }] expect(indexOf({ c: 4 })(listOfObjects)).toBe(-1) expect(indexOf({ c: 3 })(listOfObjects)).toBe(2) }) -test('list of arrays use R.equals', () => { test('list of arrays use R.equals', () => { const listOfLists = [[1], [2, 3], [2, 3, 4], [2, 3], [1], []] expect(indexOf([])(listOfLists)).toBe(5) @@ -6215,8 +6047,6 @@ export function mapAsync(fn) { return async list => { const willReturn = [] let i = 0 - for (const x of list) { - willReturn.push(await fn(x, i++)) for (const x of list) { willReturn.push(await fn(x, i++)) } @@ -6290,11 +6120,9 @@ test('error', async () => { ```typescript import { mapAsync, pipeAsync, map } from 'rambda' -import { mapAsync, pipeAsync, map } from 'rambda' const list = ['a', 'bc', 'def'] const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) -const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) it('R.mapAsync', async () => { const result = await pipeAsync( @@ -6306,7 +6134,6 @@ it('R.mapAsync', async () => { }), x => x, map(x => x +1), - map(x => x +1), mapAsync(async x => { await delay(100) return x + 1 @@ -7201,11 +7028,9 @@ It replaces `index` in array `list` with the result of `replaceFn(list[i])`. const result = R.pipe( [1, 2, 3], R.modifyItemAtIndex(1, x => x + 1) - R.modifyItemAtIndex(1, x => x + 1) ) // => [1, 3, 3] ``` -Try this R.modifyItemAtIndex example in Rambda REPL Try this R.modifyItemAtIndex example in Rambda REPL
@@ -7363,10 +7188,17 @@ export function modifyPath(pathInput, fn) { ```javascript import { modifyPath } from './modifyPath.js' +const obj = { a: { b: { c: 1 } } } + test('happy', () => { - const result = modifyPath('a.b.c', x => x + 1)({ a: { b: { c: 1 } } }) + const result = modifyPath('a.b.c', x => x + 1)(obj) expect(result).toEqual({ a: { b: { c: 2 } } }) }) + +test('works only on existing paths', () => { + const result = modifyPath('a.b.d', x => x + 1)(obj) + expect(result).toEqual(obj) +}) ```
@@ -9122,7 +8954,6 @@ const result = await R.pipeAsync( return x + 2 }, x => x +2, - x => x +2, async x => { const delayed = await R.delay(100) return delayed + x @@ -9131,7 +8962,6 @@ const result = await R.pipeAsync( // `result` resolves to `RAMBDAX_DELAY104` ``` -Try this R.pipeAsync example in Rambda REPL Try this R.pipeAsync example in Rambda REPL
@@ -10736,25 +10566,6 @@ const expected = [ Try this R.sortByDescending example in Rambda REPL -```javascript -const list = [ - {a: 2}, - {a: 3}, - {a: 1} -] -const sortFn = x => x.a - -const result = R.sortByDescending(sortFn)(list) -const expected = [ - {a: 3}, - {a: 2}, - {a: 1} -] -// => `result` is equal to `expected` -``` - -Try this R.sortByDescending example in Rambda REPL -
All TypeScript definitions @@ -10809,23 +10620,6 @@ const expected = [ Try this R.sortByPath example in Rambda REPL -```javascript -const list = [ - {a: {b: 2}, id:1}, - {a: {b: 1}, id:2}, - {a: {b: 3}, id:3}, -] -const result = R.sortByPath('a.b')(list) -const expected = [ - {a: {b: 1}, id:2}, - {a: {b: 2}, id:1}, - {a: {b: 3}, id:3} -] -// => `result` is equal to `expected` -``` - -Try this R.sortByPath example in Rambda REPL -
All TypeScript definitions @@ -10947,23 +10741,6 @@ const expected = [ Try this R.sortByPathDescending example in Rambda REPL -```javascript -const list = [ - {a: {b: 2}, id:1}, - {a: {b: 1}, id:2}, - {a: {b: 3}, id:3}, -] -const result = R.sortByPathDescending('a.b')(list) -const expected = [ - {a: {b: 3}, id:3} - {a: {b: 2}, id:1}, - {a: {b: 1}, id:2}, -] -// => `result` is equal to `expected` -``` - -Try this R.sortByPathDescending example in Rambda REPL -
All TypeScript definitions @@ -11037,12 +10814,10 @@ It returns a sorted version of `input` object. ```javascript const predicate = (propA, propB, valueA, valueB) => valueA > valueB ? -1 : 1 -const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) // => {b: 4, c: 2, a: 1} ``` -Try this R.sortObject example in Rambda REPL Try this R.sortObject example in Rambda REPL
@@ -11406,8 +11181,6 @@ It splits `input` into slices of `sliceLength`. const result = [ R.splitEvery(2)([1, 2, 3]), R.splitEvery(3)('foobar') - R.splitEvery(2)([1, 2, 3]), - R.splitEvery(3)('foobar') ] const expected = [ @@ -11417,7 +11190,6 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.splitEvery example in Rambda REPL Try this R.splitEvery example in Rambda REPL
@@ -11505,12 +11277,10 @@ It returns a merged list of `x` and `y` with all equal elements removed. const x = [ 1, 2, 3, 4 ] const y = [ 3, 4, 5, 6 ] -const result = R.symmetricDifference(x)(y) const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` -Try this R.symmetricDifference example in Rambda REPL Try this R.symmetricDifference example in Rambda REPL
@@ -12078,19 +11848,15 @@ One use case is debugging in the middle of `R.pipe` chain. ```javascript const list = [1, 2, 3] -const result = R.pipe( const result = R.pipe( list, R.filter(x => x > 1), - R.filter(x => x > 1), R.tap(console.log), R.map(x => x * 2) - R.map(x => x * 2) ) // => `2` and `3` will be logged ``` -Try this R.tap example in Rambda REPL Try this R.tap example in Rambda REPL
@@ -12252,63 +12018,6 @@ it('R.transformPropObject', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#transformPropObject) -### transformPropObject - -```typescript - -transformPropObject( - valueMapper: (value: T[K]) => Value, - prop: K, -): (data: T) => MergeTypes & { [P in K]: Value }> -``` - -```javascript -const fn = (x) => x > 2 -const obj = {a: 1, b: 2} - -const result = R.transformPropObject(fn, 'a')(obj) -// => {a: false, b: 2} -``` - -Try this R.transformPropObject example in Rambda REPL - -
- -All TypeScript definitions - -```typescript -transformPropObject( - valueMapper: (value: T[K]) => Value, - prop: K, -): (data: T) => MergeTypes & { [P in K]: Value }>; -``` - -
- -
- -TypeScript test - -```typescript -import { transformPropObject, pipe } from 'rambda' - -it('R.transformPropObject', () => { - const result = pipe( - { a: 1, b: 'foo' }, - transformPropObject(x => { - x // $ExpectType number - return x > 2 - }, 'a'), - ) - - result // $ExpectType { b: string; a: boolean; } -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#transformPropObject) - ### tryCatch ```typescript @@ -12709,11 +12418,9 @@ It takes two lists and return a new list containing a merger of both list with r ```javascript const result = R.union([1,2,3])([3,4,5]); -const result = R.union([1,2,3])([3,4,5]); // => [1, 2, 3, 4, 5] ``` -Try this R.union example in Rambda REPL Try this R.union example in Rambda REPL
@@ -12926,12 +12633,10 @@ It applies uniqueness to input list based on function that defines what to be us ```javascript const list = [{a:1}, {a:2}, {a:1}] const result = R.uniqBy(x => x)(list) -const result = R.uniqBy(x => x)(list) // => [{a:1}, {a:2}] ``` -Try this R.uniqBy example in Rambda REPL Try this R.uniqBy example in Rambda REPL
@@ -13409,12 +13114,10 @@ const index = 2 const newValue = 88 const list = [1, 2, 3, 4, 5] -const result = R.update(index, newValue)(list) const result = R.update(index, newValue)(list) // => [1, 2, 88, 4, 5] ``` -Try this R.update example in Rambda REPL Try this R.update example in Rambda REPL
@@ -13500,7 +13203,6 @@ If the `predicate` returns `false`, then it will simply return `input`. ```javascript const predicate = x => typeof x === 'number' const fn = R.when(predicate)(x => x + 1) -const fn = R.when(predicate)(x => x + 1) const positiveInput = 88 const negativeInput = 'foo' @@ -13508,19 +13210,15 @@ const negativeInput = 'foo' const result = [ fn(positiveInput), fn(negativeInput), - fn(negativeInput), ] const expected = [ 89, 'foo1', - 89, - 'foo1', ] // => `result` is equal to `expected` ``` -Try this R.when example in Rambda REPL Try this R.when example in Rambda REPL
@@ -13753,12 +13451,10 @@ zipWith( const list1 = [ 10, 20, 30, 40 ] const list2 = [ 100, 200 ] -const result = R.zipWith((x, y) => x + y, list1)(list2) const result = R.zipWith((x, y) => x + y, list1)(list2) // => [110, 220] ``` -Try this R.zipWith example in Rambda REPL Try this R.zipWith example in Rambda REPL
@@ -13848,6 +13544,12 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +10.3.1 + +- Fix issue with wrong order of inputs in `R.propOr` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) + +- Fix issue with TypeScript definitions for `R.includes`- [Issue #781](https://github.com/selfrefactor/rambda/issues/781) + 10.3.0 - Add `R.mapPropObject` @@ -13866,6 +13568,9 @@ describe('R.zipWith', () => { - Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. +- Fix `R.pluck` to work without `R.pipe` +- Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. + - Fix `R.pluck` to work without `R.pipe` 10.2.0 @@ -14329,258 +14034,6 @@ Add the following methods: - change order of `R.propEq` - [Ramda MR](https://github.com/ramda/ramda/pull/2938/files) -7.5.0 - -- IMPORTANT: Remove `export` property in `package.json` in order to allow `Rambda` support for projects with `"type": "module"` in `package.json` - [Issue #667](https://github.com/selfrefactor/rambda/issues/657) - -- Add `R.unnest` - [Rambdax issue 89](https://github.com/selfrefactor/rambdax/issues/89) - -- `R.uniq` is not using `R.equals` as Ramda does - [Issue #88](https://github.com/selfrefactor/rambdax/issues/88) - -- Fix `R.path(['non','existing','path'], obj)` TS definition as 7.4.0 release caused TS errors - [Issue #668](https://github.com/selfrefactor/rambda/issues/668) - -7.4.0 - -- Synchronize with `@types/ramda` - `R.prop`, `R.path`, `R.pickAll` - -- Remove `esm` Rollup output due to tree-shaking issues. - -- Upgrade all dev dependencies. - -7.3.0 - -- Important - changing import declaration in `package.json` in order to fix tree-shaking issue - [Issue #647](https://github.com/selfrefactor/rambda/issues/647) - -- Add `R.modify` - -- Allow multiple inputs in TypeScript versions of `R.anyPass` and `R.allPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/604) - -- Using wrong clone of object in `R.mergeDeepRight` - [Issue #650](https://github.com/selfrefactor/rambda/issues/650) - -- Missing early return in `R.where` - [Issue #648](https://github.com/selfrefactor/rambda/issues/648) - -- `R.allPass` doesn't accept more than 1 parameters for function predicates- [Issue #604](https://github.com/selfrefactor/rambda/issues/604) - -7.2.1 - -- Remove bad typings of `R.propIs` which caused the library to cannot be build with TypeScript. - -- Drop support for `Wallaby` as per [https://github.com/wallabyjs/public/issues/3037](https://github.com/wallabyjs/public/issues/3037) - -7.2.0 - -- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) - -- Wrong curried typings in `R.anyPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/642) - -- `R.modifyPath` not exported - [Issue #640](https://github.com/selfrefactor/rambda/issues/640) - -- Add new method `R.uniqBy`. Implementation is coming from [Ramda MR#2641](https://github.com/ramda/ramda/pull/2641) - -- Apply the following changes from `@types/rambda`: - --- [https://github.com/DefinitelyTyped/DefinitelyTyped/commit/bab47272d52fc7bb81e85da36dbe9c905a04d067](add `AnyFunction` and `AnyConstructor`) - --- Improve `R.ifElse` typings - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59291 - --- Make `R.propEq` safe for `null/undefined` arguments - https://github.com/ramda/ramda/pull/2594/files - -7.1.4 - -- `R.mergeRight` not found on `Deno` import - [Issue #633](https://github.com/selfrefactor/rambda/issues/633) - -7.1.0 - -- Add `R.mergeRight` - introduced by Ramda's latest release. While Ramda renames `R.merge`, Rambda will keep `R.merge`. - -- Rambda's `pipe/compose` doesn't return proper length of composed function which leads to issue with `R.applySpec`. It was fixed by using Ramda's `pipe/compose` logic - [Issue #627](https://github.com/selfrefactor/rambda/issues/627) - -- Replace `Async` with `Promise` as return type of `R.type`. - -- Add new types as TypeScript output for `R.type` - "Map", "WeakMap", "Generator", "GeneratorFunction", "BigInt", "ArrayBuffer" - -- Add `R.juxt` method - -- Add `R.propSatisfies` method - -- Add new methods after `Ramda` version upgrade to `0.28.0`: - --- R.count --- R.modifyPath --- R.on --- R.whereAny --- R.partialObject - -7.0.3 - -Rambda.none has wrong logic introduced in version `7.0.0` - [Issue #625](https://github.com/selfrefactor/rambda/issues/625) - -7.0.2 - -Rambda doesn't work with `pnpm` due to wrong export configuration - [Issue #619](https://github.com/selfrefactor/rambda/issues/619) - -7.0.1 - -- Wrong ESM export configuration in `package.json` - [Issue #614](https://github.com/selfrefactor/rambda/issues/614) - -7.0.0 - -- Breaking change - sync `R.compose`/`R.pipe` with `@types/ramda`. That is significant change so as safeguard, it will lead a major bump. Important - this lead to raising required TypeScript version to `4.2.2`. In other words, to use `Rambda` you'll need TypeScript version `4.2.2` or newer. - -Related commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1 - -There are several other changes in `@types/ramda` as stated in [this comment](https://github.com/ramda/ramda/issues/2976#issuecomment-990408945). This leads to change of typings for the following methods in **Rambda**: - --- R.unless - --- R.toString - --- R.ifElse - --- R.always - --- R.complement - --- R.cond - --- R.is - --- R.sortBy - --- R.dissoc - --- R.toPairs - --- R.assoc - --- R.toLower - --- R.toUpper - -- One more reason for the breaking change is changing of export declarations in `package.json` based on [this blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing) and [this merged Ramda's PR](https://github.com/ramda/ramda/pull/2999). This also led to renaming of `babel.config.js` to `babel.config.cjs`. - -- Add `R.apply`, `R.bind` and `R.unapply` - -- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior. - -- Remove unused typing for `R.chain`. - -- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws. - -- Make `R.lastIndexOf` follow the logic of `R.indexOf`. - -- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results. - -- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599) - -- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595) - -- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604) - -- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606). - -- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt). - -- Improve performance of `R.uniqWith`. - -- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) - -- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943). - -- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608) - -- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609) - -6.9.0 - -- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581) - -Fixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`: - -- R.includes -- R.intersection -- R.difference -- R.excludes -- R.symmetricDifference -- R.union - -- R.without no longer support the following case - `without('0:1', ['0', '0:1']) // => ['0']`. Now it throws as the first argument should be a list, not a string. Ramda, on the other hand, returns an empty list - https://github.com/ramda/ramda/issues/3086. - -6.8.3 - -- Fix TypeScript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572) - -- Add `R.objOf` method - -- Add `R.mapObjIndexed` method - -- Publish shorter README.md version to NPM - -6.8.0 - -- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572) - -- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565) - -- Fix `R.intersection` wrong order compared to Ramda. - -- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577) - -6.7.0 - -- Remove `ts-toolbelt` types from TypeScript definitions. Most affected are the following methods, which lose one of its curried definitions: - -1. R.maxBy -2. R.minBy -3. R.pathEq -4. R.viewOr -5. R.when -6. R.merge -7. R.mergeDeepRight -8. R.mergeLeft - -6.6.0 - -- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions. - -- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`. - -- Use uglify plugin for UMD bundle. - -- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570) - -- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567) - -6.5.3 - -- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes` - -This is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086 - -6.5.2 - -- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent. - -- Update dependencies - -6.5.1 - -Fix wrong versions in changelog - -6.5.0 - -- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation. - -- `R.equals` supports equality of functions. - -- `R.pipe` doesn't use `R.compose`. - -- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types - -- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings - -- Add `CHANGELOG.md` file in release files list - > This is only part of the changelog. You can read the full text in [CHANGELOG.md](CHANGELOG.md) file. [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-changelog) @@ -14589,34 +14042,24 @@ Fix wrong versions in changelog > Most influential contributors(in alphabetical order) -- [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; - [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable; -- [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; - [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain; -- [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation - [@peeja](https://github.com/peeja) - add several methods and fix mutiple issues; provides great MR documentation -- [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; - [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style; -- [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; - [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex; -- [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; - [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods; -- [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; - [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex; -- [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; - [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse; -- [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; - [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge; -- [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; - [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports; > Rambda references diff --git a/files/CHANGELOG_v8.md b/files/CHANGELOG_v8.md new file mode 100644 index 00000000..0b9e84f2 --- /dev/null +++ b/files/CHANGELOG_v8.md @@ -0,0 +1,765 @@ +7.5.0 + +- IMPORTANT: Remove `export` property in `package.json` in order to allow `Rambda` support for projects with `"type": "module"` in `package.json` - [Issue #667](https://github.com/selfrefactor/rambda/issues/657) + +- Add `R.unnest` - [Rambdax issue 89](https://github.com/selfrefactor/rambdax/issues/89) + +- `R.uniq` is not using `R.equals` as Ramda does - [Issue #88](https://github.com/selfrefactor/rambdax/issues/88) + +- Fix `R.path(['non','existing','path'], obj)` TS definition as 7.4.0 release caused TS errors - [Issue #668](https://github.com/selfrefactor/rambda/issues/668) + +7.4.0 + +- Synchronize with `@types/ramda` - `R.prop`, `R.path`, `R.pickAll` + +- Remove `esm` Rollup output due to tree-shaking issues. + +- Upgrade all dev dependencies. + +7.3.0 + +- Important - changing import declaration in `package.json` in order to fix tree-shaking issue - [Issue #647](https://github.com/selfrefactor/rambda/issues/647) + +- Add `R.modify` + +- Allow multiple inputs in TypeScript versions of `R.anyPass` and `R.allPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/604) + +- Using wrong clone of object in `R.mergeDeepRight` - [Issue #650](https://github.com/selfrefactor/rambda/issues/650) + +- Missing early return in `R.where` - [Issue #648](https://github.com/selfrefactor/rambda/issues/648) + +- `R.allPass` doesn't accept more than 1 parameters for function predicates- [Issue #604](https://github.com/selfrefactor/rambda/issues/604) + +7.2.1 + +- Remove bad typings of `R.propIs` which caused the library to cannot be build with TypeScript. + +- Drop support for `Wallaby` as per [https://github.com/wallabyjs/public/issues/3037](https://github.com/wallabyjs/public/issues/3037) + +7.2.0 + +- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) + +- Wrong curried typings in `R.anyPass` - [Issue #642](https://github.com/selfrefactor/rambda/issues/642) + +- `R.modifyPath` not exported - [Issue #640](https://github.com/selfrefactor/rambda/issues/640) + +- Add new method `R.uniqBy`. Implementation is coming from [Ramda MR#2641](https://github.com/ramda/ramda/pull/2641) + +- Apply the following changes from `@types/rambda`: + +-- [https://github.com/DefinitelyTyped/DefinitelyTyped/commit/bab47272d52fc7bb81e85da36dbe9c905a04d067](add `AnyFunction` and `AnyConstructor`) + +-- Improve `R.ifElse` typings - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59291 + +-- Make `R.propEq` safe for `null/undefined` arguments - https://github.com/ramda/ramda/pull/2594/files + +7.1.4 + +- `R.mergeRight` not found on `Deno` import - [Issue #633](https://github.com/selfrefactor/rambda/issues/633) + +7.1.0 + +- Add `R.mergeRight` - introduced by Ramda's latest release. While Ramda renames `R.merge`, Rambda will keep `R.merge`. + +- Rambda's `pipe/compose` doesn't return proper length of composed function which leads to issue with `R.applySpec`. It was fixed by using Ramda's `pipe/compose` logic - [Issue #627](https://github.com/selfrefactor/rambda/issues/627) + +- Replace `Async` with `Promise` as return type of `R.type`. + +- Add new types as TypeScript output for `R.type` - "Map", "WeakMap", "Generator", "GeneratorFunction", "BigInt", "ArrayBuffer" + +- Add `R.juxt` method + +- Add `R.propSatisfies` method + +- Add new methods after `Ramda` version upgrade to `0.28.0`: + +-- R.count +-- R.modifyPath +-- R.on +-- R.whereAny +-- R.partialObject + +7.0.3 + +Rambda.none has wrong logic introduced in version `7.0.0` - [Issue #625](https://github.com/selfrefactor/rambda/issues/625) + +7.0.2 + +Rambda doesn't work with `pnpm` due to wrong export configuration - [Issue #619](https://github.com/selfrefactor/rambda/issues/619) + +7.0.1 + +- Wrong ESM export configuration in `package.json` - [Issue #614](https://github.com/selfrefactor/rambda/issues/614) + +7.0.0 + +- Breaking change - sync `R.compose`/`R.pipe` with `@types/ramda`. That is significant change so as safeguard, it will lead a major bump. Important - this lead to raising required TypeScript version to `4.2.2`. In other words, to use `Rambda` you'll need TypeScript version `4.2.2` or newer. + +Related commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1 + +There are several other changes in `@types/ramda` as stated in [this comment](https://github.com/ramda/ramda/issues/2976#issuecomment-990408945). This leads to change of typings for the following methods in **Rambda**: + +-- R.unless + +-- R.toString + +-- R.ifElse + +-- R.always + +-- R.complement + +-- R.cond + +-- R.is + +-- R.sortBy + +-- R.dissoc + +-- R.toPairs + +-- R.assoc + +-- R.toLower + +-- R.toUpper + +- One more reason for the breaking change is changing of export declarations in `package.json` based on [this blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing) and [this merged Ramda's PR](https://github.com/ramda/ramda/pull/2999). This also led to renaming of `babel.config.js` to `babel.config.cjs`. + +- Add `R.apply`, `R.bind` and `R.unapply` + +- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior. + +- Remove unused typing for `R.chain`. + +- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws. + +- Make `R.lastIndexOf` follow the logic of `R.indexOf`. + +- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results. + +- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599) + +- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595) + +- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604) + +- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606). + +- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt). + +- Improve performance of `R.uniqWith`. + +- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593) + +- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943). + +- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608) + +- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609) + +6.9.0 + +- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581) + +Fixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`: + +- R.includes +- R.intersection +- R.difference +- R.excludes +- R.symmetricDifference +- R.union + +- R.without no longer support the following case - `without('0:1', ['0', '0:1']) // => ['0']`. Now it throws as the first argument should be a list, not a string. Ramda, on the other hand, returns an empty list - https://github.com/ramda/ramda/issues/3086. + +6.8.3 + +- Fix TypeScript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572) + +- Add `R.objOf` method + +- Add `R.mapObjIndexed` method + +- Publish shorter README.md version to NPM + +6.8.0 + +- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572) + +- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565) + +- Fix `R.intersection` wrong order compared to Ramda. + +- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577) + +6.7.0 + +- Remove `ts-toolbelt` types from TypeScript definitions. Most affected are the following methods, which lose one of its curried definitions: + +1. R.maxBy +2. R.minBy +3. R.pathEq +4. R.viewOr +5. R.when +6. R.merge +7. R.mergeDeepRight +8. R.mergeLeft + +6.6.0 + +- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions. + +- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`. + +- Use uglify plugin for UMD bundle. + +- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570) + +- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567) + +6.5.3 + +- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes` + +This is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086 + +6.5.2 + +- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent. + +- Update dependencies + +6.5.1 + +Fix wrong versions in changelog + +6.5.0 + +- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation. + +- `R.equals` supports equality of functions. + +- `R.pipe` doesn't use `R.compose`. + +- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types + +- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings + +- Add `CHANGELOG.md` file in release files list + +6.4.0 + +- Close [Issue #560](https://github.com/selfrefactor/rambda/issues/560) - apply immutable lint to TypeScript definitions + +- Close [Issue #553](https://github.com/selfrefactor/rambda/issues/553) - fix problem with curried typings of `R.prop` + +- Fix wrong `R.last` typing + +- Upgrade all `rollup` related dependencies + +- `R.type` supports `Symbol` just like *Ramda*. + +- Remove file extension in `main` property in `package.json` in order to allow `experimental-modules`. See also this Ramda's PR - https://github.com/ramda/ramda/pull/2678/files + +- Import `R.indexBy`/`R.when`/`R.zipObj`/`R.propEq`/`R.complement` changes from recent `@types/ramda` release. + +- `R.tryCatch` stop supporting asynchronous functions; the previous behaviour is exported to *Rambdax* as `R.tryCatchAsync` + +6.3.1 + +- Fix missing `Evolved` declaration in TypeScript definition + +6.3.0 + +- Add `R.takeLastWhile` + +- Add `R.dropWhile` + +- Add `R.eqProps` + +- Add `R.dropLastWhile` + +- Add `R.dropRepeats` + +- Add `R.dropRepeatsWith` + +- Add `R.evolve` + +- Add typings for `R.takeWhile` when iterable is a string + +6.2.0 + +- Add `R.props` + +- Add `R.zipWith` + +- Add `R.splitAt` + +- Add `R.splitWhen` + +- Close [Issue #547](https://github.com/selfrefactor/rambda/issues/547) - restore `readonly` declaration in TypeScript definitions. + +- `R.append`/`R.prepend` now work only with arrays just like Ramda. Previous behaviour was for them to work with both arrays and strings. + +- Sync `R.pluck` typings with `@types/ramda` as there was a tiny difference. + +6.1.0 + +- Fix `R.and` wrong definition, because the function doesn't convert the result to boolean. This introduce another difference with `@types/ramda`. + +- Add `R.once` + +- Add `R.or` + +6.0.1 + +- Fix typing of `R.reject` as it wrongly declares that with object, it pass property to predicate. + +6.0.0 + +- Breaking change - `R.map`/`R.filter`/`R.reject`/`R.forEach`/`R.partition` doesn't pass index as second argument to the predicate, when looping over arrays. The old behaviour of *map*, *filter* and *forEach* can be found in Rambdax methods *R.mapIndexed*, *R.filterIndexed* and *R.forEachIndexed*. + +- Breaking change - `R.all`/`R.none`/`R.any`/`R.find`/`R.findLast`/`R.findIndex`/`R.findLastIndex` doesn't pass index as second argument to the predicate. + +- Change `R.assocPath` typings so the user can explicitly sets type of the new object + +- Typings of `R.assoc` match its `@types/ramda` counterpart. + +- Simplify `R.forEach` typings + +- Remove `ReadonlyArray` pattern from TypeScript definitions - not enough value for the noise it adds. + +5.13.1 + +- Fix wrong `R.takeWhile` + +5.13.0 + +- Add `R.takeWhile` method + +- Fix `R.lensPath` issue when using string as path input. The issue was introduced when fixing [Issue #524](https://github.com/selfrefactor/rambda/issues/524) in the previous release. + +5.12.1 + +- Close [Issue #524](https://github.com/selfrefactor/rambda/issues/524) - + wrong `R.assocPath` when path includes numbers + +- `R.includes` throws on wrong input, i.e. `R.includes(1, null)` + +5.12.0 + +- Add `R.move` method + +- Add `R.union` method + +- Close [Issue #519](https://github.com/selfrefactor/rambda/issues/519) - +`ts-toolbelt` needs other type of export with `--isolatedModules` flag + +- Change `R.when` implementation and typings to match those of `Ramda` + +- `R.over` and `R.set` use `R.curry` instead of manual currying + +- `R.lensPath` typings support string as path, i.e. `'a.b'` instead of `['a', 'b']` + +- `R.equals` now supports negative zero just like `Ramda.equals` + +- `R.replace` uses `R.curry` + +5.11.0 + +Forgot to export `R.of` because of wrong marker in `files/index.d.ts` + +5.10.0 + +Close [Issue #514](https://github.com/selfrefactor/rambda/issues/514) - +wrong `R.length` with empty string + +Close [Issue #511](https://github.com/selfrefactor/rambda/issues/511) - error in `ts-toolbelt` library + +Close [Issue #510](https://github.com/selfrefactor/rambda/issues/510) - `R.clamp` should throw if min argument is greater than max argument + +- [PR #508](https://github.com/selfrefactor/rambda/pull/508) - add `R.of` + +- Definition of `R.curry` are not same as those of `@types/ramda` + +- Definitions of `R.either` is same as that of `R.both` + +- Definitions of `R.ifElse` no longer use `any` type + +- Definition of `R.flatten` requires passing type for the output + +- Fix definition of `R.propOr`, `R.dissoc` + +- Fix curried definitions of `R.take`, `R.takeLast`, `R.drop` and `R.dropLast` + +- 5.9.0 + +- `R.pickAll` definition allows passing string as path to search. + +- `R.propEq` definition is now similar to that in `@types/ramda`. + +- `R.none` matches `R.all` implementation and pass index as second argument to predicate input. + +- `R.reduce` - drop support for object as iterable. Now it throws the same error as Ramda. Also instead of returning the initial value when iterable is `undefined`, now it throws. + +Add index as additional argument to the TypeScript definitions of the following methods: + +- R.all +- R.find +- R.findLast +- R.findIndex +- R.findLastIndex + +- 5.8.0 + +Add `R.mergeAll` +Add `R.mergeDeepRight` +Add `R.mergeLeft` +Add `R.partition` +Add `R.pathEq` +Add `R.tryCatch` +Add `R.unless` +Add `R.whereEq` +Add `R.where` + +- Add `R.last` typing for empty array + +- 5.7.0 Revert [PR #469](https://github.com/selfrefactor/rambda/pull/469) as `R.curry` was slow | Also now `R.flip` throws if arity is greater than or equal to 5 + +- 5.6.3 Merge several PRs of [@farwayer](https://github.com/farwayer) + +- [PR #482](https://github.com/selfrefactor/rambda/pull/482) - improve `R.forEach` performance by not using `R.map` + +- [PR #485](https://github.com/selfrefactor/rambda/pull/485) - improve `R.map` performance + +- [PR #482](https://github.com/selfrefactor/rambda/pull/486) - improve `R.reduce` performance + +- Fix missing high arity typings for `R.compose/pipe` + +- `R.merge` definitions match those of `@types/ramda` + +- Remove `dist` folder from Rambda repo + +- 5.6.2 + +Close [Issue #476](https://github.com/selfrefactor/rambda/issues/476) - typesafe `R.propEq` definitions + +Approve [PR #477](https://github.com/selfrefactor/rambda/pull/477) - fix `R.groupWith` when list length is 1 + +- 5.6.1 + +Update `ts-toolbelt` files as now there is update pipeline for it. + +Approve [PR #474](https://github.com/selfrefactor/rambda/pull/474) - intruduce internal `isArray` helper + +- 5.6.0 + +Approve [PR #469](https://github.com/selfrefactor/rambda/pull/469) - R.flip supports any arity | implement `R.curry` with `R.curryN` add `R.applySpec` + +- 5.5.0 + +Close [Issue #464](https://github.com/selfrefactor/rambda/issues/464) - `R.flip` should handle functions with arity above 2 + +Close [Issue #468](https://github.com/selfrefactor/rambda/issues/468) - `fs-extra` should be dev dependency as it was wrongly added as production dependency in `5.2.0` + +`R.flip` typings now match `@types/ramda` typings + +Add `R.hasPath` method + +Add `R.mathMod` typings + +- 5.4.3 + +Fix `R.omit` typings + +- 5.4.2 + +Fix `R.pick` typings + +> Close [Issue #460](https://github.com/selfrefactor/rambda/issues/460) - `R.paths` should be curried + +- 5.4.1 + +> Close [Issue #458](https://github.com/selfrefactor/rambda/issues/458) - wrong `R.propIs` typing + +- 5.4.0 + +> Close [Issue #408](https://github.com/selfrefactor/rambda/issues/408) - add `R.chain` + +- 5.3.0 + +> Close [Issue #430](https://github.com/selfrefactor/rambda/issues/430) - add `R.when` + +Also restore `R.converge`, `R.findLast`, `R.findLastIndex` and `R.curryN` as I have forgotten to export them when releasing `5.2.0`. + +- 5.2.1 + +Fix TypeScript comment for every method + +- 5.2.0 + +Release new documentation site + +`Ramda` repo now holds all `Rambdax` methods and tests + +- 5.1.1 + +Add `R.converge` and `R.curryN` from [PR #412](https://github.com/selfrefactor/rambda/pull/412) + +Close [Issue #410](https://github.com/selfrefactor/rambda/issues/410) - wrong implementation of `R.groupWith` + +Close [Issue #411](https://github.com/selfrefactor/rambda/issues/411) - change the order of declared `R.map` typings rules + +- 5.0.0 + +Move `R.partialCurry` to Rambdax(reason for major bump). + +Use new type of export in TypeScript definitions. + +Approve [PR #381](https://github.com/selfrefactor/rambda/pull/381) - add `R.applySpec` + +- 4.6.0 + +Approve [PR #375](https://github.com/selfrefactor/rambda/pull/375) - add lenses(Thank you [@synthet1c](https://github.com/synthet1c)) + +Add `R.lens` + +Add `R.lensIndex` + +Add `R.lensPath` + +Add `R.lensProp` + +Add `R.over` + +Add `R.set` + +Add `R.view` + +> Sync with Ramda 0.27 + +Add `R.paths` + +Add `R.xor` + +> Close [Issue #373](https://github.com/selfrefactor/rambda/issues/373) + +Add `R.cond` + +- 4.5.0 Add `R.clamp` + +- 4.4.2 Improve `R.propOr` typings + +- 4.4.1 Make `R.reject` has the same typing as `R.filter` + +- 4.4.0 Several changes: + +Close [Issue #317](https://github.com/selfrefactor/rambda/issues/317) - add `R.transpose` + +Close [Issue #325](https://github.com/selfrefactor/rambda/issues/325) - `R.filter` should return equal values for bad inputs `null` and `undefined` + +Approve suggestion for `R.indexBy` to accept string not only function as first argument. + +Edit of `R.path` typings + +- 4.2.0 Approve [PR #314](https://github.com/selfrefactor/rambda/pull/314) - add `R.and` + +- 4.1.1 Add missing typings for `R.slice` + +- 4.1.0 Add `R.findLast` and `R.findLastIndex` + +- 4.0.2 Fix `R.isEmpty` wrong behaviour compared to the Ramda method + +- 4.0.1 Approve [PR #289](https://github.com/selfrefactor/rambda/pull/289) - remove console.log in `R.values` method + +- 4.0.0 Multiple breaking changes as Rambda methods are changed in order to increase the similarity between with Ramda + +Add to `Differences`: + +```text +R.type can return 'NaN' + +R.compose doesn't pass `this` context + +R.clone doesn't work with number, booleans and strings as input +``` + +All breaking changes: + +-- R.add works only with numbers + +-- Fix R.adjust which had wrong order of arguments + +-- R.adjust works when index is out of bounds + +-- R.complement support function with multiple arguments + +-- R.compose/pipe throws when called with no argument + +-- R.clone works with `Date` value as input + +-- R.drop/dropLast/take/takeLast always return new copy of the list/string + +-- R.take/takeLast return original list/string with negative index + +-- R.equals handles `NaN` and `RegExp` types + +-- R.type/R.equals supports `new Boolean/new Number/new Date/new String` expressions + +-- R.has works with non-object + +-- R.ifElse pass all arguments + +-- R.length works with bad input + +-- R.propEq work with bad input for object argument + +-- R.range work with bad inputs + +-- R.times work with bad inputs + +-- R.reverse works with strings + +-- R.splitEvery throws on non-positive integer index + +-- R.test throws just like Ramda when first argument is not regex + +-- R.values works with bad inputs + +-- R.zipObj ignores extra keys + +- 3.3.0 + +This is pre `4.0.0` release and it contains all of the above changes + +Close [issue #287](https://github.com/selfrefactor/rambda/issues/287) - `ts-toolbelt` directory was changed but not reflected in `files` property in `package.json` + +- 3.2.5 + +Close [issue #273](https://github.com/selfrefactor/rambda/issues/273) - ts-toolbelt needs other type of export when `isolatedModules` TypeScript property + +Close [issue #245](https://github.com/selfrefactor/rambda/issues/245) - complete typings tests for methods that have more specific TypeScript definitions + +- 3.2.1 Fast fix for [issue #273](https://github.com/selfrefactor/rambda/issues/273) - messed up typings + +- 3.2.0 There are several changes: + +Close [issue #263](https://github.com/selfrefactor/rambda/issues/263) - broken curry typing solved by `ts-toolbelt` local dependency. + +Add `R.partialCurry` typings. + +Approve [PR #266](https://github.com/selfrefactor/rambda/pull/266) that adds `R.slice` method. + +- 3.1.0 This might be breaking change for TypeScript users, as very different definitions are introduced. With the previous state of the definitions, it was not possible to pass `dtslint` typings tests. + +- `R.either` and `R.both` supports multiple arguments as they should. + +- Several methods added by [@squidfunk](https://github.com/squidfunk) - `R.assocPath`, `R.symmetricDifference`, `R.intersperse`, `R.intersection` and `R.difference` + +- 3.0.1 Close [issue #234](https://github.com/selfrefactor/rambda/issues/234) - wrong curry typing + +- 3.0.0 Deprecate `R.contains`, while `R.includes` is now following Ramda API(it uses `R.equals` for comparision) + +- 2.14.5 `R.without` needs currying + +- 2.14.4 Close [issue #227](https://github.com/selfrefactor/rambda/issues/227) - add index as third argument of `R.reduce` typings + +- 2.14.2 Use `R.curry` with `R.reduce` as manual curry there didn't work as expected. + +- 2.14.1 Fix wrong typescript with `R.head` - [PR #228](https://github.com/selfrefactor/rambda/pull/228) pushed by [@tonivj5](https://github.com/tonivj5) + +- 2.14.0 Add `R.groupWith` by @selfrefactor | Add `R.propOr`, `R.mathMod`, `R.mean`, `R.median`, `R.negate`, `R.product` by [@ku8ar](https://github.com/ku8ar) + +- 2.13.0 Add `R.identical` - [PR #217](https://github.com/selfrefactor/rambda/pull/217) pushed by [@ku8ar](https://github.com/ku8ar) + +- 2.12.0 Add `R.propIs` - [PR #213](https://github.com/selfrefactor/rambda/pull/213) and add `R.sum` - [issue #207](https://github.com/selfrefactor/rambda/issues/207) + +- 2.11.2 Close Rambdax [issue #32](https://github.com/selfrefactor/rambdax/issues/32) - wrong `R.type` when function is input + +- 2.11.1 Approve [PR #182](https://github.com/selfrefactor/rambda/pull/182) - Changed typings to allow object as input to `R.forEach` and `R.map` + +- 2.11.0 Approve [PR #179](https://github.com/selfrefactor/rambda/pull/179) - `R.adjust` handles negative index; `R.all` doesn't need `R.filter` + +- 2.10.2 Close [issue #175](https://github.com/selfrefactor/rambda/issues/175) - missing typescript file + +- 2.10.0 Approve huge and important [PR #171](https://github.com/selfrefactor/rambda/pull/171) submitted by [@helmuthdu](https://github.com/helmuthdu) - Add comments to each method, improve TypeScript support + +- 2.9.0 `R.toPairs` and `R.fromPairs` + +- 2.8.0 Approve [PR #165](https://github.com/selfrefactor/rambda/pull/165) `R.clone` + +- 2.7.1 expose `src` | Discussed at [issue #147](https://github.com/selfrefactor/rambda/issues/147) + +- 2.7.0 Approve [PR #161](https://github.com/selfrefactor/rambda/pull/161) `R.isEmpty` + +- 2.6.0 `R.map`, `R.filter` and `R.forEach` pass original object to iterator as third argument | Discussed at [issue #147](https://github.com/selfrefactor/rambda/issues/147) + +- 2.5.0 Close [issue #149](https://github.com/selfrefactor/rambda/issues/149) Add `R.partial` | `R.type` handles `NaN` + +- 2.4.0 Major bump of `Rollup`; Stop building for ES5 + +- 2.3.1 Close [issue #90](https://github.com/selfrefactor/rambda/issues/90) | Add string type of path in `R.pathOr` + +- 2.3.0 Close [issue #89](https://github.com/selfrefactor/rambda/issues/89) | Fix missing `Number` TS definition in `R.type` + +- 2.2.0 `R.defaultTo` accepts indefinite number of input arguments. So the following is valid expression: `const x = defaultTo('foo',null, null, 'bar')` + +- 2.1.0 Restore `R.zip` using [WatermelonDB](https://github.com/Nozbe/WatermelonDB/) implementation. + +- 2.0.0 Major version caused by removing of `R.zip` and `R.addIndex`. [Issue #85](https://github.com/selfrefactor/rambda/issues/85) rightfully finds that the implementation of `R.addIndex` is not correct. This led to removing this method and also of `R.zip` as it had depended on it. The second change is that `R.map`, `R.filter` are passing array index as second argument when looping over arrays. The third change is that `R.includes` will return `false` if input is neigher `string` nor `array`. The previous behaviour was to throw an error. The last change is to increase the number of methods that are passing index as second argument to the predicate function. + +- 1.2.6 Use `src` folder instead of `modules` +- 1.2.5 Fix `omit` typing +- 1.2.4 Add missing TypeScript definitions - [PR#82](https://github.com/selfrefactor/rambda/pull/82) +- 1.2.2 Change curry method used across most of library methods +- 1.2.1 Add `R.assoc` | fix passing `undefined` to `R.map` and `R.merge` [issue #77](https://github.com/selfrefactor/rambda/issues/77) +- 1.2.0 Add `R.min`, `R.minBy`, `R.max`, `R.maxBy`, `R.nth` and `R.keys` +- 1.1.5 Close [issue #74](https://github.com/selfrefactor/rambda/issues/74) `R.zipObj` +- 1.1.4 Close [issue #71](https://github.com/selfrefactor/rambda/issues/71) CRA fail to build `rambda` +- 1.1.3 Approve [PR #70](https://github.com/selfrefactor/rambda/pull/67) implement `R.groupBy` | Close [issue #69](https://github.com/selfrefactor/rambda/issues/69) +- 1.1.2 Approve [PR #67](https://github.com/selfrefactor/rambda/pull/67) use `babel-plugin-annotate-pure-calls` +- 1.1.1 Approve [PR #66](https://github.com/selfrefactor/rambda/pull/66) `R.zip` +- 1.1.0 `R.compose` accepts more than one input argument [issue #65](https://github.com/selfrefactor/rambda/issues/65) +- 1.0.13 Approve [PR #64](https://github.com/selfrefactor/rambda/pull/64) `R.indexOf` +- 1.0.12 Close [issue #61](https://github.com/selfrefactor/rambda/issues/61) make all functions modules +- 1.0.11 Close [issue #60](https://github.com/selfrefactor/rambda/issues/60) problem with babelrc +- 1.0.10 Close [issue #59](https://github.com/selfrefactor/rambda/issues/59) add R.dissoc +- 1.0.9 Close [issue #58](https://github.com/selfrefactor/rambda/issues/58) - Incorrect `R.equals` +- 1.0.8 `R.map` and `R.filter` pass object properties when mapping over objects +- 1.0.7 Add `R.uniqWith` +- 1.0.6 Close [issue #52](https://github.com/selfrefactor/rambda/issues/52) - ES5 compatible code +- 1.0.5 Close [issue #51](https://github.com/selfrefactor/rambda/issues/51) +- 1.0.4 Close [issue #50](https://github.com/selfrefactor/rambda/issues/50) - add `R.pipe` typings +- 1.0.3 `R.ifElse` accept also boolean as condition argument +- 1.0.2 Remove `typedDefaultTo` and `typedPathOr` | Add `R.pickAll` and `R.none` +- 1.0.0 Major change as build is now ES6 not ES5 compatible (Related to [issue #46](https://github.com/selfrefactor/rambda/issues/46))| Making `Rambda` fully tree-shakeable| Edit TypeScript definition +- 0.9.8 Revert to ES5 compatible build - [issue #46](https://github.com/selfrefactor/rambda/issues/46) +- 0.9.7 Refactor for `Rollup` tree-shake | Remove `R.padEnd` and `R.padStart` +- 0.9.6 Close [issue #44](https://github.com/selfrefactor/rambda/issues/44) - `R.reverse` mutates the array +- 0.9.5 Close [issue #45](https://github.com/selfrefactor/rambda/issues/45) - invalid TypeScript typings +- 0.9.4 Add `R.reject` and `R.without` ([PR#41](https://github.com/selfrefactor/rambda/pull/41) [PR#42](https://github.com/selfrefactor/rambda/pull/42)) | Remove 'browser' field in `package.json` due to Webpack bug [4674](https://github.com/webpack/webpack/issues/4674) +- 0.9.3 Add `R.forEach` and `R.times` +- 0.9.2 Add `TypeScript` definitions +- 0.9.1 Close [issue #36](https://github.com/selfrefactor/rambda/issues/36) - move current behaviour of `defaultTo` to a new method `typedDefaultTo`; make `defaultTo` follow Ramda spec; add `pathOr`; add `typedPathOr`. +- 0.9.0 Add `R.pipe` [PR#35](https://github.com/selfrefactor/rambda/pull/35) +- 0.8.9 Add `R.isNil` +- 0.8.8 Migrate to ES modules [PR33](https://github.com/selfrefactor/rambda/pull/33) | Add R.flip to the API | R.map/filter works with objects +- 0.8.7 Change `Webpack` with `Rollup` - [PR29](https://github.com/selfrefactor/rambda/pull/29) +- 0.8.6 Add `R.tap` and `R.identity` +- 0.8.5 Add `R.all`, `R.allPass`, `R.both`, `R.either` and `R.complement` +- 0.8.4 Learning to run `yarn test` before `yarn publish` the hard way +- 0.8.3 Add `R.always`, `R.T` and `R.F` +- 0.8.2 Add `concat`, `padStart`, `padEnd`, `lastIndexOf`, `toString`, `reverse`, `endsWith` and `startsWith` methods +- 0.8.1 Add `R.ifElse` +- 0.8.0 Add `R.not`, `R.includes` | Take string as condition for `R.pick` and `R.omit` +- 0.7.6 Fix incorrect implementation of `R.values` +- 0.7.5 Fix incorrect implementation of `R.omit` +- 0.7.4 [issue #13](https://github.com/selfrefactor/rambda/issues/13) - Fix `R.curry`, which used to return incorrectly `function` when called with more arguments +- 0.7.3 Close [issue #9](https://github.com/selfrefactor/rambda/issues/9) - Compile to `es2015`; Approve [PR #10](https://github.com/selfrefactor/rambda/pull/10) - add `R.addIndex` to the API +- 0.7.2 Add `Promise` support for `R.type` +- 0.7.1 Close [issue #7](https://github.com/selfrefactor/rambda/issues/7) - add `R.reduce` to the API +- 0.7.0 Close [issue #5](https://github.com/selfrefactor/rambda/issues/5) - change name of `curry` to `partialCurry`; add new method `curry`, which works just like Ramda's `curry` +- 0.6.2 Add separate documentation site via `docsify` diff --git a/files/README_START.md b/files/README_START.md index 5494ee0e..80957e15 100644 --- a/files/README_START.md +++ b/files/README_START.md @@ -76,7 +76,28 @@ it('within Ramda.pipe requires explicit types', () => { }); ``` -IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. Using them outside(standalone) most likely will result in `unknown` type for inputs. +:exclamation: IMPORTANT - all methods are tested to deliver correct types when they are part of `R.pipe/R.pipeAsync` chains. + +In other words: + +```typescript +R.filter(x => x > 1)([1,2,3]) +``` + +might trigger TS error as it not the same as + +```typescript + +R.pipe([1,2,3], R.filter(x => x > 1) +``` + +### :exclamation: All methods are curried + +There is one way to use `Rambda` methods and it is with currying, i.e. using `R.filter(fn, list)` will not work as it is inteded to be `R.filter(fn)(list)`. + +The reason is that all methods are supposed to be used inside `R.pipe`. After all, building chains is the very base of functional programming. + +Of course, there is value in supporting the case where you can pass all inputs at once, but I find that the price in terms of maintainability is not worth it. ### Keep only the most useful methods diff --git a/index.d.cts b/index.d.cts index 1151a035..d3baee80 100644 --- a/index.d.cts +++ b/index.d.cts @@ -428,8 +428,8 @@ export function head(listOrString: T): T extends string ? string : * * If `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list. */ -export function includes(valueToFind: T): (input: string) => boolean; -export function includes(valueToFind: T): (input: T[]) => boolean; +export function includes(s: string): (list: readonly string[] | string) => boolean; +export function includes(target: T): (list: readonly T[]) => boolean; /** * It transforms list of objects to object using specified property as the base for the returned object. diff --git a/index.d.ts b/index.d.ts index 1151a035..d3baee80 100644 --- a/index.d.ts +++ b/index.d.ts @@ -428,8 +428,8 @@ export function head(listOrString: T): T extends string ? string : * * If `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list. */ -export function includes(valueToFind: T): (input: string) => boolean; -export function includes(valueToFind: T): (input: T[]) => boolean; +export function includes(s: string): (list: readonly string[] | string) => boolean; +export function includes(target: T): (list: readonly T[]) => boolean; /** * It transforms list of objects to object using specified property as the base for the returned object. diff --git a/source/modifyPath.spec.js b/source/modifyPath.spec.js index 3a7bbfd9..cb64cdd3 100644 --- a/source/modifyPath.spec.js +++ b/source/modifyPath.spec.js @@ -1,11 +1,13 @@ import { modifyPath } from './modifyPath.js' +const obj = { a: { b: { c: 1 } } } + test('happy', () => { - const result = modifyPath('a.b.c', x => x + 1)({ a: { b: { c: 1 } } }) + const result = modifyPath('a.b.c', x => x + 1)(obj) expect(result).toEqual({ a: { b: { c: 2 } } }) }) test('works only on existing paths', () => { - const result = modifyPath('a.b.d', x => x + 1)({ a: { b: { c: 1 } } }) - expect(result).toEqual({ a: { b: { c: 1 } } }) + const result = modifyPath('a.b.d', x => x + 1)(obj) + expect(result).toEqual(obj) }) From 1e58d085f068114a3c4897a29e444e8dc7929c5c Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 12 Jul 2025 08:23:14 +0300 Subject: [PATCH 15/54] chore@small --- README.md | 3 +-- docs/README.md | 3 +-- source/includes-spec.ts | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 13e47d2f..3df76d5d 100644 --- a/README.md +++ b/README.md @@ -4882,8 +4882,7 @@ test('with wrong input that does not throw', () => { TypeScript test ```typescript -import { includes } from 'ramda' -import { pipe } from 'rambda' +import { pipe, includes } from 'rambda' describe('R.includes', () => { it('happy', () => { diff --git a/docs/README.md b/docs/README.md index 13e47d2f..3df76d5d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4882,8 +4882,7 @@ test('with wrong input that does not throw', () => { TypeScript test ```typescript -import { includes } from 'ramda' -import { pipe } from 'rambda' +import { pipe, includes } from 'rambda' describe('R.includes', () => { it('happy', () => { diff --git a/source/includes-spec.ts b/source/includes-spec.ts index 855e69d4..cc696b27 100644 --- a/source/includes-spec.ts +++ b/source/includes-spec.ts @@ -1,5 +1,4 @@ -import { includes } from 'ramda' -import { pipe } from 'rambda' +import { pipe, includes } from 'rambda' describe('R.includes', () => { it('happy', () => { From def7fc9a71292a88ac0ffeac1c34778f38139a45 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 27 Jul 2025 12:35:01 +0300 Subject: [PATCH 16/54] chore@small --- source/createObjectFromKeys.js | 4 ++-- source/createObjectFromKeys.spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/createObjectFromKeys.js b/source/createObjectFromKeys.js index 4124d334..73dca47b 100644 --- a/source/createObjectFromKeys.js +++ b/source/createObjectFromKeys.js @@ -1,5 +1,5 @@ -export function createObjectFromKeys(keys) { - return fn => { +export function createObjectFromKeys(fn) { + return keys => { const result = {} keys.forEach((key, index) => { result[key] = fn(key, index) diff --git a/source/createObjectFromKeys.spec.js b/source/createObjectFromKeys.spec.js index f046485e..7b82b9c5 100644 --- a/source/createObjectFromKeys.spec.js +++ b/source/createObjectFromKeys.spec.js @@ -1,7 +1,7 @@ import { createObjectFromKeys } from './createObjectFromKeys.js' test('happy', () => { - const result = createObjectFromKeys(['a', 'b'])((key, index) => key.toUpperCase() + index) + const result = createObjectFromKeys((key, index) => key.toUpperCase() + index)(['a', 'b']) const expected = { a: 'A0', b: 'B1' } expect(result).toEqual(expected) From 44ed90b62d8ab1f5b4934679e9ad2f61d10b61df Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 30 Jul 2025 16:05:50 +0300 Subject: [PATCH 17/54] chore@small --- CHANGELOG.md | 10 +++++----- README.md | 26 ++++++++++++-------------- dist/rambda.cjs | 4 ++-- dist/rambda.js | 4 ++-- dist/rambda.umd.js | 4 ++-- docs/README.md | 26 ++++++++++++-------------- files/index.d.ts | 6 ++---- src/createObjectFromKeys.js | 4 ++-- 8 files changed, 39 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43832c8b..211cd1dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ 10.3.1 -- Fix issue with wrong order of inputs in `R.propOr` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) +- Fix issue with wrong order of inputs in `R.createObjectFromKeys` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) + +10.3.1 + +- Fix issue with wrong order of inputs in `R.propEq` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) - Fix issue with TypeScript definitions for `R.includes`- [Issue #781](https://github.com/selfrefactor/rambda/issues/781) @@ -8,16 +12,12 @@ - Add `R.mapPropObject` -- Add `R.duplicateBy` - Add `R.duplicateBy` -- Add `R.filterAsync` - Add `R.filterAsync` -- Add `R.indexBy` - Add `R.indexBy` -- Restore `R.replaceAll` - Restore `R.replaceAll` - Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. diff --git a/README.md b/README.md index 3df76d5d..4c395392 100644 --- a/README.md +++ b/README.md @@ -834,13 +834,11 @@ append(el: T): (list: T[]) => T[] It adds element `x` at the end of `iterable`. ```javascript -const x = 'foo' - -const result = R.append(x, ['bar', 'baz']) +const result = R.append('foo')(['bar', 'baz']) // => ['bar', 'baz', 'foo'] ``` -Try this R.append example in Rambda REPL +Try this R.append example in Rambda REPL
@@ -1805,8 +1803,8 @@ createObjectFromKeys( R.createObjectFromKeys source ```javascript -export function createObjectFromKeys(keys) { - return fn => { +export function createObjectFromKeys(fn) { + return keys => { const result = {} keys.forEach((key, index) => { result[key] = fn(key, index) @@ -1827,7 +1825,7 @@ export function createObjectFromKeys(keys) { import { createObjectFromKeys } from './createObjectFromKeys.js' test('happy', () => { - const result = createObjectFromKeys(['a', 'b'])((key, index) => key.toUpperCase() + index) + const result = createObjectFromKeys((key, index) => key.toUpperCase() + index)(['a', 'b']) const expected = { a: 'A0', b: 'B1' } expect(result).toEqual(expected) @@ -3117,14 +3115,14 @@ const input = { } const result = R.pipe( input, - evolve({ + R.evolve({ foo: x => x + 1, }) ) // => result is { foo: 3, baz: 'baz' } ``` -Try this R.evolve example in Rambda REPL +Try this R.evolve example in Rambda REPL
@@ -13545,7 +13543,11 @@ describe('R.zipWith', () => { 10.3.1 -- Fix issue with wrong order of inputs in `R.propOr` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) +- Fix issue with wrong order of inputs in `R.createObjectFromKeys` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) + +10.3.1 + +- Fix issue with wrong order of inputs in `R.propEq` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) - Fix issue with TypeScript definitions for `R.includes`- [Issue #781](https://github.com/selfrefactor/rambda/issues/781) @@ -13553,16 +13555,12 @@ describe('R.zipWith', () => { - Add `R.mapPropObject` -- Add `R.duplicateBy` - Add `R.duplicateBy` -- Add `R.filterAsync` - Add `R.filterAsync` -- Add `R.indexBy` - Add `R.indexBy` -- Restore `R.replaceAll` - Restore `R.replaceAll` - Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 08f3302c..f353c2aa 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -230,8 +230,8 @@ function countBy(fn) { } } -function createObjectFromKeys(keys) { - return fn => { +function createObjectFromKeys(fn) { + return keys => { const result = {}; keys.forEach((key, index) => { result[key] = fn(key, index); diff --git a/dist/rambda.js b/dist/rambda.js index 2c54266f..8bb98b3a 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -228,8 +228,8 @@ function countBy(fn) { } } -function createObjectFromKeys(keys) { - return fn => { +function createObjectFromKeys(fn) { + return keys => { const result = {}; keys.forEach((key, index) => { result[key] = fn(key, index); diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index e12cd9dd..0d35ec22 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -234,8 +234,8 @@ } } - function createObjectFromKeys(keys) { - return fn => { + function createObjectFromKeys(fn) { + return keys => { const result = {}; keys.forEach((key, index) => { result[key] = fn(key, index); diff --git a/docs/README.md b/docs/README.md index 3df76d5d..4c395392 100644 --- a/docs/README.md +++ b/docs/README.md @@ -834,13 +834,11 @@ append(el: T): (list: T[]) => T[] It adds element `x` at the end of `iterable`. ```javascript -const x = 'foo' - -const result = R.append(x, ['bar', 'baz']) +const result = R.append('foo')(['bar', 'baz']) // => ['bar', 'baz', 'foo'] ``` -Try this R.append example in Rambda REPL +Try this R.append example in Rambda REPL
@@ -1805,8 +1803,8 @@ createObjectFromKeys( R.createObjectFromKeys source ```javascript -export function createObjectFromKeys(keys) { - return fn => { +export function createObjectFromKeys(fn) { + return keys => { const result = {} keys.forEach((key, index) => { result[key] = fn(key, index) @@ -1827,7 +1825,7 @@ export function createObjectFromKeys(keys) { import { createObjectFromKeys } from './createObjectFromKeys.js' test('happy', () => { - const result = createObjectFromKeys(['a', 'b'])((key, index) => key.toUpperCase() + index) + const result = createObjectFromKeys((key, index) => key.toUpperCase() + index)(['a', 'b']) const expected = { a: 'A0', b: 'B1' } expect(result).toEqual(expected) @@ -3117,14 +3115,14 @@ const input = { } const result = R.pipe( input, - evolve({ + R.evolve({ foo: x => x + 1, }) ) // => result is { foo: 3, baz: 'baz' } ``` -Try this R.evolve example in Rambda REPL +Try this R.evolve example in Rambda REPL
@@ -13545,7 +13543,11 @@ describe('R.zipWith', () => { 10.3.1 -- Fix issue with wrong order of inputs in `R.propOr` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) +- Fix issue with wrong order of inputs in `R.createObjectFromKeys` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) + +10.3.1 + +- Fix issue with wrong order of inputs in `R.propEq` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) - Fix issue with TypeScript definitions for `R.includes`- [Issue #781](https://github.com/selfrefactor/rambda/issues/781) @@ -13553,16 +13555,12 @@ describe('R.zipWith', () => { - Add `R.mapPropObject` -- Add `R.duplicateBy` - Add `R.duplicateBy` -- Add `R.filterAsync` - Add `R.filterAsync` -- Add `R.indexBy` - Add `R.indexBy` -- Restore `R.replaceAll` - Restore `R.replaceAll` - Remove option for `R.mapAsync` to be called outside of `R.pipeAsync`. This is done for consistency as all other methods follow this rule, i.e. they are all curried. diff --git a/files/index.d.ts b/files/index.d.ts index 1a5b52a4..1614d125 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -284,9 +284,7 @@ Explanation: It adds element `x` at the end of `iterable`. Example: ``` -const x = 'foo' - -const result = R.append(x, ['bar', 'baz']) +const result = R.append('foo')(['bar', 'baz']) // => ['bar', 'baz', 'foo'] ``` @@ -3494,7 +3492,7 @@ const input = { } const result = R.pipe( input, - evolve({ + R.evolve({ foo: x => x + 1, }) ) diff --git a/src/createObjectFromKeys.js b/src/createObjectFromKeys.js index 4124d334..73dca47b 100644 --- a/src/createObjectFromKeys.js +++ b/src/createObjectFromKeys.js @@ -1,5 +1,5 @@ -export function createObjectFromKeys(keys) { - return fn => { +export function createObjectFromKeys(fn) { + return keys => { const result = {} keys.forEach((key, index) => { result[key] = fn(key, index) From b4be76e8fbe6282fa00932a98f54ecb112771e04 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 4 Sep 2025 20:00:01 +0300 Subject: [PATCH 18/54] chore@small --- README.md | 11 +- docs/README.md | 11 +- files/index.d.ts | 4 - index.d.cts | 4 - index.d.ts | 4 - package.json | 14 +- yarn.lock | 466 +++++++++++++++++++++++++++-------------------- 7 files changed, 281 insertions(+), 233 deletions(-) diff --git a/README.md b/README.md index ed9a5ab1..6f472471 100644 --- a/README.md +++ b/README.md @@ -9790,9 +9790,8 @@ it('R.reduce', () => { ```typescript reject( - predicate: (value: T) => boolean, - list: T[], -): T[] + predicate: BooleanConstructor, +): (list: readonly T[]) => ("" | null | undefined | false | 0)[] ``` It has the opposite effect of `R.filter`. @@ -9816,10 +9815,6 @@ const result = [ All TypeScript definitions ```typescript -reject( - predicate: (value: T) => boolean, - list: T[], -): T[]; reject( predicate: BooleanConstructor, ): (list: readonly T[]) => ("" | null | undefined | false | 0)[]; @@ -9829,8 +9824,6 @@ reject( reject( predicate: (value: T) => boolean, ): (list: T[]) => T[]; -... -... ```
diff --git a/docs/README.md b/docs/README.md index ed9a5ab1..6f472471 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9790,9 +9790,8 @@ it('R.reduce', () => { ```typescript reject( - predicate: (value: T) => boolean, - list: T[], -): T[] + predicate: BooleanConstructor, +): (list: readonly T[]) => ("" | null | undefined | false | 0)[] ``` It has the opposite effect of `R.filter`. @@ -9816,10 +9815,6 @@ const result = [ All TypeScript definitions ```typescript -reject( - predicate: (value: T) => boolean, - list: T[], -): T[]; reject( predicate: BooleanConstructor, ): (list: readonly T[]) => ("" | null | undefined | false | 0)[]; @@ -9829,8 +9824,6 @@ reject( reject( predicate: (value: T) => boolean, ): (list: T[]) => T[]; -... -... ```
diff --git a/files/index.d.ts b/files/index.d.ts index 3598b229..3369e600 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -2393,10 +2393,6 @@ Notes: */ // @SINGLE_MARKER -export function reject( - predicate: (value: T) => boolean, - list: T[], -): T[]; export function reject( predicate: BooleanConstructor, ): (list: readonly T[]) => ("" | null | undefined | false | 0)[]; diff --git a/index.d.cts b/index.d.cts index aae59214..c9bb7eba 100644 --- a/index.d.cts +++ b/index.d.cts @@ -1789,10 +1789,6 @@ export function reduce(reducer: (prev: TResult, current: T, i: numbe /** * It has the opposite effect of `R.filter`. */ -export function reject( - predicate: (value: T) => boolean, - list: T[], -): T[]; export function reject( predicate: BooleanConstructor, ): (list: readonly T[]) => ("" | null | undefined | false | 0)[]; diff --git a/index.d.ts b/index.d.ts index aae59214..c9bb7eba 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1789,10 +1789,6 @@ export function reduce(reducer: (prev: TResult, current: T, i: numbe /** * It has the opposite effect of `R.filter`. */ -export function reject( - predicate: (value: T) => boolean, - list: T[], -): T[]; export function reject( predicate: BooleanConstructor, ): (list: readonly T[]) => ("" | null | undefined | false | 0)[]; diff --git a/package.json b/package.json index 28e4bf9d..d551ab99 100644 --- a/package.json +++ b/package.json @@ -40,18 +40,18 @@ "devDependencies": { "@definitelytyped/dtslint": "0.0.182", "@types/mocha": "10.0.10", - "@types/node": "24.0.8", - "@vitest/coverage-v8": "4.0.0-beta.2", + "@types/node": "24.3.0", + "@vitest/coverage-v8": "4.0.0-beta.10", "helpers-fn": "2.0.0", "lodash": "4.17.21", "radashi": "13.0.0-beta.ffa4778", "rambdax": "11.3.1", "ramda": "0.31.3", - "remeda": "2.23.2", - "rollup": "4.44.1", - "types-ramda": "0.30.1", - "typescript": "5.9.0-dev.20250630", - "vitest": "4.0.0-beta.2" + "remeda": "2.30.0", + "rollup": "4.50.0", + "types-ramda": "0.31.0", + "typescript": "6.0.0-dev.20250903", + "vitest": "4.0.0-beta.10" }, "jest": { "testEnvironment": "node", diff --git a/yarn.lock b/yarn.lock index c31c8f31..811ca3a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,14 +2,6 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - "@babel/helper-string-parser@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" @@ -277,31 +269,22 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.14": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.23": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -309,6 +292,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.30": + version "0.3.30" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz#4a76c4daeee5df09f5d3940e087442fb36ce2b99" + integrity sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -354,101 +345,206 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz#f768e3b2b0e6b55c595d7a053652c06413713983" integrity sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w== +"@rollup/rollup-android-arm-eabi@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz#939c1be9625d428d8513e4ab60d406fe8db23718" + integrity sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ== + "@rollup/rollup-android-arm64@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz#40379fd5501cfdfd7d8f86dfa1d3ce8d3a609493" integrity sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ== +"@rollup/rollup-android-arm64@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz#b74005775903f7a8f4e363d2840c1dcef3776ff3" + integrity sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw== + "@rollup/rollup-darwin-arm64@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz#972c227bc89fe8a38a3f0c493e1966900e4e1ff7" integrity sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg== +"@rollup/rollup-darwin-arm64@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz#8c04603cdcf1ec0cd6b27152b3827e49295f2962" + integrity sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg== + "@rollup/rollup-darwin-x64@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz#96c919dcb87a5aa7dec5f7f77d90de881e578fdd" integrity sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw== +"@rollup/rollup-darwin-x64@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz#19ec976f1cc663def2692cd7ffb32981f2b0b733" + integrity sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw== + "@rollup/rollup-freebsd-arm64@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz#d199d8eaef830179c0c95b7a6e5455e893d1102c" integrity sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA== +"@rollup/rollup-freebsd-arm64@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz#a96b4ad8346229f6fcbd9d57f1c53040b037c2da" + integrity sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ== + "@rollup/rollup-freebsd-x64@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz#cab01f9e06ca756c1fabe87d64825ae016af4713" integrity sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw== +"@rollup/rollup-freebsd-x64@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz#fa565a282bc57967ee6668607b181678bdd74e4a" + integrity sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA== + "@rollup/rollup-linux-arm-gnueabihf@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz#f6f1c42036dba0e58dc2315305429beff0d02c78" integrity sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ== +"@rollup/rollup-linux-arm-gnueabihf@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz#dfc88f7295e1f98d77f25296be787e8a5d6ced75" + integrity sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w== + "@rollup/rollup-linux-arm-musleabihf@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz#1157e98e740facf858993fb51431dce3a4a96239" integrity sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw== +"@rollup/rollup-linux-arm-musleabihf@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz#32cd70c87455ca031f0361090cf17da5a2ef66d5" + integrity sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg== + "@rollup/rollup-linux-arm64-gnu@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz#b39db73f8a4c22e7db31a4f3fd45170105f33265" integrity sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ== +"@rollup/rollup-linux-arm64-gnu@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz#0e7e1fe7241e3384f6c6b4ccdbcfa8ad8c78b869" + integrity sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g== + "@rollup/rollup-linux-arm64-musl@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz#4043398049fe4449c1485312d1ae9ad8af4056dd" integrity sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g== +"@rollup/rollup-linux-arm64-musl@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz#5d421f2f3e4a84786c4dfd9ce97e595c9b59e7f4" + integrity sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ== + "@rollup/rollup-linux-loongarch64-gnu@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz#855a80e7e86490da15a85dcce247dbc25265bc08" integrity sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew== +"@rollup/rollup-linux-loongarch64-gnu@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz#a0fb5c7d0e88319e18acfd9436f19ee39354b027" + integrity sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ== + "@rollup/rollup-linux-powerpc64le-gnu@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz#8cf843cb7ab1d42e1dda680937cf0a2db6d59047" integrity sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA== +"@rollup/rollup-linux-ppc64-gnu@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz#a65b598af12f25210c3295da551a6e3616ea488d" + integrity sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg== + "@rollup/rollup-linux-riscv64-gnu@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz#287c085472976c8711f16700326f736a527f2f38" integrity sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw== +"@rollup/rollup-linux-riscv64-gnu@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz#10ba776214ae2857c5bf4389690dabb2fbaf7d98" + integrity sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA== + "@rollup/rollup-linux-riscv64-musl@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz#095ad5e53a54ba475979f1b3226b92440c95c892" integrity sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg== +"@rollup/rollup-linux-riscv64-musl@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz#c2a46cbaa329d5f21e5808f5a66bb9c78cf68aac" + integrity sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ== + "@rollup/rollup-linux-s390x-gnu@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz#a3dec8281d8f2aef1703e48ebc65d29fe847933c" integrity sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw== +"@rollup/rollup-linux-s390x-gnu@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz#a07447be069d64462e30c66611be20c4513963ed" + integrity sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ== + "@rollup/rollup-linux-x64-gnu@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz#4b211e6fd57edd6a134740f4f8e8ea61972ff2c5" integrity sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw== +"@rollup/rollup-linux-x64-gnu@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz#8887c58bd51242754ae9c56947d6e883332dcc74" + integrity sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA== + "@rollup/rollup-linux-x64-musl@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz#3ecbf8e21b4157e57bb15dc6837b6db851f9a336" integrity sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g== +"@rollup/rollup-linux-x64-musl@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz#6403fda72a2b3b9fbbeeff93d14f1c45ef9775f3" + integrity sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw== + +"@rollup/rollup-openharmony-arm64@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz#52809afccaff47e731b965a0c16e5686be819d5f" + integrity sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q== + "@rollup/rollup-win32-arm64-msvc@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz#d4aae38465b2ad200557b53c8c817266a3ddbfd0" integrity sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg== +"@rollup/rollup-win32-arm64-msvc@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz#23fe00ddbb40b27a3889bc1e99e6310d97353ad5" + integrity sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg== + "@rollup/rollup-win32-ia32-msvc@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz#0258e8ca052abd48b23fd6113360fa0cd1ec3e23" integrity sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A== +"@rollup/rollup-win32-ia32-msvc@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz#520b588076b593413d919912d69dfd5728a1f305" + integrity sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw== + "@rollup/rollup-win32-x64-msvc@4.44.1": version "4.44.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz#1c982f6a5044ffc2a35cd754a0951bdcb44d5ba0" integrity sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug== +"@rollup/rollup-win32-x64-msvc@4.50.0": + version "4.50.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz#d81efe6a12060c7feddf9805e2a94c3ab0679f48" + integrity sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg== + "@types/chai@^5.2.2": version "5.2.2" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.2.tgz#6f14cea18180ffc4416bc0fd12be05fdd73bdd6b" @@ -481,12 +577,12 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== -"@types/node@24.0.8": - version "24.0.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.8.tgz#98f50977fe76ab78d02fc3bcb7f6c3b5f79a363c" - integrity sha512-WytNrFSgWO/esSH9NbpWUfTMGQwCGIKfCmNlmFDNiI5gGhgMmEA+V1AEvKLeBNvvtBnailJtkrEa2OIISwrVAA== +"@types/node@24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.3.0.tgz#89b09f45cb9a8ee69466f18ee5864e4c3eb84dec" + integrity sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow== dependencies: - undici-types "~7.8.0" + undici-types "~7.10.0" "@types/node@^14.14.35": version "14.18.63" @@ -597,83 +693,80 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@vitest/coverage-v8@4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.0.0-beta.2.tgz#35787962d60b67eaa246e64335d9c3cda8ff4ccf" - integrity sha512-UOknIOkIt05jnJyixC6ajOnPeEtCKiK/RSRpEVB+V5+L331f2C1wF3RA2H00h59+a4TKBsA79Ypab3TViLLeew== +"@vitest/coverage-v8@4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.0.0-beta.10.tgz#00fbd6c64f55b0cd9eb270a1daae149d63cbf6e0" + integrity sha512-euKtmmJPQBAzOQkS60sj9CwKHLxbVIAudybGY2Ah9yzsrZ8LL91loElv7lLd3u3OgYZWjASMDxIS0h4GriYxFA== dependencies: - "@ampproject/remapping" "^2.3.0" "@bcoe/v8-coverage" "^1.0.2" - ast-v8-to-istanbul "^0.3.3" + "@vitest/utils" "4.0.0-beta.10" + ast-v8-to-istanbul "^0.3.4" debug "^4.4.1" istanbul-lib-coverage "^3.2.2" istanbul-lib-report "^3.0.1" istanbul-lib-source-maps "^5.0.6" - istanbul-reports "^3.1.7" - magic-string "^0.30.17" + istanbul-reports "^3.2.0" magicast "^0.3.5" std-env "^3.9.0" tinyrainbow "^2.0.0" -"@vitest/expect@4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.0-beta.2.tgz#1c6a7bb0ec7fd6bad186b120267c270bcf1ddd14" - integrity sha512-ueltEsioQTNsVHCK/K+FiLvvjk0STDywGZK4Kaj39DOk+WrVb3VhXEgGPe7nEMg8lR2m5BwAHsgTXSXbJHqSKA== +"@vitest/expect@4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.0-beta.10.tgz#82df847f297973e86ca7ed6173deee4d46537202" + integrity sha512-03GDRo1imUrqG2ASfC+smzjl81MX5Q8+HDiYrSm0ULs5FJoKOiz4tN62/9BNFzflmsveTp5KCjuN80i18gCDng== dependencies: "@types/chai" "^5.2.2" - "@vitest/spy" "4.0.0-beta.2" - "@vitest/utils" "4.0.0-beta.2" - chai "^5.2.0" + "@vitest/spy" "4.0.0-beta.10" + "@vitest/utils" "4.0.0-beta.10" + chai "^6.0.1" tinyrainbow "^2.0.0" -"@vitest/mocker@4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.0-beta.2.tgz#3fa27e298f7f4d72d4b49313b12ac90890e6530d" - integrity sha512-s7wgIId6hV/uXiij/5jTHwNlMC9+x8JlLJGhu9eEKIqOVw2XsUPSTDjV6z4jBsm801HmNxUUCKUfOQlSmMrHBw== +"@vitest/mocker@4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.0-beta.10.tgz#0e4687752d621afbbbaacb1436bae3248343acd4" + integrity sha512-xjMA9qPCx2WnwX/72UyF1L8cJR6w/OD+HgTLpwcV6RhwFRk3ipdDTLBbTTngnyuaFh/IVXn04zJ7DKdPx1kV3A== dependencies: - "@vitest/spy" "4.0.0-beta.2" + "@vitest/spy" "4.0.0-beta.10" estree-walker "^3.0.3" - magic-string "^0.30.17" + magic-string "^0.30.18" -"@vitest/pretty-format@4.0.0-beta.2", "@vitest/pretty-format@^4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.0-beta.2.tgz#066dac1f4c260f400320963ca61cb7ffe33129fa" - integrity sha512-7UxHosFLnzcKNCZFPKJCeWekV2skUb3z/gvZ2Uf57KRcFfF6Gp90HvkCl+sfDGgELf9RhjRC412al6gQPOwA6g== +"@vitest/pretty-format@4.0.0-beta.10", "@vitest/pretty-format@^4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.0-beta.10.tgz#2f12bcd83fb57b3b847ec03aa7d6f2d0eca1f7c4" + integrity sha512-WHQcKjG+LPfeu4R74gjJqUgrH7y0Gj2oWyQ4rscf8u3nKQS9z+D3lxyrYdwysmX5952ayHBI0x4GJ5MXmM6LCA== dependencies: tinyrainbow "^2.0.0" -"@vitest/runner@4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.0-beta.2.tgz#aae9bf7ded9fcd4de2e737ab710ef9563b1c4bd3" - integrity sha512-5+kSs/a+BFwP3zoY7S+4KPO3FwTzI1ZfWaCrESieb13p6+a+B4jEBkMx4yyOS6fPVQchq/YrRHtbPVVTO1lemg== +"@vitest/runner@4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.0-beta.10.tgz#b25e43515f5ab0ae2d7c490e30c5c0ba2638f62e" + integrity sha512-bHJcMmhS3x9nFhwapm6DNuTbZMQSGEgYyKFm8GNZ35ixpYuCcmRDaA+rm8VwebraoSjkphVrwfdJ/dspaN6Gxw== dependencies: - "@vitest/utils" "4.0.0-beta.2" + "@vitest/utils" "4.0.0-beta.10" pathe "^2.0.3" strip-literal "^3.0.0" -"@vitest/snapshot@4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.0-beta.2.tgz#aa783b4a6165e2d6888f5d38bcc4dc0ea8ccdf5a" - integrity sha512-gFGfWU62QCkIqMIqWCrVO9KnTSLEJN/vgBgk/K9dDyVdyNwYtyDSYffj9QuxQrgq/hkeHKGmK9WDfywgZ7O+Dg== +"@vitest/snapshot@4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.0-beta.10.tgz#838ff1c3373a034a0c0d72823dcaba1475475bf3" + integrity sha512-yHpiggeAt9Fg082/5M8FGhgqp2Pv3nVeOHPZTirl9GbULEiBQiSO6pIkDZRh5gPGyKGbjXj/F/9h07BmtvOXtg== dependencies: - "@vitest/pretty-format" "4.0.0-beta.2" - magic-string "^0.30.17" + "@vitest/pretty-format" "4.0.0-beta.10" + magic-string "^0.30.18" pathe "^2.0.3" -"@vitest/spy@4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.0-beta.2.tgz#ae53e7218025bb233894a56286b83b6120ac589d" - integrity sha512-S8N2U+Z5LRyl9Mfp+0ITACIuAF6CfCpNLKjv9uT9X8TJXf1MJDN1dy5QWHIOU2eNg7B2B2c3Jabbn7Re/PfzLA== - dependencies: - tinyspy "^4.0.3" +"@vitest/spy@4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.0-beta.10.tgz#91809b20c4cc743ef33fcbfb974980214e40011a" + integrity sha512-dz6qAHX+PqMOCq5Hq6nht2L8v9hszdzZM8x2KM9xGC8WESKBJwIdTqPVqLn+DyVzFMtRSAzeujXixDGeDFsrkQ== -"@vitest/utils@4.0.0-beta.2": - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.0-beta.2.tgz#6b9a487284e6421420668e86661ee8bda5ddd814" - integrity sha512-SJuRx8e+0TZBnhJGLRemzoVziJkGskgfhZoCiD27tLEoPUvE7kk7ygSQVGIkYBH/A7i/p+psbF1seMfxV2flOA== +"@vitest/utils@4.0.0-beta.10": + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.0-beta.10.tgz#e77d5b436c59348c87ccab3b0cb965249378c223" + integrity sha512-jKjXM3KR2FUIoU6QOZsFtJG9cNAwszmVg2WWsY/jlD6jhw1ngqoesxUwp3xbbSTeKh/Ii1P1qTaufa5g0oboMA== dependencies: - "@vitest/pretty-format" "4.0.0-beta.2" - loupe "^3.1.4" + "@vitest/pretty-format" "4.0.0-beta.10" + loupe "^3.2.1" tinyrainbow "^2.0.0" acorn-jsx@^5.3.2: @@ -767,17 +860,12 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== -assertion-error@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" - integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== - -ast-v8-to-istanbul@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.3.tgz#697101c116cff6b51c0e668ba6352e7e41fe8dd5" - integrity sha512-MuXMrSLVVoA6sYN/6Hke18vMzrT4TZNbZIj/hvh0fnYFpO+/kFXcLIaiPwXXWaQUPg4yJD8fj+lfJ7/1EBconw== +ast-v8-to-istanbul@^0.3.4: + version "0.3.5" + resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz#9fba217c272dd8c2615603da5de3e1a460b4b9af" + integrity sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA== dependencies: - "@jridgewell/trace-mapping" "^0.3.25" + "@jridgewell/trace-mapping" "^0.3.30" estree-walker "^3.0.3" js-tokens "^9.0.1" @@ -869,11 +957,6 @@ builtins@^1.0.3: resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== -cac@^6.7.14: - version "6.7.14" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - call-bind@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -908,16 +991,10 @@ cfonts@3.3.0: supports-color "^8" window-size "^1" -chai@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05" - integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== - dependencies: - assertion-error "^2.0.1" - check-error "^2.1.1" - deep-eql "^5.0.1" - loupe "^3.1.0" - pathval "^2.0.0" +chai@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-6.0.1.tgz#88c2b4682fb56050647e222d2cf9d6772f2607b3" + integrity sha512-/JOoU2//6p5vCXh00FpNgtlw0LjvhGttaWc+y7wpW9yjBm3ys0dI8tSKZxIOgNruz5J0RleccatSIC3uxEZP0g== chalk@4.0.0: version "4.0.0" @@ -967,11 +1044,6 @@ charm@^1.0.2: dependencies: inherits "^2.0.1" -check-error@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" - integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== - chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -1104,11 +1176,6 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -deep-eql@^5.0.1: - version "5.0.2" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" - integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -1359,10 +1426,10 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -expect-type@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.1.tgz#af76d8b357cf5fa76c41c09dafb79c549e75f71f" - integrity sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw== +expect-type@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.2.tgz#c030a329fb61184126c8447585bc75a7ec6fbff3" + integrity sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA== extend@~3.0.2: version "3.0.2" @@ -1939,10 +2006,10 @@ istanbul-lib-source-maps@^5.0.6: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" -istanbul-reports@^3.1.7: - version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== +istanbul-reports@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93" + integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -2097,15 +2164,10 @@ log-symbols@6.0.0: chalk "^5.3.0" is-unicode-supported "^1.3.0" -loupe@^3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.3.tgz#042a8f7986d77f3d0f98ef7990a2b2fef18b0fd2" - integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug== - -loupe@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.4.tgz#784a0060545cb38778ffb19ccde44d7870d5fdd9" - integrity sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg== +loupe@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" + integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== lru-cache@^6.0.0: version "6.0.0" @@ -2114,12 +2176,12 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@^0.30.17: - version "0.30.17" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" - integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== +magic-string@^0.30.18: + version "0.30.18" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.18.tgz#905bfbbc6aa5692703a93db26a9edcaa0007d2bb" + integrity sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ== dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/sourcemap-codec" "^1.5.5" magicast@^0.3.5: version "0.3.5" @@ -2379,11 +2441,6 @@ pathe@^2.0.3: resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== -pathval@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" - integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -2404,6 +2461,11 @@ picomatch@^4.0.2: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== +picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + postcss@^8.5.6: version "8.5.6" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" @@ -2504,10 +2566,10 @@ readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -remeda@2.23.2: - version "2.23.2" - resolved "https://registry.yarnpkg.com/remeda/-/remeda-2.23.2.tgz#8a9a51d1e47885a39ea0c3b49e7407efbc01009d" - integrity sha512-4W75s4Ii5SDncp1TRLYRspJ+skm/FEHK7NLYk+q8Zy18mFeypXhGPdahmPvHkmqo38KfTTCjAqXRHMkmcQIEGA== +remeda@2.30.0: + version "2.30.0" + resolved "https://registry.yarnpkg.com/remeda/-/remeda-2.30.0.tgz#b4f10b24f32ed84ad9e5cc49ebb0a650f34da6e0" + integrity sha512-TcRpI1ecqnMer3jHhFtMerGvHFCDlCHljUp0/9A4HxHOh5bSY3kP1l8nQDFMnWYJKl3MSarDNY1tb0Bs/bCmvw== dependencies: type-fest "^4.41.0" @@ -2585,7 +2647,37 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@4.44.1, rollup@^4.40.0: +rollup@4.50.0: + version "4.50.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.50.0.tgz#6f237f598b7163ede33ce827af8534c929aaa186" + integrity sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.50.0" + "@rollup/rollup-android-arm64" "4.50.0" + "@rollup/rollup-darwin-arm64" "4.50.0" + "@rollup/rollup-darwin-x64" "4.50.0" + "@rollup/rollup-freebsd-arm64" "4.50.0" + "@rollup/rollup-freebsd-x64" "4.50.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.50.0" + "@rollup/rollup-linux-arm-musleabihf" "4.50.0" + "@rollup/rollup-linux-arm64-gnu" "4.50.0" + "@rollup/rollup-linux-arm64-musl" "4.50.0" + "@rollup/rollup-linux-loongarch64-gnu" "4.50.0" + "@rollup/rollup-linux-ppc64-gnu" "4.50.0" + "@rollup/rollup-linux-riscv64-gnu" "4.50.0" + "@rollup/rollup-linux-riscv64-musl" "4.50.0" + "@rollup/rollup-linux-s390x-gnu" "4.50.0" + "@rollup/rollup-linux-x64-gnu" "4.50.0" + "@rollup/rollup-linux-x64-musl" "4.50.0" + "@rollup/rollup-openharmony-arm64" "4.50.0" + "@rollup/rollup-win32-arm64-msvc" "4.50.0" + "@rollup/rollup-win32-ia32-msvc" "4.50.0" + "@rollup/rollup-win32-x64-msvc" "4.50.0" + fsevents "~2.3.2" + +rollup@^4.40.0: version "4.44.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.44.1.tgz#641723932894e7acbe6052aea34b8e72ef8b7c8f" integrity sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg== @@ -2937,21 +3029,16 @@ tinygradient@^1.1.5: "@types/tinycolor2" "^1.4.0" tinycolor2 "^1.0.0" -tinypool@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.1.1.tgz#059f2d042bd37567fbc017d3d426bdd2a2612591" - integrity sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg== +tinypool@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-2.0.0.tgz#7eaea50341e1026cecb75e04d4e6ea6ede68b7ca" + integrity sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg== tinyrainbow@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== -tinyspy@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-4.0.3.tgz#d1d0f0602f4c15f1aae083a34d6d0df3363b1b52" - integrity sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A== - tmp@^0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" @@ -3049,22 +3136,22 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -types-ramda@0.30.1: - version "0.30.1" - resolved "https://registry.yarnpkg.com/types-ramda/-/types-ramda-0.30.1.tgz#03d255128e3696aeaac76281ca19949e01dddc78" - integrity sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA== +types-ramda@0.31.0: + version "0.31.0" + resolved "https://registry.yarnpkg.com/types-ramda/-/types-ramda-0.31.0.tgz#7cb72d1133107679855aab1e57a0cbffff3ea8b1" + integrity sha512-vaoC35CRC3xvL8Z6HkshDbi6KWM1ezK0LHN0YyxXWUn9HKzBNg/T3xSGlJZjCYspnOD3jE7bcizsp0bUXZDxnQ== dependencies: ts-toolbelt "^9.6.0" -typescript@5.9.0-dev.20250630: - version "5.9.0-dev.20250630" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.0-dev.20250630.tgz#6f9c21e416230168f4177a978b5ed7e587823c41" - integrity sha512-Bjy0Jf/Zzzo+ho6+uRZt3CbhgOCpcvQLJehfDt4jQyaFnTETWeqNefGCy6q/YKyo0u4elifDhfK6xm+cbHCQwA== +typescript@6.0.0-dev.20250903: + version "6.0.0-dev.20250903" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.0-dev.20250903.tgz#01c50750dedfb09b62dd40ba027400cfc04fe871" + integrity sha512-+JORvpkdEk66EV3TFpTTlaEq+hg7mivLa73KRr3g3kI+GhNhmdCWOxfwC6jOG+EgagKX6b8TqO5lsCiaEn3IJA== -undici-types@~7.8.0: - version "7.8.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" - integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== +undici-types@~7.10.0: + version "7.10.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350" + integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag== universalify@^0.1.0: version "0.1.2" @@ -3117,18 +3204,7 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vite-node@4.0.0-beta.2: - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-4.0.0-beta.2.tgz#46f4c8f6442504bfbe1a4f0947a47cfc0e29c6c4" - integrity sha512-FSYo8LrMkY3oBk/zPgkdAje+t12ZHfeVUnKbHyIPK3IVD9ek1ly+JZGu0GJG2eI4QW9zANl2EM7JZX2PWf56Eg== - dependencies: - cac "^6.7.14" - debug "^4.4.1" - es-module-lexer "^1.7.0" - pathe "^2.0.3" - vite "^5.0.0 || ^6.0.0 || ^7.0.0-0" - -"vite@^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite@^6.0.0 || ^7.0.0-0": +"vite@^6.0.0 || ^7.0.0-0": version "7.0.0" resolved "https://registry.yarnpkg.com/vite/-/vite-7.0.0.tgz#5675bb4c956dd9da932583628e7758ab09fe761f" integrity sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g== @@ -3142,33 +3218,31 @@ vite-node@4.0.0-beta.2: optionalDependencies: fsevents "~2.3.3" -vitest@4.0.0-beta.2: - version "4.0.0-beta.2" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.0-beta.2.tgz#62735c72d1c4182f603f08b8e4190c8563121d4c" - integrity sha512-gcuC/+u1i6uPAqnYd/5HiHOW998s2DoiqUi0prRzY5vLyw2hWsqmd9EEqeK8ejUVR1zxh+sRLD4qOc9fJq9l3Q== - dependencies: - "@types/chai" "^5.2.2" - "@vitest/expect" "4.0.0-beta.2" - "@vitest/mocker" "4.0.0-beta.2" - "@vitest/pretty-format" "^4.0.0-beta.2" - "@vitest/runner" "4.0.0-beta.2" - "@vitest/snapshot" "4.0.0-beta.2" - "@vitest/spy" "4.0.0-beta.2" - "@vitest/utils" "4.0.0-beta.2" - chai "^5.2.0" +vitest@4.0.0-beta.10: + version "4.0.0-beta.10" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.0-beta.10.tgz#45ad153e0cd1d0ae446e8382b7546ce9c5deece1" + integrity sha512-lVVa/PjrRMCkFHd7J95UkqNEL+MkLuJoZBoS5B7Y9tqSpOzupVTAgck9HzO5ezxn2SpvIyO0e5o7uBRFW/MZVQ== + dependencies: + "@vitest/expect" "4.0.0-beta.10" + "@vitest/mocker" "4.0.0-beta.10" + "@vitest/pretty-format" "^4.0.0-beta.10" + "@vitest/runner" "4.0.0-beta.10" + "@vitest/snapshot" "4.0.0-beta.10" + "@vitest/spy" "4.0.0-beta.10" + "@vitest/utils" "4.0.0-beta.10" debug "^4.4.1" - expect-type "^1.2.1" - magic-string "^0.30.17" + es-module-lexer "^1.7.0" + expect-type "^1.2.2" + magic-string "^0.30.18" pathe "^2.0.3" - picomatch "^4.0.2" + picomatch "^4.0.3" std-env "^3.9.0" tinybench "^2.9.0" tinyexec "^0.3.2" tinyglobby "^0.2.14" - tinypool "^1.1.1" + tinypool "^2.0.0" tinyrainbow "^2.0.0" vite "^6.0.0 || ^7.0.0-0" - vite-node "4.0.0-beta.2" why-is-node-running "^2.3.0" which-module@^2.0.0: From 59f622f074ee50cb8fd976795b007419d29b1233 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 16 Oct 2025 09:07:53 +0300 Subject: [PATCH 19/54] chore@small --- CHANGELOG.md | 8 +- README.md | 22 +- docs/README.md | 22 +- files/index.d.ts | 4 +- index.d.cts | 4 +- index.d.ts | 4 +- package.json | 12 +- source/pick-spec.ts | 8 +- yarn.lock | 652 +++++++++++++++++--------------------------- 9 files changed, 312 insertions(+), 424 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 211cd1dc..ef62c587 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ -10.3.1 +10.3.3 + +- Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) + +- Improve `R.pick` to not allow non-existing keys as input. + +10.3.2 - Fix issue with wrong order of inputs in `R.createObjectFromKeys` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/README.md b/README.md index 6f472471..5d05b4f7 100644 --- a/README.md +++ b/README.md @@ -8435,7 +8435,7 @@ export function permutations(inputArray) { ```typescript -pick(propsToPick: K[]): (input: T) => MergeTypes>>> +pick(propsToPick: K[]): >>(input: K extends keyof T ? T : never) => MergeTypes> ``` It returns a partial copy of an `input` containing only `propsToPick` properties. @@ -8478,8 +8478,8 @@ const expected = [ All TypeScript definitions ```typescript -pick(propsToPick: K[]): (input: T) => MergeTypes>>>; -pick(propsToPick: S): (input: T) => MergeTypes>>>>>; +pick(propsToPick: K[]): >>(input: K extends keyof T ? T : never) => MergeTypes>; +pick>(propsToPick: S): , any>>>(input: ElementOf extends keyof T ? T : never) => ElementOf extends keyof T ? MergeTypes>> : never; ```
@@ -8567,15 +8567,19 @@ const input = { a: 'foo', c: 3 } describe('R.pick', () => { it('with string as input', () => { - const result = pipe(input, pick('a,c,b,o')) + const result = pipe(input, pick('a,c')) result.a // $ExpectType string result.c // $ExpectType number }) it('with array as input', () => { - const result = pipe(input, pick(['a', 'c'])) + const result = pipe(input, pick(['a', 'c'])) result.a // $ExpectType string result.c // $ExpectType number }) + it('throws error if some keys do not exist', () => { + // @ts-expect-error + pipe(input, pick('a,c,b,o')) + }) }) ``` @@ -13534,7 +13538,13 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -10.3.1 +10.3.3 + +- Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) + +- Improve `R.pick` to not allow non-existing keys as input. + +10.3.2 - Fix issue with wrong order of inputs in `R.createObjectFromKeys` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/docs/README.md b/docs/README.md index 6f472471..5d05b4f7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8435,7 +8435,7 @@ export function permutations(inputArray) { ```typescript -pick(propsToPick: K[]): (input: T) => MergeTypes>>> +pick(propsToPick: K[]): >>(input: K extends keyof T ? T : never) => MergeTypes> ``` It returns a partial copy of an `input` containing only `propsToPick` properties. @@ -8478,8 +8478,8 @@ const expected = [ All TypeScript definitions ```typescript -pick(propsToPick: K[]): (input: T) => MergeTypes>>>; -pick(propsToPick: S): (input: T) => MergeTypes>>>>>; +pick(propsToPick: K[]): >>(input: K extends keyof T ? T : never) => MergeTypes>; +pick>(propsToPick: S): , any>>>(input: ElementOf extends keyof T ? T : never) => ElementOf extends keyof T ? MergeTypes>> : never; ```
@@ -8567,15 +8567,19 @@ const input = { a: 'foo', c: 3 } describe('R.pick', () => { it('with string as input', () => { - const result = pipe(input, pick('a,c,b,o')) + const result = pipe(input, pick('a,c')) result.a // $ExpectType string result.c // $ExpectType number }) it('with array as input', () => { - const result = pipe(input, pick(['a', 'c'])) + const result = pipe(input, pick(['a', 'c'])) result.a // $ExpectType string result.c // $ExpectType number }) + it('throws error if some keys do not exist', () => { + // @ts-expect-error + pipe(input, pick('a,c,b,o')) + }) }) ``` @@ -13534,7 +13538,13 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -10.3.1 +10.3.3 + +- Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) + +- Improve `R.pick` to not allow non-existing keys as input. + +10.3.2 - Fix issue with wrong order of inputs in `R.createObjectFromKeys` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/files/index.d.ts b/files/index.d.ts index 3369e600..7eabd7c4 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -1886,8 +1886,8 @@ Categories: Object Notes: pipe */ // @SINGLE_MARKER -export function pick(propsToPick: K[]): (input: T) => MergeTypes>>>; -export function pick(propsToPick: S): (input: T) => MergeTypes>>>>>; +export function pick(propsToPick: K[]): >>(input: K extends keyof T ? T : never) => MergeTypes>; +export function pick>(propsToPick: S): , any>>>(input: ElementOf extends keyof T ? T : never) => ElementOf extends keyof T ? MergeTypes>> : never; /* Method: pipe diff --git a/index.d.cts b/index.d.cts index c9bb7eba..9c87a630 100644 --- a/index.d.cts +++ b/index.d.cts @@ -1231,8 +1231,8 @@ export function permutations(list: T[]): T[][]; * * String annotation of `propsToPick` is one of the differences between `Rambda` and `Ramda`. */ -export function pick(propsToPick: K[]): (input: T) => MergeTypes>>>; -export function pick(propsToPick: S): (input: T) => MergeTypes>>>>>; +export function pick(propsToPick: K[]): >>(input: K extends keyof T ? T : never) => MergeTypes>; +export function pick>(propsToPick: S): , any>>>(input: ElementOf extends keyof T ? T : never) => ElementOf extends keyof T ? MergeTypes>> : never; /** * It performs left-to-right function composition, where first argument is the input for the chain of functions. diff --git a/index.d.ts b/index.d.ts index c9bb7eba..9c87a630 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1231,8 +1231,8 @@ export function permutations(list: T[]): T[][]; * * String annotation of `propsToPick` is one of the differences between `Rambda` and `Ramda`. */ -export function pick(propsToPick: K[]): (input: T) => MergeTypes>>>; -export function pick(propsToPick: S): (input: T) => MergeTypes>>>>>; +export function pick(propsToPick: K[]): >>(input: K extends keyof T ? T : never) => MergeTypes>; +export function pick>(propsToPick: S): , any>>>(input: ElementOf extends keyof T ? T : never) => ElementOf extends keyof T ? MergeTypes>> : never; /** * It performs left-to-right function composition, where first argument is the input for the chain of functions. diff --git a/package.json b/package.json index d551ab99..7814aaf9 100644 --- a/package.json +++ b/package.json @@ -40,18 +40,18 @@ "devDependencies": { "@definitelytyped/dtslint": "0.0.182", "@types/mocha": "10.0.10", - "@types/node": "24.3.0", - "@vitest/coverage-v8": "4.0.0-beta.10", + "@types/node": "24.7.0", + "@vitest/coverage-v8": "4.0.0-beta.17", "helpers-fn": "2.0.0", "lodash": "4.17.21", "radashi": "13.0.0-beta.ffa4778", "rambdax": "11.3.1", "ramda": "0.31.3", - "remeda": "2.30.0", - "rollup": "4.50.0", + "remeda": "2.32.0", + "rollup": "4.52.4", "types-ramda": "0.31.0", - "typescript": "6.0.0-dev.20250903", - "vitest": "4.0.0-beta.10" + "typescript": "6.0.0-dev.20251006", + "vitest": "4.0.0-beta.17" }, "jest": { "testEnvironment": "node", diff --git a/source/pick-spec.ts b/source/pick-spec.ts index a2491fb6..f1eef655 100644 --- a/source/pick-spec.ts +++ b/source/pick-spec.ts @@ -4,13 +4,17 @@ const input = { a: 'foo', c: 3 } describe('R.pick', () => { it('with string as input', () => { - const result = pipe(input, pick('a,c,b,o')) + const result = pipe(input, pick('a,c')) result.a // $ExpectType string result.c // $ExpectType number }) it('with array as input', () => { - const result = pipe(input, pick(['a', 'c'])) + const result = pipe(input, pick(['a', 'c'])) result.a // $ExpectType string result.c // $ExpectType number }) + it('throws error if some keys do not exist', () => { + // @ts-expect-error + pipe(input, pick('a,c,b,o')) + }) }) diff --git a/yarn.lock b/yarn.lock index 811ca3a3..d8ac6b5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -292,10 +292,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@jridgewell/trace-mapping@^0.3.30": - version "0.3.30" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz#4a76c4daeee5df09f5d3940e087442fb36ce2b99" - integrity sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q== +"@jridgewell/trace-mapping@^0.3.31": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -340,210 +340,115 @@ optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" -"@rollup/rollup-android-arm-eabi@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz#f768e3b2b0e6b55c595d7a053652c06413713983" - integrity sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w== - -"@rollup/rollup-android-arm-eabi@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz#939c1be9625d428d8513e4ab60d406fe8db23718" - integrity sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ== - -"@rollup/rollup-android-arm64@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz#40379fd5501cfdfd7d8f86dfa1d3ce8d3a609493" - integrity sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ== - -"@rollup/rollup-android-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz#b74005775903f7a8f4e363d2840c1dcef3776ff3" - integrity sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw== - -"@rollup/rollup-darwin-arm64@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz#972c227bc89fe8a38a3f0c493e1966900e4e1ff7" - integrity sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg== - -"@rollup/rollup-darwin-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz#8c04603cdcf1ec0cd6b27152b3827e49295f2962" - integrity sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg== - -"@rollup/rollup-darwin-x64@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz#96c919dcb87a5aa7dec5f7f77d90de881e578fdd" - integrity sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw== - -"@rollup/rollup-darwin-x64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz#19ec976f1cc663def2692cd7ffb32981f2b0b733" - integrity sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw== - -"@rollup/rollup-freebsd-arm64@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz#d199d8eaef830179c0c95b7a6e5455e893d1102c" - integrity sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA== - -"@rollup/rollup-freebsd-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz#a96b4ad8346229f6fcbd9d57f1c53040b037c2da" - integrity sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ== - -"@rollup/rollup-freebsd-x64@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz#cab01f9e06ca756c1fabe87d64825ae016af4713" - integrity sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw== - -"@rollup/rollup-freebsd-x64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz#fa565a282bc57967ee6668607b181678bdd74e4a" - integrity sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA== - -"@rollup/rollup-linux-arm-gnueabihf@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz#f6f1c42036dba0e58dc2315305429beff0d02c78" - integrity sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ== - -"@rollup/rollup-linux-arm-gnueabihf@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz#dfc88f7295e1f98d77f25296be787e8a5d6ced75" - integrity sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w== - -"@rollup/rollup-linux-arm-musleabihf@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz#1157e98e740facf858993fb51431dce3a4a96239" - integrity sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw== - -"@rollup/rollup-linux-arm-musleabihf@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz#32cd70c87455ca031f0361090cf17da5a2ef66d5" - integrity sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg== - -"@rollup/rollup-linux-arm64-gnu@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz#b39db73f8a4c22e7db31a4f3fd45170105f33265" - integrity sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ== - -"@rollup/rollup-linux-arm64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz#0e7e1fe7241e3384f6c6b4ccdbcfa8ad8c78b869" - integrity sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g== - -"@rollup/rollup-linux-arm64-musl@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz#4043398049fe4449c1485312d1ae9ad8af4056dd" - integrity sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g== - -"@rollup/rollup-linux-arm64-musl@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz#5d421f2f3e4a84786c4dfd9ce97e595c9b59e7f4" - integrity sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ== - -"@rollup/rollup-linux-loongarch64-gnu@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz#855a80e7e86490da15a85dcce247dbc25265bc08" - integrity sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew== - -"@rollup/rollup-linux-loongarch64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz#a0fb5c7d0e88319e18acfd9436f19ee39354b027" - integrity sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ== - -"@rollup/rollup-linux-powerpc64le-gnu@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz#8cf843cb7ab1d42e1dda680937cf0a2db6d59047" - integrity sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA== - -"@rollup/rollup-linux-ppc64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz#a65b598af12f25210c3295da551a6e3616ea488d" - integrity sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg== - -"@rollup/rollup-linux-riscv64-gnu@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz#287c085472976c8711f16700326f736a527f2f38" - integrity sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw== - -"@rollup/rollup-linux-riscv64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz#10ba776214ae2857c5bf4389690dabb2fbaf7d98" - integrity sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA== - -"@rollup/rollup-linux-riscv64-musl@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz#095ad5e53a54ba475979f1b3226b92440c95c892" - integrity sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg== - -"@rollup/rollup-linux-riscv64-musl@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz#c2a46cbaa329d5f21e5808f5a66bb9c78cf68aac" - integrity sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ== - -"@rollup/rollup-linux-s390x-gnu@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz#a3dec8281d8f2aef1703e48ebc65d29fe847933c" - integrity sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw== - -"@rollup/rollup-linux-s390x-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz#a07447be069d64462e30c66611be20c4513963ed" - integrity sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ== - -"@rollup/rollup-linux-x64-gnu@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz#4b211e6fd57edd6a134740f4f8e8ea61972ff2c5" - integrity sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw== - -"@rollup/rollup-linux-x64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz#8887c58bd51242754ae9c56947d6e883332dcc74" - integrity sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA== - -"@rollup/rollup-linux-x64-musl@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz#3ecbf8e21b4157e57bb15dc6837b6db851f9a336" - integrity sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g== - -"@rollup/rollup-linux-x64-musl@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz#6403fda72a2b3b9fbbeeff93d14f1c45ef9775f3" - integrity sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw== - -"@rollup/rollup-openharmony-arm64@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz#52809afccaff47e731b965a0c16e5686be819d5f" - integrity sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q== - -"@rollup/rollup-win32-arm64-msvc@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz#d4aae38465b2ad200557b53c8c817266a3ddbfd0" - integrity sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg== - -"@rollup/rollup-win32-arm64-msvc@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz#23fe00ddbb40b27a3889bc1e99e6310d97353ad5" - integrity sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg== - -"@rollup/rollup-win32-ia32-msvc@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz#0258e8ca052abd48b23fd6113360fa0cd1ec3e23" - integrity sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A== - -"@rollup/rollup-win32-ia32-msvc@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz#520b588076b593413d919912d69dfd5728a1f305" - integrity sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw== - -"@rollup/rollup-win32-x64-msvc@4.44.1": - version "4.44.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz#1c982f6a5044ffc2a35cd754a0951bdcb44d5ba0" - integrity sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug== - -"@rollup/rollup-win32-x64-msvc@4.50.0": - version "4.50.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz#d81efe6a12060c7feddf9805e2a94c3ab0679f48" - integrity sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg== +"@rollup/rollup-android-arm-eabi@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz#59e7478d310f7e6a7c72453978f562483828112f" + integrity sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA== + +"@rollup/rollup-android-arm64@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz#a825192a0b1b2f27a5c950c439e7e37a33c5d056" + integrity sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w== + +"@rollup/rollup-darwin-arm64@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz#4ee37078bccd725ae3c5f30ef92efc8e1bf886f3" + integrity sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg== + +"@rollup/rollup-darwin-x64@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz#43cc08bd05bf9f388f125e7210a544e62d368d90" + integrity sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw== + +"@rollup/rollup-freebsd-arm64@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz#bc8e640e28abe52450baf3fc80d9b26d9bb6587d" + integrity sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ== + +"@rollup/rollup-freebsd-x64@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz#e981a22e057cc8c65bb523019d344d3a66b15bbc" + integrity sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw== + +"@rollup/rollup-linux-arm-gnueabihf@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz#4036b68904f392a20f3499d63b33e055b67eb274" + integrity sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ== + +"@rollup/rollup-linux-arm-musleabihf@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz#d3b1b9589606e0ff916801c855b1ace9e733427a" + integrity sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q== + +"@rollup/rollup-linux-arm64-gnu@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz#cbf0943c477e3b96340136dd3448eaf144378cf2" + integrity sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg== + +"@rollup/rollup-linux-arm64-musl@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz#837f5a428020d5dce1c3b4cc049876075402cf78" + integrity sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g== + +"@rollup/rollup-linux-loong64-gnu@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz#532c214ababb32ab4bc21b4054278b9a8979e516" + integrity sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ== + +"@rollup/rollup-linux-ppc64-gnu@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz#93900163b61b49cee666d10ee38257a8b1dd161a" + integrity sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g== + +"@rollup/rollup-linux-riscv64-gnu@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz#f0ffdcc7066ca04bc972370c74289f35c7a7dc42" + integrity sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg== + +"@rollup/rollup-linux-riscv64-musl@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz#361695c39dbe96773509745d77a870a32a9f8e48" + integrity sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA== + +"@rollup/rollup-linux-s390x-gnu@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz#09fc6cc2e266a2324e366486ae5d1bca48c43a6a" + integrity sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA== + +"@rollup/rollup-linux-x64-gnu@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz#aa9d5b307c08f05d3454225bb0a2b4cc87eeb2e1" + integrity sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg== + +"@rollup/rollup-linux-x64-musl@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz#26949e5b4645502a61daba2f7a8416bd17cb5382" + integrity sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw== + +"@rollup/rollup-openharmony-arm64@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz#ef493c072f9dac7e0edb6c72d63366846b6ffcd9" + integrity sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA== + +"@rollup/rollup-win32-arm64-msvc@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz#56e1aaa6a630d2202ee7ec0adddd05cf384ffd44" + integrity sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ== + +"@rollup/rollup-win32-ia32-msvc@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz#0a44bbf933a9651c7da2b8569fa448dec0de7480" + integrity sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw== + +"@rollup/rollup-win32-x64-gnu@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz#730e12f0b60b234a7c02d5d3179ca3ec7972033d" + integrity sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ== + +"@rollup/rollup-win32-x64-msvc@4.52.4": + version "4.52.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz#5b2dd648a960b8fa00d76f2cc4eea2f03daa80f4" + integrity sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w== "@types/chai@^5.2.2": version "5.2.2" @@ -577,12 +482,12 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== -"@types/node@24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.3.0.tgz#89b09f45cb9a8ee69466f18ee5864e4c3eb84dec" - integrity sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow== +"@types/node@24.7.0": + version "24.7.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.7.0.tgz#a34c9f0d3401db396782e440317dd5d8373c286f" + integrity sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw== dependencies: - undici-types "~7.10.0" + undici-types "~7.14.0" "@types/node@^14.14.35": version "14.18.63" @@ -693,81 +598,79 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@vitest/coverage-v8@4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.0.0-beta.10.tgz#00fbd6c64f55b0cd9eb270a1daae149d63cbf6e0" - integrity sha512-euKtmmJPQBAzOQkS60sj9CwKHLxbVIAudybGY2Ah9yzsrZ8LL91loElv7lLd3u3OgYZWjASMDxIS0h4GriYxFA== +"@vitest/coverage-v8@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.0.0-beta.17.tgz#0e01e43b988a833d7595f16af54118598d08b109" + integrity sha512-QetR5ju+OeIK6EyOKz/Z3txW9oFTn262VkCngrfXMNwPo6FWTHzMPIl98V/qxIzsAlrSVG85XuVJcC3XdC7LwA== dependencies: "@bcoe/v8-coverage" "^1.0.2" - "@vitest/utils" "4.0.0-beta.10" - ast-v8-to-istanbul "^0.3.4" - debug "^4.4.1" + "@vitest/utils" "4.0.0-beta.17" + ast-v8-to-istanbul "^0.3.5" + debug "^4.4.3" istanbul-lib-coverage "^3.2.2" istanbul-lib-report "^3.0.1" istanbul-lib-source-maps "^5.0.6" istanbul-reports "^3.2.0" magicast "^0.3.5" std-env "^3.9.0" - tinyrainbow "^2.0.0" + tinyrainbow "^3.0.3" -"@vitest/expect@4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.0-beta.10.tgz#82df847f297973e86ca7ed6173deee4d46537202" - integrity sha512-03GDRo1imUrqG2ASfC+smzjl81MX5Q8+HDiYrSm0ULs5FJoKOiz4tN62/9BNFzflmsveTp5KCjuN80i18gCDng== +"@vitest/expect@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.0-beta.17.tgz#4e9a1a1ae8800adee9f9d36f41affb13da1ce532" + integrity sha512-guY0R9wPiwecV5+ptTVC4qGiOB0Ip5NVn9e8T1Wrf4HubG61MDL+iI1dPpkxJBm1U4yXev6gBkT/vrVtR/5q0w== dependencies: "@types/chai" "^5.2.2" - "@vitest/spy" "4.0.0-beta.10" - "@vitest/utils" "4.0.0-beta.10" + "@vitest/spy" "4.0.0-beta.17" + "@vitest/utils" "4.0.0-beta.17" chai "^6.0.1" - tinyrainbow "^2.0.0" + tinyrainbow "^3.0.3" -"@vitest/mocker@4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.0-beta.10.tgz#0e4687752d621afbbbaacb1436bae3248343acd4" - integrity sha512-xjMA9qPCx2WnwX/72UyF1L8cJR6w/OD+HgTLpwcV6RhwFRk3ipdDTLBbTTngnyuaFh/IVXn04zJ7DKdPx1kV3A== +"@vitest/mocker@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.0-beta.17.tgz#9bfce78f6ebbfe93d8458c5ed4ec509db369f45a" + integrity sha512-m56dc63UL10BiFHZ++XdFv58YEHAjRvgL4Mbb+Qlrkk5ul2cs7Q6LzuXDUE2TshVRnPWzwWXT3N+aAygrplIvw== dependencies: - "@vitest/spy" "4.0.0-beta.10" + "@vitest/spy" "4.0.0-beta.17" estree-walker "^3.0.3" - magic-string "^0.30.18" + magic-string "^0.30.19" -"@vitest/pretty-format@4.0.0-beta.10", "@vitest/pretty-format@^4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.0-beta.10.tgz#2f12bcd83fb57b3b847ec03aa7d6f2d0eca1f7c4" - integrity sha512-WHQcKjG+LPfeu4R74gjJqUgrH7y0Gj2oWyQ4rscf8u3nKQS9z+D3lxyrYdwysmX5952ayHBI0x4GJ5MXmM6LCA== +"@vitest/pretty-format@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.0-beta.17.tgz#92928781c5dffd5367308f6ce4168ad93c341abc" + integrity sha512-CSlfXqUgCOem5bawWaWHyEapCiJbLkkpbQJMXbVZMjPXmS25rmTTvLR4R8pGW53GV0b6c1L4Bt2DoZiZtx1elA== dependencies: - tinyrainbow "^2.0.0" + tinyrainbow "^3.0.3" -"@vitest/runner@4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.0-beta.10.tgz#b25e43515f5ab0ae2d7c490e30c5c0ba2638f62e" - integrity sha512-bHJcMmhS3x9nFhwapm6DNuTbZMQSGEgYyKFm8GNZ35ixpYuCcmRDaA+rm8VwebraoSjkphVrwfdJ/dspaN6Gxw== +"@vitest/runner@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.0-beta.17.tgz#1f3ac12fef6effd61697370ddd06977307a15d47" + integrity sha512-jhMbh3NPjZNFQJA3OtCFP5taNmPkyujsXd6T7NK7/0lwgb8CEGqgNfFUe9vZU9i1+HcTz2vRLXKETgyg42fulg== dependencies: - "@vitest/utils" "4.0.0-beta.10" + "@vitest/utils" "4.0.0-beta.17" pathe "^2.0.3" - strip-literal "^3.0.0" -"@vitest/snapshot@4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.0-beta.10.tgz#838ff1c3373a034a0c0d72823dcaba1475475bf3" - integrity sha512-yHpiggeAt9Fg082/5M8FGhgqp2Pv3nVeOHPZTirl9GbULEiBQiSO6pIkDZRh5gPGyKGbjXj/F/9h07BmtvOXtg== +"@vitest/snapshot@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.0-beta.17.tgz#fee457fbd59d8dde9556e184ae90207bd0064487" + integrity sha512-Ccq1hYME9kgxWiqlsTyVjkpRTAaGOVMOKJryYv1ybePg0TJFdPts32WYW74J8YKg53ZcDOjWhv3QkTTl7p7Ntw== dependencies: - "@vitest/pretty-format" "4.0.0-beta.10" - magic-string "^0.30.18" + "@vitest/pretty-format" "4.0.0-beta.17" + magic-string "^0.30.19" pathe "^2.0.3" -"@vitest/spy@4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.0-beta.10.tgz#91809b20c4cc743ef33fcbfb974980214e40011a" - integrity sha512-dz6qAHX+PqMOCq5Hq6nht2L8v9hszdzZM8x2KM9xGC8WESKBJwIdTqPVqLn+DyVzFMtRSAzeujXixDGeDFsrkQ== +"@vitest/spy@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.0-beta.17.tgz#199db3930db8096896427e4c2722ec376f225b9f" + integrity sha512-c6sIXHQSMx1yDBbDF1vHDaJ+2KQySOExYuQhFMj3lG1woTVdRmX1omtPsLypsa7uVwVLc466DtLVvgAsSQIi2g== -"@vitest/utils@4.0.0-beta.10": - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.0-beta.10.tgz#e77d5b436c59348c87ccab3b0cb965249378c223" - integrity sha512-jKjXM3KR2FUIoU6QOZsFtJG9cNAwszmVg2WWsY/jlD6jhw1ngqoesxUwp3xbbSTeKh/Ii1P1qTaufa5g0oboMA== +"@vitest/utils@4.0.0-beta.17": + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.0-beta.17.tgz#357fd40911dc66f584aaefeab288695463ac1e0d" + integrity sha512-PdhF3Kk1QFQ0H6iQzILGXCNDuhFgdxJKGJwzpPr/Hk7KWKiymj2w/7gusB95Ckh0t/kJPW+O99afLzoRPGsrFw== dependencies: - "@vitest/pretty-format" "4.0.0-beta.10" - loupe "^3.2.1" - tinyrainbow "^2.0.0" + "@vitest/pretty-format" "4.0.0-beta.17" + tinyrainbow "^3.0.3" acorn-jsx@^5.3.2: version "5.3.2" @@ -860,12 +763,12 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== -ast-v8-to-istanbul@^0.3.4: - version "0.3.5" - resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz#9fba217c272dd8c2615603da5de3e1a460b4b9af" - integrity sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA== +ast-v8-to-istanbul@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.6.tgz#5ef80900b52fdf58a3d9cdb8e692f70d9460aebf" + integrity sha512-9tx1z/7OF/a8EdYL3FKoBhxLf3h3D8fXvuSj0HknsVeli2HE40qbNZxyFhMtnydaRiamwFu9zhb+BsJ5tVPehQ== dependencies: - "@jridgewell/trace-mapping" "^0.3.30" + "@jridgewell/trace-mapping" "^0.3.31" estree-walker "^3.0.3" js-tokens "^9.0.1" @@ -1164,10 +1067,10 @@ debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" -debug@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" - integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== +debug@^4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" @@ -1484,10 +1387,10 @@ fdir@6.1.1: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.1.1.tgz#316b58145a05223b75c8b371e80bb3bad8f1441e" integrity sha512-QfKBVg453Dyn3mr0Q0O+Tkr1r79lOTAKSi9f/Ot4+qVEwxWhav2Z+SudrG9vQjM2aYRMQQZ2/Q1zdA8ACM1pDg== -fdir@^6.4.4, fdir@^6.4.6: - version "6.4.6" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" - integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== file-entry-cache@^6.0.1: version "6.0.1" @@ -2164,11 +2067,6 @@ log-symbols@6.0.0: chalk "^5.3.0" is-unicode-supported "^1.3.0" -loupe@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" - integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2176,10 +2074,10 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@^0.30.18: - version "0.30.18" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.18.tgz#905bfbbc6aa5692703a93db26a9edcaa0007d2bb" - integrity sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ== +magic-string@^0.30.19: + version "0.30.19" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.19.tgz#cebe9f104e565602e5d2098c5f2e79a77cc86da9" + integrity sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw== dependencies: "@jridgewell/sourcemap-codec" "^1.5.5" @@ -2456,11 +2354,6 @@ picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - picomatch@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" @@ -2566,10 +2459,10 @@ readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -remeda@2.30.0: - version "2.30.0" - resolved "https://registry.yarnpkg.com/remeda/-/remeda-2.30.0.tgz#b4f10b24f32ed84ad9e5cc49ebb0a650f34da6e0" - integrity sha512-TcRpI1ecqnMer3jHhFtMerGvHFCDlCHljUp0/9A4HxHOh5bSY3kP1l8nQDFMnWYJKl3MSarDNY1tb0Bs/bCmvw== +remeda@2.32.0: + version "2.32.0" + resolved "https://registry.yarnpkg.com/remeda/-/remeda-2.32.0.tgz#51eafec73c6ee80c44689d44bb0233255c41b724" + integrity sha512-BZx9DsT4FAgXDTOdgJIc5eY6ECIXMwtlSPQoPglF20ycSWigttDDe88AozEsPPT4OWk5NujroGSBC1phw5uU+w== dependencies: type-fest "^4.41.0" @@ -2647,63 +2540,35 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@4.50.0: - version "4.50.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.50.0.tgz#6f237f598b7163ede33ce827af8534c929aaa186" - integrity sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw== - dependencies: - "@types/estree" "1.0.8" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.50.0" - "@rollup/rollup-android-arm64" "4.50.0" - "@rollup/rollup-darwin-arm64" "4.50.0" - "@rollup/rollup-darwin-x64" "4.50.0" - "@rollup/rollup-freebsd-arm64" "4.50.0" - "@rollup/rollup-freebsd-x64" "4.50.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.50.0" - "@rollup/rollup-linux-arm-musleabihf" "4.50.0" - "@rollup/rollup-linux-arm64-gnu" "4.50.0" - "@rollup/rollup-linux-arm64-musl" "4.50.0" - "@rollup/rollup-linux-loongarch64-gnu" "4.50.0" - "@rollup/rollup-linux-ppc64-gnu" "4.50.0" - "@rollup/rollup-linux-riscv64-gnu" "4.50.0" - "@rollup/rollup-linux-riscv64-musl" "4.50.0" - "@rollup/rollup-linux-s390x-gnu" "4.50.0" - "@rollup/rollup-linux-x64-gnu" "4.50.0" - "@rollup/rollup-linux-x64-musl" "4.50.0" - "@rollup/rollup-openharmony-arm64" "4.50.0" - "@rollup/rollup-win32-arm64-msvc" "4.50.0" - "@rollup/rollup-win32-ia32-msvc" "4.50.0" - "@rollup/rollup-win32-x64-msvc" "4.50.0" - fsevents "~2.3.2" - -rollup@^4.40.0: - version "4.44.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.44.1.tgz#641723932894e7acbe6052aea34b8e72ef8b7c8f" - integrity sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg== +rollup@4.52.4, rollup@^4.43.0: + version "4.52.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.52.4.tgz#71e64cce96a865fcbaa6bb62c6e82807f4e378a1" + integrity sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ== dependencies: "@types/estree" "1.0.8" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.44.1" - "@rollup/rollup-android-arm64" "4.44.1" - "@rollup/rollup-darwin-arm64" "4.44.1" - "@rollup/rollup-darwin-x64" "4.44.1" - "@rollup/rollup-freebsd-arm64" "4.44.1" - "@rollup/rollup-freebsd-x64" "4.44.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.44.1" - "@rollup/rollup-linux-arm-musleabihf" "4.44.1" - "@rollup/rollup-linux-arm64-gnu" "4.44.1" - "@rollup/rollup-linux-arm64-musl" "4.44.1" - "@rollup/rollup-linux-loongarch64-gnu" "4.44.1" - "@rollup/rollup-linux-powerpc64le-gnu" "4.44.1" - "@rollup/rollup-linux-riscv64-gnu" "4.44.1" - "@rollup/rollup-linux-riscv64-musl" "4.44.1" - "@rollup/rollup-linux-s390x-gnu" "4.44.1" - "@rollup/rollup-linux-x64-gnu" "4.44.1" - "@rollup/rollup-linux-x64-musl" "4.44.1" - "@rollup/rollup-win32-arm64-msvc" "4.44.1" - "@rollup/rollup-win32-ia32-msvc" "4.44.1" - "@rollup/rollup-win32-x64-msvc" "4.44.1" + "@rollup/rollup-android-arm-eabi" "4.52.4" + "@rollup/rollup-android-arm64" "4.52.4" + "@rollup/rollup-darwin-arm64" "4.52.4" + "@rollup/rollup-darwin-x64" "4.52.4" + "@rollup/rollup-freebsd-arm64" "4.52.4" + "@rollup/rollup-freebsd-x64" "4.52.4" + "@rollup/rollup-linux-arm-gnueabihf" "4.52.4" + "@rollup/rollup-linux-arm-musleabihf" "4.52.4" + "@rollup/rollup-linux-arm64-gnu" "4.52.4" + "@rollup/rollup-linux-arm64-musl" "4.52.4" + "@rollup/rollup-linux-loong64-gnu" "4.52.4" + "@rollup/rollup-linux-ppc64-gnu" "4.52.4" + "@rollup/rollup-linux-riscv64-gnu" "4.52.4" + "@rollup/rollup-linux-riscv64-musl" "4.52.4" + "@rollup/rollup-linux-s390x-gnu" "4.52.4" + "@rollup/rollup-linux-x64-gnu" "4.52.4" + "@rollup/rollup-linux-x64-musl" "4.52.4" + "@rollup/rollup-openharmony-arm64" "4.52.4" + "@rollup/rollup-win32-arm64-msvc" "4.52.4" + "@rollup/rollup-win32-ia32-msvc" "4.52.4" + "@rollup/rollup-win32-x64-gnu" "4.52.4" + "@rollup/rollup-win32-x64-msvc" "4.52.4" fsevents "~2.3.2" run-parallel@^1.1.9: @@ -2932,13 +2797,6 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-literal@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-3.0.0.tgz#ce9c452a91a0af2876ed1ae4e583539a353df3fc" - integrity sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA== - dependencies: - js-tokens "^9.0.1" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -3013,13 +2871,13 @@ tinyexec@^0.3.2: resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== -tinyglobby@^0.2.14: - version "0.2.14" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" - integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== +tinyglobby@^0.2.15: + version "0.2.15" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" + integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== dependencies: - fdir "^6.4.4" - picomatch "^4.0.2" + fdir "^6.5.0" + picomatch "^4.0.3" tinygradient@^1.1.5: version "1.1.5" @@ -3034,10 +2892,10 @@ tinypool@^2.0.0: resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-2.0.0.tgz#7eaea50341e1026cecb75e04d4e6ea6ede68b7ca" integrity sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg== -tinyrainbow@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" - integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== +tinyrainbow@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42" + integrity sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q== tmp@^0.2.1: version "0.2.3" @@ -3143,15 +3001,15 @@ types-ramda@0.31.0: dependencies: ts-toolbelt "^9.6.0" -typescript@6.0.0-dev.20250903: - version "6.0.0-dev.20250903" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.0-dev.20250903.tgz#01c50750dedfb09b62dd40ba027400cfc04fe871" - integrity sha512-+JORvpkdEk66EV3TFpTTlaEq+hg7mivLa73KRr3g3kI+GhNhmdCWOxfwC6jOG+EgagKX6b8TqO5lsCiaEn3IJA== +typescript@6.0.0-dev.20251006: + version "6.0.0-dev.20251006" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.0-dev.20251006.tgz#f8c6b3dc5f7df5fc8fdaefa691f0c6e73ebe4428" + integrity sha512-DHt+o3xZV+a3cambN7XN1l0RH9PP3bYhUn2pwWyHqSA7j5HSR4MjTEf2hFGpty3/IZj6zHztEBtq4B6bGRdJgg== -undici-types@~7.10.0: - version "7.10.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350" - integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag== +undici-types@~7.14.0: + version "7.14.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.14.0.tgz#4c037b32ca4d7d62fae042174604341588bc0840" + integrity sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA== universalify@^0.1.0: version "0.1.2" @@ -3204,45 +3062,45 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -"vite@^6.0.0 || ^7.0.0-0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/vite/-/vite-7.0.0.tgz#5675bb4c956dd9da932583628e7758ab09fe761f" - integrity sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g== +"vite@^6.0.0 || ^7.0.0": + version "7.1.10" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.10.tgz#47c9970f3b0fe9057bfbcfeff8cd370edd7bd41b" + integrity sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA== dependencies: esbuild "^0.25.0" - fdir "^6.4.6" - picomatch "^4.0.2" + fdir "^6.5.0" + picomatch "^4.0.3" postcss "^8.5.6" - rollup "^4.40.0" - tinyglobby "^0.2.14" + rollup "^4.43.0" + tinyglobby "^0.2.15" optionalDependencies: fsevents "~2.3.3" -vitest@4.0.0-beta.10: - version "4.0.0-beta.10" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.0-beta.10.tgz#45ad153e0cd1d0ae446e8382b7546ce9c5deece1" - integrity sha512-lVVa/PjrRMCkFHd7J95UkqNEL+MkLuJoZBoS5B7Y9tqSpOzupVTAgck9HzO5ezxn2SpvIyO0e5o7uBRFW/MZVQ== - dependencies: - "@vitest/expect" "4.0.0-beta.10" - "@vitest/mocker" "4.0.0-beta.10" - "@vitest/pretty-format" "^4.0.0-beta.10" - "@vitest/runner" "4.0.0-beta.10" - "@vitest/snapshot" "4.0.0-beta.10" - "@vitest/spy" "4.0.0-beta.10" - "@vitest/utils" "4.0.0-beta.10" - debug "^4.4.1" +vitest@4.0.0-beta.17: + version "4.0.0-beta.17" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.0-beta.17.tgz#ab9a1105256d52d5d2b9c0439075d66502a8de9a" + integrity sha512-R2vM2ErERS4hcmrZ0vrGhy/v9HEkCRnUXHJLhuvnQfO8uWspjuMNxIej1Ru/pBvR5pDfN2mqb1679Lk4yyJ7NA== + dependencies: + "@vitest/expect" "4.0.0-beta.17" + "@vitest/mocker" "4.0.0-beta.17" + "@vitest/pretty-format" "4.0.0-beta.17" + "@vitest/runner" "4.0.0-beta.17" + "@vitest/snapshot" "4.0.0-beta.17" + "@vitest/spy" "4.0.0-beta.17" + "@vitest/utils" "4.0.0-beta.17" + debug "^4.4.3" es-module-lexer "^1.7.0" expect-type "^1.2.2" - magic-string "^0.30.18" + magic-string "^0.30.19" pathe "^2.0.3" picomatch "^4.0.3" std-env "^3.9.0" tinybench "^2.9.0" tinyexec "^0.3.2" - tinyglobby "^0.2.14" + tinyglobby "^0.2.15" tinypool "^2.0.0" - tinyrainbow "^2.0.0" - vite "^6.0.0 || ^7.0.0-0" + tinyrainbow "^3.0.3" + vite "^6.0.0 || ^7.0.0" why-is-node-running "^2.3.0" which-module@^2.0.0: From ca308a67d78ba232e9cafa3779a3002a4a48a5ec Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 19 Oct 2025 17:53:55 +0300 Subject: [PATCH 20/54] chore@small --- README.md | 32 ++++++++++++++++++-------------- docs/README.md | 32 ++++++++++++++++++-------------- files/index.d.ts | 12 ++---------- index.d.cts | 12 ++---------- index.d.ts | 12 ++---------- source/map-spec.ts | 16 +++++++++++++++- 6 files changed, 57 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 5d05b4f7..91ac0984 100644 --- a/README.md +++ b/README.md @@ -5885,7 +5885,7 @@ describe('R.lastIndexOf', () => { ```typescript map( - fn: (value: T[number], index: number) => U, + fn: (value: T[number], index: number) => U, ): (data: T) => Mapped ``` @@ -5911,21 +5911,11 @@ const result = R.map(fn)(iterable), ```typescript map( - fn: (value: T[number], index: number) => U, + fn: (value: T[number], index: number) => U, ): (data: T) => Mapped; map( - fn: (value: T[number]) => U, + fn: (value: T[number]) => U, ): (data: T) => Mapped; -map( - fn: (value: T[number], index: number) => U, - data: T -) : Mapped; -map( - fn: (value: T[number]) => U, - data: T -) : Mapped; -... -... ```
@@ -5979,7 +5969,7 @@ import { map, pipe } from 'rambda' const list = [1, 2, 3] -it('R.map', () => { +it('R.map - within pipe', () => { const result = pipe( list, x => x, @@ -5990,6 +5980,20 @@ it('R.map', () => { ) result // $ExpectType string[] }) + +it('R.map - without pipe', () => { + map(x => { + x // $ExpectType unknown + })([1, 2, 3]) +}) + +it('R.map - without pipe but explicitly typed', () => { + const result = map(x => { + x // $ExpectType number[] + return String(x) + })([1, 2, 3]) + result // $ExpectType string[] +}) ```
diff --git a/docs/README.md b/docs/README.md index 5d05b4f7..91ac0984 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5885,7 +5885,7 @@ describe('R.lastIndexOf', () => { ```typescript map( - fn: (value: T[number], index: number) => U, + fn: (value: T[number], index: number) => U, ): (data: T) => Mapped ``` @@ -5911,21 +5911,11 @@ const result = R.map(fn)(iterable), ```typescript map( - fn: (value: T[number], index: number) => U, + fn: (value: T[number], index: number) => U, ): (data: T) => Mapped; map( - fn: (value: T[number]) => U, + fn: (value: T[number]) => U, ): (data: T) => Mapped; -map( - fn: (value: T[number], index: number) => U, - data: T -) : Mapped; -map( - fn: (value: T[number]) => U, - data: T -) : Mapped; -... -... ```
@@ -5979,7 +5969,7 @@ import { map, pipe } from 'rambda' const list = [1, 2, 3] -it('R.map', () => { +it('R.map - within pipe', () => { const result = pipe( list, x => x, @@ -5990,6 +5980,20 @@ it('R.map', () => { ) result // $ExpectType string[] }) + +it('R.map - without pipe', () => { + map(x => { + x // $ExpectType unknown + })([1, 2, 3]) +}) + +it('R.map - without pipe but explicitly typed', () => { + const result = map(x => { + x // $ExpectType number[] + return String(x) + })([1, 2, 3]) + result // $ExpectType string[] +}) ```
diff --git a/files/index.d.ts b/files/index.d.ts index 7eabd7c4..95580d96 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -986,19 +986,11 @@ Notes: This function doesn't work with objects (use R.mapObject instead) */ // @SINGLE_MARKER export function map( - fn: (value: T[number], index: number) => U, + fn: (value: T[number], index: number) => U, ): (data: T) => Mapped; export function map( - fn: (value: T[number]) => U, + fn: (value: T[number]) => U, ): (data: T) => Mapped; -export function map( - fn: (value: T[number], index: number) => U, - data: T -) : Mapped; -export function map( - fn: (value: T[number]) => U, - data: T -) : Mapped; /* Method: mapObject diff --git a/index.d.cts b/index.d.cts index 9c87a630..00f365db 100644 --- a/index.d.cts +++ b/index.d.cts @@ -508,19 +508,11 @@ export function lastIndexOf(target: T): (list: T[]) => number; * It returns the result of looping through `iterable` with `fn`. */ export function map( - fn: (value: T[number], index: number) => U, + fn: (value: T[number], index: number) => U, ): (data: T) => Mapped; export function map( - fn: (value: T[number]) => U, + fn: (value: T[number]) => U, ): (data: T) => Mapped; -export function map( - fn: (value: T[number], index: number) => U, - data: T -) : Mapped; -export function map( - fn: (value: T[number]) => U, - data: T -) : Mapped; /** * Sequential asynchronous mapping with `fn` over members of `list`. diff --git a/index.d.ts b/index.d.ts index 9c87a630..00f365db 100644 --- a/index.d.ts +++ b/index.d.ts @@ -508,19 +508,11 @@ export function lastIndexOf(target: T): (list: T[]) => number; * It returns the result of looping through `iterable` with `fn`. */ export function map( - fn: (value: T[number], index: number) => U, + fn: (value: T[number], index: number) => U, ): (data: T) => Mapped; export function map( - fn: (value: T[number]) => U, + fn: (value: T[number]) => U, ): (data: T) => Mapped; -export function map( - fn: (value: T[number], index: number) => U, - data: T -) : Mapped; -export function map( - fn: (value: T[number]) => U, - data: T -) : Mapped; /** * Sequential asynchronous mapping with `fn` over members of `list`. diff --git a/source/map-spec.ts b/source/map-spec.ts index f00d5586..44647453 100644 --- a/source/map-spec.ts +++ b/source/map-spec.ts @@ -2,7 +2,7 @@ import { map, pipe } from 'rambda' const list = [1, 2, 3] -it('R.map', () => { +it('R.map - within pipe', () => { const result = pipe( list, x => x, @@ -13,3 +13,17 @@ it('R.map', () => { ) result // $ExpectType string[] }) + +it('R.map - without pipe', () => { + map(x => { + x // $ExpectType unknown + })([1, 2, 3]) +}) + +it('R.map - without pipe but explicitly typed', () => { + const result = map(x => { + x // $ExpectType number[] + return String(x) + })([1, 2, 3]) + result // $ExpectType string[] +}) From cd6a42b2661f65352bec2716484bad48799b198b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 23 Oct 2025 00:56:00 +0300 Subject: [PATCH 21/54] kata --- source/ts-katas.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 source/ts-katas.ts diff --git a/source/ts-katas.ts b/source/ts-katas.ts new file mode 100644 index 00000000..de065d1c --- /dev/null +++ b/source/ts-katas.ts @@ -0,0 +1,56 @@ +import { IterableContainer, map, pipe,Mapped, MergeTypes } from 'rambda' + +const list = [1, 2, 3] +type SnakeCase = T extends `${infer F}${infer R}` +? F extends Uppercase +? `_${Lowercase}${SnakeCase}` +: `${F}${SnakeCase}` +: ""; + +type MapType = T extends readonly [infer F, ...infer R] +? R extends readonly string[] + ? [SnakeCase, ...MapType] + : [SnakeCase] +: [] + +const mapToSnakeCase = (str: T) => { + return str.map(x => { + return x.replace(/([A-Z])/g, '_$1').toLowerCase() + }) as MapType +} +it('R.map - with x', () => { + const strings = ['fOo', 'bar', 'baz'] as const; + const result = pipe( + strings, + mapToSnakeCase, + ) + result // $ExpectType string[] +}) + +it('R.map - within pipe', () => { + const result = pipe( + list, + x => x, + map(x => { + x // $ExpectType number + return String(x) + }), + ) + result // $ExpectType string[] +}) + + +it('R.map - without pipe', () => { + map(x => { + x // $ExpectType unknown + })([1, 2, 3]) +}) + +it('R.map - without pipe but explicitly typed', () => { + const result = map(x => { + x // $ExpectType number[] + return String(x) + })([1, 2, 3]) + result // $ExpectType string[] +}) + From 2b5ff5cadcb10978d2e8f497d95e7a685219c268 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 23 Oct 2025 01:20:47 +0300 Subject: [PATCH 22/54] 2 --- source/ts-katas.ts | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/source/ts-katas.ts b/source/ts-katas.ts index de065d1c..b460ccf0 100644 --- a/source/ts-katas.ts +++ b/source/ts-katas.ts @@ -1,6 +1,41 @@ -import { IterableContainer, map, pipe,Mapped, MergeTypes } from 'rambda' +import { IterableContainer, map, pipe,Mapped, MergeTypes, MergeTypesAlternative } from 'rambda' const list = [1, 2, 3] +type ToFunctions = T extends [infer E] ? (a: E) => void : never; +type DeepPick = K extends keyof T ? { [P in K]: T[P] } : K extends `${infer A extends keyof T & string}.${infer B}` ? { [P in A]: DeepPick } +: never +type DeepPickAll = K extends [infer F, ...infer Rest extends string[]] ? MergeTypes & DeepPickAll> : {} + +type f = DeepPick<{ a: { b: { c: string } } }, 'a.b.c'> +type f2 = DeepPickAll<{ b: 1,a: { b: { c: string } } }, ['a.b', 'b']> +type f2s = MergeTypesAlternative> + + +function deepPick(obj: T, key: K): DeepPick { + return key.split('.').reduce((acc: any, k: string) => { + return acc?.[k] + }, obj) as DeepPick +} + +function deepPickAll(obj: T, keys: K): MergeTypes> { + return keys.reduce((acc, key) => { + return { ...acc, ...deepPick(obj, key) } + }, {} as MergeTypes>) +} + +let l = deepPick({ a: { b: { c: 1 } } }, 'a.b.c') +l.a.b.c +let l2 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) +let l3 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) +let l4 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) +let l5 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) +let l6 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) +let l7 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) +let l8 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) + + + + type SnakeCase = T extends `${infer F}${infer R}` ? F extends Uppercase ? `_${Lowercase}${SnakeCase}` From 99943e225f6ff52f55b19caa81893aeb16666777 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 23 Oct 2025 01:32:03 +0300 Subject: [PATCH 23/54] 3 --- source/ts-katas.ts | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/source/ts-katas.ts b/source/ts-katas.ts index b460ccf0..8544f66b 100644 --- a/source/ts-katas.ts +++ b/source/ts-katas.ts @@ -17,23 +17,12 @@ function deepPick(obj: T, key: K): DeepPick { }, obj) as DeepPick } -function deepPickAll(obj: T, keys: K): MergeTypes> { - return keys.reduce((acc, key) => { - return { ...acc, ...deepPick(obj, key) } - }, {} as MergeTypes>) +const deepPickAll = (obj: T, keys: K): DeepPickAll => { + return null as any } - let l = deepPick({ a: { b: { c: 1 } } }, 'a.b.c') l.a.b.c -let l2 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) -let l3 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) -let l4 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) -let l5 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) -let l6 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) -let l7 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) -let l8 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c', 'a.b']) - - +let l2 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c'] as const) type SnakeCase = T extends `${infer F}${infer R}` From 53fbaec6ca96880d45cb75e375105006dcaa23f9 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Tue, 28 Oct 2025 15:27:17 +0200 Subject: [PATCH 24/54] chore@small --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6545e0ed..f535fc7d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - node-version: [ '22', '23' ] + node-version: [ '22', '24' ] steps: - uses: actions/checkout@v2 From 8aea8061ec1d0328d11839961e13d97c4d49f292 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Tue, 28 Oct 2025 15:53:25 +0200 Subject: [PATCH 25/54] chore@small --- README.md | 2 +- docs/README.md | 2 +- source/map-spec.ts | 2 +- source/ts-katas.ts | 99 +++++++++++++++++--------------------------- source/tsconfig.json | 1 + 5 files changed, 41 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 91ac0984..eebbe342 100644 --- a/README.md +++ b/README.md @@ -5989,7 +5989,7 @@ it('R.map - without pipe', () => { it('R.map - without pipe but explicitly typed', () => { const result = map(x => { - x // $ExpectType number[] + x // $ExpectType number return String(x) })([1, 2, 3]) result // $ExpectType string[] diff --git a/docs/README.md b/docs/README.md index 91ac0984..eebbe342 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5989,7 +5989,7 @@ it('R.map - without pipe', () => { it('R.map - without pipe but explicitly typed', () => { const result = map(x => { - x // $ExpectType number[] + x // $ExpectType number return String(x) })([1, 2, 3]) result // $ExpectType string[] diff --git a/source/map-spec.ts b/source/map-spec.ts index 44647453..4152beab 100644 --- a/source/map-spec.ts +++ b/source/map-spec.ts @@ -22,7 +22,7 @@ it('R.map - without pipe', () => { it('R.map - without pipe but explicitly typed', () => { const result = map(x => { - x // $ExpectType number[] + x // $ExpectType number return String(x) })([1, 2, 3]) result // $ExpectType string[] diff --git a/source/ts-katas.ts b/source/ts-katas.ts index 8544f66b..7528763f 100644 --- a/source/ts-katas.ts +++ b/source/ts-katas.ts @@ -1,80 +1,55 @@ -import { IterableContainer, map, pipe,Mapped, MergeTypes, MergeTypesAlternative } from 'rambda' - -const list = [1, 2, 3] -type ToFunctions = T extends [infer E] ? (a: E) => void : never; -type DeepPick = K extends keyof T ? { [P in K]: T[P] } : K extends `${infer A extends keyof T & string}.${infer B}` ? { [P in A]: DeepPick } -: never -type DeepPickAll = K extends [infer F, ...infer Rest extends string[]] ? MergeTypes & DeepPickAll> : {} +import { type MergeTypes, type MergeTypesAlternative, pipe } from 'rambda' + +type DeepPick = K extends keyof T + ? { [P in K]: T[P] } + : K extends `${infer A extends keyof T & string}.${infer B}` + ? { [P in A]: DeepPick } + : never +type DeepPickAll = K extends [ + infer F, + ...infer Rest extends string[], +] + ? MergeTypes & DeepPickAll> + : {} type f = DeepPick<{ a: { b: { c: string } } }, 'a.b.c'> -type f2 = DeepPickAll<{ b: 1,a: { b: { c: string } } }, ['a.b', 'b']> -type f2s = MergeTypesAlternative> - +type f2 = DeepPickAll<{ b: 1; a: { b: { c: string } } }, ['a.b', 'b']> +type f2s = MergeTypesAlternative< + DeepPickAll<{ b: 1; a: { b: { c: string } } }, ['a.b.c', 'b']> +> function deepPick(obj: T, key: K): DeepPick { - return key.split('.').reduce((acc: any, k: string) => { - return acc?.[k] - }, obj) as DeepPick + return key.split('.').reduce((acc: any, k: string) => { + return acc?.[k] + }, obj) as DeepPick } const deepPickAll = (obj: T, keys: K): DeepPickAll => { - return null as any + return null as any } -let l = deepPick({ a: { b: { c: 1 } } }, 'a.b.c') +const l = deepPick({ a: { b: { c: 1 } } }, 'a.b.c') l.a.b.c -let l2 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c'] as const) - +const l2 = deepPickAll({ a: { b: { c: 1 } } }, ['a.b.c'] as const) type SnakeCase = T extends `${infer F}${infer R}` -? F extends Uppercase -? `_${Lowercase}${SnakeCase}` -: `${F}${SnakeCase}` -: ""; + ? F extends Uppercase + ? `_${Lowercase}${SnakeCase}` + : `${F}${SnakeCase}` + : '' type MapType = T extends readonly [infer F, ...infer R] -? R extends readonly string[] - ? [SnakeCase, ...MapType] - : [SnakeCase] -: [] + ? R extends readonly string[] + ? [SnakeCase, ...MapType] + : [SnakeCase] + : [] const mapToSnakeCase = (str: T) => { - return str.map(x => { - return x.replace(/([A-Z])/g, '_$1').toLowerCase() - }) as MapType + return str.map(x => { + return x.replace(/([A-Z])/g, '_$1').toLowerCase() + }) as MapType } it('R.map - with x', () => { - const strings = ['fOo', 'bar', 'baz'] as const; - const result = pipe( - strings, - mapToSnakeCase, - ) - result // $ExpectType string[] + const strings = ['fOo', 'bar', 'baz'] as const + const result = pipe(strings, mapToSnakeCase) + result }) - -it('R.map - within pipe', () => { - const result = pipe( - list, - x => x, - map(x => { - x // $ExpectType number - return String(x) - }), - ) - result // $ExpectType string[] -}) - - -it('R.map - without pipe', () => { - map(x => { - x // $ExpectType unknown - })([1, 2, 3]) -}) - -it('R.map - without pipe but explicitly typed', () => { - const result = map(x => { - x // $ExpectType number[] - return String(x) - })([1, 2, 3]) - result // $ExpectType string[] -}) - diff --git a/source/tsconfig.json b/source/tsconfig.json index a763d57b..43d4dcf2 100644 --- a/source/tsconfig.json +++ b/source/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "baseUrl": ".", + "ignoreDeprecations": "6.0", "lib": ["es2015", "dom"], "module": "commonjs", "noEmit": true, From edbf8c3252dc73b7f5aaf77e063076631005d430 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Mon, 3 Nov 2025 23:36:29 +0200 Subject: [PATCH 26/54] chore@small --- source/tsconfig.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/tsconfig.json b/source/tsconfig.json index 43d4dcf2..c442cb0a 100644 --- a/source/tsconfig.json +++ b/source/tsconfig.json @@ -1,7 +1,5 @@ { "compilerOptions": { - "baseUrl": ".", - "ignoreDeprecations": "6.0", "lib": ["es2015", "dom"], "module": "commonjs", "noEmit": true, From fa5f220a7f523502c3218a579910a904b41326b1 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 6 Nov 2025 20:31:58 +0200 Subject: [PATCH 27/54] chore@small --- CHANGELOG.md | 4 ++++ README.md | 26 ++++++++++++++++++++++++-- docs/README.md | 26 ++++++++++++++++++++++++-- files/index.d.ts | 2 +- index.d.cts | 2 +- index.d.ts | 2 +- source/sortByDescending.spec.js | 10 ++++++++++ source/ts-katas.ts | 8 +++++++- 8 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 source/sortByDescending.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index ef62c587..8843484e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +10.3.4 + +- Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/README.md b/README.md index eebbe342..f127723c 100644 --- a/README.md +++ b/README.md @@ -10542,7 +10542,7 @@ describe('R.sortBy', () => { ```typescript -sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[] +sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[] ``` ```javascript @@ -10569,7 +10569,7 @@ const expected = [ All TypeScript definitions ```typescript -sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[]; +sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[]; ```
@@ -10588,6 +10588,24 @@ export function sortByDescending(sortFn) {
+
+ +Tests + +```javascript +import { sortByDescending } from './sortByDescending.js' +import { path } from './path.js' + +const list = [{ a: { b: 3 } }, { a: { b: 1 } }, { a: { b: 2 } }] +const sorted = [{ a: { b: 3 } }, { a: { b: 2 } }, { a: { b: 1 } }] + +test('happy', () => { + expect(sortByDescending(path('a.b'))(list)).toEqual(sorted) +}) +``` + +
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sortByDescending) ### sortByPath @@ -13542,6 +13560,10 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +10.3.4 + +- Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/docs/README.md b/docs/README.md index eebbe342..f127723c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10542,7 +10542,7 @@ describe('R.sortBy', () => { ```typescript -sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[] +sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[] ``` ```javascript @@ -10569,7 +10569,7 @@ const expected = [ All TypeScript definitions ```typescript -sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[]; +sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[]; ```
@@ -10588,6 +10588,24 @@ export function sortByDescending(sortFn) {
+
+ +Tests + +```javascript +import { sortByDescending } from './sortByDescending.js' +import { path } from './path.js' + +const list = [{ a: { b: 3 } }, { a: { b: 1 } }, { a: { b: 2 } }] +const sorted = [{ a: { b: 3 } }, { a: { b: 2 } }, { a: { b: 1 } }] + +test('happy', () => { + expect(sortByDescending(path('a.b'))(list)).toEqual(sorted) +}) +``` + +
+ [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sortByDescending) ### sortByPath @@ -13542,6 +13560,10 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +10.3.4 + +- Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/files/index.d.ts b/files/index.d.ts index 95580d96..fddf5a02 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -2536,7 +2536,7 @@ Notes: */ // @SINGLE_MARKER -export function sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[]; +export function sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[]; /* Method: sortByPath diff --git a/index.d.cts b/index.d.cts index 00f365db..51806d08 100644 --- a/index.d.cts +++ b/index.d.cts @@ -1827,7 +1827,7 @@ export function sort(sortFn: (a: T, b: T) => number): (list: T[]) => T[]; */ export function sortBy(sortFn: (x: T) => Ord): (list: T[]) => T[]; -export function sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[]; +export function sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[]; /** * It sorts `list` by the value of `path` property. diff --git a/index.d.ts b/index.d.ts index 00f365db..51806d08 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1827,7 +1827,7 @@ export function sort(sortFn: (a: T, b: T) => number): (list: T[]) => T[]; */ export function sortBy(sortFn: (x: T) => Ord): (list: T[]) => T[]; -export function sortByDescending(sortFn: (a: T, b: T) => number): (list: T[]) => T[]; +export function sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[]; /** * It sorts `list` by the value of `path` property. diff --git a/source/sortByDescending.spec.js b/source/sortByDescending.spec.js new file mode 100644 index 00000000..df831ec2 --- /dev/null +++ b/source/sortByDescending.spec.js @@ -0,0 +1,10 @@ +import { sortByDescending } from './sortByDescending.js' +import { path } from './path.js' + +const list = [{ a: { b: 3 } }, { a: { b: 1 } }, { a: { b: 2 } }] +const sorted = [{ a: { b: 3 } }, { a: { b: 2 } }, { a: { b: 1 } }] + +test('happy', () => { + expect(sortByDescending(path('a.b'))(list)).toEqual(sorted) +}) + diff --git a/source/ts-katas.ts b/source/ts-katas.ts index 7528763f..333fa26e 100644 --- a/source/ts-katas.ts +++ b/source/ts-katas.ts @@ -1,4 +1,10 @@ -import { type MergeTypes, type MergeTypesAlternative, pipe } from 'rambda' +import { map, type MergeTypes, type MergeTypesAlternative, pipe, splitEvery } from 'rambda' + +let a = pipe( + [[1,2,3],[4,5,6]], + map(splitEvery(2)) +) +a type DeepPick = K extends keyof T ? { [P in K]: T[P] } From 8d0f582b3a746c81bd7b1540a026a9cc6155b777 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Tue, 18 Nov 2025 18:14:10 +0200 Subject: [PATCH 28/54] chore@small --- CHANGELOG.md | 2 ++ README.md | 35 +++++++++++++++++++++++++++------ dist/rambda.cjs | 14 +++++++++++-- dist/rambda.js | 14 +++++++++++-- dist/rambda.umd.js | 14 +++++++++++-- docs/README.md | 35 +++++++++++++++++++++++++++------ files/index.d.ts | 5 ++--- index.d.cts | 5 ++--- index.d.ts | 5 ++--- source/mapParallelAsync.js | 14 +++++++++++-- source/mapParallelAsync.spec.js | 11 +++++++++++ src/mapParallelAsync.js | 14 +++++++++++-- 12 files changed, 137 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8843484e..91750bc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ - Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) +- Improve `R.mapParallelAsync` typings to allow optional `batchSize` parameter. + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/README.md b/README.md index f127723c..1d9ea964 100644 --- a/README.md +++ b/README.md @@ -6493,22 +6493,22 @@ it('R.mapObjectAsync', async () => { ```typescript mapParallelAsync( - fn: (value: T[number], index: number) => Promise, + fn: (value: T[number]) => Promise, + batchSize?: number, ): (data: T) => Promise> ``` Wrapper around `Promise.all` for asynchronous mapping with `fn` over members of `list`. +There is optional `batchSize` parameter to allow parallel execution to run in batches. In this case, the whole batch must complete before the next batch starts.
All TypeScript definitions ```typescript -mapParallelAsync( - fn: (value: T[number], index: number) => Promise, -): (data: T) => Promise>; mapParallelAsync( fn: (value: T[number]) => Promise, + batchSize?: number, ): (data: T) => Promise>; ``` @@ -6519,8 +6519,18 @@ mapParallelAsync( R.mapParallelAsync source ```javascript -export function mapParallelAsync(fn) { - return async list => Promise.all(list.map((x, i) => fn(x, i))) +export function mapParallelAsync(fn, batchSize){ + if(!batchSize) return async list => Promise.all(list.map(fn)) + + return async list => { + const result = [] + for(let i = 0; i < list.length; i += batchSize){ + const batch = list.slice(i, i + batchSize) + const batchResult = await Promise.all(batch.map((x, j) => fn(x, i + j))) + result.push(...batchResult) + } + return result + } } ``` @@ -6556,6 +6566,17 @@ test('pipeAsync', async () => { ) expect(result).toEqual([ 2,3,4 ]) }) + +test('with batchSize', async () => { + const fn = async (x, i) => { + await delay(100) + return `${x}:${i}` + } + const result = await mapParallelAsync(fn, 2)([1, 2, 3, 4, 5]) + expect(result).toEqual( + ['1:0', '2:1', '3:2', '4:3', '5:4'] + ) +}) ```
@@ -13564,6 +13585,8 @@ describe('R.zipWith', () => { - Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) +- Improve `R.mapParallelAsync` typings to allow optional `batchSize` parameter. + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/dist/rambda.cjs b/dist/rambda.cjs index f353c2aa..1cf98995 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -1044,8 +1044,18 @@ function mapObjectAsync(fn) { } } -function mapParallelAsync(fn) { - return async list => Promise.all(list.map((x, i) => fn(x, i))) +function mapParallelAsync(fn, batchSize){ + if(!batchSize) return async list => Promise.all(list.map(fn)) + + return async list => { + const result = []; + for(let i = 0; i < list.length; i += batchSize){ + const batch = list.slice(i, i + batchSize); + const batchResult = await Promise.all(batch.map((x, j) => fn(x, i + j))); + result.push(...batchResult); + } + return result + } } function mapPropObject(fn, prop) { diff --git a/dist/rambda.js b/dist/rambda.js index 8bb98b3a..cb7bccb9 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -1042,8 +1042,18 @@ function mapObjectAsync(fn) { } } -function mapParallelAsync(fn) { - return async list => Promise.all(list.map((x, i) => fn(x, i))) +function mapParallelAsync(fn, batchSize){ + if(!batchSize) return async list => Promise.all(list.map(fn)) + + return async list => { + const result = []; + for(let i = 0; i < list.length; i += batchSize){ + const batch = list.slice(i, i + batchSize); + const batchResult = await Promise.all(batch.map((x, j) => fn(x, i + j))); + result.push(...batchResult); + } + return result + } } function mapPropObject(fn, prop) { diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index 0d35ec22..777dc450 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -1048,8 +1048,18 @@ } } - function mapParallelAsync(fn) { - return async list => Promise.all(list.map((x, i) => fn(x, i))) + function mapParallelAsync(fn, batchSize){ + if(!batchSize) return async list => Promise.all(list.map(fn)) + + return async list => { + const result = []; + for(let i = 0; i < list.length; i += batchSize){ + const batch = list.slice(i, i + batchSize); + const batchResult = await Promise.all(batch.map((x, j) => fn(x, i + j))); + result.push(...batchResult); + } + return result + } } function mapPropObject(fn, prop) { diff --git a/docs/README.md b/docs/README.md index f127723c..1d9ea964 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6493,22 +6493,22 @@ it('R.mapObjectAsync', async () => { ```typescript mapParallelAsync( - fn: (value: T[number], index: number) => Promise, + fn: (value: T[number]) => Promise, + batchSize?: number, ): (data: T) => Promise> ``` Wrapper around `Promise.all` for asynchronous mapping with `fn` over members of `list`. +There is optional `batchSize` parameter to allow parallel execution to run in batches. In this case, the whole batch must complete before the next batch starts.
All TypeScript definitions ```typescript -mapParallelAsync( - fn: (value: T[number], index: number) => Promise, -): (data: T) => Promise>; mapParallelAsync( fn: (value: T[number]) => Promise, + batchSize?: number, ): (data: T) => Promise>; ``` @@ -6519,8 +6519,18 @@ mapParallelAsync( R.mapParallelAsync source ```javascript -export function mapParallelAsync(fn) { - return async list => Promise.all(list.map((x, i) => fn(x, i))) +export function mapParallelAsync(fn, batchSize){ + if(!batchSize) return async list => Promise.all(list.map(fn)) + + return async list => { + const result = [] + for(let i = 0; i < list.length; i += batchSize){ + const batch = list.slice(i, i + batchSize) + const batchResult = await Promise.all(batch.map((x, j) => fn(x, i + j))) + result.push(...batchResult) + } + return result + } } ``` @@ -6556,6 +6566,17 @@ test('pipeAsync', async () => { ) expect(result).toEqual([ 2,3,4 ]) }) + +test('with batchSize', async () => { + const fn = async (x, i) => { + await delay(100) + return `${x}:${i}` + } + const result = await mapParallelAsync(fn, 2)([1, 2, 3, 4, 5]) + expect(result).toEqual( + ['1:0', '2:1', '3:2', '4:3', '5:4'] + ) +}) ```
@@ -13564,6 +13585,8 @@ describe('R.zipWith', () => { - Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) +- Improve `R.mapParallelAsync` typings to allow optional `batchSize` parameter. + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/files/index.d.ts b/files/index.d.ts index fddf5a02..e2f50cb0 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -4429,6 +4429,7 @@ export function mapAsync( Method: mapParallelAsync Explanation: Wrapper around `Promise.all` for asynchronous mapping with `fn` over members of `list`. +There is optional `batchSize` parameter to allow parallel execution to run in batches. In this case, the whole batch must complete before the next batch starts. Example: @@ -4441,11 +4442,9 @@ Notes: */ // @SINGLE_MARKER -export function mapParallelAsync( - fn: (value: T[number], index: number) => Promise, -): (data: T) => Promise>; export function mapParallelAsync( fn: (value: T[number]) => Promise, + batchSize?: number, ): (data: T) => Promise>; /* diff --git a/index.d.cts b/index.d.cts index 51806d08..7f05d1b1 100644 --- a/index.d.cts +++ b/index.d.cts @@ -547,12 +547,11 @@ export function mapObjectAsync( /** * Wrapper around `Promise.all` for asynchronous mapping with `fn` over members of `list`. + * There is optional `batchSize` parameter to allow parallel execution to run in batches. In this case, the whole batch must complete before the next batch starts. */ -export function mapParallelAsync( - fn: (value: T[number], index: number) => Promise, -): (data: T) => Promise>; export function mapParallelAsync( fn: (value: T[number]) => Promise, + batchSize?: number, ): (data: T) => Promise>; /** diff --git a/index.d.ts b/index.d.ts index 51806d08..7f05d1b1 100644 --- a/index.d.ts +++ b/index.d.ts @@ -547,12 +547,11 @@ export function mapObjectAsync( /** * Wrapper around `Promise.all` for asynchronous mapping with `fn` over members of `list`. + * There is optional `batchSize` parameter to allow parallel execution to run in batches. In this case, the whole batch must complete before the next batch starts. */ -export function mapParallelAsync( - fn: (value: T[number], index: number) => Promise, -): (data: T) => Promise>; export function mapParallelAsync( fn: (value: T[number]) => Promise, + batchSize?: number, ): (data: T) => Promise>; /** diff --git a/source/mapParallelAsync.js b/source/mapParallelAsync.js index 6bb72ab5..05d17d71 100644 --- a/source/mapParallelAsync.js +++ b/source/mapParallelAsync.js @@ -1,3 +1,13 @@ -export function mapParallelAsync(fn) { - return async list => Promise.all(list.map((x, i) => fn(x, i))) +export function mapParallelAsync(fn, batchSize){ + if(!batchSize) return async list => Promise.all(list.map(fn)) + + return async list => { + const result = [] + for(let i = 0; i < list.length; i += batchSize){ + const batch = list.slice(i, i + batchSize) + const batchResult = await Promise.all(batch.map((x, j) => fn(x, i + j))) + result.push(...batchResult) + } + return result + } } diff --git a/source/mapParallelAsync.spec.js b/source/mapParallelAsync.spec.js index 02cd3134..7cc16644 100644 --- a/source/mapParallelAsync.spec.js +++ b/source/mapParallelAsync.spec.js @@ -23,3 +23,14 @@ test('pipeAsync', async () => { ) expect(result).toEqual([ 2,3,4 ]) }) + +test('with batchSize', async () => { + const fn = async (x, i) => { + await delay(100) + return `${x}:${i}` + } + const result = await mapParallelAsync(fn, 2)([1, 2, 3, 4, 5]) + expect(result).toEqual( + ['1:0', '2:1', '3:2', '4:3', '5:4'] + ) +}) diff --git a/src/mapParallelAsync.js b/src/mapParallelAsync.js index 6bb72ab5..05d17d71 100644 --- a/src/mapParallelAsync.js +++ b/src/mapParallelAsync.js @@ -1,3 +1,13 @@ -export function mapParallelAsync(fn) { - return async list => Promise.all(list.map((x, i) => fn(x, i))) +export function mapParallelAsync(fn, batchSize){ + if(!batchSize) return async list => Promise.all(list.map(fn)) + + return async list => { + const result = [] + for(let i = 0; i < list.length; i += batchSize){ + const batch = list.slice(i, i + batchSize) + const batchResult = await Promise.all(batch.map((x, j) => fn(x, i + j))) + result.push(...batchResult) + } + return result + } } From edd218cfb5e2333f70fd49d3e6a859903e850766 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 19 Nov 2025 13:10:32 +0200 Subject: [PATCH 29/54] chore@small --- package.json | 15 +- yarn.lock | 393 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 275 insertions(+), 133 deletions(-) diff --git a/package.json b/package.json index 53ea7b61..e4b8c325 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "test": "vitest run --watch -u", "test:typings": "dtslint --localTs ./node_modules/typescript/lib --expectOnly ./source", "create-docsify": "cd ../rambda-scripts && yarn create-docsify", - "deps": "run dep:next", + "deps": "run dep:next 10", + "x": "run dep:stable 10", "ts": "yarn test:typings" }, "niketaScripts": { @@ -40,18 +41,18 @@ "devDependencies": { "@definitelytyped/dtslint": "0.0.182", "@types/mocha": "10.0.10", - "@types/node": "24.7.0", - "@vitest/coverage-v8": "4.0.0-beta.17", + "@types/node": "24.10.1", + "@vitest/coverage-v8": "4.0.10", "helpers-fn": "2.0.0", "lodash": "4.17.21", "radashi": "13.0.0-beta.ffa4778", "rambdax": "11.3.1", - "ramda": "0.31.3", + "ramda": "0.32.0", "remeda": "2.32.0", - "rollup": "4.52.4", + "rollup": "4.53.3", "types-ramda": "0.31.0", - "typescript": "6.0.0-dev.20251006", - "vitest": "4.0.0-beta.17" + "typescript": "6.0.0-dev.20251119", + "vitest": "4.0.10" }, "jest": { "testEnvironment": "node", diff --git a/yarn.lock b/yarn.lock index d8ac6b5c..313fd39b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,30 +2,30 @@ # yarn lockfile v1 -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== -"@babel/parser@^7.25.4": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.7.tgz#e114cd099e5f7d17b05368678da0fb9f69b3385c" - integrity sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w== +"@babel/parser@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" + integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== dependencies: - "@babel/types" "^7.26.7" + "@babel/types" "^7.28.5" -"@babel/types@^7.25.4", "@babel/types@^7.26.7": - version "7.26.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a" - integrity sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg== +"@babel/types@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" + integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" "@bcoe/v8-coverage@^1.0.2": version "1.0.2" @@ -345,111 +345,226 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz#59e7478d310f7e6a7c72453978f562483828112f" integrity sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA== +"@rollup/rollup-android-arm-eabi@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz#7e478b66180c5330429dd161bf84dad66b59c8eb" + integrity sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w== + "@rollup/rollup-android-arm64@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz#a825192a0b1b2f27a5c950c439e7e37a33c5d056" integrity sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w== +"@rollup/rollup-android-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz#2b025510c53a5e3962d3edade91fba9368c9d71c" + integrity sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w== + "@rollup/rollup-darwin-arm64@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz#4ee37078bccd725ae3c5f30ef92efc8e1bf886f3" integrity sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg== +"@rollup/rollup-darwin-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz#3577c38af68ccf34c03e84f476bfd526abca10a0" + integrity sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA== + "@rollup/rollup-darwin-x64@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz#43cc08bd05bf9f388f125e7210a544e62d368d90" integrity sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw== +"@rollup/rollup-darwin-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz#2bf5f2520a1f3b551723d274b9669ba5b75ed69c" + integrity sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ== + "@rollup/rollup-freebsd-arm64@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz#bc8e640e28abe52450baf3fc80d9b26d9bb6587d" integrity sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ== +"@rollup/rollup-freebsd-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz#4bb9cc80252564c158efc0710153c71633f1927c" + integrity sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w== + "@rollup/rollup-freebsd-x64@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz#e981a22e057cc8c65bb523019d344d3a66b15bbc" integrity sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw== +"@rollup/rollup-freebsd-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz#2301289094d49415a380cf942219ae9d8b127440" + integrity sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q== + "@rollup/rollup-linux-arm-gnueabihf@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz#4036b68904f392a20f3499d63b33e055b67eb274" integrity sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ== +"@rollup/rollup-linux-arm-gnueabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz#1d03d776f2065e09fc141df7d143476e94acca88" + integrity sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw== + "@rollup/rollup-linux-arm-musleabihf@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz#d3b1b9589606e0ff916801c855b1ace9e733427a" integrity sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q== +"@rollup/rollup-linux-arm-musleabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz#8623de0e040b2fd52a541c602688228f51f96701" + integrity sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg== + "@rollup/rollup-linux-arm64-gnu@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz#cbf0943c477e3b96340136dd3448eaf144378cf2" integrity sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg== +"@rollup/rollup-linux-arm64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz#ce2d1999bc166277935dde0301cde3dd0417fb6e" + integrity sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w== + "@rollup/rollup-linux-arm64-musl@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz#837f5a428020d5dce1c3b4cc049876075402cf78" integrity sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g== +"@rollup/rollup-linux-arm64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz#88c2523778444da952651a2219026416564a4899" + integrity sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A== + "@rollup/rollup-linux-loong64-gnu@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz#532c214ababb32ab4bc21b4054278b9a8979e516" integrity sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ== +"@rollup/rollup-linux-loong64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz#578ca2220a200ac4226c536c10c8cc6e4f276714" + integrity sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g== + "@rollup/rollup-linux-ppc64-gnu@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz#93900163b61b49cee666d10ee38257a8b1dd161a" integrity sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g== +"@rollup/rollup-linux-ppc64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz#aa338d3effd4168a20a5023834a74ba2c3081293" + integrity sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw== + "@rollup/rollup-linux-riscv64-gnu@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz#f0ffdcc7066ca04bc972370c74289f35c7a7dc42" integrity sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg== +"@rollup/rollup-linux-riscv64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz#16ba582f9f6cff58119aa242782209b1557a1508" + integrity sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g== + "@rollup/rollup-linux-riscv64-musl@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz#361695c39dbe96773509745d77a870a32a9f8e48" integrity sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA== +"@rollup/rollup-linux-riscv64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz#e404a77ebd6378483888b8064c703adb011340ab" + integrity sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A== + "@rollup/rollup-linux-s390x-gnu@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz#09fc6cc2e266a2324e366486ae5d1bca48c43a6a" integrity sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA== +"@rollup/rollup-linux-s390x-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz#92ad52d306227c56bec43d96ad2164495437ffe6" + integrity sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg== + "@rollup/rollup-linux-x64-gnu@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz#aa9d5b307c08f05d3454225bb0a2b4cc87eeb2e1" integrity sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg== +"@rollup/rollup-linux-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz#fd0dea3bb9aa07e7083579f25e1c2285a46cb9fa" + integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== + "@rollup/rollup-linux-x64-musl@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz#26949e5b4645502a61daba2f7a8416bd17cb5382" integrity sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw== +"@rollup/rollup-linux-x64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz#37a3efb09f18d555f8afc490e1f0444885de8951" + integrity sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q== + "@rollup/rollup-openharmony-arm64@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz#ef493c072f9dac7e0edb6c72d63366846b6ffcd9" integrity sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA== +"@rollup/rollup-openharmony-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz#c489bec9f4f8320d42c9b324cca220c90091c1f7" + integrity sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw== + "@rollup/rollup-win32-arm64-msvc@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz#56e1aaa6a630d2202ee7ec0adddd05cf384ffd44" integrity sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ== +"@rollup/rollup-win32-arm64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz#152832b5f79dc22d1606fac3db946283601b7080" + integrity sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw== + "@rollup/rollup-win32-ia32-msvc@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz#0a44bbf933a9651c7da2b8569fa448dec0de7480" integrity sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw== +"@rollup/rollup-win32-ia32-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz#54d91b2bb3bf3e9f30d32b72065a4e52b3a172a5" + integrity sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA== + "@rollup/rollup-win32-x64-gnu@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz#730e12f0b60b234a7c02d5d3179ca3ec7972033d" integrity sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ== +"@rollup/rollup-win32-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz#df9df03e61a003873efec8decd2034e7f135c71e" + integrity sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg== + "@rollup/rollup-win32-x64-msvc@4.52.4": version "4.52.4" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz#5b2dd648a960b8fa00d76f2cc4eea2f03daa80f4" integrity sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w== +"@rollup/rollup-win32-x64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz#38ae84f4c04226c1d56a3b17296ef1e0460ecdfe" + integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ== + +"@standard-schema/spec@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" + integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== + "@types/chai@^5.2.2": version "5.2.2" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.2.tgz#6f14cea18180ffc4416bc0fd12be05fdd73bdd6b" @@ -482,12 +597,12 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== -"@types/node@24.7.0": - version "24.7.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.7.0.tgz#a34c9f0d3401db396782e440317dd5d8373c286f" - integrity sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw== +"@types/node@24.10.1": + version "24.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.1.tgz#91e92182c93db8bd6224fca031e2370cef9a8f01" + integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ== dependencies: - undici-types "~7.14.0" + undici-types "~7.16.0" "@types/node@^14.14.35": version "14.18.63" @@ -598,78 +713,79 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@vitest/coverage-v8@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.0.0-beta.17.tgz#0e01e43b988a833d7595f16af54118598d08b109" - integrity sha512-QetR5ju+OeIK6EyOKz/Z3txW9oFTn262VkCngrfXMNwPo6FWTHzMPIl98V/qxIzsAlrSVG85XuVJcC3XdC7LwA== +"@vitest/coverage-v8@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.0.10.tgz#834f2d411522a6e8772bfb7ef2c9e79c648a2b4d" + integrity sha512-g+brmtoKa/sAeIohNJnnWhnHtU6GuqqVOSQ4SxDIPcgZWZyhJs5RmF5LpqXs8Kq64lANP+vnbn5JLzhLj/G56g== dependencies: "@bcoe/v8-coverage" "^1.0.2" - "@vitest/utils" "4.0.0-beta.17" - ast-v8-to-istanbul "^0.3.5" + "@vitest/utils" "4.0.10" + ast-v8-to-istanbul "^0.3.8" debug "^4.4.3" istanbul-lib-coverage "^3.2.2" istanbul-lib-report "^3.0.1" istanbul-lib-source-maps "^5.0.6" istanbul-reports "^3.2.0" - magicast "^0.3.5" - std-env "^3.9.0" + magicast "^0.5.1" + std-env "^3.10.0" tinyrainbow "^3.0.3" -"@vitest/expect@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.0-beta.17.tgz#4e9a1a1ae8800adee9f9d36f41affb13da1ce532" - integrity sha512-guY0R9wPiwecV5+ptTVC4qGiOB0Ip5NVn9e8T1Wrf4HubG61MDL+iI1dPpkxJBm1U4yXev6gBkT/vrVtR/5q0w== +"@vitest/expect@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.10.tgz#cb97fc35d0938f2f7c62694812131fbb986fa5ce" + integrity sha512-3QkTX/lK39FBNwARCQRSQr0TP9+ywSdxSX+LgbJ2M1WmveXP72anTbnp2yl5fH+dU6SUmBzNMrDHs80G8G2DZg== dependencies: + "@standard-schema/spec" "^1.0.0" "@types/chai" "^5.2.2" - "@vitest/spy" "4.0.0-beta.17" - "@vitest/utils" "4.0.0-beta.17" - chai "^6.0.1" + "@vitest/spy" "4.0.10" + "@vitest/utils" "4.0.10" + chai "^6.2.1" tinyrainbow "^3.0.3" -"@vitest/mocker@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.0-beta.17.tgz#9bfce78f6ebbfe93d8458c5ed4ec509db369f45a" - integrity sha512-m56dc63UL10BiFHZ++XdFv58YEHAjRvgL4Mbb+Qlrkk5ul2cs7Q6LzuXDUE2TshVRnPWzwWXT3N+aAygrplIvw== +"@vitest/mocker@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.10.tgz#66ea2d6f563b26f72fd3e27ee5cbb01a70640584" + integrity sha512-e2OfdexYkjkg8Hh3L9NVEfbwGXq5IZbDovkf30qW2tOh7Rh9sVtmSr2ztEXOFbymNxS4qjzLXUQIvATvN4B+lg== dependencies: - "@vitest/spy" "4.0.0-beta.17" + "@vitest/spy" "4.0.10" estree-walker "^3.0.3" - magic-string "^0.30.19" + magic-string "^0.30.21" -"@vitest/pretty-format@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.0-beta.17.tgz#92928781c5dffd5367308f6ce4168ad93c341abc" - integrity sha512-CSlfXqUgCOem5bawWaWHyEapCiJbLkkpbQJMXbVZMjPXmS25rmTTvLR4R8pGW53GV0b6c1L4Bt2DoZiZtx1elA== +"@vitest/pretty-format@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.10.tgz#1ae410f4a98b60921879828143342f59a5edfcf9" + integrity sha512-99EQbpa/zuDnvVjthwz5bH9o8iPefoQZ63WV8+bsRJZNw3qQSvSltfut8yu1Jc9mqOYi7pEbsKxYTi/rjaq6PA== dependencies: tinyrainbow "^3.0.3" -"@vitest/runner@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.0-beta.17.tgz#1f3ac12fef6effd61697370ddd06977307a15d47" - integrity sha512-jhMbh3NPjZNFQJA3OtCFP5taNmPkyujsXd6T7NK7/0lwgb8CEGqgNfFUe9vZU9i1+HcTz2vRLXKETgyg42fulg== +"@vitest/runner@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.10.tgz#c91c4c6e1bad92d2a07ca6da287ff076a0a6589f" + integrity sha512-EXU2iSkKvNwtlL8L8doCpkyclw0mc/t4t9SeOnfOFPyqLmQwuceMPA4zJBa6jw0MKsZYbw7kAn+gl7HxrlB8UQ== dependencies: - "@vitest/utils" "4.0.0-beta.17" + "@vitest/utils" "4.0.10" pathe "^2.0.3" -"@vitest/snapshot@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.0-beta.17.tgz#fee457fbd59d8dde9556e184ae90207bd0064487" - integrity sha512-Ccq1hYME9kgxWiqlsTyVjkpRTAaGOVMOKJryYv1ybePg0TJFdPts32WYW74J8YKg53ZcDOjWhv3QkTTl7p7Ntw== +"@vitest/snapshot@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.10.tgz#e3d4f188105d6197e385c85c2c06a37be9732c6d" + integrity sha512-2N4X2ZZl7kZw0qeGdQ41H0KND96L3qX1RgwuCfy6oUsF2ISGD/HpSbmms+CkIOsQmg2kulwfhJ4CI0asnZlvkg== dependencies: - "@vitest/pretty-format" "4.0.0-beta.17" - magic-string "^0.30.19" + "@vitest/pretty-format" "4.0.10" + magic-string "^0.30.21" pathe "^2.0.3" -"@vitest/spy@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.0-beta.17.tgz#199db3930db8096896427e4c2722ec376f225b9f" - integrity sha512-c6sIXHQSMx1yDBbDF1vHDaJ+2KQySOExYuQhFMj3lG1woTVdRmX1omtPsLypsa7uVwVLc466DtLVvgAsSQIi2g== +"@vitest/spy@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.10.tgz#e40f246bd0e8b5321766afd97230cdac21783157" + integrity sha512-AsY6sVS8OLb96GV5RoG8B6I35GAbNrC49AO+jNRF9YVGb/g9t+hzNm1H6kD0NDp8tt7VJLs6hb7YMkDXqu03iw== -"@vitest/utils@4.0.0-beta.17": - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.0-beta.17.tgz#357fd40911dc66f584aaefeab288695463ac1e0d" - integrity sha512-PdhF3Kk1QFQ0H6iQzILGXCNDuhFgdxJKGJwzpPr/Hk7KWKiymj2w/7gusB95Ckh0t/kJPW+O99afLzoRPGsrFw== +"@vitest/utils@4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.10.tgz#04e5cb5d5237160477fd364d2b58744c0e5695be" + integrity sha512-kOuqWnEwZNtQxMKg3WmPK1vmhZu9WcoX69iwWjVz+jvKTsF1emzsv3eoPcDr6ykA3qP2bsCQE7CwqfNtAVzsmg== dependencies: - "@vitest/pretty-format" "4.0.0-beta.17" + "@vitest/pretty-format" "4.0.10" tinyrainbow "^3.0.3" acorn-jsx@^5.3.2: @@ -763,10 +879,10 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== -ast-v8-to-istanbul@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.6.tgz#5ef80900b52fdf58a3d9cdb8e692f70d9460aebf" - integrity sha512-9tx1z/7OF/a8EdYL3FKoBhxLf3h3D8fXvuSj0HknsVeli2HE40qbNZxyFhMtnydaRiamwFu9zhb+BsJ5tVPehQ== +ast-v8-to-istanbul@^0.3.8: + version "0.3.8" + resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.8.tgz#0a3faf070dc780dcebdf9d48af78dbd174a497a9" + integrity sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ== dependencies: "@jridgewell/trace-mapping" "^0.3.31" estree-walker "^3.0.3" @@ -894,10 +1010,10 @@ cfonts@3.3.0: supports-color "^8" window-size "^1" -chai@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/chai/-/chai-6.0.1.tgz#88c2b4682fb56050647e222d2cf9d6772f2607b3" - integrity sha512-/JOoU2//6p5vCXh00FpNgtlw0LjvhGttaWc+y7wpW9yjBm3ys0dI8tSKZxIOgNruz5J0RleccatSIC3uxEZP0g== +chai@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.1.tgz#d1e64bc42433fbee6175ad5346799682060b5b6a" + integrity sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg== chalk@4.0.0: version "4.0.0" @@ -2074,21 +2190,21 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@^0.30.19: - version "0.30.19" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.19.tgz#cebe9f104e565602e5d2098c5f2e79a77cc86da9" - integrity sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw== +magic-string@^0.30.21: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== dependencies: "@jridgewell/sourcemap-codec" "^1.5.5" -magicast@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.5.tgz#8301c3c7d66704a0771eb1bad74274f0ec036739" - integrity sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ== +magicast@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.5.1.tgz#518959aea78851cd35d4bb0da92f780db3f606d3" + integrity sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw== dependencies: - "@babel/parser" "^7.25.4" - "@babel/types" "^7.25.4" - source-map-js "^1.2.0" + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" + source-map-js "^1.2.1" make-dir@^4.0.0: version "4.0.0" @@ -2432,10 +2548,10 @@ rambdax@7.0.1: resolved "https://registry.yarnpkg.com/rambdax/-/rambdax-7.0.1.tgz#6a1b3184abcf4cf6df5dffc27fc0d71100aa21ec" integrity sha512-Xrrp45dg1PLt40LMcjfNyVDcPBndzpR2t+AXGAcc9iqU9lD9bnk/b1B+n4W5tFXoSKDmZmgckcA8ajgVzbtxGA== -ramda@0.31.3: - version "0.31.3" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.31.3.tgz#0f54199ec99a7bd6702277d28d6bf7f93b916bb9" - integrity sha512-xKADKRNnqmDdX59PPKLm3gGmk1ZgNnj3k7DryqWwkamp4TJ6B36DdpyKEQ0EoEYmH2R62bV4Q+S0ym2z8N2f3Q== +ramda@0.32.0: + version "0.32.0" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.32.0.tgz#b2116807b59b6b177af7a2ad19b14a3653570e96" + integrity sha512-GQWAHhxhxWBWA8oIBr1XahFVjQ9Fic6MK9ikijfd4TZHfE2+urfk+irVlR5VOn48uwMgM+loRRBJd6Yjsbc0zQ== readable-stream@^2.0.6: version "2.3.8" @@ -2540,7 +2656,38 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@4.52.4, rollup@^4.43.0: +rollup@4.53.3: + version "4.53.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.53.3.tgz#dbc8cd8743b38710019fb8297e8d7a76e3faa406" + integrity sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.53.3" + "@rollup/rollup-android-arm64" "4.53.3" + "@rollup/rollup-darwin-arm64" "4.53.3" + "@rollup/rollup-darwin-x64" "4.53.3" + "@rollup/rollup-freebsd-arm64" "4.53.3" + "@rollup/rollup-freebsd-x64" "4.53.3" + "@rollup/rollup-linux-arm-gnueabihf" "4.53.3" + "@rollup/rollup-linux-arm-musleabihf" "4.53.3" + "@rollup/rollup-linux-arm64-gnu" "4.53.3" + "@rollup/rollup-linux-arm64-musl" "4.53.3" + "@rollup/rollup-linux-loong64-gnu" "4.53.3" + "@rollup/rollup-linux-ppc64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-musl" "4.53.3" + "@rollup/rollup-linux-s390x-gnu" "4.53.3" + "@rollup/rollup-linux-x64-gnu" "4.53.3" + "@rollup/rollup-linux-x64-musl" "4.53.3" + "@rollup/rollup-openharmony-arm64" "4.53.3" + "@rollup/rollup-win32-arm64-msvc" "4.53.3" + "@rollup/rollup-win32-ia32-msvc" "4.53.3" + "@rollup/rollup-win32-x64-gnu" "4.53.3" + "@rollup/rollup-win32-x64-msvc" "4.53.3" + fsevents "~2.3.2" + +rollup@^4.43.0: version "4.52.4" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.52.4.tgz#71e64cce96a865fcbaa6bb62c6e82807f4e378a1" integrity sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ== @@ -2657,7 +2804,7 @@ slide@^1.1.6: resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw== -source-map-js@^1.2.0, source-map-js@^1.2.1: +source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -2720,10 +2867,10 @@ stackback@0.0.2: resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== -std-env@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.9.0.tgz#1a6f7243b339dca4c9fd55e1c7504c77ef23e8f1" - integrity sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw== +std-env@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" + integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== string-fn@3.3.2: version "3.3.2" @@ -2887,11 +3034,6 @@ tinygradient@^1.1.5: "@types/tinycolor2" "^1.4.0" tinycolor2 "^1.0.0" -tinypool@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-2.0.0.tgz#7eaea50341e1026cecb75e04d4e6ea6ede68b7ca" - integrity sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg== - tinyrainbow@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42" @@ -3001,15 +3143,15 @@ types-ramda@0.31.0: dependencies: ts-toolbelt "^9.6.0" -typescript@6.0.0-dev.20251006: - version "6.0.0-dev.20251006" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.0-dev.20251006.tgz#f8c6b3dc5f7df5fc8fdaefa691f0c6e73ebe4428" - integrity sha512-DHt+o3xZV+a3cambN7XN1l0RH9PP3bYhUn2pwWyHqSA7j5HSR4MjTEf2hFGpty3/IZj6zHztEBtq4B6bGRdJgg== +typescript@6.0.0-dev.20251119: + version "6.0.0-dev.20251119" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.0-dev.20251119.tgz#0b89469276f58969cfee6285de2dddac9431aa03" + integrity sha512-bP8dUqiG7IzMxPqKQRc7MSdmKvt/7eUeHgRp0Cbv7ta5x4Q0sV4OSzB/6PrTbLdpXpKVD+Cw4vobCcBPNeejUg== -undici-types@~7.14.0: - version "7.14.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.14.0.tgz#4c037b32ca4d7d62fae042174604341588bc0840" - integrity sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA== +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== universalify@^0.1.0: version "0.1.2" @@ -3076,29 +3218,28 @@ verror@1.10.0: optionalDependencies: fsevents "~2.3.3" -vitest@4.0.0-beta.17: - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.0-beta.17.tgz#ab9a1105256d52d5d2b9c0439075d66502a8de9a" - integrity sha512-R2vM2ErERS4hcmrZ0vrGhy/v9HEkCRnUXHJLhuvnQfO8uWspjuMNxIej1Ru/pBvR5pDfN2mqb1679Lk4yyJ7NA== - dependencies: - "@vitest/expect" "4.0.0-beta.17" - "@vitest/mocker" "4.0.0-beta.17" - "@vitest/pretty-format" "4.0.0-beta.17" - "@vitest/runner" "4.0.0-beta.17" - "@vitest/snapshot" "4.0.0-beta.17" - "@vitest/spy" "4.0.0-beta.17" - "@vitest/utils" "4.0.0-beta.17" +vitest@4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.10.tgz#587e3d5594444c5ae2e02310f1b1df891b04a0b7" + integrity sha512-2Fqty3MM9CDwOVet/jaQalYlbcjATZwPYGcqpiYQqgQ/dLC7GuHdISKgTYIVF/kaishKxLzleKWWfbSDklyIKg== + dependencies: + "@vitest/expect" "4.0.10" + "@vitest/mocker" "4.0.10" + "@vitest/pretty-format" "4.0.10" + "@vitest/runner" "4.0.10" + "@vitest/snapshot" "4.0.10" + "@vitest/spy" "4.0.10" + "@vitest/utils" "4.0.10" debug "^4.4.3" es-module-lexer "^1.7.0" expect-type "^1.2.2" - magic-string "^0.30.19" + magic-string "^0.30.21" pathe "^2.0.3" picomatch "^4.0.3" - std-env "^3.9.0" + std-env "^3.10.0" tinybench "^2.9.0" tinyexec "^0.3.2" tinyglobby "^0.2.15" - tinypool "^2.0.0" tinyrainbow "^3.0.3" vite "^6.0.0 || ^7.0.0" why-is-node-running "^2.3.0" From 5a891f8e5b1d388ccf1b94a0d338f2f9165ef028 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 19 Nov 2025 22:58:34 +0200 Subject: [PATCH 30/54] repl --- README.md | 232 ++++++++++++++++++++++++------------------------- docs/README.md | 232 ++++++++++++++++++++++++------------------------- 2 files changed, 232 insertions(+), 232 deletions(-) diff --git a/README.md b/README.md index 1d9ea964..2b2cdbba 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ const result = R.pipe( // => { a: 1, b: 'foo', c: 3 } ``` -Try this R.addProp example in Rambda REPL +Try this R.addProp example in Rambda REPL
@@ -278,7 +278,7 @@ const result = R.pipe( // => [{a: 1, b: 2, c: '3'}, {a: 3, b: 4, c: '7'}] ``` -Try this R.addPropToObjects example in Rambda REPL +Try this R.addPropToObjects example in Rambda REPL
@@ -393,7 +393,7 @@ const result = R.pipe( ) // => true ``` -Try this R.all example in Rambda REPL +Try this R.all example in Rambda REPL
@@ -491,7 +491,7 @@ const result = R.pipe( ) // => [[1, 2, 3, 4]] ``` -Try this R.allPass example in Rambda REPL +Try this R.allPass example in Rambda REPL
@@ -591,7 +591,7 @@ R.any(predicate)(list) // => true ``` -Try this R.any example in Rambda REPL +Try this R.any example in Rambda REPL
@@ -688,7 +688,7 @@ const result = fn(input) // => true ``` -Try this R.anyPass example in Rambda REPL +Try this R.anyPass example in Rambda REPL
@@ -838,7 +838,7 @@ const result = R.append('foo')(['bar', 'baz']) // => ['bar', 'baz', 'foo'] ``` -Try this R.append example in Rambda REPL +Try this R.append example in Rambda REPL
@@ -930,7 +930,7 @@ const result = R.pipe( // => [{a: 0}, {a: 1}, {a: 2}] ``` -Try this R.ascend example in Rambda REPL +Try this R.ascend example in Rambda REPL
@@ -1136,7 +1136,7 @@ const result = condition(input) // => true ``` -Try this R.checkObjectWithSpec example in Rambda REPL +Try this R.checkObjectWithSpec example in Rambda REPL
@@ -1272,7 +1272,7 @@ const result = R.pipe( // => { a: ['a', 'b', 'c'], b: [1, 2, 3], c: { a: 1, b: 2, c: 0, f: false } } ``` -Try this R.compact example in Rambda REPL +Try this R.compact example in Rambda REPL
@@ -1392,7 +1392,7 @@ const result = [ ] => [ true, false ] ``` -Try this R.complement example in Rambda REPL +Try this R.complement example in Rambda REPL
@@ -1473,7 +1473,7 @@ R.concat([1, 2])([3, 4]) // => [1, 2, 3, 4] R.concat('foo')('bar') // => 'foobar' ``` -Try this R.concat example in Rambda REPL +Try this R.concat example in Rambda REPL
@@ -1592,7 +1592,7 @@ const result = R.count(x => x.a !== undefined)(list) // => 2 ``` -Try this R.count example in Rambda REPL +Try this R.count example in Rambda REPL
@@ -1683,7 +1683,7 @@ const expected = { a: 2, b: 2, c: 2 } // => `result` is equal to `expected` ``` -Try this R.countBy example in Rambda REPL +Try this R.countBy example in Rambda REPL
@@ -1781,7 +1781,7 @@ const result = R.createObjectFromKeys( // => {a: 'a-0', b: 'b-1', c: 'c-2'} ``` -Try this R.createObjectFromKeys example in Rambda REPL +Try this R.createObjectFromKeys example in Rambda REPL
@@ -1857,7 +1857,7 @@ R.defaultTo('foo'))(undefined) // => 'foo' R.defaultTo('foo')('') // => 'foo' ``` -Try this R.defaultTo example in Rambda REPL +Try this R.defaultTo example in Rambda REPL
@@ -1956,7 +1956,7 @@ const result = R.pipe( // => [{a: 2}, {a: 1}, {a: 0}] ``` -Try this R.descend example in Rambda REPL +Try this R.descend example in Rambda REPL
@@ -2002,7 +2002,7 @@ It returns `howMany` items dropped from beginning of list. R.drop(2)(['foo', 'bar', 'baz']) // => ['baz'] ``` -Try this R.drop example in Rambda REPL +Try this R.drop example in Rambda REPL
@@ -2135,7 +2135,7 @@ const result = dropLastWhile(predicate)(list); // => [1, 2] ``` -Try this R.dropLastWhile example in Rambda REPL +Try this R.dropLastWhile example in Rambda REPL
@@ -2219,7 +2219,7 @@ const result = R.dropRepeatsBy( // => [1, 2, 3] ``` -Try this R.dropRepeatsBy example in Rambda REPL +Try this R.dropRepeatsBy example in Rambda REPL
@@ -2247,7 +2247,7 @@ const result = R.dropRepeatsWith(R.prop('a'))(list) // => [{a:1,b:2}, {a:2, b:4}] ``` -Try this R.dropRepeatsWith example in Rambda REPL +Try this R.dropRepeatsWith example in Rambda REPL
@@ -2275,7 +2275,7 @@ const result = R.dropWhile(predicate)(list) // => [3, 4] ``` -Try this R.dropWhile example in Rambda REPL +Try this R.dropWhile example in Rambda REPL
@@ -2394,7 +2394,7 @@ const result = R.duplicateBy(x => x, list) // => [{a:1}] ``` -Try this R.duplicateBy example in Rambda REPL +Try this R.duplicateBy example in Rambda REPL
@@ -2462,7 +2462,7 @@ const result = R.eqBy(Math.abs, 5)(-5) // => true ``` -Try this R.eqBy example in Rambda REPL +Try this R.eqBy example in Rambda REPL
@@ -2531,7 +2531,7 @@ const result = R.eqProps('a', obj1)(obj2) // => true ``` -Try this R.eqProps example in Rambda REPL +Try this R.eqProps example in Rambda REPL
@@ -2630,7 +2630,7 @@ R.equals( ) // => true ``` -Try this R.equals example in Rambda REPL +Try this R.equals example in Rambda REPL
@@ -3122,7 +3122,7 @@ const result = R.pipe( // => result is { foo: 3, baz: 'baz' } ``` -Try this R.evolve example in Rambda REPL +Try this R.evolve example in Rambda REPL
@@ -3228,7 +3228,7 @@ const result = [ // => [true, true ] ``` -Try this R.excludes example in Rambda REPL +Try this R.excludes example in Rambda REPL
@@ -3321,7 +3321,7 @@ const result = R.filter(predicate)(list) // => [2, 3] ``` -Try this R.filter example in Rambda REPL +Try this R.filter example in Rambda REPL
@@ -3583,7 +3583,7 @@ const result = R.filterObject( // => {a: 1, c: 3} ``` -Try this R.filterObject example in Rambda REPL +Try this R.filterObject example in Rambda REPL
@@ -3691,7 +3691,7 @@ const result = R.find(predicate)(list) // => {foo: 1} ``` -Try this R.find example in Rambda REPL +Try this R.find example in Rambda REPL
@@ -3795,7 +3795,7 @@ const result = R.findIndex(predicate)(list) // => 1 ``` -Try this R.findIndex example in Rambda REPL +Try this R.findIndex example in Rambda REPL
@@ -3890,7 +3890,7 @@ const result = R.findLast(predicate)(list) // => {foo: 1} ``` -Try this R.findLast example in Rambda REPL +Try this R.findLast example in Rambda REPL
@@ -3945,7 +3945,7 @@ const result = R.findLastIndex(predicate)(list) // => 1 ``` -Try this R.findLastIndex example in Rambda REPL +Try this R.findLastIndex example in Rambda REPL
@@ -4034,7 +4034,7 @@ const result = R.findNth(predicate, 2)(list) // => {foo: 2} ``` -Try this R.findNth example in Rambda REPL +Try this R.findNth example in Rambda REPL
@@ -4112,7 +4112,7 @@ const result = R.flatMap(duplicate)(list) // => [ 1, 1, 2, 2, 3, 3 ] ``` -Try this R.flatMap example in Rambda REPL +Try this R.flatMap example in Rambda REPL
@@ -4233,7 +4233,7 @@ const result = R.flatten([ // => [ 1, 2, 3, 30, 300, 4 ] ``` -Try this R.flatten example in Rambda REPL +Try this R.flatten example in Rambda REPL
@@ -4331,7 +4331,7 @@ const result = R.flattenObject( // => [3, 1, 2] or [2, 3, 1] or ... ``` -Try this R.flattenObject example in Rambda REPL +Try this R.flattenObject example in Rambda REPL
@@ -4555,7 +4555,7 @@ const result = R.groupBy(groupFn, list) // => { '1': ['a', 'b'], '2': ['aa', 'bb'] } ``` -Try this R.groupBy example in Rambda REPL +Try this R.groupBy example in Rambda REPL
@@ -4672,7 +4672,7 @@ const result = [ // => [1, 'f'] ``` -Try this R.head example in Rambda REPL +Try this R.head example in Rambda REPL
@@ -4795,7 +4795,7 @@ const result = [ // => [true, true ] ``` -Try this R.includes example in Rambda REPL +Try this R.includes example in Rambda REPL
@@ -4927,7 +4927,7 @@ const result = R.indexBy( // => {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} ``` -Try this R.indexBy example in Rambda REPL +Try this R.indexBy example in Rambda REPL
@@ -5029,7 +5029,7 @@ const result = [ // => [0, 1] ``` -Try this R.indexOf example in Rambda REPL +Try this R.indexOf example in Rambda REPL
@@ -5129,7 +5129,7 @@ const result = [ // => [[1, 2], 'fo'] ``` -Try this R.init example in Rambda REPL +Try this R.init example in Rambda REPL
@@ -5235,7 +5235,7 @@ const result = R.innerJoin(predicate, list1)(list2) // => [4, 5] ``` -Try this R.innerJoin example in Rambda REPL +Try this R.innerJoin example in Rambda REPL
@@ -5357,7 +5357,7 @@ const expected = 'foo is BAR even 1 more' // => `result` is equal to `expected` ``` -Try this R.interpolate example in Rambda REPL +Try this R.interpolate example in Rambda REPL
@@ -5466,7 +5466,7 @@ const result = R.intersection(listA)(listB) // => [{ id : 3 }, { id : 4 }] ``` -Try this R.intersection example in Rambda REPL +Try this R.intersection example in Rambda REPL
@@ -5561,7 +5561,7 @@ const result = R.intersperse(separator)(list) // => [0, 10, 1, 10, 2, 10, 3] ``` -Try this R.intersperse example in Rambda REPL +Try this R.intersperse example in Rambda REPL
@@ -5656,7 +5656,7 @@ It returns a string of all `list` instances joined with a `glue`. R.join('-', [1, 2, 3]) // => '1-2-3' ``` -Try this R.join example in Rambda REPL +Try this R.join example in Rambda REPL
@@ -5721,7 +5721,7 @@ const result = [ // => [3, 'o'] ``` -Try this R.last example in Rambda REPL +Try this R.last example in Rambda REPL
@@ -5800,7 +5800,7 @@ const result = [ // => [4, -1] ``` -Try this R.lastIndexOf example in Rambda REPL +Try this R.lastIndexOf example in Rambda REPL
@@ -5903,7 +5903,7 @@ const result = R.map(fn)(iterable), // => [2, 4] ``` -Try this R.map example in Rambda REPL +Try this R.map example in Rambda REPL
@@ -6022,7 +6022,7 @@ const result = await R.mapAsync(fn)([1, 2, 3]) // `result` resolves after 3 seconds to `[2, 3, 4]` ``` -Try this R.mapAsync example in Rambda REPL +Try this R.mapAsync example in Rambda REPL
@@ -6166,7 +6166,7 @@ const result = R.mapKeys( // => { A1: 1, B2: 2 } ``` -Try this R.mapKeys example in Rambda REPL +Try this R.mapKeys example in Rambda REPL
@@ -6257,7 +6257,7 @@ const result = R.mapObject(fn)(obj) // => {a: 'a-1', b: 'b-2'} ``` -Try this R.mapObject example in Rambda REPL +Try this R.mapObject example in Rambda REPL
@@ -6614,7 +6614,7 @@ const result = pipe( // => { a: [{ a: 1, flag: false },{ a: 2, flag: false }, { a: 3, flag: true }], b: 'foo' } ``` -Try this R.mapPropObject example in Rambda REPL +Try this R.mapPropObject example in Rambda REPL
@@ -6727,7 +6727,7 @@ const result = [ // => [[], ['ba', 'na', 'na']] ``` -Try this R.match example in Rambda REPL +Try this R.match example in Rambda REPL
@@ -6813,7 +6813,7 @@ const compareFn = Math.abs R.maxBy(compareFn, 5, -7) // => -7 ``` -Try this R.maxBy example in Rambda REPL +Try this R.maxBy example in Rambda REPL
@@ -6996,7 +6996,7 @@ const compareFn = Math.abs R.minBy(compareFn, -5, 2) // => -5 ``` -Try this R.minBy example in Rambda REPL +Try this R.minBy example in Rambda REPL
@@ -7053,7 +7053,7 @@ const result = R.pipe( ) // => [1, 3, 3] ``` -Try this R.modifyItemAtIndex example in Rambda REPL +Try this R.modifyItemAtIndex example in Rambda REPL
@@ -7134,7 +7134,7 @@ const result = R.modifyPath('a.b.c', x=> x+1, {a:{b: {c:1}}}) // => {a:{b: {c:2}}} ``` -Try this R.modifyPath example in Rambda REPL +Try this R.modifyPath example in Rambda REPL
@@ -7277,7 +7277,7 @@ const result = R.modifyProp('age', x => x + 1)(person) // => {name: 'foo', age: 21} ``` -Try this R.modifyProp example in Rambda REPL +Try this R.modifyProp example in Rambda REPL
@@ -7400,7 +7400,7 @@ const result = R.none(predicate)(arr) // => true ``` -Try this R.none example in Rambda REPL +Try this R.none example in Rambda REPL
@@ -7496,7 +7496,7 @@ const result = objectIncludes(specification)(input) // => true ``` -Try this R.objectIncludes example in Rambda REPL +Try this R.objectIncludes example in Rambda REPL
@@ -7620,7 +7620,7 @@ const result = R.objOf('foo')('bar') // => {foo: 'bar'} ``` -Try this R.objOf example in Rambda REPL +Try this R.objOf example in Rambda REPL
@@ -7706,7 +7706,7 @@ const result = [ // => [{b: 2}, {b: 2}] ``` -Try this R.omit example in Rambda REPL +Try this R.omit example in Rambda REPL
@@ -7848,7 +7848,7 @@ const expected = [[3], [1, 2]] // `result` is equal to `expected` ``` -Try this R.partition example in Rambda REPL +Try this R.partition example in Rambda REPL
@@ -7973,7 +7973,7 @@ const expected = [{c: 3}, {a: 1, b: 2}] // `result` is equal to `expected` ``` -Try this R.partitionObject example in Rambda REPL +Try this R.partitionObject example in Rambda REPL
@@ -8117,7 +8117,7 @@ const result = [ // => [1, 1, undefined] ``` -Try this R.path example in Rambda REPL +Try this R.path example in Rambda REPL
@@ -8273,7 +8273,7 @@ const result = R.pathSatisfies( // => true ``` -Try this R.pathSatisfies example in Rambda REPL +Try this R.pathSatisfies example in Rambda REPL
@@ -8393,7 +8393,7 @@ const result = R.permutations( // => [[1, 2], [2, 1]] ``` -Try this R.permutations example in Rambda REPL +Try this R.permutations example in Rambda REPL
@@ -8496,7 +8496,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.pick example in Rambda REPL +Try this R.pick example in Rambda REPL
@@ -8635,7 +8635,7 @@ const result = R.pipe( // => [20, 30] ``` -Try this R.pipe example in Rambda REPL +Try this R.pipe example in Rambda REPL
@@ -8988,7 +8988,7 @@ const result = await R.pipeAsync( // `result` resolves to `RAMBDAX_DELAY104` ``` -Try this R.pipeAsync example in Rambda REPL +Try this R.pipeAsync example in Rambda REPL
@@ -9104,7 +9104,7 @@ const result = R.pluck(property)(list) // => [1, 2] ``` -Try this R.pluck example in Rambda REPL +Try this R.pluck example in Rambda REPL
@@ -9210,7 +9210,7 @@ const result = R.prepend('foo', ['bar', 'baz']) // => ['foo', 'bar', 'baz'] ``` -Try this R.prepend example in Rambda REPL +Try this R.prepend example in Rambda REPL
@@ -9274,7 +9274,7 @@ const result = [ // => [100, undefined] ``` -Try this R.prop example in Rambda REPL +Try this R.prop example in Rambda REPL
@@ -9348,7 +9348,7 @@ const result = [ // => [true, false] ``` -Try this R.propEq example in Rambda REPL +Try this R.propEq example in Rambda REPL
@@ -9434,7 +9434,7 @@ const result = [ // => [1, 'DEFAULT_VALUE'] ``` -Try this R.propOr example in Rambda REPL +Try this R.propOr example in Rambda REPL
@@ -9522,7 +9522,7 @@ const result = R.propSatisfies(predicate, property, obj) // => true ``` -Try this R.propSatisfies example in Rambda REPL +Try this R.propSatisfies example in Rambda REPL
@@ -9609,7 +9609,7 @@ If `start` is greater than `end`, then the result will be in descending order. // => [[0, 1, 2, 3, 4], [5, 4, 3, 2, 1]] ``` -Try this R.range example in Rambda REPL +Try this R.range example in Rambda REPL
@@ -9716,7 +9716,7 @@ const result = R.reduce(reducer, initialValue, list) // => 60 ``` -Try this R.reduce example in Rambda REPL +Try this R.reduce example in Rambda REPL
@@ -9837,7 +9837,7 @@ const result = [ // => [[1], {a: 1}] ``` -Try this R.reject example in Rambda REPL +Try this R.reject example in Rambda REPL
@@ -9990,7 +9990,7 @@ const result = R.rejectObject( // => {b: 2} ``` -Try this R.rejectObject example in Rambda REPL +Try this R.rejectObject example in Rambda REPL
@@ -10096,7 +10096,7 @@ const result = [ // => ['f|1|o', 'f|1||1|'] ``` -Try this R.replace example in Rambda REPL +Try this R.replace example in Rambda REPL
@@ -10179,7 +10179,7 @@ const result = [ // => 'f|1||1|' ``` -Try this R.replaceAll example in Rambda REPL +Try this R.replaceAll example in Rambda REPL
@@ -10271,7 +10271,7 @@ const result = R.shuffle( // => [3, 1, 2] or [2, 3, 1] or ... ``` -Try this R.shuffle example in Rambda REPL +Try this R.shuffle example in Rambda REPL
@@ -10356,7 +10356,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sort example in Rambda REPL +Try this R.sort example in Rambda REPL
@@ -10463,7 +10463,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortBy example in Rambda REPL +Try this R.sortBy example in Rambda REPL
@@ -10583,7 +10583,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortByDescending example in Rambda REPL +Try this R.sortByDescending example in Rambda REPL
@@ -10655,7 +10655,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortByPath example in Rambda REPL +Try this R.sortByPath example in Rambda REPL
@@ -10776,7 +10776,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortByPathDescending example in Rambda REPL +Try this R.sortByPathDescending example in Rambda REPL
@@ -10855,7 +10855,7 @@ const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) // => {b: 4, c: 2, a: 1} ``` -Try this R.sortObject example in Rambda REPL +Try this R.sortObject example in Rambda REPL
@@ -11002,7 +11002,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortWith example in Rambda REPL +Try this R.sortWith example in Rambda REPL
@@ -11227,7 +11227,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.splitEvery example in Rambda REPL +Try this R.splitEvery example in Rambda REPL
@@ -11318,7 +11318,7 @@ const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` -Try this R.symmetricDifference example in Rambda REPL +Try this R.symmetricDifference example in Rambda REPL
@@ -11415,7 +11415,7 @@ const result = [ // => [[2, 3], 'oo'] ``` -Try this R.tail example in Rambda REPL +Try this R.tail example in Rambda REPL
@@ -11514,7 +11514,7 @@ const result = [ // => [[1, 2], 'fo'] ``` -Try this R.take example in Rambda REPL +Try this R.take example in Rambda REPL
@@ -11607,7 +11607,7 @@ const result = [ // => [[2, 3], 'ar'] ``` -Try this R.takeLast example in Rambda REPL +Try this R.takeLast example in Rambda REPL
@@ -11695,7 +11695,7 @@ const result = R.takeLastWhile(x => x > 2)([1, 2, 3, 4]) // => [3, 4] ``` -Try this R.takeLastWhile example in Rambda REPL +Try this R.takeLastWhile example in Rambda REPL
@@ -11784,7 +11784,7 @@ const result = R.takeWhile(predicate)(list) // => [1, 2] ``` -Try this R.takeWhile example in Rambda REPL +Try this R.takeWhile example in Rambda REPL
@@ -11894,7 +11894,7 @@ const result = R.pipe( // => `2` and `3` will be logged ``` -Try this R.tap example in Rambda REPL +Try this R.tap example in Rambda REPL
@@ -11938,7 +11938,7 @@ R.test(/^f/)('foo') // => true ``` -Try this R.test example in Rambda REPL +Try this R.test example in Rambda REPL
@@ -12016,7 +12016,7 @@ const result = R.transformPropObject(fn, 'a')(obj) // => {a: false, b: 2} ``` -Try this R.transformPropObject example in Rambda REPL +Try this R.transformPropObject example in Rambda REPL
@@ -12077,7 +12077,7 @@ const result = [ // => [false, 'bar'] ``` -Try this R.tryCatch example in Rambda REPL +Try this R.tryCatch example in Rambda REPL
@@ -12208,7 +12208,7 @@ const delay = ms => new Promise(resolve => { R.type(delay) // => 'Promise' ``` -Try this R.type example in Rambda REPL +Try this R.type example in Rambda REPL
@@ -12458,7 +12458,7 @@ const result = R.union([1,2,3])([3,4,5]); // => [1, 2, 3, 4, 5] ``` -Try this R.union example in Rambda REPL +Try this R.union example in Rambda REPL
@@ -12567,7 +12567,7 @@ R.uniq(list) // => [1, {a: 1}, {a: 2}] ``` -Try this R.uniq example in Rambda REPL +Try this R.uniq example in Rambda REPL
@@ -12674,7 +12674,7 @@ const result = R.uniqBy(x => x)(list) // => [{a:1}, {a:2}] ``` -Try this R.uniqBy example in Rambda REPL +Try this R.uniqBy example in Rambda REPL
@@ -12780,7 +12780,7 @@ const result = R.uniqWith(predicate)(list) // => `result` is equal to `expected` ``` -Try this R.uniqWith example in Rambda REPL +Try this R.uniqWith example in Rambda REPL
@@ -12931,7 +12931,7 @@ const result = [ // => [11, 5] ``` -Try this R.unless example in Rambda REPL +Try this R.unless example in Rambda REPL
@@ -13046,7 +13046,7 @@ const expected = [{a:1, b:2}, {a:1, b:3}] // => `result` is equal to `expected` ``` -Try this R.unwind example in Rambda REPL +Try this R.unwind example in Rambda REPL
@@ -13155,7 +13155,7 @@ const result = R.update(index, newValue)(list) // => [1, 2, 88, 4, 5] ``` -Try this R.update example in Rambda REPL +Try this R.update example in Rambda REPL
@@ -13256,7 +13256,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.when example in Rambda REPL +Try this R.when example in Rambda REPL
@@ -13374,7 +13374,7 @@ R.zip([...x, 3])(['A', 'B']) // => [[1, 'A'], [2, 'B']] ``` -Try this R.zip example in Rambda REPL +Try this R.zip example in Rambda REPL
@@ -13492,7 +13492,7 @@ const result = R.zipWith((x, y) => x + y, list1)(list2) // => [110, 220] ``` -Try this R.zipWith example in Rambda REPL +Try this R.zipWith example in Rambda REPL
diff --git a/docs/README.md b/docs/README.md index 1d9ea964..2b2cdbba 100644 --- a/docs/README.md +++ b/docs/README.md @@ -183,7 +183,7 @@ const result = R.pipe( // => { a: 1, b: 'foo', c: 3 } ``` -Try this R.addProp example in Rambda REPL +Try this R.addProp example in Rambda REPL
@@ -278,7 +278,7 @@ const result = R.pipe( // => [{a: 1, b: 2, c: '3'}, {a: 3, b: 4, c: '7'}] ``` -Try this R.addPropToObjects example in Rambda REPL +Try this R.addPropToObjects example in Rambda REPL
@@ -393,7 +393,7 @@ const result = R.pipe( ) // => true ``` -Try this R.all example in Rambda REPL +Try this R.all example in Rambda REPL
@@ -491,7 +491,7 @@ const result = R.pipe( ) // => [[1, 2, 3, 4]] ``` -Try this R.allPass example in Rambda REPL +Try this R.allPass example in Rambda REPL
@@ -591,7 +591,7 @@ R.any(predicate)(list) // => true ``` -Try this R.any example in Rambda REPL +Try this R.any example in Rambda REPL
@@ -688,7 +688,7 @@ const result = fn(input) // => true ``` -Try this R.anyPass example in Rambda REPL +Try this R.anyPass example in Rambda REPL
@@ -838,7 +838,7 @@ const result = R.append('foo')(['bar', 'baz']) // => ['bar', 'baz', 'foo'] ``` -Try this R.append example in Rambda REPL +Try this R.append example in Rambda REPL
@@ -930,7 +930,7 @@ const result = R.pipe( // => [{a: 0}, {a: 1}, {a: 2}] ``` -Try this R.ascend example in Rambda REPL +Try this R.ascend example in Rambda REPL
@@ -1136,7 +1136,7 @@ const result = condition(input) // => true ``` -Try this R.checkObjectWithSpec example in Rambda REPL +Try this R.checkObjectWithSpec example in Rambda REPL
@@ -1272,7 +1272,7 @@ const result = R.pipe( // => { a: ['a', 'b', 'c'], b: [1, 2, 3], c: { a: 1, b: 2, c: 0, f: false } } ``` -Try this R.compact example in Rambda REPL +Try this R.compact example in Rambda REPL
@@ -1392,7 +1392,7 @@ const result = [ ] => [ true, false ] ``` -Try this R.complement example in Rambda REPL +Try this R.complement example in Rambda REPL
@@ -1473,7 +1473,7 @@ R.concat([1, 2])([3, 4]) // => [1, 2, 3, 4] R.concat('foo')('bar') // => 'foobar' ``` -Try this R.concat example in Rambda REPL +Try this R.concat example in Rambda REPL
@@ -1592,7 +1592,7 @@ const result = R.count(x => x.a !== undefined)(list) // => 2 ``` -Try this R.count example in Rambda REPL +Try this R.count example in Rambda REPL
@@ -1683,7 +1683,7 @@ const expected = { a: 2, b: 2, c: 2 } // => `result` is equal to `expected` ``` -Try this R.countBy example in Rambda REPL +Try this R.countBy example in Rambda REPL
@@ -1781,7 +1781,7 @@ const result = R.createObjectFromKeys( // => {a: 'a-0', b: 'b-1', c: 'c-2'} ``` -Try this R.createObjectFromKeys example in Rambda REPL +Try this R.createObjectFromKeys example in Rambda REPL
@@ -1857,7 +1857,7 @@ R.defaultTo('foo'))(undefined) // => 'foo' R.defaultTo('foo')('') // => 'foo' ``` -Try this R.defaultTo example in Rambda REPL +Try this R.defaultTo example in Rambda REPL
@@ -1956,7 +1956,7 @@ const result = R.pipe( // => [{a: 2}, {a: 1}, {a: 0}] ``` -Try this R.descend example in Rambda REPL +Try this R.descend example in Rambda REPL
@@ -2002,7 +2002,7 @@ It returns `howMany` items dropped from beginning of list. R.drop(2)(['foo', 'bar', 'baz']) // => ['baz'] ``` -Try this R.drop example in Rambda REPL +Try this R.drop example in Rambda REPL
@@ -2135,7 +2135,7 @@ const result = dropLastWhile(predicate)(list); // => [1, 2] ``` -Try this R.dropLastWhile example in Rambda REPL +Try this R.dropLastWhile example in Rambda REPL
@@ -2219,7 +2219,7 @@ const result = R.dropRepeatsBy( // => [1, 2, 3] ``` -Try this R.dropRepeatsBy example in Rambda REPL +Try this R.dropRepeatsBy example in Rambda REPL
@@ -2247,7 +2247,7 @@ const result = R.dropRepeatsWith(R.prop('a'))(list) // => [{a:1,b:2}, {a:2, b:4}] ``` -Try this R.dropRepeatsWith example in Rambda REPL +Try this R.dropRepeatsWith example in Rambda REPL
@@ -2275,7 +2275,7 @@ const result = R.dropWhile(predicate)(list) // => [3, 4] ``` -Try this R.dropWhile example in Rambda REPL +Try this R.dropWhile example in Rambda REPL
@@ -2394,7 +2394,7 @@ const result = R.duplicateBy(x => x, list) // => [{a:1}] ``` -Try this R.duplicateBy example in Rambda REPL +Try this R.duplicateBy example in Rambda REPL
@@ -2462,7 +2462,7 @@ const result = R.eqBy(Math.abs, 5)(-5) // => true ``` -Try this R.eqBy example in Rambda REPL +Try this R.eqBy example in Rambda REPL
@@ -2531,7 +2531,7 @@ const result = R.eqProps('a', obj1)(obj2) // => true ``` -Try this R.eqProps example in Rambda REPL +Try this R.eqProps example in Rambda REPL
@@ -2630,7 +2630,7 @@ R.equals( ) // => true ``` -Try this R.equals example in Rambda REPL +Try this R.equals example in Rambda REPL
@@ -3122,7 +3122,7 @@ const result = R.pipe( // => result is { foo: 3, baz: 'baz' } ``` -Try this R.evolve example in Rambda REPL +Try this R.evolve example in Rambda REPL
@@ -3228,7 +3228,7 @@ const result = [ // => [true, true ] ``` -Try this R.excludes example in Rambda REPL +Try this R.excludes example in Rambda REPL
@@ -3321,7 +3321,7 @@ const result = R.filter(predicate)(list) // => [2, 3] ``` -Try this R.filter example in Rambda REPL +Try this R.filter example in Rambda REPL
@@ -3583,7 +3583,7 @@ const result = R.filterObject( // => {a: 1, c: 3} ``` -Try this R.filterObject example in Rambda REPL +Try this R.filterObject example in Rambda REPL
@@ -3691,7 +3691,7 @@ const result = R.find(predicate)(list) // => {foo: 1} ``` -Try this R.find example in Rambda REPL +Try this R.find example in Rambda REPL
@@ -3795,7 +3795,7 @@ const result = R.findIndex(predicate)(list) // => 1 ``` -Try this R.findIndex example in Rambda REPL +Try this R.findIndex example in Rambda REPL
@@ -3890,7 +3890,7 @@ const result = R.findLast(predicate)(list) // => {foo: 1} ``` -Try this R.findLast example in Rambda REPL +Try this R.findLast example in Rambda REPL
@@ -3945,7 +3945,7 @@ const result = R.findLastIndex(predicate)(list) // => 1 ``` -Try this R.findLastIndex example in Rambda REPL +Try this R.findLastIndex example in Rambda REPL
@@ -4034,7 +4034,7 @@ const result = R.findNth(predicate, 2)(list) // => {foo: 2} ``` -Try this R.findNth example in Rambda REPL +Try this R.findNth example in Rambda REPL
@@ -4112,7 +4112,7 @@ const result = R.flatMap(duplicate)(list) // => [ 1, 1, 2, 2, 3, 3 ] ``` -Try this R.flatMap example in Rambda REPL +Try this R.flatMap example in Rambda REPL
@@ -4233,7 +4233,7 @@ const result = R.flatten([ // => [ 1, 2, 3, 30, 300, 4 ] ``` -Try this R.flatten example in Rambda REPL +Try this R.flatten example in Rambda REPL
@@ -4331,7 +4331,7 @@ const result = R.flattenObject( // => [3, 1, 2] or [2, 3, 1] or ... ``` -Try this R.flattenObject example in Rambda REPL +Try this R.flattenObject example in Rambda REPL
@@ -4555,7 +4555,7 @@ const result = R.groupBy(groupFn, list) // => { '1': ['a', 'b'], '2': ['aa', 'bb'] } ``` -Try this R.groupBy example in Rambda REPL +Try this R.groupBy example in Rambda REPL
@@ -4672,7 +4672,7 @@ const result = [ // => [1, 'f'] ``` -Try this R.head example in Rambda REPL +Try this R.head example in Rambda REPL
@@ -4795,7 +4795,7 @@ const result = [ // => [true, true ] ``` -Try this R.includes example in Rambda REPL +Try this R.includes example in Rambda REPL
@@ -4927,7 +4927,7 @@ const result = R.indexBy( // => {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}} ``` -Try this R.indexBy example in Rambda REPL +Try this R.indexBy example in Rambda REPL
@@ -5029,7 +5029,7 @@ const result = [ // => [0, 1] ``` -Try this R.indexOf example in Rambda REPL +Try this R.indexOf example in Rambda REPL
@@ -5129,7 +5129,7 @@ const result = [ // => [[1, 2], 'fo'] ``` -Try this R.init example in Rambda REPL +Try this R.init example in Rambda REPL
@@ -5235,7 +5235,7 @@ const result = R.innerJoin(predicate, list1)(list2) // => [4, 5] ``` -Try this R.innerJoin example in Rambda REPL +Try this R.innerJoin example in Rambda REPL
@@ -5357,7 +5357,7 @@ const expected = 'foo is BAR even 1 more' // => `result` is equal to `expected` ``` -Try this R.interpolate example in Rambda REPL +Try this R.interpolate example in Rambda REPL
@@ -5466,7 +5466,7 @@ const result = R.intersection(listA)(listB) // => [{ id : 3 }, { id : 4 }] ``` -Try this R.intersection example in Rambda REPL +Try this R.intersection example in Rambda REPL
@@ -5561,7 +5561,7 @@ const result = R.intersperse(separator)(list) // => [0, 10, 1, 10, 2, 10, 3] ``` -Try this R.intersperse example in Rambda REPL +Try this R.intersperse example in Rambda REPL
@@ -5656,7 +5656,7 @@ It returns a string of all `list` instances joined with a `glue`. R.join('-', [1, 2, 3]) // => '1-2-3' ``` -Try this R.join example in Rambda REPL +Try this R.join example in Rambda REPL
@@ -5721,7 +5721,7 @@ const result = [ // => [3, 'o'] ``` -Try this R.last example in Rambda REPL +Try this R.last example in Rambda REPL
@@ -5800,7 +5800,7 @@ const result = [ // => [4, -1] ``` -Try this R.lastIndexOf example in Rambda REPL +Try this R.lastIndexOf example in Rambda REPL
@@ -5903,7 +5903,7 @@ const result = R.map(fn)(iterable), // => [2, 4] ``` -Try this R.map example in Rambda REPL +Try this R.map example in Rambda REPL
@@ -6022,7 +6022,7 @@ const result = await R.mapAsync(fn)([1, 2, 3]) // `result` resolves after 3 seconds to `[2, 3, 4]` ``` -Try this R.mapAsync example in Rambda REPL +Try this R.mapAsync example in Rambda REPL
@@ -6166,7 +6166,7 @@ const result = R.mapKeys( // => { A1: 1, B2: 2 } ``` -Try this R.mapKeys example in Rambda REPL +Try this R.mapKeys example in Rambda REPL
@@ -6257,7 +6257,7 @@ const result = R.mapObject(fn)(obj) // => {a: 'a-1', b: 'b-2'} ``` -Try this R.mapObject example in Rambda REPL +Try this R.mapObject example in Rambda REPL
@@ -6614,7 +6614,7 @@ const result = pipe( // => { a: [{ a: 1, flag: false },{ a: 2, flag: false }, { a: 3, flag: true }], b: 'foo' } ``` -Try this R.mapPropObject example in Rambda REPL +Try this R.mapPropObject example in Rambda REPL
@@ -6727,7 +6727,7 @@ const result = [ // => [[], ['ba', 'na', 'na']] ``` -Try this R.match example in Rambda REPL +Try this R.match example in Rambda REPL
@@ -6813,7 +6813,7 @@ const compareFn = Math.abs R.maxBy(compareFn, 5, -7) // => -7 ``` -Try this R.maxBy example in Rambda REPL +Try this R.maxBy example in Rambda REPL
@@ -6996,7 +6996,7 @@ const compareFn = Math.abs R.minBy(compareFn, -5, 2) // => -5 ``` -Try this R.minBy example in Rambda REPL +Try this R.minBy example in Rambda REPL
@@ -7053,7 +7053,7 @@ const result = R.pipe( ) // => [1, 3, 3] ``` -Try this R.modifyItemAtIndex example in Rambda REPL +Try this R.modifyItemAtIndex example in Rambda REPL
@@ -7134,7 +7134,7 @@ const result = R.modifyPath('a.b.c', x=> x+1, {a:{b: {c:1}}}) // => {a:{b: {c:2}}} ``` -Try this R.modifyPath example in Rambda REPL +Try this R.modifyPath example in Rambda REPL
@@ -7277,7 +7277,7 @@ const result = R.modifyProp('age', x => x + 1)(person) // => {name: 'foo', age: 21} ``` -Try this R.modifyProp example in Rambda REPL +Try this R.modifyProp example in Rambda REPL
@@ -7400,7 +7400,7 @@ const result = R.none(predicate)(arr) // => true ``` -Try this R.none example in Rambda REPL +Try this R.none example in Rambda REPL
@@ -7496,7 +7496,7 @@ const result = objectIncludes(specification)(input) // => true ``` -Try this R.objectIncludes example in Rambda REPL +Try this R.objectIncludes example in Rambda REPL
@@ -7620,7 +7620,7 @@ const result = R.objOf('foo')('bar') // => {foo: 'bar'} ``` -Try this R.objOf example in Rambda REPL +Try this R.objOf example in Rambda REPL
@@ -7706,7 +7706,7 @@ const result = [ // => [{b: 2}, {b: 2}] ``` -Try this R.omit example in Rambda REPL +Try this R.omit example in Rambda REPL
@@ -7848,7 +7848,7 @@ const expected = [[3], [1, 2]] // `result` is equal to `expected` ``` -Try this R.partition example in Rambda REPL +Try this R.partition example in Rambda REPL
@@ -7973,7 +7973,7 @@ const expected = [{c: 3}, {a: 1, b: 2}] // `result` is equal to `expected` ``` -Try this R.partitionObject example in Rambda REPL +Try this R.partitionObject example in Rambda REPL
@@ -8117,7 +8117,7 @@ const result = [ // => [1, 1, undefined] ``` -Try this R.path example in Rambda REPL +Try this R.path example in Rambda REPL
@@ -8273,7 +8273,7 @@ const result = R.pathSatisfies( // => true ``` -Try this R.pathSatisfies example in Rambda REPL +Try this R.pathSatisfies example in Rambda REPL
@@ -8393,7 +8393,7 @@ const result = R.permutations( // => [[1, 2], [2, 1]] ``` -Try this R.permutations example in Rambda REPL +Try this R.permutations example in Rambda REPL
@@ -8496,7 +8496,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.pick example in Rambda REPL +Try this R.pick example in Rambda REPL
@@ -8635,7 +8635,7 @@ const result = R.pipe( // => [20, 30] ``` -Try this R.pipe example in Rambda REPL +Try this R.pipe example in Rambda REPL
@@ -8988,7 +8988,7 @@ const result = await R.pipeAsync( // `result` resolves to `RAMBDAX_DELAY104` ``` -Try this R.pipeAsync example in Rambda REPL +Try this R.pipeAsync example in Rambda REPL
@@ -9104,7 +9104,7 @@ const result = R.pluck(property)(list) // => [1, 2] ``` -Try this R.pluck example in Rambda REPL +Try this R.pluck example in Rambda REPL
@@ -9210,7 +9210,7 @@ const result = R.prepend('foo', ['bar', 'baz']) // => ['foo', 'bar', 'baz'] ``` -Try this R.prepend example in Rambda REPL +Try this R.prepend example in Rambda REPL
@@ -9274,7 +9274,7 @@ const result = [ // => [100, undefined] ``` -Try this R.prop example in Rambda REPL +Try this R.prop example in Rambda REPL
@@ -9348,7 +9348,7 @@ const result = [ // => [true, false] ``` -Try this R.propEq example in Rambda REPL +Try this R.propEq example in Rambda REPL
@@ -9434,7 +9434,7 @@ const result = [ // => [1, 'DEFAULT_VALUE'] ``` -Try this R.propOr example in Rambda REPL +Try this R.propOr example in Rambda REPL
@@ -9522,7 +9522,7 @@ const result = R.propSatisfies(predicate, property, obj) // => true ``` -Try this R.propSatisfies example in Rambda REPL +Try this R.propSatisfies example in Rambda REPL
@@ -9609,7 +9609,7 @@ If `start` is greater than `end`, then the result will be in descending order. // => [[0, 1, 2, 3, 4], [5, 4, 3, 2, 1]] ``` -Try this R.range example in Rambda REPL +Try this R.range example in Rambda REPL
@@ -9716,7 +9716,7 @@ const result = R.reduce(reducer, initialValue, list) // => 60 ``` -Try this R.reduce example in Rambda REPL +Try this R.reduce example in Rambda REPL
@@ -9837,7 +9837,7 @@ const result = [ // => [[1], {a: 1}] ``` -Try this R.reject example in Rambda REPL +Try this R.reject example in Rambda REPL
@@ -9990,7 +9990,7 @@ const result = R.rejectObject( // => {b: 2} ``` -Try this R.rejectObject example in Rambda REPL +Try this R.rejectObject example in Rambda REPL
@@ -10096,7 +10096,7 @@ const result = [ // => ['f|1|o', 'f|1||1|'] ``` -Try this R.replace example in Rambda REPL +Try this R.replace example in Rambda REPL
@@ -10179,7 +10179,7 @@ const result = [ // => 'f|1||1|' ``` -Try this R.replaceAll example in Rambda REPL +Try this R.replaceAll example in Rambda REPL
@@ -10271,7 +10271,7 @@ const result = R.shuffle( // => [3, 1, 2] or [2, 3, 1] or ... ``` -Try this R.shuffle example in Rambda REPL +Try this R.shuffle example in Rambda REPL
@@ -10356,7 +10356,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sort example in Rambda REPL +Try this R.sort example in Rambda REPL
@@ -10463,7 +10463,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortBy example in Rambda REPL +Try this R.sortBy example in Rambda REPL
@@ -10583,7 +10583,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortByDescending example in Rambda REPL +Try this R.sortByDescending example in Rambda REPL
@@ -10655,7 +10655,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortByPath example in Rambda REPL +Try this R.sortByPath example in Rambda REPL
@@ -10776,7 +10776,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortByPathDescending example in Rambda REPL +Try this R.sortByPathDescending example in Rambda REPL
@@ -10855,7 +10855,7 @@ const result = R.sortObject(predicate)({a:1, b: 4, c: 2}) // => {b: 4, c: 2, a: 1} ``` -Try this R.sortObject example in Rambda REPL +Try this R.sortObject example in Rambda REPL
@@ -11002,7 +11002,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.sortWith example in Rambda REPL +Try this R.sortWith example in Rambda REPL
@@ -11227,7 +11227,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.splitEvery example in Rambda REPL +Try this R.splitEvery example in Rambda REPL
@@ -11318,7 +11318,7 @@ const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` -Try this R.symmetricDifference example in Rambda REPL +Try this R.symmetricDifference example in Rambda REPL
@@ -11415,7 +11415,7 @@ const result = [ // => [[2, 3], 'oo'] ``` -Try this R.tail example in Rambda REPL +Try this R.tail example in Rambda REPL
@@ -11514,7 +11514,7 @@ const result = [ // => [[1, 2], 'fo'] ``` -Try this R.take example in Rambda REPL +Try this R.take example in Rambda REPL
@@ -11607,7 +11607,7 @@ const result = [ // => [[2, 3], 'ar'] ``` -Try this R.takeLast example in Rambda REPL +Try this R.takeLast example in Rambda REPL
@@ -11695,7 +11695,7 @@ const result = R.takeLastWhile(x => x > 2)([1, 2, 3, 4]) // => [3, 4] ``` -Try this R.takeLastWhile example in Rambda REPL +Try this R.takeLastWhile example in Rambda REPL
@@ -11784,7 +11784,7 @@ const result = R.takeWhile(predicate)(list) // => [1, 2] ``` -Try this R.takeWhile example in Rambda REPL +Try this R.takeWhile example in Rambda REPL
@@ -11894,7 +11894,7 @@ const result = R.pipe( // => `2` and `3` will be logged ``` -Try this R.tap example in Rambda REPL +Try this R.tap example in Rambda REPL
@@ -11938,7 +11938,7 @@ R.test(/^f/)('foo') // => true ``` -Try this R.test example in Rambda REPL +Try this R.test example in Rambda REPL
@@ -12016,7 +12016,7 @@ const result = R.transformPropObject(fn, 'a')(obj) // => {a: false, b: 2} ``` -Try this R.transformPropObject example in Rambda REPL +Try this R.transformPropObject example in Rambda REPL
@@ -12077,7 +12077,7 @@ const result = [ // => [false, 'bar'] ``` -Try this R.tryCatch example in Rambda REPL +Try this R.tryCatch example in Rambda REPL
@@ -12208,7 +12208,7 @@ const delay = ms => new Promise(resolve => { R.type(delay) // => 'Promise' ``` -Try this R.type example in Rambda REPL +Try this R.type example in Rambda REPL
@@ -12458,7 +12458,7 @@ const result = R.union([1,2,3])([3,4,5]); // => [1, 2, 3, 4, 5] ``` -Try this R.union example in Rambda REPL +Try this R.union example in Rambda REPL
@@ -12567,7 +12567,7 @@ R.uniq(list) // => [1, {a: 1}, {a: 2}] ``` -Try this R.uniq example in Rambda REPL +Try this R.uniq example in Rambda REPL
@@ -12674,7 +12674,7 @@ const result = R.uniqBy(x => x)(list) // => [{a:1}, {a:2}] ``` -Try this R.uniqBy example in Rambda REPL +Try this R.uniqBy example in Rambda REPL
@@ -12780,7 +12780,7 @@ const result = R.uniqWith(predicate)(list) // => `result` is equal to `expected` ``` -Try this R.uniqWith example in Rambda REPL +Try this R.uniqWith example in Rambda REPL
@@ -12931,7 +12931,7 @@ const result = [ // => [11, 5] ``` -Try this R.unless example in Rambda REPL +Try this R.unless example in Rambda REPL
@@ -13046,7 +13046,7 @@ const expected = [{a:1, b:2}, {a:1, b:3}] // => `result` is equal to `expected` ``` -Try this R.unwind example in Rambda REPL +Try this R.unwind example in Rambda REPL
@@ -13155,7 +13155,7 @@ const result = R.update(index, newValue)(list) // => [1, 2, 88, 4, 5] ``` -Try this R.update example in Rambda REPL +Try this R.update example in Rambda REPL
@@ -13256,7 +13256,7 @@ const expected = [ // => `result` is equal to `expected` ``` -Try this R.when example in Rambda REPL +Try this R.when example in Rambda REPL
@@ -13374,7 +13374,7 @@ R.zip([...x, 3])(['A', 'B']) // => [[1, 'A'], [2, 'B']] ``` -Try this R.zip example in Rambda REPL +Try this R.zip example in Rambda REPL
@@ -13492,7 +13492,7 @@ const result = R.zipWith((x, y) => x + y, list1)(list2) // => [110, 220] ``` -Try this R.zipWith example in Rambda REPL +Try this R.zipWith example in Rambda REPL
From b275b0de5879b7ef9b1aea17b69a245a4632c0f0 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Thu, 20 Nov 2025 00:16:26 +0200 Subject: [PATCH 31/54] chore@small --- README.md | 2 +- docs/README.md | 2 +- files/README_START.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2b2cdbba..bd8ec07c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ const result = pipe( //=> [6, 8] ``` -You can test this example in Rambda's REPL +You can test this example in Rambda's REPL * [API](#api) * [Changelog](#-changelog) diff --git a/docs/README.md b/docs/README.md index 2b2cdbba..bd8ec07c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,7 +21,7 @@ const result = pipe( //=> [6, 8] ``` -You can test this example in Rambda's REPL +You can test this example in Rambda's REPL * [API](#api) * [Changelog](#-changelog) diff --git a/files/README_START.md b/files/README_START.md index 80957e15..239fcb0d 100644 --- a/files/README_START.md +++ b/files/README_START.md @@ -21,7 +21,7 @@ const result = pipe( //=> [6, 8] ``` -You can test this example in Rambda's REPL +You can test this example in Rambda's REPL * [API](#api) * [Changelog](#-changelog) From a9c29056b6dbd022f24b58b46716c520d726a52b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 22 Nov 2025 16:55:46 +0200 Subject: [PATCH 32/54] chore@small --- CHANGELOG.md | 2 + README.md | 77 ++++++++++++++++++++++++--------- docs/README.md | 77 ++++++++++++++++++++++++--------- files/NEXT_VERSION_CHECKLIST.md | 18 -------- files/index.d.ts | 23 ++++++---- index.d.cts | 20 ++++++--- index.d.ts | 20 ++++++--- source/mapPropObject-spec.ts | 34 +++++++++++++-- 8 files changed, 190 insertions(+), 81 deletions(-) delete mode 100644 files/NEXT_VERSION_CHECKLIST.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 91750bc3..48682cd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Improve `R.mapParallelAsync` typings to allow optional `batchSize` parameter. +- Change order of inputs in `R.mapPropObject` + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/README.md b/README.md index bd8ec07c..927e5c96 100644 --- a/README.md +++ b/README.md @@ -6587,46 +6587,53 @@ test('with batchSize', async () => { ```typescript -mapPropObject( - valueMapper: ( - value: T[K] extends ReadonlyArray ? ElementType : never, - data: T[K], - ) => Value, - prop: K, +mapPropObject( + prop: K, + valueMapper: ( + listItem: T[K] extends ReadonlyArray ? ElementType : never, + list: T[K] extends ReadonlyArray ? T[K] : never, + ) => Value, ): (data: T) => T[K] extends ReadonlyArray - ? MergeTypes & { [P in K]: Value[] }> - : never + ? MergeTypes & { [P in K]: Value[] }> + : never ``` -It maps over a property of object that is a list. +Convenience method, when one needs to maps over a object property that is a list. ```javascript const result = pipe( { a: [1,2,3], b: 'foo' }, - mapPropObject(x => { - x // $ExpectType { a: number; b: string; } + mapPropObject('a',x => { return { a: x, flag: x > 2, } - }, 'a'), + }), ) // => { a: [{ a: 1, flag: false },{ a: 2, flag: false }, { a: 3, flag: true }], b: 'foo' } ``` -Try this R.mapPropObject example in Rambda REPL +Try this R.mapPropObject example in Rambda REPL
All TypeScript definitions ```typescript -mapPropObject( +mapPropObject( + prop: K, + valueMapper: ( + listItem: T[K] extends ReadonlyArray ? ElementType : never, + list: T[K] extends ReadonlyArray ? T[K] : never, + ) => Value, +): (data: T) => T[K] extends ReadonlyArray + ? MergeTypes & { [P in K]: Value[] }> + : never; +mapPropObject( + prop: K, valueMapper: ( - value: T[K] extends ReadonlyArray ? ElementType : never, - data: T[K], + listItem: T[K] extends ReadonlyArray ? ElementType : never, ) => Value, - prop: K, ): (data: T) => T[K] extends ReadonlyArray ? MergeTypes & { [P in K]: Value[] }> : never; @@ -6685,24 +6692,52 @@ it('happy', () => { TypeScript test ```typescript -import { mapPropObject, pipe } from 'rambda' +import { map, mapPropObject, pipe } from 'rambda' describe('R.mapPropObject', () => { it('iterable with one arguments', () => { const result = pipe( { a: [1,2,3], b: 'foo' }, - mapPropObject(x => { + mapPropObject('a', x => { x // $ExpectType number return { a: x, flag: x > 2, } - }, 'a'), + }), ) result.a // $ExpectType { a: number; flag: boolean; }[] result.b // $ExpectType string }) + + it('iterable with two arguments', () => { + const result = pipe( + { a: [1,2,3], b: 'foo' }, + mapPropObject('a', (x, list) => { + x // $ExpectType number + list // $ExpectType number[] + return list.length + }), + ) + result.a // $ExpectType number[] + result.b // $ExpectType string + }) + + it('more complex example', () => { + const result = pipe( + [{a:[true, false, true], b: 'foo'}], + map( + mapPropObject( 'a',(a) => { + a // $ExpectType boolean + return {a, b: 2} + }) + ) + ) + + result[0].a[0].a // $ExpectType boolean + result[0].a[0].b // $ExpectType number + }) }) ``` @@ -13587,6 +13622,8 @@ describe('R.zipWith', () => { - Improve `R.mapParallelAsync` typings to allow optional `batchSize` parameter. +- Change order of inputs in `R.mapPropObject` + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/docs/README.md b/docs/README.md index bd8ec07c..927e5c96 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6587,46 +6587,53 @@ test('with batchSize', async () => { ```typescript -mapPropObject( - valueMapper: ( - value: T[K] extends ReadonlyArray ? ElementType : never, - data: T[K], - ) => Value, - prop: K, +mapPropObject( + prop: K, + valueMapper: ( + listItem: T[K] extends ReadonlyArray ? ElementType : never, + list: T[K] extends ReadonlyArray ? T[K] : never, + ) => Value, ): (data: T) => T[K] extends ReadonlyArray - ? MergeTypes & { [P in K]: Value[] }> - : never + ? MergeTypes & { [P in K]: Value[] }> + : never ``` -It maps over a property of object that is a list. +Convenience method, when one needs to maps over a object property that is a list. ```javascript const result = pipe( { a: [1,2,3], b: 'foo' }, - mapPropObject(x => { - x // $ExpectType { a: number; b: string; } + mapPropObject('a',x => { return { a: x, flag: x > 2, } - }, 'a'), + }), ) // => { a: [{ a: 1, flag: false },{ a: 2, flag: false }, { a: 3, flag: true }], b: 'foo' } ``` -Try this R.mapPropObject example in Rambda REPL +Try this R.mapPropObject example in Rambda REPL
All TypeScript definitions ```typescript -mapPropObject( +mapPropObject( + prop: K, + valueMapper: ( + listItem: T[K] extends ReadonlyArray ? ElementType : never, + list: T[K] extends ReadonlyArray ? T[K] : never, + ) => Value, +): (data: T) => T[K] extends ReadonlyArray + ? MergeTypes & { [P in K]: Value[] }> + : never; +mapPropObject( + prop: K, valueMapper: ( - value: T[K] extends ReadonlyArray ? ElementType : never, - data: T[K], + listItem: T[K] extends ReadonlyArray ? ElementType : never, ) => Value, - prop: K, ): (data: T) => T[K] extends ReadonlyArray ? MergeTypes & { [P in K]: Value[] }> : never; @@ -6685,24 +6692,52 @@ it('happy', () => { TypeScript test ```typescript -import { mapPropObject, pipe } from 'rambda' +import { map, mapPropObject, pipe } from 'rambda' describe('R.mapPropObject', () => { it('iterable with one arguments', () => { const result = pipe( { a: [1,2,3], b: 'foo' }, - mapPropObject(x => { + mapPropObject('a', x => { x // $ExpectType number return { a: x, flag: x > 2, } - }, 'a'), + }), ) result.a // $ExpectType { a: number; flag: boolean; }[] result.b // $ExpectType string }) + + it('iterable with two arguments', () => { + const result = pipe( + { a: [1,2,3], b: 'foo' }, + mapPropObject('a', (x, list) => { + x // $ExpectType number + list // $ExpectType number[] + return list.length + }), + ) + result.a // $ExpectType number[] + result.b // $ExpectType string + }) + + it('more complex example', () => { + const result = pipe( + [{a:[true, false, true], b: 'foo'}], + map( + mapPropObject( 'a',(a) => { + a // $ExpectType boolean + return {a, b: 2} + }) + ) + ) + + result[0].a[0].a // $ExpectType boolean + result[0].a[0].b // $ExpectType number + }) }) ``` @@ -13587,6 +13622,8 @@ describe('R.zipWith', () => { - Improve `R.mapParallelAsync` typings to allow optional `batchSize` parameter. +- Change order of inputs in `R.mapPropObject` + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/files/NEXT_VERSION_CHECKLIST.md b/files/NEXT_VERSION_CHECKLIST.md deleted file mode 100644 index c98a1b64..00000000 --- a/files/NEXT_VERSION_CHECKLIST.md +++ /dev/null @@ -1,18 +0,0 @@ -=== -ABOVE IS DONE -=== -document scripts - - -ABOVE IS IN PROGRESS -=== -export function maybe(thunk: () => T): T | undefined { - try { - return thunk(); - } catch {} -} -=== -use functor as a word -https://github.com/hemanth/functional-programming-jargon?utm_source=hackernewsletter&utm_medium=email&utm_term=code#functor - -=== diff --git a/files/index.d.ts b/files/index.d.ts index e2f50cb0..dcc0acb5 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -1050,7 +1050,7 @@ export function transformPropObject( /* Method: mapPropObject -Explanation: It maps over a property of object that is a list. +Explanation: Convenience method, when one needs to maps over a object property that is a list. Example: @@ -1058,13 +1058,12 @@ Example: const result = pipe( { a: [1,2,3], b: 'foo' }, - mapPropObject(x => { - x // $ExpectType { a: number; b: string; } + mapPropObject('a',x => { return { a: x, flag: x > 2, } - }, 'a'), + }), ) // => { a: [{ a: 1, flag: false },{ a: 2, flag: false }, { a: 3, flag: true }], b: 'foo' } ``` @@ -1075,12 +1074,20 @@ Notes: */ // @SINGLE_MARKER -export function mapPropObject( +export function mapPropObject( + prop: K, + valueMapper: ( + listItem: T[K] extends ReadonlyArray ? ElementType : never, + list: T[K] extends ReadonlyArray ? T[K] : never, + ) => Value, +): (data: T) => T[K] extends ReadonlyArray + ? MergeTypes & { [P in K]: Value[] }> + : never; +export function mapPropObject( + prop: K, valueMapper: ( - value: T[K] extends ReadonlyArray ? ElementType : never, - data: T[K], + listItem: T[K] extends ReadonlyArray ? ElementType : never, ) => Value, - prop: K, ): (data: T) => T[K] extends ReadonlyArray ? MergeTypes & { [P in K]: Value[] }> : never; diff --git a/index.d.cts b/index.d.cts index 7f05d1b1..3df22af2 100644 --- a/index.d.cts +++ b/index.d.cts @@ -555,14 +555,22 @@ export function mapParallelAsync( ): (data: T) => Promise>; /** - * It maps over a property of object that is a list. - */ -export function mapPropObject( + * Convenience method, when one needs to maps over a object property that is a list. + */ +export function mapPropObject( + prop: K, + valueMapper: ( + listItem: T[K] extends ReadonlyArray ? ElementType : never, + list: T[K] extends ReadonlyArray ? T[K] : never, + ) => Value, +): (data: T) => T[K] extends ReadonlyArray + ? MergeTypes & { [P in K]: Value[] }> + : never; +export function mapPropObject( + prop: K, valueMapper: ( - value: T[K] extends ReadonlyArray ? ElementType : never, - data: T[K], + listItem: T[K] extends ReadonlyArray ? ElementType : never, ) => Value, - prop: K, ): (data: T) => T[K] extends ReadonlyArray ? MergeTypes & { [P in K]: Value[] }> : never; diff --git a/index.d.ts b/index.d.ts index 7f05d1b1..3df22af2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -555,14 +555,22 @@ export function mapParallelAsync( ): (data: T) => Promise>; /** - * It maps over a property of object that is a list. - */ -export function mapPropObject( + * Convenience method, when one needs to maps over a object property that is a list. + */ +export function mapPropObject( + prop: K, + valueMapper: ( + listItem: T[K] extends ReadonlyArray ? ElementType : never, + list: T[K] extends ReadonlyArray ? T[K] : never, + ) => Value, +): (data: T) => T[K] extends ReadonlyArray + ? MergeTypes & { [P in K]: Value[] }> + : never; +export function mapPropObject( + prop: K, valueMapper: ( - value: T[K] extends ReadonlyArray ? ElementType : never, - data: T[K], + listItem: T[K] extends ReadonlyArray ? ElementType : never, ) => Value, - prop: K, ): (data: T) => T[K] extends ReadonlyArray ? MergeTypes & { [P in K]: Value[] }> : never; diff --git a/source/mapPropObject-spec.ts b/source/mapPropObject-spec.ts index 32f93831..4e9988ec 100644 --- a/source/mapPropObject-spec.ts +++ b/source/mapPropObject-spec.ts @@ -1,19 +1,47 @@ -import { mapPropObject, pipe } from 'rambda' +import { map, mapPropObject, pipe } from 'rambda' describe('R.mapPropObject', () => { it('iterable with one arguments', () => { const result = pipe( { a: [1,2,3], b: 'foo' }, - mapPropObject(x => { + mapPropObject('a', x => { x // $ExpectType number return { a: x, flag: x > 2, } - }, 'a'), + }), ) result.a // $ExpectType { a: number; flag: boolean; }[] result.b // $ExpectType string }) + + it('iterable with two arguments', () => { + const result = pipe( + { a: [1,2,3], b: 'foo' }, + mapPropObject('a', (x, list) => { + x // $ExpectType number + list // $ExpectType number[] + return list.length + }), + ) + result.a // $ExpectType number[] + result.b // $ExpectType string + }) + + it('more complex example', () => { + const result = pipe( + [{a:[true, false, true], b: 'foo'}], + map( + mapPropObject( 'a',(a) => { + a // $ExpectType boolean + return {a, b: 2} + }) + ) + ) + + result[0].a[0].a // $ExpectType boolean + result[0].a[0].b // $ExpectType number + }) }) From b714d9ad9871b615d2dd75e7067f0690608e6b75 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 22 Nov 2025 16:59:34 +0200 Subject: [PATCH 33/54] chore@small --- CHANGELOG.md | 4 ++++ deno.json | 2 +- files/DEV_NOTES.md | 25 +++++++++++++++++++++++++ jsr.json | 19 ------------------- sugg.txt | 24 ------------------------ 5 files changed, 30 insertions(+), 44 deletions(-) delete mode 100644 jsr.json delete mode 100644 sugg.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 48682cd8..47f12cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - Change order of inputs in `R.mapPropObject` +- Change REPL links in documentation + +- Remove `jsr.json` + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/deno.json b/deno.json index 0efb4ed4..8a8cddbf 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,6 @@ { "name": "@rambda/rambda", - "version": "10.3.3", + "version": "10.3.4", "exports": "./mod.ts", "imports": { "rambda": "./mod.ts" diff --git a/files/DEV_NOTES.md b/files/DEV_NOTES.md index 79a91795..9091b31f 100644 --- a/files/DEV_NOTES.md +++ b/files/DEV_NOTES.md @@ -7,6 +7,31 @@ export function splitEvery(sliceLength: number): { (input: T[]): (T[])[]; }; --- +Suggested new methods for Rambda library: + + +15. `sortByMultiple` - Sort by multiple criteria: +```typescript +export function sortByMultiple( + criteria: Array<(a: T, b: T) => number> +): (list: T[]) => T[]; +``` + +These suggestions are based on: +1. Common use cases in TypeScript projects +2. Working well within `R.pipe` chains +3. Having clear, single-purpose functionality +4. Being type-safe +5. Following the library's focus on object manipulation and array operations +6. Complementing existing methods + +The suggestions avoid methods that: +1. Have confusing or ambiguous behavior +2. Don't work well in pipe chains +3. Have multiple ways to be used +4. Are better suited as part of application code +5. Have complex TypeScript definitions that would be hard to maintain +--- check wrong import from './[a-zA-Z]+' diff --git a/jsr.json b/jsr.json deleted file mode 100644 index 4a54711f..00000000 --- a/jsr.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "@rambda/rambda", - "version": "10.2.0", - "exports": "./mod.ts", - "imports": { - "rambda": "./mod.ts" - }, - "publish": { - "include": [ - "src", - "rambda.js", - "index.d.ts", - "index.d.cts", - "mod.ts", - "LICENSE.md", - "README.md" - ] - } -} \ No newline at end of file diff --git a/sugg.txt b/sugg.txt deleted file mode 100644 index 4264633e..00000000 --- a/sugg.txt +++ /dev/null @@ -1,24 +0,0 @@ -Suggested new methods for Rambda library: - - -15. `sortByMultiple` - Sort by multiple criteria: -```typescript -export function sortByMultiple( - criteria: Array<(a: T, b: T) => number> -): (list: T[]) => T[]; -``` - -These suggestions are based on: -1. Common use cases in TypeScript projects -2. Working well within `R.pipe` chains -3. Having clear, single-purpose functionality -4. Being type-safe -5. Following the library's focus on object manipulation and array operations -6. Complementing existing methods - -The suggestions avoid methods that: -1. Have confusing or ambiguous behavior -2. Don't work well in pipe chains -3. Have multiple ways to be used -4. Are better suited as part of application code -5. Have complex TypeScript definitions that would be hard to maintain \ No newline at end of file From 9e3013105ff102afc4127d56bb24d85bdcda4ff2 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 29 Nov 2025 21:43:22 +0200 Subject: [PATCH 34/54] feat@fix filter --- files/index.d.ts | 6 ++++-- source/filter-spec.ts | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/files/index.d.ts b/files/index.d.ts index dcc0acb5..4ae6033d 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -88,6 +88,8 @@ MergeTypes< type StrictNonNullable = Exclude; +type ExcludeFalsy = Exclude; + type Flatten = T extends object ? T extends readonly any[] ? T @@ -479,10 +481,10 @@ export function filter( ): (list: T[]) => S[]; export function filter( predicate: BooleanConstructor, -): (list: readonly T[]) => StrictNonNullable[]; +): (list: readonly T[]) => ExcludeFalsy[]; export function filter( predicate: BooleanConstructor, -): (list: T[]) => StrictNonNullable[]; +): (list: T[]) => ExcludeFalsy[]; export function filter( predicate: (value: T) => boolean, ): (list: T[]) => T[]; diff --git a/source/filter-spec.ts b/source/filter-spec.ts index f71a05ec..aa28c640 100644 --- a/source/filter-spec.ts +++ b/source/filter-spec.ts @@ -13,6 +13,7 @@ describe('R.filter with array', () => { ) result // $ExpectType number[] }) + it('narrowing type', () => { interface Foo { a: number @@ -31,6 +32,7 @@ describe('R.filter with array', () => { ) result // $ExpectType Bar[] }) + it('narrowing type - readonly', () => { interface Foo { a: number @@ -49,11 +51,19 @@ describe('R.filter with array', () => { ) result // $ExpectType Bar[] }) - it('filtering NonNullable', () => { - const testList = [1, 2, null, undefined, 3] + + it('filtering NonNullable', () => { + const testList = [1, 2, null, undefined, false, 3] const result = pipe(testList, filter(Boolean)) result // $ExpectType number[] }) + + it('filtering NonNullable - list of objects', () => { + const testList = [{a:1}, {a:2}, false, {a:3}] + const result = pipe(testList, filter(Boolean)) + result // $ExpectType number[] + }) + it('filtering NonNullable - readonly', () => { const testList = [1, 2, null, undefined, 3] as const const result = pipe(testList, filter(Boolean)) From 1e04d6320a566ae4b146c9c4bb7bd1b4d0bf6fc8 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 30 Nov 2025 12:39:27 +0200 Subject: [PATCH 35/54] readonly on top --- CHANGELOG.md | 4 +++ README.md | 58 +++++++++++++++++++++++++------------------ docs/README.md | 58 +++++++++++++++++++++++++------------------ files/index.d.ts | 6 ++--- index.d.cts | 12 +++++---- index.d.ts | 12 +++++---- source/filter-spec.ts | 40 ++++++++++++----------------- 7 files changed, 105 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f12cc9..ecfdf402 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +10.3.5 + +- Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. + 10.3.4 - Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) diff --git a/README.md b/README.md index 927e5c96..34587987 100644 --- a/README.md +++ b/README.md @@ -828,7 +828,7 @@ describe('anyPass', () => { ```typescript -append(el: T): (list: T[]) => T[] +append(el: T): (list: readonly T[]) => T[] ``` It adds element `x` at the end of `iterable`. @@ -845,8 +845,8 @@ const result = R.append('foo')(['bar', 'baz']) All TypeScript definitions ```typescript -append(el: T): (list: T[]) => T[]; append(el: T): (list: readonly T[]) => T[]; +append(el: T): (list: T[]) => T[]; ```
@@ -3333,10 +3333,10 @@ filter( ): (list: T[]) => S[]; filter( predicate: BooleanConstructor, -): (list: readonly T[]) => StrictNonNullable[]; +): (list: readonly T[]) => ExcludeFalsy[]; filter( predicate: BooleanConstructor, -): (list: T[]) => StrictNonNullable[]; +): (list: T[]) => ExcludeFalsy[]; filter( predicate: (value: T) => boolean, ): (list: T[]) => T[]; @@ -3408,13 +3408,14 @@ describe('R.filter with array', () => { it('within pipe', () => { const result = pipe( list, - filter(x => { + filter((x) => { x // $ExpectType number return x > 1 }), ) result // $ExpectType number[] }) + it('narrowing type', () => { interface Foo { a: number @@ -3422,17 +3423,15 @@ describe('R.filter with array', () => { interface Bar extends Foo { b: string } - type T = Foo | Bar - const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] + type T = Foo | Bar + const testList: T[] = [{ a: 1 }, { a: 2 }, { a: 3 }] const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe( - testList, - filter(filterBar), - ) + const result = pipe(testList, filter(filterBar)) result // $ExpectType Bar[] }) + it('narrowing type - readonly', () => { interface Foo { a: number @@ -3440,30 +3439,33 @@ describe('R.filter with array', () => { interface Bar extends Foo { b: string } - type T = Foo | Bar - const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] as const + type T = Foo | Bar + const testList: T[] = [{ a: 1 }, { a: 2 }, { a: 3 }] as const const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe( - testList, - filter(filterBar), - ) + const result = pipe(testList, filter(filterBar)) result // $ExpectType Bar[] }) - it('filtering NonNullable', () => { - const testList = [1, 2, null, undefined, 3] + + it('filtering NonNullable - list of objects', () => { + const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] const result = pipe(testList, filter(Boolean)) - result // $ExpectType number[] + result // $ExpectType { a: number; }[] }) + it('filtering NonNullable - readonly', () => { - const testList = [1, 2, null, undefined, 3] as const + const testList = [1, 2, true, false, null, undefined, 3] as const const result = pipe(testList, filter(Boolean)) result.includes(1) // @ts-expect-error + result.includes(true) + // @ts-expect-error + result.includes(false) + // @ts-expect-error result.includes(4) // @ts-expect-error - result.includes(undefined) + result.includes(undefined) // @ts-expect-error result.includes(null) }) @@ -11558,8 +11560,8 @@ const result = [ ```typescript take(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; ... ... @@ -11651,8 +11653,8 @@ const result = [ ```typescript takeLast(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; ... ... @@ -13616,6 +13618,10 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +10.3.5 + +- Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. + 10.3.4 - Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) @@ -13624,6 +13630,10 @@ describe('R.zipWith', () => { - Change order of inputs in `R.mapPropObject` +- Change REPL links in documentation + +- Remove `jsr.json` + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/docs/README.md b/docs/README.md index 927e5c96..34587987 100644 --- a/docs/README.md +++ b/docs/README.md @@ -828,7 +828,7 @@ describe('anyPass', () => { ```typescript -append(el: T): (list: T[]) => T[] +append(el: T): (list: readonly T[]) => T[] ``` It adds element `x` at the end of `iterable`. @@ -845,8 +845,8 @@ const result = R.append('foo')(['bar', 'baz']) All TypeScript definitions ```typescript -append(el: T): (list: T[]) => T[]; append(el: T): (list: readonly T[]) => T[]; +append(el: T): (list: T[]) => T[]; ```
@@ -3333,10 +3333,10 @@ filter( ): (list: T[]) => S[]; filter( predicate: BooleanConstructor, -): (list: readonly T[]) => StrictNonNullable[]; +): (list: readonly T[]) => ExcludeFalsy[]; filter( predicate: BooleanConstructor, -): (list: T[]) => StrictNonNullable[]; +): (list: T[]) => ExcludeFalsy[]; filter( predicate: (value: T) => boolean, ): (list: T[]) => T[]; @@ -3408,13 +3408,14 @@ describe('R.filter with array', () => { it('within pipe', () => { const result = pipe( list, - filter(x => { + filter((x) => { x // $ExpectType number return x > 1 }), ) result // $ExpectType number[] }) + it('narrowing type', () => { interface Foo { a: number @@ -3422,17 +3423,15 @@ describe('R.filter with array', () => { interface Bar extends Foo { b: string } - type T = Foo | Bar - const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] + type T = Foo | Bar + const testList: T[] = [{ a: 1 }, { a: 2 }, { a: 3 }] const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe( - testList, - filter(filterBar), - ) + const result = pipe(testList, filter(filterBar)) result // $ExpectType Bar[] }) + it('narrowing type - readonly', () => { interface Foo { a: number @@ -3440,30 +3439,33 @@ describe('R.filter with array', () => { interface Bar extends Foo { b: string } - type T = Foo | Bar - const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] as const + type T = Foo | Bar + const testList: T[] = [{ a: 1 }, { a: 2 }, { a: 3 }] as const const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe( - testList, - filter(filterBar), - ) + const result = pipe(testList, filter(filterBar)) result // $ExpectType Bar[] }) - it('filtering NonNullable', () => { - const testList = [1, 2, null, undefined, 3] + + it('filtering NonNullable - list of objects', () => { + const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] const result = pipe(testList, filter(Boolean)) - result // $ExpectType number[] + result // $ExpectType { a: number; }[] }) + it('filtering NonNullable - readonly', () => { - const testList = [1, 2, null, undefined, 3] as const + const testList = [1, 2, true, false, null, undefined, 3] as const const result = pipe(testList, filter(Boolean)) result.includes(1) // @ts-expect-error + result.includes(true) + // @ts-expect-error + result.includes(false) + // @ts-expect-error result.includes(4) // @ts-expect-error - result.includes(undefined) + result.includes(undefined) // @ts-expect-error result.includes(null) }) @@ -11558,8 +11560,8 @@ const result = [ ```typescript take(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; ... ... @@ -11651,8 +11653,8 @@ const result = [ ```typescript takeLast(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; ... ... @@ -13616,6 +13618,10 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +10.3.5 + +- Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. + 10.3.4 - Fix wrong typing for `R.sortByDescending` - [Issue #797](https://github.com/selfrefactor/rambda/issues/797) @@ -13624,6 +13630,10 @@ describe('R.zipWith', () => { - Change order of inputs in `R.mapPropObject` +- Change REPL links in documentation + +- Remove `jsr.json` + 10.3.3 - Fix wrong typing for `R.reject` - [Issue #779](https://github.com/selfrefactor/rambda/issues/779) diff --git a/files/index.d.ts b/files/index.d.ts index 4ae6033d..920f3437 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -296,8 +296,8 @@ Notes: */ // @SINGLE_MARKER -export function append(el: T): (list: T[]) => T[]; export function append(el: T): (list: readonly T[]) => T[]; +export function append(el: T): (list: T[]) => T[]; /* Method: flatMap @@ -3074,8 +3074,8 @@ Notes: // @SINGLE_MARKER export function take(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; /* @@ -3103,8 +3103,8 @@ Notes: // @SINGLE_MARKER export function takeLast(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; /* diff --git a/index.d.cts b/index.d.cts index 3df22af2..d16d2250 100644 --- a/index.d.cts +++ b/index.d.cts @@ -88,6 +88,8 @@ MergeTypes< type StrictNonNullable = Exclude; +type ExcludeFalsy = Exclude; + type Flatten = T extends object ? T extends readonly any[] ? T @@ -198,8 +200,8 @@ export function anyPass boolean>(predicates: reado /** * It adds element `x` at the end of `iterable`. */ -export function append(el: T): (list: T[]) => T[]; export function append(el: T): (list: readonly T[]) => T[]; +export function append(el: T): (list: T[]) => T[]; /** * Helper function to be used with `R.sort` to sort list in ascending order. @@ -334,10 +336,10 @@ export function filter( ): (list: T[]) => S[]; export function filter( predicate: BooleanConstructor, -): (list: readonly T[]) => StrictNonNullable[]; +): (list: readonly T[]) => ExcludeFalsy[]; export function filter( predicate: BooleanConstructor, -): (list: T[]) => StrictNonNullable[]; +): (list: T[]) => ExcludeFalsy[]; export function filter( predicate: (value: T) => boolean, ): (list: T[]) => T[]; @@ -2206,8 +2208,8 @@ export function tail(input: string): string; */ export function take(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; /** @@ -2215,8 +2217,8 @@ export function take(howMany: number): { */ export function takeLast(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; export function takeLastWhile(predicate: (x: T) => boolean): (input: T[]) => T[]; diff --git a/index.d.ts b/index.d.ts index 3df22af2..d16d2250 100644 --- a/index.d.ts +++ b/index.d.ts @@ -88,6 +88,8 @@ MergeTypes< type StrictNonNullable = Exclude; +type ExcludeFalsy = Exclude; + type Flatten = T extends object ? T extends readonly any[] ? T @@ -198,8 +200,8 @@ export function anyPass boolean>(predicates: reado /** * It adds element `x` at the end of `iterable`. */ -export function append(el: T): (list: T[]) => T[]; export function append(el: T): (list: readonly T[]) => T[]; +export function append(el: T): (list: T[]) => T[]; /** * Helper function to be used with `R.sort` to sort list in ascending order. @@ -334,10 +336,10 @@ export function filter( ): (list: T[]) => S[]; export function filter( predicate: BooleanConstructor, -): (list: readonly T[]) => StrictNonNullable[]; +): (list: readonly T[]) => ExcludeFalsy[]; export function filter( predicate: BooleanConstructor, -): (list: T[]) => StrictNonNullable[]; +): (list: T[]) => ExcludeFalsy[]; export function filter( predicate: (value: T) => boolean, ): (list: T[]) => T[]; @@ -2206,8 +2208,8 @@ export function tail(input: string): string; */ export function take(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; /** @@ -2215,8 +2217,8 @@ export function take(howMany: number): { */ export function takeLast(howMany: number): { (input: string): string; - (input: T[]): T[]; (input: readonly T[]): T[]; + (input: T[]): T[]; }; export function takeLastWhile(predicate: (x: T) => boolean): (input: T[]) => T[]; diff --git a/source/filter-spec.ts b/source/filter-spec.ts index aa28c640..a4e8c0a7 100644 --- a/source/filter-spec.ts +++ b/source/filter-spec.ts @@ -6,7 +6,7 @@ describe('R.filter with array', () => { it('within pipe', () => { const result = pipe( list, - filter(x => { + filter((x) => { x // $ExpectType number return x > 1 }), @@ -21,15 +21,12 @@ describe('R.filter with array', () => { interface Bar extends Foo { b: string } - type T = Foo | Bar - const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] + type T = Foo | Bar + const testList: T[] = [{ a: 1 }, { a: 2 }, { a: 3 }] const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe( - testList, - filter(filterBar), - ) + const result = pipe(testList, filter(filterBar)) result // $ExpectType Bar[] }) @@ -40,38 +37,33 @@ describe('R.filter with array', () => { interface Bar extends Foo { b: string } - type T = Foo | Bar - const testList: T[]= [{ a: 1 }, { a: 2 }, { a: 3 }] as const + type T = Foo | Bar + const testList: T[] = [{ a: 1 }, { a: 2 }, { a: 3 }] as const const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe( - testList, - filter(filterBar), - ) + const result = pipe(testList, filter(filterBar)) result // $ExpectType Bar[] }) - - it('filtering NonNullable', () => { - const testList = [1, 2, null, undefined, false, 3] - const result = pipe(testList, filter(Boolean)) - result // $ExpectType number[] - }) - it('filtering NonNullable - list of objects', () => { - const testList = [{a:1}, {a:2}, false, {a:3}] + it('filtering NonNullable - list of objects', () => { + const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] const result = pipe(testList, filter(Boolean)) - result // $ExpectType number[] + result // $ExpectType { a: number; }[] }) it('filtering NonNullable - readonly', () => { - const testList = [1, 2, null, undefined, 3] as const + const testList = [1, 2, true, false, null, undefined, 3] as const const result = pipe(testList, filter(Boolean)) result.includes(1) // @ts-expect-error + result.includes(true) + // @ts-expect-error + result.includes(false) + // @ts-expect-error result.includes(4) // @ts-expect-error - result.includes(undefined) + result.includes(undefined) // @ts-expect-error result.includes(null) }) From 0e25f599915ff6be8989f29b4b6bfa5fa3fff07e Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 6 Dec 2025 16:37:58 +0200 Subject: [PATCH 36/54] chore@small --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecfdf402..7ffbceb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +11.0.0 + +- Rename `R.innerJoin` to `R.intersectionWith` + +- Add `R.unionWith` + +- Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: + +- R.range + +- R.difference(new method) + 10.3.5 - Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. From 645cbd7d02c9f454f3fcf7e14538b55ab331e149 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Tue, 9 Dec 2025 07:04:14 +0200 Subject: [PATCH 37/54] union.with --- CHANGELOG.md | 2 +- README.md | 382 ++++++++++++------ dist/rambda.cjs | 83 ++-- dist/rambda.js | 82 ++-- dist/rambda.umd.js | 83 ++-- docs/README.md | 382 ++++++++++++------ files/index.d.ts | 29 +- index.d.cts | 18 +- index.d.ts | 18 +- rambda.js | 3 +- source/intersectionWith-spec.ts | 14 + source/{innerJoin.js => intersectionWith.js} | 2 +- ...rJoin.spec.js => intersectionWith.spec.js} | 6 +- source/unionWith-spec.ts | 18 + source/unionWith.js | 11 + source/unionWith.spec.js | 15 + src/{innerJoin.js => intersectionWith.js} | 2 +- src/unionWith.js | 11 + 18 files changed, 782 insertions(+), 379 deletions(-) create mode 100644 source/intersectionWith-spec.ts rename source/{innerJoin.js => intersectionWith.js} (91%) rename source/{innerJoin.spec.js => intersectionWith.spec.js} (79%) create mode 100644 source/unionWith-spec.ts create mode 100644 source/unionWith.js create mode 100644 source/unionWith.spec.js rename src/{innerJoin.js => intersectionWith.js} (91%) create mode 100644 src/unionWith.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ffbceb6..0fcf5227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -11.0.0 +10.4.0 - Rename `R.innerJoin` to `R.intersectionWith` diff --git a/README.md b/README.md index 34587987..b5634747 100644 --- a/README.md +++ b/README.md @@ -5217,130 +5217,6 @@ describe('R.init', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#init) -### innerJoin - -```typescript - -innerJoin( - pred: (a: T1, b: T2) => boolean, - list1: T1[], -): (list2: T2[]) => T1[] -``` - -It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. - -```javascript -const list1 = [1, 2, 3, 4, 5] -const list2 = [4, 5, 6] -const predicate = (x, y) => x >= y -const result = R.innerJoin(predicate, list1)(list2) -// => [4, 5] -``` - -Try this R.innerJoin example in Rambda REPL - -
- -All TypeScript definitions - -```typescript -innerJoin( - pred: (a: T1, b: T2) => boolean, - list1: T1[], -): (list2: T2[]) => T1[]; -``` - -
- -
- -R.innerJoin source - -```javascript -function _includesWith(pred, x, list) { - let idx = 0 - const len = list.length - - while (idx < len) { - if (pred(x, list[idx])) { - return true - } - - idx += 1 - } - - return false -} -function _filter(fn, list) { - let idx = 0 - const len = list.length - const result = [] - - while (idx < len) { - if (fn(list[idx])) { - result[result.length] = list[idx] - } - - idx += 1 - } - - return result -} - -export function innerJoin(pred, xs) { - return ys => _filter(x => _includesWith(pred, x, ys), xs) -} -``` - -
- -
- -Tests - -```javascript -import { innerJoin } from './innerJoin.js' - -const a = { - id: 1, - name: 'a', -} -const b = { - id: 2, - name: 'b', -} -const c = { - id: 3, - name: 'c', -} -const f = (a, b) => innerJoin((r, id) => r.id === id, a)(b) - -test('only returns elements from the first list', () => { - expect(f([a, b, c], [])).toEqual([]) - expect(f([a, b, c], [1])).toEqual([a]) - expect(f([a, b, c], [1, 2])).toEqual([a, b]) - expect(f([a, b, c], [1, 2, 3])).toEqual([a, b, c]) - expect(f([a, b, c], [1, 2, 3, 4])).toEqual([a, b, c]) -}) - -test('does not remove duplicates', () => { - expect(f([a, a, a], [1, 2, 3])).toEqual([a, a, a]) - expect(f([a, b, c], [1, 1, 1])).toEqual([a]) -}) - -test('readme example', () => { - const list1 = [1, 2, 3, 4, 5] - const list2 = [4, 5, 6] - const predicate = (x, y) => x >= y - const result = innerJoin(predicate, list1)(list2) - expect(result).toEqual([4, 5]) -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#innerJoin) - ### interpolate ```typescript @@ -5547,6 +5423,153 @@ describe('R.intersection', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersection) +### intersectionWith + +```typescript + +intersectionWith( + pred: (a: T1, b: T2) => boolean, + list1: T1[], +): (list2: T2[]) => T1[] +``` + +It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. + +```javascript +const list1 = [1, 2, 3, 4, 5] +const list2 = [4, 5, 6] +const predicate = (x, y) => x >= y +const result = R.intersectionWith(predicate, list1)(list2) +// => [4, 5] +``` + +Try this R.intersectionWith example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +intersectionWith( + pred: (a: T1, b: T2) => boolean, + list1: T1[], +): (list2: T2[]) => T1[]; +``` + +
+ +
+ +R.intersectionWith source + +```javascript +function _includesWith(pred, x, list) { + let idx = 0 + const len = list.length + + while (idx < len) { + if (pred(x, list[idx])) { + return true + } + + idx += 1 + } + + return false +} +function _filter(fn, list) { + let idx = 0 + const len = list.length + const result = [] + + while (idx < len) { + if (fn(list[idx])) { + result[result.length] = list[idx] + } + + idx += 1 + } + + return result +} + +export function intersectionWith(pred, xs) { + return ys => _filter(x => _includesWith(pred, x, ys), xs) +} +``` + +
+ +
+ +Tests + +```javascript +import { intersectionWith } from './intersectionWith.js' + +const a = { + id: 1, + name: 'a', +} +const b = { + id: 2, + name: 'b', +} +const c = { + id: 3, + name: 'c', +} +const f = (a, b) => intersectionWith((r, id) => r.id === id, a)(b) + +test('only returns elements from the first list', () => { + expect(f([a, b, c], [])).toEqual([]) + expect(f([a, b, c], [1])).toEqual([a]) + expect(f([a, b, c], [1, 2])).toEqual([a, b]) + expect(f([a, b, c], [1, 2, 3])).toEqual([a, b, c]) + expect(f([a, b, c], [1, 2, 3, 4])).toEqual([a, b, c]) +}) + +test('does not remove duplicates', () => { + expect(f([a, a, a], [1, 2, 3])).toEqual([a, a, a]) + expect(f([a, b, c], [1, 1, 1])).toEqual([a]) +}) + +test('readme example', () => { + const list1 = [1, 2, 3, 4, 5] + const list2 = [4, 5, 6] + const predicate = (x, y) => x >= y + const result = intersectionWith(predicate, list1)(list2) + expect(result).toEqual([4, 5]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { intersectionWith, pipe } from 'rambda' + +const list1 = [1, 2, 3] +const list2 = [1, 3, 5] + +describe('R.intersectionWith', () => { + it('happy', () => { + const result = pipe( + list1, + intersectionWith((x, y) => x === y, list2), + ) + result // $ExpectType number[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersectionWith) + ### intersperse ```typescript @@ -12586,6 +12609,105 @@ describe('R.union', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#union) +### unionWith + +```typescript + +unionWith(predicate: (x: T, y: T) => boolean, x: T[]): (y: T[]) => T[] +``` + +```javascript +const result = R.pipe( + [{a: 1, b: 1}, {a: 2, b: 1}], + R.unionWith((x, y) => x === y, [{a: 2, b: 2}, {a: 3, b: 2}]), +) +// => [{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 2}] +``` + +Try this R.unionWith example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +unionWith(predicate: (x: T, y: T) => boolean, x: T[]): (y: T[]) => T[]; +``` + +
+ +
+ +R.unionWith source + +```javascript +export function unionWith(predicate, x) { + return y => { + const filtered = y.filter(yInstance => { + return x.every(xInstance => { + return !predicate(xInstance, yInstance) + }) + }) + + return [...x, ...filtered] + } +} +``` + +
+ +
+ +Tests + +```javascript +import { unionWith } from './unionWith.js' +import { pipe } from './pipe.js' + +test('happy', () => { + const list1 = [{a: 1, b: 1}, {a: 2, b: 1}] + const list2 = [{a: 2, b: 2}, {a: 3, b: 2}] + const result = pipe( + list2, + unionWith((x, y) => { + return x.a === y.a + }, list1), + ) + expect(result).toEqual([{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 2}]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { pipe, unionWith } from 'rambda' + +describe('R.unionWith', () => { + it('happy', () => { + const list = [{a: 1, b: 1}, {a: 2, b: 1}] + const result = pipe( + list, + unionWith((x, y) => { + x.a // $ExpectType number + y.b // $ExpectType number + return x.a === y.a + }, [{a: 2, b: 2}, {a: 3, b: 2}]), + ) + + result[0].a // $ExpectType number + result[0].b // $ExpectType number + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#unionWith) + ### uniq ```typescript @@ -13618,6 +13740,18 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +10.4.0 + +- Rename `R.innerJoin` to `R.intersectionWith` + +- Add `R.unionWith` + +- Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: + +- R.range + +- R.difference(new method) + 10.3.5 - Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 1cf98995..825a69ab 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -907,40 +907,6 @@ function init(input) { return input.length ? baseSlice(input, 0, -1) : [] } -function _includesWith(pred, x, list) { - let idx = 0; - const len = list.length; - - while (idx < len) { - if (pred(x, list[idx])) { - return true - } - - idx += 1; - } - - return false -} -function _filter(fn, list) { - let idx = 0; - const len = list.length; - const result = []; - - while (idx < len) { - if (fn(list[idx])) { - result[result.length] = list[idx]; - } - - idx += 1; - } - - return result -} - -function innerJoin(pred, xs) { - return ys => _filter(x => _includesWith(pred, x, ys), xs) -} - const getOccurrences = input => input.match(/{{\s*.+?\s*}}/g); const getOccurrenceProp = occurrence => occurrence.replace(/{{\s*|\s*}}/g, ''); @@ -975,6 +941,40 @@ function intersection(listA) { return listB => filter(x => includes(x)(listA))(listB) } +function _includesWith(pred, x, list) { + let idx = 0; + const len = list.length; + + while (idx < len) { + if (pred(x, list[idx])) { + return true + } + + idx += 1; + } + + return false +} +function _filter(fn, list) { + let idx = 0; + const len = list.length; + const result = []; + + while (idx < len) { + if (fn(list[idx])) { + result[result.length] = list[idx]; + } + + idx += 1; + } + + return result +} + +function intersectionWith(pred, xs) { + return ys => _filter(x => _includesWith(pred, x, ys), xs) +} + function intersperse(separator) { return list => { let index = -1; @@ -1785,6 +1785,18 @@ function union(x) { } } +function unionWith(predicate, x) { + return y => { + const filtered = y.filter(yInstance => { + return x.every(xInstance => { + return !predicate(xInstance, yInstance) + }) + }); + + return [...x, ...filtered] + } +} + function uniq(list) { const set = new _Set(); const willReturn = []; @@ -1940,9 +1952,9 @@ exports.includes = includes; exports.indexBy = indexBy; exports.indexOf = indexOf; exports.init = init; -exports.innerJoin = innerJoin; exports.interpolate = interpolate; exports.intersection = intersection; +exports.intersectionWith = intersectionWith; exports.intersperse = intersperse; exports.join = join; exports.last = last; @@ -2010,6 +2022,7 @@ exports.transformFlatObject = transformFlatObject; exports.tryCatch = tryCatch; exports.type = type; exports.union = union; +exports.unionWith = unionWith; exports.uniq = uniq; exports.uniqBy = uniqBy; exports.uniqWith = uniqWith; diff --git a/dist/rambda.js b/dist/rambda.js index cb7bccb9..76dcce64 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -905,40 +905,6 @@ function init(input) { return input.length ? baseSlice(input, 0, -1) : [] } -function _includesWith(pred, x, list) { - let idx = 0; - const len = list.length; - - while (idx < len) { - if (pred(x, list[idx])) { - return true - } - - idx += 1; - } - - return false -} -function _filter(fn, list) { - let idx = 0; - const len = list.length; - const result = []; - - while (idx < len) { - if (fn(list[idx])) { - result[result.length] = list[idx]; - } - - idx += 1; - } - - return result -} - -function innerJoin(pred, xs) { - return ys => _filter(x => _includesWith(pred, x, ys), xs) -} - const getOccurrences = input => input.match(/{{\s*.+?\s*}}/g); const getOccurrenceProp = occurrence => occurrence.replace(/{{\s*|\s*}}/g, ''); @@ -973,6 +939,40 @@ function intersection(listA) { return listB => filter(x => includes(x)(listA))(listB) } +function _includesWith(pred, x, list) { + let idx = 0; + const len = list.length; + + while (idx < len) { + if (pred(x, list[idx])) { + return true + } + + idx += 1; + } + + return false +} +function _filter(fn, list) { + let idx = 0; + const len = list.length; + const result = []; + + while (idx < len) { + if (fn(list[idx])) { + result[result.length] = list[idx]; + } + + idx += 1; + } + + return result +} + +function intersectionWith(pred, xs) { + return ys => _filter(x => _includesWith(pred, x, ys), xs) +} + function intersperse(separator) { return list => { let index = -1; @@ -1783,6 +1783,18 @@ function union(x) { } } +function unionWith(predicate, x) { + return y => { + const filtered = y.filter(yInstance => { + return x.every(xInstance => { + return !predicate(xInstance, yInstance) + }) + }); + + return [...x, ...filtered] + } +} + function uniq(list) { const set = new _Set(); const willReturn = []; @@ -1884,4 +1896,4 @@ function zipWith(fn, x) { ) } -export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, innerJoin, interpolate, intersection, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; +export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index 777dc450..d7797a54 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -911,40 +911,6 @@ return input.length ? baseSlice(input, 0, -1) : [] } - function _includesWith(pred, x, list) { - let idx = 0; - const len = list.length; - - while (idx < len) { - if (pred(x, list[idx])) { - return true - } - - idx += 1; - } - - return false - } - function _filter(fn, list) { - let idx = 0; - const len = list.length; - const result = []; - - while (idx < len) { - if (fn(list[idx])) { - result[result.length] = list[idx]; - } - - idx += 1; - } - - return result - } - - function innerJoin(pred, xs) { - return ys => _filter(x => _includesWith(pred, x, ys), xs) - } - const getOccurrences = input => input.match(/{{\s*.+?\s*}}/g); const getOccurrenceProp = occurrence => occurrence.replace(/{{\s*|\s*}}/g, ''); @@ -979,6 +945,40 @@ return listB => filter(x => includes(x)(listA))(listB) } + function _includesWith(pred, x, list) { + let idx = 0; + const len = list.length; + + while (idx < len) { + if (pred(x, list[idx])) { + return true + } + + idx += 1; + } + + return false + } + function _filter(fn, list) { + let idx = 0; + const len = list.length; + const result = []; + + while (idx < len) { + if (fn(list[idx])) { + result[result.length] = list[idx]; + } + + idx += 1; + } + + return result + } + + function intersectionWith(pred, xs) { + return ys => _filter(x => _includesWith(pred, x, ys), xs) + } + function intersperse(separator) { return list => { let index = -1; @@ -1789,6 +1789,18 @@ } } + function unionWith(predicate, x) { + return y => { + const filtered = y.filter(yInstance => { + return x.every(xInstance => { + return !predicate(xInstance, yInstance) + }) + }); + + return [...x, ...filtered] + } + } + function uniq(list) { const set = new _Set(); const willReturn = []; @@ -1944,9 +1956,9 @@ exports.indexBy = indexBy; exports.indexOf = indexOf; exports.init = init; - exports.innerJoin = innerJoin; exports.interpolate = interpolate; exports.intersection = intersection; + exports.intersectionWith = intersectionWith; exports.intersperse = intersperse; exports.join = join; exports.last = last; @@ -2014,6 +2026,7 @@ exports.tryCatch = tryCatch; exports.type = type; exports.union = union; + exports.unionWith = unionWith; exports.uniq = uniq; exports.uniqBy = uniqBy; exports.uniqWith = uniqWith; diff --git a/docs/README.md b/docs/README.md index 34587987..b5634747 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5217,130 +5217,6 @@ describe('R.init', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#init) -### innerJoin - -```typescript - -innerJoin( - pred: (a: T1, b: T2) => boolean, - list1: T1[], -): (list2: T2[]) => T1[] -``` - -It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. - -```javascript -const list1 = [1, 2, 3, 4, 5] -const list2 = [4, 5, 6] -const predicate = (x, y) => x >= y -const result = R.innerJoin(predicate, list1)(list2) -// => [4, 5] -``` - -Try this R.innerJoin example in Rambda REPL - -
- -All TypeScript definitions - -```typescript -innerJoin( - pred: (a: T1, b: T2) => boolean, - list1: T1[], -): (list2: T2[]) => T1[]; -``` - -
- -
- -R.innerJoin source - -```javascript -function _includesWith(pred, x, list) { - let idx = 0 - const len = list.length - - while (idx < len) { - if (pred(x, list[idx])) { - return true - } - - idx += 1 - } - - return false -} -function _filter(fn, list) { - let idx = 0 - const len = list.length - const result = [] - - while (idx < len) { - if (fn(list[idx])) { - result[result.length] = list[idx] - } - - idx += 1 - } - - return result -} - -export function innerJoin(pred, xs) { - return ys => _filter(x => _includesWith(pred, x, ys), xs) -} -``` - -
- -
- -Tests - -```javascript -import { innerJoin } from './innerJoin.js' - -const a = { - id: 1, - name: 'a', -} -const b = { - id: 2, - name: 'b', -} -const c = { - id: 3, - name: 'c', -} -const f = (a, b) => innerJoin((r, id) => r.id === id, a)(b) - -test('only returns elements from the first list', () => { - expect(f([a, b, c], [])).toEqual([]) - expect(f([a, b, c], [1])).toEqual([a]) - expect(f([a, b, c], [1, 2])).toEqual([a, b]) - expect(f([a, b, c], [1, 2, 3])).toEqual([a, b, c]) - expect(f([a, b, c], [1, 2, 3, 4])).toEqual([a, b, c]) -}) - -test('does not remove duplicates', () => { - expect(f([a, a, a], [1, 2, 3])).toEqual([a, a, a]) - expect(f([a, b, c], [1, 1, 1])).toEqual([a]) -}) - -test('readme example', () => { - const list1 = [1, 2, 3, 4, 5] - const list2 = [4, 5, 6] - const predicate = (x, y) => x >= y - const result = innerJoin(predicate, list1)(list2) - expect(result).toEqual([4, 5]) -}) -``` - -
- -[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#innerJoin) - ### interpolate ```typescript @@ -5547,6 +5423,153 @@ describe('R.intersection', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersection) +### intersectionWith + +```typescript + +intersectionWith( + pred: (a: T1, b: T2) => boolean, + list1: T1[], +): (list2: T2[]) => T1[] +``` + +It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. + +```javascript +const list1 = [1, 2, 3, 4, 5] +const list2 = [4, 5, 6] +const predicate = (x, y) => x >= y +const result = R.intersectionWith(predicate, list1)(list2) +// => [4, 5] +``` + +Try this R.intersectionWith example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +intersectionWith( + pred: (a: T1, b: T2) => boolean, + list1: T1[], +): (list2: T2[]) => T1[]; +``` + +
+ +
+ +R.intersectionWith source + +```javascript +function _includesWith(pred, x, list) { + let idx = 0 + const len = list.length + + while (idx < len) { + if (pred(x, list[idx])) { + return true + } + + idx += 1 + } + + return false +} +function _filter(fn, list) { + let idx = 0 + const len = list.length + const result = [] + + while (idx < len) { + if (fn(list[idx])) { + result[result.length] = list[idx] + } + + idx += 1 + } + + return result +} + +export function intersectionWith(pred, xs) { + return ys => _filter(x => _includesWith(pred, x, ys), xs) +} +``` + +
+ +
+ +Tests + +```javascript +import { intersectionWith } from './intersectionWith.js' + +const a = { + id: 1, + name: 'a', +} +const b = { + id: 2, + name: 'b', +} +const c = { + id: 3, + name: 'c', +} +const f = (a, b) => intersectionWith((r, id) => r.id === id, a)(b) + +test('only returns elements from the first list', () => { + expect(f([a, b, c], [])).toEqual([]) + expect(f([a, b, c], [1])).toEqual([a]) + expect(f([a, b, c], [1, 2])).toEqual([a, b]) + expect(f([a, b, c], [1, 2, 3])).toEqual([a, b, c]) + expect(f([a, b, c], [1, 2, 3, 4])).toEqual([a, b, c]) +}) + +test('does not remove duplicates', () => { + expect(f([a, a, a], [1, 2, 3])).toEqual([a, a, a]) + expect(f([a, b, c], [1, 1, 1])).toEqual([a]) +}) + +test('readme example', () => { + const list1 = [1, 2, 3, 4, 5] + const list2 = [4, 5, 6] + const predicate = (x, y) => x >= y + const result = intersectionWith(predicate, list1)(list2) + expect(result).toEqual([4, 5]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { intersectionWith, pipe } from 'rambda' + +const list1 = [1, 2, 3] +const list2 = [1, 3, 5] + +describe('R.intersectionWith', () => { + it('happy', () => { + const result = pipe( + list1, + intersectionWith((x, y) => x === y, list2), + ) + result // $ExpectType number[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersectionWith) + ### intersperse ```typescript @@ -12586,6 +12609,105 @@ describe('R.union', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#union) +### unionWith + +```typescript + +unionWith(predicate: (x: T, y: T) => boolean, x: T[]): (y: T[]) => T[] +``` + +```javascript +const result = R.pipe( + [{a: 1, b: 1}, {a: 2, b: 1}], + R.unionWith((x, y) => x === y, [{a: 2, b: 2}, {a: 3, b: 2}]), +) +// => [{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 2}] +``` + +Try this R.unionWith example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +unionWith(predicate: (x: T, y: T) => boolean, x: T[]): (y: T[]) => T[]; +``` + +
+ +
+ +R.unionWith source + +```javascript +export function unionWith(predicate, x) { + return y => { + const filtered = y.filter(yInstance => { + return x.every(xInstance => { + return !predicate(xInstance, yInstance) + }) + }) + + return [...x, ...filtered] + } +} +``` + +
+ +
+ +Tests + +```javascript +import { unionWith } from './unionWith.js' +import { pipe } from './pipe.js' + +test('happy', () => { + const list1 = [{a: 1, b: 1}, {a: 2, b: 1}] + const list2 = [{a: 2, b: 2}, {a: 3, b: 2}] + const result = pipe( + list2, + unionWith((x, y) => { + return x.a === y.a + }, list1), + ) + expect(result).toEqual([{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 2}]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { pipe, unionWith } from 'rambda' + +describe('R.unionWith', () => { + it('happy', () => { + const list = [{a: 1, b: 1}, {a: 2, b: 1}] + const result = pipe( + list, + unionWith((x, y) => { + x.a // $ExpectType number + y.b // $ExpectType number + return x.a === y.a + }, [{a: 2, b: 2}, {a: 3, b: 2}]), + ) + + result[0].a // $ExpectType number + result[0].b // $ExpectType number + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#unionWith) + ### uniq ```typescript @@ -13618,6 +13740,18 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +10.4.0 + +- Rename `R.innerJoin` to `R.intersectionWith` + +- Add `R.unionWith` + +- Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: + +- R.range + +- R.difference(new method) + 10.3.5 - Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. diff --git a/files/index.d.ts b/files/index.d.ts index 920f3437..df73488c 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -3241,6 +3241,29 @@ Notes: // @SINGLE_MARKER export function union(x: T[]): (y: T[]) => T[]; +/* +Method: unionWith + +Explanation: + +Example: + +``` +const result = R.pipe( + [{a: 1, b: 1}, {a: 2, b: 1}], + R.unionWith((x, y) => x === y, [{a: 2, b: 2}, {a: 3, b: 2}]), +) +// => [{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 2}] +``` + +Categories: List + +Notes: + +*/ +// @SINGLE_MARKER +export function unionWith(predicate: (x: T, y: T) => boolean, x: T[]): (y: T[]) => T[]; + /* Method: uniq @@ -3807,7 +3830,7 @@ Notes: export function eqBy(fn: (x: T) => unknown, a: T): (b: T) => boolean; /* -Method: innerJoin +Method: intersectionWith Explanation: It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. @@ -3817,7 +3840,7 @@ Example: const list1 = [1, 2, 3, 4, 5] const list2 = [4, 5, 6] const predicate = (x, y) => x >= y -const result = R.innerJoin(predicate, list1)(list2) +const result = R.intersectionWith(predicate, list1)(list2) // => [4, 5] ``` @@ -3827,7 +3850,7 @@ Notes: */ // @SINGLE_MARKER -export function innerJoin( +export function intersectionWith( pred: (a: T1, b: T2) => boolean, list1: T1[], ): (list2: T2[]) => T1[]; diff --git a/index.d.cts b/index.d.cts index d16d2250..fa53063b 100644 --- a/index.d.cts +++ b/index.d.cts @@ -457,14 +457,6 @@ export function indexOf(valueToFind: T): (list: T[]) => number; export function init(input: T): T extends readonly [...infer U, any] ? U : [...T]; export function init(input: string): string; -/** - * It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. - */ -export function innerJoin( - pred: (a: T1, b: T2) => boolean, - list1: T1[], -): (list2: T2[]) => T1[]; - /** * It generates a new string from `inputWithTags` by replacing all `{{x}}` occurrences with values provided by `templateArguments`. */ @@ -475,6 +467,14 @@ export function interpolate(inputWithTags: string): (templateArguments: object) */ export function intersection(listA: T[]): (listB: T[]) => T[]; +/** + * It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. + */ +export function intersectionWith( + pred: (a: T1, b: T2) => boolean, + list1: T1[], +): (list2: T2[]) => T1[]; + /** * It adds a `separator` between members of `list`. */ @@ -2264,6 +2264,8 @@ export function type(x: any): RambdaTypes; */ export function union(x: T[]): (y: T[]) => T[]; +export function unionWith(predicate: (x: T, y: T) => boolean, x: T[]): (y: T[]) => T[]; + /** * It returns a new array containing only one copy of each element of `list`. * diff --git a/index.d.ts b/index.d.ts index d16d2250..fa53063b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -457,14 +457,6 @@ export function indexOf(valueToFind: T): (list: T[]) => number; export function init(input: T): T extends readonly [...infer U, any] ? U : [...T]; export function init(input: string): string; -/** - * It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. - */ -export function innerJoin( - pred: (a: T1, b: T2) => boolean, - list1: T1[], -): (list2: T2[]) => T1[]; - /** * It generates a new string from `inputWithTags` by replacing all `{{x}}` occurrences with values provided by `templateArguments`. */ @@ -475,6 +467,14 @@ export function interpolate(inputWithTags: string): (templateArguments: object) */ export function intersection(listA: T[]): (listB: T[]) => T[]; +/** + * It returns a new list by applying a `predicate` function to all elements of `list1` and `list2` and keeping only these elements where `predicate` returns `true`. + */ +export function intersectionWith( + pred: (a: T1, b: T2) => boolean, + list1: T1[], +): (list2: T2[]) => T1[]; + /** * It adds a `separator` between members of `list`. */ @@ -2264,6 +2264,8 @@ export function type(x: any): RambdaTypes; */ export function union(x: T[]): (y: T[]) => T[]; +export function unionWith(predicate: (x: T, y: T) => boolean, x: T[]): (y: T[]) => T[]; + /** * It returns a new array containing only one copy of each element of `list`. * diff --git a/rambda.js b/rambda.js index 7fb71999..e6b6623e 100644 --- a/rambda.js +++ b/rambda.js @@ -45,9 +45,9 @@ export * from './src/includes.js' export * from './src/indexBy.js' export * from './src/indexOf.js' export * from './src/init.js' -export * from './src/innerJoin.js' export * from './src/interpolate.js' export * from './src/intersection.js' +export * from './src/intersectionWith.js' export * from './src/intersperse.js' export * from './src/join.js' export * from './src/last.js' @@ -112,6 +112,7 @@ export * from './src/test.js' export * from './src/tryCatch.js' export * from './src/type.js' export * from './src/union.js' +export * from './src/unionWith.js' export * from './src/uniq.js' export * from './src/uniqBy.js' export * from './src/uniqWith.js' diff --git a/source/intersectionWith-spec.ts b/source/intersectionWith-spec.ts new file mode 100644 index 00000000..4da78417 --- /dev/null +++ b/source/intersectionWith-spec.ts @@ -0,0 +1,14 @@ +import { intersectionWith, pipe } from 'rambda' + +const list1 = [1, 2, 3] +const list2 = [1, 3, 5] + +describe('R.intersectionWith', () => { + it('happy', () => { + const result = pipe( + list1, + intersectionWith((x, y) => x === y, list2), + ) + result // $ExpectType number[] + }) +}) diff --git a/source/innerJoin.js b/source/intersectionWith.js similarity index 91% rename from source/innerJoin.js rename to source/intersectionWith.js index f2ec51aa..60f426f0 100644 --- a/source/innerJoin.js +++ b/source/intersectionWith.js @@ -28,6 +28,6 @@ function _filter(fn, list) { return result } -export function innerJoin(pred, xs) { +export function intersectionWith(pred, xs) { return ys => _filter(x => _includesWith(pred, x, ys), xs) } diff --git a/source/innerJoin.spec.js b/source/intersectionWith.spec.js similarity index 79% rename from source/innerJoin.spec.js rename to source/intersectionWith.spec.js index 637f0d56..65b460aa 100644 --- a/source/innerJoin.spec.js +++ b/source/intersectionWith.spec.js @@ -1,4 +1,4 @@ -import { innerJoin } from './innerJoin.js' +import { intersectionWith } from './intersectionWith.js' const a = { id: 1, @@ -12,7 +12,7 @@ const c = { id: 3, name: 'c', } -const f = (a, b) => innerJoin((r, id) => r.id === id, a)(b) +const f = (a, b) => intersectionWith((r, id) => r.id === id, a)(b) test('only returns elements from the first list', () => { expect(f([a, b, c], [])).toEqual([]) @@ -31,6 +31,6 @@ test('readme example', () => { const list1 = [1, 2, 3, 4, 5] const list2 = [4, 5, 6] const predicate = (x, y) => x >= y - const result = innerJoin(predicate, list1)(list2) + const result = intersectionWith(predicate, list1)(list2) expect(result).toEqual([4, 5]) }) diff --git a/source/unionWith-spec.ts b/source/unionWith-spec.ts new file mode 100644 index 00000000..a5c4e72c --- /dev/null +++ b/source/unionWith-spec.ts @@ -0,0 +1,18 @@ +import { pipe, unionWith } from 'rambda' + +describe('R.unionWith', () => { + it('happy', () => { + const list = [{a: 1, b: 1}, {a: 2, b: 1}] + const result = pipe( + list, + unionWith((x, y) => { + x.a // $ExpectType number + y.b // $ExpectType number + return x.a === y.a + }, [{a: 2, b: 2}, {a: 3, b: 2}]), + ) + + result[0].a // $ExpectType number + result[0].b // $ExpectType number + }) +}) diff --git a/source/unionWith.js b/source/unionWith.js new file mode 100644 index 00000000..66b11186 --- /dev/null +++ b/source/unionWith.js @@ -0,0 +1,11 @@ +export function unionWith(predicate, x) { + return y => { + const filtered = y.filter(yInstance => { + return x.every(xInstance => { + return !predicate(xInstance, yInstance) + }) + }) + + return [...x, ...filtered] + } +} diff --git a/source/unionWith.spec.js b/source/unionWith.spec.js new file mode 100644 index 00000000..c8baaa05 --- /dev/null +++ b/source/unionWith.spec.js @@ -0,0 +1,15 @@ +import { unionWith } from './unionWith.js' +import { pipe } from './pipe.js' + +test('happy', () => { + const list1 = [{a: 1, b: 1}, {a: 2, b: 1}] + const list2 = [{a: 2, b: 2}, {a: 3, b: 2}] + const result = pipe( + list2, + unionWith((x, y) => { + return x.a === y.a + }, list1), + ) + expect(result).toEqual([{a: 1, b: 1}, {a: 2, b: 1}, {a: 3, b: 2}]) +}) + diff --git a/src/innerJoin.js b/src/intersectionWith.js similarity index 91% rename from src/innerJoin.js rename to src/intersectionWith.js index f2ec51aa..60f426f0 100644 --- a/src/innerJoin.js +++ b/src/intersectionWith.js @@ -28,6 +28,6 @@ function _filter(fn, list) { return result } -export function innerJoin(pred, xs) { +export function intersectionWith(pred, xs) { return ys => _filter(x => _includesWith(pred, x, ys), xs) } diff --git a/src/unionWith.js b/src/unionWith.js new file mode 100644 index 00000000..66b11186 --- /dev/null +++ b/src/unionWith.js @@ -0,0 +1,11 @@ +export function unionWith(predicate, x) { + return y => { + const filtered = y.filter(yInstance => { + return x.every(xInstance => { + return !predicate(xInstance, yInstance) + }) + }) + + return [...x, ...filtered] + } +} From 001a3b9f052097c33939627e208176ad96b27c0b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sat, 20 Dec 2025 20:22:44 +0200 Subject: [PATCH 38/54] chore@small --- CHANGELOG.md | 16 +- README.md | 286 ++++++++++++++++++++++++++------- dist/rambda.cjs | 186 ++++++++++----------- dist/rambda.js | 186 ++++++++++----------- dist/rambda.umd.js | 186 ++++++++++----------- docs/README.md | 286 ++++++++++++++++++++++++++------- files/index.d.ts | 97 +++++++++-- index.d.cts | 29 ++-- index.d.ts | 29 ++-- rambda.js | 2 + source/difference-spec.ts | 11 ++ source/difference.js | 9 ++ source/difference.spec.js | 19 +++ source/exists-spec.ts | 11 ++ source/exists.js | 7 + source/filter-spec.ts | 44 +++-- source/range.js | 25 +-- source/rangeDescending.js | 11 ++ source/rangeDescending.spec.js | 7 + src/difference.js | 9 ++ src/range.js | 25 +-- src/rangeDescending.js | 11 ++ 22 files changed, 1009 insertions(+), 483 deletions(-) create mode 100644 source/difference-spec.ts create mode 100644 source/difference.js create mode 100644 source/difference.spec.js create mode 100644 source/exists-spec.ts create mode 100644 source/exists.js create mode 100644 source/rangeDescending.js create mode 100644 source/rangeDescending.spec.js create mode 100644 src/difference.js create mode 100644 src/rangeDescending.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fcf5227..ee05687e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,24 @@ -10.4.0 +11.0.0 + +- Breaking change: `R.includes` and `R.excludes` now accept list as first argument and value to search as second argument. This makes it more useful when used with `R.filter` and `R.reject`. - Rename `R.innerJoin` to `R.intersectionWith` - Add `R.unionWith` +- Add `R.exists` + +- Add `R.symmetricDifference` + +- Add `R.rangeDescending` as now `R.range` works only in ascending order. + +- `R.range` now works similar to Ruby's `Range` - both start and end values are inclusive. + - Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: -- R.range +- R.range - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. + +- R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. - R.difference(new method) diff --git a/README.md b/README.md index b5634747..4df2e980 100644 --- a/README.md +++ b/README.md @@ -1989,6 +1989,105 @@ export function descend(getFunction) { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#descend) +### difference + +```typescript + +difference(x: T[]): (y: T[]) => T[] +``` + +It returns a merged list of `x` and `y` with all equal elements removed. + +`R.equals` is used to determine equality. + +```javascript +const x = [ 1, 2, 3, 4 ] +const y = [ 3, 4, 5, 6 ] + +const result = R.difference(x)(y) +// => [ 1, 2, 5, 6 ] +``` + +Try this R.difference example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +difference(x: T[]): (y: T[]) => T[]; +``` + +
+ +
+ +R.difference source + +```javascript +import { filter } from './filter.js' +import { includes } from './includes.js' + +export function difference(x, y) { + return [ + ...filter(value => !includes(value)(y))(x), + ...filter(value => !includes(value)(x))(y), + ] +} +``` + +
+ +
+ +Tests + +```javascript +import { difference } from './difference.js' + +test('difference', () => { + const list1 = [1, 2, 3, 4] + const list2 = [3, 4, 5, 6] + expect(difference(list1)(list2)).toEqual([1, 2, 5, 6]) + expect(difference([])([])).toEqual([]) +}) + +test('difference with objects', () => { + const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }] + const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }] + expect(difference(list1)(list2)).toEqual([ + { id: 1 }, + { id: 2 }, + { id: 5 }, + { id: 6 }, + ]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { difference } from 'rambda' + +describe('R.difference', () => { + it('happy', () => { + const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }] + const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }] + const result = difference(list1)(list2) + + result // $ExpectType { id: number; }[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#difference) + ### drop ```typescript @@ -3213,7 +3312,7 @@ it('R.evolve', () => { ```typescript -excludes(valueToFind: T): (input: string) => boolean +excludes(list: readonly string[] | string): (substringToFind: string) => boolean ``` Opposite of `R.includes` @@ -3222,21 +3321,21 @@ Opposite of `R.includes` ```javascript const result = [ - R.excludes('ar')('foo'), - R.excludes({a: 2})([{a: 1}]) + R.excludes('foo')('ar'), + R.excludes([{a: 1}])({a: 2}) ] // => [true, true ] ``` -Try this R.excludes example in Rambda REPL +Try this R.excludes example in Rambda REPL
All TypeScript definitions ```typescript -excludes(valueToFind: T): (input: string) => boolean; -excludes(valueToFind: T): (input: T[]) => boolean; +excludes(list: readonly string[] | string): (substringToFind: string) => boolean; +excludes(list: readonly T[]): (target: T) => boolean; ```
@@ -3400,22 +3499,46 @@ test('using Boolean', () => { TypeScript test ```typescript -import { filter, pipe } from 'rambda' +import { filter, includes, pipe, reject, sort, split, uniq } from 'rambda' const list = [1, 2, 3] describe('R.filter with array', () => { it('within pipe', () => { - const result = pipe( + const _result = pipe( list, - filter((x) => { + filter(x => { x // $ExpectType number return x > 1 }), ) - result // $ExpectType number[] + _result // $ExpectType number[] }) + it('complex example', () => { + const text = `Dies ist ein einfacher Beispielsatz. Il fait beau aujourd'hui!` + const language = 'de' + const SENTENCE_END_CHARS = ['.', '!', '?', '।', '؟'] + const result = pipe( + text, + split(''), + uniq, + filter(char => { + if (language === 'de') { + return /[A-Za-zäßüöÜÖÄ]/g.test(char) === false + } + if (language === 'fr') { + return /[A-Za-zÀÉàâçèéêîïôùû']/g.test(char) === false + } + throw new Error(`Language ${language} not supported`) + }), + sort((a, b) => (a === b ? 0 : a > b ? 1 : -1)), + filter(char => char.trim().length > 0), + reject(includes(SENTENCE_END_CHARS)), + ) + + result // $ExpectType string[] + }) it('narrowing type', () => { interface Foo { a: number @@ -3428,8 +3551,8 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe(testList, filter(filterBar)) - result // $ExpectType Bar[] + const _result = pipe(testList, filter(filterBar)) + _result // $ExpectType Bar[] }) it('narrowing type - readonly', () => { @@ -3444,14 +3567,14 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe(testList, filter(filterBar)) - result // $ExpectType Bar[] + const _result = pipe(testList, filter(filterBar)) + _result // $ExpectType Bar[] }) it('filtering NonNullable - list of objects', () => { const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] - const result = pipe(testList, filter(Boolean)) - result // $ExpectType { a: number; }[] + const _result = pipe(testList, filter(Boolean)) + _result // $ExpectType { a: number; }[] }) it('filtering NonNullable - readonly', () => { @@ -4782,7 +4905,7 @@ describe('R.head', () => { ```typescript -includes(s: string): (list: readonly string[] | string) => boolean +includes(list: readonly string[] | string): (substringToFind: string) => boolean ``` If `input` is string, then this method work as native `String.includes`. @@ -4791,21 +4914,21 @@ If `input` is array, then `R.equals` is used to define if `valueToFind` belongs ```javascript const result = [ - R.includes('oo')('foo'), - R.includes({a: 1})([{a: 1}]) + R.includes('foo')('oo'), + R.includes([{a: 1}])({a: 1}) ] // => [true, true ] ``` -Try this R.includes example in Rambda REPL +Try this R.includes example in Rambda REPL
All TypeScript definitions ```typescript -includes(s: string): (list: readonly string[] | string) => boolean; -includes(target: T): (list: readonly T[]) => boolean; +includes(list: readonly string[] | string): (substringToFind: string) => boolean; +includes(list: readonly T[]): (target: T) => boolean; ```
@@ -5334,8 +5457,6 @@ intersection(listA: T[]): (listB: T[]) => T[] It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. -> :boom: There is slight difference between Rambda and Ramda implementation. Ramda.intersection(['a', 'b', 'c'], ['c', 'b']) result is "[ 'c', 'b' ]", but Rambda result is "[ 'b', 'c' ]". - ```javascript const listA = [ { id : 1 }, { id : 2 }, { id : 3 }, { id : 4 } ] const listB = [ { id : 3 }, { id : 4 }, { id : 5 }, { id : 6 } ] @@ -9658,25 +9779,24 @@ describe('R.propSatisfies', () => { ```typescript -range(startInclusive: number): (endExclusive: number) => number[] +range(startInclusive: number, endInclusive: number) : number[] ``` -It returns list of numbers between `startInclusive` to `endExclusive` markers. -If `start` is greater than `end`, then the result will be in descending order. +It returns list of numbers between `startInclusive` to `endInclusive` markers. ```javascript -[R.range(0)(5), R.range(5)(0)] -// => [[0, 1, 2, 3, 4], [5, 4, 3, 2, 1]] +[R.range(5), R.range(1, 5)] +// => [[0, 1, 2, 3, 4, 5], [1, 2, 3, 4, 5]] ``` -Try this R.range example in Rambda REPL +Try this R.range example in Rambda REPL
All TypeScript definitions ```typescript -range(startInclusive: number): (endExclusive: number) => number[]; +range(startInclusive: number, endInclusive: number) : number[]; ```
@@ -9686,37 +9806,18 @@ range(startInclusive: number): (endExclusive: number) => number[]; R.range source ```javascript -function rangeDescending(start, end) { - const len = start - end - const willReturn = Array(len) - - for (let i = 0; i < len; i++) { - willReturn[i] = start - i - } - - return willReturn -} - -export function range(start) { - return end => { - if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) { - throw new TypeError('Both arguments to range must be numbers') - } - +export function range(start, end) { if (end === start) { return [] } - if (end < start) return rangeDescending(start,end) - - const len = end - start + const len = start - (end ?? 0) const willReturn = Array(len) - for (let i = 0; i < len; i++) { + for (let i = 0; i <= len; i++) { willReturn[i] = start + i } return willReturn - } } ``` @@ -9758,6 +9859,63 @@ describe('R.range', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#range) +### rangeDescending + +```typescript + +rangeDescending(startInclusive: number, endInclusive: number) : number[] +``` + +It returns list of numbers between `endInclusive` to `startInclusive` markers. + +
+ +All TypeScript definitions + +```typescript +rangeDescending(startInclusive: number, endInclusive: number) : number[]; +``` + +
+ +
+ +R.rangeDescending source + +```javascript +export function rangeDescending(start, end) { + const len = start - (end ?? 0) + if(!(len >0)) return [] + const willReturn = Array(len) + + for (let i = 0; i <= len; i++) { + willReturn[i] = start - i + } + + return willReturn +} +``` + +
+ +
+ +Tests + +```javascript +import { rangeDescending } from './rangeDescending.js' + +test('happy', () => { + expect(rangeDescending(5)).toEqual([5, 4, 3, 2, 1, 0]) + expect(rangeDescending(7,3)).toEqual([7, 6, 5, 4,3]) + expect(rangeDescending(5, 5)).toEqual([]) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#rangeDescending) + ### reduce ```typescript @@ -11363,10 +11521,10 @@ describe('R.splitEvery', () => { ```typescript -symmetricDifference(x: T[]): (y: T[]) => T[] +symmetricDifference(list: T[]): (list: T[]) => T[] ``` -It returns a merged list of `x` and `y` with all equal elements removed. +It returns all items that are in either of the lists, but not in both. `R.equals` is used to determine equality. @@ -11385,7 +11543,7 @@ const result = R.symmetricDifference(x)(y) All TypeScript definitions ```typescript -symmetricDifference(x: T[]): (y: T[]) => T[]; +symmetricDifference(list: T[]): (list: T[]) => T[]; ```
@@ -13740,15 +13898,27 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -10.4.0 +11.0.0 + +- Breaking change: `R.includes` and `R.excludes` now accept list as first argument and value to search as second argument. This makes it more useful when used with `R.filter` and `R.reject`. - Rename `R.innerJoin` to `R.intersectionWith` - Add `R.unionWith` +- Add `R.exists` + +- Add `R.symmetricDifference` + +- Add `R.rangeDescending` as now `R.range` works only in ascending order. + +- `R.range` now works similar to Ruby's `Range` - both start and end values are inclusive. + - Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: -- R.range +- R.range - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. + +- R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. - R.difference(new method) diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 825a69ab..2edac945 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -258,60 +258,6 @@ function descend(getFunction) { } } -function drop(howManyToDrop, ) { - return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) -} - -function dropLast(numberItems) { - return list => (numberItems > 0 ? list.slice(0, -numberItems) : list.slice()) -} - -function dropLastWhile(predicate) { - return list => { - if (list.length === 0) { - return list - } - - const toReturn = []; - let counter = list.length; - - while (counter) { - const item = list[--counter]; - if (!predicate(item, counter)) { - toReturn.push(item); - break - } - } - - while (counter) { - toReturn.push(list[--counter]); - } - - return toReturn.reverse() - } -} - -function dropWhile(predicate) { - return iterable => { - const toReturn = []; - let counter = 0; - - while (counter < iterable.length) { - const item = iterable[counter++]; - if (!predicate(item, counter)) { - toReturn.push(item); - break - } - } - - while (counter < iterable.length) { - toReturn.push(iterable[counter++]); - } - - return toReturn - } -} - function type(input) { if (input === null) { return 'Null' @@ -535,6 +481,83 @@ function equals(a) { return b => equalsFn(a, b) } +function includes(valueToFind) { + return iterable => { + if (typeof iterable === 'string') { + return iterable.includes(valueToFind) + } + if (!iterable) { + throw new TypeError(`Cannot read property \'indexOf\' of ${iterable}`) + } + if (!isArray(iterable)) { + return false + } + + return _indexOf(valueToFind, iterable) > -1 + } +} + +function difference(x, y) { + return [ + ...filter(value => !includes(value)(y))(x), + ...filter(value => !includes(value)(x))(y), + ] +} + +function drop(howManyToDrop, ) { + return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) +} + +function dropLast(numberItems) { + return list => (numberItems > 0 ? list.slice(0, -numberItems) : list.slice()) +} + +function dropLastWhile(predicate) { + return list => { + if (list.length === 0) { + return list + } + + const toReturn = []; + let counter = list.length; + + while (counter) { + const item = list[--counter]; + if (!predicate(item, counter)) { + toReturn.push(item); + break + } + } + + while (counter) { + toReturn.push(list[--counter]); + } + + return toReturn.reverse() + } +} + +function dropWhile(predicate) { + return iterable => { + const toReturn = []; + let counter = 0; + + while (counter < iterable.length) { + const item = iterable[counter++]; + if (!predicate(item, counter)) { + toReturn.push(item); + break + } + } + + while (counter < iterable.length) { + toReturn.push(iterable[counter++]); + } + + return toReturn + } +} + class _Set { constructor() { this.set = new Set(); @@ -613,22 +636,6 @@ function evolve(rules) { return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } -function includes(valueToFind) { - return iterable => { - if (typeof iterable === 'string') { - return iterable.includes(valueToFind) - } - if (!iterable) { - throw new TypeError(`Cannot read property \'indexOf\' of ${iterable}`) - } - if (!isArray(iterable)) { - return false - } - - return _indexOf(valueToFind, iterable) > -1 - } -} - function excludes(valueToFind) { return iterable => !includes(valueToFind)(iterable) } @@ -1507,37 +1514,30 @@ function propSatisfies(predicate, property) { return obj => predicate(obj[property]) } -function rangeDescending(start, end) { - const len = start - end; - const willReturn = Array(len); - - for (let i = 0; i < len; i++) { - willReturn[i] = start - i; - } - - return willReturn -} - -function range(start) { - return end => { - if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) { - throw new TypeError('Both arguments to range must be numbers') - } - +function range(start, end) { if (end === start) { return [] } - if (end < start) return rangeDescending(start,end) - - const len = end - start; + const len = start - (end ?? 0); const willReturn = Array(len); - for (let i = 0; i < len; i++) { + for (let i = 0; i <= len; i++) { willReturn[i] = start + i; } return willReturn - } +} + +function rangeDescending(start, end) { + const len = start - (end ?? 0); + if(!(len >0)) return [] + const willReturn = Array(len); + + for (let i = 0; i <= len; i++) { + willReturn[i] = start - i; + } + + return willReturn } function replace(pattern, replacer) { @@ -1922,6 +1922,7 @@ exports.createCompareFunction = createCompareFunction; exports.createObjectFromKeys = createObjectFromKeys; exports.defaultTo = defaultTo; exports.descend = descend; +exports.difference = difference; exports.drop = drop; exports.dropLast = dropLast; exports.dropLastWhile = dropLastWhile; @@ -1994,6 +1995,7 @@ exports.propEq = propEq; exports.propOr = propOr; exports.propSatisfies = propSatisfies; exports.range = range; +exports.rangeDescending = rangeDescending; exports.reduce = reduce; exports.reject = reject; exports.rejectObject = rejectObject; diff --git a/dist/rambda.js b/dist/rambda.js index 76dcce64..fda728d5 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -256,60 +256,6 @@ function descend(getFunction) { } } -function drop(howManyToDrop, ) { - return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) -} - -function dropLast(numberItems) { - return list => (numberItems > 0 ? list.slice(0, -numberItems) : list.slice()) -} - -function dropLastWhile(predicate) { - return list => { - if (list.length === 0) { - return list - } - - const toReturn = []; - let counter = list.length; - - while (counter) { - const item = list[--counter]; - if (!predicate(item, counter)) { - toReturn.push(item); - break - } - } - - while (counter) { - toReturn.push(list[--counter]); - } - - return toReturn.reverse() - } -} - -function dropWhile(predicate) { - return iterable => { - const toReturn = []; - let counter = 0; - - while (counter < iterable.length) { - const item = iterable[counter++]; - if (!predicate(item, counter)) { - toReturn.push(item); - break - } - } - - while (counter < iterable.length) { - toReturn.push(iterable[counter++]); - } - - return toReturn - } -} - function type(input) { if (input === null) { return 'Null' @@ -533,6 +479,83 @@ function equals(a) { return b => equalsFn(a, b) } +function includes(valueToFind) { + return iterable => { + if (typeof iterable === 'string') { + return iterable.includes(valueToFind) + } + if (!iterable) { + throw new TypeError(`Cannot read property \'indexOf\' of ${iterable}`) + } + if (!isArray(iterable)) { + return false + } + + return _indexOf(valueToFind, iterable) > -1 + } +} + +function difference(x, y) { + return [ + ...filter(value => !includes(value)(y))(x), + ...filter(value => !includes(value)(x))(y), + ] +} + +function drop(howManyToDrop, ) { + return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) +} + +function dropLast(numberItems) { + return list => (numberItems > 0 ? list.slice(0, -numberItems) : list.slice()) +} + +function dropLastWhile(predicate) { + return list => { + if (list.length === 0) { + return list + } + + const toReturn = []; + let counter = list.length; + + while (counter) { + const item = list[--counter]; + if (!predicate(item, counter)) { + toReturn.push(item); + break + } + } + + while (counter) { + toReturn.push(list[--counter]); + } + + return toReturn.reverse() + } +} + +function dropWhile(predicate) { + return iterable => { + const toReturn = []; + let counter = 0; + + while (counter < iterable.length) { + const item = iterable[counter++]; + if (!predicate(item, counter)) { + toReturn.push(item); + break + } + } + + while (counter < iterable.length) { + toReturn.push(iterable[counter++]); + } + + return toReturn + } +} + class _Set { constructor() { this.set = new Set(); @@ -611,22 +634,6 @@ function evolve(rules) { return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } -function includes(valueToFind) { - return iterable => { - if (typeof iterable === 'string') { - return iterable.includes(valueToFind) - } - if (!iterable) { - throw new TypeError(`Cannot read property \'indexOf\' of ${iterable}`) - } - if (!isArray(iterable)) { - return false - } - - return _indexOf(valueToFind, iterable) > -1 - } -} - function excludes(valueToFind) { return iterable => !includes(valueToFind)(iterable) } @@ -1505,37 +1512,30 @@ function propSatisfies(predicate, property) { return obj => predicate(obj[property]) } -function rangeDescending(start, end) { - const len = start - end; - const willReturn = Array(len); - - for (let i = 0; i < len; i++) { - willReturn[i] = start - i; - } - - return willReturn -} - -function range(start) { - return end => { - if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) { - throw new TypeError('Both arguments to range must be numbers') - } - +function range(start, end) { if (end === start) { return [] } - if (end < start) return rangeDescending(start,end) - - const len = end - start; + const len = start - (end ?? 0); const willReturn = Array(len); - for (let i = 0; i < len; i++) { + for (let i = 0; i <= len; i++) { willReturn[i] = start + i; } return willReturn - } +} + +function rangeDescending(start, end) { + const len = start - (end ?? 0); + if(!(len >0)) return [] + const willReturn = Array(len); + + for (let i = 0; i <= len; i++) { + willReturn[i] = start - i; + } + + return willReturn } function replace(pattern, replacer) { @@ -1896,4 +1896,4 @@ function zipWith(fn, x) { ) } -export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; +export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index d7797a54..c4bd64a3 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -262,60 +262,6 @@ } } - function drop(howManyToDrop, ) { - return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) - } - - function dropLast(numberItems) { - return list => (numberItems > 0 ? list.slice(0, -numberItems) : list.slice()) - } - - function dropLastWhile(predicate) { - return list => { - if (list.length === 0) { - return list - } - - const toReturn = []; - let counter = list.length; - - while (counter) { - const item = list[--counter]; - if (!predicate(item, counter)) { - toReturn.push(item); - break - } - } - - while (counter) { - toReturn.push(list[--counter]); - } - - return toReturn.reverse() - } - } - - function dropWhile(predicate) { - return iterable => { - const toReturn = []; - let counter = 0; - - while (counter < iterable.length) { - const item = iterable[counter++]; - if (!predicate(item, counter)) { - toReturn.push(item); - break - } - } - - while (counter < iterable.length) { - toReturn.push(iterable[counter++]); - } - - return toReturn - } - } - function type(input) { if (input === null) { return 'Null' @@ -539,6 +485,83 @@ return b => equalsFn(a, b) } + function includes(valueToFind) { + return iterable => { + if (typeof iterable === 'string') { + return iterable.includes(valueToFind) + } + if (!iterable) { + throw new TypeError(`Cannot read property \'indexOf\' of ${iterable}`) + } + if (!isArray(iterable)) { + return false + } + + return _indexOf(valueToFind, iterable) > -1 + } + } + + function difference(x, y) { + return [ + ...filter(value => !includes(value)(y))(x), + ...filter(value => !includes(value)(x))(y), + ] + } + + function drop(howManyToDrop, ) { + return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) + } + + function dropLast(numberItems) { + return list => (numberItems > 0 ? list.slice(0, -numberItems) : list.slice()) + } + + function dropLastWhile(predicate) { + return list => { + if (list.length === 0) { + return list + } + + const toReturn = []; + let counter = list.length; + + while (counter) { + const item = list[--counter]; + if (!predicate(item, counter)) { + toReturn.push(item); + break + } + } + + while (counter) { + toReturn.push(list[--counter]); + } + + return toReturn.reverse() + } + } + + function dropWhile(predicate) { + return iterable => { + const toReturn = []; + let counter = 0; + + while (counter < iterable.length) { + const item = iterable[counter++]; + if (!predicate(item, counter)) { + toReturn.push(item); + break + } + } + + while (counter < iterable.length) { + toReturn.push(iterable[counter++]); + } + + return toReturn + } + } + class _Set { constructor() { this.set = new Set(); @@ -617,22 +640,6 @@ return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } - function includes(valueToFind) { - return iterable => { - if (typeof iterable === 'string') { - return iterable.includes(valueToFind) - } - if (!iterable) { - throw new TypeError(`Cannot read property \'indexOf\' of ${iterable}`) - } - if (!isArray(iterable)) { - return false - } - - return _indexOf(valueToFind, iterable) > -1 - } - } - function excludes(valueToFind) { return iterable => !includes(valueToFind)(iterable) } @@ -1511,37 +1518,30 @@ return obj => predicate(obj[property]) } - function rangeDescending(start, end) { - const len = start - end; - const willReturn = Array(len); - - for (let i = 0; i < len; i++) { - willReturn[i] = start - i; - } - - return willReturn - } - - function range(start) { - return end => { - if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) { - throw new TypeError('Both arguments to range must be numbers') - } - + function range(start, end) { if (end === start) { return [] } - if (end < start) return rangeDescending(start,end) - - const len = end - start; + const len = start - (end ?? 0); const willReturn = Array(len); - for (let i = 0; i < len; i++) { + for (let i = 0; i <= len; i++) { willReturn[i] = start + i; } return willReturn - } + } + + function rangeDescending(start, end) { + const len = start - (end ?? 0); + if(!(len >0)) return [] + const willReturn = Array(len); + + for (let i = 0; i <= len; i++) { + willReturn[i] = start - i; + } + + return willReturn } function replace(pattern, replacer) { @@ -1926,6 +1926,7 @@ exports.createObjectFromKeys = createObjectFromKeys; exports.defaultTo = defaultTo; exports.descend = descend; + exports.difference = difference; exports.drop = drop; exports.dropLast = dropLast; exports.dropLastWhile = dropLastWhile; @@ -1998,6 +1999,7 @@ exports.propOr = propOr; exports.propSatisfies = propSatisfies; exports.range = range; + exports.rangeDescending = rangeDescending; exports.reduce = reduce; exports.reject = reject; exports.rejectObject = rejectObject; diff --git a/docs/README.md b/docs/README.md index b5634747..4df2e980 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1989,6 +1989,105 @@ export function descend(getFunction) { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#descend) +### difference + +```typescript + +difference(x: T[]): (y: T[]) => T[] +``` + +It returns a merged list of `x` and `y` with all equal elements removed. + +`R.equals` is used to determine equality. + +```javascript +const x = [ 1, 2, 3, 4 ] +const y = [ 3, 4, 5, 6 ] + +const result = R.difference(x)(y) +// => [ 1, 2, 5, 6 ] +``` + +Try this R.difference example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +difference(x: T[]): (y: T[]) => T[]; +``` + +
+ +
+ +R.difference source + +```javascript +import { filter } from './filter.js' +import { includes } from './includes.js' + +export function difference(x, y) { + return [ + ...filter(value => !includes(value)(y))(x), + ...filter(value => !includes(value)(x))(y), + ] +} +``` + +
+ +
+ +Tests + +```javascript +import { difference } from './difference.js' + +test('difference', () => { + const list1 = [1, 2, 3, 4] + const list2 = [3, 4, 5, 6] + expect(difference(list1)(list2)).toEqual([1, 2, 5, 6]) + expect(difference([])([])).toEqual([]) +}) + +test('difference with objects', () => { + const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }] + const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }] + expect(difference(list1)(list2)).toEqual([ + { id: 1 }, + { id: 2 }, + { id: 5 }, + { id: 6 }, + ]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { difference } from 'rambda' + +describe('R.difference', () => { + it('happy', () => { + const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }] + const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }] + const result = difference(list1)(list2) + + result // $ExpectType { id: number; }[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#difference) + ### drop ```typescript @@ -3213,7 +3312,7 @@ it('R.evolve', () => { ```typescript -excludes(valueToFind: T): (input: string) => boolean +excludes(list: readonly string[] | string): (substringToFind: string) => boolean ``` Opposite of `R.includes` @@ -3222,21 +3321,21 @@ Opposite of `R.includes` ```javascript const result = [ - R.excludes('ar')('foo'), - R.excludes({a: 2})([{a: 1}]) + R.excludes('foo')('ar'), + R.excludes([{a: 1}])({a: 2}) ] // => [true, true ] ``` -Try this R.excludes example in Rambda REPL +Try this R.excludes example in Rambda REPL
All TypeScript definitions ```typescript -excludes(valueToFind: T): (input: string) => boolean; -excludes(valueToFind: T): (input: T[]) => boolean; +excludes(list: readonly string[] | string): (substringToFind: string) => boolean; +excludes(list: readonly T[]): (target: T) => boolean; ```
@@ -3400,22 +3499,46 @@ test('using Boolean', () => { TypeScript test ```typescript -import { filter, pipe } from 'rambda' +import { filter, includes, pipe, reject, sort, split, uniq } from 'rambda' const list = [1, 2, 3] describe('R.filter with array', () => { it('within pipe', () => { - const result = pipe( + const _result = pipe( list, - filter((x) => { + filter(x => { x // $ExpectType number return x > 1 }), ) - result // $ExpectType number[] + _result // $ExpectType number[] }) + it('complex example', () => { + const text = `Dies ist ein einfacher Beispielsatz. Il fait beau aujourd'hui!` + const language = 'de' + const SENTENCE_END_CHARS = ['.', '!', '?', '।', '؟'] + const result = pipe( + text, + split(''), + uniq, + filter(char => { + if (language === 'de') { + return /[A-Za-zäßüöÜÖÄ]/g.test(char) === false + } + if (language === 'fr') { + return /[A-Za-zÀÉàâçèéêîïôùû']/g.test(char) === false + } + throw new Error(`Language ${language} not supported`) + }), + sort((a, b) => (a === b ? 0 : a > b ? 1 : -1)), + filter(char => char.trim().length > 0), + reject(includes(SENTENCE_END_CHARS)), + ) + + result // $ExpectType string[] + }) it('narrowing type', () => { interface Foo { a: number @@ -3428,8 +3551,8 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe(testList, filter(filterBar)) - result // $ExpectType Bar[] + const _result = pipe(testList, filter(filterBar)) + _result // $ExpectType Bar[] }) it('narrowing type - readonly', () => { @@ -3444,14 +3567,14 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe(testList, filter(filterBar)) - result // $ExpectType Bar[] + const _result = pipe(testList, filter(filterBar)) + _result // $ExpectType Bar[] }) it('filtering NonNullable - list of objects', () => { const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] - const result = pipe(testList, filter(Boolean)) - result // $ExpectType { a: number; }[] + const _result = pipe(testList, filter(Boolean)) + _result // $ExpectType { a: number; }[] }) it('filtering NonNullable - readonly', () => { @@ -4782,7 +4905,7 @@ describe('R.head', () => { ```typescript -includes(s: string): (list: readonly string[] | string) => boolean +includes(list: readonly string[] | string): (substringToFind: string) => boolean ``` If `input` is string, then this method work as native `String.includes`. @@ -4791,21 +4914,21 @@ If `input` is array, then `R.equals` is used to define if `valueToFind` belongs ```javascript const result = [ - R.includes('oo')('foo'), - R.includes({a: 1})([{a: 1}]) + R.includes('foo')('oo'), + R.includes([{a: 1}])({a: 1}) ] // => [true, true ] ``` -Try this R.includes example in Rambda REPL +Try this R.includes example in Rambda REPL
All TypeScript definitions ```typescript -includes(s: string): (list: readonly string[] | string) => boolean; -includes(target: T): (list: readonly T[]) => boolean; +includes(list: readonly string[] | string): (substringToFind: string) => boolean; +includes(list: readonly T[]): (target: T) => boolean; ```
@@ -5334,8 +5457,6 @@ intersection(listA: T[]): (listB: T[]) => T[] It loops through `listA` and `listB` and returns the intersection of the two according to `R.equals`. -> :boom: There is slight difference between Rambda and Ramda implementation. Ramda.intersection(['a', 'b', 'c'], ['c', 'b']) result is "[ 'c', 'b' ]", but Rambda result is "[ 'b', 'c' ]". - ```javascript const listA = [ { id : 1 }, { id : 2 }, { id : 3 }, { id : 4 } ] const listB = [ { id : 3 }, { id : 4 }, { id : 5 }, { id : 6 } ] @@ -9658,25 +9779,24 @@ describe('R.propSatisfies', () => { ```typescript -range(startInclusive: number): (endExclusive: number) => number[] +range(startInclusive: number, endInclusive: number) : number[] ``` -It returns list of numbers between `startInclusive` to `endExclusive` markers. -If `start` is greater than `end`, then the result will be in descending order. +It returns list of numbers between `startInclusive` to `endInclusive` markers. ```javascript -[R.range(0)(5), R.range(5)(0)] -// => [[0, 1, 2, 3, 4], [5, 4, 3, 2, 1]] +[R.range(5), R.range(1, 5)] +// => [[0, 1, 2, 3, 4, 5], [1, 2, 3, 4, 5]] ``` -Try this R.range example in Rambda REPL +Try this R.range example in Rambda REPL
All TypeScript definitions ```typescript -range(startInclusive: number): (endExclusive: number) => number[]; +range(startInclusive: number, endInclusive: number) : number[]; ```
@@ -9686,37 +9806,18 @@ range(startInclusive: number): (endExclusive: number) => number[]; R.range source ```javascript -function rangeDescending(start, end) { - const len = start - end - const willReturn = Array(len) - - for (let i = 0; i < len; i++) { - willReturn[i] = start - i - } - - return willReturn -} - -export function range(start) { - return end => { - if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) { - throw new TypeError('Both arguments to range must be numbers') - } - +export function range(start, end) { if (end === start) { return [] } - if (end < start) return rangeDescending(start,end) - - const len = end - start + const len = start - (end ?? 0) const willReturn = Array(len) - for (let i = 0; i < len; i++) { + for (let i = 0; i <= len; i++) { willReturn[i] = start + i } return willReturn - } } ``` @@ -9758,6 +9859,63 @@ describe('R.range', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#range) +### rangeDescending + +```typescript + +rangeDescending(startInclusive: number, endInclusive: number) : number[] +``` + +It returns list of numbers between `endInclusive` to `startInclusive` markers. + +
+ +All TypeScript definitions + +```typescript +rangeDescending(startInclusive: number, endInclusive: number) : number[]; +``` + +
+ +
+ +R.rangeDescending source + +```javascript +export function rangeDescending(start, end) { + const len = start - (end ?? 0) + if(!(len >0)) return [] + const willReturn = Array(len) + + for (let i = 0; i <= len; i++) { + willReturn[i] = start - i + } + + return willReturn +} +``` + +
+ +
+ +Tests + +```javascript +import { rangeDescending } from './rangeDescending.js' + +test('happy', () => { + expect(rangeDescending(5)).toEqual([5, 4, 3, 2, 1, 0]) + expect(rangeDescending(7,3)).toEqual([7, 6, 5, 4,3]) + expect(rangeDescending(5, 5)).toEqual([]) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#rangeDescending) + ### reduce ```typescript @@ -11363,10 +11521,10 @@ describe('R.splitEvery', () => { ```typescript -symmetricDifference(x: T[]): (y: T[]) => T[] +symmetricDifference(list: T[]): (list: T[]) => T[] ``` -It returns a merged list of `x` and `y` with all equal elements removed. +It returns all items that are in either of the lists, but not in both. `R.equals` is used to determine equality. @@ -11385,7 +11543,7 @@ const result = R.symmetricDifference(x)(y) All TypeScript definitions ```typescript -symmetricDifference(x: T[]): (y: T[]) => T[]; +symmetricDifference(list: T[]): (list: T[]) => T[]; ```
@@ -13740,15 +13898,27 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG -10.4.0 +11.0.0 + +- Breaking change: `R.includes` and `R.excludes` now accept list as first argument and value to search as second argument. This makes it more useful when used with `R.filter` and `R.reject`. - Rename `R.innerJoin` to `R.intersectionWith` - Add `R.unionWith` +- Add `R.exists` + +- Add `R.symmetricDifference` + +- Add `R.rangeDescending` as now `R.range` works only in ascending order. + +- `R.range` now works similar to Ruby's `Range` - both start and end values are inclusive. + - Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: -- R.range +- R.range - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. + +- R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. - R.difference(new method) diff --git a/files/index.d.ts b/files/index.d.ts index df73488c..6f646c99 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -547,6 +547,29 @@ Notes: // @SINGLE_MARKER export function find(predicate: (x: T) => boolean): (list: T[]) => T | undefined; +/* +Method: exists + +Explanation: It returns `true` if there is at least one element in `list` that satisfy the `predicate`. + +Example: + +``` +const predicate = x => R.type(x.foo) === 'Number' +const list = [{foo: 'bar'}, {foo: 1}] + +const result = R.exists(predicate)(list) +// => true +``` + +Categories: List + +Notes: + +*/ +// @SINGLE_MARKER +export function find(predicate: (x: T) => boolean): (list: T[]) => T | undefined; + /* Method: findNth @@ -754,8 +777,8 @@ Example: ``` const result = [ - R.includes('oo')('foo'), - R.includes({a: 1})([{a: 1}]) + R.includes('foo')('oo'), + R.includes([{a: 1}])({a: 1}) ] // => [true, true ] ``` @@ -766,8 +789,8 @@ Notes: */ // @SINGLE_MARKER -export function includes(s: string): (list: readonly string[] | string) => boolean; -export function includes(target: T): (list: readonly T[]) => boolean; +export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; +export function includes(list: readonly T[]): (target: T) => boolean; /* Method: excludes @@ -780,8 +803,8 @@ Example: ``` const result = [ - R.excludes('ar')('foo'), - R.excludes({a: 2})([{a: 1}]) + R.excludes('foo')('ar'), + R.excludes([{a: 1}])({a: 2}) ] // => [true, true ] ``` @@ -792,8 +815,8 @@ Notes: */ // @SINGLE_MARKER -export function excludes(valueToFind: T): (input: string) => boolean; -export function excludes(valueToFind: T): (input: T[]) => boolean; +export function excludes(list: readonly string[] | string): (substringToFind: string) => boolean; +export function excludes(list: readonly T[]): (target: T) => boolean; /* Method: indexOf @@ -859,7 +882,7 @@ const result = R.intersection(listA)(listB) Categories: List -Notes: There is slight difference between Rambda and Ramda implementation. Ramda.intersection(['a', 'b', 'c'], ['c', 'b']) result is "[ 'c', 'b' ]", but Rambda result is "[ 'b', 'c' ]". +Notes: */ // @SINGLE_MARKER @@ -3000,7 +3023,7 @@ Notes: export function splitEvery(sliceLength: number): (input: T[]) => (T[])[]; /* -Method: symmetricDifference +Method: difference Explanation: It returns a merged list of `x` and `y` with all equal elements removed. @@ -3012,6 +3035,31 @@ Example: const x = [ 1, 2, 3, 4 ] const y = [ 3, 4, 5, 6 ] +const result = R.difference(x)(y) +// => [ 1, 2, 5, 6 ] +``` + +Categories: List + +Notes: + +*/ +// @SINGLE_MARKER +export function difference(x: T[]): (y: T[]) => T[]; + +/* +Method: symmetricDifference + +Explanation: It returns all items that are in either of the lists, but not in both. + +`R.equals` is used to determine equality. + +Example: + +``` +const x = [ 1, 2, 3, 4 ] +const y = [ 3, 4, 5, 6 ] + const result = R.symmetricDifference(x)(y) // => [ 1, 2, 5, 6 ] ``` @@ -3022,7 +3070,7 @@ Notes: */ // @SINGLE_MARKER -export function symmetricDifference(x: T[]): (y: T[]) => T[]; +export function symmetricDifference(list: T[]): (list: T[]) => T[]; /* Method: tail @@ -4140,14 +4188,31 @@ export function split(separator: string | RegExp): (str: string) => string[]; /* Method: range -Explanation: It returns list of numbers between `startInclusive` to `endExclusive` markers. -If `start` is greater than `end`, then the result will be in descending order. +Explanation: It returns list of numbers between `startInclusive` to `endInclusive` markers. + +Example: + +``` +[R.range(5), R.range(1, 5)] +// => [[0, 1, 2, 3, 4, 5], [1, 2, 3, 4, 5]] +``` + +Categories: Number + +Notes: + +*/ +// @SINGLE_MARKER +export function range(startInclusive: number, endInclusive: number) : number[]; + +/* +Method: rangeDescending + +Explanation: It returns list of numbers between `endInclusive` to `startInclusive` markers. Example: ``` -[R.range(0)(5), R.range(5)(0)] -// => [[0, 1, 2, 3, 4], [5, 4, 3, 2, 1]] ``` Categories: Number @@ -4156,7 +4221,7 @@ Notes: */ // @SINGLE_MARKER -export function range(startInclusive: number): (endExclusive: number) => number[]; +export function rangeDescending(startInclusive: number, endInclusive: number) : number[]; /* Method: pipeAsync diff --git a/index.d.cts b/index.d.cts index fa53063b..a89f7dcd 100644 --- a/index.d.cts +++ b/index.d.cts @@ -277,6 +277,13 @@ export function defaultTo(defaultValue: T): (input: unknown) => T; */ export function descend(fn: (obj: T) => Ord): (a: T, b: T)=> Ordering; +/** + * It returns a merged list of `x` and `y` with all equal elements removed. + * + * `R.equals` is used to determine equality. + */ +export function difference(x: T[]): (y: T[]) => T[]; + /** * It returns `howMany` items dropped from beginning of list. */ @@ -325,8 +332,8 @@ export function evolve(rules: { * * `R.equals` is used to determine equality. */ -export function excludes(valueToFind: T): (input: string) => boolean; -export function excludes(valueToFind: T): (input: T[]) => boolean; +export function excludes(list: readonly string[] | string): (substringToFind: string) => boolean; +export function excludes(list: readonly T[]): (target: T) => boolean; /** * It filters list or object `input` using a `predicate` function. @@ -430,8 +437,8 @@ export function head(listOrString: T): T extends string ? string : * * If `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list. */ -export function includes(s: string): (list: readonly string[] | string) => boolean; -export function includes(target: T): (list: readonly T[]) => boolean; +export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; +export function includes(list: readonly T[]): (target: T) => boolean; /** * It transforms list of objects to object using specified property as the base for the returned object. @@ -1780,10 +1787,14 @@ export function propOr(property: P, defaultValue: T): (obj: export function propSatisfies(predicate: (x: T) => boolean, property: string): (obj: Record) => boolean; /** - * It returns list of numbers between `startInclusive` to `endExclusive` markers. - * If `start` is greater than `end`, then the result will be in descending order. + * It returns list of numbers between `startInclusive` to `endInclusive` markers. */ -export function range(startInclusive: number): (endExclusive: number) => number[]; +export function range(startInclusive: number, endInclusive: number) : number[]; + +/** + * It returns list of numbers between `endInclusive` to `startInclusive` markers. + */ +export function rangeDescending(startInclusive: number, endInclusive: number) : number[]; export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult): (list: T[]) => TResult; @@ -2191,11 +2202,11 @@ export function split(separator: string | RegExp): (str: string) => string[]; export function splitEvery(sliceLength: number): (input: T[]) => (T[])[]; /** - * It returns a merged list of `x` and `y` with all equal elements removed. + * It returns all items that are in either of the lists, but not in both. * * `R.equals` is used to determine equality. */ -export function symmetricDifference(x: T[]): (y: T[]) => T[]; +export function symmetricDifference(list: T[]): (list: T[]) => T[]; /** * It returns all but the first element of `input`. diff --git a/index.d.ts b/index.d.ts index fa53063b..a89f7dcd 100644 --- a/index.d.ts +++ b/index.d.ts @@ -277,6 +277,13 @@ export function defaultTo(defaultValue: T): (input: unknown) => T; */ export function descend(fn: (obj: T) => Ord): (a: T, b: T)=> Ordering; +/** + * It returns a merged list of `x` and `y` with all equal elements removed. + * + * `R.equals` is used to determine equality. + */ +export function difference(x: T[]): (y: T[]) => T[]; + /** * It returns `howMany` items dropped from beginning of list. */ @@ -325,8 +332,8 @@ export function evolve(rules: { * * `R.equals` is used to determine equality. */ -export function excludes(valueToFind: T): (input: string) => boolean; -export function excludes(valueToFind: T): (input: T[]) => boolean; +export function excludes(list: readonly string[] | string): (substringToFind: string) => boolean; +export function excludes(list: readonly T[]): (target: T) => boolean; /** * It filters list or object `input` using a `predicate` function. @@ -430,8 +437,8 @@ export function head(listOrString: T): T extends string ? string : * * If `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list. */ -export function includes(s: string): (list: readonly string[] | string) => boolean; -export function includes(target: T): (list: readonly T[]) => boolean; +export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; +export function includes(list: readonly T[]): (target: T) => boolean; /** * It transforms list of objects to object using specified property as the base for the returned object. @@ -1780,10 +1787,14 @@ export function propOr(property: P, defaultValue: T): (obj: export function propSatisfies(predicate: (x: T) => boolean, property: string): (obj: Record) => boolean; /** - * It returns list of numbers between `startInclusive` to `endExclusive` markers. - * If `start` is greater than `end`, then the result will be in descending order. + * It returns list of numbers between `startInclusive` to `endInclusive` markers. */ -export function range(startInclusive: number): (endExclusive: number) => number[]; +export function range(startInclusive: number, endInclusive: number) : number[]; + +/** + * It returns list of numbers between `endInclusive` to `startInclusive` markers. + */ +export function rangeDescending(startInclusive: number, endInclusive: number) : number[]; export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult): (list: T[]) => TResult; @@ -2191,11 +2202,11 @@ export function split(separator: string | RegExp): (str: string) => string[]; export function splitEvery(sliceLength: number): (input: T[]) => (T[])[]; /** - * It returns a merged list of `x` and `y` with all equal elements removed. + * It returns all items that are in either of the lists, but not in both. * * `R.equals` is used to determine equality. */ -export function symmetricDifference(x: T[]): (y: T[]) => T[]; +export function symmetricDifference(list: T[]): (list: T[]) => T[]; /** * It returns all but the first element of `input`. diff --git a/rambda.js b/rambda.js index e6b6623e..43e3c512 100644 --- a/rambda.js +++ b/rambda.js @@ -18,6 +18,7 @@ export * from './src/countBy.js' export * from './src/createObjectFromKeys.js' export * from './src/defaultTo.js' export * from './src/descend.js' +export * from './src/difference.js' export * from './src/drop.js' export * from './src/dropLast.js' export * from './src/dropLastWhile.js' @@ -86,6 +87,7 @@ export * from './src/propEq.js' export * from './src/propOr.js' export * from './src/propSatisfies.js' export * from './src/range.js' +export * from './src/rangeDescending.js' export * from './src/reduce.js' export * from './src/reject.js' export * from './src/rejectObject.js' diff --git a/source/difference-spec.ts b/source/difference-spec.ts new file mode 100644 index 00000000..3d8a4409 --- /dev/null +++ b/source/difference-spec.ts @@ -0,0 +1,11 @@ +import { difference } from 'rambda' + +describe('R.difference', () => { + it('happy', () => { + const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }] + const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }] + const result = difference(list1)(list2) + + result // $ExpectType { id: number; }[] + }) +}) diff --git a/source/difference.js b/source/difference.js new file mode 100644 index 00000000..19bd56bf --- /dev/null +++ b/source/difference.js @@ -0,0 +1,9 @@ +import { filter } from './filter.js' +import { includes } from './includes.js' + +export function difference(x, y) { + return [ + ...filter(value => !includes(value)(y))(x), + ...filter(value => !includes(value)(x))(y), + ] +} diff --git a/source/difference.spec.js b/source/difference.spec.js new file mode 100644 index 00000000..610ada73 --- /dev/null +++ b/source/difference.spec.js @@ -0,0 +1,19 @@ +import { difference } from './difference.js' + +test('difference', () => { + const list1 = [1, 2, 3, 4] + const list2 = [3, 4, 5, 6] + expect(difference(list1)(list2)).toEqual([1, 2, 5, 6]) + expect(difference([])([])).toEqual([]) +}) + +test('difference with objects', () => { + const list1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }] + const list2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }] + expect(difference(list1)(list2)).toEqual([ + { id: 1 }, + { id: 2 }, + { id: 5 }, + { id: 6 }, + ]) +}) diff --git a/source/exists-spec.ts b/source/exists-spec.ts new file mode 100644 index 00000000..efb1cab9 --- /dev/null +++ b/source/exists-spec.ts @@ -0,0 +1,11 @@ +import { exists, pipe } from 'rambda' + +const list = [1, 2, 3] + +describe('R.exists', () => { + it('happy', () => { + const predicate = (x: number) => x > 2 + const result = pipe(list, exists(predicate)) + result // $ExpectType boolean + }) +}) diff --git a/source/exists.js b/source/exists.js new file mode 100644 index 00000000..8094ee41 --- /dev/null +++ b/source/exists.js @@ -0,0 +1,7 @@ +import { find } from './find.js' + +export function exists(predicate) { + return list => { + return find(predicate)(list) !== undefined + } +} diff --git a/source/filter-spec.ts b/source/filter-spec.ts index a4e8c0a7..4013d3d4 100644 --- a/source/filter-spec.ts +++ b/source/filter-spec.ts @@ -1,19 +1,43 @@ -import { filter, pipe } from 'rambda' +import { filter, includes, pipe, reject, sort, split, uniq } from 'rambda' const list = [1, 2, 3] describe('R.filter with array', () => { it('within pipe', () => { - const result = pipe( + const _result = pipe( list, - filter((x) => { + filter(x => { x // $ExpectType number return x > 1 }), ) - result // $ExpectType number[] + _result // $ExpectType number[] }) + it('complex example', () => { + const text = `Dies ist ein einfacher Beispielsatz. Il fait beau aujourd'hui!` + const language = 'de' + const SENTENCE_END_CHARS = ['.', '!', '?', '।', '؟'] + const result = pipe( + text, + split(''), + uniq, + filter(char => { + if (language === 'de') { + return /[A-Za-zäßüöÜÖÄ]/g.test(char) === false + } + if (language === 'fr') { + return /[A-Za-zÀÉàâçèéêîïôùû']/g.test(char) === false + } + throw new Error(`Language ${language} not supported`) + }), + sort((a, b) => (a === b ? 0 : a > b ? 1 : -1)), + filter(char => char.trim().length > 0), + reject(includes(SENTENCE_END_CHARS)), + ) + + result // $ExpectType string[] + }) it('narrowing type', () => { interface Foo { a: number @@ -26,8 +50,8 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe(testList, filter(filterBar)) - result // $ExpectType Bar[] + const _result = pipe(testList, filter(filterBar)) + _result // $ExpectType Bar[] }) it('narrowing type - readonly', () => { @@ -42,14 +66,14 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const result = pipe(testList, filter(filterBar)) - result // $ExpectType Bar[] + const _result = pipe(testList, filter(filterBar)) + _result // $ExpectType Bar[] }) it('filtering NonNullable - list of objects', () => { const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] - const result = pipe(testList, filter(Boolean)) - result // $ExpectType { a: number; }[] + const _result = pipe(testList, filter(Boolean)) + _result // $ExpectType { a: number; }[] }) it('filtering NonNullable - readonly', () => { diff --git a/source/range.js b/source/range.js index f1d992e5..71390b6d 100644 --- a/source/range.js +++ b/source/range.js @@ -1,34 +1,15 @@ -function rangeDescending(start, end) { - const len = start - end - const willReturn = Array(len) - - for (let i = 0; i < len; i++) { - willReturn[i] = start - i - } - - return willReturn -} - -export function range(start) { - return end => { - if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) { - throw new TypeError('Both arguments to range must be numbers') - } - +export function range(start, end) { if (end === start) { return [] } - if (end < start) return rangeDescending(start,end) - - const len = end - start + const len = start - (end ?? 0) const willReturn = Array(len) - for (let i = 0; i < len; i++) { + for (let i = 0; i <= len; i++) { willReturn[i] = start + i } return willReturn - } } diff --git a/source/rangeDescending.js b/source/rangeDescending.js new file mode 100644 index 00000000..30ac49dd --- /dev/null +++ b/source/rangeDescending.js @@ -0,0 +1,11 @@ +export function rangeDescending(start, end) { + const len = start - (end ?? 0) + if(!(len >0)) return [] + const willReturn = Array(len) + + for (let i = 0; i <= len; i++) { + willReturn[i] = start - i + } + + return willReturn +} diff --git a/source/rangeDescending.spec.js b/source/rangeDescending.spec.js new file mode 100644 index 00000000..ab473a23 --- /dev/null +++ b/source/rangeDescending.spec.js @@ -0,0 +1,7 @@ +import { rangeDescending } from './rangeDescending.js' + +test('happy', () => { + expect(rangeDescending(5)).toEqual([5, 4, 3, 2, 1, 0]) + expect(rangeDescending(7,3)).toEqual([7, 6, 5, 4,3]) + expect(rangeDescending(5, 5)).toEqual([]) +}) diff --git a/src/difference.js b/src/difference.js new file mode 100644 index 00000000..19bd56bf --- /dev/null +++ b/src/difference.js @@ -0,0 +1,9 @@ +import { filter } from './filter.js' +import { includes } from './includes.js' + +export function difference(x, y) { + return [ + ...filter(value => !includes(value)(y))(x), + ...filter(value => !includes(value)(x))(y), + ] +} diff --git a/src/range.js b/src/range.js index f1d992e5..71390b6d 100644 --- a/src/range.js +++ b/src/range.js @@ -1,34 +1,15 @@ -function rangeDescending(start, end) { - const len = start - end - const willReturn = Array(len) - - for (let i = 0; i < len; i++) { - willReturn[i] = start - i - } - - return willReturn -} - -export function range(start) { - return end => { - if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) { - throw new TypeError('Both arguments to range must be numbers') - } - +export function range(start, end) { if (end === start) { return [] } - if (end < start) return rangeDescending(start,end) - - const len = end - start + const len = start - (end ?? 0) const willReturn = Array(len) - for (let i = 0; i < len; i++) { + for (let i = 0; i <= len; i++) { willReturn[i] = start + i } return willReturn - } } diff --git a/src/rangeDescending.js b/src/rangeDescending.js new file mode 100644 index 00000000..30ac49dd --- /dev/null +++ b/src/rangeDescending.js @@ -0,0 +1,11 @@ +export function rangeDescending(start, end) { + const len = start - (end ?? 0) + if(!(len >0)) return [] + const willReturn = Array(len) + + for (let i = 0; i <= len; i++) { + willReturn[i] = start - i + } + + return willReturn +} From 5938627e770d24e2ce8b56d1b86de97eff476596 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Sun, 21 Dec 2025 13:33:47 +0200 Subject: [PATCH 39/54] chore@small --- CHANGELOG.md | 8 ++--- README.md | 61 ++++++++++++++++------------------ dist/rambda.cjs | 41 ++++++++++------------- dist/rambda.js | 41 ++++++++++------------- dist/rambda.umd.js | 41 ++++++++++------------- docs/README.md | 61 ++++++++++++++++------------------ files/DEV_NOTES.md | 4 +++ files/index.d.ts | 2 ++ index.d.cts | 2 ++ index.d.ts | 2 ++ source/difference.js | 6 ++-- source/range.js | 22 +++++------- source/range.spec.js | 7 ++-- source/rangeDescending.js | 15 ++++----- source/rangeDescending.spec.js | 1 + src/difference.js | 6 ++-- src/range.js | 22 +++++------- src/rangeDescending.js | 15 ++++----- 18 files changed, 159 insertions(+), 198 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee05687e..0bd980e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,17 +10,15 @@ - Add `R.symmetricDifference` -- Add `R.rangeDescending` as now `R.range` works only in ascending order. +- Add `R.difference` - `R.range` now works similar to Ruby's `Range` - both start and end values are inclusive. -- Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: +- Add `R.rangeDescending` as now `R.range` works only in ascending order. -- R.range - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. +- `R.range` - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. - R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. - -- R.difference(new method) 10.3.5 diff --git a/README.md b/README.md index 4df2e980..d1aa71cf 100644 --- a/README.md +++ b/README.md @@ -2028,11 +2028,11 @@ difference(x: T[]): (y: T[]) => T[]; import { filter } from './filter.js' import { includes } from './includes.js' -export function difference(x, y) { - return [ +export function difference(x) { + return y => ([ ...filter(value => !includes(value)(y))(x), ...filter(value => !includes(value)(x))(y), - ] + ]) } ``` @@ -9779,7 +9779,7 @@ describe('R.propSatisfies', () => { ```typescript -range(startInclusive: number, endInclusive: number) : number[] +range(endInclusive: number) : number[] ``` It returns list of numbers between `startInclusive` to `endInclusive` markers. @@ -9796,6 +9796,7 @@ It returns list of numbers between `startInclusive` to `endInclusive` markers. All TypeScript definitions ```typescript +range(endInclusive: number) : number[]; range(startInclusive: number, endInclusive: number) : number[]; ``` @@ -9806,18 +9807,14 @@ range(startInclusive: number, endInclusive: number) : number[]; R.range source ```javascript -export function range(start, end) { - if (end === start) { - return [] - } - const len = start - (end ?? 0) - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start + i - } - - return willReturn +export function range(a, b) { + const start = b === undefined ? 0 : a + const end = b === undefined ? a : b + if (end<= start) { + return [] + } + const len = end - start + return Array.from({ length: len + 1 }, (_, i) => start + i) } ``` @@ -9831,9 +9828,10 @@ export function range(start, end) { import { range } from './range.js' test('happy', () => { - expect(range(0)(5)).toEqual([0, 1, 2, 3, 4]) - expect(range(7)(3)).toEqual([7, 6, 5, 4]) - expect(range(5)(5)).toEqual([]) + expect(range(5)).toEqual([0, 1, 2, 3, 4, 5]) + expect(range(3,5)).toEqual([3, 4, 5]) + expect(range(5,3)).toEqual([]) + expect(range(0)).toEqual([]) }) ``` @@ -9874,6 +9872,7 @@ It returns list of numbers between `endInclusive` to `startInclusive` markers. ```typescript rangeDescending(startInclusive: number, endInclusive: number) : number[]; +rangeDescending(endInclusive: number) : number[]; ```
@@ -9883,16 +9882,13 @@ rangeDescending(startInclusive: number, endInclusive: number) : number[]; R.rangeDescending source ```javascript -export function rangeDescending(start, end) { - const len = start - (end ?? 0) - if(!(len >0)) return [] - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start - i +export function rangeDescending(start, b) { + const end = b === undefined ? 0 : b + if (start <= end) { + return [] } - - return willReturn + const len = start - end + return Array.from({ length: len + 1 }, (_, i) => start - i) } ``` @@ -9908,6 +9904,7 @@ import { rangeDescending } from './rangeDescending.js' test('happy', () => { expect(rangeDescending(5)).toEqual([5, 4, 3, 2, 1, 0]) expect(rangeDescending(7,3)).toEqual([7, 6, 5, 4,3]) + expect(rangeDescending(5, 7)).toEqual([]) expect(rangeDescending(5, 5)).toEqual([]) }) ``` @@ -13910,17 +13907,15 @@ describe('R.zipWith', () => { - Add `R.symmetricDifference` -- Add `R.rangeDescending` as now `R.range` works only in ascending order. +- Add `R.difference` - `R.range` now works similar to Ruby's `Range` - both start and end values are inclusive. -- Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: +- Add `R.rangeDescending` as now `R.range` works only in ascending order. -- R.range - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. +- `R.range` - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. - R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. - -- R.difference(new method) 10.3.5 diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 2edac945..5cf02240 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -497,11 +497,11 @@ function includes(valueToFind) { } } -function difference(x, y) { - return [ +function difference(x) { + return y => ([ ...filter(value => !includes(value)(y))(x), ...filter(value => !includes(value)(x))(y), - ] + ]) } function drop(howManyToDrop, ) { @@ -1514,30 +1514,23 @@ function propSatisfies(predicate, property) { return obj => predicate(obj[property]) } -function range(start, end) { - if (end === start) { - return [] - } - const len = start - (end ?? 0); - const willReturn = Array(len); - - for (let i = 0; i <= len; i++) { - willReturn[i] = start + i; - } - - return willReturn +function range(a, b) { + const start = b === undefined ? 0 : a; + const end = b === undefined ? a : b; + if (end<= start) { + return [] + } + const len = end - start; + return Array.from({ length: len + 1 }, (_, i) => start + i) } -function rangeDescending(start, end) { - const len = start - (end ?? 0); - if(!(len >0)) return [] - const willReturn = Array(len); - - for (let i = 0; i <= len; i++) { - willReturn[i] = start - i; +function rangeDescending(start, b) { + const end = b === undefined ? 0 : b; + if (start <= end) { + return [] } - - return willReturn + const len = start - end; + return Array.from({ length: len + 1 }, (_, i) => start - i) } function replace(pattern, replacer) { diff --git a/dist/rambda.js b/dist/rambda.js index fda728d5..47b115d1 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -495,11 +495,11 @@ function includes(valueToFind) { } } -function difference(x, y) { - return [ +function difference(x) { + return y => ([ ...filter(value => !includes(value)(y))(x), ...filter(value => !includes(value)(x))(y), - ] + ]) } function drop(howManyToDrop, ) { @@ -1512,30 +1512,23 @@ function propSatisfies(predicate, property) { return obj => predicate(obj[property]) } -function range(start, end) { - if (end === start) { - return [] - } - const len = start - (end ?? 0); - const willReturn = Array(len); - - for (let i = 0; i <= len; i++) { - willReturn[i] = start + i; - } - - return willReturn +function range(a, b) { + const start = b === undefined ? 0 : a; + const end = b === undefined ? a : b; + if (end<= start) { + return [] + } + const len = end - start; + return Array.from({ length: len + 1 }, (_, i) => start + i) } -function rangeDescending(start, end) { - const len = start - (end ?? 0); - if(!(len >0)) return [] - const willReturn = Array(len); - - for (let i = 0; i <= len; i++) { - willReturn[i] = start - i; +function rangeDescending(start, b) { + const end = b === undefined ? 0 : b; + if (start <= end) { + return [] } - - return willReturn + const len = start - end; + return Array.from({ length: len + 1 }, (_, i) => start - i) } function replace(pattern, replacer) { diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index c4bd64a3..0dba015b 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -501,11 +501,11 @@ } } - function difference(x, y) { - return [ + function difference(x) { + return y => ([ ...filter(value => !includes(value)(y))(x), ...filter(value => !includes(value)(x))(y), - ] + ]) } function drop(howManyToDrop, ) { @@ -1518,30 +1518,23 @@ return obj => predicate(obj[property]) } - function range(start, end) { - if (end === start) { - return [] - } - const len = start - (end ?? 0); - const willReturn = Array(len); - - for (let i = 0; i <= len; i++) { - willReturn[i] = start + i; - } - - return willReturn + function range(a, b) { + const start = b === undefined ? 0 : a; + const end = b === undefined ? a : b; + if (end<= start) { + return [] + } + const len = end - start; + return Array.from({ length: len + 1 }, (_, i) => start + i) } - function rangeDescending(start, end) { - const len = start - (end ?? 0); - if(!(len >0)) return [] - const willReturn = Array(len); - - for (let i = 0; i <= len; i++) { - willReturn[i] = start - i; + function rangeDescending(start, b) { + const end = b === undefined ? 0 : b; + if (start <= end) { + return [] } - - return willReturn + const len = start - end; + return Array.from({ length: len + 1 }, (_, i) => start - i) } function replace(pattern, replacer) { diff --git a/docs/README.md b/docs/README.md index 4df2e980..d1aa71cf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2028,11 +2028,11 @@ difference(x: T[]): (y: T[]) => T[]; import { filter } from './filter.js' import { includes } from './includes.js' -export function difference(x, y) { - return [ +export function difference(x) { + return y => ([ ...filter(value => !includes(value)(y))(x), ...filter(value => !includes(value)(x))(y), - ] + ]) } ``` @@ -9779,7 +9779,7 @@ describe('R.propSatisfies', () => { ```typescript -range(startInclusive: number, endInclusive: number) : number[] +range(endInclusive: number) : number[] ``` It returns list of numbers between `startInclusive` to `endInclusive` markers. @@ -9796,6 +9796,7 @@ It returns list of numbers between `startInclusive` to `endInclusive` markers. All TypeScript definitions ```typescript +range(endInclusive: number) : number[]; range(startInclusive: number, endInclusive: number) : number[]; ``` @@ -9806,18 +9807,14 @@ range(startInclusive: number, endInclusive: number) : number[]; R.range source ```javascript -export function range(start, end) { - if (end === start) { - return [] - } - const len = start - (end ?? 0) - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start + i - } - - return willReturn +export function range(a, b) { + const start = b === undefined ? 0 : a + const end = b === undefined ? a : b + if (end<= start) { + return [] + } + const len = end - start + return Array.from({ length: len + 1 }, (_, i) => start + i) } ``` @@ -9831,9 +9828,10 @@ export function range(start, end) { import { range } from './range.js' test('happy', () => { - expect(range(0)(5)).toEqual([0, 1, 2, 3, 4]) - expect(range(7)(3)).toEqual([7, 6, 5, 4]) - expect(range(5)(5)).toEqual([]) + expect(range(5)).toEqual([0, 1, 2, 3, 4, 5]) + expect(range(3,5)).toEqual([3, 4, 5]) + expect(range(5,3)).toEqual([]) + expect(range(0)).toEqual([]) }) ``` @@ -9874,6 +9872,7 @@ It returns list of numbers between `endInclusive` to `startInclusive` markers. ```typescript rangeDescending(startInclusive: number, endInclusive: number) : number[]; +rangeDescending(endInclusive: number) : number[]; ```
@@ -9883,16 +9882,13 @@ rangeDescending(startInclusive: number, endInclusive: number) : number[]; R.rangeDescending source ```javascript -export function rangeDescending(start, end) { - const len = start - (end ?? 0) - if(!(len >0)) return [] - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start - i +export function rangeDescending(start, b) { + const end = b === undefined ? 0 : b + if (start <= end) { + return [] } - - return willReturn + const len = start - end + return Array.from({ length: len + 1 }, (_, i) => start - i) } ``` @@ -9908,6 +9904,7 @@ import { rangeDescending } from './rangeDescending.js' test('happy', () => { expect(rangeDescending(5)).toEqual([5, 4, 3, 2, 1, 0]) expect(rangeDescending(7,3)).toEqual([7, 6, 5, 4,3]) + expect(rangeDescending(5, 7)).toEqual([]) expect(rangeDescending(5, 5)).toEqual([]) }) ``` @@ -13910,17 +13907,15 @@ describe('R.zipWith', () => { - Add `R.symmetricDifference` -- Add `R.rangeDescending` as now `R.range` works only in ascending order. +- Add `R.difference` - `R.range` now works similar to Ruby's `Range` - both start and end values are inclusive. -- Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: +- Add `R.rangeDescending` as now `R.range` works only in ascending order. -- R.range - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. +- `R.range` - it accepts one or two arguments. If one argument is passed, it is considered as end value, and start is 0. - R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. - -- R.difference(new method) 10.3.5 diff --git a/files/DEV_NOTES.md b/files/DEV_NOTES.md index 9091b31f..c913977f 100644 --- a/files/DEV_NOTES.md +++ b/files/DEV_NOTES.md @@ -1,3 +1,7 @@ + +- Change several functions to be used directly without currying. It relates when there is confusion which is the input that is coming from the pipe: + +- R.difference(new method) === https:bundlejs.com === diff --git a/files/index.d.ts b/files/index.d.ts index 6f646c99..078606ee 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -4203,6 +4203,7 @@ Notes: */ // @SINGLE_MARKER +export function range(endInclusive: number) : number[]; export function range(startInclusive: number, endInclusive: number) : number[]; /* @@ -4222,6 +4223,7 @@ Notes: */ // @SINGLE_MARKER export function rangeDescending(startInclusive: number, endInclusive: number) : number[]; +export function rangeDescending(endInclusive: number) : number[]; /* Method: pipeAsync diff --git a/index.d.cts b/index.d.cts index a89f7dcd..e773f0db 100644 --- a/index.d.cts +++ b/index.d.cts @@ -1789,12 +1789,14 @@ export function propSatisfies(predicate: (x: T) => boolean, property: string) /** * It returns list of numbers between `startInclusive` to `endInclusive` markers. */ +export function range(endInclusive: number) : number[]; export function range(startInclusive: number, endInclusive: number) : number[]; /** * It returns list of numbers between `endInclusive` to `startInclusive` markers. */ export function rangeDescending(startInclusive: number, endInclusive: number) : number[]; +export function rangeDescending(endInclusive: number) : number[]; export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult): (list: T[]) => TResult; diff --git a/index.d.ts b/index.d.ts index a89f7dcd..e773f0db 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1789,12 +1789,14 @@ export function propSatisfies(predicate: (x: T) => boolean, property: string) /** * It returns list of numbers between `startInclusive` to `endInclusive` markers. */ +export function range(endInclusive: number) : number[]; export function range(startInclusive: number, endInclusive: number) : number[]; /** * It returns list of numbers between `endInclusive` to `startInclusive` markers. */ export function rangeDescending(startInclusive: number, endInclusive: number) : number[]; +export function rangeDescending(endInclusive: number) : number[]; export function reduce(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult): (list: T[]) => TResult; diff --git a/source/difference.js b/source/difference.js index 19bd56bf..64af0b8e 100644 --- a/source/difference.js +++ b/source/difference.js @@ -1,9 +1,9 @@ import { filter } from './filter.js' import { includes } from './includes.js' -export function difference(x, y) { - return [ +export function difference(x) { + return y => ([ ...filter(value => !includes(value)(y))(x), ...filter(value => !includes(value)(x))(y), - ] + ]) } diff --git a/source/range.js b/source/range.js index 71390b6d..94e3f672 100644 --- a/source/range.js +++ b/source/range.js @@ -1,15 +1,9 @@ -export function range(start, end) { - if (end === start) { - return [] - } - const len = start - (end ?? 0) - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start + i - } - - return willReturn +export function range(a, b) { + const start = b === undefined ? 0 : a + const end = b === undefined ? a : b + if (end<= start) { + return [] + } + const len = end - start + return Array.from({ length: len + 1 }, (_, i) => start + i) } - - diff --git a/source/range.spec.js b/source/range.spec.js index 24079568..49368ca1 100644 --- a/source/range.spec.js +++ b/source/range.spec.js @@ -1,7 +1,8 @@ import { range } from './range.js' test('happy', () => { - expect(range(0)(5)).toEqual([0, 1, 2, 3, 4]) - expect(range(7)(3)).toEqual([7, 6, 5, 4]) - expect(range(5)(5)).toEqual([]) + expect(range(5)).toEqual([0, 1, 2, 3, 4, 5]) + expect(range(3,5)).toEqual([3, 4, 5]) + expect(range(5,3)).toEqual([]) + expect(range(0)).toEqual([]) }) diff --git a/source/rangeDescending.js b/source/rangeDescending.js index 30ac49dd..03fce194 100644 --- a/source/rangeDescending.js +++ b/source/rangeDescending.js @@ -1,11 +1,8 @@ -export function rangeDescending(start, end) { - const len = start - (end ?? 0) - if(!(len >0)) return [] - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start - i +export function rangeDescending(start, b) { + const end = b === undefined ? 0 : b + if (start <= end) { + return [] } - - return willReturn + const len = start - end + return Array.from({ length: len + 1 }, (_, i) => start - i) } diff --git a/source/rangeDescending.spec.js b/source/rangeDescending.spec.js index ab473a23..ac9bed04 100644 --- a/source/rangeDescending.spec.js +++ b/source/rangeDescending.spec.js @@ -3,5 +3,6 @@ import { rangeDescending } from './rangeDescending.js' test('happy', () => { expect(rangeDescending(5)).toEqual([5, 4, 3, 2, 1, 0]) expect(rangeDescending(7,3)).toEqual([7, 6, 5, 4,3]) + expect(rangeDescending(5, 7)).toEqual([]) expect(rangeDescending(5, 5)).toEqual([]) }) diff --git a/src/difference.js b/src/difference.js index 19bd56bf..64af0b8e 100644 --- a/src/difference.js +++ b/src/difference.js @@ -1,9 +1,9 @@ import { filter } from './filter.js' import { includes } from './includes.js' -export function difference(x, y) { - return [ +export function difference(x) { + return y => ([ ...filter(value => !includes(value)(y))(x), ...filter(value => !includes(value)(x))(y), - ] + ]) } diff --git a/src/range.js b/src/range.js index 71390b6d..94e3f672 100644 --- a/src/range.js +++ b/src/range.js @@ -1,15 +1,9 @@ -export function range(start, end) { - if (end === start) { - return [] - } - const len = start - (end ?? 0) - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start + i - } - - return willReturn +export function range(a, b) { + const start = b === undefined ? 0 : a + const end = b === undefined ? a : b + if (end<= start) { + return [] + } + const len = end - start + return Array.from({ length: len + 1 }, (_, i) => start + i) } - - diff --git a/src/rangeDescending.js b/src/rangeDescending.js index 30ac49dd..03fce194 100644 --- a/src/rangeDescending.js +++ b/src/rangeDescending.js @@ -1,11 +1,8 @@ -export function rangeDescending(start, end) { - const len = start - (end ?? 0) - if(!(len >0)) return [] - const willReturn = Array(len) - - for (let i = 0; i <= len; i++) { - willReturn[i] = start - i +export function rangeDescending(start, b) { + const end = b === undefined ? 0 : b + if (start <= end) { + return [] } - - return willReturn + const len = start - end + return Array.from({ length: len + 1 }, (_, i) => start - i) } From a5938ed561e33cf24cd6e6219f5bbb940b80265e Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Mon, 22 Dec 2025 00:58:28 +0200 Subject: [PATCH 40/54] chore@small --- README.md | 96 ++++++++++++++++++++++++++++++++++------- dist/rambda.cjs | 39 ++++++++++------- dist/rambda.js | 40 +++++++++-------- dist/rambda.umd.js | 39 ++++++++++------- docs/README.md | 96 ++++++++++++++++++++++++++++++++++------- files/index.d.ts | 4 +- index.d.cts | 7 ++- index.d.ts | 7 ++- rambda.js | 1 + source/allPass-spec.ts | 5 ++- source/excludes-spec.ts | 2 +- source/includes-spec.ts | 14 ++---- source/range-spec.ts | 4 +- src/exists.js | 7 +++ 14 files changed, 262 insertions(+), 99 deletions(-) create mode 100644 src/exists.js diff --git a/README.md b/README.md index d1aa71cf..1223e4e2 100644 --- a/README.md +++ b/README.md @@ -565,7 +565,10 @@ describe('allPass', () => { [1, 2, 3, 4], [3, 4, 5], ] - const result = R.pipe(list, R.map(R.allPass([R.includes(3), R.includes(4)]))) + const result = R.pipe(list, R.map(R.allPass([ + (x) => x.length > 2, + (x) => x.includes(3) + ]))) result // $ExpectType boolean[] }) }) @@ -3388,7 +3391,7 @@ import { excludes, pipe } from 'rambda' describe('R.excludes', () => { it('happy', () => { const list = [{ a: { b: '1' } }, { a: { b: '2' } }, { a: { b: '3' } }] - const result = pipe(list, excludes({ a: { b: '1' } })) + const result = pipe({ a: { b: '1' } }, excludes(list)) result // $ExpectType boolean }) it('with string', () => { @@ -3402,6 +3405,73 @@ describe('R.excludes', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#excludes) +### exists + +```typescript + +exists(predicate: (x: T) => boolean): (list: T[]) => boolean +``` + +It returns `true` if there is at least one element in `list` that satisfy the `predicate`. + +```javascript +const predicate = x => R.type(x.foo) === 'Number' +const list = [{foo: 'bar'}, {foo: 1}] + +const result = R.exists(predicate)(list) +// => true +``` + +Try this R.exists example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +exists(predicate: (x: T) => boolean): (list: T[]) => boolean; +``` + +
+ +
+ +R.exists source + +```javascript +import { find } from './find.js' + +export function exists(predicate) { + return list => { + return find(predicate)(list) !== undefined + } +} +``` + +
+ +
+ +TypeScript test + +```typescript +import { exists, pipe } from 'rambda' + +const list = [1, 2, 3] + +describe('R.exists', () => { + it('happy', () => { + const predicate = (x: number) => x > 2 + const result = pipe(list, exists(predicate)) + result // $ExpectType boolean + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#exists) + ### filter ```typescript @@ -4905,7 +4975,7 @@ describe('R.head', () => { ```typescript -includes(list: readonly string[] | string): (substringToFind: string) => boolean +includes(list: readonly T[]): (target: T) => boolean ``` If `input` is string, then this method work as native `String.includes`. @@ -4927,8 +4997,8 @@ const result = [ All TypeScript definitions ```typescript -includes(list: readonly string[] | string): (substringToFind: string) => boolean; includes(list: readonly T[]): (target: T) => boolean; +includes(list: readonly string[] | string): (substringToFind: string) => boolean; ```
@@ -5005,28 +5075,22 @@ test('with wrong input that does not throw', () => { TypeScript test ```typescript -import { pipe, includes } from 'rambda' +import { pipe , includes} from 'rambda' describe('R.includes', () => { it('happy', () => { const list = [{ a: { b: '1' } }, { a: { b: '2' } }, { a: { b: '3' } }] - const result = pipe(list, includes({ a: { b: '1' } })) + const result = pipe({ a: { b: '1' } }, includes(list)) result // $ExpectType boolean }) it('with string', () => { - const result = pipe('foo', includes('bar')) + const result = pipe('oo', includes('foo')) result // $ExpectType boolean }) it('with array of strings', () => { - const result = pipe(['1','2'], includes('1')) + const result = pipe('1', includes(['1','2','3'])) result // $ExpectType boolean }) - it('without R.pipe', () => { - const result1 = includes('1')(['1', '2']) - const result2 = includes(1)([1, 2]) - result1 // $ExpectType boolean - result2 // $ExpectType boolean - }) }) ``` @@ -9846,9 +9910,9 @@ import { range } from 'rambda' describe('R.range', () => { it('curried', () => { - const result = range(1)(4) + const result = [range(1, 4), range(1)] - result // $ExpectType number[] + result // $ExpectType number[][] }) }) ``` diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 5cf02240..999bcce3 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -640,6 +640,28 @@ function excludes(valueToFind) { return iterable => !includes(valueToFind)(iterable) } +function find(predicate) { + return list => { + let index = 0; + const len = list.length; + + while (index < len) { + const x = list[index]; + if (predicate(x)) { + return x + } + + index++; + } + } +} + +function exists(predicate) { + return list => { + return find(predicate)(list) !== undefined + } +} + function filterAsync(predicate) { return async list => { const willReturn = []; @@ -669,22 +691,6 @@ function filterObject(predicate) { } } -function find(predicate) { - return list => { - let index = 0; - const len = list.length; - - while (index < len) { - const x = list[index]; - if (predicate(x)) { - return x - } - - index++; - } - } -} - function findIndex(predicate) { return list => { const len = list.length; @@ -1927,6 +1933,7 @@ exports.equals = equals; exports.equalsFn = equalsFn; exports.evolve = evolve; exports.excludes = excludes; +exports.exists = exists; exports.filter = filter; exports.filterAsync = filterAsync; exports.filterObject = filterObject; diff --git a/dist/rambda.js b/dist/rambda.js index 47b115d1..731667f3 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -638,6 +638,28 @@ function excludes(valueToFind) { return iterable => !includes(valueToFind)(iterable) } +function find(predicate) { + return list => { + let index = 0; + const len = list.length; + + while (index < len) { + const x = list[index]; + if (predicate(x)) { + return x + } + + index++; + } + } +} + +function exists(predicate) { + return list => { + return find(predicate)(list) !== undefined + } +} + function filterAsync(predicate) { return async list => { const willReturn = []; @@ -667,22 +689,6 @@ function filterObject(predicate) { } } -function find(predicate) { - return list => { - let index = 0; - const len = list.length; - - while (index < len) { - const x = list[index]; - if (predicate(x)) { - return x - } - - index++; - } - } -} - function findIndex(predicate) { return list => { const len = list.length; @@ -1889,4 +1895,4 @@ function zipWith(fn, x) { ) } -export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; +export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, exists, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index 0dba015b..ce93fa93 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -644,6 +644,28 @@ return iterable => !includes(valueToFind)(iterable) } + function find(predicate) { + return list => { + let index = 0; + const len = list.length; + + while (index < len) { + const x = list[index]; + if (predicate(x)) { + return x + } + + index++; + } + } + } + + function exists(predicate) { + return list => { + return find(predicate)(list) !== undefined + } + } + function filterAsync(predicate) { return async list => { const willReturn = []; @@ -673,22 +695,6 @@ } } - function find(predicate) { - return list => { - let index = 0; - const len = list.length; - - while (index < len) { - const x = list[index]; - if (predicate(x)) { - return x - } - - index++; - } - } - } - function findIndex(predicate) { return list => { const len = list.length; @@ -1931,6 +1937,7 @@ exports.equalsFn = equalsFn; exports.evolve = evolve; exports.excludes = excludes; + exports.exists = exists; exports.filter = filter; exports.filterAsync = filterAsync; exports.filterObject = filterObject; diff --git a/docs/README.md b/docs/README.md index d1aa71cf..1223e4e2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -565,7 +565,10 @@ describe('allPass', () => { [1, 2, 3, 4], [3, 4, 5], ] - const result = R.pipe(list, R.map(R.allPass([R.includes(3), R.includes(4)]))) + const result = R.pipe(list, R.map(R.allPass([ + (x) => x.length > 2, + (x) => x.includes(3) + ]))) result // $ExpectType boolean[] }) }) @@ -3388,7 +3391,7 @@ import { excludes, pipe } from 'rambda' describe('R.excludes', () => { it('happy', () => { const list = [{ a: { b: '1' } }, { a: { b: '2' } }, { a: { b: '3' } }] - const result = pipe(list, excludes({ a: { b: '1' } })) + const result = pipe({ a: { b: '1' } }, excludes(list)) result // $ExpectType boolean }) it('with string', () => { @@ -3402,6 +3405,73 @@ describe('R.excludes', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#excludes) +### exists + +```typescript + +exists(predicate: (x: T) => boolean): (list: T[]) => boolean +``` + +It returns `true` if there is at least one element in `list` that satisfy the `predicate`. + +```javascript +const predicate = x => R.type(x.foo) === 'Number' +const list = [{foo: 'bar'}, {foo: 1}] + +const result = R.exists(predicate)(list) +// => true +``` + +Try this R.exists example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +exists(predicate: (x: T) => boolean): (list: T[]) => boolean; +``` + +
+ +
+ +R.exists source + +```javascript +import { find } from './find.js' + +export function exists(predicate) { + return list => { + return find(predicate)(list) !== undefined + } +} +``` + +
+ +
+ +TypeScript test + +```typescript +import { exists, pipe } from 'rambda' + +const list = [1, 2, 3] + +describe('R.exists', () => { + it('happy', () => { + const predicate = (x: number) => x > 2 + const result = pipe(list, exists(predicate)) + result // $ExpectType boolean + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#exists) + ### filter ```typescript @@ -4905,7 +4975,7 @@ describe('R.head', () => { ```typescript -includes(list: readonly string[] | string): (substringToFind: string) => boolean +includes(list: readonly T[]): (target: T) => boolean ``` If `input` is string, then this method work as native `String.includes`. @@ -4927,8 +4997,8 @@ const result = [ All TypeScript definitions ```typescript -includes(list: readonly string[] | string): (substringToFind: string) => boolean; includes(list: readonly T[]): (target: T) => boolean; +includes(list: readonly string[] | string): (substringToFind: string) => boolean; ```
@@ -5005,28 +5075,22 @@ test('with wrong input that does not throw', () => { TypeScript test ```typescript -import { pipe, includes } from 'rambda' +import { pipe , includes} from 'rambda' describe('R.includes', () => { it('happy', () => { const list = [{ a: { b: '1' } }, { a: { b: '2' } }, { a: { b: '3' } }] - const result = pipe(list, includes({ a: { b: '1' } })) + const result = pipe({ a: { b: '1' } }, includes(list)) result // $ExpectType boolean }) it('with string', () => { - const result = pipe('foo', includes('bar')) + const result = pipe('oo', includes('foo')) result // $ExpectType boolean }) it('with array of strings', () => { - const result = pipe(['1','2'], includes('1')) + const result = pipe('1', includes(['1','2','3'])) result // $ExpectType boolean }) - it('without R.pipe', () => { - const result1 = includes('1')(['1', '2']) - const result2 = includes(1)([1, 2]) - result1 // $ExpectType boolean - result2 // $ExpectType boolean - }) }) ``` @@ -9846,9 +9910,9 @@ import { range } from 'rambda' describe('R.range', () => { it('curried', () => { - const result = range(1)(4) + const result = [range(1, 4), range(1)] - result // $ExpectType number[] + result // $ExpectType number[][] }) }) ``` diff --git a/files/index.d.ts b/files/index.d.ts index 078606ee..a83c3d53 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -568,7 +568,7 @@ Notes: */ // @SINGLE_MARKER -export function find(predicate: (x: T) => boolean): (list: T[]) => T | undefined; +export function exists(predicate: (x: T) => boolean): (list: T[]) => boolean; /* Method: findNth @@ -789,8 +789,8 @@ Notes: */ // @SINGLE_MARKER -export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; export function includes(list: readonly T[]): (target: T) => boolean; +export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; /* Method: excludes diff --git a/index.d.cts b/index.d.cts index e773f0db..16a50a42 100644 --- a/index.d.cts +++ b/index.d.cts @@ -335,6 +335,11 @@ export function evolve(rules: { export function excludes(list: readonly string[] | string): (substringToFind: string) => boolean; export function excludes(list: readonly T[]): (target: T) => boolean; +/** + * It returns `true` if there is at least one element in `list` that satisfy the `predicate`. + */ +export function exists(predicate: (x: T) => boolean): (list: T[]) => boolean; + /** * It filters list or object `input` using a `predicate` function. */ @@ -437,8 +442,8 @@ export function head(listOrString: T): T extends string ? string : * * If `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list. */ -export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; export function includes(list: readonly T[]): (target: T) => boolean; +export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; /** * It transforms list of objects to object using specified property as the base for the returned object. diff --git a/index.d.ts b/index.d.ts index e773f0db..16a50a42 100644 --- a/index.d.ts +++ b/index.d.ts @@ -335,6 +335,11 @@ export function evolve(rules: { export function excludes(list: readonly string[] | string): (substringToFind: string) => boolean; export function excludes(list: readonly T[]): (target: T) => boolean; +/** + * It returns `true` if there is at least one element in `list` that satisfy the `predicate`. + */ +export function exists(predicate: (x: T) => boolean): (list: T[]) => boolean; + /** * It filters list or object `input` using a `predicate` function. */ @@ -437,8 +442,8 @@ export function head(listOrString: T): T extends string ? string : * * If `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list. */ -export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; export function includes(list: readonly T[]): (target: T) => boolean; +export function includes(list: readonly string[] | string): (substringToFind: string) => boolean; /** * It transforms list of objects to object using specified property as the base for the returned object. diff --git a/rambda.js b/rambda.js index 43e3c512..51adfb45 100644 --- a/rambda.js +++ b/rambda.js @@ -29,6 +29,7 @@ export * from './src/eqProps.js' export * from './src/equals.js' export * from './src/evolve.js' export * from './src/excludes.js' +export * from './src/exists.js' export * from './src/filter.js' export * from './src/filterAsync.js' export * from './src/filterObject.js' diff --git a/source/allPass-spec.ts b/source/allPass-spec.ts index e042d9c7..a3bc1b76 100644 --- a/source/allPass-spec.ts +++ b/source/allPass-spec.ts @@ -6,7 +6,10 @@ describe('allPass', () => { [1, 2, 3, 4], [3, 4, 5], ] - const result = R.pipe(list, R.map(R.allPass([R.includes(3), R.includes(4)]))) + const result = R.pipe(list, R.map(R.allPass([ + (x) => x.length > 2, + (x) => x.includes(3) + ]))) result // $ExpectType boolean[] }) }) diff --git a/source/excludes-spec.ts b/source/excludes-spec.ts index 68ed8cf6..1852c380 100644 --- a/source/excludes-spec.ts +++ b/source/excludes-spec.ts @@ -3,7 +3,7 @@ import { excludes, pipe } from 'rambda' describe('R.excludes', () => { it('happy', () => { const list = [{ a: { b: '1' } }, { a: { b: '2' } }, { a: { b: '3' } }] - const result = pipe(list, excludes({ a: { b: '1' } })) + const result = pipe({ a: { b: '1' } }, excludes(list)) result // $ExpectType boolean }) it('with string', () => { diff --git a/source/includes-spec.ts b/source/includes-spec.ts index cc696b27..c43b72fb 100644 --- a/source/includes-spec.ts +++ b/source/includes-spec.ts @@ -1,23 +1,17 @@ -import { pipe, includes } from 'rambda' +import { pipe , includes} from 'rambda' describe('R.includes', () => { it('happy', () => { const list = [{ a: { b: '1' } }, { a: { b: '2' } }, { a: { b: '3' } }] - const result = pipe(list, includes({ a: { b: '1' } })) + const result = pipe({ a: { b: '1' } }, includes(list)) result // $ExpectType boolean }) it('with string', () => { - const result = pipe('foo', includes('bar')) + const result = pipe('oo', includes('foo')) result // $ExpectType boolean }) it('with array of strings', () => { - const result = pipe(['1','2'], includes('1')) + const result = pipe('1', includes(['1','2','3'])) result // $ExpectType boolean }) - it('without R.pipe', () => { - const result1 = includes('1')(['1', '2']) - const result2 = includes(1)([1, 2]) - result1 // $ExpectType boolean - result2 // $ExpectType boolean - }) }) diff --git a/source/range-spec.ts b/source/range-spec.ts index a1edf33d..40bcf85e 100644 --- a/source/range-spec.ts +++ b/source/range-spec.ts @@ -2,8 +2,8 @@ import { range } from 'rambda' describe('R.range', () => { it('curried', () => { - const result = range(1)(4) + const result = [range(1, 4), range(1)] - result // $ExpectType number[] + result // $ExpectType number[][] }) }) diff --git a/src/exists.js b/src/exists.js new file mode 100644 index 00000000..8094ee41 --- /dev/null +++ b/src/exists.js @@ -0,0 +1,7 @@ +import { find } from './find.js' + +export function exists(predicate) { + return list => { + return find(predicate)(list) !== undefined + } +} From 334464991c3d80abdca2019e633446d8e20eb2ee Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Tue, 23 Dec 2025 21:01:36 +0200 Subject: [PATCH 41/54] chore@small --- CHANGELOG.md | 2 -- README.md | 29 +++++++++++++++++++++++++---- docs/README.md | 29 +++++++++++++++++++++++++---- files/index.d.ts | 2 +- index.d.cts | 2 +- index.d.ts | 2 +- source/exists.spec.js | 14 ++++++++++++++ 7 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 source/exists.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bd980e4..b8848428 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,6 @@ - R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. -10.3.5 - - Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. 10.3.4 diff --git a/README.md b/README.md index 1223e4e2..9682287e 100644 --- a/README.md +++ b/README.md @@ -3452,6 +3452,29 @@ export function exists(predicate) {
+Tests + +```javascript +import { exists } from './exists.js' +import { propEq } from './propEq.js' + +const list = [{ a: 1 }, { a: 2 }, { a: 3 }] + +test('happy', () => { + const fn = propEq(2, 'a') + expect(exists(fn)(list)).toBe(true) +}) + +test('nothing is found', () => { + const fn = propEq(4, 'a') + expect(exists(fn)(list)).toBe(false) +}) +``` + +
+ +
+ TypeScript test ```typescript @@ -11582,7 +11605,7 @@ describe('R.splitEvery', () => { ```typescript -symmetricDifference(list: T[]): (list: T[]) => T[] +symmetricDifference(x: T[]): (y: T[]) => T[] ``` It returns all items that are in either of the lists, but not in both. @@ -11604,7 +11627,7 @@ const result = R.symmetricDifference(x)(y) All TypeScript definitions ```typescript -symmetricDifference(list: T[]): (list: T[]) => T[]; +symmetricDifference(x: T[]): (y: T[]) => T[]; ```
@@ -13981,8 +14004,6 @@ describe('R.zipWith', () => { - R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. -10.3.5 - - Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. 10.3.4 diff --git a/docs/README.md b/docs/README.md index 1223e4e2..9682287e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3452,6 +3452,29 @@ export function exists(predicate) {
+Tests + +```javascript +import { exists } from './exists.js' +import { propEq } from './propEq.js' + +const list = [{ a: 1 }, { a: 2 }, { a: 3 }] + +test('happy', () => { + const fn = propEq(2, 'a') + expect(exists(fn)(list)).toBe(true) +}) + +test('nothing is found', () => { + const fn = propEq(4, 'a') + expect(exists(fn)(list)).toBe(false) +}) +``` + +
+ +
+ TypeScript test ```typescript @@ -11582,7 +11605,7 @@ describe('R.splitEvery', () => { ```typescript -symmetricDifference(list: T[]): (list: T[]) => T[] +symmetricDifference(x: T[]): (y: T[]) => T[] ``` It returns all items that are in either of the lists, but not in both. @@ -11604,7 +11627,7 @@ const result = R.symmetricDifference(x)(y) All TypeScript definitions ```typescript -symmetricDifference(list: T[]): (list: T[]) => T[]; +symmetricDifference(x: T[]): (y: T[]) => T[]; ```
@@ -13981,8 +14004,6 @@ describe('R.zipWith', () => { - R.rangeDescending - it accepts one or two arguments. If one argument is passed, it is considered as start value, and end is 0. -10.3.5 - - Fix `R.filter(Boolean)` to handle filter of `false`, not only nullable values. 10.3.4 diff --git a/files/index.d.ts b/files/index.d.ts index a83c3d53..26ac4d31 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -3070,7 +3070,7 @@ Notes: */ // @SINGLE_MARKER -export function symmetricDifference(list: T[]): (list: T[]) => T[]; +export function symmetricDifference(x: T[]): (y: T[]) => T[]; /* Method: tail diff --git a/index.d.cts b/index.d.cts index 16a50a42..15ca919e 100644 --- a/index.d.cts +++ b/index.d.cts @@ -2213,7 +2213,7 @@ export function splitEvery(sliceLength: number): (input: T[]) => (T[])[]; * * `R.equals` is used to determine equality. */ -export function symmetricDifference(list: T[]): (list: T[]) => T[]; +export function symmetricDifference(x: T[]): (y: T[]) => T[]; /** * It returns all but the first element of `input`. diff --git a/index.d.ts b/index.d.ts index 16a50a42..15ca919e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -2213,7 +2213,7 @@ export function splitEvery(sliceLength: number): (input: T[]) => (T[])[]; * * `R.equals` is used to determine equality. */ -export function symmetricDifference(list: T[]): (list: T[]) => T[]; +export function symmetricDifference(x: T[]): (y: T[]) => T[]; /** * It returns all but the first element of `input`. diff --git a/source/exists.spec.js b/source/exists.spec.js new file mode 100644 index 00000000..6aee30ac --- /dev/null +++ b/source/exists.spec.js @@ -0,0 +1,14 @@ +import { exists } from './exists.js' +import { propEq } from './propEq.js' + +const list = [{ a: 1 }, { a: 2 }, { a: 3 }] + +test('happy', () => { + const fn = propEq(2, 'a') + expect(exists(fn)(list)).toBe(true) +}) + +test('nothing is found', () => { + const fn = propEq(4, 'a') + expect(exists(fn)(list)).toBe(false) +}) From 497854bba6ed497731c005bd16127b615fa40a1c Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 24 Dec 2025 00:25:45 +0200 Subject: [PATCH 42/54] chore@small --- CHANGELOG.md | 4 ++++ README.md | 34 +++++++++++++++++++--------------- dist/rambda.cjs | 8 ++++---- dist/rambda.js | 8 ++++---- dist/rambda.umd.js | 8 ++++---- docs/README.md | 34 +++++++++++++++++++--------------- source/excludes.js | 4 ++-- source/excludes.spec.js | 8 ++++---- source/includes.js | 4 ++-- source/includes.spec.js | 16 ++++++++-------- src/excludes.js | 4 ++-- src/includes.js | 4 ++-- 12 files changed, 74 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8848428..6b37beea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +11.0.1 + +- Add missing JS change for `R.includes` and `R.excludes` methods in `11.0.0` release. + 11.0.0 - Breaking change: `R.includes` and `R.excludes` now accept list as first argument and value to search as second argument. This makes it more useful when used with `R.filter` and `R.reject`. diff --git a/README.md b/README.md index 9682287e..9513f660 100644 --- a/README.md +++ b/README.md @@ -3350,8 +3350,8 @@ excludes(list: readonly T[]): (target: T) => boolean; ```javascript import { includes } from './includes.js' -export function excludes(valueToFind) { - return iterable => !includes(valueToFind)(iterable) +export function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) } ``` @@ -3367,15 +3367,15 @@ import { excludes } from './excludes.js' test('excludes with string', () => { const str = 'more is less' - expect(excludes('less')(str)).toBeFalsy() - expect(excludes('never')(str)).toBeTruthy() + expect(excludes(str)('less')).toBeFalsy() + expect(excludes(str)('never')).toBeTruthy() }) test('excludes with array', () => { const arr = [1, 2, 3] - expect(excludes(2)(arr)).toBeFalsy() - expect(excludes(4)(arr)).toBeTruthy() + expect(excludes(arr)(2)).toBeFalsy() + expect(excludes(arr)(4)).toBeTruthy() }) ``` @@ -5034,8 +5034,8 @@ includes(list: readonly string[] | string): (substringToFind: string) => boolean import { isArray } from './_internals/isArray.js' import { _indexOf } from './equals.js' -export function includes(valueToFind) { - return iterable => { +export function includes(iterable) { + return valueToFind => { if (typeof iterable === 'string') { return iterable.includes(valueToFind) } @@ -5063,30 +5063,30 @@ import { includes } from './includes.js' test('with string as iterable', () => { const str = 'foo bar' - expect(includes('bar')(str)).toBeTruthy() - expect(includes('never')(str)).toBeFalsy() + expect(includes(str)('foo')).toBeTruthy() + expect(includes(str)('never')).toBeFalsy() }) test('with array as iterable', () => { const arr = [1, 2, 3] - expect(includes(2)(arr)).toBeTruthy() - expect(includes(4)(arr)).toBeFalsy() + expect(includes(arr)(2)).toBeTruthy() + expect(includes(arr)(4)).toBeFalsy() }) test('with list of objects as iterable', () => { const arr = [{ a: 1 }, { b: 2 }, { c: 3 }] - expect(includes({ c: 3 })(arr)).toBeTruthy() + expect(includes(arr)({ c: 3 })).toBeTruthy() }) test('with NaN', () => { - const result = includes(Number.NaN)([Number.NaN]) + const result = includes([Number.NaN])(Number.NaN) expect(result).toBeTruthy() }) test('with wrong input that does not throw', () => { - const result = includes(1)(/foo/g) + const result = includes([1])(/foo/g) expect(result).toBeFalsy() }) ``` @@ -13982,6 +13982,10 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +11.0.1 + +- Add missing JS change for `R.includes` and `R.excludes` methods in `11.0.0` release. + 11.0.0 - Breaking change: `R.includes` and `R.excludes` now accept list as first argument and value to search as second argument. This makes it more useful when used with `R.filter` and `R.reject`. diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 999bcce3..5efdd4a6 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -481,8 +481,8 @@ function equals(a) { return b => equalsFn(a, b) } -function includes(valueToFind) { - return iterable => { +function includes(iterable) { + return valueToFind => { if (typeof iterable === 'string') { return iterable.includes(valueToFind) } @@ -636,8 +636,8 @@ function evolve(rules) { return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } -function excludes(valueToFind) { - return iterable => !includes(valueToFind)(iterable) +function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) } function find(predicate) { diff --git a/dist/rambda.js b/dist/rambda.js index 731667f3..dc2c8c40 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -479,8 +479,8 @@ function equals(a) { return b => equalsFn(a, b) } -function includes(valueToFind) { - return iterable => { +function includes(iterable) { + return valueToFind => { if (typeof iterable === 'string') { return iterable.includes(valueToFind) } @@ -634,8 +634,8 @@ function evolve(rules) { return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } -function excludes(valueToFind) { - return iterable => !includes(valueToFind)(iterable) +function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) } function find(predicate) { diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index ce93fa93..afbb4626 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -485,8 +485,8 @@ return b => equalsFn(a, b) } - function includes(valueToFind) { - return iterable => { + function includes(iterable) { + return valueToFind => { if (typeof iterable === 'string') { return iterable.includes(valueToFind) } @@ -640,8 +640,8 @@ return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } - function excludes(valueToFind) { - return iterable => !includes(valueToFind)(iterable) + function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) } function find(predicate) { diff --git a/docs/README.md b/docs/README.md index 9682287e..9513f660 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3350,8 +3350,8 @@ excludes(list: readonly T[]): (target: T) => boolean; ```javascript import { includes } from './includes.js' -export function excludes(valueToFind) { - return iterable => !includes(valueToFind)(iterable) +export function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) } ``` @@ -3367,15 +3367,15 @@ import { excludes } from './excludes.js' test('excludes with string', () => { const str = 'more is less' - expect(excludes('less')(str)).toBeFalsy() - expect(excludes('never')(str)).toBeTruthy() + expect(excludes(str)('less')).toBeFalsy() + expect(excludes(str)('never')).toBeTruthy() }) test('excludes with array', () => { const arr = [1, 2, 3] - expect(excludes(2)(arr)).toBeFalsy() - expect(excludes(4)(arr)).toBeTruthy() + expect(excludes(arr)(2)).toBeFalsy() + expect(excludes(arr)(4)).toBeTruthy() }) ``` @@ -5034,8 +5034,8 @@ includes(list: readonly string[] | string): (substringToFind: string) => boolean import { isArray } from './_internals/isArray.js' import { _indexOf } from './equals.js' -export function includes(valueToFind) { - return iterable => { +export function includes(iterable) { + return valueToFind => { if (typeof iterable === 'string') { return iterable.includes(valueToFind) } @@ -5063,30 +5063,30 @@ import { includes } from './includes.js' test('with string as iterable', () => { const str = 'foo bar' - expect(includes('bar')(str)).toBeTruthy() - expect(includes('never')(str)).toBeFalsy() + expect(includes(str)('foo')).toBeTruthy() + expect(includes(str)('never')).toBeFalsy() }) test('with array as iterable', () => { const arr = [1, 2, 3] - expect(includes(2)(arr)).toBeTruthy() - expect(includes(4)(arr)).toBeFalsy() + expect(includes(arr)(2)).toBeTruthy() + expect(includes(arr)(4)).toBeFalsy() }) test('with list of objects as iterable', () => { const arr = [{ a: 1 }, { b: 2 }, { c: 3 }] - expect(includes({ c: 3 })(arr)).toBeTruthy() + expect(includes(arr)({ c: 3 })).toBeTruthy() }) test('with NaN', () => { - const result = includes(Number.NaN)([Number.NaN]) + const result = includes([Number.NaN])(Number.NaN) expect(result).toBeTruthy() }) test('with wrong input that does not throw', () => { - const result = includes(1)(/foo/g) + const result = includes([1])(/foo/g) expect(result).toBeFalsy() }) ``` @@ -13982,6 +13982,10 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +11.0.1 + +- Add missing JS change for `R.includes` and `R.excludes` methods in `11.0.0` release. + 11.0.0 - Breaking change: `R.includes` and `R.excludes` now accept list as first argument and value to search as second argument. This makes it more useful when used with `R.filter` and `R.reject`. diff --git a/source/excludes.js b/source/excludes.js index 403f668a..40b82a63 100644 --- a/source/excludes.js +++ b/source/excludes.js @@ -1,5 +1,5 @@ import { includes } from './includes.js' -export function excludes(valueToFind) { - return iterable => !includes(valueToFind)(iterable) +export function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) } diff --git a/source/excludes.spec.js b/source/excludes.spec.js index ec72d1e4..fc0e34c5 100644 --- a/source/excludes.spec.js +++ b/source/excludes.spec.js @@ -3,13 +3,13 @@ import { excludes } from './excludes.js' test('excludes with string', () => { const str = 'more is less' - expect(excludes('less')(str)).toBeFalsy() - expect(excludes('never')(str)).toBeTruthy() + expect(excludes(str)('less')).toBeFalsy() + expect(excludes(str)('never')).toBeTruthy() }) test('excludes with array', () => { const arr = [1, 2, 3] - expect(excludes(2)(arr)).toBeFalsy() - expect(excludes(4)(arr)).toBeTruthy() + expect(excludes(arr)(2)).toBeFalsy() + expect(excludes(arr)(4)).toBeTruthy() }) diff --git a/source/includes.js b/source/includes.js index b10e87f6..e2854e47 100644 --- a/source/includes.js +++ b/source/includes.js @@ -1,8 +1,8 @@ import { isArray } from './_internals/isArray.js' import { _indexOf } from './equals.js' -export function includes(valueToFind) { - return iterable => { +export function includes(iterable) { + return valueToFind => { if (typeof iterable === 'string') { return iterable.includes(valueToFind) } diff --git a/source/includes.spec.js b/source/includes.spec.js index 5474b870..e8ca17c4 100644 --- a/source/includes.spec.js +++ b/source/includes.spec.js @@ -3,29 +3,29 @@ import { includes } from './includes.js' test('with string as iterable', () => { const str = 'foo bar' - expect(includes('bar')(str)).toBeTruthy() - expect(includes('never')(str)).toBeFalsy() + expect(includes(str)('foo')).toBeTruthy() + expect(includes(str)('never')).toBeFalsy() }) test('with array as iterable', () => { const arr = [1, 2, 3] - expect(includes(2)(arr)).toBeTruthy() - expect(includes(4)(arr)).toBeFalsy() + expect(includes(arr)(2)).toBeTruthy() + expect(includes(arr)(4)).toBeFalsy() }) test('with list of objects as iterable', () => { const arr = [{ a: 1 }, { b: 2 }, { c: 3 }] - expect(includes({ c: 3 })(arr)).toBeTruthy() + expect(includes(arr)({ c: 3 })).toBeTruthy() }) test('with NaN', () => { - const result = includes(Number.NaN)([Number.NaN]) + const result = includes([Number.NaN])(Number.NaN) expect(result).toBeTruthy() }) test('with wrong input that does not throw', () => { - const result = includes(1)(/foo/g) + const result = includes([1])(/foo/g) expect(result).toBeFalsy() -}) +}) \ No newline at end of file diff --git a/src/excludes.js b/src/excludes.js index 403f668a..40b82a63 100644 --- a/src/excludes.js +++ b/src/excludes.js @@ -1,5 +1,5 @@ import { includes } from './includes.js' -export function excludes(valueToFind) { - return iterable => !includes(valueToFind)(iterable) +export function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) } diff --git a/src/includes.js b/src/includes.js index b10e87f6..e2854e47 100644 --- a/src/includes.js +++ b/src/includes.js @@ -1,8 +1,8 @@ import { isArray } from './_internals/isArray.js' import { _indexOf } from './equals.js' -export function includes(valueToFind) { - return iterable => { +export function includes(iterable) { + return valueToFind => { if (typeof iterable === 'string') { return iterable.includes(valueToFind) } From 657ef80bab3e5739f5416a41560c311b2772895a Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 24 Dec 2025 00:38:02 +0200 Subject: [PATCH 43/54] chore@small --- README.md | 15 +++++++-------- dist/rambda.cjs | 16 ++++++++-------- dist/rambda.js | 16 ++++++++-------- dist/rambda.umd.js | 16 ++++++++-------- docs/README.md | 15 +++++++-------- source/allPass.spec.js | 5 ++--- source/difference.js | 10 +++++----- src/difference.js | 10 +++++----- 8 files changed, 50 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 9513f660..ca772d09 100644 --- a/README.md +++ b/README.md @@ -532,7 +532,6 @@ export function allPass(predicates) { ```javascript import { allPass } from './allPass.js' import { filter } from './filter.js' -import { includes } from './includes.js' import { pipe } from './pipe.js' const list = [ @@ -540,12 +539,12 @@ const list = [ [3, 4, 5], ] test('happy', () => { - const result = pipe(list, filter(allPass([includes(2), includes(3)]))) + const result = pipe(list, filter(allPass([x => x.includes(2), x => x.includes(3)]))) expect(result).toEqual([[1, 2, 3, 4]]) }) test('when returns false', () => { - const result = pipe(list, filter(allPass([includes(12), includes(31)]))) + const result = pipe(list, filter(allPass([x => x.includes(12), x => x.includes(31)]))) expect(result).toEqual([]) }) ``` @@ -2029,12 +2028,12 @@ difference(x: T[]): (y: T[]) => T[]; ```javascript import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function difference(x) { - return y => ([ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), +export function difference(listA) { + return listB => ([ + ...filter(value => excludes(listB)(value))(listA), + ...filter(value => excludes(listA)(value))(listB), ]) } ``` diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 5efdd4a6..da800805 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -497,10 +497,14 @@ function includes(iterable) { } } -function difference(x) { - return y => ([ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), +function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) +} + +function difference(listA) { + return listB => ([ + ...filter(value => excludes(listB)(value))(listA), + ...filter(value => excludes(listA)(value))(listB), ]) } @@ -636,10 +640,6 @@ function evolve(rules) { return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } -function excludes(iterable) { - return valueToFind => !includes(iterable)(valueToFind) -} - function find(predicate) { return list => { let index = 0; diff --git a/dist/rambda.js b/dist/rambda.js index dc2c8c40..0ef3907c 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -495,10 +495,14 @@ function includes(iterable) { } } -function difference(x) { - return y => ([ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), +function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) +} + +function difference(listA) { + return listB => ([ + ...filter(value => excludes(listB)(value))(listA), + ...filter(value => excludes(listA)(value))(listB), ]) } @@ -634,10 +638,6 @@ function evolve(rules) { return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } -function excludes(iterable) { - return valueToFind => !includes(iterable)(valueToFind) -} - function find(predicate) { return list => { let index = 0; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index afbb4626..14cf9696 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -501,10 +501,14 @@ } } - function difference(x) { - return y => ([ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), + function excludes(iterable) { + return valueToFind => !includes(iterable)(valueToFind) + } + + function difference(listA) { + return listB => ([ + ...filter(value => excludes(listB)(value))(listA), + ...filter(value => excludes(listA)(value))(listB), ]) } @@ -640,10 +644,6 @@ return mapObject((x, prop) => type(rules[prop]) === 'Function' ? rules[prop](x): x) } - function excludes(iterable) { - return valueToFind => !includes(iterable)(valueToFind) - } - function find(predicate) { return list => { let index = 0; diff --git a/docs/README.md b/docs/README.md index 9513f660..ca772d09 100644 --- a/docs/README.md +++ b/docs/README.md @@ -532,7 +532,6 @@ export function allPass(predicates) { ```javascript import { allPass } from './allPass.js' import { filter } from './filter.js' -import { includes } from './includes.js' import { pipe } from './pipe.js' const list = [ @@ -540,12 +539,12 @@ const list = [ [3, 4, 5], ] test('happy', () => { - const result = pipe(list, filter(allPass([includes(2), includes(3)]))) + const result = pipe(list, filter(allPass([x => x.includes(2), x => x.includes(3)]))) expect(result).toEqual([[1, 2, 3, 4]]) }) test('when returns false', () => { - const result = pipe(list, filter(allPass([includes(12), includes(31)]))) + const result = pipe(list, filter(allPass([x => x.includes(12), x => x.includes(31)]))) expect(result).toEqual([]) }) ``` @@ -2029,12 +2028,12 @@ difference(x: T[]): (y: T[]) => T[]; ```javascript import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function difference(x) { - return y => ([ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), +export function difference(listA) { + return listB => ([ + ...filter(value => excludes(listB)(value))(listA), + ...filter(value => excludes(listA)(value))(listB), ]) } ``` diff --git a/source/allPass.spec.js b/source/allPass.spec.js index 2487f88d..1566af05 100644 --- a/source/allPass.spec.js +++ b/source/allPass.spec.js @@ -1,6 +1,5 @@ import { allPass } from './allPass.js' import { filter } from './filter.js' -import { includes } from './includes.js' import { pipe } from './pipe.js' const list = [ @@ -8,11 +7,11 @@ const list = [ [3, 4, 5], ] test('happy', () => { - const result = pipe(list, filter(allPass([includes(2), includes(3)]))) + const result = pipe(list, filter(allPass([x => x.includes(2), x => x.includes(3)]))) expect(result).toEqual([[1, 2, 3, 4]]) }) test('when returns false', () => { - const result = pipe(list, filter(allPass([includes(12), includes(31)]))) + const result = pipe(list, filter(allPass([x => x.includes(12), x => x.includes(31)]))) expect(result).toEqual([]) }) diff --git a/source/difference.js b/source/difference.js index 64af0b8e..86bfc8a5 100644 --- a/source/difference.js +++ b/source/difference.js @@ -1,9 +1,9 @@ import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function difference(x) { - return y => ([ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), +export function difference(listA) { + return listB => ([ + ...filter(value => excludes(listB)(value))(listA), + ...filter(value => excludes(listA)(value))(listB), ]) } diff --git a/src/difference.js b/src/difference.js index 64af0b8e..86bfc8a5 100644 --- a/src/difference.js +++ b/src/difference.js @@ -1,9 +1,9 @@ import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function difference(x) { - return y => ([ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), +export function difference(listA) { + return listB => ([ + ...filter(value => excludes(listB)(value))(listA), + ...filter(value => excludes(listA)(value))(listB), ]) } From 8a20f3cfa6383405ad27a39eee075773ec3aa60f Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 24 Dec 2025 00:50:04 +0200 Subject: [PATCH 44/54] chore@small --- README.md | 36 ++++++++++++------------------ dist/rambda.cjs | 29 +++++++++--------------- dist/rambda.js | 29 +++++++++--------------- dist/rambda.umd.js | 29 +++++++++--------------- docs/README.md | 36 ++++++++++++------------------ source/intersection.js | 2 +- source/symmetricDifference.js | 12 +++++----- source/symmetricDifference.spec.js | 2 +- source/union.js | 20 +++++------------ src/intersection.js | 2 +- src/symmetricDifference.js | 12 +++++----- src/union.js | 20 +++++------------ 12 files changed, 88 insertions(+), 141 deletions(-) diff --git a/README.md b/README.md index ca772d09..491e04c2 100644 --- a/README.md +++ b/README.md @@ -5572,7 +5572,7 @@ import { filter } from './filter.js' import { includes } from './includes.js' export function intersection(listA) { - return listB => filter(x => includes(x)(listA))(listB) + return listB => filter(includes(listA))(listB) } ``` @@ -11637,13 +11637,13 @@ symmetricDifference(x: T[]): (y: T[]) => T[]; ```javascript import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function symmetricDifference(x) { - return y => [ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), - ] +export function symmetricDifference(listA) { + return listB => [ + ...filter(excludes(listB))(listA), + ...filter(excludes(listA))(listB), + ] } ``` @@ -11656,7 +11656,7 @@ export function symmetricDifference(x) { ```javascript import { symmetricDifference } from './symmetricDifference.js' -test('symmetricDifference', () => { +test.only('symmetricDifference', () => { const list1 = [1, 2, 3, 4] const list2 = [3, 4, 5, 6] expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6]) @@ -12776,21 +12776,13 @@ union(x: T[]): (y: T[]) => T[]; R.union source ```javascript -import { cloneList } from './_internals/cloneList.js' -import { includes } from './includes.js' - -export function union(x) { - return y => { - const toReturn = cloneList(x) - - y.forEach(yInstance => { - if (!includes(yInstance)(x)) { - toReturn.push(yInstance) - } - }) +import { excludes } from './excludes.js' - return toReturn - } +export function union(listA) { + return listB => [ + ...listA, + ...listB.filter(excludes(listA)), + ] } ``` diff --git a/dist/rambda.cjs b/dist/rambda.cjs index da800805..9e439af6 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -951,7 +951,7 @@ function interpolate(input) { } function intersection(listA) { - return listB => filter(x => includes(x)(listA))(listB) + return listB => filter(includes(listA))(listB) } function _includesWith(pred, x, list) { @@ -1669,11 +1669,11 @@ function splitEvery(sliceLength) { } } -function symmetricDifference(x) { - return y => [ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), - ] +function symmetricDifference(listA) { + return listB => [ + ...filter(excludes(listB))(listA), + ...filter(excludes(listA))(listB), + ] } function tail(listOrString) { @@ -1770,18 +1770,11 @@ function tryCatch(fn, fallback) { } } -function union(x) { - return y => { - const toReturn = cloneList(x); - - y.forEach(yInstance => { - if (!includes(yInstance)(x)) { - toReturn.push(yInstance); - } - }); - - return toReturn - } +function union(listA) { + return listB => [ + ...listA, + ...listB.filter(excludes(listA)), + ] } function unionWith(predicate, x) { diff --git a/dist/rambda.js b/dist/rambda.js index 0ef3907c..c87c3ebb 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -949,7 +949,7 @@ function interpolate(input) { } function intersection(listA) { - return listB => filter(x => includes(x)(listA))(listB) + return listB => filter(includes(listA))(listB) } function _includesWith(pred, x, list) { @@ -1667,11 +1667,11 @@ function splitEvery(sliceLength) { } } -function symmetricDifference(x) { - return y => [ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), - ] +function symmetricDifference(listA) { + return listB => [ + ...filter(excludes(listB))(listA), + ...filter(excludes(listA))(listB), + ] } function tail(listOrString) { @@ -1768,18 +1768,11 @@ function tryCatch(fn, fallback) { } } -function union(x) { - return y => { - const toReturn = cloneList(x); - - y.forEach(yInstance => { - if (!includes(yInstance)(x)) { - toReturn.push(yInstance); - } - }); - - return toReturn - } +function union(listA) { + return listB => [ + ...listA, + ...listB.filter(excludes(listA)), + ] } function unionWith(predicate, x) { diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index 14cf9696..8b932614 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -955,7 +955,7 @@ } function intersection(listA) { - return listB => filter(x => includes(x)(listA))(listB) + return listB => filter(includes(listA))(listB) } function _includesWith(pred, x, list) { @@ -1673,11 +1673,11 @@ } } - function symmetricDifference(x) { - return y => [ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), - ] + function symmetricDifference(listA) { + return listB => [ + ...filter(excludes(listB))(listA), + ...filter(excludes(listA))(listB), + ] } function tail(listOrString) { @@ -1774,18 +1774,11 @@ } } - function union(x) { - return y => { - const toReturn = cloneList(x); - - y.forEach(yInstance => { - if (!includes(yInstance)(x)) { - toReturn.push(yInstance); - } - }); - - return toReturn - } + function union(listA) { + return listB => [ + ...listA, + ...listB.filter(excludes(listA)), + ] } function unionWith(predicate, x) { diff --git a/docs/README.md b/docs/README.md index ca772d09..491e04c2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5572,7 +5572,7 @@ import { filter } from './filter.js' import { includes } from './includes.js' export function intersection(listA) { - return listB => filter(x => includes(x)(listA))(listB) + return listB => filter(includes(listA))(listB) } ``` @@ -11637,13 +11637,13 @@ symmetricDifference(x: T[]): (y: T[]) => T[]; ```javascript import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function symmetricDifference(x) { - return y => [ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), - ] +export function symmetricDifference(listA) { + return listB => [ + ...filter(excludes(listB))(listA), + ...filter(excludes(listA))(listB), + ] } ``` @@ -11656,7 +11656,7 @@ export function symmetricDifference(x) { ```javascript import { symmetricDifference } from './symmetricDifference.js' -test('symmetricDifference', () => { +test.only('symmetricDifference', () => { const list1 = [1, 2, 3, 4] const list2 = [3, 4, 5, 6] expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6]) @@ -12776,21 +12776,13 @@ union(x: T[]): (y: T[]) => T[]; R.union source ```javascript -import { cloneList } from './_internals/cloneList.js' -import { includes } from './includes.js' - -export function union(x) { - return y => { - const toReturn = cloneList(x) - - y.forEach(yInstance => { - if (!includes(yInstance)(x)) { - toReturn.push(yInstance) - } - }) +import { excludes } from './excludes.js' - return toReturn - } +export function union(listA) { + return listB => [ + ...listA, + ...listB.filter(excludes(listA)), + ] } ``` diff --git a/source/intersection.js b/source/intersection.js index 9d696eef..ea348283 100644 --- a/source/intersection.js +++ b/source/intersection.js @@ -2,5 +2,5 @@ import { filter } from './filter.js' import { includes } from './includes.js' export function intersection(listA) { - return listB => filter(x => includes(x)(listA))(listB) + return listB => filter(includes(listA))(listB) } diff --git a/source/symmetricDifference.js b/source/symmetricDifference.js index 8915fdca..1dd5759e 100644 --- a/source/symmetricDifference.js +++ b/source/symmetricDifference.js @@ -1,9 +1,9 @@ import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function symmetricDifference(x) { - return y => [ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), - ] +export function symmetricDifference(listA) { + return listB => [ + ...filter(excludes(listB))(listA), + ...filter(excludes(listA))(listB), + ] } diff --git a/source/symmetricDifference.spec.js b/source/symmetricDifference.spec.js index 303970f1..d7808d67 100644 --- a/source/symmetricDifference.spec.js +++ b/source/symmetricDifference.spec.js @@ -1,6 +1,6 @@ import { symmetricDifference } from './symmetricDifference.js' -test('symmetricDifference', () => { +test.only('symmetricDifference', () => { const list1 = [1, 2, 3, 4] const list2 = [3, 4, 5, 6] expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6]) diff --git a/source/union.js b/source/union.js index 9e4159a5..d7aeb952 100644 --- a/source/union.js +++ b/source/union.js @@ -1,16 +1,8 @@ -import { cloneList } from './_internals/cloneList.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function union(x) { - return y => { - const toReturn = cloneList(x) - - y.forEach(yInstance => { - if (!includes(yInstance)(x)) { - toReturn.push(yInstance) - } - }) - - return toReturn - } +export function union(listA) { + return listB => [ + ...listA, + ...listB.filter(excludes(listA)), + ] } diff --git a/src/intersection.js b/src/intersection.js index 9d696eef..ea348283 100644 --- a/src/intersection.js +++ b/src/intersection.js @@ -2,5 +2,5 @@ import { filter } from './filter.js' import { includes } from './includes.js' export function intersection(listA) { - return listB => filter(x => includes(x)(listA))(listB) + return listB => filter(includes(listA))(listB) } diff --git a/src/symmetricDifference.js b/src/symmetricDifference.js index 8915fdca..1dd5759e 100644 --- a/src/symmetricDifference.js +++ b/src/symmetricDifference.js @@ -1,9 +1,9 @@ import { filter } from './filter.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function symmetricDifference(x) { - return y => [ - ...filter(value => !includes(value)(y))(x), - ...filter(value => !includes(value)(x))(y), - ] +export function symmetricDifference(listA) { + return listB => [ + ...filter(excludes(listB))(listA), + ...filter(excludes(listA))(listB), + ] } diff --git a/src/union.js b/src/union.js index 9e4159a5..d7aeb952 100644 --- a/src/union.js +++ b/src/union.js @@ -1,16 +1,8 @@ -import { cloneList } from './_internals/cloneList.js' -import { includes } from './includes.js' +import { excludes } from './excludes.js' -export function union(x) { - return y => { - const toReturn = cloneList(x) - - y.forEach(yInstance => { - if (!includes(yInstance)(x)) { - toReturn.push(yInstance) - } - }) - - return toReturn - } +export function union(listA) { + return listB => [ + ...listA, + ...listB.filter(excludes(listA)), + ] } From ea4a258b4dd4f8176dbeed39b9c04c65a2cd8445 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 24 Dec 2025 01:10:30 +0200 Subject: [PATCH 45/54] chore@small --- README.md | 2 +- docs/README.md | 2 +- source/symmetricDifference.spec.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 491e04c2..efed3f30 100644 --- a/README.md +++ b/README.md @@ -11656,7 +11656,7 @@ export function symmetricDifference(listA) { ```javascript import { symmetricDifference } from './symmetricDifference.js' -test.only('symmetricDifference', () => { +test('symmetricDifference', () => { const list1 = [1, 2, 3, 4] const list2 = [3, 4, 5, 6] expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6]) diff --git a/docs/README.md b/docs/README.md index 491e04c2..efed3f30 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11656,7 +11656,7 @@ export function symmetricDifference(listA) { ```javascript import { symmetricDifference } from './symmetricDifference.js' -test.only('symmetricDifference', () => { +test('symmetricDifference', () => { const list1 = [1, 2, 3, 4] const list2 = [3, 4, 5, 6] expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6]) diff --git a/source/symmetricDifference.spec.js b/source/symmetricDifference.spec.js index d7808d67..303970f1 100644 --- a/source/symmetricDifference.spec.js +++ b/source/symmetricDifference.spec.js @@ -1,6 +1,6 @@ import { symmetricDifference } from './symmetricDifference.js' -test.only('symmetricDifference', () => { +test('symmetricDifference', () => { const list1 = [1, 2, 3, 4] const list2 = [3, 4, 5, 6] expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6]) From 59f9cb29a84ca0ce7ad73a331615d883294ff6e5 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 28 Jan 2026 21:14:39 +0200 Subject: [PATCH 46/54] 1 --- CHANGELOG.md | 6 ++++++ files/index.d.ts | 42 ++++++++++++++++++++++++++++++++-------- source/filter-spec.ts | 28 +++++++++++++++++++-------- source/filterMap-spec.ts | 19 ++++++++++++++++++ source/filterMap.js | 3 +++ source/filterMap.spec.js | 7 +++++++ source/reject-spec.ts | 11 +++++++++++ 7 files changed, 100 insertions(+), 16 deletions(-) create mode 100644 source/filterMap-spec.ts create mode 100644 source/filterMap.js create mode 100644 source/filterMap.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b37beea..a70d1a50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +11.1.0 + +- Add `R.filterMap` - similar to Ruby `filter_map` + +- Add index to `R.filter`/`R.reject` predicate signiture + 11.0.1 - Add missing JS change for `R.includes` and `R.excludes` methods in `11.0.0` release. diff --git a/files/index.d.ts b/files/index.d.ts index 26ac4d31..860d2b5b 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -486,7 +486,7 @@ export function filter( predicate: BooleanConstructor, ): (list: T[]) => ExcludeFalsy[]; export function filter( - predicate: (value: T) => boolean, + predicate: (value: T, index: number) => boolean, ): (list: T[]) => T[]; /* @@ -519,7 +519,7 @@ export function reject( predicate: BooleanConstructor, ): (list: T[]) => (null | undefined)[]; export function reject( - predicate: (value: T) => boolean, + predicate: (value: T, index: number) => boolean, ): (list: T[]) => T[]; /* @@ -995,12 +995,10 @@ Explanation: It returns the result of looping through `iterable` with `fn`. Example: ``` -const fn = x => x * 2 - -const iterable = [1, 2] -const obj = {a: 1, b: 2} - -const result = R.map(fn)(iterable), +const result = R.pipe( + [1, 2], + R.map(x => x * 2) +) // => [2, 4] ``` @@ -1017,6 +1015,34 @@ export function map( fn: (value: T[number]) => U, ): (data: T) => Mapped; +/* +Method: filterMap + +Explanation: Same as `R.map` but it filters out `null/undefined` if returned from functor functions. + +Example: + +``` +const result = R.pipe( + [1, 2, 3], + R.filterMap(x => x > 1 ? x : null) +) +// => [2, 3] +``` + +Categories: List + +Notes: This function doesn't work with objects (use R.mapObject instead) + +*/ +// @SINGLE_MARKER +export function filterMap( + fn: (value: T[number], index: number) => U, +): (data: T) => Mapped>; +export function filterMap( + fn: (value: T[number]) => U, +): (data: T) => Mapped>; + /* Method: mapObject diff --git a/source/filter-spec.ts b/source/filter-spec.ts index 4013d3d4..9c9a5a2a 100644 --- a/source/filter-spec.ts +++ b/source/filter-spec.ts @@ -4,14 +4,26 @@ const list = [1, 2, 3] describe('R.filter with array', () => { it('within pipe', () => { - const _result = pipe( + const result = pipe( list, filter(x => { x // $ExpectType number return x > 1 }), ) - _result // $ExpectType number[] + result // $ExpectType number[] + }) + + it('with index', () => { + const result = pipe( + list, + filter((x: number, i: number) => { + x // $ExpectType number + i // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] }) it('complex example', () => { @@ -50,8 +62,8 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const _result = pipe(testList, filter(filterBar)) - _result // $ExpectType Bar[] + const result = pipe(testList, filter(filterBar)) + result // $ExpectType Bar[] }) it('narrowing type - readonly', () => { @@ -66,14 +78,14 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const _result = pipe(testList, filter(filterBar)) - _result // $ExpectType Bar[] + const result = pipe(testList, filter(filterBar)) + result // $ExpectType Bar[] }) it('filtering NonNullable - list of objects', () => { const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] - const _result = pipe(testList, filter(Boolean)) - _result // $ExpectType { a: number; }[] + const result = pipe(testList, filter(Boolean)) + result // $ExpectType { a: number; }[] }) it('filtering NonNullable - readonly', () => { diff --git a/source/filterMap-spec.ts b/source/filterMap-spec.ts new file mode 100644 index 00000000..54886507 --- /dev/null +++ b/source/filterMap-spec.ts @@ -0,0 +1,19 @@ +import { filterMap, pipe } from 'rambda' + +const list = [1, 2, 3] + +it('R.filterMap - within pipe', () => { + const result = pipe( + list, + x => x, + filterMap(x => { + x // $ExpectType number + return Math.random() > 0.5 ? String(x) : null + }), + filterMap(x => { + x // $ExpectType string + return Math.random() > 0.5 ? Number(x) : '' + }), + ) + result // $ExpectType number[] +}) diff --git a/source/filterMap.js b/source/filterMap.js new file mode 100644 index 00000000..c46e5157 --- /dev/null +++ b/source/filterMap.js @@ -0,0 +1,3 @@ +export function filterMap(fn) { + return list => mapFn(fn, list).filter(Boolean) +} diff --git a/source/filterMap.spec.js b/source/filterMap.spec.js new file mode 100644 index 00000000..d87a7064 --- /dev/null +++ b/source/filterMap.spec.js @@ -0,0 +1,7 @@ +import { filterMap } from './filterMap.js' + +const double = x => x > 1 ? x * 2 : null + +it('happy', () => { + expect(filterMap(double)([1, 2, 3])).toEqual([4, 6]) +}) diff --git a/source/reject-spec.ts b/source/reject-spec.ts index f43e9e49..6fa72992 100644 --- a/source/reject-spec.ts +++ b/source/reject-spec.ts @@ -12,6 +12,17 @@ describe('R.reject with array', () => { }), ) result // $ExpectType number[] + }) + it('with index', () => { + const result = pipe( + list, + reject((x: number, i: number) => { + x // $ExpectType number + i // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] }) it('narrowing type', () => { interface Foo { From 3c0de2dc01f868f26d81c4dff0326475ea1f5d32 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 12:11:11 +0200 Subject: [PATCH 47/54] R.mapchain --- CHANGELOG.md | 10 +++++ files/index.d.ts | 86 +++++++++++++++++++++++++++++++++++++++-- source/drop.js | 2 +- source/init-spec.ts | 29 +++++++++++--- source/map-spec.ts | 15 ++++++- source/mapChain-spec.ts | 60 ++++++++++++++++++++++++++++ source/mapChain.js | 11 ++++++ source/mapChain.spec.js | 7 ++++ source/middle-spec.ts | 38 ++++++++++++++++++ source/middle.js | 6 +++ source/middle.spec.js | 13 +++++++ source/tail-spec.ts | 27 +++++++++++-- 12 files changed, 289 insertions(+), 15 deletions(-) create mode 100644 source/mapChain-spec.ts create mode 100644 source/mapChain.js create mode 100644 source/mapChain.spec.js create mode 100644 source/middle-spec.ts create mode 100644 source/middle.js create mode 100644 source/middle.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index a70d1a50..9533517a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,18 @@ - Add `R.filterMap` - similar to Ruby `filter_map` +- Add `R.mapChain` - when in `R.pipe` there are several `R.map` one after the other, then `R.mapChain` can be used instead. + +- Add `R.middle` - equal to `R.init` + `R.tail` + +- Add `R.sumByProp` + +- Add `R.random`, `R.shuffle`, `R.switcher`, `R.sum`, `R.delay` - imported from `Rambda` + - Add index to `R.filter`/`R.reject` predicate signiture +- Improve typing of `R.init`, `R.tail` + 11.0.1 - Add missing JS change for `R.includes` and `R.excludes` methods in `11.0.0` release. diff --git a/files/index.d.ts b/files/index.d.ts index 860d2b5b..0710e435 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -862,8 +862,9 @@ Notes: */ // @SINGLE_MARKER -export function init(input: T): T extends readonly [...infer U, any] ? U : [...T]; -export function init(input: string): string; +export function init(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [...infer U, any] ? U : T : T extends string ? string : never; /* Method: intersection @@ -1015,6 +1016,57 @@ export function map( fn: (value: T[number]) => U, ): (data: T) => Mapped; +/* +Method: mapChain + +Explanation: Chained 2 or 3 `R.map` transformations as one. + +Example: + +``` +const result = R.pipe( + [1, 2], + R.mapChain( + x => x * 2, + x => [x, x > 3], + ) +) +// => [[2, false], [4, true]] +``` + +Categories: List + +Notes: + +*/ +// @SINGLE_MARKER +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, + fn3: (value: V, index: number) => Y, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, + fn3: (value: V) => Y, +): (data: T) => Mapped; + /* Method: filterMap @@ -3098,6 +3150,31 @@ Notes: // @SINGLE_MARKER export function symmetricDifference(x: T[]): (y: T[]) => T[]; +/* +Method: middle + +Explanation: It returns all but the first and last element of `input`. + +Example: + +``` +const result = [ + R.middle([1, 2, 3, 4]), + R.middle('bar') +] +// => [[2, 3], 'a'] +``` + +Categories: List, String + +Notes: + +*/ +// @SINGLE_MARKER +export function middle(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : T['length'] extends 2 ? [] : + T extends [any, ...infer U, any] ? U : T : T extends string ? string : never; + /* Method: tail @@ -3119,8 +3196,9 @@ Notes: */ // @SINGLE_MARKER -export function tail(input: T): T extends [any, ...infer U] ? U : [...T]; -export function tail(input: string): string; +export function tail(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [any, ...infer U] ? U : T : T extends string ? string : never; /* Method: take diff --git a/source/drop.js b/source/drop.js index 5e1ff66c..658791a9 100644 --- a/source/drop.js +++ b/source/drop.js @@ -1,3 +1,3 @@ -export function drop(howManyToDrop, ) { +export function drop(howManyToDrop) { return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) } diff --git a/source/init-spec.ts b/source/init-spec.ts index 61f0bf8c..1c5da8ac 100644 --- a/source/init-spec.ts +++ b/source/init-spec.ts @@ -1,4 +1,4 @@ -import { init } from 'rambda' +import { map, pipe, init } from 'rambda' describe('R.init', () => { it('with string', () => { @@ -6,13 +6,32 @@ describe('R.init', () => { result // $ExpectType string }) - it('with list - one type', () => { - const result = init([1, 2, 3]) - + it('with list - using const on short array', () => { + const result = pipe( + [1] as const, + map(x => x * 2), + init, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + init, + ) result // $ExpectType number[] }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3] as const, + map(x => x * 2), + init, + ) + result // $ExpectType [number, number] + }) it('with list - mixed types', () => { - const result = init([1, 2, 3, 'foo', 'bar']) + const result = init(['foo', 'bar', 1, 2, 3]) result // $ExpectType (string | number)[] }) diff --git a/source/map-spec.ts b/source/map-spec.ts index 4152beab..b52bab58 100644 --- a/source/map-spec.ts +++ b/source/map-spec.ts @@ -2,7 +2,7 @@ import { map, pipe } from 'rambda' const list = [1, 2, 3] -it('R.map - within pipe', () => { +it('R.map', () => { const result = pipe( list, x => x, @@ -14,6 +14,19 @@ it('R.map - within pipe', () => { result // $ExpectType string[] }) +it('R.map - index in functor', () => { + const result = pipe( + list, + x => x, + map((x, i) => { + x // $ExpectType number + i // $ExpectType number + return String(x) + }), + ) + result // $ExpectType string[] +}) + it('R.map - without pipe', () => { map(x => { x // $ExpectType unknown diff --git a/source/mapChain-spec.ts b/source/mapChain-spec.ts new file mode 100644 index 00000000..329031ab --- /dev/null +++ b/source/mapChain-spec.ts @@ -0,0 +1,60 @@ +import { mapChain, pipe } from 'rambda' + +const list = [1, 2, 3] + +it('R.mapChain', () => { + const result = pipe( + list, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + x => { + x // $ExpectType string + return x !== 'foo' + }, + ), + ) + result // $ExpectType boolean[] +}) + +it('R.mapChain - with index', () => { + const result = pipe( + list, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + (x, i) => { + i // $ExpectType number + x // $ExpectType string + return x !== 'foo' + }, + ), + ) + result // $ExpectType boolean[] +}) + +it('R.mapChain - 3 functions', () => { + const result = pipe( + list, + x => x, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + x => { + x // $ExpectType string + return x !== 'foo' + }, + x => { + x // $ExpectType boolean + return x ? 'foo' : 'bar' + }, + ), + ) + result // $ExpectType ("bar" | "foo")[] +}) diff --git a/source/mapChain.js b/source/mapChain.js new file mode 100644 index 00000000..fb326122 --- /dev/null +++ b/source/mapChain.js @@ -0,0 +1,11 @@ +import { mapFn } from "./map.js"; + +export function mapChain(...fns) { + return list => { + let result = list.slice() + fns.forEach((fn) => { + result = mapFn(fn, result) + }) + return result + } +} diff --git a/source/mapChain.spec.js b/source/mapChain.spec.js new file mode 100644 index 00000000..1058b608 --- /dev/null +++ b/source/mapChain.spec.js @@ -0,0 +1,7 @@ +import { mapChain } from './mapChain.js' + +const double = x => x * 2 + +it('happy', () => { + expect(mapChain(double, double, double)([1, 2, 3])).toEqual([8, 16, 24]) +}) diff --git a/source/middle-spec.ts b/source/middle-spec.ts new file mode 100644 index 00000000..646d7a22 --- /dev/null +++ b/source/middle-spec.ts @@ -0,0 +1,38 @@ +import { map, middle, pipe } from 'rambda' + +describe('R.middle', () => { + it('with string', () => { + const result = middle('foo') + + result // $ExpectType string + }) + it('with list - using const on short array', () => { + const result = pipe( + [1, 2] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType number[] + }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3, 4] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType [number, number] + }) + it('with list - mixed types', () => { + const result = middle(['foo', 'bar', 1, 2, 3]) + + result // $ExpectType (string | number)[] + }) +}) diff --git a/source/middle.js b/source/middle.js new file mode 100644 index 00000000..be537f1b --- /dev/null +++ b/source/middle.js @@ -0,0 +1,6 @@ +import { init } from './init.js' +import { tail } from './tail.js' + +export function middle(listOrString) { + return tail(init(listOrString)) +} diff --git a/source/middle.spec.js b/source/middle.spec.js new file mode 100644 index 00000000..a390be34 --- /dev/null +++ b/source/middle.spec.js @@ -0,0 +1,13 @@ +import { middle } from './middle' + +test('middle', () => { + expect(middle([1, 2, 3])).toEqual([2]) + expect(middle([1, 2])).toEqual([]) + expect(middle([1])).toEqual([]) + expect(middle([])).toEqual([]) + + expect(middle('abc')).toBe('b') + expect(middle('ab')).toBe('') + expect(middle('a')).toBe('') + expect(middle('')).toBe('') +}) diff --git a/source/tail-spec.ts b/source/tail-spec.ts index 0e9e0339..ee4145f5 100644 --- a/source/tail-spec.ts +++ b/source/tail-spec.ts @@ -1,4 +1,4 @@ -import { tail } from 'rambda' +import { map, pipe, tail } from 'rambda' describe('R.tail', () => { it('with string', () => { @@ -6,11 +6,30 @@ describe('R.tail', () => { result // $ExpectType string }) - it('with list - one type', () => { - const result = tail([1, 2, 3]) - + it('with list - using const on short array', () => { + const result = pipe( + [1] as const, + map(x => x * 2), + tail, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + tail, + ) result // $ExpectType number[] }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3] as const, + map(x => x * 2), + tail, + ) + result // $ExpectType [number, number] + }) it('with list - mixed types', () => { const result = tail(['foo', 'bar', 1, 2, 3]) From b196d91217c0f7c265fbe702115157938ce32a13 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 14:05:17 +0200 Subject: [PATCH 48/54] switcher --- CHANGELOG.md | 2 - README.md | 955 +++++++++++++++++++++++++++++++++++++--- dist/rambda.cjs | 131 +++++- dist/rambda.js | 125 +++++- dist/rambda.umd.js | 131 +++++- docs/README.md | 955 +++++++++++++++++++++++++++++++++++++--- files/index.d.ts | 112 ++++- index.d.cts | 93 +++- index.d.ts | 93 +++- rambda.js | 7 + source/filterMap.js | 2 + source/random.js | 3 + source/random.spec.js | 9 + source/sum.js | 3 + source/sum.spec.js | 5 + source/switcher-spec.ts | 25 ++ source/switcher.js | 78 ++++ source/switcher.spec.js | 75 ++++ src/delay.js | 9 + src/drop.js | 2 +- src/filterMap.js | 5 + src/mapChain.js | 11 + src/middle.js | 6 + src/random.js | 3 + src/sum.js | 3 + src/switcher.js | 78 ++++ 26 files changed, 2769 insertions(+), 152 deletions(-) create mode 100644 source/random.js create mode 100644 source/random.spec.js create mode 100644 source/sum.js create mode 100644 source/sum.spec.js create mode 100644 source/switcher-spec.ts create mode 100644 source/switcher.js create mode 100644 source/switcher.spec.js create mode 100644 src/delay.js create mode 100644 src/filterMap.js create mode 100644 src/mapChain.js create mode 100644 src/middle.js create mode 100644 src/random.js create mode 100644 src/sum.js create mode 100644 src/switcher.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 9533517a..1fca893c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,6 @@ - Add `R.middle` - equal to `R.init` + `R.tail` -- Add `R.sumByProp` - - Add `R.random`, `R.shuffle`, `R.switcher`, `R.sum`, `R.delay` - imported from `Rambda` - Add index to `R.filter`/`R.reject` predicate signiture diff --git a/README.md b/README.md index efed3f30..863e28be 100644 --- a/README.md +++ b/README.md @@ -1941,6 +1941,59 @@ describe('R.defaultTo', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#defaultTo) +### delay + +```typescript + +delay(ms: number): Promise<'RAMBDA_DELAY'> +``` + +`setTimeout` as a promise that resolves to `RAMBDA_DELAY` string after `ms` milliseconds. + +
+ +All TypeScript definitions + +```typescript +delay(ms: number): Promise<'RAMBDA_DELAY'>; +``` + +
+ +
+ +R.delay source + +```javascript +export const DELAY = 'RAMBDA_DELAY' + +export function delay(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve(DELAY) + }, ms) + }) +} +``` + +
+ +
+ +Tests + +```javascript +import { DELAY, delay } from './delay.js' + +test('usage with variables', async () => { + await expect(delay(500)).resolves.toBe(DELAY) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#delay) + ### descend ```typescript @@ -2120,7 +2173,7 @@ drop(howMany: number): (list: T[]) => T[]; R.drop source ```javascript -export function drop(howManyToDrop, ) { +export function drop(howManyToDrop) { return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) } ``` @@ -3529,7 +3582,7 @@ filter( predicate: BooleanConstructor, ): (list: T[]) => ExcludeFalsy[]; filter( - predicate: (value: T) => boolean, + predicate: (value: T, index: number) => boolean, ): (list: T[]) => T[]; ... ... @@ -3597,14 +3650,26 @@ const list = [1, 2, 3] describe('R.filter with array', () => { it('within pipe', () => { - const _result = pipe( + const result = pipe( list, filter(x => { x // $ExpectType number return x > 1 }), ) - _result // $ExpectType number[] + result // $ExpectType number[] + }) + + it('with index', () => { + const result = pipe( + list, + filter((x: number, i: number) => { + x // $ExpectType number + i // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] }) it('complex example', () => { @@ -3643,8 +3708,8 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const _result = pipe(testList, filter(filterBar)) - _result // $ExpectType Bar[] + const result = pipe(testList, filter(filterBar)) + result // $ExpectType Bar[] }) it('narrowing type - readonly', () => { @@ -3659,14 +3724,14 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const _result = pipe(testList, filter(filterBar)) - _result // $ExpectType Bar[] + const result = pipe(testList, filter(filterBar)) + result // $ExpectType Bar[] }) it('filtering NonNullable - list of objects', () => { const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] - const _result = pipe(testList, filter(Boolean)) - _result // $ExpectType { a: number; }[] + const result = pipe(testList, filter(Boolean)) + result // $ExpectType { a: number; }[] }) it('filtering NonNullable - readonly', () => { @@ -3778,6 +3843,104 @@ describe('R.filter with array', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) +### filterMap + +```typescript + +filterMap( + fn: (value: T[number], index: number) => U, +): (data: T) => Mapped> +``` + +Same as `R.map` but it filters out `null/undefined` if returned from functor functions. + +> :boom: This function doesn't work with objects (use R.mapObject instead) + +```javascript +const result = R.pipe( + [1, 2, 3], + R.filterMap(x => x > 1 ? x : null) +) +// => [2, 3] +``` + +Try this R.filterMap example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +filterMap( + fn: (value: T[number], index: number) => U, +): (data: T) => Mapped>; +filterMap( + fn: (value: T[number]) => U, +): (data: T) => Mapped>; +``` + +
+ +
+ +R.filterMap source + +```javascript +import {mapFn} from './map.js' + +export function filterMap(fn) { + return list => mapFn(fn, list).filter(Boolean) +} +``` + +
+ +
+ +Tests + +```javascript +import { filterMap } from './filterMap.js' + +const double = x => x > 1 ? x * 2 : null + +it('happy', () => { + expect(filterMap(double)([1, 2, 3])).toEqual([4, 6]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { filterMap, pipe } from 'rambda' + +const list = [1, 2, 3] + +it('R.filterMap - within pipe', () => { + const result = pipe( + list, + x => x, + filterMap(x => { + x // $ExpectType number + return Math.random() > 0.5 ? String(x) : null + }), + filterMap(x => { + x // $ExpectType string + return Math.random() > 0.5 ? Number(x) : '' + }), + ) + result // $ExpectType number[] +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterMap) + ### filterObject ```typescript @@ -5151,9 +5314,6 @@ indexBy( indexBy( property: K ): (list: T[]) => Record; - -// API_MARKER_END -// ============================================ ```
@@ -5327,7 +5487,9 @@ describe('R.indexOf', () => { ```typescript -init(input: T): T extends readonly [...infer U, any] ? U : [...T] +init(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [...infer U, any] ? U : T : T extends string ? string : never ``` It returns all but the last element of list or string `input`. @@ -5347,8 +5509,9 @@ const result = [ All TypeScript definitions ```typescript -init(input: T): T extends readonly [...infer U, any] ? U : [...T]; -init(input: string): string; +init(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [...infer U, any] ? U : T : T extends string ? string : never; ```
@@ -5401,7 +5564,7 @@ test('with string', () => { TypeScript test ```typescript -import { init } from 'rambda' +import { map, pipe, init } from 'rambda' describe('R.init', () => { it('with string', () => { @@ -5409,13 +5572,32 @@ describe('R.init', () => { result // $ExpectType string }) - it('with list - one type', () => { - const result = init([1, 2, 3]) - + it('with list - using const on short array', () => { + const result = pipe( + [1] as const, + map(x => x * 2), + init, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + init, + ) result // $ExpectType number[] }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3] as const, + map(x => x * 2), + init, + ) + result // $ExpectType [number, number] + }) it('with list - mixed types', () => { - const result = init([1, 2, 3, 'foo', 'bar']) + const result = init(['foo', 'bar', 1, 2, 3]) result // $ExpectType (string | number)[] }) @@ -6126,16 +6308,14 @@ It returns the result of looping through `iterable` with `fn`. > :boom: This function doesn't work with objects (use R.mapObject instead) ```javascript -const fn = x => x * 2 - -const iterable = [1, 2] -const obj = {a: 1, b: 2} - -const result = R.map(fn)(iterable), +const result = R.pipe( + [1, 2], + R.map(x => x * 2) +) // => [2, 4] ``` -Try this R.map example in Rambda REPL +Try this R.map example in Rambda REPL
@@ -6201,7 +6381,7 @@ import { map, pipe } from 'rambda' const list = [1, 2, 3] -it('R.map - within pipe', () => { +it('R.map', () => { const result = pipe( list, x => x, @@ -6213,6 +6393,19 @@ it('R.map - within pipe', () => { result // $ExpectType string[] }) +it('R.map - index in functor', () => { + const result = pipe( + list, + x => x, + map((x, i) => { + x // $ExpectType number + i // $ExpectType number + return String(x) + }), + ) + result // $ExpectType string[] +}) + it('R.map - without pipe', () => { map(x => { x // $ExpectType unknown @@ -6380,6 +6573,165 @@ it('R.mapAsync', async () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapAsync) +### mapChain + +```typescript + +mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped +``` + +Chained 2 or 3 `R.map` transformations as one. + +```javascript +const result = R.pipe( + [1, 2], + R.mapChain( + x => x * 2, + x => [x, x > 3], + ) +) +// => [[2, false], [4, true]] +``` + +Try this R.mapChain example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +... +... +``` + +
+ +
+ +R.mapChain source + +```javascript +import { mapFn } from "./map.js"; + +export function mapChain(...fns) { + return list => { + let result = list.slice() + fns.forEach((fn) => { + result = mapFn(fn, result) + }) + return result + } +} +``` + +
+ +
+ +Tests + +```javascript +import { mapChain } from './mapChain.js' + +const double = x => x * 2 + +it('happy', () => { + expect(mapChain(double, double, double)([1, 2, 3])).toEqual([8, 16, 24]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { mapChain, pipe } from 'rambda' + +const list = [1, 2, 3] + +it('R.mapChain', () => { + const result = pipe( + list, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + x => { + x // $ExpectType string + return x !== 'foo' + }, + ), + ) + result // $ExpectType boolean[] +}) + +it('R.mapChain - with index', () => { + const result = pipe( + list, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + (x, i) => { + i // $ExpectType number + x // $ExpectType string + return x !== 'foo' + }, + ), + ) + result // $ExpectType boolean[] +}) + +it('R.mapChain - 3 functions', () => { + const result = pipe( + list, + x => x, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + x => { + x // $ExpectType string + return x !== 'foo' + }, + x => { + x // $ExpectType boolean + return x ? 'foo' : 'bar' + }, + ), + ) + result // $ExpectType ("bar" | "foo")[] +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapChain) + ### mapKeys ```typescript @@ -7226,27 +7578,146 @@ It returns its input and it is intended to be used as last method inside `R.pipe
-All TypeScript definitions +All TypeScript definitions + +```typescript +mergeTypes(x: T): MergeTypes; +``` + +
+ +
+ +R.mergeTypes source + +```javascript +export function mergeTypes(x) { + return x +} +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeTypes) + +### middle + +```typescript + +middle(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : T['length'] extends 2 ? [] : + T extends [any, ...infer U, any] ? U : T : T extends string ? string : never +``` + +It returns all but the first and last element of `input`. + +```javascript +const result = [ + R.middle([1, 2, 3, 4]), + R.middle('bar') +] +// => [[2, 3], 'a'] +``` + +Try this R.middle example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +middle(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : T['length'] extends 2 ? [] : + T extends [any, ...infer U, any] ? U : T : T extends string ? string : never; +``` + +
+ +
+ +R.middle source + +```javascript +import { init } from './init.js' +import { tail } from './tail.js' + +export function middle(listOrString) { + return tail(init(listOrString)) +} +``` + +
+ +
+ +Tests + +```javascript +import { middle } from './middle' + +test('middle', () => { + expect(middle([1, 2, 3])).toEqual([2]) + expect(middle([1, 2])).toEqual([]) + expect(middle([1])).toEqual([]) + expect(middle([])).toEqual([]) + + expect(middle('abc')).toBe('b') + expect(middle('ab')).toBe('') + expect(middle('a')).toBe('') + expect(middle('')).toBe('') +}) +``` + +
+ +
+ +TypeScript test ```typescript -mergeTypes(x: T): MergeTypes; -``` +import { map, middle, pipe } from 'rambda' -
- -
+describe('R.middle', () => { + it('with string', () => { + const result = middle('foo') -R.mergeTypes source + result // $ExpectType string + }) + it('with list - using const on short array', () => { + const result = pipe( + [1, 2] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType number[] + }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3, 4] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType [number, number] + }) + it('with list - mixed types', () => { + const result = middle(['foo', 'bar', 1, 2, 3]) -```javascript -export function mergeTypes(x) { - return x -} + result // $ExpectType (string | number)[] + }) +}) ```
-[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeTypes) +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#middle) ### minBy @@ -9861,6 +10332,56 @@ describe('R.propSatisfies', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propSatisfies) +### random + +```typescript + +random(minInclusive: number, maxInclusive: number): number +``` + +It returns a random number between `min` inclusive and `max` inclusive. + +
+ +All TypeScript definitions + +```typescript +random(minInclusive: number, maxInclusive: number): number; +``` + +
+ +
+ +R.random source + +```javascript +export function random(min, max){ + return Math.floor(Math.random() * (max - min + 1)) + min +} +``` + +
+ +
+ +Tests + +```javascript +import { random } from './random.js' +import { range } from './range.js' +import { uniq } from './uniq.js' + +test('happy', () => { + const result = uniq(range(100).map(() => random(0, 3))).sort() + expect(result).toEqual([0,1,2,3]) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#random) + ### range ```typescript @@ -10207,6 +10728,17 @@ describe('R.reject with array', () => { }), ) result // $ExpectType number[] + }) + it('with index', () => { + const result = pipe( + list, + reject((x: number, i: number) => { + x // $ExpectType number + i // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] }) it('narrowing type', () => { interface Foo { @@ -10565,15 +11097,6 @@ shuffle(list: T[]): T[] It returns a randomized copy of array. -```javascript -const result = R.shuffle( - [1, 2, 3] -) -// => [3, 1, 2] or [2, 3, 1] or ... -``` - -Try this R.shuffle example in Rambda REPL -
All TypeScript definitions @@ -11600,6 +12123,288 @@ describe('R.splitEvery', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#splitEvery) +### sum + +```typescript + +sum(list: number[]): number +``` + +```javascript +const result = R.sum( + [1,2,3] +) +// => 6 +``` + +Try this R.sum example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +sum(list: number[]): number; +``` + +
+ +
+ +R.sum source + +```javascript +export function sum(list){ + return list.reduce((acc, cur) => acc + cur, 0) +} +``` + +
+ +
+ +Tests + +```javascript +import { sum } from './sum.js' + +test('happy', () => { + expect(sum([1,2,3])).toEqual(6) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sum) + +### switcher + +```typescript + +switcher(valueToMatch: T): Switchem +``` + +
+ +All TypeScript definitions + +```typescript +switcher(valueToMatch: T): Switchem; +switcher(valueToMatch: T): Switchem2; + +// API_MARKER_END +// ============================================ +``` + +
+ +
+ +R.switcher source + +```javascript +import { equals } from './equals.js' + +const NO_MATCH_FOUND = Symbol ? Symbol('NO_MATCH_FOUND') : undefined + +const getMatchingKeyValuePair = ( + cases, testValue, defaultValue +) => { + let iterationValue + + for (let index = 0; index < cases.length; index++){ + iterationValue = cases[ index ].test(testValue) + + if (iterationValue !== NO_MATCH_FOUND){ + return iterationValue + } + } + + return defaultValue +} + +const isEqual = (testValue, matchValue) => { + const willReturn = + typeof testValue === 'function' ? + testValue(matchValue) : + equals(testValue)(matchValue) + + return willReturn +} + +const is = (testValue, matchResult = true) => ({ + key : testValue, + test : matchValue => + isEqual(testValue, matchValue) ? matchResult : NO_MATCH_FOUND, +}) + +class Switchem{ + constructor( + defaultValue, cases, willMatch + ){ + if (cases === undefined && willMatch === undefined){ + this.cases = [] + this.defaultValue = undefined + this.willMatch = defaultValue + } else { + this.cases = cases + this.defaultValue = defaultValue + this.willMatch = willMatch + } + + return this + } + + default(defaultValue){ + const holder = new Switchem( + defaultValue, this.cases, this.willMatch + ) + + return holder.match(this.willMatch) + } + + is(testValue, matchResult){ + return new Switchem( + this.defaultValue, + [ ...this.cases, is(testValue, matchResult) ], + this.willMatch + ) + } + + match(matchValue){ + return getMatchingKeyValuePair( + this.cases, matchValue, this.defaultValue + ) + } +} + +export function switcher(input){ + return new Switchem(input) +} +``` + +
+ +
+ +Tests + +```javascript +import { switcher } from './switcher.js' +import { tap } from './tap.js' + +test('with undefined', () => { + const result = switcher(undefined) + .is(x => x === 0, '0') + .is(x => x === undefined, 'UNDEFINED') + .default('3') + + expect(result).toBe('UNDEFINED') +}) + +test('happy', () => { + const a = true + const b = false + const result = switcher([ a, b ]) + .is([ false, false ], '0') + .is([ false, true ], '1') + .is([ true, true ], '2') + .default('3') + + expect(result).toBe('3') +}) + +test('can compare objects', () => { + const result = switcher({ a : 1 }) + .is({ a : 1 }, 'it is object') + .is('baz', 'it is baz') + .default('it is default') + + expect(result).toBe('it is object') +}) + +test('options are mixture of functions and values - input match function', () => { + const fn = switcher('foo').is('bar', 1) + .is('foo', x => x + 1) + .default(1000) + + expect(fn(2)).toBe(3) +}) + +test('options are mixture of functions and values - input match value', () => { + const result = switcher('bar').is('bar', 1) + .is('foo', x => x + 1) + .default(1000) + + expect(result).toBe(1) +}) + +test('return function if all options are functions', () => { + const fn = switcher('foo') + .is('bar', tap) + .is('foo', x => x + 1) + .default(9) + + expect(fn(2)).toBe(3) +}) + +const switchFn = input => + switcher(input) + .is(x => x.length && x.length === 7, 'has length of 7') + .is('baz', 'it is baz') + .default('it is default') + +test('works with function as condition', () => { + expect(switchFn([ 0, 1, 2, 3, 4, 5, 6 ])).toBe('has length of 7') +}) + +test('works with string as condition', () => { + expect(switchFn('baz')).toBe('it is baz') +}) + +test('fallback to default input when no matches', () => { + expect(switchFn(1)).toBe('it is default') +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { switcher } from 'rambda' + +describe('R.switcher', () => { + it('no transformation', () => { + const list = [1, 2, 3] + + const result = switcher(list.length) + .is(x => x < 2, 4) + .is(x => x < 4, 6) + .default(7) + + result // $ExpectType number + }) + it('with transformation', () => { + const list = [1, 2, 3] + type Stage = 'firstStage' | 'secondStage' | 'thirdStage' + + const result = switcher(list.length) + .is(x => x < 2, 'firstStage') + .is(x => x < 4, 'secondStage') + .default('thirdStage') + + result // $ExpectType { id: number; }[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#switcher) + ### symmetricDifference ```typescript @@ -11703,7 +12508,9 @@ describe('R.symmetricDifference', () => { ```typescript -tail(input: T): T extends [any, ...infer U] ? U : [...T] +tail(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [any, ...infer U] ? U : T : T extends string ? string : never ``` It returns all but the first element of `input`. @@ -11723,8 +12530,9 @@ const result = [ All TypeScript definitions ```typescript -tail(input: T): T extends [any, ...infer U] ? U : [...T]; -tail(input: string): string; +tail(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [any, ...infer U] ? U : T : T extends string ? string : never; ```
@@ -11770,7 +12578,7 @@ test('tail', () => { TypeScript test ```typescript -import { tail } from 'rambda' +import { map, pipe, tail } from 'rambda' describe('R.tail', () => { it('with string', () => { @@ -11778,11 +12586,30 @@ describe('R.tail', () => { result // $ExpectType string }) - it('with list - one type', () => { - const result = tail([1, 2, 3]) - + it('with list - using const on short array', () => { + const result = pipe( + [1] as const, + map(x => x * 2), + tail, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + tail, + ) result // $ExpectType number[] }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3] as const, + map(x => x * 2), + tail, + ) + result // $ExpectType [number, number] + }) it('with list - mixed types', () => { const result = tail(['foo', 'bar', 1, 2, 3]) @@ -13973,6 +14800,20 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +11.1.0 + +- Add `R.filterMap` - similar to Ruby `filter_map` + +- Add `R.mapChain` - when in `R.pipe` there are several `R.map` one after the other, then `R.mapChain` can be used instead. + +- Add `R.middle` - equal to `R.init` + `R.tail` + +- Add `R.random`, `R.shuffle`, `R.switcher`, `R.sum`, `R.delay` - imported from `Rambda` + +- Add index to `R.filter`/`R.reject` predicate signiture + +- Improve typing of `R.init`, `R.tail` + 11.0.1 - Add missing JS change for `R.includes` and `R.excludes` methods in `11.0.0` release. diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 9e439af6..46919443 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -249,6 +249,16 @@ function defaultTo(defaultArgument) { return input => isFalsy(input) ? defaultArgument : input } +const DELAY = 'RAMBDA_DELAY'; + +function delay(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve(DELAY); + }, ms); + }) +} + function descend(getFunction) { return (a, b) => { const aValue = getFunction(a); @@ -508,7 +518,7 @@ function difference(listA) { ]) } -function drop(howManyToDrop, ) { +function drop(howManyToDrop) { return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) } @@ -677,6 +687,10 @@ function filterAsync(predicate) { } } +function filterMap(fn) { + return list => mapFn(fn, list).filter(Boolean) +} + function filterObject(predicate) { return obj => { const willReturn = {}; @@ -1034,6 +1048,16 @@ function mapAsync(fn) { } } +function mapChain(...fns) { + return list => { + let result = list.slice(); + fns.forEach((fn) => { + result = mapFn(fn, result); + }); + return result + } +} + function mapKeys(fn) { return obj => { const willReturn = {}; @@ -1103,6 +1127,14 @@ function mergeTypes(x) { return x } +function tail(listOrString) { + return drop(1)(listOrString) +} + +function middle(listOrString) { + return tail(init(listOrString)) +} + function minBy(compareFn, x) { return y => (compareFn(y) < compareFn(x) ? y : x) } @@ -1520,6 +1552,10 @@ function propSatisfies(predicate, property) { return obj => predicate(obj[property]) } +function random(min, max){ + return Math.floor(Math.random() * (max - min + 1)) + min +} + function range(a, b) { const start = b === undefined ? 0 : a; const end = b === undefined ? a : b; @@ -1669,6 +1705,87 @@ function splitEvery(sliceLength) { } } +function sum(list){ + return list.reduce((acc, cur) => acc + cur, 0) +} + +const NO_MATCH_FOUND = Symbol ? Symbol('NO_MATCH_FOUND') : undefined; + +const getMatchingKeyValuePair = ( + cases, testValue, defaultValue +) => { + let iterationValue; + + for (let index = 0; index < cases.length; index++){ + iterationValue = cases[ index ].test(testValue); + + if (iterationValue !== NO_MATCH_FOUND){ + return iterationValue + } + } + + return defaultValue +}; + +const isEqual = (testValue, matchValue) => { + const willReturn = + typeof testValue === 'function' ? + testValue(matchValue) : + equals(testValue)(matchValue); + + return willReturn +}; + +const is = (testValue, matchResult = true) => ({ + key : testValue, + test : matchValue => + isEqual(testValue, matchValue) ? matchResult : NO_MATCH_FOUND, +}); + +class Switchem{ + constructor( + defaultValue, cases, willMatch + ){ + if (cases === undefined && willMatch === undefined){ + this.cases = []; + this.defaultValue = undefined; + this.willMatch = defaultValue; + } else { + this.cases = cases; + this.defaultValue = defaultValue; + this.willMatch = willMatch; + } + + return this + } + + default(defaultValue){ + const holder = new Switchem( + defaultValue, this.cases, this.willMatch + ); + + return holder.match(this.willMatch) + } + + is(testValue, matchResult){ + return new Switchem( + this.defaultValue, + [ ...this.cases, is(testValue, matchResult) ], + this.willMatch + ) + } + + match(matchValue){ + return getMatchingKeyValuePair( + this.cases, matchValue, this.defaultValue + ) + } +} + +function switcher(input){ + return new Switchem(input) +} + function symmetricDifference(listA) { return listB => [ ...filter(excludes(listB))(listA), @@ -1676,10 +1793,6 @@ function symmetricDifference(listA) { ] } -function tail(listOrString) { - return drop(1)(listOrString) -} - function take(numberOfItems) { return input => { if (numberOfItems < 0) { @@ -1890,6 +2003,7 @@ function zipWith(fn, x) { ) } +exports.DELAY = DELAY; exports._arity = _arity; exports._includes = _includes; exports._indexOf = _indexOf; @@ -1913,6 +2027,7 @@ exports.countBy = countBy; exports.createCompareFunction = createCompareFunction; exports.createObjectFromKeys = createObjectFromKeys; exports.defaultTo = defaultTo; +exports.delay = delay; exports.descend = descend; exports.difference = difference; exports.drop = drop; @@ -1929,6 +2044,7 @@ exports.excludes = excludes; exports.exists = exists; exports.filter = filter; exports.filterAsync = filterAsync; +exports.filterMap = filterMap; exports.filterObject = filterObject; exports.find = find; exports.findIndex = findIndex; @@ -1955,6 +2071,7 @@ exports.last = last; exports.lastIndexOf = lastIndexOf; exports.map = map; exports.mapAsync = mapAsync; +exports.mapChain = mapChain; exports.mapFn = mapFn; exports.mapKeys = mapKeys; exports.mapObject = mapObject; @@ -1965,6 +2082,7 @@ exports.match = match; exports.maxBy = maxBy; exports.merge = merge; exports.mergeTypes = mergeTypes; +exports.middle = middle; exports.minBy = minBy; exports.modifyItemAtIndex = modifyItemAtIndex; exports.modifyPath = modifyPath; @@ -1987,6 +2105,7 @@ exports.prop = prop; exports.propEq = propEq; exports.propOr = propOr; exports.propSatisfies = propSatisfies; +exports.random = random; exports.range = range; exports.rangeDescending = rangeDescending; exports.reduce = reduce; @@ -2005,6 +2124,8 @@ exports.sortObject = sortObject; exports.sortWith = sortWith; exports.split = split; exports.splitEvery = splitEvery; +exports.sum = sum; +exports.switcher = switcher; exports.symmetricDifference = symmetricDifference; exports.tail = tail; exports.take = take; diff --git a/dist/rambda.js b/dist/rambda.js index c87c3ebb..fd7bf401 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -247,6 +247,16 @@ function defaultTo(defaultArgument) { return input => isFalsy(input) ? defaultArgument : input } +const DELAY = 'RAMBDA_DELAY'; + +function delay(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve(DELAY); + }, ms); + }) +} + function descend(getFunction) { return (a, b) => { const aValue = getFunction(a); @@ -506,7 +516,7 @@ function difference(listA) { ]) } -function drop(howManyToDrop, ) { +function drop(howManyToDrop) { return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) } @@ -675,6 +685,10 @@ function filterAsync(predicate) { } } +function filterMap(fn) { + return list => mapFn(fn, list).filter(Boolean) +} + function filterObject(predicate) { return obj => { const willReturn = {}; @@ -1032,6 +1046,16 @@ function mapAsync(fn) { } } +function mapChain(...fns) { + return list => { + let result = list.slice(); + fns.forEach((fn) => { + result = mapFn(fn, result); + }); + return result + } +} + function mapKeys(fn) { return obj => { const willReturn = {}; @@ -1101,6 +1125,14 @@ function mergeTypes(x) { return x } +function tail(listOrString) { + return drop(1)(listOrString) +} + +function middle(listOrString) { + return tail(init(listOrString)) +} + function minBy(compareFn, x) { return y => (compareFn(y) < compareFn(x) ? y : x) } @@ -1518,6 +1550,10 @@ function propSatisfies(predicate, property) { return obj => predicate(obj[property]) } +function random(min, max){ + return Math.floor(Math.random() * (max - min + 1)) + min +} + function range(a, b) { const start = b === undefined ? 0 : a; const end = b === undefined ? a : b; @@ -1667,6 +1703,87 @@ function splitEvery(sliceLength) { } } +function sum(list){ + return list.reduce((acc, cur) => acc + cur, 0) +} + +const NO_MATCH_FOUND = Symbol ? Symbol('NO_MATCH_FOUND') : undefined; + +const getMatchingKeyValuePair = ( + cases, testValue, defaultValue +) => { + let iterationValue; + + for (let index = 0; index < cases.length; index++){ + iterationValue = cases[ index ].test(testValue); + + if (iterationValue !== NO_MATCH_FOUND){ + return iterationValue + } + } + + return defaultValue +}; + +const isEqual = (testValue, matchValue) => { + const willReturn = + typeof testValue === 'function' ? + testValue(matchValue) : + equals(testValue)(matchValue); + + return willReturn +}; + +const is = (testValue, matchResult = true) => ({ + key : testValue, + test : matchValue => + isEqual(testValue, matchValue) ? matchResult : NO_MATCH_FOUND, +}); + +class Switchem{ + constructor( + defaultValue, cases, willMatch + ){ + if (cases === undefined && willMatch === undefined){ + this.cases = []; + this.defaultValue = undefined; + this.willMatch = defaultValue; + } else { + this.cases = cases; + this.defaultValue = defaultValue; + this.willMatch = willMatch; + } + + return this + } + + default(defaultValue){ + const holder = new Switchem( + defaultValue, this.cases, this.willMatch + ); + + return holder.match(this.willMatch) + } + + is(testValue, matchResult){ + return new Switchem( + this.defaultValue, + [ ...this.cases, is(testValue, matchResult) ], + this.willMatch + ) + } + + match(matchValue){ + return getMatchingKeyValuePair( + this.cases, matchValue, this.defaultValue + ) + } +} + +function switcher(input){ + return new Switchem(input) +} + function symmetricDifference(listA) { return listB => [ ...filter(excludes(listB))(listA), @@ -1674,10 +1791,6 @@ function symmetricDifference(listA) { ] } -function tail(listOrString) { - return drop(1)(listOrString) -} - function take(numberOfItems) { return input => { if (numberOfItems < 0) { @@ -1888,4 +2001,4 @@ function zipWith(fn, x) { ) } -export { _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, exists, filter, filterAsync, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; +export { DELAY, _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, delay, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, exists, filter, filterAsync, filterMap, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapChain, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, middle, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, random, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, sum, switcher, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index 8b932614..01e60021 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -253,6 +253,16 @@ return input => isFalsy(input) ? defaultArgument : input } + const DELAY = 'RAMBDA_DELAY'; + + function delay(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve(DELAY); + }, ms); + }) + } + function descend(getFunction) { return (a, b) => { const aValue = getFunction(a); @@ -512,7 +522,7 @@ ]) } - function drop(howManyToDrop, ) { + function drop(howManyToDrop) { return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) } @@ -681,6 +691,10 @@ } } + function filterMap(fn) { + return list => mapFn(fn, list).filter(Boolean) + } + function filterObject(predicate) { return obj => { const willReturn = {}; @@ -1038,6 +1052,16 @@ } } + function mapChain(...fns) { + return list => { + let result = list.slice(); + fns.forEach((fn) => { + result = mapFn(fn, result); + }); + return result + } + } + function mapKeys(fn) { return obj => { const willReturn = {}; @@ -1107,6 +1131,14 @@ return x } + function tail(listOrString) { + return drop(1)(listOrString) + } + + function middle(listOrString) { + return tail(init(listOrString)) + } + function minBy(compareFn, x) { return y => (compareFn(y) < compareFn(x) ? y : x) } @@ -1524,6 +1556,10 @@ return obj => predicate(obj[property]) } + function random(min, max){ + return Math.floor(Math.random() * (max - min + 1)) + min + } + function range(a, b) { const start = b === undefined ? 0 : a; const end = b === undefined ? a : b; @@ -1673,6 +1709,87 @@ } } + function sum(list){ + return list.reduce((acc, cur) => acc + cur, 0) + } + + const NO_MATCH_FOUND = Symbol ? Symbol('NO_MATCH_FOUND') : undefined; + + const getMatchingKeyValuePair = ( + cases, testValue, defaultValue + ) => { + let iterationValue; + + for (let index = 0; index < cases.length; index++){ + iterationValue = cases[ index ].test(testValue); + + if (iterationValue !== NO_MATCH_FOUND){ + return iterationValue + } + } + + return defaultValue + }; + + const isEqual = (testValue, matchValue) => { + const willReturn = + typeof testValue === 'function' ? + testValue(matchValue) : + equals(testValue)(matchValue); + + return willReturn + }; + + const is = (testValue, matchResult = true) => ({ + key : testValue, + test : matchValue => + isEqual(testValue, matchValue) ? matchResult : NO_MATCH_FOUND, + }); + + class Switchem{ + constructor( + defaultValue, cases, willMatch + ){ + if (cases === undefined && willMatch === undefined){ + this.cases = []; + this.defaultValue = undefined; + this.willMatch = defaultValue; + } else { + this.cases = cases; + this.defaultValue = defaultValue; + this.willMatch = willMatch; + } + + return this + } + + default(defaultValue){ + const holder = new Switchem( + defaultValue, this.cases, this.willMatch + ); + + return holder.match(this.willMatch) + } + + is(testValue, matchResult){ + return new Switchem( + this.defaultValue, + [ ...this.cases, is(testValue, matchResult) ], + this.willMatch + ) + } + + match(matchValue){ + return getMatchingKeyValuePair( + this.cases, matchValue, this.defaultValue + ) + } + } + + function switcher(input){ + return new Switchem(input) + } + function symmetricDifference(listA) { return listB => [ ...filter(excludes(listB))(listA), @@ -1680,10 +1797,6 @@ ] } - function tail(listOrString) { - return drop(1)(listOrString) - } - function take(numberOfItems) { return input => { if (numberOfItems < 0) { @@ -1894,6 +2007,7 @@ ) } + exports.DELAY = DELAY; exports._arity = _arity; exports._includes = _includes; exports._indexOf = _indexOf; @@ -1917,6 +2031,7 @@ exports.createCompareFunction = createCompareFunction; exports.createObjectFromKeys = createObjectFromKeys; exports.defaultTo = defaultTo; + exports.delay = delay; exports.descend = descend; exports.difference = difference; exports.drop = drop; @@ -1933,6 +2048,7 @@ exports.exists = exists; exports.filter = filter; exports.filterAsync = filterAsync; + exports.filterMap = filterMap; exports.filterObject = filterObject; exports.find = find; exports.findIndex = findIndex; @@ -1959,6 +2075,7 @@ exports.lastIndexOf = lastIndexOf; exports.map = map; exports.mapAsync = mapAsync; + exports.mapChain = mapChain; exports.mapFn = mapFn; exports.mapKeys = mapKeys; exports.mapObject = mapObject; @@ -1969,6 +2086,7 @@ exports.maxBy = maxBy; exports.merge = merge; exports.mergeTypes = mergeTypes; + exports.middle = middle; exports.minBy = minBy; exports.modifyItemAtIndex = modifyItemAtIndex; exports.modifyPath = modifyPath; @@ -1991,6 +2109,7 @@ exports.propEq = propEq; exports.propOr = propOr; exports.propSatisfies = propSatisfies; + exports.random = random; exports.range = range; exports.rangeDescending = rangeDescending; exports.reduce = reduce; @@ -2009,6 +2128,8 @@ exports.sortWith = sortWith; exports.split = split; exports.splitEvery = splitEvery; + exports.sum = sum; + exports.switcher = switcher; exports.symmetricDifference = symmetricDifference; exports.tail = tail; exports.take = take; diff --git a/docs/README.md b/docs/README.md index efed3f30..863e28be 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1941,6 +1941,59 @@ describe('R.defaultTo', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#defaultTo) +### delay + +```typescript + +delay(ms: number): Promise<'RAMBDA_DELAY'> +``` + +`setTimeout` as a promise that resolves to `RAMBDA_DELAY` string after `ms` milliseconds. + +
+ +All TypeScript definitions + +```typescript +delay(ms: number): Promise<'RAMBDA_DELAY'>; +``` + +
+ +
+ +R.delay source + +```javascript +export const DELAY = 'RAMBDA_DELAY' + +export function delay(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve(DELAY) + }, ms) + }) +} +``` + +
+ +
+ +Tests + +```javascript +import { DELAY, delay } from './delay.js' + +test('usage with variables', async () => { + await expect(delay(500)).resolves.toBe(DELAY) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#delay) + ### descend ```typescript @@ -2120,7 +2173,7 @@ drop(howMany: number): (list: T[]) => T[]; R.drop source ```javascript -export function drop(howManyToDrop, ) { +export function drop(howManyToDrop) { return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) } ``` @@ -3529,7 +3582,7 @@ filter( predicate: BooleanConstructor, ): (list: T[]) => ExcludeFalsy[]; filter( - predicate: (value: T) => boolean, + predicate: (value: T, index: number) => boolean, ): (list: T[]) => T[]; ... ... @@ -3597,14 +3650,26 @@ const list = [1, 2, 3] describe('R.filter with array', () => { it('within pipe', () => { - const _result = pipe( + const result = pipe( list, filter(x => { x // $ExpectType number return x > 1 }), ) - _result // $ExpectType number[] + result // $ExpectType number[] + }) + + it('with index', () => { + const result = pipe( + list, + filter((x: number, i: number) => { + x // $ExpectType number + i // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] }) it('complex example', () => { @@ -3643,8 +3708,8 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const _result = pipe(testList, filter(filterBar)) - _result // $ExpectType Bar[] + const result = pipe(testList, filter(filterBar)) + result // $ExpectType Bar[] }) it('narrowing type - readonly', () => { @@ -3659,14 +3724,14 @@ describe('R.filter with array', () => { const filterBar = (x: T): x is Bar => { return typeof (x as Bar).b === 'string' } - const _result = pipe(testList, filter(filterBar)) - _result // $ExpectType Bar[] + const result = pipe(testList, filter(filterBar)) + result // $ExpectType Bar[] }) it('filtering NonNullable - list of objects', () => { const testList = [{ a: 1 }, { a: 2 }, false, { a: 3 }] - const _result = pipe(testList, filter(Boolean)) - _result // $ExpectType { a: number; }[] + const result = pipe(testList, filter(Boolean)) + result // $ExpectType { a: number; }[] }) it('filtering NonNullable - readonly', () => { @@ -3778,6 +3843,104 @@ describe('R.filter with array', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterAsync) +### filterMap + +```typescript + +filterMap( + fn: (value: T[number], index: number) => U, +): (data: T) => Mapped> +``` + +Same as `R.map` but it filters out `null/undefined` if returned from functor functions. + +> :boom: This function doesn't work with objects (use R.mapObject instead) + +```javascript +const result = R.pipe( + [1, 2, 3], + R.filterMap(x => x > 1 ? x : null) +) +// => [2, 3] +``` + +Try this R.filterMap example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +filterMap( + fn: (value: T[number], index: number) => U, +): (data: T) => Mapped>; +filterMap( + fn: (value: T[number]) => U, +): (data: T) => Mapped>; +``` + +
+ +
+ +R.filterMap source + +```javascript +import {mapFn} from './map.js' + +export function filterMap(fn) { + return list => mapFn(fn, list).filter(Boolean) +} +``` + +
+ +
+ +Tests + +```javascript +import { filterMap } from './filterMap.js' + +const double = x => x > 1 ? x * 2 : null + +it('happy', () => { + expect(filterMap(double)([1, 2, 3])).toEqual([4, 6]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { filterMap, pipe } from 'rambda' + +const list = [1, 2, 3] + +it('R.filterMap - within pipe', () => { + const result = pipe( + list, + x => x, + filterMap(x => { + x // $ExpectType number + return Math.random() > 0.5 ? String(x) : null + }), + filterMap(x => { + x // $ExpectType string + return Math.random() > 0.5 ? Number(x) : '' + }), + ) + result // $ExpectType number[] +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filterMap) + ### filterObject ```typescript @@ -5151,9 +5314,6 @@ indexBy( indexBy( property: K ): (list: T[]) => Record; - -// API_MARKER_END -// ============================================ ```
@@ -5327,7 +5487,9 @@ describe('R.indexOf', () => { ```typescript -init(input: T): T extends readonly [...infer U, any] ? U : [...T] +init(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [...infer U, any] ? U : T : T extends string ? string : never ``` It returns all but the last element of list or string `input`. @@ -5347,8 +5509,9 @@ const result = [ All TypeScript definitions ```typescript -init(input: T): T extends readonly [...infer U, any] ? U : [...T]; -init(input: string): string; +init(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [...infer U, any] ? U : T : T extends string ? string : never; ```
@@ -5401,7 +5564,7 @@ test('with string', () => { TypeScript test ```typescript -import { init } from 'rambda' +import { map, pipe, init } from 'rambda' describe('R.init', () => { it('with string', () => { @@ -5409,13 +5572,32 @@ describe('R.init', () => { result // $ExpectType string }) - it('with list - one type', () => { - const result = init([1, 2, 3]) - + it('with list - using const on short array', () => { + const result = pipe( + [1] as const, + map(x => x * 2), + init, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + init, + ) result // $ExpectType number[] }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3] as const, + map(x => x * 2), + init, + ) + result // $ExpectType [number, number] + }) it('with list - mixed types', () => { - const result = init([1, 2, 3, 'foo', 'bar']) + const result = init(['foo', 'bar', 1, 2, 3]) result // $ExpectType (string | number)[] }) @@ -6126,16 +6308,14 @@ It returns the result of looping through `iterable` with `fn`. > :boom: This function doesn't work with objects (use R.mapObject instead) ```javascript -const fn = x => x * 2 - -const iterable = [1, 2] -const obj = {a: 1, b: 2} - -const result = R.map(fn)(iterable), +const result = R.pipe( + [1, 2], + R.map(x => x * 2) +) // => [2, 4] ``` -Try this R.map example in Rambda REPL +Try this R.map example in Rambda REPL
@@ -6201,7 +6381,7 @@ import { map, pipe } from 'rambda' const list = [1, 2, 3] -it('R.map - within pipe', () => { +it('R.map', () => { const result = pipe( list, x => x, @@ -6213,6 +6393,19 @@ it('R.map - within pipe', () => { result // $ExpectType string[] }) +it('R.map - index in functor', () => { + const result = pipe( + list, + x => x, + map((x, i) => { + x // $ExpectType number + i // $ExpectType number + return String(x) + }), + ) + result // $ExpectType string[] +}) + it('R.map - without pipe', () => { map(x => { x // $ExpectType unknown @@ -6380,6 +6573,165 @@ it('R.mapAsync', async () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapAsync) +### mapChain + +```typescript + +mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped +``` + +Chained 2 or 3 `R.map` transformations as one. + +```javascript +const result = R.pipe( + [1, 2], + R.mapChain( + x => x * 2, + x => [x, x > 3], + ) +) +// => [[2, false], [4, true]] +``` + +Try this R.mapChain example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +... +... +``` + +
+ +
+ +R.mapChain source + +```javascript +import { mapFn } from "./map.js"; + +export function mapChain(...fns) { + return list => { + let result = list.slice() + fns.forEach((fn) => { + result = mapFn(fn, result) + }) + return result + } +} +``` + +
+ +
+ +Tests + +```javascript +import { mapChain } from './mapChain.js' + +const double = x => x * 2 + +it('happy', () => { + expect(mapChain(double, double, double)([1, 2, 3])).toEqual([8, 16, 24]) +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { mapChain, pipe } from 'rambda' + +const list = [1, 2, 3] + +it('R.mapChain', () => { + const result = pipe( + list, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + x => { + x // $ExpectType string + return x !== 'foo' + }, + ), + ) + result // $ExpectType boolean[] +}) + +it('R.mapChain - with index', () => { + const result = pipe( + list, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + (x, i) => { + i // $ExpectType number + x // $ExpectType string + return x !== 'foo' + }, + ), + ) + result // $ExpectType boolean[] +}) + +it('R.mapChain - 3 functions', () => { + const result = pipe( + list, + x => x, + mapChain( + x => { + x // $ExpectType number + return String(x) + }, + x => { + x // $ExpectType string + return x !== 'foo' + }, + x => { + x // $ExpectType boolean + return x ? 'foo' : 'bar' + }, + ), + ) + result // $ExpectType ("bar" | "foo")[] +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapChain) + ### mapKeys ```typescript @@ -7226,27 +7578,146 @@ It returns its input and it is intended to be used as last method inside `R.pipe
-All TypeScript definitions +All TypeScript definitions + +```typescript +mergeTypes(x: T): MergeTypes; +``` + +
+ +
+ +R.mergeTypes source + +```javascript +export function mergeTypes(x) { + return x +} +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeTypes) + +### middle + +```typescript + +middle(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : T['length'] extends 2 ? [] : + T extends [any, ...infer U, any] ? U : T : T extends string ? string : never +``` + +It returns all but the first and last element of `input`. + +```javascript +const result = [ + R.middle([1, 2, 3, 4]), + R.middle('bar') +] +// => [[2, 3], 'a'] +``` + +Try this R.middle example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +middle(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : T['length'] extends 2 ? [] : + T extends [any, ...infer U, any] ? U : T : T extends string ? string : never; +``` + +
+ +
+ +R.middle source + +```javascript +import { init } from './init.js' +import { tail } from './tail.js' + +export function middle(listOrString) { + return tail(init(listOrString)) +} +``` + +
+ +
+ +Tests + +```javascript +import { middle } from './middle' + +test('middle', () => { + expect(middle([1, 2, 3])).toEqual([2]) + expect(middle([1, 2])).toEqual([]) + expect(middle([1])).toEqual([]) + expect(middle([])).toEqual([]) + + expect(middle('abc')).toBe('b') + expect(middle('ab')).toBe('') + expect(middle('a')).toBe('') + expect(middle('')).toBe('') +}) +``` + +
+ +
+ +TypeScript test ```typescript -mergeTypes(x: T): MergeTypes; -``` +import { map, middle, pipe } from 'rambda' -
- -
+describe('R.middle', () => { + it('with string', () => { + const result = middle('foo') -R.mergeTypes source + result // $ExpectType string + }) + it('with list - using const on short array', () => { + const result = pipe( + [1, 2] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType number[] + }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3, 4] as const, + map(x => x * 2), + middle, + ) + result // $ExpectType [number, number] + }) + it('with list - mixed types', () => { + const result = middle(['foo', 'bar', 1, 2, 3]) -```javascript -export function mergeTypes(x) { - return x -} + result // $ExpectType (string | number)[] + }) +}) ```
-[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeTypes) +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#middle) ### minBy @@ -9861,6 +10332,56 @@ describe('R.propSatisfies', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propSatisfies) +### random + +```typescript + +random(minInclusive: number, maxInclusive: number): number +``` + +It returns a random number between `min` inclusive and `max` inclusive. + +
+ +All TypeScript definitions + +```typescript +random(minInclusive: number, maxInclusive: number): number; +``` + +
+ +
+ +R.random source + +```javascript +export function random(min, max){ + return Math.floor(Math.random() * (max - min + 1)) + min +} +``` + +
+ +
+ +Tests + +```javascript +import { random } from './random.js' +import { range } from './range.js' +import { uniq } from './uniq.js' + +test('happy', () => { + const result = uniq(range(100).map(() => random(0, 3))).sort() + expect(result).toEqual([0,1,2,3]) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#random) + ### range ```typescript @@ -10207,6 +10728,17 @@ describe('R.reject with array', () => { }), ) result // $ExpectType number[] + }) + it('with index', () => { + const result = pipe( + list, + reject((x: number, i: number) => { + x // $ExpectType number + i // $ExpectType number + return x > 1 + }), + ) + result // $ExpectType number[] }) it('narrowing type', () => { interface Foo { @@ -10565,15 +11097,6 @@ shuffle(list: T[]): T[] It returns a randomized copy of array. -```javascript -const result = R.shuffle( - [1, 2, 3] -) -// => [3, 1, 2] or [2, 3, 1] or ... -``` - -Try this R.shuffle example in Rambda REPL -
All TypeScript definitions @@ -11600,6 +12123,288 @@ describe('R.splitEvery', () => { [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#splitEvery) +### sum + +```typescript + +sum(list: number[]): number +``` + +```javascript +const result = R.sum( + [1,2,3] +) +// => 6 +``` + +Try this R.sum example in Rambda REPL + +
+ +All TypeScript definitions + +```typescript +sum(list: number[]): number; +``` + +
+ +
+ +R.sum source + +```javascript +export function sum(list){ + return list.reduce((acc, cur) => acc + cur, 0) +} +``` + +
+ +
+ +Tests + +```javascript +import { sum } from './sum.js' + +test('happy', () => { + expect(sum([1,2,3])).toEqual(6) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sum) + +### switcher + +```typescript + +switcher(valueToMatch: T): Switchem +``` + +
+ +All TypeScript definitions + +```typescript +switcher(valueToMatch: T): Switchem; +switcher(valueToMatch: T): Switchem2; + +// API_MARKER_END +// ============================================ +``` + +
+ +
+ +R.switcher source + +```javascript +import { equals } from './equals.js' + +const NO_MATCH_FOUND = Symbol ? Symbol('NO_MATCH_FOUND') : undefined + +const getMatchingKeyValuePair = ( + cases, testValue, defaultValue +) => { + let iterationValue + + for (let index = 0; index < cases.length; index++){ + iterationValue = cases[ index ].test(testValue) + + if (iterationValue !== NO_MATCH_FOUND){ + return iterationValue + } + } + + return defaultValue +} + +const isEqual = (testValue, matchValue) => { + const willReturn = + typeof testValue === 'function' ? + testValue(matchValue) : + equals(testValue)(matchValue) + + return willReturn +} + +const is = (testValue, matchResult = true) => ({ + key : testValue, + test : matchValue => + isEqual(testValue, matchValue) ? matchResult : NO_MATCH_FOUND, +}) + +class Switchem{ + constructor( + defaultValue, cases, willMatch + ){ + if (cases === undefined && willMatch === undefined){ + this.cases = [] + this.defaultValue = undefined + this.willMatch = defaultValue + } else { + this.cases = cases + this.defaultValue = defaultValue + this.willMatch = willMatch + } + + return this + } + + default(defaultValue){ + const holder = new Switchem( + defaultValue, this.cases, this.willMatch + ) + + return holder.match(this.willMatch) + } + + is(testValue, matchResult){ + return new Switchem( + this.defaultValue, + [ ...this.cases, is(testValue, matchResult) ], + this.willMatch + ) + } + + match(matchValue){ + return getMatchingKeyValuePair( + this.cases, matchValue, this.defaultValue + ) + } +} + +export function switcher(input){ + return new Switchem(input) +} +``` + +
+ +
+ +Tests + +```javascript +import { switcher } from './switcher.js' +import { tap } from './tap.js' + +test('with undefined', () => { + const result = switcher(undefined) + .is(x => x === 0, '0') + .is(x => x === undefined, 'UNDEFINED') + .default('3') + + expect(result).toBe('UNDEFINED') +}) + +test('happy', () => { + const a = true + const b = false + const result = switcher([ a, b ]) + .is([ false, false ], '0') + .is([ false, true ], '1') + .is([ true, true ], '2') + .default('3') + + expect(result).toBe('3') +}) + +test('can compare objects', () => { + const result = switcher({ a : 1 }) + .is({ a : 1 }, 'it is object') + .is('baz', 'it is baz') + .default('it is default') + + expect(result).toBe('it is object') +}) + +test('options are mixture of functions and values - input match function', () => { + const fn = switcher('foo').is('bar', 1) + .is('foo', x => x + 1) + .default(1000) + + expect(fn(2)).toBe(3) +}) + +test('options are mixture of functions and values - input match value', () => { + const result = switcher('bar').is('bar', 1) + .is('foo', x => x + 1) + .default(1000) + + expect(result).toBe(1) +}) + +test('return function if all options are functions', () => { + const fn = switcher('foo') + .is('bar', tap) + .is('foo', x => x + 1) + .default(9) + + expect(fn(2)).toBe(3) +}) + +const switchFn = input => + switcher(input) + .is(x => x.length && x.length === 7, 'has length of 7') + .is('baz', 'it is baz') + .default('it is default') + +test('works with function as condition', () => { + expect(switchFn([ 0, 1, 2, 3, 4, 5, 6 ])).toBe('has length of 7') +}) + +test('works with string as condition', () => { + expect(switchFn('baz')).toBe('it is baz') +}) + +test('fallback to default input when no matches', () => { + expect(switchFn(1)).toBe('it is default') +}) +``` + +
+ +
+ +TypeScript test + +```typescript +import { switcher } from 'rambda' + +describe('R.switcher', () => { + it('no transformation', () => { + const list = [1, 2, 3] + + const result = switcher(list.length) + .is(x => x < 2, 4) + .is(x => x < 4, 6) + .default(7) + + result // $ExpectType number + }) + it('with transformation', () => { + const list = [1, 2, 3] + type Stage = 'firstStage' | 'secondStage' | 'thirdStage' + + const result = switcher(list.length) + .is(x => x < 2, 'firstStage') + .is(x => x < 4, 'secondStage') + .default('thirdStage') + + result // $ExpectType { id: number; }[] + }) +}) +``` + +
+ +[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#switcher) + ### symmetricDifference ```typescript @@ -11703,7 +12508,9 @@ describe('R.symmetricDifference', () => { ```typescript -tail(input: T): T extends [any, ...infer U] ? U : [...T] +tail(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [any, ...infer U] ? U : T : T extends string ? string : never ``` It returns all but the first element of `input`. @@ -11723,8 +12530,9 @@ const result = [ All TypeScript definitions ```typescript -tail(input: T): T extends [any, ...infer U] ? U : [...T]; -tail(input: string): string; +tail(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [any, ...infer U] ? U : T : T extends string ? string : never; ```
@@ -11770,7 +12578,7 @@ test('tail', () => { TypeScript test ```typescript -import { tail } from 'rambda' +import { map, pipe, tail } from 'rambda' describe('R.tail', () => { it('with string', () => { @@ -11778,11 +12586,30 @@ describe('R.tail', () => { result // $ExpectType string }) - it('with list - one type', () => { - const result = tail([1, 2, 3]) - + it('with list - using const on short array', () => { + const result = pipe( + [1] as const, + map(x => x * 2), + tail, + ) + result // $ExpectType [] + }) + it('with list - using const on empty array', () => { + const result = pipe( + [] as const, + map(x => x * 2), + tail, + ) result // $ExpectType number[] }) + it('with list - using const', () => { + const result = pipe( + [1, 2, 3] as const, + map(x => x * 2), + tail, + ) + result // $ExpectType [number, number] + }) it('with list - mixed types', () => { const result = tail(['foo', 'bar', 1, 2, 3]) @@ -13973,6 +14800,20 @@ describe('R.zipWith', () => { ## ❯ CHANGELOG +11.1.0 + +- Add `R.filterMap` - similar to Ruby `filter_map` + +- Add `R.mapChain` - when in `R.pipe` there are several `R.map` one after the other, then `R.mapChain` can be used instead. + +- Add `R.middle` - equal to `R.init` + `R.tail` + +- Add `R.random`, `R.shuffle`, `R.switcher`, `R.sum`, `R.delay` - imported from `Rambda` + +- Add index to `R.filter`/`R.reject` predicate signiture + +- Improve typing of `R.init`, `R.tail` + 11.0.1 - Add missing JS change for `R.includes` and `R.excludes` methods in `11.0.0` release. diff --git a/files/index.d.ts b/files/index.d.ts index 0710e435..7501a273 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -123,14 +123,25 @@ export type FlattenObject = object extends T } extends Record void> ? O : never; + +type isfn = (fn: (x: T) => boolean, y: T) => U; +type isfn2 = (fn: (x: T) => boolean, y: V) => U; + +interface Switchem { + is: isfn>; + default: (x: T) => T; +}; +interface Switchem2 { + is: isfn2>; + default: (x: U) => U; +}; + // API_MARKER /* Method: modifyItemAtIndex -Explanation: - -It replaces `index` in array `list` with the result of `replaceFn(list[i])`. +Explanation: It replaces `index` in array `list` with the result of `replaceFn(list[i])`. Example: @@ -4985,5 +4996,100 @@ export function indexBy( property: K ): (list: T[]) => Record; +/* +Method: sum + +Explanation: + +Example: + +``` +const result = R.sum( + [1,2,3] +) +// => 6 +``` + +Categories: List + +Notes: + +*/ +// @SINGLE_MARKER +export function sum(list: number[]): number; + +/* +Method: delay + +Explanation: `setTimeout` as a promise that resolves to `RAMBDA_DELAY` string after `ms` milliseconds. + +Example: + +``` +``` + +Categories: + +Notes: + +*/ +// @SINGLE_MARKER +export function delay(ms: number): Promise<'RAMBDA_DELAY'>; + +/* +Method: shuffle + +Explanation: It returns a randomized copy of array. + +Example: + +``` +``` + +Categories: List + +Notes: + +*/ +// @SINGLE_MARKER +export function shuffle(list: T[]): T[]; + +/* +Method: random + +Explanation: It returns a random number between `min` inclusive and `max` inclusive. + +Example: + +``` +``` + +Categories: List + +Notes: + +*/ +// @SINGLE_MARKER +export function random(minInclusive: number, maxInclusive: number): number; + +/* +Method: switcher + +Explanation: + +Example: + +``` +``` + +Categories: Logic + +Notes: + +*/ +// @SINGLE_MARKER +export function switcher(valueToMatch: T): Switchem; +export function switcher(valueToMatch: T): Switchem2; + // API_MARKER_END // ============================================ diff --git a/index.d.cts b/index.d.cts index 15ca919e..04eb0ff6 100644 --- a/index.d.cts +++ b/index.d.cts @@ -124,6 +124,19 @@ export type FlattenObject = object extends T ? O : never; +type isfn = (fn: (x: T) => boolean, y: T) => U; +type isfn2 = (fn: (x: T) => boolean, y: V) => U; + +interface Switchem { + is: isfn>; + default: (x: T) => T; +}; +interface Switchem2 { + is: isfn2>; + default: (x: U) => U; +}; + + /** * It adds new key-value pair to the object. */ @@ -272,6 +285,11 @@ export function createObjectFromKeys( */ export function defaultTo(defaultValue: T): (input: unknown) => T; +/** + * `setTimeout` as a promise that resolves to `RAMBDA_DELAY` string after `ms` milliseconds. + */ +export function delay(ms: number): Promise<'RAMBDA_DELAY'>; + /** * Helper function to be used with `R.sort` to sort list in descending order. */ @@ -353,13 +371,23 @@ export function filter( predicate: BooleanConstructor, ): (list: T[]) => ExcludeFalsy[]; export function filter( - predicate: (value: T) => boolean, + predicate: (value: T, index: number) => boolean, ): (list: T[]) => T[]; export function filterAsync( predicate: (value: T) => Promise, ): (list: T[]) => Promise; +/** + * Same as `R.map` but it filters out `null/undefined` if returned from functor functions. + */ +export function filterMap( + fn: (value: T[number], index: number) => U, +): (data: T) => Mapped>; +export function filterMap( + fn: (value: T[number]) => U, +): (data: T) => Mapped>; + /** * It loops over each property of `obj` and returns a new object with only those properties that satisfy the `predicate`. */ @@ -455,9 +483,6 @@ export function indexBy( property: K ): (list: T[]) => Record; -// API_MARKER_END -// ============================================ - /** * It uses `R.equals` for list of objects/arrays or native `indexOf` for any other case. */ @@ -466,8 +491,9 @@ export function indexOf(valueToFind: T): (list: T[]) => number; /** * It returns all but the last element of list or string `input`. */ -export function init(input: T): T extends readonly [...infer U, any] ? U : [...T]; -export function init(input: string): string; +export function init(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [...infer U, any] ? U : T : T extends string ? string : never; /** * It generates a new string from `inputWithTags` by replacing all `{{x}}` occurrences with values provided by `templateArguments`. @@ -538,6 +564,36 @@ export function mapAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; +/** + * Chained 2 or 3 `R.map` transformations as one. + */ +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, + fn3: (value: V, index: number) => Y, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, + fn3: (value: V) => Y, +): (data: T) => Mapped; + /** * It returns a copy of `obj` with keys transformed by `fn`. */ @@ -610,6 +666,13 @@ export function merge(source: Source): (data: T) => Merge; */ export function mergeTypes(x: T): MergeTypes; +/** + * It returns all but the first and last element of `input`. + */ +export function middle(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : T['length'] extends 2 ? [] : + T extends [any, ...infer U, any] ? U : T : T extends string ? string : never; + /** * It returns the lesser value between `x` and `y` according to `compareFn` function. */ @@ -1791,6 +1854,11 @@ export function propOr(property: P, defaultValue: T): (obj: */ export function propSatisfies(predicate: (x: T) => boolean, property: string): (obj: Record) => boolean; +/** + * It returns a random number between `min` inclusive and `max` inclusive. + */ +export function random(minInclusive: number, maxInclusive: number): number; + /** * It returns list of numbers between `startInclusive` to `endInclusive` markers. */ @@ -2208,6 +2276,14 @@ export function split(separator: string | RegExp): (str: string) => string[]; */ export function splitEvery(sliceLength: number): (input: T[]) => (T[])[]; +export function sum(list: number[]): number; + +export function switcher(valueToMatch: T): Switchem; +export function switcher(valueToMatch: T): Switchem2; + +// API_MARKER_END +// ============================================ + /** * It returns all items that are in either of the lists, but not in both. * @@ -2218,8 +2294,9 @@ export function symmetricDifference(x: T[]): (y: T[]) => T[]; /** * It returns all but the first element of `input`. */ -export function tail(input: T): T extends [any, ...infer U] ? U : [...T]; -export function tail(input: string): string; +export function tail(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [any, ...infer U] ? U : T : T extends string ? string : never; /** * It returns the first `howMany` elements of `input`. diff --git a/index.d.ts b/index.d.ts index 15ca919e..04eb0ff6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -124,6 +124,19 @@ export type FlattenObject = object extends T ? O : never; +type isfn = (fn: (x: T) => boolean, y: T) => U; +type isfn2 = (fn: (x: T) => boolean, y: V) => U; + +interface Switchem { + is: isfn>; + default: (x: T) => T; +}; +interface Switchem2 { + is: isfn2>; + default: (x: U) => U; +}; + + /** * It adds new key-value pair to the object. */ @@ -272,6 +285,11 @@ export function createObjectFromKeys( */ export function defaultTo(defaultValue: T): (input: unknown) => T; +/** + * `setTimeout` as a promise that resolves to `RAMBDA_DELAY` string after `ms` milliseconds. + */ +export function delay(ms: number): Promise<'RAMBDA_DELAY'>; + /** * Helper function to be used with `R.sort` to sort list in descending order. */ @@ -353,13 +371,23 @@ export function filter( predicate: BooleanConstructor, ): (list: T[]) => ExcludeFalsy[]; export function filter( - predicate: (value: T) => boolean, + predicate: (value: T, index: number) => boolean, ): (list: T[]) => T[]; export function filterAsync( predicate: (value: T) => Promise, ): (list: T[]) => Promise; +/** + * Same as `R.map` but it filters out `null/undefined` if returned from functor functions. + */ +export function filterMap( + fn: (value: T[number], index: number) => U, +): (data: T) => Mapped>; +export function filterMap( + fn: (value: T[number]) => U, +): (data: T) => Mapped>; + /** * It loops over each property of `obj` and returns a new object with only those properties that satisfy the `predicate`. */ @@ -455,9 +483,6 @@ export function indexBy( property: K ): (list: T[]) => Record; -// API_MARKER_END -// ============================================ - /** * It uses `R.equals` for list of objects/arrays or native `indexOf` for any other case. */ @@ -466,8 +491,9 @@ export function indexOf(valueToFind: T): (list: T[]) => number; /** * It returns all but the last element of list or string `input`. */ -export function init(input: T): T extends readonly [...infer U, any] ? U : [...T]; -export function init(input: string): string; +export function init(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [...infer U, any] ? U : T : T extends string ? string : never; /** * It generates a new string from `inputWithTags` by replacing all `{{x}}` occurrences with values provided by `templateArguments`. @@ -538,6 +564,36 @@ export function mapAsync( fn: (value: T[number]) => Promise, ): (data: T) => Promise>; +/** + * Chained 2 or 3 `R.map` transformations as one. + */ +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U, index: number) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number], index: number) => U, + fn2: (value: U, index: number) => V, + fn3: (value: V, index: number) => Y, +): (data: T) => Mapped; +export function mapChain( + fn1: (value: T[number]) => U, + fn2: (value: U) => V, + fn3: (value: V) => Y, +): (data: T) => Mapped; + /** * It returns a copy of `obj` with keys transformed by `fn`. */ @@ -610,6 +666,13 @@ export function merge(source: Source): (data: T) => Merge; */ export function mergeTypes(x: T): MergeTypes; +/** + * It returns all but the first and last element of `input`. + */ +export function middle(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : T['length'] extends 2 ? [] : + T extends [any, ...infer U, any] ? U : T : T extends string ? string : never; + /** * It returns the lesser value between `x` and `y` according to `compareFn` function. */ @@ -1791,6 +1854,11 @@ export function propOr(property: P, defaultValue: T): (obj: */ export function propSatisfies(predicate: (x: T) => boolean, property: string): (obj: Record) => boolean; +/** + * It returns a random number between `min` inclusive and `max` inclusive. + */ +export function random(minInclusive: number, maxInclusive: number): number; + /** * It returns list of numbers between `startInclusive` to `endInclusive` markers. */ @@ -2208,6 +2276,14 @@ export function split(separator: string | RegExp): (str: string) => string[]; */ export function splitEvery(sliceLength: number): (input: T[]) => (T[])[]; +export function sum(list: number[]): number; + +export function switcher(valueToMatch: T): Switchem; +export function switcher(valueToMatch: T): Switchem2; + +// API_MARKER_END +// ============================================ + /** * It returns all items that are in either of the lists, but not in both. * @@ -2218,8 +2294,9 @@ export function symmetricDifference(x: T[]): (y: T[]) => T[]; /** * It returns all but the first element of `input`. */ -export function tail(input: T): T extends [any, ...infer U] ? U : [...T]; -export function tail(input: string): string; +export function tail(input: T): T extends unknown[] ? + T['length'] extends 0 ? [] : T['length'] extends 1 ? [] : + T extends [any, ...infer U] ? U : T : T extends string ? string : never; /** * It returns the first `howMany` elements of `input`. diff --git a/rambda.js b/rambda.js index 51adfb45..3ad5d98d 100644 --- a/rambda.js +++ b/rambda.js @@ -17,6 +17,7 @@ export * from './src/count.js' export * from './src/countBy.js' export * from './src/createObjectFromKeys.js' export * from './src/defaultTo.js' +export * from './src/delay.js' export * from './src/descend.js' export * from './src/difference.js' export * from './src/drop.js' @@ -32,6 +33,7 @@ export * from './src/excludes.js' export * from './src/exists.js' export * from './src/filter.js' export * from './src/filterAsync.js' +export * from './src/filterMap.js' export * from './src/filterObject.js' export * from './src/find.js' export * from './src/findIndex.js' @@ -56,6 +58,7 @@ export * from './src/last.js' export * from './src/lastIndexOf.js' export * from './src/map.js' export * from './src/mapAsync.js' +export * from './src/mapChain.js' export * from './src/mapKeys.js' export * from './src/mapObject.js' export * from './src/mapObjectAsync.js' @@ -65,6 +68,7 @@ export * from './src/match.js' export * from './src/maxBy.js' export * from './src/merge.js' export * from './src/mergeTypes.js' +export * from './src/middle.js' export * from './src/minBy.js' export * from './src/modifyItemAtIndex.js' export * from './src/modifyPath.js' @@ -87,6 +91,7 @@ export * from './src/prop.js' export * from './src/propEq.js' export * from './src/propOr.js' export * from './src/propSatisfies.js' +export * from './src/random.js' export * from './src/range.js' export * from './src/rangeDescending.js' export * from './src/reduce.js' @@ -104,6 +109,8 @@ export * from './src/sortObject.js' export * from './src/sortWith.js' export * from './src/split.js' export * from './src/splitEvery.js' +export * from './src/sum.js' +export * from './src/switcher.js' export * from './src/symmetricDifference.js' export * from './src/tail.js' export * from './src/take.js' diff --git a/source/filterMap.js b/source/filterMap.js index c46e5157..5e09e234 100644 --- a/source/filterMap.js +++ b/source/filterMap.js @@ -1,3 +1,5 @@ +import {mapFn} from './map.js' + export function filterMap(fn) { return list => mapFn(fn, list).filter(Boolean) } diff --git a/source/random.js b/source/random.js new file mode 100644 index 00000000..ebc45fbb --- /dev/null +++ b/source/random.js @@ -0,0 +1,3 @@ +export function random(min, max){ + return Math.floor(Math.random() * (max - min + 1)) + min +} diff --git a/source/random.spec.js b/source/random.spec.js new file mode 100644 index 00000000..f44184ff --- /dev/null +++ b/source/random.spec.js @@ -0,0 +1,9 @@ +import { random } from './random.js' +import { range } from './range.js' +import { uniq } from './uniq.js' + +test('happy', () => { + const result = uniq(range(100).map(() => random(0, 3))).sort() + expect(result).toEqual([0,1,2,3]) +}) + diff --git a/source/sum.js b/source/sum.js new file mode 100644 index 00000000..079c536f --- /dev/null +++ b/source/sum.js @@ -0,0 +1,3 @@ +export function sum(list){ + return list.reduce((acc, cur) => acc + cur, 0) +} \ No newline at end of file diff --git a/source/sum.spec.js b/source/sum.spec.js new file mode 100644 index 00000000..43d85963 --- /dev/null +++ b/source/sum.spec.js @@ -0,0 +1,5 @@ +import { sum } from './sum.js' + +test('happy', () => { + expect(sum([1,2,3])).toEqual(6) +}) diff --git a/source/switcher-spec.ts b/source/switcher-spec.ts new file mode 100644 index 00000000..7da4b5c9 --- /dev/null +++ b/source/switcher-spec.ts @@ -0,0 +1,25 @@ +import { switcher } from 'rambda' + +describe('R.switcher', () => { + it('no transformation', () => { + const list = [1, 2, 3] + + const result = switcher(list.length) + .is(x => x < 2, 4) + .is(x => x < 4, 6) + .default(7) + + result // $ExpectType number + }) + it('with transformation', () => { + const list = [1, 2, 3] + type Stage = 'firstStage' | 'secondStage' | 'thirdStage' + + const result = switcher(list.length) + .is(x => x < 2, 'firstStage') + .is(x => x < 4, 'secondStage') + .default('thirdStage') + + result // $ExpectType { id: number; }[] + }) +}) diff --git a/source/switcher.js b/source/switcher.js new file mode 100644 index 00000000..a4aa23b8 --- /dev/null +++ b/source/switcher.js @@ -0,0 +1,78 @@ +import { equals } from './equals.js' + +const NO_MATCH_FOUND = Symbol ? Symbol('NO_MATCH_FOUND') : undefined + +const getMatchingKeyValuePair = ( + cases, testValue, defaultValue +) => { + let iterationValue + + for (let index = 0; index < cases.length; index++){ + iterationValue = cases[ index ].test(testValue) + + if (iterationValue !== NO_MATCH_FOUND){ + return iterationValue + } + } + + return defaultValue +} + +const isEqual = (testValue, matchValue) => { + const willReturn = + typeof testValue === 'function' ? + testValue(matchValue) : + equals(testValue)(matchValue) + + return willReturn +} + +const is = (testValue, matchResult = true) => ({ + key : testValue, + test : matchValue => + isEqual(testValue, matchValue) ? matchResult : NO_MATCH_FOUND, +}) + +class Switchem{ + constructor( + defaultValue, cases, willMatch + ){ + if (cases === undefined && willMatch === undefined){ + this.cases = [] + this.defaultValue = undefined + this.willMatch = defaultValue + } else { + this.cases = cases + this.defaultValue = defaultValue + this.willMatch = willMatch + } + + return this + } + + default(defaultValue){ + const holder = new Switchem( + defaultValue, this.cases, this.willMatch + ) + + return holder.match(this.willMatch) + } + + is(testValue, matchResult){ + return new Switchem( + this.defaultValue, + [ ...this.cases, is(testValue, matchResult) ], + this.willMatch + ) + } + + match(matchValue){ + return getMatchingKeyValuePair( + this.cases, matchValue, this.defaultValue + ) + } +} + +export function switcher(input){ + return new Switchem(input) +} diff --git a/source/switcher.spec.js b/source/switcher.spec.js new file mode 100644 index 00000000..ced4c07d --- /dev/null +++ b/source/switcher.spec.js @@ -0,0 +1,75 @@ +import { switcher } from './switcher.js' +import { tap } from './tap.js' + +test('with undefined', () => { + const result = switcher(undefined) + .is(x => x === 0, '0') + .is(x => x === undefined, 'UNDEFINED') + .default('3') + + expect(result).toBe('UNDEFINED') +}) + +test('happy', () => { + const a = true + const b = false + const result = switcher([ a, b ]) + .is([ false, false ], '0') + .is([ false, true ], '1') + .is([ true, true ], '2') + .default('3') + + expect(result).toBe('3') +}) + +test('can compare objects', () => { + const result = switcher({ a : 1 }) + .is({ a : 1 }, 'it is object') + .is('baz', 'it is baz') + .default('it is default') + + expect(result).toBe('it is object') +}) + +test('options are mixture of functions and values - input match function', () => { + const fn = switcher('foo').is('bar', 1) + .is('foo', x => x + 1) + .default(1000) + + expect(fn(2)).toBe(3) +}) + +test('options are mixture of functions and values - input match value', () => { + const result = switcher('bar').is('bar', 1) + .is('foo', x => x + 1) + .default(1000) + + expect(result).toBe(1) +}) + +test('return function if all options are functions', () => { + const fn = switcher('foo') + .is('bar', tap) + .is('foo', x => x + 1) + .default(9) + + expect(fn(2)).toBe(3) +}) + +const switchFn = input => + switcher(input) + .is(x => x.length && x.length === 7, 'has length of 7') + .is('baz', 'it is baz') + .default('it is default') + +test('works with function as condition', () => { + expect(switchFn([ 0, 1, 2, 3, 4, 5, 6 ])).toBe('has length of 7') +}) + +test('works with string as condition', () => { + expect(switchFn('baz')).toBe('it is baz') +}) + +test('fallback to default input when no matches', () => { + expect(switchFn(1)).toBe('it is default') +}) diff --git a/src/delay.js b/src/delay.js new file mode 100644 index 00000000..f7ebcb43 --- /dev/null +++ b/src/delay.js @@ -0,0 +1,9 @@ +export const DELAY = 'RAMBDA_DELAY' + +export function delay(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve(DELAY) + }, ms) + }) +} diff --git a/src/drop.js b/src/drop.js index 5e1ff66c..658791a9 100644 --- a/src/drop.js +++ b/src/drop.js @@ -1,3 +1,3 @@ -export function drop(howManyToDrop, ) { +export function drop(howManyToDrop) { return list => list.slice(howManyToDrop > 0 ? howManyToDrop : 0) } diff --git a/src/filterMap.js b/src/filterMap.js new file mode 100644 index 00000000..5e09e234 --- /dev/null +++ b/src/filterMap.js @@ -0,0 +1,5 @@ +import {mapFn} from './map.js' + +export function filterMap(fn) { + return list => mapFn(fn, list).filter(Boolean) +} diff --git a/src/mapChain.js b/src/mapChain.js new file mode 100644 index 00000000..fb326122 --- /dev/null +++ b/src/mapChain.js @@ -0,0 +1,11 @@ +import { mapFn } from "./map.js"; + +export function mapChain(...fns) { + return list => { + let result = list.slice() + fns.forEach((fn) => { + result = mapFn(fn, result) + }) + return result + } +} diff --git a/src/middle.js b/src/middle.js new file mode 100644 index 00000000..be537f1b --- /dev/null +++ b/src/middle.js @@ -0,0 +1,6 @@ +import { init } from './init.js' +import { tail } from './tail.js' + +export function middle(listOrString) { + return tail(init(listOrString)) +} diff --git a/src/random.js b/src/random.js new file mode 100644 index 00000000..ebc45fbb --- /dev/null +++ b/src/random.js @@ -0,0 +1,3 @@ +export function random(min, max){ + return Math.floor(Math.random() * (max - min + 1)) + min +} diff --git a/src/sum.js b/src/sum.js new file mode 100644 index 00000000..079c536f --- /dev/null +++ b/src/sum.js @@ -0,0 +1,3 @@ +export function sum(list){ + return list.reduce((acc, cur) => acc + cur, 0) +} \ No newline at end of file diff --git a/src/switcher.js b/src/switcher.js new file mode 100644 index 00000000..a4aa23b8 --- /dev/null +++ b/src/switcher.js @@ -0,0 +1,78 @@ +import { equals } from './equals.js' + +const NO_MATCH_FOUND = Symbol ? Symbol('NO_MATCH_FOUND') : undefined + +const getMatchingKeyValuePair = ( + cases, testValue, defaultValue +) => { + let iterationValue + + for (let index = 0; index < cases.length; index++){ + iterationValue = cases[ index ].test(testValue) + + if (iterationValue !== NO_MATCH_FOUND){ + return iterationValue + } + } + + return defaultValue +} + +const isEqual = (testValue, matchValue) => { + const willReturn = + typeof testValue === 'function' ? + testValue(matchValue) : + equals(testValue)(matchValue) + + return willReturn +} + +const is = (testValue, matchResult = true) => ({ + key : testValue, + test : matchValue => + isEqual(testValue, matchValue) ? matchResult : NO_MATCH_FOUND, +}) + +class Switchem{ + constructor( + defaultValue, cases, willMatch + ){ + if (cases === undefined && willMatch === undefined){ + this.cases = [] + this.defaultValue = undefined + this.willMatch = defaultValue + } else { + this.cases = cases + this.defaultValue = defaultValue + this.willMatch = willMatch + } + + return this + } + + default(defaultValue){ + const holder = new Switchem( + defaultValue, this.cases, this.willMatch + ) + + return holder.match(this.willMatch) + } + + is(testValue, matchResult){ + return new Switchem( + this.defaultValue, + [ ...this.cases, is(testValue, matchResult) ], + this.willMatch + ) + } + + match(matchValue){ + return getMatchingKeyValuePair( + this.cases, matchValue, this.defaultValue + ) + } +} + +export function switcher(input){ + return new Switchem(input) +} From 93cbd415450cb5aa9fde9f15084d7df2da21499b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 14:06:48 +0200 Subject: [PATCH 49/54] chore@small --- README.md | 10 +++++----- docs/README.md | 10 +++++----- source/init-spec.ts | 2 +- source/mapChain-spec.ts | 2 +- source/middle-spec.ts | 2 +- source/switcher-spec.ts | 2 +- source/tail-spec.ts | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 863e28be..710f1972 100644 --- a/README.md +++ b/README.md @@ -5586,7 +5586,7 @@ describe('R.init', () => { map(x => x * 2), init, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( @@ -6724,7 +6724,7 @@ it('R.mapChain - 3 functions', () => { }, ), ) - result // $ExpectType ("bar" | "foo")[] + result // $ExpectType ("foo" | "bar")[] }) ``` @@ -7697,7 +7697,7 @@ describe('R.middle', () => { map(x => x * 2), middle, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( @@ -12396,7 +12396,7 @@ describe('R.switcher', () => { .is(x => x < 4, 'secondStage') .default('thirdStage') - result // $ExpectType { id: number; }[] + result // $ExpectType Stage }) }) ``` @@ -12600,7 +12600,7 @@ describe('R.tail', () => { map(x => x * 2), tail, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( diff --git a/docs/README.md b/docs/README.md index 863e28be..710f1972 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5586,7 +5586,7 @@ describe('R.init', () => { map(x => x * 2), init, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( @@ -6724,7 +6724,7 @@ it('R.mapChain - 3 functions', () => { }, ), ) - result // $ExpectType ("bar" | "foo")[] + result // $ExpectType ("foo" | "bar")[] }) ``` @@ -7697,7 +7697,7 @@ describe('R.middle', () => { map(x => x * 2), middle, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( @@ -12396,7 +12396,7 @@ describe('R.switcher', () => { .is(x => x < 4, 'secondStage') .default('thirdStage') - result // $ExpectType { id: number; }[] + result // $ExpectType Stage }) }) ``` @@ -12600,7 +12600,7 @@ describe('R.tail', () => { map(x => x * 2), tail, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( diff --git a/source/init-spec.ts b/source/init-spec.ts index 1c5da8ac..b0346cdb 100644 --- a/source/init-spec.ts +++ b/source/init-spec.ts @@ -20,7 +20,7 @@ describe('R.init', () => { map(x => x * 2), init, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( diff --git a/source/mapChain-spec.ts b/source/mapChain-spec.ts index 329031ab..c2c2edcc 100644 --- a/source/mapChain-spec.ts +++ b/source/mapChain-spec.ts @@ -56,5 +56,5 @@ it('R.mapChain - 3 functions', () => { }, ), ) - result // $ExpectType ("bar" | "foo")[] + result // $ExpectType ("foo" | "bar")[] }) diff --git a/source/middle-spec.ts b/source/middle-spec.ts index 646d7a22..529ae45c 100644 --- a/source/middle-spec.ts +++ b/source/middle-spec.ts @@ -20,7 +20,7 @@ describe('R.middle', () => { map(x => x * 2), middle, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( diff --git a/source/switcher-spec.ts b/source/switcher-spec.ts index 7da4b5c9..73b3fc80 100644 --- a/source/switcher-spec.ts +++ b/source/switcher-spec.ts @@ -20,6 +20,6 @@ describe('R.switcher', () => { .is(x => x < 4, 'secondStage') .default('thirdStage') - result // $ExpectType { id: number; }[] + result // $ExpectType Stage }) }) diff --git a/source/tail-spec.ts b/source/tail-spec.ts index ee4145f5..902ed518 100644 --- a/source/tail-spec.ts +++ b/source/tail-spec.ts @@ -20,7 +20,7 @@ describe('R.tail', () => { map(x => x * 2), tail, ) - result // $ExpectType number[] + result // $ExpectType [] }) it('with list - using const', () => { const result = pipe( From 98f31d45445035926a327b8501e2cca8fafbb78b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 14:43:49 +0200 Subject: [PATCH 50/54] 1 --- files/index.d.ts | 4 ++-- index.d.cts | 4 ++-- index.d.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/files/index.d.ts b/files/index.d.ts index 7501a273..e8cda07a 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -130,11 +130,11 @@ type isfn2 = (fn: (x: T) => boolean, y: V) => U; interface Switchem { is: isfn>; default: (x: T) => T; -}; +} interface Switchem2 { is: isfn2>; default: (x: U) => U; -}; +} // API_MARKER diff --git a/index.d.cts b/index.d.cts index 04eb0ff6..f346e943 100644 --- a/index.d.cts +++ b/index.d.cts @@ -130,11 +130,11 @@ type isfn2 = (fn: (x: T) => boolean, y: V) => U; interface Switchem { is: isfn>; default: (x: T) => T; -}; +} interface Switchem2 { is: isfn2>; default: (x: U) => U; -}; +} /** diff --git a/index.d.ts b/index.d.ts index 04eb0ff6..f346e943 100644 --- a/index.d.ts +++ b/index.d.ts @@ -130,11 +130,11 @@ type isfn2 = (fn: (x: T) => boolean, y: V) => U; interface Switchem { is: isfn>; default: (x: T) => T; -}; +} interface Switchem2 { is: isfn2>; default: (x: U) => U; -}; +} /** From fff02de781de44b311776284fb3f0a90410277ca Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 14:50:03 +0200 Subject: [PATCH 51/54] 1 --- files/index.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/files/index.d.ts b/files/index.d.ts index e8cda07a..c672f0bb 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -5080,6 +5080,13 @@ Explanation: Example: ``` +const list = [1, 2, 3] + +const result = switcher(list.length) + .is(x => x < 2, 4) + .is(x => x < 4, 6) + .default(7) +// => 6 ``` Categories: Logic From 0404ea11000bc56b6b72b50a60aecaa61a4a0059 Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 14:53:36 +0200 Subject: [PATCH 52/54] chore@small --- README.md | 26 +++++++++++++++++++------- docs/README.md | 26 +++++++++++++++++++------- source/addProp.spec.js | 2 +- source/addPropToObjects.spec.js | 4 ++-- source/mapChain.js | 2 +- source/mapKeys.spec.js | 2 +- source/pluck-spec.ts | 2 +- source/sortByDescending.js | 2 +- source/sum.js | 2 +- src/mapChain.js | 2 +- src/sortByDescending.js | 2 +- src/sum.js | 2 +- 12 files changed, 49 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 710f1972..10792471 100644 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ export function addProp(key, value) { Tests ```javascript -import { addProp } from "./addProp.js" +import { addProp } from './addProp.js' test('happy', () => { const result = addProp('a', 1)({ b: 2 }) @@ -325,8 +325,8 @@ export function addPropToObjects ( Tests ```javascript -import { pipe } from "./pipe.js" -import { addPropToObjects } from "./addPropToObjects.js" +import { pipe } from './pipe.js' +import { addPropToObjects } from './addPropToObjects.js' test('R.addPropToObjects', () => { let result = pipe( @@ -6630,7 +6630,7 @@ mapChain( R.mapChain source ```javascript -import { mapFn } from "./map.js"; +import { mapFn } from './map.js'; export function mapChain(...fns) { return list => { @@ -6787,7 +6787,7 @@ export function mapKeys(fn) { Tests ```javascript -import { mapKeys } from "./mapKeys.js" +import { mapKeys } from './mapKeys.js' test('happy', () => { const result = mapKeys((prop, x) => `${ prop }-${x}`)({a:1, b: 2 }) @@ -9905,7 +9905,7 @@ test('with undefined', () => { TypeScript test ```typescript -import { pipe, pluck } from "rambda"; +import { pipe, pluck } from 'rambda'; it("R.pluck", () => { const input = [ @@ -11424,7 +11424,7 @@ sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[]; R.sortByDescending source ```javascript -import { sortByFn } from "./sortBy.js"; +import { sortByFn } from './sortBy.js'; export function sortByDescending(sortFn) { return list => sortByFn(sortFn, list, true) @@ -12184,6 +12184,18 @@ test('happy', () => { switcher(valueToMatch: T): Switchem ``` +```javascript +const list = [1, 2, 3] + +const result = switcher(list.length) + .is(x => x < 2, 4) + .is(x => x < 4, 6) + .default(7) +// => 6 +``` + +Try this R.switcher example in Rambda REPL +
All TypeScript definitions diff --git a/docs/README.md b/docs/README.md index 710f1972..10792471 100644 --- a/docs/README.md +++ b/docs/README.md @@ -215,7 +215,7 @@ export function addProp(key, value) { Tests ```javascript -import { addProp } from "./addProp.js" +import { addProp } from './addProp.js' test('happy', () => { const result = addProp('a', 1)({ b: 2 }) @@ -325,8 +325,8 @@ export function addPropToObjects ( Tests ```javascript -import { pipe } from "./pipe.js" -import { addPropToObjects } from "./addPropToObjects.js" +import { pipe } from './pipe.js' +import { addPropToObjects } from './addPropToObjects.js' test('R.addPropToObjects', () => { let result = pipe( @@ -6630,7 +6630,7 @@ mapChain( R.mapChain source ```javascript -import { mapFn } from "./map.js"; +import { mapFn } from './map.js'; export function mapChain(...fns) { return list => { @@ -6787,7 +6787,7 @@ export function mapKeys(fn) { Tests ```javascript -import { mapKeys } from "./mapKeys.js" +import { mapKeys } from './mapKeys.js' test('happy', () => { const result = mapKeys((prop, x) => `${ prop }-${x}`)({a:1, b: 2 }) @@ -9905,7 +9905,7 @@ test('with undefined', () => { TypeScript test ```typescript -import { pipe, pluck } from "rambda"; +import { pipe, pluck } from 'rambda'; it("R.pluck", () => { const input = [ @@ -11424,7 +11424,7 @@ sortByDescending(sortFn: (x: T) => Ord): (list: T[]) => T[]; R.sortByDescending source ```javascript -import { sortByFn } from "./sortBy.js"; +import { sortByFn } from './sortBy.js'; export function sortByDescending(sortFn) { return list => sortByFn(sortFn, list, true) @@ -12184,6 +12184,18 @@ test('happy', () => { switcher(valueToMatch: T): Switchem ``` +```javascript +const list = [1, 2, 3] + +const result = switcher(list.length) + .is(x => x < 2, 4) + .is(x => x < 4, 6) + .default(7) +// => 6 +``` + +Try this R.switcher example in Rambda REPL +
All TypeScript definitions diff --git a/source/addProp.spec.js b/source/addProp.spec.js index d1dd641f..5ef8179b 100644 --- a/source/addProp.spec.js +++ b/source/addProp.spec.js @@ -1,4 +1,4 @@ -import { addProp } from "./addProp.js" +import { addProp } from './addProp.js' test('happy', () => { const result = addProp('a', 1)({ b: 2 }) diff --git a/source/addPropToObjects.spec.js b/source/addPropToObjects.spec.js index 2a948808..0a989300 100644 --- a/source/addPropToObjects.spec.js +++ b/source/addPropToObjects.spec.js @@ -1,5 +1,5 @@ -import { pipe } from "./pipe.js" -import { addPropToObjects } from "./addPropToObjects.js" +import { pipe } from './pipe.js' +import { addPropToObjects } from './addPropToObjects.js' test('R.addPropToObjects', () => { let result = pipe( diff --git a/source/mapChain.js b/source/mapChain.js index fb326122..1543c9a2 100644 --- a/source/mapChain.js +++ b/source/mapChain.js @@ -1,4 +1,4 @@ -import { mapFn } from "./map.js"; +import { mapFn } from './map.js'; export function mapChain(...fns) { return list => { diff --git a/source/mapKeys.spec.js b/source/mapKeys.spec.js index 47f443e1..6358439b 100644 --- a/source/mapKeys.spec.js +++ b/source/mapKeys.spec.js @@ -1,4 +1,4 @@ -import { mapKeys } from "./mapKeys.js" +import { mapKeys } from './mapKeys.js' test('happy', () => { const result = mapKeys((prop, x) => `${ prop }-${x}`)({a:1, b: 2 }) diff --git a/source/pluck-spec.ts b/source/pluck-spec.ts index 1d048373..3c15710e 100644 --- a/source/pluck-spec.ts +++ b/source/pluck-spec.ts @@ -1,4 +1,4 @@ -import { pipe, pluck } from "rambda"; +import { pipe, pluck } from 'rambda'; it("R.pluck", () => { const input = [ diff --git a/source/sortByDescending.js b/source/sortByDescending.js index 86d702d8..46522d4a 100644 --- a/source/sortByDescending.js +++ b/source/sortByDescending.js @@ -1,4 +1,4 @@ -import { sortByFn } from "./sortBy.js"; +import { sortByFn } from './sortBy.js'; export function sortByDescending(sortFn) { return list => sortByFn(sortFn, list, true) diff --git a/source/sum.js b/source/sum.js index 079c536f..fc898956 100644 --- a/source/sum.js +++ b/source/sum.js @@ -1,3 +1,3 @@ export function sum(list){ return list.reduce((acc, cur) => acc + cur, 0) -} \ No newline at end of file +} diff --git a/src/mapChain.js b/src/mapChain.js index fb326122..1543c9a2 100644 --- a/src/mapChain.js +++ b/src/mapChain.js @@ -1,4 +1,4 @@ -import { mapFn } from "./map.js"; +import { mapFn } from './map.js'; export function mapChain(...fns) { return list => { diff --git a/src/sortByDescending.js b/src/sortByDescending.js index 86d702d8..46522d4a 100644 --- a/src/sortByDescending.js +++ b/src/sortByDescending.js @@ -1,4 +1,4 @@ -import { sortByFn } from "./sortBy.js"; +import { sortByFn } from './sortBy.js'; export function sortByDescending(sortFn) { return list => sortByFn(sortFn, list, true) diff --git a/src/sum.js b/src/sum.js index 079c536f..fc898956 100644 --- a/src/sum.js +++ b/src/sum.js @@ -1,3 +1,3 @@ export function sum(list){ return list.reduce((acc, cur) => acc + cur, 0) -} \ No newline at end of file +} From 58baa5452c79a8080875bbff7b8da8a8fb5ac6cb Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 14:54:23 +0200 Subject: [PATCH 53/54] chore@small --- README.md | 4 ++-- dist/rambda.cjs | 6 +++--- dist/rambda.js | 6 +++--- dist/rambda.umd.js | 6 +++--- docs/README.md | 4 ++-- source/delay.js | 4 ++-- src/delay.js | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 10792471..80381ad4 100644 --- a/README.md +++ b/README.md @@ -1965,12 +1965,12 @@ delay(ms: number): Promise<'RAMBDA_DELAY'>; R.delay source ```javascript -export const DELAY = 'RAMBDA_DELAY' +export const RAMBDA_DELAY = 'RAMBDA_DELAY' export function delay(ms) { return new Promise(resolve => { setTimeout(() => { - resolve(DELAY) + resolve(RAMBDA_DELAY) }, ms) }) } diff --git a/dist/rambda.cjs b/dist/rambda.cjs index 46919443..23ee0a76 100644 --- a/dist/rambda.cjs +++ b/dist/rambda.cjs @@ -249,12 +249,12 @@ function defaultTo(defaultArgument) { return input => isFalsy(input) ? defaultArgument : input } -const DELAY = 'RAMBDA_DELAY'; +const RAMBDA_DELAY = 'RAMBDA_DELAY'; function delay(ms) { return new Promise(resolve => { setTimeout(() => { - resolve(DELAY); + resolve(RAMBDA_DELAY); }, ms); }) } @@ -2003,7 +2003,7 @@ function zipWith(fn, x) { ) } -exports.DELAY = DELAY; +exports.RAMBDA_DELAY = RAMBDA_DELAY; exports._arity = _arity; exports._includes = _includes; exports._indexOf = _indexOf; diff --git a/dist/rambda.js b/dist/rambda.js index fd7bf401..3019bcfe 100644 --- a/dist/rambda.js +++ b/dist/rambda.js @@ -247,12 +247,12 @@ function defaultTo(defaultArgument) { return input => isFalsy(input) ? defaultArgument : input } -const DELAY = 'RAMBDA_DELAY'; +const RAMBDA_DELAY = 'RAMBDA_DELAY'; function delay(ms) { return new Promise(resolve => { setTimeout(() => { - resolve(DELAY); + resolve(RAMBDA_DELAY); }, ms); }) } @@ -2001,4 +2001,4 @@ function zipWith(fn, x) { ) } -export { DELAY, _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, delay, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, exists, filter, filterAsync, filterMap, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapChain, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, middle, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, random, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, sum, switcher, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; +export { RAMBDA_DELAY, _arity, _includes, _indexOf, _lastIndexOf, addProp, addPropToObjects, all, allPass, any, anyPass, append, ascend, assertType, checkObjectWithSpec, compact, complement, concat, convertToType, count, countBy, createCompareFunction, createObjectFromKeys, defaultTo, delay, descend, difference, drop, dropLast, dropLastWhile, dropWhile, duplicateBy, eqBy, eqProps, equals, equalsFn, evolve, excludes, exists, filter, filterAsync, filterMap, filterObject, find, findIndex, findLast, findLastIndex, findNth, flatMap, flatten, flattenObject, flattenObjectHelper, groupBy, groupByFallback, head, includes, indexBy, indexOf, init, interpolate, intersection, intersectionWith, intersperse, join, last, lastIndexOf, map, mapAsync, mapChain, mapFn, mapKeys, mapObject, mapObjectAsync, mapParallelAsync, mapPropObject, match, maxBy, merge, mergeTypes, middle, minBy, modifyItemAtIndex, modifyPath, modifyProp, none, objOf, objectIncludes, omit, partition, partitionObject, path, pathSatisfies, permutations, pick, pipe, pipeAsync, pluck, prepend, prop, propEq, propOr, propSatisfies, random, range, rangeDescending, reduce, reject, rejectObject, replace, replaceAll, shuffle, sort, sortBy, sortByDescending, sortByFn, sortByPath, sortByPathDescending, sortObject, sortWith, split, splitEvery, sum, switcher, symmetricDifference, tail, take, takeLast, takeLastWhile, takeWhile, tap, test, transformFlatObject, tryCatch, type, union, unionWith, uniq, uniqBy, uniqWith, unless, unwind, update, when, zip, zipWith }; diff --git a/dist/rambda.umd.js b/dist/rambda.umd.js index 01e60021..23636fe1 100644 --- a/dist/rambda.umd.js +++ b/dist/rambda.umd.js @@ -253,12 +253,12 @@ return input => isFalsy(input) ? defaultArgument : input } - const DELAY = 'RAMBDA_DELAY'; + const RAMBDA_DELAY = 'RAMBDA_DELAY'; function delay(ms) { return new Promise(resolve => { setTimeout(() => { - resolve(DELAY); + resolve(RAMBDA_DELAY); }, ms); }) } @@ -2007,7 +2007,7 @@ ) } - exports.DELAY = DELAY; + exports.RAMBDA_DELAY = RAMBDA_DELAY; exports._arity = _arity; exports._includes = _includes; exports._indexOf = _indexOf; diff --git a/docs/README.md b/docs/README.md index 10792471..80381ad4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1965,12 +1965,12 @@ delay(ms: number): Promise<'RAMBDA_DELAY'>; R.delay source ```javascript -export const DELAY = 'RAMBDA_DELAY' +export const RAMBDA_DELAY = 'RAMBDA_DELAY' export function delay(ms) { return new Promise(resolve => { setTimeout(() => { - resolve(DELAY) + resolve(RAMBDA_DELAY) }, ms) }) } diff --git a/source/delay.js b/source/delay.js index f7ebcb43..6276977b 100644 --- a/source/delay.js +++ b/source/delay.js @@ -1,9 +1,9 @@ -export const DELAY = 'RAMBDA_DELAY' +export const RAMBDA_DELAY = 'RAMBDA_DELAY' export function delay(ms) { return new Promise(resolve => { setTimeout(() => { - resolve(DELAY) + resolve(RAMBDA_DELAY) }, ms) }) } diff --git a/src/delay.js b/src/delay.js index f7ebcb43..6276977b 100644 --- a/src/delay.js +++ b/src/delay.js @@ -1,9 +1,9 @@ -export const DELAY = 'RAMBDA_DELAY' +export const RAMBDA_DELAY = 'RAMBDA_DELAY' export function delay(ms) { return new Promise(resolve => { setTimeout(() => { - resolve(DELAY) + resolve(RAMBDA_DELAY) }, ms) }) } From bd00e4e5976b8a9adced4ea45217808dc22c7a5b Mon Sep 17 00:00:00 2001 From: Dejan Toteff Date: Wed, 4 Feb 2026 14:56:50 +0200 Subject: [PATCH 54/54] chore@small --- README.md | 14 -------------- docs/README.md | 14 -------------- source/delay.spec.js | 5 ----- 3 files changed, 33 deletions(-) delete mode 100644 source/delay.spec.js diff --git a/README.md b/README.md index 80381ad4..d2af17fd 100644 --- a/README.md +++ b/README.md @@ -1978,20 +1978,6 @@ export function delay(ms) {
-
- -Tests - -```javascript -import { DELAY, delay } from './delay.js' - -test('usage with variables', async () => { - await expect(delay(500)).resolves.toBe(DELAY) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#delay) ### descend diff --git a/docs/README.md b/docs/README.md index 80381ad4..d2af17fd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1978,20 +1978,6 @@ export function delay(ms) {
-
- -Tests - -```javascript -import { DELAY, delay } from './delay.js' - -test('usage with variables', async () => { - await expect(delay(500)).resolves.toBe(DELAY) -}) -``` - -
- [![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#delay) ### descend diff --git a/source/delay.spec.js b/source/delay.spec.js deleted file mode 100644 index 793513f9..00000000 --- a/source/delay.spec.js +++ /dev/null @@ -1,5 +0,0 @@ -import { DELAY, delay } from './delay.js' - -test('usage with variables', async () => { - await expect(delay(500)).resolves.toBe(DELAY) -})