npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

loony-utils

v0.2.0

Published

Loony Utils is a collection of utility functions for JavaScript and TypeScript projects, designed to simplify common tasks and enhance productivity.

Readme

loony-utils

A TypeScript utility library with zero dependencies. Lodash-compatible API, fully typed, ships both ESM and CJS.

Install

npm install loony-utils

Import

import { chunk, debounce, merge, cloneDeep } from "loony-utils";

Table of Contents


Array

| Function | Signature | Description | |---|---|---| | after | after(n, func) | Create a function that invokes func only after n calls. | | chunk | chunk(array, size=1) | Split array into groups of size. | | compact | compact(array) | Remove falsey values (false, null, 0, "", undefined, NaN). | | concat | concat(array, ...values) | Concatenate arrays/values into a new array (one-level flatten). | | countBy | countBy(array, iteratee) | Count elements grouped by iteratee result. | | difference | difference(array, ...values) | Elements in array not present in values. | | differenceBy | differenceBy(array, values, iteratee) | difference with iteratee-based comparison. | | drop | drop(array, n=1) | Drop the first n elements. | | dropRight | dropRight(array, n=1) | Drop the last n elements. | | dropWhile | dropWhile(array, predicate) | Drop elements from the start while predicate returns truthy. | | every | every(array, predicate) | Return true if all elements satisfy predicate. | | fill | fill(array, value, start=0, end) | Return a copy with the range filled with value. | | filter | filter(array, predicate) | Return elements satisfying predicate. | | find | find(array, predicate) | Return first element matching predicate. | | findIndex | findIndex(array, predicate, fromIndex=0) | Return index of first match or -1. | | findLast | findLast(array, predicate) | Return last element matching predicate. | | findLastIndex | findLastIndex(array, predicate) | Return index of last match or -1. | | flatMap | flatMap(array, iteratee) | Map then flatten one level. | | flatten | flatten(array) | Flatten one level. | | flattenDeep | flattenDeep(array) | Recursively flatten all levels. | | flattenDepth | flattenDepth(array, depth=1) | Flatten up to depth levels. | | fromPairs | fromPairs(pairs) | Convert [[key, value]] to {key: value}. | | groupBy | groupBy(array, iteratee) | Group elements by iteratee result. | | head | head(array) | First element or undefined. | | indexOf | indexOf(array, value, fromIndex=0) | Index of value using deep equality, or -1. | | initial | initial(array) | All but the last element. | | intersection | intersection(...arrays) | Values common to all arrays. | | intersectionBy | intersectionBy(...arrays, iteratee) | intersection with iteratee-based comparison. | | join | join(array, separator=',') | Join elements to a string. | | last | last(array) | Last element or undefined. | | lastIndexOf | lastIndexOf(array, value, fromIndex?) | Index of last occurrence using deep equality. | | map | map(array, iteratee) | Return mapped array. | | nth | nth(array, n=0) | Element at index n (supports negative). | | orderBy | orderBy(array, keys, orders) | Sort by multiple keys with 'asc'/'desc' orders. | | partition | partition(array, predicate) | Split into [matches, rest]. | | pull | pull(array, ...values) | Return array without specified values. | | pullAt | pullAt(array, indexes) | Remove elements at indexes (mutates) and return them. | | reduce | reduce(array, iteratee, accumulator) | Reduce left to right. | | reduceRight | reduceRight(array, iteratee, accumulator) | Reduce right to left. | | remove | remove(array, predicate) | Remove matching elements (mutates) and return them. | | reverse | reverse(array) | Return a reversed copy. | | sample | sample(array) | Return a random element. | | sampleSize | sampleSize(array, n=1) | Return n unique random elements. | | shuffle | shuffle(array) | Return a shuffled copy. | | slice | slice(array, start=0, end?) | Shallow slice copy. | | some | some(array, predicate) | Return true if any element satisfies predicate. | | sortBy | sortBy(array, ...iteratees) | Stable sort by one or more iteratees. | | sortedIndex | sortedIndex(array, value) | Binary-search insert index for a sorted array. | | sortedUniq | sortedUniq(array) | Remove adjacent duplicates (optimized for sorted arrays). | | tail | tail(array) | All but the first element. | | take | take(array, n=1) | First n elements. | | takeRight | takeRight(array, n=1) | Last n elements. | | takeWhile | takeWhile(array, predicate) | Take elements from the start while predicate is truthy. | | union | union(...arrays) | Unique values across all arrays. | | unionBy | unionBy(...arrays, iteratee) | union with iteratee-based uniqueness. | | uniq | uniq(array) | Remove duplicates (first occurrence wins). | | uniqBy | uniqBy(array, iteratee) | Remove duplicates by iteratee result. | | unzip | unzip(array) | Transpose an array of arrays. | | without | without(array, ...values) | Return array excluding specified values. | | xor | xor(...arrays) | Symmetric difference across arrays. | | xorBy | xorBy(...arrays, iteratee) | xor with iteratee-based comparison. | | zip | zip(...arrays) | Combine arrays by index. | | zipObject | zipObject(keys, values) | Create object from keys and values arrays. |

