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 🙏

© 2024 – Pkg Stats / Ryan Hefner

swiss-ak

v2.13.2

Published

A collection of useful little things that I like to reuse across projects

Downloads

253

Readme

swiss-ak (Swiss Army Knife)

A collection of useful little things that I like to reuse across projects

times

A collection of Tools for calculating simple times. Each unit (e.g. second) has: a type (second), a constant (SECOND) and a function for getting multiples (seconds(x: second) => ms)

| unit | type | constant | function | | ----------- | ------------ | ------------- | ---------------------------------- | | millisecond | ms | MILLISECOND | milliseconds(x: ms) => ms | | second | second | SECOND | seconds(x: second) => ms | | minute | minute | MINUTE | minutes(x: minute) => ms | | hour | hour | HOUR | hours(x: hour) => ms | | day | day | DAY | days(x: day) => ms | | week | week | WEEK | weeks(x: week) => ms | | month | month | MONTH | months(x: month) => ms | | year | year | YEAR | years(x: year) => ms | | decade | decade | DECADE | decades(x: decade) => ms | | century | century | CENTURY | centuries(x: century) => ms | | millennium | millennium | MILLENNIUM | millenniums(x: millennium) => ms |

waiters

Async functions that return promises at or after a given time.

'Accurate/pinged' waiters ping at intermediary points to resolve at a more accurate time.

| Name | Description | Example | | --------- | ---------------------------------------------------- | ----------------------------------------------- | | wait | Standard wait promise (using setTimeout) | minutes(2) = in 2 minutes | | waitFor | Accurate (pinged) wait the given ms | minutes(2) = in 2 minutes | | waitUntil | Accurate (pinged) wait until given time | Date.now() + minutes(2) = in 2 minutes | | waitEvery | Accurate (pinged) wait for next 'every X' event | hours(1) = next full hour (e.g. 17:00, 22:00) | | interval | Accurate (pinged) interval for every 'every X' event | hours(1) = every hour, on the hour |

wait

wait(time: ms): Promise<unknown>
waiters.wait(time: ms): Promise<unknown>

Standard wait promise (using setTimeout)

import { wait } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await wait(minutes(2));
console.log(new Date().toTimeString()); // 12:32:10

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | time | Yes | ms |

| Return Type | |--------------------| | Promise<unknown> |

waitUntil

waitUntil(time: ms): Promise<null>
waiters.waitUntil(time: ms): Promise<null>

Accurate (pinged) wait until given time

import { waitUntil } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await waitUntil(Date.now() + minutes(10));
console.log(new Date().toTimeString()); // 12:40:10

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | time | Yes | ms |

| Return Type | |-----------------| | Promise<null> |

waitFor

waitFor(time: ms): Promise<null>
waiters.waitFor(time: ms): Promise<null>

Accurate (pinged) wait the given ms

import { waitFor } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await waitFor(minutes(5));
console.log(new Date().toTimeString()); // 12:35:10

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | time | Yes | ms |

| Return Type | |-----------------| | Promise<null> |

waitEvery

waitEvery(timing: ms, offset: ms): Promise<null>
waiters.waitEvery(timing: ms, offset: ms): Promise<null>

Accurate (pinged) wait for next 'every X' event

import { waitEvery } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
await waitEvery(hours(2));
console.log(new Date().toTimeString()); // 14:00:00

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | timing | Yes | ms | | 1 | offset | No | ms |

| Return Type | |-----------------| | Promise<null> |

stopInterval

stopInterval(intID: number): void
waiters.stopInterval(intID: number): void
import { interval, stopInterval } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
interval((intID, count) => {
  console.log(new Date().toTimeString()); // 13:00:00, 14:00:00, 15:00:00
  if (count === 3) {
    stopInterval(intID);
  }
}, hours(1));

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | intID | Yes | number |

| Return Type | |-------------| | void |

interval

interval(action: (intID?: number, count?: number) => any, timing: ms): number
waiters.interval(action: (intID?: number, count?: number) => any, timing: ms): number

Accurate (pinged) interval for every 'every X' event

import { interval, stopInterval } from 'swiss-ak';

console.log(new Date().toTimeString()); // 12:30:10
interval((intID, count) => {
  console.log(new Date().toTimeString()); // 13:00:00, 14:00:00, 15:00:00
  if (count === 3) {
    stopInterval(intID);
  }
}, hours(1));

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------------------------------------------| | 0 | action | Yes | (intID?: number, count?: number) => any | | 1 | timing | Yes | ms |

| Return Type | |-------------| | number |

fn

A collection of useful higher-order functions.

noop

fn.noop(): void

No operation. Do nothing, return nothing.

const run = condition ? doSomething : fn.noop;
run();

| Return Type | |-------------| | void |

noact

fn.noact(item: T): T

No action. Returns the first argument it receives.

const items = stuff
  .map(condition ? mapSomething : fn.noact)

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | No | T |

| Return Type | |-------------| | T |

result

fn.result(item: T): () => T

Returns a function that returns the first argument.

const items = stuff
  .filter(condition ? mapSomething : fn.result(true))

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | No | T |

