Skip to content

Helpers ​

Introduction ​

H3ravel includes a number of global framework agnostic "helper" TS functions. Many of these functions are used by the framework itself; however, you are free to use them in your own applications if you find them convenient.

Installation ​

To use these helpers in your application, you may install the @h3ravel/support package by running:

sh
$ npm install @h3ravel/support --save
sh
$ yarn add @h3ravel/support
sh
$ pnpm add @h3ravel/support
sh
$ bun create @h3ravel/support

The @h3ravel/support is installed by default when using H3ravel

Available Methods ​

Array Helpers ​

The Arr class from @h3ravel/support provides a rich set of framework-agnostic utilities for working with JavaScript arrays and objects. Many of these methods mirror Laravel’s Illuminate\Support\Arr, offering familiar behavior with a TypeScript-friendly API.

AccessorsTransformersUtilities
dotarrayboolean
mapchunkcollapse
exceptsortDescisEmpty
isNotEmptyrangereverse
wrapfloatfloat
combinehasonly
crossJoinfirstprepend
divideflattenpull
randomlastshuffle
hasAnysorthasAll
pluckforgetunique
joinwherewhereNotNull
wrapmapWithKeyspush
keyBystringtake

Arr.array ​

The Arr.array method retrieves a value using dot notation, throws if value is not an array

ts
const data = { user: { emails: ['[email protected]', '[email protected]'] } };

Arr.array(data, 'user.emails');
// ['[email protected]', '[email protected]']

Arr.boolean ​

The Arr.boolean method retrieves a value using dot notation, throws if value is not a boolean

ts
const data = { user: { name: 'join', verified: true } };

Arr.boolean(data, 'user.verified');
// true

Arr.has ​

The Arr.has method determines whether a given key exists within an array or object using “dot” notation.

ts
Arr.has({ user: { profile: { name: 'Legacy' } } }, 'user.profile.name');
// true

Arr.first ​

The Arr.first method returns the first element in an array that passes a given truth test. If no callback is provided, the first element in the array is returned.

ts
Arr.first([1, 2, 3, 4], (n) => n > 2);
// 3

Arr.first([], null, 'none');
// 'none'

Arr.float ​

The Arr.float method retrieves a value from an array/object using dot notation, throws if value is not a float

ts
const data = { user: { name: 'join', balance: 1.5 } };

Arr.float(data, 'user.balance');
// 1.5

Arr.from ​

The Arr.from method converts various input types into a plain array Supports Arrays, Objects, Iterables, Map, WeakMap, and custom toArray/toJSON/jsonSerialize methods

ts
const data = { name: 'John', plan: 'Delux' };

Arr.from(data);
// 1[ 'John', 'Delux' ]

Arr.last ​

The Arr.last method returns the last element in an array that passes a given truth test. If no callback is provided, the last element is returned.

ts
Arr.last([1, 2, 3, 4], (n) => n < 3);
// 2

Arr.pluck ​

The Arr.pluck method retrieves all of the values for a given key from an array of objects.

ts
const users = [
  { name: 'Legacy', email: '[email protected]' },
  { name: 'Adajie', email: '[email protected]' },
];

Arr.pluck(users, 'email');
// ['[email protected]', '[email protected]']

Arr.only ​

The Arr.only method returns a new object containing only the specified keys from the original array or object.

ts
Arr.only({ name: 'Legacy', age: 25, role: 'Dev' }, ['name', 'role']);
// { name: 'Legacy', role: 'Dev' }

Arr.except ​

The Arr.except method removes the specified keys from the given object or array.

ts
Arr.except({ name: 'Legacy', age: 25, role: 'Dev' }, ['role']);
// { name: 'Legacy', age: 25 }

Arr.isEmpty ​

The Arr.isEmpty method determines if the given array has no elements or properties.

ts
Arr.isEmpty([]);
// true

Arr.isEmpty ​

The Arr.isNotEmpty method determines if the given array has at least one element or property (not empty).

ts
Arr.isNotEmpty([1, 2, 3]);
// true

