New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

functools

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

functools - npm Package Compare versions

Comparing version 3.2.1 to 3.3.0

66

dist/index.d.ts

@@ -0,2 +1,14 @@

export declare const add: (a: number, b: number) => number;
export declare const subtract: (a: number, b: number) => number;
export declare const multiply: (a: number, b: number) => number;
export declare const divide: (a: number, b: number) => number;
/**
* Always returns the same value supplied to it.
*/
export declare const identity: <T>(value: T) => T;
/**
* Returns a function that always returns the same value supplied to it.
*/
export declare const always: <T>(value: T) => () => T;
/**
* Minimum required cache interface.

@@ -20,6 +32,2 @@ */

/**
* Always returns the same value that was used as the argument.
*/
export declare function identity<T>(value: T): T;
/**
* Return a function that fetches `key` from its operand.

@@ -34,8 +42,56 @@ */

export declare function invoke<K extends string | number | symbol, A extends any[]>(key: K, ...args: A): <T extends Record<K, (...args: A) => any>>(obj: T) => InvokeResult<T[K], A>;
export interface ThrottleOptions {
leading?: boolean;
trailing?: boolean;
debounce?: boolean;
}
/**
* Wrap a function to rate-limit the function executions to once every `ms` milliseconds.
*/
export declare function throttle(fn: () => void, ms: number, leading?: boolean): (() => void) & {
export declare function throttle<T extends any[]>(fn: (...args: T) => void, ms: number, { leading, trailing, debounce }?: ThrottleOptions): ((...args: T) => void) & {
flush: () => void;
clear: () => void;
};
/**
* Given a `fn`, return a wrapper that accepts an array of `fn` arguments.
*/
export declare function spread<T extends any[], R>(fn: (...args: T) => R): (args: T) => R;
/**
* Flip a binary `fn` argument order.
*/
export declare function flip<T1, T2, R>(fn: (arg1: T1, arg2: T2) => R): (arg2: T2, arg1: T1) => R;
/**
* Returns a partially applied `fn` with the supplied arguments.
*/
export declare function partial<U extends any[], R>(fn: (...args: U) => R): (...args: U) => R;
export declare function partial<T1, U extends any[], R>(fn: (arg1: T1, ...args: U) => R, arg1: T1): (...args: U) => R;
export declare function partial<T1, T2, U extends any[], R>(fn: (arg1: T1, arg2: T2, ...args: U) => R, arg1: T1, arg2: T2): (...args: U) => R;
export declare function partial<T1, T2, T3, U extends any[], R>(fn: (arg1: T1, arg2: T2, arg3: T3, ...args: U) => R, arg1: T1, arg2: T2, arg3: T3): (...args: U) => R;
export declare function partial<T1, T2, T3, T4, U extends any[], R>(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, ...args: U) => R, arg1: T1, arg2: T2, arg3: T3, arg4: T4): (...args: U) => R;
export declare function partial<T1, T2, T3, T4, T5, U extends any[], R>(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, ...args: U) => R, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5): (...args: U) => R;
/**
* Left-to-right function composition.
*/
export declare function sequence<T1, T2>(fn1: (arg: T1) => T2): (arg: T1) => T2;
export declare function sequence<T1, T2, T3>(fn1: (arg: T1) => T2, fn2: (arg: T2) => T3): (arg: T1) => T3;
export declare function sequence<T1, T2, T3, T4>(fn1: (arg: T1) => T2, fn2: (arg: T2) => T3, fn3: (arg: T3) => T4): (arg: T1) => T4;
export declare function sequence<T1, T2, T3, T4, T5>(fn1: (arg: T1) => T2, fn2: (arg: T2) => T3, fn3: (arg: T3) => T4, fn4: (arg: T4) => T5): (arg: T1) => T5;
export declare function sequence<T1, T2, T3, T4, T5, T6>(fn1: (arg: T1) => T2, fn2: (arg: T2) => T3, fn3: (arg: T3) => T4, fn4: (arg: T4) => T5, fn5: (arg: T5) => T6): (arg: T1) => T6;
/**
* Right-to-left function composition.
*/
export declare function compose<T1, T2>(fn1: (arg: T1) => T2): (arg: T1) => T2;
export declare function compose<T1, T2, T3>(fn2: (arg: T2) => T3, fn1: (arg: T1) => T2): (arg: T1) => T3;
export declare function compose<T1, T2, T3, T4>(fn3: (arg: T3) => T4, fn2: (arg: T2) => T3, fn1: (arg: T1) => T2): (arg: T1) => T4;
export declare function compose<T1, T2, T3, T4, T5>(fn4: (arg: T4) => T5, fn3: (arg: T3) => T4, fn2: (arg: T2) => T3, fn1: (arg: T1) => T2): (arg: T1) => T5;
export declare function compose<T1, T2, T3, T4, T5, T6>(fn5: (arg: T5) => T6, fn4: (arg: T4) => T5, fn3: (arg: T3) => T4, fn2: (arg: T2) => T3, fn1: (arg: T1) => T2): (arg: T1) => T6;
/**
* Fix the number of receivable arguments in `origFn` to `n`.
*/
export declare function nary<U extends any[], R>(n: 0, origFn: () => R): () => R;
export declare function nary<T1, U extends any[], R>(n: 1, origFn: (arg1: T1) => R): (arg1: T1) => R;
export declare function nary<T1, T2, U extends any[], R>(n: 2, origFn: (arg1: T1, arg2: T2) => R): (arg1: T1, arg2: T2) => R;
export declare function nary<T1, T2, T3, U extends any[], R>(n: 3, origFn: (arg1: T1, arg2: T2, arg3: T3) => R): (arg1: T1, arg2: T2, arg3: T3) => R;
export declare function nary<T1, T2, T3, T4, U extends any[], R>(n: 4, origFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => R): (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => R;
export declare function nary<T1, T2, T3, T4, T5, U extends any[], R>(n: 5, origFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => R): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => R;
export declare function nary<T1, T2, T3, T4, T5, T6, U extends any[], R>(n: 6, origFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => R): (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => R;

125

dist/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.add = (a, b) => a + b;
exports.subtract = (a, b) => a - b;
exports.multiply = (a, b) => a * b;
exports.divide = (a, b) => a / b;
/**
* Always returns the same value supplied to it.
*/
exports.identity = (value) => value;
/**
* Returns a function that always returns the same value supplied to it.
*/
exports.always = (value) => () => value;
/**
* Optimize a function to speed up consecutive calls by caching the result of

@@ -34,9 +46,2 @@ * calls with identical input arguments. The cache can be overrriden to

/**
* Always returns the same value that was used as the argument.
*/
function identity(value) {
return value;
}
exports.identity = identity;
/**
* Return a function that fetches `key` from its operand.

@@ -59,41 +64,99 @@ */

*/
function throttle(fn, ms, leading = true) {
let pending = false;
function throttle(fn, ms, { leading = true, trailing = true, debounce = false } = {}) {
let pending;
let timeout = undefined;
// Clear timeout.
function clear() {
pending = false;
clearTimeout(timeout);
timeout = undefined;
pending = undefined;
}
// Wait for the next interval.
function wait() {
timeout = setTimeout(_next, ms);
}
// Invoke the function in "pending" state.
function flush() {
if (pending)
return _next();
clearTimeout(timeout);
return next();
}
// Clear timeout or flush next function call.
function _next() {
// When no pending, remove `timeout`.
if (!pending) {
timeout = undefined;
// Execute `fn` and increment timeout every loop.
function next() {
timeout = undefined;
if (!pending)
return;
}
clear(); // Clear existing timeout.
fn(); // Execute pending function.
wait(); // Start new interval.
const args = pending;
pending = undefined;
if (trailing)
fn(...args);
timeout = setTimeout(next, ms);
}
return Object.assign(() => {
pending = true;
// Throttled `fn` wrapper.
function throttled(...args) {
pending = args;
if (timeout === undefined) {
if (leading === true)
return _next();
return wait();
if (leading) {
pending = undefined;
fn(...args);
}
timeout = setTimeout(next, ms);
return;
}
}, { flush, clear });
if (debounce) {
clearTimeout(timeout);
timeout = setTimeout(next, ms);
return;
}
}
return Object.assign(throttled, { flush, clear });
}
exports.throttle = throttle;
/**
* Given a `fn`, return a wrapper that accepts an array of `fn` arguments.
*/
function spread(fn) {
return (args) => fn(...args);
}
exports.spread = spread;
/**
* Flip a binary `fn` argument order.
*/
function flip(fn) {
return (arg2, arg1) => fn(arg1, arg2);
}
exports.flip = flip;
function partial(fn, ...args1) {
return (...args2) => fn(...args1, ...args2);
}
exports.partial = partial;
const SEQUENCE_FNS = Object.create(null);
function sequence(...fns) {
const n = fns.length;
let fn = SEQUENCE_FNS[n];
if (!fn) {
const params = fns.map((_, i) => `_${i}`);
const seq = params.reduce((x, p) => `${p}(${x})`, "x");
fn = SEQUENCE_FNS[n] = new Function(...params, `return function sequence${n}(x) { return ${seq}; }`);
}
return fn(...fns);
}
exports.sequence = sequence;
const COMPOSE_FNS = Object.create(null);
function compose(...fns) {
const n = fns.length;
let fn = COMPOSE_FNS[n];
if (!fn) {
const params = fns.map((_, i) => `_${i}`);
const seq = params.reduceRight((x, p) => `${p}(${x})`, "x");
fn = COMPOSE_FNS[n] = new Function(...params, `return function compose${n}(x) { return ${seq}; }`);
}
return fn(...fns);
}
exports.compose = compose;
const NARY_FNS = Object.create(null);
function nary(n, origFn) {
let fn = NARY_FNS[n];
if (!fn) {
const args = Array.from({ length: n }, (_, i) => `_${i}`).join(", ");
fn = NARY_FNS[n] = new Function("origFn", `return function nary${n}(${args}) { return origFn(${args}); }`);
}
return fn(origFn);
}
exports.nary = nary;
//# sourceMappingURL=index.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const functools = require("./index");
describe('functools', () => {
describe('identity', () => {
it('should return the input', () => {
describe("functools", () => {
describe("identity", () => {
it("should return the input", () => {
expect(functools.identity(42)).toEqual(42);
});
});
describe('memoize', () => {
it('should cache return values by input argument', () => {
describe("always", () => {
it("should return a function that returns the input", () => {
const fn = functools.always(42);
expect(fn()).toEqual(42);
});
});
describe("memoize", () => {
it("should cache return values by input argument", () => {
let i = 0;
const fn = functools.memoize(() => ++i);
expect(fn('foo')).toEqual(1);
expect(fn('foo')).toEqual(1);
expect(fn('bar')).toEqual(2);
expect(fn('bar')).toEqual(2);
expect(fn("foo")).toEqual(1);
expect(fn("foo")).toEqual(1);
expect(fn("bar")).toEqual(2);
expect(fn("bar")).toEqual(2);
});
});
describe('memoize0', () => {
it('should memoize a zero-length function', () => {
describe("memoize0", () => {
it("should memoize a zero-length function", () => {
let i = 0;

@@ -28,13 +34,13 @@ const fn = functools.memoize0(() => ++i);

});
describe('prop', () => {
const getter = functools.prop('foo');
describe("prop", () => {
const getter = functools.prop("foo");
expect(getter({ foo: 123 })).toEqual(123);
expect(getter({})).toEqual(undefined);
});
describe('invoke', () => {
expect(functools.invoke('foo')({ foo: () => 123 })).toEqual(123);
expect(functools.invoke('add', 3, 7)({ add: (a, b) => a + b })).toEqual(10);
describe("invoke", () => {
expect(functools.invoke("foo")({ foo: () => 123 })).toEqual(123);
expect(functools.invoke("add", 3, 7)({ add: (a, b) => a + b })).toEqual(10);
});
describe('throttle', () => {
it('should throttle function calls', (done) => {
describe("throttle", () => {
it("should throttle function calls", done => {
let i = 0;

@@ -47,20 +53,21 @@ const fn = functools.throttle(() => ++i, 100);

expect(i).toEqual(1);
setTimeout(() => {
fn(); // Works after timeout.
expect(i).toEqual(2);
return done();
}, 100);
}, 10);
setTimeout(() => {
fn(); // Works after timeout.
expect(i).toEqual(2);
return done();
}, 100);
});
it('should throttle function calls without leading call', (done) => {
it("should throttle function calls without leading call", done => {
let i = 0;
const fn = functools.throttle(() => ++i, 100, false);
const fn = functools.throttle(() => ++i, 100, { leading: false });
fn(); // Leading invoke disabled.
expect(i).toEqual(0);
setTimeout(() => fn(), 50); // Noop.
setTimeout(() => {
expect(i).toEqual(1);
return done();
}, 200);
}, 110);
});
it('should flush the function call', (done) => {
it("should flush the function call", done => {
let i = 0;

@@ -77,4 +84,4 @@ const fn = functools.throttle(() => ++i, 100);

expect(i).toEqual(2);
fn(); // Enqueue `fn` after last flush (no leading since has run).
expect(i).toEqual(2);
fn(); // Enqueue `fn` after last flush.
expect(i).toEqual(3);
setTimeout(() => {

@@ -85,4 +92,67 @@ expect(i).toEqual(3);

});
it("should skip trailing calls", done => {
let i = 0;
const fn = functools.throttle(() => ++i, 100, {
trailing: false
});
fn();
expect(i).toEqual(1);
// Tracks `pending` for first "event loop".
setTimeout(() => fn(), 20);
setTimeout(() => fn(), 40);
setTimeout(() => fn(), 60);
setTimeout(() => fn(), 80);
// Nothing happened between loops with `lagging` set.
setTimeout(() => expect(i).toEqual(1), 150);
setTimeout(() => {
expect(i).toEqual(1); // Executed the second timeout.
return done();
}, 210);
});
it("should debounce function execution", done => {
let i = 0;
const fn = functools.throttle(() => ++i, 100, {
leading: false,
debounce: true
});
fn();
expect(i).toEqual(0);
// Tracks `pending` for first "event loop".
setTimeout(() => fn(), 20);
setTimeout(() => fn(), 40);
setTimeout(() => fn(), 60);
setTimeout(() => fn(), 80);
// Nothing happened between loops with `debounce` set.
setTimeout(() => expect(i).toEqual(0), 130);
setTimeout(() => {
expect(i).toEqual(1); // Executed after debounce.
return done();
}, 190);
});
});
describe("spread", () => {
it("should spread function arguments", () => {
const fn = functools.spread(functools.add);
expect(fn([1, 2])).toEqual(3);
});
});
describe("compose", () => {
it("should compose a list of functions", () => {
const fn = functools.compose(functools.partial(functools.multiply, 5), functools.partial(functools.flip(functools.subtract), 3));
expect(fn(10)).toEqual(35);
});
});
describe("sequence", () => {
it("should sequence a list of functions", () => {
const fn = functools.sequence(functools.partial(functools.flip(functools.divide), 5), functools.partial(functools.add, 3));
expect(fn(10)).toEqual(5);
});
});
describe("nary", () => {
it("should restrict function arity", () => {
const fn = functools.nary(1, parseInt);
expect(["1", "2", "3"].map(fn)).toEqual([1, 2, 3]);
});
});
});
//# sourceMappingURL=index.spec.js.map
{
"name": "functools",
"version": "3.2.1",
"version": "3.3.0",
"description": "Utilities for working with functions in JavaScript, with TypeScript",

@@ -11,2 +11,4 @@ "main": "dist/index.js",

"scripts": {
"prettier": "prettier --write",
"format": "npm run prettier -- \"{.,src/**}/*.{js,ts,json,md,yml,css}\"",
"lint": "tslint \"src/**/*.ts\" --project tsconfig.json",

@@ -16,3 +18,3 @@ "build": "rm -rf dist/ && tsc",

"test": "npm run lint && npm run build && npm run specs",
"prepublish": "npm run build"
"prepare": "npm run build"
},

@@ -56,9 +58,27 @@ "repository": {

},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,ts,json,md,yml,css}": [
"npm run prettier",
"git add"
]
},
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@types/jest": "^23.3.1",
"@types/node": "^10.1.2",
"husky": "^1.3.1",
"jest": "^23.5.0",
"lint-staged": "^8.1.0",
"prettier": "^1.16.1",
"rimraf": "^2.6.2",
"ts-jest": "^23.1.4",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.17.0",
"tslint-config-standard": "^8.0.0",

@@ -65,0 +85,0 @@ "typescript": "^3.0.3"

@@ -22,8 +22,16 @@ # Functools

Always returns the same value that was used as the argument.
Always returns the same value supplied to it.
```js
identity(42) //=> 42
identity(42); //=> 42
```
### `always<T>(arg: T) => () => T`
Returns a function that always returns the same value supplied to it.
```js
identity(42); //=> 42
```
### `memoize<T, U>(fn: (x: T) => U, cache?: Cache) => (x: T) => U`

@@ -34,13 +42,13 @@

```js
let i = 0
const fn = memoize(() => ++i)
let i = 0;
const fn = memoize(() => ++i);
fn('foo') //=> 1
fn('foo') //=> 1
fn("foo"); //=> 1
fn("foo"); //=> 1
fn('bar') //=> 2
fn('bar') //=> 2
fn("bar"); //=> 2
fn("bar"); //=> 2
```
See also: `memoize0` for zero-length function arguments.
**See also:** `memoize0` for zero-length function arguments.

@@ -52,3 +60,3 @@ ### `prop<K>(key: K) => (obj: T) => T[K]`

```js
prop('foo')({ foo: 123 }) //=> 123
prop("foo")({ foo: 123 }); //=> 123
```

@@ -61,6 +69,6 @@

```js
invoke('add', 5, 5)({ add: (a, b) => a + b }) //=> 10
invoke("add", 5, 5)({ add: (a, b) => a + b }); //=> 10
```
### `throttle(fn: () => void, ms: number, leading = true) => () => void`
### `throttle<T>(fn: (...args: T) => void, ms: number, { leading, trailing, debounce }) => (...args: T) => void`

@@ -85,2 +93,53 @@ Wrap a function to rate-limit the function executions to once every `ms` milliseconds.

### `spread<T, R>(fn: (...args: T) => R) => (args: T) => R`
Given a `fn`, return a wrapper that accepts an array of `fn` arguments.
```js
Promise.all([1, 2, 3]).then(spread(add));
```
### `flip<T1, T2, R>(fn: (arg1: T1, arg2: T2) => R) => (arg2: T2, arg1: T1) => R`
Flip a binary `fn` argument order.
```js
flip(subtract)(5, 10); //=> 5
```
### `partial<T, U, R>(fn: (...args1: T, ...args2: U) => R) => (...args: U) => R`
Returns a partially applied `fn` with the supplied arguments.
```js
partial(subtract, 10)(5); //=> 5
```
### `sequence<T>(...fns: Array<(input: T) => T>) => (input: T) => T`
Left-to-right function composition.
```js
sequence(partial(add, 10), partial(multiply, 5))(5); //=> 75
```
### `compose<T>(...fns: Array<(input: T) => T>) => (input: T) => T`
Right-to-left function composition.
```js
compose(
partial(add, 10),
partial(multiply, 5)
)(5); //=> 35
```
### `nary<T, R>(n: number, fn: (...args: T) => R) => (...args: T) => R`
Fix the number of receivable arguments in `origFn` to `n`.
```js
["1", "2", "3"].map(nary(1, fn)); //=> [1, 2, 3]
```
## TypeScript

@@ -87,0 +146,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc