angus-c

Just

A library of dependency-free JavaScript functions that do just do one thing.
Under MIT License
By angus-c

javascript library pwa utils tiny dependency-free

Just


A library of zero-dependency npm modules that do just one thing.
A guilt-free alternative to those bulkier utility libraries. Ideal for PWA development or whenever bytes are precious.


Jump To API


We welcome contributions. Please follow our contribution guidelines.


Try :icecream:

A REPL for every utility (powered by RunKit)



Read :books:

TypeScript

We're in the process of adding TypeScript definitions and tests to every Just utility. You're welcome to help us get there!
Here's an example PR.


You can verify new TypeScript definitions by running yarn test-types (This also gets run as part of the yarn test script)


Browser Support :computer:

Data based on available saucelabs test browsers. It's likely Just is also fully supported by some older versions not verifiable via saucelabs.


| Chrome | Safari | Firefox | Edge | Node | Mobile Safari | Android |
| ------ | ------ | ------- | ---- | ---- | ------------- | ------------- |
| yes | yes | yes | 12 | 6+ | iOS 8+ | Android OS 5+ |


The Modules :package:

### Collections


### just-diff


:icecream:Try It


npm install just-diff


Return an object representing the difference between two other objects
Pass converter to format as http://jsonpatch.com


```js
import {diff} from 'just-diff';


const obj1 = {a: 4, b: 5};
const obj2 = {a: 3, b: 5};
const obj3 = {a: 4, c: 5};


diff(obj1, obj2);
[
{ "op": "replace", "path": ['a'], "value": 3 }
]


diff(obj2, obj3);
[
{ "op": "remove", "path": ['b'] },
{ "op": "replace", "path": ['a'], "value": 4 }
{ "op": "add", "path": ['c'], "value": 5 }
]


// arrays
const obj4 = {a: 4, b: [1, 2, 3]};
const obj5 = {a: 3, b: [1, 2, 4]};
const obj6 = {a: 3, b: [1, 2, 4, 5]};


diff(obj4, obj5);
[
{ "op": "replace", "path": ['a'], "value": 3 }
{ "op": "replace", "path": ['b', 2], "value": 4 }
]


diff(obj5, obj6);
[
{ "op": "add", "path": ['b', 3], "value": 5 }
]


// nested paths
const obj7 = {a: 4, b: {c: 3}};
const obj8 = {a: 4, b: {c: 4}};
const obj9 = {a: 5, b: {d: 4}};


diff(obj7, obj8);
[
{ "op": "replace", "path": ['b', 'c'], "value": 4 }
]


diff(obj8, obj9);
[
{ "op": "replace", "path": ['a'], "value": 5 }
{ "op": "remove", "path": ['b', 'c']}
{ "op": "add", "path": ['b', 'd'], "value": 4 }
]


// using converter to generate jsPatch standard paths
import {diff, jsonPatchPathConverter} from 'just-diff'


diff(obj1, obj2, jsonPatchPathConverter);
[
{ "op": "replace", "path": '/a', "value": 3 }
]


diff(obj2, obj3, jsonPatchPathConverter);
[
{ "op": "remove", "path": '/b' },
{ "op": "replace", "path": '/a', "value": 4 }
{ "op": "add", "path": '/c', "value": 5 }
]
```


just-diff-apply

:icecream:Try It


npm install just-diff-apply


Apply a diff object to an object.
Pass converter to apply a http://jsonpatch.com standard patch


```js
import diffApply from 'just-diff-apply';


const obj1 = {a: 3, b: 5};
diffApply(obj1,
[
{ "op": "remove", "path": ['b'] },
{ "op": "replace", "path": ['a'], "value": 4 },
{ "op": "add", "path": ['c'], "value": 5 }
]
);
obj1; // {a: 4, c: 5}


// arrays (array key can be string or numeric)
const obj3 = {a: 4, b: [1, 2, 3]};
diffApply(obj3, [
{ "op": "replace", "path": ['a'], "value": 3 }
{ "op": "replace", "path": ['b', 2], "value": 4 }
{ "op": "add", "path": ['b', 3], "value": 9 }
]);
obj3; // {a: 3, b: [1, 2, 4, 9]}


// nested paths
const obj4 = {a: 4, b: {c: 3}};
diffApply(obj4, [
{ "op": "replace", "path": ['a'], "value": 5 }
{ "op": "remove", "path": ['b', 'c']}
{ "op": "add", "path": ['b', 'd'], "value": 4 }
]);
obj4; // {a: 5, b: {d: 4}}


// using converter to apply jsPatch standard paths
// see http://jsonpatch.com
import {diffApply, jsonPatchPathConverter} from 'just-diff-apply'


const obj2 = {a: 3, b: 5};
diffApply(obj2, [
{ "op": "remove", "path": '/b' },
{ "op": "replace", "path": '/a', "value": 4 }
{ "op": "add", "path": '/c', "value": 5 }
], jsonPatchPathConverter);
obj2; // {a: 4, c: 5}
```


just-compare

:icecream:Try It


npm install just-compare


```js
import compare from "just-compare";


// primitives: value1 === value2
// functions: value1.toString == value2.toString
// arrays: if length, sequence and values of properties are identical
// objects: if length, names and values of properties are identical
compare([1, [2, 3]], [1, [2, 3]]); // true
compare([1, [2, 3], 4], [1, [2, 3]]); // false
compare({ a: 2, b: 3 }, { a: 2, b: 3 }); // true
compare({ a: 2, b: 3 }, { b: 3, a: 2 }); // true
compare({ a: 2, b: 3, c: 4 }, { a: 2, b: 3 }); // false
compare({ a: 2, b: 3 }, { a: 2, b: 3, c: 4 }); // false
compare([1, [2, { a: 4 }], 4], [1, [2, { a: 4 }]]); // false
compare([1, [2, { a: 4 }], 4], [1, [2, { a: 4 }], 4]); // true
compare(NaN, NaN); // true
```


just-clone

:icecream:Try It