Arr.hasAll ​

The Arr.hasAll Checks if an array or object has all the specified keys.

ts
Arr.hasAll({ name: 'Legacy', age: 25 }, ['email', 'name']);
// false

Arr.hasAny ​

The Arr.hasAny method checks if at least one of the specified keys exists in the array or object.

ts
Arr.hasAny({ name: 'Legacy', age: 25 }, ['email', 'name']);
// true

Arr.integer ​

The Arr.integer method retrieves a value from an array/object using dot notation, throws if value is not an integer

ts
const data = { user: { name: 'join', id: 22 } };

Arr.integer(data, 'user.id');
// 1.5

Arr.where ​

The Arr.where method filters the array using the given callback, returning all elements that pass the test.

ts
Arr.where([1, 2, 3, 4], (n) => n > 2);
// [3, 4]

Arr.whereNotNull ​

The Arr.whereNotNull method removes all null and undefined values from an array.

ts
Arr.whereNotNull([1, null, 2, undefined, 3]);
// [1, 2, 3]

Arr.unique ​

The Arr.unique method returns all unique items from an array, preserving order.

ts
Arr.unique([1, 1, 2, 3, 3]);
// [1, 2, 3]

Arr.map ​

The Arr.map method applies a given callback to each item in the array and returns a new array of results.

ts
Arr.map([1, 2, 3], (n) => n * 2);
// [2, 4, 6]

Arr.mapWithKeys ​

The Arr.mapWithKeys method maps each element to a key-value pair.

ts
Arr.mapWithKeys([{ id: 1, name: 'A' }], (x) => [x.id, x.name]);
// { '1': 'A' }

Arr.flatten ​

The Arr.flatten method flattens a multi-dimensional array into a single level. You may specify a depth to control how deep the flattening should go.

ts
Arr.flatten([1, [2, [3, [4]]]], 2);
// [1, 2, 3, [4]]

Arr.collapse ​

The Arr.collapse method flattens an array of arrays into a single array.

ts
Arr.collapse([
  [1, 2],
  [3, 4],
]);
// [1, 2, 3, 4]

Arr.combine ​

The Arr.combine Combine arrays and sum their values element by element.

ts
Arr.combine([10, 1], [5, 25]);
// 41

Arr.divide ​

The Arr.divide method returns two arrays — one containing the keys and the other containing the values.

ts
Arr.divide({ name: 'Legacy', age: 25 });
// [['name', 'age'], ['Legacy', 25]]

Arr.dot ​

The Arr.dot method flattens a multi-dimensional array or object into a single-level object using “dot” notation.

ts
Arr.dot({ user: { profile: { name: 'Legacy' } } });
// { 'user.profile.name': 'Legacy' }

Arr.keyby ​

The Arr.keyby method creates an object indexed by a key or callback function.

ts
Arr.keyBy([{ id: 1 }, { id: 2 }], 'id');
// { '1': {id:1}, '2': {id:2} }

Arr.sort ​

The Arr.sort method sorts an array by its values. If a callback is provided, the callback’s return value determines the sort order.

ts
Arr.sort([3, 1, 2]);
// [1, 2, 3]

Arr.sortDesc ​

The Arr.sortDesc method sorts an array in descending order. Like Arr.sort, you may provide a callback to customize sorting.

ts
Arr.sortDesc([1, 2, 3]);
// [3, 2, 1]

Arr.shuffle ​

The Arr.shuffle method randomly shuffles the items in an array.

ts
Arr.shuffle([1, 2, 3, 4]);
// [3, 1, 4, 2] // random order

Arr.chunk ​

The Arr.chunk method breaks an array into smaller arrays of a given size.

ts
Arr.chunk([1, 2, 3, 4, 5], 2);
// [[1, 2], [3, 4], [5]]

Arr.wrap ​

The Arr.wrap method wraps the given value in an array. If the value is already an array, it is returned unchanged.

ts
Arr.wrap('Legacy');
// ['Legacy']

Arr.random ​

The Arr.random method returns one or more random elements from an array.