| Return Type | |-------------| | () => T |

resolve

fn.resolve(item: T): () => Promise<T>

Returns an async function that resolves to the first argument

Like fn.result, but wrapped in a Promise

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | No | T |

| Return Type | |--------------------| | () => Promise<T> |

reject

fn.reject(item: T): () => Promise<T>

Returns an async function that rejects with the first argument

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | No | T |

| Return Type | |--------------------| | () => Promise<T> |

filters

fn.filters;

Collection of functions that can be used with Array.filter

exists

fn.exists(item: T): boolean
fn.filters.exists(item: T): boolean
filters.exists(item: T): boolean

Returns true if item isn't null or undefined.

[null, 1, undefined, 2].filter(fn.exists); // [1, 2]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------| | boolean |

isTruthy

fn.isTruthy(item: T): boolean
fn.filters.isTruthy(item: T): boolean
filters.isTruthy(item: T): boolean

Returns true if item is truthy.

[0, 1, 2].filter(fn.isTruthy); // [1, 2]
['', 'a', 'b'].filter(fn.isTruthy); // ['a', 'b']

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------| | boolean |

isFalsy

fn.isFalsy(item: T): boolean
fn.filters.isFalsy(item: T): boolean
filters.isFalsy(item: T): boolean

Returns true if item is falsy.

[0, 1, 2].filter(fn.isFalsy); // [0]
['', 'a', 'b'].filter(fn.isFalsy); // ['']

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------| | boolean |

isEmpty

fn.isEmpty(item: T[] | string): boolean
fn.filters.isEmpty(item: T[] | string): boolean
filters.isEmpty(item: T[] | string): boolean

Returns true if item's length is 0

['', 'a', 'b'].filter(fn.isEmpty); // ['']
[[], [1], [2]].filter(fn.isEmpty); // [[]]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:----------------| | 0 | item | Yes | T[] \| string |

| Return Type | |-------------| | boolean |

isNotEmpty

fn.isNotEmpty(item: T[] | string): boolean
fn.filters.isNotEmpty(item: T[] | string): boolean
filters.isNotEmpty(item: T[] | string): boolean

Returns true if item's length is 1 or more

['', 'a', 'b'].filter(fn.isNotEmpty); // ['a', 'b']
[[], [1], [2]].filter(fn.isNotEmpty); // [[1], [2]]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:----------------| | 0 | item | Yes | T[] \| string |

| Return Type | |-------------| | boolean |

isEqual

fn.isEqual(item: T): (other: T) => boolean
fn.filters.isEqual(item: T): (other: T) => boolean
filters.isEqual(item: T): (other: T) => boolean

Returns a function that returns true if the item is equal to provided value.

[0, 1, 2].filter(fn.isEqual(1)); // [1]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------------------| | (other: T) => boolean |

isNotEqual

fn.isNotEqual(item: T): (other: T) => boolean
fn.filters.isNotEqual(item: T): (other: T) => boolean
filters.isNotEqual(item: T): (other: T) => boolean

Returns a function that returns true if the item is not equal to provided value.

[0, 1, 2].filter(fn.isNotEqual(1)); // [0, 2]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------------------| | (other: T) => boolean |

dedupe

fn.dedupe(item: T, index: number, array: T[]): boolean
fn.filters.dedupe(item: T, index: number, array: T[]): boolean
filters.dedupe(item: T, index: number, array: T[]): boolean

Removes duplicate items from an array.

[0, 1, 2, 1, 0].filter(fn.dedupe); // [0, 1, 2]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | item | Yes | T | | 1 | index | Yes | number | | 2 | array | Yes | T[] |

| Return Type | |-------------| | boolean |

dedupeMapped

fn.dedupeMapped(mapFn: (value?: T, index?: number, array?: T[]) => U): (item: T, index: number, array: T[]) => boolean
fn.filters.dedupeMapped(mapFn: (value?: T, index?: number, array?: T[]) => U): (item: T, index: number, array: T[]) => boolean
filters.dedupeMapped(mapFn: (value?: T, index?: number, array?: T[]) => U): (item: T, index: number, array: T[]) => boolean

Removes duplicate items from an array based on a mapped value.

[2, 4, 6, 8, 10, 12].filter(fn.dedupeMapped((v) => v % 3)); // [ 2, 4, 6 ] (maps to [ 2, 1, 0, 2, 1, 0 ])

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------------------------------------------------| | 0 | mapFn | Yes | (value?: T, index?: number, array?: T[]) => U |

| Return Type | |---------------------------------------------------| | (item: T, index: number, array: T[]) => boolean |

maps

fn.maps;

Collection of functions that can be used with Array.map

toString

fn.toString(item: T): string
fn.maps.toString(item: T): string
maps.toString(item: T): string

Maps the item to a string.

[0, 1, 2].map(fn.toString); // ['0', '1', '2']

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------| | string |

toNumber

fn.toNumber(item: T): number
fn.maps.toNumber(item: T): number
maps.toNumber(item: T): number

Maps the item to a number.

['0', '1', '2'].map(fn.toNumber); // [0, 1, 2]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------| | number |

toBool