npm install just-clone


```js
import clone from "just-clone";


// Deep copies objects and arrays, doesn't clone functions


var arr = [1, 2, 3];
var subObj = { aa: 1 };
var obj = { a: 3, b: 5, c: arr, d: subObj };
var objClone = clone(obj);
arr.push(4);
objClone.d.bb = 2;
obj; // {a: 3, b: 5, c: [1, 2, 3, 4], d: {aa: 1}}
objClone; // {a: 3, b: 5, c: [1, 2, 3], d: {aa: 1, bb: 2}}
```


just-pluck-it

:icecream:Try It


npm install just-pluck-it


```js
import pluck from "just-pluck-it";


pluck(
[
{ a: 1, b: 2 },
{ a: 4, b: 3 },
{ a: 2, b: 5 },
],
"a"
); // [1, 4, 2]
pluck({ x: { a: 1, b: 2 }, y: { a: 4, b: 3 }, z: { a: 2, b: 5 } }, "a"); // {x: 1, y: 4, z: 2}
```


just-flush

:icecream:Try It


npm install just-flush


```js
import flush from "just-flush";


flush([1, undefined, 2, null, 3, NaN, 0]); // [1, 2, 3, NaN, 0]
flush([true, null, false, true, [null], undefined]); // [true, false, true, [null]]
flush({ a: 2, b: null, c: 4, d: undefined }); // {a: 2, c: 4}
flush("something"); // undefined
flush(); // undefined
```


Objects
just-extend

:icecream:Try It


npm install just-extend


```js
import extend from 'just-extend';


var obj = {a: 3, b: 5};
extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8}
obj; // {a: 4, b: 5, c: 8}


var obj = {a: 3, b: 5};
extend({}, obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8}
obj; // {a: 3, b: 5}


var arr = [1, 2, 3];
var obj = {a: 3, b: 5};
extend(obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]}
arr.push(4);
obj; // {a: 3, b: 5, c: [1, 2, 3, 4]}


var arr = [1, 2, 3];
var obj = {a: 3, b: 5};
extend(true, obj, {c: arr}); // {a: 3, b: 5, c: [1, 2, 3]}
arr.push(4);
obj; // {a: 3, b: 5, c: [1, 2, 3]}


extend({a: 4, b: 5}); // {a: 4, b: 5}
extend({a: 4, b: 5}, 3); {a: 4, b: 5}
extend({a: 4, b: 5}, true); {a: 4, b: 5}
extend('hello', {a: 4, b: 5}); // throws
extend(3, {a: 4, b: 5}); // throws
```


just-merge

:icecream:Try It


npm install just-merge


```js
import merge from "just-merge";


let obj = { a: 3, b: 5 };
merge(obj, { a: 4, c: 8 }); // {a: 4, b: 5, c: 8}
obj; // {a: 4, b: 5, c: 8}


let obj = { a: 3, b: 5 };
merge({}, obj, { a: 4, c: 8 }); // {a: 4, b: 5, c: 8}
obj; // {a: 3, b: 5}


let arr = [1, 2, 3];
let obj = { a: 3, b: 5 };
merge(obj, { c: arr }); // {a: 3, b: 5, c: [1, 2, 3]}
arr.push[4];
obj; // {a: 3, b: 5, c: [1, 2, 3, 4]}


merge({ a: 4, b: 5 }); // {a: 4, b: 5}
merge(3, { a: 4, b: 5 }); // throws
merge({ a: 4, b: 5 }, 3); // throws
merge({ a: 4, b: 5 }, { b: 4, c: 5 }, "c"); // throws
```


just-values

:icecream:Try It


npm install just-values


```js
import values from "just-values";


values({ a: 4, c: 8 }); // [4, 8]
values({ a: { aa: 2 }, b: { bb: 4 } }); // [{aa: 2}, {bb: 4}]
values({}); // []
values([1, 2, 3]); // [1, 2, 3]
values(function (a, b) {
return a + b;
}); // []
values(String("hello")); // []
values(1); // throw exception
values(true); // throw exception
values(undefined); // throw exception
values(null); // throw exception
```


just-entries

:icecream:Try It


npm install just-entries


```js
import entries from "just-entries";


// Object:
entries({ c: 8, a: 4 }); // [['c', 8], ['a', 4]]
entries({ b: { bb: 4 }, a: { aa: 2 } }); // [['b', {bb: 4}], ['a', {aa: 2}]]
entries({}); // []


// Array:
entries([{ c: 8 }, { a: 4 }]); // [[0, {c: 8}], [1, {a: 4}]]
entries(["À", "mauvais", "ouvrier", "point", "de", "bon", "outil"]);
// [[0, 'À'], [1, 'mauvais'] ... [6, 'outil']]
entries([]); // []
```


just-pick

:icecream:Try It


npm install just-pick


```js
import pick from "just-pick";


var obj = { a: 3, b: 5, c: 9 };
pick(obj, ["a", "c"]); // {a: 3, c: 9}
pick(obj, "a", "c"); // {a: 3, c: 9}
pick(obj, ["a", "b", "d"]); // {a: 3, b: 5}
pick(obj, ["a", "a"]); // {a: 3}
```


just-omit

:icecream:Try It


npm install just-omit


```js
import omit from "just-omit";


var obj = { a: 3, b: 5, c: 9 };
omit(obj, ["a", "c"]); // {b: 5}
omit(obj, "a", "c"); // {b: 5}
omit(obj, ["a", "b", "d"]); // {c: 9}
omit(obj, ["a", "a"]); // {b: 5, c: 9}
```


just-is-empty

:icecream:Try It


npm install just-is-empty