ts
Arr.random([1, 2, 3, 4]);
// 3

Arr.random([1, 2, 3, 4], 2);
// [2, 4]

Arr.forget ​

The Arr.forget method removes one or more items from a deeply nested array or object using “dot” notation.

ts
const data = { user: { profile: { name: 'Legacy', age: 25 } } };

Arr.forget(data, 'user.profile.age');
// { user: { profile: { name: 'Legacy' } } }

Arr.pull ​

The Arr.pull method retrieves a value from a given key and then removes it from the array or object.

ts
const data = { name: 'Legacy', age: 25 };

Arr.pull(data, 'age');
// 25
// data => { name: 'Legacy' }

Arr.add ​

The Arr.add method adds a key-value pair to the array if the specified key does not already exist.

ts
Arr.add({ name: 'Legacy' }, 'age', 25);
// { name: 'Legacy', age: 25 }

Arr.prepend ​

The Arr.prepend method adds an item to the beginning of an array, optionally using a key.

ts
Arr.prepend([2, 3], 1);
// [1, 2, 3]

Arr.push ​

The Arr.push method appends a value to the end of the array.

ts
Arr.push([1, 2], 3);
// [1, 2, 3]

Arr.crossJoin ​

The Arr.crossJoin method performs a cross join across multiple arrays, returning all possible combinations.

ts
Arr.crossJoin([1, 2], ['a', 'b']);
// [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]

Arr.range ​

The Arr.range method creates an array containing a range of numbers.

ts
Arr.range(1, 5);
// [1, 2, 3, 4, 5]

Arr.reverse ​

The Arr.reverse method creates a new array in reverse order.

ts
Arr.reverse([1, 2, 3, 4, 5]);
// [5, 4, 3, 1, 1]

Arr.string ​

The Arr.string method retrieves a value using dot notation, throws if value is not a string

ts
const data = { user: { name: 'John', verified: true } };

Arr.string(data, 'user.name');
// 'John'

Arr.take ​

The Arr.take method returns the first N elements of an array

ts
const data = [22, 19, 33, 6, 44];

Arr.take(data, 3);
// [22, 19, 33]

Numbers [DOCS WIP] ​

abbreviate()toHumanTime()toBytes()
humanize()

Paths [DOCS WIP] ​

URLs [DOCS WIP] ​

abbreviate() ​

Abbreviates large numbers using SI symbols (K, M, B, T, P, E) and formats the output according to the specified locale. Perfect for displaying large numbers in dashboards, statistics, and social media counters.

Signature ​

typescript
abbreviate(value?: number, locale?: string): string

Parameters ​

  • value (optional) - The number to abbreviate
  • locale (optional) - Locale string for number formatting (default: "en-US")

Returns ​

string - A localized, abbreviated number string

Abbreviation Scale ​

Value RangeSymbolName
1,000+KThousand
1,000,000+MMillion
1,000,000,000+BBillion
1,000,000,000,000+TTrillion
1,000,000,000,000,000+PPetillion
1,000,000,000,000,000,000+EExillion

Examples ​

Basic Usage ​

typescript
import { abbreviate } from '@h3ravel/support';

abbreviate(500); // "500"
abbreviate(1000); // "1K"
abbreviate(1500); // "1.5K"
abbreviate(1000000); // "1M"
abbreviate(2500000); // "2.5M"
abbreviate(1000000000); // "1B"
abbreviate(7800000000); // "7.8B"

With Different Locales ​

typescript
import { abbreviate } from '@h3ravel/support';

// US English (default)
abbreviate(1234567, 'en-US'); // "1.23M"

// German
abbreviate(1234567, 'de-DE'); // "1,23M"

// French
abbreviate(1234567, 'fr-FR'); // "1,23M"

// Indian English
abbreviate(1234567, 'en-IN'); // "1.23M"

Dashboard Statistics ​

typescript
import { abbreviate } from '@h3ravel/support';

const stats = {
  users: 45678,
  pageViews: 1234567,
  revenue: 9876543,
};