Iteratee shorthands — wherever a function accepts an iteratee or predicate, you can pass:

  • a function: x => x.age
  • a string (property name): "age"
  • an object (matches): { active: true }
groupBy([6.1, 4.2, 6.3], Math.floor);        // { '6': [6.1, 6.3], '4': [4.2] }
groupBy(["one", "two", "three"], "length");   // { '3': ['one', 'two'], '5': ['three'] }
sortBy(users, "age");
orderBy(users, ["age", "name"], ["asc", "desc"]);
filter(users, { active: true });

Object

| Function | Signature | Description | |---|---|---| | assign | assign(object, ...sources) | Shallow merge sources into a new object. | | cloneDeep | cloneDeep(value) | Deep clone — handles plain objects, arrays, Date, RegExp, Map, Set. | | defaults | defaults(object, ...sources) | Fill in undefined properties from sources. | | entries | entries(object) | Object.entries wrapper returning [string, value][]. | | findKey | findKey(object, predicate) | First key where predicate(value, key, object) is truthy. | | forOwn | forOwn(object, iteratee) | Iterate own enumerable properties; stop when iteratee returns false. | | get | get(object, path, defaultValue?) | Get value at dot/bracket path. | | has | has(object, path) | Check if path is an own property. | | invert | invert(object) | Swap keys and values. | | invertBy | invertBy(object, iteratee?) | Group original keys by transformed value. | | keys | keys(object) | Object.keys wrapper. | | mapKeys | mapKeys(object, iteratee) | Return new object with transformed keys. | | mapValues | mapValues(object, iteratee) | Return new object with transformed values. | | merge | merge(object, ...sources) | Deep merge sources into a new object. | | mixin | mixin(object, source) | Add functions from source to object (skip existing keys). | | omit | omit(object, paths) | Return new object without the listed keys. | | omitBy | omitBy(object, predicate) | Return new object omitting keys where predicate returns truthy. | | pick | pick(object, paths) | Return new object with only the listed keys. | | pickBy | pickBy(object, predicate) | Return new object keeping keys where predicate returns truthy. | | set | set(object, path, value) | Set value at path (mutates). Creates intermediate objects/arrays as needed. | | toPairs | toPairs(object) | [[key, value]] array. | | transform | transform(collection, iteratee, accumulator) | Like reduce but iterates object/array uniformly. | | unset | unset(object, path) | Delete property at path. | | update | update(object, path, updater) | Update value at path via updater(currentValue). | | values | values(object) | Object.values wrapper. |

get({ a: { b: { c: 3 } } }, "a.b.c");          // 3
get({ a: [1, 2, 3] }, "a[1]");                  // 2
set({}, "a.b.c", 42);                           // { a: { b: { c: 42 } } }
merge({ a: 1, x: { y: 1 } }, { b: 2, x: { z: 2 } });
// { a: 1, b: 2, x: { y: 1, z: 2 } }

String