js
import isEmpty from 'just-is-empty';
isEmpty({a: 3, b: 5}) // false
isEmpty([1, 2]) // false
isEmpty(new Set([1, 2, 2])) // false
isEmpty((new Map()).set('a', 2)) // false
isEmpty({}) // true
isEmpty([]) // true
isEmpty(new Set()) // true
isEmpty(new Map()) // true
isEmpty('abc') // false
isEmpty('') // true
isEmpty(0) // true
isEmpty(1) // true
isEmpty(true) // true
isEmpty(Symbol('abc')); // true
isEmpty(//); // true
isEmpty(new String('abc')); // false
isEmpty(new String('')); // true
isEmpty(new Boolean(true)); // true
isEmpty(null) // true
isEmpty(undefined) // true


just-is-circular

:icecream:Try It


npm install just-is-circular


```js
import isCircular from "just-is-circular";


const a = {};
a.b = a;
isCircular(a); // true


const a = {};
a.b = { c: a };
isCircular(a); // true


const a = {};
a.b = { c: 4 };
isCircular(a); // false


const a = [];
a.push(a);
isCircular(a); // true


isCircular({}); // false
isCircular("hi"); // false
isCircular(undefined); // false
```


just-is-primitive

:icecream:Try It


npm install just-is-primitive


js
import isPrimitive from "just-is-primitive";
isPrimitive("hi"); // true
isPrimitive(3); // true
isPrimitive(true); // true
isPrimitive(false); // true
isPrimitive(null); // true
isPrimitive(undefined); // true
isPrimitive(Symbol()); // true
isPrimitive({}); // false
isPrimitive([]); // false
isPrimitive(function () {}); // false
isPrimitive(new Date()); // false
isPrimitive(/a/); // false


just-filter-object

:icecream:Try It


npm install just-filter-object


```js
import filter from "just-filter-object";


// returns a new object containing those original properties for which the predicate returns truthy
filter({ a: 3, b: 5, c: 9 }, (key, value) => value < 6); // {a: 3, b: 5}
filter({ a1: 3, b1: 5, a2: 9 }, (key, value) => key[0] == "a"); // {a1: 3, a2: 9}
filter({ a: 3, b: 5, c: null }, (key, value) => value); // {a: 3, b: 5}
```


just-map-object

:icecream:Try It


npm install just-map-object


```js
import map from "just-map-object";


// DEPRECATED: use just-map-values
map({ a: 3, b: 5, c: 9 }, (key, value) => value + 1); // {a: 4, b: 6, c: 10}
map({ a: 3, b: 5, c: 9 }, (key, value) => key); // {a: 'a', b: 'b', c: 'c'}
map({ a: 3, b: 5, c: 9 }, (key, value) => key + value); // {a: 'a3', b: 'b5', c: 'c9'}
```


just-map-values

:icecream:Try It


npm install just-map-values


```js
import map from "just-map-values";


// predicate updates values, receives (value, key, obj)
map({ a: 3, b: 5, c: 9 }, (value) => value + 1); // {a: 4, b: 6, c: 10}
map({ a: 3, b: 5, c: 9 }, (value, key) => value + key); // {a: 3a, b: 5b, c: 9c}
map({ a: 3, b: 5, c: 9 }, (value, key, obj) => obj.b); // {a: 5, b: 5, c: 5}
```


just-map-keys

:icecream:Try It


npm install just-map-keys


```js
import map from "just-map-keys";


// predicate updates keys, receives (value, key, object)
map({ a: "cow", b: "sheep", c: "pig" }, (value) => value);
// {cow: 'cow', sheep: 'sheep', pig: 'pig'}
map([4, 5, 6], (value, key) => key + 1); // {1: 4, 2: 5, 3: 6}
map({ a: 3, b: 5, c: 9 }, (value, key) => key + value); // {a3: 3, b5: 5, c9: 9}
map({ a: 3, b: 5, c: 9 }, (value, key, obj) => obj.b + value + key);
// {'8a': 3, '10b': 5, '14c': 9}
```


just-reduce-object

:icecream:Try It


npm install just-reduce-object


```js
import reduce from "just-reduce-object";


// applies a function against an accumulator and each key-value pairs of the object
// to reduce it to a single value
reduce(
{ a: 3, b: 5, c: 9 },
(acc, key, value, index, keys) => {
acc[value] = key;
return acc;
},
{}
); // {3: 'a', 5: 'b', 9: 'c'}


reduce({ a: 3, b: 5, c: 9 }, (acc, key, value, index, keys) => {
acc += value;
return acc;
}); // 17
```


just-safe-get

:icecream:Try It


npm install just-safe-get


```js
import get from "just-safe-get";


const obj = { a: { aa: { aaa: 2 } }, b: 4 };


get(obj, "a.aa.aaa"); // 2
get(obj, ["a", "aa", "aaa"]); // 2


get(obj, "b.bb.bbb"); // undefined
get(obj, ["b", "bb", "bbb"]); // undefined


get(obj.a, "aa.aaa"); // 2
get(obj.a, ["aa", "aaa"]); // 2


get(obj.b, "bb.bbb"); // undefined
get(obj.b, ["bb", "bbb"]); // undefined


get(obj.b, "bb.bbb", 5); // 5
get(obj.b, ["bb", "bbb"], true); // true


get(null, "a"); // undefined
get(undefined, ["a"]); // undefined


get(null, "a", 42); // 42
get(undefined, ["a"], 42); // 42


const obj = { a: {} };
const sym = Symbol();
obj.a[sym] = 4;
get(obj.a, sym); // 4
```


just-safe-set

:icecream:Try It


npm install just-safe-set


```js
import set from "just-safe-set";


const obj1 = {};
set(obj1, "a.aa.aaa", 4); // true
obj1; // {a: {aa: {aaa: 4}}}


const obj2 = {};
set(obj2, [a, aa, aaa], 4); // true
obj2; // {a: {aa: {aaa: 4}}}


const obj3 = { a: { aa: { aaa: 2 } } };
set(obj3, "a.aa.aaa", 3); // true
obj3; // {a: {aa: {aaa: 3}}}


// don't clobber existing
const obj4 = { a: { aa: { aaa: 2 } } };
set(obj4, "a.aa", { bbb: 7 }); // false


const obj5 = { a: {} };
const sym = Symbol();
set(obj5.a, sym, 7); // true
obj5; // {a: {Symbol(): 7}}
```


just-typeof

:icecream:Try It


npm install just-typeof


```js
import typeOf from "just-typeof";


typeOf({}); // 'object'
typeOf([]); // 'array'
typeOf(function () {}); // 'function'
typeOf(/a/); // 'regexp'
typeOf(new Date()); // 'date'
typeOf(null); // 'null'
typeOf(undefined); // 'undefined'
typeOf("a"); // 'string'
typeOf(1); // 'number'
typeOf(true); // 'boolean'
```


just-flip-object

:icecream:Try It


npm install just-flip-object


```js
import flip from "just-flip-object";


// flip the key and value
flip({ a: "x", b: "y", c: "z" }); // {x: 'a', y: 'b', z: 'c'}
flip({ a: 1, b: 2, c: 3 }); // {'1': 'a', '2': 'b', '3': 'c'}
flip({ a: false, b: true }); // {false: 'a', true: 'b'}
```


just-has

:icecream:Try It


npm install just-has


```js
import has from "just-has";


const obj = { a: { aa: { aaa: 2 } }, b: 4 };


has(obj, "a.aa.aaa"); // true
has(obj, ["a", "aa", "aaa"]); // true


has(obj, "b.bb.bbb"); // false
has(obj, ["b", "bb", "bbb"]); // false


has(obj.a, "aa.aaa"); // true
has(obj.a, ["aa", "aaa"]); // true


has(obj.b, "bb.bbb"); // false
has(obj.b, ["bb", "bbb"]); // false


has(null, "a"); // false
has(undefined, ["a"]); // false


const obj = { a: {} };
const sym = Symbol();
obj.a[sym] = 4;
has(obj.a, sym); // true
```


Arrays
just-cartesian-product

:icecream:Try It


npm install just-cartesian-product


```js
import cartesianProduct from "just-cartesian-product";


cartesianProduct([
[1, 2],
["a", "b"],
]); // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]
cartesianProduct([
[1, 2],
["a", "b", "c"],
]); // [[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c']]
cartesianProduct([]); // []
cartesianProduct(); // throws
```


just-unique

:icecream:Try It


npm install just-unique


```js
import unique from "just-unique";


unique([1, 2, 3, 2, 3, 4, 3, 2, 1, 3]); // [1, 2, 3, 4]


var a = { a: 3 };
var b = { b: 4 };
var c = { c: 5 };
unique([a, a, b, c, b]); // [a, b, c]


unique([1, "1", 2, "2", 3, 2]); // [1, '1', 2, '2', 3]


// declaring sorted array for performance
unique([1, 1, "1", 2, 2, 5, "5", "5"], true); // [1, '1', 2, 5, '6']


// declaring strings array for performance
unique(["a", "c", "b", "c", "a"], false, true); // ['a', 'b', 'c']
```


just-flatten-it

:icecream:Try It


npm install just-flatten-it


```js
import flatten from "just-flatten-it";


flatten([[1, [2, 3]], [[4, 5], 6, 7, [8, 9]]]);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]


flatten([[1, [2, 3]], [[4, 5], 6, 7, [8, 9]]], 1);
// [1, [2, 3], [[4, 5], 6, 7, [8, 9]]]
```


just-index

:icecream:Try It


npm install just-index


```js
import index from "just-index";


index(
[
{ id: "first", val: 1 },
{ id: "second", val: 2 },
],
"id"
);
// {first: {id: 'first', val: 1}, second: {id: 'second', val: 2}}
index([{ id: "first", val: 1 }, null], "id"); // {first: {id: 'first', val: 1}}
index([], "id"); // {}
index([], null); // throws
index({}, "id"); // throws
```


just-insert

:icecream:Try It


npm install just-insert


```js
import insert from "just-insert";


insert([1, 2, 5, 6], ["a", "c", "e"], 2); // [1, 2, 'a', 'c', 'e', 5, 6]
insert([1, 2, 5, 6], "a", 2); // [1, 2, 'a', 5, 6]
insert([1, 2, 5, 6], ["a", "c", "e"], 0); // ['a', 'c', 'e', 1, 2, 5, 6]
insert([1, 2, 5, 6], ["a", "c", "e"]); // ['a', 'c', 'e', 1, 2, 5, 6]
```


just-intersect

:icecream:Try It


npm install just-intersect


```js
import intersect from "just-intersect";


intersect([1, 2, 5, 6], [2, 3, 5, 6]); // [2, 5, 6]
intersect([1, 2, 2, 4, 5], [3, 2, 2, 5, 7]); // [2, 5]
```


just-compact

:icecream:Try It


npm install just-compact


```js
import compact from "just-compact";


compact([1, null, 2, undefined, null, NaN, 3, 4, false, 5]); // [1, 2, 3, 4, 5]
compact([1, 2, [], 4, {}]); // [1, 2, [], 4, {}]
compact([]); // []
compact({}); // throws
```


just-last

:icecream:Try It


npm install just-last


```js
import last from "just-last";


last([1, 2, 3, 4, 5]); // 5
last([{ a: 1 }, { b: 1 }, { c: 1 }]); // {c: 1}
last([true, false, [true, false]]); // [true, false]
last([]); // undefined
last(); // throws
last(null); // throws
last(undefined); // throws
```


just-tail

:icecream:Try It


npm install just-tail


```js
import tail from "just-tail";


tail([1, 2, 3, 4, 5]); // [2, 3, 4, 5]
tail([{ a: 1 }, { b: 1 }, { c: 1 }]); // [{b: 1}, {c: 1}]
tail([true, false, [true, false]]); // [false, [true, false]]
tail([]); // []
tail(); // throws
tail(null); // throws
tail(undefined); // throws
```


just-random

:icecream:Try It


npm install just-random


```js
import random from "just-random";


random([1, 2, 3]); // one of [1, 2, 3], at random
```


just-shuffle

:icecream:Try It


npm install just-shuffle


```js
import shuffle from "just-shuffle";


shuffle([1, 2, 3]);
// array with original elements randomly sorted
shuffle([1, 2, 3], { shuffleAll: true });
// array with original elements randomly sorted and all in new postions
shuffle([]); // []
shuffle([1]); // [1]
shuffle(); // undefined
shuffle(undefined); // undefined
shuffle(null); // undefined
shuffle({}); // undefined
```


just-split

:icecream:Try It


npm install just-split


```js
import split from "just-split";


split([]); // []
split([1, 2, 3, 4, 5]); // [[1, 2, 3, 4, 5]]
split([1, 2, 3, 4, 5, 6, 7, 8, 9], 3); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
split(["a", "b", "c", "d", "e"], 2); // [['a', 'b'], ['c', 'd'], ['e']];
split([1, 2, 3, 4, 5, 6, 7, 8], 3); // [[1, 2, 3], [4, 5, 6], [7, 8]];
split({}, 3); // throws
split(null, 3); // throws
split([1, 2, 3, 4, 5, 6], "3"); // throws
```


just-split-at

:icecream:Try It


npm install just-split-at


```js
import splitAt from "just-split-at";


splitAt([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4, 5]]
splitAt([{ a: 1 }, { b: 1 }, { c: 1 }], -1); // [[{a: 1}, {b: 1}], [{c: 1}]]
splitAt([], 2); // [[], []]
splitAt(null, 1); // throws
splitAt(undefined, 1); // throws
splitAt([1, 2, 3, 4, 5], {}); // throws
```


just-sort-by

:icecream:Try It


npm install just-sort-by


```js
import sortBy from 'just-array-sort-by';


sortBy([10, 1, 5, 20, 15, 35, 30, 6, 8]); // [1, 5, 6, 8, 10, 15, 20, 30, 35]


sortBy([
{user: 'fabio', details: {city: "Milan", age: 34}},
{user: 'max', details: {city: "Munich", age: 29}},
{user: 'zacarias', details: {city: "Sao Paulo", age: 44}},
{user: 'robert', details: {city: "Manchester", age: 28}},
{user: 'klaus', details: {city: "Zurich", age: 38}},
], function(o) {
return o.details.age;
});
/
[
{user: 'robert', age: 28},
{user: 'max', age: 29},
{user: 'fabio', age: 34},
{user: 'klaus', age: 38},
{user: 'zacarias', age: 44},
]
/


sortBy([
{user: 'fabio', age: 34},
{user: 'max', age: 29},
{user: 'zacarias', age: 44},
{user: 'robert', age: 28},
{user: 'klaus', age: 38},
], 'user');
/
[
{user: 'fabio', age: 34},
{user: 'klaus', age: 38},
{user: 'max', age: 29},
{user: 'robert', age: 28},
{user: 'zacarias', age: 44},
]
/
```


just-partition

:icecream:Try It


npm install just-partition


```js
import partition from "just-partition";


partition([1, 5, 2, 4, 3], (n) => n > 3); // [[5, 4],[1, 2, 3]]
partition(["a", 2, 3, "3"], (x) => typeof x == "string"); // [['a', '3'],[2, 3]]
partition([1, 2, 3, 4], (x) => typeof x == "number"); // [[1, 2, 3, 4],[]]
partition([1, 2, 3, 4], (x) => typeof x == "string"); // [[], [1, 2, 3, 4]]
partition([], (n) => n > 3); // [[], []]
partition({ a: 1, b: 2 }, (n) => n > 1); // throws
partition(null, (n) => n > 1); // throws
partition(undefined, (n) => n > 1); // throws
```


just-range

:icecream:Try It


npm install just-range


```js
import range from "just-range";


range(1, 5); // [1, 2, 3, 4]
range(5); // [0, 1, 2, 3, 4]
range(-5); // [0, -1, -2, -3, -4]
range(0, 20, 5); // [0, 5, 10, 15]
```


just-remove

:icecream:Try It


npm install just-remove


```js
import remove from "just-remove";


remove([1, 2, 3, 4, 5, 6], [1, 3, 6]); // [2, 4, 5]
```


just-union

:icecream:Try It


npm install just-union


```js
import union from "just-union";


union([1, 2, 5, 6], [2, 3, 4, 6]); // [1, 2, 3, 4, 5, 6]
```


just-zip-it

:icecream:Try It


npm install just-zip-it


```js
import zip from "just-zip-it";


zip([1, 2, 3]); // [[1], [2], [3]]
zip([1, 2, 3], ["a", "b", "c"]); // [[1, 'a'], [2, 'b'], [3, 'c']]
zip([1, 2], ["a", "b"], [true, false]); // [[1, 'a', true], [2, 'b', false]]
zip([1, 2, 3], ["a", "b"], [true]); // [[1, 'a', true], [2, 'b', undefined], [3, undefined, undefined]]
zip(undefined, {}, false, 1, "foo"); // throws
zip([1, 2], ["a", "b"], undefined, {}, false, 1, "foo"); // throws
```


just-group-by

:icecream:Try It


npm install just-group-by


```js
import groupBy from "just-group-by";


groupBy([6.1, 4.2, 6.3], Math.floor); // { '4': [4.2], '6': [6.1, 6.3] }
groupBy([1, 2, 3, 4, 5, 6, 7, 8], function (i) {
return i % 2;
}); // { '0': [2, 4, 6, 8], '1': [1, 3, 5, 7] }
groupBy("string", Math.floor); // throws
groupBy([1, 2, 3, 4], "string"); // throws
```


Statistics
just-mean

:icecream:Try It


npm install just-mean


```js
import mean from "just-mean";


mean([1, 2, 3, 2, 4, 1]); // 2.1666666667
mean(3, 2, 1); // 2
mean([4]); // 4
mean(["3", 2]); // throws
mean(); // throws
```


just-median

:icecream:Try It


npm install just-median


```js
import median from "just-median";


median([1, 2, 3, 4, 5]); // 3
median([3, -1, 2]); // 2
median([9, 14, 14, 200, 15]); // 14
median(1, 2, 4, 3); // 2.5
median(["3", 2, 1]); // throws
median(); // throws
```


just-mode

:icecream:Try It


npm install just-mode


```js
import mode from "just-mode";


mode([1, 2, 3, 2]); // 2
mode(4, 4, 1, 4); // 4
mode(100, 100, 101, 101); // [100, 101]
mode(4, 3, 2, 1); // [1, 2, 3, 4]
mode(["1", 2, 2, 1, 2]); // throws
mode(null); // throws
```


just-percentile

:icecream:Try It


npm install just-percentile


```js
import percentile from "just-percentile";


percentile([1, 2, 3], 0); // 1
percentile([1, 2, 3], 50); // 2
percentile([1, 2, 3], 100); // 3


// See https://en.wikipedia.org/wiki/Percentile (linear interpolation method)
percentile([15, 20, 35, 40, 50], 5); // 15
percentile([15, 20, 35, 40, 50], 30); // 20
percentile([15, 20, 35, 40, 50], 40); // 27.5
percentile([15, 20, 35, 40, 50], 95); // 50


percentile(1, 2, 3, 50); // throws
percentile(["1", 2, 3], 50); // throws
percentile([], 50); // throws
```


just-variance

:icecream:Try It


npm install just-variance


```js
import variance from "just-variance";


variance([1, 2, 3, 2, 4, 1]); // 1.3666666667
variance(3, 2, 1); // 1
variance([100, 100, 100.1, 100]); // 0.0025
variance(1, 2, 3, 4, 5, -6); // 15.5
variance([4]); // throws
variance(["3", 2]); // throws
variance(NaN, NaN); // throws
variance(); // throws
```


just-standard-deviation

:icecream:Try It


npm install just-standard-deviation


```js
import standardDeviation from "just-standard-deviation";


standardDeviation([1, 2, 3, 2, 4, 1]); // 1.16904519
standardDeviation(3, 2, 1); // 1
standardDeviation([100, 100, 100.1, 100]); // 0.05
standardDeviation(1, 2, 3, 4, 5, -6); // 3.9370039
standardDeviation([4]); // throws
standardDeviation(["3", 2]); // throws
standardDeviation(NaN, NaN); // throws
standardDeviation(); // throws
```


just-skewness

:icecream:Try It


npm install just-skewness


```js
import skewness from "just-skewness";


// Using Pearson's second skewness coefficient
skewness(3, 2, 1); // 0
skewness([1, 2, 3, 2, 4, 1]); // 0.4276994613841504
skewness(1, 2, 3, 4, 5, -6); // -0.762000762001143
skewness([1, 2, 3, 4, 9]); // 0.7705935588815224
skewness([4]); // throws
skewness(["3", 2]); // throws
skewness(NaN, NaN); // throws
skewness(); // throws
```


Strings
just-template

:icecream:Try It


npm install just-template


```js
import template from "just-template";


const data = {
a: {
aa: {
aaa: "apple",
bbb: "pear",
},
bb: "orange",
},
b: "plum",
};
template(
"2 {{a.aa.aaa}}s, a {{a.aa.bbb}}, 3 {{a.bb}}s and a {{b}}. Yes 1 {{a.aa.bbb}}.",
data
);
// '2 apples, a pear, 3 oranges and a plum. Yes 1 pear.'
```


just-truncate

:icecream:Try It


npm install just-truncate


js
truncate("when shall we three meet again", 9); // 'when s...'
truncate("when shall we three meet again", 12, " (etc)"); // 'when s (etc)'
truncate("when shall we", 15); // 'when shall we'
truncate("when shall we", 15, "(more)"); // 'when shall we'
truncate("when shall we", 10, " (etc etc etc)"); // ' (etc etc etc)'


just-prune

:icecream:Try It


npm install just-prune


js
prune('when shall we three meet again', 7); // 'when...'
prune('when shall we three meet again', 7, ' (more)'; // 'when (more)'
prune('when shall we', 15,); // 'when shall we'
prune('when shall we', 15, ' (etc)'); // 'when shall we'
prune('when shall we', 7, ' (more)'); // ' (more)'


just-squash

:icecream:Try It


npm install just-squash


js
squash("the cat sat on the mat"); // 'thecatsatonthemat'
squash(" the cat sat on the mat "); // 'thecatsatonthemat'
squash("\tthe cat\n sat \fon \vthe \rmat "); // '\tthecat\nsat\fon\vthe\rmat'
squash("\tthe cat\n sat \fon \vthe \rmat ", true); // 'thecatsatonthemat'
squash(
`the cat
sat on the mat`,
true
); // thecatsatonthemat


just-left-pad

:icecream:Try It


npm install just-left-pad


js
leftPad("hello", 9); // ' hello'
leftPad("hello", 3); // 'hello'
leftPad("hello", 9, "."); // '....hello'
leftPad("hello", 9, ".."); // '....hello'
leftPad("hello", 10, "ab"); // 'bababhello'
leftPad("hello", 9, "\uD83D\uDC04"); // '🐄🐄🐄🐄hello'
leftPad("hello", 10, "\uD83D\uDC11\uD83D\uDC04"), // '🐄🐑🐄🐑🐄hello'
leftPad("hello", 7, "🐄"), // '🐄🐄hello'
leftPad(null, 7); // throws
leftPad([], 4, "*"); // throws
leftPad("hello", 4, true); // throws
leftPad("hello", -4, true); // throws
leftPad("hello", 2.3, true); // throws


just-right-pad

:icecream:Try It


npm install just-right-pad


js
rightPad("hello", 9); // 'hello '
rightPad("hello", 3); // 'hello'
rightPad("hello", 9, "."); // 'hello....'
rightPad("hello", 9, ".."); // 'hello....'
rightPad("hello", 10, "ab"); // 'helloababa'
rightPad("hello", 9, "\uD83D\uDC04"); // 'hello🐄🐄🐄🐄'
rightPad("hello", 10, "\uD83D\uDC11\uD83D\uDC04"), // 'hello🐑🐄🐑🐄🐑'
rightPad("hello", 7, "🐄"), // 'hello🐄🐄'
rightPad(null, 7); // throws
rightPad([], 4, "*"); // throws
rightPad("hello", 4, true); // throws
rightPad("hello", -4, true); // throws
rightPad("hello", 2.3, true); // throws


just-camel-case

:icecream:Try It


npm install just-camel-case


js
camelCase("the quick brown fox"); // 'theQuickBrownFox'
camelCase("the_quick_brown_fox"); // 'theQuickBrownFox'
camelCase("the-quick-brown-fox"); // 'theQuickBrownFox'
camelCase("theQuickBrownFox"); // 'theQuickBrownFox'
camelCase("thequickbrownfox"); // 'thequickbrownfox'
camelCase("the - quick * brown# fox"); // 'theQuickBrownFox'
camelCase("behold theQuickBrownFox"); // 'beholdTheQuickBrownFox'
camelCase("Behold theQuickBrownFox"); // 'beholdTheQuickBrownFox'
// all caps words are camel-cased
camelCase("The quick brown FOX"); // theQuickBrownFox
// all caps substrings >= 4 chars are camel-cased
camelCase("theQUickBrownFox"); // 'theQUickBrownFox'
camelCase("theQUIckBrownFox"); // 'theQUIckBrownFox'
camelCase("theQUICKBrownFox"); // 'theQuickBrownFox'


just-kebab-case

:icecream:Try It


npm install just-kebab-case


js
kebabCase("the quick brown fox"); // 'the-quick-brown-fox'
kebabCase("the-quick-brown-fox"); // 'the-quick-brown-fox'
kebabCase("the_quick_brown_fox"); // 'the-quick-brown-fox'
kebabCase("theQuickBrownFox"); // 'the-quick-brown-fox'
kebabCase("theQuickBrown Fox"); // 'the-quick-brown-fox'
kebabCase("thequickbrownfox"); // 'thequickbrownfox'
kebabCase("the - quick * brown# fox"); // 'the-quick-brown-fox'
kebabCase("theQUICKBrownFox"); // 'the-q-u-i-c-k-brown-fox'


just-snake-case

:icecream:Try It


npm install just-snake-case


js
snakeCase("the quick brown fox"); // 'the_quick_brown_fox'
snakeCase("the-quick-brown-fox"); // 'the_quick_brown_fox'
snakeCase("the_quick_brown_fox"); // 'the_quick_brown_fox'
snakeCase("theQuickBrownFox"); // 'the_quick_brown_fox'
snakeCase("theQuickBrown Fox"); // 'the_quick_brown_Fox'
snakeCase("thequickbrownfox"); // 'thequickbrownfox'
snakeCase("the - quick * brown# fox"); // 'the_quick_brown_fox'
snakeCase("theQUICKBrownFox"); // 'the_q_u_i_c_k_brown_fox'


just-pascal-case

:icecream:Try It


npm install just-pascal-case


js
pascalCase("the quick brown fox"); // 'TheQuickBrownFox'
pascalCase("the_quick_brown_fox"); // 'TheQuickBrownFox'
pascalCase("the-quick-brown-fox"); // 'TheQuickBrownFox'
pascalCase("theQuickBrownFox"); // 'TheQuickBrownFox'
pascalCase("thequickbrownfox"); // 'Thequickbrownfox'
pascalCase("the - quick * brown# fox"); // 'TheQuickBrownFox'
pascalCase("theQUICKBrownFox"); // 'TheQUICKBrownFox'


just-capitalize

:icecream:Try It


npm install just-capitalize


js
capitalize("capitals"); // 'Capitals'
capitalize("Capitals"); // 'Capitals'
// all remaining characters are lowercased
capitalize("CAPITALS"); // 'Capitals'
capitalize("CaPiTaLs"); // 'Capitals'
capitalize(" capitals"); // ' capitals'
capitalize("Capi tals"); // 'Capi tals'
capitalize("Capi Tals"); // 'Capi tals'
capitalize("!capitals"); // '!capitals'


just-replace-all

:icecream:Try It


npm install just-replace-all


js
replaceAll("hello, world", "l", "q"); // 'heqqo, worqd'
replaceAll("hello, world", "l", "qq"); // 'heqqqqo, worqqd'
replaceAll("hello, world", "ll", "q"); // 'heqo, world'
replaceAll("hello, world", "", "q"); // 'hello, world'
replaceAll("hello, world", "l", ""); // 'heo, word'
replaceAll("hello, world", null, "q"); // 'hello, world'
replaceAll("hello, world", "l"); // throw
replaceAll("hello, world"); // throw
replaceAll(); // throw
replaceAll(null, "l", "q"); // throw
replaceAll("hello, world", null, "q"); // throw
replaceAll("hello, world", "l", null); // throw


Numbers
just-clamp

:icecream:Try It


npm install just-clamp


```js
import clamp from "just-clamp";


var n = 5;
clamp(1, n, 12); // 5
clamp(3, n, 1); // 3
clamp(8, n, 9); // 8
clamp(0, n, 0); // 0


var n = -5;
clamp(1, n, 12); // 1
clamp(-7, n, -8); // -7


clamp(NaN, n, 8); // NaN
clamp(3, n, NaN); // NaN
clamp(3, NaN, 8); // NaN


clamp(undefined, n, 8); // throws
clamp(3, n, "h"); // throws
clamp(3, false, 8); // throws
```


just-is-prime

:icecream:Try It


npm install just-is-prime


```js
import isPrime from "just-is-prime";


isPrime(1); // false
isPrime(2); // true
isPrime(17); // true
isPrime(10); // false
isPrime(); // throws
isPrime(null); // throws
isPrime("js"); // throws
isPrime({}); // throws
isPrime(function () {}); // throws
isPrime([]); // throws
```


just-modulo

:icecream:Try It


npm install just-modulo


```js
import modulo from "just-modulo";


modulo(7, 5); // 2
modulo(17, 23); // 17
modulo(16.2, 3.8); // 1
modulo(5.8, 3.4); //2.4
modulo(4, 0); // 4
modulo(-7, 5); // 3
modulo(-2, 15); // 13
modulo(-5.8, 3.4); // 1
modulo(12, -1); // NaN
modulo(-3, -8); // NaN
modulo(12, "apple"); // NaN
modulo("bee", 9); // NaN
modulo(null, undefined); // NaN
```


Functions
just-compose

:icecream:Try It


npm install just-compose


```js
import compose from "just-compose";


const sqRootBiggest = compose(Math.max, Math.sqrt, Math.trunc);
sqRootBiggest(10, 5); // 3
sqRootBiggest(7, 0, 16); // 4
```


just-curry-it

:icecream:Try It


npm install just-curry-it


```js
import curry from "just-curry-it";


function add(a, b, c) {
return a + b + c;
}
curry(add)(1)(2)(3); // 6
curry(add)(1)(2)(2); // 5
curry(add)(2)(4, 3); // 9


function add(...args) {
return args.reduce((sum, n) => sum + n, 0);
}
var curryAdd4 = curry(add, 4);
curryAdd4(1)(2, 3)(4); // 10


function converter(ratio, input) {
return (input * ratio).toFixed(1);
}
const curriedConverter = curry(converter);
const milesToKm = curriedConverter(1.62);
milesToKm(35); // 56.7
milesToKm(10); // 16.2
```


just-demethodize

:icecream:Try It


npm install just-demethodize


```js
const demethodize = require("just-demethodize");


const trimFn = demethodize("".trim);
["hello ", " goodbye", "hello again"].map(trimFn);
```


just-flip

:icecream:Try It


npm install just-flip


```js
import flip from "just-flip";


flip(console.log)(1, 2, 3); // 2, 1, 3
```


just-partial-it

:icecream:Try It


npm install just-partial-it


```js
import partial from "just-partial-it";


const cubedRoot = partial(Math.pow, _, 1 / 3);
cubedRoot(64); // 4


const getRoot = partial(Math.pow, 64);
getRoot(1 / 2); // 8
```


just-permutations

:icecream:Try It


npm install just-permutations


```js
import permutations from "just-permutations";


permutations([1, 2, 3]); // [[1, 2, 3], [2, 1, 3], [2, 3, 1], [1, 3, 2], [3, 1, 2], [3, 2, 1]]
permutations([]); // []
permutations(); // throws
```


just-debounce-it

:icecream:Try It


npm install just-debounce-it


```js
import debounce from "just-debounce-it";


const fn1 = debounce(() => console.log("Hello"), 500);
fn1();
fn1();
fn1();
// 500ms later logs 'hello' once


const fn2 = debounce(() => console.log("Hello"), 500, true);
fn2(); // logs hello immediately
fn2();
fn2();
// 500ms later logs 'hello' once


const fn3 = debounce(() => console.log("Hello"), 500);
fn1();
fn1();
fn1();
fn3.cancel();
// function cancelled before 'hello' is logged


const fn4 = debounce(() => console.log("Hello"), 500);
fn4();
fn4();
fn4();
fn4.flush();
// immediately invoke the debounced function
```


just-memoize

:icecream:Try It


npm install just-memoize


```js
import memoize from "just-memoize";


const sumByOne = memoize(function (value) {
return value + 1;
});


sumByOne(10); // Returns value returned by the function
sumByOne(10); // Cache hit!


sumByOne(20); // Returns value returned by the function
sumByOne(20); // Cache hit!


// Custom cache key (key defaults to JSON stringified arguments)
var sum = memoize(
function (a, b) {
return a + b;
},
function (a, b) {
return ${a}-${b};
}
);


sum(10, 10); // Returns value returned by the function
sum(10, 20); // Returns value returned by the function
sum(10, 20); // Cache hit!
```


just-memoize-last

:icecream:Try It


npm install just-memoize-last


```js
const memoizeLast = require('just-memoize-last')
const compare = require('just-compare')


const maxValue = memoizeLast(function(arr) {
return Math.max(...arr)
}, function(a, b) {
return compare(a, b);
});


maxValue([1,2,3]) // 3
maxValue([1,2,3]) // cache hit!
maxValue([1,3,4]) // 4
maxValue([1,2,3]) // 3
```


just-random

:icecream:Try It


npm install just-random


```js
import random from 'just-random';


random();
// Produces a random number between 0 and 1


random(5);
// Produces a random number between 0 and 5


random(5, 10);
// Produces a random number between 5 and 10
```


just-throttle

:icecream:Try It


npm install just-throttle


```js
import throttle from "just-throttle";


// no matter how many times the function is called, only invoke once within the given interval
// options:
// leading: invoke before interval
// trailing: invoke afer interval


const fn1 = throttle(() => console.log("hello"), 500, { leading: true });
setInterval(fn1, 400);
// logs 'hello' immediately and then every 500ms


const fn2 = throttle(() => console.log("hello"), 500, { trailing: true });
setInterval(fn2, 400);
// logs 'hello' after 500ms and then every 500ms


const fn3 = throttle(() => console.log("hello"), 500, {
leading: true,
trailing: true,
});
// forces trailing to false


const fn4 = throttle(() => console.log('hello'), 500, { leading: false });
fn4();
fn4();
fn4();
fn4.cancel();
// function cancelled before 'hello' is logged


const fn5 = throttle(() => console.log("Hello"), 500);
fn5();
fn5();
fn5();
fn5.flush();
// immediately invoke the throttled function
```


just-once

:icecream:Try It


npm install just-once


```js
import once from "just-once";


const fn = once(() => console.log("hello"));


fn();
// logs 'hello'
fn();
// does nothing
```


Testing

Run all tests as a single test suite with


npm run test


Cross browser tests (via saucelabs) are in the sauce branch


Contribute!

https://github.com/angus-c/just/blob/master/CONTRIBUTING.md