console.log(`Users: ${abbreviate(stats.users)}`); // "Users: 45.68K"
console.log(`Views: ${abbreviate(stats.pageViews)}`); // "Views: 1.23M"
console.log(`Revenue: ${abbreviate(stats.revenue)}`); // "Revenue: 9.88M"

Handling Edge Cases ​

typescript
import { abbreviate } from '@h3ravel/support';

abbreviate(); // "0"
abbreviate(0); // "0"
abbreviate(undefined); // "0"
abbreviate(999); // "999"

humanize() ​

Converts a number into its written word representation. Supports numbers from 0 to 9999 and can optionally format output as a slug.

Signature ​

typescript
humanize(num: number, slugify?: '-' | '_'): string

Parameters ​

  • num - The number to convert (supports 0-9999)
  • slugify (optional) - If provided ('-' or '_'), converts output to lowercase slug format

Returns ​

string - The number written in words (or as a slug if specified)

Examples ​

Basic Usage ​

typescript
import { humanize } from '@h3ravel/support';

humanize(0); // "zero"
humanize(1); // "one"
humanize(15); // "fifteen"
humanize(42); // "forty two"
humanize(100); // "one hundred"
humanize(256); // "two hundred and fifty six"
humanize(1000); // "one thousand"
humanize(1234); // "one thousand two hundred and thirty four"

Small Numbers ​

typescript
import { humanize } from '@h3ravel/support';

humanize(1); // "one"
humanize(5); // "five"
humanize(10); // "ten"
humanize(19); // "nineteen"

Tens and Twenties ​

typescript
import { humanize } from '@h3ravel/support';

humanize(20); // "twenty "
humanize(25); // "twenty five"
humanize(30); // "thirty "
humanize(99); // "ninety nine"

Hundreds ​

typescript
import { humanize } from '@h3ravel/support';

humanize(100); // "one hundred"
humanize(200); // "two hundred"
humanize(350); // "three hundred and fifty "
humanize(999); // "nine hundred and ninety nine"

Thousands ​

typescript
import { humanize } from '@h3ravel/support';

humanize(1000); // "one thousand"
humanize(2000); // "two thousand"
humanize(1050); // "one thousand and fifty "
humanize(5678); // "five thousand six hundred and seventy eight"

Slugified Output ​

typescript
import { humanize } from '@h3ravel/support';

// Using hyphen separator
humanize(42, '-'); // "forty-two"
humanize(100, '-'); // "one-hundred"
humanize(1234, '-'); // "one-thousand-two-hundred-and-thirty-four"

// Using underscore separator
humanize(42, '_'); // "forty_two"
humanize(100, '_'); // "one_hundred"
humanize(1234, '_'); // "one_thousand_two_hundred_and_thirty_four"

Practical Use Cases ​

typescript
import { humanize } from '@h3ravel/support';

// Generate readable IDs
const orderId = humanize(42, '-'); // "forty-two"

// Create URL-friendly routes
const pageNum = 5;
const route = `/page-${humanize(pageNum, '-')}`; // "/page-five"

// Display amounts in words
const quantity = 15;
console.log(`You have ${humanize(quantity)} items`); // "You have fifteen items"

Error Handling ​

typescript
import { humanize } from '@h3ravel/support';

humanize(0); // "zero"

// Negative numbers throw an error
try {
  humanize(-5);
} catch (error) {
  console.error(error.message); // "Negative numbers are not supported."
}

toBytes() ​

Converts a number of bytes into a human-readable file size string. Supports both binary (1024-based) and SI (1000-based) units.

Signature ​

typescript
toBytes(bytes?: number, decimals?: number, bits?: boolean): string

Parameters ​

  • bytes (optional) - The size in bytes to convert
  • decimals (optional) - Number of decimal places to display (default: 2)
  • bits (optional) - If true, uses SI units (1000-based); if false, uses binary units (1024-based) (default: false)

Returns ​

string - A formatted string with the appropriate unit

Unit Systems ​

Binary Units (1024-based) - Default

  • Bytes, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB

SI Units (1000-based) - When bits = true

  • B, KB, MB, GB, TB, PB, EB, ZB, YB

Examples ​

Basic Usage (Binary Units) ​

typescript
import { toBytes } from '@h3ravel/support';

toBytes(0); // "0 Bytes"
toBytes(1024); // "1 KiB"
toBytes(1048576); // "1 MiB"
toBytes(1073741824); // "1 GiB"
toBytes(1099511627776); // "1 TiB"

With Decimal Precision ​

typescript
import { toBytes } from '@h3ravel/support';

toBytes(1536, 2); // "1.5 KiB"
toBytes(1536, 0); // "2 KiB"
toBytes(1536, 3); // "1.500 KiB"
toBytes(2500000, 1); // "2.4 MiB"

SI Units (1000-based) ​

typescript
import { toBytes } from '@h3ravel/support';

toBytes(1000, 2, true); // "1 KB"
toBytes(1000000, 2, true); // "1 MB"
toBytes(1000000000, 2, true); // "1 GB"
toBytes(2500000, 2, true); // "2.5 MB"

File Size Display ​

typescript
import { toBytes } from '@h3ravel/support';

const files = [
  { name: 'document.pdf', size: 2458624 },
  { name: 'image.jpg', size: 524288 },
  { name: 'video.mp4', size: 157286400 },
];

files.forEach((file) => {
  console.log(`${file.name}: ${toBytes(file.size)}`);
});
// Output:
// document.pdf: 2.34 MiB
// image.jpg: 512 KiB
// video.mp4: 150 MiB

Download Progress ​

typescript
import { toBytes } from '@h3ravel/support';

const downloaded = 45678901;
const total = 104857600;

console.log(`Downloaded: ${toBytes(downloaded)} / ${toBytes(total)}`);
// "Downloaded: 43.56 MiB / 100 MiB"

Edge Cases ​

typescript
import { toBytes } from '@h3ravel/support';

toBytes(); // "0 Bytes"
toBytes(0); // "0 Bytes"
toBytes(undefined); // "0 Bytes"
toBytes(NaN); // "0 Bytes"
toBytes(500); // "500 Bytes"

toHumanTime() ​

Formats a duration in seconds into a human-readable time string. Supports both worded format (e.g., "1hr 2min 3sec") and digital clock format (e.g., "01:02:03").

Signature ​

typescript
toHumanTime(seconds?: number, worded?: boolean): string

Parameters ​

  • seconds (optional) - Duration in seconds (default: 0)
  • worded (optional) - If true, outputs worded format; if false, outputs HH:MM:SS format (default: false)

Returns ​

string - A formatted time string

Examples ​

Digital Clock Format (Default) ​

typescript
import { toHumanTime } from '@h3ravel/support';

toHumanTime(0); // "0:00"
toHumanTime(30); // "0:30"
toHumanTime(90); // "1:30"
toHumanTime(3600); // "1:00:00"
toHumanTime(3661); // "1:01:01"
toHumanTime(7384); // "2:03:04"

Worded Format ​

typescript
import { toHumanTime } from '@h3ravel/support';

toHumanTime(0, true); // "0sec"
toHumanTime(30, true); // "30sec"
toHumanTime(90, true); // "1min 30sec"
toHumanTime(3600, true); // "1hr"
toHumanTime(3661, true); // "1hr 1min 1sec"
toHumanTime(7384, true); // "2hr 3min 4sec"

Video Duration Display ​

typescript
import { toHumanTime } from '@h3ravel/support';

const videoDuration = 185; // 3 minutes 5 seconds

// Digital format for video player
console.log(toHumanTime(videoDuration)); // "3:05"

// Worded format for descriptions
console.log(toHumanTime(videoDuration, true)); // "3min 5sec"

Timer Display ​

typescript
import { toHumanTime } from '@h3ravel/support';

let elapsed = 0;

setInterval(() => {
  elapsed++;
  console.log(`Elapsed: ${toHumanTime(elapsed)}`);
}, 1000);
// Output: "0:01", "0:02", "0:03", ...

