A library of zero-dependency npm modules that do just do one thing.
A guilt-free alternative to those bulkier libraries. Ideal for mobile web development or wherever bytes are precious.
We welcome contributions. Please follow the contribution guidelines below.
Editable, runnable examples of every utility (powered by RunKit)
The Zen of Dependency-Free –- Why I wrote Just
-
- just-compose
- just-curry-it
- just-demethodize
- just-flip
- just-partial-it
- just-debounce-it
- just-throttle
npm install just-diff
Return an object representing the difference between two other objects
Pass converter to format as http://jsonpatch.comimport {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 } ] // 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 } ] // 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 } ]
npm install just-compare
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}]]); // true
npm install just-pluck-it
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}
npm install just-flush
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, [null], true] flush({a: 2, b: null, c: 4, d: undefined}); // {a: 2, c: 4} flush('something'); // undefined flush(); // undefined
npm install just-extend
import extend from 'just-extend';
let obj = {a: 3, b: 5};
extend(obj, {a: 4, c: 8}); // {a: 4, b: 5, c: 8}
obj; // {a: 4, b: 5, c: 8}
let obj = {a: 3, b: 5};
extend({}, 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};
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]}
let arr = [1, 2, 3];
let 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]}
npm install just-values
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
npm install just-entries
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([]); // []
npm install just-pick
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, d: undefined}
pick(obj, ['a', 'a']); // {a: 3}
npm install just-omit
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}
npm install just-is-empty
import isEmpty from 'just-is-empty';
isEmpty({a: 3, b: 5}) // false
isEmpty(['a','b']) // false
isEmpty({}) // true
isEmpty([]) // true
isEmpty(null) // true
isEmpty(undefined) // true
npm install just-is-circular
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
npm install just-is-primitive
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
npm install just-filter-object
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}
npm install just-map-object
import map from 'just-map-object';
// returns a new object with the predicate applied to each value
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'}
npm install just-reduce-object
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
npm install just-safe-get
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
npm install just-safe-set
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}}}
const obj4 = {a: {aa: {aaa: 2}}};
set(obj4, 'a.aa', {bbb: 7}); // true
obj4; // {a: {aa: {bbb: 7}}}
npm install just-typeof
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'
npm install just-flip-object
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'}
npm install just-unique
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']
npm install just-flatten-it
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]
npm install just-index
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); // undefined
index({}, 'id'); // undefined
npm install just-insert
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]
npm install just-intersect
import intersect from 'just-intersect';
intersect([1, 2, 5, 6], [2, 3, 5, 6]); // [2, 5, 6]
npm install just-compact
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({}); // undefined
npm install just-last
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([]); // undefined
last(null); // undefined
last(undefined); // undefined
npm install just-tail
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(); // undefined
tail(null); // undefined
tail(undefined); // undefined
npm install just-random
import random from 'just-random';
random([1, 2, 3]); // one of [1, 2, 3], at random
npm install just-shuffle
import shuffle from 'just-shuffle';
shuffle([1, 2, 3]); // array with original elements randomly sorted
shuffle([1]); // [1]
shuffle(); // undefined
shuffle(undefined); // undefined
shuffle(null); // undefined
shuffle({}); // undefined
npm install just-split-at
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); // undefined
splitAt(undefined, 1); // undefined
npm install just-range
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]
npm install just-remove
import remove from 'just-remove';
remove([1, 2, 3, 4, 5, 6], [1, 3, 6]); // [2, 4, 5]
npm install just-union
import union from 'just-union';
union([1, 2, 5, 6], [2, 3, 4, 6]); // [1, 2, 3, 4, 5, 6]
npm install just-zip-it
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(undefined, {}, false, 1, 'foo'); // []
zip([1, 2], ['a', 'b'], undefined, {}, false, 1, 'foo'); // [[1, 'a'], [2, 'b']]
zip([1, 2, 3], ['a', 'b'], [true]); // [[1, 'a', true], [2, 'b', undefined], [3, undefined, undefined]]
npm install just-template
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.'
npm install just-truncate
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)'
npm install just-prune
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)'
npm install just-squash
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
npm install just-left-pad
leftPad('hello', 9); // ' hello'
leftPad('hello', 3); 'hello'
leftPad('hello', 9, '.'); '....hello'
leftPad(['hello'], 7, '_'); '__hello'
leftPad(null, 7); ' null'
npm install just-right-pad
rightPad('hello', 9); // 'hello '
rightPad('hello', 3); 'hello'
rightPad('hello', 9, '.'); 'hello....'
rightPad(['hello'], 7, '_'); 'hello__'
rightPad(null, 7); 'null '
npm install just-camel-case
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('theQUICKBrownFox'); // 'theQUICKBrownFox'
npm install just-kebab-case
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'
npm install just-snake-case
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'
npm install just-clamp
import clamp from 'just-clamp';
var n = 5;
clamp(1, n, 12); // 5
clamp(1, n, 3); // 3
clamp(8, n, 9); // 8
clamp(0, n, 0); // 0
n = undefined;
clamp(3, n, 8); // 3
n = null;
clamp(3, n, 8); // 3
n = NaN;
clamp(3, n, 8); // 3
npm install just-modulo
import modulo from 'just-modulo';
modulo(7, 5); // 2
modulo(17, 23); // 17
modulo(16.2, 3.8); // 17
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
npm install just-compose
import compose from 'just-compose';
const sqRootBiggest = compose(Math.max, Math.sqrt, Math.trunc);
sqRootBiggest(10, 5); // 3
sqRootBiggest(7, 0, 16); // 4
npm install just-curry-it
import curry from 'just-curry-it';
function converter(ratio, input) {
return (input*ratio).toFixed(1);
}
const milesToKm = curry(converter)(1.62);
milesToKm(35); // 56.7
milesToKm(10); // 16.2
npm install just-demethodize
const demethodize = require('just-demethodize');
const trimFn = demethodize(''.trim);
['hello ', ' goodbye', 'hello again'].map(trimFn)
npm install just-flip
import flip from 'just-flip';
flip(console.log)(1, 2, 3) // 2, 1, 3
npm install just-partial-it
import partial from 'just-partial-it';
const cubedRoot = partial(Math.pow, undefined, 1/3);
cubedRoot(10).toFixed(1); // 56.7
cubedRoot(35).toFixed(1); // 16.2
npm install just-debounce-it
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
npm install just-throttle
import throttle from 'just-throttle';
const fn1 = throttle(() => console.log('hello'), 500, true);
setInterval(fn1, 400);
// logs 'hello' immediately and then every 500ms
const fn2 = throttle(() => console.log('hello'), 500);
setInterval(fn2, 400);
// logs 'hello' after 500ms and then every 500ms
Run all tests as a single test suite with
npm run test
We welcome pull requests for additional utilities (and corrections to existing ones).
- Must not depend on any other npm modules
- Always assume this is hot code and code accordingly
- favor for loops over high order functions
- don't repeatedly access the same property, assign to a var
- write es5
- API
- keep the api simple and intuitive
- avoid option arguments whenever possible - make it just do one thing
- README
- limit README to examples of each use case
- if you must explain the api (see api section) add a comment in the README example code
- add a section in the general README that duplicates the individual README for your module
- Tests
- write a test for each use case
- include tests for all README examples
- over-thorough is better than not thorough enough
- Interactive gh-pages (anguscroll.com/just)
- I can update this afterwards