| Function | Signature | Description | |---|---|---| | camelCase | camelCase(str) | Convert to camelCase. | | capitalize | capitalize(str) | Uppercase first char, lowercase rest. | | deburr | deburr(str) | Remove Latin extended diacritics. | | endsWith | endsWith(str, target, position?) | Test suffix at optional position. | | escape | escape(str) | Escape HTML characters (&, <, >, ", '). | | escapeRegExp | escapeRegExp(str) | Escape special RegExp characters. | | includes | includes(collection, value, fromIndex=0) | String or array membership using deep equality. | | kebabCase | kebabCase(str) | Convert to kebab-case. | | lowerCase | lowerCase(str) | Convert to lower case (space-separated words). | | lowerFirst | lowerFirst(str) | Lowercase first character only. | | pad | pad(str, length=0, chars=' ') | Pad both sides to length. | | padEnd | padEnd(str, length=0, chars=' ') | Pad right to length. | | padStart | padStart(str, length=0, chars=' ') | Pad left to length. | | repeat | repeat(str, n=1) | Repeat string n times. | | snakeCase | snakeCase(str) | Convert to snake_case. | | startCase | startCase(str) | Convert to Start Case. | | startsWith | startsWith(str, target, position=0) | Test prefix at optional position. | | toLower | toLower(str) | str.toLowerCase() with type guard. | | toUpper | toUpper(str) | str.toUpperCase() with type guard. | | trim | trim(str, chars?) | Trim whitespace or custom characters from both ends. | | trimEnd | trimEnd(str, chars?) | Trim right. | | trimStart | trimStart(str, chars?) | Trim left. | | truncate | truncate(str, options?) | Truncate to length (default 30) with omission (default "..."). | | unescape | unescape(str) | Convert HTML entities back to characters. | | upperCase | upperCase(str) | Convert to UPPER CASE (space-separated words). | | upperFirst | upperFirst(str) | Uppercase first character only. | | words | words(str, pattern?) | Split into an array of words. |

camelCase("Foo-bar_baz");   // "fooBarBaz"
snakeCase("fooBar");         // "foo_bar"
truncate("hello world", { length: 8 });  // "hello..."
truncate("hello world", { length: 8, omission: "…" });  // "hello w…"

Lang / Types

Type checks

| Function | Returns true when… | |---|---| | isArray(value) | Array.isArray(value) | | isBoolean(value) | typeof value === 'boolean' | | isDate(value) | value instanceof Date | | isError(value) | value instanceof Error | | isFinite(value) | Number.isFinite(value) | | isFunction(value) | typeof value === 'function' | | isInteger(value) | Number.isInteger(value) | | isMap(value) | value instanceof Map | | isNaN(value) | Number.isNaN(value) | | isNil(value) | value == null | | isNull(value) | value === null | | isNumber(value) | typeof value === 'number' | | isObject(value) | non-null object (excludes arrays) | | isPlainObject(value) | plain object (constructor === Object) | | isRegExp(value) | value instanceof RegExp | | isSet(value) | value instanceof Set | | isString(value) | typeof value === 'string' | | isSymbol(value) | typeof value === 'symbol' | | isUndefined(value) | value === undefined | | isWeakMap(value) | value instanceof WeakMap | | isWeakSet(value) | value instanceof WeakSet |

isEmpty

Returns true for: null, undefined, "", [], {}, empty Map/Set.

isEqual

Deep structural equality — handles primitives, arrays, plain objects, Date, RegExp, Map, Set. NaN equals NaN.

isEqual([1, { x: 2 }], [1, { x: 2 }]);  // true
isEqual(new Date("2020-01-01"), new Date("2020-01-01"));  // true

Conversions

| Function | Description | |---|---| | toArray(value) | Convert to array — iterables, strings, objects, nullish → []. | | toFinite(value) | Coerce to finite number; Infinity/-Infinity clamped to MAX_VALUE. | | toInteger(value) | Coerce to integer (truncates). | | toNumber(value) | Coerce to number; non-numeric → 0. | | toSafeInteger(value) | Coerce and clamp to safe integer range. | | toString(value) | Coerce to string; null/undefined"". |


Math

| Function | Signature | Description | |---|---|---| | add | add(a, b) | a + b | | subtract | subtract(a, b) | a - b | | multiply | multiply(a, b) | a * b | | divide | divide(a, b) | a / b | | ceil | ceil(number, precision=0) | Round up to precision decimal places. | | floor | floor(number, precision=0) | Round down to precision decimal places. | | round | round(number, precision=0) | Round to precision decimal places. | | clamp | clamp(number, lower, upper) | Clamp number into [lower, upper]. | | inRange | inRange(number, start, end?) | Check if number is in [start, end). | | max | max(array) | Maximum value in array, or undefined. | | maxBy | maxBy(array, iteratee) | Element with the largest iteratee result. | | mean | mean(array) | Average of array values. | | meanBy | meanBy(array, iteratee) | Average of iteratee results. | | min | min(array) | Minimum value in array, or undefined. | | minBy | minBy(array, iteratee) | Element with the smallest iteratee result. | | sum | sum(array) | Sum of array values. | | sumBy | sumBy(array, iteratee) | Sum of iteratee results. | | gcd | gcd(a, b) | Greatest common divisor. | | lcm | lcm(a, b) | Least common multiple. |

clamp(10, 0, 5);                   // 5
ceil(4.123, 2);                    // 4.13
sumBy([{ n: 1 }, { n: 2 }], "n"); // 3

Number

| Function | Signature | Description | |---|---|---| | random | random(lower?, upper?, floating=false) | Random integer or float. |

  • random() — float in [0, 1)
  • random(n) — integer in [0, n]
  • random(a, b) — integer in [a, b]
  • random(a, b, true) — float in [a, b]

Function

| Function | Signature | Description | |---|---|---| | after | after(n, func) | Return a function that invokes func only after being called n times. | | ary | ary(func, n) | Cap func to accept at most n arguments. | | before | before(n, func) | Return a function that invokes func at most n-1 times; returns last result thereafter. | | compose | compose(...fns) | Right-to-left function composition. | | curry | curry(func, arity?) | Auto-curry func to its arity. | | debounce | debounce(func, wait, immediate=false) | Delay invocation until wait ms after last call. | | delay | delay(func, wait, ...args) | Invoke func after wait ms. | | flip | flip(func) | Reverse argument order. | | memoize | memoize(func, resolver?) | Cache results keyed by args (or resolver). | | negate | negate(predicate) | Return the boolean complement of predicate. | | once | once(func) | Invoke func only once; return cached result on subsequent calls. | | partial | partial(func, ...args) | Pre-fill leading arguments. | | partialRight | partialRight(func, ...args) | Pre-fill trailing arguments. | | pipe | pipe(...fns) | Left-to-right function composition. | | throttle | throttle(func, wait) | Limit invocations to at most once per wait ms. |

const add = (a: number, b: number) => a + b;
const add5 = partial(add, 5);
add5(3);  // 8

const double = (x: number) => x * 2;
const inc = (x: number) => x + 1;
pipe(double, inc)(3);     // 7  (3*2 + 1)
compose(inc, double)(3);  // 7  (same, written right-to-left)

Utility

| Function | Signature | Description | |---|---|---| | attempt | attempt(func, ...args) | Call func and return the result or an Error if it throws. | | cond | cond(pairs) | Return a function that tests [predicate, transform] pairs and returns the first match. | | constant | constant(value) | Return a function that always returns value. | | identity | identity(value) | Return value unchanged. | | matches | matches(source) | Return a predicate that deep-compares objects against source. | | matchesProperty | matchesProperty(path, value) | Return a predicate that checks get(obj, path) === value (deep). | | noop | noop() | Do nothing; return undefined. | | now | now() | Date.now(). | | property | property(path) | Return a function that gets path from an object. | | propertyOf | propertyOf(object) | Return a function that gets a path from object. | | range | range(start=0, end?, step=1) | Create a numeric array. | | times | times(n, iteratee) | Call iteratee(index) n times and return the results. | | uniqueId | uniqueId(prefix='') | Generate a unique string ID with optional prefix. |

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

times(3, i => i * 2);  // [0, 2, 4]

uniqueId("user_");  // "user_1"
uniqueId("user_");  // "user_2"

const isActive = matches({ active: true });
isActive({ name: "Alice", active: true });  // true