@ebflat9/fp
Advanced tools
Comparing version 1.1.19 to 1.1.20
{ | ||
"name": "@ebflat9/fp", | ||
"version": "1.1.19", | ||
"version": "1.1.20", | ||
"description": "my fp utils", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -5,3 +5,3 @@ # fp | ||
re-writing. I am slowly adding tests, run with `npm run test` and you should see | ||
82 test passing. | ||
97 test passing. | ||
@@ -8,0 +8,0 @@ Features: |
@@ -297,2 +297,15 @@ /** | ||
/** | ||
* Pick | ||
* @param {array} names - Array of property names | ||
* @param {object} a - Object to get property names from | ||
* @returns {object} A new object with only properties names | ||
*/ | ||
export const pick = curry((names, a) => | ||
names.reduce( | ||
(result, key) => (key in a ? ((result[key] = a[key]), result) : result), | ||
{} | ||
) | ||
) | ||
/** | ||
* Invoke | ||
@@ -323,2 +336,39 @@ * @param {function} fn - Function to invoke in new context | ||
/** | ||
* DeepSetProp | ||
* @param {string} {array} path - A path of properties or an Array of | ||
* properties to set | ||
* @param {any} value - The value to set | ||
* @param {object} a - Object to set new property in | ||
* @returns {object} A copy of Object a, with new property set | ||
*/ | ||
export const deepSetProp = curry((path, value, a) => { | ||
if (!Array.isArray(path)) path = path.split('.') | ||
function innerDeepSetProp(path, value, obj) { | ||
if (path.length === 1) { | ||
obj[path[0]] = value | ||
return obj | ||
} | ||
if (path[0] in obj && isObject(obj[path[0]])) { | ||
const newObj = obj[path[0]] | ||
return innerDeepSetProp(path.slice(1), value, newObj) | ||
} | ||
const newObj = {} | ||
obj[path[0]] = newObj | ||
return innerDeepSetProp(path.slice(1), value, newObj) | ||
} | ||
const aux = deepCopy(a) | ||
return innerDeepSetProp(path, value, aux), aux | ||
}) | ||
/** | ||
* DeepPick | ||
* @param {array} paths - An array of string paths of property names | ||
* @param {object} a - The Object to pick properties from | ||
* @returns {object} A copy of Object a with only properties paths | ||
*/ | ||
export const deepPick = curry((paths, a) => | ||
paths.reduce((result, path) => deepSetProp(path, deepProp(path)(a))(result), {}) | ||
) | ||
/** | ||
* Stringifying functions | ||
@@ -538,3 +588,3 @@ * Provides helper functions to stringify and parse JSON, along with numbers | ||
*/ | ||
export const FunctionalMixin = (behaviour, sharedBehaviour = {}) => { | ||
export function FunctionalMixin(behaviour, sharedBehaviour = {}) { | ||
const instanceKeys = Reflect.ownKeys(behaviour) | ||
@@ -633,3 +683,3 @@ const sharedKeys = Reflect.ownKeys(sharedBehaviour) | ||
*/ | ||
export const deepFreeze = obj => { | ||
export function deepFreeze(obj) { | ||
if (obj && typeof obj === 'object' && !Object.isFrozen(obj)) { | ||
@@ -647,3 +697,3 @@ Object.getOwnPropertyNames(obj).forEach(name => deepFreeze(obj[name])) | ||
*/ | ||
export const deepCopy = obj => { | ||
export function deepCopy(obj) { | ||
let aux = obj | ||
@@ -650,0 +700,0 @@ if (obj && typeof obj === 'object') { |
@@ -1,2 +0,7 @@ | ||
// Iterables | ||
/** | ||
* MapWith | ||
* @param {function} fn - Mapper function | ||
* @param {iterable} iterable | ||
* @returns {function} Generator iterator function | ||
*/ | ||
export function* mapWith(fn, iterable) { | ||
@@ -8,2 +13,9 @@ for (const element of iterable) { | ||
/** | ||
* MapAllWith | ||
* @param {function} fn - Mapper function | ||
* @param {iterable} iterable | ||
* @returns {function} Generator iterator function that applies mapper to all | ||
* elements and then yields the result of their individual iteration | ||
*/ | ||
export function* mapAllWith(fn, iterable) { | ||
@@ -15,8 +27,21 @@ for (const element of iterable) { | ||
/** | ||
* FilterWith | ||
* @param {function} fn - Filter function | ||
* @param {iterable} iterable | ||
* @returns {function} Generator iterator function that filters elements by | ||
* function fn | ||
*/ | ||
export function* filterWith(fn, iterable) { | ||
for (const element of iterable) { | ||
if (!fn(element)) yield element | ||
if (fn(element)) yield element | ||
} | ||
} | ||
/** | ||
* Compact | ||
* @param {iterable} iterable | ||
* @returns {function} Generator iterator function that removes nullable | ||
* values | ||
*/ | ||
export function* compact(iterable) { | ||
@@ -28,2 +53,9 @@ for (const element of iterable) { | ||
/** | ||
* UntilWith | ||
* @param {function} fn - Tester function | ||
* @param {iterable} iterable | ||
* @returns {function} Generator iterator function that returns elements until | ||
* the result of fn(element) is true | ||
*/ | ||
export function* untilWith(fn, iterable) { | ||
@@ -36,4 +68,14 @@ for (const element of iterable) { | ||
/** | ||
* First | ||
* @param {iterable} iterable | ||
* @returns {any} First element of iterable | ||
*/ | ||
export const first = iterable => iterable[Symbol.iterator]().next().value | ||
/** | ||
* Rest | ||
* @param {iterable} iterable | ||
* @returns {function} Generator iterator function skipping the first element | ||
*/ | ||
export function* rest(iterable) { | ||
@@ -45,2 +87,9 @@ const iterator = iterable[Symbol.iterator]() | ||
/** | ||
* Take | ||
* @param {number} numberToTake | ||
* @param {iterable} iterable | ||
* @returns {function} Generator iterator function that yields numberToTake | ||
* number elements from iteratable | ||
*/ | ||
export function* take(numberToTake, iterable) { | ||
@@ -54,2 +103,8 @@ const iterator = iterable[Symbol.iterator]() | ||
/** | ||
* Zip | ||
* @param {iterable} iterables | ||
* @returns {function} Generator iterator function that yields an array of | ||
* the combined values of each iterator of iterables | ||
*/ | ||
export function* zip(...iterables) { | ||
@@ -67,2 +122,9 @@ const iterators = iterables.map(i => i[Symbol.iterator]()) | ||
/** | ||
* ZipWith | ||
* @param {function} zipper - Function to apply to values | ||
* @param {iterable} iterables - Iterables to zip | ||
* @returns {function} Generator iterator function that yields the result | ||
* of applying zipper function to elements of iterables | ||
*/ | ||
export function* zipWith(zipper, ...iterables) { | ||
@@ -80,2 +142,9 @@ const iterators = iterables.map(i => i[Symbol.iterator]()) | ||
/** | ||
* ReduceWith | ||
* @param {function} fn - Reducer function | ||
* @param {any} seed - Initial value | ||
* @param {iterable} iterable | ||
* @returns {any} Result of reducing iterable with reducer | ||
*/ | ||
export function reduceWith(fn, seed, iterable) { | ||
@@ -89,2 +158,7 @@ let accumulator = seed | ||
/** | ||
* MemoizeIter | ||
* @param {function} generator - Iterator function | ||
* @returns {function} Memoized generator function | ||
*/ | ||
export function memoizeIter(generator) { | ||
@@ -91,0 +165,0 @@ const memos = Object.create(null) |
import * as combinators from '../src/combinators.js' | ||
import { describe, it } from 'mocha' | ||
import { strict as assert } from 'assert' | ||
import { AssertionError } from 'assert/strict' | ||
@@ -288,2 +287,13 @@ describe('Combinators', function () { | ||
describe('pick', function () { | ||
it('should create a new object with only prop names', function () { | ||
const obj = { | ||
firstName: 'Bob', | ||
lastName: 'Burgers', | ||
email: 'bob@burgers.co.uk', | ||
} | ||
assert.deepEqual(combinators.pick(['email'])(obj), { email: 'bob@burgers.co.uk' }) | ||
}) | ||
}) | ||
describe('send', function () { | ||
@@ -349,2 +359,44 @@ it('should call an instance with arguments', function () { | ||
describe('deepSetProp', function () { | ||
it('should set a deeply nested property', function () { | ||
assert.deepEqual(combinators.deepSetProp('a.b.c.d', 'hi')({}), { | ||
a: { b: { c: { d: 'hi' } } }, | ||
}) | ||
}) | ||
it('should not mutate object', function () { | ||
const obj = { | ||
a: { | ||
b: { | ||
c: { | ||
d: 'hi', | ||
}, | ||
}, | ||
e: 'world', | ||
}, | ||
} | ||
const result = combinators.deepSetProp('a.b.c.d', 'hello')(obj) | ||
assert.deepEqual(result, { | ||
a: { b: { c: { d: 'hello' } }, e: 'world' }, | ||
}) | ||
assert.notEqual(obj, result) | ||
}) | ||
}) | ||
describe('deepPick', function () { | ||
it('should return an object with only keys from paths', function () { | ||
const obj = { | ||
a: { | ||
b: { | ||
c: 'hi', | ||
}, | ||
e: 'world', | ||
}, | ||
h: 'sup', | ||
} | ||
const result = combinators.deepPick(['a.b.c', 'a.e'])(obj) | ||
assert.deepEqual(result, { a: { b: { c: 'hi' }, e: 'world' } }) | ||
assert.notEqual(obj, result) | ||
}) | ||
}) | ||
describe('toJSON', function () { | ||
@@ -351,0 +403,0 @@ it('should stringify x', function () { |
Sorry, the diff of this file is too big to display
232294
20
7452