fn.toBool(item: T): boolean
fn.maps.toBool(item: T): boolean
maps.toBool(item: T): boolean

Maps the item to a boolean.

[0, 1, 2].map(fn.toBool); // [false, true, true]
['true', 'false', '', 'text'].map(fn.toBool); // [true, false, false, true]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | item | Yes | T |

| Return Type | |-------------| | boolean |

toProp

fn.toProp(prop: string | number): (item: O) => P
fn.maps.toProp(prop: string | number): (item: O) => P
maps.toProp(prop: string | number): (item: O) => P

Maps the item to a given property of the item

[{name: 'Jack'}, {name: 'Jill'}].map(fn.toProp('name')); // ['Jack', 'Jill']

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-------------------| | 0 | prop | Yes | string \| number |

| Return Type | |------------------| | (item: O) => P |

toFixed

fn.toFixed(precision: number): (num: number) => number
fn.maps.toFixed(precision: number): (num: number) => number
maps.toFixed(precision: number): (num: number) => number

Map the items (numbers) of an array to a fixed precision.

[1.234, 5.678, 9.012].map(fn.toFixed(2)); // [1.23, 5.68, 9.01]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | precision | Yes | number |

| Return Type | |---------------------------| | (num: number) => number |

sorts

fn.sorts;

Collection of functions that can be used with Array.sort

asc

fn.asc(a: any, b: any): number
fn.sorts.asc(a: any, b: any): number
sorts.asc(a: any, b: any): number

Sort ascending.

[2, 4, 3, 1].sort(fn.asc); // [1, 2, 3, 4]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------| | 0 | a | Yes | any | | 1 | b | Yes | any |

| Return Type | |-------------| | number |

desc

fn.desc(a: any, b: any): number
fn.sorts.desc(a: any, b: any): number
sorts.desc(a: any, b: any): number

Sort descending.

[2, 4, 3, 1].sort(fn.asc); // [4, 3, 2, 1]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------| | 0 | a | Yes | any | | 1 | b | Yes | any |

| Return Type | |-------------| | number |

byProp

fn.byProp(propName: string | number, sortFn: SortFn<T>): SortFn<O>
fn.sorts.byProp(propName: string | number, sortFn: SortFn<T>): SortFn<O>
sorts.byProp(propName: string | number, sortFn: SortFn<T>): SortFn<O>

Sort by a given property.

const people = [{age: 2}, {age: 4}, {age: 3}, {age: 1}];
people.sort(fn.byProp('age', fn.asc)); // [{age: 1}, {age: 2}, {age: 3}, {age: 4}]

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:-------------------|:--------| | 0 | propName | Yes | string \| number | | | 1 | sortFn | No | SortFn<T> | asc |

| Return Type | |-------------| | SortFn<O> |

nearestTo

fn.nearestTo(target: T): (a: any, b: any) => number
fn.sorts.nearestTo(target: T): (a: any, b: any) => number
sorts.nearestTo(target: T): (a: any, b: any) => number

Sort by the nearest value to the given value.

Values get converted to numbers before comparison.

const people = [2, 4, 3, 1];
people.sort(fn.nearestTo(3)); // [3, 2, 4, 1]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | target | Yes | T |

| Return Type | |------------------------------| | (a: any, b: any) => number |

furthestFrom

fn.furthestFrom(target: T): (a: any, b: any) => number
fn.sorts.furthestFrom(target: T): (a: any, b: any) => number
sorts.furthestFrom(target: T): (a: any, b: any) => number

Sort by the furthest value to the given value.

const people = [2, 4, 3, 1];
people.sort(fn.furthestFrom(3)); // [1, 2, 4, 3]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | target | Yes | T |

| Return Type | |------------------------------| | (a: any, b: any) => number |

array

fn.array(sortFn: SortFn<T>): (a: T[], b: T[]) => number
fn.sorts.array(sortFn: SortFn<T>): (a: T[], b: T[]) => number
sorts.array(sortFn: SortFn<T>): (a: T[], b: T[]) => number

Sort an array of arrays by the given sort function.

Sorts by the first item in the array, then the second, etc. until a non-zero result is found.

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:------------|:--------| | 0 | sortFn | No | SortFn<T> | asc |

| Return Type | |------------------------------| | (a: T[], b: T[]) => number |

arrayAsc

fn.arrayAsc;
fn.sorts.arrayAsc;
sorts.arrayAsc;

Sort an array of arrays in ascending order

Sorts by the first item in the array, then the second, etc. until a non-zero result is found.

arrayDesc

fn.arrayDesc;
fn.sorts.arrayDesc;
sorts.arrayDesc;

Sort an array of arrays in descending order

Sorts by the first item in the array, then the second, etc. until a non-zero result is found.

reduces

fn.reduces;

Collection of functions that can be used with Array.reduce

combine

fn.combine(a: T, b: T): T
fn.reduces.combine(a: T, b: T): T
reduces.combine(a: T, b: T): T

Adds or concats the items

[1, 2, 3].reduce(fn.combine); // 6
['a', 'b', 'c'].reduce(fn.combine); // 'abc'

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | a | Yes | T | | 1 | b | Yes | T |