Exercise Tracker ​

typescript
import { toHumanTime } from '@h3ravel/support';

const workoutDuration = 4567; // ~76 minutes

console.log(`Workout duration: ${toHumanTime(workoutDuration, true)}`);
// "Workout duration: 1hr 16min 7sec"

Different Time Ranges ​

typescript
import { toHumanTime } from '@h3ravel/support';

// Seconds only
toHumanTime(45); // "0:45"
toHumanTime(45, true); // "45sec"

// Minutes and seconds
toHumanTime(125); // "2:05"
toHumanTime(125, true); // "2min 5sec"

// Hours, minutes, and seconds
toHumanTime(4505); // "1:15:05"
toHumanTime(4505, true); // "1hr 15min 5sec"

// Multiple hours
toHumanTime(36000); // "10:00:00"
toHumanTime(36000, true); // "10hr"

Edge Cases ​

typescript
import { toHumanTime } from '@h3ravel/support';

toHumanTime(); // "0:00"
toHumanTime(0); // "0:00"
toHumanTime(0, true); // "0sec"
toHumanTime(-100); // "0:00" (negative values treated as 0)
toHumanTime(NaN); // "0:00"

Comparison Table ​

HelperInputOutput ExampleUse Case
abbreviate()1234567"1.23M"Large numbers, statistics
humanize()42"forty two"Written numbers, readable IDs
toBytes()1048576"1 MiB"File sizes, storage
toHumanTime()3661"1:01:01"Durations, timers

Usage Tips ​

1. Choose the Right Helper ​

typescript
import { abbreviate, toBytes, toHumanTime } from '@h3ravel/support';

// For large counts/stats → abbreviate()
const followers = 1543678;
console.log(abbreviate(followers)); // "1.54M"

// For file/data sizes → toBytes()
const fileSize = 5242880;
console.log(toBytes(fileSize)); // "5 MiB"

// For time durations → toHumanTime()
const duration = 3725;
console.log(toHumanTime(duration)); // "1:02:05"

2. Locale-Aware Formatting ​

typescript
import { abbreviate } from '@h3ravel/support';

// Adapt to user's locale
const userLocale = navigator.language || 'en-US';
const count = 1234567;

console.log(abbreviate(count, userLocale));

3. Consistent Decimal Places ​

typescript
import { toBytes } from '@h3ravel/support';

// Use consistent decimals for better UX
const files = [1024, 2048, 4096];

files.forEach((size) => {
  console.log(toBytes(size, 2)); // Always 2 decimal places
});
// Output: "1.00 KiB", "2.00 KiB", "4.00 KiB"

4. Dynamic Time Format ​

typescript
import { toHumanTime } from '@h3ravel/support';

// Use worded format for natural language
const duration = 125;
console.log(`Video length: ${toHumanTime(duration, true)}`);
// "Video length: 2min 5sec"

// Use digital format for UI elements
console.log(`Duration: ${toHumanTime(duration)}`);
// "Duration: 2:05"

5. Error Handling ​

typescript
import { humanize, toBytes, toHumanTime } from '@h3ravel/support';

// humanize() throws on negative numbers
try {
  humanize(-5);
} catch (error) {
  console.error('Invalid input');
}

// Other helpers handle invalid input gracefully
console.log(toBytes(undefined)); // "0 Bytes"
console.log(toHumanTime(NaN)); // "0:00"

TypeScript Support ​

All Number helpers are fully typed and provide excellent TypeScript support:

typescript
import { abbreviate, humanize, toBytes, toHumanTime } from '@h3ravel/support';

// Type inference works automatically
const abbreviated: string = abbreviate(1000000);
const words: string = humanize(42);
const size: string = toBytes(1024);
const time: string = toHumanTime(3600);

// Optional parameters are type-safe
abbreviate(1000, 'en-US'); // Valid
humanize(100, '-'); // Valid
humanize(100, '/'); // Type error
toBytes(1024, 2, true); // Valid
toHumanTime(60, true); // Valid

Released under the MIT License.