| Return Type | |-------------| | T |

combineProp

fn.combineProp(propName: string | number): (a: O | T, b: O) => T
fn.reduces.combineProp(propName: string | number): (a: O | T, b: O) => T
reduces.combineProp(propName: string | number): (a: O | T, b: O) => T

Adds or concats the given property of the items

const people = [{name: 'a', age: 1}, {name: 'b', age: 2}, {name: 'c', age: 3}];
people.reduce(fn.combineProp('age')); // 6
people.reduce(fn.combineProp('name')); // 'abc'

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-------------------| | 0 | propName | Yes | string \| number |

| Return Type | |--------------------------| | (a: O \| T, b: O) => T |

mode

fn.mode(prev: T, curr: T, index: number, arr: T[]): T
fn.reduces.mode(prev: T, curr: T, index: number, arr: T[]): T
reduces.mode(prev: T, curr: T, index: number, arr: T[]): T

Returns the most common value in an array.

[1, 2, 3, 2, 1, 1].reduce(fn.mode); // 1

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | prev | Yes | T | | 1 | curr | Yes | T | | 2 | index | Yes | number | | 3 | arr | Yes | T[] |

| Return Type | |-------------| | T |

modeMapped

fn.modeMapped(mapFn: (value: T, index: number, array: T[]) => U): (prev: T, curr: T, index: number, arr: T[]) => T
fn.reduces.modeMapped(mapFn: (value: T, index: number, array: T[]) => U): (prev: T, curr: T, index: number, arr: T[]) => T
reduces.modeMapped(mapFn: (value: T, index: number, array: T[]) => U): (prev: T, curr: T, index: number, arr: T[]) => T

Returns the most common value in an array, based on a given map function.

[2, 4, 6, 8, 9, 12].reduce(fn.modeMapped((v) => v % 3)); // 6 (maps to [ 2, 1, 0, 2, 0, 0 ])

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------------------------------------------| | 0 | mapFn | Yes | (value: T, index: number, array: T[]) => U |

| Return Type | |----------------------------------------------------| | (prev: T, curr: T, index: number, arr: T[]) => T |

everys

fn.everys;

Collection of functions that can be used with Array.every

isAllEqual

fn.isAllEqual(val: T, i: number, arr: T[]): boolean
fn.everys.isAllEqual(val: T, i: number, arr: T[]): boolean
everys.isAllEqual(val: T, i: number, arr: T[]): boolean

Returns if all the items are equal to one another.

[1, 1, 1].every(fn.isAllEqual); // true
[1, 2, 1].every(fn.isAllEqual); // false

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | val | Yes | T | | 1 | i | Yes | number | | 2 | arr | Yes | T[] |

| Return Type | |-------------| | boolean |

isUnique

fn.isUnique(val: T, i: number, arr: T[]): boolean
fn.everys.isUnique(val: T, i: number, arr: T[]): boolean
everys.isUnique(val: T, i: number, arr: T[]): boolean

Returns true if the item is unique in the array.

[1, 1, 1].every(fn.isUnique); // false
[1, 2, 1].every(fn.isUnique); // false
[1, 2, 3].every(fn.isUnique); // true

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | val | Yes | T | | 1 | i | Yes | number | | 2 | arr | Yes | T[] |

| Return Type | |-------------| | boolean |

groups

fn.groups;

Collection of functions that can be used with ArrayTools.group

bySize

fn.bySize(size: number): (value: T, index: number, array: T[]) => number
fn.groups.bySize(size: number): (value: T, index: number, array: T[]) => number
groups.bySize(size: number): (value: T, index: number, array: T[]) => number

Group an array into groups of a given size.

Note: The last group may be smaller than the given size.

Note: The groups a distributed in order, so the first group will be filled up first, then the next, etc.

const nums = [1, 2, 3, 4, 5, 6, 7, 8];
ArrayTools.group(nums, fn.bySize(3)); // [[1, 2, 3], [4, 5, 6], [7, 8]]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | size | Yes | number |

| Return Type | |---------------------------------------------------| | (value: T, index: number, array: T[]) => number |

byNumGroups

fn.byNumGroups(numGroups: number): (value: T, index: number, array: T[]) => any
fn.groups.byNumGroups(numGroups: number): (value: T, index: number, array: T[]) => any
groups.byNumGroups(numGroups: number): (value: T, index: number, array: T[]) => any

Group an array into a certain number of groups as evenly as possible.

Note: The groups a distributed in order, so the first group will be filled up first, then the next, etc.

const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ArrayTools.group(nums, byNumGroups(3)); // [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | numGroups | Yes | number |

| Return Type | |------------------------------------------------| | (value: T, index: number, array: T[]) => any |

ArrayTools

A collection of useful array functions.

create

create(length: number, value: T): T[]
ArrayTools.create(length: number, value: T): T[]

Create an array of the given length, where each value is the given value

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:---------|:---------| | 0 | length | No | number | 1 | | 1 | value | No | T | 1 as T |

| Return Type | |-------------| | T[] |

filled

filled(length: number, value: T): T[]
ArrayTools.filled(length: number, value: T): T[]

Create an array of the given length, where each value is the given value

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:---------|:--------| | 0 | length | No | number | 1 | | 1 | value | Yes | T | |

| Return Type | |-------------| | T[] |

range

range(length: number, multiplier: number, offset: number): number[]
ArrayTools.range(length: number, multiplier: number, offset: number): number[]

Returns an array of the given length, where each value is equal to it's index e.g. [0, 1, 2, ..., length]

ArrayTools.range(3);  // [0, 1, 2]
ArrayTools.range(5);  // [0, 1, 2, 3, 4]
ArrayTools.range(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

ArrayTools.range(3, 2);  // [0, 2, 4]
ArrayTools.range(5, 2);  // [0, 2, 4, 6, 8]
ArrayTools.range(10, 10); // [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:---------|:--------| | 0 | length | No | number | 1 | | 1 | multiplier | No | number | 1 | | 2 | offset | No | number | 0 |

| Return Type | |-------------| | number[] |

zip

zip(...arrs: T[]): ZippedArrays<T>[]
ArrayTools.zip(...arrs: T[]): ZippedArrays<T>[]

Converts multiple arrays into an array of 'tuples' for each value at the corresponding indexes.

Limited to the length of the shortest provided array

Inspired by python's 'zip'

ArrayTools.zip([1, 2, 3, 4], ['a', 'b', 'c']); // [ [1, 'a'], [2, 'b'], [3, 'c'] ]

| # | Parameter Name | Required | Type | |:----:|:---------------|:---------|:------| | 0… | arrs | No | T[] |

| Return Type | |---------------------| | ZippedArrays<T>[] |

zipMax

zipMax(...arrs: T[]): ZippedArrays<T>[]
ArrayTools.zipMax(...arrs: T[]): ZippedArrays<T>[]

Converts multiple arrays into an array of 'tuples' for each value at the corresponding indexes.

Unlike zip, it will match the length of the longest provided array, filling in any missing values with undefined

Inspired by python's 'zip'

ArrayTools.zipMax([1, 2, 3, 4], ['a', 'b', 'c']); //[ [ 1, 'a' ], [ 2, 'b' ], [ 3, 'c' ], [ 4, undefined ] ]

| # | Parameter Name | Required | Type | |:----:|:---------------|:---------|:------| | 0… | arrs | No | T[] |

| Return Type | |---------------------| | ZippedArrays<T>[] |

sortByMapped

sortByMapped(arr: T[], mapFn: (value: T, index: number, array: T[]) => M, sortFn: (a: M, b: M) => number): T[]
ArrayTools.sortByMapped(arr: T[], mapFn: (value: T, index: number, array: T[]) => M, sortFn: (a: M, b: M) => number): T[]

Sort an array by a mapped form of the values, but returning the initial values

ArrayTools.sortByMapped(['2p', '3p', '1p'], (v) => Number(v.replace('p', ''))); // ['1p', '2p', '3p']
ArrayTools.sortByMapped(
  ['2p', '3p', '1p'],
  (v) => Number(v.replace('p', '')),
  (a, b) => b - a
); // ['3p', '2p', '1p']

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:---------------------------------------------|:---------| | 0 | arr | Yes | T[] | | | 1 | mapFn | Yes | (value: T, index: number, array: T[]) => M | | | 2 | sortFn | No | (a: M, b: M) => number | fn.asc |

| Return Type | |-------------| | T[] |

randomise

randomise(arr: T[]): T[]
ArrayTools.randomise(arr: T[]): T[]

Returns a clone of the provided array with it's items in a random order

ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 5, 3, 4, 1, 2, 6 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 5, 1, 3, 2, 4, 6 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 6, 1, 4, 5, 2, 3 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 1, 4, 5, 2, 3, 6 ]
ArrayTools.randomise([1, 2, 3, 4, 5, 6]); // [ 2, 6, 1, 3, 4, 5 ]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------| | 0 | arr | Yes | T[] |

| Return Type | |-------------| | T[] |

reverse

reverse(arr: T[]): T[]
ArrayTools.reverse(arr: T[]): T[]

Returns a new array with the order reversed without affecting original array

const arr1 = [1, 2, 3];
arr1            // [1, 2, 3]
arr1.reverse(); // [3, 2, 1]
arr1            // [3, 2, 1]

const arr2 = [1, 2, 3];
arr2            // [1, 2, 3]
ArrayTools.reverse(arr2);  // [3, 2, 1]
arr2            // [1, 2, 3]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------| | 0 | arr | Yes | T[] |

| Return Type | |-------------| | T[] |

entries

entries(arr: T[]): [number, T][]
ArrayTools.entries(arr: T[]): [number, T][]

Returns array of 'tuples' of index/value pairs

const arr = ['a', 'b', 'c'];
ArrayTools.entries(arr); // [ [0, 'a'], [1, 'b'], [2, 'c'] ]

for (let [index, value] of entries(arr)) {
 console.log(index); // 0, 1, 2
 console.log(value); // 'a', 'b', 'c'
}

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------| | 0 | arr | Yes | T[] |

| Return Type | |-----------------| | [number, T][] |

repeat

repeat(maxLength: number, ...items: T[]): T[]
ArrayTools.repeat(maxLength: number, ...items: T[]): T[]

Returns an array with the given items repeated

ArrayTools.repeat(5, 'a'); // [ 'a', 'a', 'a', 'a', 'a' ]
ArrayTools.repeat(5, 'a', 'b'); // [ 'a', 'b', 'a', 'b', 'a' ]

| # | Parameter Name | Required | Type | |:----:|:---------------|:---------|:---------| | 0 | maxLength | Yes | number | | 1… | items | No | T[] |

| Return Type | |-------------| | T[] |

roll

roll(distance: number, arr: T[]): T[]
ArrayTools.roll(distance: number, arr: T[]): T[]

'Roll' the array by a given amount so that is has a new first item. Length and contents remain the same, but the order is changed

ArrayTools.roll(1, [0, 1, 2, 3, 4, 5, 6, 7]); // [ 1, 2, 3, 4, 5, 6, 7, 0 ]
ArrayTools.roll(4, [0, 1, 2, 3, 4, 5, 6, 7]); // [ 4, 5, 6, 7, 0, 1, 2, 3 ]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | distance | Yes | number | | 1 | arr | Yes | T[] |

| Return Type | |-------------| | T[] |

sortNumberedText

sortNumberedText(texts: string[], ignoreCase: boolean): string[]
ArrayTools.sortNumberedText(texts: string[], ignoreCase: boolean): string[]

Alphabetically sorts a list of strings, but keeps multi-digit numbers in numerical order (rather than alphabetical)

const names = ['name1', 'name10', 'name2', 'foo20', 'foo10', 'foo9'];
names.sort(); // [ 'foo10', 'foo20', 'foo9', 'name1', 'name10', 'name2' ]
ArrayTools.sortNumberedText(names); // [ 'foo9', 'foo10', 'foo20', 'name1', 'name2', 'name10' ]

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:-----------|:--------| | 0 | texts | Yes | string[] | | | 1 | ignoreCase | No | boolean | true |

| Return Type | |-------------| | string[] |

partition

partition(array: T[], partitionSize: number): T[][]
ArrayTools.partition(array: T[], partitionSize: number): T[][]

Breaks an array into smaller arrays of a given size

ArrayTools.partition([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3); // [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ], [ 10 ] ]

| # | Parameter Name | Required | Type | Default | |:---:|:----------------|:---------|:---------|:------------------------------| | 0 | array | Yes | T[] | | | 1 | partitionSize | No | number | Math.ceil(array.length / 2) |

| Return Type | |-------------| | T[][] |

groupObj

groupObj(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): { [id: string]: T[]; [id: number]: T[]; }
ArrayTools.groupObj(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): { [id: string]: T[]; [id: number]: T[]; }

Group items from an array into an object of arrays, based on a given map function.

const arr = [
  { group: 1, name: 'a' },
  { group: 2, name: 'b' },
  { group: 1, name: 'c' },
];
ArrayTools.groupObj(arr, item => item.group); // {
//   1: [ { group: 1, name: 'a' }, { group: 1, name: 'c' } ],
//   2: [ { group: 2, name: 'b' } ]
// }

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------------------------------------------------------| | 0 | array | Yes | T[] | | 1 | mapFn | Yes | (item: T, index: number, arr: T[]) => string \| number |

| Return Type | |---------------------------------------------| | { [id: string]: T[]; [id: number]: T[]; } |

group

group(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): T[][]
ArrayTools.group(array: T[], mapFn: (item: T, index: number, arr: T[]) => string | number): T[][]

Group items from an array into an array of arrays, based on a given map function.

const arr = [
  { group: 1, name: 'a' },
  { group: 2, name: 'b' },
  { group: 1, name: 'c' },
];
ArrayTools.group(arr, item => item.group); // [
//   [ { group: 1, name: 'a' }, { group: 1, name: 'c' } ],
//   [ { group: 2, name: 'b' } ]
// ]

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------------------------------------------------------| | 0 | array | Yes | T[] | | 1 | mapFn | Yes | (item: T, index: number, arr: T[]) => string \| number |

| Return Type | |-------------| | T[][] |

findAndRemove

ArrayTools.findAndRemove(array: T[], predicate: (item: T, index: number, arr: T[]) => any, ...insertItems: T[]): T

Find the first item in an array that matches a given predicate, and remove it from the array

Note: This function mutates the provided array

| # | Parameter Name | Required | Type | Description | |:----:|:---------------|:---------|:--------------------------------------------|:------------------------------------------------------------------| | 0 | array | Yes | T[] | the array to mutate | | 1 | predicate | Yes | (item: T, index: number, arr: T[]) => any | a function that returns true/truthy if the item should be removed | | 2… | insertItems | No | T[] | items to insert in place of the removed item |

| Return Type | | |-------------|---------------------------------------| | T | removed item (undefined if not found) |

findLastAndRemove

ArrayTools.findLastAndRemove(array: T[], predicate: (item: T, index: number, arr: T[]) => any, ...insertItems: T[]): T

Find the last item in an array that matches a given predicate, and remove it from the array

Note: This function mutates the provided array

| # | Parameter Name | Required | Type | Description | |:----:|:---------------|:---------|:--------------------------------------------|:------------------------------------------------------------------| | 0 | array | Yes | T[] | the array to mutate | | 1 | predicate | Yes | (item: T, index: number, arr: T[]) => any | a function that returns true/truthy if the item should be removed | | 2… | insertItems | No | T[] | items to insert in place of the removed item |

| Return Type | | |-------------|---------------------------------------| | T | removed item (undefined if not found) |

filterAndRemove

ArrayTools.filterAndRemove(array: T[], predicate: (item: T, index: number, arr: T[]) => any): T[]

Find the items in an array that matches a given predicate, and remove them from the array

Note: This function mutates the provided array

| # | Parameter Name | Required | Type | Description | |:---:|:---------------|:---------|:--------------------------------------------|:------------------------------------------------------------------| | 0 | array | Yes | T[] | the array to mutate | | 1 | predicate | Yes | (item: T, index: number, arr: T[]) => any | a function that returns true/truthy if the item should be removed |

| Return Type | | |-------------|---------------| | T[] | removed items |

utils

ArrayTools.utils;

Small helper functions that may help, but aren't important enough to be in ArrayTools directly

isNumString

ArrayTools.utils.isNumString(text: string): boolean

Returns true if the given string is a number

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | text | Yes | string |

| Return Type | |-------------| | boolean |

partitionNums

ArrayTools.utils.partitionNums(ignoreCase: boolean): (name: string) => (string | number)[]

Splits a string into an array of strings and numbers

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:----------| | 0 | ignoreCase | Yes | boolean |

| Return Type | |------------------------------------------| | (name: string) => (string \| number)[] |

ObjectTools

A collection of functions for working with objects

remodel

ObjectTools.remodel(obj: T, func: (entries: [string, V][]) => [string, W][]): O

Apply a function to the entries of an object

const input = {'foo': 2, 'bar': 1, 'baz': 4}
ObjectTools.remodel(input, (entries) => entries.filter(([k, v]) => v % 2 === 0)) // { foo: 2, baz: 4 }

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:--------------------------------------------| | 0 | obj | Yes | T | | 1 | func | Yes | (entries: [string, V][]) => [string, W][] |

| Return Type | |-------------| | O |

remodelEach

ObjectTools.remodelEach(obj: T, func: (entry: [string, V], index: number, entries: [string, V][]) => [string, W]): O

Apply a function to each of the entries of an object

Note: similar to ObjectTools.map, but the function parameters are different. Prefer ObjectTools.map where possible.

const input = {'foo': 2, 'bar': 1, 'baz': 4}
ObjectTools.remodelEach(input, ([k, v]) => [k, v * 2]) // { foo: 4, bar: 2, baz: 8 }

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----------------------------------------------------------------------------| | 0 | obj | Yes | T | | 1 | func | Yes | (entry: [string, V], index: number, entries: [string, V][]) => [string, W] |

| Return Type | |-------------| | O |

map

ObjectTools.map(obj: T, func: (key: string, value: V, index: number) => [string, W]): any

Maps the keys and values of an object in a similar way to Array.map

ObjectTools.map({a: 1, b: 2, c: 3}, (key, value) => [key, key + value]); // {a: 'a1', b: 'b2', c: 'c3'}

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:--------------------------------------------------------| | 0 | obj | Yes | T | | 1 | func | Yes | (key: string, value: V, index: number) => [string, W] |

| Return Type | |-------------| | any |

mapValues

ObjectTools.mapValues(obj: T, func: (key: string, value: V, index: number) => W): any

Maps the values of an object in a similar way to Array.map

ObjectTools.map({a: 1, b: 2, c: 3}, (key, value) => key.repeat(value)); // {a: 'a', b: 'bb', c: 'ccc'}

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:----------------------------------------------| | 0 | obj | Yes | T | | 1 | func | Yes | (key: string, value: V, index: number) => W |

| Return Type | |-------------| | any |

mapKeys

ObjectTools.mapKeys(obj: T, func: (key: string, value: V, index: number) => string): T

Maps the values of an object in a similar way to Array.map

ObjectTools.map({a: 1, b: 2, c: 3}, (key, value) => key.repeat(value)); // {a: 1, bb: 2, ccc: 3}

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------------------------------------------------| | 0 | obj | Yes | T | | 1 | func | Yes | (key: string, value: V, index: number) => string |

| Return Type | |-------------| | T |

filter

ObjectTools.filter(obj: T, func: (key: string, value: V, index: number) => boolean): O

Removes entries from an object based on a predicate function

ObjectTools.filter({a: 1, b: 2, c: 3}, (k, v) => v % 2 === 0) // { b: 2 }

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:----------------------------------------------------| | 0 | obj | Yes | T | | 1 | func | Yes | (key: string, value: V, index: number) => boolean |

| Return Type | |-------------| | O |

clean

ObjectTools.clean(obj: T): O

Removes properties with undefined values

ObjectTools.clean({a: 1, b: undefined, c: 3}) // { a: 1, c: 3 }

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | obj | Yes | T |

| Return Type | |-------------| | O |

invert

ObjectTools.invert(obj: Ti): To

Inverts the keys and values of an object

ObjectTools.invert({ a: 'foo', b: 'bar' }); // { foo: 'a', bar: 'b'}

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:-----| | 0 | obj | Yes | Ti |

| Return Type | |-------------| | To |

StringTools

A collection of string utilities

capitalise

StringTools.capitalise(input: string, forceRestToLowerCase: boolean): string

Capitalises the first letter of each word in a string

StringTools.capitalise('hello world'); // 'Hello World'

| # | Parameter Name | Required | Type | Default | |:---:|:-----------------------|:---------|:----------|:--------| | 0 | input | No | string | '' | | 1 | forceRestToLowerCase | No | boolean | true |

| Return Type | |-------------| | string |

angloise

StringTools.angloise(input: string): string

Remove accents from a string

StringTools.angloise('éèêë'); // 'eeee'

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | input | Yes | string |

| Return Type | |-------------| | string |

clean

StringTools.clean(input: string): string

Remove accents and non alphanumerics from a string

StringTools.clean('éèêë_--ab0'); // 'eeeeab0'

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:---------|:--------| | 0 | input | No | string | '' |

| Return Type | |-------------| | string |

repeat

StringTools.repeat(maxLength: number, repeated: string): string

Repeat the given string n times

StringTools.repeat(5, '-') // '-----'
StringTools.repeat(1, '-') // '-'
StringTools.repeat(0, '-') // ''
StringTools.repeat(-1, '-') // ''

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | maxLength | Yes | number | | 1 | repeated | Yes | string |

| Return Type | |-------------| | string |

makeRegExpSafe

StringTools.makeRegExpSafe(text: string): string

Makes a string safe to use in a RegExp

const textWithSpecChars = '$^*+?.()|{}[]\\';
const longText = `A long line with ${textWithSpecChars} in it`; // 'A long line with $^*+?.()|{}[]\ in it'

const safeText = makeRegExpSafe(textWithSpecChars); // '\$\^\*\+\?\.\(\)\|\{\}\[\]\\'
const regex = new RegExp(safeText);
longText.replace(regex, 'foobar'); // 'A long line with foobar in it'

longText.replace(new RegExp(makeRegExpSafe(textWithSpecChars)), 'foobar'); // 'A long line with foobar in it'

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:---------| | 0 | text | Yes | string |

| Return Type | |-------------| | string |

replaceAll

StringTools.replaceAll(text: string, searchValue: string | RegExp, replacer: string | ((substring: string, ...args: any[]) => string)): string

'Polyfill' replacement for String.prototype.replaceAll, but uses String.prototype.replace (better backwards compatibility)

Accepts a string or RegExp as the searchValue, and a string or function as the replacer.

const input = 'the quick brown fox jumps over the lazy dog';

StringTools.replaceAll(input, /A|E|I|O|U/i, (match) => match.toUpperCase()) // 'thE qUIck brOwn fOx jUmps OvEr thE lAzy dOg'
StringTools.replaceAll(input, /A|E|I|O|U/i, '#') // 'th# q##ck br#wn f#x j#mps #v#r th# l#zy d#g'
StringTools.replaceAll(input, 'o', (match) => match.toUpperCase()) // 'the quick brOwn fOx jumps Over the lazy dOg'
StringTools.replaceAll(input, 'o', '#') // 'the quick br#wn f#x jumps #ver the lazy d#g'

| # | Parameter Name | Required | Type | |:---:|:---------------|:---------|:------------------------------------------------------------| | 0 | text | Yes | string | | 1 | searchValue | Yes | string \| RegExp | | 2 | replacer | Yes | string \| ((substring: string, ...args: any[]) => string) |

| Return Type | |-------------| | string |

randomId

StringTools.randomId(prefix: string, suffix: string): string

Generate a random ID.

Provides a random string of 10 alphanumeric characters, with the option to prefix and/or suffix the string.

Note: This is a very simple random ID generator, and is not suitable for use in security contexts, and does not guarantee uniqueness.

StringTools.randomId(); // 'du9876optw'
StringTools.randomId(); // '7xf8kewrkf'
StringTools.randomId(); // 'bums15yb9n'
StringTools.randomId(); // '8tcl55y4u1'
StringTools.randomId(); // '41pxan1bog'
StringTools.randomId(); // '122pa9czh4'
StringTools.randomId(); // 'iu7xappxtz'

StringTools.randomId('foo-'); // 'foo-xpynpfiz06'
StringTools.randomId('', '-bar'); // 'dpyq3i2uwq-bar'
StringTools.randomId('foo-', '-bar'); // 'foo-wapluosnf6-bar'

| # | Parameter Name | Required | Type | Default | |:---:|:---------------|:---------|:---------|:--------| | 0 | prefix | No | string | '' | | 1 | suffix | No | string | '' |

| Return Type | |-------------| | string |

clx

clx(...args: ClxType[]): string
StringTools.clx(...args: ClxType